08.06.26 14:03, Jean-Louis Dupond пишет:
Add a new function called bdrv_open_backing_chain_until.
This is used to open a block up until a specified backing chain.

Modified bdrv_open_inherit to accept a new arg 'open_backing' to force
to to no open the next backing. Adjusting all references to keep the
existing behaviour.

Signed-off-by: Jean-Louis Dupond <[email protected]>
---
  block.c                            | 65 +++++++++++++++++++++++++-----
  block/mirror.c                     |  2 +-
  include/block/block-global-state.h |  7 +++-
  3 files changed, 62 insertions(+), 12 deletions(-)

diff --git a/block.c b/block.c
index f0a6042e61..a4f4ce1c21 100644
--- a/block.c
+++ b/block.c
@@ -83,6 +83,7 @@ static QLIST_HEAD(, BlockDriver) bdrv_drivers =
  static BlockDriverState *bdrv_open_inherit(const char *filename,
                                             const char *reference,
                                             QDict *options, int flags,
+                                           bool open_backing,
                                             BlockDriverState *parent,
                                             const BdrvChildClass *child_class,
                                             BdrvChildRole child_role,
@@ -3617,6 +3618,7 @@ out:
   * TODO Can this be unified with bdrv_open_image()?
   */
  int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
+                           bool open_backing,

"open_backing" boolean parameter for "bdrv_open_backing_file" is misleading.

                             const char *bdref_key, Error **errp)
  {
      ERRP_GUARD();
@@ -3695,9 +3697,9 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict 
*parent_options,
          qdict_put_str(options, "driver", bs->backing_format);
      }
- backing_hd = bdrv_open_inherit(backing_filename, reference, options, 0, bs,
-                                   &child_of_bds, bdrv_backing_role(bs), true,
-                                   errp);
+    backing_hd = bdrv_open_inherit(backing_filename, reference, options, 0,
+                                   open_backing, bs, &child_of_bds,
+                                   bdrv_backing_role(bs), true, errp);
      if (!backing_hd) {
          bs->open_flags |= BDRV_O_NO_BACKING;
          error_prepend(errp, "Could not open backing file: ");
@@ -3733,6 +3735,48 @@ free_exit:
      return ret;
  }
+int
+bdrv_open_backing_chain_until(BlockDriverState *top_bs,
+                              const char *base_filename,
+                              Error **errp)
+{
+    BlockDriverState *base_bs = NULL;
+    BlockDriverState *curr = top_bs;
+    int ret;
+
+    GLOBAL_STATE_CODE();
+
+    if (!base_filename) {
+        return 0;
+    }
+
+    while (!(base_bs = bdrv_find_backing_image(top_bs, base_filename))) {

So we do a downward cycle, and on each iteration call bdrv_find_backing_image(),
making same downward cycle.

Maybe better to modify bdrv_find_backing_image(), adding boolean parameter 
"do_open"?

+        QDict *options;
+
+        options = qdict_clone_shallow(curr->options);
+        ret = bdrv_open_backing_file(curr, options, false, "backing", errp);
+        qobject_unref(options);
+        if (ret < 0) {
+            return ret;
+        }
+
+        bdrv_graph_rdlock_main_loop();

I don't know actually, how to use this lock properly, but the only preexisting
call to bdrv_open_backing_file() is done under this lock.

+        if (!curr->backing) {
+            bdrv_graph_rdunlock_main_loop();
+            error_setg(errp,
+                       "Did not find '%s' in the backing chain of '%s'",
+                       base_filename, top_bs->filename);
+            return -ENOENT;
+        }
+
+        /* Switch to the next layer */
+        curr = curr->backing->bs;
+        bdrv_graph_rdunlock_main_loop();
+    }
+
+    return 0;
+}
+
  static BlockDriverState *
  bdrv_open_child_bs(const char *filename, QDict *options, const char 
*bdref_key,
                     BlockDriverState *parent, const BdrvChildClass 
*child_class,
@@ -3767,7 +3811,7 @@ bdrv_open_child_bs(const char *filename, QDict *options, 
const char *bdref_key,
          goto done;
      }
- bs = bdrv_open_inherit(filename, reference, image_options, 0,
+    bs = bdrv_open_inherit(filename, reference, image_options, 0, true,
                             parent, child_class, child_role, parse_filename,
                             errp);
      if (!bs) {
@@ -3897,8 +3941,8 @@ BlockDriverState *bdrv_open_blockdev_ref(BlockdevRef 
*ref, Error **errp)
} - bs = bdrv_open_inherit(NULL, reference, qdict, 0, NULL, NULL, 0, false,
-                           errp);
+    bs = bdrv_open_inherit(NULL, reference, qdict, 0, true, NULL, NULL, 0,
+                           false, errp);
      obj = NULL;
      qobject_unref(obj);
      visit_free(v);
@@ -3986,7 +4030,7 @@ out:
   */
  static BlockDriverState * no_coroutine_fn
  bdrv_open_inherit(const char *filename, const char *reference, QDict *options,
-                  int flags, BlockDriverState *parent,
+                  int flags, bool open_backing, BlockDriverState *parent,
                    const BdrvChildClass *child_class, BdrvChildRole child_role,
                    bool parse_filename, Error **errp)
  {
@@ -4199,8 +4243,9 @@ bdrv_open_inherit(const char *filename, const char 
*reference, QDict *options,
      }
/* If there is a backing file, use it */
-    if ((flags & BDRV_O_NO_BACKING) == 0) {
-        ret = bdrv_open_backing_file(bs, options, "backing", &local_err);
+    if ((flags & BDRV_O_NO_BACKING) == 0 && open_backing) {

This looks like you just need to pass BDRV_O_NO_BACKING flag, when you do not 
want open backing?

+        ret = bdrv_open_backing_file(bs, options, open_backing, "backing",
+                                     &local_err);
          if (ret < 0) {
              goto close_and_fail;
          }
@@ -4283,7 +4328,7 @@ BlockDriverState *bdrv_open(const char *filename, const 
char *reference,
  {
      GLOBAL_STATE_CODE();
- return bdrv_open_inherit(filename, reference, options, flags, NULL,
+    return bdrv_open_inherit(filename, reference, options, flags, true, NULL,
                               NULL, 0, true, errp);
  }
diff --git a/block/mirror.c b/block/mirror.c
index 089856f4a8..a4dde5d36d 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -785,7 +785,7 @@ static int mirror_exit_common(Job *job)
          bdrv_graph_rdlock_main_loop();
          assert(!bdrv_backing_chain_next(target_bs));
          ret = bdrv_open_backing_file(bdrv_skip_filters(target_bs), NULL,
-                                     "backing", &local_err);
+                                     true, "backing", &local_err);
          bdrv_graph_rdunlock_main_loop();
          if (ret < 0) {
              error_report_err(local_err);
diff --git a/include/block/block-global-state.h 
b/include/block/block-global-state.h
index ed89999f0f..c7becd9d73 100644
--- a/include/block/block-global-state.h
+++ b/include/block/block-global-state.h
@@ -110,7 +110,12 @@ bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState 
*backing_hd,
                      Error **errp);
int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
-                           const char *bdref_key, Error **errp);
+                           bool open_backing, const char *bdref_key,
+                           Error **errp);
+
+int bdrv_open_backing_chain_until(BlockDriverState *top_bs,
+                                  const char *base_filename,
+                                  Error **errp);
BlockDriverState * no_coroutine_fn
  bdrv_open(const char *filename, const char *reference, QDict *options,


--
Best regards,
Vladimir

Reply via email to