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/proc.h | 2 +- src/kernel/syscalls.c | 17 +++++++---- 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 +-- 9 files changed, 131 insertions(+), 119 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') diff --git a/src/kernel/proc.h b/src/kernel/proc.h index 0628ebf..13e4125 100644 --- a/src/kernel/proc.h +++ b/src/kernel/proc.h @@ -30,7 +30,7 @@ struct process { char __user *buf; size_t len; } death_msg; - struct vfs_op_request *pending_req; // PS_WAITS4FS + struct vfs_request pending_req; // PS_WAITS4FS }; struct vfs_mount *mount; diff --git a/src/kernel/syscalls.c b/src/kernel/syscalls.c index c1ba47a..fdf4b84 100644 --- a/src/kernel/syscalls.c +++ b/src/kernel/syscalls.c @@ -75,7 +75,7 @@ handle_t _syscall_open(const char __user *path, int len) { return -1; // copy the path to the kernel - // path_buf gets freed in vfs_backend_finish + // path_buf gets freed in vfs_request_finish path_buf = kmalloc(len); if (!virt_cpy_from(process_current->pages, path_buf, path, len)) goto fail; @@ -86,12 +86,15 @@ handle_t _syscall_open(const char __user *path, int len) { mount = vfs_mount_resolve(process_current->mount, path_buf, len); if (!mount) goto fail; - vfs_backend_dispatch(mount->backend, (struct vfs_op) { + vfs_request_create((struct vfs_request) { .type = VFSOP_OPEN, .open = { .path = &path_buf[mount->prefix_len], .path_len = len - mount->prefix_len, - } + }, + + .caller = process_current, + .backend = mount->backend, }); // doesn't return / fallthrough to fail @@ -141,13 +144,15 @@ int _syscall_write(handle_t handle_num, const char __user *buf, int len) { struct handle *handle = &process_current->handles[handle_num]; if (handle_num < 0 || handle_num >= HANDLE_MAX) return -1; if (handle->type != HANDLE_FILE) return -1; - vfs_backend_dispatch(handle->file.backend, (struct vfs_op) { + vfs_request_create((struct vfs_request) { .type = VFSOP_WRITE, .rw = { .buf = (userptr_t) buf, .buf_len = len, .id = handle->file.id, - } + }, + .caller = process_current, + .backend = handle->file.backend, }); return -1; } @@ -206,7 +211,7 @@ int _syscall_fs_wait(handle_t back, void __user *info) { // handle queued requests struct process *queued = back_handle->fs.backend->queue; back_handle->fs.backend->queue = NULL; // TODO get the next queued proc - vfs_request_pass2handler(queued->pending_req); + vfs_request_pass2handler(&queued->pending_req); } else { process_switch_any(); } 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