diff options
author | Anthony Liguori <aliguori@us.ibm.com> | 2012-08-22 13:31:17 -0500 |
---|---|---|
committer | Anthony Liguori <aliguori@us.ibm.com> | 2012-08-22 13:31:17 -0500 |
commit | a9b670b139ed381bd07df08bdfdcb515dff3ca8c (patch) | |
tree | 59e4e8489ef3dfbb90635b3dc9ed805b8aef973c /block | |
parent | 7b2f89c435f895431d55b675dc412275c2069314 (diff) | |
parent | 07a5298c3067ed63f7d82d8c1a6f479146447289 (diff) | |
download | qemu-a9b670b139ed381bd07df08bdfdcb515dff3ca8c.zip qemu-a9b670b139ed381bd07df08bdfdcb515dff3ca8c.tar.gz qemu-a9b670b139ed381bd07df08bdfdcb515dff3ca8c.tar.bz2 |
Merge remote-tracking branch 'bonzini/scsi-next' into staging
* bonzini/scsi-next:
virtio-scsi: add backwards-compatibility properties for 1.1 and earlier machines
iscsi: fix races between task completion and abort
iscsi: simplify iscsi_schedule_bh
iscsi: move iscsi_schedule_bh and iscsi_readv_writev_bh_cb
Revert "iscsi: Fix NULL dereferences / races between task completion and abort"
Diffstat (limited to 'block')
-rw-r--r-- | block/iscsi.c | 122 |
1 files changed, 63 insertions, 59 deletions
diff --git a/block/iscsi.c b/block/iscsi.c index bb9cf82..4828b83 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -73,13 +73,43 @@ struct IscsiTask { }; static void +iscsi_bh_cb(void *p) +{ + IscsiAIOCB *acb = p; + + qemu_bh_delete(acb->bh); + + if (acb->canceled == 0) { + acb->common.cb(acb->common.opaque, acb->status); + } + + if (acb->task != NULL) { + scsi_free_scsi_task(acb->task); + acb->task = NULL; + } + + qemu_aio_release(acb); +} + +static void +iscsi_schedule_bh(IscsiAIOCB *acb) +{ + if (acb->bh) { + return; + } + acb->bh = qemu_bh_new(iscsi_bh_cb, acb); + qemu_bh_schedule(acb->bh); +} + + +static void iscsi_abort_task_cb(struct iscsi_context *iscsi, int status, void *command_data, void *private_data) { - IscsiAIOCB *acb = (IscsiAIOCB *)private_data; + IscsiAIOCB *acb = private_data; - scsi_free_scsi_task(acb->task); - acb->task = NULL; + acb->status = -ECANCELED; + iscsi_schedule_bh(acb); } static void @@ -88,15 +118,19 @@ iscsi_aio_cancel(BlockDriverAIOCB *blockacb) IscsiAIOCB *acb = (IscsiAIOCB *)blockacb; IscsiLun *iscsilun = acb->iscsilun; - acb->canceled = 1; + if (acb->status != -EINPROGRESS) { + return; + } - acb->common.cb(acb->common.opaque, -ECANCELED); + acb->canceled = 1; - /* send a task mgmt call to the target to cancel the task on the target - * this also cancels the task in libiscsi - */ + /* send a task mgmt call to the target to cancel the task on the target */ iscsi_task_mgmt_abort_task_async(iscsilun->iscsi, acb->task, - iscsi_abort_task_cb, &acb); + iscsi_abort_task_cb, acb); + + while (acb->status == -EINPROGRESS) { + qemu_aio_wait(); + } } static AIOPool iscsi_aio_pool = { @@ -163,41 +197,6 @@ iscsi_process_write(void *arg) } -static int -iscsi_schedule_bh(QEMUBHFunc *cb, IscsiAIOCB *acb) -{ - acb->bh = qemu_bh_new(cb, acb); - if (!acb->bh) { - error_report("oom: could not create iscsi bh"); - return -EIO; - } - - qemu_bh_schedule(acb->bh); - return 0; -} - -static void -iscsi_readv_writev_bh_cb(void *p) -{ - IscsiAIOCB *acb = p; - - qemu_bh_delete(acb->bh); - - if (!acb->canceled) { - acb->common.cb(acb->common.opaque, acb->status); - } - - qemu_aio_release(acb); - - if (acb->canceled) { - return; - } - - scsi_free_scsi_task(acb->task); - acb->task = NULL; -} - - static void iscsi_aio_write16_cb(struct iscsi_context *iscsi, int status, void *command_data, void *opaque) @@ -208,8 +207,7 @@ iscsi_aio_write16_cb(struct iscsi_context *iscsi, int status, g_free(acb->buf); - if (acb->canceled) { - qemu_aio_release(acb); + if (acb->canceled != 0) { return; } @@ -220,7 +218,7 @@ iscsi_aio_write16_cb(struct iscsi_context *iscsi, int status, acb->status = -EIO; } - iscsi_schedule_bh(iscsi_readv_writev_bh_cb, acb); + iscsi_schedule_bh(acb); } static int64_t sector_qemu2lun(int64_t sector, IscsiLun *iscsilun) @@ -249,6 +247,8 @@ iscsi_aio_writev(BlockDriverState *bs, int64_t sector_num, acb->qiov = qiov; acb->canceled = 0; + acb->bh = NULL; + acb->status = -EINPROGRESS; /* XXX we should pass the iovec to write16 to avoid the extra copy */ /* this will allow us to get rid of 'buf' completely */ @@ -305,8 +305,7 @@ iscsi_aio_read16_cb(struct iscsi_context *iscsi, int status, trace_iscsi_aio_read16_cb(iscsi, status, acb, acb->canceled); - if (acb->canceled) { - qemu_aio_release(acb); + if (acb->canceled != 0) { return; } @@ -317,7 +316,7 @@ iscsi_aio_read16_cb(struct iscsi_context *iscsi, int status, acb->status = -EIO; } - iscsi_schedule_bh(iscsi_readv_writev_bh_cb, acb); + iscsi_schedule_bh(acb); } static BlockDriverAIOCB * @@ -343,6 +342,8 @@ iscsi_aio_readv(BlockDriverState *bs, int64_t sector_num, acb->qiov = qiov; acb->canceled = 0; + acb->bh = NULL; + acb->status = -EINPROGRESS; acb->read_size = qemu_read_size; acb->buf = NULL; @@ -417,8 +418,7 @@ iscsi_synccache10_cb(struct iscsi_context *iscsi, int status, { IscsiAIOCB *acb = opaque; - if (acb->canceled) { - qemu_aio_release(acb); + if (acb->canceled != 0) { return; } @@ -429,7 +429,7 @@ iscsi_synccache10_cb(struct iscsi_context *iscsi, int status, acb->status = -EIO; } - iscsi_schedule_bh(iscsi_readv_writev_bh_cb, acb); + iscsi_schedule_bh(acb); } static BlockDriverAIOCB * @@ -444,6 +444,8 @@ iscsi_aio_flush(BlockDriverState *bs, acb->iscsilun = iscsilun; acb->canceled = 0; + acb->bh = NULL; + acb->status = -EINPROGRESS; acb->task = iscsi_synchronizecache10_task(iscsi, iscsilun->lun, 0, 0, 0, 0, @@ -467,8 +469,7 @@ iscsi_unmap_cb(struct iscsi_context *iscsi, int status, { IscsiAIOCB *acb = opaque; - if (acb->canceled) { - qemu_aio_release(acb); + if (acb->canceled != 0) { return; } @@ -479,7 +480,7 @@ iscsi_unmap_cb(struct iscsi_context *iscsi, int status, acb->status = -EIO; } - iscsi_schedule_bh(iscsi_readv_writev_bh_cb, acb); + iscsi_schedule_bh(acb); } static BlockDriverAIOCB * @@ -496,6 +497,8 @@ iscsi_aio_discard(BlockDriverState *bs, acb->iscsilun = iscsilun; acb->canceled = 0; + acb->bh = NULL; + acb->status = -EINPROGRESS; list[0].lba = sector_qemu2lun(sector_num, iscsilun); list[0].num = nb_sectors * BDRV_SECTOR_SIZE / iscsilun->block_size; @@ -523,8 +526,7 @@ iscsi_aio_ioctl_cb(struct iscsi_context *iscsi, int status, { IscsiAIOCB *acb = opaque; - if (acb->canceled) { - qemu_aio_release(acb); + if (acb->canceled != 0) { return; } @@ -552,7 +554,7 @@ iscsi_aio_ioctl_cb(struct iscsi_context *iscsi, int status, memcpy(acb->ioh->sbp, &acb->task->datain.data[2], ss); } - iscsi_schedule_bh(iscsi_readv_writev_bh_cb, acb); + iscsi_schedule_bh(acb); } static BlockDriverAIOCB *iscsi_aio_ioctl(BlockDriverState *bs, @@ -570,6 +572,8 @@ static BlockDriverAIOCB *iscsi_aio_ioctl(BlockDriverState *bs, acb->iscsilun = iscsilun; acb->canceled = 0; + acb->bh = NULL; + acb->status = -EINPROGRESS; acb->buf = NULL; acb->ioh = buf; |