From 90c78624f157ba41c3761c1a54864de03a7ec350 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Thu, 7 Apr 2016 18:33:29 +0200 Subject: block: Don't disable I/O throttling on sync requests We had to disable I/O throttling with synchronous requests because we didn't use to run timers in nested event loops when the code was introduced. This isn't true any more, and throttling works just fine even when using the synchronous API. The removed code is in fact dead code since commit a8823a3b ('block: Use blk_co_pwritev() for blk_write()') because I/O throttling can only be set on the top layer, but BlockBackend always uses the coroutine interface now instead of using the sync API emulation in block.c. Signed-off-by: Kevin Wolf Message-Id: <1458660792-3035-2-git-send-email-kwolf@redhat.com> Signed-off-by: Paolo Bonzini Acked-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf --- block/io.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/block/io.c b/block/io.c index a7dbf85b19..a91d862017 100644 --- a/block/io.c +++ b/block/io.c @@ -608,17 +608,6 @@ static int bdrv_prwv_co(BlockDriverState *bs, int64_t offset, .flags = flags, }; - /** - * In sync call context, when the vcpu is blocked, this throttling timer - * will not fire; so the I/O throttling function has to be disabled here - * if it has been enabled. - */ - if (bs->io_limits_enabled) { - fprintf(stderr, "Disabling I/O throttling on '%s' due " - "to synchronous I/O.\n", bdrv_get_device_name(bs)); - bdrv_io_limits_disable(bs); - } - if (qemu_in_coroutine()) { /* Fast-path if already in coroutine context */ bdrv_rw_co_entry(&rwco); -- cgit v1.2.3 From 733bbc8ceaeeb771da55662cccd915afeb78cd01 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 7 Apr 2016 18:33:30 +0200 Subject: block: make bdrv_start_throttled_reqs return void The return value is unused and I am not sure why it would be useful. Reviewed-by: Fam Zheng Signed-off-by: Paolo Bonzini Acked-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf --- block/io.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/block/io.c b/block/io.c index a91d862017..691baa69e7 100644 --- a/block/io.c +++ b/block/io.c @@ -71,10 +71,8 @@ void bdrv_set_io_limits(BlockDriverState *bs, } } -/* this function drain all the throttled IOs */ -static bool bdrv_start_throttled_reqs(BlockDriverState *bs) +static void bdrv_start_throttled_reqs(BlockDriverState *bs) { - bool drained = false; bool enabled = bs->io_limits_enabled; int i; @@ -82,13 +80,11 @@ static bool bdrv_start_throttled_reqs(BlockDriverState *bs) for (i = 0; i < 2; i++) { while (qemu_co_enter_next(&bs->throttled_reqs[i])) { - drained = true; + ; } } bs->io_limits_enabled = enabled; - - return drained; } void bdrv_io_limits_disable(BlockDriverState *bs) -- cgit v1.2.3 From a72f641407f4a59c3adb710a821736166a484b7f Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 7 Apr 2016 18:33:31 +0200 Subject: block: move restarting of throttled reqs to block/throttle-groups.c We want to remove throttled_reqs from block/io.c. This is the easy part---hide the handling of throttled_reqs during disable/enable of throttling within throttle-groups.c. Signed-off-by: Paolo Bonzini Acked-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf --- block/io.c | 15 +-------------- block/throttle-groups.c | 14 ++++++++++++++ include/block/throttle-groups.h | 1 + 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/block/io.c b/block/io.c index 691baa69e7..9201b89c35 100644 --- a/block/io.c +++ b/block/io.c @@ -62,28 +62,15 @@ static int coroutine_fn bdrv_co_do_write_zeroes(BlockDriverState *bs, void bdrv_set_io_limits(BlockDriverState *bs, ThrottleConfig *cfg) { - int i; - throttle_group_config(bs, cfg); - - for (i = 0; i < 2; i++) { - qemu_co_enter_next(&bs->throttled_reqs[i]); - } } static void bdrv_start_throttled_reqs(BlockDriverState *bs) { bool enabled = bs->io_limits_enabled; - int i; bs->io_limits_enabled = false; - - for (i = 0; i < 2; i++) { - while (qemu_co_enter_next(&bs->throttled_reqs[i])) { - ; - } - } - + throttle_group_restart_bs(bs); bs->io_limits_enabled = enabled; } diff --git a/block/throttle-groups.c b/block/throttle-groups.c index 4920e09495..b796f6b9fa 100644 --- a/block/throttle-groups.c +++ b/block/throttle-groups.c @@ -313,6 +313,17 @@ void coroutine_fn throttle_group_co_io_limits_intercept(BlockDriverState *bs, qemu_mutex_unlock(&tg->lock); } +void throttle_group_restart_bs(BlockDriverState *bs) +{ + int i; + + for (i = 0; i < 2; i++) { + while (qemu_co_enter_next(&bs->throttled_reqs[i])) { + ; + } + } +} + /* Update the throttle configuration for a particular group. Similar * to throttle_config(), but guarantees atomicity within the * throttling group. @@ -335,6 +346,9 @@ void throttle_group_config(BlockDriverState *bs, ThrottleConfig *cfg) } throttle_config(ts, tt, cfg); qemu_mutex_unlock(&tg->lock); + + qemu_co_enter_next(&bs->throttled_reqs[0]); + qemu_co_enter_next(&bs->throttled_reqs[1]); } /* Get the throttle configuration from a particular group. Similar to diff --git a/include/block/throttle-groups.h b/include/block/throttle-groups.h index aba28f30b6..395f72d444 100644 --- a/include/block/throttle-groups.h +++ b/include/block/throttle-groups.h @@ -38,6 +38,7 @@ void throttle_group_get_config(BlockDriverState *bs, ThrottleConfig *cfg); void throttle_group_register_bs(BlockDriverState *bs, const char *groupname); void throttle_group_unregister_bs(BlockDriverState *bs); +void throttle_group_restart_bs(BlockDriverState *bs); void coroutine_fn throttle_group_co_io_limits_intercept(BlockDriverState *bs, unsigned int bytes, -- cgit v1.2.3 From b6e84c97ed0d786a7cda4e184736e25bb8824c2c Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 7 Apr 2016 18:33:32 +0200 Subject: block: extract bdrv_drain_poll/bdrv_co_yield_to_drain from bdrv_drain/bdrv_co_drain Do not call bdrv_drain_recurse twice in bdrv_co_drain. A small tweak to the logic in Fam's patch, which is harmless since no one implements bdrv_drain anyway. But better get it right. Signed-off-by: Paolo Bonzini Acked-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf --- block/io.c | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/block/io.c b/block/io.c index 9201b89c35..c4848563ad 100644 --- a/block/io.c +++ b/block/io.c @@ -243,18 +243,30 @@ typedef struct { bool done; } BdrvCoDrainData; +static void bdrv_drain_poll(BlockDriverState *bs) +{ + bool busy = true; + + while (busy) { + /* Keep iterating */ + bdrv_flush_io_queue(bs); + busy = bdrv_requests_pending(bs); + busy |= aio_poll(bdrv_get_aio_context(bs), busy); + } +} + static void bdrv_co_drain_bh_cb(void *opaque) { BdrvCoDrainData *data = opaque; Coroutine *co = data->co; qemu_bh_delete(data->bh); - bdrv_drain(data->bs); + bdrv_drain_poll(data->bs); data->done = true; qemu_coroutine_enter(co, NULL); } -void coroutine_fn bdrv_co_drain(BlockDriverState *bs) +static void coroutine_fn bdrv_co_yield_to_drain(BlockDriverState *bs) { BdrvCoDrainData data; @@ -288,20 +300,19 @@ void coroutine_fn bdrv_co_drain(BlockDriverState *bs) * not depend on events in other AioContexts. In that case, use * bdrv_drain_all() instead. */ -void bdrv_drain(BlockDriverState *bs) +void coroutine_fn bdrv_co_drain(BlockDriverState *bs) { - bool busy = true; + bdrv_drain_recurse(bs); + bdrv_co_yield_to_drain(bs); +} +void bdrv_drain(BlockDriverState *bs) +{ bdrv_drain_recurse(bs); if (qemu_in_coroutine()) { - bdrv_co_drain(bs); - return; - } - while (busy) { - /* Keep iterating */ - bdrv_flush_io_queue(bs); - busy = bdrv_requests_pending(bs); - busy |= aio_poll(bdrv_get_aio_context(bs), busy); + bdrv_co_yield_to_drain(bs); + } else { + bdrv_drain_poll(bs); } } -- cgit v1.2.3 From ce0f141259f06fd77fde2519cc352618ad797ce2 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 7 Apr 2016 18:33:33 +0200 Subject: block: introduce bdrv_no_throttling_begin/end Extract the handling of throttling from bdrv_flush_io_queue. These new functions will soon become BdrvChildRole callbacks, as they can be generalized to "beginning of drain" and "end of drain". Reviewed-by: Alberto Garcia Signed-off-by: Paolo Bonzini Acked-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf --- block.c | 1 - block/block-backend.c | 6 ++---- block/io.c | 33 +++++++++++++++++++++------------ block/throttle-groups.c | 4 ++++ include/block/block_int.h | 9 ++++++--- 5 files changed, 33 insertions(+), 20 deletions(-) diff --git a/block.c b/block.c index d4939b49bf..6cbad0e264 100644 --- a/block.c +++ b/block.c @@ -2261,7 +2261,6 @@ static void swap_feature_fields(BlockDriverState *bs_top, assert(!bs_new->throttle_state); if (bs_top->throttle_state) { - assert(bs_top->io_limits_enabled); bdrv_io_limits_enable(bs_new, throttle_group_get_name(bs_top)); bdrv_io_limits_disable(bs_top); } diff --git a/block/block-backend.c b/block/block-backend.c index 16c9d5e0f2..9538e79641 100644 --- a/block/block-backend.c +++ b/block/block-backend.c @@ -794,7 +794,6 @@ int blk_read_unthrottled(BlockBackend *blk, int64_t sector_num, uint8_t *buf, int nb_sectors) { BlockDriverState *bs = blk_bs(blk); - bool enabled; int ret; ret = blk_check_request(blk, sector_num, nb_sectors); @@ -802,10 +801,9 @@ int blk_read_unthrottled(BlockBackend *blk, int64_t sector_num, uint8_t *buf, return ret; } - enabled = bs->io_limits_enabled; - bs->io_limits_enabled = false; + bdrv_no_throttling_begin(bs); ret = blk_read(blk, sector_num, buf, nb_sectors); - bs->io_limits_enabled = enabled; + bdrv_no_throttling_end(bs); return ret; } diff --git a/block/io.c b/block/io.c index c4848563ad..b798040e52 100644 --- a/block/io.c +++ b/block/io.c @@ -65,28 +65,32 @@ void bdrv_set_io_limits(BlockDriverState *bs, throttle_group_config(bs, cfg); } -static void bdrv_start_throttled_reqs(BlockDriverState *bs) +void bdrv_no_throttling_begin(BlockDriverState *bs) { - bool enabled = bs->io_limits_enabled; + if (bs->io_limits_disabled++ == 0) { + throttle_group_restart_bs(bs); + } +} - bs->io_limits_enabled = false; - throttle_group_restart_bs(bs); - bs->io_limits_enabled = enabled; +void bdrv_no_throttling_end(BlockDriverState *bs) +{ + assert(bs->io_limits_disabled); + --bs->io_limits_disabled; } void bdrv_io_limits_disable(BlockDriverState *bs) { - bs->io_limits_enabled = false; - bdrv_start_throttled_reqs(bs); + assert(bs->throttle_state); + bdrv_no_throttling_begin(bs); throttle_group_unregister_bs(bs); + bdrv_no_throttling_end(bs); } /* should be called before bdrv_set_io_limits if a limit is set */ void bdrv_io_limits_enable(BlockDriverState *bs, const char *group) { - assert(!bs->io_limits_enabled); + assert(!bs->throttle_state); throttle_group_register_bs(bs, group); - bs->io_limits_enabled = true; } void bdrv_io_limits_update_group(BlockDriverState *bs, const char *group) @@ -302,18 +306,22 @@ static void coroutine_fn bdrv_co_yield_to_drain(BlockDriverState *bs) */ void coroutine_fn bdrv_co_drain(BlockDriverState *bs) { + bdrv_no_throttling_begin(bs); bdrv_drain_recurse(bs); bdrv_co_yield_to_drain(bs); + bdrv_no_throttling_end(bs); } void bdrv_drain(BlockDriverState *bs) { + bdrv_no_throttling_begin(bs); bdrv_drain_recurse(bs); if (qemu_in_coroutine()) { bdrv_co_yield_to_drain(bs); } else { bdrv_drain_poll(bs); } + bdrv_no_throttling_end(bs); } /* @@ -336,6 +344,7 @@ void bdrv_drain_all(void) if (bs->job) { block_job_pause(bs->job); } + bdrv_no_throttling_begin(bs); bdrv_drain_recurse(bs); aio_context_release(aio_context); @@ -377,6 +386,7 @@ void bdrv_drain_all(void) AioContext *aio_context = bdrv_get_aio_context(bs); aio_context_acquire(aio_context); + bdrv_no_throttling_end(bs); if (bs->job) { block_job_resume(bs->job); } @@ -980,7 +990,7 @@ int coroutine_fn bdrv_co_do_preadv(BlockDriverState *bs, } /* throttling disk I/O */ - if (bs->io_limits_enabled) { + if (bs->throttle_state) { throttle_group_co_io_limits_intercept(bs, bytes, false); } @@ -1330,7 +1340,7 @@ int coroutine_fn bdrv_co_do_pwritev(BlockDriverState *bs, } /* throttling disk I/O */ - if (bs->io_limits_enabled) { + if (bs->throttle_state) { throttle_group_co_io_limits_intercept(bs, bytes, true); } @@ -2772,7 +2782,6 @@ void bdrv_flush_io_queue(BlockDriverState *bs) } else if (bs->file) { bdrv_flush_io_queue(bs->file->bs); } - bdrv_start_throttled_reqs(bs); } void bdrv_drained_begin(BlockDriverState *bs) diff --git a/block/throttle-groups.c b/block/throttle-groups.c index b796f6b9fa..9ac063a0cd 100644 --- a/block/throttle-groups.c +++ b/block/throttle-groups.c @@ -219,6 +219,10 @@ static bool throttle_group_schedule_timer(BlockDriverState *bs, ThrottleGroup *tg = container_of(ts, ThrottleGroup, ts); bool must_wait; + if (bs->io_limits_disabled) { + return false; + } + /* Check if any of the timers in this group is already armed */ if (tg->any_timer_armed[is_write]) { return true; diff --git a/include/block/block_int.h b/include/block/block_int.h index 10d87595be..ed9314b615 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -424,10 +424,10 @@ struct BlockDriverState { /* I/O throttling. * throttle_state tells us if this BDS has I/O limits configured. - * io_limits_enabled tells us if they are currently being - * enforced, but it can be temporarily set to false */ + * io_limits_disabled tells us if they are currently being enforced */ CoQueue throttled_reqs[2]; - bool io_limits_enabled; + unsigned int io_limits_disabled; + /* The following fields are protected by the ThrottleGroup lock. * See the ThrottleGroup documentation for details. */ ThrottleState *throttle_state; @@ -713,6 +713,9 @@ BdrvChild *bdrv_root_attach_child(BlockDriverState *child_bs, const BdrvChildRole *child_role); void bdrv_root_unref_child(BdrvChild *child); +void bdrv_no_throttling_begin(BlockDriverState *bs); +void bdrv_no_throttling_end(BlockDriverState *bs); + void blk_dev_change_media_cb(BlockBackend *blk, bool load); bool blk_dev_has_removable_media(BlockBackend *blk); bool blk_dev_has_tray(BlockBackend *blk); -- cgit v1.2.3 From 6b98bd649520d07df4d1b7a0a54ac73bf178519c Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 7 Apr 2016 18:33:34 +0200 Subject: block: plug whole tree at once, introduce bdrv_io_unplugged_begin/end Extract the handling of io_plug "depth" from linux-aio.c and let the main bdrv_drain loop do nothing but wait on I/O. Like the two newly introduced functions, bdrv_io_plug and bdrv_io_unplug now operate on all children. The visit order is now symmetrical between plug and unplug, making it possible for formats to implement plug/unplug. Reviewed-by: Fam Zheng Signed-off-by: Paolo Bonzini Acked-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf --- block/io.c | 76 ++++++++++++++++++++++++++++++++++++----------- block/linux-aio.c | 13 ++++---- block/raw-aio.h | 2 +- block/raw-posix.c | 16 +--------- include/block/block.h | 3 +- include/block/block_int.h | 5 +++- 6 files changed, 71 insertions(+), 44 deletions(-) diff --git a/block/io.c b/block/io.c index b798040e52..b903270115 100644 --- a/block/io.c +++ b/block/io.c @@ -253,7 +253,6 @@ static void bdrv_drain_poll(BlockDriverState *bs) while (busy) { /* Keep iterating */ - bdrv_flush_io_queue(bs); busy = bdrv_requests_pending(bs); busy |= aio_poll(bdrv_get_aio_context(bs), busy); } @@ -307,20 +306,24 @@ static void coroutine_fn bdrv_co_yield_to_drain(BlockDriverState *bs) void coroutine_fn bdrv_co_drain(BlockDriverState *bs) { bdrv_no_throttling_begin(bs); + bdrv_io_unplugged_begin(bs); bdrv_drain_recurse(bs); bdrv_co_yield_to_drain(bs); + bdrv_io_unplugged_end(bs); bdrv_no_throttling_end(bs); } void bdrv_drain(BlockDriverState *bs) { bdrv_no_throttling_begin(bs); + bdrv_io_unplugged_begin(bs); bdrv_drain_recurse(bs); if (qemu_in_coroutine()) { bdrv_co_yield_to_drain(bs); } else { bdrv_drain_poll(bs); } + bdrv_io_unplugged_end(bs); bdrv_no_throttling_end(bs); } @@ -345,6 +348,7 @@ void bdrv_drain_all(void) block_job_pause(bs->job); } bdrv_no_throttling_begin(bs); + bdrv_io_unplugged_begin(bs); bdrv_drain_recurse(bs); aio_context_release(aio_context); @@ -369,7 +373,6 @@ void bdrv_drain_all(void) aio_context_acquire(aio_context); while ((bs = bdrv_next(bs))) { if (aio_context == bdrv_get_aio_context(bs)) { - bdrv_flush_io_queue(bs); if (bdrv_requests_pending(bs)) { busy = true; aio_poll(aio_context, busy); @@ -386,6 +389,7 @@ void bdrv_drain_all(void) AioContext *aio_context = bdrv_get_aio_context(bs); aio_context_acquire(aio_context); + bdrv_io_unplugged_end(bs); bdrv_no_throttling_end(bs); if (bs->job) { block_job_resume(bs->job); @@ -2756,31 +2760,67 @@ void bdrv_add_before_write_notifier(BlockDriverState *bs, void bdrv_io_plug(BlockDriverState *bs) { - BlockDriver *drv = bs->drv; - if (drv && drv->bdrv_io_plug) { - drv->bdrv_io_plug(bs); - } else if (bs->file) { - bdrv_io_plug(bs->file->bs); + BdrvChild *child; + + QLIST_FOREACH(child, &bs->children, next) { + bdrv_io_plug(child->bs); + } + + if (bs->io_plugged++ == 0 && bs->io_plug_disabled == 0) { + BlockDriver *drv = bs->drv; + if (drv && drv->bdrv_io_plug) { + drv->bdrv_io_plug(bs); + } } } void bdrv_io_unplug(BlockDriverState *bs) { - BlockDriver *drv = bs->drv; - if (drv && drv->bdrv_io_unplug) { - drv->bdrv_io_unplug(bs); - } else if (bs->file) { - bdrv_io_unplug(bs->file->bs); + BdrvChild *child; + + assert(bs->io_plugged); + if (--bs->io_plugged == 0 && bs->io_plug_disabled == 0) { + BlockDriver *drv = bs->drv; + if (drv && drv->bdrv_io_unplug) { + drv->bdrv_io_unplug(bs); + } + } + + QLIST_FOREACH(child, &bs->children, next) { + bdrv_io_unplug(child->bs); } } -void bdrv_flush_io_queue(BlockDriverState *bs) +void bdrv_io_unplugged_begin(BlockDriverState *bs) { - BlockDriver *drv = bs->drv; - if (drv && drv->bdrv_flush_io_queue) { - drv->bdrv_flush_io_queue(bs); - } else if (bs->file) { - bdrv_flush_io_queue(bs->file->bs); + BdrvChild *child; + + if (bs->io_plug_disabled++ == 0 && bs->io_plugged > 0) { + BlockDriver *drv = bs->drv; + if (drv && drv->bdrv_io_unplug) { + drv->bdrv_io_unplug(bs); + } + } + + QLIST_FOREACH(child, &bs->children, next) { + bdrv_io_unplugged_begin(child->bs); + } +} + +void bdrv_io_unplugged_end(BlockDriverState *bs) +{ + BdrvChild *child; + + assert(bs->io_plug_disabled); + QLIST_FOREACH(child, &bs->children, next) { + bdrv_io_unplugged_end(child->bs); + } + + if (--bs->io_plug_disabled == 0 && bs->io_plugged > 0) { + BlockDriver *drv = bs->drv; + if (drv && drv->bdrv_io_plug) { + drv->bdrv_io_plug(bs); + } } } diff --git a/block/linux-aio.c b/block/linux-aio.c index 805757e02e..102bf928af 100644 --- a/block/linux-aio.c +++ b/block/linux-aio.c @@ -220,19 +220,16 @@ void laio_io_plug(BlockDriverState *bs, void *aio_ctx) { struct qemu_laio_state *s = aio_ctx; - s->io_q.plugged++; + assert(!s->io_q.plugged); + s->io_q.plugged = 1; } -void laio_io_unplug(BlockDriverState *bs, void *aio_ctx, bool unplug) +void laio_io_unplug(BlockDriverState *bs, void *aio_ctx) { struct qemu_laio_state *s = aio_ctx; - assert(s->io_q.plugged > 0 || !unplug); - - if (unplug && --s->io_q.plugged > 0) { - return; - } - + assert(s->io_q.plugged); + s->io_q.plugged = 0; if (!s->io_q.blocked && !QSIMPLEQ_EMPTY(&s->io_q.pending)) { ioq_submit(s); } diff --git a/block/raw-aio.h b/block/raw-aio.h index 811e375018..0f5e35a7ec 100644 --- a/block/raw-aio.h +++ b/block/raw-aio.h @@ -43,7 +43,7 @@ BlockAIOCB *laio_submit(BlockDriverState *bs, void *aio_ctx, int fd, void laio_detach_aio_context(void *s, AioContext *old_context); void laio_attach_aio_context(void *s, AioContext *new_context); void laio_io_plug(BlockDriverState *bs, void *aio_ctx); -void laio_io_unplug(BlockDriverState *bs, void *aio_ctx, bool unplug); +void laio_io_unplug(BlockDriverState *bs, void *aio_ctx); #endif #ifdef _WIN32 diff --git a/block/raw-posix.c b/block/raw-posix.c index 906d5c9411..50135ad383 100644 --- a/block/raw-posix.c +++ b/block/raw-posix.c @@ -1345,17 +1345,7 @@ static void raw_aio_unplug(BlockDriverState *bs) #ifdef CONFIG_LINUX_AIO BDRVRawState *s = bs->opaque; if (s->use_aio) { - laio_io_unplug(bs, s->aio_ctx, true); - } -#endif -} - -static void raw_aio_flush_io_queue(BlockDriverState *bs) -{ -#ifdef CONFIG_LINUX_AIO - BDRVRawState *s = bs->opaque; - if (s->use_aio) { - laio_io_unplug(bs, s->aio_ctx, false); + laio_io_unplug(bs, s->aio_ctx); } #endif } @@ -1949,7 +1939,6 @@ BlockDriver bdrv_file = { .bdrv_refresh_limits = raw_refresh_limits, .bdrv_io_plug = raw_aio_plug, .bdrv_io_unplug = raw_aio_unplug, - .bdrv_flush_io_queue = raw_aio_flush_io_queue, .bdrv_truncate = raw_truncate, .bdrv_getlength = raw_getlength, @@ -2398,7 +2387,6 @@ static BlockDriver bdrv_host_device = { .bdrv_refresh_limits = raw_refresh_limits, .bdrv_io_plug = raw_aio_plug, .bdrv_io_unplug = raw_aio_unplug, - .bdrv_flush_io_queue = raw_aio_flush_io_queue, .bdrv_truncate = raw_truncate, .bdrv_getlength = raw_getlength, @@ -2528,7 +2516,6 @@ static BlockDriver bdrv_host_cdrom = { .bdrv_refresh_limits = raw_refresh_limits, .bdrv_io_plug = raw_aio_plug, .bdrv_io_unplug = raw_aio_unplug, - .bdrv_flush_io_queue = raw_aio_flush_io_queue, .bdrv_truncate = raw_truncate, .bdrv_getlength = raw_getlength, @@ -2664,7 +2651,6 @@ static BlockDriver bdrv_host_cdrom = { .bdrv_refresh_limits = raw_refresh_limits, .bdrv_io_plug = raw_aio_plug, .bdrv_io_unplug = raw_aio_unplug, - .bdrv_flush_io_queue = raw_aio_flush_io_queue, .bdrv_truncate = raw_truncate, .bdrv_getlength = raw_getlength, diff --git a/include/block/block.h b/include/block/block.h index 3a731377db..0e8b4d1341 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -520,7 +520,8 @@ int bdrv_probe_geometry(BlockDriverState *bs, HDGeometry *geo); void bdrv_io_plug(BlockDriverState *bs); void bdrv_io_unplug(BlockDriverState *bs); -void bdrv_flush_io_queue(BlockDriverState *bs); +void bdrv_io_unplugged_begin(BlockDriverState *bs); +void bdrv_io_unplugged_end(BlockDriverState *bs); /** * bdrv_drained_begin: diff --git a/include/block/block_int.h b/include/block/block_int.h index ed9314b615..f1aabb9103 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -294,7 +294,6 @@ struct BlockDriver { /* io queue for linux-aio */ void (*bdrv_io_plug)(BlockDriverState *bs); void (*bdrv_io_unplug)(BlockDriverState *bs); - void (*bdrv_flush_io_queue)(BlockDriverState *bs); /** * Try to get @bs's logical and physical block size. @@ -484,6 +483,10 @@ struct BlockDriverState { uint64_t write_threshold_offset; NotifierWithReturn write_threshold_notifier; + /* counters for nested bdrv_io_plug and bdrv_io_unplugged_begin */ + unsigned io_plugged; + unsigned io_plug_disabled; + int quiesce_counter; }; -- cgit v1.2.3 From dd7f7ed10459d4ed9787ba464cebf8c459491d8c Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 7 Apr 2016 18:33:35 +0200 Subject: linux-aio: make it more type safe Replace void* with an opaque LinuxAioState type. Signed-off-by: Paolo Bonzini Acked-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf --- block/linux-aio.c | 46 +++++++++++++++++----------------------------- block/raw-aio.h | 15 ++++++++------- block/raw-posix.c | 4 ++-- 3 files changed, 27 insertions(+), 38 deletions(-) diff --git a/block/linux-aio.c b/block/linux-aio.c index 102bf928af..90ec98ee23 100644 --- a/block/linux-aio.c +++ b/block/linux-aio.c @@ -30,7 +30,7 @@ struct qemu_laiocb { BlockAIOCB common; - struct qemu_laio_state *ctx; + LinuxAioState *ctx; struct iocb iocb; ssize_t ret; size_t nbytes; @@ -46,7 +46,7 @@ typedef struct { QSIMPLEQ_HEAD(, qemu_laiocb) pending; } LaioQueue; -struct qemu_laio_state { +struct LinuxAioState { io_context_t ctx; EventNotifier e; @@ -60,7 +60,7 @@ struct qemu_laio_state { int event_max; }; -static void ioq_submit(struct qemu_laio_state *s); +static void ioq_submit(LinuxAioState *s); static inline ssize_t io_event_ret(struct io_event *ev) { @@ -70,8 +70,7 @@ static inline ssize_t io_event_ret(struct io_event *ev) /* * Completes an AIO request (calls the callback and frees the ACB). */ -static void qemu_laio_process_completion(struct qemu_laio_state *s, - struct qemu_laiocb *laiocb) +static void qemu_laio_process_completion(struct qemu_laiocb *laiocb) { int ret; @@ -99,7 +98,7 @@ static void qemu_laio_process_completion(struct qemu_laio_state *s, * * The function is somewhat tricky because it supports nested event loops, for * example when a request callback invokes aio_poll(). In order to do this, - * the completion events array and index are kept in qemu_laio_state. The BH + * the completion events array and index are kept in LinuxAioState. The BH * reschedules itself as long as there are completions pending so it will * either be called again in a nested event loop or will be called after all * events have been completed. When there are no events left to complete, the @@ -107,7 +106,7 @@ static void qemu_laio_process_completion(struct qemu_laio_state *s, */ static void qemu_laio_completion_bh(void *opaque) { - struct qemu_laio_state *s = opaque; + LinuxAioState *s = opaque; /* Fetch more completion events when empty */ if (s->event_idx == s->event_max) { @@ -136,7 +135,7 @@ static void qemu_laio_completion_bh(void *opaque) laiocb->ret = io_event_ret(&s->events[s->event_idx]); s->event_idx++; - qemu_laio_process_completion(s, laiocb); + qemu_laio_process_completion(laiocb); } if (!s->io_q.plugged && !QSIMPLEQ_EMPTY(&s->io_q.pending)) { @@ -146,7 +145,7 @@ static void qemu_laio_completion_bh(void *opaque) static void qemu_laio_completion_cb(EventNotifier *e) { - struct qemu_laio_state *s = container_of(e, struct qemu_laio_state, e); + LinuxAioState *s = container_of(e, LinuxAioState, e); if (event_notifier_test_and_clear(&s->e)) { qemu_bh_schedule(s->completion_bh); @@ -185,7 +184,7 @@ static void ioq_init(LaioQueue *io_q) io_q->blocked = false; } -static void ioq_submit(struct qemu_laio_state *s) +static void ioq_submit(LinuxAioState *s) { int ret, len; struct qemu_laiocb *aiocb; @@ -216,18 +215,14 @@ static void ioq_submit(struct qemu_laio_state *s) s->io_q.blocked = (s->io_q.n > 0); } -void laio_io_plug(BlockDriverState *bs, void *aio_ctx) +void laio_io_plug(BlockDriverState *bs, LinuxAioState *s) { - struct qemu_laio_state *s = aio_ctx; - assert(!s->io_q.plugged); s->io_q.plugged = 1; } -void laio_io_unplug(BlockDriverState *bs, void *aio_ctx) +void laio_io_unplug(BlockDriverState *bs, LinuxAioState *s) { - struct qemu_laio_state *s = aio_ctx; - assert(s->io_q.plugged); s->io_q.plugged = 0; if (!s->io_q.blocked && !QSIMPLEQ_EMPTY(&s->io_q.pending)) { @@ -235,11 +230,10 @@ void laio_io_unplug(BlockDriverState *bs, void *aio_ctx) } } -BlockAIOCB *laio_submit(BlockDriverState *bs, void *aio_ctx, int fd, +BlockAIOCB *laio_submit(BlockDriverState *bs, LinuxAioState *s, int fd, int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, BlockCompletionFunc *cb, void *opaque, int type) { - struct qemu_laio_state *s = aio_ctx; struct qemu_laiocb *laiocb; struct iocb *iocbs; off_t offset = sector_num * 512; @@ -281,26 +275,22 @@ out_free_aiocb: return NULL; } -void laio_detach_aio_context(void *s_, AioContext *old_context) +void laio_detach_aio_context(LinuxAioState *s, AioContext *old_context) { - struct qemu_laio_state *s = s_; - aio_set_event_notifier(old_context, &s->e, false, NULL); qemu_bh_delete(s->completion_bh); } -void laio_attach_aio_context(void *s_, AioContext *new_context) +void laio_attach_aio_context(LinuxAioState *s, AioContext *new_context) { - struct qemu_laio_state *s = s_; - s->completion_bh = aio_bh_new(new_context, qemu_laio_completion_bh, s); aio_set_event_notifier(new_context, &s->e, false, qemu_laio_completion_cb); } -void *laio_init(void) +LinuxAioState *laio_init(void) { - struct qemu_laio_state *s; + LinuxAioState *s; s = g_malloc0(sizeof(*s)); if (event_notifier_init(&s->e, false) < 0) { @@ -322,10 +312,8 @@ out_free_state: return NULL; } -void laio_cleanup(void *s_) +void laio_cleanup(LinuxAioState *s) { - struct qemu_laio_state *s = s_; - event_notifier_cleanup(&s->e); if (io_destroy(s->ctx) != 0) { diff --git a/block/raw-aio.h b/block/raw-aio.h index 0f5e35a7ec..714714e016 100644 --- a/block/raw-aio.h +++ b/block/raw-aio.h @@ -35,15 +35,16 @@ /* linux-aio.c - Linux native implementation */ #ifdef CONFIG_LINUX_AIO -void *laio_init(void); -void laio_cleanup(void *s); -BlockAIOCB *laio_submit(BlockDriverState *bs, void *aio_ctx, int fd, +typedef struct LinuxAioState LinuxAioState; +LinuxAioState *laio_init(void); +void laio_cleanup(LinuxAioState *s); +BlockAIOCB *laio_submit(BlockDriverState *bs, LinuxAioState *s, int fd, int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, BlockCompletionFunc *cb, void *opaque, int type); -void laio_detach_aio_context(void *s, AioContext *old_context); -void laio_attach_aio_context(void *s, AioContext *new_context); -void laio_io_plug(BlockDriverState *bs, void *aio_ctx); -void laio_io_unplug(BlockDriverState *bs, void *aio_ctx); +void laio_detach_aio_context(LinuxAioState *s, AioContext *old_context); +void laio_attach_aio_context(LinuxAioState *s, AioContext *new_context); +void laio_io_plug(BlockDriverState *bs, LinuxAioState *s); +void laio_io_unplug(BlockDriverState *bs, LinuxAioState *s); #endif #ifdef _WIN32 diff --git a/block/raw-posix.c b/block/raw-posix.c index 50135ad383..71ec463b71 100644 --- a/block/raw-posix.c +++ b/block/raw-posix.c @@ -139,7 +139,7 @@ typedef struct BDRVRawState { #ifdef CONFIG_LINUX_AIO int use_aio; - void *aio_ctx; + LinuxAioState *aio_ctx; #endif #ifdef CONFIG_XFS bool is_xfs:1; @@ -398,7 +398,7 @@ static void raw_attach_aio_context(BlockDriverState *bs, } #ifdef CONFIG_LINUX_AIO -static int raw_set_aio(void **aio_ctx, int *use_aio, int bdrv_flags) +static int raw_set_aio(LinuxAioState **aio_ctx, int *use_aio, int bdrv_flags) { int ret = -1; assert(aio_ctx != NULL); -- cgit v1.2.3 From 166fe9605128e9dfa2b20dd7cc97c64cc98394e4 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Mon, 25 Apr 2016 11:46:41 +0200 Subject: block: Introduce bdrv_driver_preadv() This is a function that simply calls into the block driver for doing a read, providing the byte granularity interface we want to eventually have everywhere, and using whatever interface that driver supports. For now, this is just a wrapper for calling bs->drv->bdrv_co_readv(). Signed-off-by: Kevin Wolf Reviewed-by: Eric Blake Reviewed-by: Fam Zheng --- block/io.c | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/block/io.c b/block/io.c index b903270115..d3617fe4b4 100644 --- a/block/io.c +++ b/block/io.c @@ -797,6 +797,21 @@ int bdrv_pwrite_sync(BlockDriverState *bs, int64_t offset, return 0; } +static int coroutine_fn bdrv_driver_preadv(BlockDriverState *bs, + uint64_t offset, uint64_t bytes, + QEMUIOVector *qiov, int flags) +{ + BlockDriver *drv = bs->drv; + int64_t sector_num = offset >> BDRV_SECTOR_BITS; + unsigned int nb_sectors = bytes >> BDRV_SECTOR_BITS; + + assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0); + assert((bytes & (BDRV_SECTOR_SIZE - 1)) == 0); + assert((bytes >> BDRV_SECTOR_BITS) <= BDRV_REQUEST_MAX_SECTORS); + + return drv->bdrv_co_readv(bs, sector_num, nb_sectors, qiov); +} + static int coroutine_fn bdrv_co_do_copy_on_readv(BlockDriverState *bs, int64_t sector_num, int nb_sectors, QEMUIOVector *qiov) { @@ -833,8 +848,9 @@ static int coroutine_fn bdrv_co_do_copy_on_readv(BlockDriverState *bs, qemu_iovec_init_external(&bounce_qiov, &iov, 1); - ret = drv->bdrv_co_readv(bs, cluster_sector_num, cluster_nb_sectors, - &bounce_qiov); + ret = bdrv_driver_preadv(bs, cluster_sector_num * BDRV_SECTOR_SIZE, + cluster_nb_sectors * BDRV_SECTOR_SIZE, + &bounce_qiov, 0); if (ret < 0) { goto err; } @@ -877,7 +893,6 @@ static int coroutine_fn bdrv_aligned_preadv(BlockDriverState *bs, BdrvTrackedRequest *req, int64_t offset, unsigned int bytes, int64_t align, QEMUIOVector *qiov, int flags) { - BlockDriver *drv = bs->drv; int ret; int64_t sector_num = offset >> BDRV_SECTOR_BITS; @@ -918,7 +933,7 @@ static int coroutine_fn bdrv_aligned_preadv(BlockDriverState *bs, /* Forward the request to the BlockDriver */ if (!bs->zero_beyond_eof) { - ret = drv->bdrv_co_readv(bs, sector_num, nb_sectors, qiov); + ret = bdrv_driver_preadv(bs, offset, bytes, qiov, 0); } else { /* Read zeros after EOF */ int64_t total_sectors, max_nb_sectors; @@ -932,7 +947,7 @@ static int coroutine_fn bdrv_aligned_preadv(BlockDriverState *bs, max_nb_sectors = ROUND_UP(MAX(0, total_sectors - sector_num), align >> BDRV_SECTOR_BITS); if (nb_sectors < max_nb_sectors) { - ret = drv->bdrv_co_readv(bs, sector_num, nb_sectors, qiov); + ret = bdrv_driver_preadv(bs, offset, bytes, qiov, 0); } else if (max_nb_sectors > 0) { QEMUIOVector local_qiov; @@ -940,8 +955,9 @@ static int coroutine_fn bdrv_aligned_preadv(BlockDriverState *bs, qemu_iovec_concat(&local_qiov, qiov, 0, max_nb_sectors * BDRV_SECTOR_SIZE); - ret = drv->bdrv_co_readv(bs, sector_num, max_nb_sectors, - &local_qiov); + ret = bdrv_driver_preadv(bs, offset, + max_nb_sectors * BDRV_SECTOR_SIZE, + &local_qiov, 0); qemu_iovec_destroy(&local_qiov); } else { -- cgit v1.2.3 From 78a07294d51c6575441ab058ed56de5d364d2833 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Mon, 25 Apr 2016 12:13:39 +0200 Subject: block: Introduce bdrv_driver_pwritev() This is a function that simply calls into the block driver for doing a write, providing the byte granularity interface we want to eventually have everywhere, and using whatever interface that driver supports. This one is a bit more interesting than the version for reads: It adds support for .bdrv_co_writev_flags() everywhere, so that drivers implementing this function can drop .bdrv_co_writev() now. Signed-off-by: Kevin Wolf Reviewed-by: Eric Blake Reviewed-by: Fam Zheng --- block/io.c | 51 ++++++++++++++++++++++++++++++++++++--------------- block/iscsi.c | 8 -------- block/nbd.c | 9 --------- block/raw_bsd.c | 8 -------- 4 files changed, 36 insertions(+), 40 deletions(-) diff --git a/block/io.c b/block/io.c index d3617fe4b4..53b4f2c79f 100644 --- a/block/io.c +++ b/block/io.c @@ -812,6 +812,36 @@ static int coroutine_fn bdrv_driver_preadv(BlockDriverState *bs, return drv->bdrv_co_readv(bs, sector_num, nb_sectors, qiov); } +static int coroutine_fn bdrv_driver_pwritev(BlockDriverState *bs, + uint64_t offset, uint64_t bytes, + QEMUIOVector *qiov, int flags) +{ + BlockDriver *drv = bs->drv; + int64_t sector_num = offset >> BDRV_SECTOR_BITS; + unsigned int nb_sectors = bytes >> BDRV_SECTOR_BITS; + int ret; + + assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0); + assert((bytes & (BDRV_SECTOR_SIZE - 1)) == 0); + assert((bytes >> BDRV_SECTOR_BITS) <= BDRV_REQUEST_MAX_SECTORS); + + if (drv->bdrv_co_writev_flags) { + ret = drv->bdrv_co_writev_flags(bs, sector_num, nb_sectors, qiov, + flags); + } else { + assert(drv->supported_write_flags == 0); + ret = drv->bdrv_co_writev(bs, sector_num, nb_sectors, qiov); + } + + if (ret == 0 && (flags & BDRV_REQ_FUA) && + !(drv->supported_write_flags & BDRV_REQ_FUA)) + { + ret = bdrv_co_flush(bs); + } + + return ret; +} + static int coroutine_fn bdrv_co_do_copy_on_readv(BlockDriverState *bs, int64_t sector_num, int nb_sectors, QEMUIOVector *qiov) { @@ -863,8 +893,9 @@ static int coroutine_fn bdrv_co_do_copy_on_readv(BlockDriverState *bs, /* This does not change the data on the disk, it is not necessary * to flush even in cache=writethrough mode. */ - ret = drv->bdrv_co_writev(bs, cluster_sector_num, cluster_nb_sectors, - &bounce_qiov); + ret = bdrv_driver_pwritev(bs, cluster_sector_num * BDRV_SECTOR_SIZE, + cluster_nb_sectors * BDRV_SECTOR_SIZE, + &bounce_qiov, 0); } if (ret < 0) { @@ -1152,7 +1183,8 @@ static int coroutine_fn bdrv_co_do_write_zeroes(BlockDriverState *bs, } qemu_iovec_init_external(&qiov, &iov, 1); - ret = drv->bdrv_co_writev(bs, sector_num, num, &qiov); + ret = bdrv_driver_pwritev(bs, sector_num * BDRV_SECTOR_SIZE, + num * BDRV_SECTOR_SIZE, &qiov, 0); /* Keep bounce buffer around if it is big enough for all * all future requests. @@ -1212,23 +1244,12 @@ static int coroutine_fn bdrv_aligned_pwritev(BlockDriverState *bs, } else if (flags & BDRV_REQ_ZERO_WRITE) { bdrv_debug_event(bs, BLKDBG_PWRITEV_ZERO); ret = bdrv_co_do_write_zeroes(bs, sector_num, nb_sectors, flags); - } else if (drv->bdrv_co_writev_flags) { - bdrv_debug_event(bs, BLKDBG_PWRITEV); - ret = drv->bdrv_co_writev_flags(bs, sector_num, nb_sectors, qiov, - flags); } else { - assert(drv->supported_write_flags == 0); bdrv_debug_event(bs, BLKDBG_PWRITEV); - ret = drv->bdrv_co_writev(bs, sector_num, nb_sectors, qiov); + ret = bdrv_driver_pwritev(bs, offset, bytes, qiov, flags); } bdrv_debug_event(bs, BLKDBG_PWRITEV_DONE); - if (ret == 0 && (flags & BDRV_REQ_FUA) && - !(drv->supported_write_flags & BDRV_REQ_FUA)) - { - ret = bdrv_co_flush(bs); - } - bdrv_set_dirty(bs, sector_num, nb_sectors); if (bs->wr_highest_offset < offset + bytes) { diff --git a/block/iscsi.c b/block/iscsi.c index 302baf84c1..4f7520463e 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -513,13 +513,6 @@ retry: return 0; } -static int coroutine_fn -iscsi_co_writev(BlockDriverState *bs, int64_t sector_num, int nb_sectors, - QEMUIOVector *iov) -{ - return iscsi_co_writev_flags(bs, sector_num, nb_sectors, iov, 0); -} - static bool iscsi_allocationmap_is_allocated(IscsiLun *iscsilun, int64_t sector_num, int nb_sectors) @@ -1847,7 +1840,6 @@ static BlockDriver bdrv_iscsi = { .bdrv_co_discard = iscsi_co_discard, .bdrv_co_write_zeroes = iscsi_co_write_zeroes, .bdrv_co_readv = iscsi_co_readv, - .bdrv_co_writev = iscsi_co_writev, .bdrv_co_writev_flags = iscsi_co_writev_flags, .supported_write_flags = BDRV_REQ_FUA, .bdrv_co_flush_to_disk = iscsi_co_flush, diff --git a/block/nbd.c b/block/nbd.c index f7ea3b3608..fccbfef585 100644 --- a/block/nbd.c +++ b/block/nbd.c @@ -374,12 +374,6 @@ static int nbd_co_writev_flags(BlockDriverState *bs, int64_t sector_num, return ret; } -static int nbd_co_writev(BlockDriverState *bs, int64_t sector_num, - int nb_sectors, QEMUIOVector *qiov) -{ - return nbd_co_writev_flags(bs, sector_num, nb_sectors, qiov, 0); -} - static int nbd_co_flush(BlockDriverState *bs) { return nbd_client_co_flush(bs); @@ -476,7 +470,6 @@ static BlockDriver bdrv_nbd = { .bdrv_parse_filename = nbd_parse_filename, .bdrv_file_open = nbd_open, .bdrv_co_readv = nbd_co_readv, - .bdrv_co_writev = nbd_co_writev, .bdrv_co_writev_flags = nbd_co_writev_flags, .supported_write_flags = BDRV_REQ_FUA, .bdrv_close = nbd_close, @@ -496,7 +489,6 @@ static BlockDriver bdrv_nbd_tcp = { .bdrv_parse_filename = nbd_parse_filename, .bdrv_file_open = nbd_open, .bdrv_co_readv = nbd_co_readv, - .bdrv_co_writev = nbd_co_writev, .bdrv_co_writev_flags = nbd_co_writev_flags, .supported_write_flags = BDRV_REQ_FUA, .bdrv_close = nbd_close, @@ -516,7 +508,6 @@ static BlockDriver bdrv_nbd_unix = { .bdrv_parse_filename = nbd_parse_filename, .bdrv_file_open = nbd_open, .bdrv_co_readv = nbd_co_readv, - .bdrv_co_writev = nbd_co_writev, .bdrv_co_writev_flags = nbd_co_writev_flags, .supported_write_flags = BDRV_REQ_FUA, .bdrv_close = nbd_close, diff --git a/block/raw_bsd.c b/block/raw_bsd.c index a6cc7e9918..9c9d39bd37 100644 --- a/block/raw_bsd.c +++ b/block/raw_bsd.c @@ -116,13 +116,6 @@ fail: return ret; } -static int coroutine_fn -raw_co_writev(BlockDriverState *bs, int64_t sector_num, int nb_sectors, - QEMUIOVector *qiov) -{ - return raw_co_writev_flags(bs, sector_num, nb_sectors, qiov, 0); -} - static int64_t coroutine_fn raw_co_get_block_status(BlockDriverState *bs, int64_t sector_num, int nb_sectors, int *pnum, @@ -256,7 +249,6 @@ BlockDriver bdrv_raw = { .bdrv_close = &raw_close, .bdrv_create = &raw_create, .bdrv_co_readv = &raw_co_readv, - .bdrv_co_writev = &raw_co_writev, .bdrv_co_writev_flags = &raw_co_writev_flags, .supported_write_flags = BDRV_REQ_FUA, .bdrv_co_write_zeroes = &raw_co_write_zeroes, -- cgit v1.2.3 From 08844473820c93541fc47bdfeae0f2cc88cfab59 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Mon, 25 Apr 2016 14:13:12 +0200 Subject: block: Support AIO drivers in bdrv_driver_preadv/pwritev() Instead of registering emulation functions as .bdrv_co_writev, just directly check whether the function is there or not, and use the AIO interface if it isn't. This makes the read/write functions more consistent with how things are done in other places (flush, discard, etc.) Signed-off-by: Kevin Wolf Reviewed-by: Eric Blake Reviewed-by: Fam Zheng --- block/io.c | 126 ++++++++++++++++++++++++----------------------------------- trace-events | 1 - 2 files changed, 52 insertions(+), 75 deletions(-) diff --git a/block/io.c b/block/io.c index 53b4f2c79f..fbde5e00eb 100644 --- a/block/io.c +++ b/block/io.c @@ -40,12 +40,6 @@ static BlockAIOCB *bdrv_aio_readv_em(BlockDriverState *bs, static BlockAIOCB *bdrv_aio_writev_em(BlockDriverState *bs, int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, BlockCompletionFunc *cb, void *opaque); -static int coroutine_fn bdrv_co_readv_em(BlockDriverState *bs, - int64_t sector_num, int nb_sectors, - QEMUIOVector *iov); -static int coroutine_fn bdrv_co_writev_em(BlockDriverState *bs, - int64_t sector_num, int nb_sectors, - QEMUIOVector *iov); static BlockAIOCB *bdrv_co_aio_rw_vector(BlockDriverState *bs, int64_t sector_num, QEMUIOVector *qiov, @@ -112,19 +106,13 @@ void bdrv_io_limits_update_group(BlockDriverState *bs, const char *group) void bdrv_setup_io_funcs(BlockDriver *bdrv) { - /* Block drivers without coroutine functions need emulation */ - if (!bdrv->bdrv_co_readv) { - bdrv->bdrv_co_readv = bdrv_co_readv_em; - bdrv->bdrv_co_writev = bdrv_co_writev_em; - - /* bdrv_co_readv_em()/brdv_co_writev_em() work in terms of aio, so if - * the block driver lacks aio we need to emulate that too. - */ - if (!bdrv->bdrv_aio_readv) { - /* add AIO emulation layer */ - bdrv->bdrv_aio_readv = bdrv_aio_readv_em; - bdrv->bdrv_aio_writev = bdrv_aio_writev_em; - } + /* bdrv_co_readv_em()/brdv_co_writev_em() work in terms of aio, so if + * the block driver lacks aio we need to emulate that. + */ + if (!bdrv->bdrv_aio_readv) { + /* add AIO emulation layer */ + bdrv->bdrv_aio_readv = bdrv_aio_readv_em; + bdrv->bdrv_aio_writev = bdrv_aio_writev_em; } } @@ -797,6 +785,19 @@ int bdrv_pwrite_sync(BlockDriverState *bs, int64_t offset, return 0; } +typedef struct CoroutineIOCompletion { + Coroutine *coroutine; + int ret; +} CoroutineIOCompletion; + +static void bdrv_co_io_em_complete(void *opaque, int ret) +{ + CoroutineIOCompletion *co = opaque; + + co->ret = ret; + qemu_coroutine_enter(co->coroutine, NULL); +} + static int coroutine_fn bdrv_driver_preadv(BlockDriverState *bs, uint64_t offset, uint64_t bytes, QEMUIOVector *qiov, int flags) @@ -809,7 +810,23 @@ static int coroutine_fn bdrv_driver_preadv(BlockDriverState *bs, assert((bytes & (BDRV_SECTOR_SIZE - 1)) == 0); assert((bytes >> BDRV_SECTOR_BITS) <= BDRV_REQUEST_MAX_SECTORS); - return drv->bdrv_co_readv(bs, sector_num, nb_sectors, qiov); + if (drv->bdrv_co_readv) { + return drv->bdrv_co_readv(bs, sector_num, nb_sectors, qiov); + } else { + BlockAIOCB *acb; + CoroutineIOCompletion co = { + .coroutine = qemu_coroutine_self(), + }; + + acb = bs->drv->bdrv_aio_readv(bs, sector_num, qiov, nb_sectors, + bdrv_co_io_em_complete, &co); + if (acb == NULL) { + return -EIO; + } else { + qemu_coroutine_yield(); + return co.ret; + } + } } static int coroutine_fn bdrv_driver_pwritev(BlockDriverState *bs, @@ -828,9 +845,23 @@ static int coroutine_fn bdrv_driver_pwritev(BlockDriverState *bs, if (drv->bdrv_co_writev_flags) { ret = drv->bdrv_co_writev_flags(bs, sector_num, nb_sectors, qiov, flags); - } else { + } else if (drv->bdrv_co_writev) { assert(drv->supported_write_flags == 0); ret = drv->bdrv_co_writev(bs, sector_num, nb_sectors, qiov); + } else { + BlockAIOCB *acb; + CoroutineIOCompletion co = { + .coroutine = qemu_coroutine_self(), + }; + + acb = bs->drv->bdrv_aio_writev(bs, sector_num, qiov, nb_sectors, + bdrv_co_io_em_complete, &co); + if (acb == NULL) { + return -EIO; + } else { + qemu_coroutine_yield(); + return co.ret; + } } if (ret == 0 && (flags & BDRV_REQ_FUA) && @@ -2348,59 +2379,6 @@ void qemu_aio_unref(void *p) /**************************************************************/ /* Coroutine block device emulation */ -typedef struct CoroutineIOCompletion { - Coroutine *coroutine; - int ret; -} CoroutineIOCompletion; - -static void bdrv_co_io_em_complete(void *opaque, int ret) -{ - CoroutineIOCompletion *co = opaque; - - co->ret = ret; - qemu_coroutine_enter(co->coroutine, NULL); -} - -static int coroutine_fn bdrv_co_io_em(BlockDriverState *bs, int64_t sector_num, - int nb_sectors, QEMUIOVector *iov, - bool is_write) -{ - CoroutineIOCompletion co = { - .coroutine = qemu_coroutine_self(), - }; - BlockAIOCB *acb; - - if (is_write) { - acb = bs->drv->bdrv_aio_writev(bs, sector_num, iov, nb_sectors, - bdrv_co_io_em_complete, &co); - } else { - acb = bs->drv->bdrv_aio_readv(bs, sector_num, iov, nb_sectors, - bdrv_co_io_em_complete, &co); - } - - trace_bdrv_co_io_em(bs, sector_num, nb_sectors, is_write, acb); - if (!acb) { - return -EIO; - } - qemu_coroutine_yield(); - - return co.ret; -} - -static int coroutine_fn bdrv_co_readv_em(BlockDriverState *bs, - int64_t sector_num, int nb_sectors, - QEMUIOVector *iov) -{ - return bdrv_co_io_em(bs, sector_num, nb_sectors, iov, false); -} - -static int coroutine_fn bdrv_co_writev_em(BlockDriverState *bs, - int64_t sector_num, int nb_sectors, - QEMUIOVector *iov) -{ - return bdrv_co_io_em(bs, sector_num, nb_sectors, iov, true); -} - static void coroutine_fn bdrv_flush_co_entry(void *opaque) { RwCo *rwco = opaque; diff --git a/trace-events b/trace-events index 8350743878..b4acd2ad98 100644 --- a/trace-events +++ b/trace-events @@ -74,7 +74,6 @@ bdrv_co_copy_on_readv(void *bs, int64_t sector_num, int nb_sector) "bs %p sector bdrv_co_readv_no_serialising(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" -bdrv_co_io_em(void *bs, int64_t sector_num, int nb_sectors, int is_write, void *acb) "bs %p sector_num %"PRId64" nb_sectors %d is_write %d acb %p" bdrv_co_do_copy_on_readv(void *bs, int64_t sector_num, int nb_sectors, int64_t cluster_sector_num, int cluster_nb_sectors) "bs %p sector_num %"PRId64" nb_sectors %d cluster_sector_num %"PRId64" cluster_nb_sectors %d" # block/stream.c -- cgit v1.2.3 From cab3a3563c5484f0bedbf5f78ab4a49e71a81fe7 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Mon, 25 Apr 2016 14:57:23 +0200 Subject: block: Rename bdrv_co_do_preadv/writev to bdrv_co_preadv/writev It used to be an internal helper function just for implementing bdrv_co_do_readv/writev(), but now that it's a public interface, it deserves a name without "do" in it. Signed-off-by: Kevin Wolf Reviewed-by: Eric Blake Reviewed-by: Fam Zheng --- block/block-backend.c | 4 ++-- block/io.c | 24 ++++++++++++------------ block/raw_bsd.c | 4 ++-- hw/ide/macio.c | 4 ++-- include/block/block_int.h | 4 ++-- 5 files changed, 20 insertions(+), 20 deletions(-) diff --git a/block/block-backend.c b/block/block-backend.c index 9538e79641..a7623e841f 100644 --- a/block/block-backend.c +++ b/block/block-backend.c @@ -692,7 +692,7 @@ static int coroutine_fn blk_co_preadv(BlockBackend *blk, int64_t offset, return ret; } - return bdrv_co_do_preadv(blk_bs(blk), offset, bytes, qiov, flags); + return bdrv_co_preadv(blk_bs(blk), offset, bytes, qiov, flags); } static int coroutine_fn blk_co_pwritev(BlockBackend *blk, int64_t offset, @@ -710,7 +710,7 @@ static int coroutine_fn blk_co_pwritev(BlockBackend *blk, int64_t offset, flags |= BDRV_REQ_FUA; } - return bdrv_co_do_pwritev(blk_bs(blk), offset, bytes, qiov, flags); + return bdrv_co_pwritev(blk_bs(blk), offset, bytes, qiov, flags); } typedef struct BlkRwCo { diff --git a/block/io.c b/block/io.c index fbde5e00eb..feddb71b45 100644 --- a/block/io.c +++ b/block/io.c @@ -577,13 +577,13 @@ static void coroutine_fn bdrv_rw_co_entry(void *opaque) RwCo *rwco = opaque; if (!rwco->is_write) { - rwco->ret = bdrv_co_do_preadv(rwco->bs, rwco->offset, - rwco->qiov->size, rwco->qiov, - rwco->flags); + rwco->ret = bdrv_co_preadv(rwco->bs, rwco->offset, + rwco->qiov->size, rwco->qiov, + rwco->flags); } else { - rwco->ret = bdrv_co_do_pwritev(rwco->bs, rwco->offset, - rwco->qiov->size, rwco->qiov, - rwco->flags); + rwco->ret = bdrv_co_pwritev(rwco->bs, rwco->offset, + rwco->qiov->size, rwco->qiov, + rwco->flags); } } @@ -1042,7 +1042,7 @@ out: /* * Handle a read request in coroutine context */ -int coroutine_fn bdrv_co_do_preadv(BlockDriverState *bs, +int coroutine_fn bdrv_co_preadv(BlockDriverState *bs, int64_t offset, unsigned int bytes, QEMUIOVector *qiov, BdrvRequestFlags flags) { @@ -1124,8 +1124,8 @@ static int coroutine_fn bdrv_co_do_readv(BlockDriverState *bs, return -EINVAL; } - return bdrv_co_do_preadv(bs, sector_num << BDRV_SECTOR_BITS, - nb_sectors << BDRV_SECTOR_BITS, qiov, flags); + return bdrv_co_preadv(bs, sector_num << BDRV_SECTOR_BITS, + nb_sectors << BDRV_SECTOR_BITS, qiov, flags); } int coroutine_fn bdrv_co_readv(BlockDriverState *bs, int64_t sector_num, @@ -1385,7 +1385,7 @@ fail: /* * Handle a write request in coroutine context */ -int coroutine_fn bdrv_co_do_pwritev(BlockDriverState *bs, +int coroutine_fn bdrv_co_pwritev(BlockDriverState *bs, int64_t offset, unsigned int bytes, QEMUIOVector *qiov, BdrvRequestFlags flags) { @@ -1520,8 +1520,8 @@ static int coroutine_fn bdrv_co_do_writev(BlockDriverState *bs, return -EINVAL; } - return bdrv_co_do_pwritev(bs, sector_num << BDRV_SECTOR_BITS, - nb_sectors << BDRV_SECTOR_BITS, qiov, flags); + return bdrv_co_pwritev(bs, sector_num << BDRV_SECTOR_BITS, + nb_sectors << BDRV_SECTOR_BITS, qiov, flags); } int coroutine_fn bdrv_co_writev(BlockDriverState *bs, int64_t sector_num, diff --git a/block/raw_bsd.c b/block/raw_bsd.c index 9c9d39bd37..5e65fb02d4 100644 --- a/block/raw_bsd.c +++ b/block/raw_bsd.c @@ -105,8 +105,8 @@ raw_co_writev_flags(BlockDriverState *bs, int64_t sector_num, int nb_sectors, } BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO); - ret = bdrv_co_do_pwritev(bs->file->bs, sector_num * BDRV_SECTOR_SIZE, - nb_sectors * BDRV_SECTOR_SIZE, qiov, flags); + ret = bdrv_co_pwritev(bs->file->bs, sector_num * BDRV_SECTOR_SIZE, + nb_sectors * BDRV_SECTOR_SIZE, qiov, flags); fail: if (qiov == &local_qiov) { diff --git a/hw/ide/macio.c b/hw/ide/macio.c index 76256eb8a8..ae29b6f326 100644 --- a/hw/ide/macio.c +++ b/hw/ide/macio.c @@ -55,8 +55,8 @@ static const int debug_macio = 0; /* * Unaligned DMA read/write access functions required for OS X/Darwin which * don't perform DMA transactions on sector boundaries. These functions are - * modelled on bdrv_co_do_preadv()/bdrv_co_do_pwritev() and so should be - * easy to remove if the unaligned block APIs are ever exposed. + * modelled on bdrv_co_preadv()/bdrv_co_pwritev() and so should be easy to + * remove if the unaligned block APIs are ever exposed. */ static void pmac_dma_read(BlockBackend *blk, diff --git a/include/block/block_int.h b/include/block/block_int.h index f1aabb9103..804bc1d60b 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -520,10 +520,10 @@ extern BlockDriver bdrv_qcow2; */ void bdrv_setup_io_funcs(BlockDriver *bdrv); -int coroutine_fn bdrv_co_do_preadv(BlockDriverState *bs, +int coroutine_fn bdrv_co_preadv(BlockDriverState *bs, int64_t offset, unsigned int bytes, QEMUIOVector *qiov, BdrvRequestFlags flags); -int coroutine_fn bdrv_co_do_pwritev(BlockDriverState *bs, +int coroutine_fn bdrv_co_pwritev(BlockDriverState *bs, int64_t offset, unsigned int bytes, QEMUIOVector *qiov, BdrvRequestFlags flags); -- cgit v1.2.3 From 3fb06697ae30ea59bf245f967a043e60f2aedb17 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Mon, 25 Apr 2016 11:25:18 +0200 Subject: block: Introduce .bdrv_co_preadv/pwritev BlockDriver function Many parts of the block layer are already byte granularity. The block driver interface, however, was still missing an interface that allows making use of this. This patch introduces a new BlockDriver interface, which is based on coroutines, vectored, has flags and uses a byte granularity. This is now the preferred interface for new drivers. Signed-off-by: Kevin Wolf Reviewed-by: Eric Blake Reviewed-by: Fam Zheng --- block/io.c | 28 ++++++++++++++++++++++------ include/block/block_int.h | 4 ++++ 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/block/io.c b/block/io.c index feddb71b45..70caadd0f5 100644 --- a/block/io.c +++ b/block/io.c @@ -803,8 +803,15 @@ static int coroutine_fn bdrv_driver_preadv(BlockDriverState *bs, QEMUIOVector *qiov, int flags) { BlockDriver *drv = bs->drv; - int64_t sector_num = offset >> BDRV_SECTOR_BITS; - unsigned int nb_sectors = bytes >> BDRV_SECTOR_BITS; + int64_t sector_num; + unsigned int nb_sectors; + + if (drv->bdrv_co_preadv) { + return drv->bdrv_co_preadv(bs, offset, bytes, qiov, flags); + } + + sector_num = offset >> BDRV_SECTOR_BITS; + nb_sectors = bytes >> BDRV_SECTOR_BITS; assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0); assert((bytes & (BDRV_SECTOR_SIZE - 1)) == 0); @@ -834,10 +841,18 @@ static int coroutine_fn bdrv_driver_pwritev(BlockDriverState *bs, QEMUIOVector *qiov, int flags) { BlockDriver *drv = bs->drv; - int64_t sector_num = offset >> BDRV_SECTOR_BITS; - unsigned int nb_sectors = bytes >> BDRV_SECTOR_BITS; + int64_t sector_num; + unsigned int nb_sectors; int ret; + if (drv->bdrv_co_pwritev) { + ret = drv->bdrv_co_pwritev(bs, offset, bytes, qiov, flags); + goto emulate_flags; + } + + sector_num = offset >> BDRV_SECTOR_BITS; + nb_sectors = bytes >> BDRV_SECTOR_BITS; + assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0); assert((bytes & (BDRV_SECTOR_SIZE - 1)) == 0); assert((bytes >> BDRV_SECTOR_BITS) <= BDRV_REQUEST_MAX_SECTORS); @@ -857,13 +872,14 @@ static int coroutine_fn bdrv_driver_pwritev(BlockDriverState *bs, acb = bs->drv->bdrv_aio_writev(bs, sector_num, qiov, nb_sectors, bdrv_co_io_em_complete, &co); if (acb == NULL) { - return -EIO; + ret = -EIO; } else { qemu_coroutine_yield(); - return co.ret; + ret = co.ret; } } +emulate_flags: if (ret == 0 && (flags & BDRV_REQ_FUA) && !(drv->supported_write_flags & BDRV_REQ_FUA)) { diff --git a/include/block/block_int.h b/include/block/block_int.h index 804bc1d60b..565f795758 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -153,10 +153,14 @@ struct BlockDriver { int coroutine_fn (*bdrv_co_readv)(BlockDriverState *bs, int64_t sector_num, int nb_sectors, QEMUIOVector *qiov); + int coroutine_fn (*bdrv_co_preadv)(BlockDriverState *bs, + uint64_t offset, uint64_t bytes, QEMUIOVector *qiov, int flags); int coroutine_fn (*bdrv_co_writev)(BlockDriverState *bs, int64_t sector_num, int nb_sectors, QEMUIOVector *qiov); int coroutine_fn (*bdrv_co_writev_flags)(BlockDriverState *bs, int64_t sector_num, int nb_sectors, QEMUIOVector *qiov, int flags); + int coroutine_fn (*bdrv_co_pwritev)(BlockDriverState *bs, + uint64_t offset, uint64_t bytes, QEMUIOVector *qiov, int flags); int supported_write_flags; -- cgit v1.2.3 From 3b8fd3301147585765624cd733e6172a25efcb58 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Mon, 25 Apr 2016 14:53:22 +0200 Subject: bochs: Implement .bdrv_co_preadv() interface Signed-off-by: Kevin Wolf Reviewed-by: Eric Blake Reviewed-by: Fam Zheng --- block/bochs.c | 51 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 33 insertions(+), 18 deletions(-) diff --git a/block/bochs.c b/block/bochs.c index af8b7abdfd..f0e18c0b84 100644 --- a/block/bochs.c +++ b/block/bochs.c @@ -104,6 +104,7 @@ static int bochs_open(BlockDriverState *bs, QDict *options, int flags, int ret; bs->read_only = 1; // no write support yet + bs->request_alignment = BDRV_SECTOR_SIZE; /* No sub-sector I/O supported */ ret = bdrv_pread(bs->file->bs, 0, &bochs, sizeof(bochs)); if (ret < 0) { @@ -221,38 +222,52 @@ static int64_t seek_to_sector(BlockDriverState *bs, int64_t sector_num) return bitmap_offset + (512 * (s->bitmap_blocks + extent_offset)); } -static int bochs_read(BlockDriverState *bs, int64_t sector_num, - uint8_t *buf, int nb_sectors) +static int coroutine_fn +bochs_co_preadv(BlockDriverState *bs, uint64_t offset, uint64_t bytes, + QEMUIOVector *qiov, int flags) { + BDRVBochsState *s = bs->opaque; + uint64_t sector_num = offset >> BDRV_SECTOR_BITS; + int nb_sectors = bytes >> BDRV_SECTOR_BITS; + uint64_t bytes_done = 0; + QEMUIOVector local_qiov; int ret; + assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0); + assert((bytes & (BDRV_SECTOR_SIZE - 1)) == 0); + + qemu_iovec_init(&local_qiov, qiov->niov); + qemu_co_mutex_lock(&s->lock); + while (nb_sectors > 0) { int64_t block_offset = seek_to_sector(bs, sector_num); if (block_offset < 0) { - return block_offset; - } else if (block_offset > 0) { - ret = bdrv_pread(bs->file->bs, block_offset, buf, 512); + ret = block_offset; + goto fail; + } + + qemu_iovec_reset(&local_qiov); + qemu_iovec_concat(&local_qiov, qiov, bytes_done, 512); + + if (block_offset > 0) { + ret = bdrv_co_preadv(bs->file->bs, block_offset, 512, + &local_qiov, 0); if (ret < 0) { - return ret; + goto fail; } } else { - memset(buf, 0, 512); + qemu_iovec_memset(&local_qiov, 0, 0, 512); } nb_sectors--; sector_num++; - buf += 512; + bytes_done += 512; } - return 0; -} -static coroutine_fn int bochs_co_read(BlockDriverState *bs, int64_t sector_num, - uint8_t *buf, int nb_sectors) -{ - int ret; - BDRVBochsState *s = bs->opaque; - qemu_co_mutex_lock(&s->lock); - ret = bochs_read(bs, sector_num, buf, nb_sectors); + ret = 0; +fail: qemu_co_mutex_unlock(&s->lock); + qemu_iovec_destroy(&local_qiov); + return ret; } @@ -267,7 +282,7 @@ static BlockDriver bdrv_bochs = { .instance_size = sizeof(BDRVBochsState), .bdrv_probe = bochs_probe, .bdrv_open = bochs_open, - .bdrv_read = bochs_co_read, + .bdrv_co_preadv = bochs_co_preadv, .bdrv_close = bochs_close, }; -- cgit v1.2.3 From 5cd230819ec26caf199bf73d38cf2407344e4443 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Mon, 25 Apr 2016 15:21:46 +0200 Subject: cloop: Implement .bdrv_co_preadv() interface This implements .bdrv_co_preadv() for the cloop block driver. While updating the error paths, change -1 to a valid -errno code. Signed-off-by: Kevin Wolf Reviewed-by: Eric Blake Reviewed-by: Fam Zheng --- block/cloop.c | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/block/cloop.c b/block/cloop.c index a84f14019c..fc1ca3a05a 100644 --- a/block/cloop.c +++ b/block/cloop.c @@ -66,6 +66,7 @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags, int ret; bs->read_only = 1; + bs->request_alignment = BDRV_SECTOR_SIZE; /* No sub-sector I/O supported */ /* read header */ ret = bdrv_pread(bs->file->bs, 128, &s->block_size, 4); @@ -229,33 +230,38 @@ static inline int cloop_read_block(BlockDriverState *bs, int block_num) return 0; } -static int cloop_read(BlockDriverState *bs, int64_t sector_num, - uint8_t *buf, int nb_sectors) +static int coroutine_fn +cloop_co_preadv(BlockDriverState *bs, uint64_t offset, uint64_t bytes, + QEMUIOVector *qiov, int flags) { BDRVCloopState *s = bs->opaque; - int i; + uint64_t sector_num = offset >> BDRV_SECTOR_BITS; + int nb_sectors = bytes >> BDRV_SECTOR_BITS; + int ret, i; + + assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0); + assert((bytes & (BDRV_SECTOR_SIZE - 1)) == 0); + + qemu_co_mutex_lock(&s->lock); for (i = 0; i < nb_sectors; i++) { + void *data; uint32_t sector_offset_in_block = ((sector_num + i) % s->sectors_per_block), block_num = (sector_num + i) / s->sectors_per_block; if (cloop_read_block(bs, block_num) != 0) { - return -1; + ret = -EIO; + goto fail; } - memcpy(buf + i * 512, - s->uncompressed_block + sector_offset_in_block * 512, 512); + + data = s->uncompressed_block + sector_offset_in_block * 512; + qemu_iovec_from_buf(qiov, i * 512, data, 512); } - return 0; -} -static coroutine_fn int cloop_co_read(BlockDriverState *bs, int64_t sector_num, - uint8_t *buf, int nb_sectors) -{ - int ret; - BDRVCloopState *s = bs->opaque; - qemu_co_mutex_lock(&s->lock); - ret = cloop_read(bs, sector_num, buf, nb_sectors); + ret = 0; +fail: qemu_co_mutex_unlock(&s->lock); + return ret; } @@ -273,7 +279,7 @@ static BlockDriver bdrv_cloop = { .instance_size = sizeof(BDRVCloopState), .bdrv_probe = cloop_probe, .bdrv_open = cloop_open, - .bdrv_read = cloop_co_read, + .bdrv_co_preadv = cloop_co_preadv, .bdrv_close = cloop_close, }; -- cgit v1.2.3 From 3edf1e73d568c646202e9faa6224df4fee1bd0e6 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Mon, 25 Apr 2016 15:43:09 +0200 Subject: dmg: Implement .bdrv_co_preadv() interface This implements .bdrv_co_preadv() for the cloop block driver. While updating the error paths, change -1 to a valid -errno code. Signed-off-by: Kevin Wolf Reviewed-by: Eric Blake Reviewed-by: Fam Zheng --- block/dmg.c | 40 +++++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/block/dmg.c b/block/dmg.c index a496eb7c9b..1ea5f22d82 100644 --- a/block/dmg.c +++ b/block/dmg.c @@ -440,6 +440,8 @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags, int ret; bs->read_only = 1; + bs->request_alignment = BDRV_SECTOR_SIZE; /* No sub-sector I/O supported */ + s->n_chunks = 0; s->offsets = s->lengths = s->sectors = s->sectorcounts = NULL; /* used by dmg_read_mish_block to keep track of the current I/O position */ @@ -659,38 +661,42 @@ static inline int dmg_read_chunk(BlockDriverState *bs, uint64_t sector_num) return 0; } -static int dmg_read(BlockDriverState *bs, int64_t sector_num, - uint8_t *buf, int nb_sectors) +static int coroutine_fn +dmg_co_preadv(BlockDriverState *bs, uint64_t offset, uint64_t bytes, + QEMUIOVector *qiov, int flags) { BDRVDMGState *s = bs->opaque; - int i; + uint64_t sector_num = offset >> BDRV_SECTOR_BITS; + int nb_sectors = bytes >> BDRV_SECTOR_BITS; + int ret, i; + + assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0); + assert((bytes & (BDRV_SECTOR_SIZE - 1)) == 0); + + qemu_co_mutex_lock(&s->lock); for (i = 0; i < nb_sectors; i++) { uint32_t sector_offset_in_chunk; + void *data; + if (dmg_read_chunk(bs, sector_num + i) != 0) { - return -1; + ret = -EIO; + goto fail; } /* Special case: current chunk is all zeroes. Do not perform a memcpy as * s->uncompressed_chunk may be too small to cover the large all-zeroes * section. dmg_read_chunk is called to find s->current_chunk */ if (s->types[s->current_chunk] == 2) { /* all zeroes block entry */ - memset(buf + i * 512, 0, 512); + qemu_iovec_memset(qiov, i * 512, 0, 512); continue; } sector_offset_in_chunk = sector_num + i - s->sectors[s->current_chunk]; - memcpy(buf + i * 512, - s->uncompressed_chunk + sector_offset_in_chunk * 512, 512); + data = s->uncompressed_chunk + sector_offset_in_chunk * 512; + qemu_iovec_from_buf(qiov, i * 512, data, 512); } - return 0; -} -static coroutine_fn int dmg_co_read(BlockDriverState *bs, int64_t sector_num, - uint8_t *buf, int nb_sectors) -{ - int ret; - BDRVDMGState *s = bs->opaque; - qemu_co_mutex_lock(&s->lock); - ret = dmg_read(bs, sector_num, buf, nb_sectors); + ret = 0; +fail: qemu_co_mutex_unlock(&s->lock); return ret; } @@ -715,7 +721,7 @@ static BlockDriver bdrv_dmg = { .instance_size = sizeof(BDRVDMGState), .bdrv_probe = dmg_probe, .bdrv_open = dmg_open, - .bdrv_read = dmg_co_read, + .bdrv_co_preadv = dmg_co_preadv, .bdrv_close = dmg_close, }; -- cgit v1.2.3 From 0865bb6f0489a81043309fd4e9fd31c3657ee77e Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Mon, 25 Apr 2016 16:22:39 +0200 Subject: vdi: Implement .bdrv_co_preadv() interface Signed-off-by: Kevin Wolf Reviewed-by: Fam Zheng --- block/vdi.c | 55 ++++++++++++++++++++++++++++++++----------------------- 1 file changed, 32 insertions(+), 23 deletions(-) diff --git a/block/vdi.c b/block/vdi.c index 75d4819edb..8295511b72 100644 --- a/block/vdi.c +++ b/block/vdi.c @@ -557,48 +557,57 @@ static int64_t coroutine_fn vdi_co_get_block_status(BlockDriverState *bs, return BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID | offset; } -static int vdi_co_read(BlockDriverState *bs, - int64_t sector_num, uint8_t *buf, int nb_sectors) +static int coroutine_fn +vdi_co_preadv(BlockDriverState *bs, uint64_t offset, uint64_t bytes, + QEMUIOVector *qiov, int flags) { BDRVVdiState *s = bs->opaque; + QEMUIOVector local_qiov; uint32_t bmap_entry; uint32_t block_index; - uint32_t sector_in_block; - uint32_t n_sectors; + uint32_t offset_in_block; + uint32_t n_bytes; + uint64_t bytes_done = 0; int ret = 0; logout("\n"); - while (ret >= 0 && nb_sectors > 0) { - block_index = sector_num / s->block_sectors; - sector_in_block = sector_num % s->block_sectors; - n_sectors = s->block_sectors - sector_in_block; - if (n_sectors > nb_sectors) { - n_sectors = nb_sectors; - } + qemu_iovec_init(&local_qiov, qiov->niov); - logout("will read %u sectors starting at sector %" PRIu64 "\n", - n_sectors, sector_num); + while (ret >= 0 && bytes > 0) { + block_index = offset / s->block_size; + offset_in_block = offset % s->block_size; + n_bytes = MIN(bytes, s->block_size - offset_in_block); + + logout("will read %u bytes starting at offset %" PRIu64 "\n", + n_bytes, offset); /* prepare next AIO request */ bmap_entry = le32_to_cpu(s->bmap[block_index]); if (!VDI_IS_ALLOCATED(bmap_entry)) { /* Block not allocated, return zeros, no need to wait. */ - memset(buf, 0, n_sectors * SECTOR_SIZE); + qemu_iovec_memset(qiov, bytes_done, 0, n_bytes); ret = 0; } else { - uint64_t offset = s->header.offset_data / SECTOR_SIZE + - (uint64_t)bmap_entry * s->block_sectors + - sector_in_block; - ret = bdrv_read(bs->file->bs, offset, buf, n_sectors); + uint64_t data_offset = s->header.offset_data + + (uint64_t)bmap_entry * s->block_size + + offset_in_block; + + qemu_iovec_reset(&local_qiov); + qemu_iovec_concat(&local_qiov, qiov, bytes_done, n_bytes); + + ret = bdrv_co_preadv(bs->file->bs, data_offset, n_bytes, + &local_qiov, 0); } - logout("%u sectors read\n", n_sectors); + logout("%u bytes read\n", n_bytes); - nb_sectors -= n_sectors; - sector_num += n_sectors; - buf += n_sectors * SECTOR_SIZE; + bytes -= n_bytes; + offset += n_bytes; + bytes_done += n_bytes; } + qemu_iovec_destroy(&local_qiov); + return ret; } @@ -903,7 +912,7 @@ static BlockDriver bdrv_vdi = { .bdrv_co_get_block_status = vdi_co_get_block_status, .bdrv_make_empty = vdi_make_empty, - .bdrv_read = vdi_co_read, + .bdrv_co_preadv = vdi_co_preadv, #if defined(CONFIG_VDI_WRITE) .bdrv_write = vdi_co_write, #endif -- cgit v1.2.3 From fde9d56f5bf238bb126d9ddcf316083c40e6be28 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Mon, 25 Apr 2016 16:22:39 +0200 Subject: vdi: Implement .bdrv_co_pwritev() interface Signed-off-by: Kevin Wolf Reviewed-by: Fam Zheng --- block/vdi.c | 72 +++++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 41 insertions(+), 31 deletions(-) diff --git a/block/vdi.c b/block/vdi.c index 8295511b72..e5fe4e8358 100644 --- a/block/vdi.c +++ b/block/vdi.c @@ -611,53 +611,55 @@ vdi_co_preadv(BlockDriverState *bs, uint64_t offset, uint64_t bytes, return ret; } -static int vdi_co_write(BlockDriverState *bs, - int64_t sector_num, const uint8_t *buf, int nb_sectors) +static int coroutine_fn +vdi_co_pwritev(BlockDriverState *bs, uint64_t offset, uint64_t bytes, + QEMUIOVector *qiov, int flags) { BDRVVdiState *s = bs->opaque; + QEMUIOVector local_qiov; uint32_t bmap_entry; uint32_t block_index; - uint32_t sector_in_block; - uint32_t n_sectors; + uint32_t offset_in_block; + uint32_t n_bytes; uint32_t bmap_first = VDI_UNALLOCATED; uint32_t bmap_last = VDI_UNALLOCATED; uint8_t *block = NULL; + uint64_t bytes_done = 0; int ret = 0; logout("\n"); - while (ret >= 0 && nb_sectors > 0) { - block_index = sector_num / s->block_sectors; - sector_in_block = sector_num % s->block_sectors; - n_sectors = s->block_sectors - sector_in_block; - if (n_sectors > nb_sectors) { - n_sectors = nb_sectors; - } + qemu_iovec_init(&local_qiov, qiov->niov); - logout("will write %u sectors starting at sector %" PRIu64 "\n", - n_sectors, sector_num); + while (ret >= 0 && bytes > 0) { + block_index = offset / s->block_size; + offset_in_block = offset % s->block_size; + n_bytes = MIN(bytes, s->block_size - offset_in_block); + + logout("will write %u bytes starting at offset %" PRIu64 "\n", + n_bytes, offset); /* prepare next AIO request */ bmap_entry = le32_to_cpu(s->bmap[block_index]); if (!VDI_IS_ALLOCATED(bmap_entry)) { /* Allocate new block and write to it. */ - uint64_t offset; + uint64_t data_offset; bmap_entry = s->header.blocks_allocated; s->bmap[block_index] = cpu_to_le32(bmap_entry); s->header.blocks_allocated++; - offset = s->header.offset_data / SECTOR_SIZE + - (uint64_t)bmap_entry * s->block_sectors; + data_offset = s->header.offset_data + + (uint64_t)bmap_entry * s->block_size; if (block == NULL) { block = g_malloc(s->block_size); bmap_first = block_index; } bmap_last = block_index; /* Copy data to be written to new block and zero unused parts. */ - memset(block, 0, sector_in_block * SECTOR_SIZE); - memcpy(block + sector_in_block * SECTOR_SIZE, - buf, n_sectors * SECTOR_SIZE); - memset(block + (sector_in_block + n_sectors) * SECTOR_SIZE, 0, - (s->block_sectors - n_sectors - sector_in_block) * SECTOR_SIZE); + memset(block, 0, offset_in_block); + qemu_iovec_to_buf(qiov, bytes_done, block + offset_in_block, + n_bytes); + memset(block + offset_in_block + n_bytes, 0, + s->block_size - n_bytes - offset_in_block); /* Note that this coroutine does not yield anywhere from reading the * bmap entry until here, so in regards to all the coroutines trying @@ -667,12 +669,12 @@ static int vdi_co_write(BlockDriverState *bs, * acquire the lock and thus the padded cluster is written before * the other coroutines can write to the affected area. */ qemu_co_mutex_lock(&s->write_lock); - ret = bdrv_write(bs->file->bs, offset, block, s->block_sectors); + ret = bdrv_pwrite(bs->file->bs, data_offset, block, s->block_size); qemu_co_mutex_unlock(&s->write_lock); } else { - uint64_t offset = s->header.offset_data / SECTOR_SIZE + - (uint64_t)bmap_entry * s->block_sectors + - sector_in_block; + uint64_t data_offset = s->header.offset_data + + (uint64_t)bmap_entry * s->block_size + + offset_in_block; qemu_co_mutex_lock(&s->write_lock); /* This lock is only used to make sure the following write operation * is executed after the write issued by the coroutine allocating @@ -683,16 +685,23 @@ static int vdi_co_write(BlockDriverState *bs, * that that write operation has returned (there may be other writes * in flight, but they do not concern this very operation). */ qemu_co_mutex_unlock(&s->write_lock); - ret = bdrv_write(bs->file->bs, offset, buf, n_sectors); + + qemu_iovec_reset(&local_qiov); + qemu_iovec_concat(&local_qiov, qiov, bytes_done, n_bytes); + + ret = bdrv_co_pwritev(bs->file->bs, data_offset, n_bytes, + &local_qiov, 0); } - nb_sectors -= n_sectors; - sector_num += n_sectors; - buf += n_sectors * SECTOR_SIZE; + bytes -= n_bytes; + offset += n_bytes; + bytes_done += n_bytes; - logout("%u sectors written\n", n_sectors); + logout("%u bytes written\n", n_bytes); } + qemu_iovec_destroy(&local_qiov); + logout("finished data write\n"); if (ret < 0) { return ret; @@ -703,6 +712,7 @@ static int vdi_co_write(BlockDriverState *bs, VdiHeader *header = (VdiHeader *) block; uint8_t *base; uint64_t offset; + uint32_t n_sectors; logout("now writing modified header\n"); assert(VDI_IS_ALLOCATED(bmap_first)); @@ -914,7 +924,7 @@ static BlockDriver bdrv_vdi = { .bdrv_co_preadv = vdi_co_preadv, #if defined(CONFIG_VDI_WRITE) - .bdrv_write = vdi_co_write, + .bdrv_co_pwritev = vdi_co_pwritev, #endif .bdrv_get_info = vdi_get_info, -- cgit v1.2.3 From a844a2b0d4d11a9108c12caabb9a3eed265bf750 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Mon, 25 Apr 2016 17:14:48 +0200 Subject: vmdk: Add vmdk_find_offset_in_cluster() This is a byte granularity version of vmdk_find_index_in_cluster(). Signed-off-by: Kevin Wolf Reviewed-by: Fam Zheng --- block/vmdk.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/block/vmdk.c b/block/vmdk.c index 45f9d3c5b9..f1e01f9731 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -1259,15 +1259,26 @@ static VmdkExtent *find_extent(BDRVVmdkState *s, return NULL; } +static inline uint64_t vmdk_find_offset_in_cluster(VmdkExtent *extent, + int64_t offset) +{ + uint64_t offset_in_cluster, extent_begin_offset, extent_relative_offset; + uint64_t cluster_size = extent->cluster_sectors * BDRV_SECTOR_SIZE; + + extent_begin_offset = + (extent->end_sector - extent->sectors) * BDRV_SECTOR_SIZE; + extent_relative_offset = offset - extent_begin_offset; + offset_in_cluster = extent_relative_offset % cluster_size; + + return offset_in_cluster; +} + static inline uint64_t vmdk_find_index_in_cluster(VmdkExtent *extent, int64_t sector_num) { - uint64_t index_in_cluster, extent_begin_sector, extent_relative_sector_num; - - extent_begin_sector = extent->end_sector - extent->sectors; - extent_relative_sector_num = sector_num - extent_begin_sector; - index_in_cluster = extent_relative_sector_num % extent->cluster_sectors; - return index_in_cluster; + uint64_t offset; + offset = vmdk_find_offset_in_cluster(extent, sector_num * BDRV_SECTOR_SIZE); + return offset / BDRV_SECTOR_SIZE; } static int64_t coroutine_fn vmdk_co_get_block_status(BlockDriverState *bs, -- cgit v1.2.3 From f10cc24359917da1347c0a56a2cbda3a5fcf9ce6 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Mon, 25 Apr 2016 17:34:41 +0200 Subject: vmdk: Implement .bdrv_co_preadv() interface Signed-off-by: Kevin Wolf Reviewed-by: Fam Zheng --- block/vmdk.c | 98 ++++++++++++++++++++++++++++++++---------------------------- 1 file changed, 53 insertions(+), 45 deletions(-) diff --git a/block/vmdk.c b/block/vmdk.c index f1e01f9731..6c447add3a 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -1381,8 +1381,8 @@ static int vmdk_write_extent(VmdkExtent *extent, int64_t cluster_offset, } static int vmdk_read_extent(VmdkExtent *extent, int64_t cluster_offset, - int64_t offset_in_cluster, uint8_t *buf, - int nb_sectors) + int64_t offset_in_cluster, QEMUIOVector *qiov, + int bytes) { int ret; int cluster_bytes, buf_bytes; @@ -1394,14 +1394,13 @@ static int vmdk_read_extent(VmdkExtent *extent, int64_t cluster_offset, if (!extent->compressed) { - ret = bdrv_pread(extent->file->bs, - cluster_offset + offset_in_cluster, - buf, nb_sectors * 512); - if (ret == nb_sectors * 512) { - return 0; - } else { - return -EIO; + ret = bdrv_co_preadv(extent->file->bs, + cluster_offset + offset_in_cluster, bytes, + qiov, 0); + if (ret < 0) { + return ret; } + return 0; } cluster_bytes = extent->cluster_sectors * 512; /* Read two clusters in case GrainMarker + compressed data > one cluster */ @@ -1433,11 +1432,11 @@ static int vmdk_read_extent(VmdkExtent *extent, int64_t cluster_offset, } if (offset_in_cluster < 0 || - offset_in_cluster + nb_sectors * 512 > buf_len) { + offset_in_cluster + bytes > buf_len) { ret = -EINVAL; goto out; } - memcpy(buf, uncomp_buf + offset_in_cluster, nb_sectors * 512); + qemu_iovec_from_buf(qiov, 0, uncomp_buf + offset_in_cluster, bytes); ret = 0; out: @@ -1446,64 +1445,73 @@ static int vmdk_read_extent(VmdkExtent *extent, int64_t cluster_offset, return ret; } -static int vmdk_read(BlockDriverState *bs, int64_t sector_num, - uint8_t *buf, int nb_sectors) +static int coroutine_fn +vmdk_co_preadv(BlockDriverState *bs, uint64_t offset, uint64_t bytes, + QEMUIOVector *qiov, int flags) { BDRVVmdkState *s = bs->opaque; int ret; - uint64_t n, index_in_cluster; + uint64_t n_bytes, offset_in_cluster; VmdkExtent *extent = NULL; + QEMUIOVector local_qiov; uint64_t cluster_offset; + uint64_t bytes_done = 0; - while (nb_sectors > 0) { - extent = find_extent(s, sector_num, extent); + qemu_iovec_init(&local_qiov, qiov->niov); + qemu_co_mutex_lock(&s->lock); + + while (bytes > 0) { + extent = find_extent(s, offset >> BDRV_SECTOR_BITS, extent); if (!extent) { - return -EIO; + ret = -EIO; + goto fail; } ret = get_cluster_offset(bs, extent, NULL, - sector_num << 9, false, &cluster_offset, - 0, 0); - index_in_cluster = vmdk_find_index_in_cluster(extent, sector_num); - n = extent->cluster_sectors - index_in_cluster; - if (n > nb_sectors) { - n = nb_sectors; - } + offset, false, &cluster_offset, 0, 0); + offset_in_cluster = vmdk_find_offset_in_cluster(extent, offset); + + n_bytes = MIN(bytes, extent->cluster_sectors * BDRV_SECTOR_SIZE + - offset_in_cluster); + if (ret != VMDK_OK) { /* if not allocated, try to read from parent image, if exist */ if (bs->backing && ret != VMDK_ZEROED) { if (!vmdk_is_cid_valid(bs)) { - return -EINVAL; + ret = -EINVAL; + goto fail; } - ret = bdrv_read(bs->backing->bs, sector_num, buf, n); + + qemu_iovec_reset(&local_qiov); + qemu_iovec_concat(&local_qiov, qiov, bytes_done, n_bytes); + + ret = bdrv_co_preadv(bs->backing->bs, offset, n_bytes, + &local_qiov, 0); if (ret < 0) { - return ret; + goto fail; } } else { - memset(buf, 0, 512 * n); + qemu_iovec_memset(qiov, bytes_done, 0, n_bytes); } } else { - ret = vmdk_read_extent(extent, - cluster_offset, index_in_cluster * 512, - buf, n); + qemu_iovec_reset(&local_qiov); + qemu_iovec_concat(&local_qiov, qiov, bytes_done, n_bytes); + + ret = vmdk_read_extent(extent, cluster_offset, offset_in_cluster, + &local_qiov, n_bytes); if (ret) { - return ret; + goto fail; } } - nb_sectors -= n; - sector_num += n; - buf += n * 512; + bytes -= n_bytes; + offset += n_bytes; + bytes_done += n_bytes; } - return 0; -} -static coroutine_fn int vmdk_co_read(BlockDriverState *bs, int64_t sector_num, - uint8_t *buf, int nb_sectors) -{ - int ret; - BDRVVmdkState *s = bs->opaque; - qemu_co_mutex_lock(&s->lock); - ret = vmdk_read(bs, sector_num, buf, nb_sectors); + ret = 0; +fail: qemu_co_mutex_unlock(&s->lock); + qemu_iovec_destroy(&local_qiov); + return ret; } @@ -2332,7 +2340,7 @@ static BlockDriver bdrv_vmdk = { .bdrv_open = vmdk_open, .bdrv_check = vmdk_check, .bdrv_reopen_prepare = vmdk_reopen_prepare, - .bdrv_read = vmdk_co_read, + .bdrv_co_preadv = vmdk_co_preadv, .bdrv_write = vmdk_co_write, .bdrv_write_compressed = vmdk_write_compressed, .bdrv_co_write_zeroes = vmdk_co_write_zeroes, -- cgit v1.2.3 From 37b1d7d8c98e2faaa27593c33a858948209beea0 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Tue, 26 Apr 2016 13:39:11 +0200 Subject: vmdk: Implement .bdrv_co_pwritev() interface Signed-off-by: Kevin Wolf Reviewed-by: Fam Zheng --- block/vmdk.c | 209 ++++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 135 insertions(+), 74 deletions(-) diff --git a/block/vmdk.c b/block/vmdk.c index 6c447add3a..f243527d44 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -1016,27 +1016,26 @@ static void vmdk_refresh_limits(BlockDriverState *bs, Error **errp) */ static int get_whole_cluster(BlockDriverState *bs, VmdkExtent *extent, - uint64_t cluster_sector_num, - uint64_t sector_num, - uint64_t skip_start_sector, - uint64_t skip_end_sector) + uint64_t cluster_offset, + uint64_t offset, + uint64_t skip_start_bytes, + uint64_t skip_end_bytes) { int ret = VMDK_OK; int64_t cluster_bytes; uint8_t *whole_grain; /* For COW, align request sector_num to cluster start */ - sector_num = QEMU_ALIGN_DOWN(sector_num, extent->cluster_sectors); cluster_bytes = extent->cluster_sectors << BDRV_SECTOR_BITS; + offset = QEMU_ALIGN_DOWN(offset, cluster_bytes); whole_grain = qemu_blockalign(bs, cluster_bytes); if (!bs->backing) { - memset(whole_grain, 0, skip_start_sector << BDRV_SECTOR_BITS); - memset(whole_grain + (skip_end_sector << BDRV_SECTOR_BITS), 0, - cluster_bytes - (skip_end_sector << BDRV_SECTOR_BITS)); + memset(whole_grain, 0, skip_start_bytes); + memset(whole_grain + skip_end_bytes, 0, cluster_bytes - skip_end_bytes); } - assert(skip_end_sector <= extent->cluster_sectors); + assert(skip_end_bytes <= cluster_bytes); /* we will be here if it's first write on non-exist grain(cluster). * try to read from parent image, if exist */ if (bs->backing && !vmdk_is_cid_valid(bs)) { @@ -1045,42 +1044,43 @@ static int get_whole_cluster(BlockDriverState *bs, } /* Read backing data before skip range */ - if (skip_start_sector > 0) { + if (skip_start_bytes > 0) { if (bs->backing) { - ret = bdrv_read(bs->backing->bs, sector_num, - whole_grain, skip_start_sector); + ret = bdrv_pread(bs->backing->bs, offset, whole_grain, + skip_start_bytes); if (ret < 0) { ret = VMDK_ERROR; goto exit; } } - ret = bdrv_write(extent->file->bs, cluster_sector_num, whole_grain, - skip_start_sector); + ret = bdrv_pwrite(extent->file->bs, cluster_offset, whole_grain, + skip_start_bytes); if (ret < 0) { ret = VMDK_ERROR; goto exit; } } /* Read backing data after skip range */ - if (skip_end_sector < extent->cluster_sectors) { + if (skip_end_bytes < cluster_bytes) { if (bs->backing) { - ret = bdrv_read(bs->backing->bs, sector_num + skip_end_sector, - whole_grain + (skip_end_sector << BDRV_SECTOR_BITS), - extent->cluster_sectors - skip_end_sector); + ret = bdrv_pread(bs->backing->bs, offset + skip_end_bytes, + whole_grain + skip_end_bytes, + cluster_bytes - skip_end_bytes); if (ret < 0) { ret = VMDK_ERROR; goto exit; } } - ret = bdrv_write(extent->file->bs, cluster_sector_num + skip_end_sector, - whole_grain + (skip_end_sector << BDRV_SECTOR_BITS), - extent->cluster_sectors - skip_end_sector); + ret = bdrv_pwrite(extent->file->bs, cluster_offset + skip_end_bytes, + whole_grain + skip_end_bytes, + cluster_bytes - skip_end_bytes); if (ret < 0) { ret = VMDK_ERROR; goto exit; } } + ret = VMDK_OK; exit: qemu_vfree(whole_grain); return ret; @@ -1142,8 +1142,8 @@ static int get_cluster_offset(BlockDriverState *bs, uint64_t offset, bool allocate, uint64_t *cluster_offset, - uint64_t skip_start_sector, - uint64_t skip_end_sector) + uint64_t skip_start_bytes, + uint64_t skip_end_bytes) { unsigned int l1_index, l2_offset, l2_index; int min_index, i, j; @@ -1230,10 +1230,8 @@ static int get_cluster_offset(BlockDriverState *bs, * This problem may occur because of insufficient space on host disk * or inappropriate VM shutdown. */ - ret = get_whole_cluster(bs, extent, - cluster_sector, - offset >> BDRV_SECTOR_BITS, - skip_start_sector, skip_end_sector); + ret = get_whole_cluster(bs, extent, cluster_sector * BDRV_SECTOR_SIZE, + offset, skip_start_bytes, skip_end_bytes); if (ret) { return ret; } @@ -1330,38 +1328,57 @@ static int64_t coroutine_fn vmdk_co_get_block_status(BlockDriverState *bs, } static int vmdk_write_extent(VmdkExtent *extent, int64_t cluster_offset, - int64_t offset_in_cluster, const uint8_t *buf, - int nb_sectors, int64_t sector_num) + int64_t offset_in_cluster, QEMUIOVector *qiov, + uint64_t qiov_offset, uint64_t n_bytes, + uint64_t offset) { int ret; VmdkGrainMarker *data = NULL; uLongf buf_len; - const uint8_t *write_buf = buf; - int write_len = nb_sectors * 512; + QEMUIOVector local_qiov; + struct iovec iov; int64_t write_offset; int64_t write_end_sector; if (extent->compressed) { + void *compressed_data; + if (!extent->has_marker) { ret = -EINVAL; goto out; } buf_len = (extent->cluster_sectors << 9) * 2; data = g_malloc(buf_len + sizeof(VmdkGrainMarker)); - if (compress(data->data, &buf_len, buf, nb_sectors << 9) != Z_OK || - buf_len == 0) { + + compressed_data = g_malloc(n_bytes); + qemu_iovec_to_buf(qiov, qiov_offset, compressed_data, n_bytes); + ret = compress(data->data, &buf_len, compressed_data, n_bytes); + g_free(compressed_data); + + if (ret != Z_OK || buf_len == 0) { ret = -EINVAL; goto out; } - data->lba = sector_num; + + data->lba = offset >> BDRV_SECTOR_BITS; data->size = buf_len; - write_buf = (uint8_t *)data; - write_len = buf_len + sizeof(VmdkGrainMarker); + + n_bytes = buf_len + sizeof(VmdkGrainMarker); + iov = (struct iovec) { + .iov_base = data, + .iov_len = n_bytes, + }; + qemu_iovec_init_external(&local_qiov, &iov, 1); + } else { + qemu_iovec_init(&local_qiov, qiov->niov); + qemu_iovec_concat(&local_qiov, qiov, qiov_offset, n_bytes); } + write_offset = cluster_offset + offset_in_cluster, - ret = bdrv_pwrite(extent->file->bs, write_offset, write_buf, write_len); + ret = bdrv_co_pwritev(extent->file->bs, write_offset, n_bytes, + &local_qiov, 0); - write_end_sector = DIV_ROUND_UP(write_offset + write_len, BDRV_SECTOR_SIZE); + write_end_sector = DIV_ROUND_UP(write_offset + n_bytes, BDRV_SECTOR_SIZE); if (extent->compressed) { extent->next_cluster_sector = write_end_sector; @@ -1370,13 +1387,15 @@ static int vmdk_write_extent(VmdkExtent *extent, int64_t cluster_offset, write_end_sector); } - if (ret != write_len) { - ret = ret < 0 ? ret : -EIO; + if (ret < 0) { goto out; } ret = 0; out: g_free(data); + if (!extent->compressed) { + qemu_iovec_destroy(&local_qiov); + } return ret; } @@ -1525,38 +1544,38 @@ fail: * * Returns: error code with 0 for success. */ -static int vmdk_write(BlockDriverState *bs, int64_t sector_num, - const uint8_t *buf, int nb_sectors, - bool zeroed, bool zero_dry_run) +static int vmdk_pwritev(BlockDriverState *bs, uint64_t offset, + uint64_t bytes, QEMUIOVector *qiov, + bool zeroed, bool zero_dry_run) { BDRVVmdkState *s = bs->opaque; VmdkExtent *extent = NULL; int ret; - int64_t index_in_cluster, n; + int64_t offset_in_cluster, n_bytes; uint64_t cluster_offset; + uint64_t bytes_done = 0; VmdkMetaData m_data; - if (sector_num > bs->total_sectors) { - error_report("Wrong offset: sector_num=0x%" PRIx64 + if (DIV_ROUND_UP(offset, BDRV_SECTOR_SIZE) > bs->total_sectors) { + error_report("Wrong offset: offset=0x%" PRIx64 " total_sectors=0x%" PRIx64, - sector_num, bs->total_sectors); + offset, bs->total_sectors); return -EIO; } - while (nb_sectors > 0) { - extent = find_extent(s, sector_num, extent); + while (bytes > 0) { + extent = find_extent(s, offset >> BDRV_SECTOR_BITS, extent); if (!extent) { return -EIO; } - index_in_cluster = vmdk_find_index_in_cluster(extent, sector_num); - n = extent->cluster_sectors - index_in_cluster; - if (n > nb_sectors) { - n = nb_sectors; - } - ret = get_cluster_offset(bs, extent, &m_data, sector_num << 9, + offset_in_cluster = vmdk_find_offset_in_cluster(extent, offset); + n_bytes = MIN(bytes, extent->cluster_sectors * BDRV_SECTOR_SIZE + - offset_in_cluster); + + ret = get_cluster_offset(bs, extent, &m_data, offset, !(extent->compressed || zeroed), - &cluster_offset, - index_in_cluster, index_in_cluster + n); + &cluster_offset, offset_in_cluster, + offset_in_cluster + n_bytes); if (extent->compressed) { if (ret == VMDK_OK) { /* Refuse write to allocated cluster for streamOptimized */ @@ -1565,7 +1584,7 @@ static int vmdk_write(BlockDriverState *bs, int64_t sector_num, return -EIO; } else { /* allocate */ - ret = get_cluster_offset(bs, extent, &m_data, sector_num << 9, + ret = get_cluster_offset(bs, extent, &m_data, offset, true, &cluster_offset, 0, 0); } } @@ -1575,9 +1594,9 @@ static int vmdk_write(BlockDriverState *bs, int64_t sector_num, if (zeroed) { /* Do zeroed write, buf is ignored */ if (extent->has_zero_grain && - index_in_cluster == 0 && - n >= extent->cluster_sectors) { - n = extent->cluster_sectors; + offset_in_cluster == 0 && + n_bytes >= extent->cluster_sectors * BDRV_SECTOR_SIZE) { + n_bytes = extent->cluster_sectors * BDRV_SECTOR_SIZE; if (!zero_dry_run) { /* update L2 tables */ if (vmdk_L2update(extent, &m_data, VMDK_GTE_ZEROED) @@ -1589,9 +1608,8 @@ static int vmdk_write(BlockDriverState *bs, int64_t sector_num, return -ENOTSUP; } } else { - ret = vmdk_write_extent(extent, - cluster_offset, index_in_cluster * 512, - buf, n, sector_num); + ret = vmdk_write_extent(extent, cluster_offset, offset_in_cluster, + qiov, bytes_done, n_bytes, offset); if (ret) { return ret; } @@ -1604,9 +1622,9 @@ static int vmdk_write(BlockDriverState *bs, int64_t sector_num, } } } - nb_sectors -= n; - sector_num += n; - buf += n * 512; + bytes -= n_bytes; + offset += n_bytes; + bytes_done += n_bytes; /* update CID on the first write every time the virtual disk is * opened */ @@ -1621,25 +1639,65 @@ static int vmdk_write(BlockDriverState *bs, int64_t sector_num, return 0; } -static coroutine_fn int vmdk_co_write(BlockDriverState *bs, int64_t sector_num, - const uint8_t *buf, int nb_sectors) +static int coroutine_fn +vmdk_co_pwritev(BlockDriverState *bs, uint64_t offset, uint64_t bytes, + QEMUIOVector *qiov, int flags) { int ret; BDRVVmdkState *s = bs->opaque; qemu_co_mutex_lock(&s->lock); - ret = vmdk_write(bs, sector_num, buf, nb_sectors, false, false); + ret = vmdk_pwritev(bs, offset, bytes, qiov, false, false); qemu_co_mutex_unlock(&s->lock); return ret; } +typedef struct VmdkWriteCompressedCo { + BlockDriverState *bs; + int64_t sector_num; + const uint8_t *buf; + int nb_sectors; + int ret; +} VmdkWriteCompressedCo; + +static void vmdk_co_write_compressed(void *opaque) +{ + VmdkWriteCompressedCo *co = opaque; + QEMUIOVector local_qiov; + uint64_t offset = co->sector_num * BDRV_SECTOR_SIZE; + uint64_t bytes = co->nb_sectors * BDRV_SECTOR_SIZE; + + struct iovec iov = (struct iovec) { + .iov_base = (uint8_t*) co->buf, + .iov_len = bytes, + }; + qemu_iovec_init_external(&local_qiov, &iov, 1); + + co->ret = vmdk_pwritev(co->bs, offset, bytes, &local_qiov, false, false); +} + static int vmdk_write_compressed(BlockDriverState *bs, int64_t sector_num, const uint8_t *buf, int nb_sectors) { BDRVVmdkState *s = bs->opaque; + if (s->num_extents == 1 && s->extents[0].compressed) { - return vmdk_write(bs, sector_num, buf, nb_sectors, false, false); + Coroutine *co; + AioContext *aio_context = bdrv_get_aio_context(bs); + VmdkWriteCompressedCo data = { + .bs = bs, + .sector_num = sector_num, + .buf = buf, + .nb_sectors = nb_sectors, + .ret = -EINPROGRESS, + }; + co = qemu_coroutine_create(vmdk_co_write_compressed); + qemu_coroutine_enter(co, &data); + while (data.ret == -EINPROGRESS) { + aio_poll(aio_context, true); + } + return data.ret; } else { return -ENOTSUP; } @@ -1652,12 +1710,15 @@ static int coroutine_fn vmdk_co_write_zeroes(BlockDriverState *bs, { int ret; BDRVVmdkState *s = bs->opaque; + uint64_t offset = sector_num * BDRV_SECTOR_SIZE; + uint64_t bytes = nb_sectors * BDRV_SECTOR_SIZE; + qemu_co_mutex_lock(&s->lock); /* write zeroes could fail if sectors not aligned to cluster, test it with * dry_run == true before really updating image */ - ret = vmdk_write(bs, sector_num, NULL, nb_sectors, true, true); + ret = vmdk_pwritev(bs, offset, bytes, NULL, true, true); if (!ret) { - ret = vmdk_write(bs, sector_num, NULL, nb_sectors, true, false); + ret = vmdk_pwritev(bs, offset, bytes, NULL, true, false); } qemu_co_mutex_unlock(&s->lock); return ret; @@ -2341,7 +2402,7 @@ static BlockDriver bdrv_vmdk = { .bdrv_check = vmdk_check, .bdrv_reopen_prepare = vmdk_reopen_prepare, .bdrv_co_preadv = vmdk_co_preadv, - .bdrv_write = vmdk_co_write, + .bdrv_co_pwritev = vmdk_co_pwritev, .bdrv_write_compressed = vmdk_write_compressed, .bdrv_co_write_zeroes = vmdk_co_write_zeroes, .bdrv_close = vmdk_close, -- cgit v1.2.3 From d46b7cc680fa74a2da6618018691d3bf7c2cd10b Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Tue, 26 Apr 2016 16:24:46 +0200 Subject: vpc: Implement .bdrv_co_preadv() interface Signed-off-by: Kevin Wolf Reviewed-by: Fam Zheng --- block/vpc.c | 79 ++++++++++++++++++++++++++++++++----------------------------- 1 file changed, 42 insertions(+), 37 deletions(-) diff --git a/block/vpc.c b/block/vpc.c index 3e2ea698d9..01f5f27ad8 100644 --- a/block/vpc.c +++ b/block/vpc.c @@ -454,22 +454,21 @@ static int vpc_reopen_prepare(BDRVReopenState *state, * The parameter write must be 1 if the offset will be used for a write * operation (the block bitmaps is updated then), 0 otherwise. */ -static inline int64_t get_sector_offset(BlockDriverState *bs, - int64_t sector_num, int write) +static inline int64_t get_image_offset(BlockDriverState *bs, uint64_t offset, + bool write) { BDRVVPCState *s = bs->opaque; - uint64_t offset = sector_num * 512; uint64_t bitmap_offset, block_offset; - uint32_t pagetable_index, pageentry_index; + uint32_t pagetable_index, offset_in_block; pagetable_index = offset / s->block_size; - pageentry_index = (offset % s->block_size) / 512; + offset_in_block = offset % s->block_size; if (pagetable_index >= s->max_table_entries || s->pagetable[pagetable_index] == 0xffffffff) return -1; /* not allocated */ bitmap_offset = 512 * (uint64_t) s->pagetable[pagetable_index]; - block_offset = bitmap_offset + s->bitmap_size + (512 * pageentry_index); + block_offset = bitmap_offset + s->bitmap_size + offset_in_block; /* We must ensure that we don't write to any sectors which are marked as unused in the bitmap. We get away with setting all bits in the block @@ -487,6 +486,12 @@ static inline int64_t get_sector_offset(BlockDriverState *bs, return block_offset; } +static inline int64_t get_sector_offset(BlockDriverState *bs, + int64_t sector_num, bool write) +{ + return get_image_offset(bs, sector_num * BDRV_SECTOR_SIZE, write); +} + /* * Writes the footer to the end of the image file. This is needed when the * file grows as it overwrites the old footer @@ -573,52 +578,52 @@ static int vpc_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) return 0; } -static int vpc_read(BlockDriverState *bs, int64_t sector_num, - uint8_t *buf, int nb_sectors) +static int coroutine_fn +vpc_co_preadv(BlockDriverState *bs, uint64_t offset, uint64_t bytes, + QEMUIOVector *qiov, int flags) { BDRVVPCState *s = bs->opaque; int ret; - int64_t offset; - int64_t sectors, sectors_per_block; + int64_t image_offset; + int64_t n_bytes; + int64_t bytes_done = 0; VHDFooter *footer = (VHDFooter *) s->footer_buf; + QEMUIOVector local_qiov; if (be32_to_cpu(footer->type) == VHD_FIXED) { - return bdrv_read(bs->file->bs, sector_num, buf, nb_sectors); + return bdrv_co_preadv(bs->file->bs, offset, bytes, qiov, 0); } - while (nb_sectors > 0) { - offset = get_sector_offset(bs, sector_num, 0); - sectors_per_block = s->block_size >> BDRV_SECTOR_BITS; - sectors = sectors_per_block - (sector_num % sectors_per_block); - if (sectors > nb_sectors) { - sectors = nb_sectors; - } + qemu_co_mutex_lock(&s->lock); + qemu_iovec_init(&local_qiov, qiov->niov); - if (offset == -1) { - memset(buf, 0, sectors * BDRV_SECTOR_SIZE); + while (bytes > 0) { + image_offset = get_image_offset(bs, offset, false); + n_bytes = MIN(bytes, s->block_size - (offset % s->block_size)); + + if (image_offset == -1) { + qemu_iovec_memset(qiov, bytes_done, 0, n_bytes); } else { - ret = bdrv_pread(bs->file->bs, offset, buf, - sectors * BDRV_SECTOR_SIZE); - if (ret != sectors * BDRV_SECTOR_SIZE) { - return -1; + qemu_iovec_reset(&local_qiov); + qemu_iovec_concat(&local_qiov, qiov, bytes_done, n_bytes); + + ret = bdrv_co_preadv(bs->file->bs, image_offset, n_bytes, + &local_qiov, 0); + if (ret < 0) { + goto fail; } } - nb_sectors -= sectors; - sector_num += sectors; - buf += sectors * BDRV_SECTOR_SIZE; + bytes -= n_bytes; + offset += n_bytes; + bytes_done += n_bytes; } - return 0; -} -static coroutine_fn int vpc_co_read(BlockDriverState *bs, int64_t sector_num, - uint8_t *buf, int nb_sectors) -{ - int ret; - BDRVVPCState *s = bs->opaque; - qemu_co_mutex_lock(&s->lock); - ret = vpc_read(bs, sector_num, buf, nb_sectors); + ret = 0; +fail: + qemu_iovec_destroy(&local_qiov); qemu_co_mutex_unlock(&s->lock); + return ret; } @@ -1056,7 +1061,7 @@ static BlockDriver bdrv_vpc = { .bdrv_reopen_prepare = vpc_reopen_prepare, .bdrv_create = vpc_create, - .bdrv_read = vpc_co_read, + .bdrv_co_preadv = vpc_co_preadv, .bdrv_write = vpc_co_write, .bdrv_co_get_block_status = vpc_co_get_block_status, -- cgit v1.2.3 From 513b0f026b35e2d10855718fe9939a6152e27fb9 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Tue, 26 Apr 2016 16:24:46 +0200 Subject: vpc: Implement .bdrv_co_pwritev() interface Signed-off-by: Kevin Wolf Reviewed-by: Fam Zheng --- block/vpc.c | 86 ++++++++++++++++++++++++++++++------------------------------- 1 file changed, 43 insertions(+), 43 deletions(-) diff --git a/block/vpc.c b/block/vpc.c index 01f5f27ad8..2da4126ce6 100644 --- a/block/vpc.c +++ b/block/vpc.c @@ -518,7 +518,7 @@ static int rewrite_footer(BlockDriverState* bs) * * Returns the sectors' offset in the image file on success and < 0 on error */ -static int64_t alloc_block(BlockDriverState* bs, int64_t sector_num) +static int64_t alloc_block(BlockDriverState* bs, int64_t offset) { BDRVVPCState *s = bs->opaque; int64_t bat_offset; @@ -527,14 +527,13 @@ static int64_t alloc_block(BlockDriverState* bs, int64_t sector_num) uint8_t bitmap[s->bitmap_size]; /* Check if sector_num is valid */ - if ((sector_num < 0) || (sector_num > bs->total_sectors)) - return -1; + if ((offset < 0) || (offset > bs->total_sectors * BDRV_SECTOR_SIZE)) { + return -EINVAL; + } /* Write entry into in-memory BAT */ - index = (sector_num * 512) / s->block_size; - if (s->pagetable[index] != 0xFFFFFFFF) - return -1; - + index = offset / s->block_size; + assert(s->pagetable[index] == 0xFFFFFFFF); s->pagetable[index] = s->free_data_block_offset / 512; /* Initialize the block's bitmap */ @@ -558,11 +557,11 @@ static int64_t alloc_block(BlockDriverState* bs, int64_t sector_num) if (ret < 0) goto fail; - return get_sector_offset(bs, sector_num, 0); + return get_image_offset(bs, offset, false); fail: s->free_data_block_offset -= (s->block_size + s->bitmap_size); - return -1; + return ret; } static int vpc_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) @@ -627,55 +626,56 @@ fail: return ret; } -static int vpc_write(BlockDriverState *bs, int64_t sector_num, - const uint8_t *buf, int nb_sectors) +static int coroutine_fn +vpc_co_pwritev(BlockDriverState *bs, uint64_t offset, uint64_t bytes, + QEMUIOVector *qiov, int flags) { BDRVVPCState *s = bs->opaque; - int64_t offset; - int64_t sectors, sectors_per_block; + int64_t image_offset; + int64_t n_bytes; + int64_t bytes_done = 0; int ret; VHDFooter *footer = (VHDFooter *) s->footer_buf; + QEMUIOVector local_qiov; if (be32_to_cpu(footer->type) == VHD_FIXED) { - return bdrv_write(bs->file->bs, sector_num, buf, nb_sectors); + return bdrv_co_pwritev(bs->file->bs, offset, bytes, qiov, 0); } - while (nb_sectors > 0) { - offset = get_sector_offset(bs, sector_num, 1); - sectors_per_block = s->block_size >> BDRV_SECTOR_BITS; - sectors = sectors_per_block - (sector_num % sectors_per_block); - if (sectors > nb_sectors) { - sectors = nb_sectors; - } + qemu_co_mutex_lock(&s->lock); + qemu_iovec_init(&local_qiov, qiov->niov); + + while (bytes > 0) { + image_offset = get_image_offset(bs, offset, true); + n_bytes = MIN(bytes, s->block_size - (offset % s->block_size)); - if (offset == -1) { - offset = alloc_block(bs, sector_num); - if (offset < 0) - return -1; + if (image_offset == -1) { + image_offset = alloc_block(bs, offset); + if (image_offset < 0) { + ret = image_offset; + goto fail; + } } - ret = bdrv_pwrite(bs->file->bs, offset, buf, - sectors * BDRV_SECTOR_SIZE); - if (ret != sectors * BDRV_SECTOR_SIZE) { - return -1; + qemu_iovec_reset(&local_qiov); + qemu_iovec_concat(&local_qiov, qiov, bytes_done, n_bytes); + + ret = bdrv_co_pwritev(bs->file->bs, image_offset, n_bytes, + &local_qiov, 0); + if (ret < 0) { + goto fail; } - nb_sectors -= sectors; - sector_num += sectors; - buf += sectors * BDRV_SECTOR_SIZE; + bytes -= n_bytes; + offset += n_bytes; + bytes_done += n_bytes; } - return 0; -} - -static coroutine_fn int vpc_co_write(BlockDriverState *bs, int64_t sector_num, - const uint8_t *buf, int nb_sectors) -{ - int ret; - BDRVVPCState *s = bs->opaque; - qemu_co_mutex_lock(&s->lock); - ret = vpc_write(bs, sector_num, buf, nb_sectors); + ret = 0; +fail: + qemu_iovec_destroy(&local_qiov); qemu_co_mutex_unlock(&s->lock); + return ret; } @@ -1062,7 +1062,7 @@ static BlockDriver bdrv_vpc = { .bdrv_create = vpc_create, .bdrv_co_preadv = vpc_co_preadv, - .bdrv_write = vpc_co_write, + .bdrv_co_pwritev = vpc_co_pwritev, .bdrv_co_get_block_status = vpc_co_get_block_status, .bdrv_get_info = vpc_get_info, -- cgit v1.2.3 From 4575eb496da8da595689b286e202929f06612585 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Tue, 26 Apr 2016 17:14:08 +0200 Subject: vvfat: Implement .bdrv_co_preadv/pwritev interfaces This doesn't really convert any of the actual vvfat logic to use vectored I/O (and it's doubtful whether that would make sense), but instead just adapts the wrappers to the modern interface. Signed-off-by: Kevin Wolf Reviewed-by: Fam Zheng --- block/vvfat.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 46 insertions(+), 9 deletions(-) diff --git a/block/vvfat.c b/block/vvfat.c index 183fc4f049..5b0c8dd639 100644 --- a/block/vvfat.c +++ b/block/vvfat.c @@ -1179,6 +1179,7 @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags, bs->read_only = 0; } + bs->request_alignment = BDRV_SECTOR_SIZE; /* No sub-sector I/O supported */ bs->total_sectors = cyls * heads * secs; if (init_directories(s, dirname, heads, secs, errp)) { @@ -1421,14 +1422,31 @@ DLOG(fprintf(stderr, "sector %d not allocated\n", (int)sector_num)); return 0; } -static coroutine_fn int vvfat_co_read(BlockDriverState *bs, int64_t sector_num, - uint8_t *buf, int nb_sectors) +static int coroutine_fn +vvfat_co_preadv(BlockDriverState *bs, uint64_t offset, uint64_t bytes, + QEMUIOVector *qiov, int flags) { int ret; BDRVVVFATState *s = bs->opaque; + uint64_t sector_num = offset >> BDRV_SECTOR_BITS; + int nb_sectors = bytes >> BDRV_SECTOR_BITS; + void *buf; + + assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0); + assert((bytes & (BDRV_SECTOR_SIZE - 1)) == 0); + + buf = g_try_malloc(bytes); + if (bytes && buf == NULL) { + return -ENOMEM; + } + qemu_co_mutex_lock(&s->lock); ret = vvfat_read(bs, sector_num, buf, nb_sectors); qemu_co_mutex_unlock(&s->lock); + + qemu_iovec_from_buf(qiov, 0, buf, bytes); + g_free(buf); + return ret; } @@ -2880,14 +2898,31 @@ DLOG(checkpoint()); return 0; } -static coroutine_fn int vvfat_co_write(BlockDriverState *bs, int64_t sector_num, - const uint8_t *buf, int nb_sectors) +static int coroutine_fn +vvfat_co_pwritev(BlockDriverState *bs, uint64_t offset, uint64_t bytes, + QEMUIOVector *qiov, int flags) { int ret; BDRVVVFATState *s = bs->opaque; + uint64_t sector_num = offset >> BDRV_SECTOR_BITS; + int nb_sectors = bytes >> BDRV_SECTOR_BITS; + void *buf; + + assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0); + assert((bytes & (BDRV_SECTOR_SIZE - 1)) == 0); + + buf = g_try_malloc(bytes); + if (bytes && buf == NULL) { + return -ENOMEM; + } + qemu_iovec_to_buf(qiov, 0, buf, bytes); + qemu_co_mutex_lock(&s->lock); ret = vvfat_write(bs, sector_num, buf, nb_sectors); qemu_co_mutex_unlock(&s->lock); + + g_free(buf); + return ret; } @@ -2904,8 +2939,10 @@ static int64_t coroutine_fn vvfat_co_get_block_status(BlockDriverState *bs, return BDRV_BLOCK_DATA; } -static int write_target_commit(BlockDriverState *bs, int64_t sector_num, - const uint8_t* buffer, int nb_sectors) { +static int coroutine_fn +write_target_commit(BlockDriverState *bs, uint64_t offset, uint64_t bytes, + QEMUIOVector *qiov, int flags) +{ BDRVVVFATState* s = *((BDRVVVFATState**) bs->opaque); return try_commit(s); } @@ -2918,7 +2955,7 @@ static void write_target_close(BlockDriverState *bs) { static BlockDriver vvfat_write_target = { .format_name = "vvfat_write_target", - .bdrv_write = write_target_commit, + .bdrv_co_pwritev = write_target_commit, .bdrv_close = write_target_close, }; @@ -3014,8 +3051,8 @@ static BlockDriver bdrv_vvfat = { .bdrv_file_open = vvfat_open, .bdrv_close = vvfat_close, - .bdrv_read = vvfat_co_read, - .bdrv_write = vvfat_co_write, + .bdrv_co_preadv = vvfat_co_preadv, + .bdrv_co_pwritev = vvfat_co_pwritev, .bdrv_co_get_block_status = vvfat_co_get_block_status, }; -- cgit v1.2.3 From e3ddef25e93e7f00c2c407a6fb24b2c5dd26a43b Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Tue, 26 Apr 2016 17:28:25 +0200 Subject: block: Remove BlockDriver.bdrv_read/write There are no block drivers left that implement the old .bdrv_read/write interface, so it can be removed now. This gets us rid of the corresponding emulation functions, too. Signed-off-by: Kevin Wolf Reviewed-by: Fam Zheng --- block.c | 2 -- block/io.c | 92 ----------------------------------------------- include/block/block_int.h | 4 --- 3 files changed, 98 deletions(-) diff --git a/block.c b/block.c index 6cbad0e264..d70ae55e2a 100644 --- a/block.c +++ b/block.c @@ -218,8 +218,6 @@ void bdrv_get_full_backing_filename(BlockDriverState *bs, char *dest, size_t sz, void bdrv_register(BlockDriver *bdrv) { - bdrv_setup_io_funcs(bdrv); - QLIST_INSERT_HEAD(&bdrv_drivers, bdrv, list); } diff --git a/block/io.c b/block/io.c index 70caadd0f5..0db1146159 100644 --- a/block/io.c +++ b/block/io.c @@ -34,12 +34,6 @@ #define NOT_DONE 0x7fffffff /* used while emulated sync operation in progress */ -static BlockAIOCB *bdrv_aio_readv_em(BlockDriverState *bs, - int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, - BlockCompletionFunc *cb, void *opaque); -static BlockAIOCB *bdrv_aio_writev_em(BlockDriverState *bs, - int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, - BlockCompletionFunc *cb, void *opaque); static BlockAIOCB *bdrv_co_aio_rw_vector(BlockDriverState *bs, int64_t sector_num, QEMUIOVector *qiov, @@ -104,18 +98,6 @@ void bdrv_io_limits_update_group(BlockDriverState *bs, const char *group) bdrv_io_limits_enable(bs, group); } -void bdrv_setup_io_funcs(BlockDriver *bdrv) -{ - /* bdrv_co_readv_em()/brdv_co_writev_em() work in terms of aio, so if - * the block driver lacks aio we need to emulate that. - */ - if (!bdrv->bdrv_aio_readv) { - /* add AIO emulation layer */ - bdrv->bdrv_aio_readv = bdrv_aio_readv_em; - bdrv->bdrv_aio_writev = bdrv_aio_writev_em; - } -} - void bdrv_refresh_limits(BlockDriverState *bs, Error **errp) { BlockDriver *drv = bs->drv; @@ -2145,80 +2127,6 @@ void bdrv_aio_cancel_async(BlockAIOCB *acb) /**************************************************************/ /* async block device emulation */ -typedef struct BlockAIOCBSync { - BlockAIOCB common; - QEMUBH *bh; - int ret; - /* vector translation state */ - QEMUIOVector *qiov; - uint8_t *bounce; - int is_write; -} BlockAIOCBSync; - -static const AIOCBInfo bdrv_em_aiocb_info = { - .aiocb_size = sizeof(BlockAIOCBSync), -}; - -static void bdrv_aio_bh_cb(void *opaque) -{ - BlockAIOCBSync *acb = opaque; - - if (!acb->is_write && acb->ret >= 0) { - qemu_iovec_from_buf(acb->qiov, 0, acb->bounce, acb->qiov->size); - } - qemu_vfree(acb->bounce); - acb->common.cb(acb->common.opaque, acb->ret); - qemu_bh_delete(acb->bh); - acb->bh = NULL; - qemu_aio_unref(acb); -} - -static BlockAIOCB *bdrv_aio_rw_vector(BlockDriverState *bs, - int64_t sector_num, - QEMUIOVector *qiov, - int nb_sectors, - BlockCompletionFunc *cb, - void *opaque, - int is_write) - -{ - BlockAIOCBSync *acb; - - acb = qemu_aio_get(&bdrv_em_aiocb_info, bs, cb, opaque); - acb->is_write = is_write; - acb->qiov = qiov; - acb->bounce = qemu_try_blockalign(bs, qiov->size); - acb->bh = aio_bh_new(bdrv_get_aio_context(bs), bdrv_aio_bh_cb, acb); - - if (acb->bounce == NULL) { - acb->ret = -ENOMEM; - } else if (is_write) { - qemu_iovec_to_buf(acb->qiov, 0, acb->bounce, qiov->size); - acb->ret = bs->drv->bdrv_write(bs, sector_num, acb->bounce, nb_sectors); - } else { - acb->ret = bs->drv->bdrv_read(bs, sector_num, acb->bounce, nb_sectors); - } - - qemu_bh_schedule(acb->bh); - - return &acb->common; -} - -static BlockAIOCB *bdrv_aio_readv_em(BlockDriverState *bs, - int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, - BlockCompletionFunc *cb, void *opaque) -{ - return bdrv_aio_rw_vector(bs, sector_num, qiov, nb_sectors, cb, opaque, 0); -} - -static BlockAIOCB *bdrv_aio_writev_em(BlockDriverState *bs, - int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, - BlockCompletionFunc *cb, void *opaque) -{ - return bdrv_aio_rw_vector(bs, sector_num, qiov, nb_sectors, cb, opaque, 1); -} - - typedef struct BlockAIOCBCoroutine { BlockAIOCB common; BlockRequest req; diff --git a/include/block/block_int.h b/include/block/block_int.h index 565f795758..c512074ce9 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -127,10 +127,6 @@ struct BlockDriver { Error **errp); int (*bdrv_file_open)(BlockDriverState *bs, QDict *options, int flags, Error **errp); - int (*bdrv_read)(BlockDriverState *bs, int64_t sector_num, - uint8_t *buf, int nb_sectors); - int (*bdrv_write)(BlockDriverState *bs, int64_t sector_num, - const uint8_t *buf, int nb_sectors); void (*bdrv_close)(BlockDriverState *bs); int (*bdrv_create)(const char *filename, QemuOpts *opts, Error **errp); int (*bdrv_set_key)(BlockDriverState *bs, const char *key); -- cgit v1.2.3 From 547cb1574e29082aa194ec65c43c8e08ac1f9aa8 Mon Sep 17 00:00:00 2001 From: Wei Jiangang Date: Tue, 26 Apr 2016 18:12:43 +0800 Subject: block: Fix typo in comment s/imlement/implement/ Signed-off-by: Wei Jiangang Signed-off-by: Kevin Wolf --- blockdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blockdev.c b/blockdev.c index f1f520a265..f74eb4357a 100644 --- a/blockdev.c +++ b/blockdev.c @@ -73,7 +73,7 @@ static int if_max_devs[IF_COUNT] = { * Do not change these numbers! They govern how drive option * index maps to unit and bus. That mapping is ABI. * - * All controllers used to imlement if=T drives need to support + * All controllers used to implement if=T drives need to support * if_max_devs[T] units, for any T with if_max_devs[T] != 0. * Otherwise, some index values map to "impossible" bus, unit * values. -- cgit v1.2.3 From ed79f37d9b6f1d3543afe5103bbe9dab43484b66 Mon Sep 17 00:00:00 2001 From: Zhou Jie Date: Fri, 29 Apr 2016 13:12:01 +0800 Subject: block: always compile-check debug prints Files with conditional debug statements should ensure that the printf is always compiled. This prevents bitrot of the format string of the debug statement. And switch debug output to stderr. Signed-off-by: Zhou Jie Reviewed-by: Eric Blake Signed-off-by: Kevin Wolf --- block/curl.c | 10 ++++++++-- block/sheepdog.c | 13 ++++++++----- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/block/curl.c b/block/curl.c index 5a8f8b6239..da9f5e85de 100644 --- a/block/curl.c +++ b/block/curl.c @@ -36,10 +36,16 @@ // #define DEBUG_VERBOSE #ifdef DEBUG_CURL -#define DPRINTF(fmt, ...) do { printf(fmt, ## __VA_ARGS__); } while (0) +#define DEBUG_CURL_PRINT 1 #else -#define DPRINTF(fmt, ...) do { } while (0) +#define DEBUG_CURL_PRINT 0 #endif +#define DPRINTF(fmt, ...) \ + do { \ + if (DEBUG_CURL_PRINT) { \ + fprintf(stderr, fmt, ## __VA_ARGS__); \ + } \ + } while (0) #if LIBCURL_VERSION_NUM >= 0x071000 /* The multi interface timer callback was introduced in 7.16.0 */ diff --git a/block/sheepdog.c b/block/sheepdog.c index 33e0a33824..90236865e9 100644 --- a/block/sheepdog.c +++ b/block/sheepdog.c @@ -294,13 +294,16 @@ static inline size_t count_data_objs(const struct SheepdogInode *inode) #undef DPRINTF #ifdef DEBUG_SDOG -#define DPRINTF(fmt, args...) \ - do { \ - fprintf(stdout, "%s %d: " fmt, __func__, __LINE__, ##args); \ - } while (0) +#define DEBUG_SDOG_PRINT 1 #else -#define DPRINTF(fmt, args...) +#define DEBUG_SDOG_PRINT 0 #endif +#define DPRINTF(fmt, args...) \ + do { \ + if (DEBUG_SDOG_PRINT) { \ + fprintf(stderr, "%s %d: " fmt, __func__, __LINE__, ##args); \ + } \ + } while (0) typedef struct SheepdogAIOCB SheepdogAIOCB; -- cgit v1.2.3 From f249924e96861f1dd7c5f79e62e3fb96c78e255d Mon Sep 17 00:00:00 2001 From: Janne Karhunen Date: Tue, 3 May 2016 02:43:30 -0700 Subject: Allow users to specify the vmdk virtual hardware version. Vmdk images have metadata to indicate the vmware virtual hardware version image was created/tested to run with. Allow users to specify that version via new 'hwversion' option. [ kwolf: Adjust qemu-iotests common.filter ] Signed-off-by: Janne Karhunen Reviewed-by: Fam Zheng Signed-off-by: Kevin Wolf --- block/vmdk.c | 27 +++++++++++++++++++++++---- include/block/block_int.h | 2 +- qemu-doc.texi | 3 +++ tests/qemu-iotests/common.filter | 2 ++ 4 files changed, 29 insertions(+), 5 deletions(-) diff --git a/block/vmdk.c b/block/vmdk.c index f243527d44..61e20afecb 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -1909,8 +1909,8 @@ static int vmdk_create(const char *filename, QemuOpts *opts, Error **errp) int64_t total_size = 0, filesize; char *adapter_type = NULL; char *backing_file = NULL; + char *hw_version = NULL; char *fmt = NULL; - int flags = 0; int ret = 0; bool flat, split, compress; GString *ext_desc_lines; @@ -1941,7 +1941,7 @@ static int vmdk_create(const char *filename, QemuOpts *opts, Error **errp) "# The Disk Data Base\n" "#DDB\n" "\n" - "ddb.virtualHWVersion = \"%d\"\n" + "ddb.virtualHWVersion = \"%s\"\n" "ddb.geometry.cylinders = \"%" PRId64 "\"\n" "ddb.geometry.heads = \"%" PRIu32 "\"\n" "ddb.geometry.sectors = \"63\"\n" @@ -1958,8 +1958,20 @@ static int vmdk_create(const char *filename, QemuOpts *opts, Error **errp) BDRV_SECTOR_SIZE); adapter_type = qemu_opt_get_del(opts, BLOCK_OPT_ADAPTER_TYPE); backing_file = qemu_opt_get_del(opts, BLOCK_OPT_BACKING_FILE); + hw_version = qemu_opt_get_del(opts, BLOCK_OPT_HWVERSION); if (qemu_opt_get_bool_del(opts, BLOCK_OPT_COMPAT6, false)) { - flags |= BLOCK_FLAG_COMPAT6; + if (strcmp(hw_version, "undefined")) { + error_setg(errp, + "compat6 cannot be enabled with hwversion set"); + ret = -EINVAL; + goto exit; + } + g_free(hw_version); + hw_version = g_strdup("6"); + } + if (strcmp(hw_version, "undefined") == 0) { + g_free(hw_version); + hw_version = g_strdup("4"); } fmt = qemu_opt_get_del(opts, BLOCK_OPT_SUBFMT); if (qemu_opt_get_bool_del(opts, BLOCK_OPT_ZEROED_GRAIN, false)) { @@ -2081,7 +2093,7 @@ static int vmdk_create(const char *filename, QemuOpts *opts, Error **errp) fmt, parent_desc_line, ext_desc_lines->str, - (flags & BLOCK_FLAG_COMPAT6 ? 6 : 4), + hw_version, total_size / (int64_t)(63 * number_heads * BDRV_SECTOR_SIZE), number_heads, @@ -2127,6 +2139,7 @@ exit: } g_free(adapter_type); g_free(backing_file); + g_free(hw_version); g_free(fmt); g_free(desc); g_free(path); @@ -2377,6 +2390,12 @@ static QemuOptsList vmdk_create_opts = { .help = "VMDK version 6 image", .def_value_str = "off" }, + { + .name = BLOCK_OPT_HWVERSION, + .type = QEMU_OPT_STRING, + .help = "VMDK hardware version", + .def_value_str = "undefined" + }, { .name = BLOCK_OPT_SUBFMT, .type = QEMU_OPT_STRING, diff --git a/include/block/block_int.h b/include/block/block_int.h index c512074ce9..6fbe648231 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -38,12 +38,12 @@ #include "qemu/throttle.h" #define BLOCK_FLAG_ENCRYPT 1 -#define BLOCK_FLAG_COMPAT6 4 #define BLOCK_FLAG_LAZY_REFCOUNTS 8 #define BLOCK_OPT_SIZE "size" #define BLOCK_OPT_ENCRYPT "encryption" #define BLOCK_OPT_COMPAT6 "compat6" +#define BLOCK_OPT_HWVERSION "hwversion" #define BLOCK_OPT_BACKING_FILE "backing_file" #define BLOCK_OPT_BACKING_FMT "backing_fmt" #define BLOCK_OPT_CLUSTER_SIZE "cluster_size" diff --git a/qemu-doc.texi b/qemu-doc.texi index 79141d3582..f37fd3130e 100644 --- a/qemu-doc.texi +++ b/qemu-doc.texi @@ -693,6 +693,9 @@ Supported options: File name of a base image (see @option{create} subcommand). @item compat6 Create a VMDK version 6 image (instead of version 4) +@item hwversion +Specify vmdk virtual hardware version. Compat6 flag cannot be enabled +if hwversion is specified. @item subformat Specifies which VMDK subformat to use. Valid options are @code{monolithicSparse} (default), diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter index 8a6e1b57c1..72f77fa67c 100644 --- a/tests/qemu-iotests/common.filter +++ b/tests/qemu-iotests/common.filter @@ -92,6 +92,7 @@ _filter_img_create() -e "s# zeroed_grain=\\(on\\|off\\)##g" \ -e "s# subformat='[^']*'##g" \ -e "s# adapter_type='[^']*'##g" \ + -e "s# hwversion=[^ ]*##g" \ -e "s# lazy_refcounts=\\(on\\|off\\)##g" \ -e "s# block_size=[0-9]\\+##g" \ -e "s# block_state_zero=\\(on\\|off\\)##g" \ @@ -115,6 +116,7 @@ _filter_img_info() -e "/zeroed_grain: \\(on\\|off\\)/d" \ -e "/subformat: '[^']*'/d" \ -e "/adapter_type: '[^']*'/d" \ + -e "/hwversion: '[^']*'/d" \ -e "/lazy_refcounts: \\(on\\|off\\)/d" \ -e "/block_size: [0-9]\\+/d" \ -e "/block_state_zero: \\(on\\|off\\)/d" \ -- cgit v1.2.3 From 0e01b76e7cc43068f6b8cc05297f61539ccd5279 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Mon, 9 May 2016 12:03:04 +0200 Subject: qemu-io: Fix memory leak in 'aio_write -z' Signed-off-by: Kevin Wolf Reviewed-by: Eric Blake --- qemu-io-cmds.c | 1 + 1 file changed, 1 insertion(+) diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c index e34f777118..41580b5247 100644 --- a/qemu-io-cmds.c +++ b/qemu-io-cmds.c @@ -1699,6 +1699,7 @@ static int aio_write_f(BlockBackend *blk, int argc, char **argv) int64_t count = cvtnum(argv[optind]); if (count < 0) { print_cvtnum_err(count, argv[optind]); + g_free(ctx); return 0; } -- cgit v1.2.3 From 8341f00dc207b80a1b2e7c7784890c9b0446d062 Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Fri, 6 May 2016 10:26:27 -0600 Subject: block: Allow BDRV_REQ_FUA through blk_pwrite() We have several block drivers that understand BDRV_REQ_FUA, and emulate it in the block layer for the rest by a full flush. But without a way to actually request BDRV_REQ_FUA during a pass-through blk_pwrite(), FUA-aware block drivers like NBD are forced to repeat the emulation logic of a full flush regardless of whether the backend they are writing to could do it more efficiently. This patch just wires up a flags argument; followup patches will actually make use of it in the NBD driver and in qemu-io. Signed-off-by: Eric Blake Acked-by: Denis V. Lunev Signed-off-by: Kevin Wolf --- block/block-backend.c | 6 ++++-- block/crypto.c | 2 +- block/parallels.c | 2 +- block/qcow.c | 8 ++++---- block/qcow2.c | 4 ++-- block/qed.c | 6 +++--- block/sheepdog.c | 2 +- block/vdi.c | 4 ++-- block/vhdx.c | 5 +++-- block/vmdk.c | 10 +++++----- block/vpc.c | 10 +++++----- hw/nvram/spapr_nvram.c | 4 ++-- include/sysemu/block-backend.h | 3 ++- nbd/server.c | 2 +- qemu-io-cmds.c | 2 +- 15 files changed, 37 insertions(+), 33 deletions(-) diff --git a/block/block-backend.c b/block/block-backend.c index a7623e841f..96c1d7c445 100644 --- a/block/block-backend.c +++ b/block/block-backend.c @@ -953,9 +953,11 @@ int blk_pread(BlockBackend *blk, int64_t offset, void *buf, int count) return count; } -int blk_pwrite(BlockBackend *blk, int64_t offset, const void *buf, int count) +int blk_pwrite(BlockBackend *blk, int64_t offset, const void *buf, int count, + BdrvRequestFlags flags) { - int ret = blk_prw(blk, offset, (void*) buf, count, blk_write_entry, 0); + int ret = blk_prw(blk, offset, (void *) buf, count, blk_write_entry, + flags); if (ret < 0) { return ret; } diff --git a/block/crypto.c b/block/crypto.c index 1903e84fbd..32ba17ce00 100644 --- a/block/crypto.c +++ b/block/crypto.c @@ -91,7 +91,7 @@ static ssize_t block_crypto_write_func(QCryptoBlock *block, struct BlockCryptoCreateData *data = opaque; ssize_t ret; - ret = blk_pwrite(data->blk, offset, buf, buflen); + ret = blk_pwrite(data->blk, offset, buf, buflen, 0); if (ret < 0) { error_setg_errno(errp, -ret, "Could not write encryption header"); return ret; diff --git a/block/parallels.c b/block/parallels.c index 324ed43ac4..2d8bc87e47 100644 --- a/block/parallels.c +++ b/block/parallels.c @@ -512,7 +512,7 @@ static int parallels_create(const char *filename, QemuOpts *opts, Error **errp) memset(tmp, 0, sizeof(tmp)); memcpy(tmp, &header, sizeof(header)); - ret = blk_pwrite(file, 0, tmp, BDRV_SECTOR_SIZE); + ret = blk_pwrite(file, 0, tmp, BDRV_SECTOR_SIZE, 0); if (ret < 0) { goto exit; } diff --git a/block/qcow.c b/block/qcow.c index 60ddb12eca..d6dc1b05b3 100644 --- a/block/qcow.c +++ b/block/qcow.c @@ -853,14 +853,14 @@ static int qcow_create(const char *filename, QemuOpts *opts, Error **errp) } /* write all the data */ - ret = blk_pwrite(qcow_blk, 0, &header, sizeof(header)); + ret = blk_pwrite(qcow_blk, 0, &header, sizeof(header), 0); if (ret != sizeof(header)) { goto exit; } if (backing_file) { ret = blk_pwrite(qcow_blk, sizeof(header), - backing_file, backing_filename_len); + backing_file, backing_filename_len, 0); if (ret != backing_filename_len) { goto exit; } @@ -869,8 +869,8 @@ static int qcow_create(const char *filename, QemuOpts *opts, Error **errp) tmp = g_malloc0(BDRV_SECTOR_SIZE); for (i = 0; i < ((sizeof(uint64_t)*l1_size + BDRV_SECTOR_SIZE - 1)/ BDRV_SECTOR_SIZE); i++) { - ret = blk_pwrite(qcow_blk, header_size + - BDRV_SECTOR_SIZE*i, tmp, BDRV_SECTOR_SIZE); + ret = blk_pwrite(qcow_blk, header_size + BDRV_SECTOR_SIZE * i, + tmp, BDRV_SECTOR_SIZE, 0); if (ret != BDRV_SECTOR_SIZE) { g_free(tmp); goto exit; diff --git a/block/qcow2.c b/block/qcow2.c index 470734be9f..3090538897 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -2207,7 +2207,7 @@ static int qcow2_create2(const char *filename, int64_t total_size, cpu_to_be64(QCOW2_COMPAT_LAZY_REFCOUNTS); } - ret = blk_pwrite(blk, 0, header, cluster_size); + ret = blk_pwrite(blk, 0, header, cluster_size, 0); g_free(header); if (ret < 0) { error_setg_errno(errp, -ret, "Could not write qcow2 header"); @@ -2217,7 +2217,7 @@ static int qcow2_create2(const char *filename, int64_t total_size, /* Write a refcount table with one refcount block */ refcount_table = g_malloc0(2 * cluster_size); refcount_table[0] = cpu_to_be64(2 * cluster_size); - ret = blk_pwrite(blk, cluster_size, refcount_table, 2 * cluster_size); + ret = blk_pwrite(blk, cluster_size, refcount_table, 2 * cluster_size, 0); g_free(refcount_table); if (ret < 0) { diff --git a/block/qed.c b/block/qed.c index 0af52741df..6cfd4c1c11 100644 --- a/block/qed.c +++ b/block/qed.c @@ -601,18 +601,18 @@ static int qed_create(const char *filename, uint32_t cluster_size, } qed_header_cpu_to_le(&header, &le_header); - ret = blk_pwrite(blk, 0, &le_header, sizeof(le_header)); + ret = blk_pwrite(blk, 0, &le_header, sizeof(le_header), 0); if (ret < 0) { goto out; } ret = blk_pwrite(blk, sizeof(le_header), backing_file, - header.backing_filename_size); + header.backing_filename_size, 0); if (ret < 0) { goto out; } l1_table = g_malloc0(l1_size); - ret = blk_pwrite(blk, header.l1_table_offset, l1_table, l1_size); + ret = blk_pwrite(blk, header.l1_table_offset, l1_table, l1_size, 0); if (ret < 0) { goto out; } diff --git a/block/sheepdog.c b/block/sheepdog.c index 90236865e9..23fbace1f9 100644 --- a/block/sheepdog.c +++ b/block/sheepdog.c @@ -1681,7 +1681,7 @@ static int sd_prealloc(const char *filename, Error **errp) if (ret < 0) { goto out; } - ret = blk_pwrite(blk, idx * buf_size, buf, buf_size); + ret = blk_pwrite(blk, idx * buf_size, buf, buf_size, 0); if (ret < 0) { goto out; } diff --git a/block/vdi.c b/block/vdi.c index e5fe4e8358..54e11447c3 100644 --- a/block/vdi.c +++ b/block/vdi.c @@ -827,7 +827,7 @@ static int vdi_create(const char *filename, QemuOpts *opts, Error **errp) vdi_header_print(&header); #endif vdi_header_to_le(&header); - ret = blk_pwrite(blk, offset, &header, sizeof(header)); + ret = blk_pwrite(blk, offset, &header, sizeof(header), 0); if (ret < 0) { error_setg(errp, "Error writing header to %s", filename); goto exit; @@ -848,7 +848,7 @@ static int vdi_create(const char *filename, QemuOpts *opts, Error **errp) bmap[i] = VDI_UNALLOCATED; } } - ret = blk_pwrite(blk, offset, bmap, bmap_size); + ret = blk_pwrite(blk, offset, bmap, bmap_size, 0); if (ret < 0) { error_setg(errp, "Error writing bmap to %s", filename); goto exit; diff --git a/block/vhdx.c b/block/vhdx.c index 2b7b332404..ec778fe2a7 100644 --- a/block/vhdx.c +++ b/block/vhdx.c @@ -1856,13 +1856,14 @@ static int vhdx_create(const char *filename, QemuOpts *opts, Error **errp) creator = g_utf8_to_utf16("QEMU v" QEMU_VERSION, -1, NULL, &creator_items, NULL); signature = cpu_to_le64(VHDX_FILE_SIGNATURE); - ret = blk_pwrite(blk, VHDX_FILE_ID_OFFSET, &signature, sizeof(signature)); + ret = blk_pwrite(blk, VHDX_FILE_ID_OFFSET, &signature, sizeof(signature), + 0); if (ret < 0) { goto delete_and_exit; } if (creator) { ret = blk_pwrite(blk, VHDX_FILE_ID_OFFSET + sizeof(signature), - creator, creator_items * sizeof(gunichar2)); + creator, creator_items * sizeof(gunichar2), 0); if (ret < 0) { goto delete_and_exit; } diff --git a/block/vmdk.c b/block/vmdk.c index 61e20afecb..e6c97c25a6 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -1808,12 +1808,12 @@ static int vmdk_create_extent(const char *filename, int64_t filesize, header.check_bytes[3] = 0xa; /* write all the data */ - ret = blk_pwrite(blk, 0, &magic, sizeof(magic)); + ret = blk_pwrite(blk, 0, &magic, sizeof(magic), 0); if (ret < 0) { error_setg(errp, QERR_IO_ERROR); goto exit; } - ret = blk_pwrite(blk, sizeof(magic), &header, sizeof(header)); + ret = blk_pwrite(blk, sizeof(magic), &header, sizeof(header), 0); if (ret < 0) { error_setg(errp, QERR_IO_ERROR); goto exit; @@ -1833,7 +1833,7 @@ static int vmdk_create_extent(const char *filename, int64_t filesize, gd_buf[i] = cpu_to_le32(tmp); } ret = blk_pwrite(blk, le64_to_cpu(header.rgd_offset) * BDRV_SECTOR_SIZE, - gd_buf, gd_buf_size); + gd_buf, gd_buf_size, 0); if (ret < 0) { error_setg(errp, QERR_IO_ERROR); goto exit; @@ -1845,7 +1845,7 @@ static int vmdk_create_extent(const char *filename, int64_t filesize, gd_buf[i] = cpu_to_le32(tmp); } ret = blk_pwrite(blk, le64_to_cpu(header.gd_offset) * BDRV_SECTOR_SIZE, - gd_buf, gd_buf_size); + gd_buf, gd_buf_size, 0); if (ret < 0) { error_setg(errp, QERR_IO_ERROR); goto exit; @@ -2120,7 +2120,7 @@ static int vmdk_create(const char *filename, QemuOpts *opts, Error **errp) blk_set_allow_write_beyond_eof(new_blk, true); - ret = blk_pwrite(new_blk, desc_offset, desc, desc_len); + ret = blk_pwrite(new_blk, desc_offset, desc, desc_len, 0); if (ret < 0) { error_setg_errno(errp, -ret, "Could not write description"); goto exit; diff --git a/block/vpc.c b/block/vpc.c index 2da4126ce6..0379813e2f 100644 --- a/block/vpc.c +++ b/block/vpc.c @@ -788,13 +788,13 @@ static int create_dynamic_disk(BlockBackend *blk, uint8_t *buf, block_size = 0x200000; num_bat_entries = (total_sectors + block_size / 512) / (block_size / 512); - ret = blk_pwrite(blk, offset, buf, HEADER_SIZE); + ret = blk_pwrite(blk, offset, buf, HEADER_SIZE, 0); if (ret < 0) { goto fail; } offset = 1536 + ((num_bat_entries * 4 + 511) & ~511); - ret = blk_pwrite(blk, offset, buf, HEADER_SIZE); + ret = blk_pwrite(blk, offset, buf, HEADER_SIZE, 0); if (ret < 0) { goto fail; } @@ -804,7 +804,7 @@ static int create_dynamic_disk(BlockBackend *blk, uint8_t *buf, memset(buf, 0xFF, 512); for (i = 0; i < (num_bat_entries * 4 + 511) / 512; i++) { - ret = blk_pwrite(blk, offset, buf, 512); + ret = blk_pwrite(blk, offset, buf, 512, 0); if (ret < 0) { goto fail; } @@ -831,7 +831,7 @@ static int create_dynamic_disk(BlockBackend *blk, uint8_t *buf, /* Write the header */ offset = 512; - ret = blk_pwrite(blk, offset, buf, 1024); + ret = blk_pwrite(blk, offset, buf, 1024, 0); if (ret < 0) { goto fail; } @@ -853,7 +853,7 @@ static int create_fixed_disk(BlockBackend *blk, uint8_t *buf, return ret; } - ret = blk_pwrite(blk, total_size - HEADER_SIZE, buf, HEADER_SIZE); + ret = blk_pwrite(blk, total_size - HEADER_SIZE, buf, HEADER_SIZE, 0); if (ret < 0) { return ret; } diff --git a/hw/nvram/spapr_nvram.c b/hw/nvram/spapr_nvram.c index 802636ef35..019f25dc58 100644 --- a/hw/nvram/spapr_nvram.c +++ b/hw/nvram/spapr_nvram.c @@ -124,7 +124,7 @@ static void rtas_nvram_store(PowerPCCPU *cpu, sPAPRMachineState *spapr, alen = len; if (nvram->blk) { - alen = blk_pwrite(nvram->blk, offset, membuf, len); + alen = blk_pwrite(nvram->blk, offset, membuf, len, 0); } assert(nvram->buf); @@ -190,7 +190,7 @@ static int spapr_nvram_post_load(void *opaque, int version_id) sPAPRNVRAM *nvram = VIO_SPAPR_NVRAM(opaque); if (nvram->blk) { - int alen = blk_pwrite(nvram->blk, 0, nvram->buf, nvram->size); + int alen = blk_pwrite(nvram->blk, 0, nvram->buf, nvram->size, 0); if (alen < 0) { return alen; diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h index c62b6fe96d..6991b2610c 100644 --- a/include/sysemu/block-backend.h +++ b/include/sysemu/block-backend.h @@ -102,7 +102,8 @@ BlockAIOCB *blk_aio_write_zeroes(BlockBackend *blk, int64_t sector_num, int nb_sectors, BdrvRequestFlags flags, BlockCompletionFunc *cb, void *opaque); int blk_pread(BlockBackend *blk, int64_t offset, void *buf, int count); -int blk_pwrite(BlockBackend *blk, int64_t offset, const void *buf, int count); +int blk_pwrite(BlockBackend *blk, int64_t offset, const void *buf, int count, + BdrvRequestFlags flags); int64_t blk_getlength(BlockBackend *blk); void blk_get_geometry(BlockBackend *blk, uint64_t *nb_sectors_ptr); int64_t blk_nb_sectors(BlockBackend *blk); diff --git a/nbd/server.c b/nbd/server.c index 2184c64fef..fa862cd622 100644 --- a/nbd/server.c +++ b/nbd/server.c @@ -1115,7 +1115,7 @@ static void nbd_trip(void *opaque) TRACE("Writing to device"); ret = blk_pwrite(exp->blk, request.from + exp->dev_offset, - req->data, request.len); + req->data, request.len, 0); if (ret < 0) { LOG("writing to file failed"); reply.error = -ret; diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c index 41580b5247..ee0c5d7a55 100644 --- a/qemu-io-cmds.c +++ b/qemu-io-cmds.c @@ -474,7 +474,7 @@ static int do_pwrite(BlockBackend *blk, char *buf, int64_t offset, return -ERANGE; } - *total = blk_pwrite(blk, offset, (uint8_t *)buf, count); + *total = blk_pwrite(blk, offset, (uint8_t *)buf, count, 0); if (*total < 0) { return *total; } -- cgit v1.2.3 From b7d17f9fa4df83ed060168c450889d73c441c8f6 Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Fri, 6 May 2016 10:26:28 -0600 Subject: block: Switch blk_read_unthrottled() to byte interface Sector-based blk_read() should die; convert the one-off variant blk_read_unthrottled(). Signed-off-by: Eric Blake Signed-off-by: Kevin Wolf --- block/block-backend.c | 8 ++++---- hw/block/hd-geometry.c | 2 +- include/sysemu/block-backend.h | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/block/block-backend.c b/block/block-backend.c index 96c1d7c445..e5a8a0734f 100644 --- a/block/block-backend.c +++ b/block/block-backend.c @@ -790,19 +790,19 @@ int blk_read(BlockBackend *blk, int64_t sector_num, uint8_t *buf, return blk_rw(blk, sector_num, buf, nb_sectors, blk_read_entry, 0); } -int blk_read_unthrottled(BlockBackend *blk, int64_t sector_num, uint8_t *buf, - int nb_sectors) +int blk_pread_unthrottled(BlockBackend *blk, int64_t offset, uint8_t *buf, + int count) { BlockDriverState *bs = blk_bs(blk); int ret; - ret = blk_check_request(blk, sector_num, nb_sectors); + ret = blk_check_byte_request(blk, offset, count); if (ret < 0) { return ret; } bdrv_no_throttling_begin(bs); - ret = blk_read(blk, sector_num, buf, nb_sectors); + ret = blk_pread(blk, offset, buf, count); bdrv_no_throttling_end(bs); return ret; } diff --git a/hw/block/hd-geometry.c b/hw/block/hd-geometry.c index 6d02192dbb..d388f13e9d 100644 --- a/hw/block/hd-geometry.c +++ b/hw/block/hd-geometry.c @@ -66,7 +66,7 @@ static int guess_disk_lchs(BlockBackend *blk, * but also in async I/O mode. So the I/O throttling function has to * be disabled temporarily here, not permanently. */ - if (blk_read_unthrottled(blk, 0, buf, 1) < 0) { + if (blk_pread_unthrottled(blk, 0, buf, BDRV_SECTOR_SIZE) < 0) { return -1; } /* test msdos magic */ diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h index 6991b2610c..662a106bd2 100644 --- a/include/sysemu/block-backend.h +++ b/include/sysemu/block-backend.h @@ -92,8 +92,8 @@ void *blk_get_attached_dev(BlockBackend *blk); void blk_set_dev_ops(BlockBackend *blk, const BlockDevOps *ops, void *opaque); int blk_read(BlockBackend *blk, int64_t sector_num, uint8_t *buf, int nb_sectors); -int blk_read_unthrottled(BlockBackend *blk, int64_t sector_num, uint8_t *buf, - int nb_sectors); +int blk_pread_unthrottled(BlockBackend *blk, int64_t offset, uint8_t *buf, + int count); int blk_write(BlockBackend *blk, int64_t sector_num, const uint8_t *buf, int nb_sectors); int blk_write_zeroes(BlockBackend *blk, int64_t sector_num, -- cgit v1.2.3 From 983a1600504b1b78242b9da29b0d7018a6eb231d Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Fri, 6 May 2016 10:26:29 -0600 Subject: block: Switch blk_*write_zeroes() to byte interface Sector-based blk_write() should die; convert the one-off variant blk_write_zeroes() to use an offset/count interface instead. Likewise for blk_co_write_zeroes() and blk_aio_write_zeroes(). Signed-off-by: Eric Blake Signed-off-by: Kevin Wolf --- block/block-backend.c | 33 +++++++++++---------------------- block/parallels.c | 3 ++- hw/scsi/scsi-disk.c | 4 ++-- include/sysemu/block-backend.h | 12 ++++++------ qemu-img.c | 3 ++- qemu-io-cmds.c | 6 ++---- 6 files changed, 25 insertions(+), 36 deletions(-) diff --git a/block/block-backend.c b/block/block-backend.c index e5a8a0734f..f8f88a6d5f 100644 --- a/block/block-backend.c +++ b/block/block-backend.c @@ -814,11 +814,11 @@ int blk_write(BlockBackend *blk, int64_t sector_num, const uint8_t *buf, blk_write_entry, 0); } -int blk_write_zeroes(BlockBackend *blk, int64_t sector_num, - int nb_sectors, BdrvRequestFlags flags) +int blk_write_zeroes(BlockBackend *blk, int64_t offset, + int count, BdrvRequestFlags flags) { - return blk_rw(blk, sector_num, NULL, nb_sectors, blk_write_entry, - flags | BDRV_REQ_ZERO_WRITE); + return blk_prw(blk, offset, NULL, count, blk_write_entry, + flags | BDRV_REQ_ZERO_WRITE); } static void error_callback_bh(void *opaque) @@ -930,18 +930,12 @@ static void blk_aio_write_entry(void *opaque) blk_aio_complete(acb); } -BlockAIOCB *blk_aio_write_zeroes(BlockBackend *blk, int64_t sector_num, - int nb_sectors, BdrvRequestFlags flags, +BlockAIOCB *blk_aio_write_zeroes(BlockBackend *blk, int64_t offset, + int count, BdrvRequestFlags flags, BlockCompletionFunc *cb, void *opaque) { - if (nb_sectors < 0 || nb_sectors > BDRV_REQUEST_MAX_SECTORS) { - return blk_abort_aio_request(blk, cb, opaque, -EINVAL); - } - - return blk_aio_prwv(blk, sector_num << BDRV_SECTOR_BITS, - nb_sectors << BDRV_SECTOR_BITS, NULL, - blk_aio_write_entry, flags | BDRV_REQ_ZERO_WRITE, - cb, opaque); + return blk_aio_prwv(blk, offset, count, NULL, blk_aio_write_entry, + flags | BDRV_REQ_ZERO_WRITE, cb, opaque); } int blk_pread(BlockBackend *blk, int64_t offset, void *buf, int count) @@ -1444,15 +1438,10 @@ void *blk_aio_get(const AIOCBInfo *aiocb_info, BlockBackend *blk, return qemu_aio_get(aiocb_info, blk_bs(blk), cb, opaque); } -int coroutine_fn blk_co_write_zeroes(BlockBackend *blk, int64_t sector_num, - int nb_sectors, BdrvRequestFlags flags) +int coroutine_fn blk_co_write_zeroes(BlockBackend *blk, int64_t offset, + int count, BdrvRequestFlags flags) { - if (nb_sectors < 0 || nb_sectors > BDRV_REQUEST_MAX_SECTORS) { - return -EINVAL; - } - - return blk_co_pwritev(blk, sector_num << BDRV_SECTOR_BITS, - nb_sectors << BDRV_SECTOR_BITS, NULL, + return blk_co_pwritev(blk, offset, count, NULL, flags | BDRV_REQ_ZERO_WRITE); } diff --git a/block/parallels.c b/block/parallels.c index 2d8bc87e47..cddbfc4012 100644 --- a/block/parallels.c +++ b/block/parallels.c @@ -516,7 +516,8 @@ static int parallels_create(const char *filename, QemuOpts *opts, Error **errp) if (ret < 0) { goto exit; } - ret = blk_write_zeroes(file, 1, bat_sectors - 1, 0); + ret = blk_write_zeroes(file, BDRV_SECTOR_SIZE, + (bat_sectors - 1) << BDRV_SECTOR_BITS, 0); if (ret < 0) { goto exit; } diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c index c3ce54a203..13353924d7 100644 --- a/hw/scsi/scsi-disk.c +++ b/hw/scsi/scsi-disk.c @@ -1781,8 +1781,8 @@ static void scsi_disk_emulate_write_same(SCSIDiskReq *r, uint8_t *inbuf) nb_sectors * s->qdev.blocksize, BLOCK_ACCT_WRITE); r->req.aiocb = blk_aio_write_zeroes(s->qdev.conf.blk, - r->req.cmd.lba * (s->qdev.blocksize / 512), - nb_sectors * (s->qdev.blocksize / 512), + r->req.cmd.lba * s->qdev.blocksize, + nb_sectors * s->qdev.blocksize, flags, scsi_aio_complete, r); return; } diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h index 662a106bd2..851376b5b0 100644 --- a/include/sysemu/block-backend.h +++ b/include/sysemu/block-backend.h @@ -96,10 +96,10 @@ int blk_pread_unthrottled(BlockBackend *blk, int64_t offset, uint8_t *buf, int count); int blk_write(BlockBackend *blk, int64_t sector_num, const uint8_t *buf, int nb_sectors); -int blk_write_zeroes(BlockBackend *blk, int64_t sector_num, - int nb_sectors, BdrvRequestFlags flags); -BlockAIOCB *blk_aio_write_zeroes(BlockBackend *blk, int64_t sector_num, - int nb_sectors, BdrvRequestFlags flags, +int blk_write_zeroes(BlockBackend *blk, int64_t offset, + int count, BdrvRequestFlags flags); +BlockAIOCB *blk_aio_write_zeroes(BlockBackend *blk, int64_t offset, + int count, BdrvRequestFlags flags, BlockCompletionFunc *cb, void *opaque); int blk_pread(BlockBackend *blk, int64_t offset, void *buf, int count); int blk_pwrite(BlockBackend *blk, int64_t offset, const void *buf, int count, @@ -179,8 +179,8 @@ int blk_get_open_flags_from_root_state(BlockBackend *blk); void *blk_aio_get(const AIOCBInfo *aiocb_info, BlockBackend *blk, BlockCompletionFunc *cb, void *opaque); -int coroutine_fn blk_co_write_zeroes(BlockBackend *blk, int64_t sector_num, - int nb_sectors, BdrvRequestFlags flags); +int coroutine_fn blk_co_write_zeroes(BlockBackend *blk, int64_t offset, + int count, BdrvRequestFlags flags); int blk_write_compressed(BlockBackend *blk, int64_t sector_num, const uint8_t *buf, int nb_sectors); int blk_truncate(BlockBackend *blk, int64_t offset); diff --git a/qemu-img.c b/qemu-img.c index 46f2a6def4..76430a83cd 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -1589,7 +1589,8 @@ static int convert_write(ImgConvertState *s, int64_t sector_num, int nb_sectors, if (s->has_zero_init) { break; } - ret = blk_write_zeroes(s->target, sector_num, n, 0); + ret = blk_write_zeroes(s->target, sector_num << BDRV_SECTOR_BITS, + n << BDRV_SECTOR_BITS, 0); if (ret < 0) { return ret; } diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c index ee0c5d7a55..3040a4b12e 100644 --- a/qemu-io-cmds.c +++ b/qemu-io-cmds.c @@ -494,8 +494,7 @@ static void coroutine_fn co_write_zeroes_entry(void *opaque) { CoWriteZeroes *data = opaque; - data->ret = blk_co_write_zeroes(data->blk, data->offset / BDRV_SECTOR_SIZE, - data->count / BDRV_SECTOR_SIZE, 0); + data->ret = blk_co_write_zeroes(data->blk, data->offset, data->count, 0); data->done = true; if (data->ret < 0) { *data->total = data->ret; @@ -1704,8 +1703,7 @@ static int aio_write_f(BlockBackend *blk, int argc, char **argv) } ctx->qiov.size = count; - blk_aio_write_zeroes(blk, ctx->offset >> 9, count >> 9, 0, - aio_write_done, ctx); + blk_aio_write_zeroes(blk, ctx->offset, count, 0, aio_write_done, ctx); } else { nr_iov = argc - optind; ctx->buf = create_iovec(blk, &ctx->qiov, &argv[optind], nr_iov, -- cgit v1.2.3 From 60cb2fa7eb5431d8996589ebc5dde865c602d54b Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Fri, 6 May 2016 10:26:30 -0600 Subject: block: Introduce byte-based aio read/write blk_aio_readv() and blk_aio_writev() are annoying in that they can't access sub-sector granularity, and cannot pass flags. Also, they require the caller to pass redundant information about the size of the I/O (qiov->size in bytes must match nb_sectors in sectors). Add new blk_aio_preadv() and blk_aio_pwritev() functions to fix the flaws. The next few patches will upgrade callers, then finally delete the old interfaces. Signed-off-by: Eric Blake Signed-off-by: Kevin Wolf --- block/block-backend.c | 18 +++++++++++++++++- include/sysemu/block-backend.h | 8 +++++++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/block/block-backend.c b/block/block-backend.c index f8f88a6d5f..6ac76d0176 100644 --- a/block/block-backend.c +++ b/block/block-backend.c @@ -1,7 +1,7 @@ /* * QEMU Block backends * - * Copyright (C) 2014 Red Hat, Inc. + * Copyright (C) 2014-2016 Red Hat, Inc. * * Authors: * Markus Armbruster , @@ -998,6 +998,14 @@ BlockAIOCB *blk_aio_readv(BlockBackend *blk, int64_t sector_num, blk_aio_read_entry, 0, cb, opaque); } +BlockAIOCB *blk_aio_preadv(BlockBackend *blk, int64_t offset, + QEMUIOVector *qiov, BdrvRequestFlags flags, + BlockCompletionFunc *cb, void *opaque) +{ + return blk_aio_prwv(blk, offset, qiov->size, qiov, + blk_aio_read_entry, flags, cb, opaque); +} + BlockAIOCB *blk_aio_writev(BlockBackend *blk, int64_t sector_num, QEMUIOVector *iov, int nb_sectors, BlockCompletionFunc *cb, void *opaque) @@ -1011,6 +1019,14 @@ BlockAIOCB *blk_aio_writev(BlockBackend *blk, int64_t sector_num, blk_aio_write_entry, 0, cb, opaque); } +BlockAIOCB *blk_aio_pwritev(BlockBackend *blk, int64_t offset, + QEMUIOVector *qiov, BdrvRequestFlags flags, + BlockCompletionFunc *cb, void *opaque) +{ + return blk_aio_prwv(blk, offset, qiov->size, qiov, + blk_aio_write_entry, flags, cb, opaque); +} + BlockAIOCB *blk_aio_flush(BlockBackend *blk, BlockCompletionFunc *cb, void *opaque) { diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h index 851376b5b0..73df1a677c 100644 --- a/include/sysemu/block-backend.h +++ b/include/sysemu/block-backend.h @@ -1,7 +1,7 @@ /* * QEMU Block backends * - * Copyright (C) 2014 Red Hat, Inc. + * Copyright (C) 2014-2016 Red Hat, Inc. * * Authors: * Markus Armbruster , @@ -110,9 +110,15 @@ int64_t blk_nb_sectors(BlockBackend *blk); BlockAIOCB *blk_aio_readv(BlockBackend *blk, int64_t sector_num, QEMUIOVector *iov, int nb_sectors, BlockCompletionFunc *cb, void *opaque); +BlockAIOCB *blk_aio_preadv(BlockBackend *blk, int64_t offset, + QEMUIOVector *qiov, BdrvRequestFlags flags, + BlockCompletionFunc *cb, void *opaque); BlockAIOCB *blk_aio_writev(BlockBackend *blk, int64_t sector_num, QEMUIOVector *iov, int nb_sectors, BlockCompletionFunc *cb, void *opaque); +BlockAIOCB *blk_aio_pwritev(BlockBackend *blk, int64_t offset, + QEMUIOVector *qiov, BdrvRequestFlags flags, + BlockCompletionFunc *cb, void *opaque); BlockAIOCB *blk_aio_flush(BlockBackend *blk, BlockCompletionFunc *cb, void *opaque); BlockAIOCB *blk_aio_discard(BlockBackend *blk, -- cgit v1.2.3 From d4f510eb3f56d30dd1312fe902138c430db2b361 Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Fri, 6 May 2016 10:26:31 -0600 Subject: ide: Switch to byte-based aio block access Sector-based blk_aio_readv() and blk_aio_writev() should die; switch to byte-based blk_aio_preadv() and blk_aio_pwritev() instead. The patch had to touch multiple files at once, because dma_blk_io() takes pointers to the functions, and ide_issue_trim() piggybacks on the same interface (while ignoring offset under the hood). Signed-off-by: Eric Blake Signed-off-by: Kevin Wolf --- dma-helpers.c | 14 +++++++------- hw/ide/core.c | 10 +++++----- hw/ide/internal.h | 2 +- hw/ide/macio.c | 9 +++------ include/sysemu/dma.h | 4 ++-- 5 files changed, 18 insertions(+), 21 deletions(-) diff --git a/dma-helpers.c b/dma-helpers.c index 4ad0bca67e..a6cc15f534 100644 --- a/dma-helpers.c +++ b/dma-helpers.c @@ -73,7 +73,7 @@ typedef struct { BlockBackend *blk; BlockAIOCB *acb; QEMUSGList *sg; - uint64_t sector_num; + uint64_t offset; DMADirection dir; int sg_cur_index; dma_addr_t sg_cur_byte; @@ -130,7 +130,7 @@ static void dma_blk_cb(void *opaque, int ret) trace_dma_blk_cb(dbs, ret); dbs->acb = NULL; - dbs->sector_num += dbs->iov.size / 512; + dbs->offset += dbs->iov.size; if (dbs->sg_cur_index == dbs->sg->nsg || ret < 0) { dma_complete(dbs, ret); @@ -164,8 +164,8 @@ static void dma_blk_cb(void *opaque, int ret) qemu_iovec_discard_back(&dbs->iov, dbs->iov.size & ~BDRV_SECTOR_MASK); } - dbs->acb = dbs->io_func(dbs->blk, dbs->sector_num, &dbs->iov, - dbs->iov.size / 512, dma_blk_cb, dbs); + dbs->acb = dbs->io_func(dbs->blk, dbs->offset, &dbs->iov, 0, + dma_blk_cb, dbs); assert(dbs->acb); } @@ -203,7 +203,7 @@ BlockAIOCB *dma_blk_io( dbs->acb = NULL; dbs->blk = blk; dbs->sg = sg; - dbs->sector_num = sector_num; + dbs->offset = sector_num << BDRV_SECTOR_BITS; dbs->sg_cur_index = 0; dbs->sg_cur_byte = 0; dbs->dir = dir; @@ -219,7 +219,7 @@ BlockAIOCB *dma_blk_read(BlockBackend *blk, QEMUSGList *sg, uint64_t sector, void (*cb)(void *opaque, int ret), void *opaque) { - return dma_blk_io(blk, sg, sector, blk_aio_readv, cb, opaque, + return dma_blk_io(blk, sg, sector, blk_aio_preadv, cb, opaque, DMA_DIRECTION_FROM_DEVICE); } @@ -227,7 +227,7 @@ BlockAIOCB *dma_blk_write(BlockBackend *blk, QEMUSGList *sg, uint64_t sector, void (*cb)(void *opaque, int ret), void *opaque) { - return dma_blk_io(blk, sg, sector, blk_aio_writev, cb, opaque, + return dma_blk_io(blk, sg, sector, blk_aio_pwritev, cb, opaque, DMA_DIRECTION_TO_DEVICE); } diff --git a/hw/ide/core.c b/hw/ide/core.c index 41e6a2dc45..fe2bfba489 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -442,7 +442,7 @@ static void ide_issue_trim_cb(void *opaque, int ret) } BlockAIOCB *ide_issue_trim(BlockBackend *blk, - int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, + int64_t offset, QEMUIOVector *qiov, BdrvRequestFlags flags, BlockCompletionFunc *cb, void *opaque) { TrimAIOCB *iocb; @@ -616,8 +616,8 @@ BlockAIOCB *ide_buffered_readv(IDEState *s, int64_t sector_num, req->iov.iov_len = iov->size; qemu_iovec_init_external(&req->qiov, &req->iov, 1); - aioreq = blk_aio_readv(s->blk, sector_num, &req->qiov, nb_sectors, - ide_buffered_readv_cb, req); + aioreq = blk_aio_preadv(s->blk, sector_num << BDRV_SECTOR_BITS, + &req->qiov, 0, ide_buffered_readv_cb, req); QLIST_INSERT_HEAD(&s->buffered_requests, req, list); return aioreq; @@ -1006,8 +1006,8 @@ static void ide_sector_write(IDEState *s) block_acct_start(blk_get_stats(s->blk), &s->acct, n * BDRV_SECTOR_SIZE, BLOCK_ACCT_WRITE); - s->pio_aiocb = blk_aio_writev(s->blk, sector_num, &s->qiov, n, - ide_sector_write_cb, s); + s->pio_aiocb = blk_aio_pwritev(s->blk, sector_num << BDRV_SECTOR_BITS, + &s->qiov, 0, ide_sector_write_cb, s); } static void ide_flush_cb(void *opaque, int ret) diff --git a/hw/ide/internal.h b/hw/ide/internal.h index d2c458f579..ceb9e5994a 100644 --- a/hw/ide/internal.h +++ b/hw/ide/internal.h @@ -614,7 +614,7 @@ void ide_transfer_start(IDEState *s, uint8_t *buf, int size, void ide_transfer_stop(IDEState *s); void ide_set_inactive(IDEState *s, bool more); BlockAIOCB *ide_issue_trim(BlockBackend *blk, - int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, + int64_t offset, QEMUIOVector *qiov, BdrvRequestFlags flags, BlockCompletionFunc *cb, void *opaque); BlockAIOCB *ide_buffered_readv(IDEState *s, int64_t sector_num, QEMUIOVector *iov, int nb_sectors, diff --git a/hw/ide/macio.c b/hw/ide/macio.c index ae29b6f326..d7d9c0ff3a 100644 --- a/hw/ide/macio.c +++ b/hw/ide/macio.c @@ -120,8 +120,7 @@ static void pmac_dma_read(BlockBackend *blk, MACIO_DPRINTF("--- Block read transfer - sector_num: %" PRIx64 " " "nsector: %x\n", (offset >> 9), (bytes >> 9)); - s->bus->dma->aiocb = blk_aio_readv(blk, (offset >> 9), &io->iov, - (bytes >> 9), cb, io); + s->bus->dma->aiocb = blk_aio_preadv(blk, offset, &io->iov, 0, cb, io); } static void pmac_dma_write(BlockBackend *blk, @@ -205,8 +204,7 @@ static void pmac_dma_write(BlockBackend *blk, MACIO_DPRINTF("--- Block write transfer - sector_num: %" PRIx64 " " "nsector: %x\n", (offset >> 9), (bytes >> 9)); - s->bus->dma->aiocb = blk_aio_writev(blk, (offset >> 9), &io->iov, - (bytes >> 9), cb, io); + s->bus->dma->aiocb = blk_aio_pwritev(blk, offset, &io->iov, 0, cb, io); } static void pmac_dma_trim(BlockBackend *blk, @@ -232,8 +230,7 @@ static void pmac_dma_trim(BlockBackend *blk, s->io_buffer_index += io->len; io->len = 0; - s->bus->dma->aiocb = ide_issue_trim(blk, (offset >> 9), &io->iov, - (bytes >> 9), cb, io); + s->bus->dma->aiocb = ide_issue_trim(blk, offset, &io->iov, 0, cb, io); } static void pmac_ide_atapi_transfer_cb(void *opaque, int ret) diff --git a/include/sysemu/dma.h b/include/sysemu/dma.h index b0fbb9bb35..0f7cd4d3ce 100644 --- a/include/sysemu/dma.h +++ b/include/sysemu/dma.h @@ -197,8 +197,8 @@ void qemu_sglist_add(QEMUSGList *qsg, dma_addr_t base, dma_addr_t len); void qemu_sglist_destroy(QEMUSGList *qsg); #endif -typedef BlockAIOCB *DMAIOFunc(BlockBackend *blk, int64_t sector_num, - QEMUIOVector *iov, int nb_sectors, +typedef BlockAIOCB *DMAIOFunc(BlockBackend *blk, int64_t offset, + QEMUIOVector *iov, BdrvRequestFlags flags, BlockCompletionFunc *cb, void *opaque); BlockAIOCB *dma_blk_io(BlockBackend *blk, -- cgit v1.2.3 From 03c90063ccf5fd18b01448a8b23923769ab2ee21 Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Fri, 6 May 2016 10:26:32 -0600 Subject: scsi-disk: Switch to byte-based aio block access Sector-based blk_aio_readv() and blk_aio_writev() should die; switch to byte-based blk_aio_preadv() and blk_aio_pwritev() instead. As part of the cleanup, scsi_init_iovec() no longer needs to return a value, and reword a comment. [ kwolf: Fix read accounting change ] Signed-off-by: Eric Blake Signed-off-by: Kevin Wolf --- hw/scsi/scsi-disk.c | 41 ++++++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c index 13353924d7..ce89c98b4e 100644 --- a/hw/scsi/scsi-disk.c +++ b/hw/scsi/scsi-disk.c @@ -108,7 +108,7 @@ static void scsi_check_condition(SCSIDiskReq *r, SCSISense sense) scsi_req_complete(&r->req, CHECK_CONDITION); } -static uint32_t scsi_init_iovec(SCSIDiskReq *r, size_t size) +static void scsi_init_iovec(SCSIDiskReq *r, size_t size) { SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev); @@ -118,7 +118,6 @@ static uint32_t scsi_init_iovec(SCSIDiskReq *r, size_t size) } r->iov.iov_len = MIN(r->sector_count * 512, r->buflen); qemu_iovec_init_external(&r->qiov, &r->iov, 1); - return r->qiov.size / 512; } static void scsi_disk_save_request(QEMUFile *f, SCSIRequest *req) @@ -316,7 +315,6 @@ done: static void scsi_do_read(SCSIDiskReq *r, int ret) { SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev); - uint32_t n; assert (r->req.aiocb == NULL); @@ -340,11 +338,12 @@ static void scsi_do_read(SCSIDiskReq *r, int ret) r->req.aiocb = dma_blk_read(s->qdev.conf.blk, r->req.sg, r->sector, scsi_dma_complete, r); } else { - n = scsi_init_iovec(r, SCSI_DMA_BUF_SIZE); + scsi_init_iovec(r, SCSI_DMA_BUF_SIZE); block_acct_start(blk_get_stats(s->qdev.conf.blk), &r->acct, - n * BDRV_SECTOR_SIZE, BLOCK_ACCT_READ); - r->req.aiocb = blk_aio_readv(s->qdev.conf.blk, r->sector, &r->qiov, n, - scsi_read_complete, r); + r->qiov.size, BLOCK_ACCT_READ); + r->req.aiocb = blk_aio_preadv(s->qdev.conf.blk, + r->sector << BDRV_SECTOR_BITS, &r->qiov, + 0, scsi_read_complete, r); } done: @@ -504,7 +503,6 @@ static void scsi_write_data(SCSIRequest *req) { SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req); SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev); - uint32_t n; /* No data transfer may already be in progress */ assert(r->req.aiocb == NULL); @@ -544,11 +542,11 @@ static void scsi_write_data(SCSIRequest *req) r->req.aiocb = dma_blk_write(s->qdev.conf.blk, r->req.sg, r->sector, scsi_dma_complete, r); } else { - n = r->qiov.size / 512; block_acct_start(blk_get_stats(s->qdev.conf.blk), &r->acct, - n * BDRV_SECTOR_SIZE, BLOCK_ACCT_WRITE); - r->req.aiocb = blk_aio_writev(s->qdev.conf.blk, r->sector, &r->qiov, n, - scsi_write_complete, r); + r->qiov.size, BLOCK_ACCT_WRITE); + r->req.aiocb = blk_aio_pwritev(s->qdev.conf.blk, + r->sector << BDRV_SECTOR_BITS, &r->qiov, + 0, scsi_write_complete, r); } } @@ -1730,13 +1728,13 @@ static void scsi_write_same_complete(void *opaque, int ret) if (data->iov.iov_len) { block_acct_start(blk_get_stats(s->qdev.conf.blk), &r->acct, data->iov.iov_len, BLOCK_ACCT_WRITE); - /* blk_aio_write doesn't like the qiov size being different from - * nb_sectors, make sure they match. - */ + /* Reinitialize qiov, to handle unaligned WRITE SAME request + * where final qiov may need smaller size */ qemu_iovec_init_external(&data->qiov, &data->iov, 1); - r->req.aiocb = blk_aio_writev(s->qdev.conf.blk, data->sector, - &data->qiov, data->iov.iov_len / 512, - scsi_write_same_complete, data); + r->req.aiocb = blk_aio_pwritev(s->qdev.conf.blk, + data->sector << BDRV_SECTOR_BITS, + &data->qiov, 0, + scsi_write_same_complete, data); return; } @@ -1803,9 +1801,10 @@ static void scsi_disk_emulate_write_same(SCSIDiskReq *r, uint8_t *inbuf) scsi_req_ref(&r->req); block_acct_start(blk_get_stats(s->qdev.conf.blk), &r->acct, data->iov.iov_len, BLOCK_ACCT_WRITE); - r->req.aiocb = blk_aio_writev(s->qdev.conf.blk, data->sector, - &data->qiov, data->iov.iov_len / 512, - scsi_write_same_complete, data); + r->req.aiocb = blk_aio_pwritev(s->qdev.conf.blk, + data->sector << BDRV_SECTOR_BITS, + &data->qiov, 0, + scsi_write_same_complete, data); } static void scsi_disk_emulate_write_data(SCSIRequest *req) -- cgit v1.2.3 From b5772fdde40a8200fc20db4d5da672f1ce149d68 Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Fri, 6 May 2016 10:26:33 -0600 Subject: virtio: Switch to byte-based aio block access Sector-based blk_aio_readv() and blk_aio_writev() should die; switch to byte-based blk_aio_preadv() and blk_aio_pwritev() instead. The trace is modified at the same time, and nb_sectors is now unused. Fix a comment typo while in the vicinity. Signed-off-by: Eric Blake Signed-off-by: Kevin Wolf --- hw/block/virtio-blk.c | 18 ++++++++---------- trace-events | 2 +- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c index 3f88f8cf59..284e64667c 100644 --- a/hw/block/virtio-blk.c +++ b/hw/block/virtio-blk.c @@ -322,7 +322,6 @@ static inline void submit_requests(BlockBackend *blk, MultiReqBuffer *mrb, { QEMUIOVector *qiov = &mrb->reqs[start]->qiov; int64_t sector_num = mrb->reqs[start]->sector_num; - int nb_sectors = mrb->reqs[start]->qiov.size / BDRV_SECTOR_SIZE; bool is_write = mrb->is_write; if (num_reqs > 1) { @@ -331,7 +330,7 @@ static inline void submit_requests(BlockBackend *blk, MultiReqBuffer *mrb, int tmp_niov = qiov->niov; /* mrb->reqs[start]->qiov was initialized from external so we can't - * modifiy it here. We need to initialize it locally and then add the + * modify it here. We need to initialize it locally and then add the * external iovecs. */ qemu_iovec_init(qiov, niov); @@ -343,23 +342,22 @@ static inline void submit_requests(BlockBackend *blk, MultiReqBuffer *mrb, qemu_iovec_concat(qiov, &mrb->reqs[i]->qiov, 0, mrb->reqs[i]->qiov.size); mrb->reqs[i - 1]->mr_next = mrb->reqs[i]; - nb_sectors += mrb->reqs[i]->qiov.size / BDRV_SECTOR_SIZE; } - assert(nb_sectors == qiov->size / BDRV_SECTOR_SIZE); - trace_virtio_blk_submit_multireq(mrb, start, num_reqs, sector_num, - nb_sectors, is_write); + trace_virtio_blk_submit_multireq(mrb, start, num_reqs, + sector_num << BDRV_SECTOR_BITS, + qiov->size, is_write); block_acct_merge_done(blk_get_stats(blk), is_write ? BLOCK_ACCT_WRITE : BLOCK_ACCT_READ, num_reqs - 1); } if (is_write) { - blk_aio_writev(blk, sector_num, qiov, nb_sectors, - virtio_blk_rw_complete, mrb->reqs[start]); + blk_aio_pwritev(blk, sector_num << BDRV_SECTOR_BITS, qiov, 0, + virtio_blk_rw_complete, mrb->reqs[start]); } else { - blk_aio_readv(blk, sector_num, qiov, nb_sectors, - virtio_blk_rw_complete, mrb->reqs[start]); + blk_aio_preadv(blk, sector_num << BDRV_SECTOR_BITS, qiov, 0, + virtio_blk_rw_complete, mrb->reqs[start]); } } diff --git a/trace-events b/trace-events index b4acd2ad98..b588091b6c 100644 --- a/trace-events +++ b/trace-events @@ -118,7 +118,7 @@ virtio_blk_req_complete(void *req, int status) "req %p status %d" virtio_blk_rw_complete(void *req, int ret) "req %p ret %d" virtio_blk_handle_write(void *req, uint64_t sector, size_t nsectors) "req %p sector %"PRIu64" nsectors %zu" virtio_blk_handle_read(void *req, uint64_t sector, size_t nsectors) "req %p sector %"PRIu64" nsectors %zu" -virtio_blk_submit_multireq(void *mrb, int start, int num_reqs, uint64_t sector, size_t nsectors, bool is_write) "mrb %p start %d num_reqs %d sector %"PRIu64" nsectors %zu is_write %d" +virtio_blk_submit_multireq(void *mrb, int start, int num_reqs, uint64_t offset, size_t size, bool is_write) "mrb %p start %d num_reqs %d offset %"PRIu64" size %zu is_write %d" # hw/block/dataplane/virtio-blk.c virtio_blk_data_plane_start(void *s) "dataplane %p" -- cgit v1.2.3 From d00000f90193cdbed32a16bcc9b5b4e9ff9d7ab2 Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Fri, 6 May 2016 10:26:34 -0600 Subject: xen_disk: Switch to byte-based aio block access Sector-based blk_aio_readv() and blk_aio_writev() should die; switch to byte-based blk_aio_preadv() and blk_aio_pwritev() instead. Signed-off-by: Eric Blake Signed-off-by: Kevin Wolf --- hw/block/xen_disk.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/hw/block/xen_disk.c b/hw/block/xen_disk.c index d4ce380fee..064c116a7c 100644 --- a/hw/block/xen_disk.c +++ b/hw/block/xen_disk.c @@ -554,9 +554,8 @@ static int ioreq_runio_qemu_aio(struct ioreq *ioreq) block_acct_start(blk_get_stats(blkdev->blk), &ioreq->acct, ioreq->v.size, BLOCK_ACCT_READ); ioreq->aio_inflight++; - blk_aio_readv(blkdev->blk, ioreq->start / BLOCK_SIZE, - &ioreq->v, ioreq->v.size / BLOCK_SIZE, - qemu_aio_complete, ioreq); + blk_aio_preadv(blkdev->blk, ioreq->start, &ioreq->v, 0, + qemu_aio_complete, ioreq); break; case BLKIF_OP_WRITE: case BLKIF_OP_FLUSH_DISKCACHE: @@ -569,9 +568,8 @@ static int ioreq_runio_qemu_aio(struct ioreq *ioreq) ioreq->req.operation == BLKIF_OP_WRITE ? BLOCK_ACCT_WRITE : BLOCK_ACCT_FLUSH); ioreq->aio_inflight++; - blk_aio_writev(blkdev->blk, ioreq->start / BLOCK_SIZE, - &ioreq->v, ioreq->v.size / BLOCK_SIZE, - qemu_aio_complete, ioreq); + blk_aio_pwritev(blkdev->blk, ioreq->start, &ioreq->v, 0, + qemu_aio_complete, ioreq); break; case BLKIF_OP_DISCARD: { -- cgit v1.2.3 From a7a5b7c0fc4caeeda59b4bc91d467c4c98db79cf Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Fri, 6 May 2016 10:26:35 -0600 Subject: fdc: Switch to byte-based block access Sector-based blk_write() should die; switch to byte-based blk_pwrite() instead. Likewise for blk_read(). Signed-off-by: Eric Blake Signed-off-by: Kevin Wolf --- hw/block/fdc.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/hw/block/fdc.c b/hw/block/fdc.c index 372227569e..f73af7db46 100644 --- a/hw/block/fdc.c +++ b/hw/block/fdc.c @@ -223,6 +223,13 @@ static int fd_sector(FDrive *drv) NUM_SIDES(drv)); } +/* Returns current position, in bytes, for given drive */ +static int fd_offset(FDrive *drv) +{ + g_assert(fd_sector(drv) < INT_MAX >> BDRV_SECTOR_BITS); + return fd_sector(drv) << BDRV_SECTOR_BITS; +} + /* Seek to a new position: * returns 0 if already on right track * returns 1 if track changed @@ -1629,8 +1636,8 @@ static int fdctrl_transfer_handler (void *opaque, int nchan, if (fdctrl->data_dir != FD_DIR_WRITE || len < FD_SECTOR_LEN || rel_pos != 0) { /* READ & SCAN commands and realign to a sector for WRITE */ - if (blk_read(cur_drv->blk, fd_sector(cur_drv), - fdctrl->fifo, 1) < 0) { + if (blk_pread(cur_drv->blk, fd_offset(cur_drv), + fdctrl->fifo, BDRV_SECTOR_SIZE) < 0) { FLOPPY_DPRINTF("Floppy: error getting sector %d\n", fd_sector(cur_drv)); /* Sure, image size is too small... */ @@ -1657,8 +1664,8 @@ static int fdctrl_transfer_handler (void *opaque, int nchan, k->read_memory(fdctrl->dma, nchan, fdctrl->fifo + rel_pos, fdctrl->data_pos, len); - if (blk_write(cur_drv->blk, fd_sector(cur_drv), - fdctrl->fifo, 1) < 0) { + if (blk_pwrite(cur_drv->blk, fd_offset(cur_drv), + fdctrl->fifo, BDRV_SECTOR_SIZE, 0) < 0) { FLOPPY_DPRINTF("error writing sector %d\n", fd_sector(cur_drv)); fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM | FD_SR0_SEEK, 0x00, 0x00); @@ -1741,7 +1748,8 @@ static uint32_t fdctrl_read_data(FDCtrl *fdctrl) fd_sector(cur_drv)); return 0; } - if (blk_read(cur_drv->blk, fd_sector(cur_drv), fdctrl->fifo, 1) + if (blk_pread(cur_drv->blk, fd_offset(cur_drv), fdctrl->fifo, + BDRV_SECTOR_SIZE) < 0) { FLOPPY_DPRINTF("error getting sector %d\n", fd_sector(cur_drv)); @@ -1820,7 +1828,8 @@ static void fdctrl_format_sector(FDCtrl *fdctrl) } memset(fdctrl->fifo, 0, FD_SECTOR_LEN); if (cur_drv->blk == NULL || - blk_write(cur_drv->blk, fd_sector(cur_drv), fdctrl->fifo, 1) < 0) { + blk_pwrite(cur_drv->blk, fd_offset(cur_drv), fdctrl->fifo, + BDRV_SECTOR_SIZE, 0) < 0) { FLOPPY_DPRINTF("error formatting sector %d\n", fd_sector(cur_drv)); fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM | FD_SR0_SEEK, 0x00, 0x00); } else { @@ -2243,8 +2252,8 @@ static void fdctrl_write_data(FDCtrl *fdctrl, uint32_t value) if (pos == FD_SECTOR_LEN - 1 || fdctrl->data_pos == fdctrl->data_len) { cur_drv = get_cur_drv(fdctrl); - if (blk_write(cur_drv->blk, fd_sector(cur_drv), fdctrl->fifo, 1) - < 0) { + if (blk_pwrite(cur_drv->blk, fd_offset(cur_drv), fdctrl->fifo, + BDRV_SECTOR_SIZE, 0) < 0) { FLOPPY_DPRINTF("error writing sector %d\n", fd_sector(cur_drv)); break; -- cgit v1.2.3 From 9fc0d361cc412251500cfe3fe9a548a363c635be Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Fri, 6 May 2016 10:26:36 -0600 Subject: nand: Switch to byte-based block access Sector-based blk_write() should die; switch to byte-based blk_pwrite() instead. Likewise for blk_read(). This file is doing some complex computations to map various flash page sizes (256, 512, and 2048) atop generic uses of 512-byte sector operations. Perhaps someone will want to tidy up the file for fewer gymnastics in managing addresses and offsets, and less wasteful visits of 256-byte pages, but it was out of scope for this series, where I just went with the mechanical conversion. Signed-off-by: Eric Blake Signed-off-by: Kevin Wolf --- hw/block/nand.c | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/hw/block/nand.c b/hw/block/nand.c index 29c6596810..c69e6755d9 100644 --- a/hw/block/nand.c +++ b/hw/block/nand.c @@ -663,7 +663,8 @@ static void glue(nand_blk_write_, PAGE_SIZE)(NANDFlashState *s) sector = SECTOR(s->addr); off = (s->addr & PAGE_MASK) + s->offset; soff = SECTOR_OFFSET(s->addr); - if (blk_read(s->blk, sector, iobuf, PAGE_SECTORS) < 0) { + if (blk_pread(s->blk, sector << BDRV_SECTOR_BITS, iobuf, + PAGE_SECTORS << BDRV_SECTOR_BITS) < 0) { printf("%s: read error in sector %" PRIu64 "\n", __func__, sector); return; } @@ -675,21 +676,24 @@ static void glue(nand_blk_write_, PAGE_SIZE)(NANDFlashState *s) MIN(OOB_SIZE, off + s->iolen - PAGE_SIZE)); } - if (blk_write(s->blk, sector, iobuf, PAGE_SECTORS) < 0) { + if (blk_pwrite(s->blk, sector << BDRV_SECTOR_BITS, iobuf, + PAGE_SECTORS << BDRV_SECTOR_BITS, 0) < 0) { printf("%s: write error in sector %" PRIu64 "\n", __func__, sector); } } else { off = PAGE_START(s->addr) + (s->addr & PAGE_MASK) + s->offset; sector = off >> 9; soff = off & 0x1ff; - if (blk_read(s->blk, sector, iobuf, PAGE_SECTORS + 2) < 0) { + if (blk_pread(s->blk, sector << BDRV_SECTOR_BITS, iobuf, + (PAGE_SECTORS + 2) << BDRV_SECTOR_BITS) < 0) { printf("%s: read error in sector %" PRIu64 "\n", __func__, sector); return; } mem_and(iobuf + soff, s->io, s->iolen); - if (blk_write(s->blk, sector, iobuf, PAGE_SECTORS + 2) < 0) { + if (blk_pwrite(s->blk, sector << BDRV_SECTOR_BITS, iobuf, + (PAGE_SECTORS + 2) << BDRV_SECTOR_BITS, 0) < 0) { printf("%s: write error in sector %" PRIu64 "\n", __func__, sector); } } @@ -716,17 +720,20 @@ static void glue(nand_blk_erase_, PAGE_SIZE)(NANDFlashState *s) i = SECTOR(addr); page = SECTOR(addr + (1 << (ADDR_SHIFT + s->erase_shift))); for (; i < page; i ++) - if (blk_write(s->blk, i, iobuf, 1) < 0) { + if (blk_pwrite(s->blk, i << BDRV_SECTOR_BITS, iobuf, + BDRV_SECTOR_SIZE, 0) < 0) { printf("%s: write error in sector %" PRIu64 "\n", __func__, i); } } else { addr = PAGE_START(addr); page = addr >> 9; - if (blk_read(s->blk, page, iobuf, 1) < 0) { + if (blk_pread(s->blk, page << BDRV_SECTOR_BITS, iobuf, + BDRV_SECTOR_SIZE) < 0) { printf("%s: read error in sector %" PRIu64 "\n", __func__, page); } memset(iobuf + (addr & 0x1ff), 0xff, (~addr & 0x1ff) + 1); - if (blk_write(s->blk, page, iobuf, 1) < 0) { + if (blk_pwrite(s->blk, page << BDRV_SECTOR_BITS, iobuf, + BDRV_SECTOR_SIZE, 0) < 0) { printf("%s: write error in sector %" PRIu64 "\n", __func__, page); } @@ -734,18 +741,20 @@ static void glue(nand_blk_erase_, PAGE_SIZE)(NANDFlashState *s) i = (addr & ~0x1ff) + 0x200; for (addr += ((PAGE_SIZE + OOB_SIZE) << s->erase_shift) - 0x200; i < addr; i += 0x200) { - if (blk_write(s->blk, i >> 9, iobuf, 1) < 0) { + if (blk_pwrite(s->blk, i, iobuf, BDRV_SECTOR_SIZE, 0) < 0) { printf("%s: write error in sector %" PRIu64 "\n", __func__, i >> 9); } } page = i >> 9; - if (blk_read(s->blk, page, iobuf, 1) < 0) { + if (blk_pread(s->blk, page << BDRV_SECTOR_BITS, iobuf, + BDRV_SECTOR_SIZE) < 0) { printf("%s: read error in sector %" PRIu64 "\n", __func__, page); } memset(iobuf, 0xff, ((addr - 1) & 0x1ff) + 1); - if (blk_write(s->blk, page, iobuf, 1) < 0) { + if (blk_pwrite(s->blk, page << BDRV_SECTOR_BITS, iobuf, + BDRV_SECTOR_SIZE, 0) < 0) { printf("%s: write error in sector %" PRIu64 "\n", __func__, page); } } @@ -760,7 +769,8 @@ static void glue(nand_blk_load_, PAGE_SIZE)(NANDFlashState *s, if (s->blk) { if (s->mem_oob) { - if (blk_read(s->blk, SECTOR(addr), s->io, PAGE_SECTORS) < 0) { + if (blk_pread(s->blk, SECTOR(addr) << BDRV_SECTOR_BITS, s->io, + PAGE_SECTORS << BDRV_SECTOR_BITS) < 0) { printf("%s: read error in sector %" PRIu64 "\n", __func__, SECTOR(addr)); } @@ -769,8 +779,8 @@ static void glue(nand_blk_load_, PAGE_SIZE)(NANDFlashState *s, OOB_SIZE); s->ioaddr = s->io + SECTOR_OFFSET(s->addr) + offset; } else { - if (blk_read(s->blk, PAGE_START(addr) >> 9, - s->io, (PAGE_SECTORS + 2)) < 0) { + if (blk_pread(s->blk, PAGE_START(addr), s->io, + (PAGE_SECTORS + 2) << BDRV_SECTOR_BITS) < 0) { printf("%s: read error in sector %" PRIu64 "\n", __func__, PAGE_START(addr) >> 9); } -- cgit v1.2.3 From 441692ddd8321d5e0f09b163e86410e578d87236 Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Fri, 6 May 2016 10:26:37 -0600 Subject: onenand: Switch to byte-based block access Sector-based blk_write() should die; switch to byte-based blk_pwrite() instead. Likewise for blk_read(). This particular device picks its size during onenand_initfn(), and can be at most 0x80000000 bytes; therefore, shifting an 'int sec' request to get back to a byte offset should never overflow 32 bits. But adding assertions to document that point should not hurt. Signed-off-by: Eric Blake Signed-off-by: Kevin Wolf --- hw/block/onenand.c | 41 +++++++++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/hw/block/onenand.c b/hw/block/onenand.c index 883f4b1faa..8d8422739e 100644 --- a/hw/block/onenand.c +++ b/hw/block/onenand.c @@ -224,7 +224,8 @@ static void onenand_reset(OneNANDState *s, int cold) /* Lock the whole flash */ memset(s->blockwp, ONEN_LOCK_LOCKED, s->blocks); - if (s->blk_cur && blk_read(s->blk_cur, 0, s->boot[0], 8) < 0) { + if (s->blk_cur && blk_pread(s->blk_cur, 0, s->boot[0], + 8 << BDRV_SECTOR_BITS) < 0) { hw_error("%s: Loading the BootRAM failed.\n", __func__); } } @@ -240,8 +241,11 @@ static void onenand_system_reset(DeviceState *dev) static inline int onenand_load_main(OneNANDState *s, int sec, int secn, void *dest) { + assert(UINT32_MAX >> BDRV_SECTOR_BITS > sec); + assert(UINT32_MAX >> BDRV_SECTOR_BITS > secn); if (s->blk_cur) { - return blk_read(s->blk_cur, sec, dest, secn) < 0; + return blk_pread(s->blk_cur, sec << BDRV_SECTOR_BITS, dest, + secn << BDRV_SECTOR_BITS) < 0; } else if (sec + secn > s->secs_cur) { return 1; } @@ -257,19 +261,22 @@ static inline int onenand_prog_main(OneNANDState *s, int sec, int secn, int result = 0; if (secn > 0) { - uint32_t size = (uint32_t)secn * 512; + uint32_t size = secn << BDRV_SECTOR_BITS; + uint32_t offset = sec << BDRV_SECTOR_BITS; + assert(UINT32_MAX >> BDRV_SECTOR_BITS > sec); + assert(UINT32_MAX >> BDRV_SECTOR_BITS > secn); const uint8_t *sp = (const uint8_t *)src; uint8_t *dp = 0; if (s->blk_cur) { dp = g_malloc(size); - if (!dp || blk_read(s->blk_cur, sec, dp, secn) < 0) { + if (!dp || blk_pread(s->blk_cur, offset, dp, size) < 0) { result = 1; } } else { if (sec + secn > s->secs_cur) { result = 1; } else { - dp = (uint8_t *)s->current + (sec << 9); + dp = (uint8_t *)s->current + offset; } } if (!result) { @@ -278,7 +285,7 @@ static inline int onenand_prog_main(OneNANDState *s, int sec, int secn, dp[i] &= sp[i]; } if (s->blk_cur) { - result = blk_write(s->blk_cur, sec, dp, secn) < 0; + result = blk_pwrite(s->blk_cur, offset, dp, size, 0) < 0; } } if (dp && s->blk_cur) { @@ -295,7 +302,8 @@ static inline int onenand_load_spare(OneNANDState *s, int sec, int secn, uint8_t buf[512]; if (s->blk_cur) { - if (blk_read(s->blk_cur, s->secs_cur + (sec >> 5), buf, 1) < 0) { + uint32_t offset = (s->secs_cur + (sec >> 5)) << BDRV_SECTOR_BITS; + if (blk_pread(s->blk_cur, offset, buf, BDRV_SECTOR_SIZE) < 0) { return 1; } memcpy(dest, buf + ((sec & 31) << 4), secn << 4); @@ -304,7 +312,7 @@ static inline int onenand_load_spare(OneNANDState *s, int sec, int secn, } else { memcpy(dest, s->current + (s->secs_cur << 9) + (sec << 4), secn << 4); } - + return 0; } @@ -315,10 +323,12 @@ static inline int onenand_prog_spare(OneNANDState *s, int sec, int secn, if (secn > 0) { const uint8_t *sp = (const uint8_t *)src; uint8_t *dp = 0, *dpp = 0; + uint32_t offset = (s->secs_cur + (sec >> 5)) << BDRV_SECTOR_BITS; + assert(UINT32_MAX >> BDRV_SECTOR_BITS > s->secs_cur + (sec >> 5)); if (s->blk_cur) { dp = g_malloc(512); if (!dp - || blk_read(s->blk_cur, s->secs_cur + (sec >> 5), dp, 1) < 0) { + || blk_pread(s->blk_cur, offset, dp, BDRV_SECTOR_SIZE) < 0) { result = 1; } else { dpp = dp + ((sec & 31) << 4); @@ -336,8 +346,8 @@ static inline int onenand_prog_spare(OneNANDState *s, int sec, int secn, dpp[i] &= sp[i]; } if (s->blk_cur) { - result = blk_write(s->blk_cur, s->secs_cur + (sec >> 5), - dp, 1) < 0; + result = blk_pwrite(s->blk_cur, offset, dp, + BDRV_SECTOR_SIZE, 0) < 0; } } g_free(dp); @@ -355,14 +365,17 @@ static inline int onenand_erase(OneNANDState *s, int sec, int num) for (; num > 0; num--, sec++) { if (s->blk_cur) { int erasesec = s->secs_cur + (sec >> 5); - if (blk_write(s->blk_cur, sec, blankbuf, 1) < 0) { + if (blk_pwrite(s->blk_cur, sec << BDRV_SECTOR_BITS, blankbuf, + BDRV_SECTOR_SIZE, 0) < 0) { goto fail; } - if (blk_read(s->blk_cur, erasesec, tmpbuf, 1) < 0) { + if (blk_pread(s->blk_cur, erasesec << BDRV_SECTOR_BITS, tmpbuf, + BDRV_SECTOR_SIZE) < 0) { goto fail; } memcpy(tmpbuf + ((sec & 31) << 4), blankbuf, 1 << 4); - if (blk_write(s->blk_cur, erasesec, tmpbuf, 1) < 0) { + if (blk_pwrite(s->blk_cur, erasesec << BDRV_SECTOR_BITS, tmpbuf, + BDRV_SECTOR_SIZE, 0) < 0) { goto fail; } } else { -- cgit v1.2.3 From 098e732dbeb9d1f191da6fd6d0ddb66909690302 Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Fri, 6 May 2016 10:26:38 -0600 Subject: pflash: Switch to byte-based block access Sector-based blk_write() should die; switch to byte-based blk_pwrite() instead. Likewise for blk_read(). Signed-off-by: Eric Blake Signed-off-by: Kevin Wolf --- hw/block/pflash_cfi01.c | 12 ++++++------ hw/block/pflash_cfi02.c | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/hw/block/pflash_cfi01.c b/hw/block/pflash_cfi01.c index 106a775232..3a1f85d279 100644 --- a/hw/block/pflash_cfi01.c +++ b/hw/block/pflash_cfi01.c @@ -413,11 +413,11 @@ static void pflash_update(pflash_t *pfl, int offset, int offset_end; if (pfl->blk) { offset_end = offset + size; - /* round to sectors */ - offset = offset >> 9; - offset_end = (offset_end + 511) >> 9; - blk_write(pfl->blk, offset, pfl->storage + (offset << 9), - offset_end - offset); + /* widen to sector boundaries */ + offset = QEMU_ALIGN_DOWN(offset, BDRV_SECTOR_SIZE); + offset_end = QEMU_ALIGN_UP(offset_end, BDRV_SECTOR_SIZE); + blk_pwrite(pfl->blk, offset, pfl->storage + offset, + offset_end - offset, 0); } } @@ -739,7 +739,7 @@ static void pflash_cfi01_realize(DeviceState *dev, Error **errp) if (pfl->blk) { /* read the initial flash content */ - ret = blk_read(pfl->blk, 0, pfl->storage, total_len >> 9); + ret = blk_pread(pfl->blk, 0, pfl->storage, total_len); if (ret < 0) { vmstate_unregister_ram(&pfl->mem, DEVICE(pfl)); diff --git a/hw/block/pflash_cfi02.c b/hw/block/pflash_cfi02.c index b13172c6e1..5f106102c5 100644 --- a/hw/block/pflash_cfi02.c +++ b/hw/block/pflash_cfi02.c @@ -253,11 +253,11 @@ static void pflash_update(pflash_t *pfl, int offset, int offset_end; if (pfl->blk) { offset_end = offset + size; - /* round to sectors */ - offset = offset >> 9; - offset_end = (offset_end + 511) >> 9; - blk_write(pfl->blk, offset, pfl->storage + (offset << 9), - offset_end - offset); + /* widen to sector boundaries */ + offset = QEMU_ALIGN_DOWN(offset, BDRV_SECTOR_SIZE); + offset_end = QEMU_ALIGN_UP(offset_end, BDRV_SECTOR_SIZE); + blk_pwrite(pfl->blk, offset, pfl->storage + offset, + offset_end - offset, 0); } } @@ -622,7 +622,7 @@ static void pflash_cfi02_realize(DeviceState *dev, Error **errp) pfl->chip_len = chip_len; if (pfl->blk) { /* read the initial flash content */ - ret = blk_read(pfl->blk, 0, pfl->storage, chip_len >> 9); + ret = blk_pread(pfl->blk, 0, pfl->storage, chip_len); if (ret < 0) { vmstate_unregister_ram(&pfl->orig_mem, DEVICE(pfl)); error_setg(errp, "failed to read the initial flash content"); -- cgit v1.2.3 From 12c125cba9c548929ccf4da2515e5b795c94afd9 Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Fri, 6 May 2016 10:26:39 -0600 Subject: sd: Switch to byte-based block access Sector-based blk_write() should die; switch to byte-based blk_pwrite() instead. Likewise for blk_read(). Greatly simplifies the code, now that we let the block layer take care of alignment and read-modify-write on our behalf :) In fact, we no longer need to include 'buf' in the migration stream (although we do have to ensure that the stream remains compatible). Signed-off-by: Eric Blake Signed-off-by: Kevin Wolf --- hw/sd/sd.c | 51 ++++----------------------------------------------- 1 file changed, 4 insertions(+), 47 deletions(-) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index b66e5d2dba..87e3d23a3d 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -123,7 +123,6 @@ struct SDState { qemu_irq readonly_cb; qemu_irq inserted_cb; BlockBackend *blk; - uint8_t *buf; bool enable; }; @@ -551,7 +550,7 @@ static const VMStateDescription sd_vmstate = { VMSTATE_UINT64(data_start, SDState), VMSTATE_UINT32(data_offset, SDState), VMSTATE_UINT8_ARRAY(data, SDState, 512), - VMSTATE_BUFFER_POINTER_UNSAFE(buf, SDState, 1, 512), + VMSTATE_UNUSED_V(1, 512), VMSTATE_BOOL(enable, SDState), VMSTATE_END_OF_LIST() }, @@ -1577,57 +1576,17 @@ send_response: static void sd_blk_read(SDState *sd, uint64_t addr, uint32_t len) { - uint64_t end = addr + len; - DPRINTF("sd_blk_read: addr = 0x%08llx, len = %d\n", (unsigned long long) addr, len); - if (!sd->blk || blk_read(sd->blk, addr >> 9, sd->buf, 1) < 0) { + if (!sd->blk || blk_pread(sd->blk, addr, sd->data, len) < 0) { fprintf(stderr, "sd_blk_read: read error on host side\n"); - return; } - - if (end > (addr & ~511) + 512) { - memcpy(sd->data, sd->buf + (addr & 511), 512 - (addr & 511)); - - if (blk_read(sd->blk, end >> 9, sd->buf, 1) < 0) { - fprintf(stderr, "sd_blk_read: read error on host side\n"); - return; - } - memcpy(sd->data + 512 - (addr & 511), sd->buf, end & 511); - } else - memcpy(sd->data, sd->buf + (addr & 511), len); } static void sd_blk_write(SDState *sd, uint64_t addr, uint32_t len) { - uint64_t end = addr + len; - - if ((addr & 511) || len < 512) - if (!sd->blk || blk_read(sd->blk, addr >> 9, sd->buf, 1) < 0) { - fprintf(stderr, "sd_blk_write: read error on host side\n"); - return; - } - - if (end > (addr & ~511) + 512) { - memcpy(sd->buf + (addr & 511), sd->data, 512 - (addr & 511)); - if (blk_write(sd->blk, addr >> 9, sd->buf, 1) < 0) { - fprintf(stderr, "sd_blk_write: write error on host side\n"); - return; - } - - if (blk_read(sd->blk, end >> 9, sd->buf, 1) < 0) { - fprintf(stderr, "sd_blk_write: read error on host side\n"); - return; - } - memcpy(sd->buf, sd->data + 512 - (addr & 511), end & 511); - if (blk_write(sd->blk, end >> 9, sd->buf, 1) < 0) { - fprintf(stderr, "sd_blk_write: write error on host side\n"); - } - } else { - memcpy(sd->buf + (addr & 511), sd->data, len); - if (!sd->blk || blk_write(sd->blk, addr >> 9, sd->buf, 1) < 0) { - fprintf(stderr, "sd_blk_write: write error on host side\n"); - } + if (!sd->blk || blk_pwrite(sd->blk, addr, sd->data, len, 0) < 0) { + fprintf(stderr, "sd_blk_write: write error on host side\n"); } } @@ -1925,8 +1884,6 @@ static void sd_realize(DeviceState *dev, Error **errp) return; } - sd->buf = blk_blockalign(sd->blk, 512); - if (sd->blk) { blk_set_dev_ops(sd->blk, &sd_block_ops, sd); } -- cgit v1.2.3 From 243e6f69c129303cb7f161466e989722e9d7e02f Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Fri, 6 May 2016 10:26:40 -0600 Subject: m25p80: Switch to byte-based block access Sector-based blk_read() should die; switch to byte-based blk_pread() instead. Likewise for blk_aio_readv() and blk_aio_writev(). Signed-off-by: Eric Blake Signed-off-by: Kevin Wolf --- hw/block/m25p80.c | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c index 906b71257e..5d308637df 100644 --- a/hw/block/m25p80.c +++ b/hw/block/m25p80.c @@ -358,25 +358,21 @@ static void blk_sync_complete(void *opaque, int ret) static void flash_sync_page(Flash *s, int page) { - int blk_sector, nb_sectors; QEMUIOVector iov; if (!s->blk || blk_is_read_only(s->blk)) { return; } - blk_sector = (page * s->pi->page_size) / BDRV_SECTOR_SIZE; - nb_sectors = DIV_ROUND_UP(s->pi->page_size, BDRV_SECTOR_SIZE); qemu_iovec_init(&iov, 1); - qemu_iovec_add(&iov, s->storage + blk_sector * BDRV_SECTOR_SIZE, - nb_sectors * BDRV_SECTOR_SIZE); - blk_aio_writev(s->blk, blk_sector, &iov, nb_sectors, blk_sync_complete, - NULL); + qemu_iovec_add(&iov, s->storage + page * s->pi->page_size, + s->pi->page_size); + blk_aio_pwritev(s->blk, page * s->pi->page_size, &iov, 0, + blk_sync_complete, NULL); } static inline void flash_sync_area(Flash *s, int64_t off, int64_t len) { - int64_t start, end, nb_sectors; QEMUIOVector iov; if (!s->blk || blk_is_read_only(s->blk)) { @@ -384,13 +380,9 @@ static inline void flash_sync_area(Flash *s, int64_t off, int64_t len) } assert(!(len % BDRV_SECTOR_SIZE)); - start = off / BDRV_SECTOR_SIZE; - end = (off + len) / BDRV_SECTOR_SIZE; - nb_sectors = end - start; qemu_iovec_init(&iov, 1); - qemu_iovec_add(&iov, s->storage + (start * BDRV_SECTOR_SIZE), - nb_sectors * BDRV_SECTOR_SIZE); - blk_aio_writev(s->blk, start, &iov, nb_sectors, blk_sync_complete, NULL); + qemu_iovec_add(&iov, s->storage + off, len); + blk_aio_pwritev(s->blk, off, &iov, 0, blk_sync_complete, NULL); } static void flash_erase(Flash *s, int offset, FlashCMD cmd) @@ -907,8 +899,7 @@ static int m25p80_init(SSISlave *ss) s->storage = blk_blockalign(s->blk, s->size); /* FIXME: Move to late init */ - if (blk_read(s->blk, 0, s->storage, - DIV_ROUND_UP(s->size, BDRV_SECTOR_SIZE))) { + if (blk_pread(s->blk, 0, s->storage, s->size)) { fprintf(stderr, "Failed to initialize SPI flash!\n"); return 1; } -- cgit v1.2.3 From 26a122d3d47205969ca9e4cdba13adc2b2929d8c Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Fri, 6 May 2016 10:26:41 -0600 Subject: atapi: Switch to byte-based block access Sector-based blk_read() should die; switch to byte-based blk_pread() instead. Add new defines ATAPI_SECTOR_BITS and ATAPI_SECTOR_SIZE to use anywhere we were previously scaling BDRV_SECTOR_* by 4, for better legibility. Signed-off-by: Eric Blake Signed-off-by: Kevin Wolf --- hw/ide/atapi.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/hw/ide/atapi.c b/hw/ide/atapi.c index 2bb606c1c5..95056d92e7 100644 --- a/hw/ide/atapi.c +++ b/hw/ide/atapi.c @@ -28,6 +28,9 @@ #include "hw/scsi/scsi.h" #include "sysemu/block-backend.h" +#define ATAPI_SECTOR_BITS (2 + BDRV_SECTOR_BITS) +#define ATAPI_SECTOR_SIZE (1 << ATAPI_SECTOR_BITS) + static void ide_atapi_cmd_read_dma_cb(void *opaque, int ret); static void padstr8(uint8_t *buf, int buf_size, const char *src) @@ -111,7 +114,7 @@ cd_read_sector_sync(IDEState *s) { int ret; block_acct_start(blk_get_stats(s->blk), &s->acct, - 4 * BDRV_SECTOR_SIZE, BLOCK_ACCT_READ); + ATAPI_SECTOR_SIZE, BLOCK_ACCT_READ); #ifdef DEBUG_IDE_ATAPI printf("cd_read_sector_sync: lba=%d\n", s->lba); @@ -119,12 +122,12 @@ cd_read_sector_sync(IDEState *s) switch (s->cd_sector_size) { case 2048: - ret = blk_read(s->blk, (int64_t)s->lba << 2, - s->io_buffer, 4); + ret = blk_pread(s->blk, (int64_t)s->lba << ATAPI_SECTOR_BITS, + s->io_buffer, ATAPI_SECTOR_SIZE); break; case 2352: - ret = blk_read(s->blk, (int64_t)s->lba << 2, - s->io_buffer + 16, 4); + ret = blk_pread(s->blk, (int64_t)s->lba << ATAPI_SECTOR_BITS, + s->io_buffer + 16, ATAPI_SECTOR_SIZE); if (ret >= 0) { cd_data_to_raw(s->io_buffer, s->lba); } @@ -182,7 +185,7 @@ static int cd_read_sector(IDEState *s) s->iov.iov_base = (s->cd_sector_size == 2352) ? s->io_buffer + 16 : s->io_buffer; - s->iov.iov_len = 4 * BDRV_SECTOR_SIZE; + s->iov.iov_len = ATAPI_SECTOR_SIZE; qemu_iovec_init_external(&s->qiov, &s->iov, 1); #ifdef DEBUG_IDE_ATAPI @@ -190,7 +193,7 @@ static int cd_read_sector(IDEState *s) #endif block_acct_start(blk_get_stats(s->blk), &s->acct, - 4 * BDRV_SECTOR_SIZE, BLOCK_ACCT_READ); + ATAPI_SECTOR_SIZE, BLOCK_ACCT_READ); ide_buffered_readv(s, (int64_t)s->lba << 2, &s->qiov, 4, cd_read_sector_cb, s); @@ -435,7 +438,7 @@ static void ide_atapi_cmd_read_dma_cb(void *opaque, int ret) #endif s->bus->dma->iov.iov_base = (void *)(s->io_buffer + data_offset); - s->bus->dma->iov.iov_len = n * 4 * 512; + s->bus->dma->iov.iov_len = n * ATAPI_SECTOR_SIZE; qemu_iovec_init_external(&s->bus->dma->qiov, &s->bus->dma->iov, 1); s->bus->dma->aiocb = ide_buffered_readv(s, (int64_t)s->lba << 2, -- cgit v1.2.3 From bd31c214c328bc6a2b2f5567623d964b65c8f44c Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Fri, 6 May 2016 10:26:42 -0600 Subject: nbd: Switch to byte-based block access Sector-based blk_read() should die; switch to byte-based blk_pread() instead. Add a constant for our magic number 512, to make it obvious that this size will NOT change even if BDRV_SECTOR_SIZE does, even though the two happen to be the same for now. Split assignments from conditionals to keep checkpatch.pl happy. Signed-off-by: Eric Blake Signed-off-by: Kevin Wolf --- qemu-nbd.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/qemu-nbd.c b/qemu-nbd.c index c55b40ffc8..3e541131f4 100644 --- a/qemu-nbd.c +++ b/qemu-nbd.c @@ -46,6 +46,8 @@ #define QEMU_NBD_OPT_TLSCREDS 261 #define QEMU_NBD_OPT_IMAGE_OPTS 262 +#define MBR_SIZE 512 + static NBDExport *exp; static bool newproto; static int verbose; @@ -159,12 +161,13 @@ static int find_partition(BlockBackend *blk, int partition, off_t *offset, off_t *size) { struct partition_record mbr[4]; - uint8_t data[512]; + uint8_t data[MBR_SIZE]; int i; int ext_partnum = 4; int ret; - if ((ret = blk_read(blk, 0, data, 1)) < 0) { + ret = blk_pread(blk, 0, data, sizeof(data)); + if (ret < 0) { error_report("error while reading: %s", strerror(-ret)); exit(EXIT_FAILURE); } @@ -182,10 +185,12 @@ static int find_partition(BlockBackend *blk, int partition, if (mbr[i].system == 0xF || mbr[i].system == 0x5) { struct partition_record ext[4]; - uint8_t data1[512]; + uint8_t data1[MBR_SIZE]; int j; - if ((ret = blk_read(blk, mbr[i].start_sector_abs, data1, 1)) < 0) { + ret = blk_pread(blk, mbr[i].start_sector_abs * MBR_SIZE, + data1, sizeof(data1)); + if (ret < 0) { error_report("error while reading: %s", strerror(-ret)); exit(EXIT_FAILURE); } -- cgit v1.2.3 From 9166920a0b8481dde8d011d07cc4c733c81223eb Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Fri, 6 May 2016 10:26:43 -0600 Subject: qemu-img: Switch to byte-based block access Sector-based blk_write() should die; switch to byte-based blk_pwrite() instead. Likewise for blk_read(). Signed-off-by: Eric Blake Signed-off-by: Kevin Wolf --- qemu-img.c | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/qemu-img.c b/qemu-img.c index 76430a83cd..491a460ecf 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -1088,7 +1088,8 @@ static int check_empty_sectors(BlockBackend *blk, int64_t sect_num, uint8_t *buffer, bool quiet) { int pnum, ret = 0; - ret = blk_read(blk, sect_num, buffer, sect_count); + ret = blk_pread(blk, sect_num << BDRV_SECTOR_BITS, buffer, + sect_count << BDRV_SECTOR_BITS); if (ret < 0) { error_report("Error while reading offset %" PRId64 " of %s: %s", sectors_to_bytes(sect_num), filename, strerror(-ret)); @@ -1301,7 +1302,8 @@ static int img_compare(int argc, char **argv) nb_sectors = MIN(pnum1, pnum2); } else if (allocated1 == allocated2) { if (allocated1) { - ret = blk_read(blk1, sector_num, buf1, nb_sectors); + ret = blk_pread(blk1, sector_num << BDRV_SECTOR_BITS, buf1, + nb_sectors << BDRV_SECTOR_BITS); if (ret < 0) { error_report("Error while reading offset %" PRId64 " of %s:" " %s", sectors_to_bytes(sector_num), filename1, @@ -1309,7 +1311,8 @@ static int img_compare(int argc, char **argv) ret = 4; goto out; } - ret = blk_read(blk2, sector_num, buf2, nb_sectors); + ret = blk_pread(blk2, sector_num << BDRV_SECTOR_BITS, buf2, + nb_sectors << BDRV_SECTOR_BITS); if (ret < 0) { error_report("Error while reading offset %" PRId64 " of %s: %s", sectors_to_bytes(sector_num), @@ -1522,7 +1525,9 @@ static int convert_read(ImgConvertState *s, int64_t sector_num, int nb_sectors, bs_sectors = s->src_sectors[s->src_cur]; n = MIN(nb_sectors, bs_sectors - (sector_num - s->src_cur_offset)); - ret = blk_read(blk, sector_num - s->src_cur_offset, buf, n); + ret = blk_pread(blk, + (sector_num - s->src_cur_offset) << BDRV_SECTOR_BITS, + buf, n << BDRV_SECTOR_BITS); if (ret < 0) { return ret; } @@ -1577,7 +1582,8 @@ static int convert_write(ImgConvertState *s, int64_t sector_num, int nb_sectors, if (!s->min_sparse || is_allocated_sectors_min(buf, n, &n, s->min_sparse)) { - ret = blk_write(s->target, sector_num, buf, n); + ret = blk_pwrite(s->target, sector_num << BDRV_SECTOR_BITS, + buf, n << BDRV_SECTOR_BITS, 0); if (ret < 0) { return ret; } @@ -3024,7 +3030,8 @@ static int img_rebase(int argc, char **argv) n = old_backing_num_sectors - sector; } - ret = blk_read(blk_old_backing, sector, buf_old, n); + ret = blk_pread(blk_old_backing, sector << BDRV_SECTOR_BITS, + buf_old, n << BDRV_SECTOR_BITS); if (ret < 0) { error_report("error while reading from old backing file"); goto out; @@ -3038,7 +3045,8 @@ static int img_rebase(int argc, char **argv) n = new_backing_num_sectors - sector; } - ret = blk_read(blk_new_backing, sector, buf_new, n); + ret = blk_pread(blk_new_backing, sector << BDRV_SECTOR_BITS, + buf_new, n << BDRV_SECTOR_BITS); if (ret < 0) { error_report("error while reading from new backing file"); goto out; @@ -3054,8 +3062,10 @@ static int img_rebase(int argc, char **argv) if (compare_sectors(buf_old + written * 512, buf_new + written * 512, n - written, &pnum)) { - ret = blk_write(blk, sector + written, - buf_old + written * 512, pnum); + ret = blk_pwrite(blk, + (sector + written) << BDRV_SECTOR_BITS, + buf_old + written * 512, + pnum << BDRV_SECTOR_BITS, 0); if (ret < 0) { error_report("Error while writing to COW image: %s", strerror(-ret)); -- cgit v1.2.3 From 7b3f9712e1b64bd811ac3657fc1cb05f9e3f5d87 Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Fri, 6 May 2016 10:26:44 -0600 Subject: qemu-io: Switch to byte-based block access qemu-io is the last user of several sector-based interfaces. This patch upgrades to the new interfaces under the hood, then deletes the resulting dead code. Note that for maximum back-compat, while the -p option is no longer required to get blk_pread(), it is still needed to allow for unaligned access; this is because qemu-iotest 23 relies on qemu-io rejecting unaligned accesses without -p. A later patch may clean up the interface to be more user-friendly, but it's better to separate what's done under the hood from what the user sees. Signed-off-by: Eric Blake Signed-off-by: Kevin Wolf --- qemu-io-cmds.c | 62 ++++++++++------------------------------------------------ 1 file changed, 10 insertions(+), 52 deletions(-) diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c index 3040a4b12e..767ea5ecdb 100644 --- a/qemu-io-cmds.c +++ b/qemu-io-cmds.c @@ -419,40 +419,6 @@ fail: return buf; } -static int do_read(BlockBackend *blk, char *buf, int64_t offset, int64_t count, - int64_t *total) -{ - int ret; - - if (count >> 9 > INT_MAX) { - return -ERANGE; - } - - ret = blk_read(blk, offset >> 9, (uint8_t *)buf, count >> 9); - if (ret < 0) { - return ret; - } - *total = count; - return 1; -} - -static int do_write(BlockBackend *blk, char *buf, int64_t offset, int64_t count, - int64_t *total) -{ - int ret; - - if (count >> 9 > INT_MAX) { - return -ERANGE; - } - - ret = blk_write(blk, offset >> 9, (uint8_t *)buf, count >> 9); - if (ret < 0) { - return ret; - } - *total = count; - return 1; -} - static int do_pread(BlockBackend *blk, char *buf, int64_t offset, int64_t count, int64_t *total) { @@ -588,8 +554,7 @@ static int do_aio_readv(BlockBackend *blk, QEMUIOVector *qiov, { int async_ret = NOT_DONE; - blk_aio_readv(blk, offset >> 9, qiov, qiov->size >> 9, - aio_rw_done, &async_ret); + blk_aio_preadv(blk, offset, qiov, 0, aio_rw_done, &async_ret); while (async_ret == NOT_DONE) { main_loop_wait(false); } @@ -603,8 +568,7 @@ static int do_aio_writev(BlockBackend *blk, QEMUIOVector *qiov, { int async_ret = NOT_DONE; - blk_aio_writev(blk, offset >> 9, qiov, qiov->size >> 9, - aio_rw_done, &async_ret); + blk_aio_pwritev(blk, offset, qiov, 0, aio_rw_done, &async_ret); while (async_ret == NOT_DONE) { main_loop_wait(false); } @@ -670,7 +634,7 @@ static void read_help(void) " -b, -- read from the VM state rather than the virtual disk\n" " -C, -- report statistics in a machine parsable format\n" " -l, -- length for pattern verification (only with -P)\n" -" -p, -- use blk_pread to read the file\n" +" -p, -- allow unaligned access\n" " -P, -- use a pattern to verify read data\n" " -q, -- quiet mode, do not show I/O statistics\n" " -s, -- start offset for pattern verification (only with -P)\n" @@ -805,12 +769,10 @@ static int read_f(BlockBackend *blk, int argc, char **argv) buf = qemu_io_alloc(blk, count, 0xab); gettimeofday(&t1, NULL); - if (pflag) { - cnt = do_pread(blk, buf, offset, count, &total); - } else if (bflag) { + if (bflag) { cnt = do_load_vmstate(blk, buf, offset, count, &total); } else { - cnt = do_read(blk, buf, offset, count, &total); + cnt = do_pread(blk, buf, offset, count, &total); } gettimeofday(&t2, NULL); @@ -990,7 +952,7 @@ static void write_help(void) " filled with a set pattern (0xcdcdcdcd).\n" " -b, -- write to the VM state rather than the virtual disk\n" " -c, -- write compressed data with blk_write_compressed\n" -" -p, -- use blk_pwrite to write the file\n" +" -p, -- allow unaligned access\n" " -P, -- use different pattern to fill file\n" " -C, -- report statistics in a machine parsable format\n" " -q, -- quiet mode, do not show I/O statistics\n" @@ -1106,16 +1068,14 @@ static int write_f(BlockBackend *blk, int argc, char **argv) } gettimeofday(&t1, NULL); - if (pflag) { - cnt = do_pwrite(blk, buf, offset, count, &total); - } else if (bflag) { + if (bflag) { cnt = do_save_vmstate(blk, buf, offset, count, &total); } else if (zflag) { cnt = do_co_write_zeroes(blk, offset, count, &total); } else if (cflag) { cnt = do_write_compressed(blk, buf, offset, count, &total); } else { - cnt = do_write(blk, buf, offset, count, &total); + cnt = do_pwrite(blk, buf, offset, count, &total); } gettimeofday(&t2, NULL); @@ -1592,8 +1552,7 @@ static int aio_read_f(BlockBackend *blk, int argc, char **argv) gettimeofday(&ctx->t1, NULL); block_acct_start(blk_get_stats(blk), &ctx->acct, ctx->qiov.size, BLOCK_ACCT_READ); - blk_aio_readv(blk, ctx->offset >> 9, &ctx->qiov, - ctx->qiov.size >> 9, aio_read_done, ctx); + blk_aio_preadv(blk, ctx->offset, &ctx->qiov, 0, aio_read_done, ctx); return 0; } @@ -1718,8 +1677,7 @@ static int aio_write_f(BlockBackend *blk, int argc, char **argv) block_acct_start(blk_get_stats(blk), &ctx->acct, ctx->qiov.size, BLOCK_ACCT_WRITE); - blk_aio_writev(blk, ctx->offset >> 9, &ctx->qiov, - ctx->qiov.size >> 9, aio_write_done, ctx); + blk_aio_pwritev(blk, ctx->offset, &ctx->qiov, 0, aio_write_done, ctx); } return 0; } -- cgit v1.2.3 From 7b1deac84e2a06530b3a5855ff46a27e87a74820 Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Fri, 6 May 2016 10:26:45 -0600 Subject: block: Kill unused sector-based blk_* functions Now that there are no remaining clients, we can drop the sector-based blk_read(), blk_write(), blk_aio_readv(), and blk_aio_writev(). Sadly, there are still remaining sector-based interfaces, such as blk_*discard(), or blk_write_compressed(); those will have to wait for another day. Signed-off-by: Eric Blake Signed-off-by: Kevin Wolf --- block/block-backend.c | 51 ------------------------------------------ include/sysemu/block-backend.h | 10 --------- 2 files changed, 61 deletions(-) diff --git a/block/block-backend.c b/block/block-backend.c index 6ac76d0176..a1e2c7fa20 100644 --- a/block/block-backend.c +++ b/block/block-backend.c @@ -772,24 +772,6 @@ static int blk_prw(BlockBackend *blk, int64_t offset, uint8_t *buf, return rwco.ret; } -static int blk_rw(BlockBackend *blk, int64_t sector_num, uint8_t *buf, - int nb_sectors, CoroutineEntry co_entry, - BdrvRequestFlags flags) -{ - if (nb_sectors < 0 || nb_sectors > BDRV_REQUEST_MAX_SECTORS) { - return -EINVAL; - } - - return blk_prw(blk, sector_num << BDRV_SECTOR_BITS, buf, - nb_sectors << BDRV_SECTOR_BITS, co_entry, flags); -} - -int blk_read(BlockBackend *blk, int64_t sector_num, uint8_t *buf, - int nb_sectors) -{ - return blk_rw(blk, sector_num, buf, nb_sectors, blk_read_entry, 0); -} - int blk_pread_unthrottled(BlockBackend *blk, int64_t offset, uint8_t *buf, int count) { @@ -807,13 +789,6 @@ int blk_pread_unthrottled(BlockBackend *blk, int64_t offset, uint8_t *buf, return ret; } -int blk_write(BlockBackend *blk, int64_t sector_num, const uint8_t *buf, - int nb_sectors) -{ - return blk_rw(blk, sector_num, (uint8_t*) buf, nb_sectors, - blk_write_entry, 0); -} - int blk_write_zeroes(BlockBackend *blk, int64_t offset, int count, BdrvRequestFlags flags) { @@ -985,19 +960,6 @@ int64_t blk_nb_sectors(BlockBackend *blk) return bdrv_nb_sectors(blk_bs(blk)); } -BlockAIOCB *blk_aio_readv(BlockBackend *blk, int64_t sector_num, - QEMUIOVector *iov, int nb_sectors, - BlockCompletionFunc *cb, void *opaque) -{ - if (nb_sectors < 0 || nb_sectors > BDRV_REQUEST_MAX_SECTORS) { - return blk_abort_aio_request(blk, cb, opaque, -EINVAL); - } - - assert(nb_sectors << BDRV_SECTOR_BITS == iov->size); - return blk_aio_prwv(blk, sector_num << BDRV_SECTOR_BITS, iov->size, iov, - blk_aio_read_entry, 0, cb, opaque); -} - BlockAIOCB *blk_aio_preadv(BlockBackend *blk, int64_t offset, QEMUIOVector *qiov, BdrvRequestFlags flags, BlockCompletionFunc *cb, void *opaque) @@ -1006,19 +968,6 @@ BlockAIOCB *blk_aio_preadv(BlockBackend *blk, int64_t offset, blk_aio_read_entry, flags, cb, opaque); } -BlockAIOCB *blk_aio_writev(BlockBackend *blk, int64_t sector_num, - QEMUIOVector *iov, int nb_sectors, - BlockCompletionFunc *cb, void *opaque) -{ - if (nb_sectors < 0 || nb_sectors > BDRV_REQUEST_MAX_SECTORS) { - return blk_abort_aio_request(blk, cb, opaque, -EINVAL); - } - - assert(nb_sectors << BDRV_SECTOR_BITS == iov->size); - return blk_aio_prwv(blk, sector_num << BDRV_SECTOR_BITS, iov->size, iov, - blk_aio_write_entry, 0, cb, opaque); -} - BlockAIOCB *blk_aio_pwritev(BlockBackend *blk, int64_t offset, QEMUIOVector *qiov, BdrvRequestFlags flags, BlockCompletionFunc *cb, void *opaque) diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h index 73df1a677c..26736ed84e 100644 --- a/include/sysemu/block-backend.h +++ b/include/sysemu/block-backend.h @@ -90,12 +90,8 @@ void blk_attach_dev_nofail(BlockBackend *blk, void *dev); void blk_detach_dev(BlockBackend *blk, void *dev); void *blk_get_attached_dev(BlockBackend *blk); void blk_set_dev_ops(BlockBackend *blk, const BlockDevOps *ops, void *opaque); -int blk_read(BlockBackend *blk, int64_t sector_num, uint8_t *buf, - int nb_sectors); int blk_pread_unthrottled(BlockBackend *blk, int64_t offset, uint8_t *buf, int count); -int blk_write(BlockBackend *blk, int64_t sector_num, const uint8_t *buf, - int nb_sectors); int blk_write_zeroes(BlockBackend *blk, int64_t offset, int count, BdrvRequestFlags flags); BlockAIOCB *blk_aio_write_zeroes(BlockBackend *blk, int64_t offset, @@ -107,15 +103,9 @@ int blk_pwrite(BlockBackend *blk, int64_t offset, const void *buf, int count, int64_t blk_getlength(BlockBackend *blk); void blk_get_geometry(BlockBackend *blk, uint64_t *nb_sectors_ptr); int64_t blk_nb_sectors(BlockBackend *blk); -BlockAIOCB *blk_aio_readv(BlockBackend *blk, int64_t sector_num, - QEMUIOVector *iov, int nb_sectors, - BlockCompletionFunc *cb, void *opaque); BlockAIOCB *blk_aio_preadv(BlockBackend *blk, int64_t offset, QEMUIOVector *qiov, BdrvRequestFlags flags, BlockCompletionFunc *cb, void *opaque); -BlockAIOCB *blk_aio_writev(BlockBackend *blk, int64_t sector_num, - QEMUIOVector *iov, int nb_sectors, - BlockCompletionFunc *cb, void *opaque); BlockAIOCB *blk_aio_pwritev(BlockBackend *blk, int64_t offset, QEMUIOVector *qiov, BdrvRequestFlags flags, BlockCompletionFunc *cb, void *opaque); -- cgit v1.2.3 From 2928abce6d1d426d37c0a9bd5f85fb95cf33f709 Mon Sep 17 00:00:00 2001 From: "Denis V. Lunev" Date: Wed, 11 May 2016 10:00:14 +0300 Subject: qcow2: improve qcow2_co_write_zeroes() There is a possibility that qcow2_co_write_zeroes() will be called with the partial block. This could be synthetically triggered with qemu-io -c "write -z 32k 4k" and can happen in the real life in qemu-nbd. The latter happens under the following conditions: (1) qemu-nbd is started with --detect-zeroes=on and is connected to the kernel NBD client (2) third party program opens kernel NBD device with O_DIRECT (3) third party program performs write operation with memory buffer not aligned to the page In this case qcow2_co_write_zeroes() is unable to perform the operation and mark entire cluster as zeroed and returns ENOTSUP. Thus the caller switches to non-optimized version and writes real zeroes to the disk. The patch creates a shortcut. If the block is read as zeroes, f.e. if it is unallocated, the request is extended to cover full block. User-visible situation with this block is not changed. Before the patch the block is filled in the image with real zeroes. After that patch the block is marked as zeroed in metadata. Thus any subsequent changes in backing store chain are not affected. Kevin, thank you for a cool suggestion. Signed-off-by: Denis V. Lunev Reviewed-by: Roman Kagan CC: Kevin Wolf CC: Max Reitz Signed-off-by: Kevin Wolf --- block/qcow2.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 59 insertions(+), 6 deletions(-) diff --git a/block/qcow2.c b/block/qcow2.c index 3090538897..555627a35b 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -2411,21 +2411,74 @@ finish: return ret; } + +static bool is_zero_cluster(BlockDriverState *bs, int64_t start) +{ + BDRVQcow2State *s = bs->opaque; + int nr; + BlockDriverState *file; + int64_t res = bdrv_get_block_status_above(bs, NULL, start, + s->cluster_sectors, &nr, &file); + return res >= 0 && ((res & BDRV_BLOCK_ZERO) || !(res & BDRV_BLOCK_DATA)); +} + +static bool is_zero_cluster_top_locked(BlockDriverState *bs, int64_t start) +{ + BDRVQcow2State *s = bs->opaque; + int nr = s->cluster_sectors; + uint64_t off; + int ret; + + ret = qcow2_get_cluster_offset(bs, start << BDRV_SECTOR_BITS, &nr, &off); + return ret == QCOW2_CLUSTER_UNALLOCATED || ret == QCOW2_CLUSTER_ZERO; +} + static coroutine_fn int qcow2_co_write_zeroes(BlockDriverState *bs, int64_t sector_num, int nb_sectors, BdrvRequestFlags flags) { int ret; BDRVQcow2State *s = bs->opaque; - /* Emulate misaligned zero writes */ - if (sector_num % s->cluster_sectors || nb_sectors % s->cluster_sectors) { - return -ENOTSUP; + int head = sector_num % s->cluster_sectors; + int tail = (sector_num + nb_sectors) % s->cluster_sectors; + + if (head != 0 || tail != 0) { + int64_t cl_end = -1; + + sector_num -= head; + nb_sectors += head; + + if (tail != 0) { + nb_sectors += s->cluster_sectors - tail; + } + + if (!is_zero_cluster(bs, sector_num)) { + return -ENOTSUP; + } + + if (nb_sectors > s->cluster_sectors) { + /* Technically the request can cover 2 clusters, f.e. 4k write + at s->cluster_sectors - 2k offset. One of these cluster can + be zeroed, one unallocated */ + cl_end = sector_num + nb_sectors - s->cluster_sectors; + if (!is_zero_cluster(bs, cl_end)) { + return -ENOTSUP; + } + } + + qemu_co_mutex_lock(&s->lock); + /* We can have new write after previous check */ + if (!is_zero_cluster_top_locked(bs, sector_num) || + (cl_end > 0 && !is_zero_cluster_top_locked(bs, cl_end))) { + qemu_co_mutex_unlock(&s->lock); + return -ENOTSUP; + } + } else { + qemu_co_mutex_lock(&s->lock); } /* Whatever is left can use real zero clusters */ - qemu_co_mutex_lock(&s->lock); - ret = qcow2_zero_clusters(bs, sector_num << BDRV_SECTOR_BITS, - nb_sectors); + ret = qcow2_zero_clusters(bs, sector_num << BDRV_SECTOR_BITS, nb_sectors); qemu_co_mutex_unlock(&s->lock); return ret; -- cgit v1.2.3 From 4df863f336b76faf55f796eed7cd7f7c55ec0130 Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Tue, 3 May 2016 16:39:06 -0600 Subject: block: Make supported_write_flags a per-bds property Pre-patch, .supported_write_flags lives at the driver level, which means we are blindly declaring that all block devices using a given driver will either equally support FUA, or that we need a fallback at the block layer. But there are drivers where FUA support is a per-block decision: the NBD block driver is dependent on the remote server advertising NBD_FLAG_SEND_FUA (and has fallback code to duplicate the flush that the block layer would do if NBD had not set .supported_write_flags); and the iscsi block driver is dependent on the mode sense bits advertised by the underlying device (and is currently silently ignoring FUA requests if the underlying device does not support FUA). The fix is to make supported flags as a per-BDS option, set during .bdrv_open(). This patch moves the variable and fixes NBD and iscsi to set it only conditionally; later patches will then further simplify the NBD driver to quit duplicating work done at the block layer, as well as tackle the fact that SCSI does not support FUA semantics on WRITESAME(10/16) but only on WRITE(10/16). Signed-off-by: Eric Blake Reviewed-by: Fam Zheng Acked-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf --- block/io.c | 9 ++++----- block/iscsi.c | 10 +++++++--- block/nbd-client.c | 3 +++ block/nbd.c | 3 --- block/raw_bsd.c | 2 +- include/block/block_int.h | 4 ++-- 6 files changed, 17 insertions(+), 14 deletions(-) diff --git a/block/io.c b/block/io.c index 0db1146159..1fb7afeaf0 100644 --- a/block/io.c +++ b/block/io.c @@ -841,9 +841,10 @@ static int coroutine_fn bdrv_driver_pwritev(BlockDriverState *bs, if (drv->bdrv_co_writev_flags) { ret = drv->bdrv_co_writev_flags(bs, sector_num, nb_sectors, qiov, - flags); + flags & bs->supported_write_flags); + flags &= ~bs->supported_write_flags; } else if (drv->bdrv_co_writev) { - assert(drv->supported_write_flags == 0); + assert(!bs->supported_write_flags); ret = drv->bdrv_co_writev(bs, sector_num, nb_sectors, qiov); } else { BlockAIOCB *acb; @@ -862,9 +863,7 @@ static int coroutine_fn bdrv_driver_pwritev(BlockDriverState *bs, } emulate_flags: - if (ret == 0 && (flags & BDRV_REQ_FUA) && - !(drv->supported_write_flags & BDRV_REQ_FUA)) - { + if (ret == 0 && (flags & BDRV_REQ_FUA)) { ret = bdrv_co_flush(bs); } diff --git a/block/iscsi.c b/block/iscsi.c index 4f7520463e..6d5c1f6ceb 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -456,8 +456,11 @@ iscsi_co_writev_flags(BlockDriverState *bs, int64_t sector_num, int nb_sectors, struct IscsiTask iTask; uint64_t lba; uint32_t num_sectors; - bool fua; + bool fua = flags & BDRV_REQ_FUA; + if (fua) { + assert(iscsilun->dpofua); + } if (!is_request_lun_aligned(sector_num, nb_sectors, iscsilun)) { return -EINVAL; } @@ -472,7 +475,6 @@ iscsi_co_writev_flags(BlockDriverState *bs, int64_t sector_num, int nb_sectors, num_sectors = sector_qemu2lun(nb_sectors, iscsilun); iscsi_co_init_iscsitask(iscsilun, &iTask); retry: - fua = iscsilun->dpofua && (flags & BDRV_REQ_FUA); if (iscsilun->use_16_for_rw) { iTask.task = iscsi_write16_task(iscsilun->iscsi, iscsilun->lun, lba, NULL, num_sectors * iscsilun->block_size, @@ -1548,6 +1550,9 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags, task = NULL; iscsi_modesense_sync(iscsilun); + if (iscsilun->dpofua) { + bs->supported_write_flags = BDRV_REQ_FUA; + } /* Check the write protect flag of the LUN if we want to write */ if (iscsilun->type == TYPE_DISK && (flags & BDRV_O_RDWR) && @@ -1841,7 +1846,6 @@ static BlockDriver bdrv_iscsi = { .bdrv_co_write_zeroes = iscsi_co_write_zeroes, .bdrv_co_readv = iscsi_co_readv, .bdrv_co_writev_flags = iscsi_co_writev_flags, - .supported_write_flags = BDRV_REQ_FUA, .bdrv_co_flush_to_disk = iscsi_co_flush, #ifdef __linux__ diff --git a/block/nbd-client.c b/block/nbd-client.c index 878e879ace..5fc96e9856 100644 --- a/block/nbd-client.c +++ b/block/nbd-client.c @@ -414,6 +414,9 @@ int nbd_client_init(BlockDriverState *bs, logout("Failed to negotiate with the NBD server\n"); return ret; } + if (client->nbdflags & NBD_FLAG_SEND_FUA) { + bs->supported_write_flags = BDRV_REQ_FUA; + } qemu_co_mutex_init(&client->send_mutex); qemu_co_mutex_init(&client->free_sema); diff --git a/block/nbd.c b/block/nbd.c index fccbfef585..a4fba911c3 100644 --- a/block/nbd.c +++ b/block/nbd.c @@ -471,7 +471,6 @@ static BlockDriver bdrv_nbd = { .bdrv_file_open = nbd_open, .bdrv_co_readv = nbd_co_readv, .bdrv_co_writev_flags = nbd_co_writev_flags, - .supported_write_flags = BDRV_REQ_FUA, .bdrv_close = nbd_close, .bdrv_co_flush_to_os = nbd_co_flush, .bdrv_co_discard = nbd_co_discard, @@ -490,7 +489,6 @@ static BlockDriver bdrv_nbd_tcp = { .bdrv_file_open = nbd_open, .bdrv_co_readv = nbd_co_readv, .bdrv_co_writev_flags = nbd_co_writev_flags, - .supported_write_flags = BDRV_REQ_FUA, .bdrv_close = nbd_close, .bdrv_co_flush_to_os = nbd_co_flush, .bdrv_co_discard = nbd_co_discard, @@ -509,7 +507,6 @@ static BlockDriver bdrv_nbd_unix = { .bdrv_file_open = nbd_open, .bdrv_co_readv = nbd_co_readv, .bdrv_co_writev_flags = nbd_co_writev_flags, - .supported_write_flags = BDRV_REQ_FUA, .bdrv_close = nbd_close, .bdrv_co_flush_to_os = nbd_co_flush, .bdrv_co_discard = nbd_co_discard, diff --git a/block/raw_bsd.c b/block/raw_bsd.c index 5e65fb02d4..1a1618ef07 100644 --- a/block/raw_bsd.c +++ b/block/raw_bsd.c @@ -204,6 +204,7 @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags, Error **errp) { bs->sg = bs->file->bs->sg; + bs->supported_write_flags = BDRV_REQ_FUA; if (bs->probed && !bdrv_is_read_only(bs)) { fprintf(stderr, @@ -250,7 +251,6 @@ BlockDriver bdrv_raw = { .bdrv_create = &raw_create, .bdrv_co_readv = &raw_co_readv, .bdrv_co_writev_flags = &raw_co_writev_flags, - .supported_write_flags = BDRV_REQ_FUA, .bdrv_co_write_zeroes = &raw_co_write_zeroes, .bdrv_co_discard = &raw_co_discard, .bdrv_co_get_block_status = &raw_co_get_block_status, diff --git a/include/block/block_int.h b/include/block/block_int.h index 6fbe648231..10f4962fe8 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -158,8 +158,6 @@ struct BlockDriver { int coroutine_fn (*bdrv_co_pwritev)(BlockDriverState *bs, uint64_t offset, uint64_t bytes, QEMUIOVector *qiov, int flags); - int supported_write_flags; - /* * Efficiently zero a region of the disk image. Typically an image format * would use a compact metadata representation to implement this. This @@ -445,6 +443,8 @@ struct BlockDriverState { /* Alignment requirement for offset/length of I/O requests */ unsigned int request_alignment; + /* Flags honored during pwrite (so far: BDRV_REQ_FUA) */ + unsigned int supported_write_flags; /* the following member gives a name to every node on the bs graph. */ char node_name[32]; -- cgit v1.2.3 From 465fe887ccdcb62733666f6e91d85e88b7184298 Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Tue, 3 May 2016 16:39:07 -0600 Subject: block: Honor BDRV_REQ_FUA during write_zeroes The block layer has a couple of cases where it can lose Force Unit Access semantics when writing a large block of zeroes, such that the request returns before the zeroes have been guaranteed to land on underlying media. SCSI does not support FUA during WRITESAME(10/16); FUA is only supported if it falls back to WRITE(10/16). But where the underlying device is new enough to not need a fallback, it means that any upper layer request with FUA semantics was silently ignoring BDRV_REQ_FUA. Conversely, NBD has situations where it can support FUA but not ZERO_WRITE; when that happens, the generic block layer fallback to bdrv_driver_pwritev() (or the older bdrv_co_writev() in qemu 2.6) was losing the FUA flag. The problem of losing flags unrelated to ZERO_WRITE has been latent in bdrv_co_do_write_zeroes() since commit aa7bfbff, but back then, it did not matter because there was no FUA flag. It became observable when commit 93f5e6d8 paved the way for flags that can impact correctness, when we should have been using bdrv_co_writev_flags() with modified flags. Compare to commit 9eeb6dd, which got flag manipulation right in bdrv_co_do_zero_pwritev(). Symptoms: I tested with qemu-io with default writethrough cache (which is supposed to use FUA semantics on every write), and targetted an NBD client connected to a server that intentionally did not advertise NBD_FLAG_SEND_FUA. When doing 'write 0 512', the NBD client sent two operations (NBD_CMD_WRITE then NBD_CMD_FLUSH) to get the fallback FUA semantics; but when doing 'write -z 0 512', the NBD client sent only NBD_CMD_WRITE. The fix is do to a cleanup bdrv_co_flush() at the end of the operation if any step in the middle relied on a BDS that does not natively support FUA for that step (note that we don't need to flush after every operation, if the operation is broken into chunks based on bounce-buffer sizing). Each BDS gains a new flag .supported_zero_flags, which parallels the use of .supported_write_flags but only when accessing a zero write operation (the flags MUST be different, because of SCSI having different semantics based on WRITE vs. WRITESAME; and also because BDRV_REQ_MAY_UNMAP only makes sense on zero writes). Also fix some documentation to describe -ENOTSUP semantics, particularly since iscsi depends on those semantics. Down the road, we may want to add a driver where its .bdrv_co_pwritev() honors all three of BDRV_REQ_FUA, BDRV_REQ_ZERO_WRITE, and BDRV_REQ_MAY_UNMAP, and advertise this via bs->supported_write_flags for blocks opened by that driver; such a driver should NOT supply .bdrv_co_write_zeroes nor .supported_zero_flags. But none of the drivers touched in this patch want to do that (the act of writing zeroes is different enough from normal writes to deserve a second callback). Signed-off-by: Eric Blake Reviewed-by: Fam Zheng Acked-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf --- block/io.c | 28 +++++++++++++++++++++++++--- block/iscsi.c | 1 + block/raw-posix.c | 1 + block/raw_bsd.c | 1 + include/block/block_int.h | 7 +++++-- 5 files changed, 33 insertions(+), 5 deletions(-) diff --git a/block/io.c b/block/io.c index 1fb7afeaf0..cd6d71a503 100644 --- a/block/io.c +++ b/block/io.c @@ -652,7 +652,8 @@ int bdrv_write_zeroes(BlockDriverState *bs, int64_t sector_num, * Completely zero out a block device with the help of bdrv_write_zeroes. * The operation is sped up by checking the block status and only writing * zeroes to the device if they currently do not return zeroes. Optional - * flags are passed through to bdrv_write_zeroes (e.g. BDRV_REQ_MAY_UNMAP). + * flags are passed through to bdrv_write_zeroes (e.g. BDRV_REQ_MAY_UNMAP, + * BDRV_REQ_FUA). * * Returns < 0 on error, 0 on success. For error codes see bdrv_write(). */ @@ -1160,6 +1161,7 @@ static int coroutine_fn bdrv_co_do_write_zeroes(BlockDriverState *bs, QEMUIOVector qiov; struct iovec iov = {0}; int ret = 0; + bool need_flush = false; int max_write_zeroes = MIN_NON_ZERO(bs->bl.max_write_zeroes, BDRV_REQUEST_MAX_SECTORS); @@ -1192,13 +1194,29 @@ static int coroutine_fn bdrv_co_do_write_zeroes(BlockDriverState *bs, ret = -ENOTSUP; /* First try the efficient write zeroes operation */ if (drv->bdrv_co_write_zeroes) { - ret = drv->bdrv_co_write_zeroes(bs, sector_num, num, flags); + ret = drv->bdrv_co_write_zeroes(bs, sector_num, num, + flags & bs->supported_zero_flags); + if (ret != -ENOTSUP && (flags & BDRV_REQ_FUA) && + !(bs->supported_zero_flags & BDRV_REQ_FUA)) { + need_flush = true; + } + } else { + assert(!bs->supported_zero_flags); } if (ret == -ENOTSUP) { /* Fall back to bounce buffer if write zeroes is unsupported */ int max_xfer_len = MIN_NON_ZERO(bs->bl.max_transfer_length, MAX_WRITE_ZEROES_BOUNCE_BUFFER); + BdrvRequestFlags write_flags = flags & ~BDRV_REQ_ZERO_WRITE; + + if ((flags & BDRV_REQ_FUA) && + !(bs->supported_write_flags & BDRV_REQ_FUA)) { + /* No need for bdrv_driver_pwrite() to do a fallback + * flush on each chunk; use just one at the end */ + write_flags &= ~BDRV_REQ_FUA; + need_flush = true; + } num = MIN(num, max_xfer_len); iov.iov_len = num * BDRV_SECTOR_SIZE; if (iov.iov_base == NULL) { @@ -1212,7 +1230,8 @@ static int coroutine_fn bdrv_co_do_write_zeroes(BlockDriverState *bs, qemu_iovec_init_external(&qiov, &iov, 1); ret = bdrv_driver_pwritev(bs, sector_num * BDRV_SECTOR_SIZE, - num * BDRV_SECTOR_SIZE, &qiov, 0); + num * BDRV_SECTOR_SIZE, &qiov, + write_flags); /* Keep bounce buffer around if it is big enough for all * all future requests. @@ -1228,6 +1247,9 @@ static int coroutine_fn bdrv_co_do_write_zeroes(BlockDriverState *bs, } fail: + if (ret == 0 && need_flush) { + ret = bdrv_co_flush(bs); + } qemu_vfree(iov.iov_base); return ret; } diff --git a/block/iscsi.c b/block/iscsi.c index 6d5c1f6ceb..10f3906bcc 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -1553,6 +1553,7 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags, if (iscsilun->dpofua) { bs->supported_write_flags = BDRV_REQ_FUA; } + bs->supported_zero_flags = BDRV_REQ_MAY_UNMAP; /* Check the write protect flag of the LUN if we want to write */ if (iscsilun->type == TYPE_DISK && (flags & BDRV_O_RDWR) && diff --git a/block/raw-posix.c b/block/raw-posix.c index 71ec463b71..a4f5a1ba5f 100644 --- a/block/raw-posix.c +++ b/block/raw-posix.c @@ -517,6 +517,7 @@ static int raw_open_common(BlockDriverState *bs, QDict *options, s->has_discard = true; s->has_write_zeroes = true; + bs->supported_zero_flags = BDRV_REQ_MAY_UNMAP; if ((bs->open_flags & BDRV_O_NOCACHE) != 0) { s->needs_alignment = true; } diff --git a/block/raw_bsd.c b/block/raw_bsd.c index 1a1618ef07..3385ed448d 100644 --- a/block/raw_bsd.c +++ b/block/raw_bsd.c @@ -205,6 +205,7 @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags, { bs->sg = bs->file->bs->sg; bs->supported_write_flags = BDRV_REQ_FUA; + bs->supported_zero_flags = BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP; if (bs->probed && !bdrv_is_read_only(bs)) { fprintf(stderr, diff --git a/include/block/block_int.h b/include/block/block_int.h index 10f4962fe8..2709488ff1 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -161,8 +161,8 @@ struct BlockDriver { /* * Efficiently zero a region of the disk image. Typically an image format * would use a compact metadata representation to implement this. This - * function pointer may be NULL and .bdrv_co_writev() will be called - * instead. + * function pointer may be NULL or return -ENOSUP and .bdrv_co_writev() + * will be called instead. */ int coroutine_fn (*bdrv_co_write_zeroes)(BlockDriverState *bs, int64_t sector_num, int nb_sectors, BdrvRequestFlags flags); @@ -445,6 +445,9 @@ struct BlockDriverState { unsigned int request_alignment; /* Flags honored during pwrite (so far: BDRV_REQ_FUA) */ unsigned int supported_write_flags; + /* Flags honored during write_zeroes (so far: BDRV_REQ_FUA, + * BDRV_REQ_MAY_UNMAP) */ + unsigned int supported_zero_flags; /* the following member gives a name to every node on the bs graph. */ char node_name[32]; -- cgit v1.2.3 From 52a46505742cce4b4b7f88d32636f848287e6bfb Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Tue, 3 May 2016 16:39:08 -0600 Subject: nbd: Simplify client FUA handling Now that the block layer honors per-bds FUA support, we don't have to duplicate the fallback flush at the NBD layer. The static function nbd_co_writev_flags() is no longer needed, and the driver can just directly use nbd_client_co_writev(). Signed-off-by: Eric Blake Reviewed-by: Fam Zheng Acked-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf --- block/nbd-client.c | 8 ++++---- block/nbd-client.h | 2 +- block/nbd.c | 25 +++---------------------- 3 files changed, 8 insertions(+), 27 deletions(-) diff --git a/block/nbd-client.c b/block/nbd-client.c index 5fc96e9856..4d13444409 100644 --- a/block/nbd-client.c +++ b/block/nbd-client.c @@ -243,15 +243,15 @@ static int nbd_co_readv_1(BlockDriverState *bs, int64_t sector_num, static int nbd_co_writev_1(BlockDriverState *bs, int64_t sector_num, int nb_sectors, QEMUIOVector *qiov, - int offset, int *flags) + int offset, int flags) { NbdClientSession *client = nbd_get_client_session(bs); struct nbd_request request = { .type = NBD_CMD_WRITE }; struct nbd_reply reply; ssize_t ret; - if ((*flags & BDRV_REQ_FUA) && (client->nbdflags & NBD_FLAG_SEND_FUA)) { - *flags &= ~BDRV_REQ_FUA; + if (flags & BDRV_REQ_FUA) { + assert(client->nbdflags & NBD_FLAG_SEND_FUA); request.type |= NBD_CMD_FLAG_FUA; } @@ -291,7 +291,7 @@ int nbd_client_co_readv(BlockDriverState *bs, int64_t sector_num, } int nbd_client_co_writev(BlockDriverState *bs, int64_t sector_num, - int nb_sectors, QEMUIOVector *qiov, int *flags) + int nb_sectors, QEMUIOVector *qiov, int flags) { int offset = 0; int ret; diff --git a/block/nbd-client.h b/block/nbd-client.h index bc7aec0795..c618dadc39 100644 --- a/block/nbd-client.h +++ b/block/nbd-client.h @@ -48,7 +48,7 @@ int nbd_client_co_discard(BlockDriverState *bs, int64_t sector_num, int nb_sectors); int nbd_client_co_flush(BlockDriverState *bs); int nbd_client_co_writev(BlockDriverState *bs, int64_t sector_num, - int nb_sectors, QEMUIOVector *qiov, int *flags); + int nb_sectors, QEMUIOVector *qiov, int flags); int nbd_client_co_readv(BlockDriverState *bs, int64_t sector_num, int nb_sectors, QEMUIOVector *qiov); diff --git a/block/nbd.c b/block/nbd.c index a4fba911c3..6015e8b537 100644 --- a/block/nbd.c +++ b/block/nbd.c @@ -355,25 +355,6 @@ static int nbd_co_readv(BlockDriverState *bs, int64_t sector_num, return nbd_client_co_readv(bs, sector_num, nb_sectors, qiov); } -static int nbd_co_writev_flags(BlockDriverState *bs, int64_t sector_num, - int nb_sectors, QEMUIOVector *qiov, int flags) -{ - int ret; - - ret = nbd_client_co_writev(bs, sector_num, nb_sectors, qiov, &flags); - if (ret < 0) { - return ret; - } - - /* The flag wasn't sent to the server, so we need to emulate it with an - * explicit flush */ - if (flags & BDRV_REQ_FUA) { - ret = nbd_client_co_flush(bs); - } - - return ret; -} - static int nbd_co_flush(BlockDriverState *bs) { return nbd_client_co_flush(bs); @@ -470,7 +451,7 @@ static BlockDriver bdrv_nbd = { .bdrv_parse_filename = nbd_parse_filename, .bdrv_file_open = nbd_open, .bdrv_co_readv = nbd_co_readv, - .bdrv_co_writev_flags = nbd_co_writev_flags, + .bdrv_co_writev_flags = nbd_client_co_writev, .bdrv_close = nbd_close, .bdrv_co_flush_to_os = nbd_co_flush, .bdrv_co_discard = nbd_co_discard, @@ -488,7 +469,7 @@ static BlockDriver bdrv_nbd_tcp = { .bdrv_parse_filename = nbd_parse_filename, .bdrv_file_open = nbd_open, .bdrv_co_readv = nbd_co_readv, - .bdrv_co_writev_flags = nbd_co_writev_flags, + .bdrv_co_writev_flags = nbd_client_co_writev, .bdrv_close = nbd_close, .bdrv_co_flush_to_os = nbd_co_flush, .bdrv_co_discard = nbd_co_discard, @@ -506,7 +487,7 @@ static BlockDriver bdrv_nbd_unix = { .bdrv_parse_filename = nbd_parse_filename, .bdrv_file_open = nbd_open, .bdrv_co_readv = nbd_co_readv, - .bdrv_co_writev_flags = nbd_co_writev_flags, + .bdrv_co_writev_flags = nbd_client_co_writev, .bdrv_close = nbd_close, .bdrv_co_flush_to_os = nbd_co_flush, .bdrv_co_discard = nbd_co_discard, -- cgit v1.2.3 From 0d1c5c91607d1c55a8f5db39c57c6e5c76e21131 Mon Sep 17 00:00:00 2001 From: Fam Zheng Date: Wed, 11 May 2016 10:45:33 +0800 Subject: block: Invalidate all children Currently we only recurse to bs->file, which will miss the children in quorum and VMDK. Recurse into the whole subtree to avoid that. Signed-off-by: Fam Zheng Reviewed-by: Alberto Garcia Signed-off-by: Kevin Wolf --- block.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/block.c b/block.c index d70ae55e2a..71b523cc3e 100644 --- a/block.c +++ b/block.c @@ -3198,6 +3198,7 @@ void bdrv_init_with_whitelist(void) void bdrv_invalidate_cache(BlockDriverState *bs, Error **errp) { + BdrvChild *child; Error *local_err = NULL; int ret; @@ -3212,13 +3213,20 @@ void bdrv_invalidate_cache(BlockDriverState *bs, Error **errp) if (bs->drv->bdrv_invalidate_cache) { bs->drv->bdrv_invalidate_cache(bs, &local_err); - } else if (bs->file) { - bdrv_invalidate_cache(bs->file->bs, &local_err); + if (local_err) { + bs->open_flags |= BDRV_O_INACTIVE; + error_propagate(errp, local_err); + return; + } } - if (local_err) { - bs->open_flags |= BDRV_O_INACTIVE; - error_propagate(errp, local_err); - return; + + QLIST_FOREACH(child, &bs->children, next) { + bdrv_invalidate_cache(child->bs, &local_err); + if (local_err) { + bs->open_flags |= BDRV_O_INACTIVE; + error_propagate(errp, local_err); + return; + } } ret = refresh_total_sectors(bs, bs->total_sectors); -- cgit v1.2.3 From c9e9e9c66cee9932fb28a41a4659aa421a7a3f78 Mon Sep 17 00:00:00 2001 From: Fam Zheng Date: Wed, 11 May 2016 10:45:34 +0800 Subject: block: Drop superfluous invalidating bs->file from drivers Now they are invalidated by the block layer, so it's not necessary to do this in block drivers' implementations of .bdrv_invalidate_cache. Signed-off-by: Fam Zheng Reviewed-by: Alberto Garcia Signed-off-by: Kevin Wolf --- block/qcow2.c | 7 ------- block/qed.c | 6 ------ block/quorum.c | 16 ---------------- 3 files changed, 29 deletions(-) diff --git a/block/qcow2.c b/block/qcow2.c index 555627a35b..62febfc386 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -1757,13 +1757,6 @@ static void qcow2_invalidate_cache(BlockDriverState *bs, Error **errp) qcow2_close(bs); - bdrv_invalidate_cache(bs->file->bs, &local_err); - if (local_err) { - error_propagate(errp, local_err); - bs->drv = NULL; - return; - } - memset(s, 0, sizeof(BDRVQcow2State)); options = qdict_clone_shallow(bs->options); diff --git a/block/qed.c b/block/qed.c index 6cfd4c1c11..10ce18eb66 100644 --- a/block/qed.c +++ b/block/qed.c @@ -1594,12 +1594,6 @@ static void bdrv_qed_invalidate_cache(BlockDriverState *bs, Error **errp) bdrv_qed_close(bs); - bdrv_invalidate_cache(bs->file->bs, &local_err); - if (local_err) { - error_propagate(errp, local_err); - return; - } - memset(s, 0, sizeof(BDRVQEDState)); ret = bdrv_qed_open(bs, NULL, bs->open_flags, &local_err); if (local_err) { diff --git a/block/quorum.c b/block/quorum.c index da15465a9a..8f7c0992a2 100644 --- a/block/quorum.c +++ b/block/quorum.c @@ -747,21 +747,6 @@ static int64_t quorum_getlength(BlockDriverState *bs) return result; } -static void quorum_invalidate_cache(BlockDriverState *bs, Error **errp) -{ - BDRVQuorumState *s = bs->opaque; - Error *local_err = NULL; - int i; - - for (i = 0; i < s->num_children; i++) { - bdrv_invalidate_cache(s->children[i]->bs, &local_err); - if (local_err) { - error_propagate(errp, local_err); - return; - } - } -} - static coroutine_fn int quorum_co_flush(BlockDriverState *bs) { BDRVQuorumState *s = bs->opaque; @@ -1070,7 +1055,6 @@ static BlockDriver bdrv_quorum = { .bdrv_aio_readv = quorum_aio_readv, .bdrv_aio_writev = quorum_aio_writev, - .bdrv_invalidate_cache = quorum_invalidate_cache, .bdrv_detach_aio_context = quorum_detach_aio_context, .bdrv_attach_aio_context = quorum_attach_aio_context, -- cgit v1.2.3 From aad0b7a0bfbd6d200f617396c0d3b71ac7abfa40 Mon Sep 17 00:00:00 2001 From: Fam Zheng Date: Wed, 11 May 2016 10:45:35 +0800 Subject: block: Inactivate all children Currently we only inactivate the top BDS. Actually bdrv_inactivate should be the opposite of bdrv_invalidate_cache. Recurse into the whole subtree instead. Because a node may have multiple parents, and because once BDRV_O_INACTIVE is set for a node, further writes are not allowed, we cannot interleave flag settings and .bdrv_inactivate calls (that may submit write to other nodes in a graph) within a single pass. Therefore two passes are used here. Signed-off-by: Fam Zheng Signed-off-by: Kevin Wolf --- block.c | 47 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 36 insertions(+), 11 deletions(-) diff --git a/block.c b/block.c index 71b523cc3e..724b3b2db5 100644 --- a/block.c +++ b/block.c @@ -3255,38 +3255,63 @@ void bdrv_invalidate_cache_all(Error **errp) } } -static int bdrv_inactivate(BlockDriverState *bs) +static int bdrv_inactivate_recurse(BlockDriverState *bs, + bool setting_flag) { + BdrvChild *child; int ret; - if (bs->drv->bdrv_inactivate) { + if (!setting_flag && bs->drv->bdrv_inactivate) { ret = bs->drv->bdrv_inactivate(bs); if (ret < 0) { return ret; } } - bs->open_flags |= BDRV_O_INACTIVE; + QLIST_FOREACH(child, &bs->children, next) { + ret = bdrv_inactivate_recurse(child->bs, setting_flag); + if (ret < 0) { + return ret; + } + } + + if (setting_flag) { + bs->open_flags |= BDRV_O_INACTIVE; + } return 0; } int bdrv_inactivate_all(void) { BlockDriverState *bs = NULL; - int ret; + int ret = 0; + int pass; while ((bs = bdrv_next(bs)) != NULL) { - AioContext *aio_context = bdrv_get_aio_context(bs); + aio_context_acquire(bdrv_get_aio_context(bs)); + } - aio_context_acquire(aio_context); - ret = bdrv_inactivate(bs); - aio_context_release(aio_context); - if (ret < 0) { - return ret; + /* We do two passes of inactivation. The first pass calls to drivers' + * .bdrv_inactivate callbacks recursively so all cache is flushed to disk; + * the second pass sets the BDRV_O_INACTIVE flag so that no further write + * is allowed. */ + for (pass = 0; pass < 2; pass++) { + bs = NULL; + while ((bs = bdrv_next(bs)) != NULL) { + ret = bdrv_inactivate_recurse(bs, pass); + if (ret < 0) { + goto out; + } } } - return 0; +out: + bs = NULL; + while ((bs = bdrv_next(bs)) != NULL) { + aio_context_release(bdrv_get_aio_context(bs)); + } + + return ret; } /**************************************************************/ -- cgit v1.2.3 From 9036e87c7437388365a419a5f26445eb7809b941 Mon Sep 17 00:00:00 2001 From: Wei Jiangang Date: Tue, 26 Apr 2016 18:13:21 +0800 Subject: iotests: fix the redirection order in 083 It should redirect stdout to /dev/null first, then redirect stderr to whatever stdout currently points at. Signed-off-by: Wei Jiangang Message-id: 1461665601-14908-1-git-send-email-weijg.fnst@cn.fujitsu.com Reviewed-by: Eric Blake Signed-off-by: Max Reitz --- tests/qemu-iotests/083 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/qemu-iotests/083 b/tests/qemu-iotests/083 index bc724ae058..bff9360048 100755 --- a/tests/qemu-iotests/083 +++ b/tests/qemu-iotests/083 @@ -43,7 +43,7 @@ choose_tcp_port() { wait_for_tcp_port() { while ! (netstat --tcp --listening --numeric | \ - grep "$1.*0\\.0\\.0\\.0:\\*.*LISTEN") 2>&1 >/dev/null; do + grep "$1.*0\\.0\\.0\\.0:\\*.*LISTEN") >/dev/null 2>&1; do sleep 0.1 done } @@ -70,7 +70,7 @@ EOF nbd_url="nbd:127.0.0.1:$port:exportname=foo" fi - $PYTHON nbd-fault-injector.py $extra_args "127.0.0.1:$port" "$TEST_DIR/nbd-fault-injector.conf" 2>&1 >/dev/null & + $PYTHON nbd-fault-injector.py $extra_args "127.0.0.1:$port" "$TEST_DIR/nbd-fault-injector.conf" >/dev/null 2>&1 & wait_for_tcp_port "127\\.0\\.0\\.1:$port" $QEMU_IO -c "read 0 512" "$nbd_url" 2>&1 | _filter_qemu_io | _filter_nbd -- cgit v1.2.3 From 263a6f4c3aa9b6cd9f58d1368b318d948156a4e8 Mon Sep 17 00:00:00 2001 From: Ren Kimura Date: Thu, 28 Apr 2016 01:04:58 +0900 Subject: qemu-img: check block status of backing file when converting. When converting images, check the block status of its backing file chain to avoid needlessly reading zeros. Signed-off-by: Ren Kimura Message-id: 1461773098-20356-1-git-send-email-rkx1209dev@gmail.com Signed-off-by: Max Reitz --- qemu-img.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/qemu-img.c b/qemu-img.c index 491a460ecf..47923663be 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -1475,10 +1475,21 @@ static int convert_iteration_sectors(ImgConvertState *s, int64_t sector_num) } else if (!s->target_has_backing) { /* Without a target backing file we must copy over the contents of * the backing file as well. */ - /* TODO Check block status of the backing file chain to avoid + /* Check block status of the backing file chain to avoid * needlessly reading zeroes and limiting the iteration to the * buffer size */ - s->status = BLK_DATA; + ret = bdrv_get_block_status_above(blk_bs(s->src[s->src_cur]), NULL, + sector_num - s->src_cur_offset, + n, &n, &file); + if (ret < 0) { + return ret; + } + + if (ret & BDRV_BLOCK_ZERO) { + s->status = BLK_ZERO; + } else { + s->status = BLK_DATA; + } } else { s->status = BLK_BACKING_FILE; } -- cgit v1.2.3 From e06018ad28874703c65dbdcfa4a5cb8aed4550ec Mon Sep 17 00:00:00 2001 From: Wen Congyang Date: Tue, 10 May 2016 15:36:37 +0800 Subject: Add new block driver interface to add/delete a BDS's child In some cases, we want to take a quorum child offline, and take another child online. Signed-off-by: Wen Congyang Signed-off-by: zhanghailiang Signed-off-by: Gonglei Signed-off-by: Changlong Xie Reviewed-by: Max Reitz Reviewed-by: Alberto Garcia Message-id: 1462865799-19402-2-git-send-email-xiecl.fnst@cn.fujitsu.com Signed-off-by: Max Reitz --- block.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++ include/block/block.h | 4 ++++ include/block/block_int.h | 5 +++++ 3 files changed, 58 insertions(+) diff --git a/block.c b/block.c index 724b3b2db5..0726dab8d0 100644 --- a/block.c +++ b/block.c @@ -4011,3 +4011,52 @@ void bdrv_refresh_filename(BlockDriverState *bs) QDECREF(json); } } + +/* + * Hot add/remove a BDS's child. So the user can take a child offline when + * it is broken and take a new child online + */ +void bdrv_add_child(BlockDriverState *parent_bs, BlockDriverState *child_bs, + Error **errp) +{ + + if (!parent_bs->drv || !parent_bs->drv->bdrv_add_child) { + error_setg(errp, "The node %s does not support adding a child", + bdrv_get_device_or_node_name(parent_bs)); + return; + } + + if (!QLIST_EMPTY(&child_bs->parents)) { + error_setg(errp, "The node %s already has a parent", + child_bs->node_name); + return; + } + + parent_bs->drv->bdrv_add_child(parent_bs, child_bs, errp); +} + +void bdrv_del_child(BlockDriverState *parent_bs, BdrvChild *child, Error **errp) +{ + BdrvChild *tmp; + + if (!parent_bs->drv || !parent_bs->drv->bdrv_del_child) { + error_setg(errp, "The node %s does not support removing a child", + bdrv_get_device_or_node_name(parent_bs)); + return; + } + + QLIST_FOREACH(tmp, &parent_bs->children, next) { + if (tmp == child) { + break; + } + } + + if (!tmp) { + error_setg(errp, "The node %s does not have a child named %s", + bdrv_get_device_or_node_name(parent_bs), + bdrv_get_device_or_node_name(child->bs)); + return; + } + + parent_bs->drv->bdrv_del_child(parent_bs, child, errp); +} diff --git a/include/block/block.h b/include/block/block.h index 0e8b4d1341..c44d0a065c 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -542,4 +542,8 @@ void bdrv_drained_begin(BlockDriverState *bs); */ void bdrv_drained_end(BlockDriverState *bs); +void bdrv_add_child(BlockDriverState *parent, BlockDriverState *child, + Error **errp); +void bdrv_del_child(BlockDriverState *parent, BdrvChild *child, Error **errp); + #endif diff --git a/include/block/block_int.h b/include/block/block_int.h index 2709488ff1..a029c2003f 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -314,6 +314,11 @@ struct BlockDriver { */ void (*bdrv_drain)(BlockDriverState *bs); + void (*bdrv_add_child)(BlockDriverState *parent, BlockDriverState *child, + Error **errp); + void (*bdrv_del_child)(BlockDriverState *parent, BdrvChild *child, + Error **errp); + QLIST_ENTRY(BlockDriver) list; }; -- cgit v1.2.3 From 98292c61bc491b660c9fa2ccbdbb35131921ea65 Mon Sep 17 00:00:00 2001 From: Wen Congyang Date: Tue, 10 May 2016 15:36:38 +0800 Subject: quorum: implement bdrv_add_child() and bdrv_del_child() Signed-off-by: Wen Congyang Signed-off-by: zhanghailiang Signed-off-by: Gonglei Signed-off-by: Changlong Xie Message-id: 1462865799-19402-3-git-send-email-xiecl.fnst@cn.fujitsu.com Reviewed-by: Alberto Garcia Reviewed-by: Max Reitz Signed-off-by: Max Reitz --- block.c | 8 +++--- block/quorum.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++-- include/block/block.h | 4 +++ 3 files changed, 84 insertions(+), 6 deletions(-) diff --git a/block.c b/block.c index 0726dab8d0..18a497f69d 100644 --- a/block.c +++ b/block.c @@ -1174,10 +1174,10 @@ BdrvChild *bdrv_root_attach_child(BlockDriverState *child_bs, return child; } -static BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs, - BlockDriverState *child_bs, - const char *child_name, - const BdrvChildRole *child_role) +BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs, + BlockDriverState *child_bs, + const char *child_name, + const BdrvChildRole *child_role) { BdrvChild *child = bdrv_root_attach_child(child_bs, child_name, child_role); QLIST_INSERT_HEAD(&parent_bs->children, child, next); diff --git a/block/quorum.c b/block/quorum.c index 8f7c0992a2..1ec3511528 100644 --- a/block/quorum.c +++ b/block/quorum.c @@ -14,6 +14,7 @@ */ #include "qemu/osdep.h" +#include "qemu/cutils.h" #include "block/block_int.h" #include "qapi/qmp/qbool.h" #include "qapi/qmp/qdict.h" @@ -67,6 +68,9 @@ typedef struct QuorumVotes { typedef struct BDRVQuorumState { BdrvChild **children; /* children BlockDriverStates */ int num_children; /* children count */ + unsigned next_child_index; /* the index of the next child that should + * be added + */ int threshold; /* if less than threshold children reads gave the * same result a quorum error occurs. */ @@ -883,9 +887,9 @@ static int quorum_open(BlockDriverState *bs, QDict *options, int flags, ret = -EINVAL; goto exit; } - if (s->num_children < 2) { + if (s->num_children < 1) { error_setg(&local_err, - "Number of provided children must be greater than 1"); + "Number of provided children must be 1 or more"); ret = -EINVAL; goto exit; } @@ -949,6 +953,7 @@ static int quorum_open(BlockDriverState *bs, QDict *options, int flags, opened[i] = true; } + s->next_child_index = s->num_children; g_free(opened); goto exit; @@ -1005,6 +1010,72 @@ static void quorum_attach_aio_context(BlockDriverState *bs, } } +static void quorum_add_child(BlockDriverState *bs, BlockDriverState *child_bs, + Error **errp) +{ + BDRVQuorumState *s = bs->opaque; + BdrvChild *child; + char indexstr[32]; + int ret; + + assert(s->num_children <= INT_MAX / sizeof(BdrvChild *)); + if (s->num_children == INT_MAX / sizeof(BdrvChild *) || + s->next_child_index == UINT_MAX) { + error_setg(errp, "Too many children"); + return; + } + + ret = snprintf(indexstr, 32, "children.%u", s->next_child_index); + if (ret < 0 || ret >= 32) { + error_setg(errp, "cannot generate child name"); + return; + } + s->next_child_index++; + + bdrv_drained_begin(bs); + + /* We can safely add the child now */ + bdrv_ref(child_bs); + child = bdrv_attach_child(bs, child_bs, indexstr, &child_format); + s->children = g_renew(BdrvChild *, s->children, s->num_children + 1); + s->children[s->num_children++] = child; + + bdrv_drained_end(bs); +} + +static void quorum_del_child(BlockDriverState *bs, BdrvChild *child, + Error **errp) +{ + BDRVQuorumState *s = bs->opaque; + int i; + + for (i = 0; i < s->num_children; i++) { + if (s->children[i] == child) { + break; + } + } + + /* we have checked it in bdrv_del_child() */ + assert(i < s->num_children); + + if (s->num_children <= s->threshold) { + error_setg(errp, + "The number of children cannot be lower than the vote threshold %d", + s->threshold); + return; + } + + bdrv_drained_begin(bs); + + /* We can safely remove this child now */ + memmove(&s->children[i], &s->children[i + 1], + (s->num_children - i - 1) * sizeof(BdrvChild *)); + s->children = g_renew(BdrvChild *, s->children, --s->num_children); + bdrv_unref_child(bs, child); + + bdrv_drained_end(bs); +} + static void quorum_refresh_filename(BlockDriverState *bs, QDict *options) { BDRVQuorumState *s = bs->opaque; @@ -1059,6 +1130,9 @@ static BlockDriver bdrv_quorum = { .bdrv_detach_aio_context = quorum_detach_aio_context, .bdrv_attach_aio_context = quorum_attach_aio_context, + .bdrv_add_child = quorum_add_child, + .bdrv_del_child = quorum_del_child, + .is_filter = true, .bdrv_recurse_is_first_non_filter = quorum_recurse_is_first_non_filter, }; diff --git a/include/block/block.h b/include/block/block.h index c44d0a065c..b210832778 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -476,6 +476,10 @@ void bdrv_disable_copy_on_read(BlockDriverState *bs); void bdrv_ref(BlockDriverState *bs); void bdrv_unref(BlockDriverState *bs); void bdrv_unref_child(BlockDriverState *parent, BdrvChild *child); +BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs, + BlockDriverState *child_bs, + const char *child_name, + const BdrvChildRole *child_role); bool bdrv_op_is_blocked(BlockDriverState *bs, BlockOpType op, Error **errp); void bdrv_op_block(BlockDriverState *bs, BlockOpType op, Error *reason); -- cgit v1.2.3 From 7f82159769261419e0f3905cf758cfc4850bb26f Mon Sep 17 00:00:00 2001 From: Wen Congyang Date: Tue, 10 May 2016 15:36:39 +0800 Subject: qmp: add monitor command to add/remove a child The new QMP command name is x-blockdev-change. It's just for adding/removing quorum's child now, and doesn't support all kinds of children, all kinds of operations, nor all block drivers. So it is experimental now. Signed-off-by: Wen Congyang Signed-off-by: zhanghailiang Signed-off-by: Gonglei Signed-off-by: Changlong Xie Reviewed-by: Max Reitz Reviewed-by: Alberto Garcia Message-id: 1462865799-19402-4-git-send-email-xiecl.fnst@cn.fujitsu.com Signed-off-by: Max Reitz --- blockdev.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++ qapi/block-core.json | 32 ++++++++++++++++++++++++++++++ qmp-commands.hx | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 140 insertions(+) diff --git a/blockdev.c b/blockdev.c index f74eb4357a..1892b8ec8e 100644 --- a/blockdev.c +++ b/blockdev.c @@ -4092,6 +4092,61 @@ out: aio_context_release(aio_context); } +static BdrvChild *bdrv_find_child(BlockDriverState *parent_bs, + const char *child_name) +{ + BdrvChild *child; + + QLIST_FOREACH(child, &parent_bs->children, next) { + if (strcmp(child->name, child_name) == 0) { + return child; + } + } + + return NULL; +} + +void qmp_x_blockdev_change(const char *parent, bool has_child, + const char *child, bool has_node, + const char *node, Error **errp) +{ + BlockDriverState *parent_bs, *new_bs = NULL; + BdrvChild *p_child; + + parent_bs = bdrv_lookup_bs(parent, parent, errp); + if (!parent_bs) { + return; + } + + if (has_child == has_node) { + if (has_child) { + error_setg(errp, "The parameters child and node are in conflict"); + } else { + error_setg(errp, "Either child or node must be specified"); + } + return; + } + + if (has_child) { + p_child = bdrv_find_child(parent_bs, child); + if (!p_child) { + error_setg(errp, "Node '%s' does not have child '%s'", + parent, child); + return; + } + bdrv_del_child(parent_bs, p_child, errp); + } + + if (has_node) { + new_bs = bdrv_find_node(node); + if (!new_bs) { + error_setg(errp, "Node '%s' not found", node); + return; + } + bdrv_add_child(parent_bs, new_bs, errp); + } +} + BlockJobInfoList *qmp_query_block_jobs(Error **errp) { BlockJobInfoList *head = NULL, **p_next = &head; diff --git a/qapi/block-core.json b/qapi/block-core.json index 1d09079cc1..98a20d22f4 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -2556,3 +2556,35 @@ ## { 'command': 'block-set-write-threshold', 'data': { 'node-name': 'str', 'write-threshold': 'uint64' } } + +## +# @x-blockdev-change +# +# Dynamically reconfigure the block driver state graph. It can be used +# to add, remove, insert or replace a graph node. Currently only the +# Quorum driver implements this feature to add or remove its child. This +# is useful to fix a broken quorum child. +# +# If @node is specified, it will be inserted under @parent. @child +# may not be specified in this case. If both @parent and @child are +# specified but @node is not, @child will be detached from @parent. +# +# @parent: the id or name of the parent node. +# +# @child: #optional the name of a child under the given parent node. +# +# @node: #optional the name of the node that will be added. +# +# Note: this command is experimental, and its API is not stable. It +# does not support all kinds of operations, all kinds of children, nor +# all block drivers. +# +# Warning: The data in a new quorum child MUST be consistent with that of +# the rest of the array. +# +# Since: 2.7 +## +{ 'command': 'x-blockdev-change', + 'data' : { 'parent': 'str', + '*child': 'str', + '*node': 'str' } } diff --git a/qmp-commands.hx b/qmp-commands.hx index de896a5a31..94847e5b48 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -4395,6 +4395,59 @@ Example: <- { "return": {} } +EQMP + + { + .name = "x-blockdev-change", + .args_type = "parent:B,child:B?,node:B?", + .mhandler.cmd_new = qmp_marshal_x_blockdev_change, + }, + +SQMP +x-blockdev-change +----------------- + +Dynamically reconfigure the block driver state graph. It can be used +to add, remove, insert or replace a graph node. Currently only the +Quorum driver implements this feature to add or remove its child. This +is useful to fix a broken quorum child. + +If @node is specified, it will be inserted under @parent. @child +may not be specified in this case. If both @parent and @child are +specified but @node is not, @child will be detached from @parent. + +Arguments: +- "parent": the id or name of the parent node (json-string) +- "child": the name of a child under the given parent node (json-string, optional) +- "node": the name of the node that will be added (json-string, optional) + +Note: this command is experimental, and not a stable API. It doesn't +support all kinds of operations, all kinds of children, nor all block +drivers. + +Warning: The data in a new quorum child MUST be consistent with that of +the rest of the array. + +Example: + +Add a new node to a quorum +-> { "execute": "blockdev-add", + "arguments": { "options": { "driver": "raw", + "node-name": "new_node", + "file": { "driver": "file", + "filename": "test.raw" } } } } +<- { "return": {} } +-> { "execute": "x-blockdev-change", + "arguments": { "parent": "disk1", + "node": "new_node" } } +<- { "return": {} } + +Delete a quorum's node +-> { "execute": "x-blockdev-change", + "arguments": { "parent": "disk1", + "child": "children.1" } } +<- { "return": {} } + EQMP { -- cgit v1.2.3 From e4e12bb26d9f2e2de02ff888063f41cc1e1b3935 Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Sat, 7 May 2016 21:16:40 -0600 Subject: qemu-io: Add missing option documentation The Usage: summary is missing several options, but rather than having to maintain it, it's simpler to just state [OPTIONS], since the options are spelled out below. Commit 499afa2 added --image-opts, but forgot to document it in --help. Likewise for commit 9e8f183 and -d/--discard. Commit e3aff4f6 put "-o/--offset" in the long opts, but it has never been honored. Add a note that '-n' is short for '-t none'. Commit 9a2d77ad killed the -C option, but forgot to undocument it for the 'open' subcommand. Finally, commit 10d9d75 removed -g/--growable, but forgot to cull it from the valid short options. Signed-off-by: Eric Blake Message-id: 1462677405-4752-2-git-send-email-eblake@redhat.com Reviewed-by: Max Reitz Signed-off-by: Max Reitz --- qemu-io.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/qemu-io.c b/qemu-io.c index 0598251e7c..0a1a3df87f 100644 --- a/qemu-io.c +++ b/qemu-io.c @@ -101,7 +101,7 @@ static void open_help(void) " opens a new file in the requested mode\n" "\n" " Example:\n" -" 'open -Cn /tmp/data' - creates/opens data file read-write and uncached\n" +" 'open -n -o driver=raw /tmp/data' - opens raw data file read-write, uncached\n" "\n" " Opens a file for subsequent use by all of the other qemu-io commands.\n" " -r, -- open file read-only\n" @@ -120,7 +120,7 @@ static const cmdinfo_t open_cmd = { .argmin = 1, .argmax = -1, .flags = CMD_NOFILE_OK, - .args = "[-Crsn] [-o options] [path]", + .args = "[-rsn] [-o options] [path]", .oneline = "open the file specified by path", .help = open_help, }; @@ -144,7 +144,7 @@ static int open_f(BlockBackend *blk, int argc, char **argv) QemuOpts *qopts; QDict *opts; - while ((c = getopt(argc, argv, "snrgo:")) != -1) { + while ((c = getopt(argc, argv, "snro:")) != -1) { switch (c) { case 's': flags |= BDRV_O_SNAPSHOT; @@ -216,20 +216,22 @@ static const cmdinfo_t quit_cmd = { static void usage(const char *name) { printf( -"Usage: %s [-h] [-V] [-rsnm] [-f FMT] [-c STRING] ... [file]\n" +"Usage: %s [OPTIONS]... [-c STRING]... [file]\n" "QEMU Disk exerciser\n" "\n" " --object OBJECTDEF define an object such as 'secret' for\n" " passwords and/or encryption keys\n" +" --image-opts treat file as option string\n" " -c, --cmd STRING execute command with its arguments\n" " from the given string\n" " -f, --format FMT specifies the block driver to use\n" " -r, --read-only export read-only\n" " -s, --snapshot use snapshot file\n" -" -n, --nocache disable host cache\n" +" -n, --nocache disable host cache, short for -t none\n" " -m, --misalign misalign allocations for O_DIRECT\n" " -k, --native-aio use kernel AIO implementation (on Linux only)\n" " -t, --cache=MODE use the given cache mode for the image\n" +" -d, --discard=MODE use the given discard mode for the image\n" " -T, --trace FILE enable trace events listed in the given file\n" " -h, --help display this help and exit\n" " -V, --version output version information and exit\n" @@ -410,11 +412,10 @@ static QemuOptsList file_opts = { int main(int argc, char **argv) { int readonly = 0; - const char *sopt = "hVc:d:f:rsnmgkt:T:"; + const char *sopt = "hVc:d:f:rsnmkt:T:"; const struct option lopt[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'V' }, - { "offset", required_argument, NULL, 'o' }, { "cmd", required_argument, NULL, 'c' }, { "format", required_argument, NULL, 'f' }, { "read-only", no_argument, NULL, 'r' }, -- cgit v1.2.3 From b8d970f1a966b3c46233462879d4d5ab0bdd1712 Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Sat, 7 May 2016 21:16:41 -0600 Subject: qemu-io: Make 'open' subcommand more like command line The command line defaults to BDRV_O_UNMAP, but can use -d to reset it. Meanwhile, the 'open' subcommand was defaulting to no discards, with no way to set it. The command line has both -n and -tMODE to set a variety of cache modes, but the 'open' subcommand had only -n. The 'open' subcommand had no way to set BDRV_O_NATIVE_AIO. Note that the 'reopen' subcommand uses '-c' where the command line and 'open' use -t. Making that consistent would be a separate patch. Signed-off-by: Eric Blake Message-id: 1462677405-4752-3-git-send-email-eblake@redhat.com Reviewed-by: Max Reitz Signed-off-by: Max Reitz --- qemu-io.c | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/qemu-io.c b/qemu-io.c index 0a1a3df87f..5ef3ef7f35 100644 --- a/qemu-io.c +++ b/qemu-io.c @@ -106,7 +106,10 @@ static void open_help(void) " Opens a file for subsequent use by all of the other qemu-io commands.\n" " -r, -- open file read-only\n" " -s, -- use snapshot file\n" -" -n, -- disable host cache\n" +" -n, -- disable host cache, short for -t none\n" +" -k, -- use kernel AIO implementation (on Linux only)\n" +" -t, -- use the given cache mode for the image\n" +" -d, -- use the given discard mode for the image\n" " -o, -- options to be given to the block driver" "\n"); } @@ -120,7 +123,7 @@ static const cmdinfo_t open_cmd = { .argmin = 1, .argmax = -1, .flags = CMD_NOFILE_OK, - .args = "[-rsn] [-o options] [path]", + .args = "[-rsnk] [-t cache] [-d discard] [-o options] [path]", .oneline = "open the file specified by path", .help = open_help, }; @@ -137,14 +140,14 @@ static QemuOptsList empty_opts = { static int open_f(BlockBackend *blk, int argc, char **argv) { - int flags = 0; + int flags = BDRV_O_UNMAP; int readonly = 0; bool writethrough = true; int c; QemuOpts *qopts; QDict *opts; - while ((c = getopt(argc, argv, "snro:")) != -1) { + while ((c = getopt(argc, argv, "snro:kt:d:")) != -1) { switch (c) { case 's': flags |= BDRV_O_SNAPSHOT; @@ -156,9 +159,27 @@ static int open_f(BlockBackend *blk, int argc, char **argv) case 'r': readonly = 1; break; + case 'k': + flags |= BDRV_O_NATIVE_AIO; + break; + case 't': + if (bdrv_parse_cache_mode(optarg, &flags, &writethrough) < 0) { + error_report("Invalid cache option: %s", optarg); + qemu_opts_reset(&empty_opts); + return 0; + } + break; + case 'd': + if (bdrv_parse_discard_flags(optarg, &flags) < 0) { + error_report("Invalid discard option: %s", optarg); + qemu_opts_reset(&empty_opts); + return 0; + } + break; case 'o': if (imageOpts) { printf("--image-opts and 'open -o' are mutually exclusive\n"); + qemu_opts_reset(&empty_opts); return 0; } if (!qemu_opts_parse_noisily(&empty_opts, optarg, false)) { -- cgit v1.2.3 From dc38852aaa4ac187d8b44201f75fc2835241912d Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Sat, 7 May 2016 21:16:42 -0600 Subject: qemu-io: Use bool for command line flags We require a C99 compiler; let's use it to express what we really mean. (Yes, we now have an instance of 'if (bool + bool + bool > 1)', which, although semantically valid C, looks ugly; it gets cleaned up later.) Signed-off-by: Eric Blake Reviewed-by: Max Reitz Message-id: 1462677405-4752-4-git-send-email-eblake@redhat.com Signed-off-by: Max Reitz --- qemu-io-cmds.c | 94 +++++++++++++++++++++++++++++----------------------------- 1 file changed, 47 insertions(+), 47 deletions(-) diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c index 767ea5ecdb..e038c0309e 100644 --- a/qemu-io-cmds.c +++ b/qemu-io-cmds.c @@ -345,7 +345,7 @@ static void dump_buffer(const void *buffer, int64_t offset, int64_t len) } static void print_report(const char *op, struct timeval *t, int64_t offset, - int64_t count, int64_t total, int cnt, int Cflag) + int64_t count, int64_t total, int cnt, bool Cflag) { char s1[64], s2[64], ts[64]; @@ -658,8 +658,8 @@ static const cmdinfo_t read_cmd = { static int read_f(BlockBackend *blk, int argc, char **argv) { struct timeval t1, t2; - int Cflag = 0, pflag = 0, qflag = 0, vflag = 0; - int Pflag = 0, sflag = 0, lflag = 0, bflag = 0; + bool Cflag = false, pflag = false, qflag = false, vflag = false; + bool Pflag = false, sflag = false, lflag = false, bflag = false; int c, cnt; char *buf; int64_t offset; @@ -672,13 +672,13 @@ static int read_f(BlockBackend *blk, int argc, char **argv) while ((c = getopt(argc, argv, "bCl:pP:qs:v")) != -1) { switch (c) { case 'b': - bflag = 1; + bflag = true; break; case 'C': - Cflag = 1; + Cflag = true; break; case 'l': - lflag = 1; + lflag = true; pattern_count = cvtnum(optarg); if (pattern_count < 0) { print_cvtnum_err(pattern_count, optarg); @@ -686,20 +686,20 @@ static int read_f(BlockBackend *blk, int argc, char **argv) } break; case 'p': - pflag = 1; + pflag = true; break; case 'P': - Pflag = 1; + Pflag = true; pattern = parse_pattern(optarg); if (pattern < 0) { return 0; } break; case 'q': - qflag = 1; + qflag = true; break; case 's': - sflag = 1; + sflag = true; pattern_offset = cvtnum(optarg); if (pattern_offset < 0) { print_cvtnum_err(pattern_offset, optarg); @@ -707,7 +707,7 @@ static int read_f(BlockBackend *blk, int argc, char **argv) } break; case 'v': - vflag = 1; + vflag = true; break; default: return qemuio_command_usage(&read_cmd); @@ -844,7 +844,7 @@ static const cmdinfo_t readv_cmd = { static int readv_f(BlockBackend *blk, int argc, char **argv) { struct timeval t1, t2; - int Cflag = 0, qflag = 0, vflag = 0; + bool Cflag = false, qflag = false, vflag = false; int c, cnt; char *buf; int64_t offset; @@ -853,25 +853,25 @@ static int readv_f(BlockBackend *blk, int argc, char **argv) int nr_iov; QEMUIOVector qiov; int pattern = 0; - int Pflag = 0; + bool Pflag = false; while ((c = getopt(argc, argv, "CP:qv")) != -1) { switch (c) { case 'C': - Cflag = 1; + Cflag = true; break; case 'P': - Pflag = 1; + Pflag = true; pattern = parse_pattern(optarg); if (pattern < 0) { return 0; } break; case 'q': - qflag = 1; + qflag = true; break; case 'v': - vflag = 1; + vflag = true; break; default: return qemuio_command_usage(&readv_cmd); @@ -976,8 +976,8 @@ static const cmdinfo_t write_cmd = { static int write_f(BlockBackend *blk, int argc, char **argv) { struct timeval t1, t2; - int Cflag = 0, pflag = 0, qflag = 0, bflag = 0, Pflag = 0, zflag = 0; - int cflag = 0; + bool Cflag = false, pflag = false, qflag = false, bflag = false; + bool Pflag = false, zflag = false, cflag = false; int c, cnt; char *buf = NULL; int64_t offset; @@ -989,29 +989,29 @@ static int write_f(BlockBackend *blk, int argc, char **argv) while ((c = getopt(argc, argv, "bcCpP:qz")) != -1) { switch (c) { case 'b': - bflag = 1; + bflag = true; break; case 'c': - cflag = 1; + cflag = true; break; case 'C': - Cflag = 1; + Cflag = true; break; case 'p': - pflag = 1; + pflag = true; break; case 'P': - Pflag = 1; + Pflag = true; pattern = parse_pattern(optarg); if (pattern < 0) { return 0; } break; case 'q': - qflag = 1; + qflag = true; break; case 'z': - zflag = 1; + zflag = true; break; default: return qemuio_command_usage(&write_cmd); @@ -1133,7 +1133,7 @@ static const cmdinfo_t writev_cmd = { static int writev_f(BlockBackend *blk, int argc, char **argv) { struct timeval t1, t2; - int Cflag = 0, qflag = 0; + bool Cflag = false, qflag = false; int c, cnt; char *buf; int64_t offset; @@ -1146,10 +1146,10 @@ static int writev_f(BlockBackend *blk, int argc, char **argv) while ((c = getopt(argc, argv, "CqP:")) != -1) { switch (c) { case 'C': - Cflag = 1; + Cflag = true; break; case 'q': - qflag = 1; + qflag = true; break; case 'P': pattern = parse_pattern(optarg); @@ -1242,7 +1242,7 @@ static const cmdinfo_t multiwrite_cmd = { static int multiwrite_f(BlockBackend *blk, int argc, char **argv) { struct timeval t1, t2; - int Cflag = 0, qflag = 0; + bool Cflag = false, qflag = false; int c, cnt; char **buf; int64_t offset, first_offset = 0; @@ -1258,10 +1258,10 @@ static int multiwrite_f(BlockBackend *blk, int argc, char **argv) while ((c = getopt(argc, argv, "CqP:")) != -1) { switch (c) { case 'C': - Cflag = 1; + Cflag = true; break; case 'q': - qflag = 1; + qflag = true; break; case 'P': pattern = parse_pattern(optarg); @@ -1371,11 +1371,11 @@ struct aio_ctx { QEMUIOVector qiov; int64_t offset; char *buf; - int qflag; - int vflag; - int Cflag; - int Pflag; - int zflag; + bool qflag; + bool vflag; + bool Cflag; + bool Pflag; + bool zflag; BlockAcctCookie acct; int pattern; struct timeval t1; @@ -1498,10 +1498,10 @@ static int aio_read_f(BlockBackend *blk, int argc, char **argv) while ((c = getopt(argc, argv, "CP:qv")) != -1) { switch (c) { case 'C': - ctx->Cflag = 1; + ctx->Cflag = true; break; case 'P': - ctx->Pflag = 1; + ctx->Pflag = true; ctx->pattern = parse_pattern(optarg); if (ctx->pattern < 0) { g_free(ctx); @@ -1509,10 +1509,10 @@ static int aio_read_f(BlockBackend *blk, int argc, char **argv) } break; case 'q': - ctx->qflag = 1; + ctx->qflag = true; break; case 'v': - ctx->vflag = 1; + ctx->vflag = true; break; default: g_free(ctx); @@ -1599,10 +1599,10 @@ static int aio_write_f(BlockBackend *blk, int argc, char **argv) while ((c = getopt(argc, argv, "CqP:z")) != -1) { switch (c) { case 'C': - ctx->Cflag = 1; + ctx->Cflag = true; break; case 'q': - ctx->qflag = 1; + ctx->qflag = true; break; case 'P': pattern = parse_pattern(optarg); @@ -1612,7 +1612,7 @@ static int aio_write_f(BlockBackend *blk, int argc, char **argv) } break; case 'z': - ctx->zflag = 1; + ctx->zflag = true; break; default: g_free(ctx); @@ -1841,17 +1841,17 @@ static const cmdinfo_t discard_cmd = { static int discard_f(BlockBackend *blk, int argc, char **argv) { struct timeval t1, t2; - int Cflag = 0, qflag = 0; + bool Cflag = false, qflag = false; int c, ret; int64_t offset, count; while ((c = getopt(argc, argv, "Cq")) != -1) { switch (c) { case 'C': - Cflag = 1; + Cflag = true; break; case 'q': - qflag = 1; + qflag = true; break; default: return qemuio_command_usage(&discard_cmd); -- cgit v1.2.3 From 093ea232b0a3359ce60ab0f535d9bd04454d39eb Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Sat, 7 May 2016 21:16:43 -0600 Subject: qemu-io: Allow unaligned access by default There's no reason to require the user to specify a flag just so they can pass in unaligned numbers. Keep 'read -p' and 'write -p' as no-ops so that I don't have to hunt down and update all users of qemu-io, but otherwise make their behavior default as 'read' and 'write'. Also fix 'write -z', 'readv', 'writev', 'writev', 'aio_read', 'aio_write', and 'aio_write -z'. For now, 'read -b', 'write -b', and 'write -c' still require alignment (and 'multiwrite', but that's slated to die soon). qemu-iotest 23 is updated to match, as the only test that was previously explicitly expecting an error on an unaligned request. Signed-off-by: Eric Blake Message-id: 1462677405-4752-5-git-send-email-eblake@redhat.com Reviewed-by: Max Reitz Signed-off-by: Max Reitz --- qemu-io-cmds.c | 73 +- tests/qemu-iotests/023.out | 2168 +++++++++++++++++++++++++++++--------------- 2 files changed, 1461 insertions(+), 780 deletions(-) diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c index e038c0309e..ab140461e0 100644 --- a/qemu-io-cmds.c +++ b/qemu-io-cmds.c @@ -1,7 +1,7 @@ /* * Command line utility to exercise the QEMU I/O path. * - * Copyright (C) 2009 Red Hat, Inc. + * Copyright (C) 2009-2016 Red Hat, Inc. * Copyright (c) 2003-2005 Silicon Graphics, Inc. * * This work is licensed under the terms of the GNU GPL, version 2 or later. @@ -395,12 +395,6 @@ create_iovec(BlockBackend *blk, QEMUIOVector *qiov, char **argv, int nr_iov, goto fail; } - if (len & 0x1ff) { - printf("length argument %" PRId64 - " is not sector aligned\n", len); - goto fail; - } - sizes[i] = len; count += len; } @@ -634,7 +628,7 @@ static void read_help(void) " -b, -- read from the VM state rather than the virtual disk\n" " -C, -- report statistics in a machine parsable format\n" " -l, -- length for pattern verification (only with -P)\n" -" -p, -- allow unaligned access\n" +" -p, -- ignored for backwards compatibility\n" " -P, -- use a pattern to verify read data\n" " -q, -- quiet mode, do not show I/O statistics\n" " -s, -- start offset for pattern verification (only with -P)\n" @@ -650,7 +644,7 @@ static const cmdinfo_t read_cmd = { .cfunc = read_f, .argmin = 2, .argmax = -1, - .args = "[-abCpqv] [-P pattern [-s off] [-l len]] off len", + .args = "[-abCqv] [-P pattern [-s off] [-l len]] off len", .oneline = "reads a number of bytes at a specified offset", .help = read_help, }; @@ -658,7 +652,7 @@ static const cmdinfo_t read_cmd = { static int read_f(BlockBackend *blk, int argc, char **argv) { struct timeval t1, t2; - bool Cflag = false, pflag = false, qflag = false, vflag = false; + bool Cflag = false, qflag = false, vflag = false; bool Pflag = false, sflag = false, lflag = false, bflag = false; int c, cnt; char *buf; @@ -686,7 +680,7 @@ static int read_f(BlockBackend *blk, int argc, char **argv) } break; case 'p': - pflag = true; + /* Ignored for backwards compatibility */ break; case 'P': Pflag = true; @@ -718,11 +712,6 @@ static int read_f(BlockBackend *blk, int argc, char **argv) return qemuio_command_usage(&read_cmd); } - if (bflag && pflag) { - printf("-b and -p cannot be specified at the same time\n"); - return 0; - } - offset = cvtnum(argv[optind]); if (offset < 0) { print_cvtnum_err(offset, argv[optind]); @@ -753,7 +742,7 @@ static int read_f(BlockBackend *blk, int argc, char **argv) return 0; } - if (!pflag) { + if (bflag) { if (offset & 0x1ff) { printf("offset %" PRId64 " is not sector aligned\n", offset); @@ -836,7 +825,7 @@ static const cmdinfo_t readv_cmd = { .cfunc = readv_f, .argmin = 2, .argmax = -1, - .args = "[-Cqv] [-P pattern ] off len [len..]", + .args = "[-Cqv] [-P pattern] off len [len..]", .oneline = "reads a number of bytes at a specified offset", .help = readv_help, }; @@ -890,12 +879,6 @@ static int readv_f(BlockBackend *blk, int argc, char **argv) } optind++; - if (offset & 0x1ff) { - printf("offset %" PRId64 " is not sector aligned\n", - offset); - return 0; - } - nr_iov = argc - optind; buf = create_iovec(blk, &qiov, &argv[optind], nr_iov, 0xab); if (buf == NULL) { @@ -952,7 +935,7 @@ static void write_help(void) " filled with a set pattern (0xcdcdcdcd).\n" " -b, -- write to the VM state rather than the virtual disk\n" " -c, -- write compressed data with blk_write_compressed\n" -" -p, -- allow unaligned access\n" +" -p, -- ignored for backwards compatibility\n" " -P, -- use different pattern to fill file\n" " -C, -- report statistics in a machine parsable format\n" " -q, -- quiet mode, do not show I/O statistics\n" @@ -968,7 +951,7 @@ static const cmdinfo_t write_cmd = { .cfunc = write_f, .argmin = 2, .argmax = -1, - .args = "[-bcCpqz] [-P pattern ] off len", + .args = "[-bcCqz] [-P pattern] off len", .oneline = "writes a number of bytes at a specified offset", .help = write_help, }; @@ -976,7 +959,7 @@ static const cmdinfo_t write_cmd = { static int write_f(BlockBackend *blk, int argc, char **argv) { struct timeval t1, t2; - bool Cflag = false, pflag = false, qflag = false, bflag = false; + bool Cflag = false, qflag = false, bflag = false; bool Pflag = false, zflag = false, cflag = false; int c, cnt; char *buf = NULL; @@ -998,7 +981,7 @@ static int write_f(BlockBackend *blk, int argc, char **argv) Cflag = true; break; case 'p': - pflag = true; + /* Ignored for backwards compatibility */ break; case 'P': Pflag = true; @@ -1022,8 +1005,8 @@ static int write_f(BlockBackend *blk, int argc, char **argv) return qemuio_command_usage(&write_cmd); } - if (bflag + pflag + zflag > 1) { - printf("-b, -p, or -z cannot be specified at the same time\n"); + if (bflag && zflag) { + printf("-b and -z cannot be specified at the same time\n"); return 0; } @@ -1049,7 +1032,7 @@ static int write_f(BlockBackend *blk, int argc, char **argv) return 0; } - if (!pflag) { + if (bflag || cflag) { if (offset & 0x1ff) { printf("offset %" PRId64 " is not sector aligned\n", offset); @@ -1125,7 +1108,7 @@ static const cmdinfo_t writev_cmd = { .cfunc = writev_f, .argmin = 2, .argmax = -1, - .args = "[-Cq] [-P pattern ] off len [len..]", + .args = "[-Cq] [-P pattern] off len [len..]", .oneline = "writes a number of bytes at a specified offset", .help = writev_help, }; @@ -1173,12 +1156,6 @@ static int writev_f(BlockBackend *blk, int argc, char **argv) } optind++; - if (offset & 0x1ff) { - printf("offset %" PRId64 " is not sector aligned\n", - offset); - return 0; - } - nr_iov = argc - optind; buf = create_iovec(blk, &qiov, &argv[optind], nr_iov, pattern); if (buf == NULL) { @@ -1484,7 +1461,7 @@ static const cmdinfo_t aio_read_cmd = { .cfunc = aio_read_f, .argmin = 2, .argmax = -1, - .args = "[-Cqv] [-P pattern ] off len [len..]", + .args = "[-Cqv] [-P pattern] off len [len..]", .oneline = "asynchronously reads a number of bytes", .help = aio_read_help, }; @@ -1533,14 +1510,6 @@ static int aio_read_f(BlockBackend *blk, int argc, char **argv) } optind++; - if (ctx->offset & 0x1ff) { - printf("offset %" PRId64 " is not sector aligned\n", - ctx->offset); - block_acct_invalid(blk_get_stats(blk), BLOCK_ACCT_READ); - g_free(ctx); - return 0; - } - nr_iov = argc - optind; ctx->buf = create_iovec(blk, &ctx->qiov, &argv[optind], nr_iov, 0xab); if (ctx->buf == NULL) { @@ -1584,7 +1553,7 @@ static const cmdinfo_t aio_write_cmd = { .cfunc = aio_write_f, .argmin = 2, .argmax = -1, - .args = "[-Cqz] [-P pattern ] off len [len..]", + .args = "[-Cqz] [-P pattern] off len [len..]", .oneline = "asynchronously writes a number of bytes", .help = aio_write_help, }; @@ -1645,14 +1614,6 @@ static int aio_write_f(BlockBackend *blk, int argc, char **argv) } optind++; - if (ctx->offset & 0x1ff) { - printf("offset %" PRId64 " is not sector aligned\n", - ctx->offset); - block_acct_invalid(blk_get_stats(blk), BLOCK_ACCT_WRITE); - g_free(ctx); - return 0; - } - if (ctx->zflag) { int64_t count = cvtnum(argv[optind]); if (count < 0) { diff --git a/tests/qemu-iotests/023.out b/tests/qemu-iotests/023.out index d4e9be25e1..664871b30a 100644 --- a/tests/qemu-iotests/023.out +++ b/tests/qemu-iotests/023.out @@ -225,42 +225,78 @@ wrote 512/512 bytes at offset 108544 wrote 512/512 bytes at offset 109568 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) === IO: pattern 216 -offset 110848 is not sector aligned -offset 111872 is not sector aligned -offset 112896 is not sector aligned -offset 113920 is not sector aligned -offset 114944 is not sector aligned -offset 115968 is not sector aligned -offset 116992 is not sector aligned -offset 118016 is not sector aligned -offset 119040 is not sector aligned -offset 120064 is not sector aligned -offset 121088 is not sector aligned -offset 122112 is not sector aligned -offset 123136 is not sector aligned -offset 124160 is not sector aligned -offset 125184 is not sector aligned -offset 126208 is not sector aligned -offset 127232 is not sector aligned -offset 128256 is not sector aligned -offset 129280 is not sector aligned -offset 130304 is not sector aligned -offset 131328 is not sector aligned -offset 132352 is not sector aligned -offset 133376 is not sector aligned -offset 134400 is not sector aligned -offset 135424 is not sector aligned -offset 136448 is not sector aligned -offset 137472 is not sector aligned -offset 138496 is not sector aligned -offset 139520 is not sector aligned -offset 140544 is not sector aligned -offset 141568 is not sector aligned -offset 142592 is not sector aligned -offset 143616 is not sector aligned -offset 144640 is not sector aligned -offset 145664 is not sector aligned -offset 146688 is not sector aligned +wrote 512/512 bytes at offset 110848 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 111872 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 112896 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 113920 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 114944 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 115968 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 116992 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 118016 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 119040 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 120064 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 121088 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 122112 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 123136 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 124160 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 125184 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 126208 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 127232 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 128256 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 129280 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 130304 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 131328 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 132352 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 133376 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 134400 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 135424 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 136448 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 137472 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 138496 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 139520 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 140544 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 141568 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 142592 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 143616 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 144640 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 145664 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 146688 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) === IO: pattern 33 wrote 2048/2048 bytes at offset 147968 2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -507,42 +543,78 @@ read 512/512 bytes at offset 108544 read 512/512 bytes at offset 109568 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) === IO: pattern 216 -offset 110848 is not sector aligned -offset 111872 is not sector aligned -offset 112896 is not sector aligned -offset 113920 is not sector aligned -offset 114944 is not sector aligned -offset 115968 is not sector aligned -offset 116992 is not sector aligned -offset 118016 is not sector aligned -offset 119040 is not sector aligned -offset 120064 is not sector aligned -offset 121088 is not sector aligned -offset 122112 is not sector aligned -offset 123136 is not sector aligned -offset 124160 is not sector aligned -offset 125184 is not sector aligned -offset 126208 is not sector aligned -offset 127232 is not sector aligned -offset 128256 is not sector aligned -offset 129280 is not sector aligned -offset 130304 is not sector aligned -offset 131328 is not sector aligned -offset 132352 is not sector aligned -offset 133376 is not sector aligned -offset 134400 is not sector aligned -offset 135424 is not sector aligned -offset 136448 is not sector aligned -offset 137472 is not sector aligned -offset 138496 is not sector aligned -offset 139520 is not sector aligned -offset 140544 is not sector aligned -offset 141568 is not sector aligned -offset 142592 is not sector aligned -offset 143616 is not sector aligned -offset 144640 is not sector aligned -offset 145664 is not sector aligned -offset 146688 is not sector aligned +read 512/512 bytes at offset 110848 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 111872 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 112896 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 113920 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 114944 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 115968 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 116992 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 118016 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 119040 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 120064 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 121088 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 122112 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 123136 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 124160 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 125184 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 126208 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 127232 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 128256 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 129280 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 130304 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 131328 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 132352 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 133376 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 134400 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 135424 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 136448 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 137472 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 138496 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 139520 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 140544 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 141568 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 142592 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 143616 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 144640 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 145664 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 146688 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) === IO: pattern 33 read 2048/2048 bytes at offset 147968 2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -789,42 +861,78 @@ wrote 512/512 bytes at offset 108544 wrote 512/512 bytes at offset 109568 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) === IO: pattern 216 -offset 110848 is not sector aligned -offset 111872 is not sector aligned -offset 112896 is not sector aligned -offset 113920 is not sector aligned -offset 114944 is not sector aligned -offset 115968 is not sector aligned -offset 116992 is not sector aligned -offset 118016 is not sector aligned -offset 119040 is not sector aligned -offset 120064 is not sector aligned -offset 121088 is not sector aligned -offset 122112 is not sector aligned -offset 123136 is not sector aligned -offset 124160 is not sector aligned -offset 125184 is not sector aligned -offset 126208 is not sector aligned -offset 127232 is not sector aligned -offset 128256 is not sector aligned -offset 129280 is not sector aligned -offset 130304 is not sector aligned -offset 131328 is not sector aligned -offset 132352 is not sector aligned -offset 133376 is not sector aligned -offset 134400 is not sector aligned -offset 135424 is not sector aligned -offset 136448 is not sector aligned -offset 137472 is not sector aligned -offset 138496 is not sector aligned -offset 139520 is not sector aligned -offset 140544 is not sector aligned -offset 141568 is not sector aligned -offset 142592 is not sector aligned -offset 143616 is not sector aligned -offset 144640 is not sector aligned -offset 145664 is not sector aligned -offset 146688 is not sector aligned +wrote 512/512 bytes at offset 110848 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 111872 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 112896 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 113920 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 114944 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 115968 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 116992 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 118016 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 119040 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 120064 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 121088 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 122112 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 123136 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 124160 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 125184 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 126208 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 127232 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 128256 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 129280 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 130304 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 131328 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 132352 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 133376 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 134400 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 135424 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 136448 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 137472 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 138496 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 139520 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 140544 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 141568 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 142592 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 143616 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 144640 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 145664 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 146688 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) === IO: pattern 33 wrote 2048/2048 bytes at offset 147968 2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -1071,42 +1179,78 @@ read 512/512 bytes at offset 108544 read 512/512 bytes at offset 109568 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) === IO: pattern 216 -offset 110848 is not sector aligned -offset 111872 is not sector aligned -offset 112896 is not sector aligned -offset 113920 is not sector aligned -offset 114944 is not sector aligned -offset 115968 is not sector aligned -offset 116992 is not sector aligned -offset 118016 is not sector aligned -offset 119040 is not sector aligned -offset 120064 is not sector aligned -offset 121088 is not sector aligned -offset 122112 is not sector aligned -offset 123136 is not sector aligned -offset 124160 is not sector aligned -offset 125184 is not sector aligned -offset 126208 is not sector aligned -offset 127232 is not sector aligned -offset 128256 is not sector aligned -offset 129280 is not sector aligned -offset 130304 is not sector aligned -offset 131328 is not sector aligned -offset 132352 is not sector aligned -offset 133376 is not sector aligned -offset 134400 is not sector aligned -offset 135424 is not sector aligned -offset 136448 is not sector aligned -offset 137472 is not sector aligned -offset 138496 is not sector aligned -offset 139520 is not sector aligned -offset 140544 is not sector aligned -offset 141568 is not sector aligned -offset 142592 is not sector aligned -offset 143616 is not sector aligned -offset 144640 is not sector aligned -offset 145664 is not sector aligned -offset 146688 is not sector aligned +read 512/512 bytes at offset 110848 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 111872 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 112896 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 113920 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 114944 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 115968 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 116992 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 118016 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 119040 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 120064 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 121088 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 122112 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 123136 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 124160 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 125184 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 126208 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 127232 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 128256 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 129280 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 130304 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 131328 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 132352 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 133376 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 134400 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 135424 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 136448 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 137472 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 138496 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 139520 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 140544 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 141568 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 142592 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 143616 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 144640 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 145664 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 146688 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) === IO: pattern 33 read 2048/2048 bytes at offset 147968 2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -1355,42 +1499,78 @@ wrote 512/512 bytes at offset 4295075840 wrote 512/512 bytes at offset 4295076864 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) === IO: pattern 216 -offset 4295078144 is not sector aligned -offset 4295079168 is not sector aligned -offset 4295080192 is not sector aligned -offset 4295081216 is not sector aligned -offset 4295082240 is not sector aligned -offset 4295083264 is not sector aligned -offset 4295084288 is not sector aligned -offset 4295085312 is not sector aligned -offset 4295086336 is not sector aligned -offset 4295087360 is not sector aligned -offset 4295088384 is not sector aligned -offset 4295089408 is not sector aligned -offset 4295090432 is not sector aligned -offset 4295091456 is not sector aligned -offset 4295092480 is not sector aligned -offset 4295093504 is not sector aligned -offset 4295094528 is not sector aligned -offset 4295095552 is not sector aligned -offset 4295096576 is not sector aligned -offset 4295097600 is not sector aligned -offset 4295098624 is not sector aligned -offset 4295099648 is not sector aligned -offset 4295100672 is not sector aligned -offset 4295101696 is not sector aligned -offset 4295102720 is not sector aligned -offset 4295103744 is not sector aligned -offset 4295104768 is not sector aligned -offset 4295105792 is not sector aligned -offset 4295106816 is not sector aligned -offset 4295107840 is not sector aligned -offset 4295108864 is not sector aligned -offset 4295109888 is not sector aligned -offset 4295110912 is not sector aligned -offset 4295111936 is not sector aligned -offset 4295112960 is not sector aligned -offset 4295113984 is not sector aligned +wrote 512/512 bytes at offset 4295078144 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295079168 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295080192 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295081216 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295082240 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295083264 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295084288 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295085312 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295086336 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295087360 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295088384 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295089408 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295090432 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295091456 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295092480 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295093504 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295094528 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295095552 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295096576 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295097600 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295098624 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295099648 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295100672 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295101696 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295102720 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295103744 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295104768 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295105792 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295106816 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295107840 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295108864 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295109888 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295110912 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295111936 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295112960 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295113984 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) === IO: pattern 33 wrote 2048/2048 bytes at offset 4295115264 2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -1637,42 +1817,78 @@ read 512/512 bytes at offset 4295075840 read 512/512 bytes at offset 4295076864 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) === IO: pattern 216 -offset 4295078144 is not sector aligned -offset 4295079168 is not sector aligned -offset 4295080192 is not sector aligned -offset 4295081216 is not sector aligned -offset 4295082240 is not sector aligned -offset 4295083264 is not sector aligned -offset 4295084288 is not sector aligned -offset 4295085312 is not sector aligned -offset 4295086336 is not sector aligned -offset 4295087360 is not sector aligned -offset 4295088384 is not sector aligned -offset 4295089408 is not sector aligned -offset 4295090432 is not sector aligned -offset 4295091456 is not sector aligned -offset 4295092480 is not sector aligned -offset 4295093504 is not sector aligned -offset 4295094528 is not sector aligned -offset 4295095552 is not sector aligned -offset 4295096576 is not sector aligned -offset 4295097600 is not sector aligned -offset 4295098624 is not sector aligned -offset 4295099648 is not sector aligned -offset 4295100672 is not sector aligned -offset 4295101696 is not sector aligned -offset 4295102720 is not sector aligned -offset 4295103744 is not sector aligned -offset 4295104768 is not sector aligned -offset 4295105792 is not sector aligned -offset 4295106816 is not sector aligned -offset 4295107840 is not sector aligned -offset 4295108864 is not sector aligned -offset 4295109888 is not sector aligned -offset 4295110912 is not sector aligned -offset 4295111936 is not sector aligned -offset 4295112960 is not sector aligned -offset 4295113984 is not sector aligned +read 512/512 bytes at offset 4295078144 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295079168 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295080192 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295081216 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295082240 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295083264 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295084288 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295085312 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295086336 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295087360 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295088384 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295089408 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295090432 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295091456 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295092480 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295093504 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295094528 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295095552 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295096576 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295097600 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295098624 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295099648 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295100672 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295101696 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295102720 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295103744 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295104768 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295105792 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295106816 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295107840 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295108864 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295109888 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295110912 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295111936 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295112960 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295113984 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) === IO: pattern 33 read 2048/2048 bytes at offset 4295115264 2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -1919,42 +2135,78 @@ wrote 512/512 bytes at offset 4295075840 wrote 512/512 bytes at offset 4295076864 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) === IO: pattern 216 -offset 4295078144 is not sector aligned -offset 4295079168 is not sector aligned -offset 4295080192 is not sector aligned -offset 4295081216 is not sector aligned -offset 4295082240 is not sector aligned -offset 4295083264 is not sector aligned -offset 4295084288 is not sector aligned -offset 4295085312 is not sector aligned -offset 4295086336 is not sector aligned -offset 4295087360 is not sector aligned -offset 4295088384 is not sector aligned -offset 4295089408 is not sector aligned -offset 4295090432 is not sector aligned -offset 4295091456 is not sector aligned -offset 4295092480 is not sector aligned -offset 4295093504 is not sector aligned -offset 4295094528 is not sector aligned -offset 4295095552 is not sector aligned -offset 4295096576 is not sector aligned -offset 4295097600 is not sector aligned -offset 4295098624 is not sector aligned -offset 4295099648 is not sector aligned -offset 4295100672 is not sector aligned -offset 4295101696 is not sector aligned -offset 4295102720 is not sector aligned -offset 4295103744 is not sector aligned -offset 4295104768 is not sector aligned -offset 4295105792 is not sector aligned -offset 4295106816 is not sector aligned -offset 4295107840 is not sector aligned -offset 4295108864 is not sector aligned -offset 4295109888 is not sector aligned -offset 4295110912 is not sector aligned -offset 4295111936 is not sector aligned -offset 4295112960 is not sector aligned -offset 4295113984 is not sector aligned +wrote 512/512 bytes at offset 4295078144 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295079168 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295080192 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295081216 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295082240 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295083264 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295084288 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295085312 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295086336 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295087360 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295088384 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295089408 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295090432 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295091456 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295092480 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295093504 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295094528 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295095552 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295096576 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295097600 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295098624 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295099648 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295100672 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295101696 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295102720 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295103744 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295104768 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295105792 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295106816 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295107840 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295108864 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295109888 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295110912 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295111936 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295112960 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295113984 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) === IO: pattern 33 wrote 2048/2048 bytes at offset 4295115264 2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -2201,42 +2453,78 @@ read 512/512 bytes at offset 4295075840 read 512/512 bytes at offset 4295076864 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) === IO: pattern 216 -offset 4295078144 is not sector aligned -offset 4295079168 is not sector aligned -offset 4295080192 is not sector aligned -offset 4295081216 is not sector aligned -offset 4295082240 is not sector aligned -offset 4295083264 is not sector aligned -offset 4295084288 is not sector aligned -offset 4295085312 is not sector aligned -offset 4295086336 is not sector aligned -offset 4295087360 is not sector aligned -offset 4295088384 is not sector aligned -offset 4295089408 is not sector aligned -offset 4295090432 is not sector aligned -offset 4295091456 is not sector aligned -offset 4295092480 is not sector aligned -offset 4295093504 is not sector aligned -offset 4295094528 is not sector aligned -offset 4295095552 is not sector aligned -offset 4295096576 is not sector aligned -offset 4295097600 is not sector aligned -offset 4295098624 is not sector aligned -offset 4295099648 is not sector aligned -offset 4295100672 is not sector aligned -offset 4295101696 is not sector aligned -offset 4295102720 is not sector aligned -offset 4295103744 is not sector aligned -offset 4295104768 is not sector aligned -offset 4295105792 is not sector aligned -offset 4295106816 is not sector aligned -offset 4295107840 is not sector aligned -offset 4295108864 is not sector aligned -offset 4295109888 is not sector aligned -offset 4295110912 is not sector aligned -offset 4295111936 is not sector aligned -offset 4295112960 is not sector aligned -offset 4295113984 is not sector aligned +read 512/512 bytes at offset 4295078144 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295079168 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295080192 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295081216 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295082240 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295083264 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295084288 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295085312 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295086336 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295087360 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295088384 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295089408 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295090432 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295091456 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295092480 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295093504 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295094528 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295095552 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295096576 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295097600 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295098624 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295099648 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295100672 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295101696 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295102720 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295103744 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295104768 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295105792 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295106816 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295107840 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295108864 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295109888 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295110912 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295111936 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295112960 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295113984 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) === IO: pattern 33 read 2048/2048 bytes at offset 4295115264 2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -2489,42 +2777,78 @@ read 512/512 bytes at offset 108544 read 512/512 bytes at offset 109568 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) === IO: pattern 216 -offset 110848 is not sector aligned -offset 111872 is not sector aligned -offset 112896 is not sector aligned -offset 113920 is not sector aligned -offset 114944 is not sector aligned -offset 115968 is not sector aligned -offset 116992 is not sector aligned -offset 118016 is not sector aligned -offset 119040 is not sector aligned -offset 120064 is not sector aligned -offset 121088 is not sector aligned -offset 122112 is not sector aligned -offset 123136 is not sector aligned -offset 124160 is not sector aligned -offset 125184 is not sector aligned -offset 126208 is not sector aligned -offset 127232 is not sector aligned -offset 128256 is not sector aligned -offset 129280 is not sector aligned -offset 130304 is not sector aligned -offset 131328 is not sector aligned -offset 132352 is not sector aligned -offset 133376 is not sector aligned -offset 134400 is not sector aligned -offset 135424 is not sector aligned -offset 136448 is not sector aligned -offset 137472 is not sector aligned -offset 138496 is not sector aligned -offset 139520 is not sector aligned -offset 140544 is not sector aligned -offset 141568 is not sector aligned -offset 142592 is not sector aligned -offset 143616 is not sector aligned -offset 144640 is not sector aligned -offset 145664 is not sector aligned -offset 146688 is not sector aligned +read 512/512 bytes at offset 110848 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 111872 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 112896 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 113920 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 114944 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 115968 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 116992 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 118016 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 119040 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 120064 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 121088 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 122112 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 123136 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 124160 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 125184 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 126208 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 127232 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 128256 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 129280 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 130304 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 131328 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 132352 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 133376 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 134400 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 135424 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 136448 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 137472 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 138496 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 139520 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 140544 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 141568 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 142592 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 143616 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 144640 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 145664 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 146688 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) === IO: pattern 33 read 2048/2048 bytes at offset 147968 2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -2771,42 +3095,78 @@ read 512/512 bytes at offset 108544 read 512/512 bytes at offset 109568 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) === IO: pattern 216 -offset 110848 is not sector aligned -offset 111872 is not sector aligned -offset 112896 is not sector aligned -offset 113920 is not sector aligned -offset 114944 is not sector aligned -offset 115968 is not sector aligned -offset 116992 is not sector aligned -offset 118016 is not sector aligned -offset 119040 is not sector aligned -offset 120064 is not sector aligned -offset 121088 is not sector aligned -offset 122112 is not sector aligned -offset 123136 is not sector aligned -offset 124160 is not sector aligned -offset 125184 is not sector aligned -offset 126208 is not sector aligned -offset 127232 is not sector aligned -offset 128256 is not sector aligned -offset 129280 is not sector aligned -offset 130304 is not sector aligned -offset 131328 is not sector aligned -offset 132352 is not sector aligned -offset 133376 is not sector aligned -offset 134400 is not sector aligned -offset 135424 is not sector aligned -offset 136448 is not sector aligned -offset 137472 is not sector aligned -offset 138496 is not sector aligned -offset 139520 is not sector aligned -offset 140544 is not sector aligned -offset 141568 is not sector aligned -offset 142592 is not sector aligned -offset 143616 is not sector aligned -offset 144640 is not sector aligned -offset 145664 is not sector aligned -offset 146688 is not sector aligned +read 512/512 bytes at offset 110848 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 111872 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 112896 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 113920 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 114944 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 115968 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 116992 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 118016 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 119040 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 120064 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 121088 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 122112 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 123136 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 124160 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 125184 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 126208 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 127232 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 128256 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 129280 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 130304 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 131328 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 132352 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 133376 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 134400 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 135424 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 136448 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 137472 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 138496 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 139520 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 140544 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 141568 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 142592 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 143616 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 144640 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 145664 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 146688 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) === IO: pattern 33 read 2048/2048 bytes at offset 147968 2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -3055,42 +3415,78 @@ read 512/512 bytes at offset 4295075840 read 512/512 bytes at offset 4295076864 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) === IO: pattern 216 -offset 4295078144 is not sector aligned -offset 4295079168 is not sector aligned -offset 4295080192 is not sector aligned -offset 4295081216 is not sector aligned -offset 4295082240 is not sector aligned -offset 4295083264 is not sector aligned -offset 4295084288 is not sector aligned -offset 4295085312 is not sector aligned -offset 4295086336 is not sector aligned -offset 4295087360 is not sector aligned -offset 4295088384 is not sector aligned -offset 4295089408 is not sector aligned -offset 4295090432 is not sector aligned -offset 4295091456 is not sector aligned -offset 4295092480 is not sector aligned -offset 4295093504 is not sector aligned -offset 4295094528 is not sector aligned -offset 4295095552 is not sector aligned -offset 4295096576 is not sector aligned -offset 4295097600 is not sector aligned -offset 4295098624 is not sector aligned -offset 4295099648 is not sector aligned -offset 4295100672 is not sector aligned -offset 4295101696 is not sector aligned -offset 4295102720 is not sector aligned -offset 4295103744 is not sector aligned -offset 4295104768 is not sector aligned -offset 4295105792 is not sector aligned -offset 4295106816 is not sector aligned -offset 4295107840 is not sector aligned -offset 4295108864 is not sector aligned -offset 4295109888 is not sector aligned -offset 4295110912 is not sector aligned -offset 4295111936 is not sector aligned -offset 4295112960 is not sector aligned -offset 4295113984 is not sector aligned +read 512/512 bytes at offset 4295078144 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295079168 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295080192 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295081216 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295082240 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295083264 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295084288 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295085312 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295086336 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295087360 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295088384 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295089408 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295090432 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295091456 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295092480 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295093504 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295094528 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295095552 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295096576 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295097600 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295098624 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295099648 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295100672 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295101696 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295102720 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295103744 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295104768 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295105792 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295106816 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295107840 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295108864 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295109888 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295110912 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295111936 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295112960 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295113984 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) === IO: pattern 33 read 2048/2048 bytes at offset 4295115264 2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -3337,42 +3733,78 @@ read 512/512 bytes at offset 4295075840 read 512/512 bytes at offset 4295076864 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) === IO: pattern 216 -offset 4295078144 is not sector aligned -offset 4295079168 is not sector aligned -offset 4295080192 is not sector aligned -offset 4295081216 is not sector aligned -offset 4295082240 is not sector aligned -offset 4295083264 is not sector aligned -offset 4295084288 is not sector aligned -offset 4295085312 is not sector aligned -offset 4295086336 is not sector aligned -offset 4295087360 is not sector aligned -offset 4295088384 is not sector aligned -offset 4295089408 is not sector aligned -offset 4295090432 is not sector aligned -offset 4295091456 is not sector aligned -offset 4295092480 is not sector aligned -offset 4295093504 is not sector aligned -offset 4295094528 is not sector aligned -offset 4295095552 is not sector aligned -offset 4295096576 is not sector aligned -offset 4295097600 is not sector aligned -offset 4295098624 is not sector aligned -offset 4295099648 is not sector aligned -offset 4295100672 is not sector aligned -offset 4295101696 is not sector aligned -offset 4295102720 is not sector aligned -offset 4295103744 is not sector aligned -offset 4295104768 is not sector aligned -offset 4295105792 is not sector aligned -offset 4295106816 is not sector aligned -offset 4295107840 is not sector aligned -offset 4295108864 is not sector aligned -offset 4295109888 is not sector aligned -offset 4295110912 is not sector aligned -offset 4295111936 is not sector aligned -offset 4295112960 is not sector aligned -offset 4295113984 is not sector aligned +read 512/512 bytes at offset 4295078144 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295079168 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295080192 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295081216 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295082240 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295083264 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295084288 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295085312 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295086336 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295087360 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295088384 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295089408 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295090432 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295091456 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295092480 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295093504 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295094528 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295095552 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295096576 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295097600 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295098624 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295099648 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295100672 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295101696 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295102720 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295103744 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295104768 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295105792 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295106816 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295107840 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295108864 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295109888 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295110912 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295111936 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295112960 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295113984 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) === IO: pattern 33 read 2048/2048 bytes at offset 4295115264 2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -3616,49 +4048,85 @@ wrote 512/512 bytes at offset 105984 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 512/512 bytes at offset 107008 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -wrote 512/512 bytes at offset 108032 +wrote 512/512 bytes at offset 108032 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 109056 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 110080 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +=== IO: pattern 217 +wrote 512/512 bytes at offset 111360 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 112384 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 113408 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 114432 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 115456 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 116480 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 117504 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 118528 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 119552 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 120576 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 121600 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 122624 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 123648 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 124672 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 125696 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 126720 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 127744 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 128768 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 129792 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 130816 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 131840 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 132864 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 133888 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 134912 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 135936 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 136960 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 137984 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 139008 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 140032 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 141056 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 142080 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 143104 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 144128 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 145152 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -wrote 512/512 bytes at offset 109056 +wrote 512/512 bytes at offset 146176 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -wrote 512/512 bytes at offset 110080 +wrote 512/512 bytes at offset 147200 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -=== IO: pattern 217 -offset 111360 is not sector aligned -offset 112384 is not sector aligned -offset 113408 is not sector aligned -offset 114432 is not sector aligned -offset 115456 is not sector aligned -offset 116480 is not sector aligned -offset 117504 is not sector aligned -offset 118528 is not sector aligned -offset 119552 is not sector aligned -offset 120576 is not sector aligned -offset 121600 is not sector aligned -offset 122624 is not sector aligned -offset 123648 is not sector aligned -offset 124672 is not sector aligned -offset 125696 is not sector aligned -offset 126720 is not sector aligned -offset 127744 is not sector aligned -offset 128768 is not sector aligned -offset 129792 is not sector aligned -offset 130816 is not sector aligned -offset 131840 is not sector aligned -offset 132864 is not sector aligned -offset 133888 is not sector aligned -offset 134912 is not sector aligned -offset 135936 is not sector aligned -offset 136960 is not sector aligned -offset 137984 is not sector aligned -offset 139008 is not sector aligned -offset 140032 is not sector aligned -offset 141056 is not sector aligned -offset 142080 is not sector aligned -offset 143104 is not sector aligned -offset 144128 is not sector aligned -offset 145152 is not sector aligned -offset 146176 is not sector aligned -offset 147200 is not sector aligned === IO: pattern 34 wrote 2048/2048 bytes at offset 148480 2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -3905,42 +4373,78 @@ read 512/512 bytes at offset 109056 read 512/512 bytes at offset 110080 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) === IO: pattern 217 -offset 111360 is not sector aligned -offset 112384 is not sector aligned -offset 113408 is not sector aligned -offset 114432 is not sector aligned -offset 115456 is not sector aligned -offset 116480 is not sector aligned -offset 117504 is not sector aligned -offset 118528 is not sector aligned -offset 119552 is not sector aligned -offset 120576 is not sector aligned -offset 121600 is not sector aligned -offset 122624 is not sector aligned -offset 123648 is not sector aligned -offset 124672 is not sector aligned -offset 125696 is not sector aligned -offset 126720 is not sector aligned -offset 127744 is not sector aligned -offset 128768 is not sector aligned -offset 129792 is not sector aligned -offset 130816 is not sector aligned -offset 131840 is not sector aligned -offset 132864 is not sector aligned -offset 133888 is not sector aligned -offset 134912 is not sector aligned -offset 135936 is not sector aligned -offset 136960 is not sector aligned -offset 137984 is not sector aligned -offset 139008 is not sector aligned -offset 140032 is not sector aligned -offset 141056 is not sector aligned -offset 142080 is not sector aligned -offset 143104 is not sector aligned -offset 144128 is not sector aligned -offset 145152 is not sector aligned -offset 146176 is not sector aligned -offset 147200 is not sector aligned +read 512/512 bytes at offset 111360 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 112384 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 113408 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 114432 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 115456 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 116480 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 117504 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 118528 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 119552 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 120576 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 121600 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 122624 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 123648 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 124672 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 125696 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 126720 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 127744 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 128768 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 129792 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 130816 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 131840 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 132864 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 133888 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 134912 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 135936 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 136960 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 137984 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 139008 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 140032 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 141056 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 142080 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 143104 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 144128 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 145152 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 146176 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 147200 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) === IO: pattern 34 read 2048/2048 bytes at offset 148480 2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -4187,42 +4691,78 @@ wrote 512/512 bytes at offset 109056 wrote 512/512 bytes at offset 110080 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) === IO: pattern 217 -offset 111360 is not sector aligned -offset 112384 is not sector aligned -offset 113408 is not sector aligned -offset 114432 is not sector aligned -offset 115456 is not sector aligned -offset 116480 is not sector aligned -offset 117504 is not sector aligned -offset 118528 is not sector aligned -offset 119552 is not sector aligned -offset 120576 is not sector aligned -offset 121600 is not sector aligned -offset 122624 is not sector aligned -offset 123648 is not sector aligned -offset 124672 is not sector aligned -offset 125696 is not sector aligned -offset 126720 is not sector aligned -offset 127744 is not sector aligned -offset 128768 is not sector aligned -offset 129792 is not sector aligned -offset 130816 is not sector aligned -offset 131840 is not sector aligned -offset 132864 is not sector aligned -offset 133888 is not sector aligned -offset 134912 is not sector aligned -offset 135936 is not sector aligned -offset 136960 is not sector aligned -offset 137984 is not sector aligned -offset 139008 is not sector aligned -offset 140032 is not sector aligned -offset 141056 is not sector aligned -offset 142080 is not sector aligned -offset 143104 is not sector aligned -offset 144128 is not sector aligned -offset 145152 is not sector aligned -offset 146176 is not sector aligned -offset 147200 is not sector aligned +wrote 512/512 bytes at offset 111360 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 112384 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 113408 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 114432 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 115456 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 116480 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 117504 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 118528 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 119552 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 120576 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 121600 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 122624 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 123648 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 124672 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 125696 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 126720 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 127744 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 128768 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 129792 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 130816 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 131840 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 132864 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 133888 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 134912 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 135936 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 136960 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 137984 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 139008 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 140032 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 141056 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 142080 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 143104 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 144128 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 145152 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 146176 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 147200 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) === IO: pattern 34 wrote 2048/2048 bytes at offset 148480 2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -4469,42 +5009,78 @@ read 512/512 bytes at offset 109056 read 512/512 bytes at offset 110080 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) === IO: pattern 217 -offset 111360 is not sector aligned -offset 112384 is not sector aligned -offset 113408 is not sector aligned -offset 114432 is not sector aligned -offset 115456 is not sector aligned -offset 116480 is not sector aligned -offset 117504 is not sector aligned -offset 118528 is not sector aligned -offset 119552 is not sector aligned -offset 120576 is not sector aligned -offset 121600 is not sector aligned -offset 122624 is not sector aligned -offset 123648 is not sector aligned -offset 124672 is not sector aligned -offset 125696 is not sector aligned -offset 126720 is not sector aligned -offset 127744 is not sector aligned -offset 128768 is not sector aligned -offset 129792 is not sector aligned -offset 130816 is not sector aligned -offset 131840 is not sector aligned -offset 132864 is not sector aligned -offset 133888 is not sector aligned -offset 134912 is not sector aligned -offset 135936 is not sector aligned -offset 136960 is not sector aligned -offset 137984 is not sector aligned -offset 139008 is not sector aligned -offset 140032 is not sector aligned -offset 141056 is not sector aligned -offset 142080 is not sector aligned -offset 143104 is not sector aligned -offset 144128 is not sector aligned -offset 145152 is not sector aligned -offset 146176 is not sector aligned -offset 147200 is not sector aligned +read 512/512 bytes at offset 111360 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 112384 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 113408 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 114432 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 115456 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 116480 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 117504 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 118528 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 119552 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 120576 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 121600 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 122624 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 123648 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 124672 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 125696 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 126720 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 127744 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 128768 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 129792 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 130816 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 131840 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 132864 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 133888 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 134912 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 135936 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 136960 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 137984 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 139008 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 140032 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 141056 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 142080 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 143104 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 144128 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 145152 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 146176 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 147200 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) === IO: pattern 34 read 2048/2048 bytes at offset 148480 2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -4753,42 +5329,78 @@ wrote 512/512 bytes at offset 4295076352 wrote 512/512 bytes at offset 4295077376 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) === IO: pattern 217 -offset 4295078656 is not sector aligned -offset 4295079680 is not sector aligned -offset 4295080704 is not sector aligned -offset 4295081728 is not sector aligned -offset 4295082752 is not sector aligned -offset 4295083776 is not sector aligned -offset 4295084800 is not sector aligned -offset 4295085824 is not sector aligned -offset 4295086848 is not sector aligned -offset 4295087872 is not sector aligned -offset 4295088896 is not sector aligned -offset 4295089920 is not sector aligned -offset 4295090944 is not sector aligned -offset 4295091968 is not sector aligned -offset 4295092992 is not sector aligned -offset 4295094016 is not sector aligned -offset 4295095040 is not sector aligned -offset 4295096064 is not sector aligned -offset 4295097088 is not sector aligned -offset 4295098112 is not sector aligned -offset 4295099136 is not sector aligned -offset 4295100160 is not sector aligned -offset 4295101184 is not sector aligned -offset 4295102208 is not sector aligned -offset 4295103232 is not sector aligned -offset 4295104256 is not sector aligned -offset 4295105280 is not sector aligned -offset 4295106304 is not sector aligned -offset 4295107328 is not sector aligned -offset 4295108352 is not sector aligned -offset 4295109376 is not sector aligned -offset 4295110400 is not sector aligned -offset 4295111424 is not sector aligned -offset 4295112448 is not sector aligned -offset 4295113472 is not sector aligned -offset 4295114496 is not sector aligned +wrote 512/512 bytes at offset 4295078656 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295079680 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295080704 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295081728 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295082752 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295083776 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295084800 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295085824 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295086848 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295087872 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295088896 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295089920 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295090944 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295091968 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295092992 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295094016 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295095040 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295096064 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295097088 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295098112 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295099136 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295100160 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295101184 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295102208 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295103232 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295104256 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295105280 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295106304 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295107328 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295108352 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295109376 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295110400 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295111424 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295112448 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295113472 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295114496 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) === IO: pattern 34 wrote 2048/2048 bytes at offset 4295115776 2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -5035,42 +5647,78 @@ read 512/512 bytes at offset 4295076352 read 512/512 bytes at offset 4295077376 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) === IO: pattern 217 -offset 4295078656 is not sector aligned -offset 4295079680 is not sector aligned -offset 4295080704 is not sector aligned -offset 4295081728 is not sector aligned -offset 4295082752 is not sector aligned -offset 4295083776 is not sector aligned -offset 4295084800 is not sector aligned -offset 4295085824 is not sector aligned -offset 4295086848 is not sector aligned -offset 4295087872 is not sector aligned -offset 4295088896 is not sector aligned -offset 4295089920 is not sector aligned -offset 4295090944 is not sector aligned -offset 4295091968 is not sector aligned -offset 4295092992 is not sector aligned -offset 4295094016 is not sector aligned -offset 4295095040 is not sector aligned -offset 4295096064 is not sector aligned -offset 4295097088 is not sector aligned -offset 4295098112 is not sector aligned -offset 4295099136 is not sector aligned -offset 4295100160 is not sector aligned -offset 4295101184 is not sector aligned -offset 4295102208 is not sector aligned -offset 4295103232 is not sector aligned -offset 4295104256 is not sector aligned -offset 4295105280 is not sector aligned -offset 4295106304 is not sector aligned -offset 4295107328 is not sector aligned -offset 4295108352 is not sector aligned -offset 4295109376 is not sector aligned -offset 4295110400 is not sector aligned -offset 4295111424 is not sector aligned -offset 4295112448 is not sector aligned -offset 4295113472 is not sector aligned -offset 4295114496 is not sector aligned +read 512/512 bytes at offset 4295078656 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295079680 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295080704 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295081728 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295082752 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295083776 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295084800 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295085824 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295086848 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295087872 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295088896 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295089920 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295090944 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295091968 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295092992 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295094016 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295095040 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295096064 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295097088 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295098112 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295099136 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295100160 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295101184 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295102208 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295103232 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295104256 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295105280 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295106304 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295107328 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295108352 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295109376 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295110400 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295111424 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295112448 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295113472 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295114496 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) === IO: pattern 34 read 2048/2048 bytes at offset 4295115776 2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -5317,42 +5965,78 @@ wrote 512/512 bytes at offset 4295076352 wrote 512/512 bytes at offset 4295077376 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) === IO: pattern 217 -offset 4295078656 is not sector aligned -offset 4295079680 is not sector aligned -offset 4295080704 is not sector aligned -offset 4295081728 is not sector aligned -offset 4295082752 is not sector aligned -offset 4295083776 is not sector aligned -offset 4295084800 is not sector aligned -offset 4295085824 is not sector aligned -offset 4295086848 is not sector aligned -offset 4295087872 is not sector aligned -offset 4295088896 is not sector aligned -offset 4295089920 is not sector aligned -offset 4295090944 is not sector aligned -offset 4295091968 is not sector aligned -offset 4295092992 is not sector aligned -offset 4295094016 is not sector aligned -offset 4295095040 is not sector aligned -offset 4295096064 is not sector aligned -offset 4295097088 is not sector aligned -offset 4295098112 is not sector aligned -offset 4295099136 is not sector aligned -offset 4295100160 is not sector aligned -offset 4295101184 is not sector aligned -offset 4295102208 is not sector aligned -offset 4295103232 is not sector aligned -offset 4295104256 is not sector aligned -offset 4295105280 is not sector aligned -offset 4295106304 is not sector aligned -offset 4295107328 is not sector aligned -offset 4295108352 is not sector aligned -offset 4295109376 is not sector aligned -offset 4295110400 is not sector aligned -offset 4295111424 is not sector aligned -offset 4295112448 is not sector aligned -offset 4295113472 is not sector aligned -offset 4295114496 is not sector aligned +wrote 512/512 bytes at offset 4295078656 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295079680 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295080704 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295081728 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295082752 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295083776 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295084800 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295085824 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295086848 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295087872 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295088896 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295089920 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295090944 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295091968 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295092992 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295094016 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295095040 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295096064 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295097088 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295098112 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295099136 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295100160 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295101184 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295102208 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295103232 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295104256 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295105280 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295106304 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295107328 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295108352 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295109376 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295110400 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295111424 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295112448 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295113472 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 4295114496 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) === IO: pattern 34 wrote 2048/2048 bytes at offset 4295115776 2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -5599,42 +6283,78 @@ read 512/512 bytes at offset 4295076352 read 512/512 bytes at offset 4295077376 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) === IO: pattern 217 -offset 4295078656 is not sector aligned -offset 4295079680 is not sector aligned -offset 4295080704 is not sector aligned -offset 4295081728 is not sector aligned -offset 4295082752 is not sector aligned -offset 4295083776 is not sector aligned -offset 4295084800 is not sector aligned -offset 4295085824 is not sector aligned -offset 4295086848 is not sector aligned -offset 4295087872 is not sector aligned -offset 4295088896 is not sector aligned -offset 4295089920 is not sector aligned -offset 4295090944 is not sector aligned -offset 4295091968 is not sector aligned -offset 4295092992 is not sector aligned -offset 4295094016 is not sector aligned -offset 4295095040 is not sector aligned -offset 4295096064 is not sector aligned -offset 4295097088 is not sector aligned -offset 4295098112 is not sector aligned -offset 4295099136 is not sector aligned -offset 4295100160 is not sector aligned -offset 4295101184 is not sector aligned -offset 4295102208 is not sector aligned -offset 4295103232 is not sector aligned -offset 4295104256 is not sector aligned -offset 4295105280 is not sector aligned -offset 4295106304 is not sector aligned -offset 4295107328 is not sector aligned -offset 4295108352 is not sector aligned -offset 4295109376 is not sector aligned -offset 4295110400 is not sector aligned -offset 4295111424 is not sector aligned -offset 4295112448 is not sector aligned -offset 4295113472 is not sector aligned -offset 4295114496 is not sector aligned +read 512/512 bytes at offset 4295078656 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295079680 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295080704 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295081728 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295082752 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295083776 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295084800 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295085824 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295086848 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295087872 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295088896 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295089920 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295090944 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295091968 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295092992 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295094016 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295095040 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295096064 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295097088 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295098112 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295099136 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295100160 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295101184 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295102208 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295103232 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295104256 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295105280 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295106304 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295107328 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295108352 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295109376 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295110400 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295111424 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295112448 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295113472 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 4295114496 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) === IO: pattern 34 read 2048/2048 bytes at offset 4295115776 2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -- cgit v1.2.3 From 770e0e0e808c6cd361c718ca1a936ed18864c69e Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Sat, 7 May 2016 21:16:44 -0600 Subject: qemu-io: Add 'write -f' to test FUA flag Make it easier to test block drivers with BDRV_REQ_FUA in .supported_write_flags, by adding the '-f' flag to qemu-io to conditionally pass the flag through to specific writes ('write', 'write -z', 'writev', 'aio_write', 'aio_write -z'). You'll want to use 'qemu-io -t none' to actually make -f useful (as otherwise, the default writethrough mode automatically sets the FUA bit on every write). Signed-off-by: Eric Blake Message-id: 1462677405-4752-6-git-send-email-eblake@redhat.com Reviewed-by: Max Reitz Signed-off-by: Max Reitz --- qemu-io-cmds.c | 57 +++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 41 insertions(+), 16 deletions(-) diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c index ab140461e0..71ae8d0088 100644 --- a/qemu-io-cmds.c +++ b/qemu-io-cmds.c @@ -428,13 +428,13 @@ static int do_pread(BlockBackend *blk, char *buf, int64_t offset, } static int do_pwrite(BlockBackend *blk, char *buf, int64_t offset, - int64_t count, int64_t *total) + int64_t count, int flags, int64_t *total) { if (count > INT_MAX) { return -ERANGE; } - *total = blk_pwrite(blk, offset, (uint8_t *)buf, count, 0); + *total = blk_pwrite(blk, offset, (uint8_t *)buf, count, flags); if (*total < 0) { return *total; } @@ -446,6 +446,7 @@ typedef struct { int64_t offset; int64_t count; int64_t *total; + int flags; int ret; bool done; } CoWriteZeroes; @@ -454,7 +455,8 @@ static void coroutine_fn co_write_zeroes_entry(void *opaque) { CoWriteZeroes *data = opaque; - data->ret = blk_co_write_zeroes(data->blk, data->offset, data->count, 0); + data->ret = blk_co_write_zeroes(data->blk, data->offset, data->count, + data->flags); data->done = true; if (data->ret < 0) { *data->total = data->ret; @@ -465,7 +467,7 @@ static void coroutine_fn co_write_zeroes_entry(void *opaque) } static int do_co_write_zeroes(BlockBackend *blk, int64_t offset, int64_t count, - int64_t *total) + int flags, int64_t *total) { Coroutine *co; CoWriteZeroes data = { @@ -473,6 +475,7 @@ static int do_co_write_zeroes(BlockBackend *blk, int64_t offset, int64_t count, .offset = offset, .count = count, .total = total, + .flags = flags, .done = false, }; @@ -558,11 +561,11 @@ static int do_aio_readv(BlockBackend *blk, QEMUIOVector *qiov, } static int do_aio_writev(BlockBackend *blk, QEMUIOVector *qiov, - int64_t offset, int *total) + int64_t offset, int flags, int *total) { int async_ret = NOT_DONE; - blk_aio_pwritev(blk, offset, qiov, 0, aio_rw_done, &async_ret); + blk_aio_pwritev(blk, offset, qiov, flags, aio_rw_done, &async_ret); while (async_ret == NOT_DONE) { main_loop_wait(false); } @@ -935,6 +938,7 @@ static void write_help(void) " filled with a set pattern (0xcdcdcdcd).\n" " -b, -- write to the VM state rather than the virtual disk\n" " -c, -- write compressed data with blk_write_compressed\n" +" -f, -- use Force Unit Access semantics\n" " -p, -- ignored for backwards compatibility\n" " -P, -- use different pattern to fill file\n" " -C, -- report statistics in a machine parsable format\n" @@ -951,7 +955,7 @@ static const cmdinfo_t write_cmd = { .cfunc = write_f, .argmin = 2, .argmax = -1, - .args = "[-bcCqz] [-P pattern] off len", + .args = "[-bcCfqz] [-P pattern] off len", .oneline = "writes a number of bytes at a specified offset", .help = write_help, }; @@ -961,6 +965,7 @@ static int write_f(BlockBackend *blk, int argc, char **argv) struct timeval t1, t2; bool Cflag = false, qflag = false, bflag = false; bool Pflag = false, zflag = false, cflag = false; + int flags = 0; int c, cnt; char *buf = NULL; int64_t offset; @@ -969,7 +974,7 @@ static int write_f(BlockBackend *blk, int argc, char **argv) int64_t total = 0; int pattern = 0xcd; - while ((c = getopt(argc, argv, "bcCpP:qz")) != -1) { + while ((c = getopt(argc, argv, "bcCfpP:qz")) != -1) { switch (c) { case 'b': bflag = true; @@ -980,6 +985,9 @@ static int write_f(BlockBackend *blk, int argc, char **argv) case 'C': Cflag = true; break; + case 'f': + flags |= BDRV_REQ_FUA; + break; case 'p': /* Ignored for backwards compatibility */ break; @@ -1010,6 +1018,11 @@ static int write_f(BlockBackend *blk, int argc, char **argv) return 0; } + if ((flags & BDRV_REQ_FUA) && (bflag || cflag)) { + printf("-f and -b or -c cannot be specified at the same time\n"); + return 0; + } + if (zflag && Pflag) { printf("-z and -P cannot be specified at the same time\n"); return 0; @@ -1054,11 +1067,11 @@ static int write_f(BlockBackend *blk, int argc, char **argv) if (bflag) { cnt = do_save_vmstate(blk, buf, offset, count, &total); } else if (zflag) { - cnt = do_co_write_zeroes(blk, offset, count, &total); + cnt = do_co_write_zeroes(blk, offset, count, flags, &total); } else if (cflag) { cnt = do_write_compressed(blk, buf, offset, count, &total); } else { - cnt = do_pwrite(blk, buf, offset, count, &total); + cnt = do_pwrite(blk, buf, offset, count, flags, &total); } gettimeofday(&t2, NULL); @@ -1097,6 +1110,7 @@ writev_help(void) " filled with a set pattern (0xcdcdcdcd).\n" " -P, -- use different pattern to fill file\n" " -C, -- report statistics in a machine parsable format\n" +" -f, -- use Force Unit Access semantics\n" " -q, -- quiet mode, do not show I/O statistics\n" "\n"); } @@ -1108,7 +1122,7 @@ static const cmdinfo_t writev_cmd = { .cfunc = writev_f, .argmin = 2, .argmax = -1, - .args = "[-Cq] [-P pattern] off len [len..]", + .args = "[-Cfq] [-P pattern] off len [len..]", .oneline = "writes a number of bytes at a specified offset", .help = writev_help, }; @@ -1117,6 +1131,7 @@ static int writev_f(BlockBackend *blk, int argc, char **argv) { struct timeval t1, t2; bool Cflag = false, qflag = false; + int flags = 0; int c, cnt; char *buf; int64_t offset; @@ -1131,6 +1146,9 @@ static int writev_f(BlockBackend *blk, int argc, char **argv) case 'C': Cflag = true; break; + case 'f': + flags |= BDRV_REQ_FUA; + break; case 'q': qflag = true; break; @@ -1163,7 +1181,7 @@ static int writev_f(BlockBackend *blk, int argc, char **argv) } gettimeofday(&t1, NULL); - cnt = do_aio_writev(blk, &qiov, offset, &total); + cnt = do_aio_writev(blk, &qiov, offset, flags, &total); gettimeofday(&t2, NULL); if (cnt < 0) { @@ -1541,6 +1559,7 @@ static void aio_write_help(void) " used to ensure all outstanding aio requests have been completed.\n" " -P, -- use different pattern to fill file\n" " -C, -- report statistics in a machine parsable format\n" +" -f, -- use Force Unit Access semantics\n" " -q, -- quiet mode, do not show I/O statistics\n" " -z, -- write zeroes using blk_aio_write_zeroes\n" "\n"); @@ -1553,7 +1572,7 @@ static const cmdinfo_t aio_write_cmd = { .cfunc = aio_write_f, .argmin = 2, .argmax = -1, - .args = "[-Cqz] [-P pattern] off len [len..]", + .args = "[-Cfqz] [-P pattern] off len [len..]", .oneline = "asynchronously writes a number of bytes", .help = aio_write_help, }; @@ -1563,13 +1582,17 @@ static int aio_write_f(BlockBackend *blk, int argc, char **argv) int nr_iov, c; int pattern = 0xcd; struct aio_ctx *ctx = g_new0(struct aio_ctx, 1); + int flags = 0; ctx->blk = blk; - while ((c = getopt(argc, argv, "CqP:z")) != -1) { + while ((c = getopt(argc, argv, "CfqP:z")) != -1) { switch (c) { case 'C': ctx->Cflag = true; break; + case 'f': + flags |= BDRV_REQ_FUA; + break; case 'q': ctx->qflag = true; break; @@ -1623,7 +1646,8 @@ static int aio_write_f(BlockBackend *blk, int argc, char **argv) } ctx->qiov.size = count; - blk_aio_write_zeroes(blk, ctx->offset, count, 0, aio_write_done, ctx); + blk_aio_write_zeroes(blk, ctx->offset, count, flags, aio_write_done, + ctx); } else { nr_iov = argc - optind; ctx->buf = create_iovec(blk, &ctx->qiov, &argv[optind], nr_iov, @@ -1638,7 +1662,8 @@ static int aio_write_f(BlockBackend *blk, int argc, char **argv) block_acct_start(blk_get_stats(blk), &ctx->acct, ctx->qiov.size, BLOCK_ACCT_WRITE); - blk_aio_pwritev(blk, ctx->offset, &ctx->qiov, 0, aio_write_done, ctx); + blk_aio_pwritev(blk, ctx->offset, &ctx->qiov, flags, aio_write_done, + ctx); } return 0; } -- cgit v1.2.3 From c2e001cc829031f9c2e2c364c77861e3f75ac871 Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Sat, 7 May 2016 21:16:45 -0600 Subject: qemu-io: Add 'write -z -u' to test MAY_UNMAP flag Make it easier to control whether the BDRV_REQ_MAY_UNMAP flag can be passed through a write_zeroes command, by adding the '-u' flag to qemu-io 'write -z' and 'aio_write -z'. To be useful, the device has to be opened with BDRV_O_UNMAP (done by default in qemu-io, but can be made explicit with '-d unmap'). Signed-off-by: Eric Blake Reviewed-by: Max Reitz Message-id: 1462677405-4752-7-git-send-email-eblake@redhat.com Signed-off-by: Max Reitz --- qemu-io-cmds.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c index 71ae8d0088..4a00bc604d 100644 --- a/qemu-io-cmds.c +++ b/qemu-io-cmds.c @@ -943,6 +943,7 @@ static void write_help(void) " -P, -- use different pattern to fill file\n" " -C, -- report statistics in a machine parsable format\n" " -q, -- quiet mode, do not show I/O statistics\n" +" -u, -- with -z, allow unmapping\n" " -z, -- write zeroes using blk_co_write_zeroes\n" "\n"); } @@ -955,7 +956,7 @@ static const cmdinfo_t write_cmd = { .cfunc = write_f, .argmin = 2, .argmax = -1, - .args = "[-bcCfqz] [-P pattern] off len", + .args = "[-bcCfquz] [-P pattern] off len", .oneline = "writes a number of bytes at a specified offset", .help = write_help, }; @@ -974,7 +975,7 @@ static int write_f(BlockBackend *blk, int argc, char **argv) int64_t total = 0; int pattern = 0xcd; - while ((c = getopt(argc, argv, "bcCfpP:qz")) != -1) { + while ((c = getopt(argc, argv, "bcCfpP:quz")) != -1) { switch (c) { case 'b': bflag = true; @@ -1001,6 +1002,9 @@ static int write_f(BlockBackend *blk, int argc, char **argv) case 'q': qflag = true; break; + case 'u': + flags |= BDRV_REQ_MAY_UNMAP; + break; case 'z': zflag = true; break; @@ -1023,6 +1027,11 @@ static int write_f(BlockBackend *blk, int argc, char **argv) return 0; } + if ((flags & BDRV_REQ_MAY_UNMAP) && !zflag) { + printf("-u requires -z to be specified\n"); + return 0; + } + if (zflag && Pflag) { printf("-z and -P cannot be specified at the same time\n"); return 0; @@ -1561,6 +1570,7 @@ static void aio_write_help(void) " -C, -- report statistics in a machine parsable format\n" " -f, -- use Force Unit Access semantics\n" " -q, -- quiet mode, do not show I/O statistics\n" +" -u, -- with -z, allow unmapping\n" " -z, -- write zeroes using blk_aio_write_zeroes\n" "\n"); } @@ -1572,7 +1582,7 @@ static const cmdinfo_t aio_write_cmd = { .cfunc = aio_write_f, .argmin = 2, .argmax = -1, - .args = "[-Cfqz] [-P pattern] off len [len..]", + .args = "[-Cfquz] [-P pattern] off len [len..]", .oneline = "asynchronously writes a number of bytes", .help = aio_write_help, }; @@ -1596,6 +1606,9 @@ static int aio_write_f(BlockBackend *blk, int argc, char **argv) case 'q': ctx->qflag = true; break; + case 'u': + flags |= BDRV_REQ_MAY_UNMAP; + break; case 'P': pattern = parse_pattern(optarg); if (pattern < 0) { @@ -1623,6 +1636,11 @@ static int aio_write_f(BlockBackend *blk, int argc, char **argv) return 0; } + if ((flags & BDRV_REQ_MAY_UNMAP) && !ctx->zflag) { + printf("-u requires -z to be specified\n"); + return 0; + } + if (ctx->zflag && ctx->Pflag) { printf("-z and -P cannot be specified at the same time\n"); g_free(ctx); -- cgit v1.2.3 From 076003f526cebbf5bbef826f752019da5d2c3e89 Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Tue, 10 May 2016 17:11:27 +0100 Subject: block: add support for --image-opts in block I/O tests Currently all block tests use the traditional syntax for images just specifying a filename. To support the LUKS driver without resorting to JSON, the tests need to be able to use the new --image-opts argument to qemu-img and qemu-io. This introduces a new env variable IMGOPTSSYNTAX. If this is set to 'true', then qemu-img/qemu-io should use --image-opts. Signed-off-by: Daniel P. Berrange Message-id: 1462896689-18450-2-git-send-email-berrange@redhat.com Signed-off-by: Max Reitz --- tests/qemu-iotests/039.out | 20 +++++++------- tests/qemu-iotests/061.out | 8 +++--- tests/qemu-iotests/137.out | 4 +-- tests/qemu-iotests/common | 7 ++++- tests/qemu-iotests/common.config | 15 +++++++++-- tests/qemu-iotests/common.rc | 57 +++++++++++++++++++++++++++++----------- 6 files changed, 77 insertions(+), 34 deletions(-) diff --git a/tests/qemu-iotests/039.out b/tests/qemu-iotests/039.out index 32c884694c..c6e0ac2da3 100644 --- a/tests/qemu-iotests/039.out +++ b/tests/qemu-iotests/039.out @@ -12,9 +12,9 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 wrote 512/512 bytes at offset 0 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ./common.config: Killed ( if [ "${VALGRIND_QEMU}" == "y" ]; then - exec valgrind --log-file="${VALGRIND_LOGFILE}" --error-exitcode=99 "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@"; + exec valgrind --log-file="${VALGRIND_LOGFILE}" --error-exitcode=99 "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@"; else - exec "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@"; + exec "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@"; fi ) incompatible_features 0x1 ERROR cluster 5 refcount=0 reference=1 @@ -51,9 +51,9 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 wrote 512/512 bytes at offset 0 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ./common.config: Killed ( if [ "${VALGRIND_QEMU}" == "y" ]; then - exec valgrind --log-file="${VALGRIND_LOGFILE}" --error-exitcode=99 "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@"; + exec valgrind --log-file="${VALGRIND_LOGFILE}" --error-exitcode=99 "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@"; else - exec "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@"; + exec "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@"; fi ) incompatible_features 0x1 ERROR cluster 5 refcount=0 reference=1 @@ -69,9 +69,9 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 wrote 512/512 bytes at offset 0 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ./common.config: Killed ( if [ "${VALGRIND_QEMU}" == "y" ]; then - exec valgrind --log-file="${VALGRIND_LOGFILE}" --error-exitcode=99 "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@"; + exec valgrind --log-file="${VALGRIND_LOGFILE}" --error-exitcode=99 "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@"; else - exec "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@"; + exec "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@"; fi ) incompatible_features 0x0 No errors were found on the image. @@ -92,9 +92,9 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 wrote 512/512 bytes at offset 0 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ./common.config: Killed ( if [ "${VALGRIND_QEMU}" == "y" ]; then - exec valgrind --log-file="${VALGRIND_LOGFILE}" --error-exitcode=99 "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@"; + exec valgrind --log-file="${VALGRIND_LOGFILE}" --error-exitcode=99 "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@"; else - exec "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@"; + exec "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@"; fi ) incompatible_features 0x1 ERROR cluster 5 refcount=0 reference=1 @@ -106,9 +106,9 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 wrote 512/512 bytes at offset 0 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ./common.config: Killed ( if [ "${VALGRIND_QEMU}" == "y" ]; then - exec valgrind --log-file="${VALGRIND_LOGFILE}" --error-exitcode=99 "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@"; + exec valgrind --log-file="${VALGRIND_LOGFILE}" --error-exitcode=99 "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@"; else - exec "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@"; + exec "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@"; fi ) incompatible_features 0x0 No errors were found on the image. diff --git a/tests/qemu-iotests/061.out b/tests/qemu-iotests/061.out index a03732e19c..a431b7f305 100644 --- a/tests/qemu-iotests/061.out +++ b/tests/qemu-iotests/061.out @@ -58,9 +58,9 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 wrote 131072/131072 bytes at offset 0 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ./common.config: Killed ( if [ "${VALGRIND_QEMU}" == "y" ]; then - exec valgrind --log-file="${VALGRIND_LOGFILE}" --error-exitcode=99 "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@"; + exec valgrind --log-file="${VALGRIND_LOGFILE}" --error-exitcode=99 "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@"; else - exec "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@"; + exec "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@"; fi ) magic 0x514649fb version 3 @@ -220,9 +220,9 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 wrote 131072/131072 bytes at offset 0 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ./common.config: Killed ( if [ "${VALGRIND_QEMU}" == "y" ]; then - exec valgrind --log-file="${VALGRIND_LOGFILE}" --error-exitcode=99 "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@"; + exec valgrind --log-file="${VALGRIND_LOGFILE}" --error-exitcode=99 "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@"; else - exec "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@"; + exec "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@"; fi ) magic 0x514649fb version 3 diff --git a/tests/qemu-iotests/137.out b/tests/qemu-iotests/137.out index 88c702cf77..c0e753483b 100644 --- a/tests/qemu-iotests/137.out +++ b/tests/qemu-iotests/137.out @@ -32,9 +32,9 @@ Unsupported value 'blubb' for qcow2 option 'overlap-check'. Allowed are any of t wrote 512/512 bytes at offset 0 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ./common.config: Killed ( if [ "${VALGRIND_QEMU}" == "y" ]; then - exec valgrind --log-file="${VALGRIND_LOGFILE}" --error-exitcode=99 "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@"; + exec valgrind --log-file="${VALGRIND_LOGFILE}" --error-exitcode=99 "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@"; else - exec "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@"; + exec "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@"; fi ) incompatible_features 0x0 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 diff --git a/tests/qemu-iotests/common b/tests/qemu-iotests/common index 49e1931129..fe3b1a0af8 100644 --- a/tests/qemu-iotests/common +++ b/tests/qemu-iotests/common @@ -53,6 +53,7 @@ export QEMU_IO_OPTIONS="" export CACHEMODE_IS_DEFAULT=true export QEMU_OPTIONS="-nodefaults" export VALGRIND_QEMU= +export IMGOPTSSYNTAX=false for r do @@ -399,7 +400,11 @@ BEGIN { for (t='$start'; t<='$end'; t++) printf "%03d\n",t }' \ done # Set qemu-io cache mode with $CACHEMODE we have -QEMU_IO_OPTIONS="$QEMU_IO_OPTIONS -f $IMGFMT --cache $CACHEMODE" +if [ "$IMGOPTSSYNTAX" = "true" ]; then + QEMU_IO_OPTIONS="$QEMU_IO_OPTIONS --cache $CACHEMODE" +else + QEMU_IO_OPTIONS="$QEMU_IO_OPTIONS -f $IMGFMT --cache $CACHEMODE" +fi # Set default options for qemu-img create -o if they were not specified _set_default_imgopts diff --git a/tests/qemu-iotests/common.config b/tests/qemu-iotests/common.config index f824651bac..ea698da92e 100644 --- a/tests/qemu-iotests/common.config +++ b/tests/qemu-iotests/common.config @@ -123,12 +123,16 @@ _qemu_img_wrapper() _qemu_io_wrapper() { local VALGRIND_LOGFILE="${TEST_DIR}"/$$.valgrind + local QEMU_IO_ARGS="$QEMU_IO_OPTIONS" + if [ "$IMGOPTSSYNTAX" = "true" ]; then + QEMU_IO_ARGS="--image-opts $QEMU_IO_ARGS" + fi local RETVAL ( if [ "${VALGRIND_QEMU}" == "y" ]; then - exec valgrind --log-file="${VALGRIND_LOGFILE}" --error-exitcode=99 "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@" + exec valgrind --log-file="${VALGRIND_LOGFILE}" --error-exitcode=99 "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@" else - exec "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@" + exec "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@" fi ) RETVAL=$? @@ -154,6 +158,13 @@ export QEMU_IMG=_qemu_img_wrapper export QEMU_IO=_qemu_io_wrapper export QEMU_NBD=_qemu_nbd_wrapper +QEMU_IMG_EXTRA_ARGS= +if [ "$IMGOPTSSYNTAX" = "true" ]; then + QEMU_IMG_EXTRA_ARGS="--image-opts $QEMU_IMG_EXTRA_ARGS" +fi +export QEMU_IMG_EXTRA_ARGS + + default_machine=$($QEMU -machine help | sed -n '/(default)/ s/ .*//p') default_alias_machine=$($QEMU -machine help | \ sed -n "/(alias of $default_machine)/ { s/ .*//p; q; }") diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc index 5249ec5922..080f1bc9b2 100644 --- a/tests/qemu-iotests/common.rc +++ b/tests/qemu-iotests/common.rc @@ -53,21 +53,42 @@ fi # make sure we have a standard umask umask 022 -if [ "$IMGPROTO" = "file" ]; then - TEST_IMG=$TEST_DIR/t.$IMGFMT -elif [ "$IMGPROTO" = "nbd" ]; then - TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT - TEST_IMG="nbd:127.0.0.1:10810" -elif [ "$IMGPROTO" = "ssh" ]; then - TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT - TEST_IMG="ssh://127.0.0.1$TEST_IMG_FILE" -elif [ "$IMGPROTO" = "nfs" ]; then - TEST_DIR="nfs://127.0.0.1/$TEST_DIR" - TEST_IMG=$TEST_DIR/t.$IMGFMT -elif [ "$IMGPROTO" = "archipelago" ]; then - TEST_IMG="archipelago:at.$IMGFMT" +if [ "$IMGOPTSSYNTAX" = "true" ]; then + DRIVER="driver=$IMGFMT" + if [ "$IMGPROTO" = "file" ]; then + TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT + TEST_IMG="$DRIVER,file.filename=$TEST_DIR/t.$IMGFMT" + elif [ "$IMGPROTO" = "nbd" ]; then + TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT + TEST_IMG="$DRIVER,file.driver=nbd,file.host=127.0.0.1,file.port=10810" + elif [ "$IMGPROTO" = "ssh" ]; then + TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT + TEST_IMG="$DRIVER,file.driver=ssh,file.host=127.0.0.1,file.path=$TEST_IMG_FILE" + elif [ "$IMGPROTO" = "nfs" ]; then + TEST_DIR="$DRIVER,file.driver=nfs,file.filename=nfs://127.0.0.1/$TEST_DIR" + TEST_IMG=$TEST_DIR_OPTS/t.$IMGFMT + elif [ "$IMGPROTO" = "archipelago" ]; then + TEST_IMG="$DRIVER,file.driver=archipelago,file.volume=:at.$IMGFMT" + else + TEST_IMG="$DRIVER,file.driver=$IMGPROTO,file.filename=$TEST_DIR/t.$IMGFMT" + fi else - TEST_IMG=$IMGPROTO:$TEST_DIR/t.$IMGFMT + if [ "$IMGPROTO" = "file" ]; then + TEST_IMG=$TEST_DIR/t.$IMGFMT + elif [ "$IMGPROTO" = "nbd" ]; then + TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT + TEST_IMG="nbd:127.0.0.1:10810" + elif [ "$IMGPROTO" = "ssh" ]; then + TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT + TEST_IMG="ssh://127.0.0.1$TEST_IMG_FILE" + elif [ "$IMGPROTO" = "nfs" ]; then + TEST_DIR="nfs://127.0.0.1/$TEST_DIR" + TEST_IMG=$TEST_DIR/t.$IMGFMT + elif [ "$IMGPROTO" = "archipelago" ]; then + TEST_IMG="archipelago:at.$IMGFMT" + else + TEST_IMG=$IMGPROTO:$TEST_DIR/t.$IMGFMT + fi fi _optstr_add() @@ -199,7 +220,13 @@ _cleanup_test_img() _check_test_img() { - $QEMU_IMG check "$@" -f $IMGFMT "$TEST_IMG" 2>&1 | _filter_testdir | \ + ( + if [ "$IMGOPTSSYNTAX" = "true" ]; then + $QEMU_IMG check $QEMU_IMG_EXTRA_ARGS "$@" "$TEST_IMG" 2>&1 + else + $QEMU_IMG check "$@" -f $IMGFMT "$TEST_IMG" 2>&1 + fi + ) | _filter_testdir | \ sed -e '/allocated.*fragmented.*compressed clusters/d' \ -e 's/qemu-img: This image format does not support checks/No errors were found on the image./' \ -e '/Image end offset: [0-9]\+/d' -- cgit v1.2.3 From b7e875b2f98c2724b5f915f5808f8828fd9b05a8 Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Tue, 10 May 2016 17:11:28 +0100 Subject: block: add support for encryption secrets in block I/O tests The LUKS block driver tests will require the ability to specify encryption secrets with block devices. This requires using the --object argument to qemu-img/qemu-io to create a 'secret' object. When the IMGKEYSECRET env variable is set, it provides the password to be associated with a secret called 'keysec0' The _qemu_img_wrapper function isn't modified as that needs to cope with differing syntax for subcommands, so can't be made to use the image opts syntax unconditionally. Signed-off-by: Daniel P. Berrange Message-id: 1462896689-18450-3-git-send-email-berrange@redhat.com Signed-off-by: Max Reitz --- tests/qemu-iotests/common | 1 + tests/qemu-iotests/common.config | 6 ++++++ tests/qemu-iotests/common.filter | 3 ++- tests/qemu-iotests/common.rc | 9 +++++++-- 4 files changed, 16 insertions(+), 3 deletions(-) diff --git a/tests/qemu-iotests/common b/tests/qemu-iotests/common index fe3b1a0af8..e87287ca79 100644 --- a/tests/qemu-iotests/common +++ b/tests/qemu-iotests/common @@ -53,6 +53,7 @@ export QEMU_IO_OPTIONS="" export CACHEMODE_IS_DEFAULT=true export QEMU_OPTIONS="-nodefaults" export VALGRIND_QEMU= +export IMGKEYSECRET= export IMGOPTSSYNTAX=false for r diff --git a/tests/qemu-iotests/common.config b/tests/qemu-iotests/common.config index ea698da92e..f6384fbae7 100644 --- a/tests/qemu-iotests/common.config +++ b/tests/qemu-iotests/common.config @@ -126,6 +126,9 @@ _qemu_io_wrapper() local QEMU_IO_ARGS="$QEMU_IO_OPTIONS" if [ "$IMGOPTSSYNTAX" = "true" ]; then QEMU_IO_ARGS="--image-opts $QEMU_IO_ARGS" + if [ -n "$IMGKEYSECRET" ]; then + QEMU_IO_ARGS="--object secret,id=keysec0,data=$IMGKEYSECRET $QEMU_IO_ARGS" + fi fi local RETVAL ( @@ -161,6 +164,9 @@ export QEMU_NBD=_qemu_nbd_wrapper QEMU_IMG_EXTRA_ARGS= if [ "$IMGOPTSSYNTAX" = "true" ]; then QEMU_IMG_EXTRA_ARGS="--image-opts $QEMU_IMG_EXTRA_ARGS" + if [ -n "$IMGKEYSECRET" ]; then + QEMU_IMG_EXTRA_ARGS="--object secret,id=keysec0,data=$IMGKEYSECRET $QEMU_IMG_EXTRA_ARGS" + fi fi export QEMU_IMG_EXTRA_ARGS diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter index 72f77fa67c..7853dbbfdc 100644 --- a/tests/qemu-iotests/common.filter +++ b/tests/qemu-iotests/common.filter @@ -98,7 +98,8 @@ _filter_img_create() -e "s# block_state_zero=\\(on\\|off\\)##g" \ -e "s# log_size=[0-9]\\+##g" \ -e "s/archipelago:a/TEST_DIR\//g" \ - -e "s# refcount_bits=[0-9]\\+##g" + -e "s# refcount_bits=[0-9]\\+##g" \ + -e "s# key-secret=[a-zA-Z0-9]\\+##g" } _filter_img_info() diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc index 080f1bc9b2..164792d259 100644 --- a/tests/qemu-iotests/common.rc +++ b/tests/qemu-iotests/common.rc @@ -129,6 +129,7 @@ _make_test_img() local img_name="" local use_backing=0 local backing_file="" + local object_options="" if [ -n "$TEST_IMG_FILE" ]; then img_name=$TEST_IMG_FILE @@ -139,6 +140,10 @@ _make_test_img() if [ -n "$IMGOPTS" ]; then optstr=$(_optstr_add "$optstr" "$IMGOPTS") fi + if [ -n "$IMGKEYSECRET" ]; then + object_options="--object secret,id=keysec0,data=$IMGKEYSECRET" + optstr=$(_optstr_add "$optstr" "key-secret=keysec0") + fi if [ "$1" = "-b" ]; then use_backing=1 @@ -156,9 +161,9 @@ _make_test_img() # XXX(hch): have global image options? ( if [ $use_backing = 1 ]; then - $QEMU_IMG create -f $IMGFMT $extra_img_options -b "$backing_file" "$img_name" $image_size 2>&1 + $QEMU_IMG create $object_options -f $IMGFMT $extra_img_options -b "$backing_file" "$img_name" $image_size 2>&1 else - $QEMU_IMG create -f $IMGFMT $extra_img_options "$img_name" $image_size 2>&1 + $QEMU_IMG create $object_options -f $IMGFMT $extra_img_options "$img_name" $image_size 2>&1 fi ) | _filter_img_create -- cgit v1.2.3 From 4e9b25fb054257712004272f35de508a6ae998e5 Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Tue, 10 May 2016 17:11:29 +0100 Subject: block: enable testing of LUKS driver with block I/O tests This adds support for testing the LUKS driver with the block I/O test framework. cd tests/qemu-io-tests ./check -luks A handful of test cases are modified to work with luks - 004 - whitelist luks format - 012 - use TEST_IMG_FILE instead of TEST_IMG for file ops - 048 - use TEST_IMG_FILE instead of TEST_IMG for file ops. don't assume extended image contents is all zeros, explicitly initialize with zeros Make file size smaller to avoid having to decrypt 1 GB of data. - 052 - don't assume initial image contents is all zeros, explicitly initialize with zeros - 100 - don't assume initial image contents is all zeros, explicitly initialize with zeros With this patch applied, the results are as follows: Passed: 001 002 003 004 005 008 009 010 011 012 021 032 043 047 048 049 052 087 100 134 143 Failed: 033 120 140 145 Skipped: 007 013 014 015 017 018 019 020 022 023 024 025 026 027 028 029 030 031 034 035 036 037 038 039 040 041 042 043 044 045 046 047 049 050 051 053 054 055 056 057 058 059 060 061 062 063 064 065 066 067 068 069 070 071 072 073 074 075 076 077 078 079 080 081 082 083 084 085 086 087 088 089 090 091 092 093 094 095 096 097 098 099 101 102 103 104 105 107 108 109 110 111 112 113 114 115 116 117 118 119 121 122 123 124 128 129 130 131 132 133 134 135 136 137 138 139 141 142 144 146 148 150 152 The reasons for the failed tests are: - 033 - needs adapting to use image opts syntax with blkdebug and test image in order to correctly set align property - 120 - needs adapting to use correct -drive syntax for luks - 140 - needs adapting to use correct -drive syntax for luks - 145 - needs adapting to use correct -drive syntax for luks The vast majority of skipped tests are exercising code that is qcow2 specific, though a couple could probably be usefully enabled for luks too. Signed-off-by: Daniel P. Berrange Message-id: 1462896689-18450-4-git-send-email-berrange@redhat.com Signed-off-by: Max Reitz --- tests/qemu-iotests/004 | 2 +- tests/qemu-iotests/012 | 5 ++++- tests/qemu-iotests/048 | 26 +++++++++++++++++++------- tests/qemu-iotests/048.out | 6 ++++-- tests/qemu-iotests/052 | 4 ++++ tests/qemu-iotests/052.out | 4 ++++ tests/qemu-iotests/100 | 7 +++++++ tests/qemu-iotests/100.out | 14 ++++++++++++++ tests/qemu-iotests/common | 7 +++++++ tests/qemu-iotests/common.rc | 3 +++ 10 files changed, 67 insertions(+), 11 deletions(-) diff --git a/tests/qemu-iotests/004 b/tests/qemu-iotests/004 index 67e1beb209..6f2aa3d9a2 100755 --- a/tests/qemu-iotests/004 +++ b/tests/qemu-iotests/004 @@ -37,7 +37,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 . ./common.rc . ./common.filter -_supported_fmt raw qcow qcow2 qed vdi vmdk vhdx +_supported_fmt raw qcow qcow2 qed vdi vmdk vhdx luks _supported_proto generic _supported_os Linux diff --git a/tests/qemu-iotests/012 b/tests/qemu-iotests/012 index d1d3f22093..01a770d59c 100755 --- a/tests/qemu-iotests/012 +++ b/tests/qemu-iotests/012 @@ -43,13 +43,16 @@ _supported_fmt generic _supported_proto file _supported_os Linux +# Remove once all tests are fixed to use TEST_IMG_FILE +# correctly and common.rc sets it unconditionally +test -z "$TEST_IMG_FILE" && TEST_IMG_FILE=$TEST_IMG size=128M _make_test_img $size echo echo "== mark image read-only" -chmod a-w "$TEST_IMG" +chmod a-w "$TEST_IMG_FILE" echo echo "== read from read-only image" diff --git a/tests/qemu-iotests/048 b/tests/qemu-iotests/048 index e1eeac2a31..203c04fc7f 100755 --- a/tests/qemu-iotests/048 +++ b/tests/qemu-iotests/048 @@ -31,13 +31,13 @@ _cleanup() { echo "Cleanup" _cleanup_test_img - rm "${TEST_IMG2}" + rm "${TEST_IMG_FILE2}" } trap "_cleanup; exit \$status" 0 1 2 3 15 _compare() { - $QEMU_IMG compare "$@" "$TEST_IMG" "${TEST_IMG2}" + $QEMU_IMG compare $QEMU_IMG_EXTRA_ARGS "$@" "$TEST_IMG" "${TEST_IMG2}" echo $? } @@ -46,25 +46,37 @@ _compare() . ./common.filter . ./common.pattern -_supported_fmt raw qcow qcow2 qed +_supported_fmt raw qcow qcow2 qed luks _supported_proto file _supported_os Linux +# Remove once all tests are fixed to use TEST_IMG_FILE +# correctly and common.rc sets it unconditionally +test -z "$TEST_IMG_FILE" && TEST_IMG_FILE=$TEST_IMG + # Setup test basic parameters TEST_IMG2=$TEST_IMG.2 +TEST_IMG_FILE2=$TEST_IMG_FILE.2 CLUSTER_SIZE=4096 -size=1024M +size=128M _make_test_img $size io_pattern write 524288 $CLUSTER_SIZE $CLUSTER_SIZE 4 45 # Compare identical images -cp "$TEST_IMG" "${TEST_IMG2}" +cp "$TEST_IMG_FILE" "${TEST_IMG_FILE2}" _compare _compare -q # Compare images with different size -$QEMU_IMG resize -f $IMGFMT "$TEST_IMG" +512M +if [ "$IMGOPTSSYNTAX" = "true" ]; then + $QEMU_IMG resize $QEMU_IMG_EXTRA_ARGS "$TEST_IMG" +32M +else + $QEMU_IMG resize -f $IMGFMT "$TEST_IMG" +32M +fi +# Ensure extended space is zero-initialized +$QEMU_IO "$TEST_IMG" -c "write -z $size 32M" | _filter_qemu_io + _compare _compare -s @@ -77,7 +89,7 @@ _compare # Test unaligned case of mismatch offsets in allocated clusters _make_test_img $size io_pattern write 0 512 0 1 100 -cp "$TEST_IMG" "$TEST_IMG2" +cp "$TEST_IMG_FILE" "$TEST_IMG_FILE2" io_pattern write 512 512 0 1 101 _compare diff --git a/tests/qemu-iotests/048.out b/tests/qemu-iotests/048.out index 57100dc453..0bcf6635a1 100644 --- a/tests/qemu-iotests/048.out +++ b/tests/qemu-iotests/048.out @@ -1,5 +1,5 @@ QA output created by 048 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 === IO: pattern 45 wrote 4096/4096 bytes at offset 524288 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -13,6 +13,8 @@ Images are identical. 0 0 Image resized. +wrote 33554432/33554432 bytes at offset 134217728 +32 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) Warning: Image size mismatch! Images are identical. 0 @@ -28,7 +30,7 @@ wrote 4096/4096 bytes at offset 0 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) Content mismatch at offset 0! 1 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 === IO: pattern 100 wrote 512/512 bytes at offset 0 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) diff --git a/tests/qemu-iotests/052 b/tests/qemu-iotests/052 index 4b647242d2..842eaced3b 100755 --- a/tests/qemu-iotests/052 +++ b/tests/qemu-iotests/052 @@ -47,6 +47,10 @@ _supported_cache_modes "writeback" "writethrough" "unsafe" size=128M _make_test_img $size +echo +echo "== initializing whole image ==" +$QEMU_IO -c "write -z 0 $size" "$TEST_IMG" | _filter_qemu_io + echo echo "== reading whole image ==" $QEMU_IO -s -c "read 0 $size" "$TEST_IMG" | _filter_qemu_io diff --git a/tests/qemu-iotests/052.out b/tests/qemu-iotests/052.out index 9dab51c0e8..a377d3028d 100644 --- a/tests/qemu-iotests/052.out +++ b/tests/qemu-iotests/052.out @@ -1,6 +1,10 @@ QA output created by 052 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 +== initializing whole image == +wrote 134217728/134217728 bytes at offset 0 +128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + == reading whole image == read 134217728/134217728 bytes at offset 0 128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) diff --git a/tests/qemu-iotests/100 b/tests/qemu-iotests/100 index 5b2fb33330..e66db07982 100755 --- a/tests/qemu-iotests/100 +++ b/tests/qemu-iotests/100 @@ -47,6 +47,7 @@ size=128M echo echo "== Single request ==" _make_test_img $size +$QEMU_IO -c "write -z 0 8k" "$TEST_IMG" | _filter_qemu_io $QEMU_IO -c "multiwrite 0 4k" "$TEST_IMG" | _filter_qemu_io echo @@ -59,6 +60,7 @@ _cleanup_test_img echo echo "== Sequential requests ==" _make_test_img $size +$QEMU_IO -c "write -z 0 12k" "$TEST_IMG" | _filter_qemu_io $QEMU_IO -c "multiwrite 0 4k ; 4k 4k" "$TEST_IMG" | _filter_qemu_io echo @@ -72,6 +74,7 @@ _cleanup_test_img echo echo "== Superset overlapping requests ==" _make_test_img $size +$QEMU_IO -c "write -z 0 8k" "$TEST_IMG" | _filter_qemu_io $QEMU_IO -c "multiwrite 0 4k ; 1k 2k" "$TEST_IMG" | _filter_qemu_io echo @@ -87,6 +90,7 @@ _cleanup_test_img echo echo "== Subset overlapping requests ==" _make_test_img $size +$QEMU_IO -c "write -z 0 8k" "$TEST_IMG" | _filter_qemu_io $QEMU_IO -c "multiwrite 1k 2k ; 0k 4k" "$TEST_IMG" | _filter_qemu_io echo @@ -102,6 +106,7 @@ _cleanup_test_img echo echo "== Head overlapping requests ==" _make_test_img $size +$QEMU_IO -c "write -z 0 8k" "$TEST_IMG" | _filter_qemu_io $QEMU_IO -c "multiwrite 0k 2k ; 0k 4k" "$TEST_IMG" | _filter_qemu_io echo @@ -116,6 +121,7 @@ _cleanup_test_img echo echo "== Tail overlapping requests ==" _make_test_img $size +$QEMU_IO -c "write -z 0 8k" "$TEST_IMG" | _filter_qemu_io $QEMU_IO -c "multiwrite 2k 2k ; 0k 4k" "$TEST_IMG" | _filter_qemu_io echo @@ -130,6 +136,7 @@ _cleanup_test_img echo echo "== Disjoint requests ==" _make_test_img $size +$QEMU_IO -c "write -z 0 72k" "$TEST_IMG" | _filter_qemu_io $QEMU_IO -c "multiwrite 0 4k ; 64k 4k" "$TEST_IMG" | _filter_qemu_io echo diff --git a/tests/qemu-iotests/100.out b/tests/qemu-iotests/100.out index 05649038d9..a44cae40db 100644 --- a/tests/qemu-iotests/100.out +++ b/tests/qemu-iotests/100.out @@ -2,6 +2,8 @@ QA output created by 100 == Single request == Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 +wrote 8192/8192 bytes at offset 0 +8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 4096/4096 bytes at offset 0 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -13,6 +15,8 @@ read 4096/4096 bytes at offset 4096 == Sequential requests == Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 +wrote 12288/12288 bytes at offset 0 +12 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 8192/8192 bytes at offset 0 8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -26,6 +30,8 @@ read 4096/4096 bytes at offset 8192 == Superset overlapping requests == Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 +wrote 8192/8192 bytes at offset 0 +8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 6144/6144 bytes at offset 0 6 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -39,6 +45,8 @@ read 4096/4096 bytes at offset 4096 == Subset overlapping requests == Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 +wrote 8192/8192 bytes at offset 0 +8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 6144/6144 bytes at offset 1024 6 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -52,6 +60,8 @@ read 4096/4096 bytes at offset 4096 == Head overlapping requests == Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 +wrote 8192/8192 bytes at offset 0 +8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 6144/6144 bytes at offset 0 6 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -63,6 +73,8 @@ read 4096/4096 bytes at offset 4096 == Tail overlapping requests == Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 +wrote 8192/8192 bytes at offset 0 +8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 6144/6144 bytes at offset 2048 6 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -74,6 +86,8 @@ read 4096/4096 bytes at offset 4096 == Disjoint requests == Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 +wrote 73728/73728 bytes at offset 0 +72 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 8192/8192 bytes at offset 0 8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) diff --git a/tests/qemu-iotests/common b/tests/qemu-iotests/common index e87287ca79..d60ea2ce3c 100644 --- a/tests/qemu-iotests/common +++ b/tests/qemu-iotests/common @@ -209,6 +209,13 @@ testlist options xpand=false ;; + -luks) + IMGOPTSSYNTAX=true + IMGFMT=luks + IMGKEYSECRET=123456 + xpand=false + ;; + -qed) IMGFMT=qed xpand=false diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc index 164792d259..306b00c210 100644 --- a/tests/qemu-iotests/common.rc +++ b/tests/qemu-iotests/common.rc @@ -55,6 +55,9 @@ umask 022 if [ "$IMGOPTSSYNTAX" = "true" ]; then DRIVER="driver=$IMGFMT" + if [ "$IMGFMT" = "luks" ]; then + DRIVER="$DRIVER,key-secret=keysec0" + fi if [ "$IMGPROTO" = "file" ]; then TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT TEST_IMG="$DRIVER,file.filename=$TEST_DIR/t.$IMGFMT" -- cgit v1.2.3 From 5a8fabf3333c8b445f514377a4292ad0354fd35c Mon Sep 17 00:00:00 2001 From: Sascha Silbe Date: Tue, 19 Apr 2016 21:34:02 +0200 Subject: qemu-iotests: iotests: fail hard if not run via "check" Running an iotests-based Python test directly might appear to work, but may fail in subtle ways and is insecure: - It creates files with predictable file names in a world-writable location (/var/tmp). - Tests expect the environment to be set up by check. E.g. 041 and 055 may take the wrong code paths if QEMU_DEFAULT_MACHINE is not set. This can lead to false negatives. Instead fail hard and tell the user we want to be run via "check". The actual environment expected by the tests is currently only defined by the implementation of "check". We use two of the environment variables set by "check" as indication of whether we're being run via "check". Anyone writing their own test runner (replacing "check") will need to replicate the full environment (in a broader sense, not just environment variables) provided by "check" anyway, including setting the two environment variables we check. Whereas a regular developer just trying to invoke the tests usually won't have both of these defined in their environment so we can catch their mistake and give out useful advice. Signed-off-by: Sascha Silbe Reviewed-by: Bo Tu Message-id: 1461094442-16014-1-git-send-email-silbe@linux.vnet.ibm.com Signed-off-by: Max Reitz --- tests/qemu-iotests/iotests.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py index 56f988ab3d..1687c33efd 100644 --- a/tests/qemu-iotests/iotests.py +++ b/tests/qemu-iotests/iotests.py @@ -47,7 +47,7 @@ if os.environ.get('QEMU_OPTIONS'): imgfmt = os.environ.get('IMGFMT', 'raw') imgproto = os.environ.get('IMGPROTO', 'file') -test_dir = os.environ.get('TEST_DIR', '/var/tmp') +test_dir = os.environ.get('TEST_DIR') output_dir = os.environ.get('OUTPUT_DIR', '.') cachemode = os.environ.get('CACHEMODE') qemu_default_machine = os.environ.get('QEMU_DEFAULT_MACHINE') @@ -461,6 +461,14 @@ def verify_quorum(): def main(supported_fmts=[], supported_oses=['linux']): '''Run tests''' + # We are using TEST_DIR and QEMU_DEFAULT_MACHINE as proxies to + # indicate that we're not being run via "check". There may be + # other things set up by "check" that individual test cases rely + # on. + if test_dir is None or qemu_default_machine is None: + sys.stderr.write('Please run this test via the "check" script\n') + sys.exit(os.EX_USAGE) + debug = '-d' in sys.argv verbosity = 1 verify_image_format(supported_fmts) -- cgit v1.2.3