From e65d58357aaff7c1d05c06753538383478c1b0e9 Mon Sep 17 00:00:00 2001 From: dzwdz Date: Sun, 12 Sep 2021 12:47:51 +0200 Subject: vfs request refactor pt1 --- src/kernel/vfs/backend.c | 74 ------------------------------------------------ src/kernel/vfs/backend.h | 29 ------------------- src/kernel/vfs/mount.h | 2 +- src/kernel/vfs/request.c | 67 +++++++++++++++++++++++++++++++++++++++++++ src/kernel/vfs/request.h | 43 ++++++++++++++++++++++++++++ src/kernel/vfs/root.c | 12 ++++---- src/kernel/vfs/root.h | 4 +-- 7 files changed, 119 insertions(+), 112 deletions(-) delete mode 100644 src/kernel/vfs/backend.c delete mode 100644 src/kernel/vfs/backend.h create mode 100644 src/kernel/vfs/request.c create mode 100644 src/kernel/vfs/request.h (limited to 'src/kernel/vfs') diff --git a/src/kernel/vfs/backend.c b/src/kernel/vfs/backend.c deleted file mode 100644 index b9bc9af..0000000 --- a/src/kernel/vfs/backend.c +++ /dev/null @@ -1,74 +0,0 @@ -#include -#include -#include -#include -#include - -// dispatches a VFS operation to the correct process -_Noreturn void vfs_backend_dispatch(struct vfs_backend *backend, struct vfs_op op) { - struct vfs_op_request *req = kmalloc(sizeof *req); // freed in vfs_backend_finish - int ret; - *req = (struct vfs_op_request) { - .op = op, - .caller = process_current, - .backend = backend, - }; - - switch (backend->type) { - case VFS_BACK_ROOT: - ret = vfs_root_handler(req); - vfs_backend_finish(req, ret); - case VFS_BACK_USER: - process_current->state = PS_WAITS4FS; - if (backend->handler == NULL) { - // backend isn't ready yet, join the queue - assert(backend->queue == NULL); // TODO implement a proper queue - - backend->queue = process_current; - process_current->pending_req = req; - process_switch_any(); - } else { - vfs_request_pass2handler(req); - } - default: - panic(); - } -} - -_Noreturn void vfs_request_pass2handler(struct vfs_op_request *req) { - assert(req->backend->handler); - assert(req->backend->handler->state == PS_WAITS4REQUEST); - - req->backend->handler->state = PS_RUNNING; - // TODO pass the request to the process - process_switch(req->backend->handler); -} - -// returns from a VFS operation to the calling process -_Noreturn void vfs_backend_finish(struct vfs_op_request *req, int ret) { - struct process *caller = req->caller; - - if (req->op.type == VFSOP_OPEN && ret >= 0) { - // open() calls need special handling - // we need to wrap the id returned by the VFS in a handle passed to - // the client - handle_t handle = process_find_handle(req->caller); - if (handle < 0) panic(); - req->caller->handles[handle] = (struct handle){ - .type = HANDLE_FILE, - .file = { - .backend = req->backend, - .id = ret, - }, - }; - ret = handle; - } - - if (req->op.type == VFSOP_OPEN) - kfree(req->op.open.path); - - req->caller->state = PS_RUNNING; - regs_savereturn(&req->caller->regs, ret); - kfree(req); - process_switch(caller); -} diff --git a/src/kernel/vfs/backend.h b/src/kernel/vfs/backend.h deleted file mode 100644 index bc0dc45..0000000 --- a/src/kernel/vfs/backend.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once -#include - -enum vfs_backend_type { - VFS_BACK_ROOT, - VFS_BACK_USER, -}; - -// describes something which can act as an access function -struct vfs_backend { - enum vfs_backend_type type; - - // only used with VFS_BACK_USER - struct process *handler; - struct process *queue; -}; - -// describes an in-progress vfs call -struct vfs_op_request { - struct vfs_op op; - struct process *caller; - struct vfs_backend *backend; -}; - - -// these can switch processes -_Noreturn void vfs_backend_dispatch(struct vfs_backend *backend, struct vfs_op op); -_Noreturn void vfs_request_pass2handler(struct vfs_op_request *); -_Noreturn void vfs_backend_finish(struct vfs_op_request *, int ret); diff --git a/src/kernel/vfs/mount.h b/src/kernel/vfs/mount.h index ac55184..5fb6d16 100644 --- a/src/kernel/vfs/mount.h +++ b/src/kernel/vfs/mount.h @@ -1,5 +1,5 @@ #pragma once -#include +#include #include struct vfs_mount { diff --git a/src/kernel/vfs/request.c b/src/kernel/vfs/request.c new file mode 100644 index 0000000..1212aa4 --- /dev/null +++ b/src/kernel/vfs/request.c @@ -0,0 +1,67 @@ +#include +#include +#include +#include +#include + +// dispatches a VFS operation to the correct process +_Noreturn void vfs_request_create(struct vfs_request req) { + int ret; + switch (req.backend->type) { + case VFS_BACK_ROOT: + ret = vfs_root_handler(&req); + vfs_request_finish(&req, ret); + case VFS_BACK_USER: + process_current->state = PS_WAITS4FS; + if (req.backend->handler == NULL) { + // backend isn't ready yet, join the queue + assert(req.backend->queue == NULL); // TODO implement a proper queue + + req.backend->queue = process_current; + process_current->pending_req = req; + process_switch_any(); + } else { + vfs_request_pass2handler(&req); + } + default: + panic(); + } +} + +_Noreturn void vfs_request_pass2handler(struct vfs_request *req) { + assert(req->backend->handler); + assert(req->backend->handler->state == PS_WAITS4REQUEST); + + req->backend->handler->state = PS_RUNNING; + // TODO pass the request to the process + process_switch(req->backend->handler); +} + +// returns from a VFS operation to the calling process +_Noreturn void vfs_request_finish(struct vfs_request *req, int ret) { + struct process *caller = req->caller; + + if (req->type == VFSOP_OPEN && ret >= 0) { + // open() calls need special handling + // we need to wrap the id returned by the VFS in a handle passed to + // the client + handle_t handle = process_find_handle(req->caller); + if (handle < 0) panic(); + req->caller->handles[handle] = (struct handle){ + .type = HANDLE_FILE, + .file = { + .backend = req->backend, + .id = ret, + }, + }; + ret = handle; + } + + if (req->type == VFSOP_OPEN) + kfree(req->open.path); + + req->caller->state = PS_RUNNING; + regs_savereturn(&req->caller->regs, ret); + kfree(req); + process_switch(caller); +} diff --git a/src/kernel/vfs/request.h b/src/kernel/vfs/request.h new file mode 100644 index 0000000..3021c6f --- /dev/null +++ b/src/kernel/vfs/request.h @@ -0,0 +1,43 @@ +#pragma once + +enum vfs_backend_type { + VFS_BACK_ROOT, + VFS_BACK_USER, +}; + +// describes something which can act as an access function +struct vfs_backend { + enum vfs_backend_type type; + + // only used with VFS_BACK_USER + struct process *handler; + struct process *queue; +}; + +enum vfs_operation { + VFSOP_OPEN, + VFSOP_WRITE, +}; + +// describes an in-process vfs call +struct vfs_request { + enum vfs_operation type; + union { + struct { + char *path; + int path_len; + } open; + struct { + char __user *buf; + int buf_len; + int id; // filled in by the kernel + } rw; + }; + + struct process *caller; + struct vfs_backend *backend; +}; + +_Noreturn void vfs_request_create(struct vfs_request); +_Noreturn void vfs_request_pass2handler(struct vfs_request *); +_Noreturn void vfs_request_finish(struct vfs_request *, int ret); diff --git a/src/kernel/vfs/root.c b/src/kernel/vfs/root.c index 5b23555..29caf14 100644 --- a/src/kernel/vfs/root.c +++ b/src/kernel/vfs/root.c @@ -5,21 +5,21 @@ #include #include -int vfs_root_handler(struct vfs_op_request *req) { - switch (req->op.type) { +int vfs_root_handler(struct vfs_request *req) { + switch (req->type) { case VFSOP_OPEN: - if (req->op.open.path_len == 4 - && !memcmp(req->op.open.path, "/tty", 4)) { + if (req->open.path_len == 4 + && !memcmp(req->open.path, "/tty", 4)) { return 0; } return -1; case VFSOP_WRITE: - switch (req->op.rw.id) { + switch (req->rw.id) { // every id corresponds to a special file type // this is a shit way to do this but :shrug: case 0: { // tty struct virt_iter iter; - virt_iter_new(&iter, req->op.rw.buf, req->op.rw.buf_len, + virt_iter_new(&iter, req->rw.buf, req->rw.buf_len, req->caller->pages, true, false); while (virt_iter_next(&iter)) tty_write(iter.frag, iter.frag_len); diff --git a/src/kernel/vfs/root.h b/src/kernel/vfs/root.h index 617ba1c..501185e 100644 --- a/src/kernel/vfs/root.h +++ b/src/kernel/vfs/root.h @@ -1,5 +1,5 @@ #pragma once -#include +#include // the VFS provided to init -int vfs_root_handler(struct vfs_op_request *); +int vfs_root_handler(struct vfs_request *); -- cgit v1.2.3