vfs: change VOP_UNLINK parameters, more fixes

This commit is contained in:
Matheus
2024-08-26 22:41:01 -03:00
parent 0236ad663f
commit 76c74cfca1
4 changed files with 63 additions and 21 deletions
+13 -16
View File
@@ -1176,7 +1176,8 @@ static int ext2_lookup(vnode_t *vnode, char *name, vnode_t **result, cred_t *cre
// VOP_LOOKUP returns the vnode locked
*result = &newnode->vnode;
VOP_LOCK(*result);
if (newnode != node)
VOP_LOCK(*result);
cleanup:
if (err && newnode) {
@@ -1487,9 +1488,7 @@ static int ext2_symlink(vnode_t *vnode, char *name, vattr_t *attr, char *path, c
if (err)
return err;
// no lock needed, not gonna be accessed by anyone else as the direcotry lock is held
ext2node_t *newnode = (ext2node_t *)newvnode;
VOP_UNLOCK(newvnode);
if (linklen <= 60) {
// store it in the inode
@@ -1511,8 +1510,12 @@ static int ext2_symlink(vnode_t *vnode, char *name, vattr_t *attr, char *path, c
VOP_RELEASE(newvnode);
cleanup:
if (err)
ASSERT_UNCLEAN(fs, VOP_UNLINK(vnode, name, cred) == 0);
if (err) {
ASSERT_UNCLEAN(fs, VOP_UNLINK(vnode, newvnode, name, cred) == 0);
} else {
VOP_UNLOCK(newvnode); // locked by internalcreate
}
return err;
}
@@ -1582,22 +1585,16 @@ static int handleinodeunlink(ext2fs_t *fs, ext2node_t *node, int inode) {
return err;
}
static int internalunlink(ext2fs_t *fs, ext2node_t *node, char *name) {
static int ext2_unlink(vnode_t *vnode, vnode_t *child, char *name, cred_t *cred) {
ext2node_t *node = (ext2node_t *)vnode;
ext2fs_t *fs = (ext2fs_t *)vnode->vfs;
int inode = 0;
int err = removedent(fs, node, name, &inode);
if (err)
return err;
err = handleinodeunlink(fs, node, inode);
return err;
}
// TODO name -> child, name
static int ext2_unlink(vnode_t *vnode, char *name, cred_t *cred) {
ext2node_t *node = (ext2node_t *)vnode;
ext2fs_t *fs = (ext2fs_t *)vnode->vfs;
int err = internalunlink(fs, node, name);
return err;
}
@@ -1686,7 +1683,7 @@ static int ext2_rename(vnode_t *sourcedir, char *oldname, vnode_t *targetdir, ch
if (ext2sourcenode->id == oldinode) {
// link still points to the same inode, unlink it
err = internalunlink(fs, ext2sourcedirnode, oldname);
err = VOP_UNLINK(sourcedir, source, oldname, NULL);
}
cleanup:
+2 -1
View File
@@ -235,7 +235,7 @@ static int tmpfs_access(vnode_t *vnode, mode_t mode, cred_t *cred) {
return auth_filesystem_check(cred, auth_filesystem_convertaccess(mode), vnode) ? EACCES : 0;
}
static int tmpfs_unlink(vnode_t *node, char *name, cred_t *cred) {
static int tmpfs_unlink(vnode_t *node, vnode_t *child, char *name, cred_t *cred) {
tmpfsnode_t *tmpnode = (tmpfsnode_t *)node;
if (node->type != V_TYPE_DIR)
return ENOTDIR;
@@ -254,6 +254,7 @@ static int tmpfs_unlink(vnode_t *node, char *name, cred_t *cred) {
vnode_t *unlinknode = r;
tmpfsnode_t *unlinktmpnode = r;
__assert(child == unlinknode);
err = hashtable_remove(&tmpnode->children, name, namelen);
if (err)
+46 -2
View File
@@ -40,6 +40,15 @@ int vfs_pollstub(vnode_t *node, struct polldata *, int events) {
return revents;
}
static int noop() {
return 0;
}
static vops_t vnops = {
.lock = noop,
.unlock = noop
};
void vfs_init() {
__assert(hashtable_init(&fstable, 20) == 0);
vfsroot = alloc(sizeof(vnode_t));
@@ -47,6 +56,7 @@ void vfs_init() {
SPINLOCK_INIT(listlock);
vfsroot->type = V_TYPE_DIR;
vfsroot->refcount = 1;
vfsroot->ops = &vnops;
}
int vfs_register(vfsops_t *ops, char *name) {
@@ -131,7 +141,7 @@ int vfs_open(vnode_t *ref, char *path, int flags, vnode_t **res) {
return err;
}
vnode_t *new = ref;
vnode_t *new = tmp;
err = VOP_OPEN(&new, flags, getcred());
if (err) {
VOP_RELEASE(tmp);
@@ -455,7 +465,25 @@ int vfs_unlink(vnode_t *ref, char *path) {
if (err)
goto cleanup;
VOP_UNLINK(parent, component, getcred());
vnode_t *child = NULL;
err = VOP_LOOKUP(parent, component, &child, getcred());
if (err) {
VOP_UNLOCK(parent);
goto cleanup;
}
// TODO auth check
if (0) {
// locked by VOP_LOOKUP
VOP_UNLOCK(child);
// locked by vfs_lookup
VOP_UNLOCK(parent);
return err;
}
err = VOP_UNLINK(parent, child, component, getcred());
// locked by VOP_LOOKUP
VOP_UNLOCK(child);
// locked by vfs_lookup
VOP_UNLOCK(parent);
VOP_RELEASE(parent);
@@ -509,7 +537,9 @@ int vfs_lookup(vnode_t **result, vnode_t *start, char *path, char *lastcomp, int
return e;
if ((flags & VFS_LOOKUP_INPUTLOCKED) == 0) {
arch_e9_puts("lock1\n");
VOP_LOCK(r);
arch_e9_puts("lock1ok\n");
}
VOP_HOLD(r);
@@ -540,8 +570,10 @@ int vfs_lookup(vnode_t **result, vnode_t *start, char *path, char *lastcomp, int
error = 0;
VOP_HOLD(current);
arch_e9_puts("lock2\n");
if ((flags & VFS_LOOKUP_INPUTLOCKED) == 0 || current != start)
VOP_LOCK(current);
arch_e9_puts("lock2ok\n");
for (int i = 0; i < pathlen; ++i) {
if (compbuffer[i] == '\0')
@@ -563,12 +595,16 @@ int vfs_lookup(vnode_t **result, vnode_t *start, char *path, char *lastcomp, int
islast = j == pathlen;
}
arch_e9_puts("component: ");
arch_e9_puts(component);
if (islast && (flags & VFS_LOOKUP_PARENT)) {
__assert(lastcomp);
strcpy(lastcomp, component);
break;
}
if (strcmp(component, "..") == 0) {
// if the tree root, skip to next component
vnode_t *root = NULL;
@@ -581,6 +617,7 @@ int vfs_lookup(vnode_t **result, vnode_t *start, char *path, char *lastcomp, int
// if the root of a mounted fs, go to
if (current->flags & V_FLAGS_ROOT) {
vnode_t *n = lowestnodeinmp(current);
arch_e9_puts("lock3\n");
if (n != current) {
VOP_HOLD(n);
VOP_UNLOCK(current);
@@ -588,6 +625,7 @@ int vfs_lookup(vnode_t **result, vnode_t *start, char *path, char *lastcomp, int
current = n;
VOP_LOCK(current);
}
arch_e9_puts("lock3ok\n");
}
}
@@ -596,7 +634,9 @@ int vfs_lookup(vnode_t **result, vnode_t *start, char *path, char *lastcomp, int
if (error)
break;
arch_e9_puts("lookup\n");
error = VOP_LOOKUP(current, component, &next, getcred());
arch_e9_puts("lookupok\n");
if (error)
break;
@@ -614,11 +654,13 @@ int vfs_lookup(vnode_t **result, vnode_t *start, char *path, char *lastcomp, int
}
if (r != next) {
arch_e9_puts("lock4\n");
VOP_HOLD(r);
VOP_UNLOCK(next);
VOP_RELEASE(next);
next = r;
VOP_LOCK(next);
arch_e9_puts("lock4ok\n");
}
// dereference symlink
@@ -652,7 +694,9 @@ int vfs_lookup(vnode_t **result, vnode_t *start, char *path, char *lastcomp, int
}
// TODO possible deadlock when input vnode is locked and the vfs_lookup would lock it
arch_e9_puts("it1\n");
error = vfs_lookup(&derefresult, derefstart, linkderef, NULL, pass);
arch_e9_puts("it1ok\n");
if (*linkderef == '/')
VOP_RELEASE(derefstart);
+2 -2
View File
@@ -126,7 +126,7 @@ typedef struct vops_t {
int (*setattr)(vnode_t *node, vattr_t *attr, int attrs, cred_t *cred);
int (*poll)(vnode_t *node, struct polldata *, int events);
int (*access)(vnode_t *node, mode_t mode, cred_t *cred);
int (*unlink)(vnode_t *node, char *name, cred_t *cred);
int (*unlink)(vnode_t *node, vnode_t *child, char *name, cred_t *cred);
int (*link)(vnode_t *node, vnode_t *dir, char *name, cred_t *cred);
int (*symlink)(vnode_t *parent, char *name, vattr_t *attr, char *path, cred_t *cred);
int (*readlink)(vnode_t *parent, char **link, cred_t *cred);
@@ -180,7 +180,7 @@ typedef struct vops_t {
#define VOP_GETATTR(v, a, c) (v)->ops->getattr(v, a, c)
#define VOP_SETATTR(v, a, w, c) (v)->ops->setattr(v, a, w, c)
#define VOP_ACCESS(v, m, c) (v)->ops->access(v, m, c)
#define VOP_UNLINK(v, n, c) (v)->ops->unlink(v, n, c)
#define VOP_UNLINK(v, ch, n, c) (v)->ops->unlink(v, ch, n, c)
#define VOP_LINK(v, d, n, c) (v)->ops->link(v, d, n, c)
#define VOP_SYMLINK(v, n, a, p, c) (v)->ops->symlink(v, n, a, p, c)
#define VOP_READLINK(v, l, c) (v)->ops->readlink(v, l, c)