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 // VOP_LOOKUP returns the vnode locked
*result = &newnode->vnode; *result = &newnode->vnode;
VOP_LOCK(*result); if (newnode != node)
VOP_LOCK(*result);
cleanup: cleanup:
if (err && newnode) { if (err && newnode) {
@@ -1487,9 +1488,7 @@ static int ext2_symlink(vnode_t *vnode, char *name, vattr_t *attr, char *path, c
if (err) if (err)
return 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; ext2node_t *newnode = (ext2node_t *)newvnode;
VOP_UNLOCK(newvnode);
if (linklen <= 60) { if (linklen <= 60) {
// store it in the inode // 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); VOP_RELEASE(newvnode);
cleanup: cleanup:
if (err) if (err) {
ASSERT_UNCLEAN(fs, VOP_UNLINK(vnode, name, cred) == 0); ASSERT_UNCLEAN(fs, VOP_UNLINK(vnode, newvnode, name, cred) == 0);
} else {
VOP_UNLOCK(newvnode); // locked by internalcreate
}
return err; return err;
} }
@@ -1582,22 +1585,16 @@ static int handleinodeunlink(ext2fs_t *fs, ext2node_t *node, int inode) {
return err; 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 inode = 0;
int err = removedent(fs, node, name, &inode); int err = removedent(fs, node, name, &inode);
if (err) if (err)
return err; return err;
err = handleinodeunlink(fs, node, inode); 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; return err;
} }
@@ -1686,7 +1683,7 @@ static int ext2_rename(vnode_t *sourcedir, char *oldname, vnode_t *targetdir, ch
if (ext2sourcenode->id == oldinode) { if (ext2sourcenode->id == oldinode) {
// link still points to the same inode, unlink it // link still points to the same inode, unlink it
err = internalunlink(fs, ext2sourcedirnode, oldname); err = VOP_UNLINK(sourcedir, source, oldname, NULL);
} }
cleanup: 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; 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; tmpfsnode_t *tmpnode = (tmpfsnode_t *)node;
if (node->type != V_TYPE_DIR) if (node->type != V_TYPE_DIR)
return ENOTDIR; return ENOTDIR;
@@ -254,6 +254,7 @@ static int tmpfs_unlink(vnode_t *node, char *name, cred_t *cred) {
vnode_t *unlinknode = r; vnode_t *unlinknode = r;
tmpfsnode_t *unlinktmpnode = r; tmpfsnode_t *unlinktmpnode = r;
__assert(child == unlinknode);
err = hashtable_remove(&tmpnode->children, name, namelen); err = hashtable_remove(&tmpnode->children, name, namelen);
if (err) if (err)
+46 -2
View File
@@ -40,6 +40,15 @@ int vfs_pollstub(vnode_t *node, struct polldata *, int events) {
return revents; return revents;
} }
static int noop() {
return 0;
}
static vops_t vnops = {
.lock = noop,
.unlock = noop
};
void vfs_init() { void vfs_init() {
__assert(hashtable_init(&fstable, 20) == 0); __assert(hashtable_init(&fstable, 20) == 0);
vfsroot = alloc(sizeof(vnode_t)); vfsroot = alloc(sizeof(vnode_t));
@@ -47,6 +56,7 @@ void vfs_init() {
SPINLOCK_INIT(listlock); SPINLOCK_INIT(listlock);
vfsroot->type = V_TYPE_DIR; vfsroot->type = V_TYPE_DIR;
vfsroot->refcount = 1; vfsroot->refcount = 1;
vfsroot->ops = &vnops;
} }
int vfs_register(vfsops_t *ops, char *name) { 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; return err;
} }
vnode_t *new = ref; vnode_t *new = tmp;
err = VOP_OPEN(&new, flags, getcred()); err = VOP_OPEN(&new, flags, getcred());
if (err) { if (err) {
VOP_RELEASE(tmp); VOP_RELEASE(tmp);
@@ -455,7 +465,25 @@ int vfs_unlink(vnode_t *ref, char *path) {
if (err) if (err)
goto cleanup; 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 // locked by vfs_lookup
VOP_UNLOCK(parent); VOP_UNLOCK(parent);
VOP_RELEASE(parent); VOP_RELEASE(parent);
@@ -509,7 +537,9 @@ int vfs_lookup(vnode_t **result, vnode_t *start, char *path, char *lastcomp, int
return e; return e;
if ((flags & VFS_LOOKUP_INPUTLOCKED) == 0) { if ((flags & VFS_LOOKUP_INPUTLOCKED) == 0) {
arch_e9_puts("lock1\n");
VOP_LOCK(r); VOP_LOCK(r);
arch_e9_puts("lock1ok\n");
} }
VOP_HOLD(r); VOP_HOLD(r);
@@ -540,8 +570,10 @@ int vfs_lookup(vnode_t **result, vnode_t *start, char *path, char *lastcomp, int
error = 0; error = 0;
VOP_HOLD(current); VOP_HOLD(current);
arch_e9_puts("lock2\n");
if ((flags & VFS_LOOKUP_INPUTLOCKED) == 0 || current != start) if ((flags & VFS_LOOKUP_INPUTLOCKED) == 0 || current != start)
VOP_LOCK(current); VOP_LOCK(current);
arch_e9_puts("lock2ok\n");
for (int i = 0; i < pathlen; ++i) { for (int i = 0; i < pathlen; ++i) {
if (compbuffer[i] == '\0') 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; islast = j == pathlen;
} }
arch_e9_puts("component: ");
arch_e9_puts(component);
if (islast && (flags & VFS_LOOKUP_PARENT)) { if (islast && (flags & VFS_LOOKUP_PARENT)) {
__assert(lastcomp); __assert(lastcomp);
strcpy(lastcomp, component); strcpy(lastcomp, component);
break; break;
} }
if (strcmp(component, "..") == 0) { if (strcmp(component, "..") == 0) {
// if the tree root, skip to next component // if the tree root, skip to next component
vnode_t *root = NULL; 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 the root of a mounted fs, go to
if (current->flags & V_FLAGS_ROOT) { if (current->flags & V_FLAGS_ROOT) {
vnode_t *n = lowestnodeinmp(current); vnode_t *n = lowestnodeinmp(current);
arch_e9_puts("lock3\n");
if (n != current) { if (n != current) {
VOP_HOLD(n); VOP_HOLD(n);
VOP_UNLOCK(current); VOP_UNLOCK(current);
@@ -588,6 +625,7 @@ int vfs_lookup(vnode_t **result, vnode_t *start, char *path, char *lastcomp, int
current = n; current = n;
VOP_LOCK(current); 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) if (error)
break; break;
arch_e9_puts("lookup\n");
error = VOP_LOOKUP(current, component, &next, getcred()); error = VOP_LOOKUP(current, component, &next, getcred());
arch_e9_puts("lookupok\n");
if (error) if (error)
break; break;
@@ -614,11 +654,13 @@ int vfs_lookup(vnode_t **result, vnode_t *start, char *path, char *lastcomp, int
} }
if (r != next) { if (r != next) {
arch_e9_puts("lock4\n");
VOP_HOLD(r); VOP_HOLD(r);
VOP_UNLOCK(next); VOP_UNLOCK(next);
VOP_RELEASE(next); VOP_RELEASE(next);
next = r; next = r;
VOP_LOCK(next); VOP_LOCK(next);
arch_e9_puts("lock4ok\n");
} }
// dereference symlink // 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 // 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); error = vfs_lookup(&derefresult, derefstart, linkderef, NULL, pass);
arch_e9_puts("it1ok\n");
if (*linkderef == '/') if (*linkderef == '/')
VOP_RELEASE(derefstart); 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 (*setattr)(vnode_t *node, vattr_t *attr, int attrs, cred_t *cred);
int (*poll)(vnode_t *node, struct polldata *, int events); int (*poll)(vnode_t *node, struct polldata *, int events);
int (*access)(vnode_t *node, mode_t mode, cred_t *cred); 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 (*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 (*symlink)(vnode_t *parent, char *name, vattr_t *attr, char *path, cred_t *cred);
int (*readlink)(vnode_t *parent, char **link, 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_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_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_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_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_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) #define VOP_READLINK(v, l, c) (v)->ops->readlink(v, l, c)