From de0d5cb8f9eaa601225892c28fd06a2ff6753f67 Mon Sep 17 00:00:00 2001 From: Matheus Date: Wed, 9 Sep 2026 16:26:10 -0300 Subject: [PATCH] vfs: root event signaling --- kernel-src/fs/vfs.c | 63 ++++++++++++++++++++++++++++++--- kernel-src/include/kernel/vfs.h | 5 ++- 2 files changed, 63 insertions(+), 5 deletions(-) diff --git a/kernel-src/fs/vfs.c b/kernel-src/fs/vfs.c index e3ecc6df..defb9fe0 100644 --- a/kernel-src/fs/vfs.c +++ b/kernel-src/fs/vfs.c @@ -13,6 +13,7 @@ #include #include #include +#include #define PATHNAME_MAX 512 #define MAXLINKDEPTH 64 @@ -43,6 +44,48 @@ int vfs_pollstub(vnode_t *node, struct polldata *, int events) { 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() { return 0; } @@ -71,6 +114,8 @@ void vfs_init() { vfsroot->ops = &vnops; advlock_cache = slab_newcache(sizeof(advlock_t), 0, advlock_ctor, NULL); __assert(advlock_cache); + list_init(&root_event_list); + MUTEX_INIT(&root_event_mutex); } 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_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 -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) return ELOOP; @@ -883,6 +928,7 @@ int vfs_lookup(vnode_t **result, vnode_t *start, char *path, char *lastcomp, int VOP_HOLD(current); VOP_LOCK(current); + bool current_locked = true; for (int i = 0; i < pathlen; ++i) { if (compbuffer[i] == '\0') @@ -943,8 +989,11 @@ int vfs_lookup(vnode_t **result, vnode_t *start, char *path, char *lastcomp, int break; // 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) - VOP_UNLOCK(current); + if (current != next) { + if (isdotdot == false) + VOP_UNLOCK(current); + current_locked = false; + } vnode_t *r = next; 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) { VOP_HOLD(r); VOP_UNLOCK(next); + if (current == next) + current_locked = false; VOP_RELEASE(next); next = r; 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 error = VOP_READLINK(next, &linkderef, getcred()); VOP_UNLOCK(next); + if (current == next) + current_locked = false; if (error) { VOP_RELEASE(next); break; @@ -1011,11 +1064,13 @@ int vfs_lookup(vnode_t **result, vnode_t *start, char *path, char *lastcomp, int VOP_RELEASE(current); current = next; + current_locked = true; i += complen; } if (error) { - VOP_UNLOCK(current); + if (current_locked) + VOP_UNLOCK(current); VOP_RELEASE(current); } else { // result is already locked here diff --git a/kernel-src/include/kernel/vfs.h b/kernel-src/include/kernel/vfs.h index 05c9f822..2afd2b1f 100644 --- a/kernel-src/include/kernel/vfs.h +++ b/kernel-src/include/kernel/vfs.h @@ -260,6 +260,9 @@ void vfs_init(); int vfs_mount(vnode_t *backing, vnode_t *pathref, char *path, char *name, void *data); 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_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); @@ -277,7 +280,7 @@ void vfs_inactive(vnode_t *node); #define VFS_LOOKUP_PARENT 0x20000000 #define VFS_LOOKUP_NOLINK 0x40000000 #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) { switch (type) {