qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Kevin Wolf <kwolf@redhat.com>
To: qemu-block@nongnu.org
Cc: kwolf@redhat.com, qemu-devel@nongnu.org
Subject: [Qemu-devel] [PULL 20/42] qcow: add qcow_co_pwritev_compressed
Date: Mon,  5 Sep 2016 20:13:32 +0200	[thread overview]
Message-ID: <1473099234-10882-21-git-send-email-kwolf@redhat.com> (raw)
In-Reply-To: <1473099234-10882-1-git-send-email-kwolf@redhat.com>

From: Pavel Butsykin <pbutsykin@virtuozzo.com>

Added implementation of the qcow_co_pwritev_compressed function that
will allow us to safely use compressed writes for the qcow from running
VMs.

Signed-off-by: Pavel Butsykin <pbutsykin@virtuozzo.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Denis V. Lunev <den@openvz.org>
CC: Jeff Cody <jcody@redhat.com>
CC: Markus Armbruster <armbru@redhat.com>
CC: Eric Blake <eblake@redhat.com>
CC: John Snow <jsnow@redhat.com>
CC: Stefan Hajnoczi <stefanha@redhat.com>
CC: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block/qcow.c | 109 +++++++++++++++++++++++------------------------------------
 1 file changed, 42 insertions(+), 67 deletions(-)

diff --git a/block/qcow.c b/block/qcow.c
index 6f9b2e2..1b9c911 100644
--- a/block/qcow.c
+++ b/block/qcow.c
@@ -913,75 +913,42 @@ static int qcow_make_empty(BlockDriverState *bs)
     return 0;
 }
 
-typedef struct QcowWriteCo {
-    BlockDriverState *bs;
-    int64_t sector_num;
-    const uint8_t *buf;
-    int nb_sectors;
-    int ret;
-} QcowWriteCo;
-
-static void qcow_write_co_entry(void *opaque)
-{
-    QcowWriteCo *co = opaque;
-    QEMUIOVector qiov;
-
-    struct iovec iov = (struct iovec) {
-        .iov_base   = (uint8_t*) co->buf,
-        .iov_len    = co->nb_sectors * BDRV_SECTOR_SIZE,
-    };
-    qemu_iovec_init_external(&qiov, &iov, 1);
-
-    co->ret = qcow_co_writev(co->bs, co->sector_num, co->nb_sectors, &qiov);
-}
-
-/* Wrapper for non-coroutine contexts */
-static int qcow_write(BlockDriverState *bs, int64_t sector_num,
-                      const uint8_t *buf, int nb_sectors)
-{
-    Coroutine *co;
-    AioContext *aio_context = bdrv_get_aio_context(bs);
-    QcowWriteCo data = {
-        .bs         = bs,
-        .sector_num = sector_num,
-        .buf        = buf,
-        .nb_sectors = nb_sectors,
-        .ret        = -EINPROGRESS,
-    };
-    co = qemu_coroutine_create(qcow_write_co_entry, &data);
-    qemu_coroutine_enter(co);
-    while (data.ret == -EINPROGRESS) {
-        aio_poll(aio_context, true);
-    }
-    return data.ret;
-}
-
 /* XXX: put compressed sectors first, then all the cluster aligned
    tables to avoid losing bytes in alignment */
-static int qcow_write_compressed(BlockDriverState *bs, int64_t sector_num,
-                                 const uint8_t *buf, int nb_sectors)
+static coroutine_fn int
+qcow_co_pwritev_compressed(BlockDriverState *bs, uint64_t offset,
+                           uint64_t bytes, QEMUIOVector *qiov)
 {
     BDRVQcowState *s = bs->opaque;
+    QEMUIOVector hd_qiov;
+    struct iovec iov;
     z_stream strm;
     int ret, out_len;
-    uint8_t *out_buf;
+    uint8_t *buf, *out_buf;
     uint64_t cluster_offset;
 
-    if (nb_sectors != s->cluster_sectors) {
+    if (bytes != s->cluster_size) {
         ret = -EINVAL;
 
         /* Zero-pad last write if image size is not cluster aligned */
-        if (sector_num + nb_sectors == bs->total_sectors &&
-            nb_sectors < s->cluster_sectors) {
+        if (offset + bytes == bs->total_sectors << BDRV_SECTOR_BITS &&
+            bytes < s->cluster_size)
+        {
             uint8_t *pad_buf = qemu_blockalign(bs, s->cluster_size);
             memset(pad_buf, 0, s->cluster_size);
-            memcpy(pad_buf, buf, nb_sectors * BDRV_SECTOR_SIZE);
-            ret = qcow_write_compressed(bs, sector_num,
-                                        pad_buf, s->cluster_sectors);
+            qemu_iovec_to_buf(qiov, 0, pad_buf, s->cluster_size);
+            iov = (struct iovec) {
+                .iov_base   = pad_buf,
+                .iov_len    = s->cluster_size,
+            };
+            qemu_iovec_init_external(&hd_qiov, &iov, 1);
+            ret = qcow_co_pwritev_compressed(bs, offset, bytes, &hd_qiov);
             qemu_vfree(pad_buf);
         }
         return ret;
     }
+    buf = qemu_blockalign(bs, s->cluster_size);
+    qemu_iovec_to_buf(qiov, 0, buf, qiov->size);
 
     out_buf = g_malloc(s->cluster_size);
 
@@ -1012,27 +979,35 @@ static int qcow_write_compressed(BlockDriverState *bs, int64_t sector_num,
 
     if (ret != Z_STREAM_END || out_len >= s->cluster_size) {
         /* could not compress: write normal cluster */
-        ret = qcow_write(bs, sector_num, buf, s->cluster_sectors);
-        if (ret < 0) {
-            goto fail;
-        }
-    } else {
-        cluster_offset = get_cluster_offset(bs, sector_num << 9, 2,
-                                            out_len, 0, 0);
-        if (cluster_offset == 0) {
-            ret = -EIO;
-            goto fail;
-        }
-
-        cluster_offset &= s->cluster_offset_mask;
-        ret = bdrv_pwrite(bs->file, cluster_offset, out_buf, out_len);
+        ret = qcow_co_writev(bs, offset >> BDRV_SECTOR_BITS,
+                             bytes >> BDRV_SECTOR_BITS, qiov);
         if (ret < 0) {
             goto fail;
         }
+        goto success;
+    }
+    qemu_co_mutex_lock(&s->lock);
+    cluster_offset = get_cluster_offset(bs, offset, 2, out_len, 0, 0);
+    qemu_co_mutex_unlock(&s->lock);
+    if (cluster_offset == 0) {
+        ret = -EIO;
+        goto fail;
     }
+    cluster_offset &= s->cluster_offset_mask;
 
+    iov = (struct iovec) {
+        .iov_base   = out_buf,
+        .iov_len    = out_len,
+    };
+    qemu_iovec_init_external(&hd_qiov, &iov, 1);
+    ret = bdrv_co_pwritev(bs->file, cluster_offset, out_len, &hd_qiov, 0);
+    if (ret < 0) {
+        goto fail;
+    }
+success:
     ret = 0;
 fail:
+    qemu_vfree(buf);
     g_free(out_buf);
     return ret;
 }
@@ -1085,7 +1060,7 @@ static BlockDriver bdrv_qcow = {
 
     .bdrv_set_key           = qcow_set_key,
     .bdrv_make_empty        = qcow_make_empty,
-    .bdrv_write_compressed  = qcow_write_compressed,
+    .bdrv_co_pwritev_compressed = qcow_co_pwritev_compressed,
     .bdrv_get_info          = qcow_get_info,
 
     .create_opts            = &qcow_create_opts,
-- 
1.8.3.1

  parent reply	other threads:[~2016-09-05 18:14 UTC|newest]

Thread overview: 51+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-09-05 18:13 [Qemu-devel] [PULL 00/42] Block layer patches Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 01/42] ide: ide-cd without drive property for empty drive Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 02/42] scsi: scsi-cd " Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 03/42] block: Accept node-name for block-stream Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 04/42] block: Accept node-name for block-commit Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 05/42] block: Accept node-name for blockdev-backup Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 06/42] block: Accept node-name for blockdev-mirror Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 07/42] block: Accept node-name for blockdev-snapshot-delete-internal-sync Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 08/42] block: Accept node-name for blockdev-snapshot-internal-sync Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 09/42] block: Accept node-name for change-backing-file Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 10/42] block: Accept node-name for drive-backup Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 11/42] block: Accept node-name for drive-mirror Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 12/42] nbd-server: Use a separate BlockBackend Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 13/42] nbd-server: Allow node name for nbd-server-add Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 14/42] block: switch blk_write_compressed() to byte-based interface Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 15/42] block: Convert bdrv_pwrite_compressed() to BdrvChild Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 16/42] block/io: reuse bdrv_co_pwritev() for write compressed Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 17/42] qcow2: add qcow2_co_pwritev_compressed Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 18/42] qcow2: cleanup qcow2_co_pwritev_compressed to avoid the recursion Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 19/42] vmdk: add vmdk_co_pwritev_compressed Kevin Wolf
2016-09-05 18:13 ` Kevin Wolf [this message]
2016-09-05 18:13 ` [Qemu-devel] [PULL 21/42] qcow: cleanup qcow_co_pwritev_compressed to avoid the recursion Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 22/42] block: remove BlockDriver.bdrv_write_compressed Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 23/42] block/io: turn on dirty_bitmaps for the compressed writes Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 24/42] block: simplify drive-backup Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 25/42] block: simplify blockdev-backup Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 26/42] drive-backup: added support for data compression Kevin Wolf
2016-09-16 15:15   ` Eric Blake
2016-09-05 18:13 ` [Qemu-devel] [PULL 27/42] blockdev-backup: " Kevin Wolf
2016-09-16 15:15   ` Eric Blake
2016-09-05 18:13 ` [Qemu-devel] [PULL 28/42] qemu-iotests: test backup compression in 055 Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 29/42] qemu-iotests: add vmdk for " Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 30/42] test-coroutine: Fix coroutine pool corruption Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 31/42] qcow2: fix iovec size at qcow2_co_pwritev_compressed Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 32/42] coroutine: Let CoMutex remember who holds it Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 33/42] coroutine: Assert that no locks are held on termination Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 34/42] block jobs: Improve error message for missing job ID Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 35/42] qemu-iotests: Log QMP traffic in debug mode Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 36/42] block: Allow node name for 'qemu-io' HMP command Kevin Wolf
2016-09-15 22:18   ` Paolo Bonzini
2016-09-05 18:13 ` [Qemu-devel] [PULL 37/42] oslib-posix: add helpers for stack alloc and free Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 38/42] coroutine: add a macro for the coroutine stack size Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 39/42] coroutine-ucontext: use helper for allocating stack memory Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 40/42] coroutine-sigaltstack: " Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 41/42] oslib-posix: add a configure switch to debug stack usage Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 42/42] coroutine: reduce stack size to 64kB Kevin Wolf
2016-09-06 10:12 ` [Qemu-devel] [PULL 00/42] Block layer patches Peter Maydell
2016-09-06 10:36   ` Kevin Wolf
2016-09-16 13:25     ` Peter Lieven
2016-09-06 10:33 ` Peter Maydell
2016-09-06 10:42 ` 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=1473099234-10882-21-git-send-email-kwolf@redhat.com \
    --to=kwolf@redhat.com \
    --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).