diff options
author | dzwdz | 2021-09-12 13:26:29 +0200 |
---|---|---|
committer | dzwdz | 2021-09-12 13:26:29 +0200 |
commit | a66ce8238c08703bd1066a8094d6ab537e82b20e (patch) | |
tree | 80754d2a54fd5797b87cf9f6596f3a78a29b6e56 /src/kernel | |
parent | 625ae265cbabe76bd272e9e8f0f637635af64b23 (diff) |
implement most of fs_wait
awaited_req is a garbage name but i couldn't come up with a better one.
i also have no idea how to handle all the failure states
Diffstat (limited to 'src/kernel')
-rw-r--r-- | src/kernel/proc.h | 4 | ||||
-rw-r--r-- | src/kernel/syscalls.c | 8 | ||||
-rw-r--r-- | src/kernel/vfs/request.c | 36 |
3 files changed, 41 insertions, 7 deletions
diff --git a/src/kernel/proc.h b/src/kernel/proc.h index 13e4125..595d62c 100644 --- a/src/kernel/proc.h +++ b/src/kernel/proc.h @@ -31,6 +31,10 @@ struct process { size_t len; } death_msg; struct vfs_request pending_req; // PS_WAITS4FS + struct { + char __user *buf; + int __user *len; + } awaited_req; // PS_WAITS4REQUEST }; struct vfs_mount *mount; diff --git a/src/kernel/syscalls.c b/src/kernel/syscalls.c index eb8da09..21c1b72 100644 --- a/src/kernel/syscalls.c +++ b/src/kernel/syscalls.c @@ -196,7 +196,7 @@ fail: return -1; } -int _syscall_fs_wait(handle_t back, void __user *info) { +int _syscall_fs_wait(handle_t back, char __user *buf, int __user *len) { struct handle *back_handle; if (back < 0 || back >= HANDLE_MAX) return -1; @@ -206,6 +206,10 @@ int _syscall_fs_wait(handle_t back, void __user *info) { process_current->state = PS_WAITS4REQUEST; back_handle->fs.backend->handler = process_current; + /* checking the validity of those pointers here would make + * vfs_request_pass2handler simpler. TODO? */ + process_current->awaited_req.buf = buf; + process_current->awaited_req.len = len; if (back_handle->fs.backend->queue) { // handle queued requests @@ -238,7 +242,7 @@ int syscall_handler(int num, int a, int b, int c) { case _SYSCALL_FS_CREATE: return _syscall_fs_create((userptr_t)a); case _SYSCALL_FS_WAIT: - return _syscall_fs_wait(a, (userptr_t)b); + return _syscall_fs_wait(a, (userptr_t)b, (userptr_t)c); default: tty_const("unknown syscall "); panic(); diff --git a/src/kernel/vfs/request.c b/src/kernel/vfs/request.c index a275fd6..2ff5d72 100644 --- a/src/kernel/vfs/request.c +++ b/src/kernel/vfs/request.c @@ -1,4 +1,5 @@ #include <kernel/mem/alloc.h> +#include <kernel/mem/virt.h> #include <kernel/panic.h> #include <kernel/proc.h> #include <kernel/vfs/request.h> @@ -29,12 +30,37 @@ _Noreturn void vfs_request_create(struct vfs_request req) { } _Noreturn void vfs_request_pass2handler(struct vfs_request *req) { - assert(req->backend->handler); - assert(req->backend->handler->state == PS_WAITS4REQUEST); + struct process *handler = req->backend->handler; + int len; + assert(handler); + assert(handler->state == PS_WAITS4REQUEST); + handler->state = PS_RUNNING; - req->backend->handler->state = PS_RUNNING; - // TODO pass the request to the process - process_switch(req->backend->handler); + if (!virt_cpy_from(handler->pages, + &len, handler->awaited_req.len, sizeof len)) + goto fail; // can't read buffer length + if (len > req->input.len) { + // input bigger than buffer + // TODO what should be done during e.g. open() calls? truncating doesn't seem right + len = req->input.len; + } + + if (req->input.kern) { + if (!virt_cpy_to(handler->pages, + handler->awaited_req.buf, req->input.buf_kern, len)) + goto fail; // can't copy buffer + } else { + panic(); // TODO + } + + if (!virt_cpy_to(handler->pages, + handler->awaited_req.len, &len, sizeof len)) + goto fail; // can't copy new length + + regs_savereturn(&handler->regs, req->type); + process_switch(handler); +fail: + panic(); // TODO } // returns from a VFS operation to the calling process |