diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/kernel/proc.h | 2 | ||||
-rw-r--r-- | src/kernel/syscalls.c | 17 | ||||
-rw-r--r-- | src/kernel/vfs/backend.h | 29 | ||||
-rw-r--r-- | src/kernel/vfs/mount.h | 2 | ||||
-rw-r--r-- | src/kernel/vfs/request.c (renamed from src/kernel/vfs/backend.c) | 35 | ||||
-rw-r--r-- | src/kernel/vfs/request.h | 43 | ||||
-rw-r--r-- | src/kernel/vfs/root.c | 12 | ||||
-rw-r--r-- | src/kernel/vfs/root.h | 4 |
8 files changed, 78 insertions, 66 deletions
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.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 <shared/vfs.h> - -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 <kernel/vfs/backend.h> +#include <kernel/vfs/request.h> #include <stddef.h> struct vfs_mount { diff --git a/src/kernel/vfs/backend.c b/src/kernel/vfs/request.c index b9bc9af..1212aa4 100644 --- a/src/kernel/vfs/backend.c +++ b/src/kernel/vfs/request.c @@ -1,41 +1,34 @@ #include <kernel/mem/alloc.h> #include <kernel/panic.h> #include <kernel/proc.h> -#include <kernel/vfs/backend.h> +#include <kernel/vfs/request.h> #include <kernel/vfs/root.h> // 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 +_Noreturn void vfs_request_create(struct vfs_request req) { int ret; - *req = (struct vfs_op_request) { - .op = op, - .caller = process_current, - .backend = backend, - }; - - switch (backend->type) { + switch (req.backend->type) { case VFS_BACK_ROOT: - ret = vfs_root_handler(req); - vfs_backend_finish(req, ret); + ret = vfs_root_handler(&req); + vfs_request_finish(&req, ret); case VFS_BACK_USER: process_current->state = PS_WAITS4FS; - if (backend->handler == NULL) { + if (req.backend->handler == NULL) { // backend isn't ready yet, join the queue - assert(backend->queue == NULL); // TODO implement a proper queue + assert(req.backend->queue == NULL); // TODO implement a proper queue - backend->queue = process_current; + req.backend->queue = process_current; process_current->pending_req = req; process_switch_any(); } else { - vfs_request_pass2handler(req); + vfs_request_pass2handler(&req); } default: panic(); } } -_Noreturn void vfs_request_pass2handler(struct vfs_op_request *req) { +_Noreturn void vfs_request_pass2handler(struct vfs_request *req) { assert(req->backend->handler); assert(req->backend->handler->state == PS_WAITS4REQUEST); @@ -45,10 +38,10 @@ _Noreturn void vfs_request_pass2handler(struct vfs_op_request *req) { } // returns from a VFS operation to the calling process -_Noreturn void vfs_backend_finish(struct vfs_op_request *req, int ret) { +_Noreturn void vfs_request_finish(struct vfs_request *req, int ret) { struct process *caller = req->caller; - if (req->op.type == VFSOP_OPEN && ret >= 0) { + 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 @@ -64,8 +57,8 @@ _Noreturn void vfs_backend_finish(struct vfs_op_request *req, int ret) { ret = handle; } - if (req->op.type == VFSOP_OPEN) - kfree(req->op.open.path); + if (req->type == VFSOP_OPEN) + kfree(req->open.path); req->caller->state = PS_RUNNING; regs_savereturn(&req->caller->regs, ret); 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 <kernel/util.h> #include <kernel/vfs/root.h> -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 <kernel/vfs/mount.h> +#include <kernel/vfs/request.h> // the VFS provided to init -int vfs_root_handler(struct vfs_op_request *); +int vfs_root_handler(struct vfs_request *); |