summaryrefslogtreecommitdiff
path: root/src/kernel
diff options
context:
space:
mode:
authordzwdz2021-09-12 13:26:29 +0200
committerdzwdz2021-09-12 13:26:29 +0200
commita66ce8238c08703bd1066a8094d6ab537e82b20e (patch)
tree80754d2a54fd5797b87cf9f6596f3a78a29b6e56 /src/kernel
parent625ae265cbabe76bd272e9e8f0f637635af64b23 (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.h4
-rw-r--r--src/kernel/syscalls.c8
-rw-r--r--src/kernel/vfs/request.c36
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