Bind mounts with systemd and non-fstab filesystems
Under normal circumstances the way you deal with Linux bind mounts on a systemd based system is the same as always: you
put them in /etc/fstab and systemd makes everything work just
like normal. If you can deal with your bind mounts this way, I
recommend that you do it and keep your life simple. But sometimes
life is not simple.
Suppose, not entirely hypothetically, that
you are dealing with base filesystems that aren't represented in
/etc/fstab for one reason or another; instead they appear through
other mechanisms. For example, perhaps they appear when you import a
ZFS pool. You want to use these filesystems as the source of bind
mounts.
The first thing that doesn't work is leaving your bind mounts in
/etc/fstab. There is no way to tell systemd to not create them
until something else happens (eg your zfs-mount.service systemd
unit finishes or their source directory appears), so this is basically
never going to do the right thing. If you get bind mounts at all
they are almost certainly not going to be bound to what you want.
At this point you might be tempted to think 'oh, systemd makes
/etc/fstab mounts into magic <name>.mount systemd units, I can
just put files in /etc/systemd/system to add some extra dependencies
to those magic units'. Sadly this doesn't work; the moment you have
a real <name>.mount unit file it entirely replaces the information
from /etc/fstab and systemd will tell you that your <name>.mount
file is invalid because it doesn't specify what to mount.
In short, you need real .mount units for your bind mounts. You also need to force the ordering, and
here again we run into something that would be nice but doesn't
work. If you run 'systemctl list-units -t mount', you will see
that there are units for all of your additional non-fstab mounts.
It's tempting to make your bind mount unit depend on an appropriate
mount unit for its source filesystem, eg if you have a bind mount
from /archive/something you'd have it depend on archive.mount.
Unfortunately this doesn't work reliably because systemd doesn't
actually know about these synthetic mount units before the mount
appears. Instead you can only depend on whatever .service unit
actually does the mounting, such as zfs-mount.service.
(In an extreme situation you could create a service unit that just
used a script to wait for the mounts to come up. With a Type=oneshot
service unit, systemd won't consider the service successful until
the script exits.)
The maximally paranoid set of dependencies and guards is something like this:
[Unit] After=zfs-mount.service Requires=zfs-mount.service RequiresMountsFor=/var ConditionPathIsDirectory=/local/var/local
(This is for a bind mount from /local/var/local to /var/local.)
We can't use a RequiresMountsFor on /local/var, because as far
as systemd is concerned it's on the root filesystem and so the
dependency would be satisfied almost immediately. I don't think the
Condition will cause systemd to wait for /local/var/local to
appear, just stop the bind mount from trying to be done if ZFS
mounts happened but they didn't managed to mount a /local/var
for some reason (eg a broken or missing ZFS pool).
(Since my /var is actually on the root filesystem, the
RequiresMountsFor is likely gilding the lily; I don't think there's
any situation where this unit can even be considered before the
root filesystem is mounted. But if it's a separate filesystem you
definitely want this and so it's probably a good habit in general.)
I haven't tested using local-var.mount in just the Requires
here but I'd expect it to fail for the same reason that it definitely
doesn't work reliably in an After. This is kind of a pity, but
there you go and the Condition is probably good enough.
(If you don't want to make a bunch of .mount files, one for each
mount, you could make a single .service unit that has all of the
necessary dependencies and runs appropriate commands to do the bind
mounting (either directly or by running a script). If you do this,
don't forget to have ExecStop stuff to also do the unmounts.)
Sidebar: the likely non-masochistic way to do this for ZFS on Linux
If I was less stubborn, I would have set all of my ZFS filesystems
to have 'mountpoint=legacy' and then explicitly mentioned and
mounted them in /etc/fstab. Assuming that it worked (ie that
systemd didn't try to do the mounts before the ZFS pool came up),
this would have let me keep the bind mounts in fstab too and
avoided this whole mess.
Comments on this page:
|
|