bdrv_change_backing_file() is called both inside and outside coroutine
context. This makes it difficult for it to take the graph lock
internally. It also means that driver implementations need to be able to
run outside of coroutines, too. Switch it to the usual model with a
coroutine based implementation and a co_wrapper instead. The new
function is marked GRAPH_RDLOCK.
As the co_wrapper now runs the function in the AioContext of the node
(as it should always have done), this is not GLOBAL_STATE_CODE() any
more.
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
include/block/block-global-state.h | 3 +-
include/block/block-io.h | 8 ++++
include/block/block_int-common.h | 5 ++-
block.c | 11 ++---
block/qcow2.c | 18 +++++----
block/qed.c | 64 +++++++++++++++---------------
tests/unit/test-bdrv-drain.c | 8 ++--
7 files changed, 65 insertions(+), 52 deletions(-)
diff --git a/include/block/block-global-state.h b/include/block/block-global-state.h
index 9e0ccc1c32..6b21fbc73f 100644
--- a/include/block/block-global-state.h
+++ b/include/block/block-global-state.h
@@ -142,8 +142,7 @@ bdrv_refresh_limits(BlockDriverState *bs, Transaction *tran, Error **errp);
int bdrv_commit(BlockDriverState *bs);
int GRAPH_RDLOCK bdrv_make_empty(BdrvChild *c, Error **errp);
-int bdrv_change_backing_file(BlockDriverState *bs, const char *backing_file,
- const char *backing_fmt, bool warn);
+
void bdrv_register(BlockDriver *bdrv);
int bdrv_drop_intermediate(BlockDriverState *top, BlockDriverState *base,
const char *backing_file_str);
diff --git a/include/block/block-io.h b/include/block/block-io.h
index 58c4cf50a0..f8729ccc55 100644
--- a/include/block/block-io.h
+++ b/include/block/block-io.h
@@ -210,6 +210,14 @@ void bdrv_round_to_subclusters(BlockDriverState *bs,
void bdrv_get_backing_filename(BlockDriverState *bs,
char *filename, int filename_size);
+int coroutine_fn GRAPH_RDLOCK
+bdrv_co_change_backing_file(BlockDriverState *bs, const char *backing_file,
+ const char *backing_fmt, bool warn);
+
+int co_wrapper_bdrv_rdlock
+bdrv_change_backing_file(BlockDriverState *bs, const char *backing_file,
+ const char *backing_fmt, bool warn);
+
int bdrv_save_vmstate(BlockDriverState *bs, const uint8_t *buf,
int64_t pos, int size);
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
index ed6066929a..59f6d7f195 100644
--- a/include/block/block_int-common.h
+++ b/include/block/block_int-common.h
@@ -331,8 +331,9 @@ struct BlockDriver {
const char *name,
Error **errp);
- int (*bdrv_change_backing_file)(BlockDriverState *bs,
- const char *backing_file, const char *backing_fmt);
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_change_backing_file)(
+ BlockDriverState *bs, const char *backing_file,
+ const char *backing_fmt);
/* TODO Better pass a option string/QDict/QemuOpts to add any rule? */
int (*bdrv_debug_breakpoint)(BlockDriverState *bs, const char *event,
diff --git a/block.c b/block.c
index 41164983a3..5749358720 100644
--- a/block.c
+++ b/block.c
@@ -5760,13 +5760,14 @@ int coroutine_fn bdrv_co_check(BlockDriverState *bs,
* image file header
* -ENOTSUP - format driver doesn't support changing the backing file
*/
-int bdrv_change_backing_file(BlockDriverState *bs, const char *backing_file,
- const char *backing_fmt, bool require)
+int coroutine_fn
+bdrv_co_change_backing_file(BlockDriverState *bs, const char *backing_file,
+ const char *backing_fmt, bool require)
{
BlockDriver *drv = bs->drv;
int ret;
- GLOBAL_STATE_CODE();
+ IO_CODE();
if (!drv) {
return -ENOMEDIUM;
@@ -5781,8 +5782,8 @@ int bdrv_change_backing_file(BlockDriverState *bs, const char *backing_file,
return -EINVAL;
}
- if (drv->bdrv_change_backing_file != NULL) {
- ret = drv->bdrv_change_backing_file(bs, backing_file, backing_fmt);
+ if (drv->bdrv_co_change_backing_file != NULL) {
+ ret = drv->bdrv_co_change_backing_file(bs, backing_file, backing_fmt);
} else {
ret = -ENOTSUP;
}
diff --git a/block/qcow2.c b/block/qcow2.c
index a1443a31aa..63c7cd882e 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -3155,8 +3155,9 @@ fail:
return ret;
}
-static int qcow2_change_backing_file(BlockDriverState *bs,
- const char *backing_file, const char *backing_fmt)
+static int coroutine_fn GRAPH_RDLOCK
+qcow2_co_change_backing_file(BlockDriverState *bs, const char *backing_file,
+ const char *backing_fmt)
{
BDRVQcow2State *s = bs->opaque;
@@ -3816,8 +3817,11 @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
backing_format = BlockdevDriver_str(qcow2_opts->backing_fmt);
}
- ret = bdrv_change_backing_file(blk_bs(blk), qcow2_opts->backing_file,
- backing_format, false);
+ bdrv_graph_co_rdlock();
+ ret = bdrv_co_change_backing_file(blk_bs(blk), qcow2_opts->backing_file,
+ backing_format, false);
+ bdrv_graph_co_rdunlock();
+
if (ret < 0) {
error_setg_errno(errp, -ret, "Could not assign backing file '%s' "
"with format '%s'", qcow2_opts->backing_file,
@@ -6155,9 +6159,9 @@ BlockDriver bdrv_qcow2 = {
.bdrv_co_save_vmstate = qcow2_co_save_vmstate,
.bdrv_co_load_vmstate = qcow2_co_load_vmstate,
- .is_format = true,
- .supports_backing = true,
- .bdrv_change_backing_file = qcow2_change_backing_file,
+ .is_format = true,
+ .supports_backing = true,
+ .bdrv_co_change_backing_file = qcow2_co_change_backing_file,
.bdrv_refresh_limits = qcow2_refresh_limits,
.bdrv_co_invalidate_cache = qcow2_co_invalidate_cache,
diff --git a/block/qed.c b/block/qed.c
index 686ad711f7..996aa384fe 100644
--- a/block/qed.c
+++ b/block/qed.c
@@ -1498,9 +1498,9 @@ bdrv_qed_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
return 0;
}
-static int bdrv_qed_change_backing_file(BlockDriverState *bs,
- const char *backing_file,
- const char *backing_fmt)
+static int coroutine_fn GRAPH_RDLOCK
+bdrv_qed_co_change_backing_file(BlockDriverState *bs, const char *backing_file,
+ const char *backing_fmt)
{
BDRVQEDState *s = bs->opaque;
QEDHeader new_header, le_header;
@@ -1562,7 +1562,7 @@ static int bdrv_qed_change_backing_file(BlockDriverState *bs,
}
/* Write new header */
- ret = bdrv_pwrite_sync(bs->file, 0, buffer_len, buffer, 0);
+ ret = bdrv_co_pwrite_sync(bs->file, 0, buffer_len, buffer, 0);
g_free(buffer);
if (ret == 0) {
memcpy(&s->header, &new_header, sizeof(new_header));
@@ -1636,34 +1636,34 @@ static QemuOptsList qed_create_opts = {
};
static BlockDriver bdrv_qed = {
- .format_name = "qed",
- .instance_size = sizeof(BDRVQEDState),
- .create_opts = &qed_create_opts,
- .is_format = true,
- .supports_backing = true,
-
- .bdrv_probe = bdrv_qed_probe,
- .bdrv_open = bdrv_qed_open,
- .bdrv_close = bdrv_qed_close,
- .bdrv_reopen_prepare = bdrv_qed_reopen_prepare,
- .bdrv_child_perm = bdrv_default_perms,
- .bdrv_co_create = bdrv_qed_co_create,
- .bdrv_co_create_opts = bdrv_qed_co_create_opts,
- .bdrv_has_zero_init = bdrv_has_zero_init_1,
- .bdrv_co_block_status = bdrv_qed_co_block_status,
- .bdrv_co_readv = bdrv_qed_co_readv,
- .bdrv_co_writev = bdrv_qed_co_writev,
- .bdrv_co_pwrite_zeroes = bdrv_qed_co_pwrite_zeroes,
- .bdrv_co_truncate = bdrv_qed_co_truncate,
- .bdrv_co_getlength = bdrv_qed_co_getlength,
- .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,
- .bdrv_co_check = bdrv_qed_co_check,
- .bdrv_detach_aio_context = bdrv_qed_detach_aio_context,
- .bdrv_attach_aio_context = bdrv_qed_attach_aio_context,
- .bdrv_drain_begin = bdrv_qed_drain_begin,
+ .format_name = "qed",
+ .instance_size = sizeof(BDRVQEDState),
+ .create_opts = &qed_create_opts,
+ .is_format = true,
+ .supports_backing = true,
+
+ .bdrv_probe = bdrv_qed_probe,
+ .bdrv_open = bdrv_qed_open,
+ .bdrv_close = bdrv_qed_close,
+ .bdrv_reopen_prepare = bdrv_qed_reopen_prepare,
+ .bdrv_child_perm = bdrv_default_perms,
+ .bdrv_co_create = bdrv_qed_co_create,
+ .bdrv_co_create_opts = bdrv_qed_co_create_opts,
+ .bdrv_has_zero_init = bdrv_has_zero_init_1,
+ .bdrv_co_block_status = bdrv_qed_co_block_status,
+ .bdrv_co_readv = bdrv_qed_co_readv,
+ .bdrv_co_writev = bdrv_qed_co_writev,
+ .bdrv_co_pwrite_zeroes = bdrv_qed_co_pwrite_zeroes,
+ .bdrv_co_truncate = bdrv_qed_co_truncate,
+ .bdrv_co_getlength = bdrv_qed_co_getlength,
+ .bdrv_co_get_info = bdrv_qed_co_get_info,
+ .bdrv_refresh_limits = bdrv_qed_refresh_limits,
+ .bdrv_co_change_backing_file = bdrv_qed_co_change_backing_file,
+ .bdrv_co_invalidate_cache = bdrv_qed_co_invalidate_cache,
+ .bdrv_co_check = bdrv_qed_co_check,
+ .bdrv_detach_aio_context = bdrv_qed_detach_aio_context,
+ .bdrv_attach_aio_context = bdrv_qed_attach_aio_context,
+ .bdrv_drain_begin = bdrv_qed_drain_begin,
};
static void bdrv_qed_init(void)
diff --git a/tests/unit/test-bdrv-drain.c b/tests/unit/test-bdrv-drain.c
index ba4e42b197..8d05538bf6 100644
--- a/tests/unit/test-bdrv-drain.c
+++ b/tests/unit/test-bdrv-drain.c
@@ -96,9 +96,9 @@ static int coroutine_fn bdrv_test_co_preadv(BlockDriverState *bs,
return 0;
}
-static int bdrv_test_change_backing_file(BlockDriverState *bs,
- const char *backing_file,
- const char *backing_fmt)
+static int bdrv_test_co_change_backing_file(BlockDriverState *bs,
+ const char *backing_file,
+ const char *backing_fmt)
{
return 0;
}
@@ -116,7 +116,7 @@ static BlockDriver bdrv_test = {
.bdrv_child_perm = bdrv_default_perms,
- .bdrv_change_backing_file = bdrv_test_change_backing_file,
+ .bdrv_co_change_backing_file = bdrv_test_co_change_backing_file,
};
static void aio_ret_cb(void *opaque, int ret)
--
2.41.0
On Fri, Oct 27, 2023 at 05:53:28PM +0200, Kevin Wolf wrote: > bdrv_change_backing_file() is called both inside and outside coroutine > context. This makes it difficult for it to take the graph lock > internally. It also means that driver implementations need to be able to > run outside of coroutines, too. Switch it to the usual model with a > coroutine based implementation and a co_wrapper instead. The new > function is marked GRAPH_RDLOCK. > > As the co_wrapper now runs the function in the AioContext of the node > (as it should always have done), this is not GLOBAL_STATE_CODE() any > more. > > Signed-off-by: Kevin Wolf <kwolf@redhat.com> > --- > include/block/block-global-state.h | 3 +- > include/block/block-io.h | 8 ++++ > include/block/block_int-common.h | 5 ++- > block.c | 11 ++--- > block/qcow2.c | 18 +++++---- > block/qed.c | 64 +++++++++++++++--------------- > tests/unit/test-bdrv-drain.c | 8 ++-- > 7 files changed, 65 insertions(+), 52 deletions(-) > > +++ b/block/qcow2.c > @@ -6155,9 +6159,9 @@ BlockDriver bdrv_qcow2 = { > .bdrv_co_save_vmstate = qcow2_co_save_vmstate, > .bdrv_co_load_vmstate = qcow2_co_load_vmstate, > > - .is_format = true, > - .supports_backing = true, > - .bdrv_change_backing_file = qcow2_change_backing_file, > + .is_format = true, > + .supports_backing = true, > + .bdrv_co_change_backing_file = qcow2_co_change_backing_file, > > .bdrv_refresh_limits = qcow2_refresh_limits, > .bdrv_co_invalidate_cache = qcow2_co_invalidate_cache, Here, you only realigned = on a portion of the initializer... > diff --git a/block/qed.c b/block/qed.c > index 686ad711f7..996aa384fe 100644 > --- a/block/qed.c > +++ b/block/qed.c > static BlockDriver bdrv_qed = { > - .format_name = "qed", > - .instance_size = sizeof(BDRVQEDState), > - .create_opts = &qed_create_opts, > - .is_format = true, > - .supports_backing = true, > - > - .bdrv_probe = bdrv_qed_probe, ...while here, you are doing it on the entire block. This shows why I personally dislike aligning =, but I tolerate it when it is already prevailing style. Still, it feels weird to be inconsistent within the same patch. At any rate, that's cosmetic, and not a correctness issue. Up to you if you want to ignore my commentary in this case. Reviewed-by: Eric Blake <eblake@redhat.com> -- Eric Blake, Principal Software Engineer Red Hat, Inc. Virtualization: qemu.org | libguestfs.org
Am 30.10.2023 um 14:57 hat Eric Blake geschrieben: > On Fri, Oct 27, 2023 at 05:53:28PM +0200, Kevin Wolf wrote: > > bdrv_change_backing_file() is called both inside and outside coroutine > > context. This makes it difficult for it to take the graph lock > > internally. It also means that driver implementations need to be able to > > run outside of coroutines, too. Switch it to the usual model with a > > coroutine based implementation and a co_wrapper instead. The new > > function is marked GRAPH_RDLOCK. > > > > As the co_wrapper now runs the function in the AioContext of the node > > (as it should always have done), this is not GLOBAL_STATE_CODE() any > > more. > > > > Signed-off-by: Kevin Wolf <kwolf@redhat.com> > > --- > > include/block/block-global-state.h | 3 +- > > include/block/block-io.h | 8 ++++ > > include/block/block_int-common.h | 5 ++- > > block.c | 11 ++--- > > block/qcow2.c | 18 +++++---- > > block/qed.c | 64 +++++++++++++++--------------- > > tests/unit/test-bdrv-drain.c | 8 ++-- > > 7 files changed, 65 insertions(+), 52 deletions(-) > > > > +++ b/block/qcow2.c > > @@ -6155,9 +6159,9 @@ BlockDriver bdrv_qcow2 = { > > .bdrv_co_save_vmstate = qcow2_co_save_vmstate, > > .bdrv_co_load_vmstate = qcow2_co_load_vmstate, > > > > - .is_format = true, > > - .supports_backing = true, > > - .bdrv_change_backing_file = qcow2_change_backing_file, > > + .is_format = true, > > + .supports_backing = true, > > + .bdrv_co_change_backing_file = qcow2_co_change_backing_file, > > > > .bdrv_refresh_limits = qcow2_refresh_limits, > > .bdrv_co_invalidate_cache = qcow2_co_invalidate_cache, > > Here, you only realigned = on a portion of the initializer... > > > diff --git a/block/qed.c b/block/qed.c > > index 686ad711f7..996aa384fe 100644 > > --- a/block/qed.c > > +++ b/block/qed.c > > static BlockDriver bdrv_qed = { > > - .format_name = "qed", > > - .instance_size = sizeof(BDRVQEDState), > > - .create_opts = &qed_create_opts, > > - .is_format = true, > > - .supports_backing = true, > > - > > - .bdrv_probe = bdrv_qed_probe, > > ...while here, you are doing it on the entire block. This shows why I > personally dislike aligning =, but I tolerate it when it is already > prevailing style. Still, it feels weird to be inconsistent within the > same patch. It's because qcow2 already had multiple different indentations, but qed had everything aligned to the same column. I can update qcow2. Kevin
On Fri, Nov 03, 2023 at 11:33:47AM +0100, Kevin Wolf wrote: > Am 30.10.2023 um 14:57 hat Eric Blake geschrieben: > > On Fri, Oct 27, 2023 at 05:53:28PM +0200, Kevin Wolf wrote: > > > bdrv_change_backing_file() is called both inside and outside coroutine > > > context. This makes it difficult for it to take the graph lock > > > internally. It also means that driver implementations need to be able to > > > run outside of coroutines, too. Switch it to the usual model with a > > > coroutine based implementation and a co_wrapper instead. The new > > > function is marked GRAPH_RDLOCK. > > > > > > As the co_wrapper now runs the function in the AioContext of the node > > > (as it should always have done), this is not GLOBAL_STATE_CODE() any > > > more. > > > > > > Signed-off-by: Kevin Wolf <kwolf@redhat.com> > > > --- > > > include/block/block-global-state.h | 3 +- > > > include/block/block-io.h | 8 ++++ > > > include/block/block_int-common.h | 5 ++- > > > block.c | 11 ++--- > > > block/qcow2.c | 18 +++++---- > > > block/qed.c | 64 +++++++++++++++--------------- > > > tests/unit/test-bdrv-drain.c | 8 ++-- > > > 7 files changed, 65 insertions(+), 52 deletions(-) > > > > > > +++ b/block/qcow2.c > > > @@ -6155,9 +6159,9 @@ BlockDriver bdrv_qcow2 = { > > > .bdrv_co_save_vmstate = qcow2_co_save_vmstate, > > > .bdrv_co_load_vmstate = qcow2_co_load_vmstate, > > > > > > - .is_format = true, > > > - .supports_backing = true, > > > - .bdrv_change_backing_file = qcow2_change_backing_file, > > > + .is_format = true, > > > + .supports_backing = true, > > > + .bdrv_co_change_backing_file = qcow2_co_change_backing_file, > > > > > > .bdrv_refresh_limits = qcow2_refresh_limits, > > > .bdrv_co_invalidate_cache = qcow2_co_invalidate_cache, > > > > Here, you only realigned = on a portion of the initializer... > > > > > diff --git a/block/qed.c b/block/qed.c > > > index 686ad711f7..996aa384fe 100644 > > > --- a/block/qed.c > > > +++ b/block/qed.c > > > static BlockDriver bdrv_qed = { > > > - .format_name = "qed", > > > - .instance_size = sizeof(BDRVQEDState), > > > - .create_opts = &qed_create_opts, > > > - .is_format = true, > > > - .supports_backing = true, > > > - > > > - .bdrv_probe = bdrv_qed_probe, > > > > ...while here, you are doing it on the entire block. This shows why I > > personally dislike aligning =, but I tolerate it when it is already > > prevailing style. Still, it feels weird to be inconsistent within the > > same patch. > > It's because qcow2 already had multiple different indentations, but qed > had everything aligned to the same column. I can update qcow2. It's your call how you want it to look (as I stated, we are already inconsistent on style; my preference is a version with less churn, but I also understand preserving the existing style as a way to avoid churn). Whatever the end result, it doesn't affect my R-b. -- Eric Blake, Principal Software Engineer Red Hat, Inc. Virtualization: qemu.org | libguestfs.org
© 2016 - 2024 Red Hat, Inc.