zfs/man/man7/dracut.zfs.7

279 lines
8.7 KiB
Groff
Raw Normal View History

.\" SPDX-License-Identifier: 0BSD
.\"
contrib: dracut: fix race with root=zfs:dset when necessities required This had always worked in my testing, but a user on hardware reported this to happen 100%, and I reproduced it once with cold VM host caches. dracut-zfs-generator runs as a systemd generator, i.e. at Some Relatively Early Time; if root= is a fixed dataset, it tries to "solve [necessities] statically at generation time". If by that point zfs-import.target hasn't popped (because the import is taking a non-negligible amount of time for whatever reason), it'll see no children for the root datase, and as such generate no mounts. This has never had any right to work. No-one caught this earlier because it's just that much more convenient to have root=zfs:AUTO, which orders itself properly. To fix this, always run zfs-nonroot-necessities.service; this additionally simplifies the implementation by: * making BOOTFS from zfs-env-bootfs.service be the real, canonical, root dataset name, not just "whatever the first bootfs is", and only set it if we're ZFS-booting * zfs-{rollback,snapshot}-bootfs.service can use this instead of re-implementing it * having zfs-env-bootfs.service also set BOOTFSFLAGS * this means the sysroot.mount drop-in can be fixed text * zfs-nonroot-necessities.service can also be constant and always enabled, because it's conditioned on BOOTFS being set There is no longer any code generated at run-time (the sysroot.mount drop-in is an unavoidable gratuitous cp). The flow of BOOTFS{,FLAGS} from zfs-env-bootfs.service to sysroot.mount is not noted explicitly in dracut.zfs(7), because (a) at some point it's just visual noise and (b) it's already ordered via d-p-m.s from z-i.t. Backport-of: 3399a30ee02d0d31ba2d43d0ce0a2fd90d5c575d Signed-off-by: Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz>
2023-03-28 20:49:50 +00:00
.Dd March 28, 2023
.Dt DRACUT.ZFS 7
.Os
.
.Sh NAME
.Nm dracut.zfs
.Nd overview of ZFS dracut hooks
.
.Sh SYNOPSIS
.Bd -literal -compact
parse-zfs.sh \(-> dracut-cmdline.service
| \(da
| …
| \(da
\e\(em\(em\(em\(em\(em\(em\(em\(em\(-> dracut-initqueue.service
| zfs-import-opts.sh
zfs-load-module.service \(da | |
| | sysinit.target \(da |
\(da | | zfs-import-scan.service \(da
zfs-import-scan.service \(da \(da | zfs-import-cache.service
| zfs-import-cache.service basic.target | |
\e__________________| | \(da \(da
\(da | zfs-load-key.sh
zfs-env-bootfs.service | |
\(da \(da \(da
zfs-import.target \(-> dracut-pre-mount.service
| \(ua |
| dracut-zfs-generator |
contrib: dracut: fix race with root=zfs:dset when necessities required This had always worked in my testing, but a user on hardware reported this to happen 100%, and I reproduced it once with cold VM host caches. dracut-zfs-generator runs as a systemd generator, i.e. at Some Relatively Early Time; if root= is a fixed dataset, it tries to "solve [necessities] statically at generation time". If by that point zfs-import.target hasn't popped (because the import is taking a non-negligible amount of time for whatever reason), it'll see no children for the root datase, and as such generate no mounts. This has never had any right to work. No-one caught this earlier because it's just that much more convenient to have root=zfs:AUTO, which orders itself properly. To fix this, always run zfs-nonroot-necessities.service; this additionally simplifies the implementation by: * making BOOTFS from zfs-env-bootfs.service be the real, canonical, root dataset name, not just "whatever the first bootfs is", and only set it if we're ZFS-booting * zfs-{rollback,snapshot}-bootfs.service can use this instead of re-implementing it * having zfs-env-bootfs.service also set BOOTFSFLAGS * this means the sysroot.mount drop-in can be fixed text * zfs-nonroot-necessities.service can also be constant and always enabled, because it's conditioned on BOOTFS being set There is no longer any code generated at run-time (the sysroot.mount drop-in is an unavoidable gratuitous cp). The flow of BOOTFS{,FLAGS} from zfs-env-bootfs.service to sysroot.mount is not noted explicitly in dracut.zfs(7), because (a) at some point it's just visual noise and (b) it's already ordered via d-p-m.s from z-i.t. Backport-of: 3399a30ee02d0d31ba2d43d0ce0a2fd90d5c575d Signed-off-by: Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz>
2023-03-28 20:49:50 +00:00
| _____________________/|
|/ \(da
contrib: dracut: fix race with root=zfs:dset when necessities required This had always worked in my testing, but a user on hardware reported this to happen 100%, and I reproduced it once with cold VM host caches. dracut-zfs-generator runs as a systemd generator, i.e. at Some Relatively Early Time; if root= is a fixed dataset, it tries to "solve [necessities] statically at generation time". If by that point zfs-import.target hasn't popped (because the import is taking a non-negligible amount of time for whatever reason), it'll see no children for the root datase, and as such generate no mounts. This has never had any right to work. No-one caught this earlier because it's just that much more convenient to have root=zfs:AUTO, which orders itself properly. To fix this, always run zfs-nonroot-necessities.service; this additionally simplifies the implementation by: * making BOOTFS from zfs-env-bootfs.service be the real, canonical, root dataset name, not just "whatever the first bootfs is", and only set it if we're ZFS-booting * zfs-{rollback,snapshot}-bootfs.service can use this instead of re-implementing it * having zfs-env-bootfs.service also set BOOTFSFLAGS * this means the sysroot.mount drop-in can be fixed text * zfs-nonroot-necessities.service can also be constant and always enabled, because it's conditioned on BOOTFS being set There is no longer any code generated at run-time (the sysroot.mount drop-in is an unavoidable gratuitous cp). The flow of BOOTFS{,FLAGS} from zfs-env-bootfs.service to sysroot.mount is not noted explicitly in dracut.zfs(7), because (a) at some point it's just visual noise and (b) it's already ordered via d-p-m.s from z-i.t. Backport-of: 3399a30ee02d0d31ba2d43d0ce0a2fd90d5c575d Signed-off-by: Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz>
2023-03-28 20:49:50 +00:00
| sysroot.mount \(<-\(em\(em\(em dracut-zfs-generator
| |
| \(da
| initrd-root-fs.target \(<-\(em zfs-nonroot-necessities.service
| | |
| \(da |
\(da dracut-mount.service |
zfs-snapshot-bootfs.service | |
| \(da |
\(da … |
zfs-rollback-bootfs.service | |
| \(da |
contrib: dracut: fix race with root=zfs:dset when necessities required This had always worked in my testing, but a user on hardware reported this to happen 100%, and I reproduced it once with cold VM host caches. dracut-zfs-generator runs as a systemd generator, i.e. at Some Relatively Early Time; if root= is a fixed dataset, it tries to "solve [necessities] statically at generation time". If by that point zfs-import.target hasn't popped (because the import is taking a non-negligible amount of time for whatever reason), it'll see no children for the root datase, and as such generate no mounts. This has never had any right to work. No-one caught this earlier because it's just that much more convenient to have root=zfs:AUTO, which orders itself properly. To fix this, always run zfs-nonroot-necessities.service; this additionally simplifies the implementation by: * making BOOTFS from zfs-env-bootfs.service be the real, canonical, root dataset name, not just "whatever the first bootfs is", and only set it if we're ZFS-booting * zfs-{rollback,snapshot}-bootfs.service can use this instead of re-implementing it * having zfs-env-bootfs.service also set BOOTFSFLAGS * this means the sysroot.mount drop-in can be fixed text * zfs-nonroot-necessities.service can also be constant and always enabled, because it's conditioned on BOOTFS being set There is no longer any code generated at run-time (the sysroot.mount drop-in is an unavoidable gratuitous cp). The flow of BOOTFS{,FLAGS} from zfs-env-bootfs.service to sysroot.mount is not noted explicitly in dracut.zfs(7), because (a) at some point it's just visual noise and (b) it's already ordered via d-p-m.s from z-i.t. Backport-of: 3399a30ee02d0d31ba2d43d0ce0a2fd90d5c575d Signed-off-by: Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz>
2023-03-28 20:49:50 +00:00
| /sysroot/{usr,etc,lib,&c.} \(<-\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em/
| |
| \(da
| initrd-fs.target
\e______________________ |
\e|
\(da
export-zfs.sh initrd.target
| |
\(da \(da
dracut-shutdown.service …
|
\(da
zfs-needshutdown.sh \(-> initrd-cleanup.service
.Ed
.Pp
Compare
.Xr dracut.bootup 7
for the full flowchart.
.
.Sh DESCRIPTION
Under dracut, booting with
.No ZFS-on- Ns Pa /
is facilitated by a number of hooks in the
.Nm 90zfs
module.
.Pp
Booting into a ZFS dataset requires
.Sy mountpoint Ns = Ns Pa /
to be set on the dataset containing the root filesystem (henceforth "the boot dataset") and at the very least either the
.Sy bootfs
property to be set to that dataset, or the
.Sy root=
kernel cmdline (or dracut drop-in) argument to specify it.
.Pp
All children of the boot dataset with
.Sy canmount Ns = Ns Sy on
with
.Sy mountpoint Ns s
matching
.Pa /etc , /bin , /lib , /lib?? , /libx32 , No and Pa /usr
globs are deemed essential and will be mounted as well.
.Pp
.Xr zfs-mount-generator 8
is recommended for proper functioning of the system afterward (correct mount properties, remounting, &c.).
.
.Sh CMDLINE
.Ss Standard
.Bl -tag -compact -width ".Sy root=zfs:AUTO , root=zfs: , root=zfs , Op Sy root="
.It Sy root=zfs:\& Ns Ar dataset , Sy root=ZFS= Ns Ar dataset
Use
.Ar dataset
as the boot dataset.
All pluses
.Pq Sq +
are replaced with spaces
.Pq Sq \ .
.
.It Sy root=zfs:AUTO , root=zfs:\& , root=zfs , Op Sy root=
After import, search for the first pool with the
.Sy bootfs
property set, use its value as-if specified as the
.Ar dataset
above.
.
.It Sy rootfstype=zfs root= Ns Ar dataset
Equivalent to
.Sy root=zfs:\& Ns Ar dataset .
.
.It Sy rootfstype=zfs Op Sy root=
Equivalent to
.Sy root=zfs:AUTO .
.
.It Sy rootflags= Ns Ar flags
Mount the boot dataset with
.Fl o Ar flags ;
cf.\&
.Sx Temporary Mount Point Properties
in
.Xr zfsprops 7 .
These properties will not last, since all filesystems will be re-mounted from the real root.
.
.It Sy debug
If specified,
.Nm dracut-zfs-generator
logs to the journal.
.El
.Pp
Be careful about setting neither
.Sy rootfstype=zfs
nor
.Sy root=zfs:\& Ns Ar dataset
\(em other automatic boot selection methods, like
.Nm systemd-gpt-auto-generator
and
.Nm systemd-fstab-generator
might take precedent.
.
.Ss ZFS-specific
.Bl -tag -compact -width ".Sy bootfs.snapshot Ns Op Sy = Ns Ar snapshot-name"
.It Sy bootfs.snapshot Ns Op Sy = Ns Ar snapshot-name
Execute
.Nm zfs Cm snapshot Ar boot-dataset Ns Sy @ Ns Ar snapshot-name
before pivoting to the real root.
.Ar snapshot-name
defaults to the current kernel release.
.
.It Sy bootfs.rollback Ns Op Sy = Ns Ar snapshot-name
Execute
.Nm zfs Cm snapshot Fl Rf Ar boot-dataset Ns Sy @ Ns Ar snapshot-name
before pivoting to the real root.
.Ar snapshot-name
defaults to the current kernel release.
.
.It Sy spl_hostid= Ns Ar host-id
Use
.Xr zgenhostid 8
to set the host ID to
.Ar host-id ;
otherwise,
.Pa /etc/hostid
inherited from the real root is used.
.
.It Sy zfs_force , zfs.force , zfsforce
Appends
.Fl f
to all
.Nm zpool Cm import
invocations; primarily useful in conjunction with
.Sy spl_hostid= ,
or if no host ID was inherited.
.El
.
.Sh FILES
.Bl -tag -width 0
.It Pa parse-zfs.sh Pq Sy cmdline
Processes
.Sy spl_hostid= .
If
.Sy root=
matches a known pattern, above, provides
.Pa /dev/root
and delays the initqueue until
.Xr zfs 4
is loaded,
.
.It Pa zfs-import-opts.sh Pq Nm systemd No environment generator
Turns
.Sy zfs_force , zfs.force , No or Sy zfsforce
into
.Ev ZPOOL_IMPORT_OPTS Ns = Ns Fl f
for
.Pa zfs-import-scan.service
or
.Pa zfs-import-cache.service .
.
.It Pa zfs-load-key.sh Pq Sy pre-mount
Loads encryption keys for the boot dataset and its essential descendants.
.Bl -tag -compact -offset 4n -width ".Sy keylocation Ns = Ns Sy https:// Ns Ar URL , Sy keylocation Ns = Ns Sy http:// Ns Ar URL"
.It Sy keylocation Ns = Ns Sy prompt
Is prompted for via
.Nm systemd-ask-password
thrice.
.
.It Sy keylocation Ns = Ns Sy https:// Ns Ar URL , Sy keylocation Ns = Ns Sy http:// Ns Ar URL
.Pa network-online.target
is started before loading.
.
.It Sy keylocation Ns = Ns Sy file:// Ns Ar path
If
.Ar path
doesn't exist,
.Nm udevadm No is Cm settle Ns d .
If it still doesn't, it's waited for for up to
.Sy 10 Ns s .
.El
.
.It Pa zfs-env-bootfs.service Pq Nm systemd No service
After pool import, sets
.Ev BOOTFS Ns =
in the systemd environment to the first non-null
.Sy bootfs
value in iteration order.
.
.It Pa dracut-zfs-generator Pq Nm systemd No generator
Generates
.Pa sysroot.mount Pq using Sy rootflags= , No if any .
If an explicit boot dataset was specified, also generates essential mountpoints
.Pq Pa sysroot-etc.mount , sysroot-bin.mount , No &c.\& ,
otherwise generates
.Pa zfs-nonroot-necessities.service
which mounts them explicitly after
.Pa /sysroot
using
.Ev BOOTFS Ns = .
.
.It Pa zfs-snapshot-bootfs.service , zfs-rollback-bootfs.service Pq Nm systemd No services
Consume
.Sy bootfs.snapshot
and
.Sy bootfs.rollback
as described in
.Sx CMDLINE .
Use
.Ev BOOTFS Ns =
if no explicit boot dataset was specified.
.
.It Pa zfs-needshutdown.sh Pq Sy cleanup
If any pools were imported, signals that shutdown hooks are required.
.
.It Pa export-zfs.sh Pq Sy shutdown
Forcibly exports all pools.
.
.It Pa /etc/hostid , /etc/zfs/zpool.cache , /etc/zfs/vdev_id.conf Pq regular files
Included verbatim, hostonly.
.
.It Pa mount-zfs.sh Pq Sy mount
Does nothing on
.Nm systemd
systems
.Pq if Pa dracut-zfs-generator No succeeded .
Otherwise, loads encryption key for the boot dataset from the console or via plymouth.
It may not work at all!
.El
.
.Sh SEE ALSO
.Xr dracut.bootup 7 ,
.Xr zfsprops 7 ,
.Xr zpoolprops 7 ,
.Xr dracut-shutdown.service 8 ,
.Xr systemd-fstab-generator 8 ,
.Xr systemd-gpt-auto-generator 8 ,
.Xr zfs-mount-generator 8 ,
.Xr zgenhostid 8