diff options
author | Kevin Wolf <kwolf@redhat.com> | 2011-10-13 15:42:52 +0200 |
---|---|---|
committer | Kevin Wolf <kwolf@redhat.com> | 2011-10-14 10:29:13 +0200 |
commit | b161e2e4b32ac8fb9e6a891eba3da0b825b5d046 (patch) | |
tree | 6fce6aa203716a01110062b1563fc82074a2bb66 /linux-aio.c | |
parent | 1a6e115b19b0d3831d63bbacb843722070e6674c (diff) | |
download | qemu-b161e2e4b32ac8fb9e6a891eba3da0b825b5d046.zip qemu-b161e2e4b32ac8fb9e6a891eba3da0b825b5d046.tar.gz qemu-b161e2e4b32ac8fb9e6a891eba3da0b825b5d046.tar.bz2 |
linux-aio: Allow reads beyond the end of growable images
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 <kwolf@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
Diffstat (limited to 'linux-aio.c')
-rw-r--r-- | linux-aio.c | 17 |
1 files changed, 14 insertions, 3 deletions
diff --git a/linux-aio.c b/linux-aio.c index 50da75d..1c635ef 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; |