diff options
author | dzwdz | 2022-05-05 19:58:49 +0200 |
---|---|---|
committer | dzwdz | 2022-05-05 19:58:49 +0200 |
commit | 3beaeaadf36de4e494d0b40ad31e3c5c503c596e (patch) | |
tree | ce19bb5d1e9184e88d672e1d0d651f52dfeafa06 /src/kernel/vfs/request.c | |
parent | e7d6d031e54ef1b1c7b589648a27eea84994549f (diff) |
kernel/vfs: refactor vfs_backend to allow multiple kernel backends
Diffstat (limited to 'src/kernel/vfs/request.c')
-rw-r--r-- | src/kernel/vfs/request.c | 61 |
1 files changed, 37 insertions, 24 deletions
diff --git a/src/kernel/vfs/request.c b/src/kernel/vfs/request.c index fb196ee..5ad3b82 100644 --- a/src/kernel/vfs/request.c +++ b/src/kernel/vfs/request.c @@ -7,9 +7,8 @@ #include <shared/mem.h> int vfsreq_create(struct vfs_request req_) { - struct vfs_request *req = kmalloc(sizeof *req); + struct vfs_request *req = kmalloc(sizeof *req); // freed in vfsreq_finish memcpy(req, &req_, sizeof *req); - /* freed in vfsreq_finish */ if (req->backend) req->backend->refcount++; @@ -22,21 +21,12 @@ int vfsreq_create(struct vfs_request req_) { if (!req->backend || !req->backend->potential_handlers) return vfsreq_finish(req, -1); - switch (req->backend->type) { - case VFS_BACK_ROOT: - return vfs_root_handler(req); - case VFS_BACK_USER: { - struct vfs_request **iter = &req->backend->queue; - while (*iter != NULL) // find free spot in queue - iter = &(*iter)->queue_next; - *iter = req; - - vfs_backend_accept(req->backend); - return -1; // isn't passed to the caller process anyways - } - default: - panic_invalid_state(); - } + struct vfs_request **iter = &req->backend->queue; + while (*iter != NULL) // find free spot in queue + iter = &(*iter)->queue_next; + *iter = req; + + return vfs_backend_tryaccept(req->backend); } int vfsreq_finish(struct vfs_request *req, int ret) { @@ -76,18 +66,41 @@ int vfsreq_finish(struct vfs_request *req, int ret) { return ret; } -int vfs_backend_accept(struct vfs_backend *backend) { +int vfs_backend_tryaccept(struct vfs_backend *backend) { struct vfs_request *req = backend->queue; - struct process *handler = backend->handler; + if (!req) return -1; + + /* ensure backend is ready to accept request */ + if (backend->is_user) { + if (!backend->user.handler) return -1; + } else { + assert(backend->kern.ready); + if (!backend->kern.ready(backend)) return -1; + } + + backend->queue = req->queue_next; + + if (backend->is_user) { + return vfs_backend_user_accept(req); + } else { + assert(backend->kern.accept); + return backend->kern.accept(req); + } +} + +int vfs_backend_user_accept(struct vfs_request *req) { + struct process *handler; struct fs_wait_response res = {0}; int len = 0; - if (!handler) return -1; + assert(req && req->backend && req->backend->user.handler); + handler = req->backend->user.handler; assert(handler->state == PS_WAITS4REQUEST); - assert(!handler->handled_req); + assert(handler->handled_req == NULL); - if (!req) return -1; - backend->queue = req->queue_next; + // the virt_cpy calls aren't present in all kernel backends + // it's a way to tell apart kernel and user backends apart + // TODO check validity of memory regions somewhere else if (req->input.buf) { len = min(req->input.len, handler->awaited_req.max_len); @@ -108,7 +121,7 @@ int vfs_backend_accept(struct vfs_backend *backend) { process_transition(handler, PS_RUNNING); handler->handled_req = req; - req->backend->handler = NULL; + req->backend->user.handler = NULL; regs_savereturn(&handler->regs, 0); return 0; fail: |