Document initramfs process
authorZachary Bedell <zac@thebedells.org>
Mon, 4 Jul 2011 18:38:10 +0000 (14:38 -0400)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Wed, 6 Jul 2011 16:20:28 +0000 (09:20 -0700)
Add documentation for Dracut and the initramfs process.  This includes
detailing the basic boot process and options available.

Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
dracut/README.dracut.markdown

index 8ec28e4..2628438 100644 (file)
@@ -26,3 +26,140 @@ zfs_arc_max, zfs_prefetch_disable, and zfs_vdev_max_pending.
 4) Finally, create your new initramfs by running dracut.
 
     $ dracut --force /path/to/initramfs kernel_version
+
+Kernel Command Line
+-------------------
+
+The initramfs' behavior is influenced by the following kernel command line
+parameters passed in from the boot loader:
+
+* `root=...`: If not set, importable pools are searched for a bootfs attribute.
+If an explicitly set root is desired, you may use `root=ZFS:pool/dataset`
+
+* `zfs_force=0`: If set to 1, the initramfs will run `zpool import -f` when
+attempting to import pools if the required pool isn't automatically imported
+by the zfs module.  This can save you a trip to a bootcd if hostid has changed,
+but is dangerous and can lead to zpool corruption, particularly in cases where
+storage is on a shared fabric such as iSCSI where multiple hosts can access
+storage devices concurrently.  _Please understand the implications of
+force-importing a pool before enabling this option!_
+
+* `spl_hostid`: By default, the hostid used by the SPL module is read from
+/etc/hostid inside the initramfs.  This file is placed there from the host
+system when the initramfs is built which effectively ties the ramdisk to the
+host which builds it.  If a different hostid is desired, one may be set in
+this attribute and will override any file present in the ramdisk.  The
+format should be hex exactly as found in the `/etc/hostid` file, IE
+`spl_hostid=0x00bab10c`.
+
+Note that changing the hostid between boots will most likely lead to an
+un-importable pool since the last importing hostid won't match.  In order
+to recover from this, you may use the `zfs_force` option or boot from a
+different filesystem and `zpool import -f` then `zpool export` the pool
+before rebooting with the new hostid.
+
+How it Works
+============
+
+The Dracut module consists of the following files (less Makefile's):
+
+* `module-setup.sh`: Script run by the initramfs builder to create the
+ramdisk.  Contains instructions on which files are required by the modules
+and z* programs.  Also triggers inclusion of `/etc/hostid` and the zpool
+cache.  This file is not included in the initramfs.
+
+* `90-zfs.rules`: udev rules which trigger loading of the ZFS modules at boot.
+
+* `parse-zfs.sh`: Run early in the initramfs boot process to parse kernel
+command line and determine if ZFS is the active root filesystem.
+
+* `mount-zfs.sh`: Run later in initramfs boot process after udev has settled
+to mount the root dataset.
+
+`module-setup.sh`
+---------------
+
+This file is run by the Dracut script within the live system, not at boot
+time.  It's not included in the final initramfs.  Functions in this script
+describe which files are needed by ZFS at boot time.
+
+Currently all the various z* and spl modules are included, a dependency is
+asserted on udev-rules, and the various zfs, zpool, etc. helpers are included.
+Dracut provides library functions which automatically gather the shared libs
+necessary to run each of these binaries, so statically built binaries are
+not required.
+
+The zpool and zvol udev rules files are copied from where they are
+installed by the ZFS build.  __PACKAGERS TAKE NOTE__: If you move
+`/etc/udev/rules/60-z*.rules`, you'll need to update this file to match.
+
+Currently this file also includes `/etc/hostid` and `/etc/zfs/zpool.cache`
+which means the generated ramdisk is specific to the host system which built
+it.  If a generic initramfs is required, it may be preferable to omit these
+files and specify the `spl_hostid` from the boot loader instead.
+
+`parse-zfs.sh`
+------------
+
+Run during the cmdline phase of the initramfs boot process, this script
+performs some basic sanity checks on kernel command line parameters to
+determine if booting from ZFS is likely to be what is desired.  Dracut
+requires this script to adjust the `root` variable if required and to set
+`rootok=1` if a mountable root filesystem is available.  Unfortunately this
+script must run before udev is settled and kernel modules are known to be
+loaded, so accessing the zpool and zfs commands is unsafe.
+
+If the root=ZFS... parameter is set on the command line, then it's at least
+certain that ZFS is what is desired, though this script is unable to
+determine if ZFS is in fact available.  This script will alter the `root`
+parameter to replace several historical forms of specifying the pool and
+dataset name with the canonical form of `zfs:pool/dataset`.
+
+If no root= parameter is set, the best this script can do is guess that
+ZFS is desired.  At present, no other known filesystems will work with no
+root= parameter, though this might possibly interfere with using the
+compiled-in default root in the kernel image.  It's considered unlikely
+that would ever be the case when an initramfs is in use, so this script
+sets `root=zfs:AUTO` and hopes for the best.
+
+Once the root=... (or lack thereof) parameter is parsed, a dummy symlink
+is created from `/dev/root` -> `/dev/null` to satisfy parts of the Dracut
+process which check for presence of a single root device node.
+
+Finally, an initqueue/finished hook is registered which causes the initqueue
+phase of Dracut to wait for `/dev/zfs` to become available before attempting
+to mount anything.
+
+`mount-zfs.sh`
+------------
+
+This script is run after udev has settled and all tasks in the initqueue
+have succeeded.  This ensures that `/dev/zfs` is available and that the
+various ZFS modules are successfully loaded.  As it is now safe to call
+zpool and friends, we can proceed to find the bootfs attribute if necessary.
+
+If the root parameter was explicitly set on the command line, no parsing is
+necessary.  The list of imported pools is checked to see if the desired pool
+is already imported.  If it's not, and attempt is made to import the pool
+explicitly, though no force is attempted.  Finally the specified dataset
+is mounted on `$NEWROOT`, first using the `-o zfsutil` option to handle
+non-legacy mounts, then if that fails, without zfsutil to handle legacy
+mount points.
+
+If no root parameter was specified, this script attempts to find a pool with
+its bootfs attribute set.  First, already-imported pools are scanned and if
+an appropriate pool is found, no additional pools are imported.  If no pool
+with bootfs is found, any additional pools in the system are imported with
+`zpool import -N -a`, and the scan for bootfs is tried again.  If no bootfs
+is found with all pools imported, all pools are re-exported, and boot fails.
+Assuming a bootfs is found, an attempt is made to mount it to `$NEWROOT`,
+first with, then without the zfsutil option as above.
+
+Ordinarily pools are imported _without_ the force option which may cause
+boot to fail if the hostid has changed or a pool has been physically moved
+between servers.  The `zfs_force` kernel parameter is provided which when
+set to `1` causes `zpool import` to be run with the `-f` flag.  Forcing pool
+import can lead to serious data corruption and loss of pools, so this option
+should be used with extreme caution.  Note that even with this flag set, if
+the required zpool was auto-imported by the kernel module, no additional
+`zpool import` commands are run, so nothing is forced.