summaryrefslogtreecommitdiff
path: root/src/kernel
diff options
context:
space:
mode:
authordzwdz2021-09-04 19:34:51 +0200
committerdzwdz2021-09-04 19:34:51 +0200
commit613de4db61dd99e7d2049b0a303e167fa711030b (patch)
tree84b577c30aac3ac7f8360fcc7aa78f7d29479538 /src/kernel
parentc4531fa5e1aa16b7ba74de2975eadf06b3052b78 (diff)
new vfs impl pt. 1: implement open()
Diffstat (limited to 'src/kernel')
-rw-r--r--src/kernel/handle.h8
-rw-r--r--src/kernel/syscalls.c15
-rw-r--r--src/kernel/vfs/backend.c42
-rw-r--r--src/kernel/vfs/backend.h23
-rw-r--r--src/kernel/vfs/mount.c14
-rw-r--r--src/kernel/vfs/mount.h5
-rw-r--r--src/kernel/vfs/root.c16
-rw-r--r--src/kernel/vfs/root.h5
8 files changed, 113 insertions, 15 deletions
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 <kernel/types.h>
+#include <kernel/vfs/mount.h>
#include <stddef.h>
#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 <kernel/panic.h>
+#include <kernel/proc.h>
+#include <kernel/vfs/backend.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 = {
+ .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 <shared/vfs.h>
+
+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 <kernel/vfs/mount.h>
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 <kernel/handle.h>
+#include <kernel/vfs/backend.h>
+#include <stddef.h>
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 <kernel/vfs/root.h>
+#include <kernel/util.h>
+#include <kernel/panic.h>
+
+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 <kernel/vfs/mount.h>
+
+// the VFS provided to init
+int vfs_root_handler(struct vfs_op_request *);