Hello community,

here is the log from the commit of package qemu for openSUSE:Factory checked in 
at 2019-11-08 15:23:56
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/qemu (Old)
 and      /work/SRC/openSUSE:Factory/.qemu.new.2990 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "qemu"

Fri Nov  8 15:23:56 2019 rev:162 rq:746405 version:4.1.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/qemu/qemu.changes        2019-10-30 
14:41:38.321787916 +0100
+++ /work/SRC/openSUSE:Factory/.qemu.new.2990/qemu.changes      2019-11-08 
15:24:08.562894270 +0100
@@ -1,0 +2,25 @@
+Thu Nov  7 19:02:39 UTC 2019 - Bruce Rogers <brog...@suse.com>
+
+- Fix two issues with qcow2 image processing which could affect
+  disk integrity
+  qcow2-Fix-QCOW2_COMPRESSED_SECTOR_MASK.patch
+  qcow2-bitmap-Fix-uint64_t-left-shift-ove.patch
+
+-------------------------------------------------------------------
+Wed Nov  6 20:43:48 UTC 2019 - Bruce Rogers <brog...@suse.com>
+
+- Work around a host kernel xfs bug which can result in qcow2 image
+  corruption
+  block-io-refactor-padding.patch
+  util-iov-introduce-qemu_iovec_init_exten.patch
+  block-Make-wait-mark-serialising-request.patch
+  block-Add-bdrv_co_get_self_request.patch
+  block-file-posix-Let-post-EOF-fallocate-.patch
+- Patch queue updated from git://github.com/openSUSE/qemu.git opensuse-4.1
+
+-------------------------------------------------------------------
+Mon Nov  4 13:47:02 UTC 2019 - Stefan BrĂ¼ns <stefan.bru...@rwth-aachen.de>
+
+- Correct package names in _constraints after switch to multibuild.
+
+-------------------------------------------------------------------

New:
----
  block-Add-bdrv_co_get_self_request.patch
  block-Make-wait-mark-serialising-request.patch
  block-file-posix-Let-post-EOF-fallocate-.patch
  block-io-refactor-padding.patch
  qcow2-Fix-QCOW2_COMPRESSED_SECTOR_MASK.patch
  qcow2-bitmap-Fix-uint64_t-left-shift-ove.patch
  util-iov-introduce-qemu_iovec_init_exten.patch

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ qemu.spec ++++++
--- /var/tmp/diff_new_pack.FlPp3h/_old  2019-11-08 15:24:11.382897252 +0100
+++ /var/tmp/diff_new_pack.FlPp3h/_new  2019-11-08 15:24:11.382897252 +0100
@@ -149,46 +149,53 @@
 Patch00024:     roms-Makefile.edk2-don-t-pull-in-submodu.patch
 Patch00025:     coroutine-Add-qemu_co_mutex_assert_locke.patch
 Patch00026:     qcow2-Fix-corruption-bug-in-qcow2_detect.patch
-Patch00027:     XXX-dont-dump-core-on-sigabort.patch
-Patch00028:     qemu-binfmt-conf-Modify-default-path.patch
-Patch00029:     qemu-cvs-gettimeofday.patch
-Patch00030:     qemu-cvs-ioctl_debug.patch
-Patch00031:     qemu-cvs-ioctl_nodirection.patch
-Patch00032:     linux-user-add-binfmt-wrapper-for-argv-0.patch
-Patch00033:     PPC-KVM-Disable-mmu-notifier-check.patch
-Patch00034:     linux-user-binfmt-support-host-binaries.patch
-Patch00035:     linux-user-Fake-proc-cpuinfo.patch
-Patch00036:     linux-user-use-target_ulong.patch
-Patch00037:     Make-char-muxer-more-robust-wrt-small-FI.patch
-Patch00038:     linux-user-lseek-explicitly-cast-non-set.patch
-Patch00039:     AIO-Reduce-number-of-threads-for-32bit-h.patch
-Patch00040:     xen_disk-Add-suse-specific-flush-disable.patch
-Patch00041:     qemu-bridge-helper-reduce-security-profi.patch
-Patch00042:     qemu-binfmt-conf-use-qemu-ARCH-binfmt.patch
-Patch00043:     linux-user-properly-test-for-infinite-ti.patch
-Patch00044:     roms-Makefile-pass-a-packaging-timestamp.patch
-Patch00045:     Raise-soft-address-space-limit-to-hard-l.patch
-Patch00046:     increase-x86_64-physical-bits-to-42.patch
-Patch00047:     vga-Raise-VRAM-to-16-MiB-for-pc-0.15-and.patch
-Patch00048:     i8254-Fix-migration-from-SLE11-SP2.patch
-Patch00049:     acpi_piix4-Fix-migration-from-SLE11-SP2.patch
-Patch00050:     Switch-order-of-libraries-for-mpath-supp.patch
-Patch00051:     Make-installed-scripts-explicitly-python.patch
-Patch00052:     hw-smbios-handle-both-file-formats-regar.patch
-Patch00053:     xen-add-block-resize-support-for-xen-dis.patch
-Patch00054:     tests-qemu-iotests-Triple-timeout-of-i-o.patch
-Patch00055:     tests-Fix-block-tests-to-be-compatible-w.patch
-Patch00056:     xen-ignore-live-parameter-from-xen-save-.patch
-Patch00057:     Conditionalize-ui-bitmap-installation-be.patch
-Patch00058:     tests-change-error-message-in-test-162.patch
-Patch00059:     hw-usb-hcd-xhci-Fix-GCC-9-build-warning.patch
-Patch00060:     hw-usb-dev-mtp-Fix-GCC-9-build-warning.patch
-Patch00061:     hw-intc-exynos4210_gic-provide-more-room.patch
-Patch00062:     configure-only-populate-roms-if-softmmu.patch
-Patch00063:     pc-bios-s390-ccw-net-avoid-warning-about.patch
-Patch00064:     roms-change-cross-compiler-naming-to-be-.patch
-Patch00065:     tests-Disable-some-block-tests-for-now.patch
-Patch00066:     test-add-mapping-from-arch-of-i686-to-qe.patch
+Patch00027:     block-io-refactor-padding.patch
+Patch00028:     util-iov-introduce-qemu_iovec_init_exten.patch
+Patch00029:     block-Make-wait-mark-serialising-request.patch
+Patch00030:     block-Add-bdrv_co_get_self_request.patch
+Patch00031:     block-file-posix-Let-post-EOF-fallocate-.patch
+Patch00032:     qcow2-bitmap-Fix-uint64_t-left-shift-ove.patch
+Patch00033:     qcow2-Fix-QCOW2_COMPRESSED_SECTOR_MASK.patch
+Patch00034:     XXX-dont-dump-core-on-sigabort.patch
+Patch00035:     qemu-binfmt-conf-Modify-default-path.patch
+Patch00036:     qemu-cvs-gettimeofday.patch
+Patch00037:     qemu-cvs-ioctl_debug.patch
+Patch00038:     qemu-cvs-ioctl_nodirection.patch
+Patch00039:     linux-user-add-binfmt-wrapper-for-argv-0.patch
+Patch00040:     PPC-KVM-Disable-mmu-notifier-check.patch
+Patch00041:     linux-user-binfmt-support-host-binaries.patch
+Patch00042:     linux-user-Fake-proc-cpuinfo.patch
+Patch00043:     linux-user-use-target_ulong.patch
+Patch00044:     Make-char-muxer-more-robust-wrt-small-FI.patch
+Patch00045:     linux-user-lseek-explicitly-cast-non-set.patch
+Patch00046:     AIO-Reduce-number-of-threads-for-32bit-h.patch
+Patch00047:     xen_disk-Add-suse-specific-flush-disable.patch
+Patch00048:     qemu-bridge-helper-reduce-security-profi.patch
+Patch00049:     qemu-binfmt-conf-use-qemu-ARCH-binfmt.patch
+Patch00050:     linux-user-properly-test-for-infinite-ti.patch
+Patch00051:     roms-Makefile-pass-a-packaging-timestamp.patch
+Patch00052:     Raise-soft-address-space-limit-to-hard-l.patch
+Patch00053:     increase-x86_64-physical-bits-to-42.patch
+Patch00054:     vga-Raise-VRAM-to-16-MiB-for-pc-0.15-and.patch
+Patch00055:     i8254-Fix-migration-from-SLE11-SP2.patch
+Patch00056:     acpi_piix4-Fix-migration-from-SLE11-SP2.patch
+Patch00057:     Switch-order-of-libraries-for-mpath-supp.patch
+Patch00058:     Make-installed-scripts-explicitly-python.patch
+Patch00059:     hw-smbios-handle-both-file-formats-regar.patch
+Patch00060:     xen-add-block-resize-support-for-xen-dis.patch
+Patch00061:     tests-qemu-iotests-Triple-timeout-of-i-o.patch
+Patch00062:     tests-Fix-block-tests-to-be-compatible-w.patch
+Patch00063:     xen-ignore-live-parameter-from-xen-save-.patch
+Patch00064:     Conditionalize-ui-bitmap-installation-be.patch
+Patch00065:     tests-change-error-message-in-test-162.patch
+Patch00066:     hw-usb-hcd-xhci-Fix-GCC-9-build-warning.patch
+Patch00067:     hw-usb-dev-mtp-Fix-GCC-9-build-warning.patch
+Patch00068:     hw-intc-exynos4210_gic-provide-more-room.patch
+Patch00069:     configure-only-populate-roms-if-softmmu.patch
+Patch00070:     pc-bios-s390-ccw-net-avoid-warning-about.patch
+Patch00071:     roms-change-cross-compiler-naming-to-be-.patch
+Patch00072:     tests-Disable-some-block-tests-for-now.patch
+Patch00073:     test-add-mapping-from-arch-of-i686-to-qe.patch
 # Patches applied in roms/seabios/:
 Patch01000:     seabios-use-python2-explicitly-as-needed.patch
 Patch01001:     seabios-switch-to-python3-as-needed.patch
@@ -945,6 +952,13 @@
 %patch00064 -p1
 %patch00065 -p1
 %patch00066 -p1
+%patch00067 -p1
+%patch00068 -p1
+%patch00069 -p1
+%patch00070 -p1
+%patch00071 -p1
+%patch00072 -p1
+%patch00073 -p1
 %patch01000 -p1
 %patch01001 -p1
 %patch01002 -p1

++++++ _constraints ++++++
--- /var/tmp/diff_new_pack.FlPp3h/_old  2019-11-08 15:24:11.498897375 +0100
+++ /var/tmp/diff_new_pack.FlPp3h/_new  2019-11-08 15:24:11.502897380 +0100
@@ -3,8 +3,8 @@
   <overwrite>
     <conditions>
       <package>qemu</package>
-      <package>qemu-linux-user</package>
-      <package>qemu-testsuite</package>
+      <package>qemu:linux-user</package>
+      <package>qemu:testsuite</package>
     </conditions>
     <hardware>
       <disk>
@@ -30,7 +30,7 @@
       <arch>i586</arch>
       <arch>x86_64</arch>
       <arch>ppc64le</arch>
-      <package>qemu-testsuite</package>
+      <package>qemu:testsuite</package>
     </conditions>
     <hardware>
       <memory>
@@ -42,7 +42,7 @@
   <overwrite>
     <conditions>
       <arch>ppc64</arch>
-      <package>qemu-testsuite</package>
+      <package>qemu:testsuite</package>
     </conditions>
     <hardware>
       <memory>

++++++ block-Add-bdrv_co_get_self_request.patch ++++++
From: Max Reitz <mre...@redhat.com>
Date: Fri, 1 Nov 2019 16:25:09 +0100
Subject: block: Add bdrv_co_get_self_request()

Git-commit: c28107e9e55b11cd35cf3dc2505e3e69d10dcf13

Cc: qemu-sta...@nongnu.org
Signed-off-by: Max Reitz <mre...@redhat.com>
Message-id: 20191101152510.11719-3-mre...@redhat.com
Signed-off-by: Max Reitz <mre...@redhat.com>
Signed-off-by: Bruce Rogers <brog...@suse.com>
---
 block/io.c                | 18 ++++++++++++++++++
 include/block/block_int.h |  1 +
 2 files changed, 19 insertions(+)

diff --git a/block/io.c b/block/io.c
index d9f632f450b744515d3f91d2aa26..0366daf27f4a2133148716135d63 100644
--- a/block/io.c
+++ b/block/io.c
@@ -721,6 +721,24 @@ static bool 
is_request_serialising_and_aligned(BdrvTrackedRequest *req)
            (req->bytes == req->overlap_bytes);
 }
 
+/**
+ * Return the tracked request on @bs for the current coroutine, or
+ * NULL if there is none.
+ */
+BdrvTrackedRequest *coroutine_fn bdrv_co_get_self_request(BlockDriverState *bs)
+{
+    BdrvTrackedRequest *req;
+    Coroutine *self = qemu_coroutine_self();
+
+    QLIST_FOREACH(req, &bs->tracked_requests, list) {
+        if (req->co == self) {
+            return req;
+        }
+    }
+
+    return NULL;
+}
+
 /**
  * Round a region to cluster boundaries
  */
diff --git a/include/block/block_int.h b/include/block/block_int.h
index 4465b022424c23aea82942547cc3..05ee6b4866f84a9ab9ba0dcda5da 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -964,6 +964,7 @@ void bdrv_unapply_subtree_drain(BdrvChild *child, 
BlockDriverState *old_parent);
 
 bool coroutine_fn bdrv_wait_serialising_requests(BdrvTrackedRequest *self);
 void bdrv_mark_request_serialising(BdrvTrackedRequest *req, uint64_t align);
+BdrvTrackedRequest *coroutine_fn bdrv_co_get_self_request(BlockDriverState 
*bs);
 
 int get_tmp_filename(char *filename, int size);
 BlockDriver *bdrv_probe_all(const uint8_t *buf, int buf_size,
++++++ block-Make-wait-mark-serialising-request.patch ++++++
From: Max Reitz <mre...@redhat.com>
Date: Fri, 1 Nov 2019 16:25:08 +0100
Subject: block: Make wait/mark serialising requests public

Git-commit: 304d9d7f034ff7f5e1e66a65b7f720f63a72c57e

Make both bdrv_mark_request_serialising() and
bdrv_wait_serialising_requests() public so they can be used from block
drivers.

Cc: qemu-sta...@nongnu.org
Signed-off-by: Max Reitz <mre...@redhat.com>
Message-id: 20191101152510.11719-2-mre...@redhat.com
Signed-off-by: Max Reitz <mre...@redhat.com>
Signed-off-by: Bruce Rogers <brog...@suse.com>
---
 block/io.c                | 24 ++++++++++++------------
 include/block/block_int.h |  3 +++
 2 files changed, 15 insertions(+), 12 deletions(-)

diff --git a/block/io.c b/block/io.c
index bfb2653d8ee853e99bd4d55a1a87..d9f632f450b744515d3f91d2aa26 100644
--- a/block/io.c
+++ b/block/io.c
@@ -694,7 +694,7 @@ static void tracked_request_begin(BdrvTrackedRequest *req,
     qemu_co_mutex_unlock(&bs->reqs_lock);
 }
 
-static void mark_request_serialising(BdrvTrackedRequest *req, uint64_t align)
+void bdrv_mark_request_serialising(BdrvTrackedRequest *req, uint64_t align)
 {
     int64_t overlap_offset = req->offset & ~(align - 1);
     uint64_t overlap_bytes = ROUND_UP(req->offset + req->bytes, align)
@@ -784,7 +784,7 @@ void bdrv_dec_in_flight(BlockDriverState *bs)
     bdrv_wakeup(bs);
 }
 
-static bool coroutine_fn wait_serialising_requests(BdrvTrackedRequest *self)
+bool coroutine_fn bdrv_wait_serialising_requests(BdrvTrackedRequest *self)
 {
     BlockDriverState *bs = self->bs;
     BdrvTrackedRequest *req;
@@ -1340,14 +1340,14 @@ static int coroutine_fn bdrv_aligned_preadv(BdrvChild 
*child,
          * with each other for the same cluster.  For example, in copy-on-read
          * it ensures that the CoR read and write operations are atomic and
          * guest writes cannot interleave between them. */
-        mark_request_serialising(req, bdrv_get_cluster_size(bs));
+        bdrv_mark_request_serialising(req, bdrv_get_cluster_size(bs));
     }
 
     /* BDRV_REQ_SERIALISING is only for write operation */
     assert(!(flags & BDRV_REQ_SERIALISING));
 
     if (!(flags & BDRV_REQ_NO_SERIALISING)) {
-        wait_serialising_requests(req);
+        bdrv_wait_serialising_requests(req);
     }
 
     if (flags & BDRV_REQ_COPY_ON_READ) {
@@ -1736,10 +1736,10 @@ bdrv_co_write_req_prepare(BdrvChild *child, int64_t 
offset, uint64_t bytes,
     assert(!(flags & ~BDRV_REQ_MASK));
 
     if (flags & BDRV_REQ_SERIALISING) {
-        mark_request_serialising(req, bdrv_get_cluster_size(bs));
+        bdrv_mark_request_serialising(req, bdrv_get_cluster_size(bs));
     }
 
-    waited = wait_serialising_requests(req);
+    waited = bdrv_wait_serialising_requests(req);
 
     assert(!waited || !req->serialising ||
            is_request_serialising_and_aligned(req));
@@ -1905,8 +1905,8 @@ static int coroutine_fn bdrv_co_do_zero_pwritev(BdrvChild 
*child,
 
     padding = bdrv_init_padding(bs, offset, bytes, &pad);
     if (padding) {
-        mark_request_serialising(req, align);
-        wait_serialising_requests(req);
+        bdrv_mark_request_serialising(req, align);
+        bdrv_wait_serialising_requests(req);
 
         bdrv_padding_rmw_read(child, req, &pad, true);
 
@@ -1993,8 +1993,8 @@ int coroutine_fn bdrv_co_pwritev(BdrvChild *child,
     }
 
     if (bdrv_pad_request(bs, &qiov, &offset, &bytes, &pad)) {
-        mark_request_serialising(&req, align);
-        wait_serialising_requests(&req);
+        bdrv_mark_request_serialising(&req, align);
+        bdrv_wait_serialising_requests(&req);
         bdrv_padding_rmw_read(child, &req, &pad, false);
     }
 
@@ -3078,7 +3078,7 @@ static int coroutine_fn bdrv_co_copy_range_internal(
         /* BDRV_REQ_SERIALISING is only for write operation */
         assert(!(read_flags & BDRV_REQ_SERIALISING));
         if (!(read_flags & BDRV_REQ_NO_SERIALISING)) {
-            wait_serialising_requests(&req);
+            bdrv_wait_serialising_requests(&req);
         }
 
         ret = src->bs->drv->bdrv_co_copy_range_from(src->bs,
@@ -3205,7 +3205,7 @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, 
int64_t offset,
      * new area, we need to make sure that no write requests are made to it
      * concurrently or they might be overwritten by preallocation. */
     if (new_bytes) {
-        mark_request_serialising(&req, 1);
+        bdrv_mark_request_serialising(&req, 1);
     }
     if (bs->read_only) {
         error_setg(errp, "Image is read-only");
diff --git a/include/block/block_int.h b/include/block/block_int.h
index 3aa1e832a8fdf32bf3f33d1e1508..4465b022424c23aea82942547cc3 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -962,6 +962,9 @@ extern unsigned int bdrv_drain_all_count;
 void bdrv_apply_subtree_drain(BdrvChild *child, BlockDriverState *new_parent);
 void bdrv_unapply_subtree_drain(BdrvChild *child, BlockDriverState 
*old_parent);
 
+bool coroutine_fn bdrv_wait_serialising_requests(BdrvTrackedRequest *self);
+void bdrv_mark_request_serialising(BdrvTrackedRequest *req, uint64_t align);
+
 int get_tmp_filename(char *filename, int size);
 BlockDriver *bdrv_probe_all(const uint8_t *buf, int buf_size,
                             const char *filename);
++++++ block-file-posix-Let-post-EOF-fallocate-.patch ++++++
From: Max Reitz <mre...@redhat.com>
Date: Fri, 1 Nov 2019 16:25:10 +0100
Subject: block/file-posix: Let post-EOF fallocate serialize

Git-commit: 292d06b925b2787ee6f2430996b95651cae42fce

The XFS kernel driver has a bug that may cause data corruption for qcow2
images as of qemu commit c8bb23cbdbe32f.  We can work around it by
treating post-EOF fallocates as serializing up until infinity (INT64_MAX
in practice).

Cc: qemu-sta...@nongnu.org
Signed-off-by: Max Reitz <mre...@redhat.com>
Message-id: 20191101152510.11719-4-mre...@redhat.com
Signed-off-by: Max Reitz <mre...@redhat.com>
Signed-off-by: Bruce Rogers <brog...@suse.com>
---
 block/file-posix.c | 36 ++++++++++++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)

diff --git a/block/file-posix.c b/block/file-posix.c
index 992eb4a798b99fe02e93103028c6..c5df61b47735ee7e5201cebec46c 100644
--- a/block/file-posix.c
+++ b/block/file-posix.c
@@ -2623,6 +2623,42 @@ raw_do_pwrite_zeroes(BlockDriverState *bs, int64_t 
offset, int bytes,
     RawPosixAIOData acb;
     ThreadPoolFunc *handler;
 
+#ifdef CONFIG_FALLOCATE
+    if (offset + bytes > bs->total_sectors * BDRV_SECTOR_SIZE) {
+        BdrvTrackedRequest *req;
+        uint64_t end;
+
+        /*
+         * This is a workaround for a bug in the Linux XFS driver,
+         * where writes submitted through the AIO interface will be
+         * discarded if they happen beyond a concurrently running
+         * fallocate() that increases the file length (i.e., both the
+         * write and the fallocate() happen beyond the EOF).
+         *
+         * To work around it, we extend the tracked request for this
+         * zero write until INT64_MAX (effectively infinity), and mark
+         * it as serializing.
+         *
+         * We have to enable this workaround for all filesystems and
+         * AIO modes (not just XFS with aio=native), because for
+         * remote filesystems we do not know the host configuration.
+         */
+
+        req = bdrv_co_get_self_request(bs);
+        assert(req);
+        assert(req->type == BDRV_TRACKED_WRITE);
+        assert(req->offset <= offset);
+        assert(req->offset + req->bytes >= offset + bytes);
+
+        end = INT64_MAX & -(uint64_t)bs->bl.request_alignment;
+        req->bytes = end - req->offset;
+        req->overlap_bytes = req->bytes;
+
+        bdrv_mark_request_serialising(req, bs->bl.request_alignment);
+        bdrv_wait_serialising_requests(req);
+    }
+#endif
+
     acb = (RawPosixAIOData) {
         .bs             = bs,
         .aio_fildes     = s->fd,
++++++ block-io-refactor-padding.patch ++++++
From: Vladimir Sementsov-Ogievskiy <vsement...@virtuozzo.com>
Date: Tue, 4 Jun 2019 19:15:05 +0300
Subject: block/io: refactor padding

Git-commit: 7a3f542fbdfd799be4fa6f8b96dc8c1e6933fce4

We have similar padding code in bdrv_co_pwritev,
bdrv_co_do_pwrite_zeroes and bdrv_co_preadv. Let's combine and unify
it.

[Squashed in Vladimir's qemu-iotests 077 fix
--Stefan]

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsement...@virtuozzo.com>
Acked-by: Stefan Hajnoczi <stefa...@redhat.com>
Message-id: 20190604161514.262241-4-vsement...@virtuozzo.com
Message-Id: <20190604161514.262241-4-vsement...@virtuozzo.com>
Signed-off-by: Stefan Hajnoczi <stefa...@redhat.com>
Signed-off-by: Bruce Rogers <brog...@suse.com>
---
 block/io.c | 365 +++++++++++++++++++++++++++++------------------------
 1 file changed, 200 insertions(+), 165 deletions(-)

diff --git a/block/io.c b/block/io.c
index 06305c6ea62efabf1efb43933bf6..bfb2653d8ee853e99bd4d55a1a87 100644
--- a/block/io.c
+++ b/block/io.c
@@ -1408,28 +1408,177 @@ out:
 }
 
 /*
- * Handle a read request in coroutine context
+ * Request padding
+ *
+ *  |<---- align ----->|                     |<----- align ---->|
+ *  |<- head ->|<------------- bytes ------------->|<-- tail -->|
+ *  |          |       |                     |     |            |
+ * -*----------$-------*-------- ... --------*-----$------------*---
+ *  |          |       |                     |     |            |
+ *  |          offset  |                     |     end          |
+ *  ALIGN_DOWN(offset) ALIGN_UP(offset)      ALIGN_DOWN(end)   ALIGN_UP(end)
+ *  [buf   ... )                             [tail_buf          )
+ *
+ * @buf is an aligned allocation needed to store @head and @tail paddings. 
@head
+ * is placed at the beginning of @buf and @tail at the @end.
+ *
+ * @tail_buf is a pointer to sub-buffer, corresponding to align-sized chunk
+ * around tail, if tail exists.
+ *
+ * @merge_reads is true for small requests,
+ * if @buf_len == @head + bytes + @tail. In this case it is possible that both
+ * head and tail exist but @buf_len == align and @tail_buf == @buf.
+ */
+typedef struct BdrvRequestPadding {
+    uint8_t *buf;
+    size_t buf_len;
+    uint8_t *tail_buf;
+    size_t head;
+    size_t tail;
+    bool merge_reads;
+    QEMUIOVector local_qiov;
+} BdrvRequestPadding;
+
+static bool bdrv_init_padding(BlockDriverState *bs,
+                              int64_t offset, int64_t bytes,
+                              BdrvRequestPadding *pad)
+{
+    uint64_t align = bs->bl.request_alignment;
+    size_t sum;
+
+    memset(pad, 0, sizeof(*pad));
+
+    pad->head = offset & (align - 1);
+    pad->tail = ((offset + bytes) & (align - 1));
+    if (pad->tail) {
+        pad->tail = align - pad->tail;
+    }
+
+    if ((!pad->head && !pad->tail) || !bytes) {
+        return false;
+    }
+
+    sum = pad->head + bytes + pad->tail;
+    pad->buf_len = (sum > align && pad->head && pad->tail) ? 2 * align : align;
+    pad->buf = qemu_blockalign(bs, pad->buf_len);
+    pad->merge_reads = sum == pad->buf_len;
+    if (pad->tail) {
+        pad->tail_buf = pad->buf + pad->buf_len - align;
+    }
+
+    return true;
+}
+
+static int bdrv_padding_rmw_read(BdrvChild *child,
+                                 BdrvTrackedRequest *req,
+                                 BdrvRequestPadding *pad,
+                                 bool zero_middle)
+{
+    QEMUIOVector local_qiov;
+    BlockDriverState *bs = child->bs;
+    uint64_t align = bs->bl.request_alignment;
+    int ret;
+
+    assert(req->serialising && pad->buf);
+
+    if (pad->head || pad->merge_reads) {
+        uint64_t bytes = pad->merge_reads ? pad->buf_len : align;
+
+        qemu_iovec_init_buf(&local_qiov, pad->buf, bytes);
+
+        if (pad->head) {
+            bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_HEAD);
+        }
+        if (pad->merge_reads && pad->tail) {
+            bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_TAIL);
+        }
+        ret = bdrv_aligned_preadv(child, req, req->overlap_offset, bytes,
+                                  align, &local_qiov, 0);
+        if (ret < 0) {
+            return ret;
+        }
+        if (pad->head) {
+            bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_AFTER_HEAD);
+        }
+        if (pad->merge_reads && pad->tail) {
+            bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_AFTER_TAIL);
+        }
+
+        if (pad->merge_reads) {
+            goto zero_mem;
+        }
+    }
+
+    if (pad->tail) {
+        qemu_iovec_init_buf(&local_qiov, pad->tail_buf, align);
+
+        bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_TAIL);
+        ret = bdrv_aligned_preadv(
+                child, req,
+                req->overlap_offset + req->overlap_bytes - align,
+                align, align, &local_qiov, 0);
+        if (ret < 0) {
+            return ret;
+        }
+        bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_AFTER_TAIL);
+    }
+
+zero_mem:
+    if (zero_middle) {
+        memset(pad->buf + pad->head, 0, pad->buf_len - pad->head - pad->tail);
+    }
+
+    return 0;
+}
+
+static void bdrv_padding_destroy(BdrvRequestPadding *pad)
+{
+    if (pad->buf) {
+        qemu_vfree(pad->buf);
+        qemu_iovec_destroy(&pad->local_qiov);
+    }
+}
+
+/*
+ * bdrv_pad_request
+ *
+ * Exchange request parameters with padded request if needed. Don't include RMW
+ * read of padding, bdrv_padding_rmw_read() should be called separately if
+ * needed.
+ *
+ * All parameters except @bs are in-out: they represent original request at
+ * function call and padded (if padding needed) at function finish.
+ *
+ * Function always succeeds.
  */
+static bool bdrv_pad_request(BlockDriverState *bs, QEMUIOVector **qiov,
+                             int64_t *offset, unsigned int *bytes,
+                             BdrvRequestPadding *pad)
+{
+    if (!bdrv_init_padding(bs, *offset, *bytes, pad)) {
+        return false;
+    }
+
+    qemu_iovec_init_extended(&pad->local_qiov, pad->buf, pad->head,
+                             *qiov, 0, *bytes,
+                             pad->buf + pad->buf_len - pad->tail, pad->tail);
+    *bytes += pad->head + pad->tail;
+    *offset -= pad->head;
+    *qiov = &pad->local_qiov;
+
+    return true;
+}
+
 int coroutine_fn bdrv_co_preadv(BdrvChild *child,
     int64_t offset, unsigned int bytes, QEMUIOVector *qiov,
     BdrvRequestFlags flags)
 {
     BlockDriverState *bs = child->bs;
-    BlockDriver *drv = bs->drv;
     BdrvTrackedRequest req;
-
-    uint64_t align = bs->bl.request_alignment;
-    uint8_t *head_buf = NULL;
-    uint8_t *tail_buf = NULL;
-    QEMUIOVector local_qiov;
-    bool use_local_qiov = false;
+    BdrvRequestPadding pad;
     int ret;
 
-    trace_bdrv_co_preadv(child->bs, offset, bytes, flags);
-
-    if (!drv) {
-        return -ENOMEDIUM;
-    }
+    trace_bdrv_co_preadv(bs, offset, bytes, flags);
 
     ret = bdrv_check_byte_request(bs, offset, bytes);
     if (ret < 0) {
@@ -1443,43 +1592,16 @@ int coroutine_fn bdrv_co_preadv(BdrvChild *child,
         flags |= BDRV_REQ_COPY_ON_READ;
     }
 
-    /* Align read if necessary by padding qiov */
-    if (offset & (align - 1)) {
-        head_buf = qemu_blockalign(bs, align);
-        qemu_iovec_init(&local_qiov, qiov->niov + 2);
-        qemu_iovec_add(&local_qiov, head_buf, offset & (align - 1));
-        qemu_iovec_concat(&local_qiov, qiov, 0, qiov->size);
-        use_local_qiov = true;
-
-        bytes += offset & (align - 1);
-        offset = offset & ~(align - 1);
-    }
-
-    if ((offset + bytes) & (align - 1)) {
-        if (!use_local_qiov) {
-            qemu_iovec_init(&local_qiov, qiov->niov + 1);
-            qemu_iovec_concat(&local_qiov, qiov, 0, qiov->size);
-            use_local_qiov = true;
-        }
-        tail_buf = qemu_blockalign(bs, align);
-        qemu_iovec_add(&local_qiov, tail_buf,
-                       align - ((offset + bytes) & (align - 1)));
-
-        bytes = ROUND_UP(bytes, align);
-    }
+    bdrv_pad_request(bs, &qiov, &offset, &bytes, &pad);
 
     tracked_request_begin(&req, bs, offset, bytes, BDRV_TRACKED_READ);
-    ret = bdrv_aligned_preadv(child, &req, offset, bytes, align,
-                              use_local_qiov ? &local_qiov : qiov,
-                              flags);
+    ret = bdrv_aligned_preadv(child, &req, offset, bytes,
+                              bs->bl.request_alignment,
+                              qiov, flags);
     tracked_request_end(&req);
     bdrv_dec_in_flight(bs);
 
-    if (use_local_qiov) {
-        qemu_iovec_destroy(&local_qiov);
-        qemu_vfree(head_buf);
-        qemu_vfree(tail_buf);
-    }
+    bdrv_padding_destroy(&pad);
 
     return ret;
 }
@@ -1775,44 +1897,34 @@ static int coroutine_fn 
bdrv_co_do_zero_pwritev(BdrvChild *child,
                                                 BdrvTrackedRequest *req)
 {
     BlockDriverState *bs = child->bs;
-    uint8_t *buf = NULL;
     QEMUIOVector local_qiov;
     uint64_t align = bs->bl.request_alignment;
-    unsigned int head_padding_bytes, tail_padding_bytes;
     int ret = 0;
+    bool padding;
+    BdrvRequestPadding pad;
 
-    head_padding_bytes = offset & (align - 1);
-    tail_padding_bytes = (align - (offset + bytes)) & (align - 1);
-
-
-    assert(flags & BDRV_REQ_ZERO_WRITE);
-    if (head_padding_bytes || tail_padding_bytes) {
-        buf = qemu_blockalign(bs, align);
-        qemu_iovec_init_buf(&local_qiov, buf, align);
-    }
-    if (head_padding_bytes) {
-        uint64_t zero_bytes = MIN(bytes, align - head_padding_bytes);
-
-        /* RMW the unaligned part before head. */
+    padding = bdrv_init_padding(bs, offset, bytes, &pad);
+    if (padding) {
         mark_request_serialising(req, align);
         wait_serialising_requests(req);
-        bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_HEAD);
-        ret = bdrv_aligned_preadv(child, req, offset & ~(align - 1), align,
-                                  align, &local_qiov, 0);
-        if (ret < 0) {
-            goto fail;
-        }
-        bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_AFTER_HEAD);
 
-        memset(buf + head_padding_bytes, 0, zero_bytes);
-        ret = bdrv_aligned_pwritev(child, req, offset & ~(align - 1), align,
-                                   align, &local_qiov,
-                                   flags & ~BDRV_REQ_ZERO_WRITE);
-        if (ret < 0) {
-            goto fail;
+        bdrv_padding_rmw_read(child, req, &pad, true);
+
+        if (pad.head || pad.merge_reads) {
+            int64_t aligned_offset = offset & ~(align - 1);
+            int64_t write_bytes = pad.merge_reads ? pad.buf_len : align;
+
+            qemu_iovec_init_buf(&local_qiov, pad.buf, write_bytes);
+            ret = bdrv_aligned_pwritev(child, req, aligned_offset, write_bytes,
+                                       align, &local_qiov,
+                                       flags & ~BDRV_REQ_ZERO_WRITE);
+            if (ret < 0 || pad.merge_reads) {
+                /* Error or all work is done */
+                goto out;
+            }
+            offset += write_bytes - pad.head;
+            bytes -= write_bytes - pad.head;
         }
-        offset += zero_bytes;
-        bytes -= zero_bytes;
     }
 
     assert(!bytes || (offset & (align - 1)) == 0);
@@ -1822,7 +1934,7 @@ static int coroutine_fn bdrv_co_do_zero_pwritev(BdrvChild 
*child,
         ret = bdrv_aligned_pwritev(child, req, offset, aligned_bytes, align,
                                    NULL, flags);
         if (ret < 0) {
-            goto fail;
+            goto out;
         }
         bytes -= aligned_bytes;
         offset += aligned_bytes;
@@ -1830,26 +1942,17 @@ static int coroutine_fn 
bdrv_co_do_zero_pwritev(BdrvChild *child,
 
     assert(!bytes || (offset & (align - 1)) == 0);
     if (bytes) {
-        assert(align == tail_padding_bytes + bytes);
-        /* RMW the unaligned part after tail. */
-        mark_request_serialising(req, align);
-        wait_serialising_requests(req);
-        bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_TAIL);
-        ret = bdrv_aligned_preadv(child, req, offset, align,
-                                  align, &local_qiov, 0);
-        if (ret < 0) {
-            goto fail;
-        }
-        bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_AFTER_TAIL);
+        assert(align == pad.tail + bytes);
 
-        memset(buf, 0, bytes);
+        qemu_iovec_init_buf(&local_qiov, pad.tail_buf, align);
         ret = bdrv_aligned_pwritev(child, req, offset, align, align,
                                    &local_qiov, flags & ~BDRV_REQ_ZERO_WRITE);
     }
-fail:
-    qemu_vfree(buf);
-    return ret;
 
+out:
+    bdrv_padding_destroy(&pad);
+
+    return ret;
 }
 
 /*
@@ -1862,10 +1965,7 @@ int coroutine_fn bdrv_co_pwritev(BdrvChild *child,
     BlockDriverState *bs = child->bs;
     BdrvTrackedRequest req;
     uint64_t align = bs->bl.request_alignment;
-    uint8_t *head_buf = NULL;
-    uint8_t *tail_buf = NULL;
-    QEMUIOVector local_qiov;
-    bool use_local_qiov = false;
+    BdrvRequestPadding pad;
     int ret;
 
     trace_bdrv_co_pwritev(child->bs, offset, bytes, flags);
@@ -1892,86 +1992,21 @@ int coroutine_fn bdrv_co_pwritev(BdrvChild *child,
         goto out;
     }
 
-    if (offset & (align - 1)) {
-        QEMUIOVector head_qiov;
-
+    if (bdrv_pad_request(bs, &qiov, &offset, &bytes, &pad)) {
         mark_request_serialising(&req, align);
         wait_serialising_requests(&req);
-
-        head_buf = qemu_blockalign(bs, align);
-        qemu_iovec_init_buf(&head_qiov, head_buf, align);
-
-        bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_HEAD);
-        ret = bdrv_aligned_preadv(child, &req, offset & ~(align - 1), align,
-                                  align, &head_qiov, 0);
-        if (ret < 0) {
-            goto fail;
-        }
-        bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_AFTER_HEAD);
-
-        qemu_iovec_init(&local_qiov, qiov->niov + 2);
-        qemu_iovec_add(&local_qiov, head_buf, offset & (align - 1));
-        qemu_iovec_concat(&local_qiov, qiov, 0, qiov->size);
-        use_local_qiov = true;
-
-        bytes += offset & (align - 1);
-        offset = offset & ~(align - 1);
-
-        /* We have read the tail already if the request is smaller
-         * than one aligned block.
-         */
-        if (bytes < align) {
-            qemu_iovec_add(&local_qiov, head_buf + bytes, align - bytes);
-            bytes = align;
-        }
-    }
-
-    if ((offset + bytes) & (align - 1)) {
-        QEMUIOVector tail_qiov;
-        size_t tail_bytes;
-        bool waited;
-
-        mark_request_serialising(&req, align);
-        waited = wait_serialising_requests(&req);
-        assert(!waited || !use_local_qiov);
-
-        tail_buf = qemu_blockalign(bs, align);
-        qemu_iovec_init_buf(&tail_qiov, tail_buf, align);
-
-        bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_TAIL);
-        ret = bdrv_aligned_preadv(child, &req, (offset + bytes) & ~(align - 1),
-                                  align, align, &tail_qiov, 0);
-        if (ret < 0) {
-            goto fail;
-        }
-        bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_AFTER_TAIL);
-
-        if (!use_local_qiov) {
-            qemu_iovec_init(&local_qiov, qiov->niov + 1);
-            qemu_iovec_concat(&local_qiov, qiov, 0, qiov->size);
-            use_local_qiov = true;
-        }
-
-        tail_bytes = (offset + bytes) & (align - 1);
-        qemu_iovec_add(&local_qiov, tail_buf + tail_bytes, align - tail_bytes);
-
-        bytes = ROUND_UP(bytes, align);
+        bdrv_padding_rmw_read(child, &req, &pad, false);
     }
 
     ret = bdrv_aligned_pwritev(child, &req, offset, bytes, align,
-                               use_local_qiov ? &local_qiov : qiov,
-                               flags);
+                               qiov, flags);
 
-fail:
+    bdrv_padding_destroy(&pad);
 
-    if (use_local_qiov) {
-        qemu_iovec_destroy(&local_qiov);
-    }
-    qemu_vfree(head_buf);
-    qemu_vfree(tail_buf);
 out:
     tracked_request_end(&req);
     bdrv_dec_in_flight(bs);
+
     return ret;
 }
 
++++++ bundles.tar.xz ++++++
Binary files old/9e06029aea3b2eca1d5261352e695edc1e7d7b8b.bundle and 
new/9e06029aea3b2eca1d5261352e695edc1e7d7b8b.bundle differ

++++++ config.sh ++++++
--- /var/tmp/diff_new_pack.FlPp3h/_old  2019-11-08 15:24:11.658897545 +0100
+++ /var/tmp/diff_new_pack.FlPp3h/_new  2019-11-08 15:24:11.662897549 +0100
@@ -2,16 +2,12 @@
 
 # config.sh:
 
-# The next few VARIABLES may be edited (or uncommented) as required:
+# The next few VARIABLES are to be edited as required:
 
 # The following specifies the upstream tag or commit upon which our patchqueue
 # gets rebased. The special value LATEST may be used to "automatically" track
 # the upstream development tree in the master branch
 GIT_UPSTREAM_COMMIT_ISH=v4.1.0
-if [[ "$GIT_UPSTREAM_COMMIT_ISH" != "LATEST" ]]; then 
-    # This is the git branch used (otherwise it is computed)
-    GIT_BRANCH=opensuse-4.1
-fi
 # WARNING: If transitioning from using LATEST to not, MANUALLY re-set the
 # tarball present. If transitioning TO LATEST, make sure that
 # NEXT_RELEASE_IS_MAJOR is set correctly

++++++ qcow2-Fix-QCOW2_COMPRESSED_SECTOR_MASK.patch ++++++
From: Max Reitz <mre...@redhat.com>
Date: Mon, 28 Oct 2019 17:18:40 +0100
Subject: qcow2: Fix QCOW2_COMPRESSED_SECTOR_MASK

Git-commit: 24552feb6ae2f615b76c2b95394af43901f75046

Masks for L2 table entries should have 64 bit.

Fixes: b6c246942b14d3e0dec46a6c5868ed84e7dbea19
Buglink: https://bugs.launchpad.net/qemu/+bug/1850000
Cc: qemu-sta...@nongnu.org
Signed-off-by: Max Reitz <mre...@redhat.com>
Message-id: 20191028161841.1198-2-mre...@redhat.com
Reviewed-by: Alberto Garcia <be...@igalia.com>
Signed-off-by: Max Reitz <mre...@redhat.com>
Signed-off-by: Bruce Rogers <brog...@suse.com>
---
 block/qcow2.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/block/qcow2.h b/block/qcow2.h
index fc1b0d3c1e1e3110e86f36f0dcd9..359197f89fb9547d861d852cbf68 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -77,7 +77,7 @@
 
 /* Defined in the qcow2 spec (compressed cluster descriptor) */
 #define QCOW2_COMPRESSED_SECTOR_SIZE 512U
-#define QCOW2_COMPRESSED_SECTOR_MASK (~(QCOW2_COMPRESSED_SECTOR_SIZE - 1))
+#define QCOW2_COMPRESSED_SECTOR_MASK (~(QCOW2_COMPRESSED_SECTOR_SIZE - 1ULL))
 
 /* Must be at least 2 to cover COW */
 #define MIN_L2_CACHE_SIZE 2 /* cache entries */
++++++ qcow2-bitmap-Fix-uint64_t-left-shift-ove.patch ++++++
From: Tuguoyi <tu.gu...@h3c.com>
Date: Fri, 1 Nov 2019 07:37:35 +0000
Subject: qcow2-bitmap: Fix uint64_t left-shift overflow

Git-commit: 570542ecb11e04b61ef4b3f4d0965a6915232a88

There are two issues in In check_constraints_on_bitmap(),
1) The sanity check on the granularity will cause uint64_t
integer left-shift overflow when cluster_size is 2M and the
granularity is BIGGER than 32K.
2) The way to calculate image size that the maximum bitmap
supported can map to is a bit incorrect.
This patch fix it by add a helper function to calculate the
number of bytes needed by a normal bitmap in image and compare
it to the maximum bitmap bytes supported by qemu.

