* [Qemu-devel] [PATCH] throttle: Fix crash on reopen
@ 2018-06-08 15:15 Alberto Garcia
2018-06-09 21:52 ` Max Reitz
0 siblings, 1 reply; 2+ messages in thread
From: Alberto Garcia @ 2018-06-08 15:15 UTC (permalink / raw)
To: qemu-devel
Cc: Alberto Garcia, qemu-stable, qemu-block, Kevin Wolf, Max Reitz,
Manos Pitsidianakis
The throttle block filter can be reopened, and with this it is
possible to change the throttle group that the filter belongs to.
The way the code does that is the following:
- On throttle_reopen_prepare(): create a new ThrottleGroupMember
and attach it to the new throttle group.
- On throttle_reopen_commit(): detach the old ThrottleGroupMember,
delete it and replace it with the new one.
The problem with this is that by replacing the ThrottleGroupMember the
previous value of io_limits_disabled is lost, causing an assertion
failure in throttle_co_drain_end().
This problem can be reproduced by reopening a throttle node:
$QEMU -monitor stdio
-object throttle-group,id=tg0,x-iops-total=1000 \
-blockdev node-name=hd0,driver=qcow2,file.driver=file,file.filename=hd.qcow2 \
-blockdev node-name=root,driver=throttle,throttle-group=tg0,file=hd0,read-only=on
(qemu) block_stream root
block/throttle.c:214: throttle_co_drain_end: Assertion `tgm->io_limits_disabled' failed.
Since we only want to change the throttle group on reopen there's no
need to create a ThrottleGroupMember and discard the old one. It's
easier if we simply detach it from its current group and attach it to
the new one.
Signed-off-by: Alberto Garcia <berto@igalia.com>
---
block/throttle.c | 54 +++++++++++++++++++++++++++++++++---------------------
1 file changed, 33 insertions(+), 21 deletions(-)
diff --git a/block/throttle.c b/block/throttle.c
index 95ed06acd8..026f408aa6 100644
--- a/block/throttle.c
+++ b/block/throttle.c
@@ -36,9 +36,12 @@ static QemuOptsList throttle_opts = {
},
};
-static int throttle_configure_tgm(BlockDriverState *bs,
- ThrottleGroupMember *tgm,
- QDict *options, Error **errp)
+/*
+ * If this function succeeds then the throttle group name is stored in
+ * @group and must be freed by the caller.
+ * If there's an error then @group remains unmodified.
+ */
+static int throttle_parse_options(QDict *options, char **group, Error **errp)
{
int ret;
const char *group_name;
@@ -63,8 +66,7 @@ static int throttle_configure_tgm(BlockDriverState *bs,
goto fin;
}
- /* Register membership to group with name group_name */
- throttle_group_register_tgm(tgm, group_name, bdrv_get_aio_context(bs));
+ *group = g_strdup(group_name);
ret = 0;
fin:
qemu_opts_del(opts);
@@ -75,6 +77,8 @@ static int throttle_open(BlockDriverState *bs, QDict *options,
int flags, Error **errp)
{
ThrottleGroupMember *tgm = bs->opaque;
+ char *group;
+ int ret;
bs->file = bdrv_open_child(NULL, options, "file", bs,
&child_file, false, errp);
@@ -84,7 +88,14 @@ static int throttle_open(BlockDriverState *bs, QDict *options,
bs->supported_write_flags = bs->file->bs->supported_write_flags;
bs->supported_zero_flags = bs->file->bs->supported_zero_flags;
- return throttle_configure_tgm(bs, tgm, options, errp);
+ ret = throttle_parse_options(options, &group, errp);
+ if (ret == 0) {
+ /* Register membership to group with name group_name */
+ throttle_group_register_tgm(tgm, group, bdrv_get_aio_context(bs));
+ g_free(group);
+ }
+
+ return ret;
}
static void throttle_close(BlockDriverState *bs)
@@ -160,35 +171,36 @@ static void throttle_attach_aio_context(BlockDriverState *bs,
static int throttle_reopen_prepare(BDRVReopenState *reopen_state,
BlockReopenQueue *queue, Error **errp)
{
- ThrottleGroupMember *tgm;
+ int ret;
+ char *group = NULL;
assert(reopen_state != NULL);
assert(reopen_state->bs != NULL);
- reopen_state->opaque = g_new0(ThrottleGroupMember, 1);
- tgm = reopen_state->opaque;
-
- return throttle_configure_tgm(reopen_state->bs, tgm, reopen_state->options,
- errp);
+ ret = throttle_parse_options(reopen_state->options, &group, errp);
+ reopen_state->opaque = group;
+ return ret;
}
static void throttle_reopen_commit(BDRVReopenState *reopen_state)
{
- ThrottleGroupMember *old_tgm = reopen_state->bs->opaque;
- ThrottleGroupMember *new_tgm = reopen_state->opaque;
+ BlockDriverState *bs = reopen_state->bs;
+ ThrottleGroupMember *tgm = bs->opaque;
+ char *group = reopen_state->opaque;
- throttle_group_unregister_tgm(old_tgm);
- g_free(old_tgm);
- reopen_state->bs->opaque = new_tgm;
+ assert(group);
+
+ if (strcmp(group, throttle_group_get_name(tgm))) {
+ throttle_group_unregister_tgm(tgm);
+ throttle_group_register_tgm(tgm, group, bdrv_get_aio_context(bs));
+ }
+ g_free(reopen_state->opaque);
reopen_state->opaque = NULL;
}
static void throttle_reopen_abort(BDRVReopenState *reopen_state)
{
- ThrottleGroupMember *tgm = reopen_state->opaque;
-
- throttle_group_unregister_tgm(tgm);
- g_free(tgm);
+ g_free(reopen_state->opaque);
reopen_state->opaque = NULL;
}
--
2.11.0
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [Qemu-devel] [PATCH] throttle: Fix crash on reopen
2018-06-08 15:15 [Qemu-devel] [PATCH] throttle: Fix crash on reopen Alberto Garcia
@ 2018-06-09 21:52 ` Max Reitz
0 siblings, 0 replies; 2+ messages in thread
From: Max Reitz @ 2018-06-09 21:52 UTC (permalink / raw)
To: Alberto Garcia, qemu-devel
Cc: qemu-stable, qemu-block, Kevin Wolf, Manos Pitsidianakis
[-- Attachment #1: Type: text/plain, Size: 1666 bytes --]
On 2018-06-08 17:15, Alberto Garcia wrote:
> The throttle block filter can be reopened, and with this it is
> possible to change the throttle group that the filter belongs to.
>
> The way the code does that is the following:
>
> - On throttle_reopen_prepare(): create a new ThrottleGroupMember
> and attach it to the new throttle group.
>
> - On throttle_reopen_commit(): detach the old ThrottleGroupMember,
> delete it and replace it with the new one.
>
> The problem with this is that by replacing the ThrottleGroupMember the
> previous value of io_limits_disabled is lost, causing an assertion
> failure in throttle_co_drain_end().
>
> This problem can be reproduced by reopening a throttle node:
>
> $QEMU -monitor stdio
> -object throttle-group,id=tg0,x-iops-total=1000 \
> -blockdev node-name=hd0,driver=qcow2,file.driver=file,file.filename=hd.qcow2 \
> -blockdev node-name=root,driver=throttle,throttle-group=tg0,file=hd0,read-only=on
>
> (qemu) block_stream root
> block/throttle.c:214: throttle_co_drain_end: Assertion `tgm->io_limits_disabled' failed.
>
> Since we only want to change the throttle group on reopen there's no
> need to create a ThrottleGroupMember and discard the old one. It's
> easier if we simply detach it from its current group and attach it to
> the new one.
>
> Signed-off-by: Alberto Garcia <berto@igalia.com>
> ---
> block/throttle.c | 54 +++++++++++++++++++++++++++++++++---------------------
> 1 file changed, 33 insertions(+), 21 deletions(-)
Thanks, applied to my block branch:
https://git.xanclic.moe/XanClic/qemu/commits/branch/block
Max
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2018-06-09 21:53 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-06-08 15:15 [Qemu-devel] [PATCH] throttle: Fix crash on reopen Alberto Garcia
2018-06-09 21:52 ` Max Reitz
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).