Commit 7c12177aa3 for qemu.org

commit 7c12177aa3c9cf6d0f7262a0cbbe0a4d71416dae
Author: Niklas Cassel <cassel@kernel.org>
Date:   Wed Jun 17 15:36:58 2026 +0200

    file-posix: fix cache.direct=on check for zoned block devices

    For zoned block devices with SWR zones, the order of the writes must be
    maintained to avoid write not at write pointer errors.
    Thus, cache.direct=on must be used to bypass the page cache, since the
    page cache uses write-back caching, where the physical order of the writes
    is not guaranteed.

    There is already a check for cache.direct=on in raw_open_common(),
    however, this check is done before raw_refresh_zoned_limits() has been
    called (which initializes bs->bl.zoned), so it is currently dead code.

    Fix this by moving the check to raw_refresh_zoned_limits(), such that the
    check is done after bs->bl.zoned has been initialized.

    Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
    Reviewed-by: Dmitry Fomichev <dmitry.fomichev@wdc.com>
    Fixes: 774c726ceb2a ("block: add zoned BlockDriver check to block layer")
    Signed-off-by: Niklas Cassel <cassel@kernel.org>
    Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
    Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
    Message-ID: <20260617133658.2022750-1-cassel@kernel.org>
    Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>

diff --git a/block/file-posix.c b/block/file-posix.c
index 3c985da94f..01037f4b5c 100644
--- a/block/file-posix.c
+++ b/block/file-posix.c
@@ -793,18 +793,6 @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
             goto fail;
         }
     }
-#ifdef CONFIG_BLKZONED
-    /*
-     * The kernel page cache does not reliably work for writes to SWR zones
-     * of zoned block device because it can not guarantee the order of writes.
-     */
-    if ((bs->bl.zoned != BLK_Z_NONE) &&
-        (!(s->open_flags & O_DIRECT))) {
-        error_setg(errp, "The driver supports zoned devices, and it requires "
-                         "cache.direct=on, which was not specified.");
-        return -EINVAL; /* No host kernel page cache */
-    }
-#endif

 #ifdef __FreeBSD__
     if (S_ISCHR(st.st_mode)) {
@@ -1455,6 +1443,16 @@ static void raw_refresh_zoned_limits(BlockDriverState *bs, struct stat *st,
     }
     bs->bl.zoned = zoned;

+    /*
+     * The kernel page cache does not reliably work for writes to SWR zones of
+     * zoned block devices because it can not guarantee the order of writes.
+     */
+    if (!(s->open_flags & O_DIRECT)) {
+        error_setg(errp, "The driver supports zoned devices, and it requires "
+                         "cache.direct=on, which was not specified.");
+        goto no_zoned;
+    }
+
     ret = get_sysfs_long_val(st, "max_open_zones");
     if (ret >= 0) {
         bs->bl.max_open_zones = ret;