qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Max Reitz <mreitz@redhat.com>
To: qemu-block@nongnu.org
Cc: Kevin Wolf <kwolf@redhat.com>,
	Peter Maydell <peter.maydell@linaro.org>,
	qemu-devel@nongnu.org, Max Reitz <mreitz@redhat.com>
Subject: [PULL 31/34] qcow2: Allow writing compressed data of multiple clusters
Date: Mon,  6 Jan 2020 15:42:03 +0100	[thread overview]
Message-ID: <20200106144206.698920-32-mreitz@redhat.com> (raw)
In-Reply-To: <20200106144206.698920-1-mreitz@redhat.com>

From: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>

QEMU currently supports writing compressed data of the size equal to
one cluster. This patch allows writing QCOW2 compressed data that
exceed one cluster. Now, we split buffered data into separate clusters
and write them compressed using the block/aio_task API.

Suggested-by: Pavel Butsykin <pbutsykin@virtuozzo.com>
Suggested-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Signed-off-by: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Message-id: 1575288906-551879-3-git-send-email-andrey.shinkevich@virtuozzo.com
Signed-off-by: Max Reitz <mreitz@redhat.com>
---
 block/qcow2.c | 102 +++++++++++++++++++++++++++++++++++++-------------
 1 file changed, 75 insertions(+), 27 deletions(-)

diff --git a/block/qcow2.c b/block/qcow2.c
index 7fbaac8457..cef9d72b3a 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -4221,10 +4221,8 @@ fail:
     return ret;
 }
 
-/* XXX: put compressed sectors first, then all the cluster aligned
-   tables to avoid losing bytes in alignment */
 static coroutine_fn int
