Translate

Archives

Fedora 12 Dracut

Fedora 12 (Constantine) contains a new infrastructure for populating and building an initramfs image called Dracut. Dracut is a replacement for both the mkinitrd build script and the nash script interpreter. The project was started by Jeremy Katz when he worked at Redhat as a result of discussions at a Linux Summit a couple of years ago and some community prodding by David Jones. Currently Harald Hoyer, who works for Redhat, is the owner of the project. In this post I examine Dracut in detail and show the major differences between the existing and new infrastructures.

I assume that if you are reading this post you are somewhat familiar with how Linux (and Fedora in particular) is booted, the purpose of initrd, initramfs and mkinitrd. Dracut continues to use the initramfs architecture but replaces the /sbin/mkinitrd shell script with its own shell script /sbin/dracut, the nash script interpreter with dash (Debian Almquist shell) if available otherwise bash, and a totally new init script.

First let us look at the changes that are or may be visible when you boot your system. If you look at your grub configuration file you will see a number of changes. Here is one stanza from my current configuration file.

title Fedora (2.6.31.6-166.fc12.x86_64)
	root (hd0,1)
	kernel /vmlinuz-2.6.31.6-166.fc12.x86_64 ro root=UUID=434794ee-a7ff-4156-aabf-53a79c3d319b LANG=en_US.UTF-8 SYSFONT=latarcyrheb-sun16 KEYBOARDTYPE=pc KEYTABLE=us rhgb quiet
	initrd /initramfs-2.6.31.6-166.fc12.x86_64.img


The number of arguments on the kernel command line has increased. Now a console language (locale), a console font and keyboard type and table are specified. Console fonts are used to display text (glyphs) on a Linux console. Numerous console fonts are available; they are kept in /lib/kbd/consolefonts. The Unicode console font latarcyrheb-sun16 covers Latin, Cyrillic, Hebrew and Arabic. This is the default Fedora console font. Where specified on the kernel command line, I18N-related parameters will be written to the appropriate file in the initramfs. For example, KEYTABLE=us will be written to the initramfs’s /etc/sysconfig/keyboard, SYSFONT=latarcyrheb-sun16 will be written to the initramfs’s /etc/sysconfig/i18n, and so on.

Numerous other kernel command line options are also supported. These are all documented in the dracut(8) man page. Support for debugging initramfs problems has been significantly improved. Here is a list of the documented debugging options:

  • rdinfo – print informational output though “quiet” is set
  • rdshell – allow dropping to a shell, if root mounting fails
  • rdinitdebug – set -x for the dracut shell and logs to dmesg, console and /init.log
  • rdbreak – drop to a shell at the end
  • rdbreak={cmdline|pre-udev|pre-trigger|initqueue|pre-mount|mount|pre-pivot} – drop to a shell on defined breakpoint
  • rdudevinfo – set udev to loglevel info
  • rdudevdebug – set udev to loglevel debug
  • rdnetdebug – debug network scripts in dracut. Output is written to /tmp/

The one that I particularly like is the ability to drop into a shell on a defined breakpoint.

Here is the Dracut-related content in /var/log/dmesg when I boot my system with no debugging options set.

dracut: dracut-003-13.4.git8f397a9b.fc12
udev: starting version 145
[drm] Initialized drm 1.1.0 20060810
nouveau 0000:01:00.0: PCI INT A -> GSI 16 (level, low) -> IRQ 16
nouveau 0000:01:00.0: setting latency timer to 64
[drm] nouveau 0000:01:00.0: Detected an NV50 generation card (0x096000c1)
[drm] nouveau 0000:01:00.0: Attempting to load BIOS image from PRAMIN
[drm] nouveau 0000:01:00.0: ... appears to be valid
[drm] nouveau 0000:01:00.0: BIT BIOS found
[drm] nouveau 0000:01:00.0: Bios version 62.94.29.00
[drm] nouveau 0000:01:00.0: TMDS table revision 2.0 not currently supported
[drm] nouveau 0000:01:00.0: Found Display Configuration Block version 4.0
[drm] nouveau 0000:01:00.0: DCB connector table: VHER 0x40 5 16 4
[drm] nouveau 0000:01:00.0:   0: 0x00001030: type 0x30 idx 0 tag 0x07
[drm] nouveau 0000:01:00.0:   1: 0x00002130: type 0x30 idx 1 tag 0x08
[drm] nouveau 0000:01:00.0:   2: 0x00000210: type 0x10 idx 2 tag 0xff
[drm] nouveau 0000:01:00.0:   3: 0x00000211: type 0x11 idx 2 tag 0xff
[drm] nouveau 0000:01:00.0:   4: 0x00000213: type 0x13 idx 2 tag 0xff
[drm] nouveau 0000:01:00.0: Raw DCB entry 0: 02000300 00000028
[drm] nouveau 0000:01:00.0: Raw DCB entry 1: 01000302 00020030
[drm] nouveau 0000:01:00.0: Raw DCB entry 2: 04011310 00000028
[drm] nouveau 0000:01:00.0: Raw DCB entry 3: 02011312 00020030
[drm] nouveau 0000:01:00.0: Raw DCB entry 4: 010223f1 00c0c080
[drm] nouveau 0000:01:00.0: Parsing VBIOS init table 0 at offset 0xD0BE
[drm] nouveau 0000:01:00.0: Parsing VBIOS init table 1 at offset 0xD4D3
[drm] nouveau 0000:01:00.0: Parsing VBIOS init table 2 at offset 0xE4C4
[drm] nouveau 0000:01:00.0: Parsing VBIOS init table 3 at offset 0xE60D
[drm] nouveau 0000:01:00.0: Parsing VBIOS init table 4 at offset 0xE849
[drm] nouveau 0000:01:00.0: Parsing VBIOS init table at offset 0xE8AE
[drm] nouveau 0000:01:00.0: 0xE8AE: Condition still not met after 20ms, skipping following opcodes
[drm] nouveau 0000:01:00.0: 0xC090: parsing output script 0
SELinux: initialized (dev debugfs, type debugfs), uses genfs_contexts
SELinux: initialized (dev sockfs, type sockfs), uses task SIDs
SELinux: initialized (dev proc, type proc), uses genfs_contexts
SELinux: initialized (dev bdev, type bdev), uses genfs_contexts
SELinux: initialized (dev rootfs, type rootfs), uses genfs_contexts
SELinux: initialized (dev sysfs, type sysfs), uses genfs_contexts
type=1403 audit(1260498140.014:3): policy loaded auid=4294967295 ses=4294967295
dracut: Switching root


Here is what is outputted to the console (and to /var/log/boot.log) when the rdinfo option is added to the kernel command line.

WARNING: Deprecated config file /etc/modprobe.conf, all config files belong into /etc/modprobe.d/.
dracut: Scanning devices sda3  for LVM volume groups
dracut: Reading all physical volumes. This may take a while...
dracut: Found volume group "vg_ultra" using metadata type lvm2
dracut: 2 logical volume(s) in volume group "vg_ultra" now active
dracut: Mounted root filesystem /dev/dm-0
dracut: Loading SELinux policy
dracut: Switching root


Here is what is outputted when rdinitdebug is added to the kernel command line instead of rdinfo:

