[pve-devel] [PATCH qemu 8/8] cherry-pick stable fixes to avoid crash in IO error scenarios

Fiona Ebner f.ebner at proxmox.com
Fri Sep 29 11:50:33 CEST 2023


Upstream report of the issue [0]. I ran into it too by chance by
filling up my NFS storage with the VM's qcow2 disk.

[0]: https://bugzilla.redhat.com/show_bug.cgi?id=2234374

Signed-off-by: Fiona Ebner <f.ebner at proxmox.com>
---
 ...ile-posix-Clear-bs-bl.zoned-on-error.patch | 87 +++++++++++++++++++
 ...osix-Check-bs-bl.zoned-for-zone-info.patch | 59 +++++++++++++
 ...ix-Fix-zone-update-in-I-O-error-path.patch | 33 +++++++
 ...-Simplify-raw_co_prw-s-out-zone-code.patch | 58 +++++++++++++
 ...k-file-change-locking-default-to-off.patch |  2 +-
 ...le-posix-make-locking-optiono-on-cre.patch | 14 +--
 debian/patches/series                         |  4 +
 7 files changed, 249 insertions(+), 8 deletions(-)
 create mode 100644 debian/patches/extra/0008-file-posix-Clear-bs-bl.zoned-on-error.patch
 create mode 100644 debian/patches/extra/0009-file-posix-Check-bs-bl.zoned-for-zone-info.patch
 create mode 100644 debian/patches/extra/0010-file-posix-Fix-zone-update-in-I-O-error-path.patch
 create mode 100644 debian/patches/extra/0011-file-posix-Simplify-raw_co_prw-s-out-zone-code.patch

diff --git a/debian/patches/extra/0008-file-posix-Clear-bs-bl.zoned-on-error.patch b/debian/patches/extra/0008-file-posix-Clear-bs-bl.zoned-on-error.patch
new file mode 100644
index 0000000..0e3dc3e
--- /dev/null
+++ b/debian/patches/extra/0008-file-posix-Clear-bs-bl.zoned-on-error.patch
@@ -0,0 +1,87 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Hanna Czenczek <hreitz at redhat.com>
+Date: Thu, 24 Aug 2023 17:53:40 +0200
+Subject: [PATCH] file-posix: Clear bs->bl.zoned on error
+
+bs->bl.zoned is what indicates whether the zone information is present
+and valid; it is the only thing that raw_refresh_zoned_limits() sets if
+CONFIG_BLKZONED is not defined, and it is also the only thing that it
+sets if CONFIG_BLKZONED is defined, but there are no zones.
+
+Make sure that it is always set to BLK_Z_NONE if there is an error
+anywhere in raw_refresh_zoned_limits() so that we do not accidentally
+announce zones while our information is incomplete or invalid.
+
+This also fixes a memory leak in the last error path in
+raw_refresh_zoned_limits().
+
+Signed-off-by: Hanna Czenczek <hreitz at redhat.com>
+Message-Id: <20230824155345.109765-2-hreitz at redhat.com>
+Reviewed-by: Sam Li <faithilikerun at gmail.com>
+(cherry-picked from commit 56d1a022a77ea2125564913665eeadf3e303a671)
+Signed-off-by: Fiona Ebner <f.ebner at proxmox.com>
+---
+ block/file-posix.c | 21 ++++++++++++---------
+ 1 file changed, 12 insertions(+), 9 deletions(-)
+
+diff --git a/block/file-posix.c b/block/file-posix.c
+index b16e9c21a1..2b88b9eefa 100644
+--- a/block/file-posix.c
++++ b/block/file-posix.c
+@@ -1412,11 +1412,9 @@ static void raw_refresh_zoned_limits(BlockDriverState *bs, struct stat *st,
+     BlockZoneModel zoned;
+     int ret;
+ 
+-    bs->bl.zoned = BLK_Z_NONE;
+-
+     ret = get_sysfs_zoned_model(st, &zoned);
+     if (ret < 0 || zoned == BLK_Z_NONE) {
+-        return;
++        goto no_zoned;
+     }
+     bs->bl.zoned = zoned;
+ 
+@@ -1437,10 +1435,10 @@ static void raw_refresh_zoned_limits(BlockDriverState *bs, struct stat *st,
+     if (ret < 0) {
+         error_setg_errno(errp, -ret, "Unable to read chunk_sectors "
+                                      "sysfs attribute");
+-        return;
++        goto no_zoned;
+     } else if (!ret) {
+         error_setg(errp, "Read 0 from chunk_sectors sysfs attribute");
+-        return;
++        goto no_zoned;
+     }
+     bs->bl.zone_size = ret << BDRV_SECTOR_BITS;
+ 
+@@ -1448,10 +1446,10 @@ static void raw_refresh_zoned_limits(BlockDriverState *bs, struct stat *st,
+     if (ret < 0) {
+         error_setg_errno(errp, -ret, "Unable to read nr_zones "
+                                      "sysfs attribute");
+-        return;
++        goto no_zoned;
+     } else if (!ret) {
+         error_setg(errp, "Read 0 from nr_zones sysfs attribute");
+-        return;
++        goto no_zoned;
+     }
+     bs->bl.nr_zones = ret;
+ 
+@@ -1472,10 +1470,15 @@ static void raw_refresh_zoned_limits(BlockDriverState *bs, struct stat *st,
+     ret = get_zones_wp(bs, s->fd, 0, bs->bl.nr_zones, 0);
+     if (ret < 0) {
+         error_setg_errno(errp, -ret, "report wps failed");
+-        bs->wps = NULL;
+-        return;
++        goto no_zoned;
+     }
+     qemu_co_mutex_init(&bs->wps->colock);
++    return;
++
++no_zoned:
++    bs->bl.zoned = BLK_Z_NONE;
++    g_free(bs->wps);
++    bs->wps = NULL;
+ }
+ #else /* !defined(CONFIG_BLKZONED) */
+ static void raw_refresh_zoned_limits(BlockDriverState *bs, struct stat *st,
diff --git a/debian/patches/extra/0009-file-posix-Check-bs-bl.zoned-for-zone-info.patch b/debian/patches/extra/0009-file-posix-Check-bs-bl.zoned-for-zone-info.patch
new file mode 100644
index 0000000..a505816
--- /dev/null
+++ b/debian/patches/extra/0009-file-posix-Check-bs-bl.zoned-for-zone-info.patch
@@ -0,0 +1,59 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Hanna Czenczek <hreitz at redhat.com>
+Date: Thu, 24 Aug 2023 17:53:41 +0200
+Subject: [PATCH] file-posix: Check bs->bl.zoned for zone info
+
+Instead of checking bs->wps or bs->bl.zone_size for whether zone
+information is present, check bs->bl.zoned.  That is the flag that
+raw_refresh_zoned_limits() reliably sets to indicate zone support.  If
+it is set to something other than BLK_Z_NONE, other values and objects
+like bs->wps and bs->bl.zone_size must be non-null/zero and valid; if it
+is not, we cannot rely on their validity.
+
+Signed-off-by: Hanna Czenczek <hreitz at redhat.com>
+Message-Id: <20230824155345.109765-3-hreitz at redhat.com>
+Reviewed-by: Sam Li <faithilikerun at gmail.com>
+(cherry-picked from commit 4b5d80f3d02096a9bb1f651f6b3401ba40877159)
+Signed-off-by: Fiona Ebner <f.ebner at proxmox.com>
+---
+ block/file-posix.c | 12 +++++++-----
+ 1 file changed, 7 insertions(+), 5 deletions(-)
+
+diff --git a/block/file-posix.c b/block/file-posix.c
+index 2b88b9eefa..46e22403fe 100644
+--- a/block/file-posix.c
++++ b/block/file-posix.c
+@@ -2455,9 +2455,10 @@ static int coroutine_fn raw_co_prw(BlockDriverState *bs, uint64_t offset,
+     if (fd_open(bs) < 0)
+         return -EIO;
+ #if defined(CONFIG_BLKZONED)
+-    if ((type & (QEMU_AIO_WRITE | QEMU_AIO_ZONE_APPEND)) && bs->wps) {
++    if ((type & (QEMU_AIO_WRITE | QEMU_AIO_ZONE_APPEND)) &&
++        bs->bl.zoned != BLK_Z_NONE) {
+         qemu_co_mutex_lock(&bs->wps->colock);
+-        if (type & QEMU_AIO_ZONE_APPEND && bs->bl.zone_size) {
++        if (type & QEMU_AIO_ZONE_APPEND) {
+             int index = offset / bs->bl.zone_size;
+             offset = bs->wps->wp[index];
+         }
+@@ -2508,8 +2509,8 @@ out:
+ {
+     BlockZoneWps *wps = bs->wps;
+     if (ret == 0) {
+-        if ((type & (QEMU_AIO_WRITE | QEMU_AIO_ZONE_APPEND))
+-            && wps && bs->bl.zone_size) {
++        if ((type & (QEMU_AIO_WRITE | QEMU_AIO_ZONE_APPEND)) &&
++            bs->bl.zoned != BLK_Z_NONE) {
+             uint64_t *wp = &wps->wp[offset / bs->bl.zone_size];
+             if (!BDRV_ZT_IS_CONV(*wp)) {
+                 if (type & QEMU_AIO_ZONE_APPEND) {
+@@ -2529,7 +2530,8 @@ out:
+         }
+     }
+ 
+-    if ((type & (QEMU_AIO_WRITE | QEMU_AIO_ZONE_APPEND)) && wps) {
++    if ((type & (QEMU_AIO_WRITE | QEMU_AIO_ZONE_APPEND)) &&
++        bs->blk.zoned != BLK_Z_NONE) {
+         qemu_co_mutex_unlock(&wps->colock);
+     }
+ }
diff --git a/debian/patches/extra/0010-file-posix-Fix-zone-update-in-I-O-error-path.patch b/debian/patches/extra/0010-file-posix-Fix-zone-update-in-I-O-error-path.patch
new file mode 100644
index 0000000..fb32c62
--- /dev/null
+++ b/debian/patches/extra/0010-file-posix-Fix-zone-update-in-I-O-error-path.patch
@@ -0,0 +1,33 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Hanna Czenczek <hreitz at redhat.com>
+Date: Thu, 24 Aug 2023 17:53:42 +0200
+Subject: [PATCH] file-posix: Fix zone update in I/O error path
+
+We must check that zone information is present before running
+update_zones_wp().
+
+Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=2234374
+Fixes: Coverity CID 1512459
+Signed-off-by: Hanna Czenczek <hreitz at redhat.com>
+Message-Id: <20230824155345.109765-4-hreitz at redhat.com>
+Reviewed-by: Sam Li <faithilikerun at gmail.com>
+(cherry-picked from commit deab5c9a4ed74f76a713008a42527762b30a7e84)
+Signed-off-by: Fiona Ebner <f.ebner at proxmox.com>
+---
+ block/file-posix.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/block/file-posix.c b/block/file-posix.c
+index 46e22403fe..a050682e97 100644
+--- a/block/file-posix.c
++++ b/block/file-posix.c
+@@ -2525,7 +2525,8 @@ out:
+             }
+         }
+     } else {
+-        if (type & (QEMU_AIO_WRITE | QEMU_AIO_ZONE_APPEND)) {
++        if ((type & (QEMU_AIO_WRITE | QEMU_AIO_ZONE_APPEND)) &&
++            bs->bl.zoned != BLK_Z_NONE) {
+             update_zones_wp(bs, s->fd, 0, 1);
+         }
+     }
diff --git a/debian/patches/extra/0011-file-posix-Simplify-raw_co_prw-s-out-zone-code.patch b/debian/patches/extra/0011-file-posix-Simplify-raw_co_prw-s-out-zone-code.patch
new file mode 100644
index 0000000..6164160
--- /dev/null
+++ b/debian/patches/extra/0011-file-posix-Simplify-raw_co_prw-s-out-zone-code.patch
@@ -0,0 +1,58 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Hanna Czenczek <hreitz at redhat.com>
+Date: Thu, 24 Aug 2023 17:53:43 +0200
+Subject: [PATCH] file-posix: Simplify raw_co_prw's 'out' zone code
+
+We duplicate the same condition three times here, pull it out to the top
+level.
+
+Signed-off-by: Hanna Czenczek <hreitz at redhat.com>
+Message-Id: <20230824155345.109765-5-hreitz at redhat.com>
+Reviewed-by: Sam Li <faithilikerun at gmail.com>
+(cherry-picked from commit d31b50a15dd25a560749b25fc40b6484fd1a57b7)
+Signed-off-by: Fiona Ebner <f.ebner at proxmox.com>
+---
+ block/file-posix.c | 18 +++++-------------
+ 1 file changed, 5 insertions(+), 13 deletions(-)
+
+diff --git a/block/file-posix.c b/block/file-posix.c
+index a050682e97..aa89789737 100644
+--- a/block/file-posix.c
++++ b/block/file-posix.c
+@@ -2506,11 +2506,10 @@ static int coroutine_fn raw_co_prw(BlockDriverState *bs, uint64_t offset,
+ 
+ out:
+ #if defined(CONFIG_BLKZONED)
+-{
+-    BlockZoneWps *wps = bs->wps;
+-    if (ret == 0) {
+-        if ((type & (QEMU_AIO_WRITE | QEMU_AIO_ZONE_APPEND)) &&
+-            bs->bl.zoned != BLK_Z_NONE) {
++    if ((type & (QEMU_AIO_WRITE | QEMU_AIO_ZONE_APPEND)) &&
++        bs->bl.zoned != BLK_Z_NONE) {
++        BlockZoneWps *wps = bs->wps;
++        if (ret == 0) {
+             uint64_t *wp = &wps->wp[offset / bs->bl.zone_size];
+             if (!BDRV_ZT_IS_CONV(*wp)) {
+                 if (type & QEMU_AIO_ZONE_APPEND) {
+@@ -2523,19 +2522,12 @@ out:
+                     *wp = offset + bytes;
+                 }
+             }
+-        }
+-    } else {
+-        if ((type & (QEMU_AIO_WRITE | QEMU_AIO_ZONE_APPEND)) &&
+-            bs->bl.zoned != BLK_Z_NONE) {
++        } else {
+             update_zones_wp(bs, s->fd, 0, 1);
+         }
+-    }
+ 
+-    if ((type & (QEMU_AIO_WRITE | QEMU_AIO_ZONE_APPEND)) &&
+-        bs->blk.zoned != BLK_Z_NONE) {
+         qemu_co_mutex_unlock(&wps->colock);
+     }
+-}
+ #endif
+     return ret;
+ }
diff --git a/debian/patches/pve/0001-PVE-Config-block-file-change-locking-default-to-off.patch b/debian/patches/pve/0001-PVE-Config-block-file-change-locking-default-to-off.patch
index 1c3d08c..3d8785c 100644
--- a/debian/patches/pve/0001-PVE-Config-block-file-change-locking-default-to-off.patch
+++ b/debian/patches/pve/0001-PVE-Config-block-file-change-locking-default-to-off.patch
@@ -14,7 +14,7 @@ Signed-off-by: Thomas Lamprecht <t.lamprecht at proxmox.com>
  1 file changed, 2 insertions(+), 2 deletions(-)
 
 diff --git a/block/file-posix.c b/block/file-posix.c
-index b16e9c21a1..26aa0172b4 100644
+index aa89789737..0db366a851 100644
 --- a/block/file-posix.c
 +++ b/block/file-posix.c
 @@ -564,7 +564,7 @@ static QemuOptsList raw_runtime_opts = {
diff --git a/debian/patches/pve/0022-PVE-Up-Config-file-posix-make-locking-optiono-on-cre.patch b/debian/patches/pve/0022-PVE-Up-Config-file-posix-make-locking-optiono-on-cre.patch
index 904f76e..766c4f9 100644
--- a/debian/patches/pve/0022-PVE-Up-Config-file-posix-make-locking-optiono-on-cre.patch
+++ b/debian/patches/pve/0022-PVE-Up-Config-file-posix-make-locking-optiono-on-cre.patch
@@ -13,10 +13,10 @@ Signed-off-by: Thomas Lamprecht <t.lamprecht at proxmox.com>
  2 files changed, 42 insertions(+), 20 deletions(-)
 
 diff --git a/block/file-posix.c b/block/file-posix.c
-index 26aa0172b4..504c6ed316 100644
+index 0db366a851..46f1ee38ae 100644
 --- a/block/file-posix.c
 +++ b/block/file-posix.c
-@@ -2872,6 +2872,7 @@ raw_co_create(BlockdevCreateOptions *options, Error **errp)
+@@ -2870,6 +2870,7 @@ raw_co_create(BlockdevCreateOptions *options, Error **errp)
      int fd;
      uint64_t perm, shared;
      int result = 0;
@@ -24,7 +24,7 @@ index 26aa0172b4..504c6ed316 100644
  
      /* Validate options and set default values */
      assert(options->driver == BLOCKDEV_DRIVER_FILE);
-@@ -2912,19 +2913,22 @@ raw_co_create(BlockdevCreateOptions *options, Error **errp)
+@@ -2910,19 +2911,22 @@ raw_co_create(BlockdevCreateOptions *options, Error **errp)
      perm = BLK_PERM_WRITE | BLK_PERM_RESIZE;
      shared = BLK_PERM_ALL & ~BLK_PERM_RESIZE;
  
@@ -59,7 +59,7 @@ index 26aa0172b4..504c6ed316 100644
      }
  
      /* Clear the file by truncating it to 0 */
-@@ -2978,13 +2982,15 @@ raw_co_create(BlockdevCreateOptions *options, Error **errp)
+@@ -2976,13 +2980,15 @@ raw_co_create(BlockdevCreateOptions *options, Error **errp)
      }
  
  out_unlock:
@@ -82,7 +82,7 @@ index 26aa0172b4..504c6ed316 100644
      }
  
  out_close:
-@@ -3008,6 +3014,7 @@ raw_co_create_opts(BlockDriver *drv, const char *filename,
+@@ -3006,6 +3012,7 @@ raw_co_create_opts(BlockDriver *drv, const char *filename,
      PreallocMode prealloc;
      char *buf = NULL;
      Error *local_err = NULL;
@@ -90,7 +90,7 @@ index 26aa0172b4..504c6ed316 100644
  
      /* Skip file: protocol prefix */
      strstart(filename, "file:", &filename);
-@@ -3030,6 +3037,18 @@ raw_co_create_opts(BlockDriver *drv, const char *filename,
+@@ -3028,6 +3035,18 @@ raw_co_create_opts(BlockDriver *drv, const char *filename,
          return -EINVAL;
      }
  
@@ -109,7 +109,7 @@ index 26aa0172b4..504c6ed316 100644
      options = (BlockdevCreateOptions) {
          .driver     = BLOCKDEV_DRIVER_FILE,
          .u.file     = {
-@@ -3041,6 +3060,8 @@ raw_co_create_opts(BlockDriver *drv, const char *filename,
+@@ -3039,6 +3058,8 @@ raw_co_create_opts(BlockDriver *drv, const char *filename,
              .nocow              = nocow,
              .has_extent_size_hint = has_extent_size_hint,
              .extent_size_hint   = extent_size_hint,
diff --git a/debian/patches/series b/debian/patches/series
index c27c245..71f7e01 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -5,6 +5,10 @@ extra/0004-migration-block-dirty-bitmap-fix-loading-bitmap-when.patch
 extra/0005-hw-ide-reset-cancel-async-DMA-operation-before-reset.patch
 extra/0006-Revert-Revert-graph-lock-Disable-locking-for-now.patch
 extra/0007-migration-states-workaround-snapshot-performance-reg.patch
+extra/0008-file-posix-Clear-bs-bl.zoned-on-error.patch
+extra/0009-file-posix-Check-bs-bl.zoned-for-zone-info.patch
+extra/0010-file-posix-Fix-zone-update-in-I-O-error-path.patch
+extra/0011-file-posix-Simplify-raw_co_prw-s-out-zone-code.patch
 bitmap-mirror/0001-drive-mirror-add-support-for-sync-bitmap-mode-never.patch
 bitmap-mirror/0002-drive-mirror-add-support-for-conditional-and-always-.patch
 bitmap-mirror/0003-mirror-add-check-for-bitmap-mode-without-bitmap.patch
-- 
2.39.2






More information about the pve-devel mailing list