From 468ef8f1d57527af3fe8b67bbc73813e951a0ec5 Mon Sep 17 00:00:00 2001 From: dzwdz Date: Sat, 17 Aug 2024 01:57:04 +0200 Subject: kernel: split the kernel/user inputs in VfsReq I think I've done this refactor in the opposite direction a few years ago. This is mostly meant to prepare me for setxattr, which requires two inputs - coincidentally, one is already going to be a kernel input, and the other will be an user input, so it works out. I also just didn't like the previous way it worked, this feels cleaner. --- src/kernel/vfs/procfs.c | 14 +++++++------- src/kernel/vfs/request.c | 36 +++++++++++++++++------------------- src/kernel/vfs/request.h | 30 ++++++++++++++++-------------- 3 files changed, 40 insertions(+), 40 deletions(-) (limited to 'src/kernel/vfs') diff --git a/src/kernel/vfs/procfs.c b/src/kernel/vfs/procfs.c index ab57628..b0ebbe0 100644 --- a/src/kernel/vfs/procfs.c +++ b/src/kernel/vfs/procfs.c @@ -99,8 +99,8 @@ procfs_accept(VfsReq *req) assert(root->pns == root); if (req->type == VFSOP_OPEN) { - assert(req->input.kern); - h = openpath(req->input.buf_kern, req->input.len, root); + assert(req->kin); + h = openpath(req->kin, req->kinlen, root); vfsreq_finish_short(req, h ? (long)h : -ENOENT); return; } else if (req->type == VFSOP_CLOSE) { @@ -143,16 +143,16 @@ procfs_accept(VfsReq *req) return; } size_t res = pcpy_bi( - req->caller, req->output.buf, + req->caller, req->out, p, (__user void*)req->offset, - req->output.len + req->outlen ); vfsreq_finish_short(req, res); } else if (req->type == VFSOP_WRITE && (h->type == PhIntr || h->type == PhIntrDown)) { - size_t len = min(sizeof buf, req->input.len); - len = pcpy_from(req->caller, buf, req->input.buf, len); + size_t len = min(sizeof buf, req->uinlen); + len = pcpy_from(req->caller, buf, req->uin, len); if (h->type == PhIntr) { proc_intr(p, buf, len); } else { @@ -160,7 +160,7 @@ procfs_accept(VfsReq *req) proc_intr(it, buf, len); } } - vfsreq_finish_short(req, req->input.len); + vfsreq_finish_short(req, req->uinlen); } else { vfsreq_finish_short(req, -ENOSYS); } diff --git a/src/kernel/vfs/request.c b/src/kernel/vfs/request.c index 69a007e..9b60080 100644 --- a/src/kernel/vfs/request.c +++ b/src/kernel/vfs/request.c @@ -100,11 +100,11 @@ vfsreq_finish(VfsReq *req, char __user *stored, long ret, int flags, Proc *handl } if (req->type == VFSOP_READ && ret >= 0) { - assert((size_t)ret <= req->output.len); + assert((size_t)ret <= req->outlen); } - if (req->input.kern) { - kfree(req->input.buf_kern); + if (req->kin) { + kfree(req->kin); } if (req->backend) { @@ -148,23 +148,21 @@ vfsback_useraccept(VfsReq *req) // it's a way to tell apart kernel and user backends apart // TODO check validity of memory regions somewhere else - if (req->input.buf) { - __user void *buf = handler->awaited_req.buf; - len = min(req->input.len, handler->awaited_req.max_len); - if (req->input.kern) { - pcpy_to(handler, buf, req->input.buf_kern, len); - } else { - len = pcpy_bi( - handler, buf, - req->caller, req->input.buf, len - ); - } + assert(!(req->kin && req->uin)); + if (req->kin) { + void __user *buf = handler->awaited_req.buf; + len = min(req->kinlen, handler->awaited_req.max_len); + pcpy_to(handler, buf, req->kin, len); + } else if (req->uin) { + void __user *buf = handler->awaited_req.buf; + len = min(req->uinlen, handler->awaited_req.max_len); + len = pcpy_bi(handler, buf, req->caller, req->uin, len); } else { - len = req->output.len; + len = req->outlen; } res.len = len; - res.capacity = req->output.len; + res.capacity = req->outlen; res.id = req->id; res.id2 = req->id2; res.offset = req->offset; @@ -263,16 +261,16 @@ reqqueue_ringreadall(ReqQueue *q, ring_t *r) /* read as much as the biggest request wants */ for (req = q->head; req; req = req->reqqueue_next) { - mlen = max(mlen, req->output.len); + mlen = max(mlen, req->outlen); } mlen = min(mlen, sizeof tmp); mlen = ring_get(r, tmp, mlen); while ((req = reqqueue_pop(q))) { - size_t ret = min(mlen, req->output.len); + size_t ret = min(mlen, req->outlen); assert(req->type == VFSOP_READ); if (req->caller) { - pcpy_to(req->caller, req->output.buf, tmp, ret); + pcpy_to(req->caller, req->out, tmp, ret); } vfsreq_finish_short(req, ret); } diff --git a/src/kernel/vfs/request.h b/src/kernel/vfs/request.h index d6facfd..484fdd7 100644 --- a/src/kernel/vfs/request.h +++ b/src/kernel/vfs/request.h @@ -37,20 +37,22 @@ struct VfsBackend { /* describes an in-progress vfs call */ struct VfsReq { enum vfs_op type; - struct { - bool kern; // if false: use .buf ; if true: use .buf_kern - union { - char __user *buf; - char *buf_kern; - }; - size_t len; - } input; - struct { - char __user *buf; - size_t len; - } output; - - void __user *id, *id2; // handle.file.id + + /* "kernel" input - an allocation owned by this struct, contains a NUL + * terminated string. the NUL isn't counted in the kinlen (for compat + * with old code). used for the path in open() */ + char *kin; + size_t kinlen; + + /* user inputs and outputs - just point to some buffer in the caller */ + char __user *uin; + size_t uinlen; + char __user *out; + size_t outlen; + + /* those correspond to handle.file.id + * id2 is used for duplex() */ + void __user *id, *id2; long offset; int flags; -- cgit v1.2.3