diff options
author | Ian Moffett <ian@osmora.org> | 2024-06-28 23:19:09 -0400 |
---|---|---|
committer | Ian Moffett <ian@osmora.org> | 2024-06-28 23:19:09 -0400 |
commit | d516e8a27f1a52c92d39aada03ff92985b1fdf7e (patch) | |
tree | e9a4808cf6e2bf2da26c237622ea262e3778b000 /sys | |
parent | bbc4eeea0da272c704f00a23fe08bc6ddc021922 (diff) |
kernel: vfs: Add vnode refcount
Signed-off-by: Ian Moffett <ian@osmora.org>
Diffstat (limited to 'sys')
-rw-r--r-- | sys/include/sys/vnode.h | 4 | ||||
-rw-r--r-- | sys/kern/vfs_subr.c | 19 |
2 files changed, 23 insertions, 0 deletions
diff --git a/sys/include/sys/vnode.h b/sys/include/sys/vnode.h index 545fa2f..3f3b011 100644 --- a/sys/include/sys/vnode.h +++ b/sys/include/sys/vnode.h @@ -31,6 +31,7 @@ #define _SYS_VNODE_H_ #include <sys/types.h> +#include <sys/atomic.h> #include <sys/sio.h> #if defined(_KERNEL) @@ -42,8 +43,11 @@ struct vnode { int flags; void *data; const struct vops *vops; + uint32_t refcount; }; +#define vfs_vref(VP) (atomic_inc_int(&(VP)->refcount)) + /* Vnode type flags */ #define VNON 0x00 /* Uninitialized */ #define VREG 0x01 /* Regular file */ diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index b732cb4..0d4be72 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -30,6 +30,7 @@ #include <sys/vnode.h> #include <sys/errno.h> #include <sys/mount.h> +#include <sys/syslog.h> #include <vm/dynalloc.h> #include <string.h> @@ -46,6 +47,7 @@ vfs_alloc_vnode(struct vnode **res, int type) memset(vp, 0, sizeof(*vp)); vp->type = type; + vp->refcount = 1; *res = vp; return 0; } @@ -83,6 +85,23 @@ vfs_release_vnode(struct vnode *vp) if (vp == NULL) return -EINVAL; + + /* + * The refcount cannot be zero before we decrement it, + * something is quite wrong if this happens. + */ + if (vp->refcount == 0) { + kprintf("Cannot release vnode, bad refcount\n"); + return -EIO; + } + + /* + * Drop the reference and don't destroy the vnode + * if it's still not zero. + */ + if (atomic_dec_int(&vp->refcount) > 0) + return 0; + if (vops->reclaim != NULL) status = vops->reclaim(vp); if (status != 0) |