diff --git a/lib/kcapi-kernel-if.c b/lib/kcapi-kernel-if.c index 0df1a02..9f93603 100644 --- a/lib/kcapi-kernel-if.c +++ b/lib/kcapi-kernel-if.c @@ -421,6 +421,8 @@ ssize_t _kcapi_common_vmsplice_chunk(struct kcapi_handle *handle, int _kcapi_aio_read_all(struct kcapi_handle *handle, size_t toread, struct timespec *timeout) { + int err = 0; + if (toread > KCAPI_AIO_CONCURRENT) return -EINVAL; @@ -431,41 +433,34 @@ int _kcapi_aio_read_all(struct kcapi_handle *handle, size_t toread, events, timeout); if (rc < 0) - return rc; + return err == 0 ? rc : err; for (i = 0; i < rc; i++) { struct iocb *cb; + uint64_t idx = events[i].data; - /* - * If one cipher operation fails, so will the entire - * AIO operation - */ - if (events[i].res < 0) { - handle->aio.iocb_ret[events[i].data] = - events[i].res; - return (int)events[i].res; + if (idx >= KCAPI_AIO_CONCURRENT) { + if (err == 0) + err = -EOVERFLOW; + continue; } cb = (struct iocb *)(uintptr_t)events[i].obj; - /* - * Older symmetric AIO implementations used a wrong - * return code. - */ - if (events[i].res > 0) { - handle->aio.iocb_ret[events[i].data] = - events[i].res; + if (events[i].res == 0) { + handle->aio.iocb_ret[idx] = (__s64)cb->aio_nbytes; } else { - handle->aio.iocb_ret[events[i].data] = - (__s64)cb->aio_nbytes; + handle->aio.iocb_ret[idx] = events[i].res; + if (events[i].res < 0 && err == 0) + err = (int)events[i].res; } cb->aio_fildes = 0; } - toread -= (uint32_t)rc; + toread -= (size_t)rc; } - return 0; + return err; } int _kcapi_aio_send_iov(struct kcapi_handle *handle, struct iovec *iov, @@ -541,6 +536,7 @@ int _kcapi_aio_read_iov(struct kcapi_handle *handle, } else { kcapi_dolog(KCAPI_LOG_ERR, "Could not sumbit AIO read\n"); + _kcapi_aio_read_all(handle, (size_t)ret, NULL); return -EIO; } }