linux-aio: Allow reads beyond the end of growable images
This is the linux-aio version of commits22afa7b5
(raw-posix, synchronous) andba1d1afd
(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>
This commit is contained in:
parent
1a6e115b19
commit
b161e2e4b3
17
linux-aio.c
17
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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user