-qcow2_co_pwritev_compressed_part(BlockDriverState *bs,
+qcow2_co_pwritev_compressed_task(BlockDriverState *bs,
                                  uint64_t offset, uint64_t bytes,
                                  QEMUIOVector *qiov, size_t qiov_offset)
 {
@@ -4234,32 +4232,11 @@ qcow2_co_pwritev_compressed_part(BlockDriverState *bs,
     uint8_t *buf, *out_buf;
     uint64_t cluster_offset;
 
-    if (has_data_file(bs)) {
-        return -ENOTSUP;
-    }
-
-    if (bytes == 0) {
-        /* align end of file to a sector boundary to ease reading with
-           sector based I/Os */
-        int64_t len = bdrv_getlength(bs->file->bs);
-        if (len < 0) {
-            return len;
-        }
-        return bdrv_co_truncate(bs->file, len, false, PREALLOC_MODE_OFF, NULL);
-    }
-
-    if (offset_into_cluster(s, offset)) {
-        return -EINVAL;
-    }
+    assert(bytes == s->cluster_size || (bytes < s->cluster_size &&
+           (offset + bytes == bs->total_sectors << BDRV_SECTOR_BITS)));
 
     buf = qemu_blockalign(bs, s->cluster_size);
-    if (bytes != s->cluster_size) {
-        if (bytes > s->cluster_size ||
-            offset + bytes != bs->total_sectors << BDRV_SECTOR_BITS)
-        {
-            qemu_vfree(buf);
-            return -EINVAL;
-        }
+    if (bytes < s->cluster_size) {
         /* Zero-pad last write if image size is not cluster aligned */
         memset(buf + bytes, 0, s->cluster_size - bytes);
     }
@@ -4308,6 +4285,77 @@ fail:
     return ret;
 }
 
+static coroutine_fn int qcow2_co_pwritev_compressed_task_entry(AioTask *task)
+{
+    Qcow2AioTask *t = container_of(task, Qcow2AioTask, task);
+
+    assert(!t->cluster_type && !t->l2meta);
+
+    return qcow2_co_pwritev_compressed_task(t->bs, t->offset, t->bytes, t->qiov,
+                                            t->qiov_offset);
+}
+
+/*
+ * XXX: put compressed sectors first, then all the cluster aligned
+ * tables to avoid losing bytes in alignment
+ */
+static coroutine_fn int
+qcow2_co_pwritev_compressed_part(BlockDriverState *bs,
+                                 uint64_t offset, uint64_t bytes,
+                                 QEMUIOVector *qiov, size_t qiov_offset)
+{
+    BDRVQcow2State *s = bs->opaque;
+    AioTaskPool *aio = NULL;
+    int ret = 0;
+
+    if (has_data_file(bs)) {
+        return -ENOTSUP;
+    }
+
+    if (bytes == 0) {
+        /*
+         * align end of file to a sector boundary to ease reading with
+         * sector based I/Os
+         */
+        int64_t len = bdrv_getlength(bs->file->bs);
+        if (len < 0) {
+            return len;
+        }
+        return bdrv_co_truncate(bs->file, len, false, PREALLOC_MODE_OFF, NULL);
+    }
+
+    if (offset_into_cluster(s, offset)) {
+        return -EINVAL;
+    }
+
+    while (bytes && aio_task_pool_status(aio) == 0) {
+        uint64_t chunk_size = MIN(bytes, s->cluster_size);
+
+        if (!aio && chunk_size != bytes) {
+            aio = aio_task_pool_new(QCOW2_MAX_WORKERS);
+        }
+
+        ret = qcow2_add_task(bs, aio, qcow2_co_pwritev_compressed_task_entry,
+                             0, 0, offset, chunk_size, qiov, qiov_offset, NULL);
+        if (ret < 0) {
+            break;
+        }
+        qiov_offset += chunk_size;
+        offset += chunk_size;
+        bytes -= chunk_size;
+    }
+
+    if (aio) {
+        aio_task_pool_wait_all(aio);
+        if (ret == 0) {
+            ret = aio_task_pool_status(aio);
+        }
+        g_free(aio);
+    }
+
+    return ret;
+}
+
 static int coroutine_fn
 qcow2_co_preadv_compressed(BlockDriverState *bs,
                            uint64_t file_cluster_offset,
-- 
2.24.1



  parent reply	other threads:[~2020-01-06 15:15 UTC|newest]

Thread overview: 36+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-01-06 14:41 [PULL 00/34] Block patches Max Reitz
2020-01-06 14:41 ` [PULL 01/34] block: Add bdrv_qapi_perm_to_blk_perm() Max Reitz
2020-01-06 14:41 ` [PULL 02/34] block: Use bdrv_qapi_perm_to_blk_perm() Max Reitz
2020-01-06 14:41 ` [PULL 03/34] blkdebug: Allow taking/unsharing permissions Max Reitz
2020-01-06 14:41 ` [PULL 04/34] iotests: Add @error to wait_until_completed Max Reitz
2020-01-06 14:41 ` [PULL 05/34] iotests: Add test for failing mirror complete Max Reitz
2020-01-06 14:41 ` [PULL 06/34] throttle-groups: fix memory leak in throttle_group_set_limit: Max Reitz
2020-01-06 14:41 ` [PULL 07/34] qcow2-bitmaps: fix qcow2_can_store_new_dirty_bitmap Max Reitz
2020-01-06 14:41 ` [PULL 08/34] iotests: s/qocw2/qcow2/ Max Reitz
2020-01-06 14:41 ` [PULL 09/34] iotests/qcow2.py: Add dump-header-exts Max Reitz
2020-01-06 14:41 ` [PULL 10/34] iotests/qcow2.py: Split feature fields into bits Max Reitz
2020-01-06 14:41 ` [PULL 11/34] iotests: Add _filter_json_filename Max Reitz
2020-01-06 14:41 ` [PULL 12/34] iotests: Filter refcount_order in 036 Max Reitz
2020-01-06 14:41 ` [PULL 13/34] iotests: Replace IMGOPTS by _unsupported_imgopts Max Reitz
2020-01-06 14:41 ` [PULL 14/34] iotests: Drop compat=1.1 in 050 Max Reitz
2020-01-06 14:41 ` [PULL 15/34] iotests: Let _make_test_img parse its parameters Max Reitz
2020-01-06 14:41 ` [PULL 16/34] iotests: Add -o and --no-opts to _make_test_img Max Reitz
2020-01-06 14:41 ` [PULL 17/34] iotests: Inject space into -ocompat=0.10 in 051 Max Reitz
2020-01-06 14:41 ` [PULL 18/34] iotests: Replace IMGOPTS= by -o Max Reitz
2020-01-06 14:41 ` [PULL 19/34] iotests: Replace IMGOPTS='' by --no-opts Max Reitz
2020-01-06 14:41 ` [PULL 20/34] iotests: Drop IMGOPTS use in 267 Max Reitz
2020-01-06 14:41 ` [PULL 21/34] iotests: Avoid qemu-img create Max Reitz
2020-01-06 14:41 ` [PULL 22/34] iotests: Use _rm_test_img for deleting test images Max Reitz
2020-01-06 14:41 ` [PULL 23/34] iotests: Avoid cp/mv of " Max Reitz
2020-01-06 14:41 ` [PULL 24/34] iotests: Make 091 work with data_file Max Reitz
2020-01-06 14:41 ` [PULL 25/34] iotests: Make 110 " Max Reitz
2020-01-06 14:41 ` [PULL 26/34] iotests: Make 137 " Max Reitz
2020-01-06 14:41 ` [PULL 27/34] iotests: Make 198 " Max Reitz
2020-01-06 14:42 ` [PULL 28/34] iotests: Disable data_file where it cannot be used Max Reitz
2020-01-06 14:42 ` [PULL 29/34] iotests: Allow check -o data_file Max Reitz
2020-01-06 14:42 ` [PULL 30/34] block: introduce compress filter driver Max Reitz
2020-01-06 14:42 ` Max Reitz [this message]
2020-01-06 14:42 ` [PULL 32/34] tests/qemu-iotests: add case to write compressed data of multiple clusters Max Reitz
2020-01-06 14:42 ` [PULL 33/34] tests/qemu-iotests: Update tests to recent desugarized -accel option Max Reitz
2020-01-06 14:42 ` [PULL 34/34] backup-top: Begin drain earlier Max Reitz
2020-01-06 18:22 ` [PULL 00/34] Block patches Peter Maydell

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200106144206.698920-32-mreitz@redhat.com \
    --to=mreitz@redhat.com \
    --cc=kwolf@redhat.com \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-block@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).