diff options
author | Alex Auvolat <alex.auvolat@ens.fr> | 2015-03-02 18:38:45 +0100 |
---|---|---|
committer | Alex Auvolat <alex.auvolat@ens.fr> | 2015-03-02 18:38:45 +0100 |
commit | 969c8cacc50e8c39ddbc19e05f3f5b98c34bde01 (patch) | |
tree | 1b137ea0e940e2dd422f1d56cb8e4b67cfc2d99c /src/kernel/user | |
parent | 1a5c518ee1536db50dccd8766ce78c3790aec059 (diff) | |
download | kogata-969c8cacc50e8c39ddbc19e05f3f5b98c34bde01.tar.gz kogata-969c8cacc50e8c39ddbc19e05f3f5b98c34bde01.zip |
Fix VFS reference counting.
Diffstat (limited to 'src/kernel/user')
-rw-r--r-- | src/kernel/user/vfs.c | 33 |
1 files changed, 16 insertions, 17 deletions
diff --git a/src/kernel/user/vfs.c b/src/kernel/user/vfs.c index 15f37cc..710326a 100644 --- a/src/kernel/user/vfs.c +++ b/src/kernel/user/vfs.c @@ -83,8 +83,6 @@ fs_t *fs_subfs(fs_t *fs, const char* root, int ok_modes) { subfs->root = new_root; - ref_fs(fs); - return subfs; } @@ -99,9 +97,13 @@ void ref_fs(fs_t *fs) { void unref_fs(fs_t *fs) { fs->refs--; if (fs->refs == 0) { - unref_fs_node(fs->root); + if (fs->from_fs != 0) { + unref_fs_node(fs->root); + } else { + ASSERT(fs->root->refs == 1); + if (fs->root->ops->dispose) fs->root->ops->dispose(fs->root->data); + } if (fs->ops->shutdown) fs->ops->shutdown(fs->data); - if (fs->from_fs) unref_fs(fs->from_fs); free(fs); } } @@ -119,21 +121,18 @@ void unref_fs_node(fs_node_t *n) { mutex_lock(&n->lock); n->refs--; if (n->refs == 0) { - if (n != n->fs->root) { - ASSERT(n->parent != 0); - ASSERT(n->name != 0); + ASSERT (n != n->fs->root); - 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); + ASSERT(n->parent != 0); + ASSERT(n->name != 0); - unref_fs_node(n->parent); - unref_fs(n->fs); - } else { - ASSERT(n->fs->refs == 0); - if (n->ops->dispose) n->ops->dispose(n->data); - } + 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); if (n->children != 0) { ASSERT(hashtbl_count(n->children) == 0); |