From e401e6769552ab2b536b951958661dc0cded285c Mon Sep 17 00:00:00 2001 From: David Wendt Date: Sun, 24 Oct 2021 22:31:08 -0400 Subject: [PATCH] Implement vectored async IO fallback --- kernel/aio.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++--- kernel/fs.c | 2 +- kernel/fs.h | 7 +++++-- 3 files changed, 58 insertions(+), 6 deletions(-) diff --git a/kernel/aio.c b/kernel/aio.c index b6a15a82db..79d22f0c2d 100644 --- a/kernel/aio.c +++ b/kernel/aio.c @@ -2,6 +2,7 @@ #include "kernel/calls.h" #include "kernel/task.h" #include "kernel/aio.h" +#include "kernel/fs.h" #include "fs/aio.h" #include "fs/fd.h" @@ -186,7 +187,9 @@ dword_t sys_io_cancel(dword_t ctx_id, addr_t iocb, addr_t result) { * Do a single PREAD operation, falling back to seek-and-read if necessary. * * The return code corresponds to the 'sync error' concept of fallback_submit, - * while async errors should be flagged by writing to *err. + * while async errors should be flagged by writing to `*err`. + * + * `*err` also is used to return the total number of bytes read. */ static signed int __aio_fallback_pread( struct fd *fd, @@ -243,7 +246,9 @@ static signed int __aio_fallback_pread( * Do a single PWRITE operation, falling back to seek-and-write if necessary. * * The return code corresponds to the 'sync error' concept of fallback_submit, - * while async errors should be flagged by writing to *err. + * while async errors should be flagged by writing to `*err`. + * + * `*err` also is used to return the total number of bytes written. */ static signed int __aio_fallback_pwrite( struct fd *fd, @@ -316,6 +321,8 @@ int aio_fallback_submit(struct fd *fd, struct aioctx *ctx, unsigned int event_id return sync_err; } + struct iovec_ *iov_list = NULL; + char *buf = NULL; switch (evt->op) { case AIOCTX_PREAD: @@ -337,7 +344,49 @@ int aio_fallback_submit(struct fd *fd, struct aioctx *ctx, unsigned int event_id async_result0 = 0; sync_err = 0; break; - //TODO: AIOCTX_POLL, AIOCTX_PREADV, AIOCTX_PWRITEV + case AIOCTX_PREADV: + iov_list = read_iovec((addr_t)evt->buf, evt->nbytes); + ssize_t total_read = 0; + + for (unsigned int i = 0; i < evt->nbytes; i += 1) { + signed int cur_read = 0; + sync_err = __aio_fallback_pread(fd, iov_list[i].base, iov_list[i].len, evt->offset + total_read, &cur_read); + if (sync_err < 0 || cur_read < 0) { + async_result0 = cur_read; + break; + } + + total_read += cur_read; + + if (cur_read < iov_list[i].len) break; + } + + if (sync_err < 0 || async_result0 < 0) break; + + async_result0 = total_read; + break; + case AIOCTX_PWRITEV: + iov_list = read_iovec((addr_t)evt->buf, evt->nbytes); + ssize_t total_write = 0; + + for (unsigned int i = 0; i < evt->nbytes; i += 1) { + signed int cur_write = 0; + sync_err = __aio_fallback_pwrite(fd, iov_list[i].base, iov_list[i].len, evt->offset + total_write, &cur_write); + if (sync_err < 0 || cur_write < 0) { + async_result0 = cur_write; + break; + } + + total_write += cur_write; + + if (cur_write < iov_list[i].len) break; + } + + if (sync_err < 0 || async_result0 < 0) break; + + async_result0 = total_write; + break; + //TODO: AIOCTX_POLL default: sync_err = _EINVAL; break; diff --git a/kernel/fs.c b/kernel/fs.c index df1d2aaaa2..af74a57536 100644 --- a/kernel/fs.c +++ b/kernel/fs.c @@ -295,7 +295,7 @@ dword_t sys_write(fd_t fd_no, addr_t buf_addr, dword_t size) { // that yet because it's more work and the efficiency gain from that is dwarfed // by the inefficiency of the emulator. -static struct iovec_ *read_iovec(addr_t iovec_addr, unsigned iovec_count) { +struct iovec_ *read_iovec(addr_t iovec_addr, unsigned iovec_count) { dword_t iovec_size = sizeof(struct iovec_) * iovec_count; struct iovec_ *iovec = malloc(iovec_size); if (iovec == NULL) diff --git a/kernel/fs.h b/kernel/fs.h index 5a8154ccb4..4bbce6fa3d 100644 --- a/kernel/fs.h +++ b/kernel/fs.h @@ -1,5 +1,5 @@ -#ifndef FS_H -#define FS_H +#ifndef KERNEL_FS_H +#define KERNEL_FS_H #include "misc.h" #include "util/list.h" @@ -8,6 +8,7 @@ #include "fs/fake-db.h" #include "fs/fix_path.h" #include "emu/memory.h" +#include "kernel/calls.h" #include #include @@ -175,4 +176,6 @@ extern const struct fs_ops devptsfs; extern const struct fs_ops tmpfs; void fs_register(const struct fs_ops *fs); +struct iovec_ *read_iovec(addr_t iovec_addr, unsigned iovec_count); + #endif