mirror of https://github.com/xemu-project/xemu.git
vdi: Avoid direct AIO callback
bdrv_aio_* must not call the callback before returning to its caller. In vdi, this could happen in some error cases. This starts the real requests processing in a BH to avoid this situation. Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
parent
b11a24dee6
commit
e67a64a869
41
block/vdi.c
41
block/vdi.c
|
@ -152,6 +152,7 @@ typedef struct {
|
||||||
/* Buffer for new allocated block. */
|
/* Buffer for new allocated block. */
|
||||||
void *block_buffer;
|
void *block_buffer;
|
||||||
void *orig_buf;
|
void *orig_buf;
|
||||||
|
bool is_write;
|
||||||
int header_modified;
|
int header_modified;
|
||||||
BlockDriverAIOCB *hd_aiocb;
|
BlockDriverAIOCB *hd_aiocb;
|
||||||
struct iovec hd_iov;
|
struct iovec hd_iov;
|
||||||
|
@ -504,6 +505,8 @@ static VdiAIOCB *vdi_aio_setup(BlockDriverState *bs, int64_t sector_num,
|
||||||
acb->hd_aiocb = NULL;
|
acb->hd_aiocb = NULL;
|
||||||
acb->sector_num = sector_num;
|
acb->sector_num = sector_num;
|
||||||
acb->qiov = qiov;
|
acb->qiov = qiov;
|
||||||
|
acb->is_write = is_write;
|
||||||
|
|
||||||
if (qiov->niov > 1) {
|
if (qiov->niov > 1) {
|
||||||
acb->buf = qemu_blockalign(bs, qiov->size);
|
acb->buf = qemu_blockalign(bs, qiov->size);
|
||||||
acb->orig_buf = acb->buf;
|
acb->orig_buf = acb->buf;
|
||||||
|
@ -542,14 +545,20 @@ static int vdi_schedule_bh(QEMUBHFunc *cb, VdiAIOCB *acb)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void vdi_aio_read_cb(void *opaque, int ret);
|
static void vdi_aio_read_cb(void *opaque, int ret);
|
||||||
|
static void vdi_aio_write_cb(void *opaque, int ret);
|
||||||
|
|
||||||
static void vdi_aio_read_bh(void *opaque)
|
static void vdi_aio_rw_bh(void *opaque)
|
||||||
{
|
{
|
||||||
VdiAIOCB *acb = opaque;
|
VdiAIOCB *acb = opaque;
|
||||||
logout("\n");
|
logout("\n");
|
||||||
qemu_bh_delete(acb->bh);
|
qemu_bh_delete(acb->bh);
|
||||||
acb->bh = NULL;
|
acb->bh = NULL;
|
||||||
vdi_aio_read_cb(opaque, 0);
|
|
||||||
|
if (acb->is_write) {
|
||||||
|
vdi_aio_write_cb(opaque, 0);
|
||||||
|
} else {
|
||||||
|
vdi_aio_read_cb(opaque, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void vdi_aio_read_cb(void *opaque, int ret)
|
static void vdi_aio_read_cb(void *opaque, int ret)
|
||||||
|
@ -597,7 +606,7 @@ static void vdi_aio_read_cb(void *opaque, int ret)
|
||||||
if (bmap_entry == VDI_UNALLOCATED) {
|
if (bmap_entry == VDI_UNALLOCATED) {
|
||||||
/* Block not allocated, return zeros, no need to wait. */
|
/* Block not allocated, return zeros, no need to wait. */
|
||||||
memset(acb->buf, 0, n_sectors * SECTOR_SIZE);
|
memset(acb->buf, 0, n_sectors * SECTOR_SIZE);
|
||||||
ret = vdi_schedule_bh(vdi_aio_read_bh, acb);
|
ret = vdi_schedule_bh(vdi_aio_rw_bh, acb);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
@ -630,12 +639,23 @@ static BlockDriverAIOCB *vdi_aio_readv(BlockDriverState *bs,
|
||||||
BlockDriverCompletionFunc *cb, void *opaque)
|
BlockDriverCompletionFunc *cb, void *opaque)
|
||||||
{
|
{
|
||||||
VdiAIOCB *acb;
|
VdiAIOCB *acb;
|
||||||
|
int ret;
|
||||||
|
|
||||||
logout("\n");
|
logout("\n");
|
||||||
acb = vdi_aio_setup(bs, sector_num, qiov, nb_sectors, cb, opaque, 0);
|
acb = vdi_aio_setup(bs, sector_num, qiov, nb_sectors, cb, opaque, 0);
|
||||||
if (!acb) {
|
if (!acb) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
vdi_aio_read_cb(acb, 0);
|
|
||||||
|
ret = vdi_schedule_bh(vdi_aio_rw_bh, acb);
|
||||||
|
if (ret < 0) {
|
||||||
|
if (acb->qiov->niov > 1) {
|
||||||
|
qemu_vfree(acb->orig_buf);
|
||||||
|
}
|
||||||
|
qemu_aio_release(acb);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return &acb->common;
|
return &acb->common;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -789,12 +809,23 @@ static BlockDriverAIOCB *vdi_aio_writev(BlockDriverState *bs,
|
||||||
BlockDriverCompletionFunc *cb, void *opaque)
|
BlockDriverCompletionFunc *cb, void *opaque)
|
||||||
{
|
{
|
||||||
VdiAIOCB *acb;
|
VdiAIOCB *acb;
|
||||||
|
int ret;
|
||||||
|
|
||||||
logout("\n");
|
logout("\n");
|
||||||
acb = vdi_aio_setup(bs, sector_num, qiov, nb_sectors, cb, opaque, 1);
|
acb = vdi_aio_setup(bs, sector_num, qiov, nb_sectors, cb, opaque, 1);
|
||||||
if (!acb) {
|
if (!acb) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
vdi_aio_write_cb(acb, 0);
|
|
||||||
|
ret = vdi_schedule_bh(vdi_aio_rw_bh, acb);
|
||||||
|
if (ret < 0) {
|
||||||
|
if (acb->qiov->niov > 1) {
|
||||||
|
qemu_vfree(acb->orig_buf);
|
||||||
|
}
|
||||||
|
qemu_aio_release(acb);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return &acb->common;
|
return &acb->common;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue