aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--block/io.c60
-rw-r--r--blockdev.c23
-rw-r--r--hw/block/dataplane/virtio-blk.c63
-rw-r--r--hw/scsi/virtio-scsi.c64
-rw-r--r--hw/virtio/virtio.c7
-rw-r--r--include/block/block.h24
-rw-r--r--include/block/blockjob.h2
-rw-r--r--include/hw/virtio/virtio-scsi.h11
-rw-r--r--include/hw/virtio/virtio.h1
-rwxr-xr-xtests/qemu-iotests/07712
-rw-r--r--tests/qemu-iotests/077.out26
-rw-r--r--tests/test-coroutine.c10
-rw-r--r--tests/test-throttle.c10
-rw-r--r--trace-events1
-rw-r--r--util/throttle.c8
15 files changed, 74 insertions, 248 deletions
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 <<EOF
break pwritev_rmw_$ev A
aio_write -P 10 $((off + 0x200)) 0x200
@@ -211,16 +211,6 @@ function verify_io()
echo read -P 11 0x2400 0x200
echo read -P 0 0x2600 0xa00
- echo read -P 0 0x3000 0x200
- echo read -P 10 0x3200 0x200
- echo read -P 11 0x3400 0x200
- echo read -P 0 0x3600 0xa00
-
- echo read -P 0 0x4000 0x200
- echo read -P 10 0x4200 0x200
- echo read -P 11 0x4400 0x200
- echo read -P 0 0x4600 0xa00
-
# Chained dependencies
echo read -P 10 0x5000 0x200
echo read -P 11 0x5200 0x200
diff --git a/tests/qemu-iotests/077.out b/tests/qemu-iotests/077.out
index eab14ae2e1..16f951fd3d 100644
--- a/tests/qemu-iotests/077.out
+++ b/tests/qemu-iotests/077.out
@@ -19,16 +19,6 @@ wrote XXX/XXX bytes at offset XXX
XXX bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
wrote XXX/XXX bytes at offset XXX
XXX bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-blkdebug: Resuming request 'A'
-wrote XXX/XXX bytes at offset XXX
-XXX bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-wrote XXX/XXX bytes at offset XXX
-XXX bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-blkdebug: Resuming request 'A'
-wrote XXX/XXX bytes at offset XXX
-XXX bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-wrote XXX/XXX bytes at offset XXX
-XXX bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
wrote XXX/XXX bytes at offset XXX
XXX bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
wrote XXX/XXX bytes at offset XXX
@@ -114,22 +104,6 @@ read 512/512 bytes at offset 9216
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
read 2560/2560 bytes at offset 9728
2.500 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-read 512/512 bytes at offset 12288
-512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-read 512/512 bytes at offset 12800
-512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-read 512/512 bytes at offset 13312
-512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-read 2560/2560 bytes at offset 13824
-2.500 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-read 512/512 bytes at offset 16384
-512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-read 512/512 bytes at offset 16896
-512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-read 512/512 bytes at offset 17408
-512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-read 2560/2560 bytes at offset 17920
-2.500 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
read 512/512 bytes at offset 20480
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
read 512/512 bytes at offset 20992
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);
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/trace-events b/trace-events
index 44a8664cc2..c55d7084fb 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"
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 ||