Browse Source

fs fix

master
Mathieu Serandour 1 year ago
parent
commit
f34d3129ed
  1. 583
      kernel/fs/fat32/fat32.c
  2. 16
      kernel/fs/fat32/specs.h
  3. 4
      kernel/fs/gpt.c
  4. 16
      kernel/fs/vfs.h
  5. 103
      kernel/fs/vfs_dirs.c
  6. 2
      kernel/fs/vfs_files.c

583
kernel/fs/fat32/fat32.c

@ -19,6 +19,19 @@
#define FAT_CACHE_SIZE 2048
// stolen from Linux source
static inline
unsigned char fat_checksum(const uint8_t* name)
{
unsigned char s = name[0];
s = (s<<7) + (s>>1) + name[1]; s = (s<<7) + (s>>1) + name[2];
s = (s<<7) + (s>>1) + name[3]; s = (s<<7) + (s>>1) + name[4];
s = (s<<7) + (s>>1) + name[5]; s = (s<<7) + (s>>1) + name[6];
s = (s<<7) + (s>>1) + name[7]; s = (s<<7) + (s>>1) + name[8];
s = (s<<7) + (s>>1) + name[9]; s = (s<<7) + (s>>1) + name[10];
return s;
}
typedef uint32_t cluster_t;
@ -50,19 +63,24 @@ int fat32_write_file_sectors(
// juste take the lower
// lba bits
__attribute__((const))
static uint16_t lba_hash(uint64_t lba) {
return lba & (FAT_CACHE_SIZE-1);
}
typedef struct block_cache_entry {
uint64_t tag; // the whole lba
char* buf;
uint64_t tag: 63; // the whole lba
int modified: 1; // write back policy
// buf dimension is exactly one sector
} block_cache_entry_t;
typedef struct block_cache {
block_cache_entry_t entries[FAT_CACHE_SIZE];
void* buf;
size_t sector_size_shift;
//unsigned
} block_cache_t;
typedef struct {
@ -93,7 +111,12 @@ typedef struct {
static
void* read(disk_part_t* part, uint64_t lba, void* buf, size_t count) {
void* read(
const disk_part_t* restrict part,
uint64_t lba,
void* restrict buf,
size_t count
) {
lba += part->begin;
@ -107,10 +130,34 @@ void* read(disk_part_t* part, uint64_t lba, void* buf, size_t count) {
}
static
void* async_read(
const disk_part_t* restrict part,
uint64_t lba,
void* restrict buf,
size_t count
) {
lba += part->begin;
assert(lba >= part->begin);
assert(lba < part->end);
part->interface->async_read(part->interface->driver, lba, buf, count);
return buf;
}
static inline
void write(disk_part_t* part, uint64_t lba, const void* buf, size_t count) {
void write(
const disk_part_t* restrict part,
uint64_t lba,
const void* restrict buf,
size_t count
) {
lba += part->begin;
//log_warn("lba=%lx", lba);
assert(lba >= part->begin && lba <= part->end);
part->interface->write(part->interface->driver, lba, buf, count);
@ -127,18 +174,20 @@ cluster_begin(cluster_t cluster, fat32_privates_t* restrict fp) {
static
void setup_cache(block_cache_t* cache, unsigned sector_size) {
void* buf = malloc(sector_size * FAT_CACHE_SIZE);
void setup_cache(block_cache_t* cache, unsigned sector_size_shift) {
cache->buf = malloc(FAT_CACHE_SIZE << sector_size_shift);
cache->sector_size_shift = sector_size_shift;
for(unsigned i = 0; i < FAT_CACHE_SIZE; i++)
cache->entries[i].buf = buf + sector_size * i;
for(unsigned i = 0; i < FAT_CACHE_SIZE; i++) {
cache->entries[i].modified = 0;
cache->entries[i].tag = 0;
}
}
static
void cleanup_cache(block_cache_t* cache) {
void* buf_begin = cache->entries[0].buf;
void* buf_begin = cache->buf;
free(buf_begin);
}
@ -160,13 +209,36 @@ void* cache_access(block_cache_t* restrict cache, uint64_t lba) {
if(e->tag == lba) {
//log_debug("fat32: fat cache hit lba %lu", lba);
return e->buf;
return cache->buf + (lba << cache->sector_size_shift);
}
//log_debug("fat32: fat cache miss lba %lu", lba);
return NULL;
}
// flush cache
static
void flush_fat_cache(disk_part_t* part, block_cache_t* cache) {
int s = 0;
for(unsigned i = 0; i < FAT_CACHE_SIZE; i++) {
if(cache->entries[i].modified) {
s++;
cache->entries[i].modified = 0;
write(
part,
cache->entries[i].tag,
cache->buf + (i << cache->sector_size_shift),
1
);
//log_warn("WRITE!!!!!!!!");
}
//cache->entries[i].tag = 0;
}
log_warn("%u writes", s);
}
/**
* @brief reserve a cache entry associated
@ -177,12 +249,35 @@ void* cache_access(block_cache_t* restrict cache, uint64_t lba) {
* @return void* the buffer
*/
static
void* add_cache_entry(block_cache_t* cache, uint64_t lba) {
void* add_cache_entry(
const disk_part_t* restrict part,
block_cache_t* restrict cache,
uint64_t lba
) {
block_cache_entry_t* e = &cache->entries[lba_hash(lba)];
void* buf = cache->buf + (lba_hash(lba) << cache->sector_size_shift);
// before replacing the entry,
// we write it back to memory if needed
if(e->modified) {
write(part, e->tag, buf, 1);
e->modified = 0;
log_warn("WRITE!!!!!!!!");
}
e->tag = lba;
return e->buf;
return buf;
}
static
void mark_modified(block_cache_t* cache, uint64_t lba) {
block_cache_entry_t* e = &cache->entries[lba_hash(lba)];
assert(e->tag == lba);
e->modified = 1;
}
@ -199,14 +294,12 @@ void* add_cache_entry(block_cache_t* cache, uint64_t lba) {
*/
static
void* fetch_fat_sector(
fat32_privates_t* pr,
disk_part_t* part,
block_cache_t* cache,
const fat32_privates_t* restrict pr,
const disk_part_t* restrict part,
block_cache_t* restrict cache,
uint64_t lba
) {
static int i = 0;
//log_debug("fetch fat sector %lu", lba);
// assert that it is a fat sector
assert(lba >= pr->fat_begin);
assert(lba < pr->fat_begin + pr->fat_size);
@ -219,7 +312,7 @@ void* fetch_fat_sector(
// cache miss
buf = add_cache_entry(cache, lba);
buf = add_cache_entry(part, cache, lba);
read(part, lba, buf, 1);
@ -236,10 +329,11 @@ void* fetch_fat_sector(
* entry or 0 if the cluster is the end of the chain
*/
static
cluster_t readFAT(disk_part_t* part,
fat32_privates_t* pr,
uint32_t cluster
) {
cluster_t readFAT(
const disk_part_t* restrict part,
fat32_privates_t* restrict pr,
cluster_t cluster
) {
uint32_t offset = cluster * 4;
uint64_t lba = pr->fat_begin + offset / block_size(part);
@ -269,8 +363,8 @@ cluster_t readFAT(disk_part_t* part,
* @return int
*/
static
cluster_t allocFAT(disk_part_t* restrict part,
fat32_privates_t* restrict pr
cluster_t allocFAT(const disk_part_t* restrict part,
fat32_privates_t* restrict pr
) {
assert(pr->alloc_start >= pr->fat_begin);
@ -303,7 +397,6 @@ cluster_t allocFAT(disk_part_t* restrict part,
if(sector[i] == 0) {
// we found an unallocated cluster!
pr->alloc_start = lba;
//log_warn("allocfat %u", (lba - pr->fat_begin) * entries_per_sector + i);
return (lba - pr->fat_begin) * entries_per_sector + i;
}
}
@ -314,13 +407,12 @@ cluster_t allocFAT(disk_part_t* restrict part,
}
static
void linkFAT(disk_part_t* restrict part,
fat32_privates_t* restrict pr,
cluster_t from, cluster_t to
void linkFAT(
const disk_part_t* restrict part,
fat32_privates_t* restrict pr,
cluster_t from, cluster_t to
) {
//log_warn("linkfat %u -> %u", from, to);
uint32_t offset = from * 4;
uint64_t lba = pr->fat_begin + offset / block_size(part);
uint32_t sector_offset = offset % block_size(part);
@ -329,14 +421,18 @@ void linkFAT(disk_part_t* restrict part,
cluster_t* ent = (cluster_t *)(sector + sector_offset);
// assert((*ent & 0x0FFFFFFF) >= 0x0FFFFFF8); // last entry of the file
assert((*ent & 0x0FFFFFFF) >= 0x0FFFFFF8
|| *ent == 0); // last entry of the file
assert((to & 0xf0000000) == 0);
// don't modify reserved bits
*ent = to | (*ent & 0xf0000000);
// save
//write(part, lba, sector, 1);
mark_modified(&pr->fat_cache, lba);
//save_fat_
//log_warn("link %lu -> %lu", from, to);
}
@ -354,6 +450,61 @@ uint32_t fat_attr2fs_type(uint32_t attr) {
/**
* @brief same as readFAT if the the cluster
* is not the end of the chain
*
* Otherwise, return a new cluster, or 0 if
* the drive is full
*
* @param part
* @param pr
* @param cluster
* @return cluster_t
*/
static
cluster_t read_or_allocateFAT(
const disk_part_t* restrict part,
fat32_privates_t* restrict pr,
uint32_t cluster
) {
cluster_t next = readFAT(part, pr, cluster);
if(!next) {
// we are at the file end
// let's allocate another cluster
next = allocFAT(part, pr);
if(!next) {
// the drive is full
return 0;
}
// mark the new cluster as the end of
// the file chain
linkFAT(part, pr, next, 0xfffffff);
// link the cluster in the file chain
linkFAT(part, pr, cluster, next);
}
return next;
}
static
uint32_t __attribute__((const)) fs_type2fat_attr(uint32_t attr) {
uint32_t ret = 0;
if(attr & DT_DIR)
ret |= FAT32_DIRECTORY;
return ret;
}
static void handle_long_filename_entry(
const fat_dir_t* entry,
char* name_buf
@ -362,6 +513,7 @@ static void handle_long_filename_entry(
fat_long_filename_t* e = (fat_long_filename_t*)entry;
int order = (e->order & 0x0f) - 1;
uint16_t wchars[] = {
e->chars0[0],
e->chars0[1],
@ -390,10 +542,10 @@ static void handle_long_filename_entry(
// 1: end of directory
// 0: no new entry, not end of directory
static int parse_dir_entry(
const fat_dir_t* dir,
int* long_entry,
dirent_t* entries,
int* cur_entry_id
const fat_dir_t* restrict dir,
int* restrict long_entry,
dirent_t* restrict entries,
int* restrict cur_entry_id
) {
// last entry
@ -416,6 +568,7 @@ static int parse_dir_entry(
// short entry
if(!*long_entry) {
strncpy(cur_entry->name, dir->name, 8);
char* ptr = cur_entry->name+7;
@ -451,6 +604,7 @@ static int parse_dir_entry(
((uint32_t)dir->cluster_high << 16);
cur_entry->file_size = dir->file_size;
// prepare for next entry
@ -462,7 +616,11 @@ static int parse_dir_entry(
}
dirent_t* fat32_read_dir(fs_t* fs, uint64_t cluster, size_t* n) {
dirent_t* fat32_read_dir(
fs_t* restrict fs,
uint64_t cluster,
size_t* restrict n
) {
assert(fs->type == FS_TYPE_FAT);
disk_part_t* restrict part = fs->part;
@ -470,7 +628,7 @@ dirent_t* fat32_read_dir(fs_t* fs, uint64_t cluster, size_t* n) {
unsigned bufsize = block_size(part) * pr->cluster_size;
uint8_t* buf = malloc(bufsize);
uint8_t* buf = malloc(bufsize + 8);
int end = 0;
@ -493,6 +651,10 @@ dirent_t* fat32_read_dir(fs_t* fs, uint64_t cluster, size_t* n) {
read(part, cluster_begin(cluster, pr), buf, pr->cluster_size);
log_warn("bufsize=%u", bufsize);
dump(buf, 512, 32, DUMP_HEX8);
for(unsigned i = 0; i < entries_per_cluster; i++) {
fat_dir_t* dir = (fat_dir_t*)buf + i;
@ -525,6 +687,235 @@ dirent_t* fat32_read_dir(fs_t* fs, uint64_t cluster, size_t* n) {
}
/**
* @brief emplace a dirent in a directory
*
* @param buf the current cluster buffer
* @param ent the entry to emplace
* @param lba the lba of the current
* @param cur current entry offset
* @param entries_per_cluster
* @param cur_cluster current cluster
* @param part disk partition
* @param pr fat32 privates
* @return int the next value of entry_offset
* -1 if the drive is full and therefore no
* entry can be inserted anymore
*/
static
int emplace_dirent(
void* restrict buf,
fat_dir_t* restrict ent,
int entry_offset,
int entries_per_cluster,
cluster_t* restrict cur_cluster,
const disk_part_t* restrict part,
fat32_privates_t* restrict pr
) {
((fat_dir_t *)buf)[entry_offset++] = *ent;
if(entry_offset == entries_per_cluster) {
entry_offset = 0;
// write cluster back
write(
part,
cluster_begin(*cur_cluster, pr),
buf,
pr->cluster_size
);
*cur_cluster = read_or_allocateFAT(part, pr, *cur_cluster);
if(! *cur_cluster)
return -1; // drive full
// zero the next cluster
memset(buf, 0, entries_per_cluster * sizeof(fat_dir_t));
}
return entry_offset;
}
int fat32_add_dirent(
fs_t* restrict fs,
uint64_t dir_cluster,
const char* file_name,
uint64_t file_cluster,
uint64_t file_size,
unsigned type
) {
// we go through the dir sequentially
// and we only keep track of the current
// dir cluster
cluster_t current_dir_cluster = dir_cluster;
assert(fs->type == FS_TYPE_FAT);
disk_part_t* restrict part = fs->part;
fat32_privates_t* restrict pr = (void*)(fs+1);
unsigned bufsize = block_size(part) * pr->cluster_size;
uint8_t* buf = malloc(bufsize);
unsigned entries_per_cluster = bufsize / sizeof(fat_dir_t);
// for long name entries
int long_entry = 0;
// interator in the
// first inner loop. in the end,
// it contains the entry offset
unsigned entry_cluster_offset;
// find the end of the dir
while(1) {
uint64_t lba = cluster_begin(current_dir_cluster, pr);
read(part, lba, buf, pr->cluster_size);
int v = 0;
dirent_t entry;
for(entry_cluster_offset = 0;
entry_cluster_offset < entries_per_cluster;
entry_cluster_offset++
) {
fat_dir_t* dir = (fat_dir_t*)buf + entry_cluster_offset;
int j = 0;
v = parse_dir_entry(dir, &long_entry, &entry, &j);
if(v == 1)
break;
current_dir_cluster = readFAT(part, pr, current_dir_cluster);
if(!current_dir_cluster)
assert(0);
}
if(v == 1) // we found the end
break;
}
// we found the end!
// first compute the short filename entry
fat_dir_t sfn = {
.attr = fs_type2fat_attr(type),
.cluster_high = file_cluster >> 16,
.cluster_low = file_cluster & 0xffff,
.date0 = 0,
.date1 = 0,
.date2 = 0,
.date3 = 0,
.date4 = 0,
.date5 = 0,
.reserved = 0,
.file_size = file_size,
.name ={'I','S','S','O','U',' ',' ',' ',' ',' ',' '},
};
// fat checksum of the 'ISSOU ' string
int sfn_checksum = 0x81;
// we can easily suppose that
// we will always need long file name entries.
unsigned n_entries = strlen(file_name) / 13;
// create the name buffer
uint16_t* namebuf = malloc(13 * sizeof(uint16_t));
// padding
memset(namebuf, 0xff, 13*sizeof(uint16_t));
// chars
ascii2utf16le(namebuf, file_name, 13 * sizeof(uint16_t));
uint16_t* name_ptr = namebuf;
// I guess entries have to be inserted backward
for(int i = n_entries-1; i >= 0; i++) {
uint8_t order = i+1;
if(order == n_entries)
order |= 0x40;
fat_long_filename_t lfn_entry = {
.order = order,
.attr = FAT32_LFN,
.zero = 0,
.type = 0,
.checksum = sfn_checksum,
.chars0 = {
name_ptr[0], name_ptr[1], name_ptr[2],
name_ptr[3], name_ptr[4],
},
.chars1 = {
name_ptr[0], name_ptr[1], name_ptr[2],
name_ptr[3], name_ptr[4], name_ptr[5],
},
.chars2 = {name_ptr[0], name_ptr[1]},
};
name_ptr += 13;
// now emplace the entry
entry_cluster_offset = emplace_dirent(
buf,
(fat_dir_t*)&lfn_entry,
entry_cluster_offset,
entries_per_cluster,
&current_dir_cluster,
part,
pr
);
}
// finaly emplace the sfn entry
entry_cluster_offset = emplace_dirent(
buf,
&sfn,
entry_cluster_offset,
entries_per_cluster,
&current_dir_cluster,
part,
pr
);
// unless emplace_dirent just filled
// the current cluster, in which case
// it would return entry_cluster_offset = 0,
// we need to write the current cluster back
if(entry_cluster_offset) {
write(
part,
cluster_begin(current_dir_cluster, pr),
buf,
pr->cluster_size
);
}
free(namebuf);
free(buf);
return 0; // successs
}
int fat32_update_dirent(fs_t* fs, uint64_t dir_cluster, const char* file_name,
uint64_t file_cluster, uint64_t file_size) {
@ -559,6 +950,7 @@ int fat32_update_dirent(fs_t* fs, uint64_t dir_cluster, const char* file_name,
fat_dir_t* dir = (fat_dir_t*)buf + i;
int j = 0;
int v = parse_dir_entry(dir, &long_entry, &entry, &j);
assert(v != 1); // the entry should be present
if(v == 2) {
@ -595,6 +987,7 @@ int fat32_update_dirent(fs_t* fs, uint64_t dir_cluster, const char* file_name,
}
free(buf);
// unsuccessful
return 1;
@ -609,6 +1002,9 @@ void fat32_free_dirents(dirent_t* dir) {
fs_t* fat32_mount(disk_part_t* part) {
//assert(0);
void* buf = malloc(block_size(part)+1);
// boot record
@ -673,6 +1069,7 @@ fs_t* fat32_mount(disk_part_t* part) {
fs->read_dir = fat32_read_dir;
fs->update_dirent = fat32_update_dirent;
fs->free_dirents = fat32_free_dirents;
fs->add_dirent = fat32_add_dirent;
fs->unmount = fat32_unmount;
@ -683,11 +1080,11 @@ fs_t* fat32_mount(disk_part_t* part) {
pr->fat_size = fatsize;
pr->fat_begin = reserved;
pr->data_begin = reserved + tables_count * fatsize;
pr->alloc_start = 540;
pr->alloc_start = pr->fat_begin;
//pr->fat_begin;
// setup fat cache
setup_cache(&pr->fat_cache, block_size(fs->part));
setup_cache(&pr->fat_cache, fs->part->interface->lbashift);
free(buf);
@ -698,10 +1095,13 @@ fs_t* fat32_mount(disk_part_t* part) {
void fat32_unmount(fs_t* fs) {
log_warn("unmount fat32");
fat32_privates_t* pr = (fat32_privates_t*)(fs+1);
cleanup_cache(&pr->fat_cache);
free(fs);
log_debug("fat32 unmounted");
// open files checking should be done by the vfs
}
@ -785,27 +1185,49 @@ int fat32_read_file_sectors(
uint64_t lba = cluster_begin(cluster, pr)
+ cluster_offset;
unsigned read_size = 1;
unsigned cluster_remaining =
pr->cluster_size - cluster_offset;
unsigned read_size = 0;
if(n >= cluster_remaining) {
read_size = cluster_remaining;
// read multiple clusters
// if contiguous
while(n) {
unsigned cluster_remaining =
pr->cluster_size - cluster_offset;
cluster_offset = 0;
cluster = readFAT(fs->part, pr, cluster);
n -= read_size;
assert(cluster || !n);
}
// else, this is the last iteration
if(n < cluster_remaining) {
read_size += n;
n = 0;
// this is the last iteration
break;
}
else {
read_size += cluster_remaining;
cluster_offset = 0;
unsigned old = cluster;
cluster = readFAT(fs->part, pr, cluster);
n -= cluster_remaining;
assert(cluster || !n);
read(fs->part, lba, buf, read_size);
if(cluster != old + 1) {
// not contiguous blocks
break;
}
}
}
//log_warn("READ AT CLUSTER=%u", cluster);
async_read(fs->part, lba, buf, read_size);
buf += bsize * read_size;
}
fs->part->interface->sync(fs->part->interface->driver);
return n;
}
@ -824,13 +1246,11 @@ int fat32_write_file_sectors(
// compute the first cluster and offset
uint32_t first_cluster = begin / pr->cluster_size;
uint32_t cluster_offset = begin % pr->cluster_size;
uint64_t clusterend = 0;
cluster_t cluster = fetch_cluster(fs, pr, fd,
begin / pr->cluster_size,
&clusterend);
cluster_t cluster = fetch_cluster(fs, pr, fd, first_cluster, &clusterend);
// the write operation is beyond file end.
@ -838,10 +1258,12 @@ int fat32_write_file_sectors(
if(clusterend != ~0llu) { // cluster = 0 <=>
// if this expression is false,
// then the FS is broken
assert((begin + n - 1) * pr->cluster_size *
block_size(fs->part) >= fd->file_size);
assert(clusterend < begin);
for(unsigned i = clusterend; i <= begin; i++) {
assert(clusterend < first_cluster);
for(unsigned i = clusterend; i < first_cluster; i++) {
cluster_t cl = allocFAT(fs->part, pr);
if(!cl) // the drive is full
@ -877,15 +1299,16 @@ int fat32_write_file_sectors(
unsigned write_size = 1;
unsigned cluster_remaining =
pr->cluster_size - cluster_offset;
if(n >= cluster_remaining) {
if(n > cluster_remaining) {
write_size = cluster_remaining;
cluster_offset = 0;
}
// else, this is the last iteration
else
// this is the last iteration
write_size = n;
// log_warn("WRITE AT CLUSTER=%u", cluster);
write(fs->part, lba, buf, write_size);
buf += bsize * write_size;
@ -895,29 +1318,17 @@ int fat32_write_file_sectors(
if(n) {
cluster_t next = readFAT(fs->part, pr, cluster);
if(!next) {
// we are at the file end
// let's allocate another cluster
next = allocFAT(fs->part, pr);
cluster = read_or_allocateFAT(fs->part, pr, cluster);
if(!next) {
panic("ptn de merde");
// the drive is full
return n;
}
// mark the new cluster as the end of
// the file chain
linkFAT(fs->part, pr, next, 0xfffffff);
// link the cluster in the file chain
linkFAT(fs->part, pr, cluster, next);
if(!cluster) {
// the drive is full
return n;
}
cluster = next;
}
}
flush_fat_cache(fs->part, &pr->fat_cache);
return written;
}

16
kernel/fs/fat32/specs.h

@ -54,14 +54,14 @@ typedef struct fat_dir {
typedef struct fat_long_filename {
uint8_t order;
uint16_t chars0[5];
uint8_t attr; // = FAT32_LFN
uint8_t checksum;
uint8_t type;
uint16_t chars1[6];
uint16_t zero;
uint16_t chars2[2];
uint8_t order; // 43
uint16_t chars0[5]; // ame_w
uint8_t attr; // = FAT32_LFN // f
uint8_t type; // 0
uint8_t checksum; // ?
uint16_t chars1[6]; // tf.aya
uint16_t zero; // 0
uint16_t chars2[2];
} __attribute__((packed)) fat_long_filename_t;

4
kernel/fs/gpt.c

@ -88,8 +88,10 @@ void gpt_remove_drive_parts(driver_t* driver) {
// the partition is mounted
// somewhere
if(partitions[i].mount_point)
if(partitions[i].mount_point) {
log_warn("part %u is mounted on %s, let's unmount it", i, partitions[i].mount_point);
vfs_unmount(partitions[i].mount_point);
}
n_removed++;
n_partitions--;

16
kernel/fs/vfs.h

@ -53,6 +53,22 @@ void vfs_init(void);
// free every memory block
void vfs_cleanup(void);
/**
* @brief create a file.
* Can only create file if
* the parent directory already
* exists
*
*
* @param path file path to create
* @param type DT_DIR, DT_REG, ...
* @return 0 on success,
* non 0 on failure
*/
int vfs_create(const char* path, int type);
/**
* @brief file handler used to read,
* write, seek. Uses polymorphic calls

103
kernel/fs/vfs_dirs.c

@ -38,10 +38,9 @@ static dir_cache_ent_t *cached_dir_list;
// cache size must be a power of two
static unsigned cache_size = 0;
// dynamic array of every mounted
// file system
// static fs_t** mounted_fs_list = NULL;
// static unsigned n_mounted_fs = 0;
static int unmount(vdir_t *vdir);
static int is_absolute(const char *path)
{
@ -125,22 +124,31 @@ uint16_t path_hash(const char *path)
// recursively destruct the entire
// vdir tree
// does not remove the root path
static void free_vtree(vdir_t *root)
{
for (unsigned i = 0; i < root->n_children; i++)
{
vdir_t *child = &root->children[i];
log_warn("free_vtree");
log_warn("unmounting %s", child->path);
// unmount mounted entries
if (child->fs)
child->fs->unmount(child->fs);
unmount(child);
else
free_vtree(child);
free(child->path);
free(child);
}
root->n_children = 0;
if(root->n_children) {
free(root->children);
root->n_children = 0;
}
// don't free the root path:
// the vfs root path is static
log_warn("free_vtree end");
}
// return the vdir associated with given fs
@ -184,13 +192,18 @@ static int remove_vdir(vdir_t *vdir)
if (&vd->children[i] == vdir)
{
// actually remove it
free(vdir->path);
memmove(
vd->children + i,
vd->children + i + 1,
(vd->n_children - i - 1) * sizeof(vdir_t)
);
vd->n_children--;
vd->children = realloc(vd->children, vd->n_children);
return 1;
}
@ -217,8 +230,7 @@ static int remove_vdir(vdir_t *vdir)
// return 0 iif something
// went wrong
static int unmount(vdir_t *vdir)
{
static int unmount(vdir_t *vdir) {
fs_t *fs = vdir->fs;
assert(vdir);
@ -237,14 +249,29 @@ static int unmount(vdir_t *vdir)
return 0;
}
// assert that the partition
// is actually mounted
log_warn("----------------------------------------------------- %u", fs->part->mount_point);
assert(fs->part->mount_point);
free(fs->part->mount_point);
fs->part->mount_point = NULL;
// set the partition not mounted
if (vdir == &vfs_root)
vfs_root.fs = NULL;
else
else {
free_vtree(vdir);
remove_vdir(vdir);
}
// remove cache entries related with this thing
for (unsigned i = 0; i < cache_size; i++)
@ -256,6 +283,8 @@ static int unmount(vdir_t *vdir)
}
}
fs->unmount(fs);
return 1;
}
@ -655,16 +684,16 @@ static dir_cache_ent_t *get_cache_entry(const char *path)
// check cache
dir_cache_ent_t *ent = &cached_dir_list[hash];
if (ent->path == NULL) {// not present entry
log_debug("VFS cache miss for %s (hash %u): not present", path, hash);
//log_debug("VFS cache miss for %s (hash %u): not present", path, hash);
return NULL;
}
if (!strcmp(ent->path, path)) {// right entry (no collision)
log_debug("VFS cache hit for %s (hash %u)", path, hash);
//log_debug("VFS cache hit for %s (hash %u)", path, hash);
return ent;
}
log_debug("VFS cache miss for %s (hash %u): conflit", path, hash);
//log_debug("VFS cache miss for %s (hash %u): conflit", path, hash);
return NULL;
}
@ -681,8 +710,6 @@ fs_t *vfs_open(const char *path, fast_dirent_t *dir)
assert(is_absolute(pathbuf));
log_warn("VFS OPEN: %s -> %s", path, pathbuf);
// check cache
dir_cache_ent_t *ent = get_cache_entry(pathbuf);
if (ent) { // present entry
@ -886,7 +913,7 @@ int vfs_mount(disk_part_t *part, const char *path)
int vfs_unmount(const char *path)
{
log_warn("vfs_unmount(%s)", path);
log_info("vfs_unmount(%s)", path);
// do stuf!
char *pbuf = malloc(strlen(path) + 1);
simplify_path(pbuf, path);
@ -902,6 +929,46 @@ int vfs_unmount(const char *path)
}
int vfs_create(const char* path, int type) {
char* pathbuf = malloc(strlen(path) + 1);
simplify_path(pathbuf, path);
char* last_sep = (char*)strrchr(pathbuf, '/');
if(!last_sep) {
// bad
free(pathbuf);
return 1;
}
*last_sep = 0;
fast_dirent_t parentdir;
fs_t* fs = vfs_open(pathbuf, &parentdir);
free(pathbuf);
// if the parent directory
// is not a directory, or does not
// exist
if(!fs || parentdir.type != DT_DIR)
return 1;
// actually add the entry
assert(0);
//fs->add_dirent()
return 0;
}
struct DIR *vfs_opendir(const char *path)
{
/**

2
kernel/fs/vfs_files.c

@ -371,7 +371,7 @@ size_t vfs_read_file(void *ptr, size_t size, size_t nmemb,
if(bsize == 0)
return 0;
// first read unaligned
if(stream->buffer_valid && cachable) {

Loading…
Cancel
Save