Skip to content

Commit 97b7657

Browse files
committed
Implement vectored async IO fallback
1 parent e8f8530 commit 97b7657

File tree

3 files changed

+71
-7
lines changed

3 files changed

+71
-7
lines changed

kernel/aio.c

Lines changed: 65 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include "kernel/calls.h"
33
#include "kernel/task.h"
44
#include "kernel/aio.h"
5+
#include "kernel/fs.h"
56
#include "fs/aio.h"
67
#include "fs/fd.h"
78

@@ -186,7 +187,9 @@ dword_t sys_io_cancel(dword_t ctx_id, addr_t iocb, addr_t result) {
186187
* Do a single PREAD operation, falling back to seek-and-read if necessary.
187188
*
188189
* The return code corresponds to the 'sync error' concept of fallback_submit,
189-
* while async errors should be flagged by writing to *err.
190+
* while async errors should be flagged by writing to `*err`.
191+
*
192+
* `*err` also is used to return the total number of bytes read.
190193
*/
191194
static signed int __aio_fallback_pread(
192195
struct fd *fd,
@@ -243,7 +246,9 @@ static signed int __aio_fallback_pread(
243246
* Do a single PWRITE operation, falling back to seek-and-write if necessary.
244247
*
245248
* The return code corresponds to the 'sync error' concept of fallback_submit,
246-
* while async errors should be flagged by writing to *err.
249+
* while async errors should be flagged by writing to `*err`.
250+
*
251+
* `*err` also is used to return the total number of bytes written.
247252
*/
248253
static signed int __aio_fallback_pwrite(
249254
struct fd *fd,
@@ -316,7 +321,7 @@ int aio_fallback_submit(struct fd *fd, struct aioctx *ctx, unsigned int event_id
316321
return sync_err;
317322
}
318323

319-
char *buf = NULL;
324+
struct iovec_ *iov_list = NULL;
320325
switch (evt->op) {
321326
case AIOCTX_PREAD:
322327
sync_err = __aio_fallback_pread(fd, (addr_t)evt->buf, evt->nbytes, evt->offset, &async_result0);
@@ -337,7 +342,63 @@ int aio_fallback_submit(struct fd *fd, struct aioctx *ctx, unsigned int event_id
337342
async_result0 = 0;
338343
sync_err = 0;
339344
break;
340-
//TODO: AIOCTX_POLL, AIOCTX_PREADV, AIOCTX_PWRITEV
345+
case AIOCTX_PREADV:
346+
iov_list = read_iovec((addr_t)evt->buf, evt->nbytes);
347+
if (IS_ERR(iov_list)) {
348+
sync_err = PTR_ERR(iov_list);
349+
break;
350+
}
351+
352+
ssize_t total_read = 0;
353+
354+
for (unsigned int i = 0; i < evt->nbytes; i += 1) {
355+
signed int cur_read = 0;
356+
sync_err = __aio_fallback_pread(fd, iov_list[i].base, iov_list[i].len, evt->offset + total_read, &cur_read);
357+
if (sync_err < 0 || cur_read < 0) {
358+
async_result0 = cur_read;
359+
break;
360+
}
361+
362+
total_read += cur_read;
363+
364+
if ((uint_t)cur_read < iov_list[i].len) break;
365+
}
366+
367+
free(iov_list);
368+
369+
if (sync_err < 0 || async_result0 < 0) break;
370+
371+
async_result0 = total_read;
372+
break;
373+
case AIOCTX_PWRITEV:
374+
iov_list = read_iovec((addr_t)evt->buf, evt->nbytes);
375+
if (IS_ERR(iov_list)) {
376+
sync_err = PTR_ERR(iov_list);
377+
break;
378+
}
379+
380+
ssize_t total_write = 0;
381+
382+
for (unsigned int i = 0; i < evt->nbytes; i += 1) {
383+
signed int cur_write = 0;
384+
sync_err = __aio_fallback_pwrite(fd, iov_list[i].base, iov_list[i].len, evt->offset + total_write, &cur_write);
385+
if (sync_err < 0 || cur_write < 0) {
386+
async_result0 = cur_write;
387+
break;
388+
}
389+
390+
total_write += cur_write;
391+
392+
if ((uint_t)cur_write < iov_list[i].len) break;
393+
}
394+
395+
free(iov_list);
396+
397+
if (sync_err < 0 || async_result0 < 0) break;
398+
399+
async_result0 = total_write;
400+
break;
401+
//TODO: AIOCTX_POLL
341402
default:
342403
sync_err = _EINVAL;
343404
break;

kernel/fs.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ dword_t sys_write(fd_t fd_no, addr_t buf_addr, dword_t size) {
295295
// that yet because it's more work and the efficiency gain from that is dwarfed
296296
// by the inefficiency of the emulator.
297297

298-
static struct iovec_ *read_iovec(addr_t iovec_addr, unsigned iovec_count) {
298+
struct iovec_ *read_iovec(addr_t iovec_addr, unsigned iovec_count) {
299299
dword_t iovec_size = sizeof(struct iovec_) * iovec_count;
300300
struct iovec_ *iovec = malloc(iovec_size);
301301
if (iovec == NULL)

kernel/fs.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
#ifndef FS_H
2-
#define FS_H
1+
#ifndef KERNEL_FS_H
2+
#define KERNEL_FS_H
33

44
#include "misc.h"
55
#include "util/list.h"
@@ -8,6 +8,7 @@
88
#include "fs/fake-db.h"
99
#include "fs/fix_path.h"
1010
#include "emu/memory.h"
11+
#include "kernel/calls.h"
1112
#include <dirent.h>
1213
#include <sqlite3.h>
1314

@@ -175,4 +176,6 @@ extern const struct fs_ops devptsfs;
175176
extern const struct fs_ops tmpfs;
176177
void fs_register(const struct fs_ops *fs);
177178

179+
struct iovec_ *read_iovec(addr_t iovec_addr, unsigned iovec_count);
180+
178181
#endif

0 commit comments

Comments
 (0)