summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/init/main.c8
-rw-r--r--src/init/syscalls.c9
-rw-r--r--src/init/tar.c4
-rw-r--r--src/init/tar.h2
-rw-r--r--src/kernel/handle.h1
-rw-r--r--src/kernel/proc.c1
-rw-r--r--src/kernel/proc.h3
-rw-r--r--src/kernel/syscalls.c59
-rw-r--r--src/shared/syscalls.h11
9 files changed, 43 insertions, 55 deletions
diff --git a/src/init/main.c b/src/init/main.c
index 73df25b..795e2ac 100644
--- a/src/init/main.c
+++ b/src/init/main.c
@@ -32,11 +32,9 @@ int main(void) {
}
void fs_prep(void) {
- handle_t front, back;
- front = _syscall_fs_create(&back);
-
- if (!_syscall_fork()) {
- tar_driver(back, &_initrd);
+ handle_t front = _syscall_fs_fork2();
+ if (!front) {
+ tar_driver(&_initrd);
_syscall_exit(1);
}
diff --git a/src/init/syscalls.c b/src/init/syscalls.c
index 57a7344..b535cae 100644
--- a/src/init/syscalls.c
+++ b/src/init/syscalls.c
@@ -34,13 +34,12 @@ int _syscall_close(handle_t handle) {
return _syscall(_SYSCALL_CLOSE, handle, 0, 0, 0);
}
-handle_t _syscall_fs_create(handle_t __user *back) {
- return _syscall(_SYSCALL_FS_CREATE, (int)back, 0, 0, 0);
+handle_t _syscall_fs_fork2(void) {
+ return _syscall(_SYSCALL_FS_FORK2, 0, 0, 0, 0);
}
-int _syscall_fs_wait(handle_t back, char __user *buf, int max_len,
- struct fs_wait_response __user *res) {
- return _syscall(_SYSCALL_FS_WAIT, back, (int)buf, max_len, (int)res);
+int _syscall_fs_wait(char __user *buf, int max_len, struct fs_wait_response __user *res) {
+ return _syscall(_SYSCALL_FS_WAIT, (int)buf, max_len, (int)res, 0);
}
int _syscall_fs_respond(char __user *buf, int ret) {
diff --git a/src/init/tar.c b/src/init/tar.c
index 42efcdf..89f4e69 100644
--- a/src/init/tar.c
+++ b/src/init/tar.c
@@ -13,11 +13,11 @@ static int tar_size(void *sector);
static void *tar_find(const char *path, size_t path_len, void *base, size_t base_len);
static int oct_parse(char *str, size_t len);
-void tar_driver(handle_t back, void *base) {
+void tar_driver(void *base) {
static char buf[BUF_SIZE];
struct fs_wait_response res;
for (;;) {
- switch (_syscall_fs_wait(back, buf, BUF_SIZE, &res)) {
+ switch (_syscall_fs_wait(buf, BUF_SIZE, &res)) {
case VFSOP_OPEN:
_syscall_fs_respond(NULL, tar_open(buf, res.len, base, ~0));
break;
diff --git a/src/init/tar.h b/src/init/tar.h
index 71c30fe..c1dee78 100644
--- a/src/init/tar.h
+++ b/src/init/tar.h
@@ -1,4 +1,4 @@
#pragma once
#include <shared/types.h>
-_Noreturn void tar_driver(handle_t back, void *base);
+_Noreturn void tar_driver(void *base);
diff --git a/src/kernel/handle.h b/src/kernel/handle.h
index 6ceae2e..7d24c02 100644
--- a/src/kernel/handle.h
+++ b/src/kernel/handle.h
@@ -10,7 +10,6 @@ enum handle_type {
HANDLE_FILE,
HANDLE_FS_FRONT,
- HANDLE_FS_BACK,
};
struct handle {
diff --git a/src/kernel/proc.c b/src/kernel/proc.c
index 4df6bd7..aebd509 100644
--- a/src/kernel/proc.c
+++ b/src/kernel/proc.c
@@ -21,6 +21,7 @@ struct process *process_seed(void) {
proc->mount = vfs_mount_seed();
proc->id = next_pid++;
proc->handled_req = NULL;
+ proc->controlled = NULL;
process_first = proc;
diff --git a/src/kernel/proc.h b/src/kernel/proc.h
index 7c338bb..6723e23 100644
--- a/src/kernel/proc.h
+++ b/src/kernel/proc.h
@@ -36,6 +36,9 @@ struct process {
};
struct vfs_request *handled_req;
+ /* vfs_backend controlled (not exclusively) by this process */
+ struct vfs_backend *controlled;
+
struct vfs_mount *mount;
struct handle handles[HANDLE_MAX];
diff --git a/src/kernel/syscalls.c b/src/kernel/syscalls.c
index a819b64..9a9b5d6 100644
--- a/src/kernel/syscalls.c
+++ b/src/kernel/syscalls.c
@@ -163,61 +163,52 @@ int _syscall_close(handle_t handle) {
return -1;
}
-handle_t _syscall_fs_create(handle_t __user *back_user) {
- handle_t front, back = 0;
+handle_t _syscall_fs_fork2(void) {
struct vfs_backend *backend;
+ struct process *child;
+ handle_t front;
front = process_find_handle(process_current);
- if (front < 0) goto fail;
- // the type needs to be set here so process_find_handle skips this handle
+ if (front < 0) return -1;
process_current->handles[front].type = HANDLE_FS_FRONT;
- back = process_find_handle(process_current);
- if (back < 0) goto fail;
- process_current->handles[back].type = HANDLE_FS_BACK;
-
- // copy the back handle to back_user
- if (!virt_cpy_to(process_current->pages, back_user, &back, sizeof(back)))
- goto fail;
+ /* so this can't return 0 in the parent or it will make it think that it's
+ * the child. i could make fork()s return -1 in the child but that's weird.
+ *
+ * also there's this whole thing with handling errors here properly and
+ * errno
+ * TODO figure this out */
+ if (front == 0) panic_unimplemented();
backend = kmalloc(sizeof *backend); // TODO never freed
backend->type = VFS_BACK_USER;
backend->handler = NULL;
backend->queue = NULL;
- process_current->handles[front].fs.backend = backend;
- process_current->handles[back ].fs.backend = backend;
+ child = process_fork(process_current);
+ child->controlled = backend;
+ regs_savereturn(&child->regs, 0);
+ process_current->handles[front].fs.backend = backend;
return front;
-fail:
- if (front >= 0)
- process_current->handles[front].type = HANDLE_EMPTY;
- if (back >= 0)
- process_current->handles[back].type = HANDLE_EMPTY;
- return -1;
}
-int _syscall_fs_wait(handle_t back, char __user *buf, int max_len,
- struct fs_wait_response __user *res) {
- struct handle *back_handle;
-
- if (back < 0 || back >= HANDLE_MAX) return -1;
- back_handle = &process_current->handles[back];
- if (back_handle->type != HANDLE_FS_BACK)
- return -1;
+int _syscall_fs_wait(char __user *buf, int max_len, struct fs_wait_response __user *res) {
+ struct vfs_backend *backend = process_current->controlled;
+ if (!backend) return -1;
process_current->state = PS_WAITS4REQUEST;
- back_handle->fs.backend->handler = process_current;
+ 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.max_len = max_len;
process_current->awaited_req.res = res;
- if (back_handle->fs.backend->queue) {
+ if (backend->queue) {
// handle queued requests
- struct process *queued = back_handle->fs.backend->queue;
- back_handle->fs.backend->queue = NULL; // TODO get the next queued proc
+ struct process *queued = backend->queue;
+ backend->queue = NULL; // TODO get the next queued proc
vfs_request_pass2handler(&queued->pending_req);
} else {
process_switch_any();
@@ -281,10 +272,10 @@ int _syscall(int num, int a, int b, int c, int d) {
return _syscall_write(a, (userptr_t)b, c, d);
case _SYSCALL_CLOSE:
return _syscall_close(a);
- case _SYSCALL_FS_CREATE:
- return _syscall_fs_create((userptr_t)a);
+ case _SYSCALL_FS_FORK2:
+ return _syscall_fs_fork2();
case _SYSCALL_FS_WAIT:
- return _syscall_fs_wait(a, (userptr_t)b, c, (userptr_t)d);
+ return _syscall_fs_wait((userptr_t)a, b, (userptr_t)c);
case _SYSCALL_FS_RESPOND:
return _syscall_fs_respond((userptr_t)a, b);
case _SYSCALL_MEMFLAG:
diff --git a/src/shared/syscalls.h b/src/shared/syscalls.h
index 3a21b66..f136ed2 100644
--- a/src/shared/syscalls.h
+++ b/src/shared/syscalls.h
@@ -15,7 +15,7 @@ enum {
_SYSCALL_WRITE,
_SYSCALL_CLOSE,
- _SYSCALL_FS_CREATE,
+ _SYSCALL_FS_FORK2,
_SYSCALL_FS_WAIT,
_SYSCALL_FS_RESPOND,
@@ -47,17 +47,14 @@ int _syscall_read(handle_t, char __user *buf, int len, int offset);
int _syscall_write(handle_t, const char __user *buf, int len, int offset);
int _syscall_close(handle_t);
-/** Creates a pair of front/back filesystem handles.
- * @param back a pointer to a handle_t which will store the back pointer
- */
-handle_t _syscall_fs_create(handle_t __user *back);
+handle_t _syscall_fs_fork2(void);
+
struct fs_wait_response {
int len; // how much was put in *buf
int id; // file id (returned by the open handler, passed to other calls)
int offset;
};
-int _syscall_fs_wait(handle_t back, char __user *buf, int max_len,
- struct fs_wait_response __user *res);
+int _syscall_fs_wait(char __user *buf, int max_len, struct fs_wait_response __user *res);
int _syscall_fs_respond(char __user *buf, int ret);
int _syscall_memflag(void __user *addr, size_t len, int flags);