From db427c3e56942a50ce7f54dbf431acd1db9e1d9d Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Tue, 14 Feb 2012 11:14:23 +0100 Subject: [PATCH 58/99] linux-aio: Allow reads beyond the end of growable images RH-Author: Kevin Wolf Message-id: <1329218101-24213-59-git-send-email-kwolf@redhat.com> Patchwork-id: 37251 O-Subject: [RHEL-6.3 qemu-kvm PATCH v2 58/96] linux-aio: Allow reads beyond the end of growable images Bugzilla: 783950 RH-Acked-by: Paolo Bonzini RH-Acked-by: Marcelo Tosatti RH-Acked-by: Laszlo Ersek Bugzilla: 783950 This is the linux-aio version of commits 22afa7b5 (raw-posix, synchronous) and ba1d1afd (posix-aio-compat). Reads now produce zeros after the end of file instead of failing or resulting in short reads, making linux-aio compatible with the behaviour of synchronous raw-posix requests and posix-aio-compat. The problem can be reproduced like this: dd if=/dev/zero of=/tmp/test.raw bs=1 count=1234 ./qemu-io -k -n -g -c 'read -p 1024 512' /tmp/test.raw Previously, the result of this was 'read failed: Invalid argument', now the read completes successfully. Signed-off-by: Kevin Wolf Reviewed-by: Stefan Hajnoczi (cherry picked from commit b161e2e4b32ac8fb9e6a891eba3da0b825b5d046) --- linux-aio.c | 17 ++++++++++++++--- 1 files changed, 14 insertions(+), 3 deletions(-) Signed-off-by: Michal Novotny --- linux-aio.c | 17 ++++++++++++++--- 1 files changed, 14 insertions(+), 3 deletions(-) diff --git a/linux-aio.c b/linux-aio.c index 746a764..015e6bd 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); } @@ -171,6 +180,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; -- 1.7.7.5