summaryrefslogtreecommitdiff
path: root/src/kernel/vfs/request.c
diff options
context:
space:
mode:
authordzwdz2021-09-12 12:47:51 +0200
committerdzwdz2021-09-12 12:47:51 +0200
commite65d58357aaff7c1d05c06753538383478c1b0e9 (patch)
tree524acff4943892d62cfcd33a26fc83cace6aef83 /src/kernel/vfs/request.c
parent8fe035d7d75d09f314f9e8aefe1dcaf1e10d1954 (diff)
vfs request refactor pt1
Diffstat (limited to 'src/kernel/vfs/request.c')
-rw-r--r--src/kernel/vfs/request.c67
1 files changed, 67 insertions, 0 deletions
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 <kernel/mem/alloc.h>
+#include <kernel/panic.h>
+#include <kernel/proc.h>
+#include <kernel/vfs/request.h>
+#include <kernel/vfs/root.h>
+
+// 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);
+}