From 271b385e7ec2f1ca23c5345599cd58d9651427e5 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Fri, 20 May 2016 11:00:31 -0700 Subject: [PATCH 01/12] tests: avoid coroutine pool test crash Skip the test_co_queue test case if the coroutine pool is not enabled. The test case does not work without the pool because it touches memory belonging to a freed coroutine (on purpose). Reported-by: Eduardo Habkost Signed-off-by: Stefan Hajnoczi Reviewed-by: Fam Zheng Message-id: 1463767231-13379-1-git-send-email-stefanha@redhat.com --- tests/test-coroutine.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/tests/test-coroutine.c b/tests/test-coroutine.c index dd4ced946c..ea7f87f487 100644 --- a/tests/test-coroutine.c +++ b/tests/test-coroutine.c @@ -369,7 +369,15 @@ static void perf_cost(void) int main(int argc, char **argv) { g_test_init(&argc, &argv, NULL); - g_test_add_func("/basic/co_queue", test_co_queue); + + /* This test assumes there is a freelist and marks freed coroutine memory + * with a sentinel value. If there is no freelist this would legitimately + * crash, so skip it. + */ + if (CONFIG_COROUTINE_POOL) { + g_test_add_func("/basic/co_queue", test_co_queue); + } + g_test_add_func("/basic/lifecycle", test_lifecycle); g_test_add_func("/basic/yield", test_yield); g_test_add_func("/basic/nesting", test_nesting); From 0d97891312d24891868e341674541f4147c7faf4 Mon Sep 17 00:00:00 2001 From: Fam Zheng Date: Mon, 23 May 2016 10:19:35 +0800 Subject: [PATCH 02/12] blockdev-backup: Use bdrv_lookup_bs on target This allows backing up to a BDS that has not been attached to any BB. Signed-off-by: Fam Zheng Message-id: 1463969978-24970-2-git-send-email-famz@redhat.com Signed-off-by: Stefan Hajnoczi --- blockdev.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/blockdev.c b/blockdev.c index 717785eb8d..ea7f3974e2 100644 --- a/blockdev.c +++ b/blockdev.c @@ -3335,7 +3335,7 @@ void do_blockdev_backup(const char *device, const char *target, BlockdevOnError on_target_error, BlockJobTxn *txn, Error **errp) { - BlockBackend *blk, *target_blk; + BlockBackend *blk; BlockDriverState *bs; BlockDriverState *target_bs; Error *local_err = NULL; @@ -3366,18 +3366,11 @@ void do_blockdev_backup(const char *device, const char *target, } bs = blk_bs(blk); - target_blk = blk_by_name(target); - if (!target_blk) { - error_setg(errp, "Device '%s' not found", target); + target_bs = bdrv_lookup_bs(target, target, errp); + if (!target_bs) { goto out; } - if (!blk_is_available(target_blk)) { - error_setg(errp, "Device '%s' has no medium", target); - goto out; - } - target_bs = blk_bs(target_blk); - bdrv_set_aio_context(target_bs, aio_context); backup_start(bs, target_bs, speed, sync, NULL, on_source_error, on_target_error, block_job_cb, bs, txn, &local_err); From efd7556708bdfb61dab259e08bd71fbe5680ddcd Mon Sep 17 00:00:00 2001 From: Fam Zheng Date: Mon, 23 May 2016 10:19:36 +0800 Subject: [PATCH 03/12] blockdev-backup: Don't move target AioContext if it's attached If the BDS is attached, it will want to stay on the AioContext where its BlockBackend is. Don't call bdrv_set_aio_context in this case. Signed-off-by: Fam Zheng Message-id: 1463969978-24970-3-git-send-email-famz@redhat.com Signed-off-by: Stefan Hajnoczi --- blockdev.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/blockdev.c b/blockdev.c index ea7f3974e2..6ccb8e1f84 100644 --- a/blockdev.c +++ b/blockdev.c @@ -3371,7 +3371,17 @@ void do_blockdev_backup(const char *device, const char *target, goto out; } - bdrv_set_aio_context(target_bs, aio_context); + if (bdrv_get_aio_context(target_bs) != aio_context) { + if (!bdrv_has_blk(target_bs)) { + /* The target BDS is not attached, we can safely move it to another + * AioContext. */ + bdrv_set_aio_context(target_bs, aio_context); + } else { + error_setg(errp, "Target is attached to a different thread from " + "source."); + goto out; + } + } backup_start(bs, target_bs, speed, sync, NULL, on_source_error, on_target_error, block_job_cb, bs, txn, &local_err); if (local_err != NULL) { From 348295838384941d1e5420d10e57366c4e303d45 Mon Sep 17 00:00:00 2001 From: Fam Zheng Date: Mon, 23 May 2016 10:19:37 +0800 Subject: [PATCH 04/12] virtio-blk: Remove op blocker for dataplane Block layer is prepared to unspecialize dataplane, an evidence is this almost complete list of unblocked operations. It has all types except two (actually three if DATAPLANE itself counts but blockdev.c makes sure attaching twice is not possible): MIRROR_TARGET and BACKUP_TARGET. blockdev-mirror refuses to start if target is attached, so the first is not a problem. By removing BACKUP_TARGET, blockdev-backup will become permissive to write to a virtio-blk dataplane disk, but that is not worse than non-dataplane given the latter is already possible. In either case, blockdev.c always checks the target and source are on the same AioContext, or bring them together if possible. Signed-off-by: Fam Zheng Acked-by: Michael S. Tsirkin Message-id: 1463969978-24970-4-git-send-email-famz@redhat.com Signed-off-by: Stefan Hajnoczi --- hw/block/dataplane/virtio-blk.c | 63 --------------------------------- 1 file changed, 63 deletions(-) diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c index 3cb97c9a29..2073f9a270 100644 --- a/hw/block/dataplane/virtio-blk.c +++ b/hw/block/dataplane/virtio-blk.c @@ -37,8 +37,6 @@ struct VirtIOBlockDataPlane { EventNotifier *guest_notifier; /* irq */ QEMUBH *bh; /* bh for guest notification */ - Notifier insert_notifier, remove_notifier; - /* Note that these EventNotifiers are assigned by value. This is * fine as long as you do not call event_notifier_cleanup on them * (because you don't own the file descriptor or handle; you just @@ -46,9 +44,6 @@ struct VirtIOBlockDataPlane { */ IOThread *iothread; AioContext *ctx; - - /* Operation blocker on BDS */ - Error *blocker; }; /* Raise an interrupt to signal guest, if necessary */ @@ -68,54 +63,6 @@ static void notify_guest_bh(void *opaque) event_notifier_set(s->guest_notifier); } -static void data_plane_set_up_op_blockers(VirtIOBlockDataPlane *s) -{ - assert(!s->blocker); - error_setg(&s->blocker, "block device is in use by data plane"); - blk_op_block_all(s->conf->conf.blk, s->blocker); - blk_op_unblock(s->conf->conf.blk, BLOCK_OP_TYPE_RESIZE, s->blocker); - blk_op_unblock(s->conf->conf.blk, BLOCK_OP_TYPE_DRIVE_DEL, s->blocker); - blk_op_unblock(s->conf->conf.blk, BLOCK_OP_TYPE_BACKUP_SOURCE, s->blocker); - blk_op_unblock(s->conf->conf.blk, BLOCK_OP_TYPE_CHANGE, s->blocker); - blk_op_unblock(s->conf->conf.blk, BLOCK_OP_TYPE_COMMIT_SOURCE, s->blocker); - blk_op_unblock(s->conf->conf.blk, BLOCK_OP_TYPE_COMMIT_TARGET, s->blocker); - blk_op_unblock(s->conf->conf.blk, BLOCK_OP_TYPE_EJECT, s->blocker); - blk_op_unblock(s->conf->conf.blk, BLOCK_OP_TYPE_EXTERNAL_SNAPSHOT, - s->blocker); - blk_op_unblock(s->conf->conf.blk, BLOCK_OP_TYPE_INTERNAL_SNAPSHOT, - s->blocker); - blk_op_unblock(s->conf->conf.blk, BLOCK_OP_TYPE_INTERNAL_SNAPSHOT_DELETE, - s->blocker); - blk_op_unblock(s->conf->conf.blk, BLOCK_OP_TYPE_MIRROR_SOURCE, s->blocker); - blk_op_unblock(s->conf->conf.blk, BLOCK_OP_TYPE_STREAM, s->blocker); - blk_op_unblock(s->conf->conf.blk, BLOCK_OP_TYPE_REPLACE, s->blocker); -} - -static void data_plane_remove_op_blockers(VirtIOBlockDataPlane *s) -{ - if (s->blocker) { - blk_op_unblock_all(s->conf->conf.blk, s->blocker); - error_free(s->blocker); - s->blocker = NULL; - } -} - -static void data_plane_blk_insert_notifier(Notifier *n, void *data) -{ - VirtIOBlockDataPlane *s = container_of(n, VirtIOBlockDataPlane, - insert_notifier); - assert(s->conf->conf.blk == data); - data_plane_set_up_op_blockers(s); -} - -static void data_plane_blk_remove_notifier(Notifier *n, void *data) -{ - VirtIOBlockDataPlane *s = container_of(n, VirtIOBlockDataPlane, - remove_notifier); - assert(s->conf->conf.blk == data); - data_plane_remove_op_blockers(s); -} - /* Context: QEMU global mutex held */ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *conf, VirtIOBlockDataPlane **dataplane, @@ -158,13 +105,6 @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *conf, s->ctx = iothread_get_aio_context(s->iothread); s->bh = aio_bh_new(s->ctx, notify_guest_bh, s); - s->insert_notifier.notify = data_plane_blk_insert_notifier; - s->remove_notifier.notify = data_plane_blk_remove_notifier; - blk_add_insert_bs_notifier(conf->conf.blk, &s->insert_notifier); - blk_add_remove_bs_notifier(conf->conf.blk, &s->remove_notifier); - - data_plane_set_up_op_blockers(s); - *dataplane = s; } @@ -176,9 +116,6 @@ void virtio_blk_data_plane_destroy(VirtIOBlockDataPlane *s) } virtio_blk_data_plane_stop(s); - data_plane_remove_op_blockers(s); - notifier_remove(&s->insert_notifier); - notifier_remove(&s->remove_notifier); qemu_bh_delete(s->bh); object_unref(OBJECT(s->iothread)); g_free(s); From ef8875b5491b6eb375d0636e6cfe430f93c058f9 Mon Sep 17 00:00:00 2001 From: Fam Zheng Date: Mon, 23 May 2016 10:19:38 +0800 Subject: [PATCH 05/12] virtio-scsi: Remove op blocker for dataplane The previous patch dropped all op blockers from virtio-blk data plane. The situation of virtio-scsi is exactly the same it can drop them too. Signed-off-by: Fam Zheng Acked-by: Michael S. Tsirkin Message-id: 1463969978-24970-5-git-send-email-famz@redhat.com Signed-off-by: Stefan Hajnoczi --- hw/scsi/virtio-scsi.c | 62 --------------------------------- include/hw/virtio/virtio-scsi.h | 11 ------ 2 files changed, 73 deletions(-) diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c index 30415c6a92..d26f4908d4 100644 --- a/hw/scsi/virtio-scsi.c +++ b/hw/scsi/virtio-scsi.c @@ -773,22 +773,6 @@ static void virtio_scsi_change(SCSIBus *bus, SCSIDevice *dev, SCSISense sense) } } -static void virtio_scsi_blk_insert_notifier(Notifier *n, void *data) -{ - VirtIOSCSIBlkChangeNotifier *cn = DO_UPCAST(VirtIOSCSIBlkChangeNotifier, - n, n); - assert(cn->sd->conf.blk == data); - blk_op_block_all(cn->sd->conf.blk, cn->s->blocker); -} - -static void virtio_scsi_blk_remove_notifier(Notifier *n, void *data) -{ - VirtIOSCSIBlkChangeNotifier *cn = DO_UPCAST(VirtIOSCSIBlkChangeNotifier, - n, n); - assert(cn->sd->conf.blk == data); - blk_op_unblock_all(cn->sd->conf.blk, cn->s->blocker); -} - static void virtio_scsi_hotplug(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { @@ -797,29 +781,13 @@ static void virtio_scsi_hotplug(HotplugHandler *hotplug_dev, DeviceState *dev, SCSIDevice *sd = SCSI_DEVICE(dev); if (s->ctx && !s->dataplane_fenced) { - VirtIOSCSIBlkChangeNotifier *insert_notifier, *remove_notifier; - if (blk_op_is_blocked(sd->conf.blk, BLOCK_OP_TYPE_DATAPLANE, errp)) { 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); - insert_notifier = g_new0(VirtIOSCSIBlkChangeNotifier, 1); - insert_notifier->n.notify = virtio_scsi_blk_insert_notifier; - insert_notifier->s = s; - insert_notifier->sd = sd; - blk_add_insert_bs_notifier(sd->conf.blk, &insert_notifier->n); - QTAILQ_INSERT_TAIL(&s->insert_notifiers, insert_notifier, next); - - remove_notifier = g_new0(VirtIOSCSIBlkChangeNotifier, 1); - remove_notifier->n.notify = virtio_scsi_blk_remove_notifier; - remove_notifier->s = s; - remove_notifier->sd = sd; - blk_add_remove_bs_notifier(sd->conf.blk, &remove_notifier->n); - QTAILQ_INSERT_TAIL(&s->remove_notifiers, remove_notifier, next); } if (virtio_vdev_has_feature(vdev, VIRTIO_SCSI_F_HOTPLUG)) { @@ -835,7 +803,6 @@ static void virtio_scsi_hotunplug(HotplugHandler *hotplug_dev, DeviceState *dev, VirtIODevice *vdev = VIRTIO_DEVICE(hotplug_dev); VirtIOSCSI *s = VIRTIO_SCSI(vdev); SCSIDevice *sd = SCSI_DEVICE(dev); - VirtIOSCSIBlkChangeNotifier *insert_notifier, *remove_notifier; if (virtio_vdev_has_feature(vdev, VIRTIO_SCSI_F_HOTPLUG)) { virtio_scsi_push_event(s, sd, @@ -843,28 +810,6 @@ static void virtio_scsi_hotunplug(HotplugHandler *hotplug_dev, DeviceState *dev, VIRTIO_SCSI_EVT_RESET_REMOVED); } - if (s->ctx) { - blk_op_unblock_all(sd->conf.blk, s->blocker); - } - - QTAILQ_FOREACH(insert_notifier, &s->insert_notifiers, next) { - if (insert_notifier->sd == sd) { - notifier_remove(&insert_notifier->n); - QTAILQ_REMOVE(&s->insert_notifiers, insert_notifier, next); - g_free(insert_notifier); - break; - } - } - - QTAILQ_FOREACH(remove_notifier, &s->remove_notifiers, next) { - if (remove_notifier->sd == sd) { - notifier_remove(&remove_notifier->n); - QTAILQ_REMOVE(&s->remove_notifiers, remove_notifier, next); - g_free(remove_notifier); - break; - } - } - qdev_simple_device_unplug_cb(hotplug_dev, dev, errp); } @@ -950,11 +895,6 @@ static void virtio_scsi_device_realize(DeviceState *dev, Error **errp) register_savevm(dev, "virtio-scsi", virtio_scsi_id++, 1, virtio_scsi_save, virtio_scsi_load, s); - - error_setg(&s->blocker, "block device is in use by data plane"); - - QTAILQ_INIT(&s->insert_notifiers); - QTAILQ_INIT(&s->remove_notifiers); } static void virtio_scsi_instance_init(Object *obj) @@ -980,8 +920,6 @@ static void virtio_scsi_device_unrealize(DeviceState *dev, Error **errp) { VirtIOSCSI *s = VIRTIO_SCSI(dev); - error_free(s->blocker); - unregister_savevm(dev, "virtio-scsi", s); virtio_scsi_common_unrealize(dev, errp); } diff --git a/include/hw/virtio/virtio-scsi.h b/include/hw/virtio/virtio-scsi.h index ba2f5ce07c..b5156694e5 100644 --- a/include/hw/virtio/virtio-scsi.h +++ b/include/hw/virtio/virtio-scsi.h @@ -68,13 +68,6 @@ typedef struct VirtIOSCSICommon { VirtQueue **cmd_vqs; } VirtIOSCSICommon; -typedef struct VirtIOSCSIBlkChangeNotifier { - Notifier n; - struct VirtIOSCSI *s; - SCSIDevice *sd; - QTAILQ_ENTRY(VirtIOSCSIBlkChangeNotifier) next; -} VirtIOSCSIBlkChangeNotifier; - typedef struct VirtIOSCSI { VirtIOSCSICommon parent_obj; @@ -85,14 +78,10 @@ typedef struct VirtIOSCSI { /* Fields for dataplane below */ AioContext *ctx; /* one iothread per virtio-scsi-pci for now */ - QTAILQ_HEAD(, VirtIOSCSIBlkChangeNotifier) insert_notifiers; - QTAILQ_HEAD(, VirtIOSCSIBlkChangeNotifier) remove_notifiers; - bool dataplane_started; bool dataplane_starting; bool dataplane_stopping; bool dataplane_fenced; - Error *blocker; uint32_t host_features; } VirtIOSCSI; From 3a90c4ace2c3b368be419f02b0b09ab596877706 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Fri, 20 May 2016 11:04:21 -0700 Subject: [PATCH 06/12] virtio: drop duplicate virtio_queue_get_id() function The virtio_queue_get_id() function is the lesser used duplicate of virtio_get_queue_index(). Use the latter instead. Signed-off-by: Stefan Hajnoczi Message-id: 1463767461-17922-1-git-send-email-stefanha@redhat.com --- hw/scsi/virtio-scsi.c | 2 +- hw/virtio/virtio.c | 7 ------- include/hw/virtio/virtio.h | 1 - 3 files changed, 1 insertion(+), 9 deletions(-) diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c index d26f4908d4..71d09d3ef3 100644 --- a/hw/scsi/virtio-scsi.c +++ b/hw/scsi/virtio-scsi.c @@ -185,7 +185,7 @@ static void virtio_scsi_save_request(QEMUFile *f, SCSIRequest *sreq) { VirtIOSCSIReq *req = sreq->hba_private; VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(req->dev); - uint32_t n = virtio_queue_get_id(req->vq) - 2; + uint32_t n = virtio_get_queue_index(req->vq) - 2; assert(n < vs->conf.num_queues); qemu_put_be32s(f, &n); diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index 30ede3d1cc..7ed06eafa6 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -1062,13 +1062,6 @@ int virtio_get_num_queues(VirtIODevice *vdev) return i; } -int virtio_queue_get_id(VirtQueue *vq) -{ - VirtIODevice *vdev = vq->vdev; - assert(vq >= &vdev->vq[0] && vq < &vdev->vq[VIRTIO_QUEUE_MAX]); - return vq - &vdev->vq[0]; -} - void virtio_queue_set_align(VirtIODevice *vdev, int n, int align) { BusState *qbus = qdev_get_parent_bus(DEVICE(vdev)); diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h index 6a37065c23..96b581dc91 100644 --- a/include/hw/virtio/virtio.h +++ b/include/hw/virtio/virtio.h @@ -243,7 +243,6 @@ void virtio_queue_set_last_avail_idx(VirtIODevice *vdev, int n, uint16_t idx); void virtio_queue_invalidate_signalled_used(VirtIODevice *vdev, int n); VirtQueue *virtio_get_queue(VirtIODevice *vdev, int n); uint16_t virtio_get_queue_index(VirtQueue *vq); -int virtio_queue_get_id(VirtQueue *vq); EventNotifier *virtio_queue_get_guest_notifier(VirtQueue *vq); void virtio_queue_set_guest_notifier_fd_handler(VirtQueue *vq, bool assign, bool with_irqfd); From a7944dfad09626320791e62be6e2c9ee204c0c1c Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Mon, 30 May 2016 11:17:32 +0200 Subject: [PATCH 07/12] block/io: Remove unused bdrv_aio_write_zeroes() Signed-off-by: Kevin Wolf Message-id: 1464599852-15392-1-git-send-email-kwolf@redhat.com Signed-off-by: Stefan Hajnoczi --- block/io.c | 11 ----------- include/block/block.h | 3 --- trace-events | 1 - 3 files changed, 15 deletions(-) diff --git a/block/io.c b/block/io.c index 2d832aa532..7ac9897559 100644 --- a/block/io.c +++ b/block/io.c @@ -1865,17 +1865,6 @@ BlockAIOCB *bdrv_aio_writev(BlockDriverState *bs, int64_t sector_num, cb, opaque, true); } -BlockAIOCB *bdrv_aio_write_zeroes(BlockDriverState *bs, - int64_t sector_num, int nb_sectors, BdrvRequestFlags flags, - BlockCompletionFunc *cb, void *opaque) -{ - trace_bdrv_aio_write_zeroes(bs, sector_num, nb_sectors, flags, opaque); - - return bdrv_co_aio_rw_vector(bs, sector_num, NULL, nb_sectors, - BDRV_REQ_ZERO_WRITE | flags, - cb, opaque, true); -} - void bdrv_aio_cancel(BlockAIOCB *acb) { qemu_aio_ref(acb); diff --git a/include/block/block.h b/include/block/block.h index 70ea29947c..d6bb74d77e 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -229,9 +229,6 @@ int bdrv_write(BlockDriverState *bs, int64_t sector_num, const uint8_t *buf, int nb_sectors); int bdrv_write_zeroes(BlockDriverState *bs, int64_t sector_num, int nb_sectors, BdrvRequestFlags flags); -BlockAIOCB *bdrv_aio_write_zeroes(BlockDriverState *bs, int64_t sector_num, - int nb_sectors, BdrvRequestFlags flags, - BlockCompletionFunc *cb, void *opaque); int bdrv_make_zero(BlockDriverState *bs, BdrvRequestFlags flags); int bdrv_pread(BlockDriverState *bs, int64_t offset, void *buf, int count); diff --git a/trace-events b/trace-events index c50b8705c1..1c48f6973e 100644 --- a/trace-events +++ b/trace-events @@ -70,7 +70,6 @@ bdrv_aio_discard(void *bs, int64_t sector_num, int nb_sectors, void *opaque) "bs bdrv_aio_flush(void *bs, void *opaque) "bs %p opaque %p" bdrv_aio_readv(void *bs, int64_t sector_num, int nb_sectors, void *opaque) "bs %p sector_num %"PRId64" nb_sectors %d opaque %p" bdrv_aio_writev(void *bs, int64_t sector_num, int nb_sectors, void *opaque) "bs %p sector_num %"PRId64" nb_sectors %d opaque %p" -bdrv_aio_write_zeroes(void *bs, int64_t sector_num, int nb_sectors, int flags, void *opaque) "bs %p sector_num %"PRId64" nb_sectors %d flags %#x opaque %p" bdrv_co_readv(void *bs, int64_t sector_num, int nb_sector) "bs %p sector_num %"PRId64" nb_sectors %d" bdrv_co_writev(void *bs, int64_t sector_num, int nb_sector) "bs %p sector_num %"PRId64" nb_sectors %d" bdrv_co_write_zeroes(void *bs, int64_t sector_num, int nb_sector, int flags) "bs %p sector_num %"PRId64" nb_sectors %d flags %#x" From e3a4f91b4dda92666379e4865ea9847644f3bc19 Mon Sep 17 00:00:00 2001 From: Changlong Xie Date: Mon, 30 May 2016 17:28:11 +0800 Subject: [PATCH 08/12] iostatus: fix comments for block_job_iostatus_reset Signed-off-by: Changlong Xie Message-id: 1464600491-23340-1-git-send-email-xiecl.fnst@cn.fujitsu.com Signed-off-by: Stefan Hajnoczi --- include/block/blockjob.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/block/blockjob.h b/include/block/blockjob.h index 86d28070b8..00ac4184cc 100644 --- a/include/block/blockjob.h +++ b/include/block/blockjob.h @@ -397,7 +397,7 @@ int block_job_complete_sync(BlockJob *job, Error **errp); * @job: The job whose I/O status should be reset. * * Reset I/O status on @job and on BlockDriverState objects it uses, - * other than job->bs. + * other than job->blk. */ void block_job_iostatus_reset(BlockJob *job); From 117bc3fa22d359db6c4f0c10f34c8c9e00ed64af Mon Sep 17 00:00:00 2001 From: Peter Lieven Date: Mon, 30 May 2016 13:31:13 +0200 Subject: [PATCH 09/12] block/io: optimize bdrv_co_pwritev for small requests in a read-modify-write cycle a small request might cause head and tail to fall into the same aligned block. Currently QEMU reads the same block twice in this case which is not necessary. Signed-off-by: Peter Lieven Message-id: 1464607873-28206-1-git-send-email-pl@kamp.de Signed-off-by: Stefan Hajnoczi --- block/io.c | 8 ++++++++ tests/qemu-iotests/077 | 12 +----------- tests/qemu-iotests/077.out | 26 -------------------------- 3 files changed, 9 insertions(+), 37 deletions(-) diff --git a/block/io.c b/block/io.c index 7ac9897559..e12f303df5 100644 --- a/block/io.c +++ b/block/io.c @@ -1427,6 +1427,14 @@ int coroutine_fn bdrv_co_pwritev(BlockDriverState *bs, bytes += offset & (align - 1); offset = offset & ~(align - 1); + + /* We have read the tail already if the request is smaller + * than one aligned block. + */ + if (bytes < align) { + qemu_iovec_add(&local_qiov, head_buf + bytes, align - bytes); + bytes = align; + } } if ((offset + bytes) & (align - 1)) { diff --git a/tests/qemu-iotests/077 b/tests/qemu-iotests/077 index 4dc680b7fc..d2d2a2d687 100755 --- a/tests/qemu-iotests/077 +++ b/tests/qemu-iotests/077 @@ -60,7 +60,7 @@ EOF # Sequential RMW requests on the same physical sector off=0x1000 -for ev in "head" "after_head" "tail" "after_tail"; do +for ev in "head" "after_head"; do cat < Date: Thu, 19 May 2016 17:05:50 -0600 Subject: [PATCH 10/12] block: Move BlockRequest type to io.c I was thrown by the fact that the public type BlockRequest had an anonymous union, but no obvious discriminator. Turns out that the only client of the second branch of the union was code internal to io.c, now that commit 91c6e4b killed public multiwrite, so move it into io.c and improve the comments. Signed-off-by: Eric Blake Message-Id: <1463699150-19445-1-git-send-email-eblake@redhat.com> Signed-off-by: Fam Zheng --- block/io.c | 21 +++++++++++++++++++++ include/block/block.h | 21 --------------------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/block/io.c b/block/io.c index e12f303df5..a2fba6738a 100644 --- a/block/io.c +++ b/block/io.c @@ -1902,6 +1902,27 @@ void bdrv_aio_cancel_async(BlockAIOCB *acb) /**************************************************************/ /* async block device emulation */ +typedef struct BlockRequest { + union { + /* Used during read, write, trim */ + struct { + int64_t sector; + int nb_sectors; + int flags; + QEMUIOVector *qiov; + }; + /* Used during ioctl */ + struct { + int req; + void *buf; + }; + }; + BlockCompletionFunc *cb; + void *opaque; + + int error; +} BlockRequest; + typedef struct BlockAIOCBCoroutine { BlockAIOCB common; BlockRequest req; diff --git a/include/block/block.h b/include/block/block.h index d6bb74d77e..3fd5043d01 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -320,27 +320,6 @@ BlockAIOCB *bdrv_aio_discard(BlockDriverState *bs, void bdrv_aio_cancel(BlockAIOCB *acb); void bdrv_aio_cancel_async(BlockAIOCB *acb); -typedef struct BlockRequest { - /* Fields to be filled by caller */ - union { - struct { - int64_t sector; - int nb_sectors; - int flags; - QEMUIOVector *qiov; - }; - struct { - int req; - void *buf; - }; - }; - BlockCompletionFunc *cb; - void *opaque; - - /* Filled by block layer */ - int error; -} BlockRequest; - /* sg packet commands */ int bdrv_ioctl(BlockDriverState *bs, unsigned long int req, void *buf); BlockAIOCB *bdrv_aio_ioctl(BlockDriverState *bs, From c8a9fd80719e63615dac12e3625223fb54aa8430 Mon Sep 17 00:00:00 2001 From: Fam Zheng Date: Wed, 1 Jun 2016 09:52:23 +0800 Subject: [PATCH 11/12] block: Drop bdrv_ioctl_bh_cb Similar to the "!drv || !drv->bdrv_aio_ioctl" case above, here it is okay to set co.ret and return. As pointed out by Paolo, a BH will be created as necessary by the caller (bdrv_co_maybe_schedule_bh). Besides, as pointed out by Kevin, "data" was leaked before. Reported-by: Kevin Wolf Reported-by: Paolo Bonzini Signed-off-by: Fam Zheng Reviewed-by: Paolo Bonzini Message-id: 20160601015223.19277-1-famz@redhat.com Signed-off-by: Stefan Hajnoczi --- block/io.c | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/block/io.c b/block/io.c index a2fba6738a..6070e773b7 100644 --- a/block/io.c +++ b/block/io.c @@ -2327,19 +2327,6 @@ int bdrv_discard(BlockDriverState *bs, int64_t sector_num, int nb_sectors) return rwco.ret; } -typedef struct { - CoroutineIOCompletion *co; - QEMUBH *bh; -} BdrvIoctlCompletionData; - -static void bdrv_ioctl_bh_cb(void *opaque) -{ - BdrvIoctlCompletionData *data = opaque; - - bdrv_co_io_em_complete(data->co, -ENOTSUP); - qemu_bh_delete(data->bh); -} - static int bdrv_co_do_ioctl(BlockDriverState *bs, int req, void *buf) { BlockDriver *drv = bs->drv; @@ -2357,11 +2344,8 @@ static int bdrv_co_do_ioctl(BlockDriverState *bs, int req, void *buf) acb = drv->bdrv_aio_ioctl(bs, req, buf, bdrv_co_io_em_complete, &co); if (!acb) { - BdrvIoctlCompletionData *data = g_new(BdrvIoctlCompletionData, 1); - data->bh = aio_bh_new(bdrv_get_aio_context(bs), - bdrv_ioctl_bh_cb, data); - data->co = &co; - qemu_bh_schedule(data->bh); + co.ret = -ENOTSUP; + goto out; } qemu_coroutine_yield(); out: From 8860eabdee32f78d9a34273a340b8f74476bc9a0 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Wed, 1 Jun 2016 17:40:31 -0700 Subject: [PATCH 12/12] throttle: refuse iops-size without iops-total/read/write In a similar vein to commit ee2bdc33c913b7d765baa5aa338c29fb30a05c9a ("throttle: refuse bps_max/iops_max without bps/iops") it is likely that the user made a configuration error if iops-size has been set but no iops limit has been set. Print an error message so the user can check their throttling configuration. They should either remove iops-size if they don't want any throttling or specify one of iops-total, iops-read, or iops-write. Signed-off-by: Stefan Hajnoczi Reviewed-by: Alberto Garcia Message-id: 1464828031-25601-1-git-send-email-stefanha@redhat.com --- tests/test-throttle.c | 10 ++++++++++ util/throttle.c | 8 ++++++++ 2 files changed, 18 insertions(+) diff --git a/tests/test-throttle.c b/tests/test-throttle.c index c02be805f7..d584870950 100644 --- a/tests/test-throttle.c +++ b/tests/test-throttle.c @@ -398,6 +398,14 @@ static void test_max_is_missing_limit(void) } } +static void test_iops_size_is_missing_limit(void) +{ + /* A total/read/write iops limit is required */ + throttle_config_init(&cfg); + cfg.op_size = 4096; + g_assert(!throttle_is_valid(&cfg, NULL)); +} + static void test_have_timer(void) { /* zero structures */ @@ -653,6 +661,8 @@ int main(int argc, char **argv) g_test_add_func("/throttle/config/conflicting", test_conflicting_config); g_test_add_func("/throttle/config/is_valid", test_is_valid); g_test_add_func("/throttle/config/max", test_max_is_missing_limit); + g_test_add_func("/throttle/config/iops_size", + test_iops_size_is_missing_limit); g_test_add_func("/throttle/config_functions", test_config_functions); g_test_add_func("/throttle/accounting", test_accounting); g_test_add_func("/throttle/groups", test_groups); diff --git a/util/throttle.c b/util/throttle.c index 71246b2343..654f95caf2 100644 --- a/util/throttle.c +++ b/util/throttle.c @@ -315,6 +315,14 @@ bool throttle_is_valid(ThrottleConfig *cfg, Error **errp) return false; } + if (cfg->op_size && + !cfg->buckets[THROTTLE_OPS_TOTAL].avg && + !cfg->buckets[THROTTLE_OPS_READ].avg && + !cfg->buckets[THROTTLE_OPS_WRITE].avg) { + error_setg(errp, "iops size requires an iops value to be set"); + return false; + } + for (i = 0; i < BUCKETS_COUNT; i++) { if (cfg->buckets[i].avg < 0 || cfg->buckets[i].max < 0 ||