diff --git a/block/io.c b/block/io.c index 2d832aa532..6070e773b7 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)) { @@ -1865,17 +1873,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); @@ -1905,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; @@ -2309,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; @@ -2339,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: diff --git a/blockdev.c b/blockdev.c index 717785eb8d..6ccb8e1f84 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,19 +3366,22 @@ 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; + 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; + } } - 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); if (local_err != NULL) { 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); diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c index 30415c6a92..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); @@ -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/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/block/block.h b/include/block/block.h index 70ea29947c..3fd5043d01 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); @@ -323,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, 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); 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; 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); 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 <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 ||