freebsd-dev/contrib/dracut
наб 3399a30ee0
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.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz>
Closes #14690
2023-03-31 09:47:48 -07:00
..
02zfsexpandknowledge Ubuntu 22.04 integration: ShellCheck 2022-11-18 11:24:48 -08:00
90zfs contrib: dracut: fix race with root=zfs:dset when necessities required 2023-03-31 09:47:48 -07:00
.gitignore autoconf: use include directives instead of recursing down contrib 2022-05-10 10:19:44 -07:00
Makefile.am contrib: dracut: fix race with root=zfs:dset when necessities required 2023-03-31 09:47:48 -07:00
README.md contrib: dracut: README.md 2022-06-30 10:43:27 -07:00

Basic setup

  1. Install zfs-dracut
  2. Set mountpoint=/ for your root dataset (for compatibility, legacy also works, but is not recommended for new installations):
    zfs set mountpoint=/ pool/dataset
    
  3. Either (a) set bootfs= on the pool to the dataset:
    zpool set bootfs=pool/dataset pool
    
  4. Or (b) append root=zfs:pool/dataset to your kernel cmdline.
  5. Re-generate your initrd and update it in your boot bundle

Encrypted datasets have keys loaded automatically or prompted for.

If the root dataset contains children with mountpoint=s of /etc, /bin, /lib*, or /usr, they're mounted too.

For complete documentation, see dracut.zfs(7).

cmdline

  1. root= Root dataset is…
    (empty) the first bootfs= after zpool import -aN
    zfs:AUTO, zfs:, zfs (as above, but overriding other autoselection methods)
    ZFS=pool/dataset pool/dataset
    zfs:pool/dataset (as above)

    All +es are replaced with spaces (i.e. to boot from root pool/data set, pass root=zfs:root+pool/data+set).

    The dataset can be at any depth, including being the pool's root dataset (i.e. root=zfs:pool).

    rootfstype=zfs is equivalent to root=zfs:AUTO, rootfstype=zfs root=pool/dataset is equivalent to root=zfs:pool/dataset.

  2. spl_hostid: passed to zgenhostid -f, useful to override the /etc/hostid file baked into the initrd.

  3. bootfs.snapshot, bootfs.snapshot=snapshot-name: enables zfs-snapshot-bootfs.service, which creates a snapshot $root_dataset@$(uname -r) (or, in the second form, $root_dataset@snapshot-name) after pool import but before the rootfs is mounted. Failure to create the snapshot is noted, but booting continues.

  4. bootfs.rollback, bootfs.rollback=snapshot-name: enables zfs-rollback-bootfs.service, which -Rf rolls back to $root_dataset@$(uname -r) (or, in the second form, $root_dataset@snapshot-name) after pool import but before the rootfs is mounted. Failure to roll back will fall down to the rescue shell. This has obvious potential for data loss: make sure your persistent data is not below the rootfs and you don't care about any intermediate snapshots.

  5. If both bootfs.snapshot and bootfs.rollback are set, bootfs.rollback is ordered after bootfs.snapshot.

  6. zfs_force, zfs.force, zfsforce: add -f to all zpool import invocations. May be useful. Use with caution.