@@ -1868,6 +1868,40 @@ static void coroutine_fn qcow2_open_entry(void *opaque)
qemu_co_mutex_unlock(&s->lock);
}
+static int qcow2_vz_insert_prealloc_filter(BlockDriverState *bs, Error **errp)
+{
+ QDict *options;
+ BlockDriverState *filter_bs;
+ Error *local_err = NULL;
+ int flags;
+
+ if (!bdrv_is_file_on_fuse(bs->file->bs)) {
+ /* Nothing to do */
+ return 0;
+ }
+
+ /* Assume it's a vstorage */
+ options = qdict_new();
+ qdict_put_str(options, "driver", "preallocate");
+ qdict_put_str(options, "file", bs->file->bs->node_name);
+ flags = bdrv_is_read_only(bs->file->bs) ? 0 : BDRV_O_RDWR;
+ filter_bs = bdrv_open(NULL, NULL, options, flags, errp);
+ if (!filter_bs) {
+ return -EINVAL;
+ }
+
+ bdrv_replace_node(bs->file->bs, filter_bs, &local_err);
+
+ /*
+ * On failure we want to remove filter_bs, on success it's referenced now by
+ * qcow2 node.
+ */
+ bdrv_unref(filter_bs);
+
+ error_propagate(errp, local_err);
+ return local_err ? -EINVAL : 0;
+}
+
static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
Error **errp)
{
@@ -1886,6 +1920,10 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
return -EINVAL;
}
+ if (qcow2_vz_insert_prealloc_filter(bs, errp) < 0) {
+ return -EINVAL;
+ }
+
/* Initialise locks */
qemu_co_mutex_init(&s->lock);
vstorage has slow allocation, so this patch detect vstorage (I hope, we don't use other FUSE filesystems) and inserts preallocate filter between qcow2 node and its file child. The following test executes more than 10 times faster (43.2s -> 3.9s for me) with this patch. (/newssd3 is mount point of vstorage, both cs and mds are on same ssd local ssd disk) IMG=/newssd3/z FILE_OPTS=file.filename=$IMG COUNT=15000 CHUNK=64K CLUSTER=1M rm -f $IMG ./qemu-img create -f qcow2 -o cluster_size=$CLUSTER $IMG 1G ./qemu-img bench -c $COUNT -d 1 -s $CHUNK -w -t none -f qcow2 $IMG Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> --- block/qcow2.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+)