* [PULL 0/2] Block layer patches
@ 2026-03-17 13:45 Hanna Czenczek
2026-03-17 13:45 ` [PULL 1/2] throttle-group: Fix race condition in throttle_group_restart_queue() Hanna Czenczek
` (3 more replies)
0 siblings, 4 replies; 8+ messages in thread
From: Hanna Czenczek @ 2026-03-17 13:45 UTC (permalink / raw)
To: qemu-block; +Cc: qemu-devel, Hanna Czenczek, Kevin Wolf
The following changes since commit 559919ce54927d59b215a4665eda7ab6118a48aa:
Merge tag 'pull-trivial-patches' of https://gitlab.com/mjt0k/qemu into staging (2026-03-16 13:07:33 +0000)
are available in the Git repository at:
https://gitlab.com/hreitz/qemu.git tags/pull-block-2026-03-17
for you to fetch changes up to 9ac85f4cc7995217db8f736733b990d6addcb036:
block/mirror: fix assertion failure upon duplicate complete for job using 'replaces' (2026-03-17 12:31:54 +0100)
----------------------------------------------------------------
Block layer patches for rc0
- Fix race condition in throttle-group code triggering an assertion
failure
- Fix assertion failure in mirror job when issuing job-complete twice
----------------------------------------------------------------
Alberto Garcia (1):
throttle-group: Fix race condition in throttle_group_restart_queue()
Fiona Ebner (1):
block/mirror: fix assertion failure upon duplicate complete for job
using 'replaces'
block/mirror.c | 28 ++++++++-------
block/throttle-groups.c | 79 +++++++++++++++++++++++++++++++----------
2 files changed, 75 insertions(+), 32 deletions(-)
--
2.53.0
^ permalink raw reply [flat|nested] 8+ messages in thread* [PULL 1/2] throttle-group: Fix race condition in throttle_group_restart_queue() 2026-03-17 13:45 [PULL 0/2] Block layer patches Hanna Czenczek @ 2026-03-17 13:45 ` Hanna Czenczek 2026-03-17 13:45 ` [PULL 2/2] block/mirror: fix assertion failure upon duplicate complete for job using 'replaces' Hanna Czenczek ` (2 subsequent siblings) 3 siblings, 0 replies; 8+ messages in thread From: Hanna Czenczek @ 2026-03-17 13:45 UTC (permalink / raw) To: qemu-block; +Cc: qemu-devel, Hanna Czenczek, Kevin Wolf From: Alberto Garcia <berto@igalia.com> When a timer is fired a pending I/O request is restarted and tg->any_timer_armed is reset so other requests can be scheduled. However we're resetting any_timer_armed first in timer_cb() before the request is actually restarted, and there's a window between both moments in which another thread can arm the same timer, hitting an assertion in throttle_group_restart_queue(). This can be solved by deferring the reset of tg->any_timer_armed to the moment when the queue is actually restarted, which is protected by tg->lock, preventing other threads from arming the timer before that. In addition to that, throttle_group_restart_tgm() is also updated to hold tg->lock while the timer is being inspected. Here we consider three different scenarios: - If the tgm has a timer set, fire it immediately - If another tgm has a timer set, restart the queue anyway - If there is no timer set in this group then simulate a timer that fires immediately, by setting tg->any_timer_armed in order to prevent other threads from arming a timer in the meantime. Resolves: https://gitlab.com/qemu-project/qemu/-/issues/3194 Signed-off-by: Alberto Garcia <berto@igalia.com> Message-Id: <825598ef34ad384d936da19d634eda75598508f7.1773316842.git.berto@igalia.com> Signed-off-by: Hanna Czenczek <hreitz@redhat.com> --- block/throttle-groups.c | 79 +++++++++++++++++++++++++++++++---------- 1 file changed, 60 insertions(+), 19 deletions(-) diff --git a/block/throttle-groups.c b/block/throttle-groups.c index 5329ff1fdb..4b1b1944c2 100644 --- a/block/throttle-groups.c +++ b/block/throttle-groups.c @@ -391,6 +391,7 @@ void coroutine_fn throttle_group_co_io_limits_intercept(ThrottleGroupMember *tgm typedef struct { ThrottleGroupMember *tgm; ThrottleDirection direction; + bool reset_timer_armed; } RestartData; static void coroutine_fn throttle_group_restart_queue_entry(void *opaque) @@ -403,6 +404,9 @@ static void coroutine_fn throttle_group_restart_queue_entry(void *opaque) bool empty_queue; qemu_mutex_lock(&tg->lock); + if (data->reset_timer_armed) { + tg->any_timer_armed[direction] = false; + } empty_queue = !throttle_group_co_restart_queue(tgm, direction); /* If the request queue was empty then we have to take care of @@ -419,18 +423,23 @@ static void coroutine_fn throttle_group_restart_queue_entry(void *opaque) } static void throttle_group_restart_queue(ThrottleGroupMember *tgm, - ThrottleDirection direction) + ThrottleDirection direction, + bool reset_timer_armed) { Coroutine *co; RestartData *rd = g_new0(RestartData, 1); rd->tgm = tgm; rd->direction = direction; + rd->reset_timer_armed = reset_timer_armed; - /* This function is called when a timer is fired or when - * throttle_group_restart_tgm() is called. Either way, there can + /* If reset_timer_armed is set then this means that this function + * was called when a timer was fired (either from timer_cb() or + * from throttle_group_restart_tgm()). In this case there can * be no timer pending on this tgm at this point */ - assert(!timer_pending(tgm->throttle_timers.timers[direction])); + if (reset_timer_armed) { + assert(!timer_pending(tgm->throttle_timers.timers[direction])); + } qatomic_inc(&tgm->restart_pending); @@ -444,15 +453,50 @@ void throttle_group_restart_tgm(ThrottleGroupMember *tgm) if (tgm->throttle_state) { for (dir = THROTTLE_READ; dir < THROTTLE_MAX; dir++) { - QEMUTimer *t = tgm->throttle_timers.timers[dir]; + QEMUTimer *t; + ThrottleState *ts = tgm->throttle_state; + ThrottleGroup *tg = container_of(ts, ThrottleGroup, ts); + bool reset_timer_armed; + + /* + * This function restarts the tgm's queue immediately. + * This is used for example for callers to drain all requests. + * There are three different scenarios depending on whether + * a timer is armed for this tg and which tgm owns the timer. + */ + + qemu_mutex_lock(&tg->lock); + + t = tgm->throttle_timers.timers[dir]; if (timer_pending(t)) { - /* If there's a pending timer on this tgm, fire it now */ + /* + * Case 1: this tgm has a pending timer. + * We can fire the timer immediately. + */ timer_del(t); - timer_cb(tgm, dir); + reset_timer_armed = true; + } else if (tg->any_timer_armed[dir]) { + /* + * Case 2: another tgm has a pending timer. + * In this case we can still restart the queue but we + * have to leave any_timer_armed untouched so the + * other tgm's timer is not disrupted. + */ + reset_timer_armed = false; } else { - /* Else run the next request from the queue manually */ - throttle_group_restart_queue(tgm, dir); + /* + * Case 3: there is no timer set for this group. + * Here we can simulate a timer that fires immediately, + * so the queue is restarted but no other thread + * can arm a timer in the meantime. + */ + tg->any_timer_armed[dir] = true; + reset_timer_armed = true; } + + qemu_mutex_unlock(&tg->lock); + + throttle_group_restart_queue(tgm, dir, reset_timer_armed); } } } @@ -499,16 +543,13 @@ void throttle_group_get_config(ThrottleGroupMember *tgm, ThrottleConfig *cfg) */ static void timer_cb(ThrottleGroupMember *tgm, ThrottleDirection direction) { - ThrottleState *ts = tgm->throttle_state; - ThrottleGroup *tg = container_of(ts, ThrottleGroup, ts); - - /* The timer has just been fired, so we can update the flag */ - qemu_mutex_lock(&tg->lock); - tg->any_timer_armed[direction] = false; - qemu_mutex_unlock(&tg->lock); - - /* Run the request that was waiting for this timer */ - throttle_group_restart_queue(tgm, direction); + /* + * Run the request that was waiting for this timer. + * tg->any_timer_armed needs to be cleared, but we'll do it later + * when the queue is restarted in order to prevent another thread + * from arming the timer before that. + */ + throttle_group_restart_queue(tgm, direction, true); } static void read_timer_cb(void *opaque) -- 2.53.0 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PULL 2/2] block/mirror: fix assertion failure upon duplicate complete for job using 'replaces' 2026-03-17 13:45 [PULL 0/2] Block layer patches Hanna Czenczek 2026-03-17 13:45 ` [PULL 1/2] throttle-group: Fix race condition in throttle_group_restart_queue() Hanna Czenczek @ 2026-03-17 13:45 ` Hanna Czenczek 2026-03-18 10:12 ` [PULL 0/2] Block layer patches Peter Maydell 2026-03-18 20:35 ` Michael Tokarev 3 siblings, 0 replies; 8+ messages in thread From: Hanna Czenczek @ 2026-03-17 13:45 UTC (permalink / raw) To: qemu-block; +Cc: qemu-devel, Hanna Czenczek, Kevin Wolf From: Fiona Ebner <f.ebner@proxmox.com> If s->replace_blocker was already set by an earlier invocation of mirror_complete(), then there will be an assertion failure when error_setg() is called for it a second time. The bdrv_op_block_all() and bdrv_ref() operations should only be done a single time too. Signed-off-by: Fiona Ebner <f.ebner@proxmox.com> Message-Id: <20260311145717.668492-2-f.ebner@proxmox.com> Reviewed-by: Hanna Czenczek <hreitz@redhat.com> Signed-off-by: Hanna Czenczek <hreitz@redhat.com> --- block/mirror.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/block/mirror.c b/block/mirror.c index fa1d975eb9..2fcded9e93 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -1276,23 +1276,25 @@ static void mirror_complete(Job *job, Error **errp) return; } - /* block all operations on to_replace bs */ - if (s->replaces) { - s->to_replace = bdrv_find_node(s->replaces); - if (!s->to_replace) { - error_setg(errp, "Node name '%s' not found", s->replaces); - return; + if (!s->should_complete) { + /* block all operations on to_replace bs */ + if (s->replaces) { + s->to_replace = bdrv_find_node(s->replaces); + if (!s->to_replace) { + error_setg(errp, "Node name '%s' not found", s->replaces); + return; + } + + /* TODO Translate this into child freeze system. */ + error_setg(&s->replace_blocker, + "block device is in use by block-job-complete"); + bdrv_op_block_all(s->to_replace, s->replace_blocker); + bdrv_ref(s->to_replace); } - /* TODO Translate this into child freeze system. */ - error_setg(&s->replace_blocker, - "block device is in use by block-job-complete"); - bdrv_op_block_all(s->to_replace, s->replace_blocker); - bdrv_ref(s->to_replace); + s->should_complete = true; } - s->should_complete = true; - /* If the job is paused, it will be re-entered when it is resumed */ WITH_JOB_LOCK_GUARD() { if (!job->paused) { -- 2.53.0 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PULL 0/2] Block layer patches 2026-03-17 13:45 [PULL 0/2] Block layer patches Hanna Czenczek 2026-03-17 13:45 ` [PULL 1/2] throttle-group: Fix race condition in throttle_group_restart_queue() Hanna Czenczek 2026-03-17 13:45 ` [PULL 2/2] block/mirror: fix assertion failure upon duplicate complete for job using 'replaces' Hanna Czenczek @ 2026-03-18 10:12 ` Peter Maydell 2026-03-18 20:35 ` Michael Tokarev 3 siblings, 0 replies; 8+ messages in thread From: Peter Maydell @ 2026-03-18 10:12 UTC (permalink / raw) To: Hanna Czenczek; +Cc: qemu-block, qemu-devel, Kevin Wolf On Tue, 17 Mar 2026 at 13:45, Hanna Czenczek <hreitz@redhat.com> wrote: > > The following changes since commit 559919ce54927d59b215a4665eda7ab6118a48aa: > > Merge tag 'pull-trivial-patches' of https://gitlab.com/mjt0k/qemu into staging (2026-03-16 13:07:33 +0000) > > are available in the Git repository at: > > https://gitlab.com/hreitz/qemu.git tags/pull-block-2026-03-17 > > for you to fetch changes up to 9ac85f4cc7995217db8f736733b990d6addcb036: > > block/mirror: fix assertion failure upon duplicate complete for job using 'replaces' (2026-03-17 12:31:54 +0100) > > ---------------------------------------------------------------- > Block layer patches for rc0 > > - Fix race condition in throttle-group code triggering an assertion > failure > - Fix assertion failure in mirror job when issuing job-complete twice > Applied, thanks. Please update the changelog at https://wiki.qemu.org/ChangeLog/11.0 for any user-visible changes. -- PMM ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PULL 0/2] Block layer patches 2026-03-17 13:45 [PULL 0/2] Block layer patches Hanna Czenczek ` (2 preceding siblings ...) 2026-03-18 10:12 ` [PULL 0/2] Block layer patches Peter Maydell @ 2026-03-18 20:35 ` Michael Tokarev 2026-03-19 8:30 ` Hanna Czenczek 3 siblings, 1 reply; 8+ messages in thread From: Michael Tokarev @ 2026-03-18 20:35 UTC (permalink / raw) To: Hanna Czenczek, qemu-block; +Cc: qemu-devel, Kevin Wolf, qemu-stable On 17.03.2026 16:45, Hanna Czenczek wrote: [] > Block layer patches for rc0 > > - Fix race condition in throttle-group code triggering an assertion > failure > - Fix assertion failure in mirror job when issuing job-complete twice > > ---------------------------------------------------------------- > Alberto Garcia (1): > throttle-group: Fix race condition in throttle_group_restart_queue() > > Fiona Ebner (1): > block/mirror: fix assertion failure upon duplicate complete for job > using 'replaces' > > block/mirror.c | 28 ++++++++------- > block/throttle-groups.c | 79 +++++++++++++++++++++++++++++++---------- > 2 files changed, 75 insertions(+), 32 deletions(-) Is it not qemu-stable material? The amount of changes is a bit too high though. I'm picking it up for the currently active stable branches, please let me know if I shouldn't. Thanks, /mjt ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PULL 0/2] Block layer patches 2026-03-18 20:35 ` Michael Tokarev @ 2026-03-19 8:30 ` Hanna Czenczek 0 siblings, 0 replies; 8+ messages in thread From: Hanna Czenczek @ 2026-03-19 8:30 UTC (permalink / raw) To: Michael Tokarev, qemu-block; +Cc: qemu-devel, Kevin Wolf, qemu-stable On 18.03.26 21:35, Michael Tokarev wrote: > On 17.03.2026 16:45, Hanna Czenczek wrote: > [] >> Block layer patches for rc0 >> >> - Fix race condition in throttle-group code triggering an assertion >> failure >> - Fix assertion failure in mirror job when issuing job-complete twice >> >> ---------------------------------------------------------------- >> Alberto Garcia (1): >> throttle-group: Fix race condition in throttle_group_restart_queue() >> >> Fiona Ebner (1): >> block/mirror: fix assertion failure upon duplicate complete for job >> using 'replaces' >> >> block/mirror.c | 28 ++++++++------- >> block/throttle-groups.c | 79 +++++++++++++++++++++++++++++++---------- >> 2 files changed, 75 insertions(+), 32 deletions(-) > > Is it not qemu-stable material? > The amount of changes is a bit too high though. The mirror one should be simple enough, the throttle-groups one… I think it still is good. > I'm picking it up for the currently active stable branches, please > let me know if I shouldn't. Yes, thanks! Hanna ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PULL 0/2] Block layer patches
@ 2025-12-15 17:25 Kevin Wolf
2025-12-16 15:37 ` Richard Henderson
0 siblings, 1 reply; 8+ messages in thread
From: Kevin Wolf @ 2025-12-15 17:25 UTC (permalink / raw)
To: qemu-block; +Cc: kwolf, richard.henderson, qemu-devel
The following changes since commit 9c23f2a7b0b45277693a14074b1aaa827eecdb92:
Update version for v10.2.0-rc3 release (2025-12-09 16:44:49 -0600)
are available in the Git repository at:
https://repo.or.cz/qemu/kevin.git tags/for-upstream
for you to fetch changes up to 307bc43095b8ab1765fd66c26003d5da06681c05:
block: Fix BDS use after free during shutdown (2025-12-15 17:31:08 +0100)
----------------------------------------------------------------
Block layer patches
- Fix crash due to BDS use after free during shutdown (in particular
while migration is running)
- iotests: Fix a typo that made a check to prevent overwriting a file
ineffective
----------------------------------------------------------------
Kevin Wolf (1):
block: Fix BDS use after free during shutdown
Thomas Huth (1):
tests/qemu-iotests: Fix check for existing file in _require_disk_usage()
blockdev.c | 1 +
tests/qemu-iotests/common.rc | 2 +-
2 files changed, 2 insertions(+), 1 deletion(-)
^ permalink raw reply [flat|nested] 8+ messages in thread* Re: [PULL 0/2] Block layer patches 2025-12-15 17:25 Kevin Wolf @ 2025-12-16 15:37 ` Richard Henderson 0 siblings, 0 replies; 8+ messages in thread From: Richard Henderson @ 2025-12-16 15:37 UTC (permalink / raw) To: Kevin Wolf, qemu-block; +Cc: qemu-devel On 12/16/25 04:25, Kevin Wolf wrote: > The following changes since commit 9c23f2a7b0b45277693a14074b1aaa827eecdb92: > > Update version for v10.2.0-rc3 release (2025-12-09 16:44:49 -0600) > > are available in the Git repository at: > > https://repo.or.cz/qemu/kevin.git tags/for-upstream > > for you to fetch changes up to 307bc43095b8ab1765fd66c26003d5da06681c05: > > block: Fix BDS use after free during shutdown (2025-12-15 17:31:08 +0100) > > ---------------------------------------------------------------- > Block layer patches > > - Fix crash due to BDS use after free during shutdown (in particular > while migration is running) > - iotests: Fix a typo that made a check to prevent overwriting a file > ineffective Applied, thanks. Please update https://wiki.qemu.org/ChangeLog/10.2 as appropriate. r~ ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2026-03-19 8:30 UTC | newest] Thread overview: 8+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-03-17 13:45 [PULL 0/2] Block layer patches Hanna Czenczek 2026-03-17 13:45 ` [PULL 1/2] throttle-group: Fix race condition in throttle_group_restart_queue() Hanna Czenczek 2026-03-17 13:45 ` [PULL 2/2] block/mirror: fix assertion failure upon duplicate complete for job using 'replaces' Hanna Czenczek 2026-03-18 10:12 ` [PULL 0/2] Block layer patches Peter Maydell 2026-03-18 20:35 ` Michael Tokarev 2026-03-19 8:30 ` Hanna Czenczek -- strict thread matches above, loose matches on Subject: below -- 2025-12-15 17:25 Kevin Wolf 2025-12-16 15:37 ` Richard Henderson
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.