diff --git a/kernel-src/fs/tmpfs.c b/kernel-src/fs/tmpfs.c index 4d70cc8d..e509a8a5 100644 --- a/kernel-src/fs/tmpfs.c +++ b/kernel-src/fs/tmpfs.c @@ -291,7 +291,7 @@ static int tmpfs_unlink(vnode_t *node, vnode_t *child, char *name, cred_t *cred) if (child->type == V_TYPE_DIR) { // undo .. entry link - VOP_RELEASE(node); + // note that the parent unref happens only at freenode() time --tmpnode->attr.nlinks; } @@ -387,7 +387,7 @@ static int tmpfs_rename(vnode_t *source, vnode_t *sourcefile, char *oldname, vno if (sourcefile->type == V_TYPE_DIR && targetdir != sourcedir) { tmpfsnode_t *v = (tmpfsnode_t *)sourcefile; // handle .. entry - __assert(hashtable_set(&v->children, targetdir, "..", 3, false) == 0); + __assert(hashtable_set(&v->children, targetdir, "..", 2, false) == 0); sourcedir->attr.nlinks -= 1; targetdir->attr.nlinks += 1; @@ -396,6 +396,8 @@ static int tmpfs_rename(vnode_t *source, vnode_t *sourcefile, char *oldname, vno } if (oldnode) { + if (oldnode->type == V_TYPE_DIR) + VOP_HOLD(target); // account for the oldnode reference that will be released tmpfsnode_t *old_tmpnode = (tmpfsnode_t *)oldnode; --old_tmpnode->attr.nlinks; VOP_RELEASE(oldnode); @@ -492,6 +494,7 @@ static int tmpfs_getdents(vnode_t *node, dent_t *buffer, size_t count, uintmax_t } static int tmpfs_inactive(vnode_t *node) { + arch_e9_puts("tmpfs_inactive\n"); tmpfsnode_t *tmp_node = (tmpfsnode_t *)node; __assert(tmp_node->attr.nlinks == (node->type == V_TYPE_DIR ? 1 : 0)); if (node->type == V_TYPE_REGULAR) { diff --git a/kernel-src/fs/vfs.c b/kernel-src/fs/vfs.c index 6f13bc86..bacb10ba 100644 --- a/kernel-src/fs/vfs.c +++ b/kernel-src/fs/vfs.c @@ -334,18 +334,13 @@ int vfs_create(vnode_t *ref, char *path, vattr_t *attr, int type, vnode_t **node err = VOP_ACCESS(parent, V_ACCESS_WRITE, getcred()); if (err) { - VOP_UNLOCK(parent); - VOP_RELEASE(parent); goto cleanup_parent; } vnode_t *ret; err = VOP_CREATE(parent, component, attr, type, &ret, getcred()); - VOP_RELEASE(parent); - if (err) { - VOP_UNLOCK(parent); - goto cleanup; - } + if (err) + goto cleanup_parent; if (node) { *node = ret; @@ -356,6 +351,7 @@ int vfs_create(vnode_t *ref, char *path, vattr_t *attr, int type, vnode_t **node } cleanup_parent: + VOP_RELEASE(parent); VOP_UNLOCK(parent); cleanup: free(component); @@ -701,7 +697,12 @@ int vfs_unlink(vnode_t *ref, char *path) { if (err) goto cleanup; - bool isdotdot = strcmp(path, "..") == 0; + if (strcmp(component, "..") == 0 || strcmp(component, ".") == 0) { + VOP_UNLOCK(parent); + VOP_RELEASE(parent); + err = EBUSY; + goto cleanup; + } vnode_t *child = NULL; err = VOP_LOOKUP(parent, component, &child, getcred()); @@ -716,12 +717,11 @@ int vfs_unlink(vnode_t *ref, char *path) { goto cleanup_release; err = VOP_UNLINK(parent, child, component, getcred()); + cleanup_release: // locked by VOP_LOOKUP VOP_UNLOCK(child); - // locked by vfs_lookup, unlocked by VOP_LOOKUP if component is ".." - if (!isdotdot) - VOP_UNLOCK(parent); + VOP_UNLOCK(parent); VOP_RELEASE(child); VOP_RELEASE(parent);