docs/MOUNT_REQUIREMENTS: describe nested mounts more carefully

I was looking into a question posed in one of the Fedora discussion threads:
is it OK for a package to assume that files in different directories under /usr
are always on the same mount point? rpmlint emits a warning if a package has
files that are hardlinked between directories, i.e. rpmlint thinks that this
is not the case. But in practice, our systems are like this and our tooling
generally doesn't expect a part of /usr to be separated out. I looked at the
MOUNT_REQUIREMENTS document, but it doesn't answer this question clearly.
It was clearly written with the assumption that e.g. "/usr/" or "/var/" are one
mount point, so when it is "mounted", all of it is available. But the document
also talks about submounts being pulled in through requirements on specific
units, which requires some mounts not to be mounted all at once, so the reader
is left without any direct answer to this question.

This rewrite makes the following changes:
- rename "generally three categories of requirements" to
  "three general categories of mount points" because we're categorizing
  mount points, not requirements.
- always repeat the category name in further mentions,
  e.g. "2/early" instead of just "2" so the reader doesn't have to jump
  back to the table when reading.
- mention that it is OK for a mount point to be not split out
- say that submount which is "conceptually separate" may be mounted
  later.
- say "ephemeral system" instead of "stateless system" and split out
  the description of those systems into a separate paragraph and clearly
  state that they are an exception that skips the requirements listed in
  this document.
- be consistent in specifying the boundary before which each category must
  have been mounted. Previously, cat. 1 was described as "before transisition"
  and cat. 2 was described as "during early boot", which created the additional
  problem that later we needed to contradict this saying that "must be mounted
  during early boot" doesn't actually mean that and this can be done ealier.
  If we say "before end of early boot", we avoid this awkwardness.
This commit is contained in:
Zbigniew Jędrzejewski-Szmek
2025-10-22 15:35:09 +02:00
parent e39cde9585
commit 3e94ae6f1e

View File

@@ -7,51 +7,69 @@ SPDX-License-Identifier: LGPL-2.1-or-later
# Mount Point Availability Requirements
systemd makes various requirements on the time during boot where various parts
of the Linux file system hierarchy must be available and must be mounted. If
the file systems backing these mounts are located on external or remote media,
that require special drivers, infrastructure or networking to be set up, then
this implies that this functionality must be started and running at that point
already.
This document describes the requirements placed by systemd
on the time when various parts of the file system hierarchy
must be available and mounted during boot.
Generally, there are three categories of requirements:
If the file system backing a mount point is located on external or remote media
that require special drivers, infrastructure or networking to be set up,
then this implies that this functionality must be started and running
at the point in the boot sequence when that mount point is required.
There are three general categories of mount points:
1. 🌥️ *initrd*: File system mounts that must be established before the OS
transitions into the root file system. (i.e. that must be stablished from
transitions into the root file system. (I.e., must be mounted in
the initrd before the initrd→host transition takes place.)
2. 🌤️ *early*: File system mounts that must be established during early boot,
after the initrd→host transition took place, but before regular services are
started. (i.e. before `local-fs.target` is reached.)
2. 🌤️ *early*: File system mounts that must be established
before the end of "early boot", i.e. before `local-fs.target` is reached.
All services that do not explicitly opt-out of the dependency
are ordered after that point.
3. ☀️ *regular*: File system mounts that can be mounted at any time during the
boot process but which specific, individual services might require to be
established at the point they are started. (i.e. these mounts are typically
ordered before `remote-fs.target`.)
3. ☀️ *regular*: File system mounts that can be mounted later.
Individual services might pull in specific mount points and be ordered after them.
Mount points that require network to be available
are typically ordered before `remote-fs.target`.
Those mount points may be established as automount points.
Of course, mounts that fall into category 3 can also be mounted during the
initrd or in early boot. And those from category 2 can also be mounted already
from the initrd.
Mounts in the later categories may be established earlier,
i.e. mounts that fall into category 2/early may also be mounted in the initrd,
and mounts in category 3/regular may also be mounted in the initrd or early boot.
Since mount points that are lower in the hierarchy are mounted later,
if a mount point is *not* split out,
but a given subtree is part of the parent mount,
the requirements for that subtree are trivially satisfied by the parent.
A "mount point" in this document means the whole subtree of the hierachy,
until a mountpoint lower in the hierarchy which is conceptually separate.
For example, on a system with a custom mount point located below `/var/spool/`,
most of `/var/` would be in category 2/early,
but the additional mount would be in category 3/regular.
Conversly, if some part of `/usr/` that is normally part of that subtree
was split out to a separate mount,
this mount point would fall into category 1/initrd
and configuration would need to be provided for it to be mounted in the initrd.
Here's a table with relevant mounts and to which category they belong:
| *Mount* | *Category* |
|---------------|------------|
| `/` (root fs) | 1 |
| `/usr/` | 1 |
| `/etc/` | 1 |
| `/var/` | 2 |
| `/var/tmp/` | 2 |
| `/tmp/` | 2 |
| `/home/` | 3 |
| `/srv/` | 3 |
| XBOOTLDR | 3 |
| ESP | 3 |
| `/` (root fs) | 1/initrd |
| `/usr/` | 1/initrd |
| `/etc/` | 1/initrd |
| `/var/` | 2/early |
| `/var/tmp/` | 2/early |
| `/tmp/` | 2/early |
| `/home/` | 3/regular |
| `/srv/` | 3/regular |
| XBOOTLDR | 3/regular |
| ESP | 3/regular |
Or in other words: the root file system (obviously…), `/usr/` and `/etc/` (if
these are split off) must be mounted at the moment the initrd transitions into
the host. Then, `/var/` (with `/var/tmp/`) and `/tmp/` (if split off) must be
mounted, before the host reaches `local-fs.target` (and then `basic.target`),
mounted before the host reaches `local-fs.target` (and then `basic.target`),
after which any remaining mounts may be established.
If mounts such as `/var/` are not mounted during early boot (or from the
@@ -63,18 +81,19 @@ Also note that the whole of `/var/` (including `/var/tmp/`), and `/tmp/` must
be *writable* at the moment indicated above. It's OK if they are mounted
read-only at an earlier time as long as they are remounted writable by the
indicated point in time. Systems where these three hierarchies remain read-only
during regular operation are not supported by `systemd`. (Note that for
stateless systems it is absolutely OK and supported to mount an empty `tmpfs`
there at boot, `systemd` will know how to populate the tree as necessary.)
during regular operation are not supported by `systemd`.
An exception to the rules described above are ephemeral systems,
where the root file system is initially an empty `tmpfs` mount point
and parts of the file system hierarchy are populated by systemd during early boot.
If you intend to use network-backed mounts (NFS, SMB, iSCSI, NVME-TCP and
similar, including anything you add the `_netdev` pseudo mount option to) for
any of the mounts from category 1 or 2, make sure to use a network managing
implementation that is capable of running from the initrd/during early
boot. [`systemd-networkd(8)`](https://www.freedesktop.org/software/systemd/man/latest/systemd-networkd.html)
any of the mounts from category 1/initrd or 2/early,
make sure to use a network manager that is capable of running in the initrd or early boot.
[`systemd-networkd(8)`](https://www.freedesktop.org/software/systemd/man/latest/systemd-networkd.html)
for example works well in such scenarios.
Note that
[`systemd-homed.service(8)`](https://www.freedesktop.org/software/systemd/man/latest/systemd-homed.html)
(which is a regular service, i.e. runs after `basic.target`) requires `/home/`
to be mounted.
is an example of a regular service from category 3/regular.
It runs after `basic.target` and requires `/home/` to be mounted.