aboutsummaryrefslogtreecommitdiff
path: root/src/kernel/user/vfs.c
diff options
context:
space:
mode:
authorAlex Auvolat <alex.auvolat@ens.fr>2015-02-24 16:58:33 +0100
committerAlex Auvolat <alex.auvolat@ens.fr>2015-02-24 16:58:33 +0100
commit150dd5f860a5f22a8c3bcc1bf3a1f2e36dcf6fd8 (patch)
treee92a633a780104617483fd9fd379238299affabd /src/kernel/user/vfs.c
parentfa8a840c6dfc9eb737ef5d777f066b05eb8d9544 (diff)
downloadkogata-150dd5f860a5f22a8c3bcc1bf3a1f2e36dcf6fd8.tar.gz
kogata-150dd5f860a5f22a8c3bcc1bf3a1f2e36dcf6fd8.zip
Change VFS a bit : the root directory of a fs is now a pointer. Fix tests.
Diffstat (limited to 'src/kernel/user/vfs.c')
-rw-r--r--src/kernel/user/vfs.c86
1 files changed, 48 insertions, 38 deletions
diff --git a/src/kernel/user/vfs.c b/src/kernel/user/vfs.c
index c20caa0..1c841f7 100644
--- a/src/kernel/user/vfs.c
+++ b/src/kernel/user/vfs.c
@@ -29,31 +29,35 @@ void register_fs_driver(const char* name, fs_driver_ops_t *ops) {
// ================================== //
fs_t *make_fs(const char* drv_name, fs_handle_t *source, const char* opts) {
- // Look for driver
- fs_driver_t *d = 0;
- for(fs_driver_t *i = drivers; i != 0; i = i->next) {
- if (drv_name != 0 && strcmp(i->name, drv_name) == 0) d = i;
- if (drv_name == 0 && source != 0 && i->ops->detect && i->ops->detect(source)) d = i;
- if (d != 0) break;
- }
- if (d == 0) return 0; // driver not found
-
// Open file system
fs_t *fs = (fs_t*)malloc(sizeof(fs_t));
- if (fs == 0) return 0;
+ if (fs == 0) goto fail;
+
+ fs->root = (fs_node_t*)malloc(sizeof(fs_node_t));
+ if (fs->root == 0) goto fail;
fs->refs = 1;
- fs->root.refs = 1; // root node is never disposed of (done by fs->shutdown)
- fs->root.fs = fs;
- fs->root.parent = 0;
- fs->root.children = 0;
+ fs->root->refs = 1;
+ fs->root->fs = fs;
+ fs->root->parent = 0;
+ fs->root->children = 0;
- if (d->ops->make(source, opts, fs)) {
- return fs;
- } else {
- free(fs);
- return 0;
+ // Look for driver
+ for(fs_driver_t *i = drivers; i != 0; i = i->next) {
+ if ((drv_name != 0 && strcmp(i->name, drv_name) == 0) || (drv_name == 0 && source != 0)) {
+ if (i->ops->make(source, opts, fs)) {
+ return fs;
+ } else {
+ goto fail;
+ }
+ }
}
+
+
+fail:
+ if (fs && fs->root) free(fs->root);
+ if (fs) free(fs);
+ return 0;
}
bool fs_add_source(fs_t *fs, fs_handle_t *source, const char* opts) {
@@ -67,8 +71,7 @@ void ref_fs(fs_t *fs) {
void unref_fs(fs_t *fs) {
fs->refs--;
if (fs->refs == 0) {
- // don't unref root node, don't call dispose on it
- // (done by fs->shutdown)
+ unref_fs_node(fs->root);
fs->ops->shutdown(fs->data);
free(fs);
}
@@ -87,19 +90,26 @@ void unref_fs_node(fs_node_t *n) {
mutex_lock(&n->lock);
n->refs--;
if (n->refs == 0) {
- ASSERT(n != &n->fs->root);
- ASSERT(n->parent != 0);
- ASSERT(n->name != 0);
+ if (n != n->fs->root) {
+ ASSERT(n->parent != 0);
+ ASSERT(n->name != 0);
- mutex_lock(&n->parent->lock);
- hashtbl_remove(n->parent->children, n->name);
- if (n->ops->dispose) n->ops->dispose(n->data);
- mutex_unlock(&n->parent->lock);
+ mutex_lock(&n->parent->lock);
+ hashtbl_remove(n->parent->children, n->name);
+ if (n->ops->dispose) n->ops->dispose(n->data);
+ mutex_unlock(&n->parent->lock);
- unref_fs_node(n->parent);
- unref_fs(n->fs);
+ unref_fs_node(n->parent);
+ unref_fs(n->fs);
+ } else {
+ ASSERT(n->fs->refs == 0);
+ if (n->ops->dispose) n->ops->dispose(n->data);
+ }
- if (n->children != 0) delete_hashtbl(n->children);
+ if (n->children != 0) {
+ ASSERT(hashtbl_count(n->children) == 0);
+ delete_hashtbl(n->children);
+ }
free(n->name);
free(n);
} else {
@@ -251,7 +261,7 @@ fs_node_t* fs_walk_path_except_last(fs_node_t* from, const char* path, char* las
bool fs_create(fs_t *fs, const char* file, int type) {
char name[DIR_MAX];
- fs_node_t *n = fs_walk_path_except_last(&fs->root, file, name);
+ fs_node_t *n = fs_walk_path_except_last(fs->root, file, name);
if (n == 0) return false;
mutex_lock(&n->lock);
@@ -265,7 +275,7 @@ bool fs_create(fs_t *fs, const char* file, int type) {
bool fs_delete(fs_t *fs, const char* file) {
char name[DIR_MAX];
- fs_node_t* n = fs_walk_path_except_last(&fs->root, file, name);
+ fs_node_t* n = fs_walk_path_except_last(fs->root, file, name);
if (n == 0) return false;
if (n->children != 0) {
@@ -283,11 +293,11 @@ bool fs_delete(fs_t *fs, const char* file) {
bool fs_move(fs_t *fs, const char* from, const char* to) {
char old_name[DIR_MAX];
- fs_node_t *old_parent = fs_walk_path_except_last(&fs->root, from, old_name);
+ fs_node_t *old_parent = fs_walk_path_except_last(fs->root, from, old_name);
if (old_parent == 0) return false;
char new_name[DIR_MAX];
- fs_node_t *new_parent = fs_walk_path_except_last(&fs->root, to, new_name);
+ fs_node_t *new_parent = fs_walk_path_except_last(fs->root, to, new_name);
if (new_parent == 0) {
unref_fs_node(old_parent);
return false;
@@ -343,7 +353,7 @@ end:
}
bool fs_stat(fs_t *fs, const char* file, stat_t *st) {
- fs_node_t* n = fs_walk_path(&fs->root, file);
+ fs_node_t* n = fs_walk_path(fs->root, file);
if (n == 0) return false;
mutex_lock(&n->lock);
@@ -359,10 +369,10 @@ bool fs_stat(fs_t *fs, const char* file, stat_t *st) {
// =================== //
fs_handle_t* fs_open(fs_t *fs, const char* file, int mode) {
- fs_node_t *n = fs_walk_path(&fs->root, file);
+ fs_node_t *n = fs_walk_path(fs->root, file);
if (n == 0 && (mode & FM_CREATE)) {
if (fs_create(fs, file, FT_REGULAR)) {
- n = fs_walk_path(&fs->root, file);
+ n = fs_walk_path(fs->root, file);
}
}
if (n == 0) return 0;