The handle_aiocb_rw() can't distinguish between an error and 0 bytes transferred.
diff --git a/block/raw-win32.c b/block/raw-win32.c index 68f2338..569dda2 100644 --- a/block/raw-win32.c +++ b/block/raw-win32.c @@ -60,11 +60,13 @@ typedef struct BDRVRawState { * Returns the number of bytes handles or -errno in case of an error. Short * reads are only returned if the end of the file is reached. */ -static size_t handle_aiocb_rw(RawWin32AIOData *aiocb) +static size_t handle_aiocb_rw(RawWin32AIOData *aiocb, BOOL *err) { size_t offset = 0; int i; + *err = FALSE; + for (i = 0; i < aiocb->aio_niov; i++) { OVERLAPPED ov; DWORD ret, ret_count, len; @@ -81,7 +83,8 @@ static size_t handle_aiocb_rw(RawWin32AIOData *aiocb) len, &ret_count, &ov); } if (!ret) { - ret_count = 0; + *err = TRUE; + break; } if (ret_count != len) { offset += ret_count; @@ -98,30 +101,39 @@ static int aio_worker(void *arg) RawWin32AIOData *aiocb = arg; ssize_t ret = 0; size_t count; + BOOL err = FALSE; switch (aiocb->aio_type & QEMU_AIO_TYPE_MASK) { case QEMU_AIO_READ: - count = handle_aiocb_rw(aiocb); - if (count < aiocb->aio_nbytes) { - /* A short read means that we have reached EOF. Pad the buffer - * with zeros for bytes after EOF. */ - iov_memset(aiocb->aio_iov, aiocb->aio_niov, count, - 0, aiocb->aio_nbytes - count); - - count = aiocb->aio_nbytes; - } - if (count == aiocb->aio_nbytes) { - ret = 0; - } else { + count = handle_aiocb_rw(aiocb, &err); + if (err) { ret = -EINVAL; + } else { + if (count < aiocb->aio_nbytes) { + /* A short read means that we have reached EOF. Pad the buffer + * with zeros for bytes after EOF. */ + iov_memset(aiocb->aio_iov, aiocb->aio_niov, count, + 0, aiocb->aio_nbytes - count); + + count = aiocb->aio_nbytes; + } + if (count == aiocb->aio_nbytes) { + ret = 0; + } else { + ret = -EINVAL; + } } break; case QEMU_AIO_WRITE: - count = handle_aiocb_rw(aiocb); - if (count == aiocb->aio_nbytes) { - count = 0; + count = handle_aiocb_rw(aiocb, &err); + if (err) { + ret = -EINVAL; } else { - count = -EINVAL; + if (count == aiocb->aio_nbytes) { + count = 0; + } else { + count = -EINVAL; + } } break; case QEMU_AIO_FLUSH: