Ideas for completing WIP "add unit to switch back to initrd at shutdown" etc

Alan Jenkins alan.christopher.jenkins at gmail.com
Tue Jun 12 10:50:01 UTC 2018


Hi, Ray and anyone else.

I see the WIP commits which included "add unit to switch back to initrd 
at shutdown" etc have been reverted for now.  I'm still interested in a 
resolution to the unclean unmounts triggered by plymouth.  Or triggered 
by systemd not supporting plymouth's behaviour... whichever one wants to 
blame.[1]

So I started writing an email, and now I think I understand what it 
would take to finish the WIP, and cover all cases.  This is the 
alternative to what I think was Lennart's suggestion, of plymouth 
implementing the equivalent of `systemctl daemon-reexec` (serializing 
and de-serializing any needed process state).  Of course I'd be 
interested to hear why the WIPs were reverted.  Did the reexec approach 
come to seem more promising? Or was the WIP just taking too long to finish?


* I was unhappy with the WIP originally, because I didn't want my system 
to be left with a frozen graphic (kept up by plymouth-drm-escrow).  I 
would want the option to see the text console messages, like I can with 
the escape key in current plymouth.  But I withdraw this objection: I 
think the design still allows this feature.  It seems straightforward, 
particularly if drm-escrow doesn't bother to implement switching *back* 
to graphics mode :).

* We can have plymouth-switch-root-shutdown.service ordered 
`Before=final.target` and `After=shutdown.target umount.target` in the 
shutdown sequence. That would allow plymouth to animate during the 
shutdown of almost all services.

* When starting plymouthd outside the initramfs, we can allow plymouthd 
to be killed by `systemd-shutdown`.  By not marking it exempt, we would 
make the system more robust.  (E.g. systemd-shutdown may be triggered 
after the default 30 minute timeout on reboot.target, but while 
plymouthd is still running).

   It's a bit hairy to auto-detect whether we're inside the initramfs, 
in case we can't rely on the systemd suggestion of checking for 
/etc/initrd-release.  I think the alternative, is to define that 
plymouth-switch-root.service is the event that causes plymouthd to 
exempt itself from being killed by systemd.

* On systems which *don't* switch to a shutdown initrd, plymouth still 
wants to show the splash until the very end.  This sounds like we have 
two different cases to handle, but we can simply unify them.  If we get 
to the point in the shutdown sequence where plymouth wants to switch to 
the initrd, but we don't see any `/run/initramfs/shutdown`, then exec 
the drm-escrow program from the rootfs instead of from the initrd.

   Note, it is not acceptible to handle the one case by exempting 
plymouthd from being killed by systemd.  1) Current plymouthd keeps 
/var/log/boot.log open for writing.  2) In case plymouthd is upgraded, 
the running process pins a deleted file, and remounting root read-only 
fails with EBUSY.  This is because the deleted file would need to be 
de-allocated (hence writing to the FS) when plymouthd finished.

   In either case, if plymouthd fails to launch drm-escrow, it must 
simply shut down.

* Plymouth-switch-root-shutdown.service will be synchronous.  I.e. it 
will include `plymouth --wait` or equivalent after it signals plymouthd 
to exec drm-escrow.

* We don't need to worry that this configuration doesn't support 
plymouth on X, because the systemd killing sprees would be killing X anyway.

and then

* These still leave plymouth breaching the letter and spirit of the 
systemd RootStorageDaemons feature.  plymouthd started from the 
initramfs asks not to be killed by systemd-shutdown, but it opens files 
on the rootfs which systemd-shutdown needs to unmount.  And in principle 
systemd-shutdown may happen at literally any time, e.g. by the user 
pressing c-a-d 7x in quick succession.

   I think plymouthd can fix this fairly simply.  When plymouthd needs 
to read from or write to the filesystem, it can fork a process, 
equivalent to `popen("cat >\"$FILE\"")`.  (Let's not use popen(), but it 
shows the idea).  The child process can arrange to be killable by 
systemd-shutdown, before it touches the FS.  To log specific errors when 
opening a file, the child process can write to /dev/kmsg.

* This still leaves a potential for plymouth to pin /var/log when 
systemd wants to cleanly unmount /var.  E.g. if you press ctrl+alt+del 
during startup and after the logfile open, systemd will try to 
de-activate var.mount.  plymouth-read-write.service needs to gain 
`RemainAfterExit=yes` and `ExecStop=-/usr/bin/plymouth update-root-fs 
--no-write`. plymouthd will respond to this new command by closing the 
open log file.  (It will close the pipe FD, and then wait for the child 
process to exit.  See previous point).

Regards
Alan

[1] "dracut fails to disassemble device-mapper devices" 
https://bugzilla.redhat.com/show_bug.cgi?id=1575376  This was 
simultaneously reassigned to plymouth, and gained a dracut workaround. 
So I think it's a bit messy to read, sorry.



More information about the plymouth mailing list