From acf3927aef42a4a380fa1366b2eca8a8f2b44bc4 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Thu, 7 Feb 2019 12:18:18 +0000 Subject: [PATCH 7/8] scsi-disk: Acquire the AioContext in scsi_*_realize() RH-Author: Markus Armbruster Message-id: <20190207121819.20092-3-armbru@redhat.com> Patchwork-id: 84291 O-Subject: [RHEL-8.0/AV qemu-kvm PATCH 2/3] scsi-disk: Acquire the AioContext in scsi_*_realize() Bugzilla: 1656276 1662508 RH-Acked-by: Kevin Wolf RH-Acked-by: Max Reitz RH-Acked-by: Stefan Hajnoczi From: Alberto Garcia This fixes a crash when attaching two disks with the same blockdev to a SCSI device that is using iothreads. Test case included. Signed-off-by: Alberto Garcia Signed-off-by: Kevin Wolf (cherry picked from commit 3ff35ba391134e4e43ab96152deb38a62e62f858) Signed-off-by: Danilo C. L. de Paula --- hw/scsi/scsi-disk.c | 23 ++++++++++++++++++++--- tests/qemu-iotests/240 | 18 ++++++++++++++++++ tests/qemu-iotests/240.out | 16 ++++++++++++++++ 3 files changed, 54 insertions(+), 3 deletions(-) diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c index e74e1e7..e6db6d7 100644 --- a/hw/scsi/scsi-disk.c +++ b/hw/scsi/scsi-disk.c @@ -2389,10 +2389,13 @@ static void scsi_realize(SCSIDevice *dev, Error **errp) static void scsi_hd_realize(SCSIDevice *dev, Error **errp) { SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev); + AioContext *ctx = NULL; /* can happen for devices without drive. The error message for missing * backend will be issued in scsi_realize */ if (s->qdev.conf.blk) { + ctx = blk_get_aio_context(s->qdev.conf.blk); + aio_context_acquire(ctx); blkconf_blocksizes(&s->qdev.conf); } s->qdev.blocksize = s->qdev.conf.logical_block_size; @@ -2401,11 +2404,15 @@ static void scsi_hd_realize(SCSIDevice *dev, Error **errp) s->product = g_strdup("QEMU HARDDISK"); } scsi_realize(&s->qdev, errp); + if (ctx) { + aio_context_release(ctx); + } } static void scsi_cd_realize(SCSIDevice *dev, Error **errp) { SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev); + AioContext *ctx; int ret; if (!dev->conf.blk) { @@ -2416,6 +2423,8 @@ static void scsi_cd_realize(SCSIDevice *dev, Error **errp) assert(ret == 0); } + ctx = blk_get_aio_context(dev->conf.blk); + aio_context_acquire(ctx); s->qdev.blocksize = 2048; s->qdev.type = TYPE_ROM; s->features |= 1 << SCSI_DISK_F_REMOVABLE; @@ -2423,6 +2432,7 @@ static void scsi_cd_realize(SCSIDevice *dev, Error **errp) s->product = g_strdup("QEMU CD-ROM"); } scsi_realize(&s->qdev, errp); + aio_context_release(ctx); } static void scsi_disk_realize(SCSIDevice *dev, Error **errp) @@ -2561,6 +2571,7 @@ static int get_device_type(SCSIDiskState *s) static void scsi_block_realize(SCSIDevice *dev, Error **errp) { SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev); + AioContext *ctx; int sg_version; int rc; @@ -2575,6 +2586,9 @@ static void scsi_block_realize(SCSIDevice *dev, Error **errp) "be removed in a future version"); } + ctx = blk_get_aio_context(s->qdev.conf.blk); + aio_context_acquire(ctx); + /* check we are using a driver managing SG_IO (version 3 and after) */ rc = blk_ioctl(s->qdev.conf.blk, SG_GET_VERSION_NUM, &sg_version); if (rc < 0) { @@ -2582,18 +2596,18 @@ static void scsi_block_realize(SCSIDevice *dev, Error **errp) if (rc != -EPERM) { error_append_hint(errp, "Is this a SCSI device?\n"); } - return; + goto out; } if (sg_version < 30000) { error_setg(errp, "scsi generic interface too old"); - return; + goto out; } /* get device type from INQUIRY data */ rc = get_device_type(s); if (rc < 0) { error_setg(errp, "INQUIRY failed"); - return; + goto out; } /* Make a guess for the block size, we'll fix it when the guest sends. @@ -2613,6 +2627,9 @@ static void scsi_block_realize(SCSIDevice *dev, Error **errp) scsi_realize(&s->qdev, errp); scsi_generic_read_device_inquiry(&s->qdev); + +out: + aio_context_release(ctx); } typedef struct SCSIBlockReq { diff --git a/tests/qemu-iotests/240 b/tests/qemu-iotests/240 index ead7ee0..5d499c9 100755 --- a/tests/qemu-iotests/240 +++ b/tests/qemu-iotests/240 @@ -83,6 +83,24 @@ run_qemu <