mirror of https://github.com/xemu-project/xemu.git
rbd: Fix race between aio completition and aio cancel
This one fixes a race which qemu had also in iscsi block driver between cancellation and io completition. qemu_rbd_aio_cancel was not synchronously waiting for the end of the command. To archieve this it introduces a new status flag which uses -EINPROGRESS. Signed-off-by: Stefan Priebe <s.priebe@profihost.ag> Reviewed-by: Stefan Hajnoczi <stefanha@gmail.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
parent
791bfa35ee
commit
473c7f0255
18
block/rbd.c
18
block/rbd.c
|
@ -77,6 +77,7 @@ typedef struct RBDAIOCB {
|
||||||
int error;
|
int error;
|
||||||
struct BDRVRBDState *s;
|
struct BDRVRBDState *s;
|
||||||
int cancelled;
|
int cancelled;
|
||||||
|
int status;
|
||||||
} RBDAIOCB;
|
} RBDAIOCB;
|
||||||
|
|
||||||
typedef struct RADOSCB {
|
typedef struct RADOSCB {
|
||||||
|
@ -376,12 +377,6 @@ static void qemu_rbd_complete_aio(RADOSCB *rcb)
|
||||||
RBDAIOCB *acb = rcb->acb;
|
RBDAIOCB *acb = rcb->acb;
|
||||||
int64_t r;
|
int64_t r;
|
||||||
|
|
||||||
if (acb->cancelled) {
|
|
||||||
qemu_vfree(acb->bounce);
|
|
||||||
qemu_aio_release(acb);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = rcb->ret;
|
r = rcb->ret;
|
||||||
|
|
||||||
if (acb->cmd == RBD_AIO_WRITE ||
|
if (acb->cmd == RBD_AIO_WRITE ||
|
||||||
|
@ -409,7 +404,6 @@ static void qemu_rbd_complete_aio(RADOSCB *rcb)
|
||||||
/* Note that acb->bh can be NULL in case where the aio was cancelled */
|
/* Note that acb->bh can be NULL in case where the aio was cancelled */
|
||||||
acb->bh = qemu_bh_new(rbd_aio_bh_cb, acb);
|
acb->bh = qemu_bh_new(rbd_aio_bh_cb, acb);
|
||||||
qemu_bh_schedule(acb->bh);
|
qemu_bh_schedule(acb->bh);
|
||||||
done:
|
|
||||||
g_free(rcb);
|
g_free(rcb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -568,6 +562,12 @@ static void qemu_rbd_aio_cancel(BlockDriverAIOCB *blockacb)
|
||||||
{
|
{
|
||||||
RBDAIOCB *acb = (RBDAIOCB *) blockacb;
|
RBDAIOCB *acb = (RBDAIOCB *) blockacb;
|
||||||
acb->cancelled = 1;
|
acb->cancelled = 1;
|
||||||
|
|
||||||
|
while (acb->status == -EINPROGRESS) {
|
||||||
|
qemu_aio_wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
qemu_aio_release(acb);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const AIOCBInfo rbd_aiocb_info = {
|
static const AIOCBInfo rbd_aiocb_info = {
|
||||||
|
@ -639,9 +639,12 @@ static void rbd_aio_bh_cb(void *opaque)
|
||||||
acb->common.cb(acb->common.opaque, (acb->ret > 0 ? 0 : acb->ret));
|
acb->common.cb(acb->common.opaque, (acb->ret > 0 ? 0 : acb->ret));
|
||||||
qemu_bh_delete(acb->bh);
|
qemu_bh_delete(acb->bh);
|
||||||
acb->bh = NULL;
|
acb->bh = NULL;
|
||||||
|
acb->status = 0;
|
||||||
|
|
||||||
|
if (!acb->cancelled) {
|
||||||
qemu_aio_release(acb);
|
qemu_aio_release(acb);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int rbd_aio_discard_wrapper(rbd_image_t image,
|
static int rbd_aio_discard_wrapper(rbd_image_t image,
|
||||||
uint64_t off,
|
uint64_t off,
|
||||||
|
@ -685,6 +688,7 @@ static BlockDriverAIOCB *rbd_start_aio(BlockDriverState *bs,
|
||||||
acb->s = s;
|
acb->s = s;
|
||||||
acb->cancelled = 0;
|
acb->cancelled = 0;
|
||||||
acb->bh = NULL;
|
acb->bh = NULL;
|
||||||
|
acb->status = -EINPROGRESS;
|
||||||
|
|
||||||
if (cmd == RBD_AIO_WRITE) {
|
if (cmd == RBD_AIO_WRITE) {
|
||||||
qemu_iovec_to_buf(acb->qiov, 0, acb->bounce, qiov->size);
|
qemu_iovec_to_buf(acb->qiov, 0, acb->bounce, qiov->size);
|
||||||
|
|
Loading…
Reference in New Issue