vfs: root event signaling

This commit is contained in:
Matheus
2026-09-09 16:26:10 -03:00
parent abd1e45852
commit de0d5cb8f9
2 changed files with 63 additions and 5 deletions
+59 -4
View File
@@ -13,6 +13,7 @@
#include <kernel/auth.h> #include <kernel/auth.h>
#include <kernel/init.h> #include <kernel/init.h>
#include <kernel/slab.h> #include <kernel/slab.h>
#include <list.h>
#define PATHNAME_MAX 512 #define PATHNAME_MAX 512
#define MAXLINKDEPTH 64 #define MAXLINKDEPTH 64
@@ -43,6 +44,48 @@ int vfs_pollstub(vnode_t *node, struct polldata *, int events) {
return revents; return revents;
} }
typedef struct {
list_node_t list_node;
void (*fn)(void *);
void *ctx;
} root_event_waiter_t;
static list_t root_event_list;
static bool root_mounted;
static mutex_t root_event_mutex;
void vfs_root_event_signal(void) {
MUTEX_ACQUIRE(&root_event_mutex);
root_mounted = true;
MUTEX_RELEASE(&root_event_mutex);
list_for_each_safe (&root_event_list, node) {
root_event_waiter_t *rew = (root_event_waiter_t *)node;
rew->fn(rew->ctx);
free(rew);
}
}
int vfs_root_event_attach(void (*fn)(void *), void *ctx) {
root_event_waiter_t *rew = alloc(sizeof(root_event_waiter_t));
if (rew == NULL)
return ENOMEM;
MUTEX_ACQUIRE(&root_event_mutex);
if (root_mounted) {
MUTEX_RELEASE(&root_event_mutex);
free(rew);
return EBUSY;
}
rew->fn = fn;
rew->ctx = ctx;
list_push_back(&root_event_list, &rew->list_node);
MUTEX_RELEASE(&root_event_mutex);
return 0;
}
static int noop() { static int noop() {
return 0; return 0;
} }
@@ -71,6 +114,8 @@ void vfs_init() {
vfsroot->ops = &vnops; vfsroot->ops = &vnops;
advlock_cache = slab_newcache(sizeof(advlock_t), 0, advlock_ctor, NULL); advlock_cache = slab_newcache(sizeof(advlock_t), 0, advlock_ctor, NULL);
__assert(advlock_cache); __assert(advlock_cache);
list_init(&root_event_list);
MUTEX_INIT(&root_event_mutex);
} }
INIT_ROUTINE_DEFINE(vfs, INIT_ROUTINE_FLAGS_NONE, vfs_init, abc); INIT_ROUTINE_DEFINE(vfs, INIT_ROUTINE_FLAGS_NONE, vfs_init, abc);
@@ -850,7 +895,7 @@ static vnode_t *lowestnodeinmp(vnode_t *node) {
// if flags & VFS_LOOKUP_NOLINK, the last component will not be dereferenced if its a symbolic link // if flags & VFS_LOOKUP_NOLINK, the last component will not be dereferenced if its a symbolic link
// if flags & VFS_LOOKUP_INTERNAL, the first byte of flags will be the current count of symlinks transversed // if flags & VFS_LOOKUP_INTERNAL, the first byte of flags will be the current count of symlinks transversed
// this is not an external flag and is meant to be called from inside the function itself // this is not an external flag and is meant to be called from inside the function itself
int vfs_lookup(vnode_t **result, vnode_t *start, char *path, char *lastcomp, int flags) { int vfs_lookup(vnode_t **result, vnode_t *start, const char *path, char *lastcomp, int flags) {
if ((flags & VFS_LOOKUP_INTERNAL) && (flags & 0xff) > MAXLINKDEPTH) if ((flags & VFS_LOOKUP_INTERNAL) && (flags & 0xff) > MAXLINKDEPTH)
return ELOOP; return ELOOP;
@@ -883,6 +928,7 @@ int vfs_lookup(vnode_t **result, vnode_t *start, char *path, char *lastcomp, int
VOP_HOLD(current); VOP_HOLD(current);
VOP_LOCK(current); VOP_LOCK(current);
bool current_locked = true;
for (int i = 0; i < pathlen; ++i) { for (int i = 0; i < pathlen; ++i) {
if (compbuffer[i] == '\0') if (compbuffer[i] == '\0')
@@ -943,8 +989,11 @@ int vfs_lookup(vnode_t **result, vnode_t *start, char *path, char *lastcomp, int
break; break;
// if the current node is not the next one and VOP_LOOKUP didn't already by looking up "..", unlock it // if the current node is not the next one and VOP_LOOKUP didn't already by looking up "..", unlock it
if (current != next && isdotdot == false) if (current != next) {
VOP_UNLOCK(current); if (isdotdot == false)
VOP_UNLOCK(current);
current_locked = false;
}
vnode_t *r = next; vnode_t *r = next;
error = highestnodeinmp(next, &r); error = highestnodeinmp(next, &r);
@@ -959,6 +1008,8 @@ int vfs_lookup(vnode_t **result, vnode_t *start, char *path, char *lastcomp, int
if (r != next) { if (r != next) {
VOP_HOLD(r); VOP_HOLD(r);
VOP_UNLOCK(next); VOP_UNLOCK(next);
if (current == next)
current_locked = false;
VOP_RELEASE(next); VOP_RELEASE(next);
next = r; next = r;
VOP_LOCK(next); VOP_LOCK(next);
@@ -972,6 +1023,8 @@ int vfs_lookup(vnode_t **result, vnode_t *start, char *path, char *lastcomp, int
// next is already returned locked by VOP_LOOKUP // next is already returned locked by VOP_LOOKUP
error = VOP_READLINK(next, &linkderef, getcred()); error = VOP_READLINK(next, &linkderef, getcred());
VOP_UNLOCK(next); VOP_UNLOCK(next);
if (current == next)
current_locked = false;
if (error) { if (error) {
VOP_RELEASE(next); VOP_RELEASE(next);
break; break;
@@ -1011,11 +1064,13 @@ int vfs_lookup(vnode_t **result, vnode_t *start, char *path, char *lastcomp, int
VOP_RELEASE(current); VOP_RELEASE(current);
current = next; current = next;
current_locked = true;
i += complen; i += complen;
} }
if (error) { if (error) {
VOP_UNLOCK(current); if (current_locked)
VOP_UNLOCK(current);
VOP_RELEASE(current); VOP_RELEASE(current);
} else { } else {
// result is already locked here // result is already locked here
+4 -1
View File
@@ -260,6 +260,9 @@ void vfs_init();
int vfs_mount(vnode_t *backing, vnode_t *pathref, char *path, char *name, void *data); int vfs_mount(vnode_t *backing, vnode_t *pathref, char *path, char *name, void *data);
int vfs_register(vfsops_t *vfsops, char *name); int vfs_register(vfsops_t *vfsops, char *name);
void vfs_root_event_signal(void);
int vfs_root_event_attach(void (*fn)(void *), void *ctx);
int vfs_open(vnode_t *ref, char *path, int flags, vnode_t **result); int vfs_open(vnode_t *ref, char *path, int flags, vnode_t **result);
int vfs_close(vnode_t *node, int flags); int vfs_close(vnode_t *node, int flags);
int vfs_write_iovec(vnode_t *node, iovec_iterator_t *iovec_iterator, size_t size, uintmax_t offset, size_t *written, int flags); int vfs_write_iovec(vnode_t *node, iovec_iterator_t *iovec_iterator, size_t size, uintmax_t offset, size_t *written, int flags);
@@ -277,7 +280,7 @@ void vfs_inactive(vnode_t *node);
#define VFS_LOOKUP_PARENT 0x20000000 #define VFS_LOOKUP_PARENT 0x20000000
#define VFS_LOOKUP_NOLINK 0x40000000 #define VFS_LOOKUP_NOLINK 0x40000000
#define VFS_LOOKUP_INTERNAL 0x80000000 #define VFS_LOOKUP_INTERNAL 0x80000000
int vfs_lookup(vnode_t **result, vnode_t *start, char *path, char *lastcomp, int flags); int vfs_lookup(vnode_t **result, vnode_t *start, const char *path, char *lastcomp, int flags);
static inline mode_t vfs_getposixtype(int type) { static inline mode_t vfs_getposixtype(int type) {
switch (type) { switch (type) {