From c8fd37c06fd24d1242629dda329dd16bea20f319 Mon Sep 17 00:00:00 2001 From: Richard Jones Date: Thu, 28 May 2020 14:27:36 +0100 Subject: [PATCH 1/8] block/curl: HTTP header fields allow whitespace around values RH-Author: Richard Jones Message-id: <20200528142737.17318-2-rjones@redhat.com> Patchwork-id: 96894 O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH 1/2] block/curl: HTTP header fields allow whitespace around values Bugzilla: 1841038 RH-Acked-by: Eric Blake RH-Acked-by: Max Reitz RH-Acked-by: Danilo de Paula From: David Edmondson RFC 7230 section 3.2 indicates that whitespace is permitted between the field name and field value and after the field value. Signed-off-by: David Edmondson Message-Id: <20200224101310.101169-2-david.edmondson@oracle.com> Reviewed-by: Max Reitz Signed-off-by: Max Reitz (cherry picked from commit 7788a319399f17476ff1dd43164c869e320820a2) Signed-off-by: Danilo C. L. de Paula --- block/curl.c | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/block/curl.c b/block/curl.c index d4c8e94f3e..bfabe7eabd 100644 --- a/block/curl.c +++ b/block/curl.c @@ -212,11 +212,34 @@ static size_t curl_header_cb(void *ptr, size_t size, size_t nmemb, void *opaque) { BDRVCURLState *s = opaque; size_t realsize = size * nmemb; - const char *accept_line = "Accept-Ranges: bytes"; + const char *header = (char *)ptr; + const char *end = header + realsize; + const char *accept_ranges = "Accept-Ranges:"; + const char *bytes = "bytes"; - if (realsize >= strlen(accept_line) - && strncmp((char *)ptr, accept_line, strlen(accept_line)) == 0) { - s->accept_range = true; + if (realsize >= strlen(accept_ranges) + && strncmp(header, accept_ranges, strlen(accept_ranges)) == 0) { + + char *p = strchr(header, ':') + 1; + + /* Skip whitespace between the header name and value. */ + while (p < end && *p && g_ascii_isspace(*p)) { + p++; + } + + if (end - p >= strlen(bytes) + && strncmp(p, bytes, strlen(bytes)) == 0) { + + /* Check that there is nothing but whitespace after the value. */ + p += strlen(bytes); + while (p < end && *p && g_ascii_isspace(*p)) { + p++; + } + + if (p == end || !*p) { + s->accept_range = true; + } + } } return realsize; -- Gitee From ae2c6d13c4ac625a2c6b217a7f6a17506a2b26e5 Mon Sep 17 00:00:00 2001 From: Richard Jones Date: Thu, 28 May 2020 14:27:37 +0100 Subject: [PATCH 2/8] block/curl: HTTP header field names are case insensitive MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RH-Author: Richard Jones Message-id: <20200528142737.17318-3-rjones@redhat.com> Patchwork-id: 96895 O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH 2/2] block/curl: HTTP header field names are case insensitive Bugzilla: 1841038 RH-Acked-by: Eric Blake RH-Acked-by: Max Reitz RH-Acked-by: Philippe Mathieu-Daudé From: David Edmondson RFC 7230 section 3.2 indicates that HTTP header field names are case insensitive. Signed-off-by: David Edmondson Message-Id: <20200224101310.101169-3-david.edmondson@oracle.com> Reviewed-by: Max Reitz Signed-off-by: Max Reitz (cherry picked from commit 69032253c33ae1774233c63cedf36d32242a85fc) Signed-off-by: Danilo C. L. de Paula --- block/curl.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/block/curl.c b/block/curl.c index bfabe7eabd..a298fcc591 100644 --- a/block/curl.c +++ b/block/curl.c @@ -214,11 +214,12 @@ static size_t curl_header_cb(void *ptr, size_t size, size_t nmemb, void *opaque) size_t realsize = size * nmemb; const char *header = (char *)ptr; const char *end = header + realsize; - const char *accept_ranges = "Accept-Ranges:"; + const char *accept_ranges = "accept-ranges:"; const char *bytes = "bytes"; if (realsize >= strlen(accept_ranges) - && strncmp(header, accept_ranges, strlen(accept_ranges)) == 0) { + && g_ascii_strncasecmp(header, accept_ranges, + strlen(accept_ranges)) == 0) { char *p = strchr(header, ':') + 1; -- Gitee From 0b66aef5389d622434128fc7db9abd2cd4724b51 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Wed, 3 Jun 2020 16:03:19 +0100 Subject: [PATCH 3/8] backup: Improve error for bdrv_getlength() failure RH-Author: Kevin Wolf Message-id: <20200603160325.67506-6-kwolf@redhat.com> Patchwork-id: 97103 O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH v2 05/11] backup: Improve error for bdrv_getlength() failure Bugzilla: 1778593 RH-Acked-by: Eric Blake RH-Acked-by: Max Reitz RH-Acked-by: Stefano Garzarella bdrv_get_device_name() will be an empty string with modern management tools that don't use -drive. Use bdrv_get_device_or_node_name() instead so that the node name is used if the BlockBackend is anonymous. While at it, start with upper case to make the message consistent with the rest of the function. Signed-off-by: Kevin Wolf Reviewed-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Alberto Garcia Message-Id: <20200430142755.315494-3-kwolf@redhat.com> Signed-off-by: Kevin Wolf (cherry picked from commit 58226634c4b02af7b10862f7fbd3610a344bfb7f) Signed-off-by: Kevin Wolf Signed-off-by: Danilo C. L. de Paula --- block/backup.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/block/backup.c b/block/backup.c index 8761f1f9a7..88354dcb32 100644 --- a/block/backup.c +++ b/block/backup.c @@ -613,8 +613,8 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs, len = bdrv_getlength(bs); if (len < 0) { - error_setg_errno(errp, -len, "unable to get length for '%s'", - bdrv_get_device_name(bs)); + error_setg_errno(errp, -len, "Unable to get length for '%s'", + bdrv_get_device_or_node_name(bs)); goto error; } -- Gitee From 9f57569d541acaa4a76513d09ede7d2b19aa69ea Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Wed, 3 Jun 2020 16:03:24 +0100 Subject: [PATCH 4/8] mirror: Make sure that source and target size match RH-Author: Kevin Wolf Message-id: <20200603160325.67506-11-kwolf@redhat.com> Patchwork-id: 97110 O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH v2 10/11] mirror: Make sure that source and target size match Bugzilla: 1778593 RH-Acked-by: Eric Blake RH-Acked-by: Max Reitz RH-Acked-by: Stefano Garzarella If the target is shorter than the source, mirror would copy data until it reaches the end of the target and then fail with an I/O error when trying to write past the end. If the target is longer than the source, the mirror job would complete successfully, but the target wouldn't actually be an accurate copy of the source image (it would contain some additional garbage at the end). Fix this by checking that both images have the same size when the job starts. Signed-off-by: Kevin Wolf Reviewed-by: Eric Blake Message-Id: <20200511135825.219437-4-kwolf@redhat.com> Reviewed-by: Max Reitz Reviewed-by: Vladimir Sementsov-Ogievskiy Signed-off-by: Kevin Wolf (cherry picked from commit e83dd6808c6e0975970f37b49b27cc37bb54eea8) Signed-off-by: Kevin Wolf Signed-off-by: Danilo C. L. de Paula --- block/mirror.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/block/mirror.c b/block/mirror.c index ef6c958ff9..8f0d4544d8 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -853,6 +853,7 @@ static int coroutine_fn mirror_run(Job *job, Error **errp) BlockDriverState *target_bs = blk_bs(s->target); bool need_drain = true; int64_t length; + int64_t target_length; BlockDriverInfo bdi; char backing_filename[2]; /* we only need 2 characters because we are only checking for a NULL string */ @@ -868,24 +869,26 @@ static int coroutine_fn mirror_run(Job *job, Error **errp) goto immediate_exit; } + target_length = blk_getlength(s->target); + if (target_length < 0) { + ret = target_length; + goto immediate_exit; + } + /* Active commit must resize the base image if its size differs from the * active layer. */ if (s->base == blk_bs(s->target)) { - int64_t base_length; - - base_length = blk_getlength(s->target); - if (base_length < 0) { - ret = base_length; - goto immediate_exit; - } - - if (s->bdev_length > base_length) { + if (s->bdev_length > target_length) { ret = blk_truncate(s->target, s->bdev_length, PREALLOC_MODE_OFF, NULL); if (ret < 0) { goto immediate_exit; } } + } else if (s->bdev_length != target_length) { + error_setg(errp, "Source and target image have different sizes"); + ret = -EINVAL; + goto immediate_exit; } if (s->bdev_length == 0) { -- Gitee From 2e8fecd9e963c740cfe73d0de4491541423e185f Mon Sep 17 00:00:00 2001 From: Max Reitz Date: Thu, 17 Oct 2019 15:31:40 +0200 Subject: [PATCH 5/8] iotests/143: Create socket in $SOCK_DIR Signed-off-by: Max Reitz Reviewed-by: Eric Blake Reviewed-by: Thomas Huth Message-id: 20191017133155.5327-9-mreitz@redhat.com Signed-off-by: Max Reitz --- tests/qemu-iotests/143 | 6 +++--- tests/qemu-iotests/143.out | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/qemu-iotests/143 b/tests/qemu-iotests/143 index 92249ac8da..f649b36195 100755 --- a/tests/qemu-iotests/143 +++ b/tests/qemu-iotests/143 @@ -29,7 +29,7 @@ status=1 # failure is the default! _cleanup() { _cleanup_qemu - rm -f "$TEST_DIR/nbd" + rm -f "$SOCK_DIR/nbd" } trap "_cleanup; exit \$status" 0 1 2 3 15 @@ -51,12 +51,12 @@ _send_qemu_cmd $QEMU_HANDLE \ _send_qemu_cmd $QEMU_HANDLE \ "{ 'execute': 'nbd-server-start', 'arguments': { 'addr': { 'type': 'unix', - 'data': { 'path': '$TEST_DIR/nbd' }}}}" \ + 'data': { 'path': '$SOCK_DIR/nbd' }}}}" \ 'return' # This should just result in a client error, not in the server crashing $QEMU_IO_PROG -f raw -c quit \ - "nbd+unix:///no_such_export?socket=$TEST_DIR/nbd" 2>&1 \ + "nbd+unix:///no_such_export?socket=$SOCK_DIR/nbd" 2>&1 \ | _filter_qemu_io | _filter_nbd _send_qemu_cmd $QEMU_HANDLE \ diff --git a/tests/qemu-iotests/143.out b/tests/qemu-iotests/143.out index ee71b5aa42..037d34a409 100644 --- a/tests/qemu-iotests/143.out +++ b/tests/qemu-iotests/143.out @@ -1,7 +1,7 @@ QA output created by 143 {"return": {}} {"return": {}} -qemu-io: can't open device nbd+unix:///no_such_export?socket=TEST_DIR/nbd: Requested export not available +qemu-io: can't open device nbd+unix:///no_such_export?socket=SOCK_DIR/nbd: Requested export not available server reported: export 'no_such_export' not present {"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} -- Gitee From 719292175d391e77487f3c55f5f97a065e44d9f8 Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Wed, 10 Jun 2020 18:32:01 -0400 Subject: [PATCH 6/8] nbd/server: Avoid long error message assertions CVE-2020-10761 RH-Author: Eric Blake Message-id: <20200610183202.3780750-2-eblake@redhat.com> Patchwork-id: 97494 O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH 1/2] nbd/server: Avoid long error message assertions CVE-2020-10761 Bugzilla: 1845384 RH-Acked-by: Sergio Lopez Pascual RH-Acked-by: Max Reitz RH-Acked-by: Stefan Hajnoczi Ever since commit 36683283 (v2.8), the server code asserts that error strings sent to the client are well-formed per the protocol by not exceeding the maximum string length of 4096. At the time the server first started sending error messages, the assertion could not be triggered, because messages were completely under our control. However, over the years, we have added latent scenarios where a client could trigger the server to attempt an error message that would include the client's information if it passed other checks first: - requesting NBD_OPT_INFO/GO on an export name that is not present (commit 0cfae925 in v2.12 echoes the name) - requesting NBD_OPT_LIST/SET_META_CONTEXT on an export name that is not present (commit e7b1948d in v2.12 echoes the name) At the time, those were still safe because we flagged names larger than 256 bytes with a different message; but that changed in commit 93676c88 (v4.2) when we raised the name limit to 4096 to match the NBD string limit. (That commit also failed to change the magic number 4096 in nbd_negotiate_send_rep_err to the just-introduced named constant.) So with that commit, long client names appended to server text can now trigger the assertion, and thus be used as a denial of service attack against a server. As a mitigating factor, if the server requires TLS, the client cannot trigger the problematic paths unless it first supplies TLS credentials, and such trusted clients are less likely to try to intentionally crash the server. We may later want to further sanitize the user-supplied strings we place into our error messages, such as scrubbing out control characters, but that is less important to the CVE fix, so it can be a later patch to the new nbd_sanitize_name. Consideration was given to changing the assertion in nbd_negotiate_send_rep_verr to instead merely log a server error and truncate the message, to avoid leaving a latent path that could trigger a future CVE DoS on any new error message. However, this merely complicates the code for something that is already (correctly) flagging coding errors, and now that we are aware of the long message pitfall, we are less likely to introduce such errors in the future, which would make such error handling dead code. Reported-by: Xueqiang Wei CC: qemu-stable@nongnu.org Fixes: https://bugzilla.redhat.com/1843684 CVE-2020-10761 Fixes: 93676c88d7 Signed-off-by: Eric Blake Message-Id: <20200610163741.3745251-2-eblake@redhat.com> Reviewed-by: Vladimir Sementsov-Ogievskiy (cherry picked from commit 5c4fe018c025740fef4a0a4421e8162db0c3eefd) Signed-off-by: Eric Blake Signed-off-by: Eduardo Lima (Etrunko) --- nbd/server.c | 21 +++++++++++++++++++-- tests/qemu-iotests/143 | 4 ++++ tests/qemu-iotests/143.out | 2 ++ 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/nbd/server.c b/nbd/server.c index 2d81248967..115e8f06ed 100644 --- a/nbd/server.c +++ b/nbd/server.c @@ -229,6 +229,19 @@ out: return ret; } +/* + * Return a malloc'd copy of @name suitable for use in an error reply. + */ +static char * +nbd_sanitize_name(const char *name) +{ + if (strnlen(name, 80) < 80) { + return g_strdup(name); + } + /* XXX Should we also try to sanitize any control characters? */ + return g_strdup_printf("%.80s...", name); +} + /* Send an error reply. * Return -errno on error, 0 on success. */ static int GCC_FMT_ATTR(4, 5) @@ -584,9 +597,11 @@ static int nbd_negotiate_handle_info(NBDClient *client, uint16_t myflags, exp = nbd_export_find(name); if (!exp) { + g_autofree char *sane_name = nbd_sanitize_name(name); + return nbd_negotiate_send_rep_err(client, NBD_REP_ERR_UNKNOWN, errp, "export '%s' not present", - name); + sane_name); } /* Don't bother sending NBD_INFO_NAME unless client requested it */ @@ -975,8 +990,10 @@ static int nbd_negotiate_meta_queries(NBDClient *client, meta->exp = nbd_export_find(export_name); if (meta->exp == NULL) { + g_autofree char *sane_name = nbd_sanitize_name(export_name); + return nbd_opt_drop(client, NBD_REP_ERR_UNKNOWN, errp, - "export '%s' not present", export_name); + "export '%s' not present", sane_name); } ret = nbd_opt_read(client, &nb_queries, sizeof(nb_queries), errp); diff --git a/tests/qemu-iotests/143 b/tests/qemu-iotests/143 index f649b36195..d2349903b1 100755 --- a/tests/qemu-iotests/143 +++ b/tests/qemu-iotests/143 @@ -58,6 +58,10 @@ _send_qemu_cmd $QEMU_HANDLE \ $QEMU_IO_PROG -f raw -c quit \ "nbd+unix:///no_such_export?socket=$SOCK_DIR/nbd" 2>&1 \ | _filter_qemu_io | _filter_nbd +# Likewise, with longest possible name permitted in NBD protocol +$QEMU_IO_PROG -f raw -c quit \ + "nbd+unix:///$(printf %4096d 1 | tr ' ' a)?socket=$SOCK_DIR/nbd" 2>&1 \ + | _filter_qemu_io | _filter_nbd | sed 's/aaaa*aa/aa--aa/' _send_qemu_cmd $QEMU_HANDLE \ "{ 'execute': 'quit' }" \ diff --git a/tests/qemu-iotests/143.out b/tests/qemu-iotests/143.out index 037d34a409..fc7bab3129 100644 --- a/tests/qemu-iotests/143.out +++ b/tests/qemu-iotests/143.out @@ -3,6 +3,8 @@ QA output created by 143 {"return": {}} qemu-io: can't open device nbd+unix:///no_such_export?socket=SOCK_DIR/nbd: Requested export not available server reported: export 'no_such_export' not present +qemu-io: can't open device nbd+unix:///aa--aa1?socket=SOCK_DIR/nbd: Requested export not available +server reported: export 'aa--aa...' not present {"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} *** done -- Gitee From e94c1625c0f8155740b1bb7b2c749df759e04526 Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Wed, 10 Jun 2020 18:32:02 -0400 Subject: [PATCH 7/8] block: Call attention to truncation of long NBD exports RH-Author: Eric Blake Message-id: <20200610183202.3780750-3-eblake@redhat.com> Patchwork-id: 97495 O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH 2/2] block: Call attention to truncation of long NBD exports Bugzilla: 1845384 RH-Acked-by: Sergio Lopez Pascual RH-Acked-by: Max Reitz RH-Acked-by: Stefan Hajnoczi Commit 93676c88 relaxed our NBD client code to request export names up to the NBD protocol maximum of 4096 bytes without NUL terminator, even though the block layer can't store anything longer than 4096 bytes including NUL terminator for display to the user. Since this means there are some export names where we have to truncate things, we can at least try to make the truncation a bit more obvious for the user. Note that in spite of the truncated display name, we can still communicate with an NBD server using such a long export name; this was deemed nicer than refusing to even connect to such a server (since the server may not be under our control, and since determining our actual length limits gets tricky when nbd://host:port/export and nbd+unix:///export?socket=/path are themselves variable-length expansions beyond the export name but count towards the block layer name length). Reported-by: Xueqiang Wei Fixes: https://bugzilla.redhat.com/1843684 Signed-off-by: Eric Blake Reviewed-by: Vladimir Sementsov-Ogievskiy Message-Id: <20200610163741.3745251-3-eblake@redhat.com> (cherry picked from commit 5c86bdf1208916ece0b87e1151c9b48ee54faa3e) Signed-off-by: Eric Blake Signed-off-by: Eduardo Lima (Etrunko) --- block.c | 7 +++++-- block/nbd.c | 21 +++++++++++++-------- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/block.c b/block.c index 38880eabf8..ba36b53a00 100644 --- a/block.c +++ b/block.c @@ -6444,8 +6444,11 @@ void bdrv_refresh_filename(BlockDriverState *bs) pstrcpy(bs->filename, sizeof(bs->filename), bs->exact_filename); } else { QString *json = qobject_to_json(QOBJECT(bs->full_open_options)); - snprintf(bs->filename, sizeof(bs->filename), "json:%s", - qstring_get_str(json)); + if (snprintf(bs->filename, sizeof(bs->filename), "json:%s", + qstring_get_str(json)) >= sizeof(bs->filename)) { + /* Give user a hint if we truncated things. */ + strcpy(bs->filename + sizeof(bs->filename) - 4, "..."); + } qobject_unref(json); } } diff --git a/block/nbd.c b/block/nbd.c index 3977b1efc7..63cdd051ab 100644 --- a/block/nbd.c +++ b/block/nbd.c @@ -1714,6 +1714,7 @@ static void nbd_refresh_filename(BlockDriverState *bs) { BDRVNBDState *s = bs->opaque; const char *host = NULL, *port = NULL, *path = NULL; + size_t len = 0; if (s->saddr->type == SOCKET_ADDRESS_TYPE_INET) { const InetSocketAddress *inet = &s->saddr->u.inet; @@ -1726,17 +1727,21 @@ static void nbd_refresh_filename(BlockDriverState *bs) } /* else can't represent as pseudo-filename */ if (path && s->export) { - snprintf(bs->exact_filename, sizeof(bs->exact_filename), - "nbd+unix:///%s?socket=%s", s->export, path); + len = snprintf(bs->exact_filename, sizeof(bs->exact_filename), + "nbd+unix:///%s?socket=%s", s->export, path); } else if (path && !s->export) { - snprintf(bs->exact_filename, sizeof(bs->exact_filename), - "nbd+unix://?socket=%s", path); + len = snprintf(bs->exact_filename, sizeof(bs->exact_filename), + "nbd+unix://?socket=%s", path); } else if (host && s->export) { - snprintf(bs->exact_filename, sizeof(bs->exact_filename), - "nbd://%s:%s/%s", host, port, s->export); + len = snprintf(bs->exact_filename, sizeof(bs->exact_filename), + "nbd://%s:%s/%s", host, port, s->export); } else if (host && !s->export) { - snprintf(bs->exact_filename, sizeof(bs->exact_filename), - "nbd://%s:%s", host, port); + len = snprintf(bs->exact_filename, sizeof(bs->exact_filename), + "nbd://%s:%s", host, port); + } + if (len > sizeof(bs->exact_filename)) { + /* Name is too long to represent exactly, so leave it empty. */ + bs->exact_filename[0] = '\0'; } } -- Gitee From a2fcbe2b82c42f890a857ad8d4edcfdb273106ea Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Fri, 31 Jul 2020 08:18:31 -0400 Subject: [PATCH 8/8] qemu-img convert: Don't pre-zero images RH-Author: Kevin Wolf Message-id: <20200731081831.13781-2-kwolf@redhat.com> Patchwork-id: 98117 O-Subject: [RHEL-AV-8.2.1.z qemu-kvm PATCH 1/1] qemu-img convert: Don't pre-zero images Bugzilla: 1861682 RH-Acked-by: Stefano Garzarella RH-Acked-by: Max Reitz RH-Acked-by: Eric Blake Since commit 5a37b60a61c, qemu-img create will pre-zero the target image if it isn't already zero-initialised (most importantly, for host block devices, but also iscsi etc.), so that writing explicit zeros wouldn't be necessary later. This could speed up the operation significantly, in particular when the source image file was only sparsely populated. However, it also means that some block are written twice: Once when pre-zeroing them, and then when they are overwritten with actual data. On a full image, the pre-zeroing is wasted work because everything will be overwritten. In practice, write_zeroes typically turns out faster than writing explicit zero buffers, but slow enough that first zeroing everything and then overwriting parts can be a significant net loss. Meanwhile, qemu-img convert was rewritten in 690c7301600 and zero blocks are now written to the target using bdrv_co_pwrite_zeroes() if the target could be pre-zeroed. This way we already make use of the faster write_zeroes operation, but avoid writing any blocks twice. Remove the pre-zeroing because these days this former optimisation has actually turned into a pessimisation in the common case. Reported-by: Nir Soffer Signed-off-by: Kevin Wolf Message-Id: <20200622151203.35624-1-kwolf@redhat.com> Tested-by: Nir Soffer Reviewed-by: Eric Blake Signed-off-by: Kevin Wolf (cherry picked from commit edafc70c0c8510862f2f213a3acf7067113bcd08) Signed-off-by: Kevin Wolf Signed-off-by: Danilo C. L. de Paula --- qemu-img.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/qemu-img.c b/qemu-img.c index 2e9cc5db7c..e4abd4978a 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -1981,15 +1981,6 @@ static int convert_do_copy(ImgConvertState *s) ? bdrv_has_zero_init(blk_bs(s->target)) : false; - if (!s->has_zero_init && !s->target_has_backing && - bdrv_can_write_zeroes_with_unmap(blk_bs(s->target))) - { - ret = blk_make_zero(s->target, BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK); - if (ret == 0) { - s->has_zero_init = true; - } - } - /* Allocate buffer for copied data. For compressed images, only one cluster * can be copied at a time. */ if (s->compressed) { -- Gitee