summaryrefslogtreecommitdiff
path: root/src/kernel/vfs
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel/vfs')
-rw-r--r--src/kernel/vfs/mount.c2
-rw-r--r--src/kernel/vfs/request.c62
-rw-r--r--src/kernel/vfs/request.h8
3 files changed, 47 insertions, 25 deletions
diff --git a/src/kernel/vfs/mount.c b/src/kernel/vfs/mount.c
index adf9b8c..15d1382 100644
--- a/src/kernel/vfs/mount.c
+++ b/src/kernel/vfs/mount.c
@@ -61,7 +61,7 @@ void vfs_mount_remref(VfsMount *mnt) {
VfsMount *prev = mnt->prev;
if (mnt->backend) {
- vfs_backend_refdown(mnt->backend, true);
+ vfsback_userdown(mnt->backend);
}
if (mnt->prefix_owned) {
kfree((void*)mnt->prefix);
diff --git a/src/kernel/vfs/request.c b/src/kernel/vfs/request.c
index e3f0316..8fe0114 100644
--- a/src/kernel/vfs/request.c
+++ b/src/kernel/vfs/request.c
@@ -80,11 +80,13 @@ void vfsreq_finish(VfsReq *req, char __user *stored, long ret,
assert((size_t)ret <= req->output.len);
}
- if (req->input.kern)
+ if (req->input.kern) {
kfree(req->input.buf_kern);
+ }
- if (req->backend)
- vfs_backend_refdown(req->backend, true);
+ if (req->backend) {
+ vfsback_userdown(req->backend);
+ }
if (req->caller) {
assert(req->caller->state == PS_WAITS4FS);
@@ -159,26 +161,28 @@ static void vfs_backend_user_accept(VfsReq *req) {
return;
}
-void vfs_backend_refdown(VfsBackend *b, bool use) {
- size_t *field = use ? &b->usehcnt : &b->provhcnt;
- assert(b);
- assert(0 < *field);
- *field -= 1;
-
- if (b->provhcnt == 0 && use == false) {
- VfsReq *q = b->queue;
- while (q) {
- VfsReq *q2 = q->queue_next;
- vfsreq_finish_short(q, -1);
- q = q2;
- }
- b->queue = NULL;
+static void
+vfsback_checkfree(VfsBackend *b)
+{
+ if (b->usehcnt == 0 && b->provhcnt == 0) {
+ assert(!b->queue);
+ kfree(b);
}
- if (b->usehcnt == 0 && use == true) {
+}
+
+void
+vfsback_userdown(VfsBackend *b)
+{
+ assert(b);
+ assert(0 < b->usehcnt);
+ b->usehcnt--;
+ if (b->usehcnt == 0) {
if (!b->is_user && b->kern.cleanup) {
b->kern.cleanup(b);
}
if (b->is_user && b->user.handler) {
+ /* tell the process that the filesystem won't receive any more
+ * requests */
Proc *p = b->user.handler;
b->user.handler = NULL;
assert(p->state == PS_WAITS4REQUEST);
@@ -186,8 +190,24 @@ void vfs_backend_refdown(VfsBackend *b, bool use) {
proc_setstate(p, PS_RUNNING);
}
}
- if (b->usehcnt == 0 && b->provhcnt == 0) {
- assert(!b->queue);
- kfree(b);
+ vfsback_checkfree(b);
+}
+
+void
+vfsback_provdown(VfsBackend *b)
+{
+ assert(b);
+ assert(0 < b->provhcnt);
+ b->provhcnt--;
+ if (b->provhcnt == 0) {
+ /* discard everything in the queue */
+ VfsReq *q = b->queue;
+ while (q) {
+ VfsReq *q2 = q->queue_next;
+ vfsreq_finish_short(q, -1);
+ q = q2;
+ }
+ b->queue = NULL;
}
+ vfsback_checkfree(b);
}
diff --git a/src/kernel/vfs/request.h b/src/kernel/vfs/request.h
index 182202c..2bd8c61 100644
--- a/src/kernel/vfs/request.h
+++ b/src/kernel/vfs/request.h
@@ -74,6 +74,8 @@ static inline void vfsreq_finish_short(VfsReq *req, long ret) {
/** Try to accept an enqueued request */
void vfs_backend_tryaccept(VfsBackend *);
-// TODO the bool arg is confusing. maybe this should just be a function
-// that verified the refcount and potentially frees the backend
-void vfs_backend_refdown(VfsBackend *, bool use);
+/** Decrements the "user" reference count. */
+void vfsback_userdown(VfsBackend *);
+
+/** Decrements the "provider" reference count. */
+void vfsback_provdown(VfsBackend *);