[systemd-devel] Safe handling of root filesystem on shutdown
dsd at laptop.org
Wed Apr 11 09:33:50 PDT 2012
On Wed, Apr 11, 2012 at 9:40 AM, Lennart Poettering
<lennart at poettering.net> wrote:
> So on shutdown after stopping all services we execute systemd-shutdown
> as PID 1 replacing the normal systemd process. This is useful to drop
> all references to files on disk, so that we can remount the disk r/o
> even on upgrades.
> systemd-shutdown is basically a single loop that tries to
> umount/read-only mount all file systems it finds as long as this changes
> the list of active mounts. This code also disables all swaps and detachs
> DM/loop devices in the same loop.
Thanks as always for the fast and good explanation! With that pointer,
I found the problem, see below.
>> We do have a bit of a strange fs-layout, where our root fs is kept
>> inside /versions/pristine/X on the root partition. The initramfs takes
>> care of this with some bind-mount and chroot tricks so that it looks
>> 'normal' afterwards, but maybe something along these lines is
>> confusing systemd.
> chroot()? Meh, you should not use chroot for these kinds of things...
Actually, we don't use chroot directly. Here's what happens:
dracut mounts the root fs at /sysroot, then in a pre-pivot dracut
trigger OLPC does:
mount --bind /sysroot/versions/run/6 /vsysroot
Dracut then goes ahead and performs switch_root on $NEWROOT to pivot
onto the real system.
(Happy to hear advice on a nicer way to do this)
When the system finishes booting, /proc/self/mountinfo looks like:
Now, in systemd-shutdown we reach mount_points_list_get() in umount.c,
/* If we encounter a bind mount, don't try to remount
* the source dir too early */
skip_ro = !streq(root, "/");
Hence skip_ro gets set to 1 for our /
mount_points_list_remount_read_only() then ignores the / mount and
leaves it as RW during shutdown.
I don't really understand the reasoning for the above behaviour of
bind mounts. Would it be acceptable to special-case this condition if
the path in question is / so that skip_ro does not get set? Or are
there other options available?
More information about the systemd-devel