All of lore.kernel.org
 help / color / mirror / Atom feed
* [PULL 00/38] Block layer patches
@ 2023-01-20 12:25 Kevin Wolf
  2023-01-20 12:25 ` [PULL 01/38] tests/qemu-iotests/312: Mark "quorum" as required driver Kevin Wolf
                   ` (38 more replies)
  0 siblings, 39 replies; 48+ messages in thread
From: Kevin Wolf @ 2023-01-20 12:25 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, peter.maydell, qemu-devel

The following changes since commit 239b8b0699a222fd21da1c5fdeba0a2456085a47:

  Merge tag 'trivial-branch-for-8.0-pull-request' of https://gitlab.com/laurent_vivier/qemu into staging (2023-01-19 15:05:29 +0000)

are available in the Git repository at:

  https://repo.or.cz/qemu/kevin.git tags/for-upstream

for you to fetch changes up to 4711b0a8490827c332b3f9281f689ce9555b7fab:

  qemu-img: Change info key names for protocol nodes (2023-01-20 13:11:01 +0100)

----------------------------------------------------------------
Block layer patches

- qemu-img info: Show protocol-level information
- Move more functions to coroutines
- Make coroutine annotations ready for static analysis
- qemu-img: Fix exit code for errors closing the image
- qcow2 bitmaps: Fix theoretical corruption in error path
- pflash: Only load non-zero parts of backend image to save memory
- Code cleanup and test case improvements

----------------------------------------------------------------
Alberto Faria (2):
      coroutine: annotate coroutine_fn for libclang
      block: Add no_coroutine_fn and coroutine_mixed_fn marker

Emanuele Giuseppe Esposito (14):
      block-coroutine-wrapper: support void functions
      block: Convert bdrv_io_plug() to co_wrapper
      block: Convert bdrv_io_unplug() to co_wrapper
      block: Convert bdrv_is_inserted() to co_wrapper
      block: Rename refresh_total_sectors to bdrv_refresh_total_sectors
      block: Convert bdrv_refresh_total_sectors() to co_wrapper_mixed
      block-backend: use bdrv_getlength instead of blk_getlength
      block: use bdrv_co_refresh_total_sectors when possible
      block: Convert bdrv_get_allocated_file_size() to co_wrapper
      block: Convert bdrv_get_info() to co_wrapper_mixed
      block: Convert bdrv_eject() to co_wrapper
      block: Convert bdrv_lock_medium() to co_wrapper
      block: Convert bdrv_debug_event() to co_wrapper_mixed
      block: Rename bdrv_load/save_vmstate() to bdrv_co_load/save_vmstate()

Hanna Reitz (12):
      block: Improve empty format-specific info dump
      block/file: Add file-specific image info
      block/vmdk: Change extent info type
      block: Split BlockNodeInfo off of ImageInfo
      qemu-img: Use BlockNodeInfo
      block/qapi: Let bdrv_query_image_info() recurse
      block/qapi: Introduce BlockGraphInfo
      block/qapi: Add indentation to bdrv_node_info_dump()
      iotests: Filter child node information
      iotests/106, 214, 308: Read only one size line
      qemu-img: Let info print block graph
      qemu-img: Change info key names for protocol nodes

Kevin Wolf (4):
      qcow2: Fix theoretical corruption in store_bitmap() error path
      qemu-img commit: Report errors while closing the image
      qemu-img bitmap: Report errors while closing the image
      qemu-iotests: Test qemu-img bitmap/commit exit code on error

Paolo Bonzini (2):
      qemu-io: do not reinvent the blk_pwrite_zeroes wheel
      block: remove bdrv_coroutine_enter

Philippe Mathieu-Daudé (1):
      block/nbd: Add missing <qemu/bswap.h> include

Thomas Huth (2):
      tests/qemu-iotests/312: Mark "quorum" as required driver
      tests/qemu-iotests/262: Check for availability of "blkverify" first

Xiang Zheng (1):
      pflash: Only read non-zero parts of backend image

 qapi/block-core.json                               | 123 +++++++-
 include/block/block-common.h                       |  11 +-
 include/block/block-io.h                           |  41 ++-
 include/block/block_int-common.h                   |  26 +-
 include/block/block_int-io.h                       |   5 +-
 include/block/nbd.h                                |   1 +
 include/block/qapi.h                               |  14 +-
 include/qemu/coroutine.h                           |  43 +++
 include/sysemu/block-backend-io.h                  |  31 +-
 block.c                                            |  88 +++---
 block/blkdebug.c                                   |  11 +-
 block/blkio.c                                      |  15 +-
 block/blklogwrites.c                               |   6 +-
 block/blkreplay.c                                  |   6 +-
 block/blkverify.c                                  |   6 +-
 block/block-backend.c                              |  38 +--
 block/commit.c                                     |   4 +-
 block/copy-on-read.c                               |  18 +-
 block/crypto.c                                     |  14 +-
 block/curl.c                                       |  10 +-
 block/file-posix.c                                 | 137 +++++----
 block/file-win32.c                                 |  18 +-
 block/filter-compress.c                            |  20 +-
 block/gluster.c                                    |  23 +-
 block/io.c                                         |  76 ++---
 block/iscsi.c                                      |  17 +-
 block/mirror.c                                     |   6 +-
 block/monitor/block-hmp-cmds.c                     |   2 +-
 block/nbd.c                                        |   8 +-
 block/nfs.c                                        |   4 +-
 block/null.c                                       |  13 +-
 block/nvme.c                                       |  14 +-
 block/preallocate.c                                |  16 +-
 block/qapi.c                                       | 317 ++++++++++++++++-----
 block/qcow.c                                       |   5 +-
 block/qcow2-bitmap.c                               |   5 +-
 block/qcow2-refcount.c                             |   2 +-
 block/qcow2.c                                      |  17 +-
 block/qed.c                                        |  11 +-
 block/quorum.c                                     |   8 +-
 block/raw-format.c                                 |  25 +-
 block/rbd.c                                        |   9 +-
 block/replication.c                                |   6 +-
 block/ssh.c                                        |   4 +-
 block/throttle.c                                   |   6 +-
 block/vdi.c                                        |   7 +-
 block/vhdx.c                                       |   5 +-
 block/vmdk.c                                       |  22 +-
 block/vpc.c                                        |   5 +-
 blockdev.c                                         |   8 +-
 hw/block/block.c                                   |  36 ++-
 hw/scsi/scsi-disk.c                                |   5 +
 qemu-img.c                                         | 100 +++++--
 qemu-io-cmds.c                                     |  62 +---
 tests/unit/test-block-iothread.c                   |   3 +
 scripts/block-coroutine-wrapper.py                 |  20 +-
 tests/qemu-iotests/iotests.py                      |  18 +-
 block/meson.build                                  |   1 +
 tests/qemu-iotests/065                             |   2 +-
 tests/qemu-iotests/106                             |   4 +-
 tests/qemu-iotests/214                             |   6 +-
 tests/qemu-iotests/262                             |   3 +-
 tests/qemu-iotests/302.out                         |   5 +
 tests/qemu-iotests/308                             |   4 +-
 tests/qemu-iotests/312                             |   1 +
 tests/qemu-iotests/common.filter                   |  22 +-
 tests/qemu-iotests/common.rc                       |  22 +-
 tests/qemu-iotests/tests/qemu-img-close-errors     |  95 ++++++
 tests/qemu-iotests/tests/qemu-img-close-errors.out |  23 ++
 69 files changed, 1207 insertions(+), 552 deletions(-)
 create mode 100755 tests/qemu-iotests/tests/qemu-img-close-errors
 create mode 100644 tests/qemu-iotests/tests/qemu-img-close-errors.out



^ permalink raw reply	[flat|nested] 48+ messages in thread

* [PULL 01/38] tests/qemu-iotests/312: Mark "quorum" as required driver
  2023-01-20 12:25 [PULL 00/38] Block layer patches Kevin Wolf
@ 2023-01-20 12:25 ` Kevin Wolf
  2023-01-20 12:25 ` [PULL 02/38] tests/qemu-iotests/262: Check for availability of "blkverify" first Kevin Wolf
                   ` (37 subsequent siblings)
  38 siblings, 0 replies; 48+ messages in thread
From: Kevin Wolf @ 2023-01-20 12:25 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, peter.maydell, qemu-devel

From: Thomas Huth <thuth@redhat.com>

"quorum" is required by iotest 312 - if it is not compiled into the
QEMU binary, the test fails. Thus list "quorum" as required driver
so that the test gets skipped in case it is not available.

Signed-off-by: Thomas Huth <thuth@redhat.com>
Message-Id: <20230104114601.269351-1-thuth@redhat.com>
Reviewed-by: Alberto Garcia <berto@igalia.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 tests/qemu-iotests/312 | 1 +
 1 file changed, 1 insertion(+)

diff --git a/tests/qemu-iotests/312 b/tests/qemu-iotests/312
index 4139745f0e..0d9ea09a31 100755
--- a/tests/qemu-iotests/312
+++ b/tests/qemu-iotests/312
@@ -52,6 +52,7 @@ _supported_fmt qcow2
 _supported_proto file
 _supported_os Linux
 _unsupported_imgopts cluster_size data_file
+_require_drivers quorum
 
 echo
 echo '### Create all images' # three source (quorum), one destination
-- 
2.38.1



^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PULL 02/38] tests/qemu-iotests/262: Check for availability of "blkverify" first
  2023-01-20 12:25 [PULL 00/38] Block layer patches Kevin Wolf
  2023-01-20 12:25 ` [PULL 01/38] tests/qemu-iotests/312: Mark "quorum" as required driver Kevin Wolf
@ 2023-01-20 12:25 ` Kevin Wolf
  2023-01-20 12:25 ` [PULL 03/38] pflash: Only read non-zero parts of backend image Kevin Wolf
                   ` (36 subsequent siblings)
  38 siblings, 0 replies; 48+ messages in thread
From: Kevin Wolf @ 2023-01-20 12:25 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, peter.maydell, qemu-devel

From: Thomas Huth <thuth@redhat.com>

In downstream RHEL builds, we do not have "blkverify" enabled, so
iotest 262 is currently failing there. Thus let's list "blkverify"
as required item so that the test properly gets skipped instead if
"blkverify" is missing.

Signed-off-by: Thomas Huth <thuth@redhat.com>
Message-Id: <20230104112850.261480-1-thuth@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 tests/qemu-iotests/262 | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/tests/qemu-iotests/262 b/tests/qemu-iotests/262
index 2294fd5ecb..a4a92de45a 100755
--- a/tests/qemu-iotests/262
+++ b/tests/qemu-iotests/262
@@ -25,7 +25,8 @@ import iotests
 import os
 
 iotests.script_initialize(supported_fmts=['qcow2'],
-                          supported_platforms=['linux'])
+                          supported_platforms=['linux'],
+                          required_fmts=['blkverify'])
 
 with iotests.FilePath('img') as img_path, \
      iotests.FilePath('mig_fifo') as fifo, \
-- 
2.38.1



^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PULL 03/38] pflash: Only read non-zero parts of backend image
  2023-01-20 12:25 [PULL 00/38] Block layer patches Kevin Wolf
  2023-01-20 12:25 ` [PULL 01/38] tests/qemu-iotests/312: Mark "quorum" as required driver Kevin Wolf
  2023-01-20 12:25 ` [PULL 02/38] tests/qemu-iotests/262: Check for availability of "blkverify" first Kevin Wolf
@ 2023-01-20 12:25 ` Kevin Wolf
  2023-02-06 15:54   ` Cédric Le Goater
  2023-01-20 12:25 ` [PULL 04/38] coroutine: annotate coroutine_fn for libclang Kevin Wolf
                   ` (35 subsequent siblings)
  38 siblings, 1 reply; 48+ messages in thread
From: Kevin Wolf @ 2023-01-20 12:25 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, peter.maydell, qemu-devel

From: Xiang Zheng <zhengxiang9@huawei.com>

Currently we fill the VIRT_FLASH memory space with two 64MB NOR images
when using persistent UEFI variables on virt board. Actually we only use
a very small(non-zero) part of the memory while the rest significant
large(zero) part of memory is wasted.

So this patch checks the block status and only writes the non-zero part
into memory. This requires pflash devices to use sparse files for
backends.

Signed-off-by: Xiang Zheng <zhengxiang9@huawei.com>

[ kraxel: rebased to latest master ]

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Message-Id: <20221220084246.1984871-1-kraxel@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 hw/block/block.c | 36 +++++++++++++++++++++++++++++++++++-
 1 file changed, 35 insertions(+), 1 deletion(-)

diff --git a/hw/block/block.c b/hw/block/block.c
index f9c4fe6767..142ebe4267 100644
--- a/hw/block/block.c
+++ b/hw/block/block.c
@@ -14,6 +14,40 @@
 #include "qapi/error.h"
 #include "qapi/qapi-types-block.h"
 
+/*
+ * Read the non-zeroes parts of @blk into @buf
+ * Reading all of the @blk is expensive if the zeroes parts of @blk
+ * is large enough. Therefore check the block status and only write
+ * the non-zeroes block into @buf.
+ *
+ * Return 0 on success, non-zero on error.
+ */
+static int blk_pread_nonzeroes(BlockBackend *blk, hwaddr size, void *buf)
+{
+    int ret;
+    int64_t bytes, offset = 0;
+    BlockDriverState *bs = blk_bs(blk);
+
+    for (;;) {
+        bytes = MIN(size - offset, BDRV_REQUEST_MAX_SECTORS);
+        if (bytes <= 0) {
+            return 0;
+        }
+        ret = bdrv_block_status(bs, offset, bytes, &bytes, NULL, NULL);
+        if (ret < 0) {
+            return ret;
+        }
+        if (!(ret & BDRV_BLOCK_ZERO)) {
+            ret = bdrv_pread(bs->file, offset, bytes,
+                             (uint8_t *) buf + offset, 0);
+            if (ret < 0) {
+                return ret;
+            }
+        }
+        offset += bytes;
+    }
+}
+
 /*
  * Read the entire contents of @blk into @buf.
  * @blk's contents must be @size bytes, and @size must be at most
@@ -53,7 +87,7 @@ bool blk_check_size_and_read_all(BlockBackend *blk, void *buf, hwaddr size,
      * block device and read only on demand.
      */
     assert(size <= BDRV_REQUEST_MAX_BYTES);
-    ret = blk_pread(blk, 0, size, buf, 0);
+    ret = blk_pread_nonzeroes(blk, size, buf);
     if (ret < 0) {
         error_setg_errno(errp, -ret, "can't read block backend");
         return false;
-- 
2.38.1



^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PULL 04/38] coroutine: annotate coroutine_fn for libclang
  2023-01-20 12:25 [PULL 00/38] Block layer patches Kevin Wolf
                   ` (2 preceding siblings ...)
  2023-01-20 12:25 ` [PULL 03/38] pflash: Only read non-zero parts of backend image Kevin Wolf
@ 2023-01-20 12:25 ` Kevin Wolf
  2023-01-20 12:26 ` [PULL 05/38] block: Add no_coroutine_fn and coroutine_mixed_fn marker Kevin Wolf
                   ` (34 subsequent siblings)
  38 siblings, 0 replies; 48+ messages in thread
From: Kevin Wolf @ 2023-01-20 12:25 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, peter.maydell, qemu-devel

From: Alberto Faria <afaria@redhat.com>

Clang has a generic __annotate__ attribute that can be used by
static analyzers to understand properties of functions and
analyze the control flow.  Furthermore, unlike TSA annotations, the
__annotate__ attribute applies to function pointers as well.

As a first step towards static analysis of coroutine_fn markers,
attach the attribute to the marker when compiling with clang.

Signed-off-by: Alberto Faria <afaria@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20221216110758.559947-2-pbonzini@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 include/qemu/coroutine.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/include/qemu/coroutine.h b/include/qemu/coroutine.h
index 89650a2d7f..b0c97f6fb7 100644
--- a/include/qemu/coroutine.h
+++ b/include/qemu/coroutine.h
@@ -42,7 +42,11 @@
  *       ....
  *   }
  */
+#ifdef __clang__
+#define coroutine_fn __attribute__((__annotate__("coroutine_fn")))
+#else
 #define coroutine_fn
+#endif
 
 typedef struct Coroutine Coroutine;
 
-- 
2.38.1



^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PULL 05/38] block: Add no_coroutine_fn and coroutine_mixed_fn marker
  2023-01-20 12:25 [PULL 00/38] Block layer patches Kevin Wolf
                   ` (3 preceding siblings ...)
  2023-01-20 12:25 ` [PULL 04/38] coroutine: annotate coroutine_fn for libclang Kevin Wolf
@ 2023-01-20 12:26 ` Kevin Wolf
  2023-01-20 12:26 ` [PULL 06/38] qemu-io: do not reinvent the blk_pwrite_zeroes wheel Kevin Wolf
                   ` (33 subsequent siblings)
  38 siblings, 0 replies; 48+ messages in thread
From: Kevin Wolf @ 2023-01-20 12:26 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, peter.maydell, qemu-devel

From: Alberto Faria <afaria@redhat.com>

Add more annotations to functions, describing valid and invalid
calls from coroutine to non-coroutine context.

When applied to a function, no_coroutine_fn advertises that it should
not be called from coroutine_fn functions.  This can be because the
function blocks or, in the case of generated_co_wrapper, to enforce
that coroutine_fn functions directly call the coroutine_fn that backs
the generated_co_wrapper.

coroutine_mixed_fn instead is for function that can be called in
both coroutine and non-coroutine context, but will suspend when
called in coroutine context.  Annotating them is a first step
towards enforcing that non-annotated functions are absolutely
not going to suspend.

These can be used for example with the vrc tool:

    # find functions that *really* cannot be called from no_coroutine_fn
    (vrc) load --loader clang libblock.fa.p/meson-generated_.._block_block-gen.c.o
    (vrc) paths [no_coroutine_fn,!coroutine_mixed_fn]
    bdrv_remove_persistent_dirty_bitmap
    bdrv_create
    bdrv_can_store_new_dirty_bitmap

    # find how coroutine_fns end up calling a mixed function
    (vrc) load --loader clang --force libblock.fa.p/*.c.o
    (vrc) paths [coroutine_fn] [!no_coroutine_fn]* [coroutine_mixed_fn]
    ...
    bdrv_pread <- vhdx_log_write <- vhdx_log_write_and_flush <- vhdx_co_writev
    ...

Signed-off-by: Alberto Faria <afaria@redhat.com>
[Rebase, add coroutine_mixed_fn. - Paolo]
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20221216110758.559947-3-pbonzini@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 include/block/block-common.h | 11 ++++++----
 include/qemu/coroutine.h     | 39 ++++++++++++++++++++++++++++++++++++
 2 files changed, 46 insertions(+), 4 deletions(-)

diff --git a/include/block/block-common.h b/include/block/block-common.h
index 4749c46a5e..cce79bd001 100644
--- a/include/block/block-common.h
+++ b/include/block/block-common.h
@@ -50,11 +50,14 @@
  * - co_wrapper_mixed_bdrv_rdlock are co_wrapper_mixed functions but
  *   automatically take and release the graph rdlock when creating a new
  *   coroutine.
+ *
+ * These functions should not be called from a coroutine_fn; instead,
+ * call the wrapped function directly.
  */
-#define co_wrapper
-#define co_wrapper_mixed
-#define co_wrapper_bdrv_rdlock
-#define co_wrapper_mixed_bdrv_rdlock
+#define co_wrapper                     no_coroutine_fn
+#define co_wrapper_mixed               no_coroutine_fn coroutine_mixed_fn
+#define co_wrapper_bdrv_rdlock         no_coroutine_fn
+#define co_wrapper_mixed_bdrv_rdlock   no_coroutine_fn coroutine_mixed_fn
 
 #include "block/dirty-bitmap.h"
 #include "block/blockjob.h"
diff --git a/include/qemu/coroutine.h b/include/qemu/coroutine.h
index b0c97f6fb7..569d7a5331 100644
--- a/include/qemu/coroutine.h
+++ b/include/qemu/coroutine.h
@@ -48,6 +48,45 @@
 #define coroutine_fn
 #endif
 
+/**
+ * Mark a function that can suspend when executed in coroutine context,
+ * but can handle running in non-coroutine context too.
+ */
+#ifdef __clang__
+#define coroutine_mixed_fn __attribute__((__annotate__("coroutine_mixed_fn")))
+#else
+#define coroutine_mixed_fn
+#endif
+
+/**
+ * Mark a function that should not be called from a coroutine context.
+ * Usually there will be an analogous, coroutine_fn function that should
+ * be used instead.
+ *
+ * When the function is also marked as coroutine_mixed_fn, the function should
+ * only be called if the caller does not know whether it is in coroutine
+ * context.
+ *
+ * Functions that are only no_coroutine_fn, on the other hand, should not
+ * be called from within coroutines at all.  This for example includes
+ * functions that block.
+ *
+ * In the future it would be nice to enable compiler or static checker
+ * support for catching such errors.  This annotation is the first step
+ * towards this, and in the meantime it serves as documentation.
+ *
+ * For example:
+ *
+ *   static void no_coroutine_fn foo(void) {
+ *       ....
+ *   }
+ */
+#ifdef __clang__
+#define no_coroutine_fn __attribute__((__annotate__("no_coroutine_fn")))
+#else
+#define no_coroutine_fn
+#endif
+
 typedef struct Coroutine Coroutine;
 
 /**
-- 
2.38.1



^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PULL 06/38] qemu-io: do not reinvent the blk_pwrite_zeroes wheel
  2023-01-20 12:25 [PULL 00/38] Block layer patches Kevin Wolf
                   ` (4 preceding siblings ...)
  2023-01-20 12:26 ` [PULL 05/38] block: Add no_coroutine_fn and coroutine_mixed_fn marker Kevin Wolf
@ 2023-01-20 12:26 ` Kevin Wolf
  2023-01-20 12:26 ` [PULL 07/38] block: remove bdrv_coroutine_enter Kevin Wolf
                   ` (32 subsequent siblings)
  38 siblings, 0 replies; 48+ messages in thread
From: Kevin Wolf @ 2023-01-20 12:26 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, peter.maydell, qemu-devel

From: Paolo Bonzini <pbonzini@redhat.com>

qemu-io's do_co_pwrite_zeroes is reinventing the coroutine wrapper
blk_pwrite_zeroes.  Just use the real thing directly.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20221215130225.476477-1-pbonzini@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 qemu-io-cmds.c | 57 +++++++++-----------------------------------------
 1 file changed, 10 insertions(+), 47 deletions(-)

diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
index 952dc940f1..7a412d6512 100644
--- a/qemu-io-cmds.c
+++ b/qemu-io-cmds.c
@@ -572,54 +572,17 @@ static int do_pwrite(BlockBackend *blk, char *buf, int64_t offset,
     return 1;
 }
 
-typedef struct {
-    BlockBackend *blk;
-    int64_t offset;
-    int64_t bytes;
-    int64_t *total;
-    int flags;
-    int ret;
-    bool done;
-} CoWriteZeroes;
-
-static void coroutine_fn co_pwrite_zeroes_entry(void *opaque)
-{
-    CoWriteZeroes *data = opaque;
-
-    data->ret = blk_co_pwrite_zeroes(data->blk, data->offset, data->bytes,
-                                     data->flags);
-    data->done = true;
-    if (data->ret < 0) {
-        *data->total = data->ret;
-        return;
-    }
-
-    *data->total = data->bytes;
-}
-
-static int do_co_pwrite_zeroes(BlockBackend *blk, int64_t offset,
+static int do_pwrite_zeroes(BlockBackend *blk, int64_t offset,
                                int64_t bytes, int flags, int64_t *total)
 {
-    Coroutine *co;
-    CoWriteZeroes data = {
-        .blk    = blk,
-        .offset = offset,
-        .bytes  = bytes,
-        .total  = total,
-        .flags  = flags,
-        .done   = false,
-    };
-
-    co = qemu_coroutine_create(co_pwrite_zeroes_entry, &data);
-    bdrv_coroutine_enter(blk_bs(blk), co);
-    while (!data.done) {
-        aio_poll(blk_get_aio_context(blk), true);
-    }
-    if (data.ret < 0) {
-        return data.ret;
-    } else {
-        return 1;
+    int ret = blk_pwrite_zeroes(blk, offset, bytes,
+                                flags | BDRV_REQ_ZERO_WRITE);
+
+    if (ret < 0) {
+        return ret;
     }
+    *total = bytes;
+    return 1;
 }
 
 static int do_write_compressed(BlockBackend *blk, char *buf, int64_t offset,
@@ -1042,7 +1005,7 @@ static void write_help(void)
 " -C, -- report statistics in a machine parsable format\n"
 " -q, -- quiet mode, do not show I/O statistics\n"
 " -u, -- with -z, allow unmapping\n"
-" -z, -- write zeroes using blk_co_pwrite_zeroes\n"
+" -z, -- write zeroes using blk_pwrite_zeroes\n"
 "\n");
 }
 
@@ -1199,7 +1162,7 @@ static int write_f(BlockBackend *blk, int argc, char **argv)
     if (bflag) {
         ret = do_save_vmstate(blk, buf, offset, count, &total);
     } else if (zflag) {
-        ret = do_co_pwrite_zeroes(blk, offset, count, flags, &total);
+        ret = do_pwrite_zeroes(blk, offset, count, flags, &total);
     } else if (cflag) {
         ret = do_write_compressed(blk, buf, offset, count, &total);
     } else {
-- 
2.38.1



^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PULL 07/38] block: remove bdrv_coroutine_enter
  2023-01-20 12:25 [PULL 00/38] Block layer patches Kevin Wolf
                   ` (5 preceding siblings ...)
  2023-01-20 12:26 ` [PULL 06/38] qemu-io: do not reinvent the blk_pwrite_zeroes wheel Kevin Wolf
@ 2023-01-20 12:26 ` Kevin Wolf
  2023-01-20 12:26 ` [PULL 08/38] qcow2: Fix theoretical corruption in store_bitmap() error path Kevin Wolf
                   ` (31 subsequent siblings)
  38 siblings, 0 replies; 48+ messages in thread
From: Kevin Wolf @ 2023-01-20 12:26 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, peter.maydell, qemu-devel

From: Paolo Bonzini <pbonzini@redhat.com>

It has only one caller---inline it and remove the function.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20221215130225.476477-2-pbonzini@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 include/block/block-io.h | 5 -----
 block.c                  | 6 ------
 block/block-backend.c    | 2 +-
 3 files changed, 1 insertion(+), 12 deletions(-)

diff --git a/include/block/block-io.h b/include/block/block-io.h
index 2ed6214909..1fa717a545 100644
--- a/include/block/block-io.h
+++ b/include/block/block-io.h
@@ -210,11 +210,6 @@ AioContext *coroutine_fn bdrv_co_enter(BlockDriverState *bs);
  */
 void coroutine_fn bdrv_co_leave(BlockDriverState *bs, AioContext *old_ctx);
 
-/**
- * Transfer control to @co in the aio context of @bs
- */
-void bdrv_coroutine_enter(BlockDriverState *bs, Coroutine *co);
-
 AioContext *child_of_bds_get_parent_aio_context(BdrvChild *c);
 
 void bdrv_io_plug(BlockDriverState *bs);
diff --git a/block.c b/block.c
index 9c2ac757e4..3f2bd12857 100644
--- a/block.c
+++ b/block.c
@@ -7177,12 +7177,6 @@ void coroutine_fn bdrv_co_unlock(BlockDriverState *bs)
     }
 }
 
-void bdrv_coroutine_enter(BlockDriverState *bs, Coroutine *co)
-{
-    IO_CODE();
-    aio_co_enter(bdrv_get_aio_context(bs), co);
-}
-
 static void bdrv_do_remove_aio_context_notifier(BdrvAioNotifier *ban)
 {
     GLOBAL_STATE_CODE();
diff --git a/block/block-backend.c b/block/block-backend.c
index ba7bf1d6bc..8fbb787f41 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -1555,7 +1555,7 @@ static BlockAIOCB *blk_aio_prwv(BlockBackend *blk, int64_t offset,
     acb->has_returned = false;
 
     co = qemu_coroutine_create(co_entry, acb);
-    bdrv_coroutine_enter(blk_bs(blk), co);
+    aio_co_enter(blk_get_aio_context(blk), co);
 
     acb->has_returned = true;
     if (acb->rwco.ret != NOT_DONE) {
-- 
2.38.1



^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PULL 08/38] qcow2: Fix theoretical corruption in store_bitmap() error path
  2023-01-20 12:25 [PULL 00/38] Block layer patches Kevin Wolf
                   ` (6 preceding siblings ...)
  2023-01-20 12:26 ` [PULL 07/38] block: remove bdrv_coroutine_enter Kevin Wolf
@ 2023-01-20 12:26 ` Kevin Wolf
  2023-01-20 12:26 ` [PULL 09/38] qemu-img commit: Report errors while closing the image Kevin Wolf
                   ` (30 subsequent siblings)
  38 siblings, 0 replies; 48+ messages in thread
From: Kevin Wolf @ 2023-01-20 12:26 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, peter.maydell, qemu-devel

In order to write the bitmap table to the image file, it is converted to
big endian. If the write fails, it is passed to clear_bitmap_table() to
free all of the clusters it had allocated before. However, if we don't
convert it back to native endianness first, we'll free things at a wrong
offset.

In practical terms, the offsets will be so high that we won't actually
free any allocated clusters, but just run into an error, but in theory
this can cause image corruption.

Cc: qemu-stable@nongnu.org
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Message-Id: <20230112191454.169353-2-kwolf@redhat.com>
Reviewed-by: Hanna Czenczek <hreitz@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block/qcow2-bitmap.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
index bcad567c0c..3dff99ba06 100644
--- a/block/qcow2-bitmap.c
+++ b/block/qcow2-bitmap.c
@@ -115,7 +115,7 @@ static int update_header_sync(BlockDriverState *bs)
     return bdrv_flush(bs->file->bs);
 }
 
-static inline void bitmap_table_to_be(uint64_t *bitmap_table, size_t size)
+static inline void bitmap_table_bswap_be(uint64_t *bitmap_table, size_t size)
 {
     size_t i;
 
@@ -1401,9 +1401,10 @@ static int store_bitmap(BlockDriverState *bs, Qcow2Bitmap *bm, Error **errp)
         goto fail;
     }
 
-    bitmap_table_to_be(tb, tb_size);
+    bitmap_table_bswap_be(tb, tb_size);
     ret = bdrv_pwrite(bs->file, tb_offset, tb_size * sizeof(tb[0]), tb, 0);
     if (ret < 0) {
+        bitmap_table_bswap_be(tb, tb_size);
         error_setg_errno(errp, -ret, "Failed to write bitmap '%s' to file",
                          bm_name);
         goto fail;
-- 
2.38.1



^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PULL 09/38] qemu-img commit: Report errors while closing the image
  2023-01-20 12:25 [PULL 00/38] Block layer patches Kevin Wolf
                   ` (7 preceding siblings ...)
  2023-01-20 12:26 ` [PULL 08/38] qcow2: Fix theoretical corruption in store_bitmap() error path Kevin Wolf
@ 2023-01-20 12:26 ` Kevin Wolf
  2023-01-20 12:26 ` [PULL 10/38] qemu-img bitmap: " Kevin Wolf
                   ` (29 subsequent siblings)
  38 siblings, 0 replies; 48+ messages in thread
From: Kevin Wolf @ 2023-01-20 12:26 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, peter.maydell, qemu-devel

blk_unref() can't report any errors that happen while closing the image.
For example, if qcow2 hits an -ENOSPC error while writing out dirty
bitmaps when it's closed, it prints error messages to stderr, but
'qemu-img commit' won't see any error return value and will therefore
look successful with exit code 0.

In order to fix this, manually inactivate the image first before calling
blk_unref(). This already performs the operations that would be most
likely to fail while closing the image, but it can still return errors.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Message-Id: <20230112191454.169353-3-kwolf@redhat.com>
Reviewed-by: Hanna Czenczek <hreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 qemu-img.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/qemu-img.c b/qemu-img.c
index 439d8de1e3..22d6ecefd5 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -449,6 +449,11 @@ static BlockBackend *img_open(bool image_opts,
         blk = img_open_file(filename, NULL, fmt, flags, writethrough, quiet,
                             force_share);
     }
+
+    if (blk) {
+        blk_set_force_allow_inactivate(blk);
+    }
+
     return blk;
 }
 
@@ -1119,6 +1124,14 @@ unref_backing:
 done:
     qemu_progress_end();
 
+    /*
+     * Manually inactivate the image first because this way we can know whether
+     * an error occurred. blk_unref() doesn't tell us about failures.
+     */
+    ret = bdrv_inactivate_all();
+    if (ret < 0 && !local_err) {
+        error_setg_errno(&local_err, -ret, "Error while closing the image");
+    }
     blk_unref(blk);
 
     if (local_err) {
-- 
2.38.1



^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PULL 10/38] qemu-img bitmap: Report errors while closing the image
  2023-01-20 12:25 [PULL 00/38] Block layer patches Kevin Wolf
                   ` (8 preceding siblings ...)
  2023-01-20 12:26 ` [PULL 09/38] qemu-img commit: Report errors while closing the image Kevin Wolf
@ 2023-01-20 12:26 ` Kevin Wolf
  2023-01-20 12:26 ` [PULL 11/38] qemu-iotests: Test qemu-img bitmap/commit exit code on error Kevin Wolf
                   ` (28 subsequent siblings)
  38 siblings, 0 replies; 48+ messages in thread
From: Kevin Wolf @ 2023-01-20 12:26 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, peter.maydell, qemu-devel

blk_unref() can't report any errors that happen while closing the image.
For example, if qcow2 hits an -ENOSPC error while writing out dirty
bitmaps when it's closed, it prints error messages to stderr, but
'qemu-img bitmap' won't see any error return value and will therefore
look successful with exit code 0.

In order to fix this, manually inactivate the image first before calling
blk_unref(). This already performs the operations that would be most
likely to fail while closing the image, but it can still return errors.

Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1330
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Message-Id: <20230112191454.169353-4-kwolf@redhat.com>
Reviewed-by: Hanna Czenczek <hreitz@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 qemu-img.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/qemu-img.c b/qemu-img.c
index 22d6ecefd5..c3671d4890 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -4645,6 +4645,7 @@ static int img_bitmap(int argc, char **argv)
     QSIMPLEQ_HEAD(, ImgBitmapAction) actions;
     ImgBitmapAction *act, *act_next;
     const char *op;
+    int inactivate_ret;
 
     QSIMPLEQ_INIT(&actions);
 
@@ -4829,6 +4830,16 @@ static int img_bitmap(int argc, char **argv)
     ret = 0;
 
  out:
+    /*
+     * Manually inactivate the images first because this way we can know whether
+     * an error occurred. blk_unref() doesn't tell us about failures.
+     */
+    inactivate_ret = bdrv_inactivate_all();
+    if (inactivate_ret < 0) {
+        error_report("Error while closing the image: %s", strerror(-inactivate_ret));
+        ret = 1;
+    }
+
     blk_unref(src);
     blk_unref(blk);
     qemu_opts_del(opts);
-- 
2.38.1



^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PULL 11/38] qemu-iotests: Test qemu-img bitmap/commit exit code on error
  2023-01-20 12:25 [PULL 00/38] Block layer patches Kevin Wolf
                   ` (9 preceding siblings ...)
  2023-01-20 12:26 ` [PULL 10/38] qemu-img bitmap: " Kevin Wolf
@ 2023-01-20 12:26 ` Kevin Wolf
  2023-01-20 12:26 ` [PULL 12/38] block-coroutine-wrapper: support void functions Kevin Wolf
                   ` (27 subsequent siblings)
  38 siblings, 0 replies; 48+ messages in thread
From: Kevin Wolf @ 2023-01-20 12:26 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, peter.maydell, qemu-devel

This tests that when an error happens while writing back bitmaps to the
image file in qcow2_inactivate(), 'qemu-img bitmap/commit' actually
return an error value in their exit code instead of making the operation
look successful to scripts.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Message-Id: <20230112191454.169353-5-kwolf@redhat.com>
Reviewed-by: Hanna Czenczek <hreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 .../qemu-iotests/tests/qemu-img-close-errors  | 95 +++++++++++++++++++
 .../tests/qemu-img-close-errors.out           | 23 +++++
 2 files changed, 118 insertions(+)
 create mode 100755 tests/qemu-iotests/tests/qemu-img-close-errors
 create mode 100644 tests/qemu-iotests/tests/qemu-img-close-errors.out

diff --git a/tests/qemu-iotests/tests/qemu-img-close-errors b/tests/qemu-iotests/tests/qemu-img-close-errors
new file mode 100755
index 0000000000..662f726e5d
--- /dev/null
+++ b/tests/qemu-iotests/tests/qemu-img-close-errors
@@ -0,0 +1,95 @@
+#!/usr/bin/env bash
+# group: rw auto quick
+#
+# Check that errors while closing the image, in particular writing back dirty
+# bitmaps, is correctly reported with a failing qemu-img exit code.
+#
+# Copyright (C) 2023 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+# creator
+owner=kwolf@redhat.com
+
+seq="$(basename $0)"
+echo "QA output created by $seq"
+
+status=1	# failure is the default!
+
+_cleanup()
+{
+    _cleanup_test_img
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+cd ..
+. ./common.rc
+. ./common.filter
+
+_supported_fmt qcow2
+_supported_proto generic
+
+size=1G
+
+# The error we are going to use is ENOSPC. Depending on how many bitmaps we
+# create in the backing file (and therefore increase the used up space), we get
+# failures in different places. With a low number, only merging the bitmap
+# fails, whereas with a higher number, already 'qemu-img commit' fails.
+for max_bitmap in 6 7; do
+    echo
+    echo "=== Test with $max_bitmap bitmaps ==="
+
+    TEST_IMG="$TEST_IMG.base" _make_test_img -q $size
+    for i in $(seq 1 $max_bitmap); do
+        $QEMU_IMG bitmap --add "$TEST_IMG.base" "stale-bitmap-$i"
+    done
+
+    # Simulate a block device of 128 MB by resizing the image file accordingly
+    # and then enforcing the size with the raw driver
+    truncate "$TEST_IMG.base" --size 128M
+    BASE_JSON='json:{
+        "driver": "qcow2",
+        "file": {
+            "driver": "raw",
+            "size": 134217728,
+            "file": {
+                "driver": "file",
+                "filename":"'"$TEST_IMG.base"'"
+            }
+        }
+    }'
+
+    _make_test_img -q -b "$BASE_JSON" -F $IMGFMT
+    $QEMU_IMG bitmap --add "$TEST_IMG" "good-bitmap"
+
+    $QEMU_IO -c 'write 0 126m' "$TEST_IMG" | _filter_qemu_io
+
+    $QEMU_IMG commit -d "$TEST_IMG" 2>&1 | _filter_generated_node_ids
+    echo "qemu-img commit exit code: ${PIPESTATUS[0]}"
+
+    $QEMU_IMG bitmap --add "$BASE_JSON" "good-bitmap"
+    echo "qemu-img bitmap --add exit code: $?"
+
+    $QEMU_IMG bitmap --merge "good-bitmap" -b "$TEST_IMG" "$BASE_JSON" \
+        "good-bitmap" 2>&1 | _filter_generated_node_ids
+    echo "qemu-img bitmap --merge exit code:  ${PIPESTATUS[0]}"
+done
+
+# success, all done
+echo "*** done"
+rm -f $seq.full
+status=0
+
diff --git a/tests/qemu-iotests/tests/qemu-img-close-errors.out b/tests/qemu-iotests/tests/qemu-img-close-errors.out
new file mode 100644
index 0000000000..1bfe88f176
--- /dev/null
+++ b/tests/qemu-iotests/tests/qemu-img-close-errors.out
@@ -0,0 +1,23 @@
+QA output created by qemu-img-close-errors
+
+=== Test with 6 bitmaps ===
+wrote 132120576/132120576 bytes at offset 0
+126 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+Image committed.
+qemu-img commit exit code: 0
+qemu-img bitmap --add exit code: 0
+qemu-img: Lost persistent bitmaps during inactivation of node 'NODE_NAME': Failed to write bitmap 'good-bitmap' to file: No space left on device
+qemu-img: Error while closing the image: Invalid argument
+qemu-img: Lost persistent bitmaps during inactivation of node 'NODE_NAME': Failed to write bitmap 'good-bitmap' to file: No space left on device
+qemu-img bitmap --merge exit code:  1
+
+=== Test with 7 bitmaps ===
+wrote 132120576/132120576 bytes at offset 0
+126 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-img: Lost persistent bitmaps during inactivation of node 'NODE_NAME': Failed to write bitmap 'stale-bitmap-7' to file: No space left on device
+qemu-img: Lost persistent bitmaps during inactivation of node 'NODE_NAME': Failed to write bitmap 'stale-bitmap-7' to file: No space left on device
+qemu-img: Error while closing the image: Invalid argument
+qemu-img commit exit code: 1
+qemu-img bitmap --add exit code: 0
+qemu-img bitmap --merge exit code:  0
+*** done
-- 
2.38.1



^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PULL 12/38] block-coroutine-wrapper: support void functions
  2023-01-20 12:25 [PULL 00/38] Block layer patches Kevin Wolf
                   ` (10 preceding siblings ...)
  2023-01-20 12:26 ` [PULL 11/38] qemu-iotests: Test qemu-img bitmap/commit exit code on error Kevin Wolf
@ 2023-01-20 12:26 ` Kevin Wolf
  2023-01-20 12:26 ` [PULL 13/38] block: Convert bdrv_io_plug() to co_wrapper Kevin Wolf
                   ` (26 subsequent siblings)
  38 siblings, 0 replies; 48+ messages in thread
From: Kevin Wolf @ 2023-01-20 12:26 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, peter.maydell, qemu-devel

From: Emanuele Giuseppe Esposito <eesposit@redhat.com>

Just omit the various 'return' when the return type is void.

Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Message-Id: <20230113204212.359076-2-kwolf@redhat.com>
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 scripts/block-coroutine-wrapper.py | 20 +++++++++++++++-----
 1 file changed, 15 insertions(+), 5 deletions(-)

diff --git a/scripts/block-coroutine-wrapper.py b/scripts/block-coroutine-wrapper.py
index 6e087fa0b7..0c5d7782b1 100644
--- a/scripts/block-coroutine-wrapper.py
+++ b/scripts/block-coroutine-wrapper.py
@@ -85,6 +85,16 @@ def __init__(self, return_type: str, name: str, args: str,
             ctx = 'qemu_get_aio_context()'
         self.ctx = ctx
 
+        self.get_result = 's->ret = '
+        self.ret = 'return s.ret;'
+        self.co_ret = 'return '
+        self.return_field = self.return_type + " ret;"
+        if self.return_type == 'void':
+            self.get_result = ''
+            self.ret = ''
+            self.co_ret = ''
+            self.return_field = ''
+
     def gen_list(self, format: str) -> str:
         return ', '.join(format.format_map(arg.__dict__) for arg in self.args)
 
@@ -131,7 +141,7 @@ def create_mixed_wrapper(func: FuncDecl) -> str:
 {{
     if (qemu_in_coroutine()) {{
         {graph_assume_lock}
-        return {name}({ func.gen_list('{name}') });
+        {func.co_ret}{name}({ func.gen_list('{name}') });
     }} else {{
         {struct_name} s = {{
             .poll_state.ctx = {func.ctx},
@@ -143,7 +153,7 @@ def create_mixed_wrapper(func: FuncDecl) -> str:
         s.poll_state.co = qemu_coroutine_create({name}_entry, &s);
 
         bdrv_poll_co(&s.poll_state);
-        return s.ret;
+        {func.ret}
     }}
 }}"""
 
@@ -168,7 +178,7 @@ def create_co_wrapper(func: FuncDecl) -> str:
     s.poll_state.co = qemu_coroutine_create({name}_entry, &s);
 
     bdrv_poll_co(&s.poll_state);
-    return s.ret;
+    {func.ret}
 }}"""
 
 
@@ -195,7 +205,7 @@ def gen_wrapper(func: FuncDecl) -> str:
 
 typedef struct {struct_name} {{
     BdrvPollCo poll_state;
-    {func.return_type} ret;
+    {func.return_field}
 { func.gen_block('    {decl};') }
 }} {struct_name};
 
@@ -204,7 +214,7 @@ def gen_wrapper(func: FuncDecl) -> str:
     {struct_name} *s = opaque;
 
 {graph_lock}
-    s->ret = {name}({ func.gen_list('s->{name}') });
+    {func.get_result}{name}({ func.gen_list('s->{name}') });
 {graph_unlock}
     s->poll_state.in_progress = false;
 
-- 
2.38.1



^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PULL 13/38] block: Convert bdrv_io_plug() to co_wrapper
  2023-01-20 12:25 [PULL 00/38] Block layer patches Kevin Wolf
                   ` (11 preceding siblings ...)
  2023-01-20 12:26 ` [PULL 12/38] block-coroutine-wrapper: support void functions Kevin Wolf
@ 2023-01-20 12:26 ` Kevin Wolf
  2023-01-20 12:26 ` [PULL 14/38] block: Convert bdrv_io_unplug() " Kevin Wolf
                   ` (25 subsequent siblings)
  38 siblings, 0 replies; 48+ messages in thread
From: Kevin Wolf @ 2023-01-20 12:26 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, peter.maydell, qemu-devel

From: Emanuele Giuseppe Esposito <eesposit@redhat.com>

BlockDriver->bdrv_io_plug is categorized as IO callback, and it
currently doesn't run in a coroutine. We should let it take a graph
rdlock since the callback traverses the block nodes graph, which however
is only possible in a coroutine.

The only caller of this function is blk_io_plug(), therefore make
blk_io_plug() a co_wrapper, so that we're always running in a coroutine
where the lock can be taken.

Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Message-Id: <20230113204212.359076-3-kwolf@redhat.com>
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 include/block/block-io.h          |  3 ++-
 include/block/block_int-common.h  |  2 +-
 include/sysemu/block-backend-io.h |  4 +++-
 block/block-backend.c             |  4 ++--
 block/file-posix.c                | 10 +++++-----
 block/io.c                        |  8 ++++----
 block/nvme.c                      |  4 ++--
 7 files changed, 19 insertions(+), 16 deletions(-)

diff --git a/include/block/block-io.h b/include/block/block-io.h
index 1fa717a545..adfc792586 100644
--- a/include/block/block-io.h
+++ b/include/block/block-io.h
@@ -212,7 +212,8 @@ void coroutine_fn bdrv_co_leave(BlockDriverState *bs, AioContext *old_ctx);
 
 AioContext *child_of_bds_get_parent_aio_context(BdrvChild *c);
 
-void bdrv_io_plug(BlockDriverState *bs);
+void coroutine_fn bdrv_co_io_plug(BlockDriverState *bs);
+
 void bdrv_io_unplug(BlockDriverState *bs);
 
 bool coroutine_fn bdrv_co_can_store_new_dirty_bitmap(BlockDriverState *bs,
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
index c34c525fa6..a76bb76290 100644
--- a/include/block/block_int-common.h
+++ b/include/block/block_int-common.h
@@ -729,7 +729,7 @@ struct BlockDriver {
     void (*bdrv_debug_event)(BlockDriverState *bs, BlkdebugEvent event);
 
     /* io queue for linux-aio */
-    void (*bdrv_io_plug)(BlockDriverState *bs);
+    void coroutine_fn (*bdrv_co_io_plug)(BlockDriverState *bs);
     void (*bdrv_io_unplug)(BlockDriverState *bs);
 
     /**
diff --git a/include/sysemu/block-backend-io.h b/include/sysemu/block-backend-io.h
index 7ec6d978d4..70b73f7d11 100644
--- a/include/sysemu/block-backend-io.h
+++ b/include/sysemu/block-backend-io.h
@@ -73,7 +73,9 @@ void blk_iostatus_set_err(BlockBackend *blk, int error);
 int blk_get_max_iov(BlockBackend *blk);
 int blk_get_max_hw_iov(BlockBackend *blk);
 
-void blk_io_plug(BlockBackend *blk);
+void coroutine_fn blk_co_io_plug(BlockBackend *blk);
+void co_wrapper blk_io_plug(BlockBackend *blk);
+
 void blk_io_unplug(BlockBackend *blk);
 AioContext *blk_get_aio_context(BlockBackend *blk);
 BlockAcctStats *blk_get_stats(BlockBackend *blk);
diff --git a/block/block-backend.c b/block/block-backend.c
index 8fbb787f41..d10998fe19 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -2315,13 +2315,13 @@ void blk_add_insert_bs_notifier(BlockBackend *blk, Notifier *notify)
     notifier_list_add(&blk->insert_bs_notifiers, notify);
 }
 
-void blk_io_plug(BlockBackend *blk)
+void coroutine_fn blk_co_io_plug(BlockBackend *blk)
 {
     BlockDriverState *bs = blk_bs(blk);
     IO_CODE();
 
     if (bs) {
-        bdrv_io_plug(bs);
+        bdrv_co_io_plug(bs);
     }
 }
 
diff --git a/block/file-posix.c b/block/file-posix.c
index b9955db205..a8abcdd46f 100644
--- a/block/file-posix.c
+++ b/block/file-posix.c
@@ -2131,7 +2131,7 @@ static int coroutine_fn raw_co_pwritev(BlockDriverState *bs, int64_t offset,
     return raw_co_prw(bs, offset, bytes, qiov, QEMU_AIO_WRITE);
 }
 
-static void raw_aio_plug(BlockDriverState *bs)
+static void coroutine_fn raw_co_io_plug(BlockDriverState *bs)
 {
     BDRVRawState __attribute__((unused)) *s = bs->opaque;
 #ifdef CONFIG_LINUX_AIO
@@ -3316,7 +3316,7 @@ BlockDriver bdrv_file = {
     .bdrv_co_copy_range_from = raw_co_copy_range_from,
     .bdrv_co_copy_range_to  = raw_co_copy_range_to,
     .bdrv_refresh_limits = raw_refresh_limits,
-    .bdrv_io_plug = raw_aio_plug,
+    .bdrv_co_io_plug        = raw_co_io_plug,
     .bdrv_io_unplug = raw_aio_unplug,
     .bdrv_attach_aio_context = raw_aio_attach_aio_context,
 
@@ -3688,7 +3688,7 @@ static BlockDriver bdrv_host_device = {
     .bdrv_co_copy_range_from = raw_co_copy_range_from,
     .bdrv_co_copy_range_to  = raw_co_copy_range_to,
     .bdrv_refresh_limits = raw_refresh_limits,
-    .bdrv_io_plug = raw_aio_plug,
+    .bdrv_co_io_plug        = raw_co_io_plug,
     .bdrv_io_unplug = raw_aio_unplug,
     .bdrv_attach_aio_context = raw_aio_attach_aio_context,
 
@@ -3812,7 +3812,7 @@ static BlockDriver bdrv_host_cdrom = {
     .bdrv_co_pwritev        = raw_co_pwritev,
     .bdrv_co_flush_to_disk  = raw_co_flush_to_disk,
     .bdrv_refresh_limits = raw_refresh_limits,
-    .bdrv_io_plug = raw_aio_plug,
+    .bdrv_co_io_plug        = raw_co_io_plug,
     .bdrv_io_unplug = raw_aio_unplug,
     .bdrv_attach_aio_context = raw_aio_attach_aio_context,
 
@@ -3942,7 +3942,7 @@ static BlockDriver bdrv_host_cdrom = {
     .bdrv_co_pwritev        = raw_co_pwritev,
     .bdrv_co_flush_to_disk  = raw_co_flush_to_disk,
     .bdrv_refresh_limits = raw_refresh_limits,
-    .bdrv_io_plug = raw_aio_plug,
+    .bdrv_co_io_plug        = raw_co_io_plug,
     .bdrv_io_unplug = raw_aio_unplug,
     .bdrv_attach_aio_context = raw_aio_attach_aio_context,
 
diff --git a/block/io.c b/block/io.c
index a09b1b34ab..c05fb89267 100644
--- a/block/io.c
+++ b/block/io.c
@@ -3136,19 +3136,19 @@ void *qemu_try_blockalign0(BlockDriverState *bs, size_t size)
     return mem;
 }
 
-void bdrv_io_plug(BlockDriverState *bs)
+void coroutine_fn bdrv_co_io_plug(BlockDriverState *bs)
 {
     BdrvChild *child;
     IO_CODE();
 
     QLIST_FOREACH(child, &bs->children, next) {
-        bdrv_io_plug(child->bs);
+        bdrv_co_io_plug(child->bs);
     }
 
     if (qatomic_fetch_inc(&bs->io_plugged) == 0) {
         BlockDriver *drv = bs->drv;
-        if (drv && drv->bdrv_io_plug) {
-            drv->bdrv_io_plug(bs);
+        if (drv && drv->bdrv_co_io_plug) {
+            drv->bdrv_co_io_plug(bs);
         }
     }
 }
diff --git a/block/nvme.c b/block/nvme.c
index 656624c585..1af911e396 100644
--- a/block/nvme.c
+++ b/block/nvme.c
@@ -1566,7 +1566,7 @@ static void nvme_attach_aio_context(BlockDriverState *bs,
     }
 }
 
-static void nvme_aio_plug(BlockDriverState *bs)
+static void coroutine_fn nvme_co_io_plug(BlockDriverState *bs)
 {
     BDRVNVMeState *s = bs->opaque;
     assert(!s->plugged);
@@ -1663,7 +1663,7 @@ static BlockDriver bdrv_nvme = {
     .bdrv_detach_aio_context  = nvme_detach_aio_context,
     .bdrv_attach_aio_context  = nvme_attach_aio_context,
 
-    .bdrv_io_plug             = nvme_aio_plug,
+    .bdrv_co_io_plug          = nvme_co_io_plug,
     .bdrv_io_unplug           = nvme_aio_unplug,
 
     .bdrv_register_buf        = nvme_register_buf,
-- 
2.38.1



^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PULL 14/38] block: Convert bdrv_io_unplug() to co_wrapper
  2023-01-20 12:25 [PULL 00/38] Block layer patches Kevin Wolf
                   ` (12 preceding siblings ...)
  2023-01-20 12:26 ` [PULL 13/38] block: Convert bdrv_io_plug() to co_wrapper Kevin Wolf
@ 2023-01-20 12:26 ` Kevin Wolf
  2023-01-20 12:26 ` [PULL 15/38] block: Convert bdrv_is_inserted() " Kevin Wolf
                   ` (24 subsequent siblings)
  38 siblings, 0 replies; 48+ messages in thread
From: Kevin Wolf @ 2023-01-20 12:26 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, peter.maydell, qemu-devel

From: Emanuele Giuseppe Esposito <eesposit@redhat.com>

BlockDriver->bdrv_io_unplug is categorized as IO callback, and it
currently doesn't run in a coroutine. We should let it take a graph
rdlock since the callback traverses the block nodes graph, which however
is only possible in a coroutine.

The only caller of this function is blk_io_unplug(), therefore make
blk_io_unplug() a co_wrapper, so that we're always running in a
coroutine where the lock can be taken.

Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Message-Id: <20230113204212.359076-4-kwolf@redhat.com>
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 include/block/block-io.h          |  3 +--
 include/block/block_int-common.h  |  2 +-
 include/sysemu/block-backend-io.h |  4 +++-
 block/blkio.c                     |  4 ++--
 block/block-backend.c             |  4 ++--
 block/file-posix.c                | 10 +++++-----
 block/io.c                        |  8 ++++----
 block/nvme.c                      |  4 ++--
 8 files changed, 20 insertions(+), 19 deletions(-)

diff --git a/include/block/block-io.h b/include/block/block-io.h
index adfc792586..322c7b61c3 100644
--- a/include/block/block-io.h
+++ b/include/block/block-io.h
@@ -213,8 +213,7 @@ void coroutine_fn bdrv_co_leave(BlockDriverState *bs, AioContext *old_ctx);
 AioContext *child_of_bds_get_parent_aio_context(BdrvChild *c);
 
 void coroutine_fn bdrv_co_io_plug(BlockDriverState *bs);
-
-void bdrv_io_unplug(BlockDriverState *bs);
+void coroutine_fn bdrv_co_io_unplug(BlockDriverState *bs);
 
 bool coroutine_fn bdrv_co_can_store_new_dirty_bitmap(BlockDriverState *bs,
                                                      const char *name,
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
index a76bb76290..253df92509 100644
--- a/include/block/block_int-common.h
+++ b/include/block/block_int-common.h
@@ -730,7 +730,7 @@ struct BlockDriver {
 
     /* io queue for linux-aio */
     void coroutine_fn (*bdrv_co_io_plug)(BlockDriverState *bs);
-    void (*bdrv_io_unplug)(BlockDriverState *bs);
+    void coroutine_fn (*bdrv_co_io_unplug)(BlockDriverState *bs);
 
     /**
      * bdrv_drain_begin is called if implemented in the beginning of a
diff --git a/include/sysemu/block-backend-io.h b/include/sysemu/block-backend-io.h
index 70b73f7d11..d8cc8d74f5 100644
--- a/include/sysemu/block-backend-io.h
+++ b/include/sysemu/block-backend-io.h
@@ -76,7 +76,9 @@ int blk_get_max_hw_iov(BlockBackend *blk);
 void coroutine_fn blk_co_io_plug(BlockBackend *blk);
 void co_wrapper blk_io_plug(BlockBackend *blk);
 
-void blk_io_unplug(BlockBackend *blk);
+void coroutine_fn blk_co_io_unplug(BlockBackend *blk);
+void co_wrapper blk_io_unplug(BlockBackend *blk);
+
 AioContext *blk_get_aio_context(BlockBackend *blk);
 BlockAcctStats *blk_get_stats(BlockBackend *blk);
 void *blk_aio_get(const AIOCBInfo *aiocb_info, BlockBackend *blk,
diff --git a/block/blkio.c b/block/blkio.c
index 5eae3adfaf..1ff51ff4f3 100644
--- a/block/blkio.c
+++ b/block/blkio.c
@@ -477,7 +477,7 @@ static int coroutine_fn blkio_co_pwrite_zeroes(BlockDriverState *bs,
     return cod.ret;
 }
 
-static void blkio_io_unplug(BlockDriverState *bs)
+static void coroutine_fn blkio_co_io_unplug(BlockDriverState *bs)
 {
     BDRVBlkioState *s = bs->opaque;
 
@@ -1006,7 +1006,7 @@ static void blkio_refresh_limits(BlockDriverState *bs, Error **errp)
         .bdrv_co_pwritev         = blkio_co_pwritev, \
         .bdrv_co_flush_to_disk   = blkio_co_flush, \
         .bdrv_co_pwrite_zeroes   = blkio_co_pwrite_zeroes, \
-        .bdrv_io_unplug          = blkio_io_unplug, \
+        .bdrv_co_io_unplug       = blkio_co_io_unplug, \
         .bdrv_refresh_limits     = blkio_refresh_limits, \
         .bdrv_register_buf       = blkio_register_buf, \
         .bdrv_unregister_buf     = blkio_unregister_buf, \
diff --git a/block/block-backend.c b/block/block-backend.c
index d10998fe19..e9cc7d291e 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -2325,13 +2325,13 @@ void coroutine_fn blk_co_io_plug(BlockBackend *blk)
     }
 }
 
-void blk_io_unplug(BlockBackend *blk)
+void coroutine_fn blk_co_io_unplug(BlockBackend *blk)
 {
     BlockDriverState *bs = blk_bs(blk);
     IO_CODE();
 
     if (bs) {
-        bdrv_io_unplug(bs);
+        bdrv_co_io_unplug(bs);
     }
 }
 
diff --git a/block/file-posix.c b/block/file-posix.c
index a8abcdd46f..37bf71c5a6 100644
--- a/block/file-posix.c
+++ b/block/file-posix.c
@@ -2148,7 +2148,7 @@ static void coroutine_fn raw_co_io_plug(BlockDriverState *bs)
 #endif
 }
 
-static void raw_aio_unplug(BlockDriverState *bs)
+static void coroutine_fn raw_co_io_unplug(BlockDriverState *bs)
 {
     BDRVRawState __attribute__((unused)) *s = bs->opaque;
 #ifdef CONFIG_LINUX_AIO
@@ -3317,7 +3317,7 @@ BlockDriver bdrv_file = {
     .bdrv_co_copy_range_to  = raw_co_copy_range_to,
     .bdrv_refresh_limits = raw_refresh_limits,
     .bdrv_co_io_plug        = raw_co_io_plug,
-    .bdrv_io_unplug = raw_aio_unplug,
+    .bdrv_co_io_unplug      = raw_co_io_unplug,
     .bdrv_attach_aio_context = raw_aio_attach_aio_context,
 
     .bdrv_co_truncate = raw_co_truncate,
@@ -3689,7 +3689,7 @@ static BlockDriver bdrv_host_device = {
     .bdrv_co_copy_range_to  = raw_co_copy_range_to,
     .bdrv_refresh_limits = raw_refresh_limits,
     .bdrv_co_io_plug        = raw_co_io_plug,
-    .bdrv_io_unplug = raw_aio_unplug,
+    .bdrv_co_io_unplug      = raw_co_io_unplug,
     .bdrv_attach_aio_context = raw_aio_attach_aio_context,
 
     .bdrv_co_truncate       = raw_co_truncate,
@@ -3813,7 +3813,7 @@ static BlockDriver bdrv_host_cdrom = {
     .bdrv_co_flush_to_disk  = raw_co_flush_to_disk,
     .bdrv_refresh_limits = raw_refresh_limits,
     .bdrv_co_io_plug        = raw_co_io_plug,
-    .bdrv_io_unplug = raw_aio_unplug,
+    .bdrv_co_io_unplug      = raw_co_io_unplug,
     .bdrv_attach_aio_context = raw_aio_attach_aio_context,
 
     .bdrv_co_truncate    = raw_co_truncate,
@@ -3943,7 +3943,7 @@ static BlockDriver bdrv_host_cdrom = {
     .bdrv_co_flush_to_disk  = raw_co_flush_to_disk,
     .bdrv_refresh_limits = raw_refresh_limits,
     .bdrv_co_io_plug        = raw_co_io_plug,
-    .bdrv_io_unplug = raw_aio_unplug,
+    .bdrv_co_io_unplug      = raw_co_io_unplug,
     .bdrv_attach_aio_context = raw_aio_attach_aio_context,
 
     .bdrv_co_truncate    = raw_co_truncate,
diff --git a/block/io.c b/block/io.c
index c05fb89267..32c744d546 100644
--- a/block/io.c
+++ b/block/io.c
@@ -3153,7 +3153,7 @@ void coroutine_fn bdrv_co_io_plug(BlockDriverState *bs)
     }
 }
 
-void bdrv_io_unplug(BlockDriverState *bs)
+void coroutine_fn bdrv_co_io_unplug(BlockDriverState *bs)
 {
     BdrvChild *child;
     IO_CODE();
@@ -3161,13 +3161,13 @@ void bdrv_io_unplug(BlockDriverState *bs)
     assert(bs->io_plugged);
     if (qatomic_fetch_dec(&bs->io_plugged) == 1) {
         BlockDriver *drv = bs->drv;
-        if (drv && drv->bdrv_io_unplug) {
-            drv->bdrv_io_unplug(bs);
+        if (drv && drv->bdrv_co_io_unplug) {
+            drv->bdrv_co_io_unplug(bs);
         }
     }
 
     QLIST_FOREACH(child, &bs->children, next) {
-        bdrv_io_unplug(child->bs);
+        bdrv_co_io_unplug(child->bs);
     }
 }
 
diff --git a/block/nvme.c b/block/nvme.c
index 1af911e396..eb940f2846 100644
--- a/block/nvme.c
+++ b/block/nvme.c
@@ -1573,7 +1573,7 @@ static void coroutine_fn nvme_co_io_plug(BlockDriverState *bs)
     s->plugged = true;
 }
 
-static void nvme_aio_unplug(BlockDriverState *bs)
+static void coroutine_fn nvme_co_io_unplug(BlockDriverState *bs)
 {
     BDRVNVMeState *s = bs->opaque;
     assert(s->plugged);
@@ -1664,7 +1664,7 @@ static BlockDriver bdrv_nvme = {
     .bdrv_attach_aio_context  = nvme_attach_aio_context,
 
     .bdrv_co_io_plug          = nvme_co_io_plug,
-    .bdrv_io_unplug           = nvme_aio_unplug,
+    .bdrv_co_io_unplug        = nvme_co_io_unplug,
 
     .bdrv_register_buf        = nvme_register_buf,
     .bdrv_unregister_buf      = nvme_unregister_buf,
-- 
2.38.1



^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PULL 15/38] block: Convert bdrv_is_inserted() to co_wrapper
  2023-01-20 12:25 [PULL 00/38] Block layer patches Kevin Wolf
                   ` (13 preceding siblings ...)
  2023-01-20 12:26 ` [PULL 14/38] block: Convert bdrv_io_unplug() " Kevin Wolf
@ 2023-01-20 12:26 ` Kevin Wolf
  2023-01-20 12:26 ` [PULL 16/38] block: Rename refresh_total_sectors to bdrv_refresh_total_sectors Kevin Wolf
                   ` (23 subsequent siblings)
  38 siblings, 0 replies; 48+ messages in thread
From: Kevin Wolf @ 2023-01-20 12:26 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, peter.maydell, qemu-devel

From: Emanuele Giuseppe Esposito <eesposit@redhat.com>

bdrv_is_inserted() is categorized as an I/O function, and it currently
doesn't run in a coroutine. We should let it take a graph rdlock since
it traverses the block nodes graph, which however is only possible in a
coroutine.

Therefore turn it into a co_wrapper to move the actual function into a
coroutine where the lock can be taken.

At the same time, add also blk_is_inserted as co_wrapper_mixed, since it
is called in both coroutine and non-coroutine contexts.

Because now this function creates a new coroutine and polls, we need to
take the AioContext lock where it is missing, for the only reason that
internally c_w_mixed_bdrv_rdlock calls AIO_WAIT_WHILE and it expects to
release the AioContext lock. Once the rwlock is ultimated and placed in
every place it needs to be, we will poll using AIO_WAIT_WHILE_UNLOCKED
and remove the AioContext lock.

Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Message-Id: <20230113204212.359076-5-kwolf@redhat.com>
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 include/block/block-io.h          |  5 ++++-
 include/block/block_int-common.h  |  2 +-
 include/sysemu/block-backend-io.h |  5 ++++-
 block.c                           |  8 ++++----
 block/block-backend.c             |  4 ++--
 block/file-posix.c                |  8 ++++----
 block/io.c                        | 12 ++++++------
 blockdev.c                        |  8 +++++++-
 8 files changed, 32 insertions(+), 20 deletions(-)

diff --git a/include/block/block-io.h b/include/block/block-io.h
index 322c7b61c3..3ad053d60c 100644
--- a/include/block/block-io.h
+++ b/include/block/block-io.h
@@ -133,7 +133,10 @@ bool bdrv_is_read_only(BlockDriverState *bs);
 bool bdrv_is_writable(BlockDriverState *bs);
 bool bdrv_is_sg(BlockDriverState *bs);
 int bdrv_get_flags(BlockDriverState *bs);
-bool bdrv_is_inserted(BlockDriverState *bs);
+
+bool coroutine_fn bdrv_co_is_inserted(BlockDriverState *bs);
+bool co_wrapper bdrv_is_inserted(BlockDriverState *bs);
+
 void bdrv_lock_medium(BlockDriverState *bs, bool locked);
 void bdrv_eject(BlockDriverState *bs, bool eject_flag);
 const char *bdrv_get_format_name(BlockDriverState *bs);
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
index 253df92509..e6229c64e6 100644
--- a/include/block/block_int-common.h
+++ b/include/block/block_int-common.h
@@ -708,7 +708,7 @@ struct BlockDriver {
         BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos);
 
     /* removable device specific */
-    bool (*bdrv_is_inserted)(BlockDriverState *bs);
+    bool coroutine_fn (*bdrv_co_is_inserted)(BlockDriverState *bs);
     void (*bdrv_eject)(BlockDriverState *bs, bool eject_flag);
     void (*bdrv_lock_medium)(BlockDriverState *bs, bool locked);
 
diff --git a/include/sysemu/block-backend-io.h b/include/sysemu/block-backend-io.h
index d8cc8d74f5..4358fc6476 100644
--- a/include/sysemu/block-backend-io.h
+++ b/include/sysemu/block-backend-io.h
@@ -53,7 +53,10 @@ BlockAIOCB *blk_aio_ioctl(BlockBackend *blk, unsigned long int req, void *buf,
 
 void blk_inc_in_flight(BlockBackend *blk);
 void blk_dec_in_flight(BlockBackend *blk);
-bool blk_is_inserted(BlockBackend *blk);
+
+bool coroutine_fn blk_co_is_inserted(BlockBackend *blk);
+bool co_wrapper_mixed blk_is_inserted(BlockBackend *blk);
+
 bool blk_is_available(BlockBackend *blk);
 void blk_lock_medium(BlockBackend *blk, bool locked);
 void blk_eject(BlockBackend *blk, bool eject_flag);
diff --git a/block.c b/block.c
index 3f2bd12857..1bb20bbff6 100644
--- a/block.c
+++ b/block.c
@@ -6781,7 +6781,7 @@ out:
 /**
  * Return TRUE if the media is present
  */
-bool bdrv_is_inserted(BlockDriverState *bs)
+bool coroutine_fn bdrv_co_is_inserted(BlockDriverState *bs)
 {
     BlockDriver *drv = bs->drv;
     BdrvChild *child;
@@ -6790,11 +6790,11 @@ bool bdrv_is_inserted(BlockDriverState *bs)
     if (!drv) {
         return false;
     }
-    if (drv->bdrv_is_inserted) {
-        return drv->bdrv_is_inserted(bs);
+    if (drv->bdrv_co_is_inserted) {
+        return drv->bdrv_co_is_inserted(bs);
     }
     QLIST_FOREACH(child, &bs->children, next) {
-        if (!bdrv_is_inserted(child->bs)) {
+        if (!bdrv_co_is_inserted(child->bs)) {
             return false;
         }
     }
diff --git a/block/block-backend.c b/block/block-backend.c
index e9cc7d291e..7ba436811b 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -1983,12 +1983,12 @@ void blk_activate(BlockBackend *blk, Error **errp)
     bdrv_activate(bs, errp);
 }
 
-bool blk_is_inserted(BlockBackend *blk)
+bool coroutine_fn blk_co_is_inserted(BlockBackend *blk)
 {
     BlockDriverState *bs = blk_bs(blk);
     IO_CODE();
 
-    return bs && bdrv_is_inserted(bs);
+    return bs && bdrv_co_is_inserted(bs);
 }
 
 bool blk_is_available(BlockBackend *blk)
diff --git a/block/file-posix.c b/block/file-posix.c
index 37bf71c5a6..02a8703767 100644
--- a/block/file-posix.c
+++ b/block/file-posix.c
@@ -3756,7 +3756,7 @@ out:
     return prio;
 }
 
-static bool cdrom_is_inserted(BlockDriverState *bs)
+static bool coroutine_fn cdrom_co_is_inserted(BlockDriverState *bs)
 {
     BDRVRawState *s = bs->opaque;
     int ret;
@@ -3823,7 +3823,7 @@ static BlockDriver bdrv_host_cdrom = {
                         = raw_get_allocated_file_size,
 
     /* removable device support */
-    .bdrv_is_inserted   = cdrom_is_inserted,
+    .bdrv_co_is_inserted    = cdrom_co_is_inserted,
     .bdrv_eject         = cdrom_eject,
     .bdrv_lock_medium   = cdrom_lock_medium,
 
@@ -3882,7 +3882,7 @@ static int cdrom_reopen(BlockDriverState *bs)
     return 0;
 }
 
-static bool cdrom_is_inserted(BlockDriverState *bs)
+static bool coroutine_fn cdrom_co_is_inserted(BlockDriverState *bs)
 {
     return raw_getlength(bs) > 0;
 }
@@ -3953,7 +3953,7 @@ static BlockDriver bdrv_host_cdrom = {
                         = raw_get_allocated_file_size,
 
     /* removable device support */
-    .bdrv_is_inserted   = cdrom_is_inserted,
+    .bdrv_co_is_inserted     = cdrom_co_is_inserted,
     .bdrv_eject         = cdrom_eject,
     .bdrv_lock_medium   = cdrom_lock_medium,
 };
diff --git a/block/io.c b/block/io.c
index 32c744d546..03becd32d2 100644
--- a/block/io.c
+++ b/block/io.c
@@ -1621,7 +1621,7 @@ int coroutine_fn bdrv_co_preadv_part(BdrvChild *child,
 
     trace_bdrv_co_preadv_part(bs, offset, bytes, flags);
 
-    if (!bdrv_is_inserted(bs)) {
+    if (!bdrv_co_is_inserted(bs)) {
         return -ENOMEDIUM;
     }
 
@@ -2066,7 +2066,7 @@ int coroutine_fn bdrv_co_pwritev_part(BdrvChild *child,
 
     trace_bdrv_co_pwritev_part(child->bs, offset, bytes, flags);
 
-    if (!bdrv_is_inserted(bs)) {
+    if (!bdrv_co_is_inserted(bs)) {
         return -ENOMEDIUM;
     }
 
@@ -2834,7 +2834,7 @@ int coroutine_fn bdrv_co_flush(BlockDriverState *bs)
 
     bdrv_inc_in_flight(bs);
 
-    if (!bdrv_is_inserted(bs) || bdrv_is_read_only(bs) ||
+    if (!bdrv_co_is_inserted(bs) || bdrv_is_read_only(bs) ||
         bdrv_is_sg(bs)) {
         goto early_exit;
     }
@@ -2958,7 +2958,7 @@ int coroutine_fn bdrv_co_pdiscard(BdrvChild *child, int64_t offset,
     BlockDriverState *bs = child->bs;
     IO_CODE();
 
-    if (!bs || !bs->drv || !bdrv_is_inserted(bs)) {
+    if (!bs || !bs->drv || !bdrv_co_is_inserted(bs)) {
         return -ENOMEDIUM;
     }
 
@@ -3240,7 +3240,7 @@ static int coroutine_fn bdrv_co_copy_range_internal(
     assert(!(read_flags & BDRV_REQ_NO_WAIT));
     assert(!(write_flags & BDRV_REQ_NO_WAIT));
 
-    if (!dst || !dst->bs || !bdrv_is_inserted(dst->bs)) {
+    if (!dst || !dst->bs || !bdrv_co_is_inserted(dst->bs)) {
         return -ENOMEDIUM;
     }
     ret = bdrv_check_request32(dst_offset, bytes, NULL, 0);
@@ -3251,7 +3251,7 @@ static int coroutine_fn bdrv_co_copy_range_internal(
         return bdrv_co_pwrite_zeroes(dst, dst_offset, bytes, write_flags);
     }
 
-    if (!src || !src->bs || !bdrv_is_inserted(src->bs)) {
+    if (!src || !src->bs || !bdrv_co_is_inserted(src->bs)) {
         return -ENOMEDIUM;
     }
     ret = bdrv_check_request32(src_offset, bytes, NULL, 0);
diff --git a/blockdev.c b/blockdev.c
index ebf952cd21..ec9271ce49 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1023,6 +1023,7 @@ fail:
 static BlockDriverState *qmp_get_root_bs(const char *name, Error **errp)
 {
     BlockDriverState *bs;
+    AioContext *aio_context;
 
     bs = bdrv_lookup_bs(name, name, errp);
     if (bs == NULL) {
@@ -1034,11 +1035,16 @@ static BlockDriverState *qmp_get_root_bs(const char *name, Error **errp)
         return NULL;
     }
 
+    aio_context = bdrv_get_aio_context(bs);
+    aio_context_acquire(aio_context);
+
     if (!bdrv_is_inserted(bs)) {
         error_setg(errp, "Device has no medium");
-        return NULL;
+        bs = NULL;
     }
 
+    aio_context_release(aio_context);
+
     return bs;
 }
 
-- 
2.38.1



^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PULL 16/38] block: Rename refresh_total_sectors to bdrv_refresh_total_sectors
  2023-01-20 12:25 [PULL 00/38] Block layer patches Kevin Wolf
                   ` (14 preceding siblings ...)
  2023-01-20 12:26 ` [PULL 15/38] block: Convert bdrv_is_inserted() " Kevin Wolf
@ 2023-01-20 12:26 ` Kevin Wolf
  2023-01-20 12:26 ` [PULL 17/38] block: Convert bdrv_refresh_total_sectors() to co_wrapper_mixed Kevin Wolf
                   ` (22 subsequent siblings)
  38 siblings, 0 replies; 48+ messages in thread
From: Kevin Wolf @ 2023-01-20 12:26 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, peter.maydell, qemu-devel

From: Emanuele Giuseppe Esposito <eesposit@redhat.com>

The name is not good, not the least because we are going to convert this
to a generated co_wrapper, which adds a _co infix after the first part
of the name.

No functional change intended.

Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Message-Id: <20230113204212.359076-6-kwolf@redhat.com>
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 include/block/block_int-io.h | 2 +-
 block.c                      | 8 ++++----
 block/io.c                   | 8 +++++---
 3 files changed, 10 insertions(+), 8 deletions(-)

diff --git a/include/block/block_int-io.h b/include/block/block_int-io.h
index 8bc061ebb8..6b285fb520 100644
--- a/include/block/block_int-io.h
+++ b/include/block/block_int-io.h
@@ -120,7 +120,7 @@ int coroutine_fn bdrv_co_copy_range_to(BdrvChild *src, int64_t src_offset,
                                        BdrvRequestFlags read_flags,
                                        BdrvRequestFlags write_flags);
 
-int refresh_total_sectors(BlockDriverState *bs, int64_t hint);
+int bdrv_refresh_total_sectors(BlockDriverState *bs, int64_t hint);
 
 BdrvChild *bdrv_cow_child(BlockDriverState *bs);
 BdrvChild *bdrv_filter_child(BlockDriverState *bs);
diff --git a/block.c b/block.c
index 1bb20bbff6..6529e5a238 100644
--- a/block.c
+++ b/block.c
@@ -1034,7 +1034,7 @@ static int find_image_format(BlockBackend *file, const char *filename,
  * Set the current 'total_sectors' value
  * Return 0 on success, -errno on error.
  */
-int refresh_total_sectors(BlockDriverState *bs, int64_t hint)
+int bdrv_refresh_total_sectors(BlockDriverState *bs, int64_t hint)
 {
     BlockDriver *drv = bs->drv;
     IO_CODE();
@@ -1651,7 +1651,7 @@ static int bdrv_open_driver(BlockDriverState *bs, BlockDriver *drv,
     bs->supported_read_flags |= BDRV_REQ_REGISTERED_BUF;
     bs->supported_write_flags |= BDRV_REQ_REGISTERED_BUF;
 
-    ret = refresh_total_sectors(bs, bs->total_sectors);
+    ret = bdrv_refresh_total_sectors(bs, bs->total_sectors);
     if (ret < 0) {
         error_setg_errno(errp, -ret, "Could not refresh total sector count");
         return ret;
@@ -5808,7 +5808,7 @@ int64_t bdrv_nb_sectors(BlockDriverState *bs)
         return -ENOMEDIUM;
 
     if (drv->has_variable_length) {
-        int ret = refresh_total_sectors(bs, bs->total_sectors);
+        int ret = bdrv_refresh_total_sectors(bs, bs->total_sectors);
         if (ret < 0) {
             return ret;
         }
@@ -6590,7 +6590,7 @@ int bdrv_activate(BlockDriverState *bs, Error **errp)
             bdrv_dirty_bitmap_skip_store(bm, false);
         }
 
-        ret = refresh_total_sectors(bs, bs->total_sectors);
+        ret = bdrv_refresh_total_sectors(bs, bs->total_sectors);
         if (ret < 0) {
             bs->open_flags |= BDRV_O_INACTIVE;
             error_setg_errno(errp, -ret, "Could not refresh total sector count");
diff --git a/block/io.c b/block/io.c
index 03becd32d2..e5e51563a5 100644
--- a/block/io.c
+++ b/block/io.c
@@ -3473,15 +3473,17 @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
         goto out;
     }
 
-    ret = refresh_total_sectors(bs, offset >> BDRV_SECTOR_BITS);
+    ret = bdrv_refresh_total_sectors(bs, offset >> BDRV_SECTOR_BITS);
     if (ret < 0) {
         error_setg_errno(errp, -ret, "Could not refresh total sector count");
     } else {
         offset = bs->total_sectors * BDRV_SECTOR_SIZE;
     }
-    /* It's possible that truncation succeeded but refresh_total_sectors
+    /*
+     * It's possible that truncation succeeded but bdrv_refresh_total_sectors
      * failed, but the latter doesn't affect how we should finish the request.
-     * Pass 0 as the last parameter so that dirty bitmaps etc. are handled. */
+     * Pass 0 as the last parameter so that dirty bitmaps etc. are handled.
+     */
     bdrv_co_write_req_finish(child, offset - new_bytes, new_bytes, &req, 0);
 
 out:
-- 
2.38.1



^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PULL 17/38] block: Convert bdrv_refresh_total_sectors() to co_wrapper_mixed
  2023-01-20 12:25 [PULL 00/38] Block layer patches Kevin Wolf
                   ` (15 preceding siblings ...)
  2023-01-20 12:26 ` [PULL 16/38] block: Rename refresh_total_sectors to bdrv_refresh_total_sectors Kevin Wolf
@ 2023-01-20 12:26 ` Kevin Wolf
  2023-01-20 12:26 ` [PULL 18/38] block-backend: use bdrv_getlength instead of blk_getlength Kevin Wolf
                   ` (21 subsequent siblings)
  38 siblings, 0 replies; 48+ messages in thread
From: Kevin Wolf @ 2023-01-20 12:26 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, peter.maydell, qemu-devel

From: Emanuele Giuseppe Esposito <eesposit@redhat.com>

BlockDriver->bdrv_getlength is categorized as IO callback, and it
currently doesn't run in a coroutine. We should let it take a graph
rdlock since the callback traverses the block nodes graph, which however
is only possible in a coroutine.

Therefore turn it into a co_wrapper to move the actual function into a
coroutine where the lock can be taken.

Because now this function creates a new coroutine and polls, we need to
take the AioContext lock where it is missing, for the only reason that
internally co_wrapper calls AIO_WAIT_WHILE and it expects to release the
AioContext lock.

This is especially messy when a co_wrapper creates a coroutine and polls
in bdrv_open_driver, because this function has so many callers in so
many context that it can easily lead to deadlocks. Therefore the new
rule for bdrv_open_driver is that the caller must always hold the
AioContext lock of the given bs (except if it is a coroutine), because
the function calls bdrv_refresh_total_sectors() which is now a
co_wrapper.

Once the rwlock is ultimated and placed in every place it needs to be,
we will poll using AIO_WAIT_WHILE_UNLOCKED and remove the AioContext
lock.

Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Message-Id: <20230113204212.359076-7-kwolf@redhat.com>
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 include/block/block-io.h          |  8 ++++--
 include/block/block_int-common.h  |  2 +-
 include/block/block_int-io.h      |  5 +++-
 include/sysemu/block-backend-io.h | 10 ++++++--
 block.c                           | 32 +++++++++++++++++------
 block/blkdebug.c                  |  6 ++---
 block/blkio.c                     |  6 ++---
 block/blklogwrites.c              |  6 ++---
 block/blkreplay.c                 |  6 ++---
 block/blkverify.c                 |  6 ++---
 block/block-backend.c             | 10 +++++---
 block/commit.c                    |  4 +--
 block/copy-on-read.c              |  6 ++---
 block/crypto.c                    |  6 ++---
 block/curl.c                      | 10 ++++----
 block/file-posix.c                | 42 +++++++++++++++----------------
 block/file-win32.c                |  8 +++---
 block/filter-compress.c           |  6 ++---
 block/gluster.c                   | 12 ++++-----
 block/iscsi.c                     | 10 ++++----
 block/mirror.c                    |  4 +--
 block/nbd.c                       |  8 +++---
 block/null.c                      |  6 ++---
 block/nvme.c                      |  6 ++---
 block/preallocate.c               | 10 ++++----
 block/qed.c                       |  4 +--
 block/quorum.c                    |  8 +++---
 block/raw-format.c                |  6 ++---
 block/rbd.c                       |  4 +--
 block/replication.c               |  6 ++---
 block/ssh.c                       |  4 +--
 block/throttle.c                  |  6 ++---
 hw/scsi/scsi-disk.c               |  5 ++++
 tests/unit/test-block-iothread.c  |  3 +++
 block/meson.build                 |  1 +
 35 files changed, 161 insertions(+), 121 deletions(-)

diff --git a/include/block/block-io.h b/include/block/block-io.h
index 3ad053d60c..3677d445a4 100644
--- a/include/block/block-io.h
+++ b/include/block/block-io.h
@@ -73,8 +73,12 @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
                                   PreallocMode prealloc, BdrvRequestFlags flags,
                                   Error **errp);
 
-int64_t bdrv_nb_sectors(BlockDriverState *bs);
-int64_t bdrv_getlength(BlockDriverState *bs);
+int64_t coroutine_fn bdrv_co_nb_sectors(BlockDriverState *bs);
+int64_t co_wrapper_mixed bdrv_nb_sectors(BlockDriverState *bs);
+
+int64_t coroutine_fn bdrv_co_getlength(BlockDriverState *bs);
+int64_t co_wrapper_mixed bdrv_getlength(BlockDriverState *bs);
+
 int64_t bdrv_get_allocated_file_size(BlockDriverState *bs);
 BlockMeasureInfo *bdrv_measure(BlockDriver *drv, QemuOpts *opts,
                                BlockDriverState *in_bs, Error **errp);
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
index e6229c64e6..6336c7239a 100644
--- a/include/block/block_int-common.h
+++ b/include/block/block_int-common.h
@@ -684,7 +684,7 @@ struct BlockDriver {
     int coroutine_fn (*bdrv_co_truncate)(BlockDriverState *bs, int64_t offset,
                                          bool exact, PreallocMode prealloc,
                                          BdrvRequestFlags flags, Error **errp);
-    int64_t (*bdrv_getlength)(BlockDriverState *bs);
+    int64_t coroutine_fn (*bdrv_co_getlength)(BlockDriverState *bs);
     int64_t (*bdrv_get_allocated_file_size)(BlockDriverState *bs);
     BlockMeasureInfo *(*bdrv_measure)(QemuOpts *opts, BlockDriverState *in_bs,
                                       Error **errp);
diff --git a/include/block/block_int-io.h b/include/block/block_int-io.h
index 6b285fb520..d1559a501f 100644
--- a/include/block/block_int-io.h
+++ b/include/block/block_int-io.h
@@ -120,7 +120,10 @@ int coroutine_fn bdrv_co_copy_range_to(BdrvChild *src, int64_t src_offset,
                                        BdrvRequestFlags read_flags,
                                        BdrvRequestFlags write_flags);
 
-int bdrv_refresh_total_sectors(BlockDriverState *bs, int64_t hint);
+int coroutine_fn bdrv_co_refresh_total_sectors(BlockDriverState *bs,
+                                               int64_t hint);
+int co_wrapper_mixed
+bdrv_refresh_total_sectors(BlockDriverState *bs, int64_t hint);
 
 BdrvChild *bdrv_cow_child(BlockDriverState *bs);
 BdrvChild *bdrv_filter_child(BlockDriverState *bs);
diff --git a/include/sysemu/block-backend-io.h b/include/sysemu/block-backend-io.h
index 4358fc6476..a1eac6c00a 100644
--- a/include/sysemu/block-backend-io.h
+++ b/include/sysemu/block-backend-io.h
@@ -60,9 +60,15 @@ bool co_wrapper_mixed blk_is_inserted(BlockBackend *blk);
 bool blk_is_available(BlockBackend *blk);
 void blk_lock_medium(BlockBackend *blk, bool locked);
 void blk_eject(BlockBackend *blk, bool eject_flag);
-int64_t blk_getlength(BlockBackend *blk);
+
+int64_t coroutine_fn blk_co_getlength(BlockBackend *blk);
+int64_t co_wrapper_mixed blk_getlength(BlockBackend *blk);
+
 void blk_get_geometry(BlockBackend *blk, uint64_t *nb_sectors_ptr);
-int64_t blk_nb_sectors(BlockBackend *blk);
+
+int64_t coroutine_fn blk_co_nb_sectors(BlockBackend *blk);
+int64_t co_wrapper_mixed blk_nb_sectors(BlockBackend *blk);
+
 void *blk_try_blockalign(BlockBackend *blk, size_t size);
 void *blk_blockalign(BlockBackend *blk, size_t size);
 bool blk_is_writable(BlockBackend *blk);
diff --git a/block.c b/block.c
index 6529e5a238..c8c3e42080 100644
--- a/block.c
+++ b/block.c
@@ -1034,7 +1034,8 @@ static int find_image_format(BlockBackend *file, const char *filename,
  * Set the current 'total_sectors' value
  * Return 0 on success, -errno on error.
  */
-int bdrv_refresh_total_sectors(BlockDriverState *bs, int64_t hint)
+int coroutine_fn bdrv_co_refresh_total_sectors(BlockDriverState *bs,
+                                               int64_t hint)
 {
     BlockDriver *drv = bs->drv;
     IO_CODE();
@@ -1043,13 +1044,13 @@ int bdrv_refresh_total_sectors(BlockDriverState *bs, int64_t hint)
         return -ENOMEDIUM;
     }
 
-    /* Do not attempt drv->bdrv_getlength() on scsi-generic devices */
+    /* Do not attempt drv->bdrv_co_getlength() on scsi-generic devices */
     if (bdrv_is_sg(bs))
         return 0;
 
     /* query actual device if possible, otherwise just trust the hint */
-    if (drv->bdrv_getlength) {
-        int64_t length = drv->bdrv_getlength(bs);
+    if (drv->bdrv_co_getlength) {
+        int64_t length = drv->bdrv_co_getlength(bs);
         if (length < 0) {
             return length;
         }
@@ -1600,6 +1601,11 @@ out:
     g_free(gen_node_name);
 }
 
+/*
+ * The caller must always hold @bs AioContext lock, because this function calls
+ * bdrv_refresh_total_sectors() which polls when called from non-coroutine
+ * context.
+ */
 static int bdrv_open_driver(BlockDriverState *bs, BlockDriver *drv,
                             const char *node_name, QDict *options,
                             int open_flags, Error **errp)
@@ -3795,6 +3801,10 @@ out:
  * The reference parameter may be used to specify an existing block device which
  * should be opened. If specified, neither options nor a filename may be given,
  * nor can an existing BDS be reused (that is, *pbs has to be NULL).
+ *
+ * The caller must always hold @filename AioContext lock, because this
+ * function eventually calls bdrv_refresh_total_sectors() which polls
+ * when called from non-coroutine context.
  */
 static BlockDriverState *bdrv_open_inherit(const char *filename,
                                            const char *reference,
@@ -4083,6 +4093,11 @@ close_and_fail:
     return NULL;
 }
 
+/*
+ * The caller must always hold @filename AioContext lock, because this
+ * function eventually calls bdrv_refresh_total_sectors() which polls
+ * when called from non-coroutine context.
+ */
 BlockDriverState *bdrv_open(const char *filename, const char *reference,
                             QDict *options, int flags, Error **errp)
 {
@@ -5799,7 +5814,7 @@ BlockMeasureInfo *bdrv_measure(BlockDriver *drv, QemuOpts *opts,
 /**
  * Return number of sectors on success, -errno on error.
  */
-int64_t bdrv_nb_sectors(BlockDriverState *bs)
+int64_t coroutine_fn bdrv_co_nb_sectors(BlockDriverState *bs)
 {
     BlockDriver *drv = bs->drv;
     IO_CODE();
@@ -5808,7 +5823,7 @@ int64_t bdrv_nb_sectors(BlockDriverState *bs)
         return -ENOMEDIUM;
 
     if (drv->has_variable_length) {
-        int ret = bdrv_refresh_total_sectors(bs, bs->total_sectors);
+        int ret = bdrv_co_refresh_total_sectors(bs, bs->total_sectors);
         if (ret < 0) {
             return ret;
         }
@@ -5820,11 +5835,12 @@ int64_t bdrv_nb_sectors(BlockDriverState *bs)
  * Return length in bytes on success, -errno on error.
  * The length is always a multiple of BDRV_SECTOR_SIZE.
  */
-int64_t bdrv_getlength(BlockDriverState *bs)
+int64_t coroutine_fn bdrv_co_getlength(BlockDriverState *bs)
 {
-    int64_t ret = bdrv_nb_sectors(bs);
+    int64_t ret;
     IO_CODE();
 
+    ret = bdrv_co_nb_sectors(bs);
     if (ret < 0) {
         return ret;
     }
diff --git a/block/blkdebug.c b/block/blkdebug.c
index ca65b043f0..2294b0227b 100644
--- a/block/blkdebug.c
+++ b/block/blkdebug.c
@@ -965,9 +965,9 @@ static bool blkdebug_debug_is_suspended(BlockDriverState *bs, const char *tag)
     return false;
 }
 
-static int64_t blkdebug_getlength(BlockDriverState *bs)
+static int64_t coroutine_fn blkdebug_co_getlength(BlockDriverState *bs)
 {
-    return bdrv_getlength(bs->file->bs);
+    return bdrv_co_getlength(bs->file->bs);
 }
 
 static void blkdebug_refresh_filename(BlockDriverState *bs)
@@ -1074,7 +1074,7 @@ static BlockDriver bdrv_blkdebug = {
     .bdrv_reopen_prepare    = blkdebug_reopen_prepare,
     .bdrv_child_perm        = blkdebug_child_perm,
 
-    .bdrv_getlength         = blkdebug_getlength,
+    .bdrv_co_getlength      = blkdebug_co_getlength,
     .bdrv_refresh_filename  = blkdebug_refresh_filename,
     .bdrv_refresh_limits    = blkdebug_refresh_limits,
 
diff --git a/block/blkio.c b/block/blkio.c
index 1ff51ff4f3..2a3ab5a570 100644
--- a/block/blkio.c
+++ b/block/blkio.c
@@ -837,7 +837,7 @@ static void blkio_close(BlockDriverState *bs)
     }
 }
 
-static int64_t blkio_getlength(BlockDriverState *bs)
+static int64_t coroutine_fn blkio_co_getlength(BlockDriverState *bs)
 {
     BDRVBlkioState *s = bs->opaque;
     uint64_t capacity;
@@ -865,7 +865,7 @@ static int coroutine_fn blkio_truncate(BlockDriverState *bs, int64_t offset,
         return -ENOTSUP;
     }
 
-    current_length = blkio_getlength(bs);
+    current_length = blkio_co_getlength(bs);
 
     if (offset > current_length) {
         error_setg(errp, "Cannot grow device");
@@ -996,7 +996,7 @@ static void blkio_refresh_limits(BlockDriverState *bs, Error **errp)
         .instance_size           = sizeof(BDRVBlkioState), \
         .bdrv_file_open          = blkio_file_open, \
         .bdrv_close              = blkio_close, \
-        .bdrv_getlength          = blkio_getlength, \
+        .bdrv_co_getlength       = blkio_co_getlength, \
         .bdrv_co_truncate        = blkio_truncate, \
         .bdrv_get_info           = blkio_get_info, \
         .bdrv_attach_aio_context = blkio_attach_aio_context, \
diff --git a/block/blklogwrites.c b/block/blklogwrites.c
index cef9efe55d..6cb48d6ada 100644
--- a/block/blklogwrites.c
+++ b/block/blklogwrites.c
@@ -266,9 +266,9 @@ static void blk_log_writes_close(BlockDriverState *bs)
     s->log_file = NULL;
 }
 
-static int64_t blk_log_writes_getlength(BlockDriverState *bs)
+static int64_t coroutine_fn blk_log_writes_co_getlength(BlockDriverState *bs)
 {
-    return bdrv_getlength(bs->file->bs);
+    return bdrv_co_getlength(bs->file->bs);
 }
 
 static void blk_log_writes_child_perm(BlockDriverState *bs, BdrvChild *c,
@@ -497,7 +497,7 @@ static BlockDriver bdrv_blk_log_writes = {
 
     .bdrv_open              = blk_log_writes_open,
     .bdrv_close             = blk_log_writes_close,
-    .bdrv_getlength         = blk_log_writes_getlength,
+    .bdrv_co_getlength      = blk_log_writes_co_getlength,
     .bdrv_child_perm        = blk_log_writes_child_perm,
     .bdrv_refresh_limits    = blk_log_writes_refresh_limits,
 
diff --git a/block/blkreplay.c b/block/blkreplay.c
index 76a0b8d12a..fa1073fe4a 100644
--- a/block/blkreplay.c
+++ b/block/blkreplay.c
@@ -39,9 +39,9 @@ fail:
     return ret;
 }
 
-static int64_t blkreplay_getlength(BlockDriverState *bs)
+static int64_t coroutine_fn blkreplay_co_getlength(BlockDriverState *bs)
 {
-    return bdrv_getlength(bs->file->bs);
+    return bdrv_co_getlength(bs->file->bs);
 }
 
 /* This bh is used for synchronization of return from coroutines.
@@ -135,7 +135,7 @@ static BlockDriver bdrv_blkreplay = {
 
     .bdrv_open              = blkreplay_open,
     .bdrv_child_perm        = bdrv_default_perms,
-    .bdrv_getlength         = blkreplay_getlength,
+    .bdrv_co_getlength      = blkreplay_co_getlength,
 
     .bdrv_co_preadv         = blkreplay_co_preadv,
     .bdrv_co_pwritev        = blkreplay_co_pwritev,
diff --git a/block/blkverify.c b/block/blkverify.c
index c60a2dc624..acd730906d 100644
--- a/block/blkverify.c
+++ b/block/blkverify.c
@@ -154,11 +154,11 @@ static void blkverify_close(BlockDriverState *bs)
     s->test_file = NULL;
 }
 
-static int64_t blkverify_getlength(BlockDriverState *bs)
+static int64_t coroutine_fn blkverify_co_getlength(BlockDriverState *bs)
 {
     BDRVBlkverifyState *s = bs->opaque;
 
-    return bdrv_getlength(s->test_file->bs);
+    return bdrv_co_getlength(s->test_file->bs);
 }
 
 static void coroutine_fn blkverify_do_test_req(void *opaque)
@@ -313,7 +313,7 @@ static BlockDriver bdrv_blkverify = {
     .bdrv_file_open                   = blkverify_open,
     .bdrv_close                       = blkverify_close,
     .bdrv_child_perm                  = bdrv_default_perms,
-    .bdrv_getlength                   = blkverify_getlength,
+    .bdrv_co_getlength                = blkverify_co_getlength,
     .bdrv_refresh_filename            = blkverify_refresh_filename,
     .bdrv_dirname                     = blkverify_dirname,
 
diff --git a/block/block-backend.c b/block/block-backend.c
index 7ba436811b..d698cc3f33 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -1599,14 +1599,15 @@ BlockAIOCB *blk_aio_pwrite_zeroes(BlockBackend *blk, int64_t offset,
                         flags | BDRV_REQ_ZERO_WRITE, cb, opaque);
 }
 
-int64_t blk_getlength(BlockBackend *blk)
+int64_t coroutine_fn blk_co_getlength(BlockBackend *blk)
 {
     IO_CODE();
+
     if (!blk_is_available(blk)) {
         return -ENOMEDIUM;
     }
 
-    return bdrv_getlength(blk_bs(blk));
+    return bdrv_co_getlength(blk_bs(blk));
 }
 
 void blk_get_geometry(BlockBackend *blk, uint64_t *nb_sectors_ptr)
@@ -1619,14 +1620,15 @@ void blk_get_geometry(BlockBackend *blk, uint64_t *nb_sectors_ptr)
     }
 }
 
-int64_t blk_nb_sectors(BlockBackend *blk)
+int64_t coroutine_fn blk_co_nb_sectors(BlockBackend *blk)
 {
     IO_CODE();
+
     if (!blk_is_available(blk)) {
         return -ENOMEDIUM;
     }
 
-    return bdrv_nb_sectors(blk_bs(blk));
+    return bdrv_co_nb_sectors(blk_bs(blk));
 }
 
 BlockAIOCB *blk_aio_preadv(BlockBackend *blk, int64_t offset,
diff --git a/block/commit.c b/block/commit.c
index b346341767..41e3599281 100644
--- a/block/commit.c
+++ b/block/commit.c
@@ -123,13 +123,13 @@ static int coroutine_fn commit_run(Job *job, Error **errp)
     QEMU_AUTO_VFREE void *buf = NULL;
     int64_t len, base_len;
 
-    len = blk_getlength(s->top);
+    len = blk_co_getlength(s->top);
     if (len < 0) {
         return len;
     }
     job_progress_set_remaining(&s->common.job, len);
 
-    base_len = blk_getlength(s->base);
+    base_len = blk_co_getlength(s->base);
     if (base_len < 0) {
         return base_len;
     }
diff --git a/block/copy-on-read.c b/block/copy-on-read.c
index 815ac1d835..41777b87a4 100644
--- a/block/copy-on-read.c
+++ b/block/copy-on-read.c
@@ -120,9 +120,9 @@ static void cor_child_perm(BlockDriverState *bs, BdrvChild *c,
 }
 
 
-static int64_t cor_getlength(BlockDriverState *bs)
+static int64_t coroutine_fn cor_co_getlength(BlockDriverState *bs)
 {
-    return bdrv_getlength(bs->file->bs);
+    return bdrv_co_getlength(bs->file->bs);
 }
 
 
@@ -249,7 +249,7 @@ static BlockDriver bdrv_copy_on_read = {
     .bdrv_close                         = cor_close,
     .bdrv_child_perm                    = cor_child_perm,
 
-    .bdrv_getlength                     = cor_getlength,
+    .bdrv_co_getlength                  = cor_co_getlength,
 
     .bdrv_co_preadv_part                = cor_co_preadv_part,
     .bdrv_co_pwritev_part               = cor_co_pwritev_part,
diff --git a/block/crypto.c b/block/crypto.c
index bbeb9f437c..6d6c006887 100644
--- a/block/crypto.c
+++ b/block/crypto.c
@@ -531,10 +531,10 @@ static void block_crypto_refresh_limits(BlockDriverState *bs, Error **errp)
 }
 
 
-static int64_t block_crypto_getlength(BlockDriverState *bs)
+static int64_t coroutine_fn block_crypto_co_getlength(BlockDriverState *bs)
 {
     BlockCrypto *crypto = bs->opaque;
-    int64_t len = bdrv_getlength(bs->file->bs);
+    int64_t len = bdrv_co_getlength(bs->file->bs);
 
     uint64_t offset = qcrypto_block_get_payload_offset(crypto->block);
     assert(offset < INT64_MAX);
@@ -953,7 +953,7 @@ static BlockDriver bdrv_crypto_luks = {
     .bdrv_refresh_limits = block_crypto_refresh_limits,
     .bdrv_co_preadv     = block_crypto_co_preadv,
     .bdrv_co_pwritev    = block_crypto_co_pwritev,
-    .bdrv_getlength     = block_crypto_getlength,
+    .bdrv_co_getlength  = block_crypto_co_getlength,
     .bdrv_measure       = block_crypto_measure,
     .bdrv_get_info      = block_crypto_get_info_luks,
     .bdrv_get_specific_info = block_crypto_get_specific_info_luks,
diff --git a/block/curl.c b/block/curl.c
index cba4c4cac7..d60596e57f 100644
--- a/block/curl.c
+++ b/block/curl.c
@@ -957,7 +957,7 @@ static void curl_close(BlockDriverState *bs)
     g_free(s->proxypassword);
 }
 
-static int64_t curl_getlength(BlockDriverState *bs)
+static int64_t coroutine_fn curl_co_getlength(BlockDriverState *bs)
 {
     BDRVCURLState *s = bs->opaque;
     return s->len;
@@ -1001,7 +1001,7 @@ static BlockDriver bdrv_http = {
     .bdrv_parse_filename        = curl_parse_filename,
     .bdrv_file_open             = curl_open,
     .bdrv_close                 = curl_close,
-    .bdrv_getlength             = curl_getlength,
+    .bdrv_co_getlength          = curl_co_getlength,
 
     .bdrv_co_preadv             = curl_co_preadv,
 
@@ -1020,7 +1020,7 @@ static BlockDriver bdrv_https = {
     .bdrv_parse_filename        = curl_parse_filename,
     .bdrv_file_open             = curl_open,
     .bdrv_close                 = curl_close,
-    .bdrv_getlength             = curl_getlength,
+    .bdrv_co_getlength          = curl_co_getlength,
 
     .bdrv_co_preadv             = curl_co_preadv,
 
@@ -1039,7 +1039,7 @@ static BlockDriver bdrv_ftp = {
     .bdrv_parse_filename        = curl_parse_filename,
     .bdrv_file_open             = curl_open,
     .bdrv_close                 = curl_close,
-    .bdrv_getlength             = curl_getlength,
+    .bdrv_co_getlength          = curl_co_getlength,
 
     .bdrv_co_preadv             = curl_co_preadv,
 
@@ -1058,7 +1058,7 @@ static BlockDriver bdrv_ftps = {
     .bdrv_parse_filename        = curl_parse_filename,
     .bdrv_file_open             = curl_open,
     .bdrv_close                 = curl_close,
-    .bdrv_getlength             = curl_getlength,
+    .bdrv_co_getlength          = curl_co_getlength,
 
     .bdrv_co_preadv             = curl_co_preadv,
 
diff --git a/block/file-posix.c b/block/file-posix.c
index 02a8703767..ef1fce3782 100644
--- a/block/file-posix.c
+++ b/block/file-posix.c
@@ -188,7 +188,7 @@ static int fd_open(BlockDriverState *bs)
     return -EIO;
 }
 
-static int64_t raw_getlength(BlockDriverState *bs);
+static int64_t coroutine_fn raw_co_getlength(BlockDriverState *bs);
 
 typedef struct RawPosixAIOData {
     BlockDriverState *bs;
@@ -2279,7 +2279,7 @@ static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
     }
 
     if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) {
-        int64_t cur_length = raw_getlength(bs);
+        int64_t cur_length = raw_co_getlength(bs);
 
         if (offset != cur_length && exact) {
             error_setg(errp, "Cannot resize device files");
@@ -2297,7 +2297,7 @@ static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
 }
 
 #ifdef __OpenBSD__
-static int64_t raw_getlength(BlockDriverState *bs)
+static int64_t coroutine_fn raw_co_getlength(BlockDriverState *bs)
 {
     BDRVRawState *s = bs->opaque;
     int fd = s->fd;
@@ -2316,7 +2316,7 @@ static int64_t raw_getlength(BlockDriverState *bs)
         return st.st_size;
 }
 #elif defined(__NetBSD__)
-static int64_t raw_getlength(BlockDriverState *bs)
+static int64_t coroutine_fn raw_co_getlength(BlockDriverState *bs)
 {
     BDRVRawState *s = bs->opaque;
     int fd = s->fd;
@@ -2341,7 +2341,7 @@ static int64_t raw_getlength(BlockDriverState *bs)
         return st.st_size;
 }
 #elif defined(__sun__)
-static int64_t raw_getlength(BlockDriverState *bs)
+static int64_t coroutine_fn raw_co_getlength(BlockDriverState *bs)
 {
     BDRVRawState *s = bs->opaque;
     struct dk_minfo minfo;
@@ -2372,7 +2372,7 @@ static int64_t raw_getlength(BlockDriverState *bs)
     return size;
 }
 #elif defined(CONFIG_BSD)
-static int64_t raw_getlength(BlockDriverState *bs)
+static int64_t coroutine_fn raw_co_getlength(BlockDriverState *bs)
 {
     BDRVRawState *s = bs->opaque;
     int fd = s->fd;
@@ -2444,7 +2444,7 @@ again:
     return size;
 }
 #else
-static int64_t raw_getlength(BlockDriverState *bs)
+static int64_t coroutine_fn raw_co_getlength(BlockDriverState *bs)
 {
     BDRVRawState *s = bs->opaque;
     int ret;
@@ -2829,7 +2829,7 @@ static int coroutine_fn raw_co_block_status(BlockDriverState *bs,
          * round up if necessary.
          */
         if (!QEMU_IS_ALIGNED(*pnum, bs->bl.request_alignment)) {
-            int64_t file_length = raw_getlength(bs);
+            int64_t file_length = raw_co_getlength(bs);
             if (file_length > 0) {
                 /* Ignore errors, this is just a safeguard */
                 assert(hole == file_length);
@@ -2851,7 +2851,7 @@ static int coroutine_fn raw_co_block_status(BlockDriverState *bs,
 
 #if defined(__linux__)
 /* Verify that the file is not in the page cache */
-static void check_cache_dropped(BlockDriverState *bs, Error **errp)
+static void coroutine_fn check_cache_dropped(BlockDriverState *bs, Error **errp)
 {
     const size_t window_size = 128 * 1024 * 1024;
     BDRVRawState *s = bs->opaque;
@@ -2866,7 +2866,7 @@ static void check_cache_dropped(BlockDriverState *bs, Error **errp)
     page_size = sysconf(_SC_PAGESIZE);
     vec = g_malloc(DIV_ROUND_UP(window_size, page_size));
 
-    end = raw_getlength(bs);
+    end = raw_co_getlength(bs);
 
     for (offset = 0; offset < end; offset += window_size) {
         void *new_window;
@@ -3320,8 +3320,8 @@ BlockDriver bdrv_file = {
     .bdrv_co_io_unplug      = raw_co_io_unplug,
     .bdrv_attach_aio_context = raw_aio_attach_aio_context,
 
-    .bdrv_co_truncate = raw_co_truncate,
-    .bdrv_getlength = raw_getlength,
+    .bdrv_co_truncate                   = raw_co_truncate,
+    .bdrv_co_getlength                  = raw_co_getlength,
     .bdrv_get_info = raw_get_info,
     .bdrv_get_allocated_file_size
                         = raw_get_allocated_file_size,
@@ -3692,8 +3692,8 @@ static BlockDriver bdrv_host_device = {
     .bdrv_co_io_unplug      = raw_co_io_unplug,
     .bdrv_attach_aio_context = raw_aio_attach_aio_context,
 
-    .bdrv_co_truncate       = raw_co_truncate,
-    .bdrv_getlength	= raw_getlength,
+    .bdrv_co_truncate                   = raw_co_truncate,
+    .bdrv_co_getlength                  = raw_co_getlength,
     .bdrv_get_info = raw_get_info,
     .bdrv_get_allocated_file_size
                         = raw_get_allocated_file_size,
@@ -3816,9 +3816,9 @@ static BlockDriver bdrv_host_cdrom = {
     .bdrv_co_io_unplug      = raw_co_io_unplug,
     .bdrv_attach_aio_context = raw_aio_attach_aio_context,
 
-    .bdrv_co_truncate    = raw_co_truncate,
-    .bdrv_getlength      = raw_getlength,
-    .has_variable_length = true,
+    .bdrv_co_truncate                   = raw_co_truncate,
+    .bdrv_co_getlength                  = raw_co_getlength,
+    .has_variable_length                = true,
     .bdrv_get_allocated_file_size
                         = raw_get_allocated_file_size,
 
@@ -3884,7 +3884,7 @@ static int cdrom_reopen(BlockDriverState *bs)
 
 static bool coroutine_fn cdrom_co_is_inserted(BlockDriverState *bs)
 {
-    return raw_getlength(bs) > 0;
+    return raw_co_getlength(bs) > 0;
 }
 
 static void cdrom_eject(BlockDriverState *bs, bool eject_flag)
@@ -3946,9 +3946,9 @@ static BlockDriver bdrv_host_cdrom = {
     .bdrv_co_io_unplug      = raw_co_io_unplug,
     .bdrv_attach_aio_context = raw_aio_attach_aio_context,
 
-    .bdrv_co_truncate    = raw_co_truncate,
-    .bdrv_getlength      = raw_getlength,
-    .has_variable_length = true,
+    .bdrv_co_truncate                   = raw_co_truncate,
+    .bdrv_co_getlength                  = raw_co_getlength,
+    .has_variable_length                = true,
     .bdrv_get_allocated_file_size
                         = raw_get_allocated_file_size,
 
diff --git a/block/file-win32.c b/block/file-win32.c
index ec9d64d0e4..aedee695dd 100644
--- a/block/file-win32.c
+++ b/block/file-win32.c
@@ -525,7 +525,7 @@ static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
     return 0;
 }
 
-static int64_t raw_getlength(BlockDriverState *bs)
+static int64_t coroutine_fn raw_co_getlength(BlockDriverState *bs)
 {
     BDRVRawState *s = bs->opaque;
     LARGE_INTEGER l;
@@ -763,7 +763,7 @@ BlockDriver bdrv_file = {
     .bdrv_aio_flush     = raw_aio_flush,
 
     .bdrv_co_truncate   = raw_co_truncate,
-    .bdrv_getlength	= raw_getlength,
+    .bdrv_co_getlength  = raw_co_getlength,
     .bdrv_get_allocated_file_size
                         = raw_get_allocated_file_size,
 
@@ -932,8 +932,8 @@ static BlockDriver bdrv_host_device = {
     .bdrv_detach_aio_context = raw_detach_aio_context,
     .bdrv_attach_aio_context = raw_attach_aio_context,
 
-    .bdrv_getlength      = raw_getlength,
-    .has_variable_length = true,
+    .bdrv_co_getlength                = raw_co_getlength,
+    .has_variable_length              = true,
 
     .bdrv_get_allocated_file_size
                         = raw_get_allocated_file_size,
diff --git a/block/filter-compress.c b/block/filter-compress.c
index 305716c86c..1515fe5103 100644
--- a/block/filter-compress.c
+++ b/block/filter-compress.c
@@ -54,9 +54,9 @@ static int compress_open(BlockDriverState *bs, QDict *options, int flags,
 }
 
 
-static int64_t compress_getlength(BlockDriverState *bs)
+static int64_t coroutine_fn compress_co_getlength(BlockDriverState *bs)
 {
-    return bdrv_getlength(bs->file->bs);
+    return bdrv_co_getlength(bs->file->bs);
 }
 
 
@@ -134,7 +134,7 @@ static BlockDriver bdrv_compress = {
     .bdrv_open                          = compress_open,
     .bdrv_child_perm                    = bdrv_default_perms,
 
-    .bdrv_getlength                     = compress_getlength,
+    .bdrv_co_getlength                  = compress_co_getlength,
 
     .bdrv_co_preadv_part                = compress_co_preadv_part,
     .bdrv_co_pwritev_part               = compress_co_pwritev_part,
diff --git a/block/gluster.c b/block/gluster.c
index 7efc296399..469cdf01d4 100644
--- a/block/gluster.c
+++ b/block/gluster.c
@@ -1317,7 +1317,7 @@ static coroutine_fn int qemu_gluster_co_pdiscard(BlockDriverState *bs,
 }
 #endif
 
-static int64_t qemu_gluster_getlength(BlockDriverState *bs)
+static int64_t coroutine_fn qemu_gluster_co_getlength(BlockDriverState *bs)
 {
     BDRVGlusterState *s = bs->opaque;
     int64_t ret;
@@ -1509,7 +1509,7 @@ static int coroutine_fn qemu_gluster_co_block_status(BlockDriverState *bs,
          * round up if necessary.
          */
         if (!QEMU_IS_ALIGNED(*pnum, bs->bl.request_alignment)) {
-            int64_t file_length = qemu_gluster_getlength(bs);
+            int64_t file_length = qemu_gluster_co_getlength(bs);
             if (file_length > 0) {
                 /* Ignore errors, this is just a safeguard */
                 assert(hole == file_length);
@@ -1558,7 +1558,7 @@ static BlockDriver bdrv_gluster = {
     .bdrv_close                   = qemu_gluster_close,
     .bdrv_co_create               = qemu_gluster_co_create,
     .bdrv_co_create_opts          = qemu_gluster_co_create_opts,
-    .bdrv_getlength               = qemu_gluster_getlength,
+    .bdrv_co_getlength            = qemu_gluster_co_getlength,
     .bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size,
     .bdrv_co_truncate             = qemu_gluster_co_truncate,
     .bdrv_co_readv                = qemu_gluster_co_readv,
@@ -1587,7 +1587,7 @@ static BlockDriver bdrv_gluster_tcp = {
     .bdrv_close                   = qemu_gluster_close,
     .bdrv_co_create               = qemu_gluster_co_create,
     .bdrv_co_create_opts          = qemu_gluster_co_create_opts,
-    .bdrv_getlength               = qemu_gluster_getlength,
+    .bdrv_co_getlength            = qemu_gluster_co_getlength,
     .bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size,
     .bdrv_co_truncate             = qemu_gluster_co_truncate,
     .bdrv_co_readv                = qemu_gluster_co_readv,
@@ -1616,7 +1616,7 @@ static BlockDriver bdrv_gluster_unix = {
     .bdrv_close                   = qemu_gluster_close,
     .bdrv_co_create               = qemu_gluster_co_create,
     .bdrv_co_create_opts          = qemu_gluster_co_create_opts,
-    .bdrv_getlength               = qemu_gluster_getlength,
+    .bdrv_co_getlength            = qemu_gluster_co_getlength,
     .bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size,
     .bdrv_co_truncate             = qemu_gluster_co_truncate,
     .bdrv_co_readv                = qemu_gluster_co_readv,
@@ -1651,7 +1651,7 @@ static BlockDriver bdrv_gluster_rdma = {
     .bdrv_close                   = qemu_gluster_close,
     .bdrv_co_create               = qemu_gluster_co_create,
     .bdrv_co_create_opts          = qemu_gluster_co_create_opts,
-    .bdrv_getlength               = qemu_gluster_getlength,
+    .bdrv_co_getlength            = qemu_gluster_co_getlength,
     .bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size,
     .bdrv_co_truncate             = qemu_gluster_co_truncate,
     .bdrv_co_readv                = qemu_gluster_co_readv,
diff --git a/block/iscsi.c b/block/iscsi.c
index a316d46d96..df110dd1d2 100644
--- a/block/iscsi.c
+++ b/block/iscsi.c
@@ -1126,8 +1126,8 @@ static BlockAIOCB *iscsi_aio_ioctl(BlockDriverState *bs,
 
 #endif
 
-static int64_t
-iscsi_getlength(BlockDriverState *bs)
+static int64_t coroutine_fn
+iscsi_co_getlength(BlockDriverState *bs)
 {
     IscsiLun *iscsilun = bs->opaque;
     int64_t len;
@@ -2154,7 +2154,7 @@ static int coroutine_fn iscsi_co_truncate(BlockDriverState *bs, int64_t offset,
         return -EIO;
     }
 
-    cur_length = iscsi_getlength(bs);
+    cur_length = iscsi_co_getlength(bs);
     if (offset != cur_length && exact) {
         error_setg(errp, "Cannot resize iSCSI devices");
         return -ENOTSUP;
@@ -2433,7 +2433,7 @@ static BlockDriver bdrv_iscsi = {
     .bdrv_reopen_commit     = iscsi_reopen_commit,
     .bdrv_co_invalidate_cache = iscsi_co_invalidate_cache,
 
-    .bdrv_getlength  = iscsi_getlength,
+    .bdrv_co_getlength   = iscsi_co_getlength,
     .bdrv_get_info   = iscsi_get_info,
     .bdrv_co_truncate    = iscsi_co_truncate,
     .bdrv_refresh_limits = iscsi_refresh_limits,
@@ -2472,7 +2472,7 @@ static BlockDriver bdrv_iser = {
     .bdrv_reopen_commit     = iscsi_reopen_commit,
     .bdrv_co_invalidate_cache  = iscsi_co_invalidate_cache,
 
-    .bdrv_getlength  = iscsi_getlength,
+    .bdrv_co_getlength   = iscsi_co_getlength,
     .bdrv_get_info   = iscsi_get_info,
     .bdrv_co_truncate    = iscsi_co_truncate,
     .bdrv_refresh_limits = iscsi_refresh_limits,
diff --git a/block/mirror.c b/block/mirror.c
index 251adc5ae0..c7d7ce2f8f 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -909,13 +909,13 @@ static int coroutine_fn mirror_run(Job *job, Error **errp)
         goto immediate_exit;
     }
 
-    s->bdev_length = bdrv_getlength(bs);
+    s->bdev_length = bdrv_co_getlength(bs);
     if (s->bdev_length < 0) {
         ret = s->bdev_length;
         goto immediate_exit;
     }
 
-    target_length = blk_getlength(s->target);
+    target_length = blk_co_getlength(s->target);
     if (target_length < 0) {
         ret = target_length;
         goto immediate_exit;
diff --git a/block/nbd.c b/block/nbd.c
index 7d485c86d2..bf2894ad5c 100644
--- a/block/nbd.c
+++ b/block/nbd.c
@@ -1992,7 +1992,7 @@ static int coroutine_fn nbd_co_truncate(BlockDriverState *bs, int64_t offset,
     return 0;
 }
 
-static int64_t nbd_getlength(BlockDriverState *bs)
+static int64_t coroutine_fn nbd_co_getlength(BlockDriverState *bs)
 {
     BDRVNBDState *s = bs->opaque;
 
@@ -2124,7 +2124,7 @@ static BlockDriver bdrv_nbd = {
     .bdrv_co_pdiscard           = nbd_client_co_pdiscard,
     .bdrv_refresh_limits        = nbd_refresh_limits,
     .bdrv_co_truncate           = nbd_co_truncate,
-    .bdrv_getlength             = nbd_getlength,
+    .bdrv_co_getlength          = nbd_co_getlength,
     .bdrv_refresh_filename      = nbd_refresh_filename,
     .bdrv_co_block_status       = nbd_client_co_block_status,
     .bdrv_dirname               = nbd_dirname,
@@ -2152,7 +2152,7 @@ static BlockDriver bdrv_nbd_tcp = {
     .bdrv_co_pdiscard           = nbd_client_co_pdiscard,
     .bdrv_refresh_limits        = nbd_refresh_limits,
     .bdrv_co_truncate           = nbd_co_truncate,
-    .bdrv_getlength             = nbd_getlength,
+    .bdrv_co_getlength          = nbd_co_getlength,
     .bdrv_refresh_filename      = nbd_refresh_filename,
     .bdrv_co_block_status       = nbd_client_co_block_status,
     .bdrv_dirname               = nbd_dirname,
@@ -2180,7 +2180,7 @@ static BlockDriver bdrv_nbd_unix = {
     .bdrv_co_pdiscard           = nbd_client_co_pdiscard,
     .bdrv_refresh_limits        = nbd_refresh_limits,
     .bdrv_co_truncate           = nbd_co_truncate,
-    .bdrv_getlength             = nbd_getlength,
+    .bdrv_co_getlength          = nbd_co_getlength,
     .bdrv_refresh_filename      = nbd_refresh_filename,
     .bdrv_co_block_status       = nbd_client_co_block_status,
     .bdrv_dirname               = nbd_dirname,
diff --git a/block/null.c b/block/null.c
index 75f7d0db40..05dde6d9ab 100644
--- a/block/null.c
+++ b/block/null.c
@@ -99,7 +99,7 @@ static int null_file_open(BlockDriverState *bs, QDict *options, int flags,
     return ret;
 }
 
-static int64_t null_getlength(BlockDriverState *bs)
+static int64_t coroutine_fn null_co_getlength(BlockDriverState *bs)
 {
     BDRVNullState *s = bs->opaque;
     return s->length;
@@ -283,7 +283,7 @@ static BlockDriver bdrv_null_co = {
 
     .bdrv_file_open         = null_file_open,
     .bdrv_parse_filename    = null_co_parse_filename,
-    .bdrv_getlength         = null_getlength,
+    .bdrv_co_getlength      = null_co_getlength,
     .bdrv_get_allocated_file_size = null_allocated_file_size,
 
     .bdrv_co_preadv         = null_co_preadv,
@@ -304,7 +304,7 @@ static BlockDriver bdrv_null_aio = {
 
     .bdrv_file_open         = null_file_open,
     .bdrv_parse_filename    = null_aio_parse_filename,
-    .bdrv_getlength         = null_getlength,
+    .bdrv_co_getlength      = null_co_getlength,
     .bdrv_get_allocated_file_size = null_allocated_file_size,
 
     .bdrv_aio_preadv        = null_aio_preadv,
diff --git a/block/nvme.c b/block/nvme.c
index eb940f2846..6958715758 100644
--- a/block/nvme.c
+++ b/block/nvme.c
@@ -1001,7 +1001,7 @@ fail:
     return ret;
 }
 
-static int64_t nvme_getlength(BlockDriverState *bs)
+static int64_t coroutine_fn nvme_co_getlength(BlockDriverState *bs)
 {
     BDRVNVMeState *s = bs->opaque;
     return s->nsze << s->blkshift;
@@ -1485,7 +1485,7 @@ static int coroutine_fn nvme_co_truncate(BlockDriverState *bs, int64_t offset,
         return -ENOTSUP;
     }
 
-    cur_length = nvme_getlength(bs);
+    cur_length = nvme_co_getlength(bs);
     if (offset != cur_length && exact) {
         error_setg(errp, "Cannot resize NVMe devices");
         return -ENOTSUP;
@@ -1642,7 +1642,7 @@ static BlockDriver bdrv_nvme = {
     .bdrv_parse_filename      = nvme_parse_filename,
     .bdrv_file_open           = nvme_file_open,
     .bdrv_close               = nvme_close,
-    .bdrv_getlength           = nvme_getlength,
+    .bdrv_co_getlength        = nvme_co_getlength,
     .bdrv_probe_blocksizes    = nvme_probe_blocksizes,
     .bdrv_co_truncate         = nvme_co_truncate,
 
diff --git a/block/preallocate.c b/block/preallocate.c
index d50ee7f49b..94aa824e09 100644
--- a/block/preallocate.c
+++ b/block/preallocate.c
@@ -441,7 +441,7 @@ static int coroutine_fn preallocate_co_flush(BlockDriverState *bs)
     return bdrv_co_flush(bs->file->bs);
 }
 
-static int64_t preallocate_getlength(BlockDriverState *bs)
+static int64_t coroutine_fn preallocate_co_getlength(BlockDriverState *bs)
 {
     int64_t ret;
     BDRVPreallocateState *s = bs->opaque;
@@ -450,7 +450,7 @@ static int64_t preallocate_getlength(BlockDriverState *bs)
         return s->data_end;
     }
 
-    ret = bdrv_getlength(bs->file->bs);
+    ret = bdrv_co_getlength(bs->file->bs);
 
     if (has_prealloc_perms(bs)) {
         s->file_end = s->zero_start = s->data_end = ret;
@@ -536,9 +536,9 @@ BlockDriver bdrv_preallocate_filter = {
     .format_name = "preallocate",
     .instance_size = sizeof(BDRVPreallocateState),
 
-    .bdrv_getlength = preallocate_getlength,
-    .bdrv_open = preallocate_open,
-    .bdrv_close = preallocate_close,
+    .bdrv_co_getlength    = preallocate_co_getlength,
+    .bdrv_open            = preallocate_open,
+    .bdrv_close           = preallocate_close,
 
     .bdrv_reopen_prepare  = preallocate_reopen_prepare,
     .bdrv_reopen_commit   = preallocate_reopen_commit,
diff --git a/block/qed.c b/block/qed.c
index faa606618e..c8f9045b72 100644
--- a/block/qed.c
+++ b/block/qed.c
@@ -1480,7 +1480,7 @@ static int coroutine_fn bdrv_qed_co_truncate(BlockDriverState *bs,
     return ret;
 }
 
-static int64_t bdrv_qed_getlength(BlockDriverState *bs)
+static int64_t coroutine_fn bdrv_qed_co_getlength(BlockDriverState *bs)
 {
     BDRVQEDState *s = bs->opaque;
     return s->header.image_size;
@@ -1653,7 +1653,7 @@ static BlockDriver bdrv_qed = {
     .bdrv_co_writev           = bdrv_qed_co_writev,
     .bdrv_co_pwrite_zeroes    = bdrv_qed_co_pwrite_zeroes,
     .bdrv_co_truncate         = bdrv_qed_co_truncate,
-    .bdrv_getlength           = bdrv_qed_getlength,
+    .bdrv_co_getlength        = bdrv_qed_co_getlength,
     .bdrv_get_info            = bdrv_qed_get_info,
     .bdrv_refresh_limits      = bdrv_qed_refresh_limits,
     .bdrv_change_backing_file = bdrv_qed_change_backing_file,
diff --git a/block/quorum.c b/block/quorum.c
index 7f21c03f1f..d1dcf2eaba 100644
--- a/block/quorum.c
+++ b/block/quorum.c
@@ -754,19 +754,19 @@ static int coroutine_fn quorum_co_pwrite_zeroes(BlockDriverState *bs,
                              flags | BDRV_REQ_ZERO_WRITE);
 }
 
-static int64_t quorum_getlength(BlockDriverState *bs)
+static int64_t coroutine_fn quorum_co_getlength(BlockDriverState *bs)
 {
     BDRVQuorumState *s = bs->opaque;
     int64_t result;
     int i;
 
     /* check that all file have the same length */
-    result = bdrv_getlength(s->children[0]->bs);
+    result = bdrv_co_getlength(s->children[0]->bs);
     if (result < 0) {
         return result;
     }
     for (i = 1; i < s->num_children; i++) {
-        int64_t value = bdrv_getlength(s->children[i]->bs);
+        int64_t value = bdrv_co_getlength(s->children[i]->bs);
         if (value < 0) {
             return value;
         }
@@ -1283,7 +1283,7 @@ static BlockDriver bdrv_quorum = {
 
     .bdrv_co_flush                      = quorum_co_flush,
 
-    .bdrv_getlength                     = quorum_getlength,
+    .bdrv_co_getlength                  = quorum_co_getlength,
 
     .bdrv_co_preadv                     = quorum_co_preadv,
     .bdrv_co_pwritev                    = quorum_co_pwritev,
diff --git a/block/raw-format.c b/block/raw-format.c
index 28905b09ee..ccf23fe0b2 100644
--- a/block/raw-format.c
+++ b/block/raw-format.c
@@ -316,14 +316,14 @@ static int coroutine_fn raw_co_pdiscard(BlockDriverState *bs,
     return bdrv_co_pdiscard(bs->file, offset, bytes);
 }
 
-static int64_t raw_getlength(BlockDriverState *bs)
+static int64_t coroutine_fn raw_co_getlength(BlockDriverState *bs)
 {
     int64_t len;
     BDRVRawState *s = bs->opaque;
 
     /* Update size. It should not change unless the file was externally
      * modified. */
-    len = bdrv_getlength(bs->file->bs);
+    len = bdrv_co_getlength(bs->file->bs);
     if (len < 0) {
         return len;
     }
@@ -621,7 +621,7 @@ BlockDriver bdrv_raw = {
     .bdrv_co_copy_range_from = &raw_co_copy_range_from,
     .bdrv_co_copy_range_to  = &raw_co_copy_range_to,
     .bdrv_co_truncate     = &raw_co_truncate,
-    .bdrv_getlength       = &raw_getlength,
+    .bdrv_co_getlength    = &raw_co_getlength,
     .is_format            = true,
     .has_variable_length  = true,
     .bdrv_measure         = &raw_measure,
diff --git a/block/rbd.c b/block/rbd.c
index 3aa6aae0e0..c67d30160a 100644
--- a/block/rbd.c
+++ b/block/rbd.c
@@ -1429,7 +1429,7 @@ static int coroutine_fn qemu_rbd_co_block_status(BlockDriverState *bs,
     return status;
 }
 
-static int64_t qemu_rbd_getlength(BlockDriverState *bs)
+static int64_t coroutine_fn qemu_rbd_co_getlength(BlockDriverState *bs)
 {
     BDRVRBDState *s = bs->opaque;
     int r;
@@ -1653,7 +1653,7 @@ static BlockDriver bdrv_rbd = {
     .bdrv_get_info          = qemu_rbd_getinfo,
     .bdrv_get_specific_info = qemu_rbd_get_specific_info,
     .create_opts            = &qemu_rbd_create_opts,
-    .bdrv_getlength         = qemu_rbd_getlength,
+    .bdrv_co_getlength      = qemu_rbd_co_getlength,
     .bdrv_co_truncate       = qemu_rbd_co_truncate,
     .protocol_name          = "rbd",
 
diff --git a/block/replication.c b/block/replication.c
index c62f48a874..a27417d310 100644
--- a/block/replication.c
+++ b/block/replication.c
@@ -179,9 +179,9 @@ static void replication_child_perm(BlockDriverState *bs, BdrvChild *c,
     return;
 }
 
-static int64_t replication_getlength(BlockDriverState *bs)
+static int64_t coroutine_fn replication_co_getlength(BlockDriverState *bs)
 {
-    return bdrv_getlength(bs->file->bs);
+    return bdrv_co_getlength(bs->file->bs);
 }
 
 static int replication_get_io_status(BDRVReplicationState *s)
@@ -758,7 +758,7 @@ static BlockDriver bdrv_replication = {
     .bdrv_close                 = replication_close,
     .bdrv_child_perm            = replication_child_perm,
 
-    .bdrv_getlength             = replication_getlength,
+    .bdrv_co_getlength          = replication_co_getlength,
     .bdrv_co_readv              = replication_co_readv,
     .bdrv_co_writev             = replication_co_writev,
 
diff --git a/block/ssh.c b/block/ssh.c
index 8508710f2f..c374129c9a 100644
--- a/block/ssh.c
+++ b/block/ssh.c
@@ -1252,7 +1252,7 @@ static coroutine_fn int ssh_co_flush(BlockDriverState *bs)
     return ret;
 }
 
-static int64_t ssh_getlength(BlockDriverState *bs)
+static int64_t coroutine_fn ssh_co_getlength(BlockDriverState *bs)
 {
     BDRVSSHState *s = bs->opaque;
     int64_t length;
@@ -1363,7 +1363,7 @@ static BlockDriver bdrv_ssh = {
     .bdrv_has_zero_init           = ssh_has_zero_init,
     .bdrv_co_readv                = ssh_co_readv,
     .bdrv_co_writev               = ssh_co_writev,
-    .bdrv_getlength               = ssh_getlength,
+    .bdrv_co_getlength            = ssh_co_getlength,
     .bdrv_co_truncate             = ssh_co_truncate,
     .bdrv_co_flush_to_disk        = ssh_co_flush,
     .bdrv_refresh_filename        = ssh_refresh_filename,
diff --git a/block/throttle.c b/block/throttle.c
index 88851c84f4..80b6395899 100644
--- a/block/throttle.c
+++ b/block/throttle.c
@@ -104,9 +104,9 @@ static void throttle_close(BlockDriverState *bs)
 }
 
 
-static int64_t throttle_getlength(BlockDriverState *bs)
+static int64_t coroutine_fn throttle_co_getlength(BlockDriverState *bs)
 {
-    return bdrv_getlength(bs->file->bs);
+    return bdrv_co_getlength(bs->file->bs);
 }
 
 static int coroutine_fn throttle_co_preadv(BlockDriverState *bs,
@@ -245,7 +245,7 @@ static BlockDriver bdrv_throttle = {
 
     .bdrv_child_perm                    =   bdrv_default_perms,
 
-    .bdrv_getlength                     =   throttle_getlength,
+    .bdrv_co_getlength                  =   throttle_co_getlength,
 
     .bdrv_co_preadv                     =   throttle_co_preadv,
     .bdrv_co_pwritev                    =   throttle_co_pwritev,
diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
index e493c28814..d4e360850f 100644
--- a/hw/scsi/scsi-disk.c
+++ b/hw/scsi/scsi-disk.c
@@ -2332,10 +2332,15 @@ static void scsi_disk_reset(DeviceState *dev)
 {
     SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev.qdev, dev);
     uint64_t nb_sectors;
+    AioContext *ctx;
 
     scsi_device_purge_requests(&s->qdev, SENSE_CODE(RESET));
 
+    ctx = blk_get_aio_context(s->qdev.conf.blk);
+    aio_context_acquire(ctx);
     blk_get_geometry(s->qdev.conf.blk, &nb_sectors);
+    aio_context_release(ctx);
+
     nb_sectors /= s->qdev.blocksize / BDRV_SECTOR_SIZE;
     if (nb_sectors) {
         nb_sectors--;
diff --git a/tests/unit/test-block-iothread.c b/tests/unit/test-block-iothread.c
index 8ca5adec5e..e444aa707d 100644
--- a/tests/unit/test-block-iothread.c
+++ b/tests/unit/test-block-iothread.c
@@ -831,7 +831,10 @@ static void test_attach_second_node(void)
     qdict_put_str(options, "driver", "raw");
     qdict_put_str(options, "file", "base");
 
+    aio_context_acquire(ctx);
     filter = bdrv_open(NULL, NULL, options, BDRV_O_RDWR, &error_abort);
+    aio_context_release(ctx);
+
     g_assert(blk_get_aio_context(blk) == ctx);
     g_assert(bdrv_get_aio_context(bs) == ctx);
     g_assert(bdrv_get_aio_context(filter) == ctx);
diff --git a/block/meson.build b/block/meson.build
index 90011a2805..3662852dc2 100644
--- a/block/meson.build
+++ b/block/meson.build
@@ -139,6 +139,7 @@ block_gen_c = custom_target('block-gen.c',
                             input: files(
                                       '../include/block/block-io.h',
                                       '../include/block/dirty-bitmap.h',
+                                      '../include/block/block_int-io.h',
                                       '../include/block/block-global-state.h',
                                       '../include/sysemu/block-backend-io.h',
                                       'coroutines.h'
-- 
2.38.1



^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PULL 18/38] block-backend: use bdrv_getlength instead of blk_getlength
  2023-01-20 12:25 [PULL 00/38] Block layer patches Kevin Wolf
                   ` (16 preceding siblings ...)
  2023-01-20 12:26 ` [PULL 17/38] block: Convert bdrv_refresh_total_sectors() to co_wrapper_mixed Kevin Wolf
@ 2023-01-20 12:26 ` Kevin Wolf
  2023-01-20 12:26 ` [PULL 19/38] block: use bdrv_co_refresh_total_sectors when possible Kevin Wolf
                   ` (20 subsequent siblings)
  38 siblings, 0 replies; 48+ messages in thread
From: Kevin Wolf @ 2023-01-20 12:26 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, peter.maydell, qemu-devel

From: Emanuele Giuseppe Esposito <eesposit@redhat.com>

The only difference is that blk_ checks if the block is available,
but this check is already performed above in blk_check_byte_request().

This is in preparation for the graph rdlock, which will be taken
by both the callers of blk_check_byte_request() and blk_getlength().

Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Message-Id: <20230113204212.359076-8-kwolf@redhat.com>
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block/block-backend.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/block/block-backend.c b/block/block-backend.c
index d698cc3f33..7d4b08ee45 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -1253,7 +1253,7 @@ static int blk_check_byte_request(BlockBackend *blk, int64_t offset,
     }
 
     if (!blk->allow_write_beyond_eof) {
-        len = blk_getlength(blk);
+        len = bdrv_getlength(blk_bs(blk));
         if (len < 0) {
             return len;
         }
-- 
2.38.1



^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PULL 19/38] block: use bdrv_co_refresh_total_sectors when possible
  2023-01-20 12:25 [PULL 00/38] Block layer patches Kevin Wolf
                   ` (17 preceding siblings ...)
  2023-01-20 12:26 ` [PULL 18/38] block-backend: use bdrv_getlength instead of blk_getlength Kevin Wolf
@ 2023-01-20 12:26 ` Kevin Wolf
  2023-01-20 12:26 ` [PULL 20/38] block: Convert bdrv_get_allocated_file_size() to co_wrapper Kevin Wolf
                   ` (19 subsequent siblings)
  38 siblings, 0 replies; 48+ messages in thread
From: Kevin Wolf @ 2023-01-20 12:26 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, peter.maydell, qemu-devel

From: Emanuele Giuseppe Esposito <eesposit@redhat.com>

In some places we are sure we are always running in a
coroutine, therefore it's useless to call the generated_co_wrapper,
instead call directly the _co_ function.

Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Message-Id: <20230113204212.359076-9-kwolf@redhat.com>
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block/block-backend.c | 6 +++---
 block/io.c            | 4 ++--
 block/preallocate.c   | 6 +++---
 block/qed.c           | 2 +-
 4 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/block/block-backend.c b/block/block-backend.c
index 7d4b08ee45..b4a8d259cf 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -1235,8 +1235,8 @@ void blk_set_disable_request_queuing(BlockBackend *blk, bool disable)
     blk->disable_request_queuing = disable;
 }
 
-static int blk_check_byte_request(BlockBackend *blk, int64_t offset,
-                                  int64_t bytes)
+static coroutine_fn int blk_check_byte_request(BlockBackend *blk,
+                                               int64_t offset, int64_t bytes)
 {
     int64_t len;
 
@@ -1253,7 +1253,7 @@ static int blk_check_byte_request(BlockBackend *blk, int64_t offset,
     }
 
     if (!blk->allow_write_beyond_eof) {
-        len = bdrv_getlength(blk_bs(blk));
+        len = bdrv_co_getlength(blk_bs(blk));
         if (len < 0) {
             return len;
         }
diff --git a/block/io.c b/block/io.c
index e5e51563a5..fdc5ba9fb6 100644
--- a/block/io.c
+++ b/block/io.c
@@ -3443,7 +3443,7 @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
     if (new_bytes && backing) {
         int64_t backing_len;
 
-        backing_len = bdrv_getlength(backing->bs);
+        backing_len = bdrv_co_getlength(backing->bs);
         if (backing_len < 0) {
             ret = backing_len;
             error_setg_errno(errp, -ret, "Could not get backing file size");
@@ -3473,7 +3473,7 @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
         goto out;
     }
 
-    ret = bdrv_refresh_total_sectors(bs, offset >> BDRV_SECTOR_BITS);
+    ret = bdrv_co_refresh_total_sectors(bs, offset >> BDRV_SECTOR_BITS);
     if (ret < 0) {
         error_setg_errno(errp, -ret, "Could not refresh total sector count");
     } else {
diff --git a/block/preallocate.c b/block/preallocate.c
index 94aa824e09..5815d7a78b 100644
--- a/block/preallocate.c
+++ b/block/preallocate.c
@@ -286,7 +286,7 @@ static bool coroutine_fn handle_write(BlockDriverState *bs, int64_t offset,
     }
 
     if (s->data_end < 0) {
-        s->data_end = bdrv_getlength(bs->file->bs);
+        s->data_end = bdrv_co_getlength(bs->file->bs);
         if (s->data_end < 0) {
             return false;
         }
@@ -308,7 +308,7 @@ static bool coroutine_fn handle_write(BlockDriverState *bs, int64_t offset,
     }
 
     if (s->file_end < 0) {
-        s->file_end = bdrv_getlength(bs->file->bs);
+        s->file_end = bdrv_co_getlength(bs->file->bs);
         if (s->file_end < 0) {
             return false;
         }
@@ -380,7 +380,7 @@ preallocate_co_truncate(BlockDriverState *bs, int64_t offset,
 
     if (s->data_end >= 0 && offset > s->data_end) {
         if (s->file_end < 0) {
-            s->file_end = bdrv_getlength(bs->file->bs);
+            s->file_end = bdrv_co_getlength(bs->file->bs);
             if (s->file_end < 0) {
                 error_setg(errp, "failed to get file length");
                 return s->file_end;
diff --git a/block/qed.c b/block/qed.c
index c8f9045b72..16bf0cb080 100644
--- a/block/qed.c
+++ b/block/qed.c
@@ -424,7 +424,7 @@ static int coroutine_fn bdrv_qed_do_open(BlockDriverState *bs, QDict *options,
     }
 
     /* Round down file size to the last cluster */
-    file_size = bdrv_getlength(bs->file->bs);
+    file_size = bdrv_co_getlength(bs->file->bs);
     if (file_size < 0) {
         error_setg(errp, "Failed to get file length");
         return file_size;
-- 
2.38.1



^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PULL 20/38] block: Convert bdrv_get_allocated_file_size() to co_wrapper
  2023-01-20 12:25 [PULL 00/38] Block layer patches Kevin Wolf
                   ` (18 preceding siblings ...)
  2023-01-20 12:26 ` [PULL 19/38] block: use bdrv_co_refresh_total_sectors when possible Kevin Wolf
@ 2023-01-20 12:26 ` Kevin Wolf
  2023-01-20 12:26 ` [PULL 21/38] block: Convert bdrv_get_info() to co_wrapper_mixed Kevin Wolf
                   ` (18 subsequent siblings)
  38 siblings, 0 replies; 48+ messages in thread
From: Kevin Wolf @ 2023-01-20 12:26 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, peter.maydell, qemu-devel

From: Emanuele Giuseppe Esposito <eesposit@redhat.com>

bdrv_get_allocated_file_size() is categorized as an I/O function, and it
currently doesn't run in a coroutine. We should let it take a graph
rdlock since it traverses the block nodes graph, which however is only
possible in a coroutine.

Therefore turn it into a co_wrapper to move the actual function into a
coroutine where the lock can be taken.

Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Message-Id: <20230113204212.359076-10-kwolf@redhat.com>
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 include/block/block-io.h         |  4 +++-
 include/block/block_int-common.h |  4 +++-
 block.c                          | 12 ++++++------
 block/file-posix.c               | 14 +++++---------
 block/file-win32.c               | 10 ++++------
 block/gluster.c                  | 11 ++++++-----
 block/nfs.c                      |  4 ++--
 block/null.c                     |  7 ++++---
 block/qcow2-refcount.c           |  2 +-
 block/vmdk.c                     |  9 +++++----
 10 files changed, 39 insertions(+), 38 deletions(-)

diff --git a/include/block/block-io.h b/include/block/block-io.h
index 3677d445a4..5b89b2d958 100644
--- a/include/block/block-io.h
+++ b/include/block/block-io.h
@@ -79,7 +79,9 @@ int64_t co_wrapper_mixed bdrv_nb_sectors(BlockDriverState *bs);
 int64_t coroutine_fn bdrv_co_getlength(BlockDriverState *bs);
 int64_t co_wrapper_mixed bdrv_getlength(BlockDriverState *bs);
 
-int64_t bdrv_get_allocated_file_size(BlockDriverState *bs);
+int64_t coroutine_fn bdrv_co_get_allocated_file_size(BlockDriverState *bs);
+int64_t co_wrapper bdrv_get_allocated_file_size(BlockDriverState *bs);
+
 BlockMeasureInfo *bdrv_measure(BlockDriver *drv, QemuOpts *opts,
                                BlockDriverState *in_bs, Error **errp);
 void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr);
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
index 6336c7239a..cc03c599e7 100644
--- a/include/block/block_int-common.h
+++ b/include/block/block_int-common.h
@@ -685,7 +685,9 @@ struct BlockDriver {
                                          bool exact, PreallocMode prealloc,
                                          BdrvRequestFlags flags, Error **errp);
     int64_t coroutine_fn (*bdrv_co_getlength)(BlockDriverState *bs);
-    int64_t (*bdrv_get_allocated_file_size)(BlockDriverState *bs);
+    int64_t coroutine_fn (*bdrv_co_get_allocated_file_size)(
+        BlockDriverState *bs);
+
     BlockMeasureInfo *(*bdrv_measure)(QemuOpts *opts, BlockDriverState *in_bs,
                                       Error **errp);
 
diff --git a/block.c b/block.c
index c8c3e42080..ed7e15f4d4 100644
--- a/block.c
+++ b/block.c
@@ -5719,7 +5719,7 @@ exit:
 }
 
 /**
- * Implementation of BlockDriver.bdrv_get_allocated_file_size() that
+ * Implementation of BlockDriver.bdrv_co_get_allocated_file_size() that
  * sums the size of all data-bearing children.  (This excludes backing
  * children.)
  */
@@ -5732,7 +5732,7 @@ static int64_t bdrv_sum_allocated_file_size(BlockDriverState *bs)
         if (child->role & (BDRV_CHILD_DATA | BDRV_CHILD_METADATA |
                            BDRV_CHILD_FILTERED))
         {
-            child_size = bdrv_get_allocated_file_size(child->bs);
+            child_size = bdrv_co_get_allocated_file_size(child->bs);
             if (child_size < 0) {
                 return child_size;
             }
@@ -5747,7 +5747,7 @@ static int64_t bdrv_sum_allocated_file_size(BlockDriverState *bs)
  * Length of a allocated file in bytes. Sparse files are counted by actual
  * allocated space. Return < 0 if error or unknown.
  */
-int64_t bdrv_get_allocated_file_size(BlockDriverState *bs)
+int64_t coroutine_fn bdrv_co_get_allocated_file_size(BlockDriverState *bs)
 {
     BlockDriver *drv = bs->drv;
     IO_CODE();
@@ -5755,8 +5755,8 @@ int64_t bdrv_get_allocated_file_size(BlockDriverState *bs)
     if (!drv) {
         return -ENOMEDIUM;
     }
-    if (drv->bdrv_get_allocated_file_size) {
-        return drv->bdrv_get_allocated_file_size(bs);
+    if (drv->bdrv_co_get_allocated_file_size) {
+        return drv->bdrv_co_get_allocated_file_size(bs);
     }
 
     if (drv->bdrv_file_open) {
@@ -5768,7 +5768,7 @@ int64_t bdrv_get_allocated_file_size(BlockDriverState *bs)
         return -ENOTSUP;
     } else if (drv->is_filter) {
         /* Filter drivers default to the size of their filtered child */
-        return bdrv_get_allocated_file_size(bdrv_filter_bs(bs));
+        return bdrv_co_get_allocated_file_size(bdrv_filter_bs(bs));
     } else {
         /* Other drivers default to summing their children's sizes */
         return bdrv_sum_allocated_file_size(bs);
diff --git a/block/file-posix.c b/block/file-posix.c
index ef1fce3782..dd6427a281 100644
--- a/block/file-posix.c
+++ b/block/file-posix.c
@@ -2463,7 +2463,7 @@ static int64_t coroutine_fn raw_co_getlength(BlockDriverState *bs)
 }
 #endif
 
-static int64_t raw_get_allocated_file_size(BlockDriverState *bs)
+static int64_t coroutine_fn raw_co_get_allocated_file_size(BlockDriverState *bs)
 {
     struct stat st;
     BDRVRawState *s = bs->opaque;
@@ -3323,8 +3323,7 @@ BlockDriver bdrv_file = {
     .bdrv_co_truncate                   = raw_co_truncate,
     .bdrv_co_getlength                  = raw_co_getlength,
     .bdrv_get_info = raw_get_info,
-    .bdrv_get_allocated_file_size
-                        = raw_get_allocated_file_size,
+    .bdrv_co_get_allocated_file_size    = raw_co_get_allocated_file_size,
     .bdrv_get_specific_stats = raw_get_specific_stats,
     .bdrv_check_perm = raw_check_perm,
     .bdrv_set_perm   = raw_set_perm,
@@ -3695,8 +3694,7 @@ static BlockDriver bdrv_host_device = {
     .bdrv_co_truncate                   = raw_co_truncate,
     .bdrv_co_getlength                  = raw_co_getlength,
     .bdrv_get_info = raw_get_info,
-    .bdrv_get_allocated_file_size
-                        = raw_get_allocated_file_size,
+    .bdrv_co_get_allocated_file_size    = raw_co_get_allocated_file_size,
     .bdrv_get_specific_stats = hdev_get_specific_stats,
     .bdrv_check_perm = raw_check_perm,
     .bdrv_set_perm   = raw_set_perm,
@@ -3819,8 +3817,7 @@ static BlockDriver bdrv_host_cdrom = {
     .bdrv_co_truncate                   = raw_co_truncate,
     .bdrv_co_getlength                  = raw_co_getlength,
     .has_variable_length                = true,
-    .bdrv_get_allocated_file_size
-                        = raw_get_allocated_file_size,
+    .bdrv_co_get_allocated_file_size    = raw_co_get_allocated_file_size,
 
     /* removable device support */
     .bdrv_co_is_inserted    = cdrom_co_is_inserted,
@@ -3949,8 +3946,7 @@ static BlockDriver bdrv_host_cdrom = {
     .bdrv_co_truncate                   = raw_co_truncate,
     .bdrv_co_getlength                  = raw_co_getlength,
     .has_variable_length                = true,
-    .bdrv_get_allocated_file_size
-                        = raw_get_allocated_file_size,
+    .bdrv_co_get_allocated_file_size    = raw_co_get_allocated_file_size,
 
     /* removable device support */
     .bdrv_co_is_inserted     = cdrom_co_is_inserted,
diff --git a/block/file-win32.c b/block/file-win32.c
index aedee695dd..6ff576b20d 100644
--- a/block/file-win32.c
+++ b/block/file-win32.c
@@ -558,7 +558,7 @@ static int64_t coroutine_fn raw_co_getlength(BlockDriverState *bs)
     return l.QuadPart;
 }
 
-static int64_t raw_get_allocated_file_size(BlockDriverState *bs)
+static int64_t coroutine_fn raw_co_get_allocated_file_size(BlockDriverState *bs)
 {
     typedef DWORD (WINAPI * get_compressed_t)(const char *filename,
                                               DWORD * high);
@@ -764,8 +764,8 @@ BlockDriver bdrv_file = {
 
     .bdrv_co_truncate   = raw_co_truncate,
     .bdrv_co_getlength  = raw_co_getlength,
-    .bdrv_get_allocated_file_size
-                        = raw_get_allocated_file_size,
+    .bdrv_co_get_allocated_file_size
+                        = raw_co_get_allocated_file_size,
 
     .create_opts        = &raw_create_opts,
 };
@@ -934,9 +934,7 @@ static BlockDriver bdrv_host_device = {
 
     .bdrv_co_getlength                = raw_co_getlength,
     .has_variable_length              = true,
-
-    .bdrv_get_allocated_file_size
-                        = raw_get_allocated_file_size,
+    .bdrv_co_get_allocated_file_size  = raw_co_get_allocated_file_size,
 };
 
 static void bdrv_file_init(void)
diff --git a/block/gluster.c b/block/gluster.c
index 469cdf01d4..7b4e1dd795 100644
--- a/block/gluster.c
+++ b/block/gluster.c
@@ -1330,7 +1330,8 @@ static int64_t coroutine_fn qemu_gluster_co_getlength(BlockDriverState *bs)
     }
 }
 
-static int64_t qemu_gluster_allocated_file_size(BlockDriverState *bs)
+static int64_t coroutine_fn
+qemu_gluster_co_get_allocated_file_size(BlockDriverState *bs)
 {
     BDRVGlusterState *s = bs->opaque;
     struct stat st;
@@ -1559,7 +1560,7 @@ static BlockDriver bdrv_gluster = {
     .bdrv_co_create               = qemu_gluster_co_create,
     .bdrv_co_create_opts          = qemu_gluster_co_create_opts,
     .bdrv_co_getlength            = qemu_gluster_co_getlength,
-    .bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size,
+    .bdrv_co_get_allocated_file_size = qemu_gluster_co_get_allocated_file_size,
     .bdrv_co_truncate             = qemu_gluster_co_truncate,
     .bdrv_co_readv                = qemu_gluster_co_readv,
     .bdrv_co_writev               = qemu_gluster_co_writev,
@@ -1588,7 +1589,7 @@ static BlockDriver bdrv_gluster_tcp = {
     .bdrv_co_create               = qemu_gluster_co_create,
     .bdrv_co_create_opts          = qemu_gluster_co_create_opts,
     .bdrv_co_getlength            = qemu_gluster_co_getlength,
-    .bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size,
+    .bdrv_co_get_allocated_file_size = qemu_gluster_co_get_allocated_file_size,
     .bdrv_co_truncate             = qemu_gluster_co_truncate,
     .bdrv_co_readv                = qemu_gluster_co_readv,
     .bdrv_co_writev               = qemu_gluster_co_writev,
@@ -1617,7 +1618,7 @@ static BlockDriver bdrv_gluster_unix = {
     .bdrv_co_create               = qemu_gluster_co_create,
     .bdrv_co_create_opts          = qemu_gluster_co_create_opts,
     .bdrv_co_getlength            = qemu_gluster_co_getlength,
-    .bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size,
+    .bdrv_co_get_allocated_file_size = qemu_gluster_co_get_allocated_file_size,
     .bdrv_co_truncate             = qemu_gluster_co_truncate,
     .bdrv_co_readv                = qemu_gluster_co_readv,
     .bdrv_co_writev               = qemu_gluster_co_writev,
@@ -1652,7 +1653,7 @@ static BlockDriver bdrv_gluster_rdma = {
     .bdrv_co_create               = qemu_gluster_co_create,
     .bdrv_co_create_opts          = qemu_gluster_co_create_opts,
     .bdrv_co_getlength            = qemu_gluster_co_getlength,
-    .bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size,
+    .bdrv_co_get_allocated_file_size = qemu_gluster_co_get_allocated_file_size,
     .bdrv_co_truncate             = qemu_gluster_co_truncate,
     .bdrv_co_readv                = qemu_gluster_co_readv,
     .bdrv_co_writev               = qemu_gluster_co_writev,
diff --git a/block/nfs.c b/block/nfs.c
index ece22353ac..cbf742661e 100644
--- a/block/nfs.c
+++ b/block/nfs.c
@@ -731,7 +731,7 @@ nfs_get_allocated_file_size_cb(int ret, struct nfs_context *nfs, void *data,
     bdrv_wakeup(task->bs);
 }
 
-static int64_t nfs_get_allocated_file_size(BlockDriverState *bs)
+static int64_t coroutine_fn nfs_co_get_allocated_file_size(BlockDriverState *bs)
 {
     NFSClient *client = bs->opaque;
     NFSRPC task = {0};
@@ -884,7 +884,7 @@ static BlockDriver bdrv_nfs = {
     .bdrv_has_zero_init             = nfs_has_zero_init,
 /* libnfs does not provide the allocated filesize of a file on win32. */
 #if !defined(_WIN32)
-    .bdrv_get_allocated_file_size   = nfs_get_allocated_file_size,
+    .bdrv_co_get_allocated_file_size = nfs_co_get_allocated_file_size,
 #endif
     .bdrv_co_truncate               = nfs_file_co_truncate,
 
diff --git a/block/null.c b/block/null.c
index 05dde6d9ab..aa5931effa 100644
--- a/block/null.c
+++ b/block/null.c
@@ -264,7 +264,8 @@ static void null_refresh_filename(BlockDriverState *bs)
              bs->drv->format_name);
 }
 
-static int64_t null_allocated_file_size(BlockDriverState *bs)
+static int64_t coroutine_fn
+null_co_get_allocated_file_size(BlockDriverState *bs)
 {
     return 0;
 }
@@ -284,7 +285,7 @@ static BlockDriver bdrv_null_co = {
     .bdrv_file_open         = null_file_open,
     .bdrv_parse_filename    = null_co_parse_filename,
     .bdrv_co_getlength      = null_co_getlength,
-    .bdrv_get_allocated_file_size = null_allocated_file_size,
+    .bdrv_co_get_allocated_file_size = null_co_get_allocated_file_size,
 
     .bdrv_co_preadv         = null_co_preadv,
     .bdrv_co_pwritev        = null_co_pwritev,
@@ -305,7 +306,7 @@ static BlockDriver bdrv_null_aio = {
     .bdrv_file_open         = null_file_open,
     .bdrv_parse_filename    = null_aio_parse_filename,
     .bdrv_co_getlength      = null_co_getlength,
-    .bdrv_get_allocated_file_size = null_allocated_file_size,
+    .bdrv_co_get_allocated_file_size = null_co_get_allocated_file_size,
 
     .bdrv_aio_preadv        = null_aio_preadv,
     .bdrv_aio_pwritev       = null_aio_pwritev,
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
index 81264740f0..487681d85e 100644
--- a/block/qcow2-refcount.c
+++ b/block/qcow2-refcount.c
@@ -3719,7 +3719,7 @@ int coroutine_fn qcow2_detect_metadata_preallocation(BlockDriverState *bs)
         return file_length;
     }
 
-    real_allocation = bdrv_get_allocated_file_size(bs->file->bs);
+    real_allocation = bdrv_co_get_allocated_file_size(bs->file->bs);
     if (real_allocation < 0) {
         return real_allocation;
     }
diff --git a/block/vmdk.c b/block/vmdk.c
index 8894dac2d4..04f50d2e49 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -2856,14 +2856,15 @@ static void vmdk_close(BlockDriverState *bs)
     error_free(s->migration_blocker);
 }
 
-static int64_t vmdk_get_allocated_file_size(BlockDriverState *bs)
+static int64_t coroutine_fn
+vmdk_co_get_allocated_file_size(BlockDriverState *bs)
 {
     int i;
     int64_t ret = 0;
     int64_t r;
     BDRVVmdkState *s = bs->opaque;
 
-    ret = bdrv_get_allocated_file_size(bs->file->bs);
+    ret = bdrv_co_get_allocated_file_size(bs->file->bs);
     if (ret < 0) {
         return ret;
     }
@@ -2871,7 +2872,7 @@ static int64_t vmdk_get_allocated_file_size(BlockDriverState *bs)
         if (s->extents[i].file == bs->file) {
             continue;
         }
-        r = bdrv_get_allocated_file_size(s->extents[i].file->bs);
+        r = bdrv_co_get_allocated_file_size(s->extents[i].file->bs);
         if (r < 0) {
             return r;
         }
@@ -3124,7 +3125,7 @@ static BlockDriver bdrv_vmdk = {
     .bdrv_co_create_opts          = vmdk_co_create_opts,
     .bdrv_co_create               = vmdk_co_create,
     .bdrv_co_block_status         = vmdk_co_block_status,
-    .bdrv_get_allocated_file_size = vmdk_get_allocated_file_size,
+    .bdrv_co_get_allocated_file_size = vmdk_co_get_allocated_file_size,
     .bdrv_has_zero_init           = vmdk_has_zero_init,
     .bdrv_get_specific_info       = vmdk_get_specific_info,
     .bdrv_refresh_limits          = vmdk_refresh_limits,
-- 
2.38.1



^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PULL 21/38] block: Convert bdrv_get_info() to co_wrapper_mixed
  2023-01-20 12:25 [PULL 00/38] Block layer patches Kevin Wolf
                   ` (19 preceding siblings ...)
  2023-01-20 12:26 ` [PULL 20/38] block: Convert bdrv_get_allocated_file_size() to co_wrapper Kevin Wolf
@ 2023-01-20 12:26 ` Kevin Wolf
  2023-01-20 12:26 ` [PULL 22/38] block: Convert bdrv_eject() to co_wrapper Kevin Wolf
                   ` (17 subsequent siblings)
  38 siblings, 0 replies; 48+ messages in thread
From: Kevin Wolf @ 2023-01-20 12:26 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, peter.maydell, qemu-devel

From: Emanuele Giuseppe Esposito <eesposit@redhat.com>

bdrv_get_info() is categorized as an I/O function, and it currently
doesn't run in a coroutine. We should let it take a graph rdlock since
it traverses the block nodes graph, which however is only possible in a
coroutine.

Therefore turn it into a co_wrapper to move the actual function into a
coroutine where the lock can be taken.

Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Message-Id: <20230113204212.359076-11-kwolf@redhat.com>
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 include/block/block-io.h         | 5 ++++-
 include/block/block_int-common.h | 3 ++-
 block.c                          | 8 ++++----
 block/blkio.c                    | 5 +++--
 block/crypto.c                   | 8 ++++----
 block/file-posix.c               | 7 ++++---
 block/io.c                       | 8 ++++----
 block/iscsi.c                    | 7 ++++---
 block/mirror.c                   | 2 +-
 block/qcow.c                     | 5 +++--
 block/qcow2.c                    | 5 +++--
 block/qed.c                      | 5 +++--
 block/raw-format.c               | 7 ++++---
 block/rbd.c                      | 5 +++--
 block/vdi.c                      | 7 ++++---
 block/vhdx.c                     | 5 +++--
 block/vmdk.c                     | 5 +++--
 block/vpc.c                      | 5 +++--
 18 files changed, 59 insertions(+), 43 deletions(-)

diff --git a/include/block/block-io.h b/include/block/block-io.h
index 5b89b2d958..3a01923a0b 100644
--- a/include/block/block-io.h
+++ b/include/block/block-io.h
@@ -151,7 +151,10 @@ bool bdrv_supports_compressed_writes(BlockDriverState *bs);
 const char *bdrv_get_node_name(const BlockDriverState *bs);
 const char *bdrv_get_device_name(const BlockDriverState *bs);
 const char *bdrv_get_device_or_node_name(const BlockDriverState *bs);
-int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi);
+
+int coroutine_fn bdrv_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi);
+int co_wrapper_mixed bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi);
+
 ImageInfoSpecific *bdrv_get_specific_info(BlockDriverState *bs,
                                           Error **errp);
 BlockStatsSpecific *bdrv_get_specific_stats(BlockDriverState *bs);
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
index cc03c599e7..a6ac8afd5b 100644
--- a/include/block/block_int-common.h
+++ b/include/block/block_int-common.h
@@ -697,7 +697,8 @@ struct BlockDriver {
         int64_t offset, int64_t bytes, QEMUIOVector *qiov,
         size_t qiov_offset);
 
-    int (*bdrv_get_info)(BlockDriverState *bs, BlockDriverInfo *bdi);
+    int coroutine_fn (*bdrv_co_get_info)(BlockDriverState *bs,
+                                         BlockDriverInfo *bdi);
 
     ImageInfoSpecific *(*bdrv_get_specific_info)(BlockDriverState *bs,
                                                  Error **errp);
diff --git a/block.c b/block.c
index ed7e15f4d4..907239c267 100644
--- a/block.c
+++ b/block.c
@@ -6300,7 +6300,7 @@ void bdrv_get_backing_filename(BlockDriverState *bs,
     pstrcpy(filename, filename_size, bs->backing_file);
 }
 
-int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
+int coroutine_fn bdrv_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
 {
     int ret;
     BlockDriver *drv = bs->drv;
@@ -6309,15 +6309,15 @@ int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
     if (!drv) {
         return -ENOMEDIUM;
     }
-    if (!drv->bdrv_get_info) {
+    if (!drv->bdrv_co_get_info) {
         BlockDriverState *filtered = bdrv_filter_bs(bs);
         if (filtered) {
-            return bdrv_get_info(filtered, bdi);
+            return bdrv_co_get_info(filtered, bdi);
         }
         return -ENOTSUP;
     }
     memset(bdi, 0, sizeof(*bdi));
-    ret = drv->bdrv_get_info(bs, bdi);
+    ret = drv->bdrv_co_get_info(bs, bdi);
     if (ret < 0) {
         return ret;
     }
diff --git a/block/blkio.c b/block/blkio.c
index 2a3ab5a570..fc83e0fe13 100644
--- a/block/blkio.c
+++ b/block/blkio.c
@@ -878,7 +878,8 @@ static int coroutine_fn blkio_truncate(BlockDriverState *bs, int64_t offset,
     return 0;
 }
 
-static int blkio_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
+static int coroutine_fn
+blkio_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
 {
     return 0;
 }
@@ -998,7 +999,7 @@ static void blkio_refresh_limits(BlockDriverState *bs, Error **errp)
         .bdrv_close              = blkio_close, \
         .bdrv_co_getlength       = blkio_co_getlength, \
         .bdrv_co_truncate        = blkio_truncate, \
-        .bdrv_get_info           = blkio_get_info, \
+        .bdrv_co_get_info        = blkio_co_get_info, \
         .bdrv_attach_aio_context = blkio_attach_aio_context, \
         .bdrv_detach_aio_context = blkio_detach_aio_context, \
         .bdrv_co_pdiscard        = blkio_co_pdiscard, \
diff --git a/block/crypto.c b/block/crypto.c
index 6d6c006887..b70cec97c7 100644
--- a/block/crypto.c
+++ b/block/crypto.c
@@ -737,13 +737,13 @@ fail:
     return ret;
 }
 
-static int block_crypto_get_info_luks(BlockDriverState *bs,
-                                      BlockDriverInfo *bdi)
+static int coroutine_fn
+block_crypto_co_get_info_luks(BlockDriverState *bs, BlockDriverInfo *bdi)
 {
     BlockDriverInfo subbdi;
     int ret;
 
-    ret = bdrv_get_info(bs->file->bs, &subbdi);
+    ret = bdrv_co_get_info(bs->file->bs, &subbdi);
     if (ret != 0) {
         return ret;
     }
@@ -955,7 +955,7 @@ static BlockDriver bdrv_crypto_luks = {
     .bdrv_co_pwritev    = block_crypto_co_pwritev,
     .bdrv_co_getlength  = block_crypto_co_getlength,
     .bdrv_measure       = block_crypto_measure,
-    .bdrv_get_info      = block_crypto_get_info_luks,
+    .bdrv_co_get_info   = block_crypto_co_get_info_luks,
     .bdrv_get_specific_info = block_crypto_get_specific_info_luks,
     .bdrv_amend_options = block_crypto_amend_options_luks,
     .bdrv_co_amend      = block_crypto_co_amend_luks,
diff --git a/block/file-posix.c b/block/file-posix.c
index dd6427a281..2d7c2cbdd7 100644
--- a/block/file-posix.c
+++ b/block/file-posix.c
@@ -3085,7 +3085,8 @@ static int coroutine_fn raw_co_pwrite_zeroes(
     return raw_do_pwrite_zeroes(bs, offset, bytes, flags, false);
 }
 
-static int raw_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
+static int coroutine_fn
+raw_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
 {
     return 0;
 }
@@ -3322,7 +3323,7 @@ BlockDriver bdrv_file = {
 
     .bdrv_co_truncate                   = raw_co_truncate,
     .bdrv_co_getlength                  = raw_co_getlength,
-    .bdrv_get_info = raw_get_info,
+    .bdrv_co_get_info                   = raw_co_get_info,
     .bdrv_co_get_allocated_file_size    = raw_co_get_allocated_file_size,
     .bdrv_get_specific_stats = raw_get_specific_stats,
     .bdrv_check_perm = raw_check_perm,
@@ -3693,7 +3694,7 @@ static BlockDriver bdrv_host_device = {
 
     .bdrv_co_truncate                   = raw_co_truncate,
     .bdrv_co_getlength                  = raw_co_getlength,
-    .bdrv_get_info = raw_get_info,
+    .bdrv_co_get_info                   = raw_co_get_info,
     .bdrv_co_get_allocated_file_size    = raw_co_get_allocated_file_size,
     .bdrv_get_specific_stats = hdev_get_specific_stats,
     .bdrv_check_perm = raw_check_perm,
diff --git a/block/io.c b/block/io.c
index fdc5ba9fb6..c43637f5c1 100644
--- a/block/io.c
+++ b/block/io.c
@@ -721,14 +721,14 @@ BdrvTrackedRequest *coroutine_fn bdrv_co_get_self_request(BlockDriverState *bs)
 /**
  * Round a region to cluster boundaries
  */
-void bdrv_round_to_clusters(BlockDriverState *bs,
+void coroutine_fn bdrv_round_to_clusters(BlockDriverState *bs,
                             int64_t offset, int64_t bytes,
                             int64_t *cluster_offset,
                             int64_t *cluster_bytes)
 {
     BlockDriverInfo bdi;
     IO_CODE();
-    if (bdrv_get_info(bs, &bdi) < 0 || bdi.cluster_size == 0) {
+    if (bdrv_co_get_info(bs, &bdi) < 0 || bdi.cluster_size == 0) {
         *cluster_offset = offset;
         *cluster_bytes = bytes;
     } else {
@@ -738,12 +738,12 @@ void bdrv_round_to_clusters(BlockDriverState *bs,
     }
 }
 
-static int bdrv_get_cluster_size(BlockDriverState *bs)
+static coroutine_fn int bdrv_get_cluster_size(BlockDriverState *bs)
 {
     BlockDriverInfo bdi;
     int ret;
 
-    ret = bdrv_get_info(bs, &bdi);
+    ret = bdrv_co_get_info(bs, &bdi);
     if (ret < 0 || bdi.cluster_size == 0) {
         return bs->bl.request_alignment;
     } else {
diff --git a/block/iscsi.c b/block/iscsi.c
index df110dd1d2..b17b86cffd 100644
--- a/block/iscsi.c
+++ b/block/iscsi.c
@@ -2170,7 +2170,8 @@ static int coroutine_fn iscsi_co_truncate(BlockDriverState *bs, int64_t offset,
     return 0;
 }
 
-static int iscsi_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
+static int coroutine_fn
+iscsi_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
 {
     IscsiLun *iscsilun = bs->opaque;
     bdi->cluster_size = iscsilun->cluster_size;
@@ -2434,7 +2435,7 @@ static BlockDriver bdrv_iscsi = {
     .bdrv_co_invalidate_cache = iscsi_co_invalidate_cache,
 
     .bdrv_co_getlength   = iscsi_co_getlength,
-    .bdrv_get_info   = iscsi_get_info,
+    .bdrv_co_get_info    = iscsi_co_get_info,
     .bdrv_co_truncate    = iscsi_co_truncate,
     .bdrv_refresh_limits = iscsi_refresh_limits,
 
@@ -2473,7 +2474,7 @@ static BlockDriver bdrv_iser = {
     .bdrv_co_invalidate_cache  = iscsi_co_invalidate_cache,
 
     .bdrv_co_getlength   = iscsi_co_getlength,
-    .bdrv_get_info   = iscsi_get_info,
+    .bdrv_co_get_info    = iscsi_co_get_info,
     .bdrv_co_truncate    = iscsi_co_truncate,
     .bdrv_refresh_limits = iscsi_refresh_limits,
 
diff --git a/block/mirror.c b/block/mirror.c
index c7d7ce2f8f..26db3ad0d7 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -956,7 +956,7 @@ static int coroutine_fn mirror_run(Job *job, Error **errp)
      */
     bdrv_get_backing_filename(target_bs, backing_filename,
                               sizeof(backing_filename));
-    if (!bdrv_get_info(target_bs, &bdi) && bdi.cluster_size) {
+    if (!bdrv_co_get_info(target_bs, &bdi) && bdi.cluster_size) {
         s->target_cluster_size = bdi.cluster_size;
     } else {
         s->target_cluster_size = BDRV_SECTOR_SIZE;
diff --git a/block/qcow.c b/block/qcow.c
index 5d99f00411..5f0801f545 100644
--- a/block/qcow.c
+++ b/block/qcow.c
@@ -1129,7 +1129,8 @@ fail:
     return ret;
 }
 
-static int qcow_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
+static int coroutine_fn
+qcow_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
 {
     BDRVQcowState *s = bs->opaque;
     bdi->cluster_size = s->cluster_size;
@@ -1198,7 +1199,7 @@ static BlockDriver bdrv_qcow = {
 
     .bdrv_make_empty        = qcow_make_empty,
     .bdrv_co_pwritev_compressed = qcow_co_pwritev_compressed,
-    .bdrv_get_info          = qcow_get_info,
+    .bdrv_co_get_info       = qcow_co_get_info,
 
     .create_opts            = &qcow_create_opts,
     .strong_runtime_opts    = qcow_strong_runtime_opts,
diff --git a/block/qcow2.c b/block/qcow2.c
index bafbd077b9..460579b70a 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -5142,7 +5142,8 @@ err:
     return NULL;
 }
 
-static int qcow2_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
+static int coroutine_fn
+qcow2_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
 {
     BDRVQcow2State *s = bs->opaque;
     bdi->cluster_size = s->cluster_size;
@@ -6076,7 +6077,7 @@ BlockDriver bdrv_qcow2 = {
     .bdrv_snapshot_list     = qcow2_snapshot_list,
     .bdrv_snapshot_load_tmp = qcow2_snapshot_load_tmp,
     .bdrv_measure           = qcow2_measure,
-    .bdrv_get_info          = qcow2_get_info,
+    .bdrv_co_get_info       = qcow2_co_get_info,
     .bdrv_get_specific_info = qcow2_get_specific_info,
 
     .bdrv_save_vmstate    = qcow2_save_vmstate,
diff --git a/block/qed.c b/block/qed.c
index 16bf0cb080..4473465bba 100644
--- a/block/qed.c
+++ b/block/qed.c
@@ -1486,7 +1486,8 @@ static int64_t coroutine_fn bdrv_qed_co_getlength(BlockDriverState *bs)
     return s->header.image_size;
 }
 
-static int bdrv_qed_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
+static int coroutine_fn
+bdrv_qed_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
 {
     BDRVQEDState *s = bs->opaque;
 
@@ -1654,7 +1655,7 @@ static BlockDriver bdrv_qed = {
     .bdrv_co_pwrite_zeroes    = bdrv_qed_co_pwrite_zeroes,
     .bdrv_co_truncate         = bdrv_qed_co_truncate,
     .bdrv_co_getlength        = bdrv_qed_co_getlength,
-    .bdrv_get_info            = bdrv_qed_get_info,
+    .bdrv_co_get_info         = bdrv_qed_co_get_info,
     .bdrv_refresh_limits      = bdrv_qed_refresh_limits,
     .bdrv_change_backing_file = bdrv_qed_change_backing_file,
     .bdrv_co_invalidate_cache = bdrv_qed_co_invalidate_cache,
diff --git a/block/raw-format.c b/block/raw-format.c
index ccf23fe0b2..08f5c74838 100644
--- a/block/raw-format.c
+++ b/block/raw-format.c
@@ -367,9 +367,10 @@ static BlockMeasureInfo *raw_measure(QemuOpts *opts, BlockDriverState *in_bs,
     return info;
 }
 
-static int raw_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
+static int coroutine_fn
+raw_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
 {
-    return bdrv_get_info(bs->file->bs, bdi);
+    return bdrv_co_get_info(bs->file->bs, bdi);
 }
 
 static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
@@ -625,7 +626,7 @@ BlockDriver bdrv_raw = {
     .is_format            = true,
     .has_variable_length  = true,
     .bdrv_measure         = &raw_measure,
-    .bdrv_get_info        = &raw_get_info,
+    .bdrv_co_get_info     = &raw_co_get_info,
     .bdrv_refresh_limits  = &raw_refresh_limits,
     .bdrv_probe_blocksizes = &raw_probe_blocksizes,
     .bdrv_probe_geometry  = &raw_probe_geometry,
diff --git a/block/rbd.c b/block/rbd.c
index c67d30160a..2c03ab8408 100644
--- a/block/rbd.c
+++ b/block/rbd.c
@@ -1239,7 +1239,8 @@ coroutine_fn qemu_rbd_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset,
 }
 #endif
 
-static int qemu_rbd_getinfo(BlockDriverState *bs, BlockDriverInfo *bdi)
+static int coroutine_fn
+qemu_rbd_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
 {
     BDRVRBDState *s = bs->opaque;
     bdi->cluster_size = s->object_size;
@@ -1650,7 +1651,7 @@ static BlockDriver bdrv_rbd = {
     .bdrv_co_create         = qemu_rbd_co_create,
     .bdrv_co_create_opts    = qemu_rbd_co_create_opts,
     .bdrv_has_zero_init     = bdrv_has_zero_init_1,
-    .bdrv_get_info          = qemu_rbd_getinfo,
+    .bdrv_co_get_info       = qemu_rbd_co_get_info,
     .bdrv_get_specific_info = qemu_rbd_get_specific_info,
     .create_opts            = &qemu_rbd_create_opts,
     .bdrv_co_getlength      = qemu_rbd_co_getlength,
diff --git a/block/vdi.c b/block/vdi.c
index 479bcfe820..9c8736b26f 100644
--- a/block/vdi.c
+++ b/block/vdi.c
@@ -327,9 +327,10 @@ static int coroutine_fn vdi_co_check(BlockDriverState *bs, BdrvCheckResult *res,
     return 0;
 }
 
-static int vdi_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
+static int coroutine_fn
+vdi_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
 {
-    /* TODO: vdi_get_info would be needed for machine snapshots.
+    /* TODO: vdi_co_get_info would be needed for machine snapshots.
        vm_state_offset is still missing. */
     BDRVVdiState *s = (BDRVVdiState *)bs->opaque;
     logout("\n");
@@ -1049,7 +1050,7 @@ static BlockDriver bdrv_vdi = {
     .bdrv_co_pwritev    = vdi_co_pwritev,
 #endif
 
-    .bdrv_get_info = vdi_get_info,
+    .bdrv_co_get_info = vdi_co_get_info,
 
     .is_format = true,
     .create_opts = &vdi_create_opts,
diff --git a/block/vhdx.c b/block/vhdx.c
index 4c929800fe..ef1f65d917 100644
--- a/block/vhdx.c
+++ b/block/vhdx.c
@@ -1161,7 +1161,8 @@ static void vhdx_block_translate(BDRVVHDXState *s, int64_t sector_num,
 }
 
 
-static int vhdx_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
+static int coroutine_fn
+vhdx_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
 {
     BDRVVHDXState *s = bs->opaque;
 
@@ -2245,7 +2246,7 @@ static BlockDriver bdrv_vhdx = {
     .bdrv_co_writev         = vhdx_co_writev,
     .bdrv_co_create         = vhdx_co_create,
     .bdrv_co_create_opts    = vhdx_co_create_opts,
-    .bdrv_get_info          = vhdx_get_info,
+    .bdrv_co_get_info       = vhdx_co_get_info,
     .bdrv_co_check          = vhdx_co_check,
     .bdrv_has_zero_init     = vhdx_has_zero_init,
 
diff --git a/block/vmdk.c b/block/vmdk.c
index 04f50d2e49..1bba61ad7d 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -3012,7 +3012,8 @@ static bool vmdk_extents_type_eq(const VmdkExtent *a, const VmdkExtent *b)
            (a->flat || a->cluster_sectors == b->cluster_sectors);
 }
 
-static int vmdk_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
+static int coroutine_fn
+vmdk_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
 {
     int i;
     BDRVVmdkState *s = bs->opaque;
@@ -3129,7 +3130,7 @@ static BlockDriver bdrv_vmdk = {
     .bdrv_has_zero_init           = vmdk_has_zero_init,
     .bdrv_get_specific_info       = vmdk_get_specific_info,
     .bdrv_refresh_limits          = vmdk_refresh_limits,
-    .bdrv_get_info                = vmdk_get_info,
+    .bdrv_co_get_info             = vmdk_co_get_info,
     .bdrv_gather_child_options    = vmdk_gather_child_options,
 
     .is_format                    = true,
diff --git a/block/vpc.c b/block/vpc.c
index 6ee95dcb96..cfdea7db80 100644
--- a/block/vpc.c
+++ b/block/vpc.c
@@ -598,7 +598,8 @@ fail:
     return ret;
 }
 
-static int vpc_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
+static int coroutine_fn
+vpc_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
 {
     BDRVVPCState *s = (BDRVVPCState *)bs->opaque;
 
@@ -1240,7 +1241,7 @@ static BlockDriver bdrv_vpc = {
     .bdrv_co_pwritev            = vpc_co_pwritev,
     .bdrv_co_block_status       = vpc_co_block_status,
 
-    .bdrv_get_info          = vpc_get_info,
+    .bdrv_co_get_info       = vpc_co_get_info,
 
     .is_format              = true,
     .create_opts            = &vpc_create_opts,
-- 
2.38.1



^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PULL 22/38] block: Convert bdrv_eject() to co_wrapper
  2023-01-20 12:25 [PULL 00/38] Block layer patches Kevin Wolf
                   ` (20 preceding siblings ...)
  2023-01-20 12:26 ` [PULL 21/38] block: Convert bdrv_get_info() to co_wrapper_mixed Kevin Wolf
@ 2023-01-20 12:26 ` Kevin Wolf
  2023-01-20 12:26 ` [PULL 23/38] block: Convert bdrv_lock_medium() " Kevin Wolf
                   ` (16 subsequent siblings)
  38 siblings, 0 replies; 48+ messages in thread
From: Kevin Wolf @ 2023-01-20 12:26 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, peter.maydell, qemu-devel

From: Emanuele Giuseppe Esposito <eesposit@redhat.com>

bdrv_eject() is categorized as an I/O function, and it currently
doesn't run in a coroutine. We should let it take a graph rdlock since
it traverses the block nodes graph, which however is only possible in a
coroutine.

The only caller of this function is blk_eject(). Therefore make
blk_eject() a co_wrapper, so that it always creates a new coroutine, and
then make bdrv_eject() coroutine_fn where the lock can be taken.

Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Message-Id: <20230113204212.359076-12-kwolf@redhat.com>
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 include/block/block-io.h          | 3 ++-
 include/block/block_int-common.h  | 2 +-
 include/sysemu/block-backend-io.h | 4 +++-
 block.c                           | 6 +++---
 block/block-backend.c             | 4 ++--
 block/copy-on-read.c              | 6 +++---
 block/file-posix.c                | 8 ++++----
 block/filter-compress.c           | 7 ++++---
 block/raw-format.c                | 6 +++---
 9 files changed, 25 insertions(+), 21 deletions(-)

diff --git a/include/block/block-io.h b/include/block/block-io.h
index 3a01923a0b..f84d2b7238 100644
--- a/include/block/block-io.h
+++ b/include/block/block-io.h
@@ -144,7 +144,8 @@ bool coroutine_fn bdrv_co_is_inserted(BlockDriverState *bs);
 bool co_wrapper bdrv_is_inserted(BlockDriverState *bs);
 
 void bdrv_lock_medium(BlockDriverState *bs, bool locked);
-void bdrv_eject(BlockDriverState *bs, bool eject_flag);
+void coroutine_fn bdrv_co_eject(BlockDriverState *bs, bool eject_flag);
+
 const char *bdrv_get_format_name(BlockDriverState *bs);
 
 bool bdrv_supports_compressed_writes(BlockDriverState *bs);
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
index a6ac8afd5b..1631a26427 100644
--- a/include/block/block_int-common.h
+++ b/include/block/block_int-common.h
@@ -712,7 +712,7 @@ struct BlockDriver {
 
     /* removable device specific */
     bool coroutine_fn (*bdrv_co_is_inserted)(BlockDriverState *bs);
-    void (*bdrv_eject)(BlockDriverState *bs, bool eject_flag);
+    void coroutine_fn (*bdrv_co_eject)(BlockDriverState *bs, bool eject_flag);
     void (*bdrv_lock_medium)(BlockDriverState *bs, bool locked);
 
     /* to control generic scsi devices */
diff --git a/include/sysemu/block-backend-io.h b/include/sysemu/block-backend-io.h
index a1eac6c00a..00209625e1 100644
--- a/include/sysemu/block-backend-io.h
+++ b/include/sysemu/block-backend-io.h
@@ -59,7 +59,9 @@ bool co_wrapper_mixed blk_is_inserted(BlockBackend *blk);
 
 bool blk_is_available(BlockBackend *blk);
 void blk_lock_medium(BlockBackend *blk, bool locked);
-void blk_eject(BlockBackend *blk, bool eject_flag);
+
+void coroutine_fn blk_co_eject(BlockBackend *blk, bool eject_flag);
+void co_wrapper blk_eject(BlockBackend *blk, bool eject_flag);
 
 int64_t coroutine_fn blk_co_getlength(BlockBackend *blk);
 int64_t co_wrapper_mixed blk_getlength(BlockBackend *blk);
diff --git a/block.c b/block.c
index 907239c267..1092ac26d1 100644
--- a/block.c
+++ b/block.c
@@ -6820,13 +6820,13 @@ bool coroutine_fn bdrv_co_is_inserted(BlockDriverState *bs)
 /**
  * If eject_flag is TRUE, eject the media. Otherwise, close the tray
  */
-void bdrv_eject(BlockDriverState *bs, bool eject_flag)
+void coroutine_fn bdrv_co_eject(BlockDriverState *bs, bool eject_flag)
 {
     BlockDriver *drv = bs->drv;
     IO_CODE();
 
-    if (drv && drv->bdrv_eject) {
-        drv->bdrv_eject(bs, eject_flag);
+    if (drv && drv->bdrv_co_eject) {
+        drv->bdrv_co_eject(bs, eject_flag);
     }
 }
 
diff --git a/block/block-backend.c b/block/block-backend.c
index b4a8d259cf..7eaafc85b1 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -2009,14 +2009,14 @@ void blk_lock_medium(BlockBackend *blk, bool locked)
     }
 }
 
-void blk_eject(BlockBackend *blk, bool eject_flag)
+void coroutine_fn blk_co_eject(BlockBackend *blk, bool eject_flag)
 {
     BlockDriverState *bs = blk_bs(blk);
     char *id;
     IO_CODE();
 
     if (bs) {
-        bdrv_eject(bs, eject_flag);
+        bdrv_co_eject(bs, eject_flag);
     }
 
     /* Whether or not we ejected on the backend,
diff --git a/block/copy-on-read.c b/block/copy-on-read.c
index 41777b87a4..43f09514dc 100644
--- a/block/copy-on-read.c
+++ b/block/copy-on-read.c
@@ -216,9 +216,9 @@ static int coroutine_fn cor_co_pwritev_compressed(BlockDriverState *bs,
 }
 
 
-static void cor_eject(BlockDriverState *bs, bool eject_flag)
+static void coroutine_fn cor_co_eject(BlockDriverState *bs, bool eject_flag)
 {
-    bdrv_eject(bs->file->bs, eject_flag);
+    bdrv_co_eject(bs->file->bs, eject_flag);
 }
 
 
@@ -257,7 +257,7 @@ static BlockDriver bdrv_copy_on_read = {
     .bdrv_co_pdiscard                   = cor_co_pdiscard,
     .bdrv_co_pwritev_compressed         = cor_co_pwritev_compressed,
 
-    .bdrv_eject                         = cor_eject,
+    .bdrv_co_eject                      = cor_co_eject,
     .bdrv_lock_medium                   = cor_lock_medium,
 
     .has_variable_length                = true,
diff --git a/block/file-posix.c b/block/file-posix.c
index 2d7c2cbdd7..cfa614fea2 100644
--- a/block/file-posix.c
+++ b/block/file-posix.c
@@ -3764,7 +3764,7 @@ static bool coroutine_fn cdrom_co_is_inserted(BlockDriverState *bs)
     return ret == CDS_DISC_OK;
 }
 
-static void cdrom_eject(BlockDriverState *bs, bool eject_flag)
+static void coroutine_fn cdrom_co_eject(BlockDriverState *bs, bool eject_flag)
 {
     BDRVRawState *s = bs->opaque;
 
@@ -3822,7 +3822,7 @@ static BlockDriver bdrv_host_cdrom = {
 
     /* removable device support */
     .bdrv_co_is_inserted    = cdrom_co_is_inserted,
-    .bdrv_eject         = cdrom_eject,
+    .bdrv_co_eject          = cdrom_co_eject,
     .bdrv_lock_medium   = cdrom_lock_medium,
 
     /* generic scsi device */
@@ -3885,7 +3885,7 @@ static bool coroutine_fn cdrom_co_is_inserted(BlockDriverState *bs)
     return raw_co_getlength(bs) > 0;
 }
 
-static void cdrom_eject(BlockDriverState *bs, bool eject_flag)
+static void coroutine_fn cdrom_co_eject(BlockDriverState *bs, bool eject_flag)
 {
     BDRVRawState *s = bs->opaque;
 
@@ -3951,7 +3951,7 @@ static BlockDriver bdrv_host_cdrom = {
 
     /* removable device support */
     .bdrv_co_is_inserted     = cdrom_co_is_inserted,
-    .bdrv_eject         = cdrom_eject,
+    .bdrv_co_eject           = cdrom_co_eject,
     .bdrv_lock_medium   = cdrom_lock_medium,
 };
 #endif /* __FreeBSD__ */
diff --git a/block/filter-compress.c b/block/filter-compress.c
index 1515fe5103..97adb3de19 100644
--- a/block/filter-compress.c
+++ b/block/filter-compress.c
@@ -116,9 +116,10 @@ static void compress_refresh_limits(BlockDriverState *bs, Error **errp)
 }
 
 
-static void compress_eject(BlockDriverState *bs, bool eject_flag)
+static void coroutine_fn
+compress_co_eject(BlockDriverState *bs, bool eject_flag)
 {
-    bdrv_eject(bs->file->bs, eject_flag);
+    bdrv_co_eject(bs->file->bs, eject_flag);
 }
 
 
@@ -142,7 +143,7 @@ static BlockDriver bdrv_compress = {
     .bdrv_co_pdiscard                   = compress_co_pdiscard,
     .bdrv_refresh_limits                = compress_refresh_limits,
 
-    .bdrv_eject                         = compress_eject,
+    .bdrv_co_eject                      = compress_co_eject,
     .bdrv_lock_medium                   = compress_lock_medium,
 
     .has_variable_length                = true,
diff --git a/block/raw-format.c b/block/raw-format.c
index 08f5c74838..2585e9ef96 100644
--- a/block/raw-format.c
+++ b/block/raw-format.c
@@ -404,9 +404,9 @@ static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
     return bdrv_co_truncate(bs->file, offset, exact, prealloc, flags, errp);
 }
 
-static void raw_eject(BlockDriverState *bs, bool eject_flag)
+static void coroutine_fn raw_co_eject(BlockDriverState *bs, bool eject_flag)
 {
-    bdrv_eject(bs->file->bs, eject_flag);
+    bdrv_co_eject(bs->file->bs, eject_flag);
 }
 
 static void raw_lock_medium(BlockDriverState *bs, bool locked)
@@ -630,7 +630,7 @@ BlockDriver bdrv_raw = {
     .bdrv_refresh_limits  = &raw_refresh_limits,
     .bdrv_probe_blocksizes = &raw_probe_blocksizes,
     .bdrv_probe_geometry  = &raw_probe_geometry,
-    .bdrv_eject           = &raw_eject,
+    .bdrv_co_eject        = &raw_co_eject,
     .bdrv_lock_medium     = &raw_lock_medium,
     .bdrv_co_ioctl        = &raw_co_ioctl,
     .create_opts          = &raw_create_opts,
-- 
2.38.1



^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PULL 23/38] block: Convert bdrv_lock_medium() to co_wrapper
  2023-01-20 12:25 [PULL 00/38] Block layer patches Kevin Wolf
                   ` (21 preceding siblings ...)
  2023-01-20 12:26 ` [PULL 22/38] block: Convert bdrv_eject() to co_wrapper Kevin Wolf
@ 2023-01-20 12:26 ` Kevin Wolf
  2023-01-20 12:26 ` [PULL 24/38] block: Convert bdrv_debug_event() to co_wrapper_mixed Kevin Wolf
                   ` (15 subsequent siblings)
  38 siblings, 0 replies; 48+ messages in thread
From: Kevin Wolf @ 2023-01-20 12:26 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, peter.maydell, qemu-devel

From: Emanuele Giuseppe Esposito <eesposit@redhat.com>

bdrv_lock_medium() is categorized as an I/O function, and it currently
doesn't run in a coroutine. We should let it take a graph rdlock since
it traverses the block nodes graph, which however is only possible in a
coroutine.

The only caller of this function is blk_lock_medium(). Therefore make
blk_lock_medium() a co_wrapper, so that it always creates a new
coroutine, and then make bdrv_lock_medium() a coroutine_fn where the
lock can be taken.

Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Message-Id: <20230113204212.359076-13-kwolf@redhat.com>
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 include/block/block-io.h          | 2 +-
 include/block/block_int-common.h  | 2 +-
 include/sysemu/block-backend-io.h | 4 +++-
 block.c                           | 6 +++---
 block/block-backend.c             | 4 ++--
 block/copy-on-read.c              | 6 +++---
 block/file-posix.c                | 8 ++++----
 block/filter-compress.c           | 7 ++++---
 block/raw-format.c                | 6 +++---
 9 files changed, 24 insertions(+), 21 deletions(-)

diff --git a/include/block/block-io.h b/include/block/block-io.h
index f84d2b7238..33e0cc2068 100644
--- a/include/block/block-io.h
+++ b/include/block/block-io.h
@@ -143,7 +143,7 @@ int bdrv_get_flags(BlockDriverState *bs);
 bool coroutine_fn bdrv_co_is_inserted(BlockDriverState *bs);
 bool co_wrapper bdrv_is_inserted(BlockDriverState *bs);
 
-void bdrv_lock_medium(BlockDriverState *bs, bool locked);
+void coroutine_fn bdrv_co_lock_medium(BlockDriverState *bs, bool locked);
 void coroutine_fn bdrv_co_eject(BlockDriverState *bs, bool eject_flag);
 
 const char *bdrv_get_format_name(BlockDriverState *bs);
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
index 1631a26427..1174f13a2f 100644
--- a/include/block/block_int-common.h
+++ b/include/block/block_int-common.h
@@ -713,7 +713,7 @@ struct BlockDriver {
     /* removable device specific */
     bool coroutine_fn (*bdrv_co_is_inserted)(BlockDriverState *bs);
     void coroutine_fn (*bdrv_co_eject)(BlockDriverState *bs, bool eject_flag);
-    void (*bdrv_lock_medium)(BlockDriverState *bs, bool locked);
+    void coroutine_fn (*bdrv_co_lock_medium)(BlockDriverState *bs, bool locked);
 
     /* to control generic scsi devices */
     BlockAIOCB *(*bdrv_aio_ioctl)(BlockDriverState *bs,
diff --git a/include/sysemu/block-backend-io.h b/include/sysemu/block-backend-io.h
index 00209625e1..780c1e5f77 100644
--- a/include/sysemu/block-backend-io.h
+++ b/include/sysemu/block-backend-io.h
@@ -58,7 +58,9 @@ bool coroutine_fn blk_co_is_inserted(BlockBackend *blk);
 bool co_wrapper_mixed blk_is_inserted(BlockBackend *blk);
 
 bool blk_is_available(BlockBackend *blk);
-void blk_lock_medium(BlockBackend *blk, bool locked);
+
+void coroutine_fn blk_co_lock_medium(BlockBackend *blk, bool locked);
+void co_wrapper blk_lock_medium(BlockBackend *blk, bool locked);
 
 void coroutine_fn blk_co_eject(BlockBackend *blk, bool eject_flag);
 void co_wrapper blk_eject(BlockBackend *blk, bool eject_flag);
diff --git a/block.c b/block.c
index 1092ac26d1..cf3582f9c9 100644
--- a/block.c
+++ b/block.c
@@ -6834,14 +6834,14 @@ void coroutine_fn bdrv_co_eject(BlockDriverState *bs, bool eject_flag)
  * Lock or unlock the media (if it is locked, the user won't be able
  * to eject it manually).
  */
-void bdrv_lock_medium(BlockDriverState *bs, bool locked)
+void coroutine_fn bdrv_co_lock_medium(BlockDriverState *bs, bool locked)
 {
     BlockDriver *drv = bs->drv;
     IO_CODE();
     trace_bdrv_lock_medium(bs, locked);
 
-    if (drv && drv->bdrv_lock_medium) {
-        drv->bdrv_lock_medium(bs, locked);
+    if (drv && drv->bdrv_co_lock_medium) {
+        drv->bdrv_co_lock_medium(bs, locked);
     }
 }
 
diff --git a/block/block-backend.c b/block/block-backend.c
index 7eaafc85b1..ef512f7c48 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -1999,13 +1999,13 @@ bool blk_is_available(BlockBackend *blk)
     return blk_is_inserted(blk) && !blk_dev_is_tray_open(blk);
 }
 
-void blk_lock_medium(BlockBackend *blk, bool locked)
+void coroutine_fn blk_co_lock_medium(BlockBackend *blk, bool locked)
 {
     BlockDriverState *bs = blk_bs(blk);
     IO_CODE();
 
     if (bs) {
-        bdrv_lock_medium(bs, locked);
+        bdrv_co_lock_medium(bs, locked);
     }
 }
 
diff --git a/block/copy-on-read.c b/block/copy-on-read.c
index 43f09514dc..5032b78efc 100644
--- a/block/copy-on-read.c
+++ b/block/copy-on-read.c
@@ -222,9 +222,9 @@ static void coroutine_fn cor_co_eject(BlockDriverState *bs, bool eject_flag)
 }
 
 
-static void cor_lock_medium(BlockDriverState *bs, bool locked)
+static void coroutine_fn cor_co_lock_medium(BlockDriverState *bs, bool locked)
 {
-    bdrv_lock_medium(bs->file->bs, locked);
+    bdrv_co_lock_medium(bs->file->bs, locked);
 }
 
 
@@ -258,7 +258,7 @@ static BlockDriver bdrv_copy_on_read = {
     .bdrv_co_pwritev_compressed         = cor_co_pwritev_compressed,
 
     .bdrv_co_eject                      = cor_co_eject,
-    .bdrv_lock_medium                   = cor_lock_medium,
+    .bdrv_co_lock_medium                = cor_co_lock_medium,
 
     .has_variable_length                = true,
     .is_filter                          = true,
diff --git a/block/file-posix.c b/block/file-posix.c
index cfa614fea2..0370b550aa 100644
--- a/block/file-posix.c
+++ b/block/file-posix.c
@@ -3777,7 +3777,7 @@ static void coroutine_fn cdrom_co_eject(BlockDriverState *bs, bool eject_flag)
     }
 }
 
-static void cdrom_lock_medium(BlockDriverState *bs, bool locked)
+static void coroutine_fn cdrom_co_lock_medium(BlockDriverState *bs, bool locked)
 {
     BDRVRawState *s = bs->opaque;
 
@@ -3823,7 +3823,7 @@ static BlockDriver bdrv_host_cdrom = {
     /* removable device support */
     .bdrv_co_is_inserted    = cdrom_co_is_inserted,
     .bdrv_co_eject          = cdrom_co_eject,
-    .bdrv_lock_medium   = cdrom_lock_medium,
+    .bdrv_co_lock_medium    = cdrom_co_lock_medium,
 
     /* generic scsi device */
     .bdrv_co_ioctl      = hdev_co_ioctl,
@@ -3905,7 +3905,7 @@ static void coroutine_fn cdrom_co_eject(BlockDriverState *bs, bool eject_flag)
     cdrom_reopen(bs);
 }
 
-static void cdrom_lock_medium(BlockDriverState *bs, bool locked)
+static void coroutine_fn cdrom_co_lock_medium(BlockDriverState *bs, bool locked)
 {
     BDRVRawState *s = bs->opaque;
 
@@ -3952,7 +3952,7 @@ static BlockDriver bdrv_host_cdrom = {
     /* removable device support */
     .bdrv_co_is_inserted     = cdrom_co_is_inserted,
     .bdrv_co_eject           = cdrom_co_eject,
-    .bdrv_lock_medium   = cdrom_lock_medium,
+    .bdrv_co_lock_medium     = cdrom_co_lock_medium,
 };
 #endif /* __FreeBSD__ */
 
diff --git a/block/filter-compress.c b/block/filter-compress.c
index 97adb3de19..a4e7b191bd 100644
--- a/block/filter-compress.c
+++ b/block/filter-compress.c
@@ -123,9 +123,10 @@ compress_co_eject(BlockDriverState *bs, bool eject_flag)
 }
 
 
-static void compress_lock_medium(BlockDriverState *bs, bool locked)
+static void coroutine_fn
+compress_co_lock_medium(BlockDriverState *bs, bool locked)
 {
-    bdrv_lock_medium(bs->file->bs, locked);
+    bdrv_co_lock_medium(bs->file->bs, locked);
 }
 
 
@@ -144,7 +145,7 @@ static BlockDriver bdrv_compress = {
     .bdrv_refresh_limits                = compress_refresh_limits,
 
     .bdrv_co_eject                      = compress_co_eject,
-    .bdrv_lock_medium                   = compress_lock_medium,
+    .bdrv_co_lock_medium                = compress_co_lock_medium,
 
     .has_variable_length                = true,
     .is_filter                          = true,
diff --git a/block/raw-format.c b/block/raw-format.c
index 2585e9ef96..44d2e8a727 100644
--- a/block/raw-format.c
+++ b/block/raw-format.c
@@ -409,9 +409,9 @@ static void coroutine_fn raw_co_eject(BlockDriverState *bs, bool eject_flag)
     bdrv_co_eject(bs->file->bs, eject_flag);
 }
 
-static void raw_lock_medium(BlockDriverState *bs, bool locked)
+static void coroutine_fn raw_co_lock_medium(BlockDriverState *bs, bool locked)
 {
-    bdrv_lock_medium(bs->file->bs, locked);
+    bdrv_co_lock_medium(bs->file->bs, locked);
 }
 
 static int coroutine_fn raw_co_ioctl(BlockDriverState *bs,
@@ -631,7 +631,7 @@ BlockDriver bdrv_raw = {
     .bdrv_probe_blocksizes = &raw_probe_blocksizes,
     .bdrv_probe_geometry  = &raw_probe_geometry,
     .bdrv_co_eject        = &raw_co_eject,
-    .bdrv_lock_medium     = &raw_lock_medium,
+    .bdrv_co_lock_medium  = &raw_co_lock_medium,
     .bdrv_co_ioctl        = &raw_co_ioctl,
     .create_opts          = &raw_create_opts,
     .bdrv_has_zero_init   = &raw_has_zero_init,
-- 
2.38.1



^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PULL 24/38] block: Convert bdrv_debug_event() to co_wrapper_mixed
  2023-01-20 12:25 [PULL 00/38] Block layer patches Kevin Wolf
                   ` (22 preceding siblings ...)
  2023-01-20 12:26 ` [PULL 23/38] block: Convert bdrv_lock_medium() " Kevin Wolf
@ 2023-01-20 12:26 ` Kevin Wolf
  2023-01-20 12:26 ` [PULL 25/38] block: Rename bdrv_load/save_vmstate() to bdrv_co_load/save_vmstate() Kevin Wolf
                   ` (14 subsequent siblings)
  38 siblings, 0 replies; 48+ messages in thread
From: Kevin Wolf @ 2023-01-20 12:26 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, peter.maydell, qemu-devel

From: Emanuele Giuseppe Esposito <eesposit@redhat.com>

bdrv_debug_event() is categorized as an I/O function, and it currently
doesn't run in a coroutine. We should let it take a graph rdlock since
it traverses the block nodes graph, which however is only possible in a
coroutine.

Therefore turn it into a co_wrapper_mixed to move the actual function
into a coroutine where the lock can be taken.

Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Message-Id: <20230113204212.359076-14-kwolf@redhat.com>
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 include/block/block-io.h         |  5 ++++-
 include/block/block_int-common.h |  3 ++-
 block.c                          |  6 +++---
 block/blkdebug.c                 |  5 +++--
 block/io.c                       | 22 +++++++++++-----------
 5 files changed, 23 insertions(+), 18 deletions(-)

diff --git a/include/block/block-io.h b/include/block/block-io.h
index 33e0cc2068..6ec2309143 100644
--- a/include/block/block-io.h
+++ b/include/block/block-io.h
@@ -188,7 +188,10 @@ void *qemu_try_blockalign0(BlockDriverState *bs, size_t size);
 void bdrv_enable_copy_on_read(BlockDriverState *bs);
 void bdrv_disable_copy_on_read(BlockDriverState *bs);
 
-void bdrv_debug_event(BlockDriverState *bs, BlkdebugEvent event);
+void coroutine_fn bdrv_co_debug_event(BlockDriverState *bs,
+                                      BlkdebugEvent event);
+void co_wrapper_mixed bdrv_debug_event(BlockDriverState *bs,
+                                       BlkdebugEvent event);
 
 #define BLKDBG_EVENT(child, evt) \
     do { \
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
index 1174f13a2f..93d4350f24 100644
--- a/include/block/block_int-common.h
+++ b/include/block/block_int-common.h
@@ -729,7 +729,8 @@ struct BlockDriver {
     int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_check)(
         BlockDriverState *bs, BdrvCheckResult *result, BdrvCheckMode fix);
 
-    void (*bdrv_debug_event)(BlockDriverState *bs, BlkdebugEvent event);
+    void coroutine_fn (*bdrv_co_debug_event)(BlockDriverState *bs,
+                                             BlkdebugEvent event);
 
     /* io queue for linux-aio */
     void coroutine_fn (*bdrv_co_io_plug)(BlockDriverState *bs);
diff --git a/block.c b/block.c
index cf3582f9c9..f9dbe11aa5 100644
--- a/block.c
+++ b/block.c
@@ -6350,14 +6350,14 @@ BlockStatsSpecific *bdrv_get_specific_stats(BlockDriverState *bs)
     return drv->bdrv_get_specific_stats(bs);
 }
 
-void bdrv_debug_event(BlockDriverState *bs, BlkdebugEvent event)
+void coroutine_fn bdrv_co_debug_event(BlockDriverState *bs, BlkdebugEvent event)
 {
     IO_CODE();
-    if (!bs || !bs->drv || !bs->drv->bdrv_debug_event) {
+    if (!bs || !bs->drv || !bs->drv->bdrv_co_debug_event) {
         return;
     }
 
-    bs->drv->bdrv_debug_event(bs, event);
+    bs->drv->bdrv_co_debug_event(bs, event);
 }
 
 static BlockDriverState *bdrv_find_debug_node(BlockDriverState *bs)
diff --git a/block/blkdebug.c b/block/blkdebug.c
index 2294b0227b..69aa7aa43d 100644
--- a/block/blkdebug.c
+++ b/block/blkdebug.c
@@ -835,7 +835,8 @@ static void process_rule(BlockDriverState *bs, struct BlkdebugRule *rule,
     }
 }
 
-static void blkdebug_debug_event(BlockDriverState *bs, BlkdebugEvent event)
+static void coroutine_fn
+blkdebug_co_debug_event(BlockDriverState *bs, BlkdebugEvent event)
 {
     BDRVBlkdebugState *s = bs->opaque;
     struct BlkdebugRule *rule, *next;
@@ -1085,7 +1086,7 @@ static BlockDriver bdrv_blkdebug = {
     .bdrv_co_pdiscard       = blkdebug_co_pdiscard,
     .bdrv_co_block_status   = blkdebug_co_block_status,
 
-    .bdrv_debug_event           = blkdebug_debug_event,
+    .bdrv_co_debug_event        = blkdebug_co_debug_event,
     .bdrv_debug_breakpoint      = blkdebug_debug_breakpoint,
     .bdrv_debug_remove_breakpoint
                                 = blkdebug_debug_remove_breakpoint,
diff --git a/block/io.c b/block/io.c
index c43637f5c1..cd1cea2515 100644
--- a/block/io.c
+++ b/block/io.c
@@ -1250,7 +1250,7 @@ static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child,
                 goto err;
             }
 
-            bdrv_debug_event(bs, BLKDBG_COR_WRITE);
+            bdrv_co_debug_event(bs, BLKDBG_COR_WRITE);
             if (drv->bdrv_co_pwrite_zeroes &&
                 buffer_is_zero(bounce_buffer, pnum)) {
                 /* FIXME: Should we (perhaps conditionally) be setting
@@ -1495,10 +1495,10 @@ static coroutine_fn int bdrv_padding_rmw_read(BdrvChild *child,
         qemu_iovec_init_buf(&local_qiov, pad->buf, bytes);
 
         if (pad->head) {
-            bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_HEAD);
+            bdrv_co_debug_event(bs, BLKDBG_PWRITEV_RMW_HEAD);
         }
         if (pad->merge_reads && pad->tail) {
-            bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_TAIL);
+            bdrv_co_debug_event(bs, BLKDBG_PWRITEV_RMW_TAIL);
         }
         ret = bdrv_aligned_preadv(child, req, req->overlap_offset, bytes,
                                   align, &local_qiov, 0, 0);
@@ -1506,10 +1506,10 @@ static coroutine_fn int bdrv_padding_rmw_read(BdrvChild *child,
             return ret;
         }
         if (pad->head) {
-            bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_AFTER_HEAD);
+            bdrv_co_debug_event(bs, BLKDBG_PWRITEV_RMW_AFTER_HEAD);
         }
         if (pad->merge_reads && pad->tail) {
-            bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_AFTER_TAIL);
+            bdrv_co_debug_event(bs, BLKDBG_PWRITEV_RMW_AFTER_TAIL);
         }
 
         if (pad->merge_reads) {
@@ -1520,7 +1520,7 @@ static coroutine_fn int bdrv_padding_rmw_read(BdrvChild *child,
     if (pad->tail) {
         qemu_iovec_init_buf(&local_qiov, pad->tail_buf, align);
 
-        bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_TAIL);
+        bdrv_co_debug_event(bs, BLKDBG_PWRITEV_RMW_TAIL);
         ret = bdrv_aligned_preadv(
                 child, req,
                 req->overlap_offset + req->overlap_bytes - align,
@@ -1528,7 +1528,7 @@ static coroutine_fn int bdrv_padding_rmw_read(BdrvChild *child,
         if (ret < 0) {
             return ret;
         }
-        bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_AFTER_TAIL);
+        bdrv_co_debug_event(bs, BLKDBG_PWRITEV_RMW_AFTER_TAIL);
     }
 
 zero_mem:
@@ -1930,16 +1930,16 @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child,
     if (ret < 0) {
         /* Do nothing, write notifier decided to fail this request */
     } else if (flags & BDRV_REQ_ZERO_WRITE) {
-        bdrv_debug_event(bs, BLKDBG_PWRITEV_ZERO);
+        bdrv_co_debug_event(bs, BLKDBG_PWRITEV_ZERO);
         ret = bdrv_co_do_pwrite_zeroes(bs, offset, bytes, flags);
     } else if (flags & BDRV_REQ_WRITE_COMPRESSED) {
         ret = bdrv_driver_pwritev_compressed(bs, offset, bytes,
                                              qiov, qiov_offset);
     } else if (bytes <= max_transfer) {
-        bdrv_debug_event(bs, BLKDBG_PWRITEV);
+        bdrv_co_debug_event(bs, BLKDBG_PWRITEV);
         ret = bdrv_driver_pwritev(bs, offset, bytes, qiov, qiov_offset, flags);
     } else {
-        bdrv_debug_event(bs, BLKDBG_PWRITEV);
+        bdrv_co_debug_event(bs, BLKDBG_PWRITEV);
         while (bytes_remaining) {
             int num = MIN(bytes_remaining, max_transfer);
             int local_flags = flags;
@@ -1962,7 +1962,7 @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child,
             bytes_remaining -= num;
         }
     }
-    bdrv_debug_event(bs, BLKDBG_PWRITEV_DONE);
+    bdrv_co_debug_event(bs, BLKDBG_PWRITEV_DONE);
 
     if (ret >= 0) {
         ret = 0;
-- 
2.38.1



^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PULL 25/38] block: Rename bdrv_load/save_vmstate() to bdrv_co_load/save_vmstate()
  2023-01-20 12:25 [PULL 00/38] Block layer patches Kevin Wolf
                   ` (23 preceding siblings ...)
  2023-01-20 12:26 ` [PULL 24/38] block: Convert bdrv_debug_event() to co_wrapper_mixed Kevin Wolf
@ 2023-01-20 12:26 ` Kevin Wolf
  2023-01-20 12:26 ` [PULL 26/38] block/nbd: Add missing <qemu/bswap.h> include Kevin Wolf
                   ` (13 subsequent siblings)
  38 siblings, 0 replies; 48+ messages in thread
From: Kevin Wolf @ 2023-01-20 12:26 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, peter.maydell, qemu-devel

From: Emanuele Giuseppe Esposito <eesposit@redhat.com>

Since these functions always run in coroutine context, adjust
their name to include "_co_", just like all other BlockDriver callbacks.

No functional change intended.

Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Message-Id: <20230113204212.359076-15-kwolf@redhat.com>
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 include/block/block_int-common.h |  4 ++--
 block/io.c                       |  8 ++++----
 block/qcow2.c                    | 12 ++++++------
 3 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
index 93d4350f24..fd8ccaefee 100644
--- a/include/block/block_int-common.h
+++ b/include/block/block_int-common.h
@@ -704,10 +704,10 @@ struct BlockDriver {
                                                  Error **errp);
     BlockStatsSpecific *(*bdrv_get_specific_stats)(BlockDriverState *bs);
 
-    int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_save_vmstate)(
+    int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_save_vmstate)(
         BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos);
 
-    int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_load_vmstate)(
+    int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_load_vmstate)(
         BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos);
 
     /* removable device specific */
diff --git a/block/io.c b/block/io.c
index cd1cea2515..445c757c2a 100644
--- a/block/io.c
+++ b/block/io.c
@@ -2719,8 +2719,8 @@ bdrv_co_readv_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos)
 
     bdrv_inc_in_flight(bs);
 
-    if (drv->bdrv_load_vmstate) {
-        ret = drv->bdrv_load_vmstate(bs, qiov, pos);
+    if (drv->bdrv_co_load_vmstate) {
+        ret = drv->bdrv_co_load_vmstate(bs, qiov, pos);
     } else if (child_bs) {
         ret = bdrv_co_readv_vmstate(child_bs, qiov, pos);
     } else {
@@ -2752,8 +2752,8 @@ bdrv_co_writev_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos)
 
     bdrv_inc_in_flight(bs);
 
-    if (drv->bdrv_save_vmstate) {
-        ret = drv->bdrv_save_vmstate(bs, qiov, pos);
+    if (drv->bdrv_co_save_vmstate) {
+        ret = drv->bdrv_co_save_vmstate(bs, qiov, pos);
     } else if (child_bs) {
         ret = bdrv_co_writev_vmstate(child_bs, qiov, pos);
     } else {
diff --git a/block/qcow2.c b/block/qcow2.c
index 460579b70a..ce644dfc59 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -5286,8 +5286,8 @@ static int64_t qcow2_check_vmstate_request(BlockDriverState *bs,
     return pos;
 }
 
-static coroutine_fn int qcow2_save_vmstate(BlockDriverState *bs,
-                                           QEMUIOVector *qiov, int64_t pos)
+static coroutine_fn int qcow2_co_save_vmstate(BlockDriverState *bs,
+                                              QEMUIOVector *qiov, int64_t pos)
 {
     int64_t offset = qcow2_check_vmstate_request(bs, qiov, pos);
     if (offset < 0) {
@@ -5298,8 +5298,8 @@ static coroutine_fn int qcow2_save_vmstate(BlockDriverState *bs,
     return bs->drv->bdrv_co_pwritev_part(bs, offset, qiov->size, qiov, 0, 0);
 }
 
-static coroutine_fn int qcow2_load_vmstate(BlockDriverState *bs,
-                                           QEMUIOVector *qiov, int64_t pos)
+static coroutine_fn int qcow2_co_load_vmstate(BlockDriverState *bs,
+                                              QEMUIOVector *qiov, int64_t pos)
 {
     int64_t offset = qcow2_check_vmstate_request(bs, qiov, pos);
     if (offset < 0) {
@@ -6080,8 +6080,8 @@ BlockDriver bdrv_qcow2 = {
     .bdrv_co_get_info       = qcow2_co_get_info,
     .bdrv_get_specific_info = qcow2_get_specific_info,
 
-    .bdrv_save_vmstate    = qcow2_save_vmstate,
-    .bdrv_load_vmstate    = qcow2_load_vmstate,
+    .bdrv_co_save_vmstate   = qcow2_co_save_vmstate,
+    .bdrv_co_load_vmstate   = qcow2_co_load_vmstate,
 
     .is_format                  = true,
     .supports_backing           = true,
-- 
2.38.1



^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PULL 26/38] block/nbd: Add missing <qemu/bswap.h> include
  2023-01-20 12:25 [PULL 00/38] Block layer patches Kevin Wolf
                   ` (24 preceding siblings ...)
  2023-01-20 12:26 ` [PULL 25/38] block: Rename bdrv_load/save_vmstate() to bdrv_co_load/save_vmstate() Kevin Wolf
@ 2023-01-20 12:26 ` Kevin Wolf
  2023-01-20 12:26 ` [PULL 27/38] block: Improve empty format-specific info dump Kevin Wolf
                   ` (12 subsequent siblings)
  38 siblings, 0 replies; 48+ messages in thread
From: Kevin Wolf @ 2023-01-20 12:26 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, peter.maydell, qemu-devel

From: Philippe Mathieu-Daudé <philmd@linaro.org>

The inlined nbd_readXX() functions call beXX_to_cpu(), themselves
declared in <qemu/bswap.h>. This fixes when refactoring:

  In file included from ../../block/nbd.c:44:
  include/block/nbd.h: In function 'nbd_read16':
  include/block/nbd.h:383:12: error: implicit declaration of function 'be16_to_cpu' [-Werror=implicit-function-declaration]
    383 |     *val = be##bits##_to_cpu(*val);                                     \
        |            ^~
  include/block/nbd.h:387:1: note: in expansion of macro 'DEF_NBD_READ_N'
    387 | DEF_NBD_READ_N(16) /* Defines nbd_read16(). */
        | ^~~~~~~~~~~~~~

Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Message-Id: <20221125175328.48539-1-philmd@linaro.org>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 include/block/nbd.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/block/nbd.h b/include/block/nbd.h
index 4ede3b2bd0..a4c98169c3 100644
--- a/include/block/nbd.h
+++ b/include/block/nbd.h
@@ -24,6 +24,7 @@
 #include "io/channel-socket.h"
 #include "crypto/tlscreds.h"
 #include "qapi/error.h"
+#include "qemu/bswap.h"
 
 extern const BlockExportDriver blk_exp_nbd;
 
-- 
2.38.1



^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PULL 27/38] block: Improve empty format-specific info dump
  2023-01-20 12:25 [PULL 00/38] Block layer patches Kevin Wolf
                   ` (25 preceding siblings ...)
  2023-01-20 12:26 ` [PULL 26/38] block/nbd: Add missing <qemu/bswap.h> include Kevin Wolf
@ 2023-01-20 12:26 ` Kevin Wolf
  2023-01-20 12:26 ` [PULL 28/38] block/file: Add file-specific image info Kevin Wolf
                   ` (11 subsequent siblings)
  38 siblings, 0 replies; 48+ messages in thread
From: Kevin Wolf @ 2023-01-20 12:26 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, peter.maydell, qemu-devel

From: Hanna Reitz <hreitz@redhat.com>

When a block driver supports obtaining format-specific information, but
that object only contains optional fields, it is possible that none of
them are present, so that dump_qobject() (called by
bdrv_image_info_specific_dump()) will not print anything.

The callers of bdrv_image_info_specific_dump() put a header above this
information ("Format specific information:\n"), which will look strange
when there is nothing below.  Modify bdrv_image_info_specific_dump() to
print this header instead of its callers, and only if there is indeed
something to be printed.

Signed-off-by: Hanna Reitz <hreitz@redhat.com>
Message-Id: <20220620162704.80987-2-hreitz@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 include/block/qapi.h |  3 ++-
 block/qapi.c         | 41 +++++++++++++++++++++++++++++++++++++----
 qemu-io-cmds.c       |  4 ++--
 3 files changed, 41 insertions(+), 7 deletions(-)

diff --git a/include/block/qapi.h b/include/block/qapi.h
index 22c7807c89..c09859ea78 100644
--- a/include/block/qapi.h
+++ b/include/block/qapi.h
@@ -40,6 +40,7 @@ void bdrv_query_image_info(BlockDriverState *bs,
                            Error **errp);
 
 void bdrv_snapshot_dump(QEMUSnapshotInfo *sn);
-void bdrv_image_info_specific_dump(ImageInfoSpecific *info_spec);
+void bdrv_image_info_specific_dump(ImageInfoSpecific *info_spec,
+                                   const char *prefix);
 void bdrv_image_info_dump(ImageInfo *info);
 #endif
diff --git a/block/qapi.c b/block/qapi.c
index fea808425b..b2584f8740 100644
--- a/block/qapi.c
+++ b/block/qapi.c
@@ -759,7 +759,35 @@ static void dump_qdict(int indentation, QDict *dict)
     }
 }
 
-void bdrv_image_info_specific_dump(ImageInfoSpecific *info_spec)
+/*
+ * Return whether dumping the given QObject with dump_qobject() would
+ * yield an empty dump, i.e. not print anything.
+ */
+static bool qobject_is_empty_dump(const QObject *obj)
+{
+    switch (qobject_type(obj)) {
+    case QTYPE_QNUM:
+    case QTYPE_QSTRING:
+    case QTYPE_QBOOL:
+        return false;
+
+    case QTYPE_QDICT:
+        return qdict_size(qobject_to(QDict, obj)) == 0;
+
+    case QTYPE_QLIST:
+        return qlist_empty(qobject_to(QList, obj));
+
+    default:
+        abort();
+    }
+}
+
+/**
+ * Dumps the given ImageInfoSpecific object in a human-readable form,
+ * prepending an optional prefix if the dump is not empty.
+ */
+void bdrv_image_info_specific_dump(ImageInfoSpecific *info_spec,
+                                   const char *prefix)
 {
     QObject *obj, *data;
     Visitor *v = qobject_output_visitor_new(&obj);
@@ -767,7 +795,12 @@ void bdrv_image_info_specific_dump(ImageInfoSpecific *info_spec)
     visit_type_ImageInfoSpecific(v, NULL, &info_spec, &error_abort);
     visit_complete(v, &obj);
     data = qdict_get(qobject_to(QDict, obj), "data");
-    dump_qobject(1, data);
+    if (!qobject_is_empty_dump(data)) {
+        if (prefix) {
+            qemu_printf("%s", prefix);
+        }
+        dump_qobject(1, data);
+    }
     qobject_unref(obj);
     visit_free(v);
 }
@@ -848,7 +881,7 @@ void bdrv_image_info_dump(ImageInfo *info)
     }
 
     if (info->format_specific) {
-        qemu_printf("Format specific information:\n");
-        bdrv_image_info_specific_dump(info->format_specific);
+        bdrv_image_info_specific_dump(info->format_specific,
+                                      "Format specific information:\n");
     }
 }
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
index 7a412d6512..d7e562dda6 100644
--- a/qemu-io-cmds.c
+++ b/qemu-io-cmds.c
@@ -1788,8 +1788,8 @@ static int info_f(BlockBackend *blk, int argc, char **argv)
         return -EIO;
     }
     if (spec_info) {
-        printf("Format specific information:\n");
-        bdrv_image_info_specific_dump(spec_info);
+        bdrv_image_info_specific_dump(spec_info,
+                                      "Format specific information:\n");
         qapi_free_ImageInfoSpecific(spec_info);
     }
 
-- 
2.38.1



^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PULL 28/38] block/file: Add file-specific image info
  2023-01-20 12:25 [PULL 00/38] Block layer patches Kevin Wolf
                   ` (26 preceding siblings ...)
  2023-01-20 12:26 ` [PULL 27/38] block: Improve empty format-specific info dump Kevin Wolf
@ 2023-01-20 12:26 ` Kevin Wolf
  2023-01-20 12:26 ` [PULL 29/38] block/vmdk: Change extent info type Kevin Wolf
                   ` (10 subsequent siblings)
  38 siblings, 0 replies; 48+ messages in thread
From: Kevin Wolf @ 2023-01-20 12:26 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, peter.maydell, qemu-devel

From: Hanna Reitz <hreitz@redhat.com>

Add some (optional) information that the file driver can provide for
image files, namely the extent size hint.

Signed-off-by: Hanna Reitz <hreitz@redhat.com>
Message-Id: <20220620162704.80987-3-hreitz@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 qapi/block-core.json | 26 ++++++++++++++++++++++++--
 block/file-posix.c   | 30 ++++++++++++++++++++++++++++++
 2 files changed, 54 insertions(+), 2 deletions(-)

diff --git a/qapi/block-core.json b/qapi/block-core.json
index 95ac4fa634..f5d822cbd6 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -139,16 +139,29 @@
       '*encryption-format': 'RbdImageEncryptionFormat'
   } }
 
+##
+# @ImageInfoSpecificFile:
+#
+# @extent-size-hint: Extent size hint (if available)
+#
+# Since: 8.0
+##
+{ 'struct': 'ImageInfoSpecificFile',
+  'data': {
+      '*extent-size-hint': 'size'
+  } }
+
 ##
 # @ImageInfoSpecificKind:
 #
 # @luks: Since 2.7
 # @rbd: Since 6.1
+# @file: Since 8.0
 #
 # Since: 1.7
 ##
 { 'enum': 'ImageInfoSpecificKind',
-  'data': [ 'qcow2', 'vmdk', 'luks', 'rbd' ] }
+  'data': [ 'qcow2', 'vmdk', 'luks', 'rbd', 'file' ] }
 
 ##
 # @ImageInfoSpecificQCow2Wrapper:
@@ -185,6 +198,14 @@
 { 'struct': 'ImageInfoSpecificRbdWrapper',
   'data': { 'data': 'ImageInfoSpecificRbd' } }
 
+##
+# @ImageInfoSpecificFileWrapper:
+#
+# Since: 8.0
+##
+{ 'struct': 'ImageInfoSpecificFileWrapper',
+  'data': { 'data': 'ImageInfoSpecificFile' } }
+
 ##
 # @ImageInfoSpecific:
 #
@@ -199,7 +220,8 @@
       'qcow2': 'ImageInfoSpecificQCow2Wrapper',
       'vmdk': 'ImageInfoSpecificVmdkWrapper',
       'luks': 'ImageInfoSpecificLUKSWrapper',
-      'rbd': 'ImageInfoSpecificRbdWrapper'
+      'rbd': 'ImageInfoSpecificRbdWrapper',
+      'file': 'ImageInfoSpecificFileWrapper'
   } }
 
 ##
diff --git a/block/file-posix.c b/block/file-posix.c
index 0370b550aa..98a743e519 100644
--- a/block/file-posix.c
+++ b/block/file-posix.c
@@ -3091,6 +3091,34 @@ raw_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
     return 0;
 }
 
+static ImageInfoSpecific *raw_get_specific_info(BlockDriverState *bs,
+                                                Error **errp)
+{
+    BDRVRawState *s = bs->opaque;
+    ImageInfoSpecificFile *file_info = g_new0(ImageInfoSpecificFile, 1);
+    ImageInfoSpecific *spec_info = g_new(ImageInfoSpecific, 1);
+
+    *spec_info = (ImageInfoSpecific){
+        .type = IMAGE_INFO_SPECIFIC_KIND_FILE,
+        .u.file.data = file_info,
+    };
+
+#ifdef FS_IOC_FSGETXATTR
+    {
+        struct fsxattr attr;
+        int ret;
+
+        ret = ioctl(s->fd, FS_IOC_FSGETXATTR, &attr);
+        if (!ret && attr.fsx_extsize != 0) {
+            file_info->has_extent_size_hint = true;
+            file_info->extent_size_hint = attr.fsx_extsize;
+        }
+    }
+#endif
+
+    return spec_info;
+}
+
 static BlockStatsSpecificFile get_blockstats_specific_file(BlockDriverState *bs)
 {
     BDRVRawState *s = bs->opaque;
@@ -3324,6 +3352,7 @@ BlockDriver bdrv_file = {
     .bdrv_co_truncate                   = raw_co_truncate,
     .bdrv_co_getlength                  = raw_co_getlength,
     .bdrv_co_get_info                   = raw_co_get_info,
+    .bdrv_get_specific_info             = raw_get_specific_info,
     .bdrv_co_get_allocated_file_size    = raw_co_get_allocated_file_size,
     .bdrv_get_specific_stats = raw_get_specific_stats,
     .bdrv_check_perm = raw_check_perm,
@@ -3695,6 +3724,7 @@ static BlockDriver bdrv_host_device = {
     .bdrv_co_truncate                   = raw_co_truncate,
     .bdrv_co_getlength                  = raw_co_getlength,
     .bdrv_co_get_info                   = raw_co_get_info,
+    .bdrv_get_specific_info             = raw_get_specific_info,
     .bdrv_co_get_allocated_file_size    = raw_co_get_allocated_file_size,
     .bdrv_get_specific_stats = hdev_get_specific_stats,
     .bdrv_check_perm = raw_check_perm,
-- 
2.38.1



^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PULL 29/38] block/vmdk: Change extent info type
  2023-01-20 12:25 [PULL 00/38] Block layer patches Kevin Wolf
                   ` (27 preceding siblings ...)
  2023-01-20 12:26 ` [PULL 28/38] block/file: Add file-specific image info Kevin Wolf
@ 2023-01-20 12:26 ` Kevin Wolf
  2023-01-20 12:26 ` [PULL 30/38] block: Split BlockNodeInfo off of ImageInfo Kevin Wolf
                   ` (9 subsequent siblings)
  38 siblings, 0 replies; 48+ messages in thread
From: Kevin Wolf @ 2023-01-20 12:26 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, peter.maydell, qemu-devel

From: Hanna Reitz <hreitz@redhat.com>

VMDK's implementation of .bdrv_get_specific_info() returns information
about its extent files, ostensibly in the form of ImageInfo objects.
However, it does not get this information through
bdrv_query_image_info(), but fills only a select few fields with custom
information that does not always match the fields' purposes.

For example, @format, which is supposed to be a block driver name, is
filled with the extent type, e.g. SPARSE or FLAT.

In ImageInfo, @compressed shows whether the data that can be seen in the
image is stored in compressed form or not.  For example, a compressed
qcow2 image will store compressed data in its data file, but when
accessing the qcow2 node, you will see normal data.  This is not how
VMDK uses the @compressed field for its extent files: Instead, it
signifies whether accessing the extent file will yield compressed data
(which the VMDK driver then (de-)compresses).

Create a new structure to represent the extent information.  This allows
us to clarify the fields' meanings, and it clearly shows that these are
not complete ImageInfo objects.  (That is, if a user wants an extent
file's ImageInfo object, they will need to query it separately, and will
not get it from ImageInfoSpecificVmdk.extents.)

Note that this removes the last use of ['ImageInfo'] (i.e. an array of
ImageInfo objects), so the QAPI generator will no longer generate
ImageInfoList by default.  However, we use it in qemu-img.c, so we need
to create a dummy object to force the generate to create that type,
similarly to DummyForceArrays in machine.json (introduced in commit
9f08c8ec73878122ad4b061ed334f0437afaaa32 ("qapi: Lazy creation of array
types")).

Signed-off-by: Hanna Reitz <hreitz@redhat.com>
Message-Id: <20220620162704.80987-4-hreitz@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 qapi/block-core.json | 38 +++++++++++++++++++++++++++++++++++++-
 block/vmdk.c         |  8 ++++----
 2 files changed, 41 insertions(+), 5 deletions(-)

diff --git a/qapi/block-core.json b/qapi/block-core.json
index f5d822cbd6..4b9365167f 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -124,7 +124,33 @@
       'create-type': 'str',
       'cid': 'int',
       'parent-cid': 'int',
-      'extents': ['ImageInfo']
+      'extents': ['VmdkExtentInfo']
+  } }
+
+##
+# @VmdkExtentInfo:
+#
+# Information about a VMDK extent file
+#
+# @filename: Name of the extent file
+#
+# @format: Extent type (e.g. FLAT or SPARSE)
+#
+# @virtual-size: Number of bytes covered by this extent
+#
+# @cluster-size: Cluster size in bytes (for non-flat extents)
+#
+# @compressed: Whether this extent contains compressed data
+#
+# Since: 8.0
+##
+{ 'struct': 'VmdkExtentInfo',
+  'data': {
+      'filename': 'str',
+      'format': 'str',
+      'virtual-size': 'int',
+      '*cluster-size': 'int',
+      '*compressed': 'bool'
   } }
 
 ##
@@ -5754,3 +5780,13 @@
   'data': { 'device': 'str', '*id': 'str', '*name': 'str'},
   'returns': 'SnapshotInfo',
   'allow-preconfig': true }
+
+##
+# @DummyBlockCoreForceArrays:
+#
+# Not used by QMP; hack to let us use ImageInfoList internally
+#
+# Since: 8.0
+##
+{ 'struct': 'DummyBlockCoreForceArrays',
+  'data': { 'unused-image-info': ['ImageInfo'] } }
diff --git a/block/vmdk.c b/block/vmdk.c
index 1bba61ad7d..5b0eae877e 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -2898,12 +2898,12 @@ static int vmdk_has_zero_init(BlockDriverState *bs)
     return 1;
 }
 
-static ImageInfo *vmdk_get_extent_info(VmdkExtent *extent)
+static VmdkExtentInfo *vmdk_get_extent_info(VmdkExtent *extent)
 {
-    ImageInfo *info = g_new0(ImageInfo, 1);
+    VmdkExtentInfo *info = g_new0(VmdkExtentInfo, 1);
 
     bdrv_refresh_filename(extent->file->bs);
-    *info = (ImageInfo){
+    *info = (VmdkExtentInfo){
         .filename         = g_strdup(extent->file->bs->filename),
         .format           = g_strdup(extent->type),
         .virtual_size     = extent->sectors * BDRV_SECTOR_SIZE,
@@ -2982,7 +2982,7 @@ static ImageInfoSpecific *vmdk_get_specific_info(BlockDriverState *bs,
     int i;
     BDRVVmdkState *s = bs->opaque;
     ImageInfoSpecific *spec_info = g_new0(ImageInfoSpecific, 1);
-    ImageInfoList **tail;
+    VmdkExtentInfoList **tail;
 
     *spec_info = (ImageInfoSpecific){
         .type = IMAGE_INFO_SPECIFIC_KIND_VMDK,
-- 
2.38.1



^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PULL 30/38] block: Split BlockNodeInfo off of ImageInfo
  2023-01-20 12:25 [PULL 00/38] Block layer patches Kevin Wolf
                   ` (28 preceding siblings ...)
  2023-01-20 12:26 ` [PULL 29/38] block/vmdk: Change extent info type Kevin Wolf
@ 2023-01-20 12:26 ` Kevin Wolf
  2023-01-20 12:26 ` [PULL 31/38] qemu-img: Use BlockNodeInfo Kevin Wolf
                   ` (8 subsequent siblings)
  38 siblings, 0 replies; 48+ messages in thread
From: Kevin Wolf @ 2023-01-20 12:26 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, peter.maydell, qemu-devel

From: Hanna Reitz <hreitz@redhat.com>

ImageInfo sometimes contains flat information, and sometimes it does
not.  Split off a BlockNodeInfo struct, which only contains information
about a single node and has no link to the backing image.

We do this so we can extend BlockNodeInfo to a BlockGraphInfo struct,
which has links to all child nodes, not just the backing node.  It would
be strange to base BlockGraphInfo on ImageInfo, because then this
extended struct would have two links to the backing node (one in
BlockGraphInfo as one of all the child links, and one in ImageInfo).

Furthermore, it is quite common to ignore the backing-image field
altogether: bdrv_query_image_info() does not set it, and
bdrv_image_info_dump() does not evaluate it.  That signals that we
should have different structs for describing a single node and one that
has a link to the backing image.

Still, bdrv_query_image_info() and bdrv_image_info_dump() are not
changed too much in this patch.  Follow-up patches will handle them.

Signed-off-by: Hanna Reitz <hreitz@redhat.com>
Message-Id: <20220620162704.80987-5-hreitz@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 qapi/block-core.json | 24 +++++++++----
 include/block/qapi.h |  3 ++
 block/qapi.c         | 86 ++++++++++++++++++++++++++++++++------------
 3 files changed, 85 insertions(+), 28 deletions(-)

diff --git a/qapi/block-core.json b/qapi/block-core.json
index 4b9365167f..7720da0498 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -251,7 +251,7 @@
   } }
 
 ##
-# @ImageInfo:
+# @BlockNodeInfo:
 #
 # Information about a QEMU image file
 #
@@ -279,22 +279,34 @@
 #
 # @snapshots: list of VM snapshots
 #
-# @backing-image: info of the backing image (since 1.6)
-#
 # @format-specific: structure supplying additional format-specific
 #                   information (since 1.7)
 #
-# Since: 1.3
+# Since: 8.0
 ##
-{ 'struct': 'ImageInfo',
+{ 'struct': 'BlockNodeInfo',
   'data': {'filename': 'str', 'format': 'str', '*dirty-flag': 'bool',
            '*actual-size': 'int', 'virtual-size': 'int',
            '*cluster-size': 'int', '*encrypted': 'bool', '*compressed': 'bool',
            '*backing-filename': 'str', '*full-backing-filename': 'str',
            '*backing-filename-format': 'str', '*snapshots': ['SnapshotInfo'],
-           '*backing-image': 'ImageInfo',
            '*format-specific': 'ImageInfoSpecific' } }
 
+##
+# @ImageInfo:
+#
+# Information about a QEMU image file, and potentially its backing image
+#
+# @backing-image: info of the backing image
+#
+# Since: 1.3
+##
+{ 'struct': 'ImageInfo',
+  'base': 'BlockNodeInfo',
+  'data': {
+      '*backing-image': 'ImageInfo'
+  } }
+
 ##
 # @ImageCheck:
 #
diff --git a/include/block/qapi.h b/include/block/qapi.h
index c09859ea78..c7de4e3fa9 100644
--- a/include/block/qapi.h
+++ b/include/block/qapi.h
@@ -35,6 +35,9 @@ BlockDeviceInfo *bdrv_block_device_info(BlockBackend *blk,
 int bdrv_query_snapshot_info_list(BlockDriverState *bs,
                                   SnapshotInfoList **p_list,
                                   Error **errp);
+void bdrv_query_block_node_info(BlockDriverState *bs,
+                                BlockNodeInfo **p_info,
+                                Error **errp);
 void bdrv_query_image_info(BlockDriverState *bs,
                            ImageInfo **p_info,
                            Error **errp);
diff --git a/block/qapi.c b/block/qapi.c
index b2584f8740..b3f812a071 100644
--- a/block/qapi.c
+++ b/block/qapi.c
@@ -237,30 +237,18 @@ int bdrv_query_snapshot_info_list(BlockDriverState *bs,
 }
 
 /**
- * bdrv_query_image_info:
- * @bs: block device to examine
- * @p_info: location to store image information
- * @errp: location to store error information
- *
- * Store "flat" image information in @p_info.
- *
- * "Flat" means it does *not* query backing image information,
- * i.e. (*pinfo)->has_backing_image will be set to false and
- * (*pinfo)->backing_image to NULL even when the image does in fact have
- * a backing image.
- *
- * @p_info will be set only on success. On error, store error in @errp.
+ * Helper function for other query info functions.  Store information about @bs
+ * in @info, setting @errp on error.
  */
-void bdrv_query_image_info(BlockDriverState *bs,
-                           ImageInfo **p_info,
-                           Error **errp)
+static void bdrv_do_query_node_info(BlockDriverState *bs,
+                                    BlockNodeInfo *info,
+                                    Error **errp)
 {
     int64_t size;
     const char *backing_filename;
     BlockDriverInfo bdi;
     int ret;
     Error *err = NULL;
-    ImageInfo *info;
 
     aio_context_acquire(bdrv_get_aio_context(bs));
 
@@ -273,7 +261,6 @@ void bdrv_query_image_info(BlockDriverState *bs,
 
     bdrv_refresh_filename(bs);
 
-    info = g_new0(ImageInfo, 1);
     info->filename        = g_strdup(bs->filename);
     info->format          = g_strdup(bdrv_get_format_name(bs));
     info->virtual_size    = size;
@@ -294,7 +281,6 @@ void bdrv_query_image_info(BlockDriverState *bs,
     info->format_specific = bdrv_get_specific_info(bs, &err);
     if (err) {
         error_propagate(errp, err);
-        qapi_free_ImageInfo(info);
         goto out;
     }
     backing_filename = bs->backing_file;
@@ -330,16 +316,72 @@ void bdrv_query_image_info(BlockDriverState *bs,
         break;
     default:
         error_propagate(errp, err);
-        qapi_free_ImageInfo(info);
         goto out;
     }
 
-    *p_info = info;
-
 out:
     aio_context_release(bdrv_get_aio_context(bs));
 }
 
+/**
+ * bdrv_query_block_node_info:
+ * @bs: block node to examine
+ * @p_info: location to store node information
+ * @errp: location to store error information
+ *
+ * Store image information about @bs in @p_info.
+ *
+ * @p_info will be set only on success. On error, store error in @errp.
+ */
+void bdrv_query_block_node_info(BlockDriverState *bs,
+                                BlockNodeInfo **p_info,
+                                Error **errp)
+{
+    BlockNodeInfo *info;
+    ERRP_GUARD();
+
+    info = g_new0(BlockNodeInfo, 1);
+    bdrv_do_query_node_info(bs, info, errp);
+    if (*errp) {
+        qapi_free_BlockNodeInfo(info);
+        return;
+    }
+
+    *p_info = info;
+}
+
+/**
+ * bdrv_query_image_info:
+ * @bs: block node to examine
+ * @p_info: location to store image information
+ * @errp: location to store error information
+ *
+ * Store "flat" image information in @p_info.
+ *
+ * "Flat" means it does *not* query backing image information,
+ * i.e. (*pinfo)->has_backing_image will be set to false and
+ * (*pinfo)->backing_image to NULL even when the image does in fact have
+ * a backing image.
+ *
+ * @p_info will be set only on success. On error, store error in @errp.
+ */
+void bdrv_query_image_info(BlockDriverState *bs,
+                           ImageInfo **p_info,
+                           Error **errp)
+{
+    ImageInfo *info;
+    ERRP_GUARD();
+
+    info = g_new0(ImageInfo, 1);
+    bdrv_do_query_node_info(bs, qapi_ImageInfo_base(info), errp);
+    if (*errp) {
+        qapi_free_ImageInfo(info);
+        return;
+    }
+
+    *p_info = info;
+}
+
 /* @p_info will be set only on success. */
 static void bdrv_query_info(BlockBackend *blk, BlockInfo **p_info,
                             Error **errp)
-- 
2.38.1



^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PULL 31/38] qemu-img: Use BlockNodeInfo
  2023-01-20 12:25 [PULL 00/38] Block layer patches Kevin Wolf
                   ` (29 preceding siblings ...)
  2023-01-20 12:26 ` [PULL 30/38] block: Split BlockNodeInfo off of ImageInfo Kevin Wolf
@ 2023-01-20 12:26 ` Kevin Wolf
  2023-01-20 12:26 ` [PULL 32/38] block/qapi: Let bdrv_query_image_info() recurse Kevin Wolf
                   ` (7 subsequent siblings)
  38 siblings, 0 replies; 48+ messages in thread
From: Kevin Wolf @ 2023-01-20 12:26 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, peter.maydell, qemu-devel

From: Hanna Reitz <hreitz@redhat.com>

qemu-img info never uses ImageInfo's backing-image field, because it
opens the backing chain one by one with BDRV_O_NO_BACKING, and prints
all backing chain nodes' information consecutively.  Use BlockNodeInfo
to make it clear that we only print information about a single node, and
that we are not using the backing-image field.

Notably, bdrv_image_info_dump() does not evaluate the backing-image
field, so we can easily make it take a BlockNodeInfo pointer (and
consequentially rename it to bdrv_node_info_dump()).  It makes more
sense this way, because again, the interface now makes it syntactically
clear that backing-image is ignored by this function.

Signed-off-by: Hanna Reitz <hreitz@redhat.com>
Message-Id: <20220620162704.80987-6-hreitz@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 qapi/block-core.json           |  4 +--
 include/block/qapi.h           |  2 +-
 block/monitor/block-hmp-cmds.c |  2 +-
 block/qapi.c                   |  2 +-
 qemu-img.c                     | 48 +++++++++++++++++-----------------
 5 files changed, 29 insertions(+), 29 deletions(-)

diff --git a/qapi/block-core.json b/qapi/block-core.json
index 7720da0498..4cf2deeb6c 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -5796,9 +5796,9 @@
 ##
 # @DummyBlockCoreForceArrays:
 #
-# Not used by QMP; hack to let us use ImageInfoList internally
+# Not used by QMP; hack to let us use BlockNodeInfoList internally
 #
 # Since: 8.0
 ##
 { 'struct': 'DummyBlockCoreForceArrays',
-  'data': { 'unused-image-info': ['ImageInfo'] } }
+  'data': { 'unused-block-node-info': ['BlockNodeInfo'] } }
diff --git a/include/block/qapi.h b/include/block/qapi.h
index c7de4e3fa9..22198dcd0c 100644
--- a/include/block/qapi.h
+++ b/include/block/qapi.h
@@ -45,5 +45,5 @@ void bdrv_query_image_info(BlockDriverState *bs,
 void bdrv_snapshot_dump(QEMUSnapshotInfo *sn);
 void bdrv_image_info_specific_dump(ImageInfoSpecific *info_spec,
                                    const char *prefix);
-void bdrv_image_info_dump(ImageInfo *info);
+void bdrv_node_info_dump(BlockNodeInfo *info);
 #endif
diff --git a/block/monitor/block-hmp-cmds.c b/block/monitor/block-hmp-cmds.c
index 0ff7c84039..d6eaacdb12 100644
--- a/block/monitor/block-hmp-cmds.c
+++ b/block/monitor/block-hmp-cmds.c
@@ -725,7 +725,7 @@ static void print_block_info(Monitor *mon, BlockInfo *info,
         monitor_printf(mon, "\nImages:\n");
         image_info = inserted->image;
         while (1) {
-                bdrv_image_info_dump(image_info);
+            bdrv_node_info_dump(qapi_ImageInfo_base(image_info));
             if (image_info->backing_image) {
                 image_info = image_info->backing_image;
             } else {
diff --git a/block/qapi.c b/block/qapi.c
index b3f812a071..21ef684a1c 100644
--- a/block/qapi.c
+++ b/block/qapi.c
@@ -847,7 +847,7 @@ void bdrv_image_info_specific_dump(ImageInfoSpecific *info_spec,
     visit_free(v);
 }
 
-void bdrv_image_info_dump(ImageInfo *info)
+void bdrv_node_info_dump(BlockNodeInfo *info)
 {
     char *size_buf, *dsize_buf;
     if (!info->has_actual_size) {
diff --git a/qemu-img.c b/qemu-img.c
index c3671d4890..0cad524267 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -2816,13 +2816,13 @@ static void dump_snapshots(BlockDriverState *bs)
     g_free(sn_tab);
 }
 
-static void dump_json_image_info_list(ImageInfoList *list)
+static void dump_json_block_node_info_list(BlockNodeInfoList *list)
 {
     GString *str;
     QObject *obj;
     Visitor *v = qobject_output_visitor_new(&obj);
 
-    visit_type_ImageInfoList(v, NULL, &list, &error_abort);
+    visit_type_BlockNodeInfoList(v, NULL, &list, &error_abort);
     visit_complete(v, &obj);
     str = qobject_to_json_pretty(obj, true);
     assert(str != NULL);
@@ -2832,13 +2832,13 @@ static void dump_json_image_info_list(ImageInfoList *list)
     g_string_free(str, true);
 }
 
-static void dump_json_image_info(ImageInfo *info)
+static void dump_json_block_node_info(BlockNodeInfo *info)
 {
     GString *str;
     QObject *obj;
     Visitor *v = qobject_output_visitor_new(&obj);
 
-    visit_type_ImageInfo(v, NULL, &info, &error_abort);
+    visit_type_BlockNodeInfo(v, NULL, &info, &error_abort);
     visit_complete(v, &obj);
     str = qobject_to_json_pretty(obj, true);
     assert(str != NULL);
@@ -2848,9 +2848,9 @@ static void dump_json_image_info(ImageInfo *info)
     g_string_free(str, true);
 }
 
-static void dump_human_image_info_list(ImageInfoList *list)
+static void dump_human_image_info_list(BlockNodeInfoList *list)
 {
-    ImageInfoList *elem;
+    BlockNodeInfoList *elem;
     bool delim = false;
 
     for (elem = list; elem; elem = elem->next) {
@@ -2859,7 +2859,7 @@ static void dump_human_image_info_list(ImageInfoList *list)
         }
         delim = true;
 
-        bdrv_image_info_dump(elem->value);
+        bdrv_node_info_dump(elem->value);
     }
 }
 
@@ -2869,24 +2869,24 @@ static gboolean str_equal_func(gconstpointer a, gconstpointer b)
 }
 
 /**
- * Open an image file chain and return an ImageInfoList
+ * Open an image file chain and return an BlockNodeInfoList
  *
  * @filename: topmost image filename
  * @fmt: topmost image format (may be NULL to autodetect)
  * @chain: true  - enumerate entire backing file chain
  *         false - only topmost image file
  *
- * Returns a list of ImageInfo objects or NULL if there was an error opening an
- * image file.  If there was an error a message will have been printed to
- * stderr.
+ * Returns a list of BlockNodeInfo objects or NULL if there was an error
+ * opening an image file.  If there was an error a message will have been
+ * printed to stderr.
  */
-static ImageInfoList *collect_image_info_list(bool image_opts,
-                                              const char *filename,
-                                              const char *fmt,
-                                              bool chain, bool force_share)
+static BlockNodeInfoList *collect_image_info_list(bool image_opts,
+                                                  const char *filename,
+                                                  const char *fmt,
+                                                  bool chain, bool force_share)
 {
-    ImageInfoList *head = NULL;
-    ImageInfoList **tail = &head;
+    BlockNodeInfoList *head = NULL;
+    BlockNodeInfoList **tail = &head;
     GHashTable *filenames;
     Error *err = NULL;
 
@@ -2895,7 +2895,7 @@ static ImageInfoList *collect_image_info_list(bool image_opts,
     while (filename) {
         BlockBackend *blk;
         BlockDriverState *bs;
-        ImageInfo *info;
+        BlockNodeInfo *info;
 
         if (g_hash_table_lookup_extended(filenames, filename, NULL, NULL)) {
             error_report("Backing file '%s' creates an infinite loop.",
@@ -2912,7 +2912,7 @@ static ImageInfoList *collect_image_info_list(bool image_opts,
         }
         bs = blk_bs(blk);
 
-        bdrv_query_image_info(bs, &info, &err);
+        bdrv_query_block_node_info(bs, &info, &err);
         if (err) {
             error_report_err(err);
             blk_unref(blk);
@@ -2945,7 +2945,7 @@ static ImageInfoList *collect_image_info_list(bool image_opts,
     return head;
 
 err:
-    qapi_free_ImageInfoList(head);
+    qapi_free_BlockNodeInfoList(head);
     g_hash_table_destroy(filenames);
     return NULL;
 }
@@ -2956,7 +2956,7 @@ static int img_info(int argc, char **argv)
     OutputFormat output_format = OFORMAT_HUMAN;
     bool chain = false;
     const char *filename, *fmt, *output;
-    ImageInfoList *list;
+    BlockNodeInfoList *list;
     bool image_opts = false;
     bool force_share = false;
 
@@ -3035,14 +3035,14 @@ static int img_info(int argc, char **argv)
         break;
     case OFORMAT_JSON:
         if (chain) {
-            dump_json_image_info_list(list);
+            dump_json_block_node_info_list(list);
         } else {
-            dump_json_image_info(list->value);
+            dump_json_block_node_info(list->value);
         }
         break;
     }
 
-    qapi_free_ImageInfoList(list);
+    qapi_free_BlockNodeInfoList(list);
     return 0;
 }
 
-- 
2.38.1



^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PULL 32/38] block/qapi: Let bdrv_query_image_info() recurse
  2023-01-20 12:25 [PULL 00/38] Block layer patches Kevin Wolf
                   ` (30 preceding siblings ...)
  2023-01-20 12:26 ` [PULL 31/38] qemu-img: Use BlockNodeInfo Kevin Wolf
@ 2023-01-20 12:26 ` Kevin Wolf
  2023-01-20 12:26 ` [PULL 33/38] block/qapi: Introduce BlockGraphInfo Kevin Wolf
                   ` (6 subsequent siblings)
  38 siblings, 0 replies; 48+ messages in thread
From: Kevin Wolf @ 2023-01-20 12:26 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, peter.maydell, qemu-devel

From: Hanna Reitz <hreitz@redhat.com>

There is no real reason why bdrv_query_image_info() should generally not
recurse.  The ImageInfo struct has a pointer to the backing image, so it
should generally be filled, unless the caller explicitly opts out.

This moves the recursing code from bdrv_block_device_info() into
bdrv_query_image_info().

Signed-off-by: Hanna Reitz <hreitz@redhat.com>
Message-Id: <20220620162704.80987-7-hreitz@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 include/block/qapi.h |  2 +
 block/qapi.c         | 92 +++++++++++++++++++++++++++-----------------
 2 files changed, 58 insertions(+), 36 deletions(-)

diff --git a/include/block/qapi.h b/include/block/qapi.h
index 22198dcd0c..2174bf8fa2 100644
--- a/include/block/qapi.h
+++ b/include/block/qapi.h
@@ -40,6 +40,8 @@ void bdrv_query_block_node_info(BlockDriverState *bs,
                                 Error **errp);
 void bdrv_query_image_info(BlockDriverState *bs,
                            ImageInfo **p_info,
+                           bool flat,
+                           bool skip_implicit_filters,
                            Error **errp);
 
 void bdrv_snapshot_dump(QEMUSnapshotInfo *sn);
diff --git a/block/qapi.c b/block/qapi.c
index 21ef684a1c..fa8bbc3fc7 100644
--- a/block/qapi.c
+++ b/block/qapi.c
@@ -47,8 +47,10 @@ BlockDeviceInfo *bdrv_block_device_info(BlockBackend *blk,
                                         Error **errp)
 {
     ImageInfo **p_image_info;
+    ImageInfo *backing_info;
     BlockDriverState *bs0, *backing;
     BlockDeviceInfo *info;
+    ERRP_GUARD();
 
     if (!bs->drv) {
         error_setg(errp, "Block device %s is ejected", bs->node_name);
@@ -146,37 +148,21 @@ BlockDeviceInfo *bdrv_block_device_info(BlockBackend *blk,
     bs0 = bs;
     p_image_info = &info->image;
     info->backing_file_depth = 0;
-    while (1) {
-        Error *local_err = NULL;
-        bdrv_query_image_info(bs0, p_image_info, &local_err);
-        if (local_err) {
-            error_propagate(errp, local_err);
-            qapi_free_BlockDeviceInfo(info);
-            return NULL;
-        }
-
-        /* stop gathering data for flat output */
-        if (flat) {
-            break;
-        }
 
-        if (bs0->drv && bdrv_filter_or_cow_child(bs0)) {
-            /*
-             * Put any filtered child here (for backwards compatibility to when
-             * we put bs0->backing here, which might be any filtered child).
-             */
-            info->backing_file_depth++;
-            bs0 = bdrv_filter_or_cow_bs(bs0);
-            p_image_info = &((*p_image_info)->backing_image);
-        } else {
-            break;
-        }
+    /*
+     * Skip automatically inserted nodes that the user isn't aware of for
+     * query-block (blk != NULL), but not for query-named-block-nodes
+     */
+    bdrv_query_image_info(bs0, p_image_info, flat, blk != NULL, errp);
+    if (*errp) {
+        qapi_free_BlockDeviceInfo(info);
+        return NULL;
+    }
 
-        /* Skip automatically inserted nodes that the user isn't aware of for
-         * query-block (blk != NULL), but not for query-named-block-nodes */
-        if (blk) {
-            bs0 = bdrv_skip_implicit_filters(bs0);
-        }
+    backing_info = info->image->backing_image;
+    while (backing_info) {
+        info->backing_file_depth++;
+        backing_info = backing_info->backing_image;
     }
 
     return info;
@@ -354,19 +340,28 @@ void bdrv_query_block_node_info(BlockDriverState *bs,
  * bdrv_query_image_info:
  * @bs: block node to examine
  * @p_info: location to store image information
+ * @flat: skip backing node information
+ * @skip_implicit_filters: skip implicit filters in the backing chain
  * @errp: location to store error information
  *
- * Store "flat" image information in @p_info.
+ * Store image information in @p_info, potentially recursively covering the
+ * backing chain.
  *
- * "Flat" means it does *not* query backing image information,
- * i.e. (*pinfo)->has_backing_image will be set to false and
- * (*pinfo)->backing_image to NULL even when the image does in fact have
- * a backing image.
+ * If @flat is true, do not query backing image information, i.e.
+ * (*p_info)->has_backing_image will be set to false and
+ * (*p_info)->backing_image to NULL even when the image does in fact have a
+ * backing image.
+ *
+ * If @skip_implicit_filters is true, implicit filter nodes in the backing chain
+ * will be skipped when querying backing image information.
+ * (@skip_implicit_filters is ignored when @flat is true.)
  *
  * @p_info will be set only on success. On error, store error in @errp.
  */
 void bdrv_query_image_info(BlockDriverState *bs,
                            ImageInfo **p_info,
+                           bool flat,
+                           bool skip_implicit_filters,
                            Error **errp)
 {
     ImageInfo *info;
@@ -375,11 +370,36 @@ void bdrv_query_image_info(BlockDriverState *bs,
     info = g_new0(ImageInfo, 1);
     bdrv_do_query_node_info(bs, qapi_ImageInfo_base(info), errp);
     if (*errp) {
-        qapi_free_ImageInfo(info);
-        return;
+        goto fail;
+    }
+
+    if (!flat) {
+        BlockDriverState *backing;
+
+        /*
+         * Use any filtered child here (for backwards compatibility to when
+         * we always took bs->backing, which might be any filtered child).
+         */
+        backing = bdrv_filter_or_cow_bs(bs);
+        if (skip_implicit_filters) {
+            backing = bdrv_skip_implicit_filters(backing);
+        }
+
+        if (backing) {
+            bdrv_query_image_info(backing, &info->backing_image, false,
+                                  skip_implicit_filters, errp);
+            if (*errp) {
+                goto fail;
+            }
+        }
     }
 
     *p_info = info;
+    return;
+
+fail:
+    assert(*errp);
+    qapi_free_ImageInfo(info);
 }
 
 /* @p_info will be set only on success. */
-- 
2.38.1



^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PULL 33/38] block/qapi: Introduce BlockGraphInfo
  2023-01-20 12:25 [PULL 00/38] Block layer patches Kevin Wolf
                   ` (31 preceding siblings ...)
  2023-01-20 12:26 ` [PULL 32/38] block/qapi: Let bdrv_query_image_info() recurse Kevin Wolf
@ 2023-01-20 12:26 ` Kevin Wolf
  2023-01-20 12:26 ` [PULL 34/38] block/qapi: Add indentation to bdrv_node_info_dump() Kevin Wolf
                   ` (5 subsequent siblings)
  38 siblings, 0 replies; 48+ messages in thread
From: Kevin Wolf @ 2023-01-20 12:26 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, peter.maydell, qemu-devel

From: Hanna Reitz <hreitz@redhat.com>

Introduce a new QAPI type BlockGraphInfo and an associated
bdrv_query_block_graph_info() function that recursively gathers
BlockNodeInfo objects through a block graph.

A follow-up patch is going to make "qemu-img info" use this to print
information about all nodes that are (usually implicitly) opened for a
given image file.

Signed-off-by: Hanna Reitz <hreitz@redhat.com>
Message-Id: <20220620162704.80987-8-hreitz@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 qapi/block-core.json | 35 ++++++++++++++++++++++++++++++++
 include/block/qapi.h |  3 +++
 block/qapi.c         | 48 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 86 insertions(+)

diff --git a/qapi/block-core.json b/qapi/block-core.json
index 4cf2deeb6c..d703e0fb16 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -307,6 +307,41 @@
       '*backing-image': 'ImageInfo'
   } }
 
+##
+# @BlockChildInfo:
+#
+# Information about all nodes in the block graph starting at some node,
+# annotated with information about that node in relation to its parent.
+#
+# @name: Child name of the root node in the BlockGraphInfo struct, in its role
+#        as the child of some undescribed parent node
+#
+# @info: Block graph information starting at this node
+#
+# Since: 8.0
+##
+{ 'struct': 'BlockChildInfo',
+  'data': {
+      'name': 'str',
+      'info': 'BlockGraphInfo'
+  } }
+
+##
+# @BlockGraphInfo:
+#
+# Information about all nodes in a block (sub)graph in the form of BlockNodeInfo
+# data.
+# The base BlockNodeInfo struct contains the information for the (sub)graph's
+# root node.
+#
+# @children: Array of links to this node's child nodes' information
+#
+# Since: 8.0
+##
+{ 'struct': 'BlockGraphInfo',
+  'base': 'BlockNodeInfo',
+  'data': { 'children': ['BlockChildInfo'] } }
+
 ##
 # @ImageCheck:
 #
diff --git a/include/block/qapi.h b/include/block/qapi.h
index 2174bf8fa2..196436020e 100644
--- a/include/block/qapi.h
+++ b/include/block/qapi.h
@@ -43,6 +43,9 @@ void bdrv_query_image_info(BlockDriverState *bs,
                            bool flat,
                            bool skip_implicit_filters,
                            Error **errp);
+void bdrv_query_block_graph_info(BlockDriverState *bs,
+                                 BlockGraphInfo **p_info,
+                                 Error **errp);
 
 void bdrv_snapshot_dump(QEMUSnapshotInfo *sn);
 void bdrv_image_info_specific_dump(ImageInfoSpecific *info_spec,
diff --git a/block/qapi.c b/block/qapi.c
index fa8bbc3fc7..7335c9728d 100644
--- a/block/qapi.c
+++ b/block/qapi.c
@@ -402,6 +402,54 @@ fail:
     qapi_free_ImageInfo(info);
 }
 
+/**
+ * bdrv_query_block_graph_info:
+ * @bs: root node to start from
+ * @p_info: location to store image information
+ * @errp: location to store error information
+ *
+ * Store image information about the graph starting from @bs in @p_info.
+ *
+ * @p_info will be set only on success. On error, store error in @errp.
+ */
+void bdrv_query_block_graph_info(BlockDriverState *bs,
+                                 BlockGraphInfo **p_info,
+                                 Error **errp)
+{
+    BlockGraphInfo *info;
+    BlockChildInfoList **children_list_tail;
+    BdrvChild *c;
+    ERRP_GUARD();
+
+    info = g_new0(BlockGraphInfo, 1);
+    bdrv_do_query_node_info(bs, qapi_BlockGraphInfo_base(info), errp);
+    if (*errp) {
+        goto fail;
+    }
+
+    children_list_tail = &info->children;
+
+    QLIST_FOREACH(c, &bs->children, next) {
+        BlockChildInfo *c_info;
+
+        c_info = g_new0(BlockChildInfo, 1);
+        QAPI_LIST_APPEND(children_list_tail, c_info);
+
+        c_info->name = g_strdup(c->name);
+        bdrv_query_block_graph_info(c->bs, &c_info->info, errp);
+        if (*errp) {
+            goto fail;
+        }
+    }
+
+    *p_info = info;
+    return;
+
+fail:
+    assert(*errp != NULL);
+    qapi_free_BlockGraphInfo(info);
+}
+
 /* @p_info will be set only on success. */
 static void bdrv_query_info(BlockBackend *blk, BlockInfo **p_info,
                             Error **errp)
-- 
2.38.1



^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PULL 34/38] block/qapi: Add indentation to bdrv_node_info_dump()
  2023-01-20 12:25 [PULL 00/38] Block layer patches Kevin Wolf
                   ` (32 preceding siblings ...)
  2023-01-20 12:26 ` [PULL 33/38] block/qapi: Introduce BlockGraphInfo Kevin Wolf
@ 2023-01-20 12:26 ` Kevin Wolf
  2023-01-20 12:26 ` [PULL 35/38] iotests: Filter child node information Kevin Wolf
                   ` (4 subsequent siblings)
  38 siblings, 0 replies; 48+ messages in thread
From: Kevin Wolf @ 2023-01-20 12:26 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, peter.maydell, qemu-devel

From: Hanna Reitz <hreitz@redhat.com>

In order to let qemu-img info present a block graph, add a parameter to
bdrv_node_info_dump() and bdrv_image_info_specific_dump() so that the
information of nodes below the root level can be given an indentation.

Signed-off-by: Hanna Reitz <hreitz@redhat.com>
Message-Id: <20220620162704.80987-9-hreitz@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 include/block/qapi.h           |  5 ++--
 block/monitor/block-hmp-cmds.c |  2 +-
 block/qapi.c                   | 47 +++++++++++++++++++---------------
 qemu-img.c                     |  2 +-
 qemu-io-cmds.c                 |  3 ++-
 5 files changed, 34 insertions(+), 25 deletions(-)

diff --git a/include/block/qapi.h b/include/block/qapi.h
index 196436020e..38855f2ae9 100644
--- a/include/block/qapi.h
+++ b/include/block/qapi.h
@@ -49,6 +49,7 @@ void bdrv_query_block_graph_info(BlockDriverState *bs,
 
 void bdrv_snapshot_dump(QEMUSnapshotInfo *sn);
 void bdrv_image_info_specific_dump(ImageInfoSpecific *info_spec,
-                                   const char *prefix);
-void bdrv_node_info_dump(BlockNodeInfo *info);
+                                   const char *prefix,
+                                   int indentation);
+void bdrv_node_info_dump(BlockNodeInfo *info, int indentation);
 #endif
diff --git a/block/monitor/block-hmp-cmds.c b/block/monitor/block-hmp-cmds.c
index d6eaacdb12..4b441ac468 100644
--- a/block/monitor/block-hmp-cmds.c
+++ b/block/monitor/block-hmp-cmds.c
@@ -725,7 +725,7 @@ static void print_block_info(Monitor *mon, BlockInfo *info,
         monitor_printf(mon, "\nImages:\n");
         image_info = inserted->image;
         while (1) {
-            bdrv_node_info_dump(qapi_ImageInfo_base(image_info));
+            bdrv_node_info_dump(qapi_ImageInfo_base(image_info), 0);
             if (image_info->backing_image) {
                 image_info = image_info->backing_image;
             } else {
diff --git a/block/qapi.c b/block/qapi.c
index 7335c9728d..ae61d2c856 100644
--- a/block/qapi.c
+++ b/block/qapi.c
@@ -897,7 +897,8 @@ static bool qobject_is_empty_dump(const QObject *obj)
  * prepending an optional prefix if the dump is not empty.
  */
 void bdrv_image_info_specific_dump(ImageInfoSpecific *info_spec,
-                                   const char *prefix)
+                                   const char *prefix,
+                                   int indentation)
 {
     QObject *obj, *data;
     Visitor *v = qobject_output_visitor_new(&obj);
@@ -907,48 +908,51 @@ void bdrv_image_info_specific_dump(ImageInfoSpecific *info_spec,
     data = qdict_get(qobject_to(QDict, obj), "data");
     if (!qobject_is_empty_dump(data)) {
         if (prefix) {
-            qemu_printf("%s", prefix);
+            qemu_printf("%*s%s", indentation * 4, "", prefix);
         }
-        dump_qobject(1, data);
+        dump_qobject(indentation + 1, data);
     }
     qobject_unref(obj);
     visit_free(v);
 }
 
-void bdrv_node_info_dump(BlockNodeInfo *info)
+void bdrv_node_info_dump(BlockNodeInfo *info, int indentation)
 {
     char *size_buf, *dsize_buf;
+    g_autofree char *ind_s = g_strdup_printf("%*s", indentation * 4, "");
+
     if (!info->has_actual_size) {
         dsize_buf = g_strdup("unavailable");
     } else {
         dsize_buf = size_to_str(info->actual_size);
     }
     size_buf = size_to_str(info->virtual_size);
-    qemu_printf("image: %s\n"
-                "file format: %s\n"
-                "virtual size: %s (%" PRId64 " bytes)\n"
-                "disk size: %s\n",
-                info->filename, info->format, size_buf,
-                info->virtual_size,
-                dsize_buf);
+    qemu_printf("%simage: %s\n"
+                "%sfile format: %s\n"
+                "%svirtual size: %s (%" PRId64 " bytes)\n"
+                "%sdisk size: %s\n",
+                ind_s, info->filename,
+                ind_s, info->format,
+                ind_s, size_buf, info->virtual_size,
+                ind_s, dsize_buf);
     g_free(size_buf);
     g_free(dsize_buf);
 
     if (info->has_encrypted && info->encrypted) {
-        qemu_printf("encrypted: yes\n");
+        qemu_printf("%sencrypted: yes\n", ind_s);
     }
 
     if (info->has_cluster_size) {
-        qemu_printf("cluster_size: %" PRId64 "\n",
-                    info->cluster_size);
+        qemu_printf("%scluster_size: %" PRId64 "\n",
+                    ind_s, info->cluster_size);
     }
 
     if (info->has_dirty_flag && info->dirty_flag) {
-        qemu_printf("cleanly shut down: no\n");
+        qemu_printf("%scleanly shut down: no\n", ind_s);
     }
 
     if (info->backing_filename) {
-        qemu_printf("backing file: %s", info->backing_filename);
+        qemu_printf("%sbacking file: %s", ind_s, info->backing_filename);
         if (!info->full_backing_filename) {
             qemu_printf(" (cannot determine actual path)");
         } else if (strcmp(info->backing_filename,
@@ -957,15 +961,16 @@ void bdrv_node_info_dump(BlockNodeInfo *info)
         }
         qemu_printf("\n");
         if (info->backing_filename_format) {
-            qemu_printf("backing file format: %s\n",
-                        info->backing_filename_format);
+            qemu_printf("%sbacking file format: %s\n",
+                        ind_s, info->backing_filename_format);
         }
     }
 
     if (info->has_snapshots) {
         SnapshotInfoList *elem;
 
-        qemu_printf("Snapshot list:\n");
+        qemu_printf("%sSnapshot list:\n", ind_s);
+        qemu_printf("%s", ind_s);
         bdrv_snapshot_dump(NULL);
         qemu_printf("\n");
 
@@ -985,6 +990,7 @@ void bdrv_node_info_dump(BlockNodeInfo *info)
 
             pstrcpy(sn.id_str, sizeof(sn.id_str), elem->value->id);
             pstrcpy(sn.name, sizeof(sn.name), elem->value->name);
+            qemu_printf("%s", ind_s);
             bdrv_snapshot_dump(&sn);
             qemu_printf("\n");
         }
@@ -992,6 +998,7 @@ void bdrv_node_info_dump(BlockNodeInfo *info)
 
     if (info->format_specific) {
         bdrv_image_info_specific_dump(info->format_specific,
-                                      "Format specific information:\n");
+                                      "Format specific information:\n",
+                                      indentation);
     }
 }
diff --git a/qemu-img.c b/qemu-img.c
index 0cad524267..04937bad11 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -2859,7 +2859,7 @@ static void dump_human_image_info_list(BlockNodeInfoList *list)
         }
         delim = true;
 
-        bdrv_node_info_dump(elem->value);
+        bdrv_node_info_dump(elem->value, 0);
     }
 }
 
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
index d7e562dda6..a061031615 100644
--- a/qemu-io-cmds.c
+++ b/qemu-io-cmds.c
@@ -1789,7 +1789,8 @@ static int info_f(BlockBackend *blk, int argc, char **argv)
     }
     if (spec_info) {
         bdrv_image_info_specific_dump(spec_info,
-                                      "Format specific information:\n");
+                                      "Format specific information:\n",
+                                      0);
         qapi_free_ImageInfoSpecific(spec_info);
     }
 
-- 
2.38.1



^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PULL 35/38] iotests: Filter child node information
  2023-01-20 12:25 [PULL 00/38] Block layer patches Kevin Wolf
                   ` (33 preceding siblings ...)
  2023-01-20 12:26 ` [PULL 34/38] block/qapi: Add indentation to bdrv_node_info_dump() Kevin Wolf
@ 2023-01-20 12:26 ` Kevin Wolf
  2023-01-20 12:26 ` [PULL 36/38] iotests/106, 214, 308: Read only one size line Kevin Wolf
                   ` (3 subsequent siblings)
  38 siblings, 0 replies; 48+ messages in thread
From: Kevin Wolf @ 2023-01-20 12:26 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, peter.maydell, qemu-devel

From: Hanna Reitz <hreitz@redhat.com>

Before we let qemu-img info print child node information, have
common.filter, common.rc, and iotests.py filter it from the test output
so we get as few reference output changes as possible.

Signed-off-by: Hanna Reitz <hreitz@redhat.com>
Message-Id: <20220620162704.80987-10-hreitz@redhat.com>
Tested-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 tests/qemu-iotests/iotests.py    | 18 +++++++++++++++---
 tests/qemu-iotests/common.filter | 22 ++++++++++++++--------
 tests/qemu-iotests/common.rc     | 22 ++++++++++++++--------
 3 files changed, 43 insertions(+), 19 deletions(-)

diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
index da7d6637e1..94aeb3f3b2 100644
--- a/tests/qemu-iotests/iotests.py
+++ b/tests/qemu-iotests/iotests.py
@@ -329,7 +329,7 @@ def qemu_img_log(*args: str, check: bool = True
 
 def img_info_log(filename: str, filter_path: Optional[str] = None,
                  use_image_opts: bool = False, extra_args: Sequence[str] = (),
-                 check: bool = True,
+                 check: bool = True, drop_child_info: bool = True,
                  ) -> None:
     args = ['info']
     if use_image_opts:
@@ -342,7 +342,7 @@ def img_info_log(filename: str, filter_path: Optional[str] = None,
     output = qemu_img(*args, check=check).stdout
     if not filter_path:
         filter_path = filename
-    log(filter_img_info(output, filter_path))
+    log(filter_img_info(output, filter_path, drop_child_info))
 
 def qemu_io_wrap_args(args: Sequence[str]) -> List[str]:
     if '-f' in args or '--image-opts' in args:
@@ -642,11 +642,23 @@ def _filter(_key, value):
 def filter_generated_node_ids(msg):
     return re.sub("#block[0-9]+", "NODE_NAME", msg)
 
-def filter_img_info(output, filename):
+def filter_img_info(output: str, filename: str,
+                    drop_child_info: bool = True) -> str:
     lines = []
+    drop_indented = False
     for line in output.split('\n'):
         if 'disk size' in line or 'actual-size' in line:
             continue
+
+        # Drop child node info
+        if drop_indented:
+            if line.startswith(' '):
+                continue
+            drop_indented = False
+        if drop_child_info and "Child node '/" in line:
+            drop_indented = True
+            continue
+
         line = line.replace(filename, 'TEST_IMG')
         line = filter_testfiles(line)
         line = line.replace(imgfmt, 'IMGFMT')
diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter
index cc9f1a5891..6b32c7fbfa 100644
--- a/tests/qemu-iotests/common.filter
+++ b/tests/qemu-iotests/common.filter
@@ -223,6 +223,7 @@ _filter_img_info()
 
     discard=0
     regex_json_spec_start='^ *"format-specific": \{'
+    regex_json_child_start='^ *"children": \['
     gsed -e "s#$REMOTE_TEST_DIR#TEST_DIR#g" \
         -e "s#$IMGPROTO:$TEST_DIR#TEST_DIR#g" \
         -e "s#$TEST_DIR#TEST_DIR#g" \
@@ -251,20 +252,25 @@ _filter_img_info()
         -e 's/\(compression type: \)\(zlib\|zstd\)/\1COMPRESSION_TYPE/' \
         -e "s/uuid: [-a-f0-9]\\+/uuid: 00000000-0000-0000-0000-000000000000/" | \
     while IFS='' read -r line; do
-        if [[ $format_specific == 1 ]]; then
-            discard=0
-        elif [[ $line == "Format specific information:" ]]; then
-            discard=1
-        elif [[ $line =~ $regex_json_spec_start ]]; then
-            discard=2
-            regex_json_spec_end="^${line%%[^ ]*}\\},? *$"
+        if [[ $discard == 0 ]]; then
+            if [[ $format_specific == 0 && $line == "Format specific information:" ]]; then
+                discard=1
+            elif [[ $line =~ "Child node '/" ]]; then
+                discard=1
+            elif [[ $line =~ $regex_json_spec_start ]]; then
+                discard=2
+                regex_json_end="^${line%%[^ ]*}\\},? *$"
+            elif [[ $line =~ $regex_json_child_start ]]; then
+                discard=2
+                regex_json_end="^${line%%[^ ]*}\\],? *$"
+            fi
         fi
         if [[ $discard == 0 ]]; then
             echo "$line"
         elif [[ $discard == 1 && ! $line ]]; then
             echo
             discard=0
-        elif [[ $discard == 2 && $line =~ $regex_json_spec_end ]]; then
+        elif [[ $discard == 2 && $line =~ $regex_json_end ]]; then
             discard=0
         fi
     done
diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc
index db757025cb..f4476b62f7 100644
--- a/tests/qemu-iotests/common.rc
+++ b/tests/qemu-iotests/common.rc
@@ -711,6 +711,7 @@ _img_info()
 
     discard=0
     regex_json_spec_start='^ *"format-specific": \{'
+    regex_json_child_start='^ *"children": \['
     $QEMU_IMG info $QEMU_IMG_EXTRA_ARGS "$@" "$TEST_IMG" 2>&1 | \
         sed -e "s#$REMOTE_TEST_DIR#TEST_DIR#g" \
             -e "s#$IMGPROTO:$TEST_DIR#TEST_DIR#g" \
@@ -721,20 +722,25 @@ _img_info()
             -e "/^disk size:/ D" \
             -e "/actual-size/ D" | \
         while IFS='' read -r line; do
-            if [[ $format_specific == 1 ]]; then
-                discard=0
-            elif [[ $line == "Format specific information:" ]]; then
-                discard=1
-            elif [[ $line =~ $regex_json_spec_start ]]; then
-                discard=2
-                regex_json_spec_end="^${line%%[^ ]*}\\},? *$"
+            if [[ $discard == 0 ]]; then
+                if [[ $format_specific == 0 && $line == "Format specific information:" ]]; then
+                    discard=1
+                elif [[ $line =~ "Child node '/" ]]; then
+                    discard=1
+                elif [[ $format_specific == 0 && $line =~ $regex_json_spec_start ]]; then
+                    discard=2
+                    regex_json_end="^${line%%[^ ]*}\\},? *$"
+                elif [[ $line =~ $regex_json_child_start ]]; then
+                    discard=2
+                    regex_json_end="^${line%%[^ ]*}\\],? *$"
+                fi
             fi
             if [[ $discard == 0 ]]; then
                 echo "$line"
             elif [[ $discard == 1 && ! $line ]]; then
                 echo
                 discard=0
-            elif [[ $discard == 2 && $line =~ $regex_json_spec_end ]]; then
+            elif [[ $discard == 2 && $line =~ $regex_json_end ]]; then
                 discard=0
             fi
         done
-- 
2.38.1



^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PULL 36/38] iotests/106, 214, 308: Read only one size line
  2023-01-20 12:25 [PULL 00/38] Block layer patches Kevin Wolf
                   ` (34 preceding siblings ...)
  2023-01-20 12:26 ` [PULL 35/38] iotests: Filter child node information Kevin Wolf
@ 2023-01-20 12:26 ` Kevin Wolf
  2023-01-20 12:26 ` [PULL 37/38] qemu-img: Let info print block graph Kevin Wolf
                   ` (2 subsequent siblings)
  38 siblings, 0 replies; 48+ messages in thread
From: Kevin Wolf @ 2023-01-20 12:26 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, peter.maydell, qemu-devel

From: Hanna Reitz <hreitz@redhat.com>

These tests read size information (sometimes disk size, sometimes
virtual size) from qemu-img info's output.  Once qemu-img starts
printing info about child nodes, we are going to see multiple instances
of that per image, but these tests are only interested in the first one,
so use "head -n 1" to get it.

Signed-off-by: Hanna Reitz <hreitz@redhat.com>
Message-Id: <20220620162704.80987-11-hreitz@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 tests/qemu-iotests/106 | 4 ++--
 tests/qemu-iotests/214 | 6 ++++--
 tests/qemu-iotests/308 | 4 ++--
 3 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/tests/qemu-iotests/106 b/tests/qemu-iotests/106
index 9d6adb542d..ae0fc46691 100755
--- a/tests/qemu-iotests/106
+++ b/tests/qemu-iotests/106
@@ -66,7 +66,7 @@ for create_mode in off falloc full; do
             expected_size=$((expected_size + $GROWTH_SIZE))
         fi
 
-        actual_size=$($QEMU_IMG info -f "$IMGFMT" "$TEST_IMG" | grep 'disk size')
+        actual_size=$($QEMU_IMG info -f "$IMGFMT" "$TEST_IMG" | grep 'disk size' | head -n 1)
         actual_size=$(echo "$actual_size" | sed -e 's/^[^0-9]*\([0-9]\+\).*$/\1/')
 
         # The actual size may exceed the expected size, depending on the file
@@ -105,7 +105,7 @@ for growth_mode in falloc full; do
     _make_test_img -o "extent_size_hint=0" 2G
     $QEMU_IMG resize -f "$IMGFMT" --preallocation=$growth_mode "$TEST_IMG" +${GROWTH_SIZE}K
 
-    actual_size=$($QEMU_IMG info -f "$IMGFMT" "$TEST_IMG" | grep 'disk size')
+    actual_size=$($QEMU_IMG info -f "$IMGFMT" "$TEST_IMG" | grep 'disk size' | head -n 1)
     actual_size=$(echo "$actual_size" | sed -e 's/^[^0-9]*\([0-9]\+\).*$/\1/')
 
     if [ $actual_size -lt $GROWTH_SIZE ]; then
diff --git a/tests/qemu-iotests/214 b/tests/qemu-iotests/214
index c66e246ba2..55ffcd7f44 100755
--- a/tests/qemu-iotests/214
+++ b/tests/qemu-iotests/214
@@ -102,7 +102,8 @@ let data_size="8 * $cluster_size"
 $QEMU_IO -c "write -P 0xaa 0 $data_size" "$TEST_IMG" \
          2>&1 | _filter_qemu_io | _filter_testdir
 sizeA=$($QEMU_IMG info --output=json "$TEST_IMG" |
-        sed -n '/"actual-size":/ s/[^0-9]//gp')
+        sed -n '/"actual-size":/ s/[^0-9]//gp' |
+        head -n 1)
 
 _make_test_img 2M -o cluster_size=$cluster_size
 echo "Write compressed data:"
@@ -124,7 +125,8 @@ $QEMU_IO -c "write -P 0xcc $offset $data_size" "json:{\
                           _filter_qemu_io | _filter_testdir
 
 sizeB=$($QEMU_IMG info --output=json "$TEST_IMG" |
-        sed -n '/"actual-size":/ s/[^0-9]//gp')
+        sed -n '/"actual-size":/ s/[^0-9]//gp' |
+        head -n 1)
 
 if [ $sizeA -lt $sizeB ]
 then
diff --git a/tests/qemu-iotests/308 b/tests/qemu-iotests/308
index bde4aac2fa..09275e9a10 100755
--- a/tests/qemu-iotests/308
+++ b/tests/qemu-iotests/308
@@ -217,12 +217,12 @@ echo
 echo '=== Remove export ==='
 
 # Double-check that $EXT_MP appears as a non-empty file (the raw image)
-$QEMU_IMG info -f raw "$EXT_MP" | grep 'virtual size'
+$QEMU_IMG info -f raw "$EXT_MP" | grep 'virtual size' | head -n 1
 
 fuse_export_del 'export-mp'
 
 # See that the file appears empty again
-$QEMU_IMG info -f raw "$EXT_MP" | grep 'virtual size'
+$QEMU_IMG info -f raw "$EXT_MP" | grep 'virtual size' | head -n 1
 
 echo
 echo '=== Writable export ==='
-- 
2.38.1



^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PULL 37/38] qemu-img: Let info print block graph
  2023-01-20 12:25 [PULL 00/38] Block layer patches Kevin Wolf
                   ` (35 preceding siblings ...)
  2023-01-20 12:26 ` [PULL 36/38] iotests/106, 214, 308: Read only one size line Kevin Wolf
@ 2023-01-20 12:26 ` Kevin Wolf
  2023-01-20 12:26 ` [PULL 38/38] qemu-img: Change info key names for protocol nodes Kevin Wolf
  2023-01-21 13:03 ` [PULL 00/38] Block layer patches Peter Maydell
  38 siblings, 0 replies; 48+ messages in thread
From: Kevin Wolf @ 2023-01-20 12:26 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, peter.maydell, qemu-devel

From: Hanna Reitz <hreitz@redhat.com>

For every node in the backing chain, collect its BlockGraphInfo struct
using bdrv_query_block_graph_info().  Print all nodes' information,
indenting child nodes and labelling them with a path constructed from
the child names leading to the node from the root (e.g. /file/file).

Note that we open each image with BDRV_O_NO_BACKING, so its backing
child is omitted from this graph, and thus presented in the previous
manner: By simply concatenating all images' information, separated with
blank lines.

This affects two iotests:
- 065: Here we try to get the format node's format specific information.
  The pre-patch code does so by taking all lines from "Format specific
  information:" until an empty line.  This format specific information
  is no longer followed by an empty line, though, but by child node
  information, so limit the range by "Child node '/file':".
- 302: Calls qemu_img() for qemu-img info directly, which does not
  filter the output, so the child node information ends up in the
  output.

Signed-off-by: Hanna Reitz <hreitz@redhat.com>
Message-Id: <20220620162704.80987-12-hreitz@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 qapi/block-core.json       |  4 +--
 qemu-img.c                 | 69 ++++++++++++++++++++++++++------------
 tests/qemu-iotests/065     |  2 +-
 tests/qemu-iotests/302.out |  5 +++
 4 files changed, 56 insertions(+), 24 deletions(-)

diff --git a/qapi/block-core.json b/qapi/block-core.json
index d703e0fb16..7f331eb8ea 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -5831,9 +5831,9 @@
 ##
 # @DummyBlockCoreForceArrays:
 #
-# Not used by QMP; hack to let us use BlockNodeInfoList internally
+# Not used by QMP; hack to let us use BlockGraphInfoList internally
 #
 # Since: 8.0
 ##
 { 'struct': 'DummyBlockCoreForceArrays',
-  'data': { 'unused-block-node-info': ['BlockNodeInfo'] } }
+  'data': { 'unused-block-graph-info': ['BlockGraphInfo'] } }
diff --git a/qemu-img.c b/qemu-img.c
index 04937bad11..919b9dfcc4 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -2816,13 +2816,13 @@ static void dump_snapshots(BlockDriverState *bs)
     g_free(sn_tab);
 }
 
-static void dump_json_block_node_info_list(BlockNodeInfoList *list)
+static void dump_json_block_graph_info_list(BlockGraphInfoList *list)
 {
     GString *str;
     QObject *obj;
     Visitor *v = qobject_output_visitor_new(&obj);
 
-    visit_type_BlockNodeInfoList(v, NULL, &list, &error_abort);
+    visit_type_BlockGraphInfoList(v, NULL, &list, &error_abort);
     visit_complete(v, &obj);
     str = qobject_to_json_pretty(obj, true);
     assert(str != NULL);
@@ -2832,13 +2832,13 @@ static void dump_json_block_node_info_list(BlockNodeInfoList *list)
     g_string_free(str, true);
 }
 
-static void dump_json_block_node_info(BlockNodeInfo *info)
+static void dump_json_block_graph_info(BlockGraphInfo *info)
 {
     GString *str;
     QObject *obj;
     Visitor *v = qobject_output_visitor_new(&obj);
 
-    visit_type_BlockNodeInfo(v, NULL, &info, &error_abort);
+    visit_type_BlockGraphInfo(v, NULL, &info, &error_abort);
     visit_complete(v, &obj);
     str = qobject_to_json_pretty(obj, true);
     assert(str != NULL);
@@ -2848,9 +2848,29 @@ static void dump_json_block_node_info(BlockNodeInfo *info)
     g_string_free(str, true);
 }
 
-static void dump_human_image_info_list(BlockNodeInfoList *list)
+static void dump_human_image_info(BlockGraphInfo *info, int indentation,
+                                  const char *path)
 {
-    BlockNodeInfoList *elem;
+    BlockChildInfoList *children_list;
+
+    bdrv_node_info_dump(qapi_BlockGraphInfo_base(info), indentation);
+
+    for (children_list = info->children; children_list;
+         children_list = children_list->next)
+    {
+        BlockChildInfo *child = children_list->value;
+        g_autofree char *child_path;
+
+        printf("%*sChild node '%s%s':\n",
+               indentation * 4, "", path, child->name);
+        child_path = g_strdup_printf("%s%s/", path, child->name);
+        dump_human_image_info(child->info, indentation + 1, child_path);
+    }
+}
+
+static void dump_human_image_info_list(BlockGraphInfoList *list)
+{
+    BlockGraphInfoList *elem;
     bool delim = false;
 
     for (elem = list; elem; elem = elem->next) {
@@ -2859,7 +2879,7 @@ static void dump_human_image_info_list(BlockNodeInfoList *list)
         }
         delim = true;
 
-        bdrv_node_info_dump(elem->value, 0);
+        dump_human_image_info(elem->value, 0, "/");
     }
 }
 
@@ -2869,7 +2889,7 @@ static gboolean str_equal_func(gconstpointer a, gconstpointer b)
 }
 
 /**
- * Open an image file chain and return an BlockNodeInfoList
+ * Open an image file chain and return an BlockGraphInfoList
  *
  * @filename: topmost image filename
  * @fmt: topmost image format (may be NULL to autodetect)
@@ -2880,13 +2900,13 @@ static gboolean str_equal_func(gconstpointer a, gconstpointer b)
  * opening an image file.  If there was an error a message will have been
  * printed to stderr.
  */
-static BlockNodeInfoList *collect_image_info_list(bool image_opts,
-                                                  const char *filename,
-                                                  const char *fmt,
-                                                  bool chain, bool force_share)
+static BlockGraphInfoList *collect_image_info_list(bool image_opts,
+                                                   const char *filename,
+                                                   const char *fmt,
+                                                   bool chain, bool force_share)
 {
-    BlockNodeInfoList *head = NULL;
-    BlockNodeInfoList **tail = &head;
+    BlockGraphInfoList *head = NULL;
+    BlockGraphInfoList **tail = &head;
     GHashTable *filenames;
     Error *err = NULL;
 
@@ -2895,7 +2915,7 @@ static BlockNodeInfoList *collect_image_info_list(bool image_opts,
     while (filename) {
         BlockBackend *blk;
         BlockDriverState *bs;
-        BlockNodeInfo *info;
+        BlockGraphInfo *info;
 
         if (g_hash_table_lookup_extended(filenames, filename, NULL, NULL)) {
             error_report("Backing file '%s' creates an infinite loop.",
@@ -2912,7 +2932,14 @@ static BlockNodeInfoList *collect_image_info_list(bool image_opts,
         }
         bs = blk_bs(blk);
 
-        bdrv_query_block_node_info(bs, &info, &err);
+        /*
+         * Note that the returned BlockGraphInfo object will not have
+         * information about this image's backing node, because we have opened
+         * it with BDRV_O_NO_BACKING.  Printing this object will therefore not
+         * duplicate the backing chain information that we obtain by walking
+         * the chain manually here.
+         */
+        bdrv_query_block_graph_info(bs, &info, &err);
         if (err) {
             error_report_err(err);
             blk_unref(blk);
@@ -2945,7 +2972,7 @@ static BlockNodeInfoList *collect_image_info_list(bool image_opts,
     return head;
 
 err:
-    qapi_free_BlockNodeInfoList(head);
+    qapi_free_BlockGraphInfoList(head);
     g_hash_table_destroy(filenames);
     return NULL;
 }
@@ -2956,7 +2983,7 @@ static int img_info(int argc, char **argv)
     OutputFormat output_format = OFORMAT_HUMAN;
     bool chain = false;
     const char *filename, *fmt, *output;
-    BlockNodeInfoList *list;
+    BlockGraphInfoList *list;
     bool image_opts = false;
     bool force_share = false;
 
@@ -3035,14 +3062,14 @@ static int img_info(int argc, char **argv)
         break;
     case OFORMAT_JSON:
         if (chain) {
-            dump_json_block_node_info_list(list);
+            dump_json_block_graph_info_list(list);
         } else {
-            dump_json_block_node_info(list->value);
+            dump_json_block_graph_info(list->value);
         }
         break;
     }
 
-    qapi_free_BlockNodeInfoList(list);
+    qapi_free_BlockGraphInfoList(list);
     return 0;
 }
 
diff --git a/tests/qemu-iotests/065 b/tests/qemu-iotests/065
index b724c89c7c..b76701c71e 100755
--- a/tests/qemu-iotests/065
+++ b/tests/qemu-iotests/065
@@ -56,7 +56,7 @@ class TestQemuImgInfo(TestImageInfoSpecific):
     def test_human(self):
         data = qemu_img('info', '--output=human', test_img).stdout.split('\n')
         data = data[(data.index('Format specific information:') + 1)
-                    :data.index('')]
+                    :data.index("Child node '/file':")]
         for field in data:
             self.assertTrue(re.match('^ {4}[^ ]', field) is not None)
         data = [line.strip() for line in data]
diff --git a/tests/qemu-iotests/302.out b/tests/qemu-iotests/302.out
index 3e7c281b91..edfa1c4f05 100644
--- a/tests/qemu-iotests/302.out
+++ b/tests/qemu-iotests/302.out
@@ -4,6 +4,11 @@ image: nbd+unix:///exp?socket=SOCK_DIR/PID-nbd-sock
 file format: raw
 virtual size: 448 KiB (458752 bytes)
 disk size: unavailable
+Child node '/file':
+    image: nbd+unix:///exp?socket=SOCK_DIR/PID-nbd-sock
+    file format: nbd
+    virtual size: 448 KiB (458752 bytes)
+    disk size: unavailable
 
 === Converted image info ===
 image: TEST_IMG
-- 
2.38.1



^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PULL 38/38] qemu-img: Change info key names for protocol nodes
  2023-01-20 12:25 [PULL 00/38] Block layer patches Kevin Wolf
                   ` (36 preceding siblings ...)
  2023-01-20 12:26 ` [PULL 37/38] qemu-img: Let info print block graph Kevin Wolf
@ 2023-01-20 12:26 ` Kevin Wolf
  2023-01-21 13:03 ` [PULL 00/38] Block layer patches Peter Maydell
  38 siblings, 0 replies; 48+ messages in thread
From: Kevin Wolf @ 2023-01-20 12:26 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, peter.maydell, qemu-devel

From: Hanna Reitz <hreitz@redhat.com>

Currently, when querying a qcow2 image, qemu-img info reports something
like this:

image: test.qcow2
file format: qcow2
virtual size: 64 MiB (67108864 bytes)
disk size: 196 KiB
cluster_size: 65536
Format specific information:
    compat: 1.1
    compression type: zlib
    lazy refcounts: false
    refcount bits: 16
    corrupt: false
    extended l2: false
Child node '/file':
    image: test.qcow2
    file format: file
    virtual size: 192 KiB (197120 bytes)
    disk size: 196 KiB
    Format specific information:
        extent size hint: 1048576

Notably, the way the keys are named is specific for image files: The
filename is shown under "image", the BDS driver under "file format", and
the BDS length under "virtual size".  This does not make much sense for
nodes that are not actually supposed to be guest images, like the /file
child node shown above.

Give bdrv_node_info_dump() a @protocol parameter that gives a hint that
the respective node is probably just used for data storage and does not
necessarily present the data for a VM guest disk.  This renames the keys
so that with this patch, the output becomes:

image: test.qcow2
[...]
Child node '/file':
    filename: test.qcow2
    protocol type: file
    file length: 192 KiB (197120 bytes)
    disk size: 196 KiB
    Format specific information:
        extent size hint: 1048576

(Perhaps we should also rename "Format specific information", but I
could not come up with anything better that will not become problematic
if we guess wrong with the protocol "heuristic".)

This change affects iotest 302, which has protocol node information in
its reference output.

Signed-off-by: Hanna Reitz <hreitz@redhat.com>
Message-Id: <20220620162704.80987-13-hreitz@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 include/block/qapi.h           |  2 +-
 block/monitor/block-hmp-cmds.c |  2 +-
 block/qapi.c                   | 39 ++++++++++++++++++++++++++++------
 qemu-img.c                     |  3 ++-
 tests/qemu-iotests/302.out     |  6 +++---
 5 files changed, 39 insertions(+), 13 deletions(-)

diff --git a/include/block/qapi.h b/include/block/qapi.h
index 38855f2ae9..26113da21a 100644
--- a/include/block/qapi.h
+++ b/include/block/qapi.h
@@ -51,5 +51,5 @@ void bdrv_snapshot_dump(QEMUSnapshotInfo *sn);
 void bdrv_image_info_specific_dump(ImageInfoSpecific *info_spec,
                                    const char *prefix,
                                    int indentation);
-void bdrv_node_info_dump(BlockNodeInfo *info, int indentation);
+void bdrv_node_info_dump(BlockNodeInfo *info, int indentation, bool protocol);
 #endif
diff --git a/block/monitor/block-hmp-cmds.c b/block/monitor/block-hmp-cmds.c
index 4b441ac468..4dc07f71d4 100644
--- a/block/monitor/block-hmp-cmds.c
+++ b/block/monitor/block-hmp-cmds.c
@@ -725,7 +725,7 @@ static void print_block_info(Monitor *mon, BlockInfo *info,
         monitor_printf(mon, "\nImages:\n");
         image_info = inserted->image;
         while (1) {
-            bdrv_node_info_dump(qapi_ImageInfo_base(image_info), 0);
+            bdrv_node_info_dump(qapi_ImageInfo_base(image_info), 0, false);
             if (image_info->backing_image) {
                 image_info = image_info->backing_image;
             } else {
diff --git a/block/qapi.c b/block/qapi.c
index ae61d2c856..a2c3030118 100644
--- a/block/qapi.c
+++ b/block/qapi.c
@@ -916,24 +916,49 @@ void bdrv_image_info_specific_dump(ImageInfoSpecific *info_spec,
     visit_free(v);
 }
 
-void bdrv_node_info_dump(BlockNodeInfo *info, int indentation)
+/**
+ * Print the given @info object in human-readable form.  Every field is indented
+ * using the given @indentation (four spaces per indentation level).
+ *
+ * When using this to print a whole block graph, @protocol can be set to true to
+ * signify that the given information is associated with a protocol node, i.e.
+ * just data storage for an image, such that the data it presents is not really
+ * a full VM disk.  If so, several fields change name: For example, "virtual
+ * size" is printed as "file length".
+ * (Consider a qcow2 image, which is represented by a qcow2 node and a file
+ * node.  Printing a "virtual size" for the file node does not make sense,
+ * because without the qcow2 node, it is not really a guest disk, so it does not
+ * have a "virtual size".  Therefore, we call it "file length" instead.)
+ *
+ * @protocol is ignored when @indentation is 0, because we take that to mean
+ * that the associated node is the root node in the queried block graph, and
+ * thus is always to be interpreted as a standalone guest disk.
+ */
+void bdrv_node_info_dump(BlockNodeInfo *info, int indentation, bool protocol)
 {
     char *size_buf, *dsize_buf;
     g_autofree char *ind_s = g_strdup_printf("%*s", indentation * 4, "");
 
+    if (indentation == 0) {
+        /* Top level, consider this a normal image */
+        protocol = false;
+    }
+
     if (!info->has_actual_size) {
         dsize_buf = g_strdup("unavailable");
     } else {
         dsize_buf = size_to_str(info->actual_size);
     }
     size_buf = size_to_str(info->virtual_size);
-    qemu_printf("%simage: %s\n"
-                "%sfile format: %s\n"
-                "%svirtual size: %s (%" PRId64 " bytes)\n"
+    qemu_printf("%s%s: %s\n"
+                "%s%s: %s\n"
+                "%s%s: %s (%" PRId64 " bytes)\n"
                 "%sdisk size: %s\n",
-                ind_s, info->filename,
-                ind_s, info->format,
-                ind_s, size_buf, info->virtual_size,
+                ind_s, protocol ? "filename" : "image", info->filename,
+                ind_s, protocol ? "protocol type" : "file format",
+                info->format,
+                ind_s, protocol ? "file length" : "virtual size",
+                size_buf, info->virtual_size,
                 ind_s, dsize_buf);
     g_free(size_buf);
     g_free(dsize_buf);
diff --git a/qemu-img.c b/qemu-img.c
index 919b9dfcc4..13b1f33e8a 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -2853,7 +2853,8 @@ static void dump_human_image_info(BlockGraphInfo *info, int indentation,
 {
     BlockChildInfoList *children_list;
 
-    bdrv_node_info_dump(qapi_BlockGraphInfo_base(info), indentation);
+    bdrv_node_info_dump(qapi_BlockGraphInfo_base(info), indentation,
+                        info->children == NULL);
 
     for (children_list = info->children; children_list;
          children_list = children_list->next)
diff --git a/tests/qemu-iotests/302.out b/tests/qemu-iotests/302.out
index edfa1c4f05..7b5014cdd8 100644
--- a/tests/qemu-iotests/302.out
+++ b/tests/qemu-iotests/302.out
@@ -5,9 +5,9 @@ file format: raw
 virtual size: 448 KiB (458752 bytes)
 disk size: unavailable
 Child node '/file':
-    image: nbd+unix:///exp?socket=SOCK_DIR/PID-nbd-sock
-    file format: nbd
-    virtual size: 448 KiB (458752 bytes)
+    filename: nbd+unix:///exp?socket=SOCK_DIR/PID-nbd-sock
+    protocol type: nbd
+    file length: 448 KiB (458752 bytes)
     disk size: unavailable
 
 === Converted image info ===
-- 
2.38.1



^ permalink raw reply related	[flat|nested] 48+ messages in thread

* Re: [PULL 00/38] Block layer patches
  2023-01-20 12:25 [PULL 00/38] Block layer patches Kevin Wolf
                   ` (37 preceding siblings ...)
  2023-01-20 12:26 ` [PULL 38/38] qemu-img: Change info key names for protocol nodes Kevin Wolf
@ 2023-01-21 13:03 ` Peter Maydell
  38 siblings, 0 replies; 48+ messages in thread
From: Peter Maydell @ 2023-01-21 13:03 UTC (permalink / raw)
  To: Kevin Wolf; +Cc: qemu-block, qemu-devel

On Fri, 20 Jan 2023 at 12:26, Kevin Wolf <kwolf@redhat.com> wrote:
>
> The following changes since commit 239b8b0699a222fd21da1c5fdeba0a2456085a47:
>
>   Merge tag 'trivial-branch-for-8.0-pull-request' of https://gitlab.com/laurent_vivier/qemu into staging (2023-01-19 15:05:29 +0000)
>
> are available in the Git repository at:
>
>   https://repo.or.cz/qemu/kevin.git tags/for-upstream
>
> for you to fetch changes up to 4711b0a8490827c332b3f9281f689ce9555b7fab:
>
>   qemu-img: Change info key names for protocol nodes (2023-01-20 13:11:01 +0100)
>
> ----------------------------------------------------------------
> Block layer patches
>
> - qemu-img info: Show protocol-level information
> - Move more functions to coroutines
> - Make coroutine annotations ready for static analysis
> - qemu-img: Fix exit code for errors closing the image
> - qcow2 bitmaps: Fix theoretical corruption in error path
> - pflash: Only load non-zero parts of backend image to save memory
> - Code cleanup and test case improvements
>

Hi -- this has a conflict in coroutine.h. Could you rebase and resend,
please?

thanks
-- PMM


^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PULL 03/38] pflash: Only read non-zero parts of backend image
  2023-01-20 12:25 ` [PULL 03/38] pflash: Only read non-zero parts of backend image Kevin Wolf
@ 2023-02-06 15:54   ` Cédric Le Goater
  2023-02-07  8:38     ` Kevin Wolf
  0 siblings, 1 reply; 48+ messages in thread
From: Cédric Le Goater @ 2023-02-06 15:54 UTC (permalink / raw)
  To: Kevin Wolf, qemu-block
  Cc: peter.maydell, qemu-devel, Daniel P. Berrangé, Xiang Zheng

Hello,

On 1/20/23 13:25, Kevin Wolf wrote:
> From: Xiang Zheng <zhengxiang9@huawei.com>
> 
> Currently we fill the VIRT_FLASH memory space with two 64MB NOR images
> when using persistent UEFI variables on virt board. Actually we only use
> a very small(non-zero) part of the memory while the rest significant
> large(zero) part of memory is wasted.
> 
> So this patch checks the block status and only writes the non-zero part
> into memory. This requires pflash devices to use sparse files for
> backends.
> 
> Signed-off-by: Xiang Zheng <zhengxiang9@huawei.com>
> 
> [ kraxel: rebased to latest master ]
> 
> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
> Message-Id: <20221220084246.1984871-1-kraxel@redhat.com>
> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
> Reviewed-by: Kevin Wolf <kwolf@redhat.com>
> Signed-off-by: Kevin Wolf <kwolf@redhat.com>

This newly merged patch introduces a "regression" when booting an Aspeed
machine. The following extra m25p80 patch (not yet merged) is required
for the issue to show:

   https://lore.kernel.org/qemu-devel/20221115151000.2080833-1-clg@kaod.org/

U-Boot fails to find the filesystem in that case.

It can be easily reproduced with the witherspoon-bmc machine and seems
to be related to the use of a UBI filesystem. Other Aspeed machines not
using UBI are not impacted.

Here is a tentative fix. I don't know enough the block layer to explain
what is happening :/

Thanks,

C.


@@ -39,7 +39,7 @@ static int blk_pread_nonzeroes(BlockBack
              return ret;
          }
          if (!(ret & BDRV_BLOCK_ZERO)) {
-            ret = bdrv_pread(bs->file, offset, bytes,
+            ret = blk_pread(blk, offset, bytes,
                               (uint8_t *) buf + offset, 0);
              if (ret < 0) {
                  return ret;


^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PULL 03/38] pflash: Only read non-zero parts of backend image
  2023-02-06 15:54   ` Cédric Le Goater
@ 2023-02-07  8:38     ` Kevin Wolf
  2023-02-07  9:19       ` Cédric Le Goater
  0 siblings, 1 reply; 48+ messages in thread
From: Kevin Wolf @ 2023-02-07  8:38 UTC (permalink / raw)
  To: Cédric Le Goater
  Cc: qemu-block, peter.maydell, qemu-devel, Daniel P. Berrangé,
	kraxel, Xiang Zheng

Am 06.02.2023 um 16:54 hat Cédric Le Goater geschrieben:
> On 1/20/23 13:25, Kevin Wolf wrote:
> > From: Xiang Zheng <zhengxiang9@huawei.com>
> > 
> > Currently we fill the VIRT_FLASH memory space with two 64MB NOR images
> > when using persistent UEFI variables on virt board. Actually we only use
> > a very small(non-zero) part of the memory while the rest significant
> > large(zero) part of memory is wasted.
> > 
> > So this patch checks the block status and only writes the non-zero part
> > into memory. This requires pflash devices to use sparse files for
> > backends.
> > 
> > Signed-off-by: Xiang Zheng <zhengxiang9@huawei.com>
> > 
> > [ kraxel: rebased to latest master ]
> > 
> > Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
> > Message-Id: <20221220084246.1984871-1-kraxel@redhat.com>
> > Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
> > Reviewed-by: Kevin Wolf <kwolf@redhat.com>
> > Signed-off-by: Kevin Wolf <kwolf@redhat.com>
> 
> This newly merged patch introduces a "regression" when booting an Aspeed
> machine. The following extra m25p80 patch (not yet merged) is required
> for the issue to show:
> 
>   https://lore.kernel.org/qemu-devel/20221115151000.2080833-1-clg@kaod.org/
> 
> U-Boot fails to find the filesystem in that case.
> 
> It can be easily reproduced with the witherspoon-bmc machine and seems
> to be related to the use of a UBI filesystem. Other Aspeed machines not
> using UBI are not impacted.
> 
> Here is a tentative fix. I don't know enough the block layer to explain
> what is happening :/

I was puzzled for a moment, but...

> @@ -39,7 +39,7 @@ static int blk_pread_nonzeroes(BlockBack
>              return ret;
>          }
>          if (!(ret & BDRV_BLOCK_ZERO)) {
> -            ret = bdrv_pread(bs->file, offset, bytes,

'bs->file' rather than 'bs' really looks wrong. I think replacing that
would already fix the bug you're seeing.

Just to be sure, how did you configure the block backend? bs->file would
happen to work more or less with raw over file-posix (which is probably
what Gerd tested), but I think it breaks with anything else.

> +            ret = blk_pread(blk, offset, bytes,
>                               (uint8_t *) buf + offset, 0);

blk_*() makes even more sense conceptually, but it should behave the
same.

Kevin



^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PULL 03/38] pflash: Only read non-zero parts of backend image
  2023-02-07  8:38     ` Kevin Wolf
@ 2023-02-07  9:19       ` Cédric Le Goater
  2023-02-07 12:48         ` Kevin Wolf
  0 siblings, 1 reply; 48+ messages in thread
From: Cédric Le Goater @ 2023-02-07  9:19 UTC (permalink / raw)
  To: Kevin Wolf
  Cc: qemu-block, peter.maydell, qemu-devel, Daniel P. Berrangé, kraxel

On 2/7/23 09:38, Kevin Wolf wrote:
> Am 06.02.2023 um 16:54 hat Cédric Le Goater geschrieben:
>> On 1/20/23 13:25, Kevin Wolf wrote:
>>> From: Xiang Zheng <zhengxiang9@huawei.com>
>>>
>>> Currently we fill the VIRT_FLASH memory space with two 64MB NOR images
>>> when using persistent UEFI variables on virt board. Actually we only use
>>> a very small(non-zero) part of the memory while the rest significant
>>> large(zero) part of memory is wasted.
>>>
>>> So this patch checks the block status and only writes the non-zero part
>>> into memory. This requires pflash devices to use sparse files for
>>> backends.
>>>
>>> Signed-off-by: Xiang Zheng <zhengxiang9@huawei.com>
>>>
>>> [ kraxel: rebased to latest master ]
>>>
>>> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
>>> Message-Id: <20221220084246.1984871-1-kraxel@redhat.com>
>>> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
>>> Reviewed-by: Kevin Wolf <kwolf@redhat.com>
>>> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
>>
>> This newly merged patch introduces a "regression" when booting an Aspeed
>> machine. The following extra m25p80 patch (not yet merged) is required
>> for the issue to show:
>>
>>    https://lore.kernel.org/qemu-devel/20221115151000.2080833-1-clg@kaod.org/
>>
>> U-Boot fails to find the filesystem in that case.
>>
>> It can be easily reproduced with the witherspoon-bmc machine and seems
>> to be related to the use of a UBI filesystem. Other Aspeed machines not
>> using UBI are not impacted.
>>
>> Here is a tentative fix. I don't know enough the block layer to explain
>> what is happening :/
> 
> I was puzzled for a moment, but...
> 
>> @@ -39,7 +39,7 @@ static int blk_pread_nonzeroes(BlockBack
>>               return ret;
>>           }
>>           if (!(ret & BDRV_BLOCK_ZERO)) {
>> -            ret = bdrv_pread(bs->file, offset, bytes,
> 
> 'bs->file' rather than 'bs' really looks wrong. I think replacing that
> would already fix the bug you're seeing.
> 
> Just to be sure, how did you configure the block backend? bs->file would
> happen to work more or less with raw over file-posix (which is probably
> what Gerd tested), but I think it breaks with anything else.

The command is  :

   $ qemu-system-arm -M witherspoon-bmc -net user \
	-drive file=/path/to/file.mtd,format=raw,if=mtd \
	-nographic -serial mon:stdio -snapshot

If I remove '-snapshot', all works fine.

Here is a file :

   https://jenkins.openbmc.org/job/ci-openbmc/distro=ubuntu,label=docker-builder,target=witherspoon/lastSuccessfulBuild/artifact/openbmc/build/tmp/deploy/images/witherspoon/obmc-phosphor-image-witherspoon-20230207051412.ubi.mtd

Thanks,

C.

> 
>> +            ret = blk_pread(blk, offset, bytes,
>>                                (uint8_t *) buf + offset, 0);
> 
> blk_*() makes even more sense conceptually, but it should behave the
> same.
> 
> Kevin
> 



^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PULL 03/38] pflash: Only read non-zero parts of backend image
  2023-02-07  9:19       ` Cédric Le Goater
@ 2023-02-07 12:48         ` Kevin Wolf
  2023-02-08 11:19           ` Cédric Le Goater
  0 siblings, 1 reply; 48+ messages in thread
From: Kevin Wolf @ 2023-02-07 12:48 UTC (permalink / raw)
  To: Cédric Le Goater
  Cc: qemu-block, peter.maydell, qemu-devel, Daniel P. Berrangé, kraxel

Am 07.02.2023 um 10:19 hat Cédric Le Goater geschrieben:
> On 2/7/23 09:38, Kevin Wolf wrote:
> > Am 06.02.2023 um 16:54 hat Cédric Le Goater geschrieben:
> > > On 1/20/23 13:25, Kevin Wolf wrote:
> > > > From: Xiang Zheng <zhengxiang9@huawei.com>
> > > > 
> > > > Currently we fill the VIRT_FLASH memory space with two 64MB NOR images
> > > > when using persistent UEFI variables on virt board. Actually we only use
> > > > a very small(non-zero) part of the memory while the rest significant
> > > > large(zero) part of memory is wasted.
> > > > 
> > > > So this patch checks the block status and only writes the non-zero part
> > > > into memory. This requires pflash devices to use sparse files for
> > > > backends.
> > > > 
> > > > Signed-off-by: Xiang Zheng <zhengxiang9@huawei.com>
> > > > 
> > > > [ kraxel: rebased to latest master ]
> > > > 
> > > > Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
> > > > Message-Id: <20221220084246.1984871-1-kraxel@redhat.com>
> > > > Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
> > > > Reviewed-by: Kevin Wolf <kwolf@redhat.com>
> > > > Signed-off-by: Kevin Wolf <kwolf@redhat.com>
> > > 
> > > This newly merged patch introduces a "regression" when booting an Aspeed
> > > machine. The following extra m25p80 patch (not yet merged) is required
> > > for the issue to show:
> > > 
> > >    https://lore.kernel.org/qemu-devel/20221115151000.2080833-1-clg@kaod.org/
> > > 
> > > U-Boot fails to find the filesystem in that case.
> > > 
> > > It can be easily reproduced with the witherspoon-bmc machine and seems
> > > to be related to the use of a UBI filesystem. Other Aspeed machines not
> > > using UBI are not impacted.
> > > 
> > > Here is a tentative fix. I don't know enough the block layer to explain
> > > what is happening :/
> > 
> > I was puzzled for a moment, but...
> > 
> > > @@ -39,7 +39,7 @@ static int blk_pread_nonzeroes(BlockBack
> > >               return ret;
> > >           }
> > >           if (!(ret & BDRV_BLOCK_ZERO)) {
> > > -            ret = bdrv_pread(bs->file, offset, bytes,
> > 
> > 'bs->file' rather than 'bs' really looks wrong. I think replacing that
> > would already fix the bug you're seeing.
> > 
> > Just to be sure, how did you configure the block backend? bs->file would
> > happen to work more or less with raw over file-posix (which is probably
> > what Gerd tested), but I think it breaks with anything else.
> 
> The command is  :
> 
>   $ qemu-system-arm -M witherspoon-bmc -net user \
> 	-drive file=/path/to/file.mtd,format=raw,if=mtd \
> 	-nographic -serial mon:stdio -snapshot
> 
> If I remove '-snapshot', all works fine.

Ok, that makes sense then. -snapshot creates a temporary qcow2 overlay,
and then what your guest sees with bs->file is not the virtual disk
content of the qcow2 image, but the qcow2 file itself.

Kevin



^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PULL 03/38] pflash: Only read non-zero parts of backend image
  2023-02-07 12:48         ` Kevin Wolf
@ 2023-02-08 11:19           ` Cédric Le Goater
  2023-03-03 22:51             ` Maciej S. Szmigiero
  0 siblings, 1 reply; 48+ messages in thread
From: Cédric Le Goater @ 2023-02-08 11:19 UTC (permalink / raw)
  To: Kevin Wolf
  Cc: qemu-block, peter.maydell, qemu-devel, Daniel P. Berrangé, kraxel

On 2/7/23 13:48, Kevin Wolf wrote:
> Am 07.02.2023 um 10:19 hat Cédric Le Goater geschrieben:
>> On 2/7/23 09:38, Kevin Wolf wrote:
>>> Am 06.02.2023 um 16:54 hat Cédric Le Goater geschrieben:
>>>> On 1/20/23 13:25, Kevin Wolf wrote:
>>>>> From: Xiang Zheng <zhengxiang9@huawei.com>
>>>>>
>>>>> Currently we fill the VIRT_FLASH memory space with two 64MB NOR images
>>>>> when using persistent UEFI variables on virt board. Actually we only use
>>>>> a very small(non-zero) part of the memory while the rest significant
>>>>> large(zero) part of memory is wasted.
>>>>>
>>>>> So this patch checks the block status and only writes the non-zero part
>>>>> into memory. This requires pflash devices to use sparse files for
>>>>> backends.
>>>>>
>>>>> Signed-off-by: Xiang Zheng <zhengxiang9@huawei.com>
>>>>>
>>>>> [ kraxel: rebased to latest master ]
>>>>>
>>>>> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
>>>>> Message-Id: <20221220084246.1984871-1-kraxel@redhat.com>
>>>>> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
>>>>> Reviewed-by: Kevin Wolf <kwolf@redhat.com>
>>>>> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
>>>>
>>>> This newly merged patch introduces a "regression" when booting an Aspeed
>>>> machine. The following extra m25p80 patch (not yet merged) is required
>>>> for the issue to show:
>>>>
>>>>     https://lore.kernel.org/qemu-devel/20221115151000.2080833-1-clg@kaod.org/
>>>>
>>>> U-Boot fails to find the filesystem in that case.
>>>>
>>>> It can be easily reproduced with the witherspoon-bmc machine and seems
>>>> to be related to the use of a UBI filesystem. Other Aspeed machines not
>>>> using UBI are not impacted.
>>>>
>>>> Here is a tentative fix. I don't know enough the block layer to explain
>>>> what is happening :/
>>>
>>> I was puzzled for a moment, but...
>>>
>>>> @@ -39,7 +39,7 @@ static int blk_pread_nonzeroes(BlockBack
>>>>                return ret;
>>>>            }
>>>>            if (!(ret & BDRV_BLOCK_ZERO)) {
>>>> -            ret = bdrv_pread(bs->file, offset, bytes,
>>>
>>> 'bs->file' rather than 'bs' really looks wrong. I think replacing that
>>> would already fix the bug you're seeing.
>>>
>>> Just to be sure, how did you configure the block backend? bs->file would
>>> happen to work more or less with raw over file-posix (which is probably
>>> what Gerd tested), but I think it breaks with anything else.
>>
>> The command is  :
>>
>>    $ qemu-system-arm -M witherspoon-bmc -net user \
>> 	-drive file=/path/to/file.mtd,format=raw,if=mtd \
>> 	-nographic -serial mon:stdio -snapshot
>>
>> If I remove '-snapshot', all works fine.
> 
> Ok, that makes sense then. -snapshot creates a temporary qcow2 overlay,
> and then what your guest sees with bs->file is not the virtual disk
> content of the qcow2 image, but the qcow2 file itself.

yes. Same symptom with pflash devices, TCG and KVM. The guest hangs with -snapshot.

C.

qemu-system-aarch64 -M virt -smp 2 -cpu max -accel tcg,thread=multi -nographic -m 2G -drive if=pflash,format=raw,file=/usr/share/edk2/aarch64/QEMU_EFI-silent-pflash.raw,readonly=on -drive if=pflash,format=raw,file=rhel9-varstore.img -device virtio-net,netdev=net0,bus=pcie.0,addr=0x3 -netdev user,id=net0 -drive file=rhel9-arm64.qcow2,if=none,id=disk,format=qcow2,cache=none -device virtio-blk-device,drive=disk -serial mon:stdio -snapshot



^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PULL 03/38] pflash: Only read non-zero parts of backend image
  2023-02-08 11:19           ` Cédric Le Goater
@ 2023-03-03 22:51             ` Maciej S. Szmigiero
  2023-03-07 14:00               ` Kevin Wolf
  0 siblings, 1 reply; 48+ messages in thread
From: Maciej S. Szmigiero @ 2023-03-03 22:51 UTC (permalink / raw)
  To: Cédric Le Goater, Kevin Wolf
  Cc: qemu-block, peter.maydell, qemu-devel, Daniel P. Berrangé, kraxel

On 8.02.2023 12:19, Cédric Le Goater wrote:
> On 2/7/23 13:48, Kevin Wolf wrote:
>> Am 07.02.2023 um 10:19 hat Cédric Le Goater geschrieben:
>>> On 2/7/23 09:38, Kevin Wolf wrote:
>>>> Am 06.02.2023 um 16:54 hat Cédric Le Goater geschrieben:
>>>>> On 1/20/23 13:25, Kevin Wolf wrote:
>>>>>> From: Xiang Zheng <zhengxiang9@huawei.com>
>>>>>>
>>>>>> Currently we fill the VIRT_FLASH memory space with two 64MB NOR images
>>>>>> when using persistent UEFI variables on virt board. Actually we only use
>>>>>> a very small(non-zero) part of the memory while the rest significant
>>>>>> large(zero) part of memory is wasted.
>>>>>>
>>>>>> So this patch checks the block status and only writes the non-zero part
>>>>>> into memory. This requires pflash devices to use sparse files for
>>>>>> backends.
>>>>>>
>>>>>> Signed-off-by: Xiang Zheng <zhengxiang9@huawei.com>
>>>>>>
>>>>>> [ kraxel: rebased to latest master ]
>>>>>>
>>>>>> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
>>>>>> Message-Id: <20221220084246.1984871-1-kraxel@redhat.com>
>>>>>> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
>>>>>> Reviewed-by: Kevin Wolf <kwolf@redhat.com>
>>>>>> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
>>>>>
>>>>> This newly merged patch introduces a "regression" when booting an Aspeed
>>>>> machine. The following extra m25p80 patch (not yet merged) is required
>>>>> for the issue to show:
>>>>>
>>>>>     https://lore.kernel.org/qemu-devel/20221115151000.2080833-1-clg@kaod.org/
>>>>>
>>>>> U-Boot fails to find the filesystem in that case.
>>>>>
>>>>> It can be easily reproduced with the witherspoon-bmc machine and seems
>>>>> to be related to the use of a UBI filesystem. Other Aspeed machines not
>>>>> using UBI are not impacted.
>>>>>
>>>>> Here is a tentative fix. I don't know enough the block layer to explain
>>>>> what is happening :/
>>>>
>>>> I was puzzled for a moment, but...
>>>>
>>>>> @@ -39,7 +39,7 @@ static int blk_pread_nonzeroes(BlockBack
>>>>>                return ret;
>>>>>            }
>>>>>            if (!(ret & BDRV_BLOCK_ZERO)) {
>>>>> -            ret = bdrv_pread(bs->file, offset, bytes,
>>>>
>>>> 'bs->file' rather than 'bs' really looks wrong. I think replacing that
>>>> would already fix the bug you're seeing.
>>>>
>>>> Just to be sure, how did you configure the block backend? bs->file would
>>>> happen to work more or less with raw over file-posix (which is probably
>>>> what Gerd tested), but I think it breaks with anything else.
>>>
>>> The command is  :
>>>
>>>    $ qemu-system-arm -M witherspoon-bmc -net user \
>>>     -drive file=/path/to/file.mtd,format=raw,if=mtd \
>>>     -nographic -serial mon:stdio -snapshot
>>>
>>> If I remove '-snapshot', all works fine.
>>
>> Ok, that makes sense then. -snapshot creates a temporary qcow2 overlay,
>> and then what your guest sees with bs->file is not the virtual disk
>> content of the qcow2 image, but the qcow2 file itself.
> 
> yes. Same symptom with pflash devices, TCG and KVM. The guest hangs with -snapshot.
> 
> C.
> 
> qemu-system-aarch64 -M virt -smp 2 -cpu max -accel tcg,thread=multi -nographic -m 2G -drive if=pflash,format=raw,file=/usr/share/edk2/aarch64/QEMU_EFI-silent-pflash.raw,readonly=on -drive if=pflash,format=raw,file=rhel9-varstore.img -device virtio-net,netdev=net0,bus=pcie.0,addr=0x3 -netdev user,id=net0 -drive file=rhel9-arm64.qcow2,if=none,id=disk,format=qcow2,cache=none -device virtio-blk-device,drive=disk -serial mon:stdio -snapshot
> 
> 
> 

+1 here for QEMU + KVM/x86: OVMF CODE file fails to load (is all zeroes)
with either "-snapshot" QEMU command line option or even with just "snapshot=on"
setting enabled on pflash0.

Reverting this patch seems to fix the issue.

Thanks,
Maciej



^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PULL 03/38] pflash: Only read non-zero parts of backend image
  2023-03-03 22:51             ` Maciej S. Szmigiero
@ 2023-03-07 14:00               ` Kevin Wolf
  2023-03-07 14:15                 ` Cédric Le Goater
  0 siblings, 1 reply; 48+ messages in thread
From: Kevin Wolf @ 2023-03-07 14:00 UTC (permalink / raw)
  To: Maciej S. Szmigiero
  Cc: Cédric Le Goater, qemu-block, peter.maydell, qemu-devel,
	Daniel P. Berrangé,
	kraxel

Am 03.03.2023 um 23:51 hat Maciej S. Szmigiero geschrieben:
> On 8.02.2023 12:19, Cédric Le Goater wrote:
> > On 2/7/23 13:48, Kevin Wolf wrote:
> > > Am 07.02.2023 um 10:19 hat Cédric Le Goater geschrieben:
> > > > On 2/7/23 09:38, Kevin Wolf wrote:
> > > > > Am 06.02.2023 um 16:54 hat Cédric Le Goater geschrieben:
> > > > > > On 1/20/23 13:25, Kevin Wolf wrote:
> > > > > > > From: Xiang Zheng <zhengxiang9@huawei.com>
> > > > > > > 
> > > > > > > Currently we fill the VIRT_FLASH memory space with two 64MB NOR images
> > > > > > > when using persistent UEFI variables on virt board. Actually we only use
> > > > > > > a very small(non-zero) part of the memory while the rest significant
> > > > > > > large(zero) part of memory is wasted.
> > > > > > > 
> > > > > > > So this patch checks the block status and only writes the non-zero part
> > > > > > > into memory. This requires pflash devices to use sparse files for
> > > > > > > backends.
> > > > > > > 
> > > > > > > Signed-off-by: Xiang Zheng <zhengxiang9@huawei.com>
> > > > > > > 
> > > > > > > [ kraxel: rebased to latest master ]
> > > > > > > 
> > > > > > > Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
> > > > > > > Message-Id: <20221220084246.1984871-1-kraxel@redhat.com>
> > > > > > > Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
> > > > > > > Reviewed-by: Kevin Wolf <kwolf@redhat.com>
> > > > > > > Signed-off-by: Kevin Wolf <kwolf@redhat.com>
> > > > > > 
> > > > > > This newly merged patch introduces a "regression" when booting an Aspeed
> > > > > > machine. The following extra m25p80 patch (not yet merged) is required
> > > > > > for the issue to show:
> > > > > > 
> > > > > >     https://lore.kernel.org/qemu-devel/20221115151000.2080833-1-clg@kaod.org/
> > > > > > 
> > > > > > U-Boot fails to find the filesystem in that case.
> > > > > > 
> > > > > > It can be easily reproduced with the witherspoon-bmc machine and seems
> > > > > > to be related to the use of a UBI filesystem. Other Aspeed machines not
> > > > > > using UBI are not impacted.
> > > > > > 
> > > > > > Here is a tentative fix. I don't know enough the block layer to explain
> > > > > > what is happening :/
> > > > > 
> > > > > I was puzzled for a moment, but...
> > > > > 
> > > > > > @@ -39,7 +39,7 @@ static int blk_pread_nonzeroes(BlockBack
> > > > > >                return ret;
> > > > > >            }
> > > > > >            if (!(ret & BDRV_BLOCK_ZERO)) {
> > > > > > -            ret = bdrv_pread(bs->file, offset, bytes,
> > > > > 
> > > > > 'bs->file' rather than 'bs' really looks wrong. I think replacing that
> > > > > would already fix the bug you're seeing.
> > > > > 
> > > > > Just to be sure, how did you configure the block backend? bs->file would
> > > > > happen to work more or less with raw over file-posix (which is probably
> > > > > what Gerd tested), but I think it breaks with anything else.
> > > > 
> > > > The command is  :
> > > > 
> > > >    $ qemu-system-arm -M witherspoon-bmc -net user \
> > > >     -drive file=/path/to/file.mtd,format=raw,if=mtd \
> > > >     -nographic -serial mon:stdio -snapshot
> > > > 
> > > > If I remove '-snapshot', all works fine.
> > > 
> > > Ok, that makes sense then. -snapshot creates a temporary qcow2 overlay,
> > > and then what your guest sees with bs->file is not the virtual disk
> > > content of the qcow2 image, but the qcow2 file itself.
> > 
> > yes. Same symptom with pflash devices, TCG and KVM. The guest hangs with -snapshot.
> > 
> > C.
> > 
> > qemu-system-aarch64 -M virt -smp 2 -cpu max -accel tcg,thread=multi -nographic -m 2G -drive if=pflash,format=raw,file=/usr/share/edk2/aarch64/QEMU_EFI-silent-pflash.raw,readonly=on -drive if=pflash,format=raw,file=rhel9-varstore.img -device virtio-net,netdev=net0,bus=pcie.0,addr=0x3 -netdev user,id=net0 -drive file=rhel9-arm64.qcow2,if=none,id=disk,format=qcow2,cache=none -device virtio-blk-device,drive=disk -serial mon:stdio -snapshot
> > 
> > 
> > 
> 
> +1 here for QEMU + KVM/x86: OVMF CODE file fails to load (is all zeroes)
> with either "-snapshot" QEMU command line option or even with just "snapshot=on"
> setting enabled on pflash0.
> 
> Reverting this patch seems to fix the issue.

Hm, so we know the fix, but nobody has submitted it as an actual patch?
I'll send one...

Kevin



^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PULL 03/38] pflash: Only read non-zero parts of backend image
  2023-03-07 14:00               ` Kevin Wolf
@ 2023-03-07 14:15                 ` Cédric Le Goater
  0 siblings, 0 replies; 48+ messages in thread
From: Cédric Le Goater @ 2023-03-07 14:15 UTC (permalink / raw)
  To: Kevin Wolf, Maciej S. Szmigiero
  Cc: qemu-block, peter.maydell, qemu-devel, Daniel P. Berrangé, kraxel

On 3/7/23 15:00, Kevin Wolf wrote:
> Am 03.03.2023 um 23:51 hat Maciej S. Szmigiero geschrieben:
>> On 8.02.2023 12:19, Cédric Le Goater wrote:
>>> On 2/7/23 13:48, Kevin Wolf wrote:
>>>> Am 07.02.2023 um 10:19 hat Cédric Le Goater geschrieben:
>>>>> On 2/7/23 09:38, Kevin Wolf wrote:
>>>>>> Am 06.02.2023 um 16:54 hat Cédric Le Goater geschrieben:
>>>>>>> On 1/20/23 13:25, Kevin Wolf wrote:
>>>>>>>> From: Xiang Zheng <zhengxiang9@huawei.com>
>>>>>>>>
>>>>>>>> Currently we fill the VIRT_FLASH memory space with two 64MB NOR images
>>>>>>>> when using persistent UEFI variables on virt board. Actually we only use
>>>>>>>> a very small(non-zero) part of the memory while the rest significant
>>>>>>>> large(zero) part of memory is wasted.
>>>>>>>>
>>>>>>>> So this patch checks the block status and only writes the non-zero part
>>>>>>>> into memory. This requires pflash devices to use sparse files for
>>>>>>>> backends.
>>>>>>>>
>>>>>>>> Signed-off-by: Xiang Zheng <zhengxiang9@huawei.com>
>>>>>>>>
>>>>>>>> [ kraxel: rebased to latest master ]
>>>>>>>>
>>>>>>>> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
>>>>>>>> Message-Id: <20221220084246.1984871-1-kraxel@redhat.com>
>>>>>>>> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
>>>>>>>> Reviewed-by: Kevin Wolf <kwolf@redhat.com>
>>>>>>>> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
>>>>>>>
>>>>>>> This newly merged patch introduces a "regression" when booting an Aspeed
>>>>>>> machine. The following extra m25p80 patch (not yet merged) is required
>>>>>>> for the issue to show:
>>>>>>>
>>>>>>>      https://lore.kernel.org/qemu-devel/20221115151000.2080833-1-clg@kaod.org/
>>>>>>>
>>>>>>> U-Boot fails to find the filesystem in that case.
>>>>>>>
>>>>>>> It can be easily reproduced with the witherspoon-bmc machine and seems
>>>>>>> to be related to the use of a UBI filesystem. Other Aspeed machines not
>>>>>>> using UBI are not impacted.
>>>>>>>
>>>>>>> Here is a tentative fix. I don't know enough the block layer to explain
>>>>>>> what is happening :/
>>>>>>
>>>>>> I was puzzled for a moment, but...
>>>>>>
>>>>>>> @@ -39,7 +39,7 @@ static int blk_pread_nonzeroes(BlockBack
>>>>>>>                 return ret;
>>>>>>>             }
>>>>>>>             if (!(ret & BDRV_BLOCK_ZERO)) {
>>>>>>> -            ret = bdrv_pread(bs->file, offset, bytes,
>>>>>>
>>>>>> 'bs->file' rather than 'bs' really looks wrong. I think replacing that
>>>>>> would already fix the bug you're seeing.
>>>>>>
>>>>>> Just to be sure, how did you configure the block backend? bs->file would
>>>>>> happen to work more or less with raw over file-posix (which is probably
>>>>>> what Gerd tested), but I think it breaks with anything else.
>>>>>
>>>>> The command is  :
>>>>>
>>>>>     $ qemu-system-arm -M witherspoon-bmc -net user \
>>>>>      -drive file=/path/to/file.mtd,format=raw,if=mtd \
>>>>>      -nographic -serial mon:stdio -snapshot
>>>>>
>>>>> If I remove '-snapshot', all works fine.
>>>>
>>>> Ok, that makes sense then. -snapshot creates a temporary qcow2 overlay,
>>>> and then what your guest sees with bs->file is not the virtual disk
>>>> content of the qcow2 image, but the qcow2 file itself.
>>>
>>> yes. Same symptom with pflash devices, TCG and KVM. The guest hangs with -snapshot.
>>>
>>> C.
>>>
>>> qemu-system-aarch64 -M virt -smp 2 -cpu max -accel tcg,thread=multi -nographic -m 2G -drive if=pflash,format=raw,file=/usr/share/edk2/aarch64/QEMU_EFI-silent-pflash.raw,readonly=on -drive if=pflash,format=raw,file=rhel9-varstore.img -device virtio-net,netdev=net0,bus=pcie.0,addr=0x3 -netdev user,id=net0 -drive file=rhel9-arm64.qcow2,if=none,id=disk,format=qcow2,cache=none -device virtio-blk-device,drive=disk -serial mon:stdio -snapshot
>>>
>>>
>>>
>>
>> +1 here for QEMU + KVM/x86: OVMF CODE file fails to load (is all zeroes)
>> with either "-snapshot" QEMU command line option or even with just "snapshot=on"
>> setting enabled on pflash0.
>>
>> Reverting this patch seems to fix the issue.
> 
> Hm, so we know the fix, but nobody has submitted it as an actual patch?

Sorry. I thought the solution was more complex and got pulled in other
tasks ...

> I'll send one...

Thanks,

C.



^ permalink raw reply	[flat|nested] 48+ messages in thread

end of thread, other threads:[~2023-03-07 14:16 UTC | newest]

Thread overview: 48+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-01-20 12:25 [PULL 00/38] Block layer patches Kevin Wolf
2023-01-20 12:25 ` [PULL 01/38] tests/qemu-iotests/312: Mark "quorum" as required driver Kevin Wolf
2023-01-20 12:25 ` [PULL 02/38] tests/qemu-iotests/262: Check for availability of "blkverify" first Kevin Wolf
2023-01-20 12:25 ` [PULL 03/38] pflash: Only read non-zero parts of backend image Kevin Wolf
2023-02-06 15:54   ` Cédric Le Goater
2023-02-07  8:38     ` Kevin Wolf
2023-02-07  9:19       ` Cédric Le Goater
2023-02-07 12:48         ` Kevin Wolf
2023-02-08 11:19           ` Cédric Le Goater
2023-03-03 22:51             ` Maciej S. Szmigiero
2023-03-07 14:00               ` Kevin Wolf
2023-03-07 14:15                 ` Cédric Le Goater
2023-01-20 12:25 ` [PULL 04/38] coroutine: annotate coroutine_fn for libclang Kevin Wolf
2023-01-20 12:26 ` [PULL 05/38] block: Add no_coroutine_fn and coroutine_mixed_fn marker Kevin Wolf
2023-01-20 12:26 ` [PULL 06/38] qemu-io: do not reinvent the blk_pwrite_zeroes wheel Kevin Wolf
2023-01-20 12:26 ` [PULL 07/38] block: remove bdrv_coroutine_enter Kevin Wolf
2023-01-20 12:26 ` [PULL 08/38] qcow2: Fix theoretical corruption in store_bitmap() error path Kevin Wolf
2023-01-20 12:26 ` [PULL 09/38] qemu-img commit: Report errors while closing the image Kevin Wolf
2023-01-20 12:26 ` [PULL 10/38] qemu-img bitmap: " Kevin Wolf
2023-01-20 12:26 ` [PULL 11/38] qemu-iotests: Test qemu-img bitmap/commit exit code on error Kevin Wolf
2023-01-20 12:26 ` [PULL 12/38] block-coroutine-wrapper: support void functions Kevin Wolf
2023-01-20 12:26 ` [PULL 13/38] block: Convert bdrv_io_plug() to co_wrapper Kevin Wolf
2023-01-20 12:26 ` [PULL 14/38] block: Convert bdrv_io_unplug() " Kevin Wolf
2023-01-20 12:26 ` [PULL 15/38] block: Convert bdrv_is_inserted() " Kevin Wolf
2023-01-20 12:26 ` [PULL 16/38] block: Rename refresh_total_sectors to bdrv_refresh_total_sectors Kevin Wolf
2023-01-20 12:26 ` [PULL 17/38] block: Convert bdrv_refresh_total_sectors() to co_wrapper_mixed Kevin Wolf
2023-01-20 12:26 ` [PULL 18/38] block-backend: use bdrv_getlength instead of blk_getlength Kevin Wolf
2023-01-20 12:26 ` [PULL 19/38] block: use bdrv_co_refresh_total_sectors when possible Kevin Wolf
2023-01-20 12:26 ` [PULL 20/38] block: Convert bdrv_get_allocated_file_size() to co_wrapper Kevin Wolf
2023-01-20 12:26 ` [PULL 21/38] block: Convert bdrv_get_info() to co_wrapper_mixed Kevin Wolf
2023-01-20 12:26 ` [PULL 22/38] block: Convert bdrv_eject() to co_wrapper Kevin Wolf
2023-01-20 12:26 ` [PULL 23/38] block: Convert bdrv_lock_medium() " Kevin Wolf
2023-01-20 12:26 ` [PULL 24/38] block: Convert bdrv_debug_event() to co_wrapper_mixed Kevin Wolf
2023-01-20 12:26 ` [PULL 25/38] block: Rename bdrv_load/save_vmstate() to bdrv_co_load/save_vmstate() Kevin Wolf
2023-01-20 12:26 ` [PULL 26/38] block/nbd: Add missing <qemu/bswap.h> include Kevin Wolf
2023-01-20 12:26 ` [PULL 27/38] block: Improve empty format-specific info dump Kevin Wolf
2023-01-20 12:26 ` [PULL 28/38] block/file: Add file-specific image info Kevin Wolf
2023-01-20 12:26 ` [PULL 29/38] block/vmdk: Change extent info type Kevin Wolf
2023-01-20 12:26 ` [PULL 30/38] block: Split BlockNodeInfo off of ImageInfo Kevin Wolf
2023-01-20 12:26 ` [PULL 31/38] qemu-img: Use BlockNodeInfo Kevin Wolf
2023-01-20 12:26 ` [PULL 32/38] block/qapi: Let bdrv_query_image_info() recurse Kevin Wolf
2023-01-20 12:26 ` [PULL 33/38] block/qapi: Introduce BlockGraphInfo Kevin Wolf
2023-01-20 12:26 ` [PULL 34/38] block/qapi: Add indentation to bdrv_node_info_dump() Kevin Wolf
2023-01-20 12:26 ` [PULL 35/38] iotests: Filter child node information Kevin Wolf
2023-01-20 12:26 ` [PULL 36/38] iotests/106, 214, 308: Read only one size line Kevin Wolf
2023-01-20 12:26 ` [PULL 37/38] qemu-img: Let info print block graph Kevin Wolf
2023-01-20 12:26 ` [PULL 38/38] qemu-img: Change info key names for protocol nodes Kevin Wolf
2023-01-21 13:03 ` [PULL 00/38] Block layer patches Peter Maydell

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.