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