summaryrefslogtreecommitdiff
path: root/src/kernel/vfs
diff options
context:
space:
mode:
authordzwdz2022-07-07 19:24:42 +0200
committerdzwdz2022-07-07 19:24:42 +0200
commitbbdacaddcc25d1d137a0bb0781eba603641baa92 (patch)
tree898ddd186d8e1def04e818b192a8c9b8d2721504 /src/kernel/vfs
parent8dc3d7df4c73b320fa84b2e871732276a7c6e20f (diff)
kernel/vfs: delegate support in _syscall_fs_respond!
this is big in terms of speed, it avoids a lot of unnecessary context switches
Diffstat (limited to 'src/kernel/vfs')
-rw-r--r--src/kernel/vfs/request.c36
-rw-r--r--src/kernel/vfs/request.h2
2 files changed, 24 insertions, 14 deletions
diff --git a/src/kernel/vfs/request.c b/src/kernel/vfs/request.c
index 4ee5986..1729ca1 100644
--- a/src/kernel/vfs/request.c
+++ b/src/kernel/vfs/request.c
@@ -19,7 +19,7 @@ void vfsreq_create(struct vfs_request req_) {
}
if (!req->backend || !req->backend->potential_handlers)
- vfsreq_finish(req, -1);
+ vfsreq_finish(req, -1, 0, NULL);
struct vfs_request **iter = &req->backend->queue;
while (*iter != NULL) // find free spot in queue
@@ -29,27 +29,37 @@ void vfsreq_create(struct vfs_request req_) {
vfs_backend_tryaccept(req->backend);
}
-void vfsreq_finish(struct vfs_request *req, int ret) {
+void vfsreq_finish(struct vfs_request *req, int ret, int flags, struct process *handler) {
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
- if (req->caller) {
- handle_t handle = process_find_free_handle(req->caller, 0);
- if (handle < 0)
- panic_invalid_state(); // we check for free handles before the open() call
+ // TODO write tests for caller getting killed while opening a file
+ if (!req->caller) panic_unimplemented();
+ handle_t handle = process_find_free_handle(req->caller, 0);
+ if (handle < 0)
+ panic_invalid_state(); // we check for free handles before the open() call
+
+ if (!(flags & FSR_DELEGATE)) {
+ /* default behavior - create a new handle for the file, wrap the id */
struct handle *backing = handle_init(HANDLE_FILE);
backing->backend = req->backend;
req->backend->refcount++;
+ // TODO file ids can only be 31bit long, so they can't be pointers
backing->file_id = ret;
req->caller->handles[handle] = backing;
- ret = handle;
} else {
- // caller got killed
- // TODO write tests & implement
- panic_unimplemented();
+ /* delegating - moving a handle to the caller */
+ assert(handler);
+
+ struct handle *h = handler->handles[ret];
+ if (!h) {
+ kprintf("tried delegating an invalid handle\n");
+ handle = -1; // return error
+ } else {
+ req->caller->handles[handle] = h;
+ handler->handles[ret] = NULL;
+ }
}
+ ret = handle;
}
if (req->input.kern)
diff --git a/src/kernel/vfs/request.h b/src/kernel/vfs/request.h
index cad0981..35173ca 100644
--- a/src/kernel/vfs/request.h
+++ b/src/kernel/vfs/request.h
@@ -59,7 +59,7 @@ struct vfs_request {
/** Assigns the vfs_request to the caller, and dispatches the call */
void vfsreq_create(struct vfs_request);
-void vfsreq_finish(struct vfs_request *, int ret);
+void vfsreq_finish(struct vfs_request*, int ret, int flags, struct process *handler);
/** Try to accept an enqueued request */
void vfs_backend_tryaccept(struct vfs_backend *);