The new handle_alloc_space() function only speeds up the allocation of new ranges on solid-state drives. We should skip it if we know that the file is stored on a rotating disk.
Signed-off-by: Max Reitz <mre...@redhat.com> --- block/qcow2.h | 3 +++ block/qcow2.c | 34 ++++++++++++++++++++++++++++++---- 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/block/qcow2.h b/block/qcow2.h index fc1b0d3c1e..5052ab187f 100644 --- a/block/qcow2.h +++ b/block/qcow2.h @@ -359,6 +359,9 @@ typedef struct BDRVQcow2State { bool metadata_preallocation_checked; bool metadata_preallocation; + + /* True if the image is stored on a rotating disk */ + bool optimize_for_rotating; } BDRVQcow2State; typedef struct Qcow2COWRegion { diff --git a/block/qcow2.c b/block/qcow2.c index 14f914117f..b4df6d5085 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -1197,6 +1197,22 @@ static int qcow2_update_options(BlockDriverState *bs, QDict *options, return ret; } +static void qcow2_update_rotational_info(BlockDriverState *bs) +{ + BDRVQcow2State *s = bs->opaque; + BlockDriverInfo file_bdi; + + s->optimize_for_rotating = false; + + if (bdrv_get_info(bs->file->bs, &file_bdi) < 0) { + return; + } + + s->optimize_for_rotating = + file_bdi.has_rotational_info && + file_bdi.rotational_info == IMAGE_ROTATIONAL_INFO_ROTATING; +} + /* Called with s->lock held. */ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options, int flags, Error **errp) @@ -1461,6 +1477,8 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options, } } + qcow2_update_rotational_info(bs); + /* Parse driver-specific options */ ret = qcow2_update_options(bs, options, flags, errp); if (ret < 0) { @@ -1829,6 +1847,8 @@ static void qcow2_reopen_commit(BDRVReopenState *state) { qcow2_update_options_commit(state->bs, state->opaque); g_free(state->opaque); + + qcow2_update_rotational_info(state->bs); } static void qcow2_reopen_abort(BDRVReopenState *state) @@ -2297,10 +2317,16 @@ static coroutine_fn int qcow2_co_pwritev(BlockDriverState *bs, uint64_t offset, qemu_iovec_add(&hd_qiov, cluster_data, cur_bytes); } - /* Try to efficiently initialize the physical space with zeroes */ - ret = handle_alloc_space(bs, l2meta); - if (ret < 0) { - goto out_unlocked; + /* + * Try to efficiently initialize the physical space with zeroes. + * This incurs a performance penalty on rotating disks, so + * avoid doing it there. + */ + if (!s->optimize_for_rotating) { + ret = handle_alloc_space(bs, l2meta); + if (ret < 0) { + goto out_unlocked; + } } /* If we need to do COW, check if it's possible to merge the -- 2.21.0