All of lore.kernel.org
 help / color / mirror / Atom feed
From: Kevin Wolf <kwolf@redhat.com>
To: qemu-block@nongnu.org
Cc: kwolf@redhat.com, peter.maydell@linaro.org, qemu-devel@nongnu.org
Subject: [PULL 29/30] vhdx: Rework truncation logic
Date: Fri,  8 May 2020 14:41:34 +0200	[thread overview]
Message-ID: <20200508124135.252565-30-kwolf@redhat.com> (raw)
In-Reply-To: <20200508124135.252565-1-kwolf@redhat.com>

From: Eric Blake <eblake@redhat.com>

The vhdx driver uses truncation for image growth, with a special case
for blocks that already read as zero but which are only being
partially written.  But with a bit of rearranging, it's just as easy
to defer the decision on whether truncation resulted in zeroes to the
actual allocation attempt, reducing the number of places that still
use bdrv_has_zero_init_truncate.

Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <20200428202905.770727-9-eblake@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block/vhdx.c | 89 ++++++++++++++++++++++++++++++----------------------
 1 file changed, 51 insertions(+), 38 deletions(-)

diff --git a/block/vhdx.c b/block/vhdx.c
index e11fb7413a..53e756438a 100644
--- a/block/vhdx.c
+++ b/block/vhdx.c
@@ -1240,12 +1240,16 @@ exit:
 /*
  * Allocate a new payload block at the end of the file.
  *
- * Allocation will happen at 1MB alignment inside the file
+ * Allocation will happen at 1MB alignment inside the file.
+ *
+ * If @need_zero is set on entry but not cleared on return, then truncation
+ * could not guarantee that the new portion reads as zero, and the caller
+ * will take care of it instead.
  *
  * Returns the file offset start of the new payload block
  */
 static int vhdx_allocate_block(BlockDriverState *bs, BDRVVHDXState *s,
-                                    uint64_t *new_offset)
+                               uint64_t *new_offset, bool *need_zero)
 {
     int64_t current_len;
 
@@ -1262,6 +1266,17 @@ static int vhdx_allocate_block(BlockDriverState *bs, BDRVVHDXState *s,
         return -EINVAL;
     }
 
+    if (*need_zero) {
+        int ret;
+
+        ret = bdrv_truncate(bs->file, *new_offset + s->block_size, false,
+                            PREALLOC_MODE_OFF, BDRV_REQ_ZERO_WRITE, NULL);
+        if (ret != -ENOTSUP) {
+            *need_zero = false;
+            return ret;
+        }
+    }
+
     return bdrv_truncate(bs->file, *new_offset + s->block_size, false,
                          PREALLOC_MODE_OFF, 0, NULL);
 }
@@ -1355,18 +1370,38 @@ static coroutine_fn int vhdx_co_writev(BlockDriverState *bs, int64_t sector_num,
                 /* in this case, we need to preserve zero writes for
                  * data that is not part of this write, so we must pad
                  * the rest of the buffer to zeroes */
-
-                /* if we are on a posix system with ftruncate() that extends
-                 * a file, then it is zero-filled for us.  On Win32, the raw
-                 * layer uses SetFilePointer and SetFileEnd, which does not
-                 * zero fill AFAIK */
-
-                /* Queue another write of zero buffers if the underlying file
-                 * does not zero-fill on file extension */
-
-                if (bdrv_has_zero_init_truncate(bs->file->bs) == 0) {
-                    use_zero_buffers = true;
-
+                use_zero_buffers = true;
+                /* fall through */
+            case PAYLOAD_BLOCK_NOT_PRESENT: /* fall through */
+            case PAYLOAD_BLOCK_UNMAPPED:
+            case PAYLOAD_BLOCK_UNMAPPED_v095:
+            case PAYLOAD_BLOCK_UNDEFINED:
+                bat_prior_offset = sinfo.file_offset;
+                ret = vhdx_allocate_block(bs, s, &sinfo.file_offset,
+                                          &use_zero_buffers);
+                if (ret < 0) {
+                    goto exit;
+                }
+                /*
+                 * once we support differencing files, this may also be
+                 * partially present
+                 */
+                /* update block state to the newly specified state */
+                vhdx_update_bat_table_entry(bs, s, &sinfo, &bat_entry,
+                                            &bat_entry_offset,
+                                            PAYLOAD_BLOCK_FULLY_PRESENT);
+                bat_update = true;
+                /*
+                 * Since we just allocated a block, file_offset is the
+                 * beginning of the payload block. It needs to be the
+                 * write address, which includes the offset into the
+                 * block, unless the entire block needs to read as
+                 * zeroes but truncation was not able to provide them,
+                 * in which case we need to fill in the rest.
+                 */
+                if (!use_zero_buffers) {
+                    sinfo.file_offset += sinfo.block_offset;
+                } else {
                     /* zero fill the front, if any */
                     if (sinfo.block_offset) {
                         iov1.iov_len = sinfo.block_offset;
@@ -1378,7 +1413,7 @@ static coroutine_fn int vhdx_co_writev(BlockDriverState *bs, int64_t sector_num,
                     }
 
                     /* our actual data */
-                    qemu_iovec_concat(&hd_qiov, qiov,  bytes_done,
+                    qemu_iovec_concat(&hd_qiov, qiov, bytes_done,
                                       sinfo.bytes_avail);
 
                     /* zero fill the back, if any */
@@ -1393,29 +1428,7 @@ static coroutine_fn int vhdx_co_writev(BlockDriverState *bs, int64_t sector_num,
                         sectors_to_write += iov2.iov_len >> BDRV_SECTOR_BITS;
                     }
                 }
-                /* fall through */
-            case PAYLOAD_BLOCK_NOT_PRESENT: /* fall through */
-            case PAYLOAD_BLOCK_UNMAPPED:
-            case PAYLOAD_BLOCK_UNMAPPED_v095:
-            case PAYLOAD_BLOCK_UNDEFINED:
-                bat_prior_offset = sinfo.file_offset;
-                ret = vhdx_allocate_block(bs, s, &sinfo.file_offset);
-                if (ret < 0) {
-                    goto exit;
-                }
-                /* once we support differencing files, this may also be
-                 * partially present */
-                /* update block state to the newly specified state */
-                vhdx_update_bat_table_entry(bs, s, &sinfo, &bat_entry,
-                                            &bat_entry_offset,
-                                            PAYLOAD_BLOCK_FULLY_PRESENT);
-                bat_update = true;
-                /* since we just allocated a block, file_offset is the
-                 * beginning of the payload block. It needs to be the
-                 * write address, which includes the offset into the block */
-                if (!use_zero_buffers) {
-                    sinfo.file_offset += sinfo.block_offset;
-                }
+
                 /* fall through */
             case PAYLOAD_BLOCK_FULLY_PRESENT:
                 /* if the file offset address is in the header zone,
-- 
2.25.3



  parent reply	other threads:[~2020-05-08 13:00 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-05-08 12:41 [PULL 00/30] Block layer patches Kevin Wolf
2020-05-08 12:41 ` [PULL 01/30] iotests: handle tmpfs Kevin Wolf
2020-05-08 12:41 ` [PULL 02/30] iotests/082: require bochs Kevin Wolf
2020-05-08 12:41 ` [PULL 03/30] iotests/148: use skip_if_unsupported Kevin Wolf
2020-05-08 12:41 ` [PULL 04/30] iotests/041: drop self.assert_no_active_block_jobs() Kevin Wolf
2020-05-08 12:41 ` [PULL 05/30] iotests/055: refactor compressed backup to vmdk Kevin Wolf
2020-05-08 12:41 ` [PULL 06/30] iotests/055: skip vmdk target tests if vmdk is not whitelisted Kevin Wolf
2020-05-08 12:41 ` [PULL 07/30] iotests/109: mark required formats as required to support whitelisting Kevin Wolf
2020-05-08 12:41 ` [PULL 08/30] iotests/113: mark bochs " Kevin Wolf
2020-05-08 12:41 ` [PULL 09/30] qcow2: Avoid integer wraparound in qcow2_co_truncate() Kevin Wolf
2020-05-08 12:41 ` [PULL 10/30] vmdk: Rename VmdkMetaData.valid to new_allocation Kevin Wolf
2020-05-08 12:41 ` [PULL 11/30] vmdk: Fix zero cluster allocation Kevin Wolf
2020-05-08 12:41 ` [PULL 12/30] vmdk: Fix partial overwrite of zero cluster Kevin Wolf
2020-05-08 12:41 ` [PULL 13/30] vmdk: Don't update L2 table for zero write on " Kevin Wolf
2020-05-08 12:41 ` [PULL 14/30] vmdk: Flush only once in vmdk_L2update() Kevin Wolf
2020-05-08 12:41 ` [PULL 15/30] iotests: vmdk: Enable zeroed_grained=on by default Kevin Wolf
2020-05-08 12:41 ` [PULL 16/30] iotests/283: Use consistent size for source and target Kevin Wolf
2020-05-08 12:41 ` [PULL 17/30] backup: Improve error for bdrv_getlength() failure Kevin Wolf
2020-05-08 12:41 ` [PULL 18/30] backup: Make sure that source and target size match Kevin Wolf
2020-05-08 12:41 ` [PULL 19/30] iotests: Backup with different source/target size Kevin Wolf
2020-05-08 12:41 ` [PULL 20/30] iotests/055: Use cache.no-flush for vmdk target Kevin Wolf
2020-05-08 12:41 ` [PULL 21/30] qcow2: Fix preallocation on block devices Kevin Wolf
2020-05-08 12:41 ` [PULL 22/30] gluster: Drop useless has_zero_init callback Kevin Wolf
2020-05-08 12:41 ` [PULL 23/30] file-win32: Support BDRV_REQ_ZERO_WRITE for truncate Kevin Wolf
2020-05-08 12:41 ` [PULL 24/30] nfs: " Kevin Wolf
2020-05-08 12:41 ` [PULL 25/30] rbd: " Kevin Wolf
2020-05-08 12:41 ` [PULL 26/30] sheepdog: " Kevin Wolf
2020-05-08 12:41 ` [PULL 27/30] ssh: " Kevin Wolf
2020-05-08 12:41 ` [PULL 28/30] parallels: Rework truncation logic Kevin Wolf
2020-05-08 12:41 ` Kevin Wolf [this message]
2020-05-08 12:41 ` [PULL 30/30] block: Drop unused .bdrv_has_zero_init_truncate Kevin Wolf
2020-05-08 15:10 ` [PULL 00/30] Block layer 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=20200508124135.252565-30-kwolf@redhat.com \
    --to=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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.