Fixes: 5f72826e7fc62167cf3a
Signed-off-by: Guoyi Tu <tu.gu...@h3c.com>
Message-id: 4ba40cd1e7ee4a708b40899952e49...@h3c.com
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsement...@virtuozzo.com>
Cc: qemu-sta...@nongnu.org
Signed-off-by: Max Reitz <mre...@redhat.com>
Signed-off-by: Bruce Rogers <brog...@suse.com>
---
 block/qcow2-bitmap.c | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
index b2487101edec0bdde613c561da89..65034da1c0766603d273c200797d 100644
--- a/block/qcow2-bitmap.c
+++ b/block/qcow2-bitmap.c
@@ -142,6 +142,13 @@ static int check_table_entry(uint64_t entry, int 
cluster_size)
     return 0;
 }
 
+static int64_t get_bitmap_bytes_needed(int64_t len, uint32_t granularity)
+{
+    int64_t num_bits = DIV_ROUND_UP(len, granularity);
+
+    return DIV_ROUND_UP(num_bits, 8);
+}
+
 static int check_constraints_on_bitmap(BlockDriverState *bs,
                                        const char *name,
                                        uint32_t granularity,
@@ -150,6 +157,7 @@ static int check_constraints_on_bitmap(BlockDriverState *bs,
     BDRVQcow2State *s = bs->opaque;
     int granularity_bits = ctz32(granularity);
     int64_t len = bdrv_getlength(bs);
+    int64_t bitmap_bytes;
 
     assert(granularity > 0);
     assert((granularity & (granularity - 1)) == 0);
@@ -171,9 +179,9 @@ static int check_constraints_on_bitmap(BlockDriverState *bs,
         return -EINVAL;
     }
 
-    if ((len > (uint64_t)BME_MAX_PHYS_SIZE << granularity_bits) ||
-        (len > (uint64_t)BME_MAX_TABLE_SIZE * s->cluster_size <<
-               granularity_bits))
+    bitmap_bytes = get_bitmap_bytes_needed(len, granularity);
+    if ((bitmap_bytes > (uint64_t)BME_MAX_PHYS_SIZE) ||
+        (bitmap_bytes > (uint64_t)BME_MAX_TABLE_SIZE * s->cluster_size))
     {
         error_setg(errp, "Too much space will be occupied by the bitmap. "
                    "Use larger granularity");



++++++ update_git.sh ++++++
++++ 720 lines (skipped)
++++ between /work/SRC/openSUSE:Factory/qemu/update_git.sh
++++ and /work/SRC/openSUSE:Factory/.qemu.new.2990/update_git.sh

++++++ util-iov-introduce-qemu_iovec_init_exten.patch ++++++
From: Vladimir Sementsov-Ogievskiy <vsement...@virtuozzo.com>
Date: Tue, 4 Jun 2019 19:15:03 +0300
Subject: util/iov: introduce qemu_iovec_init_extended

Git-commit: d953169d4840f312d3b9a54952f4a7ccfcb3b311

Introduce new initialization API, to create requests with padding. Will
be used in the following patch. New API uses qemu_iovec_init_buf if
resulting io vector has only one element, to avoid extra allocations.
So, we need to update qemu_iovec_destroy to support destroying such
QIOVs.

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsement...@virtuozzo.com>
Acked-by: Stefan Hajnoczi <stefa...@redhat.com>
Message-id: 20190604161514.262241-2-vsement...@virtuozzo.com
Message-Id: <20190604161514.262241-2-vsement...@virtuozzo.com>
Signed-off-by: Stefan Hajnoczi <stefa...@redhat.com>
Signed-off-by: Bruce Rogers <brog...@suse.com>
---
 include/qemu/iov.h |   7 +++
 util/iov.c         | 112 +++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 114 insertions(+), 5 deletions(-)

diff --git a/include/qemu/iov.h b/include/qemu/iov.h
index 48b45987b70ea28879af7989c31f..f3787a0cf768bd0ea1031913a038 100644
--- a/include/qemu/iov.h
+++ b/include/qemu/iov.h
@@ -199,6 +199,13 @@ static inline void *qemu_iovec_buf(QEMUIOVector *qiov)
 
 void qemu_iovec_init(QEMUIOVector *qiov, int alloc_hint);
 void qemu_iovec_init_external(QEMUIOVector *qiov, struct iovec *iov, int niov);
+void qemu_iovec_init_extended(
+        QEMUIOVector *qiov,
+        void *head_buf, size_t head_len,
+        QEMUIOVector *mid_qiov, size_t mid_offset, size_t mid_len,
+        void *tail_buf, size_t tail_len);
+void qemu_iovec_init_slice(QEMUIOVector *qiov, QEMUIOVector *source,
+                           size_t offset, size_t len);
 void qemu_iovec_add(QEMUIOVector *qiov, void *base, size_t len);
 void qemu_iovec_concat(QEMUIOVector *dst,
                        QEMUIOVector *src, size_t soffset, size_t sbytes);
diff --git a/util/iov.c b/util/iov.c
index 74e6ca8ed7298c833e52257923c1..366ff9cdd1dee06c5d62712cb5ef 100644
--- a/util/iov.c
+++ b/util/iov.c
@@ -353,6 +353,103 @@ void qemu_iovec_concat(QEMUIOVector *dst,
     qemu_iovec_concat_iov(dst, src->iov, src->niov, soffset, sbytes);
 }
 
+/*
+ * qiov_find_iov
+ *
+ * Return pointer to iovec structure, where byte at @offset in original vector
+ * @iov exactly is.
+ * Set @remaining_offset to be offset inside that iovec to the same byte.
+ */
+static struct iovec *iov_skip_offset(struct iovec *iov, size_t offset,
+                                     size_t *remaining_offset)
+{
+    while (offset > 0 && offset >= iov->iov_len) {
+        offset -= iov->iov_len;
+        iov++;
+    }
+    *remaining_offset = offset;
+
+    return iov;
+}
+
+/*
+ * qiov_slice
+ *
+ * Find subarray of iovec's, containing requested range. @head would
+ * be offset in first iov (returned by the function), @tail would be
+ * count of extra bytes in last iovec (returned iov + @niov - 1).
+ */
+static struct iovec *qiov_slice(QEMUIOVector *qiov,
+                                size_t offset, size_t len,
+                                size_t *head, size_t *tail, int *niov)
+{
+    struct iovec *iov, *end_iov;
+
+    assert(offset + len <= qiov->size);
+
+    iov = iov_skip_offset(qiov->iov, offset, head);
+    end_iov = iov_skip_offset(iov, *head + len, tail);
+
+    if (*tail > 0) {
+        assert(*tail < end_iov->iov_len);
+        *tail = end_iov->iov_len - *tail;
+        end_iov++;
+    }
+
+    *niov = end_iov - iov;
+
+    return iov;
+}
+
+/*
+ * Compile new iovec, combining @head_buf buffer, sub-qiov of @mid_qiov,
+ * and @tail_buf buffer into new qiov.
+ */
+void qemu_iovec_init_extended(
+        QEMUIOVector *qiov,
+        void *head_buf, size_t head_len,
+        QEMUIOVector *mid_qiov, size_t mid_offset, size_t mid_len,
+        void *tail_buf, size_t tail_len)
+{
+    size_t mid_head, mid_tail;
+    int total_niov, mid_niov = 0;
+    struct iovec *p, *mid_iov;
+
+    if (mid_len) {
+        mid_iov = qiov_slice(mid_qiov, mid_offset, mid_len,
+                             &mid_head, &mid_tail, &mid_niov);
+    }
+
+    total_niov = !!head_len + mid_niov + !!tail_len;
+    if (total_niov == 1) {
+        qemu_iovec_init_buf(qiov, NULL, 0);
+        p = &qiov->local_iov;
+    } else {
+        qiov->niov = qiov->nalloc = total_niov;
+        qiov->size = head_len + mid_len + tail_len;
+        p = qiov->iov = g_new(struct iovec, qiov->niov);
+    }
+
+    if (head_len) {
+        p->iov_base = head_buf;
+        p->iov_len = head_len;
+        p++;
+    }
+
+    if (mid_len) {
+        memcpy(p, mid_iov, mid_niov * sizeof(*p));
+        p[0].iov_base = (uint8_t *)p[0].iov_base + mid_head;
+        p[0].iov_len -= mid_head;
+        p[mid_niov - 1].iov_len -= mid_tail;
+        p += mid_niov;
+    }
+
+    if (tail_len) {
+        p->iov_base = tail_buf;
+        p->iov_len = tail_len;
+    }
+}
+
 /*
  * Check if the contents of the iovecs are all zero
  */
@@ -374,14 +471,19 @@ bool qemu_iovec_is_zero(QEMUIOVector *qiov)
     return true;
 }
 
+void qemu_iovec_init_slice(QEMUIOVector *qiov, QEMUIOVector *source,
+                           size_t offset, size_t len)
+{
+    qemu_iovec_init_extended(qiov, NULL, 0, source, offset, len, NULL, 0);
+}
+
 void qemu_iovec_destroy(QEMUIOVector *qiov)
 {
-    assert(qiov->nalloc != -1);
+    if (qiov->nalloc != -1) {
+        g_free(qiov->iov);
+    }
 
-    qemu_iovec_reset(qiov);
-    g_free(qiov->iov);
-    qiov->nalloc = 0;
-    qiov->iov = NULL;
+    memset(qiov, 0, sizeof(*qiov));
 }
 
 void qemu_iovec_reset(QEMUIOVector *qiov)

Reply via email to