From 613de4db61dd99e7d2049b0a303e167fa711030b Mon Sep 17 00:00:00 2001 From: dzwdz Date: Sat, 4 Sep 2021 19:34:51 +0200 Subject: new vfs impl pt. 1: implement open() --- src/kernel/handle.h | 8 ++++++++ src/kernel/syscalls.c | 15 +++++++++------ src/kernel/vfs/backend.c | 42 ++++++++++++++++++++++++++++++++++++++++++ src/kernel/vfs/backend.h | 23 +++++++++++++++++++++++ src/kernel/vfs/mount.c | 14 +++++++------- src/kernel/vfs/mount.h | 5 +++-- src/kernel/vfs/root.c | 16 ++++++++++++++++ src/kernel/vfs/root.h | 5 +++++ 8 files changed, 113 insertions(+), 15 deletions(-) create mode 100644 src/kernel/vfs/backend.c create mode 100644 src/kernel/vfs/backend.h create mode 100644 src/kernel/vfs/root.c create mode 100644 src/kernel/vfs/root.h (limited to 'src/kernel') diff --git a/src/kernel/handle.h b/src/kernel/handle.h index aae8937..0bf0f33 100644 --- a/src/kernel/handle.h +++ b/src/kernel/handle.h @@ -1,5 +1,6 @@ #pragma once #include +#include #include #define HANDLE_MAX 16 @@ -8,8 +9,15 @@ typedef int handle_t; // TODO duplicated in syscalls.h enum handle_type { HANDLE_EMPTY, + HANDLE_FILE, }; struct handle { enum handle_type type; + union { + struct { + struct vfs_backend *backend; + int id; + } file; + }; }; diff --git a/src/kernel/syscalls.c b/src/kernel/syscalls.c index 002f3fd..8f520ab 100644 --- a/src/kernel/syscalls.c +++ b/src/kernel/syscalls.c @@ -89,16 +89,19 @@ handle_t _syscall_fs_open(const user_ptr path, int len) { mount = vfs_mount_resolve(process_current->mount, buffer, len); if (!mount) return -1; - res = -1; // TODO pass to filesystem - if (res < 0) - return res; - else - return handle; + vfs_backend_dispatch(mount->backend, (struct vfs_op) { + .type = VFSOP_OPEN, + .open = { + .path = &buffer[mount->prefix_len], + .path_len = len - mount->prefix_len, + } + }); + // doesn't return. TODO mark as noreturn } int _syscall_fd_mount(handle_t handle, const user_ptr path, int len) { struct virt_iter iter; - struct vfs_mount *mount; + struct vfs_mount *mount = NULL; char *path_buf; int res; diff --git a/src/kernel/vfs/backend.c b/src/kernel/vfs/backend.c new file mode 100644 index 0000000..cf73ef0 --- /dev/null +++ b/src/kernel/vfs/backend.c @@ -0,0 +1,42 @@ +#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 = { + .op = op, + .caller = process_current, + }; + switch (backend->type) { + case VFS_BACK_ROOT: + int ret = vfs_root_handler(&req); + vfs_backend_finish(&req, ret); + default: + panic(); + } +} + +// returns from a VFS operation to the calling process +_Noreturn void vfs_backend_finish(struct vfs_op_request *req, int ret) { + 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; + } + + req->caller->state = PS_RUNNING; + regs_savereturn(&req->caller->regs, ret); + process_switch(req->caller); +} diff --git a/src/kernel/vfs/backend.h b/src/kernel/vfs/backend.h new file mode 100644 index 0000000..6a8bee6 --- /dev/null +++ b/src/kernel/vfs/backend.h @@ -0,0 +1,23 @@ +#pragma once +#include + +enum vfs_backend_type { + VFS_BACK_ROOT, +}; + +// describes something which can acts as an access function +struct vfs_backend { + enum vfs_backend_type type; +}; + +// 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_backend_finish(struct vfs_op_request *, int ret); diff --git a/src/kernel/vfs/mount.c b/src/kernel/vfs/mount.c index 9d66f0b..07eed0d 100644 --- a/src/kernel/vfs/mount.c +++ b/src/kernel/vfs/mount.c @@ -3,15 +3,15 @@ #include struct vfs_mount *vfs_mount_seed(void) { - struct vfs_mount *mount = NULL; /*kmalloc(sizeof(struct vfs_mount)); + struct vfs_mount *mount = kmalloc(sizeof(struct vfs_mount)); + struct vfs_backend *backend = kmalloc(sizeof(struct vfs_backend)); + backend->type = VFS_BACK_ROOT; *mount = (struct vfs_mount){ .prev = NULL, - .prefix = "/tty", - .prefix_len = 4, - .handle = { - .type = HANDLE_SPECIAL_TTY, - }, - };*/ + .prefix = "", + .prefix_len = 0, + .backend = backend, + }; return mount; } diff --git a/src/kernel/vfs/mount.h b/src/kernel/vfs/mount.h index b7029cd..ac55184 100644 --- a/src/kernel/vfs/mount.h +++ b/src/kernel/vfs/mount.h @@ -1,14 +1,15 @@ #pragma once -#include +#include +#include struct vfs_mount { struct vfs_mount *prev; char *prefix; size_t prefix_len; + struct vfs_backend *backend; }; // prepares init's filesystem view struct vfs_mount *vfs_mount_seed(void); struct vfs_mount *vfs_mount_resolve( struct vfs_mount *top, const char *path, size_t path_len); - diff --git a/src/kernel/vfs/root.c b/src/kernel/vfs/root.c new file mode 100644 index 0000000..c90557b --- /dev/null +++ b/src/kernel/vfs/root.c @@ -0,0 +1,16 @@ +#include +#include +#include + +int vfs_root_handler(struct vfs_op_request *req) { + switch (req->op.type) { + case VFSOP_OPEN: + if (req->op.open.path_len == 4 + && !memcmp(req->op.open.path, "/tty", 4)) { + return 0; + } + return -1; + default: + panic(); + } +} diff --git a/src/kernel/vfs/root.h b/src/kernel/vfs/root.h new file mode 100644 index 0000000..617ba1c --- /dev/null +++ b/src/kernel/vfs/root.h @@ -0,0 +1,5 @@ +#pragma once +#include + +// the VFS provided to init +int vfs_root_handler(struct vfs_op_request *); -- cgit v1.2.3