dracut: + /bin/plymouth --show-splash+
dracut: vinfo
dracut: + read line
dracut: + [ -e /pre-trigger/30parse-dm.sh ]
dracut: + . /pre-trigger/30parse-dm.sh
dracut: + getarg rd_NO_DM
dracut: + set +x
dracut: + return 1
dracut: + getarg nodmraid
dracut: + set +x
dracut: + return 1
dracut: + [ -e /pre-trigger/30parse-md.sh ]
dracut: + . /pre-trigger/30parse-md.sh
dracut: + getarg rd_NO_MD
dracut: + set +x
dracut: + return 1
dracut: + getargs rd_MD_UUID=
dracut: + set +x
dracut: + return 1
dracut: + MD_UUID=
dracut: + [ -n  ]
dracut: + [ -e /etc/mdadm.conf ]
dracut: + getarg rd_NO_MDIMSM
dracut: + set +x
dracut: + return 1
dracut: + getarg noiswmd
dracut: + set +x
dracut: + return 1
dracut: + getarg nodmraid
dracut: + set +x
dracut: + return 1
dracut: + udevadm trigger
dracut: + getarg rdbreak=initqueue
dracut: + set +x
dracut: + return 1
dracut: + i=0
dracut: + :
dracut: + check_finished
dracut: + local f
dracut: + [ -e /initqueue-finished/block.sh ]
dracut: + . /initqueue-finished/block.sh
dracut: + [ -e /dev/root ]
dracut: + return 1
dracut: + udevsettle
dracut: + [ -z 145 ]
dracut: + [ 145 -ge 143 ]
dracut: + udevadm settle --exit-if-exists=/initqueue/work
dracut: + check_finished
dracut: + local f
dracut: + [ -e /initqueue-finished/block.sh ]
dracut: + . /initqueue-finished/block.sh
dracut: + [ -e /dev/root ]
dracut: + return 1
dracut: + [ -f /initqueue/work ]
dracut: + [ -e /initqueue/*.sh ]
dracut: + break
dracut: + udevadm settle --timeout=0
dracut: + modprobe scsi_wait_scan
dracut: WARNING: Deprecated config file /etc/modprobe.conf, all config files belong into /etc/modprobe.d/.
dracut: + rmmod scsi_wait_scan
dracut: + udevadm settle --timeout=0
dracut: + [ -e /initqueue-settled/blocksymlink.sh ]
dracut: + job=/initqueue-settled/blocksymlink.sh . /initqueue-settled/blocksymlink.sh
dracut: + [ -e /dev/disk/by-uuid/434794ee-a7ff-4156-aabf-53a79c3d319b ]
dracut: + check_finished
dracut: + local f
dracut: + [ -e /initqueue-finished/block.sh ]
dracut: + . /initqueue-finished/block.sh
dracut: + [ -e /dev/root ]
dracut: + return 1
dracut: + [ -e /initqueue-settled/lvm_scan.sh ]
dracut: + job=/initqueue-settled/lvm_scan.sh . /initqueue-settled/lvm_scan.sh
dracut: + [ -e /initqueue-settled/lvm_scan.sh ]
dracut: + rm /initqueue-settled/lvm_scan.sh
dracut: + /sbin/lvm_scan
dracut: + getargs rd_LVM_VG=
dracut: + set +x
dracut: + return 1
dracut: + VGS=
dracut: + [ -d /etc/lvm ]
dracut: + [ -e /tmp/.lvm_scan-sda3 ]
dracut: + echo -n sda3
dracut: + lvmdevs=sda3
dracut: + [ ! -e /etc/lvm/lvm.conf ]
dracut: + info Scanning devices sda3  for LVM volume groups
dracut: + [ -z  ]
dracut: + DRACUT_QUIET=no
dracut: + getarg quiet
dracut: + set +x
dracut: + return 1
dracut: + echo <6>dracut: Scanning devices sda3  for LVM volume groups
dracut: + [ yes != yes ]
dracut: + lvm vgscan
dracut: + vinfo
dracut: + read line
dracut: + info Reading all physical volumes. This may take a while...
dracut: + [ -z yes ]
dracut: + echo <6>dracut: Reading all physical volumes. This may take a while...
dracut: + [ yes != yes ]
dracut: + read line
dracut: + info Found volume group "vg_ultra" using metadata type lvm2
dracut: + [ -z yes ]
dracut: + echo <6>dracut: Found volume group "vg_ultra" using metadata type lvm2
dracut: + [ yes != yes ]
dracut: + read line
dracut: + lvm vgchange+  -ay
dracut: vinfo
dracut: + read line
dracut: + info 2 logical volume(s) in volume group "vg_ultra" now active
dracut: + [ -z yes ]
dracut: + echo <6>dracut: 2 logical volume(s) in volume group "vg_ultra" now active
dracut: + [ yes != yes ]
dracut: + read line
dracut: + [  ]
dracut: + unset lvmwritten
dracut: + check_finished
dracut: + local f
dracut: + [ -e /initqueue-finished/block.sh ]
dracut: + . /initqueue-finished/block.sh
dracut: + [ -e /dev/root ]
dracut: + return 1
dracut: + udevadm settle --timeout=0
dracut: + continue
dracut: + :
dracut: + check_finished
dracut: + local f
dracut: + [ -e /initqueue-finished/block.sh ]
dracut: + . /initqueue-finished/block.sh
dracut: + [ -e /dev/root ]
dracut: + return 1
dracut: + udevsettle
dracut: + [ -z 145 ]
dracut: + [ 145 -ge 143 ]
dracut: + udevadm settle --exit-if-exists=/initqueue/work
dracut: + check_finished
dracut: + local f
dracut: + [ -e /initqueue-finished/block.sh ]
dracut: + . /initqueue-finished/block.sh
dracut: + [ -e /dev/root ]
dracut: + return 0
dracut: + break
dracut: + unset job
dracut: + unset queuetriggered
dracut: + getarg rdbreak=pre-mount
dracut: + set +x
dracut: + return 1
dracut: + source_all pre-mount
dracut: + local f
dracut: + [ pre-mount ]
dracut: + [ -d /pre-mount ]
dracut: + return
dracut: + getarg rdbreak=mount
dracut: + set +x
dracut: + return 1
dracut: + i=0
dracut: + :
dracut: + [ -d /sysroot/proc ]
dracut: + [ -f /mount/10resume.sh ]
dracut: + . /mount/10resume.sh
dracut: + [ -s /.resume -a -b  ]
dracut: + [ -d /sysroot/proc ]
dracut: + [ -f /mount/99mount-root.sh ]
dracut: + . /mount/99mount-root.sh
dracut: + [ -n block:/dev/disk/by-uuid/434794ee-a7ff-4156-aabf-53a79c3d319b -a -z  ]
dracut: + mount -t auto -o ro /dev/disk/by-uuid/434794ee-a7ff-4156-aabf-53a79c3d319b /sysroot
dracut: + ROOTFS_MOUNTED=yes
dracut: + [ -d /sysroot/proc ]
dracut: + break
dracut: + i=1
dracut: + [ 1 -gt 20 ]
dracut: + :
dracut: + [ -d /sysroot/proc ]
dracut: + break
dracut: + echo -n Mounted root filesystem
dracut: + vinfo
dracut: + read line
dracut: + read dev mp rest
dracut: + [ / = /sysroot ]
dracut: + read dev mp rest
dracut: + [ /proc = /sysroot ]
dracut: + read dev mp rest
dracut: + [ /sys = /sysroot ]
dracut: + read dev mp rest
dracut: + [ /dev = /sysroot ]
dracut: + read dev mp rest
dracut: + [ /dev/pts = /sysroot ]
dracut: + read dev mp rest
dracut: + [ /dev/shm = /sysroot ]
dracut: + read dev mp rest
dracut: + [ /sysroot = /sysroot ]
dracut: + echo /dev/dm-0
dracut: + info Mounted root filesystem /dev/dm-0
dracut: + [ -z yes ]
dracut: + echo <6>dracut: Mounted root filesystem /dev/dm-0
dracut: + [ yes != yes ]
dracut: + read line
dracut: + read dev mp rest
dracut: + getarg rdbreak=pre-pivot
dracut: + set +x
dracut: + return 1
dracut: + source_all pre-pivot
dracut: + local f
dracut: + [ pre-pivot ]
dracut: + [ -d /pre-pivot ]
dracut: + [ -e /pre-pivot/30crypt-cleanup.sh ]
dracut: + . /pre-pivot/30crypt-cleanup.sh
dracut: + cryptsetup luksClose /dev/mapper/luks-*
dracut: + [ -e /pre-pivot/31crypt-cleanup.sh ]
dracut: + . /pre-pivot/31crypt-cleanup.sh
dracut: + cryptsetup luksClose /dev/mapper/luks-*
dracut: + [ -e /pre-pivot/50selinux-loadpolicy.sh ]
dracut: + . /pre-pivot/50selinux-loadpolicy.sh
dracut: + rd_load_policy
dracut: + SELINUX=enforcing
dracut: + [ -e /sysroot/etc/selinux/config ]
dracut: + . /sysroot/etc/selinux/config
dracut: + SELINUX=enforcing
dracut: + SELINUXTYPE=targeted
dracut: + getarg selinux=0
dracut: + set +x
dracut: + return 1
dracut: + [ 1 -eq 0 -o enforcing = disabled ]
dracut: + permissive=0
dracut: + getarg enforcing=0
dracut: + set +x
dracut: + return 1
dracut: + [ 1 -eq 0 -o enforcing = permissive ]
dracut: + [ -x /sysroot/usr/sbin/load_policy -o -x /sysroot/sbin/load_policy ]
dracut: + ret=0
dracut: + info Loading SELinux policy
dracut: + [ -z yes ]
dracut: + echo <6>dracut: Loading SELinux policy
dracut: + [ yes != yes ]
dracut: + vinfo
dracut: + read line
dracut: + info + [ -x /sysroot/sbin/load_policy ]
dracut: + [ -z yes ]
dracut: + echo <6>dracut: + [ -x /sysroot/sbin/load_policy ]
dracut: + [ yes != yes ]
dracut: + read line
dracut: + info + chroot /sysroot /sbin/load_policy -i
dracut: + [ -z yes ]
dracut: + echo <6>dracut: + chroot /sysroot /sbin/load_policy -i
dracut: + [ yes != yes ]
dracut: + read line
dracut: + info + ret=0
dracut: + [ -z yes ]
dracut: + echo <6>dracut: + ret=0
dracut: + [ yes != yes ]
dracut: + read line
dracut: + [ 0 -eq 0 -o 0 -eq 2 ]
dracut: + return 0
dracut: + [ -e /pre-pivot/90plymouth-newroot.sh ]
dracut: + . /pre-pivot/90plymouth-newroot.sh
dracut: + [ -x /bin/plymouth ]
dracut: + /bin/plymouth --newroot=/sysroot
dracut: + getarg init=
dracut: + set +x
dracut: + return 1
dracut: + [ -f /sysroot -a -x /sysroot ]
dracut: + [ -f /sysroot/sbin/init -a -x /sysroot/sbin/init ]
dracut: + INIT=/sbin/init
dracut: + break
dracut: + [ /sbin/init ]
dracut: + getarg rdbreak
dracut: + set +x
dracut: + return 1
dracut: + udevadm control --stop-exec-queue
dracut: + HARD=
dracut: + pidof udevd
dracut: + pidof udevd
dracut: + kill 187
dracut: + kill 186
dracut: + kill 185
dracut: + kill 184
dracut: + kill 183
dracut: + kill 182
dracut: + kill 180
dracut: + kill 179
dracut: + kill 177
dracut: + kill 175
dracut: + kill 169
dracut: + kill 166
dracut: + kill 136
dracut: + kill 134
dracut: + kill 133
dracut: + kill 132
dracut: + kill 131
dracut: + kill 130
dracut: + kill 129
dracut: + kill 126
dracut: + kill 124
dracut: + HARD=-9
dracut: + pidof udevd
dracut: + pidof udevd
dracut: + kill -9 124
dracut: + HARD=-9
dracut: + pidof udevd
dracut: + pidof udevd
dracut: + kill -9 124
dracut: + HARD=-9
dracut: + pidof udevd
dracut: + export -p
dracut: + i=export
dracut: + i=
dracut: + i=
dracut: + [  = root -o  = PATH -o  = HOME -o  = TERM ]
dracut: + unset
dracut: + i=HOME='/'
dracut: + i=HOME='/'
dracut: + i=HOME
dracut: + [ HOME = root -o HOME = PATH -o HOME = HOME -o HOME = TERM ]
dracut: + i=export
dracut: + i=
dracut: + i=
dracut: + [  = root -o  = PATH -o  = HOME -o  = TERM ]
dracut: + unset
dracut: + i=KEYBOARDTYPE='pc'
dracut: + i=KEYBOARDTYPE='pc'
dracut: + i=KEYBOARDTYPE
dracut: + [ KEYBOARDTYPE = root -o KEYBOARDTYPE = PATH -o KEYBOARDTYPE = HOME -o KEYBOARDTYPE = TERM ]
dracut: + unset KEYBOARDTYPE
dracut: + i=export
dracut: + i=
dracut: + i=
dracut: + [  = root -o  = PATH -o  = HOME -o  = TERM ]
dracut: + unset
dracut: + i=KEYTABLE='us'
dracut: + i=KEYTABLE='us'
dracut: + i=KEYTABLE
dracut: + [ KEYTABLE = root -o KEYTABLE = PATH -o KEYTABLE = HOME -o KEYTABLE = TERM ]
dracut: + unset KEYTABLE
dracut: + i=export
dracut: + i=
dracut: + i=
dracut: + [  = root -o  = PATH -o  = HOME -o  = TERM ]
dracut: + unset
dracut: + i=LANG='en_US.UTF-8'
dracut: + i=LANG='en_US.UTF-8'
dracut: + i=LANG
dracut: + [ LANG = root -o LANG = PATH -o LANG = HOME -o LANG = TERM ]
dracut: + unset LANG
dracut: + i=export
dracut: + i=
dracut: + i=
dracut: + [  = root -o  = PATH -o  = HOME -o  = TERM ]
dracut: + unset
dracut: + i=PATH='/sbin:/bin:/usr/sbin:/usr/bin'
dracut: + i=PATH='/sbin:/bin:/usr/sbin:/usr/bin'
dracut: + i=PATH
dracut: + [ PATH = root -o PATH = PATH -o PATH = HOME -o PATH = TERM ]
dracut: + i=export
dracut: + i=
dracut: + i=
dracut: + [  = root -o  = PATH -o  = HOME -o  = TERM ]
dracut: + unset
dracut: + i=PWD='/'
dracut: + i=PWD='/'
dracut: + i=PWD
dracut: + [ PWD = root -o PWD = PATH -o PWD = HOME -o PWD = TERM ]
dracut: + unset PWD
dracut: + i=export
dracut: + i=
dracut: + i=
dracut: + [  = root -o  = PATH -o  = HOME -o  = TERM ]
dracut: + unset
dracut: + i=SYSFONT='latarcyrheb-sun16'
dracut: + i=SYSFONT='latarcyrheb-sun16'
dracut: + i=SYSFONT
dracut: + [ SYSFONT = root -o SYSFONT = PATH -o SYSFONT = HOME -o SYSFONT = TERM ]
dracut: + unset SYSFONT
dracut: + i=export
dracut: + i=
dracut: + i=
dracut: + [  = root -o  = PATH -o  = HOME -o  = TERM ]
dracut: + unset
dracut: + i=TERM='linux'
dracut: + i=TERM='linux'
dracut: + i=TERM
dracut: + [ TERM = root -o TERM = PATH -o TERM = HOME -o TERM = TERM ]
dracut: + i=export
dracut: + i=
dracut: + i=
dracut: + [  = root -o  = PATH -o  = HOME -o  = TERM ]
dracut: + unset
dracut: + i=ip='eth0:dhcp'
dracut: + i=ip='eth0:dhcp'
dracut: + i=ip
dracut: + [ ip = root -o ip = PATH -o ip = HOME -o ip = TERM ]
dracut: + unset ip
dracut: + initargs=
dracut: + getarg init=
dracut: + set +x
dracut: + return 1
dracut: + [ -e /tmp/net.ifaces ]
dracut: + getarg rdcopystate
dracut: + set +x
dracut: + return 1
dracut: + info Switching root
dracut: + [ -z yes ]
dracut: + echo <6>dracut: Switching root
dracut: + [ yes != yes ]
dracut: + wait_for_loginit
dracut: + getarg rdinitdebug
dracut: + set +x
+ exec switch_root /sysroot /sbin/init


The first thing you will notice is that the init script immediately invokes Plymouth (which I discussed recently in another post. If you do not want Plymouth to be started by Dracut, add rd_NO_PLYMOUTH (can anybody explain why part of this option in uppercase?) to the kernel command line. Note that, according to the man page, this will not work with encrypted partitions.

Turning now to the question of how to build a new initramfs file using Dracut. If you want to build a generic initramfs file using Dracut, which should be able to boot any bootable configuration given the appropriate boot flags (root device, network configuration information, etc.) the following packages must be installed on your system:

  • cryptsetup-luks
  • device-mapper
  • iscsi-initiator-utils
  • lvm2
  • mdadm
  • nbd
  • net-tools iproute
  • rpcbind nfs-utils

Note that a generic initramfs file is huge. The following three files show the difference in size between a 2.6.30.96 initrd made using /sbin/mkinitrd, the same one made using Dracut and a generic one made using Dracut:

-rw-------. 1 root root  3774369 2009-11-11 13:18 /boot/initrd-2.6.30.9-96.fc11.x86_64.img
-rw-r--r--. 1 root root  4163575 2009-11-13 17:19 /boot/initrd-dracut-2.6.30.9-96.fc11.x86_64.img
-rw-r--r--. 1 root root 14971825 2009-11-13 16:09 /boot/initrd-dracut-generic-2.6.30.9-96.fc11.x86_64.img


Most of the functionality that Dracut implements is actually implemented by individual Dracut (generator) modules that are sourced by the main Dracut script to install specific functionality into the initramfs directory structure using additional functionality provided by /usr/share/dracut/dracut-functions. Dracut modules live in subdirectories under /usr/share/dracut/modules.d/. Each module name is prefixed by a two-digit numeric sort code in the range of 00 to 99, e.g. 50plymouth. Modules with lower numbers are installed first in the initramfs directory structure. Each module takes 2 standard arguments – install and check. Install is used to install the module functionality onto the initramfs directory structure in a controlled manner. Mainly this consists of copying files into the initramfs directory structure. The check option is used by Dracut to check that all the files that the modules needs to install into the initramfs from the host system are present. Check can take a number of options. For example the -h option is used to check if the functionality implemented by the module is actually being used by the host system. The -d option outputs a list of other dracut modules that a module has dependencies on.

The following modules are part of the initial release of Dracut: i18n, network, plymouth, crypt, dmraid, lvm, mdraid, dmsquash-live, fcoe, iscsi, nbd, nfs, resume, rootfs-block and s390. Let us example one module, i.e. plymouth, in more detail. This module consists of a total of 8 shell scripts. (Interestingly, the file utility reports a mix of Bourne shell and POSIX shell scripts!)

# pwd
/usr/share/dracut/modules.d/50plymouth
# ls -l 
total 32
-rwxr-xr-x. 1 root root  128 2009-09-29 12:29 check
-rwxr-xr-x. 1 root root  815 2009-09-29 12:29 cryptroot-ask.sh
-rwxr-xr-x. 1 root root  641 2009-09-29 12:29 install
-rwxr-xr-x. 1 root root  191 2009-09-29 12:29 installkernel
-rw-r--r--. 1 root root   52 2009-09-29 12:29 plymouth-emergency.sh
-rwxr-xr-x. 1 root root   79 2009-09-29 12:29 plymouth-newroot.sh
-rwxr-xr-x. 1 root root 1633 2009-09-29 12:29 plymouth-populate-initrd
-rwxr-xr-x. 1 root root  756 2009-09-29 12:29 plymouth-pretrigger.sh
# file *
check:                    Bourne-Again shell script text executable
cryptroot-ask.sh:         POSIX shell script text executable
install:                  Bourne-Again shell script text executable
installkernel:            Bourne-Again shell script text executable
plymouth-emergency.sh:    ASCII text
plymouth-newroot.sh:      POSIX shell script text executable
plymouth-populate-initrd: Bourne-Again shell script text executable
plymouth-pretrigger.sh:   POSIX shell script text executable


Here is the install script:

#!/bin/bash

if grep -q nash /usr/libexec/plymouth/plymouth-populate-initrd \
   || ! grep -q PLYMOUTH_POPULATE_SOURCE_FUNCTIONS /usr/libexec/plymouth/plymouth-populate-initrd \
   || [ ! -x /usr/libexec/plymouth/plymouth-populate-initrd ]; then
    . "$moddir"/plymouth-populate-initrd
else
    PLYMOUTH_POPULATE_SOURCE_FUNCTIONS="$dracutfunctions" \
        /usr/libexec/plymouth/plymouth-populate-initrd -t $initdir
fi

inst_hook pre-pivot 90 "$moddir"/plymouth-newroot.sh
inst_hook pre-trigger 10 "$moddir"/plymouth-pretrigger.sh
inst_hook emergency 50 "$moddir"/plymouth-emergency.sh
inst "$moddir"/cryptroot-ask.sh /sbin/cryptroot-ask


and here is what is in the check script

#!/bin/bash
[[ $1 = -d ]] && echo crypt
[[ -x /sbin/plymouthd && -x /bin/plymouth && -x /usr/sbin/plymouth-set-default-theme ]]


Dracut can have a number of configuration files. The main configuration file is /etc/dracut.conf. Here is what comes out-of-the-box with Fedora 12.

# Sample dracut config file

# Specific list of dracut modules to use
#dracutmodules=""

# Dracut modules to omit
#omit_dracutmodules=""

# additional kernel modules to the default
#add_drivers=""

# build initrd only to boot current hardware
#hostonly="-h"

# install local /etc/mdadm.conf
mdadmconf="yes"

# install local /etc/lvm/lvm.conf
lvmconf="yes"


Unfortunately no details of what options can be placed in the configuration file are detailed in the Dracut man page or elsewhere.

Traditionally on Fedora /sbin/mkinitrd was used to build a new initramfs. Here is the contents of an initramfs file which was build for a Fedora 11 system using mkinitrd:

init
sbin
etc
etc/ld.so.conf.d
etc/ld.so.conf.d/mysql-x86_64.conf
etc/ld.so.conf.d/kernel-2.6.29.6-217.2.16.fc11.x86_64.conf
etc/ld.so.conf.d/kernel-2.6.30.9-96.fc11.x86_64.conf
etc/ld.so.conf.d/nvidia-lib64.conf
etc/ld.so.conf.d/atlas-x86_64.conf
etc/ld.so.conf.d/kernel-2.6.29.6-217.2.8.fc11.x86_64.conf
etc/ld.so.conf.d/xulrunner-64.conf
etc/ld.so.conf.d/qt-x86_64.conf
etc/ld.so.conf.d/kernel-2.6.30.5-43.fc11.x86_64.conf
etc/ld.so.cache
etc/sysconfig
etc/sysconfig/i18n
etc/sysconfig/keyboard
etc/lvm
etc/lvm/lvm.conf
etc/fedora-release
etc/system-release
etc/ld.so.conf
usr
usr/lib64
usr/lib64/plymouth
usr/lib64/plymouth/details.so
usr/lib64/plymouth/text.so
usr/lib64/plymouth/space-flares.so
usr/lib64/libpng12.so.0.37.0
usr/lib64/libnl.so.1
usr/lib64/libelf.so.1
usr/lib64/libnl.so.1.1
usr/lib64/libbdevid.so.6.0.87
usr/lib64/libnash.so.6.0.87
usr/lib64/libpng12.so.0
usr/lib64/libplybootsplash.so.2.0.0
usr/lib64/libplybootsplash.so.2
usr/lib64/libelf-0.142.so
usr/share
usr/share/plymouth
usr/share/plymouth/bizcom.png
usr/share/plymouth/themes
usr/share/plymouth/themes/details
usr/share/plymouth/themes/details/details.plymouth
usr/share/plymouth/themes/text
usr/share/plymouth/themes/text/text.plymouth
usr/share/plymouth/themes/default.plymouth
usr/share/plymouth/themes/solar
usr/share/plymouth/themes/solar/progress_bar.png
usr/share/plymouth/themes/solar/star.png
usr/share/plymouth/themes/solar/lock.png
usr/share/plymouth/themes/solar/solar.plymouth
usr/share/plymouth/themes/solar/bullet.png
usr/share/plymouth/themes/solar/box.png
usr/share/plymouth/themes/solar/entry.png
sys
lib64
lib64/libpopt.so.0.0.0
lib64/libparted-1.8.so.8
lib64/libgcc_s.so.1
lib64/libz.so.1
lib64/libpthread.so.0
lib64/libc.so.6
lib64/libpthread-2.10.1.so
lib64/libuuid.so.1
lib64/libpopt.so.0
lib64/libz.so.1.2.3
lib64/libtinfo.so.5.7
lib64/libgcc_s-4.4.1-20090729.so.1
lib64/librt.so.1
lib64/libreadline.so.5
lib64/libdl-2.10.1.so
lib64/libparted-1.8.so.8.0.0
lib64/libglib-2.0.so.0
lib64/libreadline.so.5.2
lib64/libm.so.6
lib64/librt-2.10.1.so
lib64/libtinfo.so.5
lib64/libuuid.so.1.2
lib64/libglib-2.0.so.0.2000.5
lib64/libply.so.2.0.0
lib64/libselinux.so.1
lib64/libply.so.2
lib64/libblkid.so.1.0
lib64/libresolv.so.2
lib64/libblkid.so.1
lib64/libsepol.so.1
lib64/libc-2.10.1.so
lib64/libm-2.10.1.so
lib64/libdl.so.2
lib64/ld-linux-x86-64.so.2
lib64/ld-2.10.1.so
lib64/libdevmapper.so.1.02
lib64/libresolv-2.10.1.so
bin
bin/nash
bin/setfont
bin/loadkeys
bin/plymouth
bin/plymouthd
bin/modprobe
bin/rmmod
bin/lvm
lib
lib/kbd
lib/kbd/consolefonts
lib/kbd/consolefonts/latarcyrheb-sun16.psfu
lib/kbd/keymaps
lib/kbd/keymaps/i386
lib/kbd/keymaps/i386/include
lib/kbd/keymaps/i386/include/linux-with-alt-and-altgr.inc
lib/kbd/keymaps/i386/include/linux-keys-bare.inc
lib/kbd/keymaps/i386/include/euro1.map
lib/kbd/keymaps/i386/include/compose.inc
lib/kbd/keymaps/i386/include/qwerty-layout.inc
lib/kbd/keymaps/i386/qwerty
lib/kbd/keymaps/i386/qwerty/us.map
lib/kbd/keymaps/include
lib/kbd/keymaps/include/compose.latin4
lib/kbd/keymaps/include/compose.8859_8
lib/kbd/keymaps/include/compose.latin1
lib/kbd/keymaps/include/compose.latin3
lib/kbd/keymaps/include/compose.8859_7
lib/kbd/keymaps/include/compose.latin2
lib/kbd/keymaps/include/compose.latin
lib/modules
lib/modules/2.6.30.9-96.fc11.x86_64
lib/modules/2.6.30.9-96.fc11.x86_64/scsi_wait_scan.ko
lib/modules/2.6.30.9-96.fc11.x86_64/modules.symbols
lib/modules/2.6.30.9-96.fc11.x86_64/modules.alias.bin
lib/modules/2.6.30.9-96.fc11.x86_64/modules.alias
lib/modules/2.6.30.9-96.fc11.x86_64/modules.symbols.bin
lib/modules/2.6.30.9-96.fc11.x86_64/modules.ofmap
lib/modules/2.6.30.9-96.fc11.x86_64/modules.pcimap
lib/modules/2.6.30.9-96.fc11.x86_64/modules.dep
lib/modules/2.6.30.9-96.fc11.x86_64/modules.isapnpmap
lib/modules/2.6.30.9-96.fc11.x86_64/modules.dep.bin
lib/modules/2.6.30.9-96.fc11.x86_64/modules.usbmap
lib/modules/2.6.30.9-96.fc11.x86_64/modules.ccwmap
lib/modules/2.6.30.9-96.fc11.x86_64/modules.seriomap
lib/modules/2.6.30.9-96.fc11.x86_64/modules.inputmap
lib/modules/2.6.30.9-96.fc11.x86_64/modules.ieee1394map
lib/firmware
lib/udev
lib/udev/console_init
sysroot
dev
dev/ttyS1
dev/tty6
dev/tty12
dev/tty9
dev/ptmx
dev/tty2
dev/tty
dev/ttyS0
dev/mapper
dev/ttyS2
dev/tty1
dev/tty3
dev/tty0
dev/console
dev/tty4
dev/ttyS3
dev/ram0
dev/tty5
dev/null
dev/zero
dev/systty
dev/ram1
dev/tty10
dev/tty11
dev/ram
dev/tty8
dev/tty7
proc
16476 blocks


As you can see the script interpreter is nash.

Here is the init script which nash uses to start the boot process.

#!/bin/nash

mount -t proc /proc /proc
setquiet
echo Mounting proc filesystem
echo Mounting sysfs filesystem
mount -t sysfs /sys /sys
echo Creating /dev
mount -o mode=0755 -t tmpfs /dev /dev
mkdir /dev/pts
mount -t devpts -o gid=5,mode=620 /dev/pts /dev/pts
mkdir /dev/shm
mkdir /dev/mapper
echo Creating initial device nodes
mknod /dev/null c 1 3
mknod /dev/zero c 1 5
mknod /dev/systty c 4 0
mknod /dev/tty c 5 0
mknod /dev/console c 5 1
mknod /dev/ptmx c 5 2
mknod /dev/fb c 29 0
mknod /dev/hvc0 c 229 0
mknod /dev/tty0 c 4 0
mknod /dev/tty1 c 4 1
mknod /dev/tty2 c 4 2
mknod /dev/tty3 c 4 3
mknod /dev/tty4 c 4 4
mknod /dev/tty5 c 4 5
mknod /dev/tty6 c 4 6
mknod /dev/tty7 c 4 7
mknod /dev/tty8 c 4 8
mknod /dev/tty9 c 4 9
mknod /dev/tty10 c 4 10
mknod /dev/tty11 c 4 11
mknod /dev/tty12 c 4 12
mknod /dev/ttyS0 c 4 64
mknod /dev/ttyS1 c 4 65
mknod /dev/ttyS2 c 4 66
mknod /dev/ttyS3 c 4 67
daemonize --ignore-missing /bin/plymouthd
echo Setting up hotplug.
hotplug
/lib/udev/console_init tty0
plymouth --show-splash
echo Creating block device nodes.
mkblkdevs
echo Creating character device nodes.
mkchardevs
echo Making device-mapper control node
mkdmnod
modprobe scsi_wait_scan
rmmod scsi_wait_scan
mkblkdevs
echo Scanning logical volumes
lvm vgscan --ignorelockingfailure
echo Activating logical volumes
lvm vgchange -ay --ignorelockingfailure  vg_ultra
resume /dev/mapper/vg_ultra-lv_swap
echo Creating root device.
mkrootdev -t ext4 -o defaults,ro /dev/mapper/vg_ultra-lv_root
echo Mounting root filesystem.
mount /sysroot
cond -ne 0 plymouth --hide-splash
echo Setting up other filesystems.
setuproot
loadpolicy
plymouth --newroot=/sysroot
echo Switching to new root and running init.
switchroot
echo Booting has failed.
sleep -1


In Fedora 12, /sbin/mkinitrd is not available and the shell script /sbin/dracut must be used to build an initramfs file. Like mkinitrd, this script has numerous options but you will probably never need to use most of them. Like mkinitrd, the script creates a series of subdirectories and populates them with assorted files using various Dracut modules from the /usr/share/dracut/modules.d subdirectories. Finally, it uses the following command line to create the image file:

( cd "$initdir"; find . |cpio -R 0:0 -H newc -o --quiet |gzip -9 > "$outfile"; )


Here is the contents of a functionally equivalent initramfs built on Fedora 11 using /sbin/dracut instead of /sbin/mkinitrd:

init
initqueue-settled
pre-udev
pre-udev/30block-genrules.sh
pre-udev/30resume-genrules.sh
pre-pivot
pre-pivot/31crypt-cleanup.sh
pre-pivot/50selinux-loadpolicy.sh
pre-pivot/30crypt-cleanup.sh
pre-pivot/90plymouth-newroot.sh
tmp
dracut-002-9.git99fd62e3.fc11
var
var/run
sbin
sbin/initqueue
sbin/cryptsetup
sbin/switch_root
sbin/pidof
sbin/modprobe
sbin/lvm_scan
sbin/udevd
sbin/lvm-cleanup
sbin/rmmod
sbin/lvm
sbin/udevadm
sbin/cryptroot-ask
initqueue
etc
etc/sysconfig
etc/sysconfig/i18n
etc/sysconfig/keyboard
etc/udev
etc/udev/rules.d
etc/udev/rules.d/64-lvm.rules
etc/udev/rules.d/59-persistent-storage-volid.rules
etc/udev/rules.d/61-persistent-storage.rules
etc/udev/rules.d/95-udev-late.rules
etc/udev/rules.d/80-drivers.rules
etc/udev/rules.d/01-ignore.rules
etc/udev/rules.d/60-pcmcia.rules
etc/udev/rules.d/61-persistent-storage-edd.rules
etc/udev/rules.d/50-firmware.rules
etc/udev/rules.d/60-persistent-storage.rules
etc/udev/rules.d/70-luks.rules
etc/udev/rules.d/10-console.rules
etc/udev/rules.d/50-udev-default.rules
etc/udev/udev.conf
etc/lvm
etc/lvm/lvm.conf
etc/modprobe.d
etc/modprobe.d/dist-oss.conf
etc/modprobe.d/blacklist-visor.conf
etc/modprobe.d/ipv6.conf
etc/modprobe.d/blacklist.conf
etc/modprobe.d/blacklist-nouveau.conf
etc/modprobe.d/floppy-pnp.conf
etc/modprobe.d/dist.conf
etc/modprobe.d/anaconda.conf
etc/fedora-release
etc/system-release
etc/group
initqueue-finished
usr
usr/sbin
usr/sbin/chroot
usr/lib64
usr/lib64/libusb-0.1.so.4
usr/lib64/plymouth
usr/lib64/plymouth/details.so
usr/lib64/plymouth/text.so
usr/lib64/libpng12.so.0.37.0
usr/lib64/libpng12.so.0
usr/lib64/libplybootsplash.so.2.0.0
usr/lib64/libplybootsplash.so.2
usr/lib64/libusb-0.1.so.4.4.4
usr/bin
usr/bin/flock
usr/lib
usr/share
usr/share/plymouth
usr/share/plymouth/bizcom.png
usr/share/plymouth/themes
usr/share/plymouth/themes/details
usr/share/plymouth/themes/details/details.plymouth
usr/share/plymouth/themes/text
usr/share/plymouth/themes/text/text.plymouth
usr/share/plymouth/themes/default.plymouth
sys
emergency
emergency/50plymouth-emergency.sh
lib64
lib64/libgpg-error.so.0.4.0
lib64/libpopt.so.0.0.0
lib64/libnss_files-2.10.1.so
lib64/libz.so.1
lib64/libpthread.so.0
lib64/libattr.so.1.1.0
lib64/libc.so.6
lib64/libpthread-2.10.1.so
lib64/libuuid.so.1
lib64/libvolume_id.so.1
lib64/libpopt.so.0
lib64/libz.so.1.2.3
lib64/libtinfo.so.5.7
lib64/libudev.so.0
lib64/librt.so.1
lib64/libreadline.so.5
lib64/libcryptsetup.so.0.0.0
lib64/libdl-2.10.1.so
lib64/libglib-2.0.so.0
lib64/libreadline.so.5.2
lib64/libm.so.6
lib64/libvolume_id.so.1.1.0
lib64/libacl.so.1
lib64/librt-2.10.1.so
lib64/libtinfo.so.5
lib64/libuuid.so.1.2
lib64/libcap.so.2
lib64/libgcrypt.so.11
lib64/libglib-2.0.so.0.2000.5
lib64/libudev.so.0.2.0
lib64/libply.so.2.0.0
lib64/libacl.so.1.1.0
lib64/libselinux.so.1
lib64/libply.so.2
lib64/libcryptsetup.so.0
lib64/libblkid.so.1.0
lib64/libgcrypt.so.11.5.2
lib64/libblkid.so.1
lib64/libsepol.so.1
lib64/libc-2.10.1.so
lib64/libcap.so.2.16
lib64/libm-2.10.1.so
lib64/libdl.so.2
lib64/ld-linux-x86-64.so.2
lib64/libattr.so.1
lib64/ld-2.10.1.so
lib64/libdevmapper.so.1.02
lib64/libgpg-error.so.0
lib64/libnss_files.so.2
bin
bin/setfont
bin/cp
bin/loadkeys
bin/plymouth
bin/uname
bin/ln
bin/mkdir
bin/cat
bin/rm
bin/plymouthd
bin/sleep
bin/basename
bin/sh
bin/mknod
bin/ls
bin/mount
bin/mv
bin/sed
bin/dmesg
bin/dash
mount
mount/99mount-root.sh
mount/10resume.sh
lib
lib/dracut-lib.sh
lib/kbd
lib/kbd/consolefonts
lib/kbd/consolefonts/latarcyrheb-sun16.psfu
lib/kbd/keymaps
lib/kbd/keymaps/i386
lib/kbd/keymaps/i386/include
lib/kbd/keymaps/i386/include/linux-with-alt-and-altgr.inc
lib/kbd/keymaps/i386/include/linux-keys-bare.inc
lib/kbd/keymaps/i386/include/euro1.map
lib/kbd/keymaps/i386/include/compose.inc
lib/kbd/keymaps/i386/include/qwerty-layout.inc
lib/kbd/keymaps/i386/qwerty
lib/kbd/keymaps/i386/qwerty/us.map
lib/kbd/keymaps/include
lib/kbd/keymaps/include/compose.latin4
lib/kbd/keymaps/include/compose.8859_8
lib/kbd/keymaps/include/compose.latin1
lib/kbd/keymaps/include/compose.latin3
lib/kbd/keymaps/include/compose.8859_7
lib/kbd/keymaps/include/compose.latin2
lib/kbd/keymaps/include/compose.latin
lib/modules
lib/modules/2.6.30.9-96.fc11.x86_64
lib/modules/2.6.30.9-96.fc11.x86_64/modules.symbols
lib/modules/2.6.30.9-96.fc11.x86_64/modules.alias.bin
lib/modules/2.6.30.9-96.fc11.x86_64/modules.alias
lib/modules/2.6.30.9-96.fc11.x86_64/modules.symbols.bin
lib/modules/2.6.30.9-96.fc11.x86_64/modules.ofmap
lib/modules/2.6.30.9-96.fc11.x86_64/modules.pcimap
lib/modules/2.6.30.9-96.fc11.x86_64/modules.dep
lib/modules/2.6.30.9-96.fc11.x86_64/modules.isapnpmap
lib/modules/2.6.30.9-96.fc11.x86_64/modules.dep.bin
lib/modules/2.6.30.9-96.fc11.x86_64/modules.usbmap
lib/modules/2.6.30.9-96.fc11.x86_64/modules.ccwmap
lib/modules/2.6.30.9-96.fc11.x86_64/modules.seriomap
lib/modules/2.6.30.9-96.fc11.x86_64/kernel
lib/modules/2.6.30.9-96.fc11.x86_64/kernel/drivers
lib/modules/2.6.30.9-96.fc11.x86_64/kernel/drivers/i2c
lib/modules/2.6.30.9-96.fc11.x86_64/kernel/drivers/i2c/algos
lib/modules/2.6.30.9-96.fc11.x86_64/kernel/drivers/i2c/algos/i2c-algo-bit.ko
lib/modules/2.6.30.9-96.fc11.x86_64/kernel/drivers/i2c/i2c-core.ko
lib/modules/2.6.30.9-96.fc11.x86_64/kernel/drivers/scsi
lib/modules/2.6.30.9-96.fc11.x86_64/kernel/drivers/scsi/scsi_wait_scan.ko
lib/modules/2.6.30.9-96.fc11.x86_64/kernel/drivers/gpu
lib/modules/2.6.30.9-96.fc11.x86_64/kernel/drivers/gpu/drm
lib/modules/2.6.30.9-96.fc11.x86_64/kernel/drivers/gpu/drm/drm.ko
lib/modules/2.6.30.9-96.fc11.x86_64/kernel/drivers/gpu/drm/nouveau
lib/modules/2.6.30.9-96.fc11.x86_64/kernel/drivers/gpu/drm/nouveau/nouveau.ko
lib/modules/2.6.30.9-96.fc11.x86_64/modules.inputmap
lib/modules/2.6.30.9-96.fc11.x86_64/modules.ieee1394map
lib/udev
lib/udev/edd_id
lib/udev/hid2hci
lib/udev/vol_id
lib/udev/firmware.sh
lib/udev/usb_id
lib/udev/ata_id
lib/udev/pcmcia-socket-startup
lib/udev/rules.d
lib/udev/fw_unit_symlinks.sh
lib/udev/pcmcia-check-broken-cis
lib/udev/scsi_id
lib/udev/console_init
lib/udev/path_id
lib/udev/create_floppy_devices
lib/udev/cdrom_id
lib/terminfo
lib/terminfo/d
lib/terminfo/d/dumb
lib/terminfo/a
lib/terminfo/a/ansi
lib/terminfo/l
lib/terminfo/l/linux
lib/terminfo/v
lib/terminfo/v/vt100-nav
lib/terminfo/v/vt100
lib/terminfo/v/vt200
lib/terminfo/v/vt102
lib/terminfo/v/vt100-am
lib/terminfo/v/vt52
lib/terminfo/v/vt220
cmdline
cmdline/30parse-lvm.sh
cmdline/01version.sh
cmdline/10parse-root-opts.sh
cmdline/30parse-crypt.sh
cmdline/20parse-blacklist.sh
cmdline/95parse-block.sh
cmdline/20parse-i18n.sh
cmdline/10parse-resume.sh
pre-trigger
pre-trigger/10plymouth-pretrigger.sh
sysroot
dev
dev/pts
proc


Note that the nash script interpreter is not part of the initramfs image. Instead /bin/dash is included. The following is the contents of the init script from this initramfs. As you can see it is significantly different from the init script included in the initramfs built using /sbin/mkinitrd.

#!/bin/sh
#
# Licensed under the GPLv2
#
# Copyright 2008, Red Hat, Inc.
# Jeremy Katz 

emergency_shell()
{
    exec >/dev/console 2>&1 </dev/console
    echo ; echo
    echo $@
    source_all emergency
    echo
    if getarg rdshell || getarg rdbreak; then
        echo "Dropping to debug shell."
        echo
        sh -i
    else
        echo "Boot has failed, sleeping forever."
        while :; do sleep 365d;done
    fi
}

export PATH=/sbin:/bin:/usr/sbin:/usr/bin
export TERM=linux
NEWROOT="/sysroot"

trap "emergency_shell Signal caught!" 0

. /lib/dracut-lib.sh

mknod /dev/null c 1 3

# mount some important things
mount -t proc /proc /proc >/dev/null 2>&1
mount -t sysfs /sys /sys >/dev/null 2>&1
if [ ! -c /dev/ptmx ]; then
    # try to mount devtmpfs
    if ! mount -t devtmpfs -omode=0755 udev /dev >/dev/null 2>&1; then
        # if it failed fall back to normal tmpfs
        mount -t tmpfs -omode=0755 udev /dev >/dev/null 2>&1
        # Make some basic devices first, let udev handle the rest
        mknod /dev/null c 1 3
        mknod /dev/ptmx c 5 2
        mknod /dev/console c 5 1
        mknod /dev/kmsg c 1 11
    fi
fi

if getarg rdinitdebug; then
    set -x
fi

mkdir /dev/shm
mkdir /dev/pts
mount -t devpts -o gid=5,mode=620 /dev/pts /dev/pts >/dev/null 2>&1

UDEVVERSION=$(udevadm --version)

source_conf /etc/conf.d
# run scriptlets to parse the command line
getarg 'rdbreak=cmdline' && emergency_shell "Break before cmdline"
source_all cmdline

[ -z "$root" ] && die "No or empty root= argument"
[ -z "$rootok" ] && die "Don't know how to handle 'root=$root'"

# Network root scripts may need updated root= options,
# so deposit them where they can see them (udev purges the env)
{
    echo "root='$root'"
    echo "rflags='$rflags'"
    echo "fstype='$fstype'"
    echo "netroot='$netroot'"
    echo "NEWROOT='$NEWROOT'"
} > /tmp/root.info

# pre-udev scripts run before udev starts, and are run only once.
getarg 'rdbreak=pre-udev' && emergency_shell "Break before pre-udev"
source_all pre-udev

# start up udev and trigger cold plugs
udevd --daemon

UDEV_LOG_PRIO_ARG=--log-priority
UDEV_QUEUE_EMPTY="udevadm settle --timeout=0"

if [ $UDEVVERSION -lt 140 ]; then
   UDEV_LOG_PRIO_ARG=--log_priority
   UDEV_QUEUE_EMPTY="udevadm settle --timeout=1"
fi

getarg rdudevinfo && udevadm control $UDEV_LOG_PRIO_ARG=info
getarg rdudevdebug && udevadm control $UDEV_LOG_PRIO_ARG=debug

getarg 'rdbreak=pre-trigger' && emergency_shell "Break before pre-trigger"
source_all pre-trigger
# then the rest
udevadm trigger $udevtriggeropts  >/dev/null 2>&1

getarg 'rdbreak=initqueue' && emergency_shell "Break before initqueue"

i=0
while :; do

    check_finished && break

    udevsettle

    check_finished && break

    if [ -f /initqueue/work ]; then
        rm /initqueue/work
    fi

    for job in /initqueue/*.sh; do
        [ -e "$job" ] || break
        job=$job . $job
        check_finished && break 2
    done

    $UDEV_QUEUE_EMPTY >/dev/null 2>&1 || continue

    modprobe scsi_wait_scan && rmmod scsi_wait_scan

    $UDEV_QUEUE_EMPTY >/dev/null 2>&1 || continue

    for job in /initqueue-settled/*.sh; do
        [ -e "$job" ] || break
        job=$job . $job
        check_finished && break 2
    done

    $UDEV_QUEUE_EMPTY >/dev/null 2>&1 || continue

    # no more udev jobs and queues empty.
    sleep 0.5
    i=$(($i+1))
    [ $i -gt 20 ] \
        && { flock -s 9 ; emergency_shell "No root device found"; } 9>/.console_lock
done
unset job
unset queuetriggered

# pre-mount happens before we try to mount the root filesystem,
# and happens once.
getarg 'rdbreak=pre-mount' && emergency_shell "Break pre-mount"
source_all pre-mount

getarg 'rdbreak=mount' && emergency_shell "Break mount"
# mount scripts actually try to mount the root filesystem, and may
# be sourced any number of times. As soon as one suceeds, no more are sourced.
i=0
while :; do
    [ -d "$NEWROOT/proc" ] && break;
    for f in /mount/*.sh; do
       [ -f "$f" ] && . "$f"
       [ -d "$NEWROOT/proc" ] && break;
    done

    i=$(($i+1))
    [ $i -gt 20 ] \
        && { flock -s 9 ; emergency_shell "Can't mount root filesystem"; } 9>/.console_lock
done

{
    echo -n "Mounted root filesystem "
    while read dev mp rest; do [ "$mp" = "$NEWROOT" ] && echo $dev; done < /proc/mounts
} | vinfo

getarg 'rdbreak=pre-pivot' && emergency_shell "Break pre-pivot"
source_all pre-pivot

# by the time we get here, the root filesystem should be mounted.
# Try to find init.
for i in "$(getarg init=)" /sbin/init /etc/init /init /bin/sh; do
    [ -f "$NEWROOT$i" -a -x "$NEWROOT$i" ] && { INIT="$i"; break; }
done

[ "$INIT" ] || {
    echo "Cannot find init!"
    echo "Please check to make sure you passed a valid root filesystem!"
    emergency_shell
}

getarg rdbreak && emergency_shell "Break before switch_root"

HARD=""
while pidof udevd >/dev/null 2>&1; do
    for pid in $(pidof udevd); do
        kill $HARD $pid >/dev/null 2>&1
    done
    HARD="-9"
done

# Clean up the environment
for i in $(export -p); do
    i=${i#declare -x}
    i=${i#export}
    i=${i%%=*}
    [ "$i" = "root" -o "$i" = "PATH" -o "$i" = "HOME" -o "$i" = "TERM" ] || unset $i
done

initargs=""

if getarg init= >/dev/null ; then
    ignoreargs="console BOOT_IMAGE"
    # only pass arguments after init= to the init
    read CLINE </proc/cmdline
    CLINE=${CLINE#*init=}
    set $CLINE
    for x in "$@"; do
        for s in $ignoreargs; do
            [ "${x%%=*}" = $s ] && continue 2
        done
        initargs="$initargs $x"
    done
    unset CLINE
fi

# Prepare network opts for passing
if [ -e /tmp/net.ifaces ]; then
    mkdir /dev/.initramfs/
    cp /tmp/net.* /dev/.initramfs/ >/dev/null 2>&1
    mkdir -p /dev/.initramfs/state/etc/sysconfig/network-scripts/
    cp /tmp/resolv.conf /dev/.initramfs/state/etc/ >/dev/null 2>&1
    echo "files /etc/sysconfig/network-scripts" > /dev/.initramfs/rwtab
    cp -a /tmp/ifcfg/* /dev/.initramfs/state/etc/sysconfig/network-scripts/ >/dev/null 2>&1
fi

# Debug: Copy state
if getarg rdcopystate; then
    cp /tmp/* /dev/.initramfs/ >/dev/null 2>&1
fi

info "Switching root"

exec switch_root "$NEWROOT" "$INIT" $initargs || {
    echo "Something went very badly wrong in the initramfs.  Please "
    echo "file a bug against dracut."
    emergency_shell
}


Note the use of udev to discover devices, the use of /sysroot for mounting filesystems, and how breakpoints are handled. The purpose of the /sbin/switch_root executable is similar to the switchroot command in nash. Basically it changes the current directory to /, removes a lot of temporary subdirectories, chroots . and exec’s the init process.

Well, hopefully I have covered Dracut in sufficient detail to enable you to understand what has changed in Fedora 12 with respect to the boot process and building an initramfs file. The changes are significant and I expect that it will be a while before all the corner cases are found and fixed. If I have missed anything important regarding Dracut in this post, please add the information via a comment so that others can share in the knowledge.
 

Comments are closed.