diff options
author | dzwdz | 2022-05-03 20:31:50 +0200 |
---|---|---|
committer | dzwdz | 2022-05-03 20:31:50 +0200 |
commit | 9692ed2f93777e1060837b97687509f8a22c2b60 (patch) | |
tree | 967dd6c85e7f07dbc9277bc0d2a534a49091de26 /src/kernel | |
parent | beb55e5fcaa5098943352bd07eb27cf8b00e336c (diff) |
kernel: reference count mount objects, free them on process kills
Diffstat (limited to 'src/kernel')
-rw-r--r-- | src/kernel/proc.c | 7 | ||||
-rw-r--r-- | src/kernel/syscalls.c | 7 | ||||
-rw-r--r-- | src/kernel/vfs/mount.c | 16 | ||||
-rw-r--r-- | src/kernel/vfs/mount.h | 6 |
4 files changed, 34 insertions, 2 deletions
diff --git a/src/kernel/proc.c b/src/kernel/proc.c index ba19943..90570b8 100644 --- a/src/kernel/proc.c +++ b/src/kernel/proc.c @@ -72,6 +72,9 @@ struct process *process_fork(struct process *parent, int flags) { // no overflow check - if you manage to get 2^32 references to a handle you have bigger problems } + assert(child->mount); + child->mount->refs++; + child->id = next_pid++; return child; @@ -104,6 +107,10 @@ void process_free(struct process *p) { while (p->child) process_free(p->child); + // also could be done on kill + vfs_mount_remref(p->mount); + p->mount = NULL; + if (!p->parent) return; process_forget(p); pagedir_free(p->pages); // TODO could be done on kill diff --git a/src/kernel/syscalls.c b/src/kernel/syscalls.c index 57286f1..7748bc5 100644 --- a/src/kernel/syscalls.c +++ b/src/kernel/syscalls.c @@ -109,12 +109,17 @@ int _syscall_mount(handle_t hid, const char __user *path, int len) { } // otherwise backend == NULL // append to mount list + // TODO move to kernel/vfs/mount.c mount = kmalloc(sizeof *mount); mount->prev = process_current->mount; - mount->prefix = path_buf; + mount->prefix = path_buf; // owned mount->prefix_len = len; mount->backend = backend; + mount->refs = 1; process_current->mount = mount; + + kmalloc_sanity(mount); + kmalloc_sanity(mount->prefix); return 0; fail: diff --git a/src/kernel/vfs/mount.c b/src/kernel/vfs/mount.c index 423bf10..3fe192d 100644 --- a/src/kernel/vfs/mount.c +++ b/src/kernel/vfs/mount.c @@ -1,4 +1,5 @@ #include <kernel/mem/alloc.h> +#include <kernel/panic.h> #include <kernel/vfs/mount.h> #include <shared/mem.h> @@ -9,9 +10,10 @@ struct vfs_mount *vfs_mount_seed(void) { backend->potential_handlers = 1; *mount = (struct vfs_mount){ .prev = NULL, - .prefix = "", + .prefix = NULL, .prefix_len = 0, .backend = backend, + .refs = 1, // never to be freed }; return mount; } @@ -36,3 +38,15 @@ struct vfs_mount *vfs_mount_resolve( } return top; } + +void vfs_mount_remref(struct vfs_mount *mnt) { + assert(mnt); + assert(mnt->refs > 0); + if (--(mnt->refs) > 0) return; + + struct vfs_mount *prev = mnt->prev; + kfree(mnt->prefix); + kfree(mnt); + + if (prev) vfs_mount_remref(prev); +} diff --git a/src/kernel/vfs/mount.h b/src/kernel/vfs/mount.h index 5fb6d16..96a2d7b 100644 --- a/src/kernel/vfs/mount.h +++ b/src/kernel/vfs/mount.h @@ -7,9 +7,15 @@ struct vfs_mount { char *prefix; size_t prefix_len; struct vfs_backend *backend; + size_t refs; /* counts all references, atm from: + * - struct vfs_mount + * - struct proc + */ }; // prepares init's filesystem view struct vfs_mount *vfs_mount_seed(void); struct vfs_mount *vfs_mount_resolve( struct vfs_mount *top, const char *path, size_t path_len); +/** Decrements the reference count, potentially freeing the mount. */ +void vfs_mount_remref(struct vfs_mount *mnt); |