* [Qemu-devel] [PATCH v2 0/2] block, virtio-scsi: Fix blk_set_aio_context
@ 2015-02-15 2:40 Fam Zheng
2015-02-15 2:40 ` [Qemu-devel] [PATCH v2 1/2] block: Forbid bdrv_set_aio_context outside BQL Fam Zheng
2015-02-15 2:40 ` [Qemu-devel] [PATCH v2 2/2] virtio-scsi-dataplane: Call blk_set_aio_context within BQL Fam Zheng
0 siblings, 2 replies; 4+ messages in thread
From: Fam Zheng @ 2015-02-15 2:40 UTC (permalink / raw)
To: qemu-devel; +Cc: kwolf, Paolo Bonzini, stefanha
This is the simplified fix of:
[PATCH 0/3] virtio-scsi: Fix unsafe bdrv_set_aio_context calls
I included the original patch 1 - the function header comment update for
bdrv_set_aio_context and added Paolo's rev-by.
Fam Zheng (2):
block: Forbid bdrv_set_aio_context outside BQL
virtio-scsi-dataplane: Call blk_set_aio_context within BQL
hw/scsi/virtio-scsi.c | 15 +++++++--------
include/block/block.h | 3 +--
2 files changed, 8 insertions(+), 10 deletions(-)
--
2.1.0
^ permalink raw reply [flat|nested] 4+ messages in thread
* [Qemu-devel] [PATCH v2 1/2] block: Forbid bdrv_set_aio_context outside BQL
2015-02-15 2:40 [Qemu-devel] [PATCH v2 0/2] block, virtio-scsi: Fix blk_set_aio_context Fam Zheng
@ 2015-02-15 2:40 ` Fam Zheng
2015-02-15 3:05 ` Fam Zheng
2015-02-15 2:40 ` [Qemu-devel] [PATCH v2 2/2] virtio-scsi-dataplane: Call blk_set_aio_context within BQL Fam Zheng
1 sibling, 1 reply; 4+ messages in thread
From: Fam Zheng @ 2015-02-15 2:40 UTC (permalink / raw)
To: qemu-devel; +Cc: kwolf, Paolo Bonzini, stefanha
Even if the caller has the old #AioContext, there can be a deadlock, due
to the leading bdrv_drain_all:
Suppose there are three io threads (a, b, c) with each owning a BDS
(bds_a, bds_b, bds_c), and a and b want to move their own BDS to c at
the same time:
iothread a iothread b
--------------------------------------------------------------------------
bdrv_set_aio_context(bds_a, c) bdrv_set_aio_context(bds_b, c)
-> bdrv_drain_all() -> bdrv_drain_all()
-> acquire a (OK, already has) -> acquire a (blocked)
-> acquire b (blocked) -> acquire b
-> acquire c -> acquire c
Current caller of bdrv_set_aio_context outside BQL is
virtio-scsi-dataplane, which will be fixed in the next patches.
Signed-off-by: Fam Zheng <famz@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
---
include/block/block.h | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/include/block/block.h b/include/block/block.h
index 321295e..4fce25d 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -546,8 +546,7 @@ AioContext *bdrv_get_aio_context(BlockDriverState *bs);
* Changes the #AioContext used for fd handlers, timers, and BHs by this
* BlockDriverState and all its children.
*
- * This function must be called from the old #AioContext or with a lock held so
- * the old #AioContext is not executing.
+ * This function must be called with iothread lock held.
*/
void bdrv_set_aio_context(BlockDriverState *bs, AioContext *new_context);
--
2.1.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [Qemu-devel] [PATCH v2 2/2] virtio-scsi-dataplane: Call blk_set_aio_context within BQL
2015-02-15 2:40 [Qemu-devel] [PATCH v2 0/2] block, virtio-scsi: Fix blk_set_aio_context Fam Zheng
2015-02-15 2:40 ` [Qemu-devel] [PATCH v2 1/2] block: Forbid bdrv_set_aio_context outside BQL Fam Zheng
@ 2015-02-15 2:40 ` Fam Zheng
1 sibling, 0 replies; 4+ messages in thread
From: Fam Zheng @ 2015-02-15 2:40 UTC (permalink / raw)
To: qemu-devel; +Cc: kwolf, Paolo Bonzini, stefanha
It's not safe to call blk_set_aio_context from outside BQL because of
the bdrv_drain_all there. Let's put it in the hotplug callback which
will be called by qdev device realization for each scsi device attached
to the bus.
Signed-off-by: Fam Zheng <famz@redhat.com>
---
hw/scsi/virtio-scsi.c | 15 +++++++--------
1 file changed, 7 insertions(+), 8 deletions(-)
diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
index 9e2c718..8c437dd 100644
--- a/hw/scsi/virtio-scsi.c
+++ b/hw/scsi/virtio-scsi.c
@@ -254,10 +254,8 @@ static int virtio_scsi_do_tmf(VirtIOSCSI *s, VirtIOSCSIReq *req)
int target;
int ret = 0;
- if (s->dataplane_started && blk_get_aio_context(d->conf.blk) != s->ctx) {
- aio_context_acquire(s->ctx);
- blk_set_aio_context(d->conf.blk, s->ctx);
- aio_context_release(s->ctx);
+ if (s->dataplane_started) {
+ assert(blk_get_aio_context(d->conf.blk) == s->ctx);
}
/* Here VIRTIO_SCSI_S_OK means "FUNCTION COMPLETE". */
req->resp.tmf.response = VIRTIO_SCSI_S_OK;
@@ -540,10 +538,8 @@ bool virtio_scsi_handle_cmd_req_prepare(VirtIOSCSI *s, VirtIOSCSIReq *req)
virtio_scsi_complete_cmd_req(req);
return false;
}
- if (s->dataplane_started && blk_get_aio_context(d->conf.blk) != s->ctx) {
- aio_context_acquire(s->ctx);
- blk_set_aio_context(d->conf.blk, s->ctx);
- aio_context_release(s->ctx);
+ if (s->dataplane_started) {
+ assert(blk_get_aio_context(d->conf.blk) == s->ctx);
}
req->sreq = scsi_req_new(d, req->req.cmd.tag,
virtio_scsi_get_lun(req->req.cmd.lun),
@@ -767,6 +763,9 @@ static void virtio_scsi_hotplug(HotplugHandler *hotplug_dev, DeviceState *dev,
return;
}
blk_op_block_all(sd->conf.blk, s->blocker);
+ aio_context_acquire(s->ctx);
+ blk_set_aio_context(sd->conf.blk, s->ctx);
+ aio_context_release(s->ctx);
}
if ((vdev->guest_features >> VIRTIO_SCSI_F_HOTPLUG) & 1) {
--
2.1.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [Qemu-devel] [PATCH v2 1/2] block: Forbid bdrv_set_aio_context outside BQL
2015-02-15 2:40 ` [Qemu-devel] [PATCH v2 1/2] block: Forbid bdrv_set_aio_context outside BQL Fam Zheng
@ 2015-02-15 3:05 ` Fam Zheng
0 siblings, 0 replies; 4+ messages in thread
From: Fam Zheng @ 2015-02-15 3:05 UTC (permalink / raw)
To: qemu-devel; +Cc: kwolf, Paolo Bonzini, stefanha
On Sun, 02/15 10:40, Fam Zheng wrote:
> Even if the caller has the old #AioContext, there can be a deadlock, due
> to the leading bdrv_drain_all:
>
> Suppose there are three io threads (a, b, c) with each owning a BDS
> (bds_a, bds_b, bds_c), and a and b want to move their own BDS to c at
> the same time:
>
> iothread a iothread b
> --------------------------------------------------------------------------
> bdrv_set_aio_context(bds_a, c) bdrv_set_aio_context(bds_b, c)
> -> bdrv_drain_all() -> bdrv_drain_all()
> -> acquire a (OK, already has) -> acquire a (blocked)
> -> acquire b (blocked) -> acquire b
> -> acquire c -> acquire c
This doesn't recap the essence of the bug because one may argue that
aio_context_acquire(c) is needed before either thread calling
bdrv_set_aio_context. Actually it doesn't matter in this case, because iothread
b can as well do bdrv_set_aio_context(bds_b, d).
I'll update the commit log with v3.
Fam
>
> Current caller of bdrv_set_aio_context outside BQL is
> virtio-scsi-dataplane, which will be fixed in the next patches.
>
> Signed-off-by: Fam Zheng <famz@redhat.com>
> Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
> include/block/block.h | 3 +--
> 1 file changed, 1 insertion(+), 2 deletions(-)
>
> diff --git a/include/block/block.h b/include/block/block.h
> index 321295e..4fce25d 100644
> --- a/include/block/block.h
> +++ b/include/block/block.h
> @@ -546,8 +546,7 @@ AioContext *bdrv_get_aio_context(BlockDriverState *bs);
> * Changes the #AioContext used for fd handlers, timers, and BHs by this
> * BlockDriverState and all its children.
> *
> - * This function must be called from the old #AioContext or with a lock held so
> - * the old #AioContext is not executing.
> + * This function must be called with iothread lock held.
> */
> void bdrv_set_aio_context(BlockDriverState *bs, AioContext *new_context);
>
> --
> 2.1.0
>
>
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2015-02-15 3:05 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-02-15 2:40 [Qemu-devel] [PATCH v2 0/2] block, virtio-scsi: Fix blk_set_aio_context Fam Zheng
2015-02-15 2:40 ` [Qemu-devel] [PATCH v2 1/2] block: Forbid bdrv_set_aio_context outside BQL Fam Zheng
2015-02-15 3:05 ` Fam Zheng
2015-02-15 2:40 ` [Qemu-devel] [PATCH v2 2/2] virtio-scsi-dataplane: Call blk_set_aio_context within BQL Fam Zheng
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).