From 881be872675e4cff153c27c641980451c4a3f479 Mon Sep 17 00:00:00 2001 From: dzwdz Date: Sun, 14 Jul 2024 19:40:31 +0200 Subject: kernel: make the adhoc VfsQueue queues use ReqQueue instead I'm still not sure if I should use sys/queue.h for this. But yeah, this is more consistent, and it will also let me switch over to O(1) insertions later on. --- src/kernel/vfs/mount.c | 1 - src/kernel/vfs/procfs.c | 1 - src/kernel/vfs/request.c | 58 ++++++++++++++++++++---------------------------- src/kernel/vfs/request.h | 34 +++++++++++++--------------- 4 files changed, 39 insertions(+), 55 deletions(-) (limited to 'src/kernel/vfs') diff --git a/src/kernel/vfs/mount.c b/src/kernel/vfs/mount.c index 15d1382..fa5d65b 100644 --- a/src/kernel/vfs/mount.c +++ b/src/kernel/vfs/mount.c @@ -15,7 +15,6 @@ void vfs_root_register(const char *path, void (*accept)(VfsReq *)) { *backend = (VfsBackend) { .is_user = false, .usehcnt = 1, - .provhcnt = 1, .kern.accept = accept, }; *mount = (VfsMount){ diff --git a/src/kernel/vfs/procfs.c b/src/kernel/vfs/procfs.c index 79dfdc0..86042cd 100644 --- a/src/kernel/vfs/procfs.c +++ b/src/kernel/vfs/procfs.c @@ -185,7 +185,6 @@ procfs_backend(Proc *proc) VfsBackend *be = kzalloc(sizeof(VfsBackend), "kern fs"); *be = (VfsBackend) { .is_user = false, - .provhcnt = 1, .usehcnt = 1, .kern.accept = procfs_accept, .kern.data = proc, diff --git a/src/kernel/vfs/request.c b/src/kernel/vfs/request.c index 8f44afb..58e2987 100644 --- a/src/kernel/vfs/request.c +++ b/src/kernel/vfs/request.c @@ -52,8 +52,7 @@ vfsreq_dispatchcopy(VfsReq tmpl) vfsreq_finish_short(req, -EINVAL); return; } - assert(req->queue_next == NULL); - assert(req->postqueue_next == NULL); + assert(req->reqqueue_next == NULL); if (backend == NULL) { /* null mount - probably never had a real backend */ @@ -111,8 +110,7 @@ vfsreq_finish(VfsReq *req, char __user *stored, long ret, int flags, Proc *handl vfsback_userdown(req->backend); } - assert(req->queue_next == NULL); - assert(req->postqueue_next == NULL); + assert(req->reqqueue_next == NULL); if (req->caller) { assert(req->caller->state == PS_WAITS4FS); @@ -134,17 +132,11 @@ vfsback_useraccept(VfsReq *req) backend = req->backend; assert(backend); assert(backend->is_user); - if (backend->provhcnt == 0) { + if (backend->user.provhcnt == 0) { vfsreq_finish_short(req, -EPIPE); return; } else if (backend->user.handler == NULL) { - /* queue the request up */ - // TODO use postqueue - VfsReq **it = &backend->queue; - while (*it != NULL) { /* find a free spot in queue */ - it = &(*it)->queue_next; - } - *it = req; + reqqueue_join(&backend->user.queue, req); return; } @@ -194,8 +186,8 @@ vfsback_useraccept(VfsReq *req) static void vfsback_checkfree(VfsBackend *b) { - if (b->usehcnt == 0 && b->provhcnt == 0) { - assert(!b->queue); + if (b->is_user && b->usehcnt == 0 && b->user.provhcnt == 0) { + assert(b->user.queue.head == NULL); kfree(b); } } @@ -227,54 +219,52 @@ void vfsback_provdown(VfsBackend *b) { assert(b); - assert(0 < b->provhcnt); - b->provhcnt--; - if (b->provhcnt == 0) { + assert(b->is_user); + assert(0 < b->user.provhcnt); + b->user.provhcnt--; + if (b->user.provhcnt == 0) { + assert(b->is_user); /* discard everything in the queue */ - VfsReq *q = b->queue; - while (q) { - VfsReq *q2 = q->queue_next; - q->queue_next = NULL; + VfsReq *q; + while ((q = reqqueue_pop(&b->user.queue))) { vfsreq_finish_short(q, -EPIPE); - q = q2; } - b->queue = NULL; } vfsback_checkfree(b); } void -postqueue_init(ReqQueue *q) +reqqueue_init(ReqQueue *q) { q->head = NULL; } void -postqueue_join(ReqQueue *q, VfsReq *req) +reqqueue_join(ReqQueue *q, VfsReq *req) { - if (req->postqueue_next) + if (req->reqqueue_next) panic_invalid_state(); VfsReq **it = &q->head; while (*it != NULL) { - it = &(*it)->postqueue_next; + it = &(*it)->reqqueue_next; } *it = req; } VfsReq * -postqueue_pop(ReqQueue *q) +reqqueue_pop(ReqQueue *q) { VfsReq *req = q->head; if (req) { - q->head = req->postqueue_next; - req->postqueue_next = NULL; + q->head = req->reqqueue_next; + req->reqqueue_next = NULL; } return req; } void -postqueue_ringreadall(ReqQueue *q, ring_t *r) +reqqueue_ringreadall(ReqQueue *q, ring_t *r) { VfsReq **queue = &q->head; /* whatever */ VfsReq *req; @@ -283,15 +273,15 @@ postqueue_ringreadall(ReqQueue *q, ring_t *r) if (ring_used(r) == 0) return; /* read as much as the biggest request wants */ - for (req = *queue; req; req = req->postqueue_next) + for (req = *queue; req; req = req->reqqueue_next) mlen = max(mlen, req->output.len); mlen = min(mlen, sizeof tmp); mlen = ring_get(r, tmp, mlen); while (*queue) { req = *queue; - *queue = req->postqueue_next; - req->postqueue_next = NULL; + *queue = req->reqqueue_next; + req->reqqueue_next = NULL; size_t ret = min(mlen, req->output.len); assert(req->type == VFSOP_READ); diff --git a/src/kernel/vfs/request.h b/src/kernel/vfs/request.h index 616c044..6786e72 100644 --- a/src/kernel/vfs/request.h +++ b/src/kernel/vfs/request.h @@ -4,6 +4,10 @@ #include #include +struct ReqQueue { + VfsReq *head; +}; + struct VfsBackend { /* amount of using references * VfsMount @@ -11,17 +15,15 @@ struct VfsBackend { * Handle * once it reaches 0, it'll never increase */ size_t usehcnt; /* VfsMount */ - /* amount of providing references - * Proc - * 0 - orphaned, will never increase */ - // TODO move this into .user - size_t provhcnt; - VfsReq *queue; bool is_user; union { struct { Proc *handler; + ReqQueue queue; /* kernel backends keep their own queues */ + /* amount of processes that control this backend + * won't ever increase if it becomes 0 */ + size_t provhcnt; } user; struct { void (*accept)(VfsReq *); @@ -56,10 +58,7 @@ struct VfsReq { Proc *caller; VfsBackend *backend; - VfsReq *queue_next; - VfsReq *postqueue_next; /* used by kernel backends */ - /* only one of these queues is in use at a given moment, they could - * be merged into a single field */ + VfsReq *reqqueue_next; }; /** Assigns the vfs_request to the caller, and dispatches the call */ @@ -79,13 +78,10 @@ void vfsback_userdown(VfsBackend *); /** Decrements the "provider" reference count. */ void vfsback_provdown(VfsBackend *); -struct ReqQueue { - VfsReq *head; -}; -void postqueue_init(ReqQueue *q); -void postqueue_join(ReqQueue *q, VfsReq *req); -VfsReq *postqueue_pop(ReqQueue *q); +void reqqueue_init(ReqQueue *q); +void reqqueue_join(ReqQueue *q, VfsReq *req); +VfsReq *reqqueue_pop(ReqQueue *q); -/** If there are any pending read requests, and the ring buffer isn't empty, fulfill them - * all with a single read. */ -void postqueue_ringreadall(ReqQueue *q, ring_t *r); +/** If there are any pending read requests, and the ring buffer isn't empty, + * fulfill them all with a single read. */ +void reqqueue_ringreadall(ReqQueue *q, ring_t *r); -- cgit v1.2.3