From: Antonio Alvarez Feijoo <antonio.feijoo@suse.com>
To: dm-devel@lists.linux.dev
Cc: Benjamin Marzinski <bmarzins@redhat.com>,
Martin Wilck <mwilck@suse.com>,
Antonio Alvarez Feijoo <antonio.feijoo@suse.com>
Subject: [PATCH] multipath.rules.in: fix race in unit cancel-multipath-wait-$kernel
Date: Fri, 28 Aug 2026 11:25:48 +0200 [thread overview]
Message-ID: <20260828092548.34637-1-antonio.feijoo@suse.com> (raw)
The transient unit cancel-multipath-wait-$kernel creates a timer and
service with "Conflicts=initrd-cleanup.service":
- sda: /usr/lib/udev/rules.d/56-multipath.rules ...
--on-active=1.000000 ...
- sda: ... 'Running timer as unit: cancel-multipath-wait-sda.timer'
- sda: ... 'Will run service as unit:
cancel-multipath-wait-sda.service'
This introduces a race not always reproducible: there is a 1 second
window where this transient unit can start after
initrd-cleanup.service/start is enqueued but is still held back. When
that happens, starting cancel-multipath-wait-$kernel.service pulls in
a stop job for initrd-cleanup.service and the queued start job is
cancelled, the initrd is left with an empty job queue and hangs
forever, before switch-root:
- initrd-parse-etc.service: Triggering OnSuccess= dependencies.
- initrd-cleanup.service: Installed new job
initrd-cleanup.service/start as 115
- initrd-cleanup.service: starting held back, waiting for:
dracut-pre-pivot.service
- initrd-cleanup.service: Job 115 initrd-cleanup.service/start
finished, result=canceled
- initrd-cleanup.service: Installed new job
initrd-cleanup.service/stop as 133
- initrd-cleanup.service: Job 133 initrd-cleanup.service/stop
finished, result=done
"Conflicts=" is symmetric: if a unit has a "Conflicts=" requirement
on a set of other units, then starting it will stop all of them and
starting any of them will stop it. This is safe against
shutdown.target, whose jobs are enqueued irreversibly: a unit
starting during shutdown fails to start rather than cancelling the
shutdown. It is not safe against initrd-cleanup.service, whose start
job is an ordinary job enqueued by initrd-parse-etc.service via
"OnSuccess=".
Ordering "Before=initrd-cleanup.service" is enough and is not
destructive: a trigger already in flight completes before cleanup
runs, and a unit with no job does not delay it. Tearing the
transient units down before switch-root is already handled by the
isolate to initrd-switch-root.target, which stops everything that
is not "IgnoreOnIsolate=yes".
Signed-off-by: Antonio Alvarez Feijoo <antonio.feijoo@suse.com>
---
multipath/multipath.rules.in | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)
diff --git a/multipath/multipath.rules.in b/multipath/multipath.rules.in
index 2ac1972f..7b605dd4 100644
--- a/multipath/multipath.rules.in
+++ b/multipath/multipath.rules.in
@@ -68,8 +68,18 @@ ENV{.SAVED_FM_WAIT_UNTIL}=="?*", GOTO="pretend_mpath"
# the --on-active timeout.
#
# We must trigger an "add" event because LVM2 will only act on those.
-
-RUN+="@SYSDIR_BIN@/systemd-run --unit=cancel-multipath-wait-$kernel --description 'cancel waiting for multipath siblings of $kernel' --no-block --timer-property DefaultDependencies=no --timer-property Conflicts=shutdown.target --timer-property Before=shutdown.target --timer-property Conflicts=initrd-cleanup.service --timer-property Before=initrd-cleanup.service --timer-property AccuracySec=500ms --property DefaultDependencies=no --property Conflicts=shutdown.target --property Before=shutdown.target --property Conflicts=initrd-cleanup.service --property Before=initrd-cleanup.service --on-active=$env{FIND_MULTIPATHS_WAIT_UNTIL} @SYSDIR_BIN@/udevadm trigger --action=add $sys$devpath"
+#
+# These units are ordered Before=initrd-cleanup.service so that a trigger that
+# is already in flight completes before the initrd switches root. They must
+# *not* use Conflicts=initrd-cleanup.service: unlike shutdown.target, whose
+# jobs are enqueued irreversibly, initrd-cleanup.service/start is a plain job
+# enqueued by initrd-parse-etc.service via OnSuccess=. Starting a unit that
+# conflicts with it therefore cancels that job instead of failing to start,
+# and OnSuccess= is never retried, so the initrd would hang forever with an
+# empty job queue. Stopping these units before switch-root is already
+# guaranteed by the isolate to initrd-switch-root.target.
+
+RUN+="@SYSDIR_BIN@/systemd-run --unit=cancel-multipath-wait-$kernel --description 'cancel waiting for multipath siblings of $kernel' --no-block --timer-property DefaultDependencies=no --timer-property Conflicts=shutdown.target --timer-property Before=shutdown.target --timer-property Before=initrd-cleanup.service --timer-property AccuracySec=500ms --property DefaultDependencies=no --property Conflicts=shutdown.target --property Before=shutdown.target --property Before=initrd-cleanup.service --on-active=$env{FIND_MULTIPATHS_WAIT_UNTIL} @SYSDIR_BIN@/udevadm trigger --action=add $sys$devpath"
LABEL="pretend_mpath"
ENV{DM_MULTIPATH_DEVICE_PATH}="1"
--
2.51.0
next reply other threads:[~2026-08-28 9:26 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-28 9:25 Antonio Alvarez Feijoo [this message]
2026-08-28 13:57 ` [PATCH] multipath.rules.in: fix race in unit cancel-multipath-wait-$kernel Martin Wilck
2026-08-28 18:00 ` Benjamin Marzinski
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260828092548.34637-1-antonio.feijoo@suse.com \
--to=antonio.feijoo@suse.com \
--cc=bmarzins@redhat.com \
--cc=dm-devel@lists.linux.dev \
--cc=mwilck@suse.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.