generator: order cryptsetup/verity/integrity after systemd-udevd
During soft-reboot teardown, systemd-cryptsetup@.service's ExecStop runs
libcryptsetup's crypt_deactivate(), which issues DM_REMOVE with a udev
cookie and blocks in dm_udev_wait() until 95-dm-notify.rules decrements
the cookie semaphore via "dmsetup udevcomplete $env{DM_COOKIE}".
The generated cryptsetup unit had only After=systemd-udevd-kernel.socket,
not After=systemd-udevd.service. The .socket has IgnoreOnIsolate=yes and
is not stopped during soft-reboot, so it provides no ordering at all for
the service teardown. Meanwhile systemd-udevd.service has
Conflicts=soft-reboot.target (added in 0d1819e791) and stops as soon as
soft-reboot.target starts, with no ordering relative to cryptsetup's
ExecStop.
Once udevd's device monitor event source is disabled in manager_exit(),
pending DM_REMOVE uevents are no longer processed and the cookie
semaphore stays at 1 forever, blocking soft-reboot at "Stopping
Cryptography Setup..." until JobTimeoutSec=30min on soft-reboot.target
fires.
Add systemd-udevd.service to the After= ordering of the generated
cryptsetup, veritysetup and integritysetup units. By systemd's job
ordering rules (job_compare() in src/core/job.c), when two units are
both being stopped and one has After= the other, the After= unit is
stopped first. So with cryptsetup@*.service After=systemd-udevd.service,
cryptsetup stops first (cookie acknowledged by the still-live udevd),
then udevd stops.
Putting After=umount.target on systemd-udevd.service does not work: at
soft-reboot, udevd's stop job runs concurrently with umount.target's
start job, and JOB_STOP unconditionally precedes JOB_START in the
transaction (see src/core/job.c:1742). The ordering has to be expressed
between two stop jobs, which is what putting After=systemd-udevd.service
on the dm consumers achieves.
Fixes: #40298
This commit is contained in:
committed by
Lennart Poettering
parent
e652ec1099
commit
66a0bdad4f
@@ -80,7 +80,11 @@ static int create_disk(
|
||||
"SourcePath=%s\n"
|
||||
"DefaultDependencies=no\n"
|
||||
"IgnoreOnIsolate=true\n"
|
||||
"After=integritysetup-pre.target systemd-udevd-kernel.socket\n"
|
||||
/* The systemd-udevd.service ordering is mostly about shutdown, not startup: on stop the dm
|
||||
* device is detached via an ioctl carrying a udev cookie that blocks in dm_udev_wait() until
|
||||
* udev releases it (95-dm-notify.rules). Stopping before udevd keeps it around to service the
|
||||
* cookie; otherwise during soft-reboot/shutdown udevd may exit first and the detach hangs. */
|
||||
"After=integritysetup-pre.target systemd-udevd-kernel.socket systemd-udevd.service\n"
|
||||
"Before=blockdev@dev-mapper-%%i.target\n"
|
||||
"Wants=blockdev@dev-mapper-%%i.target\n"
|
||||
"Conflicts=umount.target\n"
|
||||
|
||||
+11
-2
@@ -921,7 +921,12 @@ int generator_write_cryptsetup_unit_section(FILE *f, const char *source) {
|
||||
fprintf(f,
|
||||
"\n"
|
||||
"DefaultDependencies=no\n"
|
||||
"After=cryptsetup-pre.target systemd-udevd-kernel.socket systemd-tpm2-setup-early.service\n"
|
||||
/* The ordering against systemd-udevd.service is mostly about shutdown, not startup: on stop
|
||||
* the device is detached via a device-mapper ioctl that carries a udev cookie, and we block in
|
||||
* dm_udev_wait() until udev releases it (see 95-dm-notify.rules). Ordering After= it means we
|
||||
* are stopped first, while udevd is still around to service that cookie; otherwise during
|
||||
* soft-reboot/shutdown udevd may exit first and the detach hangs until the job timeout. */
|
||||
"After=cryptsetup-pre.target systemd-udevd-kernel.socket systemd-udevd.service systemd-tpm2-setup-early.service\n"
|
||||
"Before=blockdev@dev-mapper-%%i.target\n"
|
||||
"Wants=blockdev@dev-mapper-%%i.target\n"
|
||||
"IgnoreOnIsolate=true\n");
|
||||
@@ -993,7 +998,11 @@ int generator_write_veritysetup_unit_section(FILE *f, const char *source) {
|
||||
fprintf(f,
|
||||
"DefaultDependencies=no\n"
|
||||
"IgnoreOnIsolate=true\n"
|
||||
"After=veritysetup-pre.target systemd-udevd-kernel.socket\n"
|
||||
/* The systemd-udevd.service ordering is mostly about shutdown, not startup: on stop the dm
|
||||
* device is detached via an ioctl carrying a udev cookie that blocks in dm_udev_wait() until
|
||||
* udev releases it (95-dm-notify.rules). Stopping before udevd keeps it around to service the
|
||||
* cookie; otherwise during soft-reboot/shutdown udevd may exit first and the detach hangs. */
|
||||
"After=veritysetup-pre.target systemd-udevd-kernel.socket systemd-udevd.service\n"
|
||||
"Before=blockdev@dev-mapper-%%i.target\n"
|
||||
"Wants=blockdev@dev-mapper-%%i.target\n");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user