aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--linux-aio.c17
1 files changed, 14 insertions, 3 deletions
diff --git a/linux-aio.c b/linux-aio.c
index 50da75db19..1c635ef12d 100644
--- a/linux-aio.c
+++ b/linux-aio.c
@@ -31,6 +31,8 @@ struct qemu_laiocb {
struct iocb iocb;
ssize_t ret;
size_t nbytes;
+ QEMUIOVector *qiov;
+ bool is_read;
QLIST_ENTRY(qemu_laiocb) node;
};
@@ -57,10 +59,17 @@ static void qemu_laio_process_completion(struct qemu_laio_state *s,
ret = laiocb->ret;
if (ret != -ECANCELED) {
- if (ret == laiocb->nbytes)
+ if (ret == laiocb->nbytes) {
ret = 0;
- else if (ret >= 0)
- ret = -EINVAL;
+ } else if (ret >= 0) {
+ /* Short reads mean EOF, pad with zeros. */
+ if (laiocb->is_read) {
+ qemu_iovec_memset_skip(laiocb->qiov, 0,
+ laiocb->qiov->size - ret, ret);
+ } else {
+ ret = -EINVAL;
+ }
+ }
laiocb->common.cb(laiocb->common.opaque, ret);
}
@@ -162,6 +171,8 @@ BlockDriverAIOCB *laio_submit(BlockDriverState *bs, void *aio_ctx, int fd,
laiocb->nbytes = nb_sectors * 512;
laiocb->ctx = s;
laiocb->ret = -EINPROGRESS;
+ laiocb->is_read = (type == QEMU_AIO_READ);
+ laiocb->qiov = qiov;
iocbs = &laiocb->iocb;