<?xml version="1.0"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
	<channel>
		<title>SlackWiki - User contributions [en]</title>
		<link>https://www.slackwiki.com/Special:Contributions/Foobarz</link>
		<description>User contributions</description>
		<language>en</language>
		<generator>MediaWiki 1.40.0</generator>
		<lastBuildDate>Sat, 23 May 2026 17:09:19 GMT</lastBuildDate>
		<item>
			<title>ZFS root (builtin)</title>
			<link>https://www.slackwiki.com/index.php?title=ZFS_root_(builtin)&amp;diff=805</link>
			<guid isPermaLink="false">https://www.slackwiki.com/index.php?title=ZFS_root_(builtin)&amp;diff=805</guid>
			<description>&lt;p&gt;Foobarz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Tutorials]]&lt;br /&gt;
The first [http://slackwiki.com/ZFS_root &amp;quot;ZFS root&amp;quot;] wiki explains the details of running ZFS as your root filesystem by using a fully modular generic kernel approach. Now, I can share how it can be done with the SPL and ZFS modules built into the kernel. This procedure is just an example and can use some fine tuning, but here goes:&lt;br /&gt;
&lt;br /&gt;
The steps below are to create a kernel with SPL and ZFS modules builtin. This kernel will be installed as an alternative kernel to boot in lilo, and it will have a separate kernel installation from the fully modular and working system kernel. This will allow testing the builtin kernel while able to boot back onto a working modular ZFS system. We start this procedure assuming you are on a working fully modular ZFS install as in the &amp;quot;ZFS root&amp;quot; wiki.&lt;br /&gt;
&lt;br /&gt;
Use mountpoint=legacy so that zfs will not expect &amp;lt;code&amp;gt;zfs mount&amp;lt;/code&amp;gt;, but instead expect standard &amp;lt;code&amp;gt;mount&amp;lt;/code&amp;gt; for mounting zfs-root:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=legacy zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Edit &amp;lt;code&amp;gt;/etc/rc.d/rc.S&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;rc.6&amp;lt;/code&amp;gt; to use regular &amp;lt;code&amp;gt;mount&amp;lt;/code&amp;gt; commands, remove &amp;lt;code&amp;gt;zfs&amp;lt;/code&amp;gt; commands. Edit &amp;lt;code&amp;gt;rc.6&amp;lt;/code&amp;gt; and remove or comment out &amp;lt;code&amp;gt;zpool export&amp;lt;/code&amp;gt; command. These edits undo changes made in the &amp;quot;ZFS root&amp;quot; wiki, but it shows the two different ways of mounting a zfs filesystem.&lt;br /&gt;
&lt;br /&gt;
You &amp;lt;i&amp;gt;might&amp;lt;/i&amp;gt; think to set &amp;lt;code&amp;gt;bootfs&amp;lt;/code&amp;gt; property like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool set bootfs=zfs-root zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
However, this will result in ZFS placing many restrictions on zfs-root as per how that option is used on Solaris systems:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; zfs-root must be VTOC (SMI) label, not GPT (EFI) label&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; zfs-root can only contain 1 vdev: either a plain disk, or a mirror&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
So, do &amp;lt;b&amp;gt;NOT&amp;lt;/b&amp;gt; set that property! If &amp;lt;code&amp;gt;bootfs&amp;lt;/code&amp;gt; is set, you would find that you cannot add vdevs to your zfs-root. If it is set already, then unset it like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool set bootfs= zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Make a directory to store files to be inside the initramfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkdir /boot/initramfs-source&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This directory will hold some files for the initial rootfs inside the kernel. Your &amp;lt;code&amp;gt;/boot&amp;lt;/code&amp;gt; should be on a small ext4 partition or on a mounted USB stick that you use to boot.&lt;br /&gt;
&lt;br /&gt;
Extract the slackware kernel-source package to obtain a copy of the kernel source, and make an initial kernel config for it:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir src&lt;br /&gt;
cd src&lt;br /&gt;
tar xvzf /mnt/cdrom/slackware64/k/kernel-source-*.txz&lt;br /&gt;
mv usr/src/linux-3.2.29 /usr/src/linux-3.2.29b&lt;br /&gt;
rm -r install&lt;br /&gt;
cd /usr/src/linux-3.2.29b&lt;br /&gt;
make menuconfig&lt;br /&gt;
  General setup-&amp;gt;Local version - append to kernel release = b&lt;br /&gt;
  General setup-&amp;gt;Default hostname                         = slackzfs&lt;br /&gt;
  General setup-&amp;gt;Initramfs source files(s)                = /boot/initramfs-source&lt;br /&gt;
  Device Drivers-&amp;gt;SCSI device support-&amp;gt;SCSI low-level drivers-&amp;gt; &amp;lt;*&amp;gt; SYM53C8XX Version 2 SCSI support&lt;br /&gt;
  File systems -&amp;gt; &amp;lt;*&amp;gt; The Extended 4 (ext4) filesystem&lt;br /&gt;
  # build in any hard drive controllers and filesystems that you need for booting&lt;br /&gt;
  # then save the config&lt;br /&gt;
make prepare scripts&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The kernel source has been set to have a &amp;quot;Local version&amp;quot; &amp;lt;code&amp;gt;b&amp;lt;/code&amp;gt;. This will result in modules installed to &amp;lt;code&amp;gt;/lib/modules/3.2.29b&amp;lt;/code&amp;gt; and keeps this kernel's source and modules seperate from slackware's kernel-generic package installation. The &amp;lt;code&amp;gt;make prepare scripts&amp;lt;/code&amp;gt; command readies the kernel source as needed before we can install a copy of spl and zfs modules into the kernel source tree.&lt;br /&gt;
&lt;br /&gt;
Now proceed to configure and copy spl and zfs into the kernel source tree:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd ~/src&lt;br /&gt;
tar xvzf ~/spl-0.6.0-rc11.tar.gz&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-0.6.0-rc11&lt;br /&gt;
./configure \&lt;br /&gt;
    --prefix=/ \&lt;br /&gt;
    --libdir=/lib64 \&lt;br /&gt;
    --includedir=/usr/include \&lt;br /&gt;
    --datarootdir=/usr/share \&lt;br /&gt;
    --enable-linux-builtin=yes \&lt;br /&gt;
    --with-linux=/usr/src/linux-3.2.29b \&lt;br /&gt;
    --with-linux-obj=/usr/src/linux-3.2.29b&lt;br /&gt;
./copy-builtin /usr/src/linux-3.2.29b&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../spl-0.6.0rc11_3.2.29b-x86_64-1root.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
&lt;br /&gt;
tar xvzf ~/zfs-0.6.0-rc11.tar.gz&lt;br /&gt;
mkdir install&lt;br /&gt;
cd zfs-0.6.0-rc11&lt;br /&gt;
./configure \&lt;br /&gt;
    --prefix=/ \&lt;br /&gt;
    --libdir=/lib64 \&lt;br /&gt;
    --includedir=/usr/include \&lt;br /&gt;
    --datarootdir=/usr/share \&lt;br /&gt;
    --enable-linux-builtin=yes \&lt;br /&gt;
    --with-linux=/usr/src/linux-3.2.29b \&lt;br /&gt;
    --with-linux-obj=/usr/src/linux-3.2.29b \&lt;br /&gt;
    --with-spl=/root/src/spl-0.6.0-rc11&lt;br /&gt;
    --with-spl-obj=/root/src/spl-0.6.0-rc11&lt;br /&gt;
./copy-builtin /usr/src/linux-3.2.29b&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../zfs-0.6.0rc11_3.2.29b-x86_64-1root.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
At this point, the &amp;lt;code&amp;gt;copy-builtin&amp;lt;/code&amp;gt; scripts have installed the configured spl and zfs modules source into the kernel source. The regular &amp;lt;code&amp;gt;make menuconfig&amp;lt;/code&amp;gt; in the kernel source should now show options for spl and zfs in the kernel config.&lt;br /&gt;
&lt;br /&gt;
As of this writing, the copy-builtin script places the spl and zfs modules into the kernel source in places where the modules may not initialize in the best order, &amp;lt;i&amp;gt;after&amp;lt;/i&amp;gt; all lower-level storage drivers are initialized. If spl and zfs initialize too soon, there is a chance they may not be able to see all of the storage devices. The order of initialization (as seen in dmesg) of modules that are builtin to the kernel is the order that the modules are linked into the kernel during kernel compilation. The order of link depends on where the module source files are located in the kernel source tree. To ensure that spl and zfs will initialize after all hardware drivers, we can move them into the &amp;lt;code&amp;gt;drivers&amp;lt;/code&amp;gt; tree and after all other drivers. This move is &amp;lt;b&amp;gt;optional&amp;lt;/b&amp;gt; and you can skip doing this and everything will probably work fine, but it is shown here how to move the modules to under drivers in case you prefer them there:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /usr/src/linux-3.2.29b&lt;br /&gt;
mkdir drivers/zfsonlinux&lt;br /&gt;
mv spl drivers/zfsonlinux&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  # remove references to spl&lt;br /&gt;
vi Makefile&lt;br /&gt;
  # remove references to spl&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.29b/fs&lt;br /&gt;
mv zfs ../drivers/zfsonlinux&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  # remove references to zfs&lt;br /&gt;
vi Makefile&lt;br /&gt;
  # remove references to zfs&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.29b/drivers&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  )# add line at end of menu, before &amp;quot;endmenu&amp;quot;:&lt;br /&gt;
  )source &amp;quot;drivers/zfsonlinux/Kconfig&amp;quot;&lt;br /&gt;
  )endmenu&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.29b/drivers&lt;br /&gt;
vi Makefile&lt;br /&gt;
  )# add line at very end of file:&lt;br /&gt;
  )obj-$(CONFIG_ZFSONLINUX) += zfsonlinux/&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.29b/drivers/zfsonlinux&lt;br /&gt;
cat &amp;gt; Kconfig &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
menuconfig ZFSONLINUX&lt;br /&gt;
	tristate &amp;quot;ZFSonLinux support&amp;quot;&lt;br /&gt;
&lt;br /&gt;
if ZFSONLINUX&lt;br /&gt;
&lt;br /&gt;
source &amp;quot;drivers/zfsonlinux/spl/Kconifg&amp;quot;&lt;br /&gt;
&lt;br /&gt;
source &amp;quot;drivers/zfsonlinux/zfs/Kconifg&amp;quot;&lt;br /&gt;
&lt;br /&gt;
endif&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.29b/zfsonlinux&lt;br /&gt;
cat &amp;gt; Makefile &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
obj-$(CONFIG_SPL) += spl/&lt;br /&gt;
obj-$(CONFIG_ZFS) += zfs/&lt;br /&gt;
EOF&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This completes the move of the spl and zfs modules in the kernel source tree to be under &amp;lt;code&amp;gt;drivers/zfsonlinux&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Now, in kernel configuration, you can build in the modules as follows:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /usr/src/linux-3.2.29b&lt;br /&gt;
make menuconfig&lt;br /&gt;
   Device Drivers -&amp;gt;&lt;br /&gt;
    &amp;lt;*&amp;gt; ZFSonLinux support -&amp;gt;&lt;br /&gt;
      &amp;lt;*&amp;gt; Solaris Porting Layer (SPL)&lt;br /&gt;
      &amp;lt;*&amp;gt;     ZFS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the kernel config, we set &amp;lt;code&amp;gt;/boot/initramfs-source&amp;lt;/code&amp;gt; as source location of the contents to be linked into kernel's builtin initramfs (rootfs). Now, we create some files that are needed to be in the initramfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /boot/initramfs-source&lt;br /&gt;
&lt;br /&gt;
# make standard directories&lt;br /&gt;
mkdir -p proc dev sys mnt bin sbin etc/zfs&lt;br /&gt;
&lt;br /&gt;
# zfs seems to want mtab present, even if empty&lt;br /&gt;
touch etc/mtab&lt;br /&gt;
&lt;br /&gt;
# if zpool.cache file can be read by zfs at module init, it imports the pools in the cache&lt;br /&gt;
cp /etc/zfs/zpool.cache-initrd etc/zfs/zpool.cache&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
It is time to pause for a moment here and talk about zpool.cache: Using it is actually dangerous. We are not using udev and it's persistent block device filenames (/dev/disk/by-*), but are using the default kernel block device names (/dev/sd*) in devtmpfs. Device names for a hard drive in /dev can potentially change on boot depending on disk controller initialization order and disk drive response time. Adding another disk controller or hard disk on a controller can result in device name assignment changes to all the hard disks. A zpool.cache file holds all the zfs_member device filenames /dev/sd* for a pool configuration, but the zpool.cache configuration will be incorrect if device filenames have been changed or swapped around and this could result in a faulted pool that may or may not be recoverable. Using zpool.cache to import pools at boot, even with udev persistent device filenames, is potentially destructive if devices have been changed around. The proper thing to do is zpool_import and do not include zpool.cache in the initramfs.&lt;br /&gt;
&lt;br /&gt;
Now, let's continue making some files in the initramfs-source:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# make initial console device node; otherwise, there is a problem at startup:&lt;br /&gt;
# &amp;quot;Warning: unable to open an initial console&amp;quot; and you'd have problems with console and tty login&lt;br /&gt;
# making these nodes from within /init is not early enough to avoid problem&lt;br /&gt;
mknod dev/console c 5 1   # system console&lt;br /&gt;
&lt;br /&gt;
# make memory device kmsg to &amp;quot;printk&amp;quot; kernel messages&lt;br /&gt;
# we can write to this file to send out messages&lt;br /&gt;
mknod dev/kmsg    c 1 11  # lines printed to kmsg enter kernel messages buffer&lt;br /&gt;
&lt;br /&gt;
# recommended loop0 device to mount fs images&lt;br /&gt;
mknod dev/loop0   b 7 0&lt;br /&gt;
&lt;br /&gt;
# make initial virtual terminal devices&lt;br /&gt;
mknod dev/tty     c 5 0   # current tty&lt;br /&gt;
mknod dev/tty0    c 4 0   # current virtual term&lt;br /&gt;
mknod dev/tty1    c 4 1   # login virtual term 1 (F1)&lt;br /&gt;
&lt;br /&gt;
# make alternative console=ttyS0 standard 8250/16550 UART serial port devices&lt;br /&gt;
#   useful with kernel parameter console=ttyS0&lt;br /&gt;
#          with qemu -nographic -option-rom sgabios.bin,bootindex=0&lt;br /&gt;
mknod dev/ttyS0   c 4 64  # COM1&lt;br /&gt;
mknod dev/ttyS1   c 4 65  # COM2&lt;br /&gt;
mknod dev/ttyS2   c 4 66  # COM3&lt;br /&gt;
mknod dev/ttyS3   c 4 67  $ COM4&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This should be enough device nodes initially in the initramfs. Once devtmpfs mounts over /dev inside initramfs, a lot more devices are available in it by default.&lt;br /&gt;
&lt;br /&gt;
The initramfs needs an &amp;lt;code&amp;gt;/init&amp;lt;/code&amp;gt; program that will be run automatically by the kernel as process id 1, the first program to run on the system. This program's task is to mount a root filesystem, switch it to be the new root (/), and then exec the init (&amp;lt;code&amp;gt;/sbin/init&amp;lt;/code&amp;gt;) program that is on the new root so that the new root system is booted.&lt;br /&gt;
&lt;br /&gt;
The common way to make /init is using busybox with files like these in /boot/initrd-tree or /boot/initramfs-source:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
bin/busybox&lt;br /&gt;
bin/ash -&amp;gt; busybox&lt;br /&gt;
bin/sh -&amp;gt; busybox&lt;br /&gt;
# run busybox to see what other &amp;quot;applets&amp;quot; can be symlinked to it&lt;br /&gt;
# when busybox is run as a different symlinked applet name, it runs as the applet&lt;br /&gt;
init&lt;br /&gt;
# init can be an ash script, see slackware's /boot/initrd-tree/init for example&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For example, as an ash script, slackware's init does the following:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;parse kernel parameters passed into it and set variables based on them&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;start udevd and trigger rules for block devices to setup initial /dev devices&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;load kernel modules and keyboard map&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;run mdadm, cryptsetup, lvm, zpool/zfs to setup more devices&lt;br /&gt;
     (any udev rules for them should do more /dev setup in the background)&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;mount the root filesystem read-only at /mnt&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;stat /mnt/sbin/init, and if not executable run a rescue shell /bin/sh&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;shutdown udevd so it can be restarted by root system when booted&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;mount --move {proc,sys,run,dev} to under /mnt&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;run: exec switch_root /mnt /sbin/init $RUNLEVEL&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The slackware mkinitrd package is a fully configured BusyBox installation that makes an external initramfs image file, initrd.gz, that is passed to the kernel by the bootloader (lilo). It could be changed to be internal to the kernel by just using initrd-tree as the CONFIG_INITRAMFS_SOURCE in the kernel config and removing initrd in the lilo.conf.&lt;br /&gt;
&lt;br /&gt;
The main purpose of most initramfs/initrd is to load and configure kernel modules and devices needed to mount a root filesystem. Because the spl/zfs modules are builtin, there isn't really a lot that needs to be done by an initramfs. What remains to be done is import the zfs-root pool, mount it, and exec the system /sbin/init. The kernel's &amp;quot;legacy&amp;quot; parameters &amp;lt;code&amp;gt;root=&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;rootfstype=&amp;lt;/code&amp;gt; that are able to directly boot a root disk do not work with ZFS at this time because ZFS pools always need to be imported before it is possible to mount and boot on them. The automatic import that ZFS can do by using a cachefile (/etc/zfs/zpool.cache) stored in initramfs still does not work with the legacy boot parameters because at an earlier stage of the boot process, the kernel ignores a rootfs that does not contain an &amp;lt;code&amp;gt;/init&amp;lt;/code&amp;gt; program, and/or the device type of an imported pool is not the device types recognized by the legacy boot as valid root devices.&lt;br /&gt;
&lt;br /&gt;
You could just continue to use slackware's mkinitrd package as in the &amp;quot;ZFS root&amp;quot; wiki and it works the same whether the modules are builtin or not. But, by building the spl/zfs modules in, aren't we really wanting to get rid of using the mkinitrd/initrd.gz? We'd like to have a kernel with everything in it to boot, and use a simple lilo image entry that has no initrd.&lt;br /&gt;
&lt;br /&gt;
We can do this, and not use the mkinitrd package, but we still need to finish our own initramfs &amp;lt;code&amp;gt;/init&amp;lt;/code&amp;gt; program to import, mount, switch root, and boot. Save the following c program to &amp;quot;foobarz-init.c&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/* software product name: foobarz-init.c&lt;br /&gt;
 * suggested binary name: /init (in initramfs-source, rootfs)&lt;br /&gt;
 * license              : BSD&lt;br /&gt;
 * license text:&lt;br /&gt;
Copyright (c) 2012, foobarz&lt;br /&gt;
All rights reserved.&lt;br /&gt;
&lt;br /&gt;
Redistribution and use in source and binary forms, with or without&lt;br /&gt;
modification, are permitted provided that the following conditions are met:&lt;br /&gt;
    * Redistributions of source code must retain the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer.&lt;br /&gt;
    * Redistributions in binary form must reproduce the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer in the&lt;br /&gt;
      documentation and/or other materials provided with the distribution.&lt;br /&gt;
    * Neither the name of the &amp;lt;organization&amp;gt; nor the&lt;br /&gt;
      names of its contributors may be used to endorse or promote products&lt;br /&gt;
      derived from this software without specific prior written permission.&lt;br /&gt;
&lt;br /&gt;
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &amp;quot;AS IS&amp;quot; AND&lt;br /&gt;
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED&lt;br /&gt;
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE&lt;br /&gt;
DISCLAIMED. IN NO EVENT SHALL &amp;lt;COPYRIGHT HOLDER&amp;gt; BE LIABLE FOR ANY&lt;br /&gt;
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES&lt;br /&gt;
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;&lt;br /&gt;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND&lt;br /&gt;
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT&lt;br /&gt;
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS&lt;br /&gt;
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
/* Your initramfs-source should contain the following&lt;br /&gt;
 *&lt;br /&gt;
 * cd /boot/initramfs-source&lt;br /&gt;
 * mkdir -p proc dev sys mnt bin sbin etc/zfs&lt;br /&gt;
 * touch etc/mtab&lt;br /&gt;
 * cp /etc/zfs/zpool.cache-initrd etc/zfs/zpool.cache&lt;br /&gt;
 * # zpool.cache is optional - zpool_import_ kernel params can be used instead&lt;br /&gt;
 * #  see below for details on using zpool_import&lt;br /&gt;
 * mknod dev/console c 5 1   # system console&lt;br /&gt;
 * mknod dev/kmsg    c 1 11  # lines printed to kmsg enter kernel messages buffer&lt;br /&gt;
 * mknod dev/loop0   b 7 0&lt;br /&gt;
 * mknod dev/tty     c 5 0   # current tty&lt;br /&gt;
 * mknod dev/tty0    c 4 0   # current virtual term&lt;br /&gt;
 * mknod dev/tty1    c 4 1   # login virtual term 1 (F1)&lt;br /&gt;
 * mknod dev/ttyS0   c 4 64  # COM1&lt;br /&gt;
 * mknod dev/ttyS1   c 4 65  # COM2&lt;br /&gt;
 * mknod dev/ttyS2   c 4 66  # COM3&lt;br /&gt;
 * mknod dev/ttyS3   c 4 67  $ COM4&lt;br /&gt;
 *&lt;br /&gt;
 * Copy this compiled program to /boot/initramfs-source/init&lt;br /&gt;
 * If not named /init, then use rdinit=/othername kernel parameter.&lt;br /&gt;
 *&lt;br /&gt;
 * Set kernel config option&lt;br /&gt;
 *  CONFIG_INITRAMFS_SOURCE=/boot/initramfs-source&lt;br /&gt;
 * to build the initramfs into your kernel image&lt;br /&gt;
 *  that also has builtin drivers (spl and zfs, etc).&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
#define FOOBARZ_INIT_VERSION &amp;quot;1.1.2&amp;quot;&lt;br /&gt;
#define _BSD_SOURCE&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdarg.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;fcntl.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/mount.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sysexits.h&amp;gt;&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
/* support for zpool import&lt;br /&gt;
 *&lt;br /&gt;
 * If -DINCLUDE_ZPOOL_IMPORT, then support to import a zpool is&lt;br /&gt;
 * enabled in the program. Enabling it will add many dependencies to the&lt;br /&gt;
 * compile and link; for example:&lt;br /&gt;
 *&lt;br /&gt;
 * gcc -static -DINCLUDE_ZPOOL_IMPORT \&lt;br /&gt;
 *    foobarz-init.c -include /usr/src/zfs-0.6.0-rc10/3.2.29/zfs_config.h \&lt;br /&gt;
 *   -o init \&lt;br /&gt;
 *   -I /usr/include/libspl -I /usr/include/libzfs \&lt;br /&gt;
 *   -lzfs -lnvpair -lzpool -luutil -luuid -lrt -lz -lm -lpthread \&lt;br /&gt;
 *   -I /usr/include/tirpc \&lt;br /&gt;
 *   -ltirpc&lt;br /&gt;
 *&lt;br /&gt;
 * Note that libtirpc is a drop-in replacement for the SunRPC functions that&lt;br /&gt;
 * used to be in glibc. No additional includes are needed, just the gcc -I and -l&lt;br /&gt;
 * options for tirpc.&lt;br /&gt;
 *&lt;br /&gt;
 * Otherwise, with -UINCLUDE_ZPOOL_IMPORT, the compile is just:&lt;br /&gt;
 * gcc -static foobarz-init.c -o init&lt;br /&gt;
 */&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
#include &amp;lt;libzfs.h&amp;gt;&lt;br /&gt;
#else&lt;br /&gt;
#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/stat.h&amp;gt;&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#define PARAM_REQ_NO 0&lt;br /&gt;
#define PARAM_REQ_YES 1&lt;br /&gt;
#define PARAM_SRC_DEFAULT 0&lt;br /&gt;
#define PARAM_SRC_CMDLINE 1&lt;br /&gt;
&lt;br /&gt;
void printk(char *fmt, ...) {&lt;br /&gt;
  FILE* f;&lt;br /&gt;
  int fd;&lt;br /&gt;
  va_list args;&lt;br /&gt;
&lt;br /&gt;
  f = fopen(&amp;quot;/dev/kmsg&amp;quot;, &amp;quot;w&amp;quot;);&lt;br /&gt;
  va_start(args, fmt);&lt;br /&gt;
  vfprintf(f, fmt, args);&lt;br /&gt;
  va_end(args);&lt;br /&gt;
  fflush(f);&lt;br /&gt;
  fclose(f);&lt;br /&gt;
  /* avoid flooding kmsg and having msgs suppressed; 20msgs/sec */&lt;br /&gt;
  usleep(50000);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[]) {&lt;br /&gt;
 /*** variables */&lt;br /&gt;
&lt;br /&gt;
 int i;&lt;br /&gt;
 int   fd = 0; /* file descriptor */&lt;br /&gt;
 unsigned long mountflags;&lt;br /&gt;
&lt;br /&gt;
 /* kernel command line */&lt;br /&gt;
 off_t cmdline_size;&lt;br /&gt;
 char* cmdline; /* to be malloc 4096B */&lt;br /&gt;
 char* cmdline_end;&lt;br /&gt;
 char* temp_end;&lt;br /&gt;
 char* src_msg; /* default or cmdline */&lt;br /&gt;
 int flag_param_missing = 0;&lt;br /&gt;
&lt;br /&gt;
 /* use to hold contents of a misc /proc/&amp;lt;file&amp;gt; */&lt;br /&gt;
 char* miscproc_buff; /* to be malloc 4096B */&lt;br /&gt;
 off_t miscproc_size;&lt;br /&gt;
&lt;br /&gt;
 /* note about environ, argv, and kernel cmdline for init:&lt;br /&gt;
  *   environ is not defined for init&lt;br /&gt;
  *   only argv[0] is set for init&lt;br /&gt;
  *   kernel command line parameters are accessed&lt;br /&gt;
  *   at /proc/cmdline&lt;br /&gt;
  */&lt;br /&gt;
&lt;br /&gt;
 /* kernel parameters expected to be name=value */&lt;br /&gt;
 /* do not use quotes or spaces in parameters   */&lt;br /&gt;
 /* you can add more params somwhere after root= */&lt;br /&gt;
 struct nv { char* n; char* v; char* v_end; int req; int src; };&lt;br /&gt;
 struct nv param[] = {&lt;br /&gt;
   { &amp;quot; root=&amp;quot;,       NULL, NULL, PARAM_REQ_YES, PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot; rootfstype=&amp;quot;, NULL, NULL, PARAM_REQ_YES, PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot; mountopt=&amp;quot;,   NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot; init=&amp;quot;,       NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot; runlevel=&amp;quot;,   NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot; console=&amp;quot;,    NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT }&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
   ,&lt;br /&gt;
   { &amp;quot; zpool_import_name=&amp;quot;,    NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot; zpool_import_guid=&amp;quot;,    NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot; zpool_import_newname=&amp;quot;, NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot; zpool_import_force=&amp;quot;,   NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT }&lt;br /&gt;
#endif&lt;br /&gt;
 };&lt;br /&gt;
 enum {&lt;br /&gt;
	 iroot,&lt;br /&gt;
	 irootfstype,&lt;br /&gt;
	 imountopt,&lt;br /&gt;
	 iinit,&lt;br /&gt;
	 irunlevel,&lt;br /&gt;
	 iconsole,&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
	 izpool_import_name,&lt;br /&gt;
	 izpool_import_guid,&lt;br /&gt;
	 izpool_import_newname,&lt;br /&gt;
	 izpool_import_force,&lt;br /&gt;
#endif&lt;br /&gt;
	 ilastparam&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
 libzfs_handle_t* libzfs = NULL;&lt;br /&gt;
 importargs_t iargs = { 0 };&lt;br /&gt;
 nvlist_t* pools = NULL;&lt;br /&gt;
 nvpair_t* pool = NULL;&lt;br /&gt;
 nvlist_t* config = NULL;&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
 /*** program */&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;foobarz-init, version %s: booting initramfs.\n&amp;quot;, FOOBARZ_INIT_VERSION);&lt;br /&gt;
&lt;br /&gt;
 cmdline       = (char*) malloc(4096);&lt;br /&gt;
 miscproc_buff = (char*) malloc(4096);&lt;br /&gt;
 if( (cmdline == NULL) || (miscproc_buff == NULL) ) {&lt;br /&gt;
   printk(&amp;quot;Unable to allocate buffer memory: malloc: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount proc /proc&lt;br /&gt;
  *  note: some /dev devices symlink into /proc&lt;br /&gt;
  *  proc contains info about processes, including cmdline etc. */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount proc /proc\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;proc&amp;quot;, &amp;quot;/proc&amp;quot;, &amp;quot;proc&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
   printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
   printk(&amp;quot;Mount proc successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount devtmpfs /dev&lt;br /&gt;
  *  note: This simple init program works if your root device is made from devices&lt;br /&gt;
  *  that are available by default in devtmpfs, such as /dev/sd*&lt;br /&gt;
  *&lt;br /&gt;
  *  For zfs, your root zfs pool should be created with default device nodes and&lt;br /&gt;
  *  then it should be mountable by this simple init program.&lt;br /&gt;
  *&lt;br /&gt;
  *  udev may be needed to configure device nodes and symlinks required&lt;br /&gt;
  *  to access a root device configuration made with such nodes and symlinks.&lt;br /&gt;
  *  If you need udevd, you can include it into your initramfs-source and&lt;br /&gt;
  *  modify this program to run it before attempting to mount your root device.&lt;br /&gt;
  *  However, if udevd is needed, a significant number of userspace programs may also be&lt;br /&gt;
  *  required by rules in /lib/udev/. You could install busybox + udev (about 5MB) or&lt;br /&gt;
  *  coreutils + util-linux + bash + udev (about 25MB) into initramfs-source. But, at that&lt;br /&gt;
  *  point you'd have ash or bash and many tools that are easier to use than this&lt;br /&gt;
  *  simple init program; it would then be easy to have /init as #!/bin/&amp;lt;b&amp;gt;ash script. */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount devtmpfs /dev\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;devtmpfs&amp;quot;, &amp;quot;/dev&amp;quot;, &amp;quot;devtmpfs&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
   printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
   printk(&amp;quot;Mount devtmpfs successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount sysfs /sys&lt;br /&gt;
  *  note: some kernel modules try to access /sys with userspace helpers to echo values into /sys variables;&lt;br /&gt;
  *  such modules expect a minimal userspace that contains coreutils or busybox */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount sysfs /sys\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;sysfs&amp;quot;, &amp;quot;/sys&amp;quot;, &amp;quot;sysfs&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
   printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
   printk(&amp;quot;Mount sysfs successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* process kernel command line */&lt;br /&gt;
 fd = open(&amp;quot;/proc/cmdline&amp;quot;, O_RDONLY);&lt;br /&gt;
 if( fd == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Cannot open /proc/cmdline: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 /* note, on /proc fs:&lt;br /&gt;
  *       lseek likely always returns error&lt;br /&gt;
  *       stat likely always returns st_size = 0&lt;br /&gt;
  *   so determining size of /proc file means just reading it;&lt;br /&gt;
  *   you have to read /proc files according to their documented&lt;br /&gt;
  *   maximum sizes; this is probably for performance reasons */&lt;br /&gt;
 cmdline_size = read(fd, cmdline, 4095);&lt;br /&gt;
 if( cmdline_size == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Failed to read /proc/cmdline: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 close(fd);&lt;br /&gt;
&lt;br /&gt;
 /* cmdline may be newline + null terminated, but make it null + null */&lt;br /&gt;
 cmdline[cmdline_size] = '\0';&lt;br /&gt;
 if( cmdline[cmdline_size-1] == '\n' ) {&lt;br /&gt;
   cmdline[cmdline_size-1] = '\0';&lt;br /&gt;
   cmdline_size--;&lt;br /&gt;
   cmdline_end = cmdline + cmdline_size;&lt;br /&gt;
 }&lt;br /&gt;
 printk(&amp;quot;Kernel cmdline size: %i\n&amp;quot;, cmdline_size);&lt;br /&gt;
 printk(&amp;quot;Kernel cmdline: \&amp;quot;%s\&amp;quot;\n&amp;quot;, cmdline);&lt;br /&gt;
&lt;br /&gt;
 /* find v and v_end of values in cmdline */&lt;br /&gt;
 for( i=iroot; i&amp;lt;ilastparam; i++ ) {&lt;br /&gt;
   param[i].v = strstr(cmdline, param[i].n);&lt;br /&gt;
   if( param[i].v != NULL ) {&lt;br /&gt;
     param[i].src = PARAM_SRC_CMDLINE;&lt;br /&gt;
     while( *(param[i].v) != '=' ) param[i].v++;&lt;br /&gt;
     param[i].v++;&lt;br /&gt;
     temp_end = param[i].v;&lt;br /&gt;
     while( !( (*temp_end == ' ') ||&lt;br /&gt;
               (*temp_end == '\n') ||&lt;br /&gt;
               (temp_end == cmdline_end)&lt;br /&gt;
	     ) ) temp_end++;&lt;br /&gt;
     if( temp_end == param[i].v ) {&lt;br /&gt;
       printk(&amp;quot;Kernel parameter %s: value missing.\n&amp;quot;, param[i].n);&lt;br /&gt;
       param[i].v = NULL;&lt;br /&gt;
     } else param[i].v_end = temp_end;&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* set defaults for params not given on cmdline */&lt;br /&gt;
 for( i=iroot; i&amp;lt;ilastparam; i++ ) {&lt;br /&gt;
   /* terminate value strings */&lt;br /&gt;
   if( param[i].v_end != NULL ) *(param[i].v_end) = '\0';&lt;br /&gt;
   /* set defaults if no value on cmdline */&lt;br /&gt;
   if( param[i].v == NULL ) {&lt;br /&gt;
     param[i].src = PARAM_SRC_DEFAULT;&lt;br /&gt;
     if( param[i].req == PARAM_REQ_YES ) flag_param_missing = 1;&lt;br /&gt;
     switch(i) {&lt;br /&gt;
       case iroot      : param[i].v = &amp;quot;&amp;lt;missing required param&amp;gt;&amp;quot; ; break;&lt;br /&gt;
       case irootfstype: param[i].v = &amp;quot;&amp;lt;missing required param&amp;gt;&amp;quot; ; break;&lt;br /&gt;
       case imountopt  : param[i].v = &amp;quot;ro&amp;quot;        ; break;&lt;br /&gt;
       case iinit      : param[i].v = &amp;quot;/sbin/init&amp;quot;; break;&lt;br /&gt;
       case irunlevel  : param[i].v = &amp;quot;3&amp;quot;         ; break;&lt;br /&gt;
       case iconsole   : param[i].v = &amp;quot;console&amp;quot;   ; break;&lt;br /&gt;
       default         : param[i].v = NULL;&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
   if(param[i].src == PARAM_SRC_DEFAULT) src_msg = &amp;quot;default&amp;quot;;&lt;br /&gt;
   else src_msg = &amp;quot;cmdline&amp;quot;;&lt;br /&gt;
   printk(&amp;quot;Using %s \&amp;quot;%s\&amp;quot; (source: %s)\n&amp;quot;, param[i].n, param[i].v, src_msg);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 if( flag_param_missing ) {&lt;br /&gt;
   printk(&amp;quot;Aborting boot process: missing required kernel parameter(s).\n&amp;quot;);&lt;br /&gt;
   return EX_USAGE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* generic nv pair kernel cmdline processing finished&lt;br /&gt;
  *  now, examine specific params for defaults and correctness */&lt;br /&gt;
&lt;br /&gt;
 /* param[irootfstype]: can be checked against /proc/filesystems: */&lt;br /&gt;
 fd = open(&amp;quot;/proc/filesystems&amp;quot;, O_RDONLY);&lt;br /&gt;
 if( fd == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Cannot open /proc/filesystems: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 miscproc_size = read(fd, miscproc_buff, 4095);&lt;br /&gt;
 if( miscproc_size == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Failed to read /proc/filesystems: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 close(fd);&lt;br /&gt;
 if( strstr(miscproc_buff, param[irootfstype].v) == NULL ) {&lt;br /&gt;
   printk(&amp;quot;%s \&amp;quot;%s\&amp;quot;: filesystem type not available.\n&amp;quot;, param[irootfstype].n, param[irootfstype].v);&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* zfs-specific */&lt;br /&gt;
 if( strcmp(param[irootfstype].v, &amp;quot;zfs&amp;quot;) == 0 ) {&lt;br /&gt;
   if( access(&amp;quot;/etc/zfs/zpool.cache&amp;quot;, F_OK) == 0 )&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/zfs/zpool.cache is present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
   else&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/zfs/zpool.cache not present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
&lt;br /&gt;
   if( access(&amp;quot;/etc/hostid&amp;quot;, F_OK) == 0 )&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/hostid is present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
   else&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/hostid not present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
   /* zpool import */&lt;br /&gt;
   if( (param[izpool_import_name].v != NULL) || (param[izpool_import_guid].v != NULL) ) {&lt;br /&gt;
	printk(&amp;quot;zpool_import: import requested.\n&amp;quot;);&lt;br /&gt;
	if( (param[izpool_import_name].v != NULL) &amp;amp;&amp;amp; (param[izpool_import_guid].v != NULL) ) {&lt;br /&gt;
		printk(&amp;quot;zpool_import: given both pool name and guid; using guid.\n&amp;quot;);&lt;br /&gt;
		param[izpool_import_name].v = NULL;&lt;br /&gt;
	}&lt;br /&gt;
	if( param[izpool_import_name].v != NULL )&lt;br /&gt;
		printk(&amp;quot;zpool_import: pool name: %s\n&amp;quot;, param[izpool_import_name].v );&lt;br /&gt;
	else&lt;br /&gt;
		printk(&amp;quot;zpool_import: pool guid: %s\n&amp;quot;, param[izpool_import_guid].v );&lt;br /&gt;
&lt;br /&gt;
	iargs.path = NULL;&lt;br /&gt;
	iargs.paths = 0;&lt;br /&gt;
	iargs.poolname = param[izpool_import_name].v;&lt;br /&gt;
	if( param[izpool_import_guid].v != NULL )&lt;br /&gt;
		iargs.guid = strtoull(param[izpool_import_guid].v, NULL, 10);&lt;br /&gt;
	else&lt;br /&gt;
		iargs.guid = 0;&lt;br /&gt;
	iargs.cachefile = NULL;&lt;br /&gt;
	if( (param[izpool_import_force].v != NULL) &amp;amp;&amp;amp; (strcmp(param[izpool_import_force].v, &amp;quot;1&amp;quot;) == 0) ) {&lt;br /&gt;
		iargs.can_be_active = 1;&lt;br /&gt;
		printk(&amp;quot;zpool_import: import forced.\n&amp;quot;);&lt;br /&gt;
	} else {&lt;br /&gt;
		iargs.can_be_active = 0;&lt;br /&gt;
		printk(&amp;quot;zpool_import: import not forced.\n&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
	iargs.unique = 1;&lt;br /&gt;
	iargs.exists = 1;&lt;br /&gt;
&lt;br /&gt;
	printk(&amp;quot;zpool_import: init libzfs.\n&amp;quot;);&lt;br /&gt;
	libzfs = libzfs_init();&lt;br /&gt;
	if( libzfs != NULL ) {&lt;br /&gt;
		printk(&amp;quot;zpool_import: searching for pool.\n&amp;quot;);&lt;br /&gt;
		pools = zpool_search_import(libzfs, &amp;amp;iargs);&lt;br /&gt;
		if( (pools == NULL) || nvlist_empty(pools) )&lt;br /&gt;
			printk(&amp;quot;zpool_import: pool not available for import, or already imported by cachefile.\n&amp;quot;);&lt;br /&gt;
		else {&lt;br /&gt;
			printk(&amp;quot;zpool_import: getting pool information.\n&amp;quot;);&lt;br /&gt;
			pool = nvlist_next_nvpair(pools, pool);&lt;br /&gt;
			printk(&amp;quot;zpool_import: getting pool configuration.\n&amp;quot;);&lt;br /&gt;
			nvpair_value_nvlist(pool, &amp;amp;config);&lt;br /&gt;
			printk(&amp;quot;zpool_import: attempting pool import.\n&amp;quot;);&lt;br /&gt;
			if( zpool_import(libzfs, config, param[izpool_import_newname].v, NULL) != 0 ) {&lt;br /&gt;
				printk(&amp;quot;zpool_import: import failed.\n&amp;quot;);&lt;br /&gt;
				printk(&amp;quot;zpool_import: error description: %s\n&amp;quot;, libzfs_error_description(libzfs) );&lt;br /&gt;
				printk(&amp;quot;zpool_import: error action: %s\n&amp;quot;, libzfs_error_action(libzfs) );&lt;br /&gt;
			} else  printk(&amp;quot;zpool_import: import successful.\n&amp;quot;);&lt;br /&gt;
		}&lt;br /&gt;
		printk(&amp;quot;zpool_import: fini libzfs.\n&amp;quot;);&lt;br /&gt;
		libzfs_fini(libzfs);&lt;br /&gt;
	} else {&lt;br /&gt;
		printk(&amp;quot;zpool_import: unable to initialize libzfs.\n&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
   }&lt;br /&gt;
#endif /* zpool_import */&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 if(      strcmp(param[imountopt].v, &amp;quot;ro&amp;quot;) == 0 ) mountflags = MS_RDONLY;&lt;br /&gt;
 else if( strcmp(param[imountopt].v, &amp;quot;rw&amp;quot;) == 0 ) mountflags = 0;&lt;br /&gt;
 else {&lt;br /&gt;
   printk(&amp;quot;%s \&amp;quot;%s\&amp;quot;: invalid parameter value; defaulting to \&amp;quot;ro\&amp;quot;.\n&amp;quot;, param[imountopt].n, param[imountopt].v);&lt;br /&gt;
   mountflags = MS_RDONLY;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* param[iroot]: nothing to check; if user gives bad root=device then mount fails */&lt;br /&gt;
&lt;br /&gt;
 /* try to mount root=device at /mnt&lt;br /&gt;
  *&lt;br /&gt;
  * note: for zfs, if a copy of /etc/zfs/zpool.cache (when pool is imported) is put in initramfs-source, then&lt;br /&gt;
  * the zfs module can read it and automatically import the pools described in the cache file; the imported&lt;br /&gt;
  * pools can be available to mount here if they were created using standard device names, otherwise&lt;br /&gt;
  * udevd may be required to run before mounting the pool */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount -t %s -o %s %s /mnt.\n&amp;quot;, param[irootfstype].v, param[imountopt].v, param[iroot].v);&lt;br /&gt;
 if( mount(param[iroot].v, &amp;quot;/mnt&amp;quot;, param[irootfstype].v, mountflags, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 printk(&amp;quot;%s mounted successfully.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
&lt;br /&gt;
 /* check to see if the mounted root filesystem has an executable init program */&lt;br /&gt;
 chdir(&amp;quot;/mnt&amp;quot;);&lt;br /&gt;
 if( access(param[iinit].v+1, X_OK) != 0 ) {&lt;br /&gt;
   chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
   printk(&amp;quot;access X_OK: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   printk(&amp;quot;The init program /mnt/%s is not present or not executable.\n&amp;quot;, param[iinit].v+1);&lt;br /&gt;
   printk(&amp;quot;Aborting boot process: no init program.\n&amp;quot;);&lt;br /&gt;
   printk(&amp;quot;Unmounting %s.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
   if( umount(&amp;quot;/mnt&amp;quot;) == -1 ) {&lt;br /&gt;
     printk(&amp;quot;umount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
     printk(&amp;quot;Failed to umount %s.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
   } else printk(&amp;quot;Successfully unmounted %s.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
 printk(&amp;quot;Init program /mnt/%s is present and executable.\n&amp;quot;, param[iinit].v+1);&lt;br /&gt;
&lt;br /&gt;
 /* switch the root / from initramfs to the mounted new root device at /mnt.&lt;br /&gt;
  *&lt;br /&gt;
  * note: after this switch, it is not possible to access the initramfs files anymore,&lt;br /&gt;
  * yet they consume ram memory unless they are deleted here before switching.&lt;br /&gt;
  * Any programs that are run after clearing the initramfs and switching root must exist on the new root.&lt;br /&gt;
  * This program may safely delete itself (/init) since it is already in ram and executing.&lt;br /&gt;
  * If you have installed additional files and programs in initramfs that consume significant ram,&lt;br /&gt;
  * then you need to insert additional code here to delete those files (carefully). */&lt;br /&gt;
&lt;br /&gt;
 /* delete files off of initramfs to free ram memory */&lt;br /&gt;
 printk(&amp;quot;Freeing memory from initramfs...\n&amp;quot;);&lt;br /&gt;
 if( unlink(argv[0]) != 0 ) printk(&amp;quot;unlink %s: %s\n&amp;quot;, argv[0], strerror(errno));&lt;br /&gt;
 else printk(&amp;quot;%s %s&amp;quot;, argv[0], &amp;quot;deleted from initramfs.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 /* switch root */&lt;br /&gt;
 printk(&amp;quot;Beginning switch root procedure.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(1) Attempting cmd: mount --move /dev /mnt/dev \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/dev&amp;quot;, &amp;quot;/mnt/dev&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(2) Attempting cmd: mount --move /proc /mnt/proc \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/proc&amp;quot;, &amp;quot;/mnt/proc&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(3) Attempting cmd: mount --move /sys /mnt/sys \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/sys&amp;quot;, &amp;quot;/mnt/sys&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(4) Attempting cmd: chdir /mnt \n&amp;quot;);&lt;br /&gt;
 if( chdir(&amp;quot;/mnt&amp;quot;) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: chdir: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(5) Attempting cmd: mount --move . / \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;.&amp;quot;, &amp;quot;/&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(6) Attempting cmd: chroot . \n&amp;quot;);&lt;br /&gt;
 if( chroot(&amp;quot;.&amp;quot;) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: chroot: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(7) Attempting cmd: chdir / \n&amp;quot;);&lt;br /&gt;
 if( chdir(&amp;quot;/&amp;quot;) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: chdir: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 printk(&amp;quot;Completed switch root procedure.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 /* check for &amp;quot;console=&amp;quot; kernel parameter and switch&lt;br /&gt;
  *  stdin, stdout, and stderr to named console device&lt;br /&gt;
  */&lt;br /&gt;
 if( param[iconsole].src == PARAM_SRC_CMDLINE ) {&lt;br /&gt;
   printk(&amp;quot;Console redirection to device %s requested.\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
   /* expect only basename of console device (e.g., ttyS0), so chdir /dev */&lt;br /&gt;
   chdir(&amp;quot;/dev&amp;quot;);&lt;br /&gt;
   if( access(param[iconsole].v, F_OK ) == 0 ) {&lt;br /&gt;
     printk(&amp;quot;Opening stdin, stdout, and stderr on %s.\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
     close(0);&lt;br /&gt;
     open(param[iconsole].v, O_RDWR);&lt;br /&gt;
     dup2(0, 1);&lt;br /&gt;
     dup2(0, 2);&lt;br /&gt;
   } else {&lt;br /&gt;
     printk(&amp;quot;access F_OK: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
     printk(&amp;quot;Could not access device: %s!\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
     printk(&amp;quot;Console redirection to device %s aborted!\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
   }&lt;br /&gt;
   chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;Execing: \&amp;quot;%s %s\&amp;quot; to boot mounted root system.\n&amp;quot;, param[iinit].v, param[irunlevel].v);&lt;br /&gt;
&lt;br /&gt;
 /* free resources held to this point */&lt;br /&gt;
 free(cmdline);&lt;br /&gt;
 free(miscproc_buff);&lt;br /&gt;
&lt;br /&gt;
 if( execl(param[iinit].v, param[irunlevel].v, (char *) NULL ) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: execl: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If foobarz-init is updated, you can find the latest version at [https://github.com/foobarz/foobarz-init github].&lt;br /&gt;
&lt;br /&gt;
The foobarz-init program can be compiled two ways as of v1.1.1. First, the simpler compile that does not support zpool_import but does support importing pools using a /etc/zfs/zpool.cache file in the initramfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gcc --static init.c -o init&lt;br /&gt;
strip init&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The second way to compile it adds support for zpool_import so that you do not have to include a &amp;lt;code&amp;gt;/etc/zfs/zpool.cache&amp;lt;/code&amp;gt; file in the initramfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gcc -static -DINCLUDE_ZPOOL_IMPORT \&lt;br /&gt;
     foobarz-init.c -include /usr/src/linux-3.2.29b/zfs_config.h \&lt;br /&gt;
    -o init \&lt;br /&gt;
    -I /usr/include/libspl -I /usr/include/libzfs \&lt;br /&gt;
    -lzfs -lnvpair -lzpool -luutil -luuid -lrt -lz -lm -lpthread \&lt;br /&gt;
    -I /usr/include/tirpc \&lt;br /&gt;
    -ltirpc&lt;br /&gt;
strip init&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Dependencies required before you can compile this second way:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Install [http://sourceforge.net/projects/libtirpc/ libtirpc]. The glibc package has removed the RPC-related functions from the static libc. The libtirpc is the new replacement as a separate library. You can make your own libtirpc package and install it to resolve these RPC-related functions. Without this, the compile fails because it cannot find many &amp;quot;xdr&amp;quot; functions.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Reinstall the [ftp://slackware.mirrors.tds.net/pub/slackware/slackware64-current/source/a/util-linux/ util-linux] package with static libraries enabled. Edit the &amp;lt;code&amp;gt;util-linux.SlackBuild&amp;lt;/code&amp;gt; and remove the line &amp;lt;code&amp;gt;--disable-static&amp;lt;/code&amp;gt;, then build it and use upgradepkg to install the new package. This resolves linking static to libuuid.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;code&amp;gt;zfs_config.h&amp;lt;/code&amp;gt; can be found in the kernel source when you have installed the builtin spl/zfs configuration; for example at &amp;lt;code&amp;gt;/usr/src/linux-3.2.29b/zfs_config.h&amp;lt;/code&amp;gt;. If you currently have installed the modular spl/zfs configuration, &amp;lt;code&amp;gt;zfs_config.h&amp;lt;/code&amp;gt; is found where the zfs module headers are installed; for example at &amp;lt;code&amp;gt;/usr/src/zfs-0.6.0-rc11/3.2.29/zfs_config.h&amp;lt;/code&amp;gt;. Wherever it is, &amp;lt;code&amp;gt;-include&amp;lt;/code&amp;gt; it as shown in the example gcc line above. zfs_config.h seems misplaced because it would seem that using libzfs shouldn't depend on modules header files.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;You may need to install the spl and zfs packages configured for --enable-linux-builtin=yes before compiling and linking to libzfs to make sure you are using the version of libzfs intended for builtin modules in case a difference between the two configurations exists. Currently, there seems to be no difference in the libzfs for either modular or builtin modules, but later there could be at least a small difference for detection of modules to load or builtin already. You may see a message that the ZFS modules stack load failed, but it can be ignored since the modules are builtin; this is just libzfs trying to load the modules even though they are builtin.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
With these dependencies, you can probably compile static with the zpool_import support. The exact location of &amp;quot;zfs_config.h&amp;quot; may vary depending on your zfs and kernel versions, so adjust accordingly.&lt;br /&gt;
&lt;br /&gt;
Read the foobarz-init source code to see how it uses kernel parameters. The params &amp;lt;code&amp;gt;root&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;rootfstype&amp;lt;/code&amp;gt; are always required to tell init what root pool name to mount and the filesystem type (e.g. zfs).&lt;br /&gt;
&lt;br /&gt;
For the zpool_import support: &amp;lt;code&amp;gt;zpool_import_name=poolname&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;zpool_import_guid=&amp;lt;guid of a pool&amp;gt;&amp;lt;/code&amp;gt; tells what pool to import. You can also import the pool with a new different name by also using &amp;lt;code&amp;gt;zpool_import_newname=newpoolname&amp;lt;/code&amp;gt;. If the import is not working, &amp;lt;code&amp;gt;zpool_import_force=1&amp;lt;/code&amp;gt; can be used to force import even if ZFS thinks the pool may be in use by another system.&lt;br /&gt;
&lt;br /&gt;
However you import the pool, either using zpool.cache or zpool_import support, the kernel param &amp;lt;code&amp;gt;root=&amp;lt;your poolname or newpoolname&amp;gt;&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;rootfstype=zfs&amp;lt;/code&amp;gt; needs to be given also. The zpool_import only imports, it does not say what to mount. What to mount is still told using root= and rootfstype=.&lt;br /&gt;
&lt;br /&gt;
Now copy the compiled static program into the initramfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp init /boot/initramfs-source/init&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Build and install kernel:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /usr/src/linux-3.2.29b&lt;br /&gt;
make -j8&lt;br /&gt;
make -j8 modules_install&lt;br /&gt;
cp arch/x86/boot/bzImage /boot/vm3.2.29b&lt;br /&gt;
cp System.map /boot/System.map-vm3.2.29b&lt;br /&gt;
# add new lilo menu entry for vm3.2.29b kernel&lt;br /&gt;
vi /etc/lilo.conf&lt;br /&gt;
  image = /boot/vm3.2.29b&lt;br /&gt;
   label = vm3.2.29b&lt;br /&gt;
   addappend = &amp;quot; spl.spl_hostid=0x007f0100 zfs.spa_config_path=/etc/zfs/zpool.cache root=zfs-root rootfstype=zfs&amp;quot;&lt;br /&gt;
lilo&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Note: If &amp;lt;code&amp;gt;spl.spl_hostid=0x007f0100&amp;lt;/code&amp;gt; is not included in addappend, then during boot SPL module will attempt to read &amp;lt;code&amp;gt;/etc/hostid&amp;lt;/code&amp;gt; or else run a user-space helper to write the &amp;lt;code&amp;gt;hostid&amp;lt;/code&amp;gt; into &amp;lt;code&amp;gt;/proc/sys/kernel/spl/hostid&amp;lt;/code&amp;gt;. Reading &amp;lt;code&amp;gt;/etc/hostid&amp;lt;/code&amp;gt; fails unless you use [https://github.com/foobarz/foobarz-chhostid foobarz-chhostid] to make the file and copy it to &amp;lt;code&amp;gt;/boot/initramfs-source/etc/hostid&amp;lt;/code&amp;gt; then run the steps above again. The helper will fail because no &amp;lt;code&amp;gt;sh&amp;lt;/code&amp;gt; shell and no &amp;lt;code&amp;gt;hostid&amp;lt;/code&amp;gt; command are installed in the initramfs. The default hostid becomes 0xffffffff, which is considered an invalid hostid.&lt;br /&gt;
&lt;br /&gt;
Congrats! If this works, you can select the &amp;quot;vm3.2.29b&amp;quot; lilo entry to boot. If you are using the zpool_import support in the init program, you need to add at least the &amp;lt;code&amp;gt;zpool_import_name=zfs-root&amp;lt;/code&amp;gt; param to the addappend line in lilo.conf.&lt;br /&gt;
&lt;br /&gt;
Notes on kernel params (lilo append and addappend lines): root= and rootfstype= are used by both foorbarz-init and mkinitrd. The &amp;quot;ro&amp;quot; param is not used by foobarz-init, so instead use: mountopt=ro|rw. See &amp;quot;modinfo spl&amp;quot; and &amp;quot;modinfo zfs&amp;quot; to see all of the options those modules can take on the kernel command line. Notice the &amp;lt;code&amp;gt;spl.spl_hostid=0x007f0100&amp;lt;/code&amp;gt; param that works around the hostid mismatch problem while trying to import a pool; this param and hostname/ip set to use local loopback 127.0.0.1 in etc/hosts etc/HOSTNAME in initramfs will work most of the time, and if not the pool import needs to be forced.&lt;br /&gt;
&lt;br /&gt;
Notes on the spl and zfs packages to install: &amp;lt;i&amp;gt;If&amp;lt;/i&amp;gt; you have errors using zfs and zpool commands on booted system with builtin modules, then upgrade/switch to the 0.6.0rc11_3.2.29b builds, or you can make a custom package with the binaries renamed like zpoolb, zfsb etc for builtin.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
Using qemu's -nographic serial console (/usr/share/qemu/sgabios.bin): If you have a boot problem, you might want to run in qemu's -nographic console mode:&lt;br /&gt;
&lt;br /&gt;
First, edit /etc/inittab, and uncomment the line for local serial ports runlevel &amp;quot;s1&amp;quot; (ttyS0) for serial console login support. This is done in the guest (host does not need this):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Local serial lines:&lt;br /&gt;
s1:12345:respawn:/sbin/agetty -L ttyS0 38400 linux&lt;br /&gt;
#s1:12345:respawn:/sbin/agetty -L ttyS0 9600 vt100&lt;br /&gt;
#s2:12345:respawn:/sbin/agetty -L ttyS1 9600 vt100&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Second, edit /etc/securetty, and uncomment ttyS0 line:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ttyS0&lt;br /&gt;
#ttyS1&lt;br /&gt;
# ...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
You cannot login on ttyS0 without this change even though you get the login prompt!&lt;br /&gt;
&lt;br /&gt;
Then, run qemu such as:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
qemu-kvm &amp;lt;all regular options&amp;gt; -nographic -option-rom sgabios.bin,bootindex=0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Wait for the lilo prompt, it may take several seconds show up in this mode.&lt;br /&gt;
&lt;br /&gt;
In the lilo menu, select your kernel image with builtin spl/zfs, and use kernel params such as:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
boot: vm3.2.29b console=ttyS0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
At the lilo prompt, use kernel parameter: console=ttyS0 (do NOT say /dev/ttS0). Passing runlevel=s1 does not appear to be necessary.&lt;br /&gt;
&lt;br /&gt;
When you are in qemu's serial mode, the interface is a little different than in the normal graphical mode: use keypresses:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ctrl-a h    # for help&lt;br /&gt;
ctrl-a c    # toggle access to (QEMU) console / back to emulation&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If you cannot get a login: prompt, try ctrl-a c, then do (QEMU) sendkey ctrl-alt-delete. This will reboot cleanly back to lilo, then you can do (QEMU) quit.&lt;br /&gt;
&lt;br /&gt;
Once you login to the guest, the terminal size needs adjustment. On your host, in another xterm sized the same as your guest console terminal, get the size of the terminal:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo $LINES&lt;br /&gt;
echo $COLUMNS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Now, back in the guest terminal of same size:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export LINES &amp;lt;lines&amp;gt;&lt;br /&gt;
export COLUMNS &amp;lt;columns&amp;gt;&lt;br /&gt;
stty cols $COLUMNS rows $LINES&lt;br /&gt;
exec bash&lt;br /&gt;
reset&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
So, you set the environment variables and also set them with stty. Then, restart bash (exec, or else it is a child shell process).&lt;br /&gt;
&lt;br /&gt;
BECAREFUL not to start qemu twice on the same ZFS guest! Two simultaneous running qemu on the same ZFS will corrupt the pool and it will NOT recover - you lose your whole installation! Before running qemu, check ps -A, look for an already running qemu process incase it somehow entered into the background!&lt;br /&gt;
&lt;br /&gt;
BECAREFUL when using -nographic ttyS0 that you are not doing commands on the HOST! Only use -nographic to see kernel problems. Use regular console if booting is working normally.&lt;br /&gt;
&lt;br /&gt;
To use the qemu -drive if=scsi option, the linux module sym53c8xx should be loaded in the guest. You may need to use the qemu option:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-option-rom 8xx_64.rom,bootindex=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The file 8xx_64.rom used to be inside qemu, but in new versions it is missing. You can download it:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
wget http://www.lsi.com/downloads/Public/Host%20Bus%20Adapters/Host%20Bus%20Adapters%20Common%20Files/lsi_bios.zip&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Extract the zip and place 8xx_64.rom in /usr/share/qemu/.&lt;br /&gt;
&lt;br /&gt;
Good luck!&lt;/div&gt;</description>
			<pubDate>Tue, 25 Sep 2012 12:12:38 GMT</pubDate>
			<dc:creator>Foobarz</dc:creator>
			<comments>https://www.slackwiki.com/Talk:ZFS_root_(builtin)</comments>
		</item>
		<item>
			<title>ZFS root (builtin)</title>
			<link>https://www.slackwiki.com/index.php?title=ZFS_root_(builtin)&amp;diff=804</link>
			<guid isPermaLink="false">https://www.slackwiki.com/index.php?title=ZFS_root_(builtin)&amp;diff=804</guid>
			<description>&lt;p&gt;Foobarz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Tutorials]]&lt;br /&gt;
The first [http://slackwiki.com/ZFS_root &amp;quot;ZFS root&amp;quot;] wiki explains the details of running ZFS as your root filesystem by using a fully modular generic kernel approach. Now, I can share how it can be done with the SPL and ZFS modules built into the kernel. This procedure is just an example and can use some fine tuning, but here goes:&lt;br /&gt;
&lt;br /&gt;
The steps below are to create a kernel with SPL and ZFS modules builtin. This kernel will be installed as an alternative kernel to boot in lilo, and it will have a separate kernel installation from the fully modular and working system kernel. This will allow testing the builtin kernel while able to boot back onto a working modular ZFS system. We start this procedure assuming you are on a working fully modular ZFS install as in the &amp;quot;ZFS root&amp;quot; wiki.&lt;br /&gt;
&lt;br /&gt;
Use mountpoint=legacy so that zfs will not expect &amp;lt;code&amp;gt;zfs mount&amp;lt;/code&amp;gt;, but instead expect standard &amp;lt;code&amp;gt;mount&amp;lt;/code&amp;gt; for mounting zfs-root:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=legacy zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Edit &amp;lt;code&amp;gt;/etc/rc.d/rc.S&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;rc.6&amp;lt;/code&amp;gt; to use regular &amp;lt;code&amp;gt;mount&amp;lt;/code&amp;gt; commands, remove &amp;lt;code&amp;gt;zfs&amp;lt;/code&amp;gt; commands. Edit &amp;lt;code&amp;gt;rc.6&amp;lt;/code&amp;gt; and remove or comment out &amp;lt;code&amp;gt;zpool export&amp;lt;/code&amp;gt; command. These edits undo changes made in the &amp;quot;ZFS root&amp;quot; wiki, but it shows the two different ways of mounting a zfs filesystem.&lt;br /&gt;
&lt;br /&gt;
You &amp;lt;i&amp;gt;might&amp;lt;/i&amp;gt; think to set &amp;lt;code&amp;gt;bootfs&amp;lt;/code&amp;gt; property like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool set bootfs=zfs-root zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
However, this will result in ZFS placing many restrictions on zfs-root as per how that option is used on Solaris systems:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; zfs-root must be VTOC (SMI) label, not GPT (EFI) label&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; zfs-root can only contain 1 vdev: either a plain disk, or a mirror&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
So, do &amp;lt;b&amp;gt;NOT&amp;lt;/b&amp;gt; set that property! If &amp;lt;code&amp;gt;bootfs&amp;lt;/code&amp;gt; is set, you would find that you cannot add vdevs to your zfs-root. If it is set already, then unset it like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool set bootfs= zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Make a directory to store files to be inside the initramfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkdir /boot/initramfs-source&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This directory will hold some files for the initial rootfs inside the kernel. Your &amp;lt;code&amp;gt;/boot&amp;lt;/code&amp;gt; should be on a small ext4 partition or on a mounted USB stick that you use to boot.&lt;br /&gt;
&lt;br /&gt;
Extract the slackware kernel-source package to obtain a copy of the kernel source, and make an initial kernel config for it:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir src&lt;br /&gt;
cd src&lt;br /&gt;
tar xvzf /mnt/cdrom/slackware64/k/kernel-source-*.txz&lt;br /&gt;
mv usr/src/linux-3.2.29 /usr/src/linux-3.2.29b&lt;br /&gt;
rm -r install&lt;br /&gt;
cd /usr/src/linux-3.2.29b&lt;br /&gt;
make menuconfig&lt;br /&gt;
  General setup-&amp;gt;Local version - append to kernel release = b&lt;br /&gt;
  General setup-&amp;gt;Default hostname                         = slackzfs&lt;br /&gt;
  General setup-&amp;gt;Initramfs source files(s)                = /boot/initramfs-source&lt;br /&gt;
  Device Drivers-&amp;gt;SCSI device support-&amp;gt;SCSI low-level drivers-&amp;gt; &amp;lt;*&amp;gt; SYM53C8XX Version 2 SCSI support&lt;br /&gt;
  File systems -&amp;gt; &amp;lt;*&amp;gt; The Extended 4 (ext4) filesystem&lt;br /&gt;
  # build in any hard drive controllers and filesystems that you need for booting&lt;br /&gt;
  # then save the config&lt;br /&gt;
make prepare scripts&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The kernel source has been set to have a &amp;quot;Local version&amp;quot; &amp;lt;code&amp;gt;b&amp;lt;/code&amp;gt;. This will result in modules installed to &amp;lt;code&amp;gt;/lib/modules/3.2.29b&amp;lt;/code&amp;gt; and keeps this kernel's source and modules seperate from slackware's kernel-generic package installation. The &amp;lt;code&amp;gt;make prepare scripts&amp;lt;/code&amp;gt; command readies the kernel source as needed before we can install a copy of spl and zfs modules into the kernel source tree.&lt;br /&gt;
&lt;br /&gt;
Now proceed to configure and copy spl and zfs into the kernel source tree:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd ~/src&lt;br /&gt;
tar xvzf ~/spl-0.6.0-rc11.tar.gz&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-0.6.0-rc11&lt;br /&gt;
./configure \&lt;br /&gt;
    --prefix=/ \&lt;br /&gt;
    --libdir=/lib64 \&lt;br /&gt;
    --includedir=/usr/include \&lt;br /&gt;
    --datarootdir=/usr/share \&lt;br /&gt;
    --enable-linux-builtin=yes \&lt;br /&gt;
    --with-linux=/usr/src/linux-3.2.29b \&lt;br /&gt;
    --with-linux-obj=/usr/src/linux-3.2.29b&lt;br /&gt;
./copy-builtin /usr/src/linux-3.2.29b&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../spl-0.6.0rc11_3.2.29b-x86_64-1root.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
&lt;br /&gt;
tar xvzf ~/zfs-0.6.0-rc11.tar.gz&lt;br /&gt;
mkdir install&lt;br /&gt;
cd zfs-0.6.0-rc11&lt;br /&gt;
./configure \&lt;br /&gt;
    --prefix=/ \&lt;br /&gt;
    --libdir=/lib64 \&lt;br /&gt;
    --includedir=/usr/include \&lt;br /&gt;
    --datarootdir=/usr/share \&lt;br /&gt;
    --enable-linux-builtin=yes \&lt;br /&gt;
    --with-linux=/usr/src/linux-3.2.29b \&lt;br /&gt;
    --with-linux-obj=/usr/src/linux-3.2.29b \&lt;br /&gt;
    --with-spl=/root/src/spl-0.6.0-rc11&lt;br /&gt;
    --with-spl-obj=/root/src/spl-0.6.0-rc11&lt;br /&gt;
./copy-builtin /usr/src/linux-3.2.29b&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../zfs-0.6.0rc11_3.2.29b-x86_64-1root.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
At this point, the &amp;lt;code&amp;gt;copy-builtin&amp;lt;/code&amp;gt; scripts have installed the configured spl and zfs modules source into the kernel source. The regular &amp;lt;code&amp;gt;make menuconfig&amp;lt;/code&amp;gt; in the kernel source should now show options for spl and zfs in the kernel config.&lt;br /&gt;
&lt;br /&gt;
As of this writing, the copy-builtin script places the spl and zfs modules into the kernel source in places where the modules may not initialize in the best order, &amp;lt;i&amp;gt;after&amp;lt;/i&amp;gt; all lower-level storage drivers are initialized. If spl and zfs initialize too soon, there is a chance they may not be able to see all of the storage devices. The order of initialization (as seen in dmesg) of modules that are builtin to the kernel is the order that the modules are linked into the kernel during kernel compilation. The order of link depends on where the module source files are located in the kernel source tree. To ensure that spl and zfs will initialize after all hardware drivers, we can move them into the &amp;lt;code&amp;gt;drivers&amp;lt;/code&amp;gt; tree and after all other drivers. This move is &amp;lt;b&amp;gt;optional&amp;lt;/b&amp;gt; and you can skip doing this and everything will probably work fine, but it is shown here how to move the modules to under drivers in case you prefer them there:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /usr/src/linux-3.2.29b&lt;br /&gt;
mkdir drivers/zfsonlinux&lt;br /&gt;
mv spl drivers/zfsonlinux&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  # remove references to spl&lt;br /&gt;
vi Makefile&lt;br /&gt;
  # remove references to spl&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.29b/fs&lt;br /&gt;
mv zfs ../drivers/zfsonlinux&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  # remove references to zfs&lt;br /&gt;
vi Makefile&lt;br /&gt;
  # remove references to zfs&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.29b/drivers&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  )# add line at end of menu, before &amp;quot;endmenu&amp;quot;:&lt;br /&gt;
  )source &amp;quot;drivers/zfsonlinux/Kconfig&amp;quot;&lt;br /&gt;
  )endmenu&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.29b/drivers&lt;br /&gt;
vi Makefile&lt;br /&gt;
  )# add line at very end of file:&lt;br /&gt;
  )obj-$(CONFIG_ZFSONLINUX) += zfsonlinux/&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.29b/drivers/zfsonlinux&lt;br /&gt;
cat &amp;gt; Kconfig &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
menuconfig ZFSONLINUX&lt;br /&gt;
	tristate &amp;quot;ZFSonLinux support&amp;quot;&lt;br /&gt;
&lt;br /&gt;
if ZFSONLINUX&lt;br /&gt;
&lt;br /&gt;
source &amp;quot;drivers/zfsonlinux/spl/Kconifg&amp;quot;&lt;br /&gt;
&lt;br /&gt;
source &amp;quot;drivers/zfsonlinux/zfs/Kconifg&amp;quot;&lt;br /&gt;
&lt;br /&gt;
endif&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.29b/zfsonlinux&lt;br /&gt;
cat &amp;gt; Makefile &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
obj-$(CONFIG_SPL) += spl/&lt;br /&gt;
obj-$(CONFIG_ZFS) += zfs/&lt;br /&gt;
EOF&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This completes the move of the spl and zfs modules in the kernel source tree to be under &amp;lt;code&amp;gt;drivers/zfsonlinux&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Now, in kernel configuration, you can build in the modules as follows:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /usr/src/linux-3.2.29b&lt;br /&gt;
make menuconfig&lt;br /&gt;
   Device Drivers -&amp;gt;&lt;br /&gt;
    &amp;lt;*&amp;gt; ZFSonLinux support -&amp;gt;&lt;br /&gt;
      &amp;lt;*&amp;gt; Solaris Porting Layer (SPL)&lt;br /&gt;
      &amp;lt;*&amp;gt;     ZFS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the kernel config, we set &amp;lt;code&amp;gt;/boot/initramfs-source&amp;lt;/code&amp;gt; as source location of the contents to be linked into kernel's builtin initramfs (rootfs). Now, we create some files that are needed to be in the initramfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /boot/initramfs-source&lt;br /&gt;
&lt;br /&gt;
# make standard directories&lt;br /&gt;
mkdir -p proc dev sys mnt bin sbin etc/zfs&lt;br /&gt;
&lt;br /&gt;
# zfs seems to want mtab present, even if empty&lt;br /&gt;
touch etc/mtab&lt;br /&gt;
&lt;br /&gt;
# if zpool.cache file can be read by zfs at module init, it imports the pools in the cache&lt;br /&gt;
cp /etc/zfs/zpool.cache-initrd etc/zfs/zpool.cache&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
It is time to pause for a moment here and talk about zpool.cache: Using it is actually dangerous. We are not using udev and it's persistent block device filenames (/dev/disk/by-*), but are using the default kernel block device names (/dev/sd*) in devtmpfs. Device names for a hard drive in /dev can potentially change on boot depending on disk controller initialization order and disk drive response time. Adding another disk controller or hard disk on a controller can result in device name assignment changes to all the hard disks. A zpool.cache file holds all the zfs_member device filenames /dev/sd* for a pool configuration, but the zpool.cache configuration will be incorrect if device filenames have been changed or swapped around and this could result in a faulted pool that may or may not be recoverable. Using zpool.cache to import pools at boot, even with udev persistent device filenames, is potentially destructive if devices have been changed around. The proper thing to do is zpool_import and do not include zpool.cache in the initramfs.&lt;br /&gt;
&lt;br /&gt;
Now, let's continue making some files in the initramfs-source:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# make initial console device node; otherwise, there is a problem at startup:&lt;br /&gt;
# &amp;quot;Warning: unable to open an initial console&amp;quot; and you'd have problems with console and tty login&lt;br /&gt;
# making these nodes from within /init is not early enough to avoid problem&lt;br /&gt;
mknod dev/console c 5 1   # system console&lt;br /&gt;
&lt;br /&gt;
# make memory device kmsg to &amp;quot;printk&amp;quot; kernel messages&lt;br /&gt;
# we can write to this file to send out messages&lt;br /&gt;
mknod dev/kmsg    c 1 11  # lines printed to kmsg enter kernel messages buffer&lt;br /&gt;
&lt;br /&gt;
# recommended loop0 device to mount fs images&lt;br /&gt;
mknod dev/loop0   b 7 0&lt;br /&gt;
&lt;br /&gt;
# make initial virtual terminal devices&lt;br /&gt;
mknod dev/tty     c 5 0   # current tty&lt;br /&gt;
mknod dev/tty0    c 4 0   # current virtual term&lt;br /&gt;
mknod dev/tty1    c 4 1   # login virtual term 1 (F1)&lt;br /&gt;
&lt;br /&gt;
# make alternative console=ttyS0 standard 8250/16550 UART serial port devices&lt;br /&gt;
#   useful with kernel parameter console=ttyS0&lt;br /&gt;
#          with qemu -nographic -option-rom sgabios.bin,bootindex=0&lt;br /&gt;
mknod dev/ttyS0   c 4 64  # COM1&lt;br /&gt;
mknod dev/ttyS1   c 4 65  # COM2&lt;br /&gt;
mknod dev/ttyS2   c 4 66  # COM3&lt;br /&gt;
mknod dev/ttyS3   c 4 67  $ COM4&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This should be enough device nodes initially in the initramfs. Once devtmpfs mounts over /dev inside initramfs, a lot more devices are available in it by default.&lt;br /&gt;
&lt;br /&gt;
The initramfs needs an &amp;lt;code&amp;gt;/init&amp;lt;/code&amp;gt; program that will be run automatically by the kernel as process id 1, the first program to run on the system. This program's task is to mount a root filesystem, switch it to be the new root (/), and then exec the init (&amp;lt;code&amp;gt;/sbin/init&amp;lt;/code&amp;gt;) program that is on the new root so that the new root system is booted.&lt;br /&gt;
&lt;br /&gt;
The common way to make /init is using busybox with files like these in /boot/initrd-tree or /boot/initramfs-source:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
bin/busybox&lt;br /&gt;
bin/ash -&amp;gt; busybox&lt;br /&gt;
bin/sh -&amp;gt; busybox&lt;br /&gt;
# run busybox to see what other &amp;quot;applets&amp;quot; can be symlinked to it&lt;br /&gt;
# when busybox is run as a different symlinked applet name, it runs as the applet&lt;br /&gt;
init&lt;br /&gt;
# init can be an ash script, see slackware's /boot/initrd-tree/init for example&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For example, as an ash script, slackware's init does the following:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;parse kernel parameters passed into it and set variables based on them&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;start udevd and trigger rules for block devices to setup initial /dev devices&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;load kernel modules and keyboard map&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;run mdadm, cryptsetup, lvm, zpool/zfs to setup more devices&lt;br /&gt;
     (any udev rules for them should do more /dev setup in the background)&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;mount the root filesystem read-only at /mnt&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;stat /mnt/sbin/init, and if not executable run a rescue shell /bin/sh&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;shutdown udevd so it can be restarted by root system when booted&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;mount --move {proc,sys,run,dev} to under /mnt&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;run: exec switch_root /mnt /sbin/init $RUNLEVEL&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The slackware mkinitrd package is a fully configured BusyBox installation that makes an external initramfs image file, initrd.gz, that is passed to the kernel by the bootloader (lilo). It could be changed to be internal to the kernel by just using initrd-tree as the CONFIG_INITRAMFS_SOURCE in the kernel config and removing initrd in the lilo.conf.&lt;br /&gt;
&lt;br /&gt;
The main purpose of most initramfs/initrd is to load and configure kernel modules and devices needed to mount a root filesystem. Because the spl/zfs modules are builtin, there isn't really a lot that needs to be done by an initramfs. What remains to be done is import the zfs-root pool, mount it, and exec the system /sbin/init. The kernel's &amp;quot;legacy&amp;quot; parameters &amp;lt;code&amp;gt;root=&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;rootfstype=&amp;lt;/code&amp;gt; that are able to directly boot a root disk do not work with ZFS at this time because ZFS pools always need to be imported before it is possible to mount and boot on them. The automatic import that ZFS can do by using a cachefile (/etc/zfs/zpool.cache) stored in initramfs still does not work with the legacy boot parameters because at an earlier stage of the boot process, the kernel ignores a rootfs that does not contain an &amp;lt;code&amp;gt;/init&amp;lt;/code&amp;gt; program, and/or the device type of an imported pool is not the device types recognized by the legacy boot as valid root devices.&lt;br /&gt;
&lt;br /&gt;
You could just continue to use slackware's mkinitrd package as in the &amp;quot;ZFS root&amp;quot; wiki and it works the same whether the modules are builtin or not. But, by building the spl/zfs modules in, aren't we really wanting to get rid of using the mkinitrd/initrd.gz? We'd like to have a kernel with everything in it to boot, and use a simple lilo image entry that has no initrd.&lt;br /&gt;
&lt;br /&gt;
We can do this, and not use the mkinitrd package, but we still need to finish our own initramfs &amp;lt;code&amp;gt;/init&amp;lt;/code&amp;gt; program to import, mount, switch root, and boot. Save the following c program to &amp;quot;foobarz-init.c&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/* software product name: foobarz-init.c&lt;br /&gt;
 * suggested binary name: /init (in initramfs-source, rootfs)&lt;br /&gt;
 * license              : BSD&lt;br /&gt;
 * license text:&lt;br /&gt;
Copyright (c) 2012, foobarz&lt;br /&gt;
All rights reserved.&lt;br /&gt;
&lt;br /&gt;
Redistribution and use in source and binary forms, with or without&lt;br /&gt;
modification, are permitted provided that the following conditions are met:&lt;br /&gt;
    * Redistributions of source code must retain the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer.&lt;br /&gt;
    * Redistributions in binary form must reproduce the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer in the&lt;br /&gt;
      documentation and/or other materials provided with the distribution.&lt;br /&gt;
    * Neither the name of the &amp;lt;organization&amp;gt; nor the&lt;br /&gt;
      names of its contributors may be used to endorse or promote products&lt;br /&gt;
      derived from this software without specific prior written permission.&lt;br /&gt;
&lt;br /&gt;
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &amp;quot;AS IS&amp;quot; AND&lt;br /&gt;
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED&lt;br /&gt;
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE&lt;br /&gt;
DISCLAIMED. IN NO EVENT SHALL &amp;lt;COPYRIGHT HOLDER&amp;gt; BE LIABLE FOR ANY&lt;br /&gt;
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES&lt;br /&gt;
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;&lt;br /&gt;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND&lt;br /&gt;
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT&lt;br /&gt;
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS&lt;br /&gt;
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
/* Your initramfs-source should contain the following&lt;br /&gt;
 *&lt;br /&gt;
 * cd /boot/initramfs-source&lt;br /&gt;
 * mkdir -p proc dev sys mnt bin sbin etc/zfs&lt;br /&gt;
 * touch etc/mtab&lt;br /&gt;
 * cp /etc/zfs/zpool.cache-initrd etc/zfs/zpool.cache&lt;br /&gt;
 * # zpool.cache is optional - zpool_import_ kernel params can be used instead&lt;br /&gt;
 * #  see below for details on using zpool_import&lt;br /&gt;
 * mknod dev/console c 5 1   # system console&lt;br /&gt;
 * mknod dev/kmsg    c 1 11  # lines printed to kmsg enter kernel messages buffer&lt;br /&gt;
 * mknod dev/loop0   b 7 0&lt;br /&gt;
 * mknod dev/tty     c 5 0   # current tty&lt;br /&gt;
 * mknod dev/tty0    c 4 0   # current virtual term&lt;br /&gt;
 * mknod dev/tty1    c 4 1   # login virtual term 1 (F1)&lt;br /&gt;
 * mknod dev/ttyS0   c 4 64  # COM1&lt;br /&gt;
 * mknod dev/ttyS1   c 4 65  # COM2&lt;br /&gt;
 * mknod dev/ttyS2   c 4 66  # COM3&lt;br /&gt;
 * mknod dev/ttyS3   c 4 67  $ COM4&lt;br /&gt;
 *&lt;br /&gt;
 * Copy this compiled program to /boot/initramfs-source/init&lt;br /&gt;
 * If not named /init, then use rdinit=/othername kernel parameter.&lt;br /&gt;
 *&lt;br /&gt;
 * Set kernel config option&lt;br /&gt;
 *  CONFIG_INITRAMFS_SOURCE=/boot/initramfs-source&lt;br /&gt;
 * to build the initramfs into your kernel image&lt;br /&gt;
 *  that also has builtin drivers (spl and zfs, etc).&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
#define FOOBARZ_INIT_VERSION &amp;quot;1.1.2&amp;quot;&lt;br /&gt;
#define _BSD_SOURCE&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdarg.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;fcntl.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/mount.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sysexits.h&amp;gt;&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
/* support for zpool import&lt;br /&gt;
 *&lt;br /&gt;
 * If -DINCLUDE_ZPOOL_IMPORT, then support to import a zpool is&lt;br /&gt;
 * enabled in the program. Enabling it will add many dependencies to the&lt;br /&gt;
 * compile and link; for example:&lt;br /&gt;
 *&lt;br /&gt;
 * gcc -static -DINCLUDE_ZPOOL_IMPORT \&lt;br /&gt;
 *    foobarz-init.c -include /usr/src/zfs-0.6.0-rc10/3.2.29/zfs_config.h \&lt;br /&gt;
 *   -o init \&lt;br /&gt;
 *   -I /usr/include/libspl -I /usr/include/libzfs \&lt;br /&gt;
 *   -lzfs -lnvpair -lzpool -luutil -luuid -lrt -lz -lm -lpthread \&lt;br /&gt;
 *   -I /usr/include/tirpc \&lt;br /&gt;
 *   -ltirpc&lt;br /&gt;
 *&lt;br /&gt;
 * Note that libtirpc is a drop-in replacement for the SunRPC functions that&lt;br /&gt;
 * used to be in glibc. No additional includes are needed, just the gcc -I and -l&lt;br /&gt;
 * options for tirpc.&lt;br /&gt;
 *&lt;br /&gt;
 * Otherwise, with -UINCLUDE_ZPOOL_IMPORT, the compile is just:&lt;br /&gt;
 * gcc -static foobarz-init.c -o init&lt;br /&gt;
 */&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
#include &amp;lt;libzfs.h&amp;gt;&lt;br /&gt;
#else&lt;br /&gt;
#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/stat.h&amp;gt;&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#define PARAM_REQ_NO 0&lt;br /&gt;
#define PARAM_REQ_YES 1&lt;br /&gt;
#define PARAM_SRC_DEFAULT 0&lt;br /&gt;
#define PARAM_SRC_CMDLINE 1&lt;br /&gt;
&lt;br /&gt;
void printk(char *fmt, ...) {&lt;br /&gt;
  FILE* f;&lt;br /&gt;
  int fd;&lt;br /&gt;
  va_list args;&lt;br /&gt;
&lt;br /&gt;
  f = fopen(&amp;quot;/dev/kmsg&amp;quot;, &amp;quot;w&amp;quot;);&lt;br /&gt;
  va_start(args, fmt);&lt;br /&gt;
  vfprintf(f, fmt, args);&lt;br /&gt;
  va_end(args);&lt;br /&gt;
  fflush(f);&lt;br /&gt;
  fclose(f);&lt;br /&gt;
  /* avoid flooding kmsg and having msgs suppressed; 20msgs/sec */&lt;br /&gt;
  usleep(50000);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[]) {&lt;br /&gt;
 /*** variables */&lt;br /&gt;
&lt;br /&gt;
 int i;&lt;br /&gt;
 int   fd = 0; /* file descriptor */&lt;br /&gt;
 unsigned long mountflags;&lt;br /&gt;
&lt;br /&gt;
 /* kernel command line */&lt;br /&gt;
 off_t cmdline_size;&lt;br /&gt;
 char* cmdline; /* to be malloc 4096B */&lt;br /&gt;
 char* cmdline_end;&lt;br /&gt;
 char* temp_end;&lt;br /&gt;
 char* src_msg; /* default or cmdline */&lt;br /&gt;
 int flag_param_missing = 0;&lt;br /&gt;
&lt;br /&gt;
 /* use to hold contents of a misc /proc/&amp;lt;file&amp;gt; */&lt;br /&gt;
 char* miscproc_buff; /* to be malloc 4096B */&lt;br /&gt;
 off_t miscproc_size;&lt;br /&gt;
&lt;br /&gt;
 /* note about environ, argv, and kernel cmdline for init:&lt;br /&gt;
  *   environ is not defined for init&lt;br /&gt;
  *   only argv[0] is set for init&lt;br /&gt;
  *   kernel command line parameters are accessed&lt;br /&gt;
  *   at /proc/cmdline&lt;br /&gt;
  */&lt;br /&gt;
&lt;br /&gt;
 /* kernel parameters expected to be name=value */&lt;br /&gt;
 /* do not use quotes or spaces in parameters   */&lt;br /&gt;
 /* you can add more params somwhere after root= */&lt;br /&gt;
 struct nv { char* n; char* v; char* v_end; int req; int src; };&lt;br /&gt;
 struct nv param[] = {&lt;br /&gt;
   { &amp;quot; root=&amp;quot;,       NULL, NULL, PARAM_REQ_YES, PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot; rootfstype=&amp;quot;, NULL, NULL, PARAM_REQ_YES, PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot; mountopt=&amp;quot;,   NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot; init=&amp;quot;,       NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot; runlevel=&amp;quot;,   NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot; console=&amp;quot;,    NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT }&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
   ,&lt;br /&gt;
   { &amp;quot; zpool_import_name=&amp;quot;,    NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot; zpool_import_guid=&amp;quot;,    NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot; zpool_import_newname=&amp;quot;, NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot; zpool_import_force=&amp;quot;,   NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT }&lt;br /&gt;
#endif&lt;br /&gt;
 };&lt;br /&gt;
 enum {&lt;br /&gt;
	 iroot,&lt;br /&gt;
	 irootfstype,&lt;br /&gt;
	 imountopt,&lt;br /&gt;
	 iinit,&lt;br /&gt;
	 irunlevel,&lt;br /&gt;
	 iconsole,&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
	 izpool_import_name,&lt;br /&gt;
	 izpool_import_guid,&lt;br /&gt;
	 izpool_import_newname,&lt;br /&gt;
	 izpool_import_force,&lt;br /&gt;
#endif&lt;br /&gt;
	 ilastparam&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
 libzfs_handle_t* libzfs = NULL;&lt;br /&gt;
 importargs_t iargs = { 0 };&lt;br /&gt;
 nvlist_t* pools = NULL;&lt;br /&gt;
 nvpair_t* pool = NULL;&lt;br /&gt;
 nvlist_t* config = NULL;&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
 /*** program */&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;foobarz-init, version %s: booting initramfs.\n&amp;quot;, FOOBARZ_INIT_VERSION);&lt;br /&gt;
&lt;br /&gt;
 cmdline       = (char*) malloc(4096);&lt;br /&gt;
 miscproc_buff = (char*) malloc(4096);&lt;br /&gt;
 if( (cmdline == NULL) || (miscproc_buff == NULL) ) {&lt;br /&gt;
   printk(&amp;quot;Unable to allocate buffer memory: malloc: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount proc /proc&lt;br /&gt;
  *  note: some /dev devices symlink into /proc&lt;br /&gt;
  *  proc contains info about processes, including cmdline etc. */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount proc /proc\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;proc&amp;quot;, &amp;quot;/proc&amp;quot;, &amp;quot;proc&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
   printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
   printk(&amp;quot;Mount proc successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount devtmpfs /dev&lt;br /&gt;
  *  note: This simple init program works if your root device is made from devices&lt;br /&gt;
  *  that are available by default in devtmpfs, such as /dev/sd*&lt;br /&gt;
  *&lt;br /&gt;
  *  For zfs, your root zfs pool should be created with default device nodes and&lt;br /&gt;
  *  then it should be mountable by this simple init program.&lt;br /&gt;
  *&lt;br /&gt;
  *  udev may be needed to configure device nodes and symlinks required&lt;br /&gt;
  *  to access a root device configuration made with such nodes and symlinks.&lt;br /&gt;
  *  If you need udevd, you can include it into your initramfs-source and&lt;br /&gt;
  *  modify this program to run it before attempting to mount your root device.&lt;br /&gt;
  *  However, if udevd is needed, a significant number of userspace programs may also be&lt;br /&gt;
  *  required by rules in /lib/udev/. You could install busybox + udev (about 5MB) or&lt;br /&gt;
  *  coreutils + util-linux + bash + udev (about 25MB) into initramfs-source. But, at that&lt;br /&gt;
  *  point you'd have ash or bash and many tools that are easier to use than this&lt;br /&gt;
  *  simple init program; it would then be easy to have /init as #!/bin/&amp;lt;b&amp;gt;ash script. */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount devtmpfs /dev\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;devtmpfs&amp;quot;, &amp;quot;/dev&amp;quot;, &amp;quot;devtmpfs&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
   printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
   printk(&amp;quot;Mount devtmpfs successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount sysfs /sys&lt;br /&gt;
  *  note: some kernel modules try to access /sys with userspace helpers to echo values into /sys variables;&lt;br /&gt;
  *  such modules expect a minimal userspace that contains coreutils or busybox */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount sysfs /sys\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;sysfs&amp;quot;, &amp;quot;/sys&amp;quot;, &amp;quot;sysfs&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
   printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
   printk(&amp;quot;Mount sysfs successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* process kernel command line */&lt;br /&gt;
 fd = open(&amp;quot;/proc/cmdline&amp;quot;, O_RDONLY);&lt;br /&gt;
 if( fd == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Cannot open /proc/cmdline: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 /* note, on /proc fs:&lt;br /&gt;
  *       lseek likely always returns error&lt;br /&gt;
  *       stat likely always returns st_size = 0&lt;br /&gt;
  *   so determining size of /proc file means just reading it;&lt;br /&gt;
  *   you have to read /proc files according to their documented&lt;br /&gt;
  *   maximum sizes; this is probably for performance reasons */&lt;br /&gt;
 cmdline_size = read(fd, cmdline, 4095);&lt;br /&gt;
 if( cmdline_size == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Failed to read /proc/cmdline: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 close(fd);&lt;br /&gt;
&lt;br /&gt;
 /* cmdline may be newline + null terminated, but make it null + null */&lt;br /&gt;
 cmdline[cmdline_size] = '\0';&lt;br /&gt;
 if( cmdline[cmdline_size-1] == '\n' ) {&lt;br /&gt;
   cmdline[cmdline_size-1] = '\0';&lt;br /&gt;
   cmdline_size--;&lt;br /&gt;
   cmdline_end = cmdline + cmdline_size;&lt;br /&gt;
 }&lt;br /&gt;
 printk(&amp;quot;Kernel cmdline size: %i\n&amp;quot;, cmdline_size);&lt;br /&gt;
 printk(&amp;quot;Kernel cmdline: \&amp;quot;%s\&amp;quot;\n&amp;quot;, cmdline);&lt;br /&gt;
&lt;br /&gt;
 /* find v and v_end of values in cmdline */&lt;br /&gt;
 for( i=iroot; i&amp;lt;ilastparam; i++ ) {&lt;br /&gt;
   param[i].v = strstr(cmdline, param[i].n);&lt;br /&gt;
   if( param[i].v != NULL ) {&lt;br /&gt;
     param[i].src = PARAM_SRC_CMDLINE;&lt;br /&gt;
     while( *(param[i].v) != '=' ) param[i].v++;&lt;br /&gt;
     param[i].v++;&lt;br /&gt;
     temp_end = param[i].v;&lt;br /&gt;
     while( !( (*temp_end == ' ') ||&lt;br /&gt;
               (*temp_end == '\n') ||&lt;br /&gt;
               (temp_end == cmdline_end)&lt;br /&gt;
	     ) ) temp_end++;&lt;br /&gt;
     if( temp_end == param[i].v ) {&lt;br /&gt;
       printk(&amp;quot;Kernel parameter %s: value missing.\n&amp;quot;, param[i].n);&lt;br /&gt;
       param[i].v = NULL;&lt;br /&gt;
     } else param[i].v_end = temp_end;&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* set defaults for params not given on cmdline */&lt;br /&gt;
 for( i=iroot; i&amp;lt;ilastparam; i++ ) {&lt;br /&gt;
   /* terminate value strings */&lt;br /&gt;
   if( param[i].v_end != NULL ) *(param[i].v_end) = '\0';&lt;br /&gt;
   /* set defaults if no value on cmdline */&lt;br /&gt;
   if( param[i].v == NULL ) {&lt;br /&gt;
     param[i].src = PARAM_SRC_DEFAULT;&lt;br /&gt;
     if( param[i].req == PARAM_REQ_YES ) flag_param_missing = 1;&lt;br /&gt;
     switch(i) {&lt;br /&gt;
       case iroot      : param[i].v = &amp;quot;&amp;lt;missing required param&amp;gt;&amp;quot; ; break;&lt;br /&gt;
       case irootfstype: param[i].v = &amp;quot;&amp;lt;missing required param&amp;gt;&amp;quot; ; break;&lt;br /&gt;
       case imountopt  : param[i].v = &amp;quot;ro&amp;quot;        ; break;&lt;br /&gt;
       case iinit      : param[i].v = &amp;quot;/sbin/init&amp;quot;; break;&lt;br /&gt;
       case irunlevel  : param[i].v = &amp;quot;3&amp;quot;         ; break;&lt;br /&gt;
       case iconsole   : param[i].v = &amp;quot;console&amp;quot;   ; break;&lt;br /&gt;
       default         : param[i].v = NULL;&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
   if(param[i].src == PARAM_SRC_DEFAULT) src_msg = &amp;quot;default&amp;quot;;&lt;br /&gt;
   else src_msg = &amp;quot;cmdline&amp;quot;;&lt;br /&gt;
   printk(&amp;quot;Using %s \&amp;quot;%s\&amp;quot; (source: %s)\n&amp;quot;, param[i].n, param[i].v, src_msg);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 if( flag_param_missing ) {&lt;br /&gt;
   printk(&amp;quot;Aborting boot process: missing required kernel parameter(s).\n&amp;quot;);&lt;br /&gt;
   return EX_USAGE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* generic nv pair kernel cmdline processing finished&lt;br /&gt;
  *  now, examine specific params for defaults and correctness */&lt;br /&gt;
&lt;br /&gt;
 /* param[irootfstype]: can be checked against /proc/filesystems: */&lt;br /&gt;
 fd = open(&amp;quot;/proc/filesystems&amp;quot;, O_RDONLY);&lt;br /&gt;
 if( fd == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Cannot open /proc/filesystems: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 miscproc_size = read(fd, miscproc_buff, 4095);&lt;br /&gt;
 if( miscproc_size == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Failed to read /proc/filesystems: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 close(fd);&lt;br /&gt;
 if( strstr(miscproc_buff, param[irootfstype].v) == NULL ) {&lt;br /&gt;
   printk(&amp;quot;%s \&amp;quot;%s\&amp;quot;: filesystem type not available.\n&amp;quot;, param[irootfstype].n, param[irootfstype].v);&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* zfs-specific */&lt;br /&gt;
 if( strcmp(param[irootfstype].v, &amp;quot;zfs&amp;quot;) == 0 ) {&lt;br /&gt;
   if( access(&amp;quot;/etc/zfs/zpool.cache&amp;quot;, F_OK) == 0 )&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/zfs/zpool.cache is present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
   else&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/zfs/zpool.cache not present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
&lt;br /&gt;
   if( access(&amp;quot;/etc/hostid&amp;quot;, F_OK) == 0 )&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/hostid is present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
   else&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/hostid not present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
   /* zpool import */&lt;br /&gt;
   if( (param[izpool_import_name].v != NULL) || (param[izpool_import_guid].v != NULL) ) {&lt;br /&gt;
	printk(&amp;quot;zpool_import: import requested.\n&amp;quot;);&lt;br /&gt;
	if( (param[izpool_import_name].v != NULL) &amp;amp;&amp;amp; (param[izpool_import_guid].v != NULL) ) {&lt;br /&gt;
		printk(&amp;quot;zpool_import: given both pool name and guid; using guid.\n&amp;quot;);&lt;br /&gt;
		param[izpool_import_name].v = NULL;&lt;br /&gt;
	}&lt;br /&gt;
	if( param[izpool_import_name].v != NULL )&lt;br /&gt;
		printk(&amp;quot;zpool_import: pool name: %s\n&amp;quot;, param[izpool_import_name].v );&lt;br /&gt;
	else&lt;br /&gt;
		printk(&amp;quot;zpool_import: pool guid: %s\n&amp;quot;, param[izpool_import_guid].v );&lt;br /&gt;
&lt;br /&gt;
	iargs.path = NULL;&lt;br /&gt;
	iargs.paths = 0;&lt;br /&gt;
	iargs.poolname = param[izpool_import_name].v;&lt;br /&gt;
	if( param[izpool_import_guid].v != NULL )&lt;br /&gt;
		iargs.guid = strtoull(param[izpool_import_guid].v, NULL, 10);&lt;br /&gt;
	else&lt;br /&gt;
		iargs.guid = 0;&lt;br /&gt;
	iargs.cachefile = NULL;&lt;br /&gt;
	if( (param[izpool_import_force].v != NULL) &amp;amp;&amp;amp; (strcmp(param[izpool_import_force].v, &amp;quot;1&amp;quot;) == 0) ) {&lt;br /&gt;
		iargs.can_be_active = 1;&lt;br /&gt;
		printk(&amp;quot;zpool_import: import forced.\n&amp;quot;);&lt;br /&gt;
	} else {&lt;br /&gt;
		iargs.can_be_active = 0;&lt;br /&gt;
		printk(&amp;quot;zpool_import: import not forced.\n&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
	iargs.unique = 1;&lt;br /&gt;
	iargs.exists = 1;&lt;br /&gt;
&lt;br /&gt;
	printk(&amp;quot;zpool_import: init libzfs.\n&amp;quot;);&lt;br /&gt;
	libzfs = libzfs_init();&lt;br /&gt;
	if( libzfs != NULL ) {&lt;br /&gt;
		printk(&amp;quot;zpool_import: searching for pool.\n&amp;quot;);&lt;br /&gt;
		pools = zpool_search_import(libzfs, &amp;amp;iargs);&lt;br /&gt;
		if( (pools == NULL) || nvlist_empty(pools) )&lt;br /&gt;
			printk(&amp;quot;zpool_import: pool not available for import, or already imported by cachefile.\n&amp;quot;);&lt;br /&gt;
		else {&lt;br /&gt;
			printk(&amp;quot;zpool_import: getting pool information.\n&amp;quot;);&lt;br /&gt;
			pool = nvlist_next_nvpair(pools, pool);&lt;br /&gt;
			printk(&amp;quot;zpool_import: getting pool configuration.\n&amp;quot;);&lt;br /&gt;
			nvpair_value_nvlist(pool, &amp;amp;config);&lt;br /&gt;
			printk(&amp;quot;zpool_import: attempting pool import.\n&amp;quot;);&lt;br /&gt;
			if( zpool_import(libzfs, config, param[izpool_import_newname].v, NULL) != 0 ) {&lt;br /&gt;
				printk(&amp;quot;zpool_import: import failed.\n&amp;quot;);&lt;br /&gt;
				printk(&amp;quot;zpool_import: error description: %s\n&amp;quot;, libzfs_error_description(libzfs) );&lt;br /&gt;
				printk(&amp;quot;zpool_import: error action: %s\n&amp;quot;, libzfs_error_action(libzfs) );&lt;br /&gt;
			} else  printk(&amp;quot;zpool_import: import successful.\n&amp;quot;);&lt;br /&gt;
		}&lt;br /&gt;
		printk(&amp;quot;zpool_import: fini libzfs.\n&amp;quot;);&lt;br /&gt;
		libzfs_fini(libzfs);&lt;br /&gt;
	} else {&lt;br /&gt;
		printk(&amp;quot;zpool_import: unable to initialize libzfs.\n&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
   }&lt;br /&gt;
#endif /* zpool_import */&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 if(      strcmp(param[imountopt].v, &amp;quot;ro&amp;quot;) == 0 ) mountflags = MS_RDONLY;&lt;br /&gt;
 else if( strcmp(param[imountopt].v, &amp;quot;rw&amp;quot;) == 0 ) mountflags = 0;&lt;br /&gt;
 else {&lt;br /&gt;
   printk(&amp;quot;%s \&amp;quot;%s\&amp;quot;: invalid parameter value; defaulting to \&amp;quot;ro\&amp;quot;.\n&amp;quot;, param[imountopt].n, param[imountopt].v);&lt;br /&gt;
   mountflags = MS_RDONLY;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* param[iroot]: nothing to check; if user gives bad root=device then mount fails */&lt;br /&gt;
&lt;br /&gt;
 /* try to mount root=device at /mnt&lt;br /&gt;
  *&lt;br /&gt;
  * note: for zfs, if a copy of /etc/zfs/zpool.cache (when pool is imported) is put in initramfs-source, then&lt;br /&gt;
  * the zfs module can read it and automatically import the pools described in the cache file; the imported&lt;br /&gt;
  * pools can be available to mount here if they were created using standard device names, otherwise&lt;br /&gt;
  * udevd may be required to run before mounting the pool */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount -t %s -o %s %s /mnt.\n&amp;quot;, param[irootfstype].v, param[imountopt].v, param[iroot].v);&lt;br /&gt;
 if( mount(param[iroot].v, &amp;quot;/mnt&amp;quot;, param[irootfstype].v, mountflags, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 printk(&amp;quot;%s mounted successfully.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
&lt;br /&gt;
 /* check to see if the mounted root filesystem has an executable init program */&lt;br /&gt;
 chdir(&amp;quot;/mnt&amp;quot;);&lt;br /&gt;
 if( access(param[iinit].v+1, X_OK) != 0 ) {&lt;br /&gt;
   chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
   printk(&amp;quot;access X_OK: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   printk(&amp;quot;The init program /mnt/%s is not present or not executable.\n&amp;quot;, param[iinit].v+1);&lt;br /&gt;
   printk(&amp;quot;Aborting boot process: no init program.\n&amp;quot;);&lt;br /&gt;
   printk(&amp;quot;Unmounting %s.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
   if( umount(&amp;quot;/mnt&amp;quot;) == -1 ) {&lt;br /&gt;
     printk(&amp;quot;umount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
     printk(&amp;quot;Failed to umount %s.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
   } else printk(&amp;quot;Successfully unmounted %s.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
 printk(&amp;quot;Init program /mnt/%s is present and executable.\n&amp;quot;, param[iinit].v+1);&lt;br /&gt;
&lt;br /&gt;
 /* switch the root / from initramfs to the mounted new root device at /mnt.&lt;br /&gt;
  *&lt;br /&gt;
  * note: after this switch, it is not possible to access the initramfs files anymore,&lt;br /&gt;
  * yet they consume ram memory unless they are deleted here before switching.&lt;br /&gt;
  * Any programs that are run after clearing the initramfs and switching root must exist on the new root.&lt;br /&gt;
  * This program may safely delete itself (/init) since it is already in ram and executing.&lt;br /&gt;
  * If you have installed additional files and programs in initramfs that consume significant ram,&lt;br /&gt;
  * then you need to insert additional code here to delete those files (carefully). */&lt;br /&gt;
&lt;br /&gt;
 /* delete files off of initramfs to free ram memory */&lt;br /&gt;
 printk(&amp;quot;Freeing memory from initramfs...\n&amp;quot;);&lt;br /&gt;
 if( unlink(argv[0]) != 0 ) printk(&amp;quot;unlink %s: %s\n&amp;quot;, argv[0], strerror(errno));&lt;br /&gt;
 else printk(&amp;quot;%s %s&amp;quot;, argv[0], &amp;quot;deleted from initramfs.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 /* switch root */&lt;br /&gt;
 printk(&amp;quot;Beginning switch root procedure.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(1) Attempting cmd: mount --move /dev /mnt/dev \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/dev&amp;quot;, &amp;quot;/mnt/dev&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(2) Attempting cmd: mount --move /proc /mnt/proc \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/proc&amp;quot;, &amp;quot;/mnt/proc&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(3) Attempting cmd: mount --move /sys /mnt/sys \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/sys&amp;quot;, &amp;quot;/mnt/sys&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(4) Attempting cmd: chdir /mnt \n&amp;quot;);&lt;br /&gt;
 if( chdir(&amp;quot;/mnt&amp;quot;) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: chdir: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(5) Attempting cmd: mount --move . / \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;.&amp;quot;, &amp;quot;/&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(6) Attempting cmd: chroot . \n&amp;quot;);&lt;br /&gt;
 if( chroot(&amp;quot;.&amp;quot;) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: chroot: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(7) Attempting cmd: chdir / \n&amp;quot;);&lt;br /&gt;
 if( chdir(&amp;quot;/&amp;quot;) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: chdir: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 printk(&amp;quot;Completed switch root procedure.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 /* check for &amp;quot;console=&amp;quot; kernel parameter and switch&lt;br /&gt;
  *  stdin, stdout, and stderr to named console device&lt;br /&gt;
  */&lt;br /&gt;
 if( param[iconsole].src == PARAM_SRC_CMDLINE ) {&lt;br /&gt;
   printk(&amp;quot;Console redirection to device %s requested.\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
   /* expect only basename of console device (e.g., ttyS0), so chdir /dev */&lt;br /&gt;
   chdir(&amp;quot;/dev&amp;quot;);&lt;br /&gt;
   if( access(param[iconsole].v, F_OK ) == 0 ) {&lt;br /&gt;
     printk(&amp;quot;Opening stdin, stdout, and stderr on %s.\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
     close(0);&lt;br /&gt;
     open(param[iconsole].v, O_RDWR);&lt;br /&gt;
     dup2(0, 1);&lt;br /&gt;
     dup2(0, 2);&lt;br /&gt;
   } else {&lt;br /&gt;
     printk(&amp;quot;access F_OK: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
     printk(&amp;quot;Could not access device: %s!\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
     printk(&amp;quot;Console redirection to device %s aborted!\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
   }&lt;br /&gt;
   chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;Execing: \&amp;quot;%s %s\&amp;quot; to boot mounted root system.\n&amp;quot;, param[iinit].v, param[irunlevel].v);&lt;br /&gt;
&lt;br /&gt;
 /* free resources held to this point */&lt;br /&gt;
 free(cmdline);&lt;br /&gt;
 free(miscproc_buff);&lt;br /&gt;
&lt;br /&gt;
 if( execl(param[iinit].v, param[irunlevel].v, (char *) NULL ) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: execl: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If foobarz-init is updated, you can find the latest version at [https://github.com/foobarz/foobarz-init github].&lt;br /&gt;
&lt;br /&gt;
The foobarz-init program can be compiled two ways as of v1.1.1. First, the simpler compile that does not support zpool_import but does support importing pools using a /etc/zfs/zpool.cache file in the initramfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gcc --static init.c -o init&lt;br /&gt;
strip init&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The second way to compile it adds support for zpool_import so that you do not have to include a &amp;lt;code&amp;gt;/etc/zfs/zpool.cache&amp;lt;/code&amp;gt; file in the initramfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gcc -static -DINCLUDE_ZPOOL_IMPORT \&lt;br /&gt;
     foobarz-init.c -include /usr/src/linux-3.2.29b/zfs_config.h \&lt;br /&gt;
    -o init \&lt;br /&gt;
    -I /usr/include/libspl -I /usr/include/libzfs \&lt;br /&gt;
    -lzfs -lnvpair -lzpool -luutil -luuid -lrt -lz -lm -lpthread \&lt;br /&gt;
    -I /usr/include/tirpc \&lt;br /&gt;
    -ltirpc&lt;br /&gt;
strip init&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Dependencies required before you can compile this second way:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Install [http://sourceforge.net/projects/libtirpc/ libtirpc]. The glibc package has removed the RPC-related functions from the static libc. The libtirpc is the new replacement as a separate library. You can make your own libtirpc package and install it to resolve these RPC-related functions. Without this, the compile fails because it cannot find many &amp;quot;xdr&amp;quot; functions.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Reinstall the [ftp://slackware.mirrors.tds.net/pub/slackware/slackware64-current/source/a/util-linux/ util-linux] package with static libraries enabled. Edit the &amp;lt;code&amp;gt;util-linux.SlackBuild&amp;lt;/code&amp;gt; and remove the line &amp;lt;code&amp;gt;--disable-static&amp;lt;/code&amp;gt;, then build it and use upgradepkg to install the new package. This resolves linking static to libuuid.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;code&amp;gt;zfs_config.h&amp;lt;/code&amp;gt; can be found in the kernel source when you have installed the builtin spl/zfs configuration; for example at &amp;lt;code&amp;gt;/usr/src/linux-3.2.29b/zfs_config.h&amp;lt;/code&amp;gt;. If you currently have installed the modular spl/zfs configuration, &amp;lt;code&amp;gt;zfs_config.h&amp;lt;/code&amp;gt; is found where the zfs module headers are installed; for example at &amp;lt;code&amp;gt;/usr/src/zfs-0.6.0-rc11/3.2.29/zfs_config.h&amp;lt;/code&amp;gt;. Wherever it is, &amp;lt;code&amp;gt;-include&amp;lt;/code&amp;gt; it as shown in the example gcc line above. zfs_config.h seems misplaced because it would seem that using libzfs shouldn't depend on modules header files.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;You may need to install the spl and zfs packages configured for --enable-linux-builtin=yes before compiling and linking to libzfs to make sure you are using the version of libzfs intended for builtin modules in case a difference between the two configurations exists. Currently, there seems to be no difference in the libzfs for either modular or builtin modules, but later there could be at least a small difference for detection of modules to load or builtin already. You may see a message that the ZFS modules stack load failed, but it can be ignored since the modules are builtin; this is just libzfs trying to load the modules even though they are builtin.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
With these dependencies, you can probably compile static with the zpool_import support. The exact location of &amp;quot;zfs_config.h&amp;quot; may vary depending on your zfs and kernel versions, so adjust accordingly.&lt;br /&gt;
&lt;br /&gt;
Read the foobarz-init source code to see how it uses kernel parameters. The params &amp;lt;code&amp;gt;root&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;rootfstype&amp;lt;/code&amp;gt; are always required to tell init what root pool name to mount and the filesystem type (e.g. zfs).&lt;br /&gt;
&lt;br /&gt;
For the zpool_import support: &amp;lt;code&amp;gt;zpool_import_name=poolname&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;zpool_import_guid=&amp;lt;guid of a pool&amp;gt;&amp;lt;/code&amp;gt; tells what pool to import. You can also import the pool with a new different name by also using &amp;lt;code&amp;gt;zpool_import_newname=newpoolname&amp;lt;/code&amp;gt;. If the import is not working, &amp;lt;code&amp;gt;zpool_import_force=1&amp;lt;/code&amp;gt; can be used to force import even if ZFS thinks the pool may be in use by another system.&lt;br /&gt;
&lt;br /&gt;
However you import the pool, either using zpool.cache or zpool_import support, the kernel param &amp;lt;code&amp;gt;root=&amp;lt;your poolname or newpoolname&amp;gt;&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;rootfstype=zfs&amp;lt;/code&amp;gt; needs to be given also. The zpool_import only imports, it does not say what to mount. What to mount is still told using root= and rootfstype=.&lt;br /&gt;
&lt;br /&gt;
Now copy the compiled static program into the initramfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp init /boot/initramfs-source/init&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Build and install kernel:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /usr/src/linux-3.2.29b&lt;br /&gt;
make -j8&lt;br /&gt;
make -j8 modules_install&lt;br /&gt;
cp arch/x86/boot/bzImage /boot/vm3.2.29b&lt;br /&gt;
cp System.map /boot/System.map-vm3.2.29b&lt;br /&gt;
# add new lilo menu entry for vm3.2.29b kernel&lt;br /&gt;
vi /etc/lilo.conf&lt;br /&gt;
  image = /boot/vm3.2.29b&lt;br /&gt;
   label = vm3.2.29b&lt;br /&gt;
   addappend = &amp;quot; spl.spl_hostid=0x007f0100 zfs.spa_config_path=/etc/zfs/zpool.cache root=zfs-root rootfstype=zfs&amp;quot;&lt;br /&gt;
lilo&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Note: If &amp;lt;code&amp;gt;spl.spl_hostid=0x007f0100&amp;lt;/code&amp;gt; is not included in addappend, then during boot SPL module will attempt to read /etc/hostid or run a user-space helper to write the &amp;lt;code&amp;gt;hostid&amp;lt;/code&amp;gt; into &amp;lt;code&amp;gt;/proc/sys/kernel/spl/hostid&amp;lt;/code&amp;gt;. Reading /etc/hostid fails unless you use foobarz-chhostid and make the file and copy it into /boot/initramfs-source/etc/hostid. The helper will fail because no &amp;lt;code&amp;gt;sh&amp;lt;/code&amp;gt; shell and no &amp;lt;code&amp;gt;hostid&amp;lt;/code&amp;gt; command are installed in the initramfs. The default hostid becomes 0xffffffff, which is considered an invalid hostid.&lt;br /&gt;
&lt;br /&gt;
Congrats! If this works, you can select the &amp;quot;vm3.2.29b&amp;quot; lilo entry to boot. If you are using the zpool_import support in the init program, you need to add at least the &amp;lt;code&amp;gt;zpool_import_name=zfs-root&amp;lt;/code&amp;gt; param to the addappend line in lilo.conf.&lt;br /&gt;
&lt;br /&gt;
Notes on kernel params (lilo append and addappend lines): root= and rootfstype= are used by both foorbarz-init and mkinitrd. The &amp;quot;ro&amp;quot; param is not used by foobarz-init, so instead use: mountopt=ro|rw. See &amp;quot;modinfo spl&amp;quot; and &amp;quot;modinfo zfs&amp;quot; to see all of the options those modules can take on the kernel command line. Notice the &amp;lt;code&amp;gt;spl.spl_hostid=0x007f0100&amp;lt;/code&amp;gt; param that works around the hostid mismatch problem while trying to import a pool; this param and hostname/ip set to use local loopback 127.0.0.1 in etc/hosts etc/HOSTNAME in initramfs will work most of the time, and if not the pool import needs to be forced.&lt;br /&gt;
&lt;br /&gt;
Notes on the spl and zfs packages to install: &amp;lt;i&amp;gt;If&amp;lt;/i&amp;gt; you have errors using zfs and zpool commands on booted system with builtin modules, then upgrade/switch to the 0.6.0rc11_3.2.29b builds, or you can make a custom package with the binaries renamed like zpoolb, zfsb etc for builtin.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
Using qemu's -nographic serial console (/usr/share/qemu/sgabios.bin): If you have a boot problem, you might want to run in qemu's -nographic console mode:&lt;br /&gt;
&lt;br /&gt;
First, edit /etc/inittab, and uncomment the line for local serial ports runlevel &amp;quot;s1&amp;quot; (ttyS0) for serial console login support. This is done in the guest (host does not need this):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Local serial lines:&lt;br /&gt;
s1:12345:respawn:/sbin/agetty -L ttyS0 38400 linux&lt;br /&gt;
#s1:12345:respawn:/sbin/agetty -L ttyS0 9600 vt100&lt;br /&gt;
#s2:12345:respawn:/sbin/agetty -L ttyS1 9600 vt100&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Second, edit /etc/securetty, and uncomment ttyS0 line:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ttyS0&lt;br /&gt;
#ttyS1&lt;br /&gt;
# ...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
You cannot login on ttyS0 without this change even though you get the login prompt!&lt;br /&gt;
&lt;br /&gt;
Then, run qemu such as:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
qemu-kvm &amp;lt;all regular options&amp;gt; -nographic -option-rom sgabios.bin,bootindex=0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Wait for the lilo prompt, it may take several seconds show up in this mode.&lt;br /&gt;
&lt;br /&gt;
In the lilo menu, select your kernel image with builtin spl/zfs, and use kernel params such as:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
boot: vm3.2.29b console=ttyS0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
At the lilo prompt, use kernel parameter: console=ttyS0 (do NOT say /dev/ttS0). Passing runlevel=s1 does not appear to be necessary.&lt;br /&gt;
&lt;br /&gt;
When you are in qemu's serial mode, the interface is a little different than in the normal graphical mode: use keypresses:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ctrl-a h    # for help&lt;br /&gt;
ctrl-a c    # toggle access to (QEMU) console / back to emulation&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If you cannot get a login: prompt, try ctrl-a c, then do (QEMU) sendkey ctrl-alt-delete. This will reboot cleanly back to lilo, then you can do (QEMU) quit.&lt;br /&gt;
&lt;br /&gt;
Once you login to the guest, the terminal size needs adjustment. On your host, in another xterm sized the same as your guest console terminal, get the size of the terminal:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo $LINES&lt;br /&gt;
echo $COLUMNS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Now, back in the guest terminal of same size:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export LINES &amp;lt;lines&amp;gt;&lt;br /&gt;
export COLUMNS &amp;lt;columns&amp;gt;&lt;br /&gt;
stty cols $COLUMNS rows $LINES&lt;br /&gt;
exec bash&lt;br /&gt;
reset&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
So, you set the environment variables and also set them with stty. Then, restart bash (exec, or else it is a child shell process).&lt;br /&gt;
&lt;br /&gt;
BECAREFUL not to start qemu twice on the same ZFS guest! Two simultaneous running qemu on the same ZFS will corrupt the pool and it will NOT recover - you lose your whole installation! Before running qemu, check ps -A, look for an already running qemu process incase it somehow entered into the background!&lt;br /&gt;
&lt;br /&gt;
BECAREFUL when using -nographic ttyS0 that you are not doing commands on the HOST! Only use -nographic to see kernel problems. Use regular console if booting is working normally.&lt;br /&gt;
&lt;br /&gt;
To use the qemu -drive if=scsi option, the linux module sym53c8xx should be loaded in the guest. You may need to use the qemu option:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-option-rom 8xx_64.rom,bootindex=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The file 8xx_64.rom used to be inside qemu, but in new versions it is missing. You can download it:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
wget http://www.lsi.com/downloads/Public/Host%20Bus%20Adapters/Host%20Bus%20Adapters%20Common%20Files/lsi_bios.zip&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Extract the zip and place 8xx_64.rom in /usr/share/qemu/.&lt;br /&gt;
&lt;br /&gt;
Good luck!&lt;/div&gt;</description>
			<pubDate>Mon, 24 Sep 2012 20:08:44 GMT</pubDate>
			<dc:creator>Foobarz</dc:creator>
			<comments>https://www.slackwiki.com/Talk:ZFS_root_(builtin)</comments>
		</item>
		<item>
			<title>ZFS root</title>
			<link>https://www.slackwiki.com/index.php?title=ZFS_root&amp;diff=803</link>
			<guid isPermaLink="false">https://www.slackwiki.com/index.php?title=ZFS_root&amp;diff=803</guid>
			<description>&lt;p&gt;Foobarz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Tutorials]]&lt;br /&gt;
If you have heard about the ZFS filesystem and you're curious to try it out, then you can try it on slackware64, thanks to the ZFSonLinux.org project!&lt;br /&gt;
&lt;br /&gt;
In this article, an example is shown of how to install slackware64 14.0 onto a ZFS root filesystem (zfs-root) inside a QEMU virtual machine for testing purposes. It is recommended that you install qemu and learn how to use it to test a ZFS installation before you decide to use it on real hardware. A slackbuild for qemu can be found on slackbuilds.org. If you have a processor that supports Intel VT-x or AMD AMD-V virtualization acceleration (try modprobe kvm-intel or modprobe kvm-amd), then use the slackbuild for qemu-kvm.&lt;br /&gt;
&lt;br /&gt;
This article isn't going to go into any detail on actually using ZFS or what kinds of installation options and settings might be optimal. This article just presents an example of how to get started with ZFS on slackware.&lt;br /&gt;
&lt;br /&gt;
At this time of writing, ZFSonLinux is at &amp;quot;release candidate&amp;quot; (version 0.6.0-rc11) development stage, and many issues can occur. See the ZFSonLinux.org web site and the issues tracker for an idea about the current issues. There is also an irc channel on irc.freenode.net, #zfsonlinux, for discussion of issues and help.&lt;br /&gt;
&lt;br /&gt;
Although not required, it is helpful to keep a local mirror of slackware64 on your system. Having a local mirror makes it easier to upgrade to slackware64-current or to patches/* in a release. To help manage your own local slackware mirror and generate your own CD and DVD slackware installers, see http://alien.slackbook.org/blog/local-slackware-mirror/.&lt;br /&gt;
&lt;br /&gt;
In this article, we use a slackware64-current DVD image file as the qemu cdrom device media for the installation of the slackware guest. This was tested at slackware64-current = slackware64 14.0rc4. You can obtain a slackware DVD image using a torrent, buy the DVD from slackware.com, or generate your own DVD image file using the mirror script. For an actual DVD, you can pass your DVD device (e.g., /dev/sr0) as the qemu cdrom device. For a DVD image file, pass the image file as the qemu cdrom device.&lt;br /&gt;
&lt;br /&gt;
The ZFSonLinux packages are not included in slackware at this time. There are two packages involved: spl and zfs. The first, spl, is &amp;quot;Solaris Porting Layer&amp;quot; and must be installed on the system before zfs can be compiled. The source code tarballs for these are at ZFSonLinux.org. At this time of writing, they are spl-0.6.0-rc11.tar.gz and zfs-0.6.0-rc11.tar.gz.&lt;br /&gt;
&lt;br /&gt;
At this point, it is assumed you have qemu installed, have obtained a slackware64-current/14.0 DVD, and have downloaded spl and zfs tarballs to your host system. The first step now is, if your host is not slackware64-current/14.0 (the same as the guest will be), then you need to create a minimal development slackware64 guest system in qemu for just the purpose of compiling and packaging the spl and zfs slackware packages and transferring a copy of these packages back onto your host system to use later to install onto zfs during the slackware install process.&lt;br /&gt;
&lt;br /&gt;
From this point onward, instructions become a bit terse and mostly limited to examples of the commands you might use to complete tasks. You are encouraged to examine what each command does by reading the command's man pages. For example, the command &amp;quot;man qemu&amp;quot; can show you most of what you need to know about running qemu on the command line.&lt;br /&gt;
&lt;br /&gt;
So, here's an example of how you might build the spl and zfs packages, starting in your home directory:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on host)&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir qemu&lt;br /&gt;
cd qemu&lt;br /&gt;
mkdir slackdevel&lt;br /&gt;
cd slackdevel&lt;br /&gt;
mkdir packages&lt;br /&gt;
cp ~/spl-*.tar.gz packages&lt;br /&gt;
cp ~/zfs-*.tar.gz packages&lt;br /&gt;
qemu-img create disk1.raw 10G&lt;br /&gt;
ln -s ~/slackware64-current-install-dvd.iso dvd.iso&lt;br /&gt;
qemu-kvm \&lt;br /&gt;
 -option-rom 8xx_64.rom,bootindex=1 \&lt;br /&gt;
 -no-quit \&lt;br /&gt;
 -no-shutdown \&lt;br /&gt;
 -boot order=cd,menu=on \&lt;br /&gt;
 -m 2G \&lt;br /&gt;
 -cpu host \&lt;br /&gt;
 -smp sockets=1,cores=4 \&lt;br /&gt;
 -net nic,model=e1000 -net user \&lt;br /&gt;
 -cdrom dvd.iso \&lt;br /&gt;
 -drive format=raw,media=disk,cache=none,aio=native,if=scsi,index=0,file=disk1.raw \&lt;br /&gt;
 -virtfs local,path=./packages/,security_model=none,mount_tag=hostpackages&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When you need to change boot to cd or disk, try changing &amp;quot;order=dc&amp;quot; or hitting F12 at boot prompt and select the CD/DVD boot option.&lt;br /&gt;
&lt;br /&gt;
Note: The support for booting drives using if=scsi is not included with current versions of qemu. Booting scsi requires the 8xx_64.rom option-rom, which can be downloaded at&lt;br /&gt;
[http://www.lsi.com/downloads/Public/Host%20Bus%20Adapters/Host%20Bus%20Adapters%20Common%20Files/lsi_bios.zip LSI.com]. Unzip it, and then:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp 8xx_64.rom /usr/share/qemu&lt;br /&gt;
# then run qemu-kvm with additional command line option: -option-rom 8xx_64.rom,bootindex=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Qemu should boot into the install-dvd, and now perform a very ordinary slackware64 install onto /dev/sda. Install d package set and most others, but package sets x, kde, xfce not really needed.&lt;br /&gt;
&lt;br /&gt;
First note: examples here use tools from the gptfdisk package (gdisk, sgdisk, cgdisk) to partition the disk with GUID partition table (GPT) format. GPT might not be too familiar to everyone, who mostly have only used MBR partitions with fdisk. In the slackware installations this author has tested in qemu, using GPT partitions has caused no problems with lilo or other tools used in slackware. GPT disk labels support creating up to 128 partitions and support disks larger than 2TB (the limit of MBR fdisk). LILO installs into the first 440 bytes on /dev/sda, inside a GPT &amp;quot;protective MBR&amp;quot; that serves to provide compatibility with MBR bootloaders like lilo. LILO uses LBA32 sector addressing and can see all 512-byte sectors inside the first 2TB of a disk. So long as the /boot partition is within the first 2TB of a disk, lilo can work on a disk larger than 2TB. Unlike the common default of fdisk to start the first partition at sector 63, which is not aligned with the 4KiB sector size of Advanced Format hard disks, gdisk's default is to start partitions at 2048 sector (1MiB) boundaries which are also 4KiB aligned. Using gdisk GPT works on all disks and is compatible with using Advanced Format hard disks larger than 2TB. More information about GPT disk label format can be found on wikipedia.org. For those that have used grub instead of lilo, grub installation is different with GPT than with MBR, and grub requires a GPT partition of type grub-bios or 0xEF02 &amp;quot;BIOS Boot Partition&amp;quot; of about 8MiB where it can install it's additional bootloader stages because grub cannot embed in sectors 1-62 on GPT where GPT keeps it's partition tables. On MBR, sectors 1-62 were normally reserved space for bootloaders to keep a 2nd stage.&lt;br /&gt;
&lt;br /&gt;
For this purpose of development guest, just create a simple 1-partition system, /dev/sda1, and do a simple slackware install on it. Don't bother with swap or separate /boot unless you want to:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on install-dvd)&lt;br /&gt;
cgdisk /dev/sda&lt;br /&gt;
setup&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When this simple development guest boots, login as root, and continue:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on qemu guest)&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir packages&lt;br /&gt;
mount hostpackages -t 9p -o trans=virtio packages&lt;br /&gt;
echo --prefix=/ --libexecdir=/usr/libexec --libdir=/lib64 --includedir=/usr/include --datarootdir=/usr/share &amp;gt; configure-options&lt;br /&gt;
mkdir src&lt;br /&gt;
cd src&lt;br /&gt;
&lt;br /&gt;
mkdir install&lt;br /&gt;
tar xvzf ~/packages/spl-*.tar.gz&lt;br /&gt;
cd spl-*&lt;br /&gt;
./configure $( cat ~/configure-options )&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../spl-&amp;lt;version&amp;gt;_&amp;lt;kernel_version&amp;gt;-x86_64-&amp;lt;build_id&amp;gt;.txz&lt;br /&gt;
(e.g., makepkg ../spl-0.6.0rc11_3.2.28-x86_64-1root.txz)&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
installpkg spl-0.6.0rc11_3.2.28-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
cp spl-0.6.0rc11_3.2.28-x86_64-1root.txz ~/packages&lt;br /&gt;
&lt;br /&gt;
mkdir install&lt;br /&gt;
tar xvzf ~/packages/zfs-*.tar.gz&lt;br /&gt;
cd zfs-*&lt;br /&gt;
./configure $( cat ~/configure-options )&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../zfs-&amp;lt;version&amp;gt;_&amp;lt;kernel_version&amp;gt;-x86_64-&amp;lt;build_id&amp;gt;.txz&lt;br /&gt;
(e.g., makepkg ../zfs-0.6.0rc11_3.2.28-x86_64-1root.txz)&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
installpkg zfs-0.6.0rc11_3.2.28-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
cp zfs-0.6.0rc11_3.2.28-x86_64-1root.txz ~/packages&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point spl and zfs packages are copied back to the host in the packages directory. Also, spl and zfs are installed in this simple development guest, so one could begin to experiment with zfs pools and datasets but while the root fs is whatever you made it during setup (probably the default, ext4). This development guest isn't really needed anymore, so it can be deleted:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
halt&lt;br /&gt;
(exit qemu: ctrl-alt-2 then enter quit at QEMU command prompt)&lt;br /&gt;
&lt;br /&gt;
(on host)&lt;br /&gt;
rm disk1.raw dvd.iso&lt;br /&gt;
mv packages ..&lt;br /&gt;
cd ..&lt;br /&gt;
rmdir slackdevel&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now that we have the spl and zfs packages on the host, it is possible to copy them into your local slackware64 mirror and then generate your own install DVD image that includes them. For example, change to the directory that contains the slackware README files, and create a &amp;quot;addon&amp;quot; directory and copy the spl and zfs slackware packages into there. Then, generate the DVD image using a command such as $( ./mirror-slackware-current.sh -i ) from where you have this script configured to maintain your local mirror. We can also just continue to access them inside the installer using qemu's virtfs option. When you are going to do a real installation onto real hardware, you need to generate and burn your own DVD that includes the packages.&lt;br /&gt;
&lt;br /&gt;
It is time to begin the installation of slackware64 on a ZFS root, assuming either you have regenerated dvd.iso with zfs packages in addon/* or we access the zfs packages while in the installer using qemu's virtfs to the host's packages directory.&lt;br /&gt;
&lt;br /&gt;
ZFS supports creating complex data storage configurations in data storage pools (similar to a LVM volume group) backed by one or more virtual devices (similar to physical disks and raid arrays) and containing one or more datasets (similar to mounted filesystems, logical volume devices, or snapshots). But here, we keep it simple and will install on just a single disk device.&lt;br /&gt;
&lt;br /&gt;
On a real ZFS installation, users will typically want to use the ZFS mirror or raidz virtual device (vdev) types for reliability against hard drive failures. For example, a good configuration might be to use a USB memory stick (and a backup stick) for /boot that is plugged into an on-motherboard &amp;quot;Type A&amp;quot; USB connector. Then, use four whole hard drives in a raidz2 vdev as the initial storage space in the root zpool. At a later time, to add more storage space, additional whole four-drive raidz2 vdevs of the same size could be added to the zpool. It is recommended to only add the same vdev type (disk, mirror, or raidz|1|2|3) and size to a zpool since zfs stripes across the vdevs, and vdevs of different types/sizes do not stripe together optimally. After adding a vdev to your zpool, you might need to copy the new /etc/zfs/zpool.cache to your initrd-tree or initramfs-source (and rebuild/reinstall them) if you are using the cachefile to import your zpool. Using mirror vdevs would be similar to a raid10. Using 4-disk raidz2 vdevs would give the same storage space as raid10 while fully reliable against any double-disk failure; however, the raidz2 parity calculations results in higher CPU usage and/or lower performance. Because raidz vdevs cannot be grown by adding hard drives to them, and vdevs in a zpool are striped, it is important with ZFS to decide what type and size of vdev will be used in a zpool as the units of add-on storage space; it could be difficult to alter this decision later. Finally, on a real installation with raidz, data scrub should be scheduled to actively search for &amp;quot;latent defects&amp;quot; on the hard drives so that unknown read/write errors do not become known later during a disk swap/rebuild and result in the zpool becoming faulted (lost).&lt;br /&gt;
&lt;br /&gt;
If you decide to test raidz in qemu, consider making the qemu disk files on different physical disks on your host to avoid putting all the stress onto a single disk on your host. The raidz qemu disks that are all on a single physical hard drive will cause poor performance and stress on the disk due to the large amount of seek operations to access the stripes/columns in the raidz. Again, we'll keep it simple in this wiki and just make a root zpool that is just holding a single qemu disk that you've given to qemu to avoid stress on the host hard drive. But, if you really want to test raidz, you can do it by just making more qemu disks (with incremented index=X number) and making your zpool a raidz; there's no technical restriction here on the kind of vdevs in your root zpool.&lt;br /&gt;
&lt;br /&gt;
Make &amp;quot;slackzfs&amp;quot; guest, and boot it into the slackware installer to begin installation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on host)&lt;br /&gt;
mkdir slackzfs&lt;br /&gt;
mv packages slackzfs/&lt;br /&gt;
cd slackzfs&lt;br /&gt;
qemu-img create disk1.raw 10G&lt;br /&gt;
ln -s ~/slackware64-current-install-dvd.iso dvd.iso&lt;br /&gt;
qemu-kvm \&lt;br /&gt;
 -option-rom 8xx_64.rom,bootindex=1 \&lt;br /&gt;
 -no-quit \&lt;br /&gt;
 -no-shutdown \&lt;br /&gt;
 -boot order=cd,menu=on \&lt;br /&gt;
 -m 2G \&lt;br /&gt;
 -cpu host \&lt;br /&gt;
 -smp sockets=1,cores=4 \&lt;br /&gt;
 -net nic,model=e1000 -net user \&lt;br /&gt;
 -cdrom dvd.iso \&lt;br /&gt;
 -drive format=raw,media=disk,cache=none,aio=native,if=scsi,index=0,file=disk1.raw \&lt;br /&gt;
 -virtfs local,path=./packages/,security_model=none,mount_tag=hostpackages&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The install-dvd should boot, and then begin installation steps on the installer command line:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on install-dvd)&lt;br /&gt;
# mount the install-dvd&lt;br /&gt;
mkdir /dvd&lt;br /&gt;
mount /dev/sr0 /dvd&lt;br /&gt;
&lt;br /&gt;
# install coreutils, which provides the &amp;quot;hostid&amp;quot; command needed to load the spl module&lt;br /&gt;
installpkg /dvd/slackware64/a/coreutils-8.17-x86_64-1.txz&lt;br /&gt;
&lt;br /&gt;
# install kmod package which includes &amp;quot;depmod&amp;quot; command and others&lt;br /&gt;
installpkg /dvd/slackware64/a/kmod-9-x86_64-2.txz&lt;br /&gt;
depmod&lt;br /&gt;
&lt;br /&gt;
# install the full kernel modules so you can load 9p filesystem and use it if you want&lt;br /&gt;
# .. you might keep the zfs modules packages off the dvd and use a plain slack dvd&lt;br /&gt;
installpkg /dvd/slackware64/a/kernel-modules-*.txz&lt;br /&gt;
depmod&lt;br /&gt;
&lt;br /&gt;
# install bash and libtermcap because udev rules in zfs use bash scripts&lt;br /&gt;
installpkg /dvd/slackware64/a/bash-*.txz&lt;br /&gt;
installpkg /dvd/slackware64/l/libtermcap-*.txz&lt;br /&gt;
&lt;br /&gt;
# install spl and zfs that you have copied into the mirror before running the DVD creation&lt;br /&gt;
installpkg /dvd/addon/spl-0.6.0rc11_3.2.28-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /dvd/addon/zfs-0.6.0rc11_3.2.28-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
&lt;br /&gt;
#Or:&lt;br /&gt;
mkdir /packages&lt;br /&gt;
find /lib/modules/ | grep 9p&lt;br /&gt;
lsmod&lt;br /&gt;
# check that 9p modules load, mainly 9pnet_virtio&lt;br /&gt;
modprobe 9pnet_virtio&lt;br /&gt;
mount hostpackages -t 9p -o trans=virtio /packages&lt;br /&gt;
installpkg /packages/spl-0.6.0rc11_3.2.28-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /packages/zfs-0.6.0rc11_3.2.28-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
modprobe zfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now zfs tools: &amp;quot;zpool&amp;quot; and &amp;quot;zfs&amp;quot; should work in the live installer.&lt;br /&gt;
On the installer, there can be trouble seeing man pages, so install:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
installpkg /dvd/slackware64/ap/man-*.txz&lt;br /&gt;
installpkg /dvd/slackware64/ap/groff-*.txz&lt;br /&gt;
installpkg /dvd/slackware64/a/less-*.txz&lt;br /&gt;
export MANPATH=/usr/man:/usr/share/man&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The manual pages should be readable:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
man zpool&lt;br /&gt;
man zfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After seeing the man pages, we should be fully ready to continue to setup on ZFS.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(still on install-dvd)&lt;br /&gt;
ls -l /dev/sd*&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Make sure the disk devices you expect are there. We'll use sda and make boot (/boot on /dev/sda1) and root (/ on /dev/sda2) partitions.&lt;br /&gt;
&lt;br /&gt;
First, some background info: A ZFS filesystem is not supported by lilo as the filesystem containing /boot, which holds lilo's 2nd stage and the linux kernel files. The on-disk format of a ZFS filesystem is often a complex raid configuration where even if lilo understood ZFS it would likely require /boot to reside in only certain simple ZFS configurations to be plainly readable to lilo. As things are, a linux root installed in a partition with ZFS filesystem needs /boot to be on another partition with a filesystem that lilo understands, such as ext4 fs. In addition, because the spl and zfs modules are not built into the kernel, and the zfs startup requires some configuration to mount the zfs root, an initial ram/root filesystem (initrd) is needed. The initrd is a gzip compressed cpio archive file that contains a small linux root operating system that is decompressed into a ramfs block device at boot up and takes initial control of the system. The initrd contains an init script that configures devices in devtmpfs mounted at /dev. For example, if using mdadm, lvm, luks, losetup, and now zfs, this init script runs all the commands to create or start these devices (one of which is the root device), mounts the root device, and then transfers system control to the init script in the mounted root filesystem. The ramfs-based root environment on the booted install-dvd or booted initrd image (in rescue command line) are small slackware installations that exist only in ram and are temporary, but while inside them you can install, upgrade, and remove slackware packages inside them using the regular package management tools; this allows you access to any kernel modules and programs as needed inside these ramfs root. Packages can be installed, upgraded, or removed permanantly in the initrd image file to manage the programs and modules required during the initrd boot stage. Also from within these ramfs initial root environments, once the root device is mounted, chroot can be used to work on the mounted root system as if it were booted; this allows one to fix problems that are occuring in the root fs init scripts that cause normal booting to fail, or to install a kernel and/or modules etc. Now on to partitioning:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cgdisk /dev/sda&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, cgdisk looks just like cfdisk, but it makes GPT partitions.&lt;br /&gt;
&lt;br /&gt;
Make a partition for /boot that is about 512MiB of whatever partition type you like (8300 &amp;quot;Linux filesystem&amp;quot; is fine), or make it type bf07 &amp;quot;Solaris Reserved 1&amp;quot; if you want ZFS to maybe see the disk as if it was given as a whole disk to ZFS. Make a second partition using the remaining space with partition type bf01 &amp;quot;Solaris ZFS&amp;quot;. Currently, when ZFSonLinux is given a whole disk device like /dev/sdb to use, it will automatically GPT partition it with a bf01 partition #1 that is the whole disk except a small 8MiB type bf07 partition #9 at the end of the disk (/dev/sdb1 and /dev/sb9). The small 8MiB type bf07 partition #9 is most likely reserved for use by bootloaders, like lilo, to have a /boot or other boot-related files kept there. For example, you might have /dev/sda that is totally non-ZFS for booting and /dev/sdb passed to ZFS whole where it automatically partitions sdb, but you can just use one disk here and make partitions. Let's use type 8300 for /boot to be sure nothing is confused:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
We'll continue with this partitioning:&lt;br /&gt;
Part. #    Size        Partition Type           Partition Name&lt;br /&gt;
           4.0 MiB     free space&lt;br /&gt;
   1       512.0 MiB   Linux filesystem         boot&lt;br /&gt;
           4.0 MiB     free space&lt;br /&gt;
   2       9.4 GiB     Solaris /usr &amp;amp; Mac ZFS   root&lt;br /&gt;
           96.0 MiB    free space&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The free space is left as a recommendation. The free space has potential uses for data recovery techniques, changing boot configuration, accomodating a replacement disk that is slightly smaller, and avoiding the end of the disk where GPT and other disk labels may need to claim space at the end of a drive to hold metadata. The &amp;quot;partition name&amp;quot; can be blank or any arbitrary name you'd like to give them.&lt;br /&gt;
&lt;br /&gt;
If you are going to test a ZFS mirror or raidz configuration, then you can repeat this same partitioning on each disk. For example, for a four-disk raidz2 with /dev/sd[abcd] you might do:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sgdisk -R /dev/sdb /dev/sda&lt;br /&gt;
sgdisk -G /dev/sdb&lt;br /&gt;
sgdisk -R /dev/sdc /dev/sda&lt;br /&gt;
sgdisk -G /dev/sdc&lt;br /&gt;
sgdisk -R /dev/sdd /dev/sda&lt;br /&gt;
sgdisk -G /dev/sdd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Then, you could use the boot partitions /dev/sd[abcd]1 in a mdadm raid1 as your boot device:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mdadm --create /dev/md0 -l 1 -n 4 /dev/sd[abcd]1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
In this configuration, /dev/md0 is your 4-way mirror /boot device and is used as explained in the slackware [ftp://slackware.mirrors.tds.net/pub/slackware/slackware64-current/README_RAID.TXT README_RAID.TXT]. The /dev/sd[abcd]2 would be given to ZFS for the raidz2 (instead of to mdadm raid). This is only an example and there are many possible configurations, including using whole un-partitioned disks; however, we will continue in this wiki with a simpler configuration with /dev/sda1 as a non-raid /boot device and /dev/sda2 in a non-raidz/non-mirror zpool.&lt;br /&gt;
&lt;br /&gt;
Create a zpool called zfs-root:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool create -m none zfs-root /dev/sda2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A zpool created like this, the normal way, is a kernel-internal block device that contains already a zfs filesystem. There is normally no entry in /dev for this device. However, it can still be referenced as a mountable device similar to how devtmpfs, proc, and sysfs are also kernel-internal mountable block devices. The -m option told zpool not to automatically mount it anywhere, and without -m the default is to always automatically mount to /zfs-root. These kinds of details are explained better elsewhere. For this situation, we do not want it automounted.&lt;br /&gt;
&lt;br /&gt;
Because a zpool itself is a useable zfs fs, it has a full set of zfs &amp;quot;properties&amp;quot; to set options about the filesystem, perhaps similar to tune2fs. The &amp;quot;mountpoint=&amp;lt;some place to mount&amp;gt;&amp;quot; is one such property. We want it set to the special value &amp;quot;none&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs get mountpoint zfs-root&lt;br /&gt;
zfs set mountpoint=none zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also use &amp;quot;legacy&amp;quot; for the mountpoint and the management of mounting and unmounting the pool will be expected to be done using the regular &amp;quot;mount&amp;quot; and &amp;quot;umount&amp;quot; commands:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=legacy zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Later in the wiki, it is shown how to mount using &amp;quot;zfs mount&amp;quot; for mountpoint=none, and regular &amp;quot;mount&amp;quot; for mountpoint=legacy. Using mountpoint=legacy is probably the preferred setting for the zfs-root because you can use the normal mount and umount commands and do not have to change slackware /etc/rc.d/* scripts much, if any. The normal slackware scripts handle a root filesystem's mounting and remounting using the normal mount command.&lt;br /&gt;
&lt;br /&gt;
On creation, the zpool zfs-root is &amp;quot;imported&amp;quot; and has a zpool status that can be viewed:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool status zfs-root&lt;br /&gt;
&lt;br /&gt;
zpool export zfs-root&lt;br /&gt;
zpool status zfs-root&lt;br /&gt;
# Now there is no status.&lt;br /&gt;
&lt;br /&gt;
zpool import zfs-root&lt;br /&gt;
# Now it is back.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
When a zpool is imported, it has it's current configuration cached in a file /etc/zfs/zpool.cache. When a zpool is exported, then it's entries in the cache file are removed and the cache file is deleted if it becomes empty. So long as the zfs kernel modules see this cache file and valid cache data inside it, ZFS considers the described zpools in the cache file to be valid as imported zpools. If the zpool.cache file is present at the time the zfs modules are loaded, then there is no further need to use the import and export zpool commands at system startup and shutdown. With root on a zfs, it is not possible to export the pool that root is on, but this is not a problem. At shutdown, the safe procedure will be to set the zfs-root property readonly=on or remount read-only and sync disks.&lt;br /&gt;
&lt;br /&gt;
To avoid the requirement to import the zfs-root pool at startup, you can keep a copy of the zpool.cache file to later copy onto the initrd image to read at modules load time to have the pool reactivated without need to issue the zpool import command:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/zfs/zpool.cache /etc/zfs/zpool.cache-initrd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
A warning about the zpool.cache file: Having /etc/zfs/zpool.cache present at zfs module load or module init time can be unsafe if the device names in /dev have changed since the last boot. Especially dangerous is if two hard drives have swapped names, like /dev/sda and /dev/sdb have swapped names. It is safer to not have a zpool.cache file on the system at boot and zfs module load/init time to guard against the possibility that the cache file is no longer correct. This wiki will try to show how you can use zpool.cache to import your pool if the regular zpool import command seems to always require you to force it. This wiki will also show how to not need a zpool.cache file to import normally.&lt;br /&gt;
&lt;br /&gt;
A zfs filesystem will not normally allow you to mount over any files. The mountpoint is expected to be an empty directory. Remove any junk files inside the installer's /mnt because zfs won't mount over any files:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rm /mnt/README&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The directory /mnt is where the slackware setup expects you to mount your root for installation.&lt;br /&gt;
&lt;br /&gt;
Controlling whether a zfs fs is to be mounted read-only or read-write is best managed by setting the readonly property while it is not yet mounted:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set readonly=on zfs-root&lt;br /&gt;
zfs set readonly=off zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If you are using &amp;lt;code&amp;gt;mountpoint=legacy&amp;lt;/code&amp;gt; then the options for the mount command for ro or rw mounting will work as normal also and override whatever the readonly property is set to. The readonly property does serve as a default.&lt;br /&gt;
&lt;br /&gt;
Slackware expects root to be mounted readonly when /etc/rc.d/rc.S runs during normal startup, so later this is used to satisfy slackware's expectation to avoid rc.S complaining.&lt;br /&gt;
&lt;br /&gt;
The zfs-root can be mounted and unmounted in two different ways:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=/mnt zfs-root&lt;br /&gt;
zfs set mountpoint=none zfs-root&lt;br /&gt;
# or&lt;br /&gt;
mount zfs-root -t zfs /mnt&lt;br /&gt;
umount /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If it is already mounted and you want to change it to mount somewhere else, it is best to transition it to unmounted first, then mount it in the new place.&lt;br /&gt;
&lt;br /&gt;
The mount options &amp;lt;code&amp;gt;-o ro, -o rw, -o remount,ro, and -o remount,rw &amp;lt;/code&amp;gt; can also be used and will override the &amp;lt;code&amp;gt;readonly=on|off&amp;lt;/code&amp;gt; property without altering the property value. This can be confusing until you are familiar with how the two methods of mounting interact. When &amp;lt;code&amp;gt;mountpoint=legacy&amp;lt;/code&amp;gt; is set, zfs expects the regular mount and umount commands to be used to mount and unmount the dataset with the assistance of the mount.zfs helper. For now, we will continue with &amp;lt;code&amp;gt;mountpoint=none&amp;lt;/code&amp;gt;, but using legacy is also a good option.&lt;br /&gt;
&lt;br /&gt;
Now, let's continue some, and mount to /mnt using the current &amp;lt;code&amp;gt;readonly=off&amp;lt;/code&amp;gt; setting (rw mount):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=/mnt zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method of mounting will show the most detailed mount options in /etc/mtab. They are the mount options that zfs thinks are proper, and they are probably what should be kept in /etc/fstab for zfs-root until we know better.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cat /etc/mtab &amp;gt;&amp;gt; /etc/fstab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now edit /etc/fstab to make sure it looks right, and remove the &amp;quot;rw&amp;quot; mount option, because we want to let it use a default for that, which will come from how we set the readonly= property most of the time. Unmount again:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=none zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mount again, now using all options from /etc/fstab:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It should be mounted at /mnt, and touch /mnt/t should allow you to make the file t. Then rm it: rm /mnt/t&lt;br /&gt;
For installation, we want to make sure it is mounted read-write. After installation, it should mount readonly inside the initrd.&lt;br /&gt;
&lt;br /&gt;
Sometimes there can be problems using the mount command, and then you can try it with the -i option:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 mount -i zfs-root&lt;br /&gt;
 mount -i zfs-root -t zfs /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
but, you should not have to use -i. When using -i makes it work, it performs an &amp;quot;internal-only&amp;quot; mount and does not use any mount.&amp;lt;fstype&amp;gt; helper scripts that might be on the system. You can use &amp;lt;code&amp;gt;mountpoint=legacy&amp;quot;&amp;lt;/code&amp;gt; to avoid this small problem if you are preferring to use the regular mount and umount commands on your zfs-root.&lt;br /&gt;
&lt;br /&gt;
Setup the /boot device:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkfs.ext4 /dev/sda1&lt;br /&gt;
mkdir /mnt/boot&lt;br /&gt;
mount /dev/sda1 /mnt/boot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We have both root and boot mounted where the slackware installer expects them. Unmount the dvd so setup can find it normally:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
umount /dev/sr0&lt;br /&gt;
setup&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the setup, skip straight to TARGET selection for the root device, but the setup doesn't see or understand the zfs-root, so it is not listed. This does not matter because we have mounted it already. Just skip down to a slot that say to continue, and continue on with setup. Because TARGET is skipped, you may not see the ADDITIONAL prompt (or if so, skip it too) where normally you give /dev/sda1 and have it mounted as /boot. This is also okay because we have mounted /mnt/boot already.&lt;br /&gt;
Because we did not give TARGET the root device or say what device /boot is on, the lilo installation will fail, or you can skip it. Otherwise, this installation process is normal.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Finish installation and exit setup, but do NOT reboot!&lt;br /&gt;
# There is still a lot to do before rebooting.&lt;br /&gt;
umount /dev/sr0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point, it is assumed that the setup has completed installing into /mnt. Congrats! You've installed slackware into a ZFS root!&lt;br /&gt;
&lt;br /&gt;
The next steps are to prepare to use &amp;quot;chroot /mnt&amp;quot; and finish up the configuration on the installed root system and then be able to reboot onto the completed installation. Before doing chroot, copy some files from the setup environment into /mnt.&lt;br /&gt;
&lt;br /&gt;
Copy the current installer /etc/fstab for later use inside the initrd. This fstab is what is proper inside the initrd, except remove option &amp;quot;rw&amp;quot; (if not done already).&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/fstab /mnt/etc/fstab.initrd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The fstab.initrd will look like:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 proc /proc proc defaults 0 0&lt;br /&gt;
 zfs-root /mnt zfs defaults,atime,dev,exec,suid,xattr,nomand,zfsutil 0 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the initrd, we want zfs-root to mount to /mnt.&lt;br /&gt;
&lt;br /&gt;
Create /mnt/etc/fstab:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cat /etc/mtab &amp;gt;&amp;gt; /mnt/etc/fstab&lt;br /&gt;
vi /mnt/etc/fstab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using vi started above, edit /mnt/etc/fstab and make it have lines such as:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 zfs-root / zfs defaults,atime,dev,exec,suid,xattr,nomand,zfsutil 0 0&lt;br /&gt;
 /dev/sda1 /boot ext4 defaults 0 2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
These two lines in &amp;lt;code&amp;gt;/mnt/etc/fstab&amp;lt;/code&amp;gt; are how the mounts should be looking when root is booted. Although the fstab option for fs_passno is 0 and indicates that root (/) should not be fsck, this fs_passno option in fstab is ignored during system startup for / in rc.S because rc.S explicity runs &amp;quot;fsck /&amp;quot; which does not look at options inside fstab. Fsck doesn't work on a zfs fs, and we will deal with that problem in a moment (see below).&lt;br /&gt;
&lt;br /&gt;
Mount some special mounts before chroot:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount -t devtmpfs none /mnt/dev&lt;br /&gt;
mount -t proc none /mnt/proc&lt;br /&gt;
mount -t sysfs none /mnt/sys&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Make sure /boot is mounted:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount /dev/sda1 /mnt/boot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you had mounted a 9p fs share to access spl and zfs packages, then unmount that now:&lt;br /&gt;
umount /packages&lt;br /&gt;
&lt;br /&gt;
Ready, now:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chroot /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point, you should be on the installed system, and now try to configure mkinitrd and lilo. First, switch to use the generic kernel:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /boot&lt;br /&gt;
rm System.map config vmlinuz&lt;br /&gt;
ln -s System.map-gen* System.map&lt;br /&gt;
ln -s config-gen* config&lt;br /&gt;
ln -s vmlinuz-gen* vmlinuz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We installed spl and zfs inside the live ramfs install-dvd environment, but not yet have we installed them into the root system:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount /dev/sr0 /mnt/cdrom&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /mnt/cdrom/addon/spl-*.txz&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /mnt/cdrom/addon/zfs-*.txz&lt;br /&gt;
depmod&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If instead, you used a 9p share to access the spl and zfs packages, then repeat that procedure here to install them onto the root system.&lt;br /&gt;
&lt;br /&gt;
Setup lilo: edit /etc/lilo.conf so it is like:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  lba32&lt;br /&gt;
  append = &amp;quot; vt.default_utf8=1&amp;quot;&lt;br /&gt;
  boot = /dev/sda&lt;br /&gt;
  message = /boot/boot_message.txt&lt;br /&gt;
  prompt&lt;br /&gt;
  timeout = 1200&lt;br /&gt;
  change-rules&lt;br /&gt;
   reset&lt;br /&gt;
  vga = normal&lt;br /&gt;
  image = /boot/vmlinuz&lt;br /&gt;
   label = vmlinuz&lt;br /&gt;
   initrd = /boot/initrd.gz&lt;br /&gt;
   root = /dev/ram0&lt;br /&gt;
   read-write&lt;br /&gt;
# alternatively, the root and read-write lines&lt;br /&gt;
# can be this one line of kernel parameters:&lt;br /&gt;
#  addappend = &amp;quot; root=/dev/ram0 rw &amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A note about initrd: The /boot/initrd.gz is a gzipped cpio archive containing a minimal BusyBox-based slackware root system that is sourced from /boot/initrd-tree. The commands &amp;quot;mkinitrd&amp;quot; and &amp;quot;mkinitrd -F&amp;quot; generates /boot/initrd-tree and /boot/initrd.gz. When using a initrd, the initial root device is normally set to root=/dev/ram0 (a ramfs block device) and allowed read-write. The kernel refers to devices in terms of &amp;quot;major&amp;quot; and &amp;quot;minor&amp;quot; numbers, and the ram0 device is assigned the block device major 1 and minor 0. This ram0 major/minor is written in hexadecimal as 0x0100 (256 in decimal). This hexademical number makes an appearance in /boot/initrd-tree/int where it runs: &amp;quot;echo 0x0100 &amp;gt; /proc/sys/kernel/real-root-dev&amp;quot;. Echoing a device code to real-root-dev is part of a deprecated initrd mechanism, but is probably harmless to leave alone as slackware has it unless you know otherwise. More information about how initrd works can be found in:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/usr/src/linux/Documentation/devices.txt (info about major:minor device numbers)&lt;br /&gt;
/usr/src/linux/Documentation/initrd.txt  (mostly obsolete info on old initrd)&lt;br /&gt;
/usr/src/linux/Documentation/filesystems/ramfs-rootfs-initramfs.txt (current info on new initrd, called initramfs)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Advanced note about initrd: Slackware's mkinitrd package does not use the &amp;quot;pivot_root&amp;quot; command as documented in &amp;quot;initrd.txt&amp;quot;, but instead uses &amp;quot;switch_root&amp;quot; provided by a project called BusyBox. The switch_root command changes the effective root filesystem from the initrd (unpacked in rootfs at /) to the new root filesystem (zfs-root mounted at /mnt); it overmounts rootfs / with zfs-root /mnt. The switch_root works as follows: delete everything in rootfs / (one filesystem only) that held initrd to free up ram memory, then use mount, chroot, and chdir to make the effective root change. In concept (as a shell script), the command &amp;quot;exec switch_root /mnt $INIT $RUNLEVEL&amp;quot; is performed as follows:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 find / -xdev | xargs rm -rf&lt;br /&gt;
 cd &amp;quot;$1&amp;quot;&lt;br /&gt;
 shift&lt;br /&gt;
 mount --move . /&lt;br /&gt;
 exec chroot . &amp;quot;$@&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Here, typically INIT=/sbin/init RUNLEVEL=3. The 'exec' causes switch_root to take the place of the parent process having PID=1. In system calls, the switch_root looks similar to this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chdir(&amp;quot;/mnt&amp;quot;);&lt;br /&gt;
/* &amp;lt;insert code to unlink/rmdir all initrd files/directories&lt;br /&gt;
 *  installed in rootfs / without crossing filesystems &amp;gt; */&lt;br /&gt;
mount(&amp;quot;.&amp;quot;, &amp;quot;/&amp;quot;, NULL, MS_MOVE, NULL);&lt;br /&gt;
chroot(&amp;quot;.&amp;quot;);&lt;br /&gt;
chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
execl(&amp;quot;/sbin/init&amp;quot;, &amp;quot;3&amp;quot;, (char*) NULL );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The kernel's rootfs / that contained initrd is never actually unmounted (it can't be) because it is built into the kernel and always exists as at least a tiny ramfs or tmpfs, so you can continue to see it in /proc/mounts. When you give lilo root=/dev/ram0 (a ramfs device), the kernel will actually use the internal rootfs, which is an instance of a tmpfs (if your kernel config includes tmpfs) or ramfs. The rootfs that is a tmpfs can by default use up to half of system ram. If rootfs is a ramfs, it can use up to almost all of system ram until the system panics. Typically, tmpfs is built into the kernel, and so depending on how much ram your computer has, the initrd-tree can probably be up to about half that size.&lt;br /&gt;
&lt;br /&gt;
Quite a lot of notes... now to continue on...&lt;br /&gt;
&lt;br /&gt;
Setup mkinitrd:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/mkinitrd.conf.sample /etc/mkinitrd.conf&lt;br /&gt;
vi /etc/mkinitrd.conf&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Edit it to look like this (other defaults should be ok):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 MODULE_LIST=&amp;quot;sym53c8xx:ext4:e1000:zfs:9p:9pnet_virtio&amp;quot;&lt;br /&gt;
 ROOTDEV=&amp;quot;zfs-root&amp;quot;&lt;br /&gt;
 ROOTFS=&amp;quot;zfs&amp;quot;&lt;br /&gt;
#Module sym53c8xx is the driver for qemu's if=scsi drive device.&lt;br /&gt;
#Module ext4 for /boot.&lt;br /&gt;
#Module e1000 for eth0 net device.&lt;br /&gt;
#Module zfs for ZFSonLinux.&lt;br /&gt;
#Modules 9p and 9pnet_virtio for mounting qemu -virtfs mount_tag.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These 9p modules could be useful from the rescue command line inside the initrd to get needed files that are on the host.&lt;br /&gt;
&lt;br /&gt;
All dependent modules will also be included automatically into /boot/initrd-tree, which is packaged as /boot/initrd.gz. For example, to see the dependent modules of zfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
modprobe --show-depends zfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All listed modules will also be in the initrd. Now, make a /boot/initrd-tree that we can begin to look at and edit:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkinitrd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create an empty /etc/mtab or else zpool import fails (zfs expects /etc/mtab to exists already, it won't make it):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
touch /boot/initrd-tree/etc/mtab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Copy in the fstab.initrd that was made earlier while on the installer. This provides all the mount options for a simple &amp;quot;mount zfs-root&amp;quot; onto /mnt:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/fstab.initrd /boot/initrd-tree/etc/fstab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More package installing! This time into an alternate root, the root of the initrd, /boot/initrd-tree. This is how you can put whatever packages you like into your initrd. These installations work independent of your normal installations. You can install, upgrade, and remove packages using an altroot:&lt;br /&gt;
&lt;br /&gt;
If spl and zfs are on your customized dvd:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/addon/spl-*.txz&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/addon/zfs-*.txz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Otherwise, repeat same procedure but you mount your 9p mount_tag and get them installed.&lt;br /&gt;
&lt;br /&gt;
More regular packages from the dvd:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/kmod-*.txz&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/coreutils-*.txz&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/gptfdisk-*.txz&lt;br /&gt;
&lt;br /&gt;
# A bash script is in /boot/initrd-tree/lib/udev/, so we need it or udev rules have problems:&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/bash-*.txz&lt;br /&gt;
# Bash needs this:&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/l/libtermcap-*.txz&lt;br /&gt;
&lt;br /&gt;
# Install net-tools to ensure that /etc/HOSTNAME, /etc/hosts, and potentially, /etc/hostid are handled proper.&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/n/net-tools-*.txz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When ZFS has to import a zpool while the initrd is running (this can be avoided by not exporting and keeping /etc/zfs/zpool.cache inside the initrd), ZFS will refuse to import a pool if it thinks that the pool may be in use by another system. ZFS was designed for network attached storage (NAS) where multiple hosts might have access to the same disks but ZFS cannot support two hosts importing and using a ZFS pool at the same time (that requires a &amp;quot;cluster&amp;quot; fs). ZFS checks a value called &amp;quot;hostid&amp;quot; to determine this kind of conflict, and it can be a tricky issue with an initrd boot process. The value of hostid is returned by the gethostid() function or the hostid command. This function will return the hostid from /etc/hostid if that file exists and has a valid id in it, or else if the file doesn't exist it obtains a hostid number based on the hostname and ip address assigned to hostname found in /etc/hosts or in DNS. If the hostid trying to import a pool is not the same as the hostid that imported it last time, ZFS will not import the pool unless &amp;quot;zpool import -f zfs-root&amp;quot; is used to force the import. This force option is not recommended to use, so it is best to configure your initrd with matching /etc/HOSTNAME and /etc/hosts as on the root installation and ensure what your system looks like on the initrd matches the booted root system. The hostid can also be passed to the SPL module with the module parameter &amp;lt;code&amp;gt;spl.spl_hostid=0xHHHHHHHH&amp;lt;/code&amp;gt; where the Hs are a hexadecimal hostid value and this overrides any /etc/hostid or hostname/IP-based hostid value.&lt;br /&gt;
&lt;br /&gt;
Edit /boot/initrd-tree/init (this is the main system startup script on the initrd, responsible for configuring your block devices, mounting root at /mnt, and booting root):&lt;br /&gt;
&lt;br /&gt;
Inside init, right near the top of the file after the PATH= line, add this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/bin/hostname -F /etc/HOSTNAME&lt;br /&gt;
/bin/hostname $( /bin/hostname -s )&lt;br /&gt;
#/sbin/chhostid 13371400&lt;br /&gt;
# you can make your hostid whatever, but this didn't work right with ZFS, so it is commented out&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This sets the name reported by the hostname command (the default is &amp;quot;darkstar&amp;quot;) to be what is contained in /etc/HOSTNAME. The hostname is modified in the next line to be the short hostname. These lines will help ZFS to properly identify your host when importing pools.&lt;br /&gt;
&lt;br /&gt;
Inside init, right after it runs &amp;quot;mdadm&amp;quot; commands as used for raid setup, we like it to setup ZFS, so add:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/sbin/zpool import zfs-root&lt;br /&gt;
/sbin/zfs set readonly=on zfs-root&lt;br /&gt;
mount zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
We want to make sure the default is to mount readonly, then it mounts using defaults from /etc/fstab inside the initrd.&lt;br /&gt;
&lt;br /&gt;
Inside init, close to the bottom, where it &amp;quot;Switch to real root partition&amp;quot;, comment out 1 line that normally does the mount:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# mount -o ro -t $ROOTFS $ROOTDEV /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
We have already mounted zfs-root, and we don't want to use any mount options because we should be using a properly set /etc/fstab inside the initrd for the zfs-root mount options onto /mnt.&lt;br /&gt;
&lt;br /&gt;
During a normal startup we want a readonly mount.&lt;br /&gt;
&lt;br /&gt;
Note: we are going to setup with using &amp;quot;zpool import&amp;quot; and &amp;quot;zpool export&amp;quot; commands at startup and shutdown. But later, you can experiment having /etc/zfs/zpool.cache stored in the initrd and commenting out the zpool import/export lines. Using zpool import/export is safer than using a zpool.cache, so we try to setup that way preferably.&lt;br /&gt;
&lt;br /&gt;
As mentioned, the zpool import command may sometimes fail, and give the message: &amp;quot;pool may be in use from another system&amp;quot;. This is nothing serious in this test situation. When this happens, zfs-root will not get mounted to /mnt and the init script will detect this and drop you into a rescue command line where you may manually do:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool import -f zfs-root&lt;br /&gt;
mount zfs-root&lt;br /&gt;
exit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This will force import, overriding the conflict that zfs thinks may be happening. Next is mount. After this, exit to let the init script continue on to boot the system normally.&lt;br /&gt;
&lt;br /&gt;
To avoid this problem we copy some files in (assuming you first edit /etc/HOSTNAME to hold the hostname you like to see on your command prompts, and edited /etc/hosts to have hostname on your loopback or other local ip address):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/HOSTNAME /etc/hosts /boot/initrd-tree/etc&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The value reported by the hostid command is what ZFS sees as your hostid (the SPL module actually tries to run the hostid command to get this value or it uses the spl.spl_hostid value that is given to it). In this setup so far, the value is based on the ip assigned to your hostname. If your hostname is on the line in /etc/hosts for ip address 192.168.13.37, then your hostid will be hex numbers C0.A8.0D.25 rearranged as A8C0250D (pairs of bytes are swapped). This is a ip-based hostid value, a 32bit hexadecimal number. The hostid has to be the same each boot or import will need a -f option to force it. Simply setting the hostid using the function sethostid() which writes a /etc/hostid file doesn't seem to agree with ZFS and you'd have to force the import, so this setup now assumes that you do not have or have deleted /etc/hostid.&lt;br /&gt;
&lt;br /&gt;
You can sometimes see what has been happening to a zpool by using the command &amp;quot;zpool history -li zfs-root&amp;quot; to see a log of commands.&lt;br /&gt;
&lt;br /&gt;
Once again, you can do away with the import and export commands by trying to have /etc/zfs/zpool.cache inside your initrd. To create zpool.cache, while on the installer or in the rescue shell of the initrd (at lilo &amp;quot;boot: vmlinuz rescue&amp;quot;):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on installer or initrd rescue shell)&lt;br /&gt;
zpool import zfs-root&lt;br /&gt;
zfs set readonly=off zfs-root&lt;br /&gt;
mount zfs-root&lt;br /&gt;
cp /etc/zfs/zpool.cache /mnt/etc/zfs/zpool.cache-initrd&lt;br /&gt;
cp /mnt/etc/zfs/zpool.cache-initrd /mnt/boot/initrd-tree/etc/zfs/zpool.cache&lt;br /&gt;
umount /mnt&lt;br /&gt;
zfs set readonly=on zfs-root&lt;br /&gt;
#mount zfs-root&lt;br /&gt;
#exit (to continue boot process onto rootfs mounted at /mnt)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Words of caution, again: Doing this zpool.cache approach is not necessary, and some talk suggests this is deprecated or discouraged. Although /etc/hostid setup fails to import without -f option, ip-based (hosts|dns) hostid works on booting and import works without -f option and may be the more proper way to do shutdown and startup rather than using a cache file which could become invalid and cause a problem that is difficult to understand. The contents and exact function of the cache file are not well understood by many people. As will be spammed all over this wiki, using zpool.cache is not recommended if you can avoid it because it is potentially unsafe for your pool.&lt;br /&gt;
&lt;br /&gt;
Save /boot/initrd-tree/init and quit vi.&lt;br /&gt;
&lt;br /&gt;
Now, edit /etc/rc.d/rc.S and rc.6 to understand how to remount rw or ro as readonly property changes:&lt;br /&gt;
&lt;br /&gt;
In /etc/rc.d/rc.S:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# comment out the line&lt;br /&gt;
#    /sbin/mount -w -v -n -o remount /&lt;br /&gt;
#add the line&lt;br /&gt;
     /sbin/zfs set readonly=off zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If you are using &amp;lt;code&amp;gt;mountpoint=legacy&amp;lt;/code&amp;gt; for zfs-root, you do not need to make the above change.&lt;br /&gt;
&lt;br /&gt;
In /etc/rc.d/rc.6:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# before: echo &amp;quot;Unmounting local file systems.&amp;quot;&lt;br /&gt;
# add lines:&lt;br /&gt;
  rm -f /etc/zfs/zpool.cache&lt;br /&gt;
  echo &amp;quot;Removed /etc/zfs/zpool.cache&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Remove /etc/zfs/zpool.cache on shutdown. This is recommended because if it is present when you import a pool, it might use this old cache to determine the device filenames in the pool, which may have changed filenames since the last boot, especially the non-persistent /dev/sd* device filenames. It is safest to avoid any usage of the zpool.cache file at boot in initramfs, zfs module load, and at zpool import of other pools.&lt;br /&gt;
&lt;br /&gt;
It is also possible to prevent &amp;lt;code&amp;gt;/etc/zfs/zpool.cache&amp;lt;/code&amp;gt; from ever being created by using the zfs module option 'spa_config_path=' to tell the zfs module not to use any zpool.cache file (a blank filename). To set this zfs module option, do the following:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo options zfs spa_config_path= &amp;gt; /etc/modprobe.d/zfs.conf&lt;br /&gt;
cp -a /etc/modprobe.d /boot/initrd-tree/etc&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If zfs is built into the kernel (see [http://slackwiki.com/ZFS_root_%28builtin%29 ZFS root (builtin)]), then this zfs module option is set as a kernel parameter: &amp;lt;code&amp;gt;zfs.spa_config_path=&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In /etc/rc.d/rc.6:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# comment out the line:&lt;br /&gt;
#    /bin/mount -v -n -o remount,ro /&lt;br /&gt;
# add the line:&lt;br /&gt;
     /sbin/zfs set readonly=on zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If you are using &amp;lt;code&amp;gt;mountpoint=legacy&amp;lt;/code&amp;gt; for zfs-root, you do not need to make the above change.&lt;br /&gt;
&lt;br /&gt;
In /etc/rc.d/rc.6, near the bottom just before poweroff|reboot, add the following block of lines:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
########################&lt;br /&gt;
# Try to export zfs-root&lt;br /&gt;
/sbin/zpool export zfs-root&lt;br /&gt;
if [ $? -gt 0 ] ; then&lt;br /&gt;
 echo &amp;quot;ZFS export failed.&amp;quot;&lt;br /&gt;
 echo &amp;quot;Notice: if root fs is busy, then this is normal fail.&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;ZFS export successful.&amp;quot;&lt;br /&gt;
 echo &amp;quot;Warning: successful export is abnormal for root fs.&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
/bin/sleep 5&lt;br /&gt;
########################&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This attempts to export even though it cannot return success for the root pool. The attempt is still recorded in the zpool history, and even though it fails the pool may actually be marked as exported (not sure).&lt;br /&gt;
&lt;br /&gt;
For ZFS, you cannot run fsck on it. It doesn't support that kind of filesystem check. The rc.S script will complain a lot in many places about not being able to run fsck on the zfs-root. To disable all attempts to run fsck, we can simply create a file that acts as a flag in /etc/rc.d/rc.S to tell it to skip fsck:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
touch /etc/fastboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This fastboot file is normally a run-once temporary file, and it is deleted near the bottom inside rc.S. Edit rc.S and stop it from deleting /etc/fastboot. We would like it to always skip all fsck. Edit /etc/rc.d/rc.S, and find the &amp;quot;rm&amp;quot; of fastboot, and do not have it removed!&lt;br /&gt;
&lt;br /&gt;
An alternative to using /etc/fastboot is to make the file &amp;lt;code&amp;gt;/sbin/fsck.zfs&amp;lt;/code&amp;gt; that always just &amp;quot;does nothing successfully&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
exec /bin/true&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Or, it can be:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Or, just do:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ln -s /bin/true /sbin/fsck.zfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This fsck helper has the advantage that you do not need to alter &amp;lt;code&amp;gt;rc.S&amp;lt;/code&amp;gt; as much, or at all if you use zfs property &amp;lt;code&amp;gt;mountpoint=legacy&amp;lt;/code&amp;gt; and the regular &amp;lt;code&amp;gt;mount&amp;lt;/code&amp;gt; command on your zfs-root. With these ideas, no slackware /etc/rc.d/* files really need editing, but it is up to you how you want to experiment. I prefer to use &amp;lt;code&amp;gt;mountpoint=legacy&amp;lt;/code&amp;gt; and edit just the initrd init script as above, and edit rc.6 to remove /etc/zfs/zpool.cache and try to export.&lt;br /&gt;
&lt;br /&gt;
We are getting close, and have finished all editing, so make /boot/initrd.gz and install lilo:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkinitrd -F&lt;br /&gt;
lilo&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We finished! All that's left to do is clean up.&lt;br /&gt;
&lt;br /&gt;
Exit the chroot.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
exit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Try to umount everything:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
umount /mnt/proc&lt;br /&gt;
umount /mnt/sys&lt;br /&gt;
umount /mnt/dev&lt;br /&gt;
umount /mnt/boot&lt;br /&gt;
umount /mnt/mnt/cdrom&lt;br /&gt;
umount /mnt/root/packages&lt;br /&gt;
umount /mnt&lt;br /&gt;
zpool export zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note, that export stops a pool and frees devices, while import binds devices and starts a pool. It is somewhat like mdadm -A -s and mdadm -S -s, while /etc/zfs/zpool.cache might be somewhat like mdadm -E -s &amp;gt; /etc/mdadm.conf.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Remove the DVD or change boot order&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When you reboot, if all is good, you are booting properly onto a slackware installed on a ZFS root! Congrats!&lt;br /&gt;
&lt;br /&gt;
If this seems to go badly, and this might happen if the import fails as explained some before, then you will be on the initrd's rescue command line just before the part in init where it wants to mount zfs-root and switch_root to boot up. In this case, you typically got commands like these to do:&lt;br /&gt;
&lt;br /&gt;
If you get dumped to rescue because zpool import will not work and requires -f (force), then:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 zpool import -f zfs-root&lt;br /&gt;
 zpool export    zfs-root&lt;br /&gt;
 zpool import    zfs-root&lt;br /&gt;
 mount zfs-root&lt;br /&gt;
 exit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This can happen if hostname, hostid, or uname changes.&lt;br /&gt;
&lt;br /&gt;
If you get into a jam and need to boot into the initrd and skip zpool import etc, use the lilo prompt (or, boot the install-dvd):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
boot: vmlinuz rescue&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
In the rescue mode of the initrd, after you have mounted your zfs-root as readonly=on to /mnt, then &amp;quot;exit&amp;quot; to continue booting.&lt;br /&gt;
&lt;br /&gt;
An alternative rescue shell on the initrd can be started as follows:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
boot: vmlinuz rdinit=/bin/sh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This puts you into a sh shell inside the initrd, and the normal /init script is not run at all. In this shell, you can fix problems and then attempt to start the system normally as follows:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
exec /init&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This runs the normal rdinit program, &amp;quot;execing&amp;quot; it so that it takes process ID (PID) 1 of your sh shell, which is the required PID for the init program.&lt;br /&gt;
&lt;br /&gt;
In other emergency command lines, you might need to run the lines at the end of init starting from: &amp;lt;code&amp;gt;udevadm info --cleanup-db; udevadm control --exit&amp;lt;/code&amp;gt;&lt;br /&gt;
If you don't run those udevadm commands, two runs of udevd could fight each other and it is slow; you have to wait 2 minutes twice for timeouts (4 minutes).&lt;br /&gt;
The last line in init is run like: &amp;lt;code&amp;gt;exec switch_root /mnt /sbin/init 1&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Warning: the switch_root command is kind of dangerous, so read the manual page about it. From what I can tell, everything except the new root &amp;quot;/mnt&amp;quot; is deleted, so you are giving a command that says what NOT to delete! Make sure nothing got mounted outside of &amp;quot;/mnt&amp;quot; before you run it. However, the deletes should not cross filesystems, but only delete the contents of initramfs.&lt;br /&gt;
&lt;br /&gt;
Also, in rescue command line or anytime you have finished making changes and are about to reboot in some abnormal situation, first run:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set readonly=on zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If you are using &amp;lt;code&amp;gt;mountpoint=legacy&amp;lt;/code&amp;gt; for zfs-root, then you may want to use &amp;lt;code&amp;gt;readonly=off&amp;lt;/code&amp;gt; and use the options to the &amp;lt;code&amp;gt;mount&amp;lt;/code&amp;gt; command to control ro|rw mounting. With &amp;lt;code&amp;gt;mountpoint=legacy&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;readonly=on&amp;lt;/code&amp;gt; used together, there can be a contradiction between how the kernel actually mounts zfs-root (ro according to the readonly property) and how the userspace mount command and /etc/mtab attempt to mount the zfs-root (if you give &amp;lt;code&amp;gt;-o rw&amp;lt;/code&amp;gt;). The kernel might actually mount ro, even when you have told the mount command to mount rw. The /etc/mtab can erroneously report rw, while the kernel's /proc/mounts file reports the actual mount as ro. Again, the two methods of mounting a zfs fs, either &amp;quot;legacy&amp;quot; &amp;lt;code&amp;gt;mount&amp;lt;/code&amp;gt; command or by using the &amp;lt;code&amp;gt;zfs set mountpoint&amp;lt;/code&amp;gt; can conflict with each other on the mode of mounting. If you create a zfs filesystem under zfs-root, like &amp;lt;code&amp;gt;zfs create &amp;quot;zfs-root/movies&amp;quot;&amp;lt;/code&amp;gt; and then try to mount it, it may have inherited &amp;lt;code&amp;gt;mountpoint=legacy&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;readonly=on&amp;lt;/code&amp;gt; from zfs-root, and it may mount ro even if you use the rw mount option: in this case, you have to do another command &amp;lt;code&amp;gt;mount -o remount,rw &amp;quot;zfs-root/movies&amp;quot;&amp;lt;/code&amp;gt; to make it actually switch to rw (kind of weird!).&lt;br /&gt;
&lt;br /&gt;
A bug in unpatched grep 2.13 build 1, found slackware 14.0rc1, causes problems when processing files stored on ZFS but rarely shows problems on other filesystems; the bug does not handle sparse files on zfs and btrfs correctly and results in chaos with slackpkg, compiling kernel modules, and possibly many other things. You must downgrade grep to 2.12 or use the patched grep 2.13 build 2 in slackware 14.0rc2 or later.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
Upgrading:&lt;br /&gt;
&lt;br /&gt;
From time to time you will want to upgrade the kernel to the new kernel in slackware64-current or in patches/. This will also necessitate a rebuild and reinstall or upgrade of spl and zfs. Below is an example of when both kernel and spl/zfs are being upgraded, to give an idea of the process:&lt;br /&gt;
&lt;br /&gt;
Using slackpkg, that is configured to use your local slackware mirror is a good option but you can also configure it to use a remote mirror.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slackpkg upgrade-all&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Assume slackpkg just upgraded your kernel, kernel-modules, kernel-headers, and kernel-source.&lt;br /&gt;
&lt;br /&gt;
Note: the first time you try to run on kernel-generic, setup kernel-huge in lilo as 2nd choice. Huge has all the hard drive controllers builtin, but generic has them all as modules. For example, run &amp;quot;modinfo mptsas&amp;quot; to see module options (maybe you have a LSISAS1068) for your hard drive controller. Add file /etc/modprobe.d/mptsas.conf to set options you want with a line: options mptsas ... Do this for all the device driver modules for your hardware. Do this setup while you are on the huge kernel, then setup to reboot to generic. Include all these modules you need into mkinitrd.conf MODULES_LIST. Check that /boot/initrd-tree/etc/modprobe.d/ has a copy of your customized module conf files because it is on the initrd where the modules will load and use the conf files. mkinitrd probably copies all /etc/modprobe.d/* files into the initrd-tree, but check it. Pay attention to /etc/modprobe.d/README and /lib/modprobe.d/* /lib/modprobe.d/* maybe not copied to initrd-tree but you might want to copy some of it into your initrd-tree yourself to use them.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Check that upgraded kernel-source is symlinked to /usr/src/linux (zfs build looks here). SPL/ZFS modules will install to the kernel version in /lib/modules/&amp;lt;/usr/src/linux kernel version&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /usr/local/src&lt;br /&gt;
tar xvzf ~/spl-*.tar.gz&lt;br /&gt;
tar xvzf ~/zfs-*.tar.gz&lt;br /&gt;
&lt;br /&gt;
###### upgrade spl 1st&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-*&lt;br /&gt;
./configure --prefix=/ --libexecdir=/usr/libexec --libdir=/lib64 --includedir=/usr/include --datarootdir=/usr/share&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=/usr/local/src/install&lt;br /&gt;
cd ../install&lt;br /&gt;
makepkg ../spl-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
upgradepkg spl-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
depmod &amp;lt;new kernel version&amp;gt;     (e.g. depmod 3.2.28, if .28 is new kernel upgrade; you currently run on old, maybe .27)&lt;br /&gt;
# this builds the module dependencies in /lib/modules/&amp;lt;new kernel version&amp;gt;&lt;br /&gt;
###### upgrade zfs 2nd&lt;br /&gt;
mkdir install&lt;br /&gt;
cd zfs-*&lt;br /&gt;
./configure --prefix=/ --libexecdir=/usr/libexec --libdir=/lib64 --includedir=/usr/include --datarootdir=/usr/share&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=/usr/local/src/install&lt;br /&gt;
cd ../install&lt;br /&gt;
makepkg ../zfs-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
upgradepkg zfs-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
depmod 3.2.28&lt;br /&gt;
####### upgrade spl/zfs inside altroot /boot/initrd-tree&lt;br /&gt;
ROOT=/boot/initrd-tree upgradepkg spl-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
ROOT=/boot/initrd-tree upgradepkg zfs-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
# note: ROOT is an environment variable, not a command line option to upgradepkg!&lt;br /&gt;
# note: do not worry about depmod inside initrd-tree, mkinitrd -F actually installs the modules&lt;br /&gt;
# note: this upgrade here is really to just upgrade the command line tools zpool, zfs etc&lt;br /&gt;
####### rebuild /boot/initrd.gz and reinstall lilo&lt;br /&gt;
vi /etc/mkinitrd.conf&lt;br /&gt;
# temporarily set KERNEL_VERSION to new version, but you are still running on old version&lt;br /&gt;
mkinitrd -F&lt;br /&gt;
lilo&lt;br /&gt;
vi /etc/mkinitrd.conf&lt;br /&gt;
# you can set KERNEL_VERSION back to $(uname -r) now&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After reboot you can remove any old /lib/modules/&amp;lt;old kernel version&amp;gt; directory.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
More about /etc/hostid. If you want to experiment changing your /etc/hostid file and seeing if you can use it and make zpool import work normally, here is a tool that might be helpful:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/* software product name: foobarz-chhostid.c&lt;br /&gt;
 * suggested binary name: chhostid&lt;br /&gt;
 * license              : BSD&lt;br /&gt;
 * license text:&lt;br /&gt;
Copyright (c) 2012, foobarz&lt;br /&gt;
All rights reserved.&lt;br /&gt;
&lt;br /&gt;
Redistribution and use in source and binary forms, with or without&lt;br /&gt;
modification, are permitted provided that the following conditions are met:&lt;br /&gt;
    * Redistributions of source code must retain the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer.&lt;br /&gt;
    * Redistributions in binary form must reproduce the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer in the&lt;br /&gt;
      documentation and/or other materials provided with the distribution.&lt;br /&gt;
    * Neither the name of the &amp;lt;organization&amp;gt; nor the&lt;br /&gt;
      names of its contributors may be used to endorse or promote products&lt;br /&gt;
      derived from this software without specific prior written permission.&lt;br /&gt;
&lt;br /&gt;
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &amp;quot;AS IS&amp;quot; AND&lt;br /&gt;
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED&lt;br /&gt;
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE&lt;br /&gt;
DISCLAIMED. IN NO EVENT SHALL &amp;lt;COPYRIGHT HOLDER&amp;gt; BE LIABLE FOR ANY&lt;br /&gt;
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES&lt;br /&gt;
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;&lt;br /&gt;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND&lt;br /&gt;
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT&lt;br /&gt;
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS&lt;br /&gt;
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#define FOOBARZ_CHHOSTID_VERSION &amp;quot;1.0.5&amp;quot;&lt;br /&gt;
#include &amp;lt;sys/socket.h&amp;gt;&lt;br /&gt;
#include &amp;lt;netinet/in.h&amp;gt;&lt;br /&gt;
#include &amp;lt;arpa/inet.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;endian.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sysexits.h&amp;gt;&lt;br /&gt;
/* note: if include stdlib then sethostid fails even with _BSD_SOURCE defined */&lt;br /&gt;
&lt;br /&gt;
long swapbytes(long abcd) {&lt;br /&gt;
  long badc;&lt;br /&gt;
  unsigned char addr_a;&lt;br /&gt;
  unsigned char addr_b;&lt;br /&gt;
  unsigned char addr_c;&lt;br /&gt;
  unsigned char addr_d;&lt;br /&gt;
  addr_a = (unsigned char) (abcd &amp;gt;&amp;gt; 24);&lt;br /&gt;
  addr_b = (unsigned char) (abcd &amp;gt;&amp;gt; 16);&lt;br /&gt;
  addr_c = (unsigned char) (abcd &amp;gt;&amp;gt;  8);&lt;br /&gt;
  addr_d = (unsigned char) (abcd);&lt;br /&gt;
  return badc = ( (addr_b &amp;lt;&amp;lt; 24) | (addr_a &amp;lt;&amp;lt; 16) | (addr_d &amp;lt;&amp;lt; 8) | addr_c );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[])&lt;br /&gt;
{&lt;br /&gt;
 long newhostid;&lt;br /&gt;
 struct in_addr addr;&lt;br /&gt;
 char* invalidchar;&lt;br /&gt;
&lt;br /&gt;
 /*********** check command line */&lt;br /&gt;
 if(!( ((argc==3) &amp;amp;&amp;amp; ( (strcmp(argv[1],&amp;quot;-h&amp;quot;)==0) ||&lt;br /&gt;
                       (strcmp(argv[1],&amp;quot;-i&amp;quot;)==0) ||&lt;br /&gt;
                       (strcmp(argv[1],&amp;quot;-l&amp;quot;)==0) )) ||&lt;br /&gt;
       ((argc==2) &amp;amp;&amp;amp; ( (strcmp(argv[1],&amp;quot;-s&amp;quot;)==0) ))&lt;br /&gt;
     )&lt;br /&gt;
   ) {&lt;br /&gt;
                 /*01234567890123456789012345678901234567890123456789012345678901234567890123456789*/&lt;br /&gt;
  fprintf(stderr, &amp;quot;foobarz-chhostid, version %s. License: BSD.\n&amp;quot;, FOOBARZ_CHHOSTID_VERSION);&lt;br /&gt;
  fprintf(stderr, &amp;quot;foobarz-chhostid, (c) 2012, foobarz; all rights reserved.\n&amp;quot;);&lt;br /&gt;
  fprintf(stderr, &amp;quot;descr: %s change system hostid (in /etc/hostid).\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -h &amp;lt;new hostid&amp;gt;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        Change system hostid to &amp;lt;new hostid&amp;gt;;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        &amp;lt;new hostid&amp;gt; must be 32bit 8-digit hex number xxxxxxxx, each x in 0-f|F.\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        The ip corresponding to &amp;lt;new hostid&amp;gt; is also listed for reference only.\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -i &amp;lt;dotted ip address&amp;gt;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        Change system hostid to hostid corresponding to &amp;lt;dotted ip address&amp;gt;.\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -l &amp;lt;dotted ip address&amp;gt;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        List hostid corresponding to &amp;lt;dotted ip address&amp;gt;;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        no change to system hostid.\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -s\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        List current system hostid and corresponding ip address;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        no change to system hostid.\n&amp;quot;, argv[0]);&lt;br /&gt;
  return EX_USAGE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -h &amp;lt;hostid&amp;gt; */&lt;br /&gt;
 if( strcmp(argv[1],&amp;quot;-h&amp;quot;) == 0 ) {&lt;br /&gt;
  if(strlen(argv[2]) != 8) { fprintf(stderr, &amp;quot;new hostid must be 8-digit hex number xxxxxxxx, each x in 0-f|F\n&amp;quot;); return EX_USAGE; }&lt;br /&gt;
&lt;br /&gt;
  newhostid = strtol(argv[2],&amp;amp;invalidchar,16);&lt;br /&gt;
  if( newhostid==LONG_MIN ) { perror(&amp;quot;strtol (underflow)&amp;quot;); return EX_USAGE; }&lt;br /&gt;
  if( newhostid==LONG_MAX ) { perror(&amp;quot;strtol (overflow)&amp;quot;); return EX_USAGE; }&lt;br /&gt;
  if(*invalidchar != '\0') { fprintf(stderr, &amp;quot;invalid hex number %c; must be in 0-f|F\n&amp;quot;, *invalidchar); return EX_USAGE; }&lt;br /&gt;
&lt;br /&gt;
  if( sethostid(newhostid) != 0 ) {&lt;br /&gt;
   perror(&amp;quot;sethostid&amp;quot;);&lt;br /&gt;
   if( errno == EPERM ) return EX_NOPERM;&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
  }&lt;br /&gt;
  printf(&amp;quot;System hostid changed.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  /* hostid is a byte-swapped ip like b.a.d.c */&lt;br /&gt;
  /* get ip by swapping to correct order a.b.c.d and save into in_addr struct */&lt;br /&gt;
  addr.s_addr = htonl(swapbytes(newhostid));&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -i or -l, then find hostid for &amp;lt;dotted ip address&amp;gt; */&lt;br /&gt;
 if( (strcmp(argv[1],&amp;quot;-i&amp;quot;) == 0) || (strcmp(argv[1],&amp;quot;-l&amp;quot;) == 0) ) {&lt;br /&gt;
  if( inet_aton(argv[2], &amp;amp;addr) == 0 ) { fprintf(stderr, &amp;quot;inet_aton: invalid dotted ip address: %s\n&amp;quot;, argv[2]); return EX_USAGE; }&lt;br /&gt;
&lt;br /&gt;
  /* hostid is a byte-swapped ip like b.a.d.c */&lt;br /&gt;
  /* get hostid by swapping bytes of ip a.b.c.d */&lt;br /&gt;
  newhostid = swapbytes(ntohl(addr.s_addr));&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -i &amp;lt;dotted ip address&amp;gt; */&lt;br /&gt;
 if( strcmp(argv[1],&amp;quot;-i&amp;quot;) == 0 ) {&lt;br /&gt;
  if( sethostid(newhostid) != 0 ) {&lt;br /&gt;
   perror(&amp;quot;sethostid&amp;quot;);&lt;br /&gt;
   if( errno == EPERM ) return EX_NOPERM;&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
  }&lt;br /&gt;
  printf(&amp;quot;System hostid changed.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -l &amp;lt;dotted ip address&amp;gt; */&lt;br /&gt;
 if(strcmp(argv[1],&amp;quot;-l&amp;quot;) == 0 ) {&lt;br /&gt;
   printf(&amp;quot;Listing hostid for ip. (no changes)\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -s */&lt;br /&gt;
 if(strcmp(argv[1],&amp;quot;-s&amp;quot;) == 0 ) {&lt;br /&gt;
   /* see if /etc/hostid exists and print info */&lt;br /&gt;
   if( access(&amp;quot;/etc/hostid&amp;quot;, F_OK) != 0 ) {&lt;br /&gt;
     printf(&amp;quot;Notice: /etc/hostid does not exist.\n&amp;quot;);&lt;br /&gt;
     perror(&amp;quot;Reason&amp;quot;);&lt;br /&gt;
     printf(&amp;quot;System hostid derived from ip of hostname found in hosts file or dns.\n&amp;quot;);&lt;br /&gt;
   } else {&lt;br /&gt;
     printf(&amp;quot;Notice: /etc/hostid exists.\n&amp;quot;&lt;br /&gt;
            &amp;quot;System hostid is obtained from hostid file.\n&amp;quot;);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
  errno=0;&lt;br /&gt;
  newhostid = gethostid();&lt;br /&gt;
  if(errno!=0) { perror(&amp;quot;gethostid&amp;quot;); return EX_UNAVAILABLE; }&lt;br /&gt;
&lt;br /&gt;
  /* hostid is a byte-swapped ip like b.a.d.c */&lt;br /&gt;
  /* get ip by swapping to correct order a.b.c.d and save into in_addr struct */&lt;br /&gt;
  addr.s_addr = htonl(swapbytes(newhostid));&lt;br /&gt;
&lt;br /&gt;
  printf(&amp;quot;Listing current system hostid. (no changes)\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** print info and return */&lt;br /&gt;
 printf(&amp;quot;ip dot: %s\n&amp;quot;, inet_ntoa(addr) );&lt;br /&gt;
 printf(&amp;quot;ip hex: %.8x\n&amp;quot;, ntohl(addr.s_addr) );&lt;br /&gt;
 printf(&amp;quot;hostid: %.8x\n&amp;quot;, newhostid );&lt;br /&gt;
 return EX_OK;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
----&lt;br /&gt;
Now available! &amp;quot;ZFS root (builtin)&amp;quot; wiki (aka &amp;quot;ZFS root, part II&amp;quot;):&lt;br /&gt;
http://slackwiki.com/ZFS_root_(builtin)&lt;br /&gt;
It is now possible to build the modules and a small initramfs into your kernel to have a fully-contained and bootable ZFS root kernel from a simple lilo entry. Good luck!&lt;/div&gt;</description>
			<pubDate>Mon, 24 Sep 2012 14:44:46 GMT</pubDate>
			<dc:creator>Foobarz</dc:creator>
			<comments>https://www.slackwiki.com/Talk:ZFS_root</comments>
		</item>
		<item>
			<title>ZFS root</title>
			<link>https://www.slackwiki.com/index.php?title=ZFS_root&amp;diff=802</link>
			<guid isPermaLink="false">https://www.slackwiki.com/index.php?title=ZFS_root&amp;diff=802</guid>
			<description>&lt;p&gt;Foobarz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Tutorials]]&lt;br /&gt;
If you have heard about the ZFS filesystem and you're curious to try it out, then you can try it on slackware64, thanks to the ZFSonLinux.org project!&lt;br /&gt;
&lt;br /&gt;
In this article, an example is shown of how to install slackware64 14.0 onto a ZFS root filesystem (zfs-root) inside a QEMU virtual machine for testing purposes. It is recommended that you install qemu and learn how to use it to test a ZFS installation before you decide to use it on real hardware. A slackbuild for qemu can be found on slackbuilds.org. If you have a processor that supports Intel VT-x or AMD AMD-V virtualization acceleration (try modprobe kvm-intel or modprobe kvm-amd), then use the slackbuild for qemu-kvm.&lt;br /&gt;
&lt;br /&gt;
This article isn't going to go into any detail on actually using ZFS or what kinds of installation options and settings might be optimal. This article just presents an example of how to get started with ZFS on slackware.&lt;br /&gt;
&lt;br /&gt;
At this time of writing, ZFSonLinux is at &amp;quot;release candidate&amp;quot; (version 0.6.0-rc11) development stage, and many issues can occur. See the ZFSonLinux.org web site and the issues tracker for an idea about the current issues. There is also an irc channel on irc.freenode.net, #zfsonlinux, for discussion of issues and help.&lt;br /&gt;
&lt;br /&gt;
Although not required, it is helpful to keep a local mirror of slackware64 on your system. Having a local mirror makes it easier to upgrade to slackware64-current or to patches/* in a release. To help manage your own local slackware mirror and generate your own CD and DVD slackware installers, see http://alien.slackbook.org/blog/local-slackware-mirror/.&lt;br /&gt;
&lt;br /&gt;
In this article, we use a slackware64-current DVD image file as the qemu cdrom device media for the installation of the slackware guest. This was tested at slackware64-current = slackware64 14.0rc4. You can obtain a slackware DVD image using a torrent, buy the DVD from slackware.com, or generate your own DVD image file using the mirror script. For an actual DVD, you can pass your DVD device (e.g., /dev/sr0) as the qemu cdrom device. For a DVD image file, pass the image file as the qemu cdrom device.&lt;br /&gt;
&lt;br /&gt;
The ZFSonLinux packages are not included in slackware at this time. There are two packages involved: spl and zfs. The first, spl, is &amp;quot;Solaris Porting Layer&amp;quot; and must be installed on the system before zfs can be compiled. The source code tarballs for these are at ZFSonLinux.org. At this time of writing, they are spl-0.6.0-rc11.tar.gz and zfs-0.6.0-rc11.tar.gz.&lt;br /&gt;
&lt;br /&gt;
At this point, it is assumed you have qemu installed, have obtained a slackware64-current/14.0 DVD, and have downloaded spl and zfs tarballs to your host system. The first step now is, if your host is not slackware64-current/14.0 (the same as the guest will be), then you need to create a minimal development slackware64 guest system in qemu for just the purpose of compiling and packaging the spl and zfs slackware packages and transferring a copy of these packages back onto your host system to use later to install onto zfs during the slackware install process.&lt;br /&gt;
&lt;br /&gt;
From this point onward, instructions become a bit terse and mostly limited to examples of the commands you might use to complete tasks. You are encouraged to examine what each command does by reading the command's man pages. For example, the command &amp;quot;man qemu&amp;quot; can show you most of what you need to know about running qemu on the command line.&lt;br /&gt;
&lt;br /&gt;
So, here's an example of how you might build the spl and zfs packages, starting in your home directory:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on host)&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir qemu&lt;br /&gt;
cd qemu&lt;br /&gt;
mkdir slackdevel&lt;br /&gt;
cd slackdevel&lt;br /&gt;
mkdir packages&lt;br /&gt;
cp ~/spl-*.tar.gz packages&lt;br /&gt;
cp ~/zfs-*.tar.gz packages&lt;br /&gt;
qemu-img create disk1.raw 10G&lt;br /&gt;
ln -s ~/slackware64-current-install-dvd.iso dvd.iso&lt;br /&gt;
qemu-kvm \&lt;br /&gt;
 -option-rom 8xx_64.rom,bootindex=1 \&lt;br /&gt;
 -no-quit \&lt;br /&gt;
 -no-shutdown \&lt;br /&gt;
 -boot order=cd,menu=on \&lt;br /&gt;
 -m 2G \&lt;br /&gt;
 -cpu host \&lt;br /&gt;
 -smp sockets=1,cores=4 \&lt;br /&gt;
 -net nic,model=e1000 -net user \&lt;br /&gt;
 -cdrom dvd.iso \&lt;br /&gt;
 -drive format=raw,media=disk,cache=none,aio=native,if=scsi,index=0,file=disk1.raw \&lt;br /&gt;
 -virtfs local,path=./packages/,security_model=none,mount_tag=hostpackages&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When you need to change boot to cd or disk, try changing &amp;quot;order=dc&amp;quot; or hitting F12 at boot prompt and select the CD/DVD boot option.&lt;br /&gt;
&lt;br /&gt;
Note: The support for booting drives using if=scsi is not included with current versions of qemu. Booting scsi requires the 8xx_64.rom option-rom, which can be downloaded at&lt;br /&gt;
[http://www.lsi.com/downloads/Public/Host%20Bus%20Adapters/Host%20Bus%20Adapters%20Common%20Files/lsi_bios.zip LSI.com]. Unzip it, and then:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp 8xx_64.rom /usr/share/qemu&lt;br /&gt;
# then run qemu-kvm with additional command line option: -option-rom 8xx_64.rom,bootindex=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Qemu should boot into the install-dvd, and now perform a very ordinary slackware64 install onto /dev/sda. Install d package set and most others, but package sets x, kde, xfce not really needed.&lt;br /&gt;
&lt;br /&gt;
First note: examples here use tools from the gptfdisk package (gdisk, sgdisk, cgdisk) to partition the disk with GUID partition table (GPT) format. GPT might not be too familiar to everyone, who mostly have only used MBR partitions with fdisk. In the slackware installations this author has tested in qemu, using GPT partitions has caused no problems with lilo or other tools used in slackware. GPT disk labels support creating up to 128 partitions and support disks larger than 2TB (the limit of MBR fdisk). LILO installs into the first 440 bytes on /dev/sda, inside a GPT &amp;quot;protective MBR&amp;quot; that serves to provide compatibility with MBR bootloaders like lilo. LILO uses LBA32 sector addressing and can see all 512-byte sectors inside the first 2TB of a disk. So long as the /boot partition is within the first 2TB of a disk, lilo can work on a disk larger than 2TB. Unlike the common default of fdisk to start the first partition at sector 63, which is not aligned with the 4KiB sector size of Advanced Format hard disks, gdisk's default is to start partitions at 2048 sector (1MiB) boundaries which are also 4KiB aligned. Using gdisk GPT works on all disks and is compatible with using Advanced Format hard disks larger than 2TB. More information about GPT disk label format can be found on wikipedia.org. For those that have used grub instead of lilo, grub installation is different with GPT than with MBR, and grub requires a GPT partition of type grub-bios or 0xEF02 &amp;quot;BIOS Boot Partition&amp;quot; of about 8MiB where it can install it's additional bootloader stages because grub cannot embed in sectors 1-62 on GPT where GPT keeps it's partition tables. On MBR, sectors 1-62 were normally reserved space for bootloaders to keep a 2nd stage.&lt;br /&gt;
&lt;br /&gt;
For this purpose of development guest, just create a simple 1-partition system, /dev/sda1, and do a simple slackware install on it. Don't bother with swap or separate /boot unless you want to:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on install-dvd)&lt;br /&gt;
cgdisk /dev/sda&lt;br /&gt;
setup&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When this simple development guest boots, login as root, and continue:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on qemu guest)&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir packages&lt;br /&gt;
mount hostpackages -t 9p -o trans=virtio packages&lt;br /&gt;
echo --prefix=/ --libexecdir=/usr/libexec --libdir=/lib64 --includedir=/usr/include --datarootdir=/usr/share &amp;gt; configure-options&lt;br /&gt;
mkdir src&lt;br /&gt;
cd src&lt;br /&gt;
&lt;br /&gt;
mkdir install&lt;br /&gt;
tar xvzf ~/packages/spl-*.tar.gz&lt;br /&gt;
cd spl-*&lt;br /&gt;
./configure $( cat ~/configure-options )&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../spl-&amp;lt;version&amp;gt;_&amp;lt;kernel_version&amp;gt;-x86_64-&amp;lt;build_id&amp;gt;.txz&lt;br /&gt;
(e.g., makepkg ../spl-0.6.0rc11_3.2.28-x86_64-1root.txz)&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
installpkg spl-0.6.0rc11_3.2.28-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
cp spl-0.6.0rc11_3.2.28-x86_64-1root.txz ~/packages&lt;br /&gt;
&lt;br /&gt;
mkdir install&lt;br /&gt;
tar xvzf ~/packages/zfs-*.tar.gz&lt;br /&gt;
cd zfs-*&lt;br /&gt;
./configure $( cat ~/configure-options )&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../zfs-&amp;lt;version&amp;gt;_&amp;lt;kernel_version&amp;gt;-x86_64-&amp;lt;build_id&amp;gt;.txz&lt;br /&gt;
(e.g., makepkg ../zfs-0.6.0rc11_3.2.28-x86_64-1root.txz)&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
installpkg zfs-0.6.0rc11_3.2.28-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
cp zfs-0.6.0rc11_3.2.28-x86_64-1root.txz ~/packages&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point spl and zfs packages are copied back to the host in the packages directory. Also, spl and zfs are installed in this simple development guest, so one could begin to experiment with zfs pools and datasets but while the root fs is whatever you made it during setup (probably the default, ext4). This development guest isn't really needed anymore, so it can be deleted:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
halt&lt;br /&gt;
(exit qemu: ctrl-alt-2 then enter quit at QEMU command prompt)&lt;br /&gt;
&lt;br /&gt;
(on host)&lt;br /&gt;
rm disk1.raw dvd.iso&lt;br /&gt;
mv packages ..&lt;br /&gt;
cd ..&lt;br /&gt;
rmdir slackdevel&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now that we have the spl and zfs packages on the host, it is possible to copy them into your local slackware64 mirror and then generate your own install DVD image that includes them. For example, change to the directory that contains the slackware README files, and create a &amp;quot;addon&amp;quot; directory and copy the spl and zfs slackware packages into there. Then, generate the DVD image using a command such as $( ./mirror-slackware-current.sh -i ) from where you have this script configured to maintain your local mirror. We can also just continue to access them inside the installer using qemu's virtfs option. When you are going to do a real installation onto real hardware, you need to generate and burn your own DVD that includes the packages.&lt;br /&gt;
&lt;br /&gt;
It is time to begin the installation of slackware64 on a ZFS root, assuming either you have regenerated dvd.iso with zfs packages in addon/* or we access the zfs packages while in the installer using qemu's virtfs to the host's packages directory.&lt;br /&gt;
&lt;br /&gt;
ZFS supports creating complex data storage configurations in data storage pools (similar to a LVM volume group) backed by one or more virtual devices (similar to physical disks and raid arrays) and containing one or more datasets (similar to mounted filesystems, logical volume devices, or snapshots). But here, we keep it simple and will install on just a single disk device.&lt;br /&gt;
&lt;br /&gt;
On a real ZFS installation, users will typically want to use the ZFS mirror or raidz virtual device (vdev) types for reliability against hard drive failures. For example, a good configuration might be to use a USB memory stick (and a backup stick) for /boot that is plugged into an on-motherboard &amp;quot;Type A&amp;quot; USB connector. Then, use four whole hard drives in a raidz2 vdev as the initial storage space in the root zpool. At a later time, to add more storage space, additional whole four-drive raidz2 vdevs of the same size could be added to the zpool. It is recommended to only add the same vdev type (disk, mirror, or raidz|1|2|3) and size to a zpool since zfs stripes across the vdevs, and vdevs of different types/sizes do not stripe together optimally. After adding a vdev to your zpool, you might need to copy the new /etc/zfs/zpool.cache to your initrd-tree or initramfs-source (and rebuild/reinstall them) if you are using the cachefile to import your zpool. Using mirror vdevs would be similar to a raid10. Using 4-disk raidz2 vdevs would give the same storage space as raid10 while fully reliable against any double-disk failure; however, the raidz2 parity calculations results in higher CPU usage and/or lower performance. Because raidz vdevs cannot be grown by adding hard drives to them, and vdevs in a zpool are striped, it is important with ZFS to decide what type and size of vdev will be used in a zpool as the units of add-on storage space; it could be difficult to alter this decision later. Finally, on a real installation with raidz, data scrub should be scheduled to actively search for &amp;quot;latent defects&amp;quot; on the hard drives so that unknown read/write errors do not become known later during a disk swap/rebuild and result in the zpool becoming faulted (lost).&lt;br /&gt;
&lt;br /&gt;
If you decide to test raidz in qemu, consider making the qemu disk files on different physical disks on your host to avoid putting all the stress onto a single disk on your host. The raidz qemu disks that are all on a single physical hard drive will cause poor performance and stress on the disk due to the large amount of seek operations to access the stripes/columns in the raidz. Again, we'll keep it simple in this wiki and just make a root zpool that is just holding a single qemu disk that you've given to qemu to avoid stress on the host hard drive. But, if you really want to test raidz, you can do it by just making more qemu disks (with incremented index=X number) and making your zpool a raidz; there's no technical restriction here on the kind of vdevs in your root zpool.&lt;br /&gt;
&lt;br /&gt;
Make &amp;quot;slackzfs&amp;quot; guest, and boot it into the slackware installer to begin installation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on host)&lt;br /&gt;
mkdir slackzfs&lt;br /&gt;
mv packages slackzfs/&lt;br /&gt;
cd slackzfs&lt;br /&gt;
qemu-img create disk1.raw 10G&lt;br /&gt;
ln -s ~/slackware64-current-install-dvd.iso dvd.iso&lt;br /&gt;
qemu-kvm \&lt;br /&gt;
 -option-rom 8xx_64.rom,bootindex=1 \&lt;br /&gt;
 -no-quit \&lt;br /&gt;
 -no-shutdown \&lt;br /&gt;
 -boot order=cd,menu=on \&lt;br /&gt;
 -m 2G \&lt;br /&gt;
 -cpu host \&lt;br /&gt;
 -smp sockets=1,cores=4 \&lt;br /&gt;
 -net nic,model=e1000 -net user \&lt;br /&gt;
 -cdrom dvd.iso \&lt;br /&gt;
 -drive format=raw,media=disk,cache=none,aio=native,if=scsi,index=0,file=disk1.raw \&lt;br /&gt;
 -virtfs local,path=./packages/,security_model=none,mount_tag=hostpackages&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The install-dvd should boot, and then begin installation steps on the installer command line:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on install-dvd)&lt;br /&gt;
# mount the install-dvd&lt;br /&gt;
mkdir /dvd&lt;br /&gt;
mount /dev/sr0 /dvd&lt;br /&gt;
&lt;br /&gt;
# install coreutils, which provides the &amp;quot;hostid&amp;quot; command needed to load the spl module&lt;br /&gt;
installpkg /dvd/slackware64/a/coreutils-8.17-x86_64-1.txz&lt;br /&gt;
&lt;br /&gt;
# install kmod package which includes &amp;quot;depmod&amp;quot; command and others&lt;br /&gt;
installpkg /dvd/slackware64/a/kmod-9-x86_64-2.txz&lt;br /&gt;
depmod&lt;br /&gt;
&lt;br /&gt;
# install the full kernel modules so you can load 9p filesystem and use it if you want&lt;br /&gt;
# .. you might keep the zfs modules packages off the dvd and use a plain slack dvd&lt;br /&gt;
installpkg /dvd/slackware64/a/kernel-modules-*.txz&lt;br /&gt;
depmod&lt;br /&gt;
&lt;br /&gt;
# install bash and libtermcap because udev rules in zfs use bash scripts&lt;br /&gt;
installpkg /dvd/slackware64/a/bash-*.txz&lt;br /&gt;
installpkg /dvd/slackware64/l/libtermcap-*.txz&lt;br /&gt;
&lt;br /&gt;
# install spl and zfs that you have copied into the mirror before running the DVD creation&lt;br /&gt;
installpkg /dvd/addon/spl-0.6.0rc11_3.2.28-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /dvd/addon/zfs-0.6.0rc11_3.2.28-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
&lt;br /&gt;
#Or:&lt;br /&gt;
mkdir /packages&lt;br /&gt;
find /lib/modules/ | grep 9p&lt;br /&gt;
lsmod&lt;br /&gt;
# check that 9p modules load, mainly 9pnet_virtio&lt;br /&gt;
modprobe 9pnet_virtio&lt;br /&gt;
mount hostpackages -t 9p -o trans=virtio /packages&lt;br /&gt;
installpkg /packages/spl-0.6.0rc11_3.2.28-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /packages/zfs-0.6.0rc11_3.2.28-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
modprobe zfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now zfs tools: &amp;quot;zpool&amp;quot; and &amp;quot;zfs&amp;quot; should work in the live installer.&lt;br /&gt;
On the installer, there can be trouble seeing man pages, so install:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
installpkg /dvd/slackware64/ap/man-*.txz&lt;br /&gt;
installpkg /dvd/slackware64/ap/groff-*.txz&lt;br /&gt;
installpkg /dvd/slackware64/a/less-*.txz&lt;br /&gt;
export MANPATH=/usr/man:/usr/share/man&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The manual pages should be readable:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
man zpool&lt;br /&gt;
man zfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After seeing the man pages, we should be fully ready to continue to setup on ZFS.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(still on install-dvd)&lt;br /&gt;
ls -l /dev/sd*&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Make sure the disk devices you expect are there. We'll use sda and make boot (/boot on /dev/sda1) and root (/ on /dev/sda2) partitions.&lt;br /&gt;
&lt;br /&gt;
First, some background info: A ZFS filesystem is not supported by lilo as the filesystem containing /boot, which holds lilo's 2nd stage and the linux kernel files. The on-disk format of a ZFS filesystem is often a complex raid configuration where even if lilo understood ZFS it would likely require /boot to reside in only certain simple ZFS configurations to be plainly readable to lilo. As things are, a linux root installed in a partition with ZFS filesystem needs /boot to be on another partition with a filesystem that lilo understands, such as ext4 fs. In addition, because the spl and zfs modules are not built into the kernel, and the zfs startup requires some configuration to mount the zfs root, an initial ram/root filesystem (initrd) is needed. The initrd is a gzip compressed cpio archive file that contains a small linux root operating system that is decompressed into a ramfs block device at boot up and takes initial control of the system. The initrd contains an init script that configures devices in devtmpfs mounted at /dev. For example, if using mdadm, lvm, luks, losetup, and now zfs, this init script runs all the commands to create or start these devices (one of which is the root device), mounts the root device, and then transfers system control to the init script in the mounted root filesystem. The ramfs-based root environment on the booted install-dvd or booted initrd image (in rescue command line) are small slackware installations that exist only in ram and are temporary, but while inside them you can install, upgrade, and remove slackware packages inside them using the regular package management tools; this allows you access to any kernel modules and programs as needed inside these ramfs root. Packages can be installed, upgraded, or removed permanantly in the initrd image file to manage the programs and modules required during the initrd boot stage. Also from within these ramfs initial root environments, once the root device is mounted, chroot can be used to work on the mounted root system as if it were booted; this allows one to fix problems that are occuring in the root fs init scripts that cause normal booting to fail, or to install a kernel and/or modules etc. Now on to partitioning:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cgdisk /dev/sda&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, cgdisk looks just like cfdisk, but it makes GPT partitions.&lt;br /&gt;
&lt;br /&gt;
Make a partition for /boot that is about 512MiB of whatever partition type you like (8300 &amp;quot;Linux filesystem&amp;quot; is fine), or make it type bf07 &amp;quot;Solaris Reserved 1&amp;quot; if you want ZFS to maybe see the disk as if it was given as a whole disk to ZFS. Make a second partition using the remaining space with partition type bf01 &amp;quot;Solaris ZFS&amp;quot;. Currently, when ZFSonLinux is given a whole disk device like /dev/sdb to use, it will automatically GPT partition it with a bf01 partition #1 that is the whole disk except a small 8MiB type bf07 partition #9 at the end of the disk (/dev/sdb1 and /dev/sb9). The small 8MiB type bf07 partition #9 is most likely reserved for use by bootloaders, like lilo, to have a /boot or other boot-related files kept there. For example, you might have /dev/sda that is totally non-ZFS for booting and /dev/sdb passed to ZFS whole where it automatically partitions sdb, but you can just use one disk here and make partitions. Let's use type 8300 for /boot to be sure nothing is confused:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
We'll continue with this partitioning:&lt;br /&gt;
Part. #    Size        Partition Type           Partition Name&lt;br /&gt;
           4.0 MiB     free space&lt;br /&gt;
   1       512.0 MiB   Linux filesystem         boot&lt;br /&gt;
           4.0 MiB     free space&lt;br /&gt;
   2       9.4 GiB     Solaris /usr &amp;amp; Mac ZFS   root&lt;br /&gt;
           96.0 MiB    free space&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The free space is left as a recommendation. The free space has potential uses for data recovery techniques, changing boot configuration, accomodating a replacement disk that is slightly smaller, and avoiding the end of the disk where GPT and other disk labels may need to claim space at the end of a drive to hold metadata. The &amp;quot;partition name&amp;quot; can be blank or any arbitrary name you'd like to give them.&lt;br /&gt;
&lt;br /&gt;
If you are going to test a ZFS mirror or raidz configuration, then you can repeat this same partitioning on each disk. For example, for a four-disk raidz2 with /dev/sd[abcd] you might do:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sgdisk -R /dev/sdb /dev/sda&lt;br /&gt;
sgdisk -G /dev/sdb&lt;br /&gt;
sgdisk -R /dev/sdc /dev/sda&lt;br /&gt;
sgdisk -G /dev/sdc&lt;br /&gt;
sgdisk -R /dev/sdd /dev/sda&lt;br /&gt;
sgdisk -G /dev/sdd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Then, you could use the boot partitions /dev/sd[abcd]1 in a mdadm raid1 as your boot device:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mdadm --create /dev/md0 -l 1 -n 4 /dev/sd[abcd]1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
In this configuration, /dev/md0 is your 4-way mirror /boot device and is used as explained in the slackware [ftp://slackware.mirrors.tds.net/pub/slackware/slackware64-current/README_RAID.TXT README_RAID.TXT]. The /dev/sd[abcd]2 would be given to ZFS for the raidz2 (instead of to mdadm raid). This is only an example and there are many possible configurations, including using whole un-partitioned disks; however, we will continue in this wiki with a simpler configuration with /dev/sda1 as a non-raid /boot device and /dev/sda2 in a non-raidz/non-mirror zpool.&lt;br /&gt;
&lt;br /&gt;
Create a zpool called zfs-root:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool create -m none zfs-root /dev/sda2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A zpool created like this, the normal way, is a kernel-internal block device that contains already a zfs filesystem. There is normally no entry in /dev for this device. However, it can still be referenced as a mountable device similar to how devtmpfs, proc, and sysfs are also kernel-internal mountable block devices. The -m option told zpool not to automatically mount it anywhere, and without -m the default is to always automatically mount to /zfs-root. These kinds of details are explained better elsewhere. For this situation, we do not want it automounted.&lt;br /&gt;
&lt;br /&gt;
Because a zpool itself is a useable zfs fs, it has a full set of zfs &amp;quot;properties&amp;quot; to set options about the filesystem, perhaps similar to tune2fs. The &amp;quot;mountpoint=&amp;lt;some place to mount&amp;gt;&amp;quot; is one such property. We want it set to the special value &amp;quot;none&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs get mountpoint zfs-root&lt;br /&gt;
zfs set mountpoint=none zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also use &amp;quot;legacy&amp;quot; for the mountpoint and the management of mounting and unmounting the pool will be expected to be done using the regular &amp;quot;mount&amp;quot; and &amp;quot;umount&amp;quot; commands:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=legacy zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Later in the wiki, it is shown how to mount using &amp;quot;zfs mount&amp;quot; for mountpoint=none, and regular &amp;quot;mount&amp;quot; for mountpoint=legacy. Using mountpoint=legacy is probably the preferred setting for the zfs-root because you can use the normal mount and umount commands and do not have to change slackware /etc/rc.d/* scripts much, if any. The normal slackware scripts handle a root filesystem's mounting and remounting using the normal mount command.&lt;br /&gt;
&lt;br /&gt;
On creation, the zpool zfs-root is &amp;quot;imported&amp;quot; and has a zpool status that can be viewed:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool status zfs-root&lt;br /&gt;
&lt;br /&gt;
zpool export zfs-root&lt;br /&gt;
zpool status zfs-root&lt;br /&gt;
# Now there is no status.&lt;br /&gt;
&lt;br /&gt;
zpool import zfs-root&lt;br /&gt;
# Now it is back.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
When a zpool is imported, it has it's current configuration cached in a file /etc/zfs/zpool.cache. When a zpool is exported, then it's entries in the cache file are removed and the cache file is deleted if it becomes empty. So long as the zfs kernel modules see this cache file and valid cache data inside it, ZFS considers the described zpools in the cache file to be valid as imported zpools. If the zpool.cache file is present at the time the zfs modules are loaded, then there is no further need to use the import and export zpool commands at system startup and shutdown. With root on a zfs, it is not possible to export the pool that root is on, but this is not a problem. At shutdown, the safe procedure will be to set the zfs-root property readonly=on or remount read-only and sync disks.&lt;br /&gt;
&lt;br /&gt;
To avoid the requirement to import the zfs-root pool at startup, you can keep a copy of the zpool.cache file to later copy onto the initrd image to read at modules load time to have the pool reactivated without need to issue the zpool import command:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/zfs/zpool.cache /etc/zfs/zpool.cache-initrd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
A warning about the zpool.cache file: Having /etc/zfs/zpool.cache present at zfs module load or module init time can be unsafe if the device names in /dev have changed since the last boot. Especially dangerous is if two hard drives have swapped names, like /dev/sda and /dev/sdb have swapped names. It is safer to not have a zpool.cache file on the system at boot and zfs module load/init time to guard against the possibility that the cache file is no longer correct. This wiki will try to show how you can use zpool.cache to import your pool if the regular zpool import command seems to always require you to force it. This wiki will also show how to not need a zpool.cache file to import normally.&lt;br /&gt;
&lt;br /&gt;
A zfs filesystem will not normally allow you to mount over any files. The mountpoint is expected to be an empty directory. Remove any junk files inside the installer's /mnt because zfs won't mount over any files:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rm /mnt/README&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The directory /mnt is where the slackware setup expects you to mount your root for installation.&lt;br /&gt;
&lt;br /&gt;
Controlling whether a zfs fs is to be mounted read-only or read-write is best managed by setting the readonly property while it is not yet mounted:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set readonly=on zfs-root&lt;br /&gt;
zfs set readonly=off zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If you are using &amp;lt;code&amp;gt;mountpoint=legacy&amp;lt;/code&amp;gt; then the options for the mount command for ro or rw mounting will work as normal also and override whatever the readonly property is set to. The readonly property does serve as a default.&lt;br /&gt;
&lt;br /&gt;
Slackware expects root to be mounted readonly when /etc/rc.d/rc.S runs during normal startup, so later this is used to satisfy slackware's expectation to avoid rc.S complaining.&lt;br /&gt;
&lt;br /&gt;
The zfs-root can be mounted and unmounted in two different ways:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=/mnt zfs-root&lt;br /&gt;
zfs set mountpoint=none zfs-root&lt;br /&gt;
# or&lt;br /&gt;
mount zfs-root -t zfs /mnt&lt;br /&gt;
umount /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If it is already mounted and you want to change it to mount somewhere else, it is best to transition it to unmounted first, then mount it in the new place.&lt;br /&gt;
&lt;br /&gt;
The mount options &amp;lt;code&amp;gt;-o ro, -o rw, -o remount,ro, and -o remount,rw &amp;lt;/code&amp;gt; can also be used and will override the &amp;lt;code&amp;gt;readonly=on|off&amp;lt;/code&amp;gt; property without altering the property value. This can be confusing until you are familiar with how the two methods of mounting interact. When &amp;lt;code&amp;gt;mountpoint=legacy&amp;lt;/code&amp;gt; is set, zfs expects the regular mount and umount commands to be used to mount and unmount the dataset with the assistance of the mount.zfs helper. For now, we will continue with &amp;lt;code&amp;gt;mountpoint=none&amp;lt;/code&amp;gt;, but using legacy is also a good option.&lt;br /&gt;
&lt;br /&gt;
Now, let's continue some, and mount to /mnt using the current &amp;lt;code&amp;gt;readonly=off&amp;lt;/code&amp;gt; setting (rw mount):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=/mnt zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method of mounting will show the most detailed mount options in /etc/mtab. They are the mount options that zfs thinks are proper, and they are probably what should be kept in /etc/fstab for zfs-root until we know better.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cat /etc/mtab &amp;gt;&amp;gt; /etc/fstab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now edit /etc/fstab to make sure it looks right, and remove the &amp;quot;rw&amp;quot; mount option, because we want to let it use a default for that, which will come from how we set the readonly= property most of the time. Unmount again:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=none zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mount again, now using all options from /etc/fstab:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It should be mounted at /mnt, and touch /mnt/t should allow you to make the file t. Then rm it: rm /mnt/t&lt;br /&gt;
For installation, we want to make sure it is mounted read-write. After installation, it should mount readonly inside the initrd.&lt;br /&gt;
&lt;br /&gt;
Sometimes there can be problems using the mount command, and then you can try it with the -i option:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 mount -i zfs-root&lt;br /&gt;
 mount -i zfs-root -t zfs /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
but, you should not have to use -i. When using -i makes it work, it performs an &amp;quot;internal-only&amp;quot; mount and does not use any mount.&amp;lt;fstype&amp;gt; helper scripts that might be on the system. You can use &amp;lt;code&amp;gt;mountpoint=legacy&amp;quot;&amp;lt;/code&amp;gt; to avoid this small problem if you are preferring to use the regular mount and umount commands on your zfs-root.&lt;br /&gt;
&lt;br /&gt;
Setup the /boot device:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkfs.ext4 /dev/sda1&lt;br /&gt;
mkdir /mnt/boot&lt;br /&gt;
mount /dev/sda1 /mnt/boot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We have both root and boot mounted where the slackware installer expects them. Unmount the dvd so setup can find it normally:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
umount /dev/sr0&lt;br /&gt;
setup&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the setup, skip straight to TARGET selection for the root device, but the setup doesn't see or understand the zfs-root, so it is not listed. This does not matter because we have mounted it already. Just skip down to a slot that say to continue, and continue on with setup. Because TARGET is skipped, you may not see the ADDITIONAL prompt (or if so, skip it too) where normally you give /dev/sda1 and have it mounted as /boot. This is also okay because we have mounted /mnt/boot already.&lt;br /&gt;
Because we did not give TARGET the root device or say what device /boot is on, the lilo installation will fail, or you can skip it. Otherwise, this installation process is normal.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Finish installation and exit setup, but do NOT reboot!&lt;br /&gt;
# There is still a lot to do before rebooting.&lt;br /&gt;
umount /dev/sr0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point, it is assumed that the setup has completed installing into /mnt. Congrats! You've installed slackware into a ZFS root!&lt;br /&gt;
&lt;br /&gt;
The next steps are to prepare to use &amp;quot;chroot /mnt&amp;quot; and finish up the configuration on the installed root system and then be able to reboot onto the completed installation. Before doing chroot, copy some files from the setup environment into /mnt.&lt;br /&gt;
&lt;br /&gt;
Copy the current installer /etc/fstab for later use inside the initrd. This fstab is what is proper inside the initrd, except remove option &amp;quot;rw&amp;quot; (if not done already).&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/fstab /mnt/etc/fstab.initrd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The fstab.initrd will look like:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 proc /proc proc defaults 0 0&lt;br /&gt;
 zfs-root /mnt zfs defaults,atime,dev,exec,suid,xattr,nomand,zfsutil 0 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the initrd, we want zfs-root to mount to /mnt.&lt;br /&gt;
&lt;br /&gt;
Create /mnt/etc/fstab:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cat /etc/mtab &amp;gt;&amp;gt; /mnt/etc/fstab&lt;br /&gt;
vi /mnt/etc/fstab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using vi started above, edit /mnt/etc/fstab and make it have lines such as:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 zfs-root / zfs defaults,atime,dev,exec,suid,xattr,nomand,zfsutil 0 0&lt;br /&gt;
 /dev/sda1 /boot ext4 defaults 0 2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
These two lines in &amp;lt;code&amp;gt;/mnt/etc/fstab&amp;lt;/code&amp;gt; are how the mounts should be looking when root is booted. Although the fstab option for fs_passno is 0 and indicates that root (/) should not be fsck, this fs_passno option in fstab is ignored during system startup for / in rc.S because rc.S explicity runs &amp;quot;fsck /&amp;quot; which does not look at options inside fstab. Fsck doesn't work on a zfs fs, and we will deal with that problem in a moment (see below).&lt;br /&gt;
&lt;br /&gt;
Mount some special mounts before chroot:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount -t devtmpfs none /mnt/dev&lt;br /&gt;
mount -t proc none /mnt/proc&lt;br /&gt;
mount -t sysfs none /mnt/sys&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Make sure /boot is mounted:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount /dev/sda1 /mnt/boot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you had mounted a 9p fs share to access spl and zfs packages, then unmount that now:&lt;br /&gt;
umount /packages&lt;br /&gt;
&lt;br /&gt;
Ready, now:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chroot /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point, you should be on the installed system, and now try to configure mkinitrd and lilo. First, switch to use the generic kernel:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /boot&lt;br /&gt;
rm System.map config vmlinuz&lt;br /&gt;
ln -s System.map-gen* System.map&lt;br /&gt;
ln -s config-gen* config&lt;br /&gt;
ln -s vmlinuz-gen* vmlinuz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We installed spl and zfs inside the live ramfs install-dvd environment, but not yet have we installed them into the root system:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount /dev/sr0 /mnt/cdrom&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /mnt/cdrom/addon/spl-*.txz&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /mnt/cdrom/addon/zfs-*.txz&lt;br /&gt;
depmod&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If instead, you used a 9p share to access the spl and zfs packages, then repeat that procedure here to install them onto the root system.&lt;br /&gt;
&lt;br /&gt;
Setup lilo: edit /etc/lilo.conf so it is like:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  lba32&lt;br /&gt;
  append = &amp;quot; vt.default_utf8=1&amp;quot;&lt;br /&gt;
  boot = /dev/sda&lt;br /&gt;
  message = /boot/boot_message.txt&lt;br /&gt;
  prompt&lt;br /&gt;
  timeout = 1200&lt;br /&gt;
  change-rules&lt;br /&gt;
   reset&lt;br /&gt;
  vga = normal&lt;br /&gt;
  image = /boot/vmlinuz&lt;br /&gt;
   label = vmlinuz&lt;br /&gt;
   initrd = /boot/initrd.gz&lt;br /&gt;
   root = /dev/ram0&lt;br /&gt;
   read-write&lt;br /&gt;
# alternatively, the root and read-write lines&lt;br /&gt;
# can be this one line of kernel parameters:&lt;br /&gt;
#  addappend = &amp;quot; root=/dev/ram0 rw &amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A note about initrd: The /boot/initrd.gz is a gzipped cpio archive containing a minimal BusyBox-based slackware root system that is sourced from /boot/initrd-tree. The commands &amp;quot;mkinitrd&amp;quot; and &amp;quot;mkinitrd -F&amp;quot; generates /boot/initrd-tree and /boot/initrd.gz. When using a initrd, the initial root device is normally set to root=/dev/ram0 (a ramfs block device) and allowed read-write. The kernel refers to devices in terms of &amp;quot;major&amp;quot; and &amp;quot;minor&amp;quot; numbers, and the ram0 device is assigned the block device major 1 and minor 0. This ram0 major/minor is written in hexadecimal as 0x0100 (256 in decimal). This hexademical number makes an appearance in /boot/initrd-tree/int where it runs: &amp;quot;echo 0x0100 &amp;gt; /proc/sys/kernel/real-root-dev&amp;quot;. Echoing a device code to real-root-dev is part of a deprecated initrd mechanism, but is probably harmless to leave alone as slackware has it unless you know otherwise. More information about how initrd works can be found in:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/usr/src/linux/Documentation/devices.txt (info about major:minor device numbers)&lt;br /&gt;
/usr/src/linux/Documentation/initrd.txt  (mostly obsolete info on old initrd)&lt;br /&gt;
/usr/src/linux/Documentation/filesystems/ramfs-rootfs-initramfs.txt (current info on new initrd, called initramfs)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Advanced note about initrd: Slackware's mkinitrd package does not use the &amp;quot;pivot_root&amp;quot; command as documented in &amp;quot;initrd.txt&amp;quot;, but instead uses &amp;quot;switch_root&amp;quot; provided by a project called BusyBox. The switch_root command changes the effective root filesystem from the initrd (unpacked in rootfs at /) to the new root filesystem (zfs-root mounted at /mnt); it overmounts rootfs / with zfs-root /mnt. The switch_root works as follows: delete everything in rootfs / (one filesystem only) that held initrd to free up ram memory, then use mount, chroot, and chdir to make the effective root change. In concept (as a shell script), the command &amp;quot;exec switch_root /mnt $INIT $RUNLEVEL&amp;quot; is performed as follows:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 find / -xdev | xargs rm -rf&lt;br /&gt;
 cd &amp;quot;$1&amp;quot;&lt;br /&gt;
 shift&lt;br /&gt;
 mount --move . /&lt;br /&gt;
 exec chroot . &amp;quot;$@&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Here, typically INIT=/sbin/init RUNLEVEL=3. The 'exec' causes switch_root to take the place of the parent process having PID=1. In system calls, the switch_root looks similar to this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chdir(&amp;quot;/mnt&amp;quot;);&lt;br /&gt;
/* &amp;lt;insert code to unlink/rmdir all initrd files/directories&lt;br /&gt;
 *  installed in rootfs / without crossing filesystems &amp;gt; */&lt;br /&gt;
mount(&amp;quot;.&amp;quot;, &amp;quot;/&amp;quot;, NULL, MS_MOVE, NULL);&lt;br /&gt;
chroot(&amp;quot;.&amp;quot;);&lt;br /&gt;
chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
execl(&amp;quot;/sbin/init&amp;quot;, &amp;quot;3&amp;quot;, (char*) NULL );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The kernel's rootfs / that contained initrd is never actually unmounted (it can't be) because it is built into the kernel and always exists as at least a tiny ramfs or tmpfs, so you can continue to see it in /proc/mounts. When you give lilo root=/dev/ram0 (a ramfs device), the kernel will actually use the internal rootfs, which is an instance of a tmpfs (if your kernel config includes tmpfs) or ramfs. The rootfs that is a tmpfs can by default use up to half of system ram. If rootfs is a ramfs, it can use up to almost all of system ram until the system panics. Typically, tmpfs is built into the kernel, and so depending on how much ram your computer has, the initrd-tree can probably be up to about half that size.&lt;br /&gt;
&lt;br /&gt;
Quite a lot of notes... now to continue on...&lt;br /&gt;
&lt;br /&gt;
Setup mkinitrd:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/mkinitrd.conf.sample /etc/mkinitrd.conf&lt;br /&gt;
vi /etc/mkinitrd.conf&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Edit it to look like this (other defaults should be ok):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 MODULE_LIST=&amp;quot;sym53c8xx:ext4:e1000:zfs:9p:9pnet_virtio&amp;quot;&lt;br /&gt;
 ROOTDEV=&amp;quot;zfs-root&amp;quot;&lt;br /&gt;
 ROOTFS=&amp;quot;zfs&amp;quot;&lt;br /&gt;
#Module sym53c8xx is the driver for qemu's if=scsi drive device.&lt;br /&gt;
#Module ext4 for /boot.&lt;br /&gt;
#Module e1000 for eth0 net device.&lt;br /&gt;
#Module zfs for ZFSonLinux.&lt;br /&gt;
#Modules 9p and 9pnet_virtio for mounting qemu -virtfs mount_tag.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These 9p modules could be useful from the rescue command line inside the initrd to get needed files that are on the host.&lt;br /&gt;
&lt;br /&gt;
All dependent modules will also be included automatically into /boot/initrd-tree, which is packaged as /boot/initrd.gz. For example, to see the dependent modules of zfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
modprobe --show-depends zfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All listed modules will also be in the initrd. Now, make a /boot/initrd-tree that we can begin to look at and edit:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkinitrd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create an empty /etc/mtab or else zpool import fails (zfs expects /etc/mtab to exists already, it won't make it):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
touch /boot/initrd-tree/etc/mtab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Copy in the fstab.initrd that was made earlier while on the installer. This provides all the mount options for a simple &amp;quot;mount zfs-root&amp;quot; onto /mnt:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/fstab.initrd /boot/initrd-tree/etc/fstab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More package installing! This time into an alternate root, the root of the initrd, /boot/initrd-tree. This is how you can put whatever packages you like into your initrd. These installations work independent of your normal installations. You can install, upgrade, and remove packages using an altroot:&lt;br /&gt;
&lt;br /&gt;
If spl and zfs are on your customized dvd:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/addon/spl-*.txz&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/addon/zfs-*.txz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Otherwise, repeat same procedure but you mount your 9p mount_tag and get them installed.&lt;br /&gt;
&lt;br /&gt;
More regular packages from the dvd:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/kmod-*.txz&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/coreutils-*.txz&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/gptfdisk-*.txz&lt;br /&gt;
&lt;br /&gt;
# A bash script is in /boot/initrd-tree/lib/udev/, so we need it or udev rules have problems:&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/bash-*.txz&lt;br /&gt;
# Bash needs this:&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/l/libtermcap-*.txz&lt;br /&gt;
&lt;br /&gt;
# Install net-tools to ensure that /etc/HOSTNAME, /etc/hosts, and potentially, /etc/hostid are handled proper.&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/n/net-tools-*.txz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When ZFS has to import a zpool while the initrd is running (this can be avoided by not exporting and keeping /etc/zfs/zpool.cache inside the initrd), ZFS will refuse to import a pool if it thinks that the pool may be in use by another system. ZFS was designed for network attached storage (NAS) where multiple hosts might have access to the same disks but ZFS cannot support two hosts importing and using a ZFS pool at the same time (that requires a &amp;quot;cluster&amp;quot; fs). ZFS checks a value called &amp;quot;hostid&amp;quot; to determine this kind of conflict, and it can be a tricky issue with an initrd boot process. The value of hostid is returned by the gethostid() function or the hostid command. This function will return the hostid from /etc/hostid if that file exists and has a valid id in it, or else if the file doesn't exist it obtains a hostid number based on the hostname and ip address assigned to hostname found in /etc/hosts or in DNS. If the hostid trying to import a pool is not the same as the hostid that imported it last time, ZFS will not import the pool unless &amp;quot;zpool import -f zfs-root&amp;quot; is used to force the import. This force option is not recommended to use, so it is best to configure your initrd with matching /etc/HOSTNAME and /etc/hosts as on the root installation and ensure what your system looks like on the initrd matches the booted root system. The hostid can also be passed to the SPL module with the module parameter &amp;lt;code&amp;gt;spl.spl_hostid=0xHHHHHHHH&amp;lt;/code&amp;gt; where the Hs are a hexadecimal hostid value and this overrides any /etc/hostid or hostname/IP-based hostid value.&lt;br /&gt;
&lt;br /&gt;
Edit /boot/initrd-tree/init (this is the main system startup script on the initrd, responsible for configuring your block devices, mounting root at /mnt, and booting root):&lt;br /&gt;
&lt;br /&gt;
Inside init, right near the top of the file after the PATH= line, add this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/bin/hostname -F /etc/HOSTNAME&lt;br /&gt;
/bin/hostname $( /bin/hostname -s )&lt;br /&gt;
#/sbin/chhostid 13371400&lt;br /&gt;
# you can make your hostid whatever, but this didn't work right with ZFS, so it is commented out&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This sets the name reported by the hostname command (the default is &amp;quot;darkstar&amp;quot;) to be what is contained in /etc/HOSTNAME. The hostname is modified in the next line to be the short hostname. These lines will help ZFS to properly identify your host when importing pools.&lt;br /&gt;
&lt;br /&gt;
Inside init, right after it runs &amp;quot;mdadm&amp;quot; commands as used for raid setup, we like it to setup ZFS, so add:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/sbin/zpool import zfs-root&lt;br /&gt;
/sbin/zfs set readonly=on zfs-root&lt;br /&gt;
mount zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
We want to make sure the default is to mount readonly, then it mounts using defaults from /etc/fstab inside the initrd.&lt;br /&gt;
&lt;br /&gt;
Inside init, close to the bottom, where it &amp;quot;Switch to real root partition&amp;quot;, comment out 1 line that normally does the mount:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# mount -o ro -t $ROOTFS $ROOTDEV /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
We have already mounted zfs-root, and we don't want to use any mount options because we should be using a properly set /etc/fstab inside the initrd for the zfs-root mount options onto /mnt.&lt;br /&gt;
&lt;br /&gt;
During a normal startup we want a readonly mount.&lt;br /&gt;
&lt;br /&gt;
Note: we are going to setup with using &amp;quot;zpool import&amp;quot; and &amp;quot;zpool export&amp;quot; commands at startup and shutdown. But later, you can experiment having /etc/zfs/zpool.cache stored in the initrd and commenting out the zpool import/export lines. Using zpool import/export is safer than using a zpool.cache, so we try to setup that way preferably.&lt;br /&gt;
&lt;br /&gt;
As mentioned, the zpool import command may sometimes fail, and give the message: &amp;quot;pool may be in use from another system&amp;quot;. This is nothing serious in this test situation. When this happens, zfs-root will not get mounted to /mnt and the init script will detect this and drop you into a rescue command line where you may manually do:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool import -f zfs-root&lt;br /&gt;
mount zfs-root&lt;br /&gt;
exit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This will force import, overriding the conflict that zfs thinks may be happening. Next is mount. After this, exit to let the init script continue on to boot the system normally.&lt;br /&gt;
&lt;br /&gt;
To avoid this problem we copy some files in (assuming you first edit /etc/HOSTNAME to hold the hostname you like to see on your command prompts, and edited /etc/hosts to have hostname on your loopback or other local ip address):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/HOSTNAME /etc/hosts /boot/initrd-tree/etc&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The value reported by the hostid command is what ZFS sees as your hostid (the SPL module actually tries to run the hostid command to get this value or it uses the spl.spl_hostid value that is given to it). In this setup so far, the value is based on the ip assigned to your hostname. If your hostname is on the line in /etc/hosts for ip address 192.168.13.37, then your hostid will be hex numbers C0.A8.0D.25 rearranged as A8C0250D (pairs of bytes are swapped). This is a ip-based hostid value, a 32bit hexadecimal number. The hostid has to be the same each boot or import will need a -f option to force it. Simply setting the hostid using the function sethostid() which writes a /etc/hostid file doesn't seem to agree with ZFS and you'd have to force the import, so this setup now assumes that you do not have or have deleted /etc/hostid.&lt;br /&gt;
&lt;br /&gt;
You can sometimes see what has been happening to a zpool by using the command &amp;quot;zpool history -li zfs-root&amp;quot; to see a log of commands.&lt;br /&gt;
&lt;br /&gt;
Once again, you can do away with the import and export commands by trying to have /etc/zfs/zpool.cache inside your initrd. To create zpool.cache, while on the installer or in the rescue shell of the initrd (at lilo &amp;quot;boot: vmlinuz rescue&amp;quot;):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on installer or initrd rescue shell)&lt;br /&gt;
zpool import zfs-root&lt;br /&gt;
zfs set readonly=off zfs-root&lt;br /&gt;
mount zfs-root&lt;br /&gt;
cp /etc/zfs/zpool.cache /mnt/etc/zfs/zpool.cache-initrd&lt;br /&gt;
cp /mnt/etc/zfs/zpool.cache-initrd /mnt/boot/initrd-tree/etc/zfs/zpool.cache&lt;br /&gt;
umount /mnt&lt;br /&gt;
zfs set readonly=on zfs-root&lt;br /&gt;
#mount zfs-root&lt;br /&gt;
#exit (to continue boot process onto rootfs mounted at /mnt)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Words of caution, again: Doing this zpool.cache approach is not necessary, and some talk suggests this is deprecated or discouraged. Although /etc/hostid setup fails to import without -f option, ip-based (hosts|dns) hostid works on booting and import works without -f option and may be the more proper way to do shutdown and startup rather than using a cache file which could become invalid and cause a problem that is difficult to understand. The contents and exact function of the cache file are not well understood by many people. As will be spammed all over this wiki, using zpool.cache is not recommended if you can avoid it because it is potentially unsafe for your pool.&lt;br /&gt;
&lt;br /&gt;
Save /boot/initrd-tree/init and quit vi.&lt;br /&gt;
&lt;br /&gt;
Now, edit /etc/rc.d/rc.S and rc.6 to understand how to remount rw or ro as readonly property changes:&lt;br /&gt;
&lt;br /&gt;
In /etc/rc.d/rc.S:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# comment out the line&lt;br /&gt;
#    /sbin/mount -w -v -n -o remount /&lt;br /&gt;
#add the line&lt;br /&gt;
     /sbin/zfs set readonly=off zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If you are using &amp;lt;code&amp;gt;mountpoint=legacy&amp;lt;/code&amp;gt; for zfs-root, you do not need to make the above change.&lt;br /&gt;
&lt;br /&gt;
In /etc/rc.d/rc.6:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# before: echo &amp;quot;Unmounting local file systems.&amp;quot;&lt;br /&gt;
# add lines:&lt;br /&gt;
  rm -f /etc/zfs/zpool.cache&lt;br /&gt;
  echo &amp;quot;Removed /etc/zfs/zpool.cache&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Remove /etc/zfs/zpool.cache on shutdown. This is recommended because if it is present when you import a pool, it might use this old cache to determine the device filenames in the pool, which may have changed filenames since the last boot, especially the non-persistent /dev/sd* device filenames. It is safest to avoid any usage of the zpool.cache file at boot in initramfs, zfs module load, and at zpool import of other pools.&lt;br /&gt;
&lt;br /&gt;
In /etc/rc.d/rc.6:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# comment out the line:&lt;br /&gt;
#    /bin/mount -v -n -o remount,ro /&lt;br /&gt;
# add the line:&lt;br /&gt;
     /sbin/zfs set readonly=on zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If you are using &amp;lt;code&amp;gt;mountpoint=legacy&amp;lt;/code&amp;gt; for zfs-root, you do not need to make the above change.&lt;br /&gt;
&lt;br /&gt;
In /etc/rc.d/rc.6, near the bottom just before poweroff|reboot, add the following block of lines:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
########################&lt;br /&gt;
# Try to export zfs-root&lt;br /&gt;
/sbin/zpool export zfs-root&lt;br /&gt;
if [ $? -gt 0 ] ; then&lt;br /&gt;
 echo &amp;quot;ZFS export failed.&amp;quot;&lt;br /&gt;
 echo &amp;quot;Notice: if root fs is busy, then this is normal fail.&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;ZFS export successful.&amp;quot;&lt;br /&gt;
 echo &amp;quot;Warning: successful export is abnormal for root fs.&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
/bin/sleep 5&lt;br /&gt;
########################&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This attempts to export even though it cannot return success for the root pool. The attempt is still recorded in the zpool history, and even though it fails the pool may actually be marked as exported (not sure).&lt;br /&gt;
&lt;br /&gt;
For ZFS, you cannot run fsck on it. It doesn't support that kind of filesystem check. The rc.S script will complain a lot in many places about not being able to run fsck on the zfs-root. To disable all attempts to run fsck, we can simply create a file that acts as a flag in /etc/rc.d/rc.S to tell it to skip fsck:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
touch /etc/fastboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This fastboot file is normally a run-once temporary file, and it is deleted near the bottom inside rc.S. Edit rc.S and stop it from deleting /etc/fastboot. We would like it to always skip all fsck. Edit /etc/rc.d/rc.S, and find the &amp;quot;rm&amp;quot; of fastboot, and do not have it removed!&lt;br /&gt;
&lt;br /&gt;
An alternative to using /etc/fastboot is to make the file &amp;lt;code&amp;gt;/sbin/fsck.zfs&amp;lt;/code&amp;gt; that always just &amp;quot;does nothing successfully&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
exec /bin/true&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Or, it can be:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Or, just do:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ln -s /bin/true /sbin/fsck.zfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This fsck helper has the advantage that you do not need to alter &amp;lt;code&amp;gt;rc.S&amp;lt;/code&amp;gt; as much, or at all if you use zfs property &amp;lt;code&amp;gt;mountpoint=legacy&amp;lt;/code&amp;gt; and the regular &amp;lt;code&amp;gt;mount&amp;lt;/code&amp;gt; command on your zfs-root. With these ideas, no slackware /etc/rc.d/* files really need editing, but it is up to you how you want to experiment. I prefer to use &amp;lt;code&amp;gt;mountpoint=legacy&amp;lt;/code&amp;gt; and edit just the initrd init script as above, and edit rc.6 to remove /etc/zfs/zpool.cache and try to export.&lt;br /&gt;
&lt;br /&gt;
We are getting close, and have finished all editing, so make /boot/initrd.gz and install lilo:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkinitrd -F&lt;br /&gt;
lilo&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We finished! All that's left to do is clean up.&lt;br /&gt;
&lt;br /&gt;
Exit the chroot.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
exit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Try to umount everything:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
umount /mnt/proc&lt;br /&gt;
umount /mnt/sys&lt;br /&gt;
umount /mnt/dev&lt;br /&gt;
umount /mnt/boot&lt;br /&gt;
umount /mnt/mnt/cdrom&lt;br /&gt;
umount /mnt/root/packages&lt;br /&gt;
umount /mnt&lt;br /&gt;
zpool export zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note, that export stops a pool and frees devices, while import binds devices and starts a pool. It is somewhat like mdadm -A -s and mdadm -S -s, while /etc/zfs/zpool.cache might be somewhat like mdadm -E -s &amp;gt; /etc/mdadm.conf.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Remove the DVD or change boot order&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When you reboot, if all is good, you are booting properly onto a slackware installed on a ZFS root! Congrats!&lt;br /&gt;
&lt;br /&gt;
If this seems to go badly, and this might happen if the import fails as explained some before, then you will be on the initrd's rescue command line just before the part in init where it wants to mount zfs-root and switch_root to boot up. In this case, you typically got commands like these to do:&lt;br /&gt;
&lt;br /&gt;
If you get dumped to rescue because zpool import will not work and requires -f (force), then:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 zpool import -f zfs-root&lt;br /&gt;
 zpool export    zfs-root&lt;br /&gt;
 zpool import    zfs-root&lt;br /&gt;
 mount zfs-root&lt;br /&gt;
 exit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This can happen if hostname, hostid, or uname changes.&lt;br /&gt;
&lt;br /&gt;
If you get into a jam and need to boot into the initrd and skip zpool import etc, use the lilo prompt (or, boot the install-dvd):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
boot: vmlinuz rescue&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
In the rescue mode of the initrd, after you have mounted your zfs-root as readonly=on to /mnt, then &amp;quot;exit&amp;quot; to continue booting.&lt;br /&gt;
&lt;br /&gt;
An alternative rescue shell on the initrd can be started as follows:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
boot: vmlinuz rdinit=/bin/sh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This puts you into a sh shell inside the initrd, and the normal /init script is not run at all. In this shell, you can fix problems and then attempt to start the system normally as follows:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
exec /init&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This runs the normal rdinit program, &amp;quot;execing&amp;quot; it so that it takes process ID (PID) 1 of your sh shell, which is the required PID for the init program.&lt;br /&gt;
&lt;br /&gt;
In other emergency command lines, you might need to run the lines at the end of init starting from: &amp;lt;code&amp;gt;udevadm info --cleanup-db; udevadm control --exit&amp;lt;/code&amp;gt;&lt;br /&gt;
If you don't run those udevadm commands, two runs of udevd could fight each other and it is slow; you have to wait 2 minutes twice for timeouts (4 minutes).&lt;br /&gt;
The last line in init is run like: &amp;lt;code&amp;gt;exec switch_root /mnt /sbin/init 1&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Warning: the switch_root command is kind of dangerous, so read the manual page about it. From what I can tell, everything except the new root &amp;quot;/mnt&amp;quot; is deleted, so you are giving a command that says what NOT to delete! Make sure nothing got mounted outside of &amp;quot;/mnt&amp;quot; before you run it. However, the deletes should not cross filesystems, but only delete the contents of initramfs.&lt;br /&gt;
&lt;br /&gt;
Also, in rescue command line or anytime you have finished making changes and are about to reboot in some abnormal situation, first run:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set readonly=on zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If you are using &amp;lt;code&amp;gt;mountpoint=legacy&amp;lt;/code&amp;gt; for zfs-root, then you may want to use &amp;lt;code&amp;gt;readonly=off&amp;lt;/code&amp;gt; and use the options to the &amp;lt;code&amp;gt;mount&amp;lt;/code&amp;gt; command to control ro|rw mounting. With &amp;lt;code&amp;gt;mountpoint=legacy&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;readonly=on&amp;lt;/code&amp;gt; used together, there can be a contradiction between how the kernel actually mounts zfs-root (ro according to the readonly property) and how the userspace mount command and /etc/mtab attempt to mount the zfs-root (if you give &amp;lt;code&amp;gt;-o rw&amp;lt;/code&amp;gt;). The kernel might actually mount ro, even when you have told the mount command to mount rw. The /etc/mtab can erroneously report rw, while the kernel's /proc/mounts file reports the actual mount as ro. Again, the two methods of mounting a zfs fs, either &amp;quot;legacy&amp;quot; &amp;lt;code&amp;gt;mount&amp;lt;/code&amp;gt; command or by using the &amp;lt;code&amp;gt;zfs set mountpoint&amp;lt;/code&amp;gt; can conflict with each other on the mode of mounting. If you create a zfs filesystem under zfs-root, like &amp;lt;code&amp;gt;zfs create &amp;quot;zfs-root/movies&amp;quot;&amp;lt;/code&amp;gt; and then try to mount it, it may have inherited &amp;lt;code&amp;gt;mountpoint=legacy&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;readonly=on&amp;lt;/code&amp;gt; from zfs-root, and it may mount ro even if you use the rw mount option: in this case, you have to do another command &amp;lt;code&amp;gt;mount -o remount,rw &amp;quot;zfs-root/movies&amp;quot;&amp;lt;/code&amp;gt; to make it actually switch to rw (kind of weird!).&lt;br /&gt;
&lt;br /&gt;
A bug in unpatched grep 2.13 build 1, found slackware 14.0rc1, causes problems when processing files stored on ZFS but rarely shows problems on other filesystems; the bug does not handle sparse files on zfs and btrfs correctly and results in chaos with slackpkg, compiling kernel modules, and possibly many other things. You must downgrade grep to 2.12 or use the patched grep 2.13 build 2 in slackware 14.0rc2 or later.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
Upgrading:&lt;br /&gt;
&lt;br /&gt;
From time to time you will want to upgrade the kernel to the new kernel in slackware64-current or in patches/. This will also necessitate a rebuild and reinstall or upgrade of spl and zfs. Below is an example of when both kernel and spl/zfs are being upgraded, to give an idea of the process:&lt;br /&gt;
&lt;br /&gt;
Using slackpkg, that is configured to use your local slackware mirror is a good option but you can also configure it to use a remote mirror.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slackpkg upgrade-all&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Assume slackpkg just upgraded your kernel, kernel-modules, kernel-headers, and kernel-source.&lt;br /&gt;
&lt;br /&gt;
Note: the first time you try to run on kernel-generic, setup kernel-huge in lilo as 2nd choice. Huge has all the hard drive controllers builtin, but generic has them all as modules. For example, run &amp;quot;modinfo mptsas&amp;quot; to see module options (maybe you have a LSISAS1068) for your hard drive controller. Add file /etc/modprobe.d/mptsas.conf to set options you want with a line: options mptsas ... Do this for all the device driver modules for your hardware. Do this setup while you are on the huge kernel, then setup to reboot to generic. Include all these modules you need into mkinitrd.conf MODULES_LIST. Check that /boot/initrd-tree/etc/modprobe.d/ has a copy of your customized module conf files because it is on the initrd where the modules will load and use the conf files. mkinitrd probably copies all /etc/modprobe.d/* files into the initrd-tree, but check it. Pay attention to /etc/modprobe.d/README and /lib/modprobe.d/* /lib/modprobe.d/* maybe not copied to initrd-tree but you might want to copy some of it into your initrd-tree yourself to use them.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Check that upgraded kernel-source is symlinked to /usr/src/linux (zfs build looks here). SPL/ZFS modules will install to the kernel version in /lib/modules/&amp;lt;/usr/src/linux kernel version&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /usr/local/src&lt;br /&gt;
tar xvzf ~/spl-*.tar.gz&lt;br /&gt;
tar xvzf ~/zfs-*.tar.gz&lt;br /&gt;
&lt;br /&gt;
###### upgrade spl 1st&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-*&lt;br /&gt;
./configure --prefix=/ --libexecdir=/usr/libexec --libdir=/lib64 --includedir=/usr/include --datarootdir=/usr/share&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=/usr/local/src/install&lt;br /&gt;
cd ../install&lt;br /&gt;
makepkg ../spl-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
upgradepkg spl-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
depmod &amp;lt;new kernel version&amp;gt;     (e.g. depmod 3.2.28, if .28 is new kernel upgrade; you currently run on old, maybe .27)&lt;br /&gt;
# this builds the module dependencies in /lib/modules/&amp;lt;new kernel version&amp;gt;&lt;br /&gt;
###### upgrade zfs 2nd&lt;br /&gt;
mkdir install&lt;br /&gt;
cd zfs-*&lt;br /&gt;
./configure --prefix=/ --libexecdir=/usr/libexec --libdir=/lib64 --includedir=/usr/include --datarootdir=/usr/share&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=/usr/local/src/install&lt;br /&gt;
cd ../install&lt;br /&gt;
makepkg ../zfs-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
upgradepkg zfs-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
depmod 3.2.28&lt;br /&gt;
####### upgrade spl/zfs inside altroot /boot/initrd-tree&lt;br /&gt;
ROOT=/boot/initrd-tree upgradepkg spl-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
ROOT=/boot/initrd-tree upgradepkg zfs-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
# note: ROOT is an environment variable, not a command line option to upgradepkg!&lt;br /&gt;
# note: do not worry about depmod inside initrd-tree, mkinitrd -F actually installs the modules&lt;br /&gt;
# note: this upgrade here is really to just upgrade the command line tools zpool, zfs etc&lt;br /&gt;
####### rebuild /boot/initrd.gz and reinstall lilo&lt;br /&gt;
vi /etc/mkinitrd.conf&lt;br /&gt;
# temporarily set KERNEL_VERSION to new version, but you are still running on old version&lt;br /&gt;
mkinitrd -F&lt;br /&gt;
lilo&lt;br /&gt;
vi /etc/mkinitrd.conf&lt;br /&gt;
# you can set KERNEL_VERSION back to $(uname -r) now&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After reboot you can remove any old /lib/modules/&amp;lt;old kernel version&amp;gt; directory.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
More about /etc/hostid. If you want to experiment changing your /etc/hostid file and seeing if you can use it and make zpool import work normally, here is a tool that might be helpful:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/* software product name: foobarz-chhostid.c&lt;br /&gt;
 * suggested binary name: chhostid&lt;br /&gt;
 * license              : BSD&lt;br /&gt;
 * license text:&lt;br /&gt;
Copyright (c) 2012, foobarz&lt;br /&gt;
All rights reserved.&lt;br /&gt;
&lt;br /&gt;
Redistribution and use in source and binary forms, with or without&lt;br /&gt;
modification, are permitted provided that the following conditions are met:&lt;br /&gt;
    * Redistributions of source code must retain the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer.&lt;br /&gt;
    * Redistributions in binary form must reproduce the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer in the&lt;br /&gt;
      documentation and/or other materials provided with the distribution.&lt;br /&gt;
    * Neither the name of the &amp;lt;organization&amp;gt; nor the&lt;br /&gt;
      names of its contributors may be used to endorse or promote products&lt;br /&gt;
      derived from this software without specific prior written permission.&lt;br /&gt;
&lt;br /&gt;
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &amp;quot;AS IS&amp;quot; AND&lt;br /&gt;
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED&lt;br /&gt;
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE&lt;br /&gt;
DISCLAIMED. IN NO EVENT SHALL &amp;lt;COPYRIGHT HOLDER&amp;gt; BE LIABLE FOR ANY&lt;br /&gt;
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES&lt;br /&gt;
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;&lt;br /&gt;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND&lt;br /&gt;
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT&lt;br /&gt;
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS&lt;br /&gt;
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#define FOOBARZ_CHHOSTID_VERSION &amp;quot;1.0.5&amp;quot;&lt;br /&gt;
#include &amp;lt;sys/socket.h&amp;gt;&lt;br /&gt;
#include &amp;lt;netinet/in.h&amp;gt;&lt;br /&gt;
#include &amp;lt;arpa/inet.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;endian.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sysexits.h&amp;gt;&lt;br /&gt;
/* note: if include stdlib then sethostid fails even with _BSD_SOURCE defined */&lt;br /&gt;
&lt;br /&gt;
long swapbytes(long abcd) {&lt;br /&gt;
  long badc;&lt;br /&gt;
  unsigned char addr_a;&lt;br /&gt;
  unsigned char addr_b;&lt;br /&gt;
  unsigned char addr_c;&lt;br /&gt;
  unsigned char addr_d;&lt;br /&gt;
  addr_a = (unsigned char) (abcd &amp;gt;&amp;gt; 24);&lt;br /&gt;
  addr_b = (unsigned char) (abcd &amp;gt;&amp;gt; 16);&lt;br /&gt;
  addr_c = (unsigned char) (abcd &amp;gt;&amp;gt;  8);&lt;br /&gt;
  addr_d = (unsigned char) (abcd);&lt;br /&gt;
  return badc = ( (addr_b &amp;lt;&amp;lt; 24) | (addr_a &amp;lt;&amp;lt; 16) | (addr_d &amp;lt;&amp;lt; 8) | addr_c );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[])&lt;br /&gt;
{&lt;br /&gt;
 long newhostid;&lt;br /&gt;
 struct in_addr addr;&lt;br /&gt;
 char* invalidchar;&lt;br /&gt;
&lt;br /&gt;
 /*********** check command line */&lt;br /&gt;
 if(!( ((argc==3) &amp;amp;&amp;amp; ( (strcmp(argv[1],&amp;quot;-h&amp;quot;)==0) ||&lt;br /&gt;
                       (strcmp(argv[1],&amp;quot;-i&amp;quot;)==0) ||&lt;br /&gt;
                       (strcmp(argv[1],&amp;quot;-l&amp;quot;)==0) )) ||&lt;br /&gt;
       ((argc==2) &amp;amp;&amp;amp; ( (strcmp(argv[1],&amp;quot;-s&amp;quot;)==0) ))&lt;br /&gt;
     )&lt;br /&gt;
   ) {&lt;br /&gt;
                 /*01234567890123456789012345678901234567890123456789012345678901234567890123456789*/&lt;br /&gt;
  fprintf(stderr, &amp;quot;foobarz-chhostid, version %s. License: BSD.\n&amp;quot;, FOOBARZ_CHHOSTID_VERSION);&lt;br /&gt;
  fprintf(stderr, &amp;quot;foobarz-chhostid, (c) 2012, foobarz; all rights reserved.\n&amp;quot;);&lt;br /&gt;
  fprintf(stderr, &amp;quot;descr: %s change system hostid (in /etc/hostid).\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -h &amp;lt;new hostid&amp;gt;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        Change system hostid to &amp;lt;new hostid&amp;gt;;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        &amp;lt;new hostid&amp;gt; must be 32bit 8-digit hex number xxxxxxxx, each x in 0-f|F.\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        The ip corresponding to &amp;lt;new hostid&amp;gt; is also listed for reference only.\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -i &amp;lt;dotted ip address&amp;gt;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        Change system hostid to hostid corresponding to &amp;lt;dotted ip address&amp;gt;.\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -l &amp;lt;dotted ip address&amp;gt;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        List hostid corresponding to &amp;lt;dotted ip address&amp;gt;;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        no change to system hostid.\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -s\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        List current system hostid and corresponding ip address;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        no change to system hostid.\n&amp;quot;, argv[0]);&lt;br /&gt;
  return EX_USAGE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -h &amp;lt;hostid&amp;gt; */&lt;br /&gt;
 if( strcmp(argv[1],&amp;quot;-h&amp;quot;) == 0 ) {&lt;br /&gt;
  if(strlen(argv[2]) != 8) { fprintf(stderr, &amp;quot;new hostid must be 8-digit hex number xxxxxxxx, each x in 0-f|F\n&amp;quot;); return EX_USAGE; }&lt;br /&gt;
&lt;br /&gt;
  newhostid = strtol(argv[2],&amp;amp;invalidchar,16);&lt;br /&gt;
  if( newhostid==LONG_MIN ) { perror(&amp;quot;strtol (underflow)&amp;quot;); return EX_USAGE; }&lt;br /&gt;
  if( newhostid==LONG_MAX ) { perror(&amp;quot;strtol (overflow)&amp;quot;); return EX_USAGE; }&lt;br /&gt;
  if(*invalidchar != '\0') { fprintf(stderr, &amp;quot;invalid hex number %c; must be in 0-f|F\n&amp;quot;, *invalidchar); return EX_USAGE; }&lt;br /&gt;
&lt;br /&gt;
  if( sethostid(newhostid) != 0 ) {&lt;br /&gt;
   perror(&amp;quot;sethostid&amp;quot;);&lt;br /&gt;
   if( errno == EPERM ) return EX_NOPERM;&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
  }&lt;br /&gt;
  printf(&amp;quot;System hostid changed.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  /* hostid is a byte-swapped ip like b.a.d.c */&lt;br /&gt;
  /* get ip by swapping to correct order a.b.c.d and save into in_addr struct */&lt;br /&gt;
  addr.s_addr = htonl(swapbytes(newhostid));&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -i or -l, then find hostid for &amp;lt;dotted ip address&amp;gt; */&lt;br /&gt;
 if( (strcmp(argv[1],&amp;quot;-i&amp;quot;) == 0) || (strcmp(argv[1],&amp;quot;-l&amp;quot;) == 0) ) {&lt;br /&gt;
  if( inet_aton(argv[2], &amp;amp;addr) == 0 ) { fprintf(stderr, &amp;quot;inet_aton: invalid dotted ip address: %s\n&amp;quot;, argv[2]); return EX_USAGE; }&lt;br /&gt;
&lt;br /&gt;
  /* hostid is a byte-swapped ip like b.a.d.c */&lt;br /&gt;
  /* get hostid by swapping bytes of ip a.b.c.d */&lt;br /&gt;
  newhostid = swapbytes(ntohl(addr.s_addr));&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -i &amp;lt;dotted ip address&amp;gt; */&lt;br /&gt;
 if( strcmp(argv[1],&amp;quot;-i&amp;quot;) == 0 ) {&lt;br /&gt;
  if( sethostid(newhostid) != 0 ) {&lt;br /&gt;
   perror(&amp;quot;sethostid&amp;quot;);&lt;br /&gt;
   if( errno == EPERM ) return EX_NOPERM;&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
  }&lt;br /&gt;
  printf(&amp;quot;System hostid changed.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -l &amp;lt;dotted ip address&amp;gt; */&lt;br /&gt;
 if(strcmp(argv[1],&amp;quot;-l&amp;quot;) == 0 ) {&lt;br /&gt;
   printf(&amp;quot;Listing hostid for ip. (no changes)\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -s */&lt;br /&gt;
 if(strcmp(argv[1],&amp;quot;-s&amp;quot;) == 0 ) {&lt;br /&gt;
   /* see if /etc/hostid exists and print info */&lt;br /&gt;
   if( access(&amp;quot;/etc/hostid&amp;quot;, F_OK) != 0 ) {&lt;br /&gt;
     printf(&amp;quot;Notice: /etc/hostid does not exist.\n&amp;quot;);&lt;br /&gt;
     perror(&amp;quot;Reason&amp;quot;);&lt;br /&gt;
     printf(&amp;quot;System hostid derived from ip of hostname found in hosts file or dns.\n&amp;quot;);&lt;br /&gt;
   } else {&lt;br /&gt;
     printf(&amp;quot;Notice: /etc/hostid exists.\n&amp;quot;&lt;br /&gt;
            &amp;quot;System hostid is obtained from hostid file.\n&amp;quot;);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
  errno=0;&lt;br /&gt;
  newhostid = gethostid();&lt;br /&gt;
  if(errno!=0) { perror(&amp;quot;gethostid&amp;quot;); return EX_UNAVAILABLE; }&lt;br /&gt;
&lt;br /&gt;
  /* hostid is a byte-swapped ip like b.a.d.c */&lt;br /&gt;
  /* get ip by swapping to correct order a.b.c.d and save into in_addr struct */&lt;br /&gt;
  addr.s_addr = htonl(swapbytes(newhostid));&lt;br /&gt;
&lt;br /&gt;
  printf(&amp;quot;Listing current system hostid. (no changes)\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** print info and return */&lt;br /&gt;
 printf(&amp;quot;ip dot: %s\n&amp;quot;, inet_ntoa(addr) );&lt;br /&gt;
 printf(&amp;quot;ip hex: %.8x\n&amp;quot;, ntohl(addr.s_addr) );&lt;br /&gt;
 printf(&amp;quot;hostid: %.8x\n&amp;quot;, newhostid );&lt;br /&gt;
 return EX_OK;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
----&lt;br /&gt;
Now available! &amp;quot;ZFS root (builtin)&amp;quot; wiki (aka &amp;quot;ZFS root, part II&amp;quot;):&lt;br /&gt;
http://slackwiki.com/ZFS_root_(builtin)&lt;br /&gt;
It is now possible to build the modules and a small initramfs into your kernel to have a fully-contained and bootable ZFS root kernel from a simple lilo entry. Good luck!&lt;/div&gt;</description>
			<pubDate>Mon, 24 Sep 2012 08:39:14 GMT</pubDate>
			<dc:creator>Foobarz</dc:creator>
			<comments>https://www.slackwiki.com/Talk:ZFS_root</comments>
		</item>
		<item>
			<title>ZFS root (builtin)</title>
			<link>https://www.slackwiki.com/index.php?title=ZFS_root_(builtin)&amp;diff=801</link>
			<guid isPermaLink="false">https://www.slackwiki.com/index.php?title=ZFS_root_(builtin)&amp;diff=801</guid>
			<description>&lt;p&gt;Foobarz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Tutorials]]&lt;br /&gt;
The first [http://slackwiki.com/ZFS_root &amp;quot;ZFS root&amp;quot;] wiki explains the details of running ZFS as your root filesystem by using a fully modular generic kernel approach. Now, I can share how it can be done with the SPL and ZFS modules built into the kernel. This procedure is just an example and can use some fine tuning, but here goes:&lt;br /&gt;
&lt;br /&gt;
The steps below are to create a kernel with SPL and ZFS modules builtin. This kernel will be installed as an alternative kernel to boot in lilo, and it will have a separate kernel installation from the fully modular and working system kernel. This will allow testing the builtin kernel while able to boot back onto a working modular ZFS system. We start this procedure assuming you are on a working fully modular ZFS install as in the &amp;quot;ZFS root&amp;quot; wiki.&lt;br /&gt;
&lt;br /&gt;
Use mountpoint=legacy so that zfs will not expect &amp;lt;code&amp;gt;zfs mount&amp;lt;/code&amp;gt;, but instead expect standard &amp;lt;code&amp;gt;mount&amp;lt;/code&amp;gt; for mounting zfs-root:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=legacy zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Edit &amp;lt;code&amp;gt;/etc/rc.d/rc.S&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;rc.6&amp;lt;/code&amp;gt; to use regular &amp;lt;code&amp;gt;mount&amp;lt;/code&amp;gt; commands, remove &amp;lt;code&amp;gt;zfs&amp;lt;/code&amp;gt; commands. Edit &amp;lt;code&amp;gt;rc.6&amp;lt;/code&amp;gt; and remove or comment out &amp;lt;code&amp;gt;zpool export&amp;lt;/code&amp;gt; command. These edits undo changes made in the &amp;quot;ZFS root&amp;quot; wiki, but it shows the two different ways of mounting a zfs filesystem.&lt;br /&gt;
&lt;br /&gt;
You &amp;lt;i&amp;gt;might&amp;lt;/i&amp;gt; think to set &amp;lt;code&amp;gt;bootfs&amp;lt;/code&amp;gt; property like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool set bootfs=zfs-root zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
However, this will result in ZFS placing many restrictions on zfs-root as per how that option is used on Solaris systems:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; zfs-root must be VTOC (SMI) label, not GPT (EFI) label&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; zfs-root can only contain 1 vdev: either a plain disk, or a mirror&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
So, do &amp;lt;b&amp;gt;NOT&amp;lt;/b&amp;gt; set that property! If &amp;lt;code&amp;gt;bootfs&amp;lt;/code&amp;gt; is set, you would find that you cannot add vdevs to your zfs-root. If it is set already, then unset it like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool set bootfs= zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Make a directory to store files to be inside the initramfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkdir /boot/initramfs-source&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This directory will hold some files for the initial rootfs inside the kernel. Your &amp;lt;code&amp;gt;/boot&amp;lt;/code&amp;gt; should be on a small ext4 partition or on a mounted USB stick that you use to boot.&lt;br /&gt;
&lt;br /&gt;
Extract the slackware kernel-source package to obtain a copy of the kernel source, and make an initial kernel config for it:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir src&lt;br /&gt;
cd src&lt;br /&gt;
tar xvzf /mnt/cdrom/slackware64/k/kernel-source-*.txz&lt;br /&gt;
mv usr/src/linux-3.2.28 /usr/src/linux-3.2.28b&lt;br /&gt;
rm -r install&lt;br /&gt;
cd /usr/src/linux-3.2.28b&lt;br /&gt;
make menuconfig&lt;br /&gt;
  General setup-&amp;gt;Local version - append to kernel release = b&lt;br /&gt;
  General setup-&amp;gt;Default hostname                         = slackzfs&lt;br /&gt;
  General setup-&amp;gt;Initramfs source files(s)                = /boot/initramfs-source&lt;br /&gt;
  Device Drivers-&amp;gt;SCSI device support-&amp;gt;SCSI low-level drivers-&amp;gt; &amp;lt;*&amp;gt; SYM53C8XX Version 2 SCSI support&lt;br /&gt;
  File systems -&amp;gt; &amp;lt;*&amp;gt; The Extended 4 (ext4) filesystem&lt;br /&gt;
  # build in any hard drive controllers and filesystems that you need for booting&lt;br /&gt;
  # then save the config&lt;br /&gt;
make prepare scripts&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The kernel source has been set to have a &amp;quot;Local version&amp;quot; &amp;lt;code&amp;gt;b&amp;lt;/code&amp;gt;. This will result in modules installed to &amp;lt;code&amp;gt;/lib/modules/3.2.28b&amp;lt;/code&amp;gt; and keeps this kernel's source and modules seperate from slackware's kernel-generic package installation. The &amp;lt;code&amp;gt;make prepare scripts&amp;lt;/code&amp;gt; command readies the kernel source as needed before we can install a copy of spl and zfs modules into the kernel source tree.&lt;br /&gt;
&lt;br /&gt;
Now proceed to configure and copy spl and zfs into the kernel source tree:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd ~/src&lt;br /&gt;
tar xvzf ~/spl-0.6.0-rc11.tar.gz&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-0.6.0-rc11&lt;br /&gt;
./configure \&lt;br /&gt;
    --prefix=/ \&lt;br /&gt;
    --libdir=/lib64 \&lt;br /&gt;
    --includedir=/usr/include \&lt;br /&gt;
    --datarootdir=/usr/share \&lt;br /&gt;
    --enable-linux-builtin=yes \&lt;br /&gt;
    --with-linux=/usr/src/linux-3.2.28b \&lt;br /&gt;
    --with-linux-obj=/usr/src/linux-3.2.28b&lt;br /&gt;
./copy-builtin /usr/src/linux-3.2.28b&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../spl-0.6.0rc11_3.2.28b-x86_64-1root.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
&lt;br /&gt;
tar xvzf ~/zfs-0.6.0-rc11.tar.gz&lt;br /&gt;
mkdir install&lt;br /&gt;
cd zfs-0.6.0-rc11&lt;br /&gt;
./configure \&lt;br /&gt;
    --prefix=/ \&lt;br /&gt;
    --libdir=/lib64 \&lt;br /&gt;
    --includedir=/usr/include \&lt;br /&gt;
    --datarootdir=/usr/share \&lt;br /&gt;
    --enable-linux-builtin=yes \&lt;br /&gt;
    --with-linux=/usr/src/linux-3.2.28b \&lt;br /&gt;
    --with-linux-obj=/usr/src/linux-3.2.28b \&lt;br /&gt;
    --with-spl=/root/src/spl-0.6.0-rc11&lt;br /&gt;
    --with-spl-obj=/root/src/spl-0.6.0-rc11&lt;br /&gt;
./copy-builtin /usr/src/linux-3.2.28b&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../zfs-0.6.0rc11_3.2.28b-x86_64-1root.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
At this point, the &amp;lt;code&amp;gt;copy-builtin&amp;lt;/code&amp;gt; scripts have installed the configured spl and zfs modules source into the kernel source. The regular &amp;lt;code&amp;gt;make menuconfig&amp;lt;/code&amp;gt; in the kernel source should now show options for spl and zfs in the kernel config.&lt;br /&gt;
&lt;br /&gt;
As of this writing, the copy-builtin script places the spl and zfs modules into the kernel source in places where the modules may not initialize in the best order, &amp;lt;i&amp;gt;after&amp;lt;/i&amp;gt; all lower-level storage drivers are initialized. If spl and zfs initialize too soon, there is a chance they may not be able to see all of the storage devices. The order of initialization (as seen in dmesg) of modules that are builtin to the kernel is the order that the modules are linked into the kernel during kernel compilation. The order of link depends on where the module source files are located in the kernel source tree. To ensure that spl and zfs will initialize after all hardware drivers, we can move them into the &amp;lt;code&amp;gt;drivers&amp;lt;/code&amp;gt; tree and after all other drivers. This move is &amp;lt;b&amp;gt;optional&amp;lt;/b&amp;gt; and you can skip doing this and everything will probably work fine, but it is shown here how to move the modules to under drivers in case you prefer them there:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /usr/src/linux-3.2.28b&lt;br /&gt;
mkdir drivers/zfsonlinux&lt;br /&gt;
mv spl drivers/zfsonlinux&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  # remove references to spl&lt;br /&gt;
vi Makefile&lt;br /&gt;
  # remove references to spl&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.28b/fs&lt;br /&gt;
mv zfs ../drivers/zfsonlinux&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  # remove references to zfs&lt;br /&gt;
vi Makefile&lt;br /&gt;
  # remove references to zfs&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.28b/drivers&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  )# add line at end of menu, before &amp;quot;endmenu&amp;quot;:&lt;br /&gt;
  )source &amp;quot;drivers/zfsonlinux/Kconfig&amp;quot;&lt;br /&gt;
  )endmenu&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.28b/drivers&lt;br /&gt;
vi Makefile&lt;br /&gt;
  )# add line at very end of file:&lt;br /&gt;
  )obj-$(CONFIG_ZFSONLINUX) += zfsonlinux/&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.28b/drivers/zfsonlinux&lt;br /&gt;
cat &amp;gt; Kconfig &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
menuconfig ZFSONLINUX&lt;br /&gt;
	tristate &amp;quot;ZFSonLinux support&amp;quot;&lt;br /&gt;
&lt;br /&gt;
if ZFSONLINUX&lt;br /&gt;
&lt;br /&gt;
source &amp;quot;drivers/zfsonlinux/spl/Kconifg&amp;quot;&lt;br /&gt;
&lt;br /&gt;
source &amp;quot;drivers/zfsonlinux/zfs/Kconifg&amp;quot;&lt;br /&gt;
&lt;br /&gt;
endif&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.28b/zfsonlinux&lt;br /&gt;
cat &amp;gt; Makefile &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
obj-$(CONFIG_SPL) += spl/&lt;br /&gt;
obj-$(CONFIG_ZFS) += zfs/&lt;br /&gt;
EOF&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This completes the move of the spl and zfs modules in the kernel source tree to be under &amp;lt;code&amp;gt;drivers/zfsonlinux&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Now, in kernel configuration, you can build in the modules as follows:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /usr/src/linux-3.2.28b&lt;br /&gt;
make menuconfig&lt;br /&gt;
   Device Drivers -&amp;gt;&lt;br /&gt;
    &amp;lt;*&amp;gt; ZFSonLinux support -&amp;gt;&lt;br /&gt;
      &amp;lt;*&amp;gt; Solaris Porting Layer (SPL)&lt;br /&gt;
      &amp;lt;*&amp;gt;     ZFS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the kernel config, we set &amp;lt;code&amp;gt;/boot/initramfs-source&amp;lt;/code&amp;gt; as source location of the contents to be linked into kernel's builtin initramfs (rootfs). Now, we create some files that are needed to be in the initramfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /boot/initramfs-source&lt;br /&gt;
&lt;br /&gt;
# make standard directories&lt;br /&gt;
mkdir -p proc dev sys mnt bin sbin etc/zfs&lt;br /&gt;
&lt;br /&gt;
# zfs seems to want mtab present, even if empty&lt;br /&gt;
touch etc/mtab&lt;br /&gt;
&lt;br /&gt;
# if zpool.cache file can be read by zfs at module init, it imports the pools in the cache&lt;br /&gt;
cp /etc/zfs/zpool.cache-initrd etc/zfs/zpool.cache&lt;br /&gt;
&lt;br /&gt;
It is time to pause for a moment here and talk about zpool.cache: Using it is actually dangerous. We are not using udev and it's persistent block device filenames (/dev/disk/by-*), but are using the default kernel block device names (/dev/sd*) in devtmpfs. Device names for a hard drive in /dev can potentially change on boot depending on disk controller initialization order and disk drive response time. Adding another disk controller or hard disk on a controller can result in device name assignment changes to all the hard disks. A zpool.cache file holds all the zfs_member device filenames /dev/sd* for a pool configuration, but the zpool.cache configuration will be incorrect if device filenames have been changed or swapped around and this could result in a faulted pool that may or may not be recoverable. Using zpool.cache to import pools at boot, even with udev persistent device filenames, is potentially destructive if devices have been changed around. The proper thing to do is zpool_import and do not include zpool.cache in the initramfs.&lt;br /&gt;
&lt;br /&gt;
# make initial console device node; otherwise, there is a problem at startup:&lt;br /&gt;
# &amp;quot;Warning: unable to open an initial console&amp;quot; and you'd have problems with console and tty login&lt;br /&gt;
# making these nodes from within /init is not early enough to avoid problem&lt;br /&gt;
mknod dev/console c 5 1   # system console&lt;br /&gt;
&lt;br /&gt;
# make memory device kmsg to &amp;quot;printk&amp;quot; kernel messages&lt;br /&gt;
# we can write to this file to send out messages&lt;br /&gt;
mknod dev/kmsg    c 1 11  # lines printed to kmsg enter kernel messages buffer&lt;br /&gt;
&lt;br /&gt;
# recommended loop0 device to mount fs images&lt;br /&gt;
mknod dev/loop0   b 7 0&lt;br /&gt;
&lt;br /&gt;
# make initial virtual terminal devices&lt;br /&gt;
mknod dev/tty     c 5 0   # current tty&lt;br /&gt;
mknod dev/tty0    c 4 0   # current virtual term&lt;br /&gt;
mknod dev/tty1    c 4 1   # login virtual term 1 (F1)&lt;br /&gt;
&lt;br /&gt;
# make alternative console=ttyS0 standard 8250/16550 UART serial port devices&lt;br /&gt;
#   useful with kernel parameter console=ttyS0&lt;br /&gt;
#          with qemu -nographic -option-rom sgabios.bin,bootindex=0&lt;br /&gt;
mknod dev/ttyS0   c 4 64  # COM1&lt;br /&gt;
mknod dev/ttyS1   c 4 65  # COM2&lt;br /&gt;
mknod dev/ttyS2   c 4 66  # COM3&lt;br /&gt;
mknod dev/ttyS3   c 4 67  $ COM4&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This should be enough device nodes initially in the initramfs. Once devtmpfs mounts over /dev inside initramfs, a lot more devices are available in it by default.&lt;br /&gt;
&lt;br /&gt;
The initramfs needs an &amp;lt;code&amp;gt;/init&amp;lt;/code&amp;gt; program that will be run automatically by the kernel as process id 1, the first program to run on the system. This program's task is to mount a root filesystem, switch it to be the new root (/), and then exec the init (&amp;lt;code&amp;gt;/sbin/init&amp;lt;/code&amp;gt;) program that is on the new root so that the new root system is booted.&lt;br /&gt;
&lt;br /&gt;
The common way to make /init is using busybox with files like these in /boot/initrd-tree or /boot/initramfs-source:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
bin/busybox&lt;br /&gt;
bin/ash -&amp;gt; busybox&lt;br /&gt;
bin/sh -&amp;gt; busybox&lt;br /&gt;
# run busybox to see what other &amp;quot;applets&amp;quot; can be symlinked to it&lt;br /&gt;
# when busybox is run as a different symlinked applet name, it runs as the applet&lt;br /&gt;
init&lt;br /&gt;
# init can be an ash script, see slackware's /boot/initrd-tree/init for example&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For example, as an ash script, slackware's init does the following:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;parse kernel parameters passed into it and set variables based on them&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;start udevd and trigger rules for block devices to setup initial /dev devices&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;load kernel modules and keyboard map&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;run mdadm, cryptsetup, lvm, zpool/zfs to setup more devices&lt;br /&gt;
     (any udev rules for them should do more /dev setup in the background)&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;mount the root filesystem read-only at /mnt&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;stat /mnt/sbin/init, and if not executable run a rescue shell /bin/sh&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;shutdown udevd so it can be restarted by root system when booted&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;mount --move {proc,sys,run,dev} to under /mnt&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;run: exec switch_root /mnt /sbin/init $RUNLEVEL&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The slackware mkinitrd package is a fully configured BusyBox installation that makes an external initramfs image file, initrd.gz, that is passed to the kernel by the bootloader (lilo). It could be changed to be internal to the kernel by just using initrd-tree as the CONFIG_INITRAMFS_SOURCE in the kernel config and removing initrd in the lilo.conf.&lt;br /&gt;
&lt;br /&gt;
The main purpose of most initramfs/initrd is to load and configure kernel modules and devices needed to mount a root filesystem. Because the spl/zfs modules are builtin, there isn't really a lot that needs to be done by an initramfs. What remains to be done is import the zfs-root pool, mount it, and exec the system /sbin/init. The kernel's &amp;quot;legacy&amp;quot; parameters &amp;lt;code&amp;gt;root=&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;rootfstype=&amp;lt;/code&amp;gt; that are able to directly boot a root disk do not work with ZFS at this time because ZFS pools always need to be imported before it is possible to mount and boot on them. The automatic import that ZFS can do by using a cachefile (/etc/zfs/zpool.cache) stored in initramfs still does not work with the legacy boot parameters because at an earlier stage of the boot process, the kernel ignores a rootfs that does not contain an &amp;lt;code&amp;gt;/init&amp;lt;/code&amp;gt; program, and/or the device type of an imported pool is not the device types recognized by the legacy boot as valid root devices.&lt;br /&gt;
&lt;br /&gt;
You could just continue to use slackware's mkinitrd package as in the &amp;quot;ZFS root&amp;quot; wiki and it works the same whether the modules are builtin or not. But, by building the spl/zfs modules in, aren't we really wanting to get rid of using the mkinitrd/initrd.gz? We'd like to have a kernel with everything in it to boot, and use a simple lilo image entry that has no initrd.&lt;br /&gt;
&lt;br /&gt;
We can do this, and not use the mkinitrd package, but we still need to finish our own initramfs &amp;lt;code&amp;gt;/init&amp;lt;/code&amp;gt; program to import, mount, switch root, and boot. Save the following c program to &amp;quot;foobarz-init.c&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/* software product name: foobarz-init.c&lt;br /&gt;
 * suggested binary name: /init (in initramfs-source, rootfs)&lt;br /&gt;
 * license              : BSD&lt;br /&gt;
 * license text:&lt;br /&gt;
Copyright (c) 2012, foobarz&lt;br /&gt;
All rights reserved.&lt;br /&gt;
&lt;br /&gt;
Redistribution and use in source and binary forms, with or without&lt;br /&gt;
modification, are permitted provided that the following conditions are met:&lt;br /&gt;
    * Redistributions of source code must retain the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer.&lt;br /&gt;
    * Redistributions in binary form must reproduce the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer in the&lt;br /&gt;
      documentation and/or other materials provided with the distribution.&lt;br /&gt;
    * Neither the name of the &amp;lt;organization&amp;gt; nor the&lt;br /&gt;
      names of its contributors may be used to endorse or promote products&lt;br /&gt;
      derived from this software without specific prior written permission.&lt;br /&gt;
&lt;br /&gt;
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &amp;quot;AS IS&amp;quot; AND&lt;br /&gt;
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED&lt;br /&gt;
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE&lt;br /&gt;
DISCLAIMED. IN NO EVENT SHALL &amp;lt;COPYRIGHT HOLDER&amp;gt; BE LIABLE FOR ANY&lt;br /&gt;
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES&lt;br /&gt;
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;&lt;br /&gt;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND&lt;br /&gt;
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT&lt;br /&gt;
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS&lt;br /&gt;
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
/* Your initramfs-source should contain the following&lt;br /&gt;
 *&lt;br /&gt;
 * cd /boot/initramfs-source&lt;br /&gt;
 * mkdir -p proc dev sys mnt bin sbin etc/zfs&lt;br /&gt;
 * touch etc/mtab&lt;br /&gt;
 * cp /etc/zfs/zpool.cache-initrd etc/zfs/zpool.cache&lt;br /&gt;
 * # zpool.cache is optional - zpool_import_ kernel params can be used instead&lt;br /&gt;
 * #  see below for details on using zpool_import&lt;br /&gt;
 * mknod dev/console c 5 1   # system console&lt;br /&gt;
 * mknod dev/kmsg    c 1 11  # lines printed to kmsg enter kernel messages buffer&lt;br /&gt;
 * mknod dev/loop0   b 7 0&lt;br /&gt;
 * mknod dev/tty     c 5 0   # current tty&lt;br /&gt;
 * mknod dev/tty0    c 4 0   # current virtual term&lt;br /&gt;
 * mknod dev/tty1    c 4 1   # login virtual term 1 (F1)&lt;br /&gt;
 * mknod dev/ttyS0   c 4 64  # COM1&lt;br /&gt;
 * mknod dev/ttyS1   c 4 65  # COM2&lt;br /&gt;
 * mknod dev/ttyS2   c 4 66  # COM3&lt;br /&gt;
 * mknod dev/ttyS3   c 4 67  $ COM4&lt;br /&gt;
 *&lt;br /&gt;
 * Copy this compiled program to /boot/initramfs-source/init&lt;br /&gt;
 * If not named /init, then use rdinit=/othername kernel parameter.&lt;br /&gt;
 *&lt;br /&gt;
 * Set kernel config option&lt;br /&gt;
 *  CONFIG_INITRAMFS_SOURCE=/boot/initramfs-source&lt;br /&gt;
 * to build the initramfs into your kernel image&lt;br /&gt;
 *  that also has builtin drivers (spl and zfs, etc).&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
#define FOOBARZ_INIT_VERSION &amp;quot;1.1.2&amp;quot;&lt;br /&gt;
#define _BSD_SOURCE&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdarg.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;fcntl.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/mount.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sysexits.h&amp;gt;&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
/* support for zpool import&lt;br /&gt;
 *&lt;br /&gt;
 * If -DINCLUDE_ZPOOL_IMPORT, then support to import a zpool is&lt;br /&gt;
 * enabled in the program. Enabling it will add many dependencies to the&lt;br /&gt;
 * compile and link; for example:&lt;br /&gt;
 *&lt;br /&gt;
 * gcc -static -DINCLUDE_ZPOOL_IMPORT \&lt;br /&gt;
 *    foobarz-init.c -include /usr/src/zfs-0.6.0-rc10/3.2.28/zfs_config.h \&lt;br /&gt;
 *   -o init \&lt;br /&gt;
 *   -I /usr/include/libspl -I /usr/include/libzfs \&lt;br /&gt;
 *   -lzfs -lnvpair -lzpool -luutil -luuid -lrt -lz -lm -lpthread \&lt;br /&gt;
 *   -I /usr/include/tirpc \&lt;br /&gt;
 *   -ltirpc&lt;br /&gt;
 *&lt;br /&gt;
 * Note that libtirpc is a drop-in replacement for the SunRPC functions that&lt;br /&gt;
 * used to be in glibc. No additional includes are needed, just the gcc -I and -l&lt;br /&gt;
 * options for tirpc.&lt;br /&gt;
 *&lt;br /&gt;
 * Otherwise, with -UINCLUDE_ZPOOL_IMPORT, the compile is just:&lt;br /&gt;
 * gcc -static foobarz-init.c -o init&lt;br /&gt;
 */&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
#include &amp;lt;libzfs.h&amp;gt;&lt;br /&gt;
#else&lt;br /&gt;
#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/stat.h&amp;gt;&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#define PARAM_REQ_NO 0&lt;br /&gt;
#define PARAM_REQ_YES 1&lt;br /&gt;
#define PARAM_SRC_DEFAULT 0&lt;br /&gt;
#define PARAM_SRC_CMDLINE 1&lt;br /&gt;
&lt;br /&gt;
void printk(char *fmt, ...) {&lt;br /&gt;
  FILE* f;&lt;br /&gt;
  int fd;&lt;br /&gt;
  va_list args;&lt;br /&gt;
&lt;br /&gt;
  f = fopen(&amp;quot;/dev/kmsg&amp;quot;, &amp;quot;w&amp;quot;);&lt;br /&gt;
  va_start(args, fmt);&lt;br /&gt;
  vfprintf(f, fmt, args);&lt;br /&gt;
  va_end(args);&lt;br /&gt;
  fflush(f);&lt;br /&gt;
  fclose(f);&lt;br /&gt;
  /* avoid flooding kmsg and having msgs suppressed; 20msgs/sec */&lt;br /&gt;
  usleep(50000);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[]) {&lt;br /&gt;
 /*** variables */&lt;br /&gt;
&lt;br /&gt;
 int i;&lt;br /&gt;
 int   fd = 0; /* file descriptor */&lt;br /&gt;
 unsigned long mountflags;&lt;br /&gt;
&lt;br /&gt;
 /* kernel command line */&lt;br /&gt;
 off_t cmdline_size;&lt;br /&gt;
 char* cmdline; /* to be malloc 4096B */&lt;br /&gt;
 char* cmdline_end;&lt;br /&gt;
 char* temp_end;&lt;br /&gt;
 char* src_msg; /* default or cmdline */&lt;br /&gt;
 int flag_param_missing = 0;&lt;br /&gt;
&lt;br /&gt;
 /* use to hold contents of a misc /proc/&amp;lt;file&amp;gt; */&lt;br /&gt;
 char* miscproc_buff; /* to be malloc 4096B */&lt;br /&gt;
 off_t miscproc_size;&lt;br /&gt;
&lt;br /&gt;
 /* note about environ, argv, and kernel cmdline for init:&lt;br /&gt;
  *   environ is not defined for init&lt;br /&gt;
  *   only argv[0] is set for init&lt;br /&gt;
  *   kernel command line parameters are accessed&lt;br /&gt;
  *   at /proc/cmdline&lt;br /&gt;
  */&lt;br /&gt;
&lt;br /&gt;
 /* kernel parameters expected to be name=value */&lt;br /&gt;
 /* do not use quotes or spaces in parameters   */&lt;br /&gt;
 /* you can add more params somwhere after root= */&lt;br /&gt;
 struct nv { char* n; char* v; char* v_end; int req; int src; };&lt;br /&gt;
 struct nv param[] = {&lt;br /&gt;
   { &amp;quot; root=&amp;quot;,       NULL, NULL, PARAM_REQ_YES, PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot; rootfstype=&amp;quot;, NULL, NULL, PARAM_REQ_YES, PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot; mountopt=&amp;quot;,   NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot; init=&amp;quot;,       NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot; runlevel=&amp;quot;,   NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot; console=&amp;quot;,    NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT }&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
   ,&lt;br /&gt;
   { &amp;quot; zpool_import_name=&amp;quot;,    NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot; zpool_import_guid=&amp;quot;,    NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot; zpool_import_newname=&amp;quot;, NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot; zpool_import_force=&amp;quot;,   NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT }&lt;br /&gt;
#endif&lt;br /&gt;
 };&lt;br /&gt;
 enum {&lt;br /&gt;
	 iroot,&lt;br /&gt;
	 irootfstype,&lt;br /&gt;
	 imountopt,&lt;br /&gt;
	 iinit,&lt;br /&gt;
	 irunlevel,&lt;br /&gt;
	 iconsole,&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
	 izpool_import_name,&lt;br /&gt;
	 izpool_import_guid,&lt;br /&gt;
	 izpool_import_newname,&lt;br /&gt;
	 izpool_import_force,&lt;br /&gt;
#endif&lt;br /&gt;
	 ilastparam&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
 libzfs_handle_t* libzfs = NULL;&lt;br /&gt;
 importargs_t iargs = { 0 };&lt;br /&gt;
 nvlist_t* pools = NULL;&lt;br /&gt;
 nvpair_t* pool = NULL;&lt;br /&gt;
 nvlist_t* config = NULL;&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
 /*** program */&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;foobarz-init, version %s: booting initramfs.\n&amp;quot;, FOOBARZ_INIT_VERSION);&lt;br /&gt;
&lt;br /&gt;
 cmdline       = (char*) malloc(4096);&lt;br /&gt;
 miscproc_buff = (char*) malloc(4096);&lt;br /&gt;
 if( (cmdline == NULL) || (miscproc_buff == NULL) ) {&lt;br /&gt;
   printk(&amp;quot;Unable to allocate buffer memory: malloc: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount proc /proc&lt;br /&gt;
  *  note: some /dev devices symlink into /proc&lt;br /&gt;
  *  proc contains info about processes, including cmdline etc. */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount proc /proc\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;proc&amp;quot;, &amp;quot;/proc&amp;quot;, &amp;quot;proc&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
   printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
   printk(&amp;quot;Mount proc successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount devtmpfs /dev&lt;br /&gt;
  *  note: This simple init program works if your root device is made from devices&lt;br /&gt;
  *  that are available by default in devtmpfs, such as /dev/sd*&lt;br /&gt;
  *&lt;br /&gt;
  *  For zfs, your root zfs pool should be created with default device nodes and&lt;br /&gt;
  *  then it should be mountable by this simple init program.&lt;br /&gt;
  *&lt;br /&gt;
  *  udev may be needed to configure device nodes and symlinks required&lt;br /&gt;
  *  to access a root device configuration made with such nodes and symlinks.&lt;br /&gt;
  *  If you need udevd, you can include it into your initramfs-source and&lt;br /&gt;
  *  modify this program to run it before attempting to mount your root device.&lt;br /&gt;
  *  However, if udevd is needed, a significant number of userspace programs may also be&lt;br /&gt;
  *  required by rules in /lib/udev/. You could install busybox + udev (about 5MB) or&lt;br /&gt;
  *  coreutils + util-linux + bash + udev (about 25MB) into initramfs-source. But, at that&lt;br /&gt;
  *  point you'd have ash or bash and many tools that are easier to use than this&lt;br /&gt;
  *  simple init program; it would then be easy to have /init as #!/bin/&amp;lt;b&amp;gt;ash script. */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount devtmpfs /dev\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;devtmpfs&amp;quot;, &amp;quot;/dev&amp;quot;, &amp;quot;devtmpfs&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
   printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
   printk(&amp;quot;Mount devtmpfs successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount sysfs /sys&lt;br /&gt;
  *  note: some kernel modules try to access /sys with userspace helpers to echo values into /sys variables;&lt;br /&gt;
  *  such modules expect a minimal userspace that contains coreutils or busybox */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount sysfs /sys\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;sysfs&amp;quot;, &amp;quot;/sys&amp;quot;, &amp;quot;sysfs&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
   printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
   printk(&amp;quot;Mount sysfs successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* process kernel command line */&lt;br /&gt;
 fd = open(&amp;quot;/proc/cmdline&amp;quot;, O_RDONLY);&lt;br /&gt;
 if( fd == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Cannot open /proc/cmdline: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 /* note, on /proc fs:&lt;br /&gt;
  *       lseek likely always returns error&lt;br /&gt;
  *       stat likely always returns st_size = 0&lt;br /&gt;
  *   so determining size of /proc file means just reading it;&lt;br /&gt;
  *   you have to read /proc files according to their documented&lt;br /&gt;
  *   maximum sizes; this is probably for performance reasons */&lt;br /&gt;
 cmdline_size = read(fd, cmdline, 4095);&lt;br /&gt;
 if( cmdline_size == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Failed to read /proc/cmdline: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 close(fd);&lt;br /&gt;
&lt;br /&gt;
 /* cmdline may be newline + null terminated, but make it null + null */&lt;br /&gt;
 cmdline[cmdline_size] = '\0';&lt;br /&gt;
 if( cmdline[cmdline_size-1] == '\n' ) {&lt;br /&gt;
   cmdline[cmdline_size-1] = '\0';&lt;br /&gt;
   cmdline_size--;&lt;br /&gt;
   cmdline_end = cmdline + cmdline_size;&lt;br /&gt;
 }&lt;br /&gt;
 printk(&amp;quot;Kernel cmdline size: %i\n&amp;quot;, cmdline_size);&lt;br /&gt;
 printk(&amp;quot;Kernel cmdline: \&amp;quot;%s\&amp;quot;\n&amp;quot;, cmdline);&lt;br /&gt;
&lt;br /&gt;
 /* find v and v_end of values in cmdline */&lt;br /&gt;
 for( i=iroot; i&amp;lt;ilastparam; i++ ) {&lt;br /&gt;
   param[i].v = strstr(cmdline, param[i].n);&lt;br /&gt;
   if( param[i].v != NULL ) {&lt;br /&gt;
     param[i].src = PARAM_SRC_CMDLINE;&lt;br /&gt;
     while( *(param[i].v) != '=' ) param[i].v++;&lt;br /&gt;
     param[i].v++;&lt;br /&gt;
     temp_end = param[i].v;&lt;br /&gt;
     while( !( (*temp_end == ' ') ||&lt;br /&gt;
               (*temp_end == '\n') ||&lt;br /&gt;
               (temp_end == cmdline_end)&lt;br /&gt;
	     ) ) temp_end++;&lt;br /&gt;
     if( temp_end == param[i].v ) {&lt;br /&gt;
       printk(&amp;quot;Kernel parameter %s: value missing.\n&amp;quot;, param[i].n);&lt;br /&gt;
       param[i].v = NULL;&lt;br /&gt;
     } else param[i].v_end = temp_end;&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* set defaults for params not given on cmdline */&lt;br /&gt;
 for( i=iroot; i&amp;lt;ilastparam; i++ ) {&lt;br /&gt;
   /* terminate value strings */&lt;br /&gt;
   if( param[i].v_end != NULL ) *(param[i].v_end) = '\0';&lt;br /&gt;
   /* set defaults if no value on cmdline */&lt;br /&gt;
   if( param[i].v == NULL ) {&lt;br /&gt;
     param[i].src = PARAM_SRC_DEFAULT;&lt;br /&gt;
     if( param[i].req == PARAM_REQ_YES ) flag_param_missing = 1;&lt;br /&gt;
     switch(i) {&lt;br /&gt;
       case iroot      : param[i].v = &amp;quot;&amp;lt;missing required param&amp;gt;&amp;quot; ; break;&lt;br /&gt;
       case irootfstype: param[i].v = &amp;quot;&amp;lt;missing required param&amp;gt;&amp;quot; ; break;&lt;br /&gt;
       case imountopt  : param[i].v = &amp;quot;ro&amp;quot;        ; break;&lt;br /&gt;
       case iinit      : param[i].v = &amp;quot;/sbin/init&amp;quot;; break;&lt;br /&gt;
       case irunlevel  : param[i].v = &amp;quot;3&amp;quot;         ; break;&lt;br /&gt;
       case iconsole   : param[i].v = &amp;quot;console&amp;quot;   ; break;&lt;br /&gt;
       default         : param[i].v = NULL;&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
   if(param[i].src == PARAM_SRC_DEFAULT) src_msg = &amp;quot;default&amp;quot;;&lt;br /&gt;
   else src_msg = &amp;quot;cmdline&amp;quot;;&lt;br /&gt;
   printk(&amp;quot;Using %s \&amp;quot;%s\&amp;quot; (source: %s)\n&amp;quot;, param[i].n, param[i].v, src_msg);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 if( flag_param_missing ) {&lt;br /&gt;
   printk(&amp;quot;Aborting boot process: missing required kernel parameter(s).\n&amp;quot;);&lt;br /&gt;
   return EX_USAGE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* generic nv pair kernel cmdline processing finished&lt;br /&gt;
  *  now, examine specific params for defaults and correctness */&lt;br /&gt;
&lt;br /&gt;
 /* param[irootfstype]: can be checked against /proc/filesystems: */&lt;br /&gt;
 fd = open(&amp;quot;/proc/filesystems&amp;quot;, O_RDONLY);&lt;br /&gt;
 if( fd == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Cannot open /proc/filesystems: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 miscproc_size = read(fd, miscproc_buff, 4095);&lt;br /&gt;
 if( miscproc_size == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Failed to read /proc/filesystems: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 close(fd);&lt;br /&gt;
 if( strstr(miscproc_buff, param[irootfstype].v) == NULL ) {&lt;br /&gt;
   printk(&amp;quot;%s \&amp;quot;%s\&amp;quot;: filesystem type not available.\n&amp;quot;, param[irootfstype].n, param[irootfstype].v);&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* zfs-specific */&lt;br /&gt;
 if( strcmp(param[irootfstype].v, &amp;quot;zfs&amp;quot;) == 0 ) {&lt;br /&gt;
   if( access(&amp;quot;/etc/zfs/zpool.cache&amp;quot;, F_OK) == 0 )&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/zfs/zpool.cache is present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
   else&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/zfs/zpool.cache not present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
&lt;br /&gt;
   if( access(&amp;quot;/etc/hostid&amp;quot;, F_OK) == 0 )&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/hostid is present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
   else&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/hostid not present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
   /* zpool import */&lt;br /&gt;
   if( (param[izpool_import_name].v != NULL) || (param[izpool_import_guid].v != NULL) ) {&lt;br /&gt;
	printk(&amp;quot;zpool_import: import requested.\n&amp;quot;);&lt;br /&gt;
	if( (param[izpool_import_name].v != NULL) &amp;amp;&amp;amp; (param[izpool_import_guid].v != NULL) ) {&lt;br /&gt;
		printk(&amp;quot;zpool_import: given both pool name and guid; using guid.\n&amp;quot;);&lt;br /&gt;
		param[izpool_import_name].v = NULL;&lt;br /&gt;
	}&lt;br /&gt;
	if( param[izpool_import_name].v != NULL )&lt;br /&gt;
		printk(&amp;quot;zpool_import: pool name: %s\n&amp;quot;, param[izpool_import_name].v );&lt;br /&gt;
	else&lt;br /&gt;
		printk(&amp;quot;zpool_import: pool guid: %s\n&amp;quot;, param[izpool_import_guid].v );&lt;br /&gt;
&lt;br /&gt;
	iargs.path = NULL;&lt;br /&gt;
	iargs.paths = 0;&lt;br /&gt;
	iargs.poolname = param[izpool_import_name].v;&lt;br /&gt;
	if( param[izpool_import_guid].v != NULL )&lt;br /&gt;
		iargs.guid = strtoull(param[izpool_import_guid].v, NULL, 10);&lt;br /&gt;
	else&lt;br /&gt;
		iargs.guid = 0;&lt;br /&gt;
	iargs.cachefile = NULL;&lt;br /&gt;
	if( (param[izpool_import_force].v != NULL) &amp;amp;&amp;amp; (strcmp(param[izpool_import_force].v, &amp;quot;1&amp;quot;) == 0) ) {&lt;br /&gt;
		iargs.can_be_active = 1;&lt;br /&gt;
		printk(&amp;quot;zpool_import: import forced.\n&amp;quot;);&lt;br /&gt;
	} else {&lt;br /&gt;
		iargs.can_be_active = 0;&lt;br /&gt;
		printk(&amp;quot;zpool_import: import not forced.\n&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
	iargs.unique = 1;&lt;br /&gt;
	iargs.exists = 1;&lt;br /&gt;
&lt;br /&gt;
	printk(&amp;quot;zpool_import: init libzfs.\n&amp;quot;);&lt;br /&gt;
	libzfs = libzfs_init();&lt;br /&gt;
	if( libzfs != NULL ) {&lt;br /&gt;
		printk(&amp;quot;zpool_import: searching for pool.\n&amp;quot;);&lt;br /&gt;
		pools = zpool_search_import(libzfs, &amp;amp;iargs);&lt;br /&gt;
		if( (pools == NULL) || nvlist_empty(pools) )&lt;br /&gt;
			printk(&amp;quot;zpool_import: pool not available for import, or already imported by cachefile.\n&amp;quot;);&lt;br /&gt;
		else {&lt;br /&gt;
			printk(&amp;quot;zpool_import: getting pool information.\n&amp;quot;);&lt;br /&gt;
			pool = nvlist_next_nvpair(pools, pool);&lt;br /&gt;
			printk(&amp;quot;zpool_import: getting pool configuration.\n&amp;quot;);&lt;br /&gt;
			nvpair_value_nvlist(pool, &amp;amp;config);&lt;br /&gt;
			printk(&amp;quot;zpool_import: attempting pool import.\n&amp;quot;);&lt;br /&gt;
			if( zpool_import(libzfs, config, param[izpool_import_newname].v, NULL) != 0 ) {&lt;br /&gt;
				printk(&amp;quot;zpool_import: import failed.\n&amp;quot;);&lt;br /&gt;
				printk(&amp;quot;zpool_import: error description: %s\n&amp;quot;, libzfs_error_description(libzfs) );&lt;br /&gt;
				printk(&amp;quot;zpool_import: error action: %s\n&amp;quot;, libzfs_error_action(libzfs) );&lt;br /&gt;
			} else  printk(&amp;quot;zpool_import: import successful.\n&amp;quot;);&lt;br /&gt;
		}&lt;br /&gt;
		printk(&amp;quot;zpool_import: fini libzfs.\n&amp;quot;);&lt;br /&gt;
		libzfs_fini(libzfs);&lt;br /&gt;
	} else {&lt;br /&gt;
		printk(&amp;quot;zpool_import: unable to initialize libzfs.\n&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
   }&lt;br /&gt;
#endif /* zpool_import */&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 if(      strcmp(param[imountopt].v, &amp;quot;ro&amp;quot;) == 0 ) mountflags = MS_RDONLY;&lt;br /&gt;
 else if( strcmp(param[imountopt].v, &amp;quot;rw&amp;quot;) == 0 ) mountflags = 0;&lt;br /&gt;
 else {&lt;br /&gt;
   printk(&amp;quot;%s \&amp;quot;%s\&amp;quot;: invalid parameter value; defaulting to \&amp;quot;ro\&amp;quot;.\n&amp;quot;, param[imountopt].n, param[imountopt].v);&lt;br /&gt;
   mountflags = MS_RDONLY;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* param[iroot]: nothing to check; if user gives bad root=device then mount fails */&lt;br /&gt;
&lt;br /&gt;
 /* try to mount root=device at /mnt&lt;br /&gt;
  *&lt;br /&gt;
  * note: for zfs, if a copy of /etc/zfs/zpool.cache (when pool is imported) is put in initramfs-source, then&lt;br /&gt;
  * the zfs module can read it and automatically import the pools described in the cache file; the imported&lt;br /&gt;
  * pools can be available to mount here if they were created using standard device names, otherwise&lt;br /&gt;
  * udevd may be required to run before mounting the pool */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount -t %s -o %s %s /mnt.\n&amp;quot;, param[irootfstype].v, param[imountopt].v, param[iroot].v);&lt;br /&gt;
 if( mount(param[iroot].v, &amp;quot;/mnt&amp;quot;, param[irootfstype].v, mountflags, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 printk(&amp;quot;%s mounted successfully.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
&lt;br /&gt;
 /* check to see if the mounted root filesystem has an executable init program */&lt;br /&gt;
 chdir(&amp;quot;/mnt&amp;quot;);&lt;br /&gt;
 if( access(param[iinit].v+1, X_OK) != 0 ) {&lt;br /&gt;
   chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
   printk(&amp;quot;access X_OK: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   printk(&amp;quot;The init program /mnt/%s is not present or not executable.\n&amp;quot;, param[iinit].v+1);&lt;br /&gt;
   printk(&amp;quot;Aborting boot process: no init program.\n&amp;quot;);&lt;br /&gt;
   printk(&amp;quot;Unmounting %s.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
   if( umount(&amp;quot;/mnt&amp;quot;) == -1 ) {&lt;br /&gt;
     printk(&amp;quot;umount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
     printk(&amp;quot;Failed to umount %s.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
   } else printk(&amp;quot;Successfully unmounted %s.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
 printk(&amp;quot;Init program /mnt/%s is present and executable.\n&amp;quot;, param[iinit].v+1);&lt;br /&gt;
&lt;br /&gt;
 /* switch the root / from initramfs to the mounted new root device at /mnt.&lt;br /&gt;
  *&lt;br /&gt;
  * note: after this switch, it is not possible to access the initramfs files anymore,&lt;br /&gt;
  * yet they consume ram memory unless they are deleted here before switching.&lt;br /&gt;
  * Any programs that are run after clearing the initramfs and switching root must exist on the new root.&lt;br /&gt;
  * This program may safely delete itself (/init) since it is already in ram and executing.&lt;br /&gt;
  * If you have installed additional files and programs in initramfs that consume significant ram,&lt;br /&gt;
  * then you need to insert additional code here to delete those files (carefully). */&lt;br /&gt;
&lt;br /&gt;
 /* delete files off of initramfs to free ram memory */&lt;br /&gt;
 printk(&amp;quot;Freeing memory from initramfs...\n&amp;quot;);&lt;br /&gt;
 if( unlink(argv[0]) != 0 ) printk(&amp;quot;unlink %s: %s\n&amp;quot;, argv[0], strerror(errno));&lt;br /&gt;
 else printk(&amp;quot;%s %s&amp;quot;, argv[0], &amp;quot;deleted from initramfs.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 /* switch root */&lt;br /&gt;
 printk(&amp;quot;Beginning switch root procedure.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(1) Attempting cmd: mount --move /dev /mnt/dev \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/dev&amp;quot;, &amp;quot;/mnt/dev&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(2) Attempting cmd: mount --move /proc /mnt/proc \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/proc&amp;quot;, &amp;quot;/mnt/proc&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(3) Attempting cmd: mount --move /sys /mnt/sys \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/sys&amp;quot;, &amp;quot;/mnt/sys&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(4) Attempting cmd: chdir /mnt \n&amp;quot;);&lt;br /&gt;
 if( chdir(&amp;quot;/mnt&amp;quot;) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: chdir: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(5) Attempting cmd: mount --move . / \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;.&amp;quot;, &amp;quot;/&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(6) Attempting cmd: chroot . \n&amp;quot;);&lt;br /&gt;
 if( chroot(&amp;quot;.&amp;quot;) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: chroot: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(7) Attempting cmd: chdir / \n&amp;quot;);&lt;br /&gt;
 if( chdir(&amp;quot;/&amp;quot;) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: chdir: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 printk(&amp;quot;Completed switch root procedure.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 /* check for &amp;quot;console=&amp;quot; kernel parameter and switch&lt;br /&gt;
  *  stdin, stdout, and stderr to named console device&lt;br /&gt;
  */&lt;br /&gt;
 if( param[iconsole].src == PARAM_SRC_CMDLINE ) {&lt;br /&gt;
   printk(&amp;quot;Console redirection to device %s requested.\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
   /* expect only basename of console device (e.g., ttyS0), so chdir /dev */&lt;br /&gt;
   chdir(&amp;quot;/dev&amp;quot;);&lt;br /&gt;
   if( access(param[iconsole].v, F_OK ) == 0 ) {&lt;br /&gt;
     printk(&amp;quot;Opening stdin, stdout, and stderr on %s.\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
     close(0);&lt;br /&gt;
     open(param[iconsole].v, O_RDWR);&lt;br /&gt;
     dup2(0, 1);&lt;br /&gt;
     dup2(0, 2);&lt;br /&gt;
   } else {&lt;br /&gt;
     printk(&amp;quot;access F_OK: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
     printk(&amp;quot;Could not access device: %s!\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
     printk(&amp;quot;Console redirection to device %s aborted!\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
   }&lt;br /&gt;
   chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;Execing: \&amp;quot;%s %s\&amp;quot; to boot mounted root system.\n&amp;quot;, param[iinit].v, param[irunlevel].v);&lt;br /&gt;
&lt;br /&gt;
 /* free resources held to this point */&lt;br /&gt;
 free(cmdline);&lt;br /&gt;
 free(miscproc_buff);&lt;br /&gt;
&lt;br /&gt;
 if( execl(param[iinit].v, param[irunlevel].v, (char *) NULL ) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: execl: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If foobarz-init is updated, you can find the latest version at [https://github.com/foobarz/foobarz-init github].&lt;br /&gt;
&lt;br /&gt;
The foobarz-init program can be compiled two ways as of v1.1.1. First, the simpler compile that does not support zpool_import but does support importing pools using a /etc/zfs/zpool.cache file in the initramfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gcc --static init.c -o init&lt;br /&gt;
strip init&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The second way to compile it adds support for zpool_import so that you do not have to include a &amp;lt;code&amp;gt;/etc/zfs/zpool.cache&amp;lt;/code&amp;gt; file in the initramfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gcc -static -DINCLUDE_ZPOOL_IMPORT \&lt;br /&gt;
     foobarz-init.c -include /usr/src/linux-3.2.28b/zfs_config.h \&lt;br /&gt;
    -o init \&lt;br /&gt;
    -I /usr/include/libspl -I /usr/include/libzfs \&lt;br /&gt;
    -lzfs -lnvpair -lzpool -luutil -luuid -lrt -lz -lm -lpthread \&lt;br /&gt;
    -I /usr/include/tirpc \&lt;br /&gt;
    -ltirpc&lt;br /&gt;
strip init&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Dependencies required before you can compile this second way:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Install [http://sourceforge.net/projects/libtirpc/ libtirpc]. The glibc package has removed the RPC-related functions from the static libc. The libtirpc is the new replacement as a separate library. You can make your own libtirpc package and install it to resolve these RPC-related functions. Without this, the compile fails because it cannot find many &amp;quot;xdr&amp;quot; functions.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Reinstall the [ftp://slackware.mirrors.tds.net/pub/slackware/slackware64-current/source/a/util-linux/ util-linux] package with static libraries enabled. Edit the &amp;lt;code&amp;gt;util-linux.SlackBuild&amp;lt;/code&amp;gt; and remove the line &amp;lt;code&amp;gt;--disable-static&amp;lt;/code&amp;gt;, then build it and use upgradepkg to install the new package. This resolves linking static to libuuid.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;code&amp;gt;zfs_config.h&amp;lt;/code&amp;gt; can be found in the kernel source when you have installed the builtin spl/zfs configuration; for example at &amp;lt;code&amp;gt;/usr/src/linux-3.2.28b/zfs_config.h&amp;lt;/code&amp;gt;. If you currently have installed the modular spl/zfs configuration, &amp;lt;code&amp;gt;zfs_config.h&amp;lt;/code&amp;gt; is found where the zfs module headers are installed; for example at &amp;lt;code&amp;gt;/usr/src/zfs-0.6.0-rc11/3.2.28/zfs_config.h&amp;lt;/code&amp;gt;. Wherever it is, &amp;lt;code&amp;gt;-include&amp;lt;/code&amp;gt; it as shown in the example gcc line above. zfs_config.h seems misplaced because it would seem that using libzfs shouldn't depend on modules header files.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;You may need to install the spl and zfs packages configured for --enable-linux-builtin=yes before compiling and linking to libzfs to make sure you are using the version of libzfs intended for builtin modules in case a difference between the two configurations exists. Currently, there seems to be no difference in the libzfs for either modular or builtin modules, but later there could be at least a small difference for detection of modules to load or builtin already. You may see a message that the ZFS modules stack load failed, but it can be ignored since the modules are builtin; this is just libzfs trying to load the modules even though they are builtin.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
With these dependencies, you can probably compile static with the zpool_import support. The exact location of &amp;quot;zfs_config.h&amp;quot; may vary depending on your zfs and kernel versions, so adjust accordingly.&lt;br /&gt;
&lt;br /&gt;
Read the foobarz-init source code to see how it uses kernel parameters. The params &amp;lt;code&amp;gt;root&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;rootfstype&amp;lt;/code&amp;gt; are always required to tell init what root pool name to mount and the filesystem type (e.g. zfs).&lt;br /&gt;
&lt;br /&gt;
For the zpool_import support: &amp;lt;code&amp;gt;zpool_import_name=poolname&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;zpool_import_guid=&amp;lt;guid of a pool&amp;gt;&amp;lt;/code&amp;gt; tells what pool to import. You can also import the pool with a new different name by also using &amp;lt;code&amp;gt;zpool_import_newname=newpoolname&amp;lt;/code&amp;gt;. If the import is not working, &amp;lt;code&amp;gt;zpool_import_force=1&amp;lt;/code&amp;gt; can be used to force import even if ZFS thinks the pool may be in use by another system.&lt;br /&gt;
&lt;br /&gt;
However you import the pool, either using zpool.cache or zpool_import support, the kernel param &amp;lt;code&amp;gt;root=&amp;lt;your poolname or newpoolname&amp;gt;&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;rootfstype=zfs&amp;lt;/code&amp;gt; needs to be given also. The zpool_import only imports, it does not say what to mount. What to mount is still told using root= and rootfstype=.&lt;br /&gt;
&lt;br /&gt;
Now copy the compiled static program into the initramfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp init /boot/initramfs-source/init&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Build and install kernel:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /usr/src/linux-3.2.28b&lt;br /&gt;
make -j8&lt;br /&gt;
make -j8 modules_install&lt;br /&gt;
cp arch/x86/boot/bzImage /boot/vm3.2.28b&lt;br /&gt;
cp System.map /boot/System.map-vm3.2.28b&lt;br /&gt;
# add new lilo menu entry for vm3.2.28b kernel&lt;br /&gt;
vi /etc/lilo.conf&lt;br /&gt;
  image = /boot/vm3.2.28b&lt;br /&gt;
   label = vm3.2.28b&lt;br /&gt;
   addappend = &amp;quot; spl.spl_hostid=0x007f0100 zfs.spa_config_path=/etc/zfs/zpool.cache root=zfs-root rootfstype=zfs&amp;quot;&lt;br /&gt;
lilo&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Note: If &amp;lt;code&amp;gt;spl.spl_hostid=0x007f0100&amp;lt;/code&amp;gt; is not included in addappend, then during boot SPL module will attempt to read /etc/hostid or run a user-space helper to write the &amp;lt;code&amp;gt;hostid&amp;lt;/code&amp;gt; into &amp;lt;code&amp;gt;/proc/sys/kernel/spl/hostid&amp;lt;/code&amp;gt;. Reading /etc/hostid fails unless you use foobarz-chhostid and make the file and copy it into /boot/initramfs-source/etc/hostid. The helper will fail because no &amp;lt;code&amp;gt;sh&amp;lt;/code&amp;gt; shell and no &amp;lt;code&amp;gt;hostid&amp;lt;/code&amp;gt; command are installed in the initramfs. The default hostid becomes 0xffffffff, which is considered an invalid hostid.&lt;br /&gt;
&lt;br /&gt;
Congrats! If this works, you can select the &amp;quot;vm3.2.28b&amp;quot; lilo entry to boot. If you are using the zpool_import support in the init program, you need to add at least the &amp;lt;code&amp;gt;zpool_import_name=zfs-root&amp;lt;/code&amp;gt; param to the addappend line in lilo.conf.&lt;br /&gt;
&lt;br /&gt;
Notes on kernel params (lilo append and addappend lines): root= and rootfstype= are used by both foorbarz-init and mkinitrd. The &amp;quot;ro&amp;quot; param is not used by foobarz-init, so instead use: mountopt=ro|rw. See &amp;quot;modinfo spl&amp;quot; and &amp;quot;modinfo zfs&amp;quot; to see all of the options those modules can take on the kernel command line. Notice the &amp;lt;code&amp;gt;spl.spl_hostid=0x007f0100&amp;lt;/code&amp;gt; param that works around the hostid mismatch problem while trying to import a pool; this param and hostname/ip set to use local loopback 127.0.0.1 in etc/hosts etc/HOSTNAME in initramfs will work most of the time, and if not the pool import needs to be forced.&lt;br /&gt;
&lt;br /&gt;
Notes on the spl and zfs packages to install: &amp;lt;i&amp;gt;If&amp;lt;/i&amp;gt; you have errors using zfs and zpool commands on booted system with builtin modules, then upgrade/switch to the 0.6.0rc11_3.2.28b builds, or you can make a custom package with the binaries renamed like zpoolb, zfsb etc for builtin.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
Using qemu's -nographic serial console (/usr/share/qemu/sgabios.bin): If you have a boot problem, you might want to run in qemu's -nographic console mode:&lt;br /&gt;
&lt;br /&gt;
First, edit /etc/inittab, and uncomment the line for local serial ports runlevel &amp;quot;s1&amp;quot; (ttyS0) for serial console login support. This is done in the guest (host does not need this):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Local serial lines:&lt;br /&gt;
s1:12345:respawn:/sbin/agetty -L ttyS0 38400 linux&lt;br /&gt;
#s1:12345:respawn:/sbin/agetty -L ttyS0 9600 vt100&lt;br /&gt;
#s2:12345:respawn:/sbin/agetty -L ttyS1 9600 vt100&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Second, edit /etc/securetty, and uncomment ttyS0 line:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ttyS0&lt;br /&gt;
#ttyS1&lt;br /&gt;
# ...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
You cannot login on ttyS0 without this change even though you get the login prompt!&lt;br /&gt;
&lt;br /&gt;
Then, run qemu such as:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
qemu-kvm &amp;lt;all regular options&amp;gt; -nographic -option-rom sgabios.bin,bootindex=0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Wait for the lilo prompt, it may take several seconds show up in this mode.&lt;br /&gt;
&lt;br /&gt;
In the lilo menu, select your kernel image with builtin spl/zfs, and use kernel params such as:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
boot: vm3.2.28b console=ttyS0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
At the lilo prompt, use kernel parameter: console=ttyS0 (do NOT say /dev/ttS0). Passing runlevel=s1 does not appear to be necessary.&lt;br /&gt;
&lt;br /&gt;
When you are in qemu's serial mode, the interface is a little different than in the normal graphical mode: use keypresses:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ctrl-a h    # for help&lt;br /&gt;
ctrl-a c    # toggle access to (QEMU) console / back to emulation&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If you cannot get a login: prompt, try ctrl-a c, then do (QEMU) sendkey ctrl-alt-delete. This will reboot cleanly back to lilo, then you can do (QEMU) quit.&lt;br /&gt;
&lt;br /&gt;
Once you login to the guest, the terminal size needs adjustment. On your host, in another xterm sized the same as your guest console terminal, get the size of the terminal:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo $LINES&lt;br /&gt;
echo $COLUMNS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Now, back in the guest terminal of same size:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export LINES &amp;lt;lines&amp;gt;&lt;br /&gt;
export COLUMNS &amp;lt;columns&amp;gt;&lt;br /&gt;
stty cols $COLUMNS rows $LINES&lt;br /&gt;
exec bash&lt;br /&gt;
reset&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
So, you set the environment variables and also set them with stty. Then, restart bash (exec, or else it is a child shell process).&lt;br /&gt;
&lt;br /&gt;
BECAREFUL not to start qemu twice on the same ZFS guest! Two simultaneous running qemu on the same ZFS will corrupt the pool and it will NOT recover - you lose your whole installation! Before running qemu, check ps -A, look for an already running qemu process incase it somehow entered into the background!&lt;br /&gt;
&lt;br /&gt;
BECAREFUL when using -nographic ttyS0 that you are not doing commands on the HOST! Only use -nographic to see kernel problems. Use regular console if booting is working normally.&lt;br /&gt;
&lt;br /&gt;
To use the qemu -drive if=scsi option, the linux module sym53c8xx should be loaded in the guest. You may need to use the qemu option:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-option-rom 8xx_64.rom,bootindex=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The file 8xx_64.rom used to be inside qemu, but in new versions it is missing. You can download it:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
wget http://www.lsi.com/downloads/Public/Host%20Bus%20Adapters/Host%20Bus%20Adapters%20Common%20Files/lsi_bios.zip&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Extract the zip and place 8xx_64.rom in /usr/share/qemu/.&lt;br /&gt;
&lt;br /&gt;
Good luck!&lt;/div&gt;</description>
			<pubDate>Sat, 22 Sep 2012 09:30:40 GMT</pubDate>
			<dc:creator>Foobarz</dc:creator>
			<comments>https://www.slackwiki.com/Talk:ZFS_root_(builtin)</comments>
		</item>
		<item>
			<title>ZFS root (builtin)</title>
			<link>https://www.slackwiki.com/index.php?title=ZFS_root_(builtin)&amp;diff=800</link>
			<guid isPermaLink="false">https://www.slackwiki.com/index.php?title=ZFS_root_(builtin)&amp;diff=800</guid>
			<description>&lt;p&gt;Foobarz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Tutorials]]&lt;br /&gt;
The first [http://slackwiki.com/ZFS_root &amp;quot;ZFS root&amp;quot;] wiki explains the details of running ZFS as your root filesystem by using a fully modular generic kernel approach. Now, I can share how it can be done with the SPL and ZFS modules built into the kernel. This procedure is just an example and can use some fine tuning, but here goes:&lt;br /&gt;
&lt;br /&gt;
The steps below are to create a kernel with SPL and ZFS modules builtin. This kernel will be installed as an alternative kernel to boot in lilo, and it will have a separate kernel installation from the fully modular and working system kernel. This will allow testing the builtin kernel while able to boot back onto a working modular ZFS system. We start this procedure assuming you are on a working fully modular ZFS install as in the &amp;quot;ZFS root&amp;quot; wiki.&lt;br /&gt;
&lt;br /&gt;
Use mountpoint=legacy so that zfs will not expect &amp;lt;code&amp;gt;zfs mount&amp;lt;/code&amp;gt;, but instead expect standard &amp;lt;code&amp;gt;mount&amp;lt;/code&amp;gt; for mounting zfs-root:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=legacy zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Edit &amp;lt;code&amp;gt;/etc/rc.d/rc.S&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;rc.6&amp;lt;/code&amp;gt; to use regular &amp;lt;code&amp;gt;mount&amp;lt;/code&amp;gt; commands, remove &amp;lt;code&amp;gt;zfs&amp;lt;/code&amp;gt; commands. Edit &amp;lt;code&amp;gt;rc.6&amp;lt;/code&amp;gt; and remove or comment out &amp;lt;code&amp;gt;zpool export&amp;lt;/code&amp;gt; command. These edits undo changes made in the &amp;quot;ZFS root&amp;quot; wiki, but it shows the two different ways of mounting a zfs filesystem.&lt;br /&gt;
&lt;br /&gt;
You &amp;lt;i&amp;gt;might&amp;lt;/i&amp;gt; think to set &amp;lt;code&amp;gt;bootfs&amp;lt;/code&amp;gt; property like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool set bootfs=zfs-root zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
However, this will result in ZFS placing many restrictions on zfs-root as per how that option is used on Solaris systems:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; zfs-root must be VTOC (SMI) label, not GPT (EFI) label&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; zfs-root can only contain 1 vdev: either a plain disk, or a mirror&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
So, do &amp;lt;b&amp;gt;NOT&amp;lt;/b&amp;gt; set that property! If &amp;lt;code&amp;gt;bootfs&amp;lt;/code&amp;gt; is set, you would find that you cannot add vdevs to your zfs-root. If it is set already, then unset it like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool set bootfs= zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Make a directory to store files to be inside the initramfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkdir /boot/initramfs-source&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This directory will hold some files for the initial rootfs inside the kernel. Your &amp;lt;code&amp;gt;/boot&amp;lt;/code&amp;gt; should be on a small ext4 partition or on a mounted USB stick that you use to boot.&lt;br /&gt;
&lt;br /&gt;
Extract the slackware kernel-source package to obtain a copy of the kernel source, and make an initial kernel config for it:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir src&lt;br /&gt;
cd src&lt;br /&gt;
tar xvzf /mnt/cdrom/slackware64/k/kernel-source-*.txz&lt;br /&gt;
mv usr/src/linux-3.2.28 /usr/src/linux-3.2.28b&lt;br /&gt;
rm -r install&lt;br /&gt;
cd /usr/src/linux-3.2.28b&lt;br /&gt;
make menuconfig&lt;br /&gt;
  General setup-&amp;gt;Local version - append to kernel release = b&lt;br /&gt;
  General setup-&amp;gt;Default hostname                         = slackzfs&lt;br /&gt;
  General setup-&amp;gt;Initramfs source files(s)                = /boot/initramfs-source&lt;br /&gt;
  Device Drivers-&amp;gt;SCSI device support-&amp;gt;SCSI low-level drivers-&amp;gt; &amp;lt;*&amp;gt; SYM53C8XX Version 2 SCSI support&lt;br /&gt;
  File systems -&amp;gt; &amp;lt;*&amp;gt; The Extended 4 (ext4) filesystem&lt;br /&gt;
  # build in any hard drive controllers and filesystems that you need for booting&lt;br /&gt;
  # then save the config&lt;br /&gt;
make prepare scripts&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The kernel source has been set to have a &amp;quot;Local version&amp;quot; &amp;lt;code&amp;gt;b&amp;lt;/code&amp;gt;. This will result in modules installed to &amp;lt;code&amp;gt;/lib/modules/3.2.28b&amp;lt;/code&amp;gt; and keeps this kernel's source and modules seperate from slackware's kernel-generic package installation. The &amp;lt;code&amp;gt;make prepare scripts&amp;lt;/code&amp;gt; command readies the kernel source as needed before we can install a copy of spl and zfs modules into the kernel source tree.&lt;br /&gt;
&lt;br /&gt;
Now proceed to configure and copy spl and zfs into the kernel source tree:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd ~/src&lt;br /&gt;
tar xvzf ~/spl-0.6.0-rc11.tar.gz&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-0.6.0-rc11&lt;br /&gt;
./configure \&lt;br /&gt;
    --prefix=/ \&lt;br /&gt;
    --libdir=/lib64 \&lt;br /&gt;
    --includedir=/usr/include \&lt;br /&gt;
    --datarootdir=/usr/share \&lt;br /&gt;
    --enable-linux-builtin=yes \&lt;br /&gt;
    --with-linux=/usr/src/linux-3.2.28b \&lt;br /&gt;
    --with-linux-obj=/usr/src/linux-3.2.28b&lt;br /&gt;
./copy-builtin /usr/src/linux-3.2.28b&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../spl-0.6.0rc11_3.2.28b-x86_64-1root.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
&lt;br /&gt;
tar xvzf ~/zfs-0.6.0-rc11.tar.gz&lt;br /&gt;
mkdir install&lt;br /&gt;
cd zfs-0.6.0-rc11&lt;br /&gt;
./configure \&lt;br /&gt;
    --prefix=/ \&lt;br /&gt;
    --libdir=/lib64 \&lt;br /&gt;
    --includedir=/usr/include \&lt;br /&gt;
    --datarootdir=/usr/share \&lt;br /&gt;
    --enable-linux-builtin=yes \&lt;br /&gt;
    --with-linux=/usr/src/linux-3.2.28b \&lt;br /&gt;
    --with-linux-obj=/usr/src/linux-3.2.28b \&lt;br /&gt;
    --with-spl=/root/src/spl-0.6.0-rc11&lt;br /&gt;
    --with-spl-obj=/root/src/spl-0.6.0-rc11&lt;br /&gt;
./copy-builtin /usr/src/linux-3.2.28b&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../zfs-0.6.0rc11_3.2.28b-x86_64-1root.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
At this point, the &amp;lt;code&amp;gt;copy-builtin&amp;lt;/code&amp;gt; scripts have installed the configured spl and zfs modules source into the kernel source. The regular &amp;lt;code&amp;gt;make menuconfig&amp;lt;/code&amp;gt; in the kernel source should now show options for spl and zfs in the kernel config.&lt;br /&gt;
&lt;br /&gt;
As of this writing, the copy-builtin script places the spl and zfs modules into the kernel source in places where the modules may not initialize in the best order, &amp;lt;i&amp;gt;after&amp;lt;/i&amp;gt; all lower-level storage drivers are initialized. If spl and zfs initialize too soon, there is a chance they may not be able to see all of the storage devices. The order of initialization (as seen in dmesg) of modules that are builtin to the kernel is the order that the modules are linked into the kernel during kernel compilation. The order of link depends on where the module source files are located in the kernel source tree. To ensure that spl and zfs will initialize after all hardware drivers, we can move them into the &amp;lt;code&amp;gt;drivers&amp;lt;/code&amp;gt; tree and after all other drivers. This move is &amp;lt;b&amp;gt;optional&amp;lt;/b&amp;gt; and you can skip doing this and everything will probably work fine, but it is shown here how to move the modules to under drivers in case you prefer them there:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /usr/src/linux-3.2.28b&lt;br /&gt;
mkdir drivers/zfsonlinux&lt;br /&gt;
mv spl drivers/zfsonlinux&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  # remove references to spl&lt;br /&gt;
vi Makefile&lt;br /&gt;
  # remove references to spl&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.28b/fs&lt;br /&gt;
mv zfs ../drivers/zfsonlinux&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  # remove references to zfs&lt;br /&gt;
vi Makefile&lt;br /&gt;
  # remove references to zfs&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.28b/drivers&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  )# add line at end of menu, before &amp;quot;endmenu&amp;quot;:&lt;br /&gt;
  )source &amp;quot;drivers/zfsonlinux/Kconfig&amp;quot;&lt;br /&gt;
  )endmenu&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.28b/drivers&lt;br /&gt;
vi Makefile&lt;br /&gt;
  )# add line at very end of file:&lt;br /&gt;
  )obj-$(CONFIG_ZFSONLINUX) += zfsonlinux/&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.28b/drivers/zfsonlinux&lt;br /&gt;
cat &amp;gt; Kconfig &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
menuconfig ZFSONLINUX&lt;br /&gt;
	tristate &amp;quot;ZFSonLinux support&amp;quot;&lt;br /&gt;
&lt;br /&gt;
if ZFSONLINUX&lt;br /&gt;
&lt;br /&gt;
source &amp;quot;drivers/zfsonlinux/spl/Kconifg&amp;quot;&lt;br /&gt;
&lt;br /&gt;
source &amp;quot;drivers/zfsonlinux/zfs/Kconifg&amp;quot;&lt;br /&gt;
&lt;br /&gt;
endif&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.28b/zfsonlinux&lt;br /&gt;
cat &amp;gt; Makefile &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
obj-$(CONFIG_SPL) += spl/&lt;br /&gt;
obj-$(CONFIG_ZFS) += zfs/&lt;br /&gt;
EOF&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This completes the move of the spl and zfs modules in the kernel source tree to be under &amp;lt;code&amp;gt;drivers/zfsonlinux&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Now, in kernel configuration, you can build in the modules as follows:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /usr/src/linux-3.2.28b&lt;br /&gt;
make menuconfig&lt;br /&gt;
   Device Drivers -&amp;gt;&lt;br /&gt;
    &amp;lt;*&amp;gt; ZFSonLinux support -&amp;gt;&lt;br /&gt;
      &amp;lt;*&amp;gt; Solaris Porting Layer (SPL)&lt;br /&gt;
      &amp;lt;*&amp;gt;     ZFS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the kernel config, we set &amp;lt;code&amp;gt;/boot/initramfs-source&amp;lt;/code&amp;gt; as source location of the contents to be linked into kernel's builtin initramfs (rootfs). Now, we create some files that are needed to be in the initramfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /boot/initramfs-source&lt;br /&gt;
&lt;br /&gt;
# make standard directories&lt;br /&gt;
mkdir -p proc dev sys mnt bin sbin etc/zfs&lt;br /&gt;
&lt;br /&gt;
# zfs seems to want mtab present, even if empty&lt;br /&gt;
touch etc/mtab&lt;br /&gt;
&lt;br /&gt;
# if zpool.cache file can be read by zfs at module init, it imports the pools in the cache&lt;br /&gt;
cp /etc/zfs/zpool.cache-initrd etc/zfs/zpool.cache&lt;br /&gt;
&lt;br /&gt;
It is time to pause for a moment here and talk about zpool.cache: Using it is actually dangerous. We are not using udev and it's persistent block device filenames (/dev/disk/by-*), but are using the default kernel block device names (/dev/sd*) in devtmpfs. Device names for a hard drive in /dev can potentially change on boot depending on disk controller initialization order and disk drive response time. Adding another disk controller or hard disk on a controller can result in device name assignment changes to all the hard disks. A zpool.cache file holds all the zfs_member device filenames /dev/sd* for a pool configuration, but the zpool.cache configuration will be incorrect if device filenames have been changed or swapped around and this could result in a faulted pool that may or may not be recoverable. Using zpool.cache to import pools at boot, even with udev persistent device filenames, is potentially destructive if devices have been changed around. The proper thing to do is zpool_import and do not include zpool.cache in the initramfs.&lt;br /&gt;
&lt;br /&gt;
# make initial console device node; otherwise, there is a problem at startup:&lt;br /&gt;
# &amp;quot;Warning: unable to open an initial console&amp;quot; and you'd have problems with console and tty login&lt;br /&gt;
# making these nodes from within /init is not early enough to avoid problem&lt;br /&gt;
mknod dev/console c 5 1   # system console&lt;br /&gt;
&lt;br /&gt;
# make memory device kmsg to &amp;quot;printk&amp;quot; kernel messages&lt;br /&gt;
# we can write to this file to send out messages&lt;br /&gt;
mknod dev/kmsg    c 1 11  # lines printed to kmsg enter kernel messages buffer&lt;br /&gt;
&lt;br /&gt;
# recommended loop0 device to mount fs images&lt;br /&gt;
mknod dev/loop0   b 7 0&lt;br /&gt;
&lt;br /&gt;
# make initial virtual terminal devices&lt;br /&gt;
mknod dev/tty     c 5 0   # current tty&lt;br /&gt;
mknod dev/tty0    c 4 0   # current virtual term&lt;br /&gt;
mknod dev/tty1    c 4 1   # login virtual term 1 (F1)&lt;br /&gt;
&lt;br /&gt;
# make alternative console=ttyS0 standard 8250/16550 UART serial port devices&lt;br /&gt;
#   useful with kernel parameter console=ttyS0&lt;br /&gt;
#          with qemu -nographic -option-rom sgabios.bin,bootindex=0&lt;br /&gt;
mknod dev/ttyS0   c 4 64  # COM1&lt;br /&gt;
mknod dev/ttyS1   c 4 65  # COM2&lt;br /&gt;
mknod dev/ttyS2   c 4 66  # COM3&lt;br /&gt;
mknod dev/ttyS3   c 4 67  $ COM4&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This should be enough device nodes initially in the initramfs. Once devtmpfs mounts over /dev inside initramfs, a lot more devices are available in it by default.&lt;br /&gt;
&lt;br /&gt;
The initramfs needs an &amp;lt;code&amp;gt;/init&amp;lt;/code&amp;gt; program that will be run automatically by the kernel as process id 1, the first program to run on the system. This program's task is to mount a root filesystem, switch it to be the new root (/), and then exec the init (&amp;lt;code&amp;gt;/sbin/init&amp;lt;/code&amp;gt;) program that is on the new root so that the new root system is booted.&lt;br /&gt;
&lt;br /&gt;
The common way to make /init is using busybox with files like these in /boot/initrd-tree or /boot/initramfs-source:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
bin/busybox&lt;br /&gt;
bin/ash -&amp;gt; busybox&lt;br /&gt;
bin/sh -&amp;gt; busybox&lt;br /&gt;
# run busybox to see what other &amp;quot;applets&amp;quot; can be symlinked to it&lt;br /&gt;
# when busybox is run as a different symlinked applet name, it runs as the applet&lt;br /&gt;
init&lt;br /&gt;
# init can be an ash script, see slackware's /boot/initrd-tree/init for example&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For example, as an ash script, slackware's init does the following:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;parse kernel parameters passed into it and set variables based on them&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;start udevd and trigger rules for block devices to setup initial /dev devices&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;load kernel modules and keyboard map&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;run mdadm, cryptsetup, lvm, zpool/zfs to setup more devices&lt;br /&gt;
     (any udev rules for them should do more /dev setup in the background)&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;mount the root filesystem read-only at /mnt&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;stat /mnt/sbin/init, and if not executable run a rescue shell /bin/sh&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;shutdown udevd so it can be restarted by root system when booted&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;mount --move {proc,sys,run,dev} to under /mnt&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;run: exec switch_root /mnt /sbin/init $RUNLEVEL&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The slackware mkinitrd package is a fully configured BusyBox installation that makes an external initramfs image file, initrd.gz, that is passed to the kernel by the bootloader (lilo). It could be changed to be internal to the kernel by just using initrd-tree as the CONFIG_INITRAMFS_SOURCE in the kernel config and removing initrd in the lilo.conf.&lt;br /&gt;
&lt;br /&gt;
The main purpose of most initramfs/initrd is to load and configure kernel modules and devices needed to mount a root filesystem. Because the spl/zfs modules are builtin, there isn't really a lot that needs to be done by an initramfs. What remains to be done is import the zfs-root pool, mount it, and exec the system /sbin/init. The kernel's &amp;quot;legacy&amp;quot; parameters &amp;lt;code&amp;gt;root=&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;rootfstype=&amp;lt;/code&amp;gt; that are able to directly boot a root disk do not work with ZFS at this time because ZFS pools always need to be imported before it is possible to mount and boot on them. The automatic import that ZFS can do by using a cachefile (/etc/zfs/zpool.cache) stored in initramfs still does not work with the legacy boot parameters because at an earlier stage of the boot process, the kernel ignores a rootfs that does not contain an &amp;lt;code&amp;gt;/init&amp;lt;/code&amp;gt; program, and/or the device type of an imported pool is not the device types recognized by the legacy boot as valid root devices.&lt;br /&gt;
&lt;br /&gt;
You could just continue to use slackware's mkinitrd package as in the &amp;quot;ZFS root&amp;quot; wiki and it works the same whether the modules are builtin or not. But, by building the spl/zfs modules in, aren't we really wanting to get rid of using the mkinitrd/initrd.gz? We'd like to have a kernel with everything in it to boot, and use a simple lilo image entry that has no initrd.&lt;br /&gt;
&lt;br /&gt;
We can do this, and not use the mkinitrd package, but we still need to finish our own initramfs &amp;lt;code&amp;gt;/init&amp;lt;/code&amp;gt; program to import, mount, switch root, and boot. Save the following c program to &amp;quot;foobarz-init.c&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/* software product name: foobarz-init.c&lt;br /&gt;
 * suggested binary name: /init (in initramfs-source, rootfs)&lt;br /&gt;
 * license              : BSD&lt;br /&gt;
 * license text:&lt;br /&gt;
Copyright (c) 2012, foobarz&lt;br /&gt;
All rights reserved.&lt;br /&gt;
&lt;br /&gt;
Redistribution and use in source and binary forms, with or without&lt;br /&gt;
modification, are permitted provided that the following conditions are met:&lt;br /&gt;
    * Redistributions of source code must retain the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer.&lt;br /&gt;
    * Redistributions in binary form must reproduce the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer in the&lt;br /&gt;
      documentation and/or other materials provided with the distribution.&lt;br /&gt;
    * Neither the name of the &amp;lt;organization&amp;gt; nor the&lt;br /&gt;
      names of its contributors may be used to endorse or promote products&lt;br /&gt;
      derived from this software without specific prior written permission.&lt;br /&gt;
&lt;br /&gt;
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &amp;quot;AS IS&amp;quot; AND&lt;br /&gt;
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED&lt;br /&gt;
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE&lt;br /&gt;
DISCLAIMED. IN NO EVENT SHALL &amp;lt;COPYRIGHT HOLDER&amp;gt; BE LIABLE FOR ANY&lt;br /&gt;
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES&lt;br /&gt;
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;&lt;br /&gt;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND&lt;br /&gt;
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT&lt;br /&gt;
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS&lt;br /&gt;
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
/* Your initramfs-source should contain the following&lt;br /&gt;
 *&lt;br /&gt;
 * cd /boot/initramfs-source&lt;br /&gt;
 * mkdir -p proc dev sys mnt bin sbin etc/zfs&lt;br /&gt;
 * touch etc/mtab&lt;br /&gt;
 * cp /etc/zfs/zpool.cache-initrd etc/zfs/zpool.cache&lt;br /&gt;
 * # zpool.cache is optional - zpool_import_ kernel params can be used instead&lt;br /&gt;
 * #  see below for details on using zpool_import&lt;br /&gt;
 * mknod dev/console c 5 1   # system console&lt;br /&gt;
 * mknod dev/kmsg    c 1 11  # lines printed to kmsg enter kernel messages buffer&lt;br /&gt;
 * mknod dev/loop0   b 7 0&lt;br /&gt;
 * mknod dev/tty     c 5 0   # current tty&lt;br /&gt;
 * mknod dev/tty0    c 4 0   # current virtual term&lt;br /&gt;
 * mknod dev/tty1    c 4 1   # login virtual term 1 (F1)&lt;br /&gt;
 * mknod dev/ttyS0   c 4 64  # COM1&lt;br /&gt;
 * mknod dev/ttyS1   c 4 65  # COM2&lt;br /&gt;
 * mknod dev/ttyS2   c 4 66  # COM3&lt;br /&gt;
 * mknod dev/ttyS3   c 4 67  $ COM4&lt;br /&gt;
 *&lt;br /&gt;
 * and this program compiled to /boot/initramfs-source/init&lt;br /&gt;
 *&lt;br /&gt;
 * Set kernel config option&lt;br /&gt;
 *  CONFIG_INITRAMFS_SOURCE=/boot/initramfs-source&lt;br /&gt;
 * to build the initramfs into your kernel image&lt;br /&gt;
 *  that also has builtin drivers (spl and zfs, etc).&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
#define FOOBARZ_INIT_VERSION &amp;quot;1.1.1&amp;quot;&lt;br /&gt;
#define _BSD_SOURCE&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdarg.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;fcntl.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/mount.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sysexits.h&amp;gt;&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
/* support for zpool import&lt;br /&gt;
 *&lt;br /&gt;
 * If -DINCLUDE_ZPOOL_IMPORT, then support to import a zpool is&lt;br /&gt;
 * enabled in the program. Enabling it will add many dependencies to the&lt;br /&gt;
 * compile and link; for example:&lt;br /&gt;
 *&lt;br /&gt;
 * gcc -static -DINCLUDE_ZPOOL_IMPORT \&lt;br /&gt;
 *    foobarz-init.c -include /usr/src/zfs-0.6.0-rc11/3.2.28/zfs_config.h \&lt;br /&gt;
 *   -o init \&lt;br /&gt;
 *   -I /usr/include/libspl -I /usr/include/libzfs \&lt;br /&gt;
 *   -lzfs -lnvpair -lzpool -luutil -luuid -lrt -lz -lm -lpthread \&lt;br /&gt;
 *   -I /usr/include/tirpc \&lt;br /&gt;
 *   -ltirpc&lt;br /&gt;
 *&lt;br /&gt;
 * Note that libtirpc is a drop-in replacement for the SunRPC functions that&lt;br /&gt;
 * used to be in glibc. No additional includes are needed, just the gcc -I and -l&lt;br /&gt;
 * options for tirpc.&lt;br /&gt;
 *&lt;br /&gt;
 * Otherwise, with -UINCLUDE_ZPOOL_IMPORT, the compile is just:&lt;br /&gt;
 * gcc -static foobarz-init.c -o init&lt;br /&gt;
 */&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
#include &amp;lt;libzfs.h&amp;gt;&lt;br /&gt;
#else&lt;br /&gt;
#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/stat.h&amp;gt;&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#define PARAM_REQ_NO 0&lt;br /&gt;
#define PARAM_REQ_YES 1&lt;br /&gt;
#define PARAM_SRC_DEFAULT 0&lt;br /&gt;
#define PARAM_SRC_CMDLINE 1&lt;br /&gt;
&lt;br /&gt;
void printk(char *fmt, ...) {&lt;br /&gt;
  FILE* f;&lt;br /&gt;
  int fd;&lt;br /&gt;
  va_list args;&lt;br /&gt;
&lt;br /&gt;
  f = fopen(&amp;quot;/dev/kmsg&amp;quot;, &amp;quot;w&amp;quot;);&lt;br /&gt;
  va_start(args, fmt);&lt;br /&gt;
  vfprintf(f, fmt, args);&lt;br /&gt;
  va_end(args);&lt;br /&gt;
  fflush(f);&lt;br /&gt;
  fclose(f);&lt;br /&gt;
  /* avoid flooding kmsg and having msgs suppressed; 20msgs/sec */&lt;br /&gt;
  usleep(50000);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[]) {&lt;br /&gt;
 /*** variables */&lt;br /&gt;
&lt;br /&gt;
 int i;&lt;br /&gt;
 int   fd = 0; /* file descriptor */&lt;br /&gt;
 unsigned long mountflags;&lt;br /&gt;
&lt;br /&gt;
 /* kernel command line */&lt;br /&gt;
 off_t cmdline_size;&lt;br /&gt;
 char* cmdline; /* to be malloc 4096B */&lt;br /&gt;
 char* cmdline_end;&lt;br /&gt;
 char* temp_end;&lt;br /&gt;
 char* src_msg; /* default or cmdline */&lt;br /&gt;
 int flag_param_missing = 0;&lt;br /&gt;
&lt;br /&gt;
 /* use to hold contents of a misc /proc/&amp;lt;file&amp;gt; */&lt;br /&gt;
 char* miscproc_buff; /* to be malloc 4096B */&lt;br /&gt;
 off_t miscproc_size;&lt;br /&gt;
&lt;br /&gt;
 /* note about environ, argv, and kernel cmdline for init:&lt;br /&gt;
  *   environ is not defined for init&lt;br /&gt;
  *   only argv[0] is set for init&lt;br /&gt;
  *   kernel command line parameters are accessed&lt;br /&gt;
  *   at /proc/cmdline&lt;br /&gt;
  */&lt;br /&gt;
&lt;br /&gt;
 /* kernel parameters expected to be name=value */&lt;br /&gt;
 /* do not use quotes or spaces in parameters   */&lt;br /&gt;
 /* you can add more params somwhere after root= */&lt;br /&gt;
 struct nv { char* n; char* v; char* v_end; int req; int src; };&lt;br /&gt;
 struct nv param[] = {&lt;br /&gt;
   { &amp;quot;root=&amp;quot;,       NULL, NULL, PARAM_REQ_YES, PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;rootfstype=&amp;quot;, NULL, NULL, PARAM_REQ_YES, PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;mountopt=&amp;quot;,   NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;init=&amp;quot;,       NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;runlevel=&amp;quot;,   NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;console=&amp;quot;,    NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT }&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
   ,&lt;br /&gt;
   { &amp;quot;zpool_import_name=&amp;quot;,    NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;zpool_import_guid=&amp;quot;,    NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;zpool_import_newname=&amp;quot;, NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;zpool_import_force=&amp;quot;,   NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT }&lt;br /&gt;
#endif&lt;br /&gt;
 };&lt;br /&gt;
 enum {&lt;br /&gt;
	 iroot,&lt;br /&gt;
	 irootfstype,&lt;br /&gt;
	 imountopt,&lt;br /&gt;
	 iinit,&lt;br /&gt;
	 irunlevel,&lt;br /&gt;
	 iconsole,&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
	 izpool_import_name,&lt;br /&gt;
	 izpool_import_guid,&lt;br /&gt;
	 izpool_import_newname,&lt;br /&gt;
	 izpool_import_force,&lt;br /&gt;
#endif&lt;br /&gt;
	 ilastparam&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
 libzfs_handle_t* libzfs = NULL;&lt;br /&gt;
 importargs_t iargs = { 0 };&lt;br /&gt;
 nvlist_t* pools = NULL;&lt;br /&gt;
 nvpair_t* pool = NULL;&lt;br /&gt;
 nvlist_t* config = NULL;&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
 /*** program */&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;foobarz-init, version %s: booting initramfs.\n&amp;quot;, FOOBARZ_INIT_VERSION);&lt;br /&gt;
&lt;br /&gt;
 cmdline       = (char*) malloc(4096);&lt;br /&gt;
 miscproc_buff = (char*) malloc(4096);&lt;br /&gt;
 if( (cmdline == NULL) || (miscproc_buff == NULL) ) {&lt;br /&gt;
   printk(&amp;quot;Unable to allocate buffer memory: malloc: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount proc /proc&lt;br /&gt;
  *  note: some /dev devices symlink into /proc&lt;br /&gt;
  *  proc contains info about processes, including cmdline etc. */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount proc /proc\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;proc&amp;quot;, &amp;quot;/proc&amp;quot;, &amp;quot;proc&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
   printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
   printk(&amp;quot;Mount proc successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount devtmpfs /dev&lt;br /&gt;
  *  note: This simple init program works if your root device is made from devices&lt;br /&gt;
  *  that are available by default in devtmpfs, such as /dev/sd*&lt;br /&gt;
  *&lt;br /&gt;
  *  For zfs, your root zfs pool should be created with default device nodes and&lt;br /&gt;
  *  then it should be mountable by this simple init program.&lt;br /&gt;
  *&lt;br /&gt;
  *  udev may be needed to configure device nodes and symlinks required&lt;br /&gt;
  *  to access a root device configuration made with such nodes and symlinks.&lt;br /&gt;
  *  If you need udevd, you can include it into your initramfs-source and&lt;br /&gt;
  *  modify this program to run it before attempting to mount your root device.&lt;br /&gt;
  *  However, if udevd is needed, a significant number of userspace programs may also be&lt;br /&gt;
  *  required by rules in /lib/udev/. You could install busybox + udev (about 5MB) or&lt;br /&gt;
  *  coreutils + util-linux + bash + udev (about 25MB) into initramfs-source. But, at that&lt;br /&gt;
  *  point you'd have ash or bash and many tools that are easier to use than this&lt;br /&gt;
  *  simple init program; it would then be easy to have /init as #!/bin/&amp;lt;b&amp;gt;ash script. */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount devtmpfs /dev\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;devtmpfs&amp;quot;, &amp;quot;/dev&amp;quot;, &amp;quot;devtmpfs&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
   printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
   printk(&amp;quot;Mount devtmpfs successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount sysfs /sys&lt;br /&gt;
  *  note: some kernel modules try to access /sys with userspace helpers to echo values into /sys variables;&lt;br /&gt;
  *  such modules expect a minimal userspace that contains coreutils or busybox */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount sysfs /sys\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;sysfs&amp;quot;, &amp;quot;/sys&amp;quot;, &amp;quot;sysfs&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
   printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
   printk(&amp;quot;Mount sysfs successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* process kernel command line */&lt;br /&gt;
 fd = open(&amp;quot;/proc/cmdline&amp;quot;, O_RDONLY);&lt;br /&gt;
 if( fd == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Cannot open /proc/cmdline: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 /* note, on /proc fs:&lt;br /&gt;
  *       lseek likely always returns error&lt;br /&gt;
  *       stat likely always returns st_size = 0&lt;br /&gt;
  *   so determining size of /proc file means just reading it;&lt;br /&gt;
  *   you have to read /proc files according to their documented&lt;br /&gt;
  *   maximum sizes; this is probably for performance reasons */&lt;br /&gt;
 cmdline_size = read(fd, cmdline, 4095);&lt;br /&gt;
 if( cmdline_size == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Failed to read /proc/cmdline: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 close(fd);&lt;br /&gt;
&lt;br /&gt;
 /* cmdline may be newline + null terminated, but make it null + null */&lt;br /&gt;
 cmdline[cmdline_size] = '\0';&lt;br /&gt;
 if( cmdline[cmdline_size-1] == '\n' ) {&lt;br /&gt;
   cmdline[cmdline_size-1] = '\0';&lt;br /&gt;
   cmdline_size--;&lt;br /&gt;
   cmdline_end = cmdline + cmdline_size;&lt;br /&gt;
 }&lt;br /&gt;
 printk(&amp;quot;Kernel cmdline size: %i\n&amp;quot;, cmdline_size);&lt;br /&gt;
 printk(&amp;quot;Kernel cmdline: \&amp;quot;%s\&amp;quot;\n&amp;quot;, cmdline);&lt;br /&gt;
&lt;br /&gt;
 /* find v and v_end of values in cmdline */&lt;br /&gt;
 for( i=iroot; i&amp;lt;ilastparam; i++ ) {&lt;br /&gt;
   param[i].v = strstr(cmdline, param[i].n);&lt;br /&gt;
   if( param[i].v != NULL ) {&lt;br /&gt;
     param[i].src = PARAM_SRC_CMDLINE;&lt;br /&gt;
     while( *(param[i].v) != '=' ) param[i].v++;&lt;br /&gt;
     param[i].v++;&lt;br /&gt;
     temp_end = param[i].v;&lt;br /&gt;
     while( !( (*temp_end == ' ') ||&lt;br /&gt;
               (*temp_end == '\n') ||&lt;br /&gt;
               (temp_end == cmdline_end)&lt;br /&gt;
	     ) ) temp_end++;&lt;br /&gt;
     if( temp_end == param[i].v ) {&lt;br /&gt;
       printk(&amp;quot;Kernel parameter %s: value missing.\n&amp;quot;, param[i].n);&lt;br /&gt;
       param[i].v = NULL;&lt;br /&gt;
     } else param[i].v_end = temp_end;&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 for( i=iroot; i&amp;lt;ilastparam; i++ ) {&lt;br /&gt;
   /* terminate value strings */&lt;br /&gt;
   if( param[i].v_end != NULL ) *(param[i].v_end) = '\0';&lt;br /&gt;
   /* set defaults if no value on cmdline */&lt;br /&gt;
   if( param[i].v == NULL ) {&lt;br /&gt;
     param[i].src = PARAM_SRC_DEFAULT;&lt;br /&gt;
     if( param[i].req == PARAM_REQ_YES ) flag_param_missing = 1;&lt;br /&gt;
     switch(i) {&lt;br /&gt;
       case iroot      : param[i].v = &amp;quot;&amp;lt;missing required param&amp;gt;&amp;quot; ; break;&lt;br /&gt;
       case irootfstype: param[i].v = &amp;quot;&amp;lt;missing required param&amp;gt;&amp;quot; ; break;&lt;br /&gt;
       case imountopt  : param[i].v = &amp;quot;ro&amp;quot;        ; break;&lt;br /&gt;
       case iinit      : param[i].v = &amp;quot;/sbin/init&amp;quot;; break;&lt;br /&gt;
       case irunlevel  : param[i].v = &amp;quot;3&amp;quot;         ; break;&lt;br /&gt;
       case iconsole   : param[i].v = &amp;quot;console&amp;quot;   ; break;&lt;br /&gt;
       default         : param[i].v = NULL;&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
   if(param[i].src == PARAM_SRC_DEFAULT) src_msg = &amp;quot;default&amp;quot;;&lt;br /&gt;
   else src_msg = &amp;quot;cmdline&amp;quot;;&lt;br /&gt;
   printk(&amp;quot;Using %s \&amp;quot;%s\&amp;quot; (source: %s)\n&amp;quot;, param[i].n, param[i].v, src_msg);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 if( flag_param_missing ) {&lt;br /&gt;
   printk(&amp;quot;Aborting boot process: missing required kernel parameter(s).\n&amp;quot;);&lt;br /&gt;
   return EX_USAGE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* generic nv pair kernel cmdline processing finished&lt;br /&gt;
  *  now, examine specific params for defaults and correctness */&lt;br /&gt;
&lt;br /&gt;
 /* param[irootfstype]: can be checked against /proc/filesystems: */&lt;br /&gt;
 fd = open(&amp;quot;/proc/filesystems&amp;quot;, O_RDONLY);&lt;br /&gt;
 if( fd == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Cannot open /proc/filesystems: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 miscproc_size = read(fd, miscproc_buff, 4095);&lt;br /&gt;
 if( miscproc_size == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Failed to read /proc/filesystems: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 close(fd);&lt;br /&gt;
 if( strstr(miscproc_buff, param[irootfstype].v) == NULL ) {&lt;br /&gt;
   printk(&amp;quot;%s \&amp;quot;%s\&amp;quot;: filesystem type not available.\n&amp;quot;, param[irootfstype].n, param[irootfstype].v);&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* zfs-specific */&lt;br /&gt;
 if( strcmp(param[irootfstype].v, &amp;quot;zfs&amp;quot;) == 0 ) {&lt;br /&gt;
   if( access(&amp;quot;/etc/zfs/zpool.cache&amp;quot;, F_OK) == 0 )&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/zfs/zpool.cache is present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
   else&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/zfs/zpool.cache not present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
&lt;br /&gt;
   if( access(&amp;quot;/etc/hostid&amp;quot;, F_OK) == 0 )&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/hostid is present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
   else&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/hostid not present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
   /* zpool import */&lt;br /&gt;
   if( (param[izpool_import_name].v != NULL) || (param[izpool_import_guid].v != NULL) ) {&lt;br /&gt;
	printk(&amp;quot;zpool_import: import requested.\n&amp;quot;);&lt;br /&gt;
	if( (param[izpool_import_name].v != NULL) &amp;amp;&amp;amp; (param[izpool_import_guid].v != NULL) ) {&lt;br /&gt;
		printk(&amp;quot;zpool_import: given both pool name and guid; using guid.\n&amp;quot;);&lt;br /&gt;
		param[izpool_import_name].v = NULL;&lt;br /&gt;
	}&lt;br /&gt;
	if( param[izpool_import_name].v != NULL )&lt;br /&gt;
		printk(&amp;quot;zpool_import: pool name: %s\n&amp;quot;, param[izpool_import_name].v );&lt;br /&gt;
	else&lt;br /&gt;
		printk(&amp;quot;zpool_import: pool guid: %s\n&amp;quot;, param[izpool_import_guid].v );&lt;br /&gt;
&lt;br /&gt;
	iargs.path = NULL;&lt;br /&gt;
	iargs.paths = 0;&lt;br /&gt;
	iargs.poolname = param[izpool_import_name].v;&lt;br /&gt;
	if( param[izpool_import_guid].v != NULL )&lt;br /&gt;
		iargs.guid = strtoull(param[izpool_import_guid].v, NULL, 10);&lt;br /&gt;
	else&lt;br /&gt;
		iargs.guid = 0;&lt;br /&gt;
	iargs.cachefile = NULL;&lt;br /&gt;
	if( (param[izpool_import_force].v != NULL) &amp;amp;&amp;amp; (strcmp(param[izpool_import_force].v, &amp;quot;1&amp;quot;) == 0) ) {&lt;br /&gt;
		iargs.can_be_active = 1;&lt;br /&gt;
		printk(&amp;quot;zpool_import: import forced.\n&amp;quot;);&lt;br /&gt;
	} else {&lt;br /&gt;
		iargs.can_be_active = 0;&lt;br /&gt;
		printk(&amp;quot;zpool_import: import not forced.\n&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
	iargs.unique = 1;&lt;br /&gt;
	iargs.exists = 1;&lt;br /&gt;
&lt;br /&gt;
	printk(&amp;quot;zpool_import: init libzfs.\n&amp;quot;);&lt;br /&gt;
	libzfs = libzfs_init();&lt;br /&gt;
	printk(&amp;quot;zpool_import: searching for pool.\n&amp;quot;);&lt;br /&gt;
	pools = zpool_search_import(libzfs, &amp;amp;iargs);&lt;br /&gt;
	if( (pools == NULL) || nvlist_empty(pools) )&lt;br /&gt;
		printk(&amp;quot;zpool_import: pool not available for import, or already imported by cachefile.\n&amp;quot;);&lt;br /&gt;
	else {&lt;br /&gt;
		printk(&amp;quot;zpool_import: getting pool information.\n&amp;quot;);&lt;br /&gt;
		pool = nvlist_next_nvpair(pools, pool);&lt;br /&gt;
		printk(&amp;quot;zpool_import: getting pool configuration.\n&amp;quot;);&lt;br /&gt;
		nvpair_value_nvlist(pool, &amp;amp;config);&lt;br /&gt;
		printk(&amp;quot;zpool_import: attempting pool import.\n&amp;quot;);&lt;br /&gt;
		if( zpool_import(libzfs, config, param[izpool_import_newname].v, NULL) != 0 ) {&lt;br /&gt;
			printk(&amp;quot;zpool_import: import failed.\n&amp;quot;);&lt;br /&gt;
			printk(&amp;quot;zpool_import: error description: %s\n&amp;quot;, libzfs_error_description(libzfs) );&lt;br /&gt;
			printk(&amp;quot;zpool_import: error action: %s\n&amp;quot;, libzfs_error_action(libzfs) );&lt;br /&gt;
		} else  printk(&amp;quot;zpool_import: import successful.\n&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
	printk(&amp;quot;zpool_import: fini libzfs.\n&amp;quot;);&lt;br /&gt;
	libzfs_fini(libzfs);&lt;br /&gt;
   }&lt;br /&gt;
#endif /* zpool_import */&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 if(      strcmp(param[imountopt].v, &amp;quot;ro&amp;quot;) == 0 ) mountflags = MS_RDONLY;&lt;br /&gt;
 else if( strcmp(param[imountopt].v, &amp;quot;rw&amp;quot;) == 0 ) mountflags = 0;&lt;br /&gt;
 else {&lt;br /&gt;
   printk(&amp;quot;%s \&amp;quot;%s\&amp;quot;: invalid parameter value; defaulting to \&amp;quot;ro\&amp;quot;.\n&amp;quot;, param[imountopt].n, param[imountopt].v);&lt;br /&gt;
   mountflags = MS_RDONLY;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* param[iroot]: nothing to check; if user gives bad root=device then mount fails */&lt;br /&gt;
&lt;br /&gt;
 /* try to mount root=device at /mnt&lt;br /&gt;
  *&lt;br /&gt;
  * note: for zfs, if a copy of /etc/zfs/zpool.cache (when pool is imported) is put in initramfs-source, then&lt;br /&gt;
  * the zfs module can read it and automatically import the pools described in the cache file; the imported&lt;br /&gt;
  * pools can be available to mount here if they were created using standard device names, otherwise&lt;br /&gt;
  * udevd may be required to run before mounting the pool */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount -t %s -o %s %s /mnt.\n&amp;quot;, param[irootfstype].v, param[imountopt].v, param[iroot].v);&lt;br /&gt;
 if( mount(param[iroot].v, &amp;quot;/mnt&amp;quot;, param[irootfstype].v, mountflags, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 printk(&amp;quot;%s mounted successfully.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
&lt;br /&gt;
 /* check to see if the mounted root filesystem has an executable init program */&lt;br /&gt;
 chdir(&amp;quot;/mnt&amp;quot;);&lt;br /&gt;
 if( access(param[iinit].v+1, X_OK) != 0 ) {&lt;br /&gt;
   chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
   printk(&amp;quot;access X_OK: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   printk(&amp;quot;The init program /mnt/%s is not present or not executable.\n&amp;quot;, param[iinit].v+1);&lt;br /&gt;
   printk(&amp;quot;Aborting boot process: no init program.\n&amp;quot;);&lt;br /&gt;
   printk(&amp;quot;Unmounting %s.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
   if( umount(&amp;quot;/mnt&amp;quot;) == -1 ) {&lt;br /&gt;
     printk(&amp;quot;umount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
     printk(&amp;quot;Failed to umount %s.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
   } else printk(&amp;quot;Successfully unmounted %s.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
 printk(&amp;quot;Init program /mnt/%s is present and executable.\n&amp;quot;, param[iinit].v+1);&lt;br /&gt;
&lt;br /&gt;
 /* switch the root / from initramfs to the mounted new root device at /mnt.&lt;br /&gt;
  *&lt;br /&gt;
  * note: after this switch, it is not possible to access the initramfs files anymore,&lt;br /&gt;
  * yet they consume ram memory unless they are deleted here before switching.&lt;br /&gt;
  * Any programs that are run after clearing the initramfs and switching root must exist on the new root.&lt;br /&gt;
  * This program may safely delete itself (/init) since it is already in ram and executing.&lt;br /&gt;
  * If you have installed additional files and programs in initramfs that consume significant ram,&lt;br /&gt;
  * then you need to insert additional code here to delete those files (carefully). */&lt;br /&gt;
&lt;br /&gt;
 /* delete files off of initramfs to free ram memory */&lt;br /&gt;
 printk(&amp;quot;Freeing memory from initramfs...\n&amp;quot;);&lt;br /&gt;
 if( unlink(argv[0]) != 0 ) printk(&amp;quot;unlink %s: %s\n&amp;quot;, argv[0], strerror(errno));&lt;br /&gt;
 else printk(&amp;quot;%s %s&amp;quot;, argv[0], &amp;quot;deleted from initramfs.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 /* switch root */&lt;br /&gt;
 printk(&amp;quot;Beginning switch root procedure.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(1) Attempting cmd: mount --move /dev /mnt/dev \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/dev&amp;quot;, &amp;quot;/mnt/dev&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(2) Attempting cmd: mount --move /proc /mnt/proc \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/proc&amp;quot;, &amp;quot;/mnt/proc&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(3) Attempting cmd: mount --move /sys /mnt/sys \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/sys&amp;quot;, &amp;quot;/mnt/sys&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(4) Attempting cmd: chdir /mnt \n&amp;quot;);&lt;br /&gt;
 if( chdir(&amp;quot;/mnt&amp;quot;) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: chdir: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(5) Attempting cmd: mount --move . / \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;.&amp;quot;, &amp;quot;/&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(6) Attempting cmd: chroot . \n&amp;quot;);&lt;br /&gt;
 if( chroot(&amp;quot;.&amp;quot;) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: chroot: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(7) Attempting cmd: chdir / \n&amp;quot;);&lt;br /&gt;
 if( chdir(&amp;quot;/&amp;quot;) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: chdir: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 printk(&amp;quot;Completed switch root procedure.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 /* check for &amp;quot;console=&amp;quot; kernel parameter and switch&lt;br /&gt;
  *  stdin, stdout, and stderr to named console device&lt;br /&gt;
  */&lt;br /&gt;
 if( param[iconsole].src == PARAM_SRC_CMDLINE ) {&lt;br /&gt;
   printk(&amp;quot;Console redirection to device %s requested.\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
   /* expect only basename of console device (e.g., ttyS0), so chdir /dev */&lt;br /&gt;
   chdir(&amp;quot;/dev&amp;quot;);&lt;br /&gt;
   if( access(param[iconsole].v, F_OK ) == 0 ) {&lt;br /&gt;
     printk(&amp;quot;Opening stdin, stdout, and stderr on %s.\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
     close(0);&lt;br /&gt;
     open(param[iconsole].v, O_RDWR);&lt;br /&gt;
     dup2(0, 1);&lt;br /&gt;
     dup2(0, 2);&lt;br /&gt;
   } else {&lt;br /&gt;
     printk(&amp;quot;access F_OK: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
     printk(&amp;quot;Could not access device: %s!\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
     printk(&amp;quot;Console redirection to device %s aborted!\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
   }&lt;br /&gt;
   chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;Execing: \&amp;quot;%s %s\&amp;quot; to boot mounted root system.\n&amp;quot;, param[iinit].v, param[irunlevel].v);&lt;br /&gt;
&lt;br /&gt;
 /* free resources held to this point */&lt;br /&gt;
 free(cmdline);&lt;br /&gt;
 free(miscproc_buff);&lt;br /&gt;
&lt;br /&gt;
 if( execl(param[iinit].v, param[irunlevel].v, (char *) NULL ) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: execl: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If foobarz-init is updated, you can find the latest version at [https://github.com/foobarz/foobarz-init github].&lt;br /&gt;
&lt;br /&gt;
The foobarz-init program can be compiled two ways as of v1.1.1. First, the simpler compile that does not support zpool_import but does support importing pools using a /etc/zfs/zpool.cache file in the initramfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gcc --static init.c -o init&lt;br /&gt;
strip init&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The second way to compile it adds support for zpool_import so that you do not have to include a &amp;lt;code&amp;gt;/etc/zfs/zpool.cache&amp;lt;/code&amp;gt; file in the initramfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gcc -static -DINCLUDE_ZPOOL_IMPORT \&lt;br /&gt;
     foobarz-init.c -include /usr/src/linux-3.2.28b/zfs_config.h \&lt;br /&gt;
    -o init \&lt;br /&gt;
    -I /usr/include/libspl -I /usr/include/libzfs \&lt;br /&gt;
    -lzfs -lnvpair -lzpool -luutil -luuid -lrt -lz -lm -lpthread \&lt;br /&gt;
    -I /usr/include/tirpc \&lt;br /&gt;
    -ltirpc&lt;br /&gt;
strip init&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Dependencies required before you can compile this second way:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Install [http://sourceforge.net/projects/libtirpc/ libtirpc]. The glibc package has removed the RPC-related functions from the static libc. The libtirpc is the new replacement as a separate library. You can make your own libtirpc package and install it to resolve these RPC-related functions. Without this, the compile fails because it cannot find many &amp;quot;xdr&amp;quot; functions.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Reinstall the [ftp://slackware.mirrors.tds.net/pub/slackware/slackware64-current/source/a/util-linux/ util-linux] package with static libraries enabled. Edit the &amp;lt;code&amp;gt;util-linux.SlackBuild&amp;lt;/code&amp;gt; and remove the line &amp;lt;code&amp;gt;--disable-static&amp;lt;/code&amp;gt;, then build it and use upgradepkg to install the new package. This resolves linking static to libuuid.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;code&amp;gt;zfs_config.h&amp;lt;/code&amp;gt; can be found in the kernel source when you have installed the builtin spl/zfs configuration; for example at &amp;lt;code&amp;gt;/usr/src/linux-3.2.28b/zfs_config.h&amp;lt;/code&amp;gt;. If you currently have installed the modular spl/zfs configuration, &amp;lt;code&amp;gt;zfs_config.h&amp;lt;/code&amp;gt; is found where the zfs module headers are installed; for example at &amp;lt;code&amp;gt;/usr/src/zfs-0.6.0-rc11/3.2.28/zfs_config.h&amp;lt;/code&amp;gt;. Wherever it is, &amp;lt;code&amp;gt;-include&amp;lt;/code&amp;gt; it as shown in the example gcc line above. zfs_config.h seems misplaced because it would seem that using libzfs shouldn't depend on modules header files.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;You may need to install the spl and zfs packages configured for --enable-linux-builtin=yes before compiling and linking to libzfs to make sure you are using the version of libzfs intended for builtin modules in case a difference between the two configurations exists. Currently, there seems to be no difference in the libzfs for either modular or builtin modules, but later there could be at least a small difference for detection of modules to load or builtin already. You may see a message that the ZFS modules stack load failed, but it can be ignored since the modules are builtin; this is just libzfs trying to load the modules even though they are builtin.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
With these dependencies, you can probably compile static with the zpool_import support. The exact location of &amp;quot;zfs_config.h&amp;quot; may vary depending on your zfs and kernel versions, so adjust accordingly.&lt;br /&gt;
&lt;br /&gt;
Read the foobarz-init source code to see how it uses kernel parameters. The params &amp;lt;code&amp;gt;root&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;rootfstype&amp;lt;/code&amp;gt; are always required to tell init what root pool name to mount and the filesystem type (e.g. zfs).&lt;br /&gt;
&lt;br /&gt;
For the zpool_import support: &amp;lt;code&amp;gt;zpool_import_name=poolname&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;zpool_import_guid=&amp;lt;guid of a pool&amp;gt;&amp;lt;/code&amp;gt; tells what pool to import. You can also import the pool with a new different name by also using &amp;lt;code&amp;gt;zpool_import_newname=newpoolname&amp;lt;/code&amp;gt;. If the import is not working, &amp;lt;code&amp;gt;zpool_import_force=1&amp;lt;/code&amp;gt; can be used to force import even if ZFS thinks the pool may be in use by another system.&lt;br /&gt;
&lt;br /&gt;
However you import the pool, either using zpool.cache or zpool_import support, the kernel param &amp;lt;code&amp;gt;root=&amp;lt;your poolname or newpoolname&amp;gt;&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;rootfstype=zfs&amp;lt;/code&amp;gt; needs to be given also. The zpool_import only imports, it does not say what to mount. What to mount is still told using root= and rootfstype=.&lt;br /&gt;
&lt;br /&gt;
Now copy the compiled static program into the initramfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp init /boot/initramfs-source/init&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Build and install kernel:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /usr/src/linux-3.2.28b&lt;br /&gt;
make -j8&lt;br /&gt;
make -j8 modules_install&lt;br /&gt;
cp arch/x86/boot/bzImage /boot/vm3.2.28b&lt;br /&gt;
cp System.map /boot/System.map-vm3.2.28b&lt;br /&gt;
# add new lilo menu entry for vm3.2.28b kernel&lt;br /&gt;
vi /etc/lilo.conf&lt;br /&gt;
  image = /boot/vm3.2.28b&lt;br /&gt;
   label = vm3.2.28b&lt;br /&gt;
   addappend = &amp;quot; spl.spl_hostid=0x007f0100 zfs.spa_config_path=/etc/zfs/zpool.cache root=zfs-root rootfstype=zfs&amp;quot;&lt;br /&gt;
lilo&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Note: If &amp;lt;code&amp;gt;spl.spl_hostid=0x007f0100&amp;lt;/code&amp;gt; is not included in addappend, then during boot SPL module will attempt to read /etc/hostid or run a user-space helper to write the &amp;lt;code&amp;gt;hostid&amp;lt;/code&amp;gt; into &amp;lt;code&amp;gt;/proc/sys/kernel/spl/hostid&amp;lt;/code&amp;gt;. Reading /etc/hostid fails unless you use foobarz-chhostid and make the file and copy it into /boot/initramfs-source/etc/hostid. The helper will fail because no &amp;lt;code&amp;gt;sh&amp;lt;/code&amp;gt; shell and no &amp;lt;code&amp;gt;hostid&amp;lt;/code&amp;gt; command are installed in the initramfs. The default hostid becomes 0xffffffff, which is considered an invalid hostid.&lt;br /&gt;
&lt;br /&gt;
Congrats! If this works, you can select the &amp;quot;vm3.2.28b&amp;quot; lilo entry to boot. If you are using the zpool_import support in the init program, you need to add at least the &amp;lt;code&amp;gt;zpool_import_name=zfs-root&amp;lt;/code&amp;gt; param to the addappend line in lilo.conf.&lt;br /&gt;
&lt;br /&gt;
Notes on kernel params (lilo append and addappend lines): root= and rootfstype= are used by both foorbarz-init and mkinitrd. The &amp;quot;ro&amp;quot; param is not used by foobarz-init, so instead use: mountopt=ro|rw. See &amp;quot;modinfo spl&amp;quot; and &amp;quot;modinfo zfs&amp;quot; to see all of the options those modules can take on the kernel command line. Notice the &amp;lt;code&amp;gt;spl.spl_hostid=0x007f0100&amp;lt;/code&amp;gt; param that works around the hostid mismatch problem while trying to import a pool; this param and hostname/ip set to use local loopback 127.0.0.1 in etc/hosts etc/HOSTNAME in initramfs will work most of the time, and if not the pool import needs to be forced.&lt;br /&gt;
&lt;br /&gt;
Notes on the spl and zfs packages to install: &amp;lt;i&amp;gt;If&amp;lt;/i&amp;gt; you have errors using zfs and zpool commands on booted system with builtin modules, then upgrade/switch to the 0.6.0rc11_3.2.28b builds, or you can make a custom package with the binaries renamed like zpoolb, zfsb etc for builtin.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
Using qemu's -nographic serial console (/usr/share/qemu/sgabios.bin): If you have a boot problem, you might want to run in qemu's -nographic console mode:&lt;br /&gt;
&lt;br /&gt;
First, edit /etc/inittab, and uncomment the line for local serial ports runlevel &amp;quot;s1&amp;quot; (ttyS0) for serial console login support. This is done in the guest (host does not need this):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Local serial lines:&lt;br /&gt;
s1:12345:respawn:/sbin/agetty -L ttyS0 38400 linux&lt;br /&gt;
#s1:12345:respawn:/sbin/agetty -L ttyS0 9600 vt100&lt;br /&gt;
#s2:12345:respawn:/sbin/agetty -L ttyS1 9600 vt100&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Second, edit /etc/securetty, and uncomment ttyS0 line:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ttyS0&lt;br /&gt;
#ttyS1&lt;br /&gt;
# ...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
You cannot login on ttyS0 without this change even though you get the login prompt!&lt;br /&gt;
&lt;br /&gt;
Then, run qemu such as:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
qemu-kvm &amp;lt;all regular options&amp;gt; -nographic -option-rom sgabios.bin,bootindex=0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Wait for the lilo prompt, it may take several seconds show up in this mode.&lt;br /&gt;
&lt;br /&gt;
In the lilo menu, select your kernel image with builtin spl/zfs, and use kernel params such as:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
boot: vm3.2.28b console=ttyS0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
At the lilo prompt, use kernel parameter: console=ttyS0 (do NOT say /dev/ttS0). Passing runlevel=s1 does not appear to be necessary.&lt;br /&gt;
&lt;br /&gt;
When you are in qemu's serial mode, the interface is a little different than in the normal graphical mode: use keypresses:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ctrl-a h    # for help&lt;br /&gt;
ctrl-a c    # toggle access to (QEMU) console / back to emulation&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If you cannot get a login: prompt, try ctrl-a c, then do (QEMU) sendkey ctrl-alt-delete. This will reboot cleanly back to lilo, then you can do (QEMU) quit.&lt;br /&gt;
&lt;br /&gt;
Once you login to the guest, the terminal size needs adjustment. On your host, in another xterm sized the same as your guest console terminal, get the size of the terminal:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo $LINES&lt;br /&gt;
echo $COLUMNS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Now, back in the guest terminal of same size:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export LINES &amp;lt;lines&amp;gt;&lt;br /&gt;
export COLUMNS &amp;lt;columns&amp;gt;&lt;br /&gt;
stty cols $COLUMNS rows $LINES&lt;br /&gt;
exec bash&lt;br /&gt;
reset&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
So, you set the environment variables and also set them with stty. Then, restart bash (exec, or else it is a child shell process).&lt;br /&gt;
&lt;br /&gt;
BECAREFUL not to start qemu twice on the same ZFS guest! Two simultaneous running qemu on the same ZFS will corrupt the pool and it will NOT recover - you lose your whole installation! Before running qemu, check ps -A, look for an already running qemu process incase it somehow entered into the background!&lt;br /&gt;
&lt;br /&gt;
BECAREFUL when using -nographic ttyS0 that you are not doing commands on the HOST! Only use -nographic to see kernel problems. Use regular console if booting is working normally.&lt;br /&gt;
&lt;br /&gt;
To use the qemu -drive if=scsi option, the linux module sym53c8xx should be loaded in the guest. You may need to use the qemu option:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-option-rom 8xx_64.rom,bootindex=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The file 8xx_64.rom used to be inside qemu, but in new versions it is missing. You can download it:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
wget http://www.lsi.com/downloads/Public/Host%20Bus%20Adapters/Host%20Bus%20Adapters%20Common%20Files/lsi_bios.zip&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Extract the zip and place 8xx_64.rom in /usr/share/qemu/.&lt;br /&gt;
&lt;br /&gt;
Good luck!&lt;/div&gt;</description>
			<pubDate>Wed, 19 Sep 2012 13:28:18 GMT</pubDate>
			<dc:creator>Foobarz</dc:creator>
			<comments>https://www.slackwiki.com/Talk:ZFS_root_(builtin)</comments>
		</item>
		<item>
			<title>ZFS root (builtin)</title>
			<link>https://www.slackwiki.com/index.php?title=ZFS_root_(builtin)&amp;diff=799</link>
			<guid isPermaLink="false">https://www.slackwiki.com/index.php?title=ZFS_root_(builtin)&amp;diff=799</guid>
			<description>&lt;p&gt;Foobarz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Tutorials]]&lt;br /&gt;
The first [http://slackwiki.com/ZFS_root &amp;quot;ZFS root&amp;quot;] wiki explains the details of running ZFS as your root filesystem by using a fully modular generic kernel approach. Now, I can share how it can be done with the SPL and ZFS modules built into the kernel. This procedure is just an example and can use some fine tuning, but here goes:&lt;br /&gt;
&lt;br /&gt;
The steps below are to create a kernel with SPL and ZFS modules builtin. This kernel will be installed as an alternative kernel to boot in lilo, and it will have a separate kernel installation from the fully modular and working system kernel. This will allow testing the builtin kernel while able to boot back onto a working modular ZFS system. We start this procedure assuming you are on a working fully modular ZFS install as in the &amp;quot;ZFS root&amp;quot; wiki.&lt;br /&gt;
&lt;br /&gt;
Use mountpoint=legacy so that zfs will not expect &amp;lt;code&amp;gt;zfs mount&amp;lt;/code&amp;gt;, but instead expect standard &amp;lt;code&amp;gt;mount&amp;lt;/code&amp;gt; for mounting zfs-root:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=legacy zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Edit &amp;lt;code&amp;gt;/etc/rc.d/rc.S&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;rc.6&amp;lt;/code&amp;gt; to use regular &amp;lt;code&amp;gt;mount&amp;lt;/code&amp;gt; commands, remove &amp;lt;code&amp;gt;zfs&amp;lt;/code&amp;gt; commands. Edit &amp;lt;code&amp;gt;rc.6&amp;lt;/code&amp;gt; and remove or comment out &amp;lt;code&amp;gt;zpool export&amp;lt;/code&amp;gt; command. These edits undo changes made in the &amp;quot;ZFS root&amp;quot; wiki, but it shows the two different ways of mounting a zfs filesystem.&lt;br /&gt;
&lt;br /&gt;
You &amp;lt;i&amp;gt;might&amp;lt;/i&amp;gt; think to set &amp;lt;code&amp;gt;bootfs&amp;lt;/code&amp;gt; property like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool set bootfs=zfs-root zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
However, this will result in ZFS placing many restrictions on zfs-root as per how that option is used on Solaris systems:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; zfs-root must be VTOC (SMI) label, not GPT (EFI) label&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; zfs-root can only contain 1 vdev: either a plain disk, or a mirror&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
So, do &amp;lt;b&amp;gt;NOT&amp;lt;/b&amp;gt; set that property! If &amp;lt;code&amp;gt;bootfs&amp;lt;/code&amp;gt; is set, you would find that you cannot add vdevs to your zfs-root. If it is set already, then unset it like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool set bootfs= zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Make a directory to store files to be inside the initramfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkdir /boot/initramfs-source&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This directory will hold some files for the initial rootfs inside the kernel. Your &amp;lt;code&amp;gt;/boot&amp;lt;/code&amp;gt; should be on a small ext4 partition or on a mounted USB stick that you use to boot.&lt;br /&gt;
&lt;br /&gt;
Extract the slackware kernel-source package to obtain a copy of the kernel source, and make an initial kernel config for it:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir src&lt;br /&gt;
cd src&lt;br /&gt;
tar xvzf /mnt/cdrom/slackware64/k/kernel-source-*.txz&lt;br /&gt;
mv usr/src/linux-3.2.28 /usr/src/linux-3.2.28b&lt;br /&gt;
rm -r install&lt;br /&gt;
cd /usr/src/linux-3.2.28b&lt;br /&gt;
make menuconfig&lt;br /&gt;
  General setup-&amp;gt;Local version - append to kernel release = b&lt;br /&gt;
  General setup-&amp;gt;Default hostname                         = slackzfs&lt;br /&gt;
  General setup-&amp;gt;Initramfs source files(s)                = /boot/initramfs-source&lt;br /&gt;
  Device Drivers-&amp;gt;SCSI device support-&amp;gt;SCSI low-level drivers-&amp;gt; &amp;lt;*&amp;gt; SYM53C8XX Version 2 SCSI support&lt;br /&gt;
  File systems -&amp;gt; &amp;lt;*&amp;gt; The Extended 4 (ext4) filesystem&lt;br /&gt;
  # build in any hard drive controllers and filesystems that you need for booting&lt;br /&gt;
  # then save the config&lt;br /&gt;
make prepare scripts&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The kernel source has been set to have a &amp;quot;Local version&amp;quot; &amp;lt;code&amp;gt;b&amp;lt;/code&amp;gt;. This will result in modules installed to &amp;lt;code&amp;gt;/lib/modules/3.2.28b&amp;lt;/code&amp;gt; and keeps this kernel's source and modules seperate from slackware's kernel-generic package installation. The &amp;lt;code&amp;gt;make prepare scripts&amp;lt;/code&amp;gt; command readies the kernel source as needed before we can install a copy of spl and zfs modules into the kernel source tree.&lt;br /&gt;
&lt;br /&gt;
Now proceed to configure and copy spl and zfs into the kernel source tree:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd ~/src&lt;br /&gt;
tar xvzf ~/spl-0.6.0-rc11.tar.gz&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-0.6.0-rc11&lt;br /&gt;
./configure \&lt;br /&gt;
    --prefix=/ \&lt;br /&gt;
    --libdir=/lib64 \&lt;br /&gt;
    --includedir=/usr/include \&lt;br /&gt;
    --datarootdir=/usr/share \&lt;br /&gt;
    --enable-linux-builtin=yes \&lt;br /&gt;
    --with-linux=/usr/src/linux-3.2.28b \&lt;br /&gt;
    --with-linux-obj=/usr/src/linux-3.2.28b&lt;br /&gt;
./copy-builtin /usr/src/linux-3.2.28b&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../spl-0.6.0rc11_3.2.28b-x86_64-1root.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
&lt;br /&gt;
tar xvzf ~/zfs-0.6.0-rc11.tar.gz&lt;br /&gt;
mkdir install&lt;br /&gt;
cd zfs-0.6.0-rc11&lt;br /&gt;
./configure \&lt;br /&gt;
    --prefix=/ \&lt;br /&gt;
    --libdir=/lib64 \&lt;br /&gt;
    --includedir=/usr/include \&lt;br /&gt;
    --datarootdir=/usr/share \&lt;br /&gt;
    --enable-linux-builtin=yes \&lt;br /&gt;
    --with-linux=/usr/src/linux-3.2.28b \&lt;br /&gt;
    --with-linux-obj=/usr/src/linux-3.2.28b \&lt;br /&gt;
    --with-spl=/root/src/spl-0.6.0-rc11&lt;br /&gt;
    --with-spl-obj=/root/src/spl-0.6.0-rc11&lt;br /&gt;
./copy-builtin /usr/src/linux-3.2.28b&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../zfs-0.6.0rc11_3.2.28b-x86_64-1root.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
At this point, the &amp;lt;code&amp;gt;copy-builtin&amp;lt;/code&amp;gt; scripts have installed the configured spl and zfs modules source into the kernel source. The regular &amp;lt;code&amp;gt;make menuconfig&amp;lt;/code&amp;gt; in the kernel source should now show options for spl and zfs in the kernel config.&lt;br /&gt;
&lt;br /&gt;
As of this writing, the copy-builtin script places the spl and zfs modules into the kernel source in places where the modules may not initialize in the best order, &amp;lt;i&amp;gt;after&amp;lt;/i&amp;gt; all lower-level storage drivers are initialized. If spl and zfs initialize too soon, there is a chance they may not be able to see all of the storage devices. The order of initialization (as seen in dmesg) of modules that are builtin to the kernel is the order that the modules are linked into the kernel during kernel compilation. The order of link depends on where the module source files are located in the kernel source tree. To ensure that spl and zfs will initialize after all hardware drivers, we can move them into the &amp;lt;code&amp;gt;drivers&amp;lt;/code&amp;gt; tree and after all other drivers. This move is &amp;lt;bold&amp;gt;optional&amp;lt;/bold&amp;gt; and you can skip doing this and everything will probably work fine, but it is shown here how to move the modules to under drivers in case you prefer them there:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /usr/src/linux-3.2.28b&lt;br /&gt;
mkdir drivers/zfsonlinux&lt;br /&gt;
mv spl drivers/zfsonlinux&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  # remove references to spl&lt;br /&gt;
vi Makefile&lt;br /&gt;
  # remove references to spl&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.28b/fs&lt;br /&gt;
mv zfs ../drivers/zfsonlinux&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  # remove references to zfs&lt;br /&gt;
vi Makefile&lt;br /&gt;
  # remove references to zfs&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.28b/drivers&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  )# add line at end of menu, before &amp;quot;endmenu&amp;quot;:&lt;br /&gt;
  )source &amp;quot;drivers/zfsonlinux/Kconfig&amp;quot;&lt;br /&gt;
  )endmenu&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.28b/drivers&lt;br /&gt;
vi Makefile&lt;br /&gt;
  )# add line at very end of file:&lt;br /&gt;
  )obj-$(CONFIG_ZFSONLINUX) += zfsonlinux/&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.28b/drivers/zfsonlinux&lt;br /&gt;
cat &amp;gt; Kconfig &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
menuconfig ZFSONLINUX&lt;br /&gt;
	tristate &amp;quot;ZFSonLinux support&amp;quot;&lt;br /&gt;
&lt;br /&gt;
if ZFSONLINUX&lt;br /&gt;
&lt;br /&gt;
source &amp;quot;drivers/zfsonlinux/spl/Kconifg&amp;quot;&lt;br /&gt;
&lt;br /&gt;
source &amp;quot;drivers/zfsonlinux/zfs/Kconifg&amp;quot;&lt;br /&gt;
&lt;br /&gt;
endif&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.28b/zfsonlinux&lt;br /&gt;
cat &amp;gt; Makefile &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
obj-$(CONFIG_SPL) += spl/&lt;br /&gt;
obj-$(CONFIG_ZFS) += zfs/&lt;br /&gt;
EOF&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This completes the move of the spl and zfs modules in the kernel source tree to be under &amp;lt;code&amp;gt;drivers/zfsonlinux&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Now, in kernel configuration, you can build in the modules as follows:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /usr/src/linux-3.2.28b&lt;br /&gt;
make menuconfig&lt;br /&gt;
   Device Drivers -&amp;gt;&lt;br /&gt;
    &amp;lt;*&amp;gt; ZFSonLinux support -&amp;gt;&lt;br /&gt;
      &amp;lt;*&amp;gt; Solaris Porting Layer (SPL)&lt;br /&gt;
      &amp;lt;*&amp;gt;     ZFS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the kernel config, we set &amp;lt;code&amp;gt;/boot/initramfs-source&amp;lt;/code&amp;gt; as source location of the contents to be linked into kernel's builtin initramfs (rootfs). Now, we create some files that are needed to be in the initramfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /boot/initramfs-source&lt;br /&gt;
&lt;br /&gt;
# make standard directories&lt;br /&gt;
mkdir -p proc dev sys mnt bin sbin etc/zfs&lt;br /&gt;
&lt;br /&gt;
# zfs seems to want mtab present, even if empty&lt;br /&gt;
touch etc/mtab&lt;br /&gt;
&lt;br /&gt;
# if zpool.cache file can be read by zfs at module init, it imports the pools in the cache&lt;br /&gt;
cp /etc/zfs/zpool.cache-initrd etc/zfs/zpool.cache&lt;br /&gt;
&lt;br /&gt;
It is time to pause for a moment here and talk about zpool.cache: Using it is actually dangerous. We are not using udev and it's persistent block device filenames (/dev/disk/by-*), but are using the default kernel block device names (/dev/sd*) in devtmpfs. Device names for a hard drive in /dev can potentially change on boot depending on disk controller initialization order and disk drive response time. Adding another disk controller or hard disk on a controller can result in device name assignment changes to all the hard disks. A zpool.cache file holds all the zfs_member device filenames /dev/sd* for a pool configuration, but the zpool.cache configuration will be incorrect if device filenames have been changed or swapped around and this could result in a faulted pool that may or may not be recoverable. Using zpool.cache to import pools at boot, even with udev persistent device filenames, is potentially destructive if devices have been changed around. The proper thing to do is zpool_import and do not include zpool.cache in the initramfs.&lt;br /&gt;
&lt;br /&gt;
# make initial console device node; otherwise, there is a problem at startup:&lt;br /&gt;
# &amp;quot;Warning: unable to open an initial console&amp;quot; and you'd have problems with console and tty login&lt;br /&gt;
# making these nodes from within /init is not early enough to avoid problem&lt;br /&gt;
mknod dev/console c 5 1   # system console&lt;br /&gt;
&lt;br /&gt;
# make memory device kmsg to &amp;quot;printk&amp;quot; kernel messages&lt;br /&gt;
# we can write to this file to send out messages&lt;br /&gt;
mknod dev/kmsg    c 1 11  # lines printed to kmsg enter kernel messages buffer&lt;br /&gt;
&lt;br /&gt;
# recommended loop0 device to mount fs images&lt;br /&gt;
mknod dev/loop0   b 7 0&lt;br /&gt;
&lt;br /&gt;
# make initial virtual terminal devices&lt;br /&gt;
mknod dev/tty     c 5 0   # current tty&lt;br /&gt;
mknod dev/tty0    c 4 0   # current virtual term&lt;br /&gt;
mknod dev/tty1    c 4 1   # login virtual term 1 (F1)&lt;br /&gt;
&lt;br /&gt;
# make alternative console=ttyS0 standard 8250/16550 UART serial port devices&lt;br /&gt;
#   useful with kernel parameter console=ttyS0&lt;br /&gt;
#          with qemu -nographic -option-rom sgabios.bin,bootindex=0&lt;br /&gt;
mknod dev/ttyS0   c 4 64  # COM1&lt;br /&gt;
mknod dev/ttyS1   c 4 65  # COM2&lt;br /&gt;
mknod dev/ttyS2   c 4 66  # COM3&lt;br /&gt;
mknod dev/ttyS3   c 4 67  $ COM4&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This should be enough device nodes initially in the initramfs. Once devtmpfs mounts over /dev inside initramfs, a lot more devices are available in it by default.&lt;br /&gt;
&lt;br /&gt;
The initramfs needs an &amp;lt;code&amp;gt;/init&amp;lt;/code&amp;gt; program that will be run automatically by the kernel as process id 1, the first program to run on the system. This program's task is to mount a root filesystem, switch it to be the new root (/), and then exec the init (&amp;lt;code&amp;gt;/sbin/init&amp;lt;/code&amp;gt;) program that is on the new root so that the new root system is booted.&lt;br /&gt;
&lt;br /&gt;
The common way to make /init is using busybox with files like these in /boot/initrd-tree or /boot/initramfs-source:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
bin/busybox&lt;br /&gt;
bin/ash -&amp;gt; busybox&lt;br /&gt;
bin/sh -&amp;gt; busybox&lt;br /&gt;
# run busybox to see what other &amp;quot;applets&amp;quot; can be symlinked to it&lt;br /&gt;
# when busybox is run as a different symlinked applet name, it runs as the applet&lt;br /&gt;
init&lt;br /&gt;
# init can be an ash script, see slackware's /boot/initrd-tree/init for example&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For example, as an ash script, slackware's init does the following:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;parse kernel parameters passed into it and set variables based on them&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;start udevd and trigger rules for block devices to setup initial /dev devices&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;load kernel modules and keyboard map&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;run mdadm, cryptsetup, lvm, zpool/zfs to setup more devices&lt;br /&gt;
     (any udev rules for them should do more /dev setup in the background)&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;mount the root filesystem read-only at /mnt&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;stat /mnt/sbin/init, and if not executable run a rescue shell /bin/sh&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;shutdown udevd so it can be restarted by root system when booted&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;mount --move {proc,sys,run,dev} to under /mnt&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;run: exec switch_root /mnt /sbin/init $RUNLEVEL&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The slackware mkinitrd package is a fully configured BusyBox installation that makes an external initramfs image file, initrd.gz, that is passed to the kernel by the bootloader (lilo). It could be changed to be internal to the kernel by just using initrd-tree as the CONFIG_INITRAMFS_SOURCE in the kernel config and removing initrd in the lilo.conf.&lt;br /&gt;
&lt;br /&gt;
The main purpose of most initramfs/initrd is to load and configure kernel modules and devices needed to mount a root filesystem. Because the spl/zfs modules are builtin, there isn't really a lot that needs to be done by an initramfs. What remains to be done is import the zfs-root pool, mount it, and exec the system /sbin/init. The kernel's &amp;quot;legacy&amp;quot; parameters &amp;lt;code&amp;gt;root=&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;rootfstype=&amp;lt;/code&amp;gt; that are able to directly boot a root disk do not work with ZFS at this time because ZFS pools always need to be imported before it is possible to mount and boot on them. The automatic import that ZFS can do by using a cachefile (/etc/zfs/zpool.cache) stored in initramfs still does not work with the legacy boot parameters because at an earlier stage of the boot process, the kernel ignores a rootfs that does not contain an &amp;lt;code&amp;gt;/init&amp;lt;/code&amp;gt; program, and/or the device type of an imported pool is not the device types recognized by the legacy boot as valid root devices.&lt;br /&gt;
&lt;br /&gt;
You could just continue to use slackware's mkinitrd package as in the &amp;quot;ZFS root&amp;quot; wiki and it works the same whether the modules are builtin or not. But, by building the spl/zfs modules in, aren't we really wanting to get rid of using the mkinitrd/initrd.gz? We'd like to have a kernel with everything in it to boot, and use a simple lilo image entry that has no initrd.&lt;br /&gt;
&lt;br /&gt;
We can do this, and not use the mkinitrd package, but we still need to finish our own initramfs &amp;lt;code&amp;gt;/init&amp;lt;/code&amp;gt; program to import, mount, switch root, and boot. Save the following c program to &amp;quot;foobarz-init.c&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/* software product name: foobarz-init.c&lt;br /&gt;
 * suggested binary name: /init (in initramfs-source, rootfs)&lt;br /&gt;
 * license              : BSD&lt;br /&gt;
 * license text:&lt;br /&gt;
Copyright (c) 2012, foobarz&lt;br /&gt;
All rights reserved.&lt;br /&gt;
&lt;br /&gt;
Redistribution and use in source and binary forms, with or without&lt;br /&gt;
modification, are permitted provided that the following conditions are met:&lt;br /&gt;
    * Redistributions of source code must retain the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer.&lt;br /&gt;
    * Redistributions in binary form must reproduce the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer in the&lt;br /&gt;
      documentation and/or other materials provided with the distribution.&lt;br /&gt;
    * Neither the name of the &amp;lt;organization&amp;gt; nor the&lt;br /&gt;
      names of its contributors may be used to endorse or promote products&lt;br /&gt;
      derived from this software without specific prior written permission.&lt;br /&gt;
&lt;br /&gt;
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &amp;quot;AS IS&amp;quot; AND&lt;br /&gt;
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED&lt;br /&gt;
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE&lt;br /&gt;
DISCLAIMED. IN NO EVENT SHALL &amp;lt;COPYRIGHT HOLDER&amp;gt; BE LIABLE FOR ANY&lt;br /&gt;
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES&lt;br /&gt;
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;&lt;br /&gt;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND&lt;br /&gt;
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT&lt;br /&gt;
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS&lt;br /&gt;
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
/* Your initramfs-source should contain the following&lt;br /&gt;
 *&lt;br /&gt;
 * cd /boot/initramfs-source&lt;br /&gt;
 * mkdir -p proc dev sys mnt bin sbin etc/zfs&lt;br /&gt;
 * touch etc/mtab&lt;br /&gt;
 * cp /etc/zfs/zpool.cache-initrd etc/zfs/zpool.cache&lt;br /&gt;
 * # zpool.cache is optional - zpool_import_ kernel params can be used instead&lt;br /&gt;
 * #  see below for details on using zpool_import&lt;br /&gt;
 * mknod dev/console c 5 1   # system console&lt;br /&gt;
 * mknod dev/kmsg    c 1 11  # lines printed to kmsg enter kernel messages buffer&lt;br /&gt;
 * mknod dev/loop0   b 7 0&lt;br /&gt;
 * mknod dev/tty     c 5 0   # current tty&lt;br /&gt;
 * mknod dev/tty0    c 4 0   # current virtual term&lt;br /&gt;
 * mknod dev/tty1    c 4 1   # login virtual term 1 (F1)&lt;br /&gt;
 * mknod dev/ttyS0   c 4 64  # COM1&lt;br /&gt;
 * mknod dev/ttyS1   c 4 65  # COM2&lt;br /&gt;
 * mknod dev/ttyS2   c 4 66  # COM3&lt;br /&gt;
 * mknod dev/ttyS3   c 4 67  $ COM4&lt;br /&gt;
 *&lt;br /&gt;
 * and this program compiled to /boot/initramfs-source/init&lt;br /&gt;
 *&lt;br /&gt;
 * Set kernel config option&lt;br /&gt;
 *  CONFIG_INITRAMFS_SOURCE=/boot/initramfs-source&lt;br /&gt;
 * to build the initramfs into your kernel image&lt;br /&gt;
 *  that also has builtin drivers (spl and zfs, etc).&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
#define FOOBARZ_INIT_VERSION &amp;quot;1.1.1&amp;quot;&lt;br /&gt;
#define _BSD_SOURCE&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdarg.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;fcntl.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/mount.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sysexits.h&amp;gt;&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
/* support for zpool import&lt;br /&gt;
 *&lt;br /&gt;
 * If -DINCLUDE_ZPOOL_IMPORT, then support to import a zpool is&lt;br /&gt;
 * enabled in the program. Enabling it will add many dependencies to the&lt;br /&gt;
 * compile and link; for example:&lt;br /&gt;
 *&lt;br /&gt;
 * gcc -static -DINCLUDE_ZPOOL_IMPORT \&lt;br /&gt;
 *    foobarz-init.c -include /usr/src/zfs-0.6.0-rc11/3.2.28/zfs_config.h \&lt;br /&gt;
 *   -o init \&lt;br /&gt;
 *   -I /usr/include/libspl -I /usr/include/libzfs \&lt;br /&gt;
 *   -lzfs -lnvpair -lzpool -luutil -luuid -lrt -lz -lm -lpthread \&lt;br /&gt;
 *   -I /usr/include/tirpc \&lt;br /&gt;
 *   -ltirpc&lt;br /&gt;
 *&lt;br /&gt;
 * Note that libtirpc is a drop-in replacement for the SunRPC functions that&lt;br /&gt;
 * used to be in glibc. No additional includes are needed, just the gcc -I and -l&lt;br /&gt;
 * options for tirpc.&lt;br /&gt;
 *&lt;br /&gt;
 * Otherwise, with -UINCLUDE_ZPOOL_IMPORT, the compile is just:&lt;br /&gt;
 * gcc -static foobarz-init.c -o init&lt;br /&gt;
 */&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
#include &amp;lt;libzfs.h&amp;gt;&lt;br /&gt;
#else&lt;br /&gt;
#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/stat.h&amp;gt;&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#define PARAM_REQ_NO 0&lt;br /&gt;
#define PARAM_REQ_YES 1&lt;br /&gt;
#define PARAM_SRC_DEFAULT 0&lt;br /&gt;
#define PARAM_SRC_CMDLINE 1&lt;br /&gt;
&lt;br /&gt;
void printk(char *fmt, ...) {&lt;br /&gt;
  FILE* f;&lt;br /&gt;
  int fd;&lt;br /&gt;
  va_list args;&lt;br /&gt;
&lt;br /&gt;
  f = fopen(&amp;quot;/dev/kmsg&amp;quot;, &amp;quot;w&amp;quot;);&lt;br /&gt;
  va_start(args, fmt);&lt;br /&gt;
  vfprintf(f, fmt, args);&lt;br /&gt;
  va_end(args);&lt;br /&gt;
  fflush(f);&lt;br /&gt;
  fclose(f);&lt;br /&gt;
  /* avoid flooding kmsg and having msgs suppressed; 20msgs/sec */&lt;br /&gt;
  usleep(50000);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[]) {&lt;br /&gt;
 /*** variables */&lt;br /&gt;
&lt;br /&gt;
 int i;&lt;br /&gt;
 int   fd = 0; /* file descriptor */&lt;br /&gt;
 unsigned long mountflags;&lt;br /&gt;
&lt;br /&gt;
 /* kernel command line */&lt;br /&gt;
 off_t cmdline_size;&lt;br /&gt;
 char* cmdline; /* to be malloc 4096B */&lt;br /&gt;
 char* cmdline_end;&lt;br /&gt;
 char* temp_end;&lt;br /&gt;
 char* src_msg; /* default or cmdline */&lt;br /&gt;
 int flag_param_missing = 0;&lt;br /&gt;
&lt;br /&gt;
 /* use to hold contents of a misc /proc/&amp;lt;file&amp;gt; */&lt;br /&gt;
 char* miscproc_buff; /* to be malloc 4096B */&lt;br /&gt;
 off_t miscproc_size;&lt;br /&gt;
&lt;br /&gt;
 /* note about environ, argv, and kernel cmdline for init:&lt;br /&gt;
  *   environ is not defined for init&lt;br /&gt;
  *   only argv[0] is set for init&lt;br /&gt;
  *   kernel command line parameters are accessed&lt;br /&gt;
  *   at /proc/cmdline&lt;br /&gt;
  */&lt;br /&gt;
&lt;br /&gt;
 /* kernel parameters expected to be name=value */&lt;br /&gt;
 /* do not use quotes or spaces in parameters   */&lt;br /&gt;
 /* you can add more params somwhere after root= */&lt;br /&gt;
 struct nv { char* n; char* v; char* v_end; int req; int src; };&lt;br /&gt;
 struct nv param[] = {&lt;br /&gt;
   { &amp;quot;root=&amp;quot;,       NULL, NULL, PARAM_REQ_YES, PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;rootfstype=&amp;quot;, NULL, NULL, PARAM_REQ_YES, PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;mountopt=&amp;quot;,   NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;init=&amp;quot;,       NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;runlevel=&amp;quot;,   NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;console=&amp;quot;,    NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT }&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
   ,&lt;br /&gt;
   { &amp;quot;zpool_import_name=&amp;quot;,    NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;zpool_import_guid=&amp;quot;,    NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;zpool_import_newname=&amp;quot;, NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;zpool_import_force=&amp;quot;,   NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT }&lt;br /&gt;
#endif&lt;br /&gt;
 };&lt;br /&gt;
 enum {&lt;br /&gt;
	 iroot,&lt;br /&gt;
	 irootfstype,&lt;br /&gt;
	 imountopt,&lt;br /&gt;
	 iinit,&lt;br /&gt;
	 irunlevel,&lt;br /&gt;
	 iconsole,&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
	 izpool_import_name,&lt;br /&gt;
	 izpool_import_guid,&lt;br /&gt;
	 izpool_import_newname,&lt;br /&gt;
	 izpool_import_force,&lt;br /&gt;
#endif&lt;br /&gt;
	 ilastparam&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
 libzfs_handle_t* libzfs = NULL;&lt;br /&gt;
 importargs_t iargs = { 0 };&lt;br /&gt;
 nvlist_t* pools = NULL;&lt;br /&gt;
 nvpair_t* pool = NULL;&lt;br /&gt;
 nvlist_t* config = NULL;&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
 /*** program */&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;foobarz-init, version %s: booting initramfs.\n&amp;quot;, FOOBARZ_INIT_VERSION);&lt;br /&gt;
&lt;br /&gt;
 cmdline       = (char*) malloc(4096);&lt;br /&gt;
 miscproc_buff = (char*) malloc(4096);&lt;br /&gt;
 if( (cmdline == NULL) || (miscproc_buff == NULL) ) {&lt;br /&gt;
   printk(&amp;quot;Unable to allocate buffer memory: malloc: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount proc /proc&lt;br /&gt;
  *  note: some /dev devices symlink into /proc&lt;br /&gt;
  *  proc contains info about processes, including cmdline etc. */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount proc /proc\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;proc&amp;quot;, &amp;quot;/proc&amp;quot;, &amp;quot;proc&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
   printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
   printk(&amp;quot;Mount proc successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount devtmpfs /dev&lt;br /&gt;
  *  note: This simple init program works if your root device is made from devices&lt;br /&gt;
  *  that are available by default in devtmpfs, such as /dev/sd*&lt;br /&gt;
  *&lt;br /&gt;
  *  For zfs, your root zfs pool should be created with default device nodes and&lt;br /&gt;
  *  then it should be mountable by this simple init program.&lt;br /&gt;
  *&lt;br /&gt;
  *  udev may be needed to configure device nodes and symlinks required&lt;br /&gt;
  *  to access a root device configuration made with such nodes and symlinks.&lt;br /&gt;
  *  If you need udevd, you can include it into your initramfs-source and&lt;br /&gt;
  *  modify this program to run it before attempting to mount your root device.&lt;br /&gt;
  *  However, if udevd is needed, a significant number of userspace programs may also be&lt;br /&gt;
  *  required by rules in /lib/udev/. You could install busybox + udev (about 5MB) or&lt;br /&gt;
  *  coreutils + util-linux + bash + udev (about 25MB) into initramfs-source. But, at that&lt;br /&gt;
  *  point you'd have ash or bash and many tools that are easier to use than this&lt;br /&gt;
  *  simple init program; it would then be easy to have /init as #!/bin/&amp;lt;b&amp;gt;ash script. */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount devtmpfs /dev\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;devtmpfs&amp;quot;, &amp;quot;/dev&amp;quot;, &amp;quot;devtmpfs&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
   printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
   printk(&amp;quot;Mount devtmpfs successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount sysfs /sys&lt;br /&gt;
  *  note: some kernel modules try to access /sys with userspace helpers to echo values into /sys variables;&lt;br /&gt;
  *  such modules expect a minimal userspace that contains coreutils or busybox */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount sysfs /sys\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;sysfs&amp;quot;, &amp;quot;/sys&amp;quot;, &amp;quot;sysfs&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
   printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
   printk(&amp;quot;Mount sysfs successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* process kernel command line */&lt;br /&gt;
 fd = open(&amp;quot;/proc/cmdline&amp;quot;, O_RDONLY);&lt;br /&gt;
 if( fd == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Cannot open /proc/cmdline: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 /* note, on /proc fs:&lt;br /&gt;
  *       lseek likely always returns error&lt;br /&gt;
  *       stat likely always returns st_size = 0&lt;br /&gt;
  *   so determining size of /proc file means just reading it;&lt;br /&gt;
  *   you have to read /proc files according to their documented&lt;br /&gt;
  *   maximum sizes; this is probably for performance reasons */&lt;br /&gt;
 cmdline_size = read(fd, cmdline, 4095);&lt;br /&gt;
 if( cmdline_size == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Failed to read /proc/cmdline: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 close(fd);&lt;br /&gt;
&lt;br /&gt;
 /* cmdline may be newline + null terminated, but make it null + null */&lt;br /&gt;
 cmdline[cmdline_size] = '\0';&lt;br /&gt;
 if( cmdline[cmdline_size-1] == '\n' ) {&lt;br /&gt;
   cmdline[cmdline_size-1] = '\0';&lt;br /&gt;
   cmdline_size--;&lt;br /&gt;
   cmdline_end = cmdline + cmdline_size;&lt;br /&gt;
 }&lt;br /&gt;
 printk(&amp;quot;Kernel cmdline size: %i\n&amp;quot;, cmdline_size);&lt;br /&gt;
 printk(&amp;quot;Kernel cmdline: \&amp;quot;%s\&amp;quot;\n&amp;quot;, cmdline);&lt;br /&gt;
&lt;br /&gt;
 /* find v and v_end of values in cmdline */&lt;br /&gt;
 for( i=iroot; i&amp;lt;ilastparam; i++ ) {&lt;br /&gt;
   param[i].v = strstr(cmdline, param[i].n);&lt;br /&gt;
   if( param[i].v != NULL ) {&lt;br /&gt;
     param[i].src = PARAM_SRC_CMDLINE;&lt;br /&gt;
     while( *(param[i].v) != '=' ) param[i].v++;&lt;br /&gt;
     param[i].v++;&lt;br /&gt;
     temp_end = param[i].v;&lt;br /&gt;
     while( !( (*temp_end == ' ') ||&lt;br /&gt;
               (*temp_end == '\n') ||&lt;br /&gt;
               (temp_end == cmdline_end)&lt;br /&gt;
	     ) ) temp_end++;&lt;br /&gt;
     if( temp_end == param[i].v ) {&lt;br /&gt;
       printk(&amp;quot;Kernel parameter %s: value missing.\n&amp;quot;, param[i].n);&lt;br /&gt;
       param[i].v = NULL;&lt;br /&gt;
     } else param[i].v_end = temp_end;&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 for( i=iroot; i&amp;lt;ilastparam; i++ ) {&lt;br /&gt;
   /* terminate value strings */&lt;br /&gt;
   if( param[i].v_end != NULL ) *(param[i].v_end) = '\0';&lt;br /&gt;
   /* set defaults if no value on cmdline */&lt;br /&gt;
   if( param[i].v == NULL ) {&lt;br /&gt;
     param[i].src = PARAM_SRC_DEFAULT;&lt;br /&gt;
     if( param[i].req == PARAM_REQ_YES ) flag_param_missing = 1;&lt;br /&gt;
     switch(i) {&lt;br /&gt;
       case iroot      : param[i].v = &amp;quot;&amp;lt;missing required param&amp;gt;&amp;quot; ; break;&lt;br /&gt;
       case irootfstype: param[i].v = &amp;quot;&amp;lt;missing required param&amp;gt;&amp;quot; ; break;&lt;br /&gt;
       case imountopt  : param[i].v = &amp;quot;ro&amp;quot;        ; break;&lt;br /&gt;
       case iinit      : param[i].v = &amp;quot;/sbin/init&amp;quot;; break;&lt;br /&gt;
       case irunlevel  : param[i].v = &amp;quot;3&amp;quot;         ; break;&lt;br /&gt;
       case iconsole   : param[i].v = &amp;quot;console&amp;quot;   ; break;&lt;br /&gt;
       default         : param[i].v = NULL;&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
   if(param[i].src == PARAM_SRC_DEFAULT) src_msg = &amp;quot;default&amp;quot;;&lt;br /&gt;
   else src_msg = &amp;quot;cmdline&amp;quot;;&lt;br /&gt;
   printk(&amp;quot;Using %s \&amp;quot;%s\&amp;quot; (source: %s)\n&amp;quot;, param[i].n, param[i].v, src_msg);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 if( flag_param_missing ) {&lt;br /&gt;
   printk(&amp;quot;Aborting boot process: missing required kernel parameter(s).\n&amp;quot;);&lt;br /&gt;
   return EX_USAGE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* generic nv pair kernel cmdline processing finished&lt;br /&gt;
  *  now, examine specific params for defaults and correctness */&lt;br /&gt;
&lt;br /&gt;
 /* param[irootfstype]: can be checked against /proc/filesystems: */&lt;br /&gt;
 fd = open(&amp;quot;/proc/filesystems&amp;quot;, O_RDONLY);&lt;br /&gt;
 if( fd == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Cannot open /proc/filesystems: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 miscproc_size = read(fd, miscproc_buff, 4095);&lt;br /&gt;
 if( miscproc_size == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Failed to read /proc/filesystems: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 close(fd);&lt;br /&gt;
 if( strstr(miscproc_buff, param[irootfstype].v) == NULL ) {&lt;br /&gt;
   printk(&amp;quot;%s \&amp;quot;%s\&amp;quot;: filesystem type not available.\n&amp;quot;, param[irootfstype].n, param[irootfstype].v);&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* zfs-specific */&lt;br /&gt;
 if( strcmp(param[irootfstype].v, &amp;quot;zfs&amp;quot;) == 0 ) {&lt;br /&gt;
   if( access(&amp;quot;/etc/zfs/zpool.cache&amp;quot;, F_OK) == 0 )&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/zfs/zpool.cache is present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
   else&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/zfs/zpool.cache not present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
&lt;br /&gt;
   if( access(&amp;quot;/etc/hostid&amp;quot;, F_OK) == 0 )&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/hostid is present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
   else&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/hostid not present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
   /* zpool import */&lt;br /&gt;
   if( (param[izpool_import_name].v != NULL) || (param[izpool_import_guid].v != NULL) ) {&lt;br /&gt;
	printk(&amp;quot;zpool_import: import requested.\n&amp;quot;);&lt;br /&gt;
	if( (param[izpool_import_name].v != NULL) &amp;amp;&amp;amp; (param[izpool_import_guid].v != NULL) ) {&lt;br /&gt;
		printk(&amp;quot;zpool_import: given both pool name and guid; using guid.\n&amp;quot;);&lt;br /&gt;
		param[izpool_import_name].v = NULL;&lt;br /&gt;
	}&lt;br /&gt;
	if( param[izpool_import_name].v != NULL )&lt;br /&gt;
		printk(&amp;quot;zpool_import: pool name: %s\n&amp;quot;, param[izpool_import_name].v );&lt;br /&gt;
	else&lt;br /&gt;
		printk(&amp;quot;zpool_import: pool guid: %s\n&amp;quot;, param[izpool_import_guid].v );&lt;br /&gt;
&lt;br /&gt;
	iargs.path = NULL;&lt;br /&gt;
	iargs.paths = 0;&lt;br /&gt;
	iargs.poolname = param[izpool_import_name].v;&lt;br /&gt;
	if( param[izpool_import_guid].v != NULL )&lt;br /&gt;
		iargs.guid = strtoull(param[izpool_import_guid].v, NULL, 10);&lt;br /&gt;
	else&lt;br /&gt;
		iargs.guid = 0;&lt;br /&gt;
	iargs.cachefile = NULL;&lt;br /&gt;
	if( (param[izpool_import_force].v != NULL) &amp;amp;&amp;amp; (strcmp(param[izpool_import_force].v, &amp;quot;1&amp;quot;) == 0) ) {&lt;br /&gt;
		iargs.can_be_active = 1;&lt;br /&gt;
		printk(&amp;quot;zpool_import: import forced.\n&amp;quot;);&lt;br /&gt;
	} else {&lt;br /&gt;
		iargs.can_be_active = 0;&lt;br /&gt;
		printk(&amp;quot;zpool_import: import not forced.\n&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
	iargs.unique = 1;&lt;br /&gt;
	iargs.exists = 1;&lt;br /&gt;
&lt;br /&gt;
	printk(&amp;quot;zpool_import: init libzfs.\n&amp;quot;);&lt;br /&gt;
	libzfs = libzfs_init();&lt;br /&gt;
	printk(&amp;quot;zpool_import: searching for pool.\n&amp;quot;);&lt;br /&gt;
	pools = zpool_search_import(libzfs, &amp;amp;iargs);&lt;br /&gt;
	if( (pools == NULL) || nvlist_empty(pools) )&lt;br /&gt;
		printk(&amp;quot;zpool_import: pool not available for import, or already imported by cachefile.\n&amp;quot;);&lt;br /&gt;
	else {&lt;br /&gt;
		printk(&amp;quot;zpool_import: getting pool information.\n&amp;quot;);&lt;br /&gt;
		pool = nvlist_next_nvpair(pools, pool);&lt;br /&gt;
		printk(&amp;quot;zpool_import: getting pool configuration.\n&amp;quot;);&lt;br /&gt;
		nvpair_value_nvlist(pool, &amp;amp;config);&lt;br /&gt;
		printk(&amp;quot;zpool_import: attempting pool import.\n&amp;quot;);&lt;br /&gt;
		if( zpool_import(libzfs, config, param[izpool_import_newname].v, NULL) != 0 ) {&lt;br /&gt;
			printk(&amp;quot;zpool_import: import failed.\n&amp;quot;);&lt;br /&gt;
			printk(&amp;quot;zpool_import: error description: %s\n&amp;quot;, libzfs_error_description(libzfs) );&lt;br /&gt;
			printk(&amp;quot;zpool_import: error action: %s\n&amp;quot;, libzfs_error_action(libzfs) );&lt;br /&gt;
		} else  printk(&amp;quot;zpool_import: import successful.\n&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
	printk(&amp;quot;zpool_import: fini libzfs.\n&amp;quot;);&lt;br /&gt;
	libzfs_fini(libzfs);&lt;br /&gt;
   }&lt;br /&gt;
#endif /* zpool_import */&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 if(      strcmp(param[imountopt].v, &amp;quot;ro&amp;quot;) == 0 ) mountflags = MS_RDONLY;&lt;br /&gt;
 else if( strcmp(param[imountopt].v, &amp;quot;rw&amp;quot;) == 0 ) mountflags = 0;&lt;br /&gt;
 else {&lt;br /&gt;
   printk(&amp;quot;%s \&amp;quot;%s\&amp;quot;: invalid parameter value; defaulting to \&amp;quot;ro\&amp;quot;.\n&amp;quot;, param[imountopt].n, param[imountopt].v);&lt;br /&gt;
   mountflags = MS_RDONLY;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* param[iroot]: nothing to check; if user gives bad root=device then mount fails */&lt;br /&gt;
&lt;br /&gt;
 /* try to mount root=device at /mnt&lt;br /&gt;
  *&lt;br /&gt;
  * note: for zfs, if a copy of /etc/zfs/zpool.cache (when pool is imported) is put in initramfs-source, then&lt;br /&gt;
  * the zfs module can read it and automatically import the pools described in the cache file; the imported&lt;br /&gt;
  * pools can be available to mount here if they were created using standard device names, otherwise&lt;br /&gt;
  * udevd may be required to run before mounting the pool */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount -t %s -o %s %s /mnt.\n&amp;quot;, param[irootfstype].v, param[imountopt].v, param[iroot].v);&lt;br /&gt;
 if( mount(param[iroot].v, &amp;quot;/mnt&amp;quot;, param[irootfstype].v, mountflags, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 printk(&amp;quot;%s mounted successfully.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
&lt;br /&gt;
 /* check to see if the mounted root filesystem has an executable init program */&lt;br /&gt;
 chdir(&amp;quot;/mnt&amp;quot;);&lt;br /&gt;
 if( access(param[iinit].v+1, X_OK) != 0 ) {&lt;br /&gt;
   chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
   printk(&amp;quot;access X_OK: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   printk(&amp;quot;The init program /mnt/%s is not present or not executable.\n&amp;quot;, param[iinit].v+1);&lt;br /&gt;
   printk(&amp;quot;Aborting boot process: no init program.\n&amp;quot;);&lt;br /&gt;
   printk(&amp;quot;Unmounting %s.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
   if( umount(&amp;quot;/mnt&amp;quot;) == -1 ) {&lt;br /&gt;
     printk(&amp;quot;umount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
     printk(&amp;quot;Failed to umount %s.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
   } else printk(&amp;quot;Successfully unmounted %s.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
 printk(&amp;quot;Init program /mnt/%s is present and executable.\n&amp;quot;, param[iinit].v+1);&lt;br /&gt;
&lt;br /&gt;
 /* switch the root / from initramfs to the mounted new root device at /mnt.&lt;br /&gt;
  *&lt;br /&gt;
  * note: after this switch, it is not possible to access the initramfs files anymore,&lt;br /&gt;
  * yet they consume ram memory unless they are deleted here before switching.&lt;br /&gt;
  * Any programs that are run after clearing the initramfs and switching root must exist on the new root.&lt;br /&gt;
  * This program may safely delete itself (/init) since it is already in ram and executing.&lt;br /&gt;
  * If you have installed additional files and programs in initramfs that consume significant ram,&lt;br /&gt;
  * then you need to insert additional code here to delete those files (carefully). */&lt;br /&gt;
&lt;br /&gt;
 /* delete files off of initramfs to free ram memory */&lt;br /&gt;
 printk(&amp;quot;Freeing memory from initramfs...\n&amp;quot;);&lt;br /&gt;
 if( unlink(argv[0]) != 0 ) printk(&amp;quot;unlink %s: %s\n&amp;quot;, argv[0], strerror(errno));&lt;br /&gt;
 else printk(&amp;quot;%s %s&amp;quot;, argv[0], &amp;quot;deleted from initramfs.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 /* switch root */&lt;br /&gt;
 printk(&amp;quot;Beginning switch root procedure.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(1) Attempting cmd: mount --move /dev /mnt/dev \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/dev&amp;quot;, &amp;quot;/mnt/dev&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(2) Attempting cmd: mount --move /proc /mnt/proc \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/proc&amp;quot;, &amp;quot;/mnt/proc&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(3) Attempting cmd: mount --move /sys /mnt/sys \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/sys&amp;quot;, &amp;quot;/mnt/sys&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(4) Attempting cmd: chdir /mnt \n&amp;quot;);&lt;br /&gt;
 if( chdir(&amp;quot;/mnt&amp;quot;) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: chdir: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(5) Attempting cmd: mount --move . / \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;.&amp;quot;, &amp;quot;/&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(6) Attempting cmd: chroot . \n&amp;quot;);&lt;br /&gt;
 if( chroot(&amp;quot;.&amp;quot;) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: chroot: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(7) Attempting cmd: chdir / \n&amp;quot;);&lt;br /&gt;
 if( chdir(&amp;quot;/&amp;quot;) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: chdir: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 printk(&amp;quot;Completed switch root procedure.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 /* check for &amp;quot;console=&amp;quot; kernel parameter and switch&lt;br /&gt;
  *  stdin, stdout, and stderr to named console device&lt;br /&gt;
  */&lt;br /&gt;
 if( param[iconsole].src == PARAM_SRC_CMDLINE ) {&lt;br /&gt;
   printk(&amp;quot;Console redirection to device %s requested.\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
   /* expect only basename of console device (e.g., ttyS0), so chdir /dev */&lt;br /&gt;
   chdir(&amp;quot;/dev&amp;quot;);&lt;br /&gt;
   if( access(param[iconsole].v, F_OK ) == 0 ) {&lt;br /&gt;
     printk(&amp;quot;Opening stdin, stdout, and stderr on %s.\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
     close(0);&lt;br /&gt;
     open(param[iconsole].v, O_RDWR);&lt;br /&gt;
     dup2(0, 1);&lt;br /&gt;
     dup2(0, 2);&lt;br /&gt;
   } else {&lt;br /&gt;
     printk(&amp;quot;access F_OK: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
     printk(&amp;quot;Could not access device: %s!\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
     printk(&amp;quot;Console redirection to device %s aborted!\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
   }&lt;br /&gt;
   chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;Execing: \&amp;quot;%s %s\&amp;quot; to boot mounted root system.\n&amp;quot;, param[iinit].v, param[irunlevel].v);&lt;br /&gt;
&lt;br /&gt;
 /* free resources held to this point */&lt;br /&gt;
 free(cmdline);&lt;br /&gt;
 free(miscproc_buff);&lt;br /&gt;
&lt;br /&gt;
 if( execl(param[iinit].v, param[irunlevel].v, (char *) NULL ) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: execl: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If foobarz-init is updated, you can find the latest version at [https://github.com/foobarz/foobarz-init github].&lt;br /&gt;
&lt;br /&gt;
The foobarz-init program can be compiled two ways as of v1.1.1. First, the simpler compile that does not support zpool_import but does support importing pools using a /etc/zfs/zpool.cache file in the initramfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gcc --static init.c -o init&lt;br /&gt;
strip init&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The second way to compile it adds support for zpool_import so that you do not have to include a &amp;lt;code&amp;gt;/etc/zfs/zpool.cache&amp;lt;/code&amp;gt; file in the initramfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gcc -static -DINCLUDE_ZPOOL_IMPORT \&lt;br /&gt;
     foobarz-init.c -include /usr/src/linux-3.2.28b/zfs_config.h \&lt;br /&gt;
    -o init \&lt;br /&gt;
    -I /usr/include/libspl -I /usr/include/libzfs \&lt;br /&gt;
    -lzfs -lnvpair -lzpool -luutil -luuid -lrt -lz -lm -lpthread \&lt;br /&gt;
    -I /usr/include/tirpc \&lt;br /&gt;
    -ltirpc&lt;br /&gt;
strip init&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Dependencies required before you can compile this second way:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Install [http://sourceforge.net/projects/libtirpc/ libtirpc]. The glibc package has removed the RPC-related functions from the static libc. The libtirpc is the new replacement as a separate library. You can make your own libtirpc package and install it to resolve these RPC-related functions. Without this, the compile fails because it cannot find many &amp;quot;xdr&amp;quot; functions.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Reinstall the [ftp://slackware.mirrors.tds.net/pub/slackware/slackware64-current/source/a/util-linux/ util-linux] package with static libraries enabled. Edit the &amp;lt;code&amp;gt;util-linux.SlackBuild&amp;lt;/code&amp;gt; and remove the line &amp;lt;code&amp;gt;--disable-static&amp;lt;/code&amp;gt;, then build it and use upgradepkg to install the new package. This resolves linking static to libuuid.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;code&amp;gt;zfs_config.h&amp;lt;/code&amp;gt; can be found in the kernel source when you have installed the builtin spl/zfs configuration; for example at &amp;lt;code&amp;gt;/usr/src/linux-3.2.28b/zfs_config.h&amp;lt;/code&amp;gt;. If you currently have installed the modular spl/zfs configuration, &amp;lt;code&amp;gt;zfs_config.h&amp;lt;/code&amp;gt; is found where the zfs module headers are installed; for example at &amp;lt;code&amp;gt;/usr/src/zfs-0.6.0-rc11/3.2.28/zfs_config.h&amp;lt;/code&amp;gt;. Wherever it is, &amp;lt;code&amp;gt;-include&amp;lt;/code&amp;gt; it as shown in the example gcc line above. zfs_config.h seems misplaced because it would seem that using libzfs shouldn't depend on modules header files.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;You may need to install the spl and zfs packages configured for --enable-linux-builtin=yes before compiling and linking to libzfs to make sure you are using the version of libzfs intended for builtin modules in case a difference between the two configurations exists. Currently, there seems to be no difference in the libzfs for either modular or builtin modules, but later there could be at least a small difference for detection of modules to load or builtin already. You may see a message that the ZFS modules stack load failed, but it can be ignored since the modules are builtin; this is just libzfs trying to load the modules even though they are builtin.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
With these dependencies, you can probably compile static with the zpool_import support. The exact location of &amp;quot;zfs_config.h&amp;quot; may vary depending on your zfs and kernel versions, so adjust accordingly.&lt;br /&gt;
&lt;br /&gt;
Read the foobarz-init source code to see how it uses kernel parameters. The params &amp;lt;code&amp;gt;root&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;rootfstype&amp;lt;/code&amp;gt; are always required to tell init what root pool name to mount and the filesystem type (e.g. zfs).&lt;br /&gt;
&lt;br /&gt;
For the zpool_import support: &amp;lt;code&amp;gt;zpool_import_name=poolname&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;zpool_import_guid=&amp;lt;guid of a pool&amp;gt;&amp;lt;/code&amp;gt; tells what pool to import. You can also import the pool with a new different name by also using &amp;lt;code&amp;gt;zpool_import_newname=newpoolname&amp;lt;/code&amp;gt;. If the import is not working, &amp;lt;code&amp;gt;zpool_import_force=1&amp;lt;/code&amp;gt; can be used to force import even if ZFS thinks the pool may be in use by another system.&lt;br /&gt;
&lt;br /&gt;
However you import the pool, either using zpool.cache or zpool_import support, the kernel param &amp;lt;code&amp;gt;root=&amp;lt;your poolname or newpoolname&amp;gt;&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;rootfstype=zfs&amp;lt;/code&amp;gt; needs to be given also. The zpool_import only imports, it does not say what to mount. What to mount is still told using root= and rootfstype=.&lt;br /&gt;
&lt;br /&gt;
Now copy the compiled static program into the initramfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp init /boot/initramfs-source/init&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Build and install kernel:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /usr/src/linux-3.2.28b&lt;br /&gt;
make -j8&lt;br /&gt;
make -j8 modules_install&lt;br /&gt;
cp arch/x86/boot/bzImage /boot/vm3.2.28b&lt;br /&gt;
cp System.map /boot/System.map-vm3.2.28b&lt;br /&gt;
# add new lilo menu entry for vm3.2.28b kernel&lt;br /&gt;
vi /etc/lilo.conf&lt;br /&gt;
  image = /boot/vm3.2.28b&lt;br /&gt;
   label = vm3.2.28b&lt;br /&gt;
   addappend = &amp;quot; spl.spl_hostid=0x007f0100 zfs.spa_config_path=/etc/zfs/zpool.cache root=zfs-root rootfstype=zfs&amp;quot;&lt;br /&gt;
lilo&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Note: If &amp;lt;code&amp;gt;spl.spl_hostid=0x007f0100&amp;lt;/code&amp;gt; is not included in addappend, then during boot SPL module will attempt to read /etc/hostid or run a user-space helper to write the &amp;lt;code&amp;gt;hostid&amp;lt;/code&amp;gt; into &amp;lt;code&amp;gt;/proc/sys/kernel/spl/hostid&amp;lt;/code&amp;gt;. Reading /etc/hostid fails unless you use foobarz-chhostid and make the file and copy it into /boot/initramfs-source/etc/hostid. The helper will fail because no &amp;lt;code&amp;gt;sh&amp;lt;/code&amp;gt; shell and no &amp;lt;code&amp;gt;hostid&amp;lt;/code&amp;gt; command are installed in the initramfs. The default hostid becomes 0xffffffff, which is considered an invalid hostid.&lt;br /&gt;
&lt;br /&gt;
Congrats! If this works, you can select the &amp;quot;vm3.2.28b&amp;quot; lilo entry to boot. If you are using the zpool_import support in the init program, you need to add at least the &amp;lt;code&amp;gt;zpool_import_name=zfs-root&amp;lt;/code&amp;gt; param to the addappend line in lilo.conf.&lt;br /&gt;
&lt;br /&gt;
Notes on kernel params (lilo append and addappend lines): root= and rootfstype= are used by both foorbarz-init and mkinitrd. The &amp;quot;ro&amp;quot; param is not used by foobarz-init, so instead use: mountopt=ro|rw. See &amp;quot;modinfo spl&amp;quot; and &amp;quot;modinfo zfs&amp;quot; to see all of the options those modules can take on the kernel command line. Notice the &amp;lt;code&amp;gt;spl.spl_hostid=0x007f0100&amp;lt;/code&amp;gt; param that works around the hostid mismatch problem while trying to import a pool; this param and hostname/ip set to use local loopback 127.0.0.1 in etc/hosts etc/HOSTNAME in initramfs will work most of the time, and if not the pool import needs to be forced.&lt;br /&gt;
&lt;br /&gt;
Notes on the spl and zfs packages to install: &amp;lt;i&amp;gt;If&amp;lt;/i&amp;gt; you have errors using zfs and zpool commands on booted system with builtin modules, then upgrade/switch to the 0.6.0rc11_3.2.28b builds, or you can make a custom package with the binaries renamed like zpoolb, zfsb etc for builtin.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
Using qemu's -nographic serial console (/usr/share/qemu/sgabios.bin): If you have a boot problem, you might want to run in qemu's -nographic console mode:&lt;br /&gt;
&lt;br /&gt;
First, edit /etc/inittab, and uncomment the line for local serial ports runlevel &amp;quot;s1&amp;quot; (ttyS0) for serial console login support. This is done in the guest (host does not need this):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Local serial lines:&lt;br /&gt;
s1:12345:respawn:/sbin/agetty -L ttyS0 38400 linux&lt;br /&gt;
#s1:12345:respawn:/sbin/agetty -L ttyS0 9600 vt100&lt;br /&gt;
#s2:12345:respawn:/sbin/agetty -L ttyS1 9600 vt100&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Second, edit /etc/securetty, and uncomment ttyS0 line:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ttyS0&lt;br /&gt;
#ttyS1&lt;br /&gt;
# ...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
You cannot login on ttyS0 without this change even though you get the login prompt!&lt;br /&gt;
&lt;br /&gt;
Then, run qemu such as:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
qemu-kvm &amp;lt;all regular options&amp;gt; -nographic -option-rom sgabios.bin,bootindex=0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Wait for the lilo prompt, it may take several seconds show up in this mode.&lt;br /&gt;
&lt;br /&gt;
In the lilo menu, select your kernel image with builtin spl/zfs, and use kernel params such as:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
boot: vm3.2.28b console=ttyS0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
At the lilo prompt, use kernel parameter: console=ttyS0 (do NOT say /dev/ttS0). Passing runlevel=s1 does not appear to be necessary.&lt;br /&gt;
&lt;br /&gt;
When you are in qemu's serial mode, the interface is a little different than in the normal graphical mode: use keypresses:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ctrl-a h    # for help&lt;br /&gt;
ctrl-a c    # toggle access to (QEMU) console / back to emulation&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If you cannot get a login: prompt, try ctrl-a c, then do (QEMU) sendkey ctrl-alt-delete. This will reboot cleanly back to lilo, then you can do (QEMU) quit.&lt;br /&gt;
&lt;br /&gt;
Once you login to the guest, the terminal size needs adjustment. On your host, in another xterm sized the same as your guest console terminal, get the size of the terminal:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo $LINES&lt;br /&gt;
echo $COLUMNS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Now, back in the guest terminal of same size:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export LINES &amp;lt;lines&amp;gt;&lt;br /&gt;
export COLUMNS &amp;lt;columns&amp;gt;&lt;br /&gt;
stty cols $COLUMNS rows $LINES&lt;br /&gt;
exec bash&lt;br /&gt;
reset&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
So, you set the environment variables and also set them with stty. Then, restart bash (exec, or else it is a child shell process).&lt;br /&gt;
&lt;br /&gt;
BECAREFUL not to start qemu twice on the same ZFS guest! Two simultaneous running qemu on the same ZFS will corrupt the pool and it will NOT recover - you lose your whole installation! Before running qemu, check ps -A, look for an already running qemu process incase it somehow entered into the background!&lt;br /&gt;
&lt;br /&gt;
BECAREFUL when using -nographic ttyS0 that you are not doing commands on the HOST! Only use -nographic to see kernel problems. Use regular console if booting is working normally.&lt;br /&gt;
&lt;br /&gt;
To use the qemu -drive if=scsi option, the linux module sym53c8xx should be loaded in the guest. You may need to use the qemu option:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-option-rom 8xx_64.rom,bootindex=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The file 8xx_64.rom used to be inside qemu, but in new versions it is missing. You can download it:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
wget http://www.lsi.com/downloads/Public/Host%20Bus%20Adapters/Host%20Bus%20Adapters%20Common%20Files/lsi_bios.zip&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Extract the zip and place 8xx_64.rom in /usr/share/qemu/.&lt;br /&gt;
&lt;br /&gt;
Good luck!&lt;/div&gt;</description>
			<pubDate>Wed, 19 Sep 2012 13:26:56 GMT</pubDate>
			<dc:creator>Foobarz</dc:creator>
			<comments>https://www.slackwiki.com/Talk:ZFS_root_(builtin)</comments>
		</item>
		<item>
			<title>ZFS root (builtin)</title>
			<link>https://www.slackwiki.com/index.php?title=ZFS_root_(builtin)&amp;diff=798</link>
			<guid isPermaLink="false">https://www.slackwiki.com/index.php?title=ZFS_root_(builtin)&amp;diff=798</guid>
			<description>&lt;p&gt;Foobarz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Tutorials]]&lt;br /&gt;
The first [http://slackwiki.com/ZFS_root &amp;quot;ZFS root&amp;quot;] wiki explains the details of running ZFS as your root filesystem by using a fully modular generic kernel approach. Now, I can share how it can be done with the SPL and ZFS modules built into the kernel. This procedure is just an example and can use some fine tuning, but here goes:&lt;br /&gt;
&lt;br /&gt;
The steps below are to create a kernel with SPL and ZFS modules builtin. This kernel will be installed as an alternative kernel to boot in lilo, and it will have a separate kernel installation from the fully modular and working system kernel. This will allow testing the builtin kernel while able to boot back onto a working modular ZFS system. We start this procedure assuming you are on a working fully modular ZFS install as in the &amp;quot;ZFS root&amp;quot; wiki.&lt;br /&gt;
&lt;br /&gt;
Use mountpoint=legacy so that zfs will not expect &amp;lt;code&amp;gt;zfs mount&amp;lt;/code&amp;gt;, but instead expect standard &amp;lt;code&amp;gt;mount&amp;lt;/code&amp;gt; for mounting zfs-root:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=legacy zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Edit &amp;lt;code&amp;gt;/etc/rc.d/rc.S&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;rc.6&amp;lt;/code&amp;gt; to use regular &amp;lt;code&amp;gt;mount&amp;lt;/code&amp;gt; commands, remove &amp;lt;code&amp;gt;zfs&amp;lt;/code&amp;gt; commands. Edit &amp;lt;code&amp;gt;rc.6&amp;lt;/code&amp;gt; and remove or comment out &amp;lt;code&amp;gt;zpool export&amp;lt;/code&amp;gt; command. These edits undo changes made in the &amp;quot;ZFS root&amp;quot; wiki, but it shows the two different ways of mounting a zfs filesystem.&lt;br /&gt;
&lt;br /&gt;
You &amp;lt;i&amp;gt;might&amp;lt;/i&amp;gt; think to set &amp;lt;code&amp;gt;bootfs&amp;lt;/code&amp;gt; property like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool set bootfs=zfs-root zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
However, this will result in ZFS placing many restrictions on zfs-root as per how that option is used on Solaris systems:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; zfs-root must be VTOC (SMI) label, not GPT (EFI) label&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; zfs-root can only contain 1 vdev: either a plain disk, or a mirror&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
So, do &amp;lt;b&amp;gt;NOT&amp;lt;/b&amp;gt; set that property! If &amp;lt;code&amp;gt;bootfs&amp;lt;/code&amp;gt; is set, you would find that you cannot add vdevs to your zfs-root. If it is set already, then unset it like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool set bootfs= zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Make a directory to store files to be inside the initramfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkdir /boot/initramfs-source&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This directory will hold some files for the initial rootfs inside the kernel. Your &amp;lt;code&amp;gt;/boot&amp;lt;/code&amp;gt; should be on a small ext4 partition or on a mounted USB stick that you use to boot.&lt;br /&gt;
&lt;br /&gt;
Extract the slackware kernel-source package to obtain a copy of the kernel source, and make an initial kernel config for it:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir src&lt;br /&gt;
cd src&lt;br /&gt;
tar xvzf /mnt/cdrom/slackware64/k/kernel-source-*.txz&lt;br /&gt;
mv usr/src/linux-3.2.28 /usr/src/linux-3.2.28b&lt;br /&gt;
rm -r install&lt;br /&gt;
cd /usr/src/linux-3.2.28b&lt;br /&gt;
make menuconfig&lt;br /&gt;
  General setup-&amp;gt;Local version - append to kernel release = b&lt;br /&gt;
  General setup-&amp;gt;Default hostname                         = slackzfs&lt;br /&gt;
  General setup-&amp;gt;Initramfs source files(s)                = /boot/initramfs-source&lt;br /&gt;
  Device Drivers-&amp;gt;SCSI device support-&amp;gt;SCSI low-level drivers-&amp;gt; &amp;lt;*&amp;gt; SYM53C8XX Version 2 SCSI support&lt;br /&gt;
  File systems -&amp;gt; &amp;lt;*&amp;gt; The Extended 4 (ext4) filesystem&lt;br /&gt;
  # build in any hard drive controllers and filesystems that you need for booting&lt;br /&gt;
  # then save the config&lt;br /&gt;
make prepare scripts&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The kernel source has been set to have a &amp;quot;Local version&amp;quot; &amp;lt;code&amp;gt;b&amp;lt;/code&amp;gt;. This will result in modules installed to &amp;lt;code&amp;gt;/lib/modules/3.2.28b&amp;lt;/code&amp;gt; and keeps this kernel's source and modules seperate from slackware's kernel-generic package installation. The &amp;lt;code&amp;gt;make prepare scripts&amp;lt;/code&amp;gt; command readies the kernel source as needed before we can install a copy of spl and zfs modules into the kernel source tree.&lt;br /&gt;
&lt;br /&gt;
Now proceed to configure and copy spl and zfs into the kernel source tree:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd ~/src&lt;br /&gt;
tar xvzf ~/spl-0.6.0-rc11.tar.gz&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-0.6.0-rc11&lt;br /&gt;
./configure \&lt;br /&gt;
    --prefix=/ \&lt;br /&gt;
    --libdir=/lib64 \&lt;br /&gt;
    --includedir=/usr/include \&lt;br /&gt;
    --datarootdir=/usr/share \&lt;br /&gt;
    --enable-linux-builtin=yes \&lt;br /&gt;
    --with-linux=/usr/src/linux-3.2.28b \&lt;br /&gt;
    --with-linux-obj=/usr/src/linux-3.2.28b&lt;br /&gt;
wget https://raw.github.com/zfsonlinux/spl/master/copy-builtin&lt;br /&gt;
chmod +x copy-builtin&lt;br /&gt;
./copy-builtin /usr/src/linux-3.2.28b&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../spl-0.6.0rc11_3.2.28b-x86_64-1root.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
&lt;br /&gt;
tar xvzf ~/zfs-0.6.0-rc11.tar.gz&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-0.6.0-rc11&lt;br /&gt;
./configure \&lt;br /&gt;
    --prefix=/ \&lt;br /&gt;
    --libdir=/lib64 \&lt;br /&gt;
    --includedir=/usr/include \&lt;br /&gt;
    --datarootdir=/usr/share \&lt;br /&gt;
    --enable-linux-builtin=yes \&lt;br /&gt;
    --with-linux=/usr/src/linux-3.2.28b \&lt;br /&gt;
    --with-linux-obj=/usr/src/linux-3.2.28b \&lt;br /&gt;
    --with-spl=/root/src/spl-0.6.0-rc11&lt;br /&gt;
wget https://raw.github.com/zfsonlinux/zfs/master/copy-builtin&lt;br /&gt;
chmod +x copy-builtin&lt;br /&gt;
./copy-builtin /usr/src/linux-3.2.28b&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../zfs-0.6.0rc11_3.2.28b-x86_64-1root.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
At this point, the &amp;lt;code&amp;gt;copy-builtin&amp;lt;/code&amp;gt; scripts have installed the configured spl and zfs modules source into the kernel source. The regular &amp;lt;code&amp;gt;make menuconfig&amp;lt;/code&amp;gt; in the kernel source should now show options for spl and zfs in the kernel config.&lt;br /&gt;
&lt;br /&gt;
As of this writing, the copy-builtin script places the spl and zfs modules into the kernel source in places where the modules may not initialize in the best order, &amp;lt;i&amp;gt;after&amp;lt;/i&amp;gt; all lower-level storage drivers are initialized. If spl and zfs initialize too soon, there is a chance they may not be able to see all of the storage devices. The order of initialization (as seen in dmesg) of modules that are builtin to the kernel is the order that the modules are linked into the kernel during kernel compilation. The order of link depends on where the module source files are located in the kernel source tree. To ensure that spl and zfs will initialize after all hardware drivers, we move them into the &amp;lt;code&amp;gt;drivers&amp;lt;/code&amp;gt; tree and after all other drivers:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /usr/src/linux-3.2.28b&lt;br /&gt;
mkdir drivers/zfsonlinux&lt;br /&gt;
mv spl drivers/zfsonlinux&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  # remove references to spl&lt;br /&gt;
vi Makefile&lt;br /&gt;
  # remove references to spl&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.28b/fs&lt;br /&gt;
mv zfs ../drivers/zfsonlinux&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  # remove references to zfs&lt;br /&gt;
vi Makefile&lt;br /&gt;
  # remove references to zfs&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.28b/drivers&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  )# add line at end of menu, before &amp;quot;endmenu&amp;quot;:&lt;br /&gt;
  )source &amp;quot;drivers/zfsonlinux/Kconfig&amp;quot;&lt;br /&gt;
  )endmenu&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.28b/drivers&lt;br /&gt;
vi Makefile&lt;br /&gt;
  )# add line at very end of file:&lt;br /&gt;
  )obj-$(CONFIG_ZFSONLINUX) += zfsonlinux/&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.28b/drivers/zfsonlinux&lt;br /&gt;
cat &amp;gt; Kconfig &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
menuconfig ZFSONLINUX&lt;br /&gt;
	tristate &amp;quot;ZFSonLinux support&amp;quot;&lt;br /&gt;
&lt;br /&gt;
if ZFSONLINUX&lt;br /&gt;
&lt;br /&gt;
source &amp;quot;drivers/zfsonlinux/spl/Kconifg&amp;quot;&lt;br /&gt;
&lt;br /&gt;
source &amp;quot;drivers/zfsonlinux/zfs/Kconifg&amp;quot;&lt;br /&gt;
&lt;br /&gt;
endif&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.28b/zfsonlinux&lt;br /&gt;
cat &amp;gt; Makefile &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
obj-$(CONFIG_SPL) += spl/&lt;br /&gt;
obj-$(CONFIG_ZFS) += zfs/&lt;br /&gt;
EOF&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This completes the move of the spl and zfs modules in the kernel source tree to be under &amp;lt;code&amp;gt;drivers/zfsonlinux&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Now, in kernel configuration, you can build in the modules as follows:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /usr/src/linux-3.2.28b&lt;br /&gt;
make menuconfig&lt;br /&gt;
   Device Drivers -&amp;gt;&lt;br /&gt;
    &amp;lt;*&amp;gt; ZFSonLinux support -&amp;gt;&lt;br /&gt;
      &amp;lt;*&amp;gt; Solaris Porting Layer (SPL)&lt;br /&gt;
      &amp;lt;*&amp;gt;     ZFS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the kernel config, we set &amp;lt;code&amp;gt;/boot/initramfs-source&amp;lt;/code&amp;gt; as source location of the contents to be linked into kernel's builtin initramfs (rootfs). Now, we create some files that are needed to be in the initramfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /boot/initramfs-source&lt;br /&gt;
&lt;br /&gt;
# make standard directories&lt;br /&gt;
mkdir -p proc dev sys mnt bin sbin etc/zfs&lt;br /&gt;
&lt;br /&gt;
# zfs seems to want mtab present, even if empty&lt;br /&gt;
touch etc/mtab&lt;br /&gt;
&lt;br /&gt;
# if zpool.cache file can be read by zfs at module init, it imports the pools in the cache&lt;br /&gt;
cp /etc/zfs/zpool.cache-initrd etc/zfs/zpool.cache&lt;br /&gt;
&lt;br /&gt;
It is time to pause for a moment here and talk about zpool.cache: Using it is actually dangerous. We are not using udev and it's persistent block device filenames (/dev/disk/by-*), but are using the default kernel block device names (/dev/sd*) in devtmpfs. Device names for a hard drive in /dev can potentially change on boot depending on disk controller initialization order and disk drive response time. Adding another disk controller or hard disk on a controller can result in device name assignment changes to all the hard disks. A zpool.cache file holds all the zfs_member device filenames /dev/sd* for a pool configuration, but the zpool.cache configuration will be incorrect if device filenames have been changed or swapped around and this could result in a faulted pool that may or may not be recoverable. Using zpool.cache to import pools at boot, even with udev persistent device filenames, is potentially destructive if devices have been changed around. The proper thing to do is zpool_import and do not include zpool.cache in the initramfs.&lt;br /&gt;
&lt;br /&gt;
# make initial console device node; otherwise, there is a problem at startup:&lt;br /&gt;
# &amp;quot;Warning: unable to open an initial console&amp;quot; and you'd have problems with console and tty login&lt;br /&gt;
# making these nodes from within /init is not early enough to avoid problem&lt;br /&gt;
mknod dev/console c 5 1   # system console&lt;br /&gt;
&lt;br /&gt;
# make memory device kmsg to &amp;quot;printk&amp;quot; kernel messages&lt;br /&gt;
# we can write to this file to send out messages&lt;br /&gt;
mknod dev/kmsg    c 1 11  # lines printed to kmsg enter kernel messages buffer&lt;br /&gt;
&lt;br /&gt;
# recommended loop0 device to mount fs images&lt;br /&gt;
mknod dev/loop0   b 7 0&lt;br /&gt;
&lt;br /&gt;
# make initial virtual terminal devices&lt;br /&gt;
mknod dev/tty     c 5 0   # current tty&lt;br /&gt;
mknod dev/tty0    c 4 0   # current virtual term&lt;br /&gt;
mknod dev/tty1    c 4 1   # login virtual term 1 (F1)&lt;br /&gt;
&lt;br /&gt;
# make alternative console=ttyS0 standard 8250/16550 UART serial port devices&lt;br /&gt;
#   useful with kernel parameter console=ttyS0&lt;br /&gt;
#          with qemu -nographic -option-rom sgabios.bin,bootindex=0&lt;br /&gt;
mknod dev/ttyS0   c 4 64  # COM1&lt;br /&gt;
mknod dev/ttyS1   c 4 65  # COM2&lt;br /&gt;
mknod dev/ttyS2   c 4 66  # COM3&lt;br /&gt;
mknod dev/ttyS3   c 4 67  $ COM4&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This should be enough device nodes initially in the initramfs. Once devtmpfs mounts over /dev inside initramfs, a lot more devices are available in it by default.&lt;br /&gt;
&lt;br /&gt;
The initramfs needs an &amp;lt;code&amp;gt;/init&amp;lt;/code&amp;gt; program that will be run automatically by the kernel as process id 1, the first program to run on the system. This program's task is to mount a root filesystem, switch it to be the new root (/), and then exec the init (&amp;lt;code&amp;gt;/sbin/init&amp;lt;/code&amp;gt;) program that is on the new root so that the new root system is booted.&lt;br /&gt;
&lt;br /&gt;
The common way to make /init is using busybox with files like these in /boot/initrd-tree or /boot/initramfs-source:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
bin/busybox&lt;br /&gt;
bin/ash -&amp;gt; busybox&lt;br /&gt;
bin/sh -&amp;gt; busybox&lt;br /&gt;
# run busybox to see what other &amp;quot;applets&amp;quot; can be symlinked to it&lt;br /&gt;
# when busybox is run as a different symlinked applet name, it runs as the applet&lt;br /&gt;
init&lt;br /&gt;
# init can be an ash script, see slackware's /boot/initrd-tree/init for example&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For example, as an ash script, slackware's init does the following:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;parse kernel parameters passed into it and set variables based on them&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;start udevd and trigger rules for block devices to setup initial /dev devices&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;load kernel modules and keyboard map&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;run mdadm, cryptsetup, lvm, zpool/zfs to setup more devices&lt;br /&gt;
     (any udev rules for them should do more /dev setup in the background)&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;mount the root filesystem read-only at /mnt&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;stat /mnt/sbin/init, and if not executable run a rescue shell /bin/sh&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;shutdown udevd so it can be restarted by root system when booted&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;mount --move {proc,sys,run,dev} to under /mnt&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;run: exec switch_root /mnt /sbin/init $RUNLEVEL&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The slackware mkinitrd package is a fully configured BusyBox installation that makes an external initramfs image file, initrd.gz, that is passed to the kernel by the bootloader (lilo). It could be changed to be internal to the kernel by just using initrd-tree as the CONFIG_INITRAMFS_SOURCE in the kernel config and removing initrd in the lilo.conf.&lt;br /&gt;
&lt;br /&gt;
The main purpose of most initramfs/initrd is to load and configure kernel modules and devices needed to mount a root filesystem. Because the spl/zfs modules are builtin, there isn't really a lot that needs to be done by an initramfs. What remains to be done is import the zfs-root pool, mount it, and exec the system /sbin/init. The kernel's &amp;quot;legacy&amp;quot; parameters &amp;lt;code&amp;gt;root=&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;rootfstype=&amp;lt;/code&amp;gt; that are able to directly boot a root disk do not work with ZFS at this time because ZFS pools always need to be imported before it is possible to mount and boot on them. The automatic import that ZFS can do by using a cachefile (/etc/zfs/zpool.cache) stored in initramfs still does not work with the legacy boot parameters because at an earlier stage of the boot process, the kernel ignores a rootfs that does not contain an &amp;lt;code&amp;gt;/init&amp;lt;/code&amp;gt; program, and/or the device type of an imported pool is not the device types recognized by the legacy boot as valid root devices.&lt;br /&gt;
&lt;br /&gt;
You could just continue to use slackware's mkinitrd package as in the &amp;quot;ZFS root&amp;quot; wiki and it works the same whether the modules are builtin or not. But, by building the spl/zfs modules in, aren't we really wanting to get rid of using the mkinitrd/initrd.gz? We'd like to have a kernel with everything in it to boot, and use a simple lilo image entry that has no initrd.&lt;br /&gt;
&lt;br /&gt;
We can do this, and not use the mkinitrd package, but we still need to finish our own initramfs &amp;lt;code&amp;gt;/init&amp;lt;/code&amp;gt; program to import, mount, switch root, and boot. Save the following c program to &amp;quot;foobarz-init.c&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/* software product name: foobarz-init.c&lt;br /&gt;
 * suggested binary name: /init (in initramfs-source, rootfs)&lt;br /&gt;
 * license              : BSD&lt;br /&gt;
 * license text:&lt;br /&gt;
Copyright (c) 2012, foobarz&lt;br /&gt;
All rights reserved.&lt;br /&gt;
&lt;br /&gt;
Redistribution and use in source and binary forms, with or without&lt;br /&gt;
modification, are permitted provided that the following conditions are met:&lt;br /&gt;
    * Redistributions of source code must retain the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer.&lt;br /&gt;
    * Redistributions in binary form must reproduce the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer in the&lt;br /&gt;
      documentation and/or other materials provided with the distribution.&lt;br /&gt;
    * Neither the name of the &amp;lt;organization&amp;gt; nor the&lt;br /&gt;
      names of its contributors may be used to endorse or promote products&lt;br /&gt;
      derived from this software without specific prior written permission.&lt;br /&gt;
&lt;br /&gt;
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &amp;quot;AS IS&amp;quot; AND&lt;br /&gt;
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED&lt;br /&gt;
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE&lt;br /&gt;
DISCLAIMED. IN NO EVENT SHALL &amp;lt;COPYRIGHT HOLDER&amp;gt; BE LIABLE FOR ANY&lt;br /&gt;
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES&lt;br /&gt;
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;&lt;br /&gt;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND&lt;br /&gt;
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT&lt;br /&gt;
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS&lt;br /&gt;
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
/* Your initramfs-source should contain the following&lt;br /&gt;
 *&lt;br /&gt;
 * cd /boot/initramfs-source&lt;br /&gt;
 * mkdir -p proc dev sys mnt bin sbin etc/zfs&lt;br /&gt;
 * touch etc/mtab&lt;br /&gt;
 * cp /etc/zfs/zpool.cache-initrd etc/zfs/zpool.cache&lt;br /&gt;
 * # zpool.cache is optional - zpool_import_ kernel params can be used instead&lt;br /&gt;
 * #  see below for details on using zpool_import&lt;br /&gt;
 * mknod dev/console c 5 1   # system console&lt;br /&gt;
 * mknod dev/kmsg    c 1 11  # lines printed to kmsg enter kernel messages buffer&lt;br /&gt;
 * mknod dev/loop0   b 7 0&lt;br /&gt;
 * mknod dev/tty     c 5 0   # current tty&lt;br /&gt;
 * mknod dev/tty0    c 4 0   # current virtual term&lt;br /&gt;
 * mknod dev/tty1    c 4 1   # login virtual term 1 (F1)&lt;br /&gt;
 * mknod dev/ttyS0   c 4 64  # COM1&lt;br /&gt;
 * mknod dev/ttyS1   c 4 65  # COM2&lt;br /&gt;
 * mknod dev/ttyS2   c 4 66  # COM3&lt;br /&gt;
 * mknod dev/ttyS3   c 4 67  $ COM4&lt;br /&gt;
 *&lt;br /&gt;
 * and this program compiled to /boot/initramfs-source/init&lt;br /&gt;
 *&lt;br /&gt;
 * Set kernel config option&lt;br /&gt;
 *  CONFIG_INITRAMFS_SOURCE=/boot/initramfs-source&lt;br /&gt;
 * to build the initramfs into your kernel image&lt;br /&gt;
 *  that also has builtin drivers (spl and zfs, etc).&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
#define FOOBARZ_INIT_VERSION &amp;quot;1.1.1&amp;quot;&lt;br /&gt;
#define _BSD_SOURCE&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdarg.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;fcntl.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/mount.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sysexits.h&amp;gt;&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
/* support for zpool import&lt;br /&gt;
 *&lt;br /&gt;
 * If -DINCLUDE_ZPOOL_IMPORT, then support to import a zpool is&lt;br /&gt;
 * enabled in the program. Enabling it will add many dependencies to the&lt;br /&gt;
 * compile and link; for example:&lt;br /&gt;
 *&lt;br /&gt;
 * gcc -static -DINCLUDE_ZPOOL_IMPORT \&lt;br /&gt;
 *    foobarz-init.c -include /usr/src/zfs-0.6.0-rc11/3.2.28/zfs_config.h \&lt;br /&gt;
 *   -o init \&lt;br /&gt;
 *   -I /usr/include/libspl -I /usr/include/libzfs \&lt;br /&gt;
 *   -lzfs -lnvpair -lzpool -luutil -luuid -lrt -lz -lm -lpthread \&lt;br /&gt;
 *   -I /usr/include/tirpc \&lt;br /&gt;
 *   -ltirpc&lt;br /&gt;
 *&lt;br /&gt;
 * Note that libtirpc is a drop-in replacement for the SunRPC functions that&lt;br /&gt;
 * used to be in glibc. No additional includes are needed, just the gcc -I and -l&lt;br /&gt;
 * options for tirpc.&lt;br /&gt;
 *&lt;br /&gt;
 * Otherwise, with -UINCLUDE_ZPOOL_IMPORT, the compile is just:&lt;br /&gt;
 * gcc -static foobarz-init.c -o init&lt;br /&gt;
 */&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
#include &amp;lt;libzfs.h&amp;gt;&lt;br /&gt;
#else&lt;br /&gt;
#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/stat.h&amp;gt;&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#define PARAM_REQ_NO 0&lt;br /&gt;
#define PARAM_REQ_YES 1&lt;br /&gt;
#define PARAM_SRC_DEFAULT 0&lt;br /&gt;
#define PARAM_SRC_CMDLINE 1&lt;br /&gt;
&lt;br /&gt;
void printk(char *fmt, ...) {&lt;br /&gt;
  FILE* f;&lt;br /&gt;
  int fd;&lt;br /&gt;
  va_list args;&lt;br /&gt;
&lt;br /&gt;
  f = fopen(&amp;quot;/dev/kmsg&amp;quot;, &amp;quot;w&amp;quot;);&lt;br /&gt;
  va_start(args, fmt);&lt;br /&gt;
  vfprintf(f, fmt, args);&lt;br /&gt;
  va_end(args);&lt;br /&gt;
  fflush(f);&lt;br /&gt;
  fclose(f);&lt;br /&gt;
  /* avoid flooding kmsg and having msgs suppressed; 20msgs/sec */&lt;br /&gt;
  usleep(50000);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[]) {&lt;br /&gt;
 /*** variables */&lt;br /&gt;
&lt;br /&gt;
 int i;&lt;br /&gt;
 int   fd = 0; /* file descriptor */&lt;br /&gt;
 unsigned long mountflags;&lt;br /&gt;
&lt;br /&gt;
 /* kernel command line */&lt;br /&gt;
 off_t cmdline_size;&lt;br /&gt;
 char* cmdline; /* to be malloc 4096B */&lt;br /&gt;
 char* cmdline_end;&lt;br /&gt;
 char* temp_end;&lt;br /&gt;
 char* src_msg; /* default or cmdline */&lt;br /&gt;
 int flag_param_missing = 0;&lt;br /&gt;
&lt;br /&gt;
 /* use to hold contents of a misc /proc/&amp;lt;file&amp;gt; */&lt;br /&gt;
 char* miscproc_buff; /* to be malloc 4096B */&lt;br /&gt;
 off_t miscproc_size;&lt;br /&gt;
&lt;br /&gt;
 /* note about environ, argv, and kernel cmdline for init:&lt;br /&gt;
  *   environ is not defined for init&lt;br /&gt;
  *   only argv[0] is set for init&lt;br /&gt;
  *   kernel command line parameters are accessed&lt;br /&gt;
  *   at /proc/cmdline&lt;br /&gt;
  */&lt;br /&gt;
&lt;br /&gt;
 /* kernel parameters expected to be name=value */&lt;br /&gt;
 /* do not use quotes or spaces in parameters   */&lt;br /&gt;
 /* you can add more params somwhere after root= */&lt;br /&gt;
 struct nv { char* n; char* v; char* v_end; int req; int src; };&lt;br /&gt;
 struct nv param[] = {&lt;br /&gt;
   { &amp;quot;root=&amp;quot;,       NULL, NULL, PARAM_REQ_YES, PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;rootfstype=&amp;quot;, NULL, NULL, PARAM_REQ_YES, PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;mountopt=&amp;quot;,   NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;init=&amp;quot;,       NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;runlevel=&amp;quot;,   NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;console=&amp;quot;,    NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT }&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
   ,&lt;br /&gt;
   { &amp;quot;zpool_import_name=&amp;quot;,    NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;zpool_import_guid=&amp;quot;,    NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;zpool_import_newname=&amp;quot;, NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;zpool_import_force=&amp;quot;,   NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT }&lt;br /&gt;
#endif&lt;br /&gt;
 };&lt;br /&gt;
 enum {&lt;br /&gt;
	 iroot,&lt;br /&gt;
	 irootfstype,&lt;br /&gt;
	 imountopt,&lt;br /&gt;
	 iinit,&lt;br /&gt;
	 irunlevel,&lt;br /&gt;
	 iconsole,&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
	 izpool_import_name,&lt;br /&gt;
	 izpool_import_guid,&lt;br /&gt;
	 izpool_import_newname,&lt;br /&gt;
	 izpool_import_force,&lt;br /&gt;
#endif&lt;br /&gt;
	 ilastparam&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
 libzfs_handle_t* libzfs = NULL;&lt;br /&gt;
 importargs_t iargs = { 0 };&lt;br /&gt;
 nvlist_t* pools = NULL;&lt;br /&gt;
 nvpair_t* pool = NULL;&lt;br /&gt;
 nvlist_t* config = NULL;&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
 /*** program */&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;foobarz-init, version %s: booting initramfs.\n&amp;quot;, FOOBARZ_INIT_VERSION);&lt;br /&gt;
&lt;br /&gt;
 cmdline       = (char*) malloc(4096);&lt;br /&gt;
 miscproc_buff = (char*) malloc(4096);&lt;br /&gt;
 if( (cmdline == NULL) || (miscproc_buff == NULL) ) {&lt;br /&gt;
   printk(&amp;quot;Unable to allocate buffer memory: malloc: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount proc /proc&lt;br /&gt;
  *  note: some /dev devices symlink into /proc&lt;br /&gt;
  *  proc contains info about processes, including cmdline etc. */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount proc /proc\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;proc&amp;quot;, &amp;quot;/proc&amp;quot;, &amp;quot;proc&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
   printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
   printk(&amp;quot;Mount proc successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount devtmpfs /dev&lt;br /&gt;
  *  note: This simple init program works if your root device is made from devices&lt;br /&gt;
  *  that are available by default in devtmpfs, such as /dev/sd*&lt;br /&gt;
  *&lt;br /&gt;
  *  For zfs, your root zfs pool should be created with default device nodes and&lt;br /&gt;
  *  then it should be mountable by this simple init program.&lt;br /&gt;
  *&lt;br /&gt;
  *  udev may be needed to configure device nodes and symlinks required&lt;br /&gt;
  *  to access a root device configuration made with such nodes and symlinks.&lt;br /&gt;
  *  If you need udevd, you can include it into your initramfs-source and&lt;br /&gt;
  *  modify this program to run it before attempting to mount your root device.&lt;br /&gt;
  *  However, if udevd is needed, a significant number of userspace programs may also be&lt;br /&gt;
  *  required by rules in /lib/udev/. You could install busybox + udev (about 5MB) or&lt;br /&gt;
  *  coreutils + util-linux + bash + udev (about 25MB) into initramfs-source. But, at that&lt;br /&gt;
  *  point you'd have ash or bash and many tools that are easier to use than this&lt;br /&gt;
  *  simple init program; it would then be easy to have /init as #!/bin/&amp;lt;b&amp;gt;ash script. */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount devtmpfs /dev\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;devtmpfs&amp;quot;, &amp;quot;/dev&amp;quot;, &amp;quot;devtmpfs&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
   printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
   printk(&amp;quot;Mount devtmpfs successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount sysfs /sys&lt;br /&gt;
  *  note: some kernel modules try to access /sys with userspace helpers to echo values into /sys variables;&lt;br /&gt;
  *  such modules expect a minimal userspace that contains coreutils or busybox */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount sysfs /sys\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;sysfs&amp;quot;, &amp;quot;/sys&amp;quot;, &amp;quot;sysfs&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
   printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
   printk(&amp;quot;Mount sysfs successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* process kernel command line */&lt;br /&gt;
 fd = open(&amp;quot;/proc/cmdline&amp;quot;, O_RDONLY);&lt;br /&gt;
 if( fd == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Cannot open /proc/cmdline: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 /* note, on /proc fs:&lt;br /&gt;
  *       lseek likely always returns error&lt;br /&gt;
  *       stat likely always returns st_size = 0&lt;br /&gt;
  *   so determining size of /proc file means just reading it;&lt;br /&gt;
  *   you have to read /proc files according to their documented&lt;br /&gt;
  *   maximum sizes; this is probably for performance reasons */&lt;br /&gt;
 cmdline_size = read(fd, cmdline, 4095);&lt;br /&gt;
 if( cmdline_size == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Failed to read /proc/cmdline: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 close(fd);&lt;br /&gt;
&lt;br /&gt;
 /* cmdline may be newline + null terminated, but make it null + null */&lt;br /&gt;
 cmdline[cmdline_size] = '\0';&lt;br /&gt;
 if( cmdline[cmdline_size-1] == '\n' ) {&lt;br /&gt;
   cmdline[cmdline_size-1] = '\0';&lt;br /&gt;
   cmdline_size--;&lt;br /&gt;
   cmdline_end = cmdline + cmdline_size;&lt;br /&gt;
 }&lt;br /&gt;
 printk(&amp;quot;Kernel cmdline size: %i\n&amp;quot;, cmdline_size);&lt;br /&gt;
 printk(&amp;quot;Kernel cmdline: \&amp;quot;%s\&amp;quot;\n&amp;quot;, cmdline);&lt;br /&gt;
&lt;br /&gt;
 /* find v and v_end of values in cmdline */&lt;br /&gt;
 for( i=iroot; i&amp;lt;ilastparam; i++ ) {&lt;br /&gt;
   param[i].v = strstr(cmdline, param[i].n);&lt;br /&gt;
   if( param[i].v != NULL ) {&lt;br /&gt;
     param[i].src = PARAM_SRC_CMDLINE;&lt;br /&gt;
     while( *(param[i].v) != '=' ) param[i].v++;&lt;br /&gt;
     param[i].v++;&lt;br /&gt;
     temp_end = param[i].v;&lt;br /&gt;
     while( !( (*temp_end == ' ') ||&lt;br /&gt;
               (*temp_end == '\n') ||&lt;br /&gt;
               (temp_end == cmdline_end)&lt;br /&gt;
	     ) ) temp_end++;&lt;br /&gt;
     if( temp_end == param[i].v ) {&lt;br /&gt;
       printk(&amp;quot;Kernel parameter %s: value missing.\n&amp;quot;, param[i].n);&lt;br /&gt;
       param[i].v = NULL;&lt;br /&gt;
     } else param[i].v_end = temp_end;&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 for( i=iroot; i&amp;lt;ilastparam; i++ ) {&lt;br /&gt;
   /* terminate value strings */&lt;br /&gt;
   if( param[i].v_end != NULL ) *(param[i].v_end) = '\0';&lt;br /&gt;
   /* set defaults if no value on cmdline */&lt;br /&gt;
   if( param[i].v == NULL ) {&lt;br /&gt;
     param[i].src = PARAM_SRC_DEFAULT;&lt;br /&gt;
     if( param[i].req == PARAM_REQ_YES ) flag_param_missing = 1;&lt;br /&gt;
     switch(i) {&lt;br /&gt;
       case iroot      : param[i].v = &amp;quot;&amp;lt;missing required param&amp;gt;&amp;quot; ; break;&lt;br /&gt;
       case irootfstype: param[i].v = &amp;quot;&amp;lt;missing required param&amp;gt;&amp;quot; ; break;&lt;br /&gt;
       case imountopt  : param[i].v = &amp;quot;ro&amp;quot;        ; break;&lt;br /&gt;
       case iinit      : param[i].v = &amp;quot;/sbin/init&amp;quot;; break;&lt;br /&gt;
       case irunlevel  : param[i].v = &amp;quot;3&amp;quot;         ; break;&lt;br /&gt;
       case iconsole   : param[i].v = &amp;quot;console&amp;quot;   ; break;&lt;br /&gt;
       default         : param[i].v = NULL;&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
   if(param[i].src == PARAM_SRC_DEFAULT) src_msg = &amp;quot;default&amp;quot;;&lt;br /&gt;
   else src_msg = &amp;quot;cmdline&amp;quot;;&lt;br /&gt;
   printk(&amp;quot;Using %s \&amp;quot;%s\&amp;quot; (source: %s)\n&amp;quot;, param[i].n, param[i].v, src_msg);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 if( flag_param_missing ) {&lt;br /&gt;
   printk(&amp;quot;Aborting boot process: missing required kernel parameter(s).\n&amp;quot;);&lt;br /&gt;
   return EX_USAGE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* generic nv pair kernel cmdline processing finished&lt;br /&gt;
  *  now, examine specific params for defaults and correctness */&lt;br /&gt;
&lt;br /&gt;
 /* param[irootfstype]: can be checked against /proc/filesystems: */&lt;br /&gt;
 fd = open(&amp;quot;/proc/filesystems&amp;quot;, O_RDONLY);&lt;br /&gt;
 if( fd == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Cannot open /proc/filesystems: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 miscproc_size = read(fd, miscproc_buff, 4095);&lt;br /&gt;
 if( miscproc_size == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Failed to read /proc/filesystems: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 close(fd);&lt;br /&gt;
 if( strstr(miscproc_buff, param[irootfstype].v) == NULL ) {&lt;br /&gt;
   printk(&amp;quot;%s \&amp;quot;%s\&amp;quot;: filesystem type not available.\n&amp;quot;, param[irootfstype].n, param[irootfstype].v);&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* zfs-specific */&lt;br /&gt;
 if( strcmp(param[irootfstype].v, &amp;quot;zfs&amp;quot;) == 0 ) {&lt;br /&gt;
   if( access(&amp;quot;/etc/zfs/zpool.cache&amp;quot;, F_OK) == 0 )&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/zfs/zpool.cache is present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
   else&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/zfs/zpool.cache not present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
&lt;br /&gt;
   if( access(&amp;quot;/etc/hostid&amp;quot;, F_OK) == 0 )&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/hostid is present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
   else&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/hostid not present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
   /* zpool import */&lt;br /&gt;
   if( (param[izpool_import_name].v != NULL) || (param[izpool_import_guid].v != NULL) ) {&lt;br /&gt;
	printk(&amp;quot;zpool_import: import requested.\n&amp;quot;);&lt;br /&gt;
	if( (param[izpool_import_name].v != NULL) &amp;amp;&amp;amp; (param[izpool_import_guid].v != NULL) ) {&lt;br /&gt;
		printk(&amp;quot;zpool_import: given both pool name and guid; using guid.\n&amp;quot;);&lt;br /&gt;
		param[izpool_import_name].v = NULL;&lt;br /&gt;
	}&lt;br /&gt;
	if( param[izpool_import_name].v != NULL )&lt;br /&gt;
		printk(&amp;quot;zpool_import: pool name: %s\n&amp;quot;, param[izpool_import_name].v );&lt;br /&gt;
	else&lt;br /&gt;
		printk(&amp;quot;zpool_import: pool guid: %s\n&amp;quot;, param[izpool_import_guid].v );&lt;br /&gt;
&lt;br /&gt;
	iargs.path = NULL;&lt;br /&gt;
	iargs.paths = 0;&lt;br /&gt;
	iargs.poolname = param[izpool_import_name].v;&lt;br /&gt;
	if( param[izpool_import_guid].v != NULL )&lt;br /&gt;
		iargs.guid = strtoull(param[izpool_import_guid].v, NULL, 10);&lt;br /&gt;
	else&lt;br /&gt;
		iargs.guid = 0;&lt;br /&gt;
	iargs.cachefile = NULL;&lt;br /&gt;
	if( (param[izpool_import_force].v != NULL) &amp;amp;&amp;amp; (strcmp(param[izpool_import_force].v, &amp;quot;1&amp;quot;) == 0) ) {&lt;br /&gt;
		iargs.can_be_active = 1;&lt;br /&gt;
		printk(&amp;quot;zpool_import: import forced.\n&amp;quot;);&lt;br /&gt;
	} else {&lt;br /&gt;
		iargs.can_be_active = 0;&lt;br /&gt;
		printk(&amp;quot;zpool_import: import not forced.\n&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
	iargs.unique = 1;&lt;br /&gt;
	iargs.exists = 1;&lt;br /&gt;
&lt;br /&gt;
	printk(&amp;quot;zpool_import: init libzfs.\n&amp;quot;);&lt;br /&gt;
	libzfs = libzfs_init();&lt;br /&gt;
	printk(&amp;quot;zpool_import: searching for pool.\n&amp;quot;);&lt;br /&gt;
	pools = zpool_search_import(libzfs, &amp;amp;iargs);&lt;br /&gt;
	if( (pools == NULL) || nvlist_empty(pools) )&lt;br /&gt;
		printk(&amp;quot;zpool_import: pool not available for import, or already imported by cachefile.\n&amp;quot;);&lt;br /&gt;
	else {&lt;br /&gt;
		printk(&amp;quot;zpool_import: getting pool information.\n&amp;quot;);&lt;br /&gt;
		pool = nvlist_next_nvpair(pools, pool);&lt;br /&gt;
		printk(&amp;quot;zpool_import: getting pool configuration.\n&amp;quot;);&lt;br /&gt;
		nvpair_value_nvlist(pool, &amp;amp;config);&lt;br /&gt;
		printk(&amp;quot;zpool_import: attempting pool import.\n&amp;quot;);&lt;br /&gt;
		if( zpool_import(libzfs, config, param[izpool_import_newname].v, NULL) != 0 ) {&lt;br /&gt;
			printk(&amp;quot;zpool_import: import failed.\n&amp;quot;);&lt;br /&gt;
			printk(&amp;quot;zpool_import: error description: %s\n&amp;quot;, libzfs_error_description(libzfs) );&lt;br /&gt;
			printk(&amp;quot;zpool_import: error action: %s\n&amp;quot;, libzfs_error_action(libzfs) );&lt;br /&gt;
		} else  printk(&amp;quot;zpool_import: import successful.\n&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
	printk(&amp;quot;zpool_import: fini libzfs.\n&amp;quot;);&lt;br /&gt;
	libzfs_fini(libzfs);&lt;br /&gt;
   }&lt;br /&gt;
#endif /* zpool_import */&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 if(      strcmp(param[imountopt].v, &amp;quot;ro&amp;quot;) == 0 ) mountflags = MS_RDONLY;&lt;br /&gt;
 else if( strcmp(param[imountopt].v, &amp;quot;rw&amp;quot;) == 0 ) mountflags = 0;&lt;br /&gt;
 else {&lt;br /&gt;
   printk(&amp;quot;%s \&amp;quot;%s\&amp;quot;: invalid parameter value; defaulting to \&amp;quot;ro\&amp;quot;.\n&amp;quot;, param[imountopt].n, param[imountopt].v);&lt;br /&gt;
   mountflags = MS_RDONLY;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* param[iroot]: nothing to check; if user gives bad root=device then mount fails */&lt;br /&gt;
&lt;br /&gt;
 /* try to mount root=device at /mnt&lt;br /&gt;
  *&lt;br /&gt;
  * note: for zfs, if a copy of /etc/zfs/zpool.cache (when pool is imported) is put in initramfs-source, then&lt;br /&gt;
  * the zfs module can read it and automatically import the pools described in the cache file; the imported&lt;br /&gt;
  * pools can be available to mount here if they were created using standard device names, otherwise&lt;br /&gt;
  * udevd may be required to run before mounting the pool */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount -t %s -o %s %s /mnt.\n&amp;quot;, param[irootfstype].v, param[imountopt].v, param[iroot].v);&lt;br /&gt;
 if( mount(param[iroot].v, &amp;quot;/mnt&amp;quot;, param[irootfstype].v, mountflags, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 printk(&amp;quot;%s mounted successfully.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
&lt;br /&gt;
 /* check to see if the mounted root filesystem has an executable init program */&lt;br /&gt;
 chdir(&amp;quot;/mnt&amp;quot;);&lt;br /&gt;
 if( access(param[iinit].v+1, X_OK) != 0 ) {&lt;br /&gt;
   chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
   printk(&amp;quot;access X_OK: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   printk(&amp;quot;The init program /mnt/%s is not present or not executable.\n&amp;quot;, param[iinit].v+1);&lt;br /&gt;
   printk(&amp;quot;Aborting boot process: no init program.\n&amp;quot;);&lt;br /&gt;
   printk(&amp;quot;Unmounting %s.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
   if( umount(&amp;quot;/mnt&amp;quot;) == -1 ) {&lt;br /&gt;
     printk(&amp;quot;umount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
     printk(&amp;quot;Failed to umount %s.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
   } else printk(&amp;quot;Successfully unmounted %s.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
 printk(&amp;quot;Init program /mnt/%s is present and executable.\n&amp;quot;, param[iinit].v+1);&lt;br /&gt;
&lt;br /&gt;
 /* switch the root / from initramfs to the mounted new root device at /mnt.&lt;br /&gt;
  *&lt;br /&gt;
  * note: after this switch, it is not possible to access the initramfs files anymore,&lt;br /&gt;
  * yet they consume ram memory unless they are deleted here before switching.&lt;br /&gt;
  * Any programs that are run after clearing the initramfs and switching root must exist on the new root.&lt;br /&gt;
  * This program may safely delete itself (/init) since it is already in ram and executing.&lt;br /&gt;
  * If you have installed additional files and programs in initramfs that consume significant ram,&lt;br /&gt;
  * then you need to insert additional code here to delete those files (carefully). */&lt;br /&gt;
&lt;br /&gt;
 /* delete files off of initramfs to free ram memory */&lt;br /&gt;
 printk(&amp;quot;Freeing memory from initramfs...\n&amp;quot;);&lt;br /&gt;
 if( unlink(argv[0]) != 0 ) printk(&amp;quot;unlink %s: %s\n&amp;quot;, argv[0], strerror(errno));&lt;br /&gt;
 else printk(&amp;quot;%s %s&amp;quot;, argv[0], &amp;quot;deleted from initramfs.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 /* switch root */&lt;br /&gt;
 printk(&amp;quot;Beginning switch root procedure.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(1) Attempting cmd: mount --move /dev /mnt/dev \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/dev&amp;quot;, &amp;quot;/mnt/dev&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(2) Attempting cmd: mount --move /proc /mnt/proc \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/proc&amp;quot;, &amp;quot;/mnt/proc&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(3) Attempting cmd: mount --move /sys /mnt/sys \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/sys&amp;quot;, &amp;quot;/mnt/sys&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(4) Attempting cmd: chdir /mnt \n&amp;quot;);&lt;br /&gt;
 if( chdir(&amp;quot;/mnt&amp;quot;) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: chdir: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(5) Attempting cmd: mount --move . / \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;.&amp;quot;, &amp;quot;/&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(6) Attempting cmd: chroot . \n&amp;quot;);&lt;br /&gt;
 if( chroot(&amp;quot;.&amp;quot;) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: chroot: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(7) Attempting cmd: chdir / \n&amp;quot;);&lt;br /&gt;
 if( chdir(&amp;quot;/&amp;quot;) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: chdir: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 printk(&amp;quot;Completed switch root procedure.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 /* check for &amp;quot;console=&amp;quot; kernel parameter and switch&lt;br /&gt;
  *  stdin, stdout, and stderr to named console device&lt;br /&gt;
  */&lt;br /&gt;
 if( param[iconsole].src == PARAM_SRC_CMDLINE ) {&lt;br /&gt;
   printk(&amp;quot;Console redirection to device %s requested.\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
   /* expect only basename of console device (e.g., ttyS0), so chdir /dev */&lt;br /&gt;
   chdir(&amp;quot;/dev&amp;quot;);&lt;br /&gt;
   if( access(param[iconsole].v, F_OK ) == 0 ) {&lt;br /&gt;
     printk(&amp;quot;Opening stdin, stdout, and stderr on %s.\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
     close(0);&lt;br /&gt;
     open(param[iconsole].v, O_RDWR);&lt;br /&gt;
     dup2(0, 1);&lt;br /&gt;
     dup2(0, 2);&lt;br /&gt;
   } else {&lt;br /&gt;
     printk(&amp;quot;access F_OK: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
     printk(&amp;quot;Could not access device: %s!\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
     printk(&amp;quot;Console redirection to device %s aborted!\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
   }&lt;br /&gt;
   chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;Execing: \&amp;quot;%s %s\&amp;quot; to boot mounted root system.\n&amp;quot;, param[iinit].v, param[irunlevel].v);&lt;br /&gt;
&lt;br /&gt;
 /* free resources held to this point */&lt;br /&gt;
 free(cmdline);&lt;br /&gt;
 free(miscproc_buff);&lt;br /&gt;
&lt;br /&gt;
 if( execl(param[iinit].v, param[irunlevel].v, (char *) NULL ) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: execl: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If foobarz-init is updated, you can find the latest version at [https://github.com/foobarz/foobarz-init github].&lt;br /&gt;
&lt;br /&gt;
The foobarz-init program can be compiled two ways as of v1.1.1. First, the simpler compile that does not support zpool_import but does support importing pools using a /etc/zfs/zpool.cache file in the initramfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gcc --static init.c -o init&lt;br /&gt;
strip init&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The second way to compile it adds support for zpool_import so that you do not have to include a &amp;lt;code&amp;gt;/etc/zfs/zpool.cache&amp;lt;/code&amp;gt; file in the initramfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gcc -static -DINCLUDE_ZPOOL_IMPORT \&lt;br /&gt;
     foobarz-init.c -include /usr/src/zfs-0.6.0-rc11/3.2.28/zfs_config.h \&lt;br /&gt;
    -o init \&lt;br /&gt;
    -I /usr/include/libspl -I /usr/include/libzfs \&lt;br /&gt;
    -lzfs -lnvpair -lzpool -luutil -luuid -lrt -lz -lm -lpthread \&lt;br /&gt;
    -I /usr/include/tirpc \&lt;br /&gt;
    -ltirpc&lt;br /&gt;
strip init&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Dependencies required before you can compile this second way:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Install [http://sourceforge.net/projects/libtirpc/ libtirpc]. The glibc package has removed the RPC-related functions from the static libc. The libtirpc is the new replacement as a separate library. You can make your own libtirpc package and install it to resolve these RPC-related functions. Without this, the compile fails because it cannot find many &amp;quot;xdr&amp;quot; functions.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Reinstall the [ftp://slackware.mirrors.tds.net/pub/slackware/slackware64-current/source/a/util-linux/ util-linux] package with static libraries enabled. Edit the &amp;lt;code&amp;gt;util-linux.SlackBuild&amp;lt;/code&amp;gt; and remove the line &amp;lt;code&amp;gt;--disable-static&amp;lt;/code&amp;gt;, then build it and use upgradepkg to install the new package. This resolves linking static to libuuid.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;code&amp;gt;zfs_config.h&amp;lt;/code&amp;gt; can be found in the kernel source when you have installed the builtin spl/zfs configuration; for example at &amp;lt;code&amp;gt;/usr/src/linux-3.2.28b/zfs_config.h&amp;lt;/code&amp;gt;. If you currently have installed the modular spl/zfs configuration, &amp;lt;code&amp;gt;zfs_config.h&amp;lt;/code&amp;gt; is found where the zfs module headers are installed; for example at &amp;lt;code&amp;gt;/usr/src/zfs-0.6.0-rc11/3.2.28/zfs_config.h&amp;lt;/code&amp;gt;. Wherever it is, &amp;lt;code&amp;gt;-include&amp;lt;/code&amp;gt; it as shown in the example gcc line above. zfs_config.h seems misplaced because it would seem that using libzfs shouldn't depend on modules header files.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;You may need to install the spl and zfs packages configured for --enable-linux-builtin=yes before compiling and linking to libzfs to make sure you are using the version of libzfs intended for builtin modules in case a difference between the two configurations exists. Currently, there seems to be no difference in the libzfs for either modular or builtin modules, but later there could be at least a small difference for detection of modules to load or builtin already. You may see a message that the ZFS modules stack load failed, but it can be ignored since the modules are builtin; this is just libzfs trying to load the modules even though they are builtin.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
With these dependencies, you can probably compile static with the zpool_import support. The exact location of &amp;quot;zfs_config.h&amp;quot; may vary depending on your zfs and kernel versions, so adjust accordingly.&lt;br /&gt;
&lt;br /&gt;
Read the foobarz-init source code to see how it uses kernel parameters. The params &amp;lt;code&amp;gt;root&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;rootfstype&amp;lt;/code&amp;gt; are always required to tell init what root pool name to mount and the filesystem type (e.g. zfs).&lt;br /&gt;
&lt;br /&gt;
For the zpool_import support: &amp;lt;code&amp;gt;zpool_import_name=poolname&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;zpool_import_guid=&amp;lt;guid of a pool&amp;gt;&amp;lt;/code&amp;gt; tells what pool to import. You can also import the pool with a new different name by also using &amp;lt;code&amp;gt;zpool_import_newname=newpoolname&amp;lt;/code&amp;gt;. If the import is not working, &amp;lt;code&amp;gt;zpool_import_force=1&amp;lt;/code&amp;gt; can be used to force import even if ZFS thinks the pool may be in use by another system.&lt;br /&gt;
&lt;br /&gt;
However you import the pool, either using zpool.cache or zpool_import support, the kernel param &amp;lt;code&amp;gt;root=&amp;lt;your poolname or newpoolname&amp;gt;&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;rootfstype=zfs&amp;lt;/code&amp;gt; needs to be given also. The zpool_import only imports, it does not say what to mount. What to mount is still told using root= and rootfstype=.&lt;br /&gt;
&lt;br /&gt;
Now copy the compiled static program into the initramfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp init /boot/initramfs-source/init&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Build and install kernel:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /usr/src/linux-3.2.28b&lt;br /&gt;
make -j8&lt;br /&gt;
make -j8 modules_install&lt;br /&gt;
cp arch/x86/boot/bzImage /boot/vm3.2.28b&lt;br /&gt;
cp System.map /boot/System.map-vm3.2.28b&lt;br /&gt;
# add new lilo menu entry for vm3.2.28b kernel&lt;br /&gt;
vi /etc/lilo.conf&lt;br /&gt;
  image = /boot/vm3.2.28b&lt;br /&gt;
   label = vm3.2.28b&lt;br /&gt;
   addappend = &amp;quot; spl.spl_hostid=0x007f0100 zfs.spa_config_path=/etc/zfs/zpool.cache root=zfs-root rootfstype=zfs&amp;quot;&lt;br /&gt;
lilo&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Note: If &amp;lt;code&amp;gt;spl.spl_hostid=0x007f0100&amp;lt;/code&amp;gt; is not included in addappend, then during boot SPL module will attempt to read /etc/hostid or run a user-space helper to write the &amp;lt;code&amp;gt;hostid&amp;lt;/code&amp;gt; into &amp;lt;code&amp;gt;/proc/sys/kernel/spl/hostid&amp;lt;/code&amp;gt;. Reading /etc/hostid fails unless you use foobarz-chhostid and make the file and copy it into /boot/initramfs-source/etc/hostid. The helper will fail because no &amp;lt;code&amp;gt;sh&amp;lt;/code&amp;gt; shell and no &amp;lt;code&amp;gt;hostid&amp;lt;/code&amp;gt; command are installed in the initramfs. The default hostid becomes 0xffffffff, which is considered an invalid hostid.&lt;br /&gt;
&lt;br /&gt;
Congrats! If this works, you can select the &amp;quot;vm3.2.28b&amp;quot; lilo entry to boot. If you are using the zpool_import support in the init program, you need to add at least the &amp;lt;code&amp;gt;zpool_import_name=zfs-root&amp;lt;/code&amp;gt; param to the addappend line in lilo.conf.&lt;br /&gt;
&lt;br /&gt;
Notes on kernel params (lilo append and addappend lines): root= and rootfstype= are used by both foorbarz-init and mkinitrd. The &amp;quot;ro&amp;quot; param is not used by foobarz-init, so instead use: mountopt=ro|rw. See &amp;quot;modinfo spl&amp;quot; and &amp;quot;modinfo zfs&amp;quot; to see all of the options those modules can take on the kernel command line. Notice the &amp;lt;code&amp;gt;spl.spl_hostid=0x007f0100&amp;lt;/code&amp;gt; param that works around the hostid mismatch problem while trying to import a pool; this param and hostname/ip set to use local loopback 127.0.0.1 in etc/hosts etc/HOSTNAME in initramfs will work most of the time, and if not the pool import needs to be forced.&lt;br /&gt;
&lt;br /&gt;
Notes on the spl and zfs packages to install: &amp;lt;i&amp;gt;If&amp;lt;/i&amp;gt; you have errors using zfs and zpool commands on booted system with builtin modules, then upgrade/switch to the 0.6.0rc11_3.2.28b builds, or you can make a custom package with the binaries renamed like zpoolb, zfsb etc for builtin.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
Using qemu's -nographic serial console (/usr/share/qemu/sgabios.bin): If you have a boot problem, you might want to run in qemu's -nographic console mode:&lt;br /&gt;
&lt;br /&gt;
First, edit /etc/inittab, and uncomment the line for local serial ports runlevel &amp;quot;s1&amp;quot; (ttyS0) for serial console login support. This is done in the guest (host does not need this):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Local serial lines:&lt;br /&gt;
s1:12345:respawn:/sbin/agetty -L ttyS0 38400 linux&lt;br /&gt;
#s1:12345:respawn:/sbin/agetty -L ttyS0 9600 vt100&lt;br /&gt;
#s2:12345:respawn:/sbin/agetty -L ttyS1 9600 vt100&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Second, edit /etc/securetty, and uncomment ttyS0 line:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ttyS0&lt;br /&gt;
#ttyS1&lt;br /&gt;
# ...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
You cannot login on ttyS0 without this change even though you get the login prompt!&lt;br /&gt;
&lt;br /&gt;
Then, run qemu such as:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
qemu-kvm &amp;lt;all regular options&amp;gt; -nographic -option-rom sgabios.bin,bootindex=0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Wait for the lilo prompt, it may take several seconds show up in this mode.&lt;br /&gt;
&lt;br /&gt;
In the lilo menu, select your kernel image with builtin spl/zfs, and use kernel params such as:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
boot: vm3.2.28b console=ttyS0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
At the lilo prompt, use kernel parameter: console=ttyS0 (do NOT say /dev/ttS0). Passing runlevel=s1 does not appear to be necessary.&lt;br /&gt;
&lt;br /&gt;
When you are in qemu's serial mode, the interface is a little different than in the normal graphical mode: use keypresses:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ctrl-a h    # for help&lt;br /&gt;
ctrl-a c    # toggle access to (QEMU) console / back to emulation&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If you cannot get a login: prompt, try ctrl-a c, then do (QEMU) sendkey ctrl-alt-delete. This will reboot cleanly back to lilo, then you can do (QEMU) quit.&lt;br /&gt;
&lt;br /&gt;
Once you login to the guest, the terminal size needs adjustment. On your host, in another xterm sized the same as your guest console terminal, get the size of the terminal:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo $LINES&lt;br /&gt;
echo $COLUMNS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Now, back in the guest terminal of same size:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export LINES &amp;lt;lines&amp;gt;&lt;br /&gt;
export COLUMNS &amp;lt;columns&amp;gt;&lt;br /&gt;
stty cols $COLUMNS rows $LINES&lt;br /&gt;
exec bash&lt;br /&gt;
reset&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
So, you set the environment variables and also set them with stty. Then, restart bash (exec, or else it is a child shell process).&lt;br /&gt;
&lt;br /&gt;
BECAREFUL not to start qemu twice on the same ZFS guest! Two simultaneous running qemu on the same ZFS will corrupt the pool and it will NOT recover - you lose your whole installation! Before running qemu, check ps -A, look for an already running qemu process incase it somehow entered into the background!&lt;br /&gt;
&lt;br /&gt;
BECAREFUL when using -nographic ttyS0 that you are not doing commands on the HOST! Only use -nographic to see kernel problems. Use regular console if booting is working normally.&lt;br /&gt;
&lt;br /&gt;
To use the qemu -drive if=scsi option, the linux module sym53c8xx should be loaded in the guest. You may need to use the qemu option:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-option-rom 8xx_64.rom,bootindex=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The file 8xx_64.rom used to be inside qemu, but in new versions it is missing. You can download it:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
wget http://www.lsi.com/downloads/Public/Host%20Bus%20Adapters/Host%20Bus%20Adapters%20Common%20Files/lsi_bios.zip&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Extract the zip and place 8xx_64.rom in /usr/share/qemu/.&lt;br /&gt;
&lt;br /&gt;
Good luck!&lt;/div&gt;</description>
			<pubDate>Wed, 19 Sep 2012 10:49:36 GMT</pubDate>
			<dc:creator>Foobarz</dc:creator>
			<comments>https://www.slackwiki.com/Talk:ZFS_root_(builtin)</comments>
		</item>
		<item>
			<title>ZFS root</title>
			<link>https://www.slackwiki.com/index.php?title=ZFS_root&amp;diff=797</link>
			<guid isPermaLink="false">https://www.slackwiki.com/index.php?title=ZFS_root&amp;diff=797</guid>
			<description>&lt;p&gt;Foobarz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Tutorials]]&lt;br /&gt;
If you have heard about the ZFS filesystem and you're curious to try it out, then you can try it on slackware64, thanks to the ZFSonLinux.org project!&lt;br /&gt;
&lt;br /&gt;
In this article, an example is shown of how to install slackware64 14.0 onto a ZFS root filesystem (zfs-root) inside a QEMU virtual machine for testing purposes. It is recommended that you install qemu and learn how to use it to test a ZFS installation before you decide to use it on real hardware. A slackbuild for qemu can be found on slackbuilds.org. If you have a processor that supports Intel VT-x or AMD AMD-V virtualization acceleration (try modprobe kvm-intel or modprobe kvm-amd), then use the slackbuild for qemu-kvm.&lt;br /&gt;
&lt;br /&gt;
This article isn't going to go into any detail on actually using ZFS or what kinds of installation options and settings might be optimal. This article just presents an example of how to get started with ZFS on slackware.&lt;br /&gt;
&lt;br /&gt;
At this time of writing, ZFSonLinux is at &amp;quot;release candidate&amp;quot; (version 0.6.0-rc11) development stage, and many issues can occur. See the ZFSonLinux.org web site and the issues tracker for an idea about the current issues. There is also an irc channel on irc.freenode.net, #zfsonlinux, for discussion of issues and help.&lt;br /&gt;
&lt;br /&gt;
Although not required, it is helpful to keep a local mirror of slackware64 on your system. Having a local mirror makes it easier to upgrade to slackware64-current or to patches/* in a release. To help manage your own local slackware mirror and generate your own CD and DVD slackware installers, see http://alien.slackbook.org/blog/local-slackware-mirror/.&lt;br /&gt;
&lt;br /&gt;
In this article, we use a slackware64-current DVD image file as the qemu cdrom device media for the installation of the slackware guest. This was tested at slackware64-current = slackware64 14.0rc4. You can obtain a slackware DVD image using a torrent, buy the DVD from slackware.com, or generate your own DVD image file using the mirror script. For an actual DVD, you can pass your DVD device (e.g., /dev/sr0) as the qemu cdrom device. For a DVD image file, pass the image file as the qemu cdrom device.&lt;br /&gt;
&lt;br /&gt;
The ZFSonLinux packages are not included in slackware at this time. There are two packages involved: spl and zfs. The first, spl, is &amp;quot;Solaris Porting Layer&amp;quot; and must be installed on the system before zfs can be compiled. The source code tarballs for these are at ZFSonLinux.org. At this time of writing, they are spl-0.6.0-rc11.tar.gz and zfs-0.6.0-rc11.tar.gz.&lt;br /&gt;
&lt;br /&gt;
At this point, it is assumed you have qemu installed, have obtained a slackware64-current/14.0 DVD, and have downloaded spl and zfs tarballs to your host system. The first step now is, if your host is not slackware64-current/14.0 (the same as the guest will be), then you need to create a minimal development slackware64 guest system in qemu for just the purpose of compiling and packaging the spl and zfs slackware packages and transferring a copy of these packages back onto your host system to use later to install onto zfs during the slackware install process.&lt;br /&gt;
&lt;br /&gt;
From this point onward, instructions become a bit terse and mostly limited to examples of the commands you might use to complete tasks. You are encouraged to examine what each command does by reading the command's man pages. For example, the command &amp;quot;man qemu&amp;quot; can show you most of what you need to know about running qemu on the command line.&lt;br /&gt;
&lt;br /&gt;
So, here's an example of how you might build the spl and zfs packages, starting in your home directory:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on host)&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir qemu&lt;br /&gt;
cd qemu&lt;br /&gt;
mkdir slackdevel&lt;br /&gt;
cd slackdevel&lt;br /&gt;
mkdir packages&lt;br /&gt;
cp ~/spl-*.tar.gz packages&lt;br /&gt;
cp ~/zfs-*.tar.gz packages&lt;br /&gt;
qemu-img create disk1.raw 10G&lt;br /&gt;
ln -s ~/slackware64-current-install-dvd.iso dvd.iso&lt;br /&gt;
qemu-kvm \&lt;br /&gt;
 -option-rom 8xx_64.rom,bootindex=1 \&lt;br /&gt;
 -no-quit \&lt;br /&gt;
 -no-shutdown \&lt;br /&gt;
 -boot order=cd,menu=on \&lt;br /&gt;
 -m 2G \&lt;br /&gt;
 -cpu host \&lt;br /&gt;
 -smp sockets=1,cores=4 \&lt;br /&gt;
 -net nic,model=e1000 -net user \&lt;br /&gt;
 -cdrom dvd.iso \&lt;br /&gt;
 -drive format=raw,media=disk,cache=none,aio=native,if=scsi,index=0,file=disk1.raw \&lt;br /&gt;
 -virtfs local,path=./packages/,security_model=none,mount_tag=hostpackages&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When you need to change boot to cd or disk, try changing &amp;quot;order=dc&amp;quot; or hitting F12 at boot prompt and select the CD/DVD boot option.&lt;br /&gt;
&lt;br /&gt;
Note: The support for booting drives using if=scsi is not included with current versions of qemu. Booting scsi requires the 8xx_64.rom option-rom, which can be downloaded at&lt;br /&gt;
[http://www.lsi.com/downloads/Public/Host%20Bus%20Adapters/Host%20Bus%20Adapters%20Common%20Files/lsi_bios.zip LSI.com]. Unzip it, and then:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp 8xx_64.rom /usr/share/qemu&lt;br /&gt;
# then run qemu-kvm with additional command line option: -option-rom 8xx_64.rom,bootindex=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Qemu should boot into the install-dvd, and now perform a very ordinary slackware64 install onto /dev/sda. Install d package set and most others, but package sets x, kde, xfce not really needed.&lt;br /&gt;
&lt;br /&gt;
First note: examples here use tools from the gptfdisk package (gdisk, sgdisk, cgdisk) to partition the disk with GUID partition table (GPT) format. GPT might not be too familiar to everyone, who mostly have only used MBR partitions with fdisk. In the slackware installations this author has tested in qemu, using GPT partitions has caused no problems with lilo or other tools used in slackware. GPT disk labels support creating up to 128 partitions and support disks larger than 2TB (the limit of MBR fdisk). LILO installs into the first 440 bytes on /dev/sda, inside a GPT &amp;quot;protective MBR&amp;quot; that serves to provide compatibility with MBR bootloaders like lilo. LILO uses LBA32 sector addressing and can see all 512-byte sectors inside the first 2TB of a disk. So long as the /boot partition is within the first 2TB of a disk, lilo can work on a disk larger than 2TB. Unlike the common default of fdisk to start the first partition at sector 63, which is not aligned with the 4KiB sector size of Advanced Format hard disks, gdisk's default is to start partitions at 2048 sector (1MiB) boundaries which are also 4KiB aligned. Using gdisk GPT works on all disks and is compatible with using Advanced Format hard disks larger than 2TB. More information about GPT disk label format can be found on wikipedia.org. For those that have used grub instead of lilo, grub installation is different with GPT than with MBR, and grub requires a GPT partition of type grub-bios or 0xEF02 &amp;quot;BIOS Boot Partition&amp;quot; of about 8MiB where it can install it's additional bootloader stages because grub cannot embed in sectors 1-62 on GPT where GPT keeps it's partition tables. On MBR, sectors 1-62 were normally reserved space for bootloaders to keep a 2nd stage.&lt;br /&gt;
&lt;br /&gt;
For this purpose of development guest, just create a simple 1-partition system, /dev/sda1, and do a simple slackware install on it. Don't bother with swap or separate /boot unless you want to:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on install-dvd)&lt;br /&gt;
cgdisk /dev/sda&lt;br /&gt;
setup&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When this simple development guest boots, login as root, and continue:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on qemu guest)&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir packages&lt;br /&gt;
mount hostpackages -t 9p -o trans=virtio packages&lt;br /&gt;
echo --prefix=/ --libexecdir=/usr/libexec --libdir=/lib64 --includedir=/usr/include --datarootdir=/usr/share &amp;gt; configure-options&lt;br /&gt;
mkdir src&lt;br /&gt;
cd src&lt;br /&gt;
&lt;br /&gt;
mkdir install&lt;br /&gt;
tar xvzf ~/packages/spl-*.tar.gz&lt;br /&gt;
cd spl-*&lt;br /&gt;
./configure $( cat ~/configure-options )&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../spl-&amp;lt;version&amp;gt;_&amp;lt;kernel_version&amp;gt;-x86_64-&amp;lt;build_id&amp;gt;.txz&lt;br /&gt;
(e.g., makepkg ../spl-0.6.0rc11_3.2.28-x86_64-1root.txz)&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
installpkg spl-0.6.0rc11_3.2.28-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
cp spl-0.6.0rc11_3.2.28-x86_64-1root.txz ~/packages&lt;br /&gt;
&lt;br /&gt;
mkdir install&lt;br /&gt;
tar xvzf ~/packages/zfs-*.tar.gz&lt;br /&gt;
cd zfs-*&lt;br /&gt;
./configure $( cat ~/configure-options )&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../zfs-&amp;lt;version&amp;gt;_&amp;lt;kernel_version&amp;gt;-x86_64-&amp;lt;build_id&amp;gt;.txz&lt;br /&gt;
(e.g., makepkg ../zfs-0.6.0rc11_3.2.28-x86_64-1root.txz)&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
installpkg zfs-0.6.0rc11_3.2.28-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
cp zfs-0.6.0rc11_3.2.28-x86_64-1root.txz ~/packages&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point spl and zfs packages are copied back to the host in the packages directory. Also, spl and zfs are installed in this simple development guest, so one could begin to experiment with zfs pools and datasets but while the root fs is whatever you made it during setup (probably the default, ext4). This development guest isn't really needed anymore, so it can be deleted:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
halt&lt;br /&gt;
(exit qemu: ctrl-alt-2 then enter quit at QEMU command prompt)&lt;br /&gt;
&lt;br /&gt;
(on host)&lt;br /&gt;
rm disk1.raw dvd.iso&lt;br /&gt;
mv packages ..&lt;br /&gt;
cd ..&lt;br /&gt;
rmdir slackdevel&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now that we have the spl and zfs packages on the host, it is possible to copy them into your local slackware64 mirror and then generate your own install DVD image that includes them. For example, change to the directory that contains the slackware README files, and create a &amp;quot;addon&amp;quot; directory and copy the spl and zfs slackware packages into there. Then, generate the DVD image using a command such as $( ./mirror-slackware-current.sh -i ) from where you have this script configured to maintain your local mirror. We can also just continue to access them inside the installer using qemu's virtfs option. When you are going to do a real installation onto real hardware, you need to generate and burn your own DVD that includes the packages.&lt;br /&gt;
&lt;br /&gt;
It is time to begin the installation of slackware64 on a ZFS root, assuming either you have regenerated dvd.iso with zfs packages in addon/* or we access the zfs packages while in the installer using qemu's virtfs to the host's packages directory.&lt;br /&gt;
&lt;br /&gt;
ZFS supports creating complex data storage configurations in data storage pools (similar to a LVM volume group) backed by one or more virtual devices (similar to physical disks and raid arrays) and containing one or more datasets (similar to mounted filesystems, logical volume devices, or snapshots). But here, we keep it simple and will install on just a single disk device.&lt;br /&gt;
&lt;br /&gt;
On a real ZFS installation, users will typically want to use the ZFS mirror or raidz virtual device (vdev) types for reliability against hard drive failures. For example, a good configuration might be to use a USB memory stick (and a backup stick) for /boot that is plugged into an on-motherboard &amp;quot;Type A&amp;quot; USB connector. Then, use four whole hard drives in a raidz2 vdev as the initial storage space in the root zpool. At a later time, to add more storage space, additional whole four-drive raidz2 vdevs of the same size could be added to the zpool. It is recommended to only add the same vdev type (disk, mirror, or raidz|1|2|3) and size to a zpool since zfs stripes across the vdevs, and vdevs of different types/sizes do not stripe together optimally. After adding a vdev to your zpool, you might need to copy the new /etc/zfs/zpool.cache to your initrd-tree or initramfs-source (and rebuild/reinstall them) if you are using the cachefile to import your zpool. Using mirror vdevs would be similar to a raid10. Using 4-disk raidz2 vdevs would give the same storage space as raid10 while fully reliable against any double-disk failure; however, the raidz2 parity calculations results in higher CPU usage and/or lower performance. Because raidz vdevs cannot be grown by adding hard drives to them, and vdevs in a zpool are striped, it is important with ZFS to decide what type and size of vdev will be used in a zpool as the units of add-on storage space; it could be difficult to alter this decision later. Finally, on a real installation with raidz, data scrub should be scheduled to actively search for &amp;quot;latent defects&amp;quot; on the hard drives so that unknown read/write errors do not become known later during a disk swap/rebuild and result in the zpool becoming faulted (lost).&lt;br /&gt;
&lt;br /&gt;
If you decide to test raidz in qemu, consider making the qemu disk files on different physical disks on your host to avoid putting all the stress onto a single disk on your host. The raidz qemu disks that are all on a single physical hard drive will cause poor performance and stress on the disk due to the large amount of seek operations to access the stripes/columns in the raidz. Again, we'll keep it simple in this wiki and just make a root zpool that is just holding a single qemu disk that you've given to qemu to avoid stress on the host hard drive. But, if you really want to test raidz, you can do it by just making more qemu disks (with incremented index=X number) and making your zpool a raidz; there's no technical restriction here on the kind of vdevs in your root zpool.&lt;br /&gt;
&lt;br /&gt;
Make &amp;quot;slackzfs&amp;quot; guest, and boot it into the slackware installer to begin installation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on host)&lt;br /&gt;
mkdir slackzfs&lt;br /&gt;
mv packages slackzfs/&lt;br /&gt;
cd slackzfs&lt;br /&gt;
qemu-img create disk1.raw 10G&lt;br /&gt;
ln -s ~/slackware64-current-install-dvd.iso dvd.iso&lt;br /&gt;
qemu-kvm \&lt;br /&gt;
 -option-rom 8xx_64.rom,bootindex=1 \&lt;br /&gt;
 -no-quit \&lt;br /&gt;
 -no-shutdown \&lt;br /&gt;
 -boot order=cd,menu=on \&lt;br /&gt;
 -m 2G \&lt;br /&gt;
 -cpu host \&lt;br /&gt;
 -smp sockets=1,cores=4 \&lt;br /&gt;
 -net nic,model=e1000 -net user \&lt;br /&gt;
 -cdrom dvd.iso \&lt;br /&gt;
 -drive format=raw,media=disk,cache=none,aio=native,if=scsi,index=0,file=disk1.raw \&lt;br /&gt;
 -virtfs local,path=./packages/,security_model=none,mount_tag=hostpackages&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The install-dvd should boot, and then begin installation steps on the installer command line:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on install-dvd)&lt;br /&gt;
# mount the install-dvd&lt;br /&gt;
mkdir /dvd&lt;br /&gt;
mount /dev/sr0 /dvd&lt;br /&gt;
&lt;br /&gt;
# install coreutils, which provides the &amp;quot;hostid&amp;quot; command needed to load the spl module&lt;br /&gt;
installpkg /dvd/slackware64/a/coreutils-8.17-x86_64-1.txz&lt;br /&gt;
&lt;br /&gt;
# install kmod package which includes &amp;quot;depmod&amp;quot; command and others&lt;br /&gt;
installpkg /dvd/slackware64/a/kmod-9-x86_64-2.txz&lt;br /&gt;
depmod&lt;br /&gt;
&lt;br /&gt;
# install the full kernel modules so you can load 9p filesystem and use it if you want&lt;br /&gt;
# .. you might keep the zfs modules packages off the dvd and use a plain slack dvd&lt;br /&gt;
installpkg /dvd/slackware64/a/kernel-modules-*.txz&lt;br /&gt;
depmod&lt;br /&gt;
&lt;br /&gt;
# install bash and libtermcap because udev rules in zfs use bash scripts&lt;br /&gt;
installpkg /dvd/slackware64/a/bash-*.txz&lt;br /&gt;
installpkg /dvd/slackware64/l/libtermcap-*.txz&lt;br /&gt;
&lt;br /&gt;
# install spl and zfs that you have copied into the mirror before running the DVD creation&lt;br /&gt;
installpkg /dvd/addon/spl-0.6.0rc11_3.2.28-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /dvd/addon/zfs-0.6.0rc11_3.2.28-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
&lt;br /&gt;
#Or:&lt;br /&gt;
mkdir /packages&lt;br /&gt;
find /lib/modules/ | grep 9p&lt;br /&gt;
lsmod&lt;br /&gt;
# check that 9p modules load, mainly 9pnet_virtio&lt;br /&gt;
modprobe 9pnet_virtio&lt;br /&gt;
mount hostpackages -t 9p -o trans=virtio /packages&lt;br /&gt;
installpkg /packages/spl-0.6.0rc11_3.2.28-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /packages/zfs-0.6.0rc11_3.2.28-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
modprobe zfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now zfs tools: &amp;quot;zpool&amp;quot; and &amp;quot;zfs&amp;quot; should work in the live installer.&lt;br /&gt;
On the installer, there can be trouble seeing man pages, so install:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
installpkg /dvd/slackware64/ap/man-*.txz&lt;br /&gt;
installpkg /dvd/slackware64/ap/groff-*.txz&lt;br /&gt;
installpkg /dvd/slackware64/a/less-*.txz&lt;br /&gt;
export MANPATH=/usr/man:/usr/share/man&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The manual pages should be readable:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
man zpool&lt;br /&gt;
man zfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After seeing the man pages, we should be fully ready to continue to setup on ZFS.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(still on install-dvd)&lt;br /&gt;
ls -l /dev/sd*&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Make sure the disk devices you expect are there. We'll use sda and make boot (/boot on /dev/sda1) and root (/ on /dev/sda2) partitions.&lt;br /&gt;
&lt;br /&gt;
First, some background info: A ZFS filesystem is not supported by lilo as the filesystem containing /boot, which holds lilo's 2nd stage and the linux kernel files. The on-disk format of a ZFS filesystem is often a complex raid configuration where even if lilo understood ZFS it would likely require /boot to reside in only certain simple ZFS configurations to be plainly readable to lilo. As things are, a linux root installed in a partition with ZFS filesystem needs /boot to be on another partition with a filesystem that lilo understands, such as ext4 fs. In addition, because the spl and zfs modules are not built into the kernel, and the zfs startup requires some configuration to mount the zfs root, an initial ram/root filesystem (initrd) is needed. The initrd is a gzip compressed cpio archive file that contains a small linux root operating system that is decompressed into a ramfs block device at boot up and takes initial control of the system. The initrd contains an init script that configures devices in devtmpfs mounted at /dev. For example, if using mdadm, lvm, luks, losetup, and now zfs, this init script runs all the commands to create or start these devices (one of which is the root device), mounts the root device, and then transfers system control to the init script in the mounted root filesystem. The ramfs-based root environment on the booted install-dvd or booted initrd image (in rescue command line) are small slackware installations that exist only in ram and are temporary, but while inside them you can install, upgrade, and remove slackware packages inside them using the regular package management tools; this allows you access to any kernel modules and programs as needed inside these ramfs root. Packages can be installed, upgraded, or removed permanantly in the initrd image file to manage the programs and modules required during the initrd boot stage. Also from within these ramfs initial root environments, once the root device is mounted, chroot can be used to work on the mounted root system as if it were booted; this allows one to fix problems that are occuring in the root fs init scripts that cause normal booting to fail, or to install a kernel and/or modules etc. Now on to partitioning:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cgdisk /dev/sda&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, cgdisk looks just like cfdisk, but it makes GPT partitions.&lt;br /&gt;
&lt;br /&gt;
Make a partition for /boot that is about 512MiB of whatever partition type you like (8300 &amp;quot;Linux filesystem&amp;quot; is fine), or make it type bf07 &amp;quot;Solaris Reserved 1&amp;quot; if you want ZFS to maybe see the disk as if it was given as a whole disk to ZFS. Make a second partition using the remaining space with partition type bf01 &amp;quot;Solaris ZFS&amp;quot;. Currently, when ZFSonLinux is given a whole disk device like /dev/sdb to use, it will automatically GPT partition it with a bf01 partition #1 that is the whole disk except a small 8MiB type bf07 partition #9 at the end of the disk (/dev/sdb1 and /dev/sb9). The small 8MiB type bf07 partition #9 is most likely reserved for use by bootloaders, like lilo, to have a /boot or other boot-related files kept there. For example, you might have /dev/sda that is totally non-ZFS for booting and /dev/sdb passed to ZFS whole where it automatically partitions sdb, but you can just use one disk here and make partitions. Let's use type 8300 for /boot to be sure nothing is confused:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
We'll continue with this partitioning:&lt;br /&gt;
Part. #    Size        Partition Type           Partition Name&lt;br /&gt;
           4.0 MiB     free space&lt;br /&gt;
   1       512.0 MiB   Linux filesystem         boot&lt;br /&gt;
           4.0 MiB     free space&lt;br /&gt;
   2       9.4 GiB     Solaris /usr &amp;amp; Mac ZFS   root&lt;br /&gt;
           96.0 MiB    free space&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The free space is left as a recommendation. The free space has potential uses for data recovery techniques, changing boot configuration, accomodating a replacement disk that is slightly smaller, and avoiding the end of the disk where GPT and other disk labels may need to claim space at the end of a drive to hold metadata. The &amp;quot;partition name&amp;quot; can be blank or any arbitrary name you'd like to give them.&lt;br /&gt;
&lt;br /&gt;
If you are going to test a ZFS mirror or raidz configuration, then you can repeat this same partitioning on each disk. For example, for a four-disk raidz2 with /dev/sd[abcd] you might do:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sgdisk -R /dev/sdb /dev/sda&lt;br /&gt;
sgdisk -G /dev/sdb&lt;br /&gt;
sgdisk -R /dev/sdc /dev/sda&lt;br /&gt;
sgdisk -G /dev/sdc&lt;br /&gt;
sgdisk -R /dev/sdd /dev/sda&lt;br /&gt;
sgdisk -G /dev/sdd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Then, you could use the boot partitions /dev/sd[abcd]1 in a mdadm raid1 as your boot device:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mdadm --create /dev/md0 -l 1 -n 4 /dev/sd[abcd]1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
In this configuration, /dev/md0 is your 4-way mirror /boot device and is used as explained in the slackware [ftp://slackware.mirrors.tds.net/pub/slackware/slackware64-current/README_RAID.TXT README_RAID.TXT]. The /dev/sd[abcd]2 would be given to ZFS for the raidz2 (instead of to mdadm raid). This is only an example and there are many possible configurations, including using whole un-partitioned disks; however, we will continue in this wiki with a simpler configuration with /dev/sda1 as a non-raid /boot device and /dev/sda2 in a non-raidz/non-mirror zpool.&lt;br /&gt;
&lt;br /&gt;
Create a zpool called zfs-root:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool create -m none zfs-root /dev/sda2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A zpool created like this, the normal way, is a kernel-internal block device that contains already a zfs filesystem. There is normally no entry in /dev for this device. However, it can still be referenced as a mountable device similar to how devtmpfs, proc, and sysfs are also kernel-internal mountable block devices. The -m option told zpool not to automatically mount it anywhere, and without -m the default is to always automatically mount to /zfs-root. These kinds of details are explained better elsewhere. For this situation, we do not want it automounted.&lt;br /&gt;
&lt;br /&gt;
Because a zpool itself is a useable zfs fs, it has a full set of zfs &amp;quot;properties&amp;quot; to set options about the filesystem, perhaps similar to tune2fs. The &amp;quot;mountpoint=&amp;lt;some place to mount&amp;gt;&amp;quot; is one such property. We want it set to the special value &amp;quot;none&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs get mountpoint zfs-root&lt;br /&gt;
zfs set mountpoint=none zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also use &amp;quot;legacy&amp;quot; for the mountpoint and the management of mounting and unmounting the pool will be expected to be done using the regular &amp;quot;mount&amp;quot; and &amp;quot;umount&amp;quot; commands:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=legacy zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Later in the wiki, it is shown how to mount using &amp;quot;zfs mount&amp;quot; for mountpoint=none, and regular &amp;quot;mount&amp;quot; for mountpoint=legacy. Using mountpoint=legacy is probably the preferred setting for the zfs-root because you can use the normal mount and umount commands and do not have to change slackware /etc/rc.d/* scripts much, if any. The normal slackware scripts handle a root filesystem's mounting and remounting using the normal mount command.&lt;br /&gt;
&lt;br /&gt;
On creation, the zpool zfs-root is &amp;quot;imported&amp;quot; and has a zpool status that can be viewed:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool status zfs-root&lt;br /&gt;
&lt;br /&gt;
zpool export zfs-root&lt;br /&gt;
zpool status zfs-root&lt;br /&gt;
# Now there is no status.&lt;br /&gt;
&lt;br /&gt;
zpool import zfs-root&lt;br /&gt;
# Now it is back.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
When a zpool is imported, it has it's current configuration cached in a file /etc/zfs/zpool.cache. When a zpool is exported, then it's entries in the cache file are removed and the cache file is deleted if it becomes empty. So long as the zfs kernel modules see this cache file and valid cache data inside it, ZFS considers the described zpools in the cache file to be valid as imported zpools. If the zpool.cache file is present at the time the zfs modules are loaded, then there is no further need to use the import and export zpool commands at system startup and shutdown. With root on a zfs, it is not possible to export the pool that root is on, but this is not a problem. At shutdown, the safe procedure will be to set the zfs-root property readonly=on or remount read-only and sync disks.&lt;br /&gt;
&lt;br /&gt;
To avoid the requirement to import the zfs-root pool at startup, you can keep a copy of the zpool.cache file to later copy onto the initrd image to read at modules load time to have the pool reactivated without need to issue the zpool import command:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/zfs/zpool.cache /etc/zfs/zpool.cache-initrd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
A warning about the zpool.cache file: Having /etc/zfs/zpool.cache present at zfs module load or module init time can be unsafe if the device names in /dev have changed since the last boot. Especially dangerous is if two hard drives have swapped names, like /dev/sda and /dev/sdb have swapped names. It is safer to not have a zpool.cache file on the system at boot and zfs module load/init time to guard against the possibility that the cache file is no longer correct. This wiki will try to show how you can use zpool.cache to import your pool if the regular zpool import command seems to always require you to force it. This wiki will also show how to not need a zpool.cache file to import normally.&lt;br /&gt;
&lt;br /&gt;
A zfs filesystem will not normally allow you to mount over any files. The mountpoint is expected to be an empty directory. Remove any junk files inside the installer's /mnt because zfs won't mount over any files:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rm /mnt/README&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The directory /mnt is where the slackware setup expects you to mount your root for installation.&lt;br /&gt;
&lt;br /&gt;
Controlling whether a zfs fs is to be mounted read-only or read-write is best managed by setting the readonly property while it is not yet mounted:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set readonly=on zfs-root&lt;br /&gt;
zfs set readonly=off zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If you are using &amp;lt;code&amp;gt;mountpoint=legacy&amp;lt;/code&amp;gt; then the options for the mount command for ro or rw mounting will work as normal also and override whatever the readonly property is set to. The readonly property does serve as a default.&lt;br /&gt;
&lt;br /&gt;
Slackware expects root to be mounted readonly when /etc/rc.d/rc.S runs during normal startup, so later this is used to satisfy slackware's expectation to avoid rc.S complaining.&lt;br /&gt;
&lt;br /&gt;
The zfs-root can be mounted and unmounted in two different ways:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=/mnt zfs-root&lt;br /&gt;
zfs set mountpoint=none zfs-root&lt;br /&gt;
# or&lt;br /&gt;
mount zfs-root -t zfs /mnt&lt;br /&gt;
umount /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If it is already mounted and you want to change it to mount somewhere else, it is best to transition it to unmounted first, then mount it in the new place.&lt;br /&gt;
&lt;br /&gt;
The mount options &amp;lt;code&amp;gt;-o ro, -o rw, -o remount,ro, and -o remount,rw &amp;lt;/code&amp;gt; can also be used and will override the &amp;lt;code&amp;gt;readonly=on|off&amp;lt;/code&amp;gt; property without altering the property value. This can be confusing until you are familiar with how the two methods of mounting interact. When &amp;lt;code&amp;gt;mountpoint=legacy&amp;lt;/code&amp;gt; is set, zfs expects the regular mount and umount commands to be used to mount and unmount the dataset with the assistance of the mount.zfs helper. For now, we will continue with &amp;lt;code&amp;gt;mountpoint=none&amp;lt;/code&amp;gt;, but using legacy is also a good option.&lt;br /&gt;
&lt;br /&gt;
Now, let's continue some, and mount to /mnt using the current &amp;lt;code&amp;gt;readonly=off&amp;lt;/code&amp;gt; setting (rw mount):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=/mnt zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method of mounting will show the most detailed mount options in /etc/mtab. They are the mount options that zfs thinks are proper, and they are probably what should be kept in /etc/fstab for zfs-root until we know better.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cat /etc/mtab &amp;gt;&amp;gt; /etc/fstab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now edit /etc/fstab to make sure it looks right, and remove the &amp;quot;rw&amp;quot; mount option, because we want to let it use a default for that, which will come from how we set the readonly= property most of the time. Unmount again:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=none zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mount again, now using all options from /etc/fstab:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It should be mounted at /mnt, and touch /mnt/t should allow you to make the file t. Then rm it: rm /mnt/t&lt;br /&gt;
For installation, we want to make sure it is mounted read-write. After installation, it should mount readonly inside the initrd.&lt;br /&gt;
&lt;br /&gt;
Sometimes there can be problems using the mount command, and then you can try it with the -i option:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 mount -i zfs-root&lt;br /&gt;
 mount -i zfs-root -t zfs /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
but, you should not have to use -i. When using -i makes it work, it performs an &amp;quot;internal-only&amp;quot; mount and does not use any mount.&amp;lt;fstype&amp;gt; helper scripts that might be on the system. You can use &amp;lt;code&amp;gt;mountpoint=legacy&amp;quot;&amp;lt;/code&amp;gt; to avoid this small problem if you are preferring to use the regular mount and umount commands on your zfs-root.&lt;br /&gt;
&lt;br /&gt;
Setup the /boot device:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkfs.ext4 /dev/sda1&lt;br /&gt;
mkdir /mnt/boot&lt;br /&gt;
mount /dev/sda1 /mnt/boot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We have both root and boot mounted where the slackware installer expects them. Unmount the dvd so setup can find it normally:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
umount /dev/sr0&lt;br /&gt;
setup&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the setup, skip straight to TARGET selection for the root device, but the setup doesn't see or understand the zfs-root, so it is not listed. This does not matter because we have mounted it already. Just skip down to a slot that say to continue, and continue on with setup. Because TARGET is skipped, you may not see the ADDITIONAL prompt (or if so, skip it too) where normally you give /dev/sda1 and have it mounted as /boot. This is also okay because we have mounted /mnt/boot already.&lt;br /&gt;
Because we did not give TARGET the root device or say what device /boot is on, the lilo installation will fail, or you can skip it. Otherwise, this installation process is normal.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Finish installation and exit setup, but do NOT reboot!&lt;br /&gt;
# There is still a lot to do before rebooting.&lt;br /&gt;
umount /dev/sr0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point, it is assumed that the setup has completed installing into /mnt. Congrats! You've installed slackware into a ZFS root!&lt;br /&gt;
&lt;br /&gt;
The next steps are to prepare to use &amp;quot;chroot /mnt&amp;quot; and finish up the configuration on the installed root system and then be able to reboot onto the completed installation. Before doing chroot, copy some files from the setup environment into /mnt.&lt;br /&gt;
&lt;br /&gt;
Copy the current installer /etc/fstab for later use inside the initrd. This fstab is what is proper inside the initrd, except remove option &amp;quot;rw&amp;quot; (if not done already).&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/fstab /mnt/etc/fstab.initrd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The fstab.initrd will look like:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 proc /proc proc defaults 0 0&lt;br /&gt;
 zfs-root /mnt zfs defaults,atime,dev,exec,suid,xattr,nomand,zfsutil 0 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the initrd, we want zfs-root to mount to /mnt.&lt;br /&gt;
&lt;br /&gt;
Create /mnt/etc/fstab:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cat /etc/mtab &amp;gt;&amp;gt; /mnt/etc/fstab&lt;br /&gt;
vi /mnt/etc/fstab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using vi started above, edit /mnt/etc/fstab and make it have lines such as:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 zfs-root / zfs defaults,atime,dev,exec,suid,xattr,nomand,zfsutil 0 0&lt;br /&gt;
 /dev/sda1 /boot ext4 defaults 0 2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
These two lines in &amp;lt;code&amp;gt;/mnt/etc/fstab&amp;lt;/code&amp;gt; are how the mounts should be looking when root is booted. Although the fstab option for fs_passno is 0 and indicates that root (/) should not be fsck, this fs_passno option in fstab is ignored during system startup for / in rc.S because rc.S explicity runs &amp;quot;fsck /&amp;quot; which does not look at options inside fstab. Fsck doesn't work on a zfs fs, and we will deal with that problem in a moment (see below).&lt;br /&gt;
&lt;br /&gt;
Mount some special mounts before chroot:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount -t devtmpfs none /mnt/dev&lt;br /&gt;
mount -t proc none /mnt/proc&lt;br /&gt;
mount -t sysfs none /mnt/sys&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Make sure /boot is mounted:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount /dev/sda1 /mnt/boot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you had mounted a 9p fs share to access spl and zfs packages, then unmount that now:&lt;br /&gt;
umount /packages&lt;br /&gt;
&lt;br /&gt;
Ready, now:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chroot /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point, you should be on the installed system, and now try to configure mkinitrd and lilo. First, switch to use the generic kernel:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /boot&lt;br /&gt;
rm System.map config vmlinuz&lt;br /&gt;
ln -s System.map-gen* System.map&lt;br /&gt;
ln -s config-gen* config&lt;br /&gt;
ln -s vmlinuz-gen* vmlinuz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We installed spl and zfs inside the live ramfs install-dvd environment, but not yet have we installed them into the root system:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount /dev/sr0 /mnt/cdrom&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /mnt/cdrom/addon/spl-*.txz&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /mnt/cdrom/addon/zfs-*.txz&lt;br /&gt;
depmod&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If instead, you used a 9p share to access the spl and zfs packages, then repeat that procedure here to install them onto the root system.&lt;br /&gt;
&lt;br /&gt;
Setup lilo: edit /etc/lilo.conf so it is like:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  lba32&lt;br /&gt;
  append = &amp;quot; vt.default_utf8=1&amp;quot;&lt;br /&gt;
  boot = /dev/sda&lt;br /&gt;
  message = /boot/boot_message.txt&lt;br /&gt;
  prompt&lt;br /&gt;
  timeout = 1200&lt;br /&gt;
  change-rules&lt;br /&gt;
   reset&lt;br /&gt;
  vga = normal&lt;br /&gt;
  image = /boot/vmlinuz&lt;br /&gt;
   label = vmlinuz&lt;br /&gt;
   initrd = /boot/initrd.gz&lt;br /&gt;
   root = /dev/ram0&lt;br /&gt;
   read-write&lt;br /&gt;
# alternatively, the root and read-write lines&lt;br /&gt;
# can be this one line of kernel parameters:&lt;br /&gt;
#  addappend = &amp;quot; root=/dev/ram0 rw &amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A note about initrd: The /boot/initrd.gz is a gzipped cpio archive containing a minimal BusyBox-based slackware root system that is sourced from /boot/initrd-tree. The commands &amp;quot;mkinitrd&amp;quot; and &amp;quot;mkinitrd -F&amp;quot; generates /boot/initrd-tree and /boot/initrd.gz. When using a initrd, the initial root device is normally set to root=/dev/ram0 (a ramfs block device) and allowed read-write. The kernel refers to devices in terms of &amp;quot;major&amp;quot; and &amp;quot;minor&amp;quot; numbers, and the ram0 device is assigned the block device major 1 and minor 0. This ram0 major/minor is written in hexadecimal as 0x0100 (256 in decimal). This hexademical number makes an appearance in /boot/initrd-tree/int where it runs: &amp;quot;echo 0x0100 &amp;gt; /proc/sys/kernel/real-root-dev&amp;quot;. Echoing a device code to real-root-dev is part of a deprecated initrd mechanism, but is probably harmless to leave alone as slackware has it unless you know otherwise. More information about how initrd works can be found in:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/usr/src/linux/Documentation/devices.txt (info about major:minor device numbers)&lt;br /&gt;
/usr/src/linux/Documentation/initrd.txt  (mostly obsolete info on old initrd)&lt;br /&gt;
/usr/src/linux/Documentation/filesystems/ramfs-rootfs-initramfs.txt (current info on new initrd, called initramfs)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Advanced note about initrd: Slackware's mkinitrd package does not use the &amp;quot;pivot_root&amp;quot; command as documented in &amp;quot;initrd.txt&amp;quot;, but instead uses &amp;quot;switch_root&amp;quot; provided by a project called BusyBox. The switch_root command changes the effective root filesystem from the initrd (unpacked in rootfs at /) to the new root filesystem (zfs-root mounted at /mnt); it overmounts rootfs / with zfs-root /mnt. The switch_root works as follows: delete everything in rootfs / (one filesystem only) that held initrd to free up ram memory, then use mount, chroot, and chdir to make the effective root change. In concept (as a shell script), the command &amp;quot;exec switch_root /mnt $INIT $RUNLEVEL&amp;quot; is performed as follows:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 find / -xdev | xargs rm -rf&lt;br /&gt;
 cd &amp;quot;$1&amp;quot;&lt;br /&gt;
 shift&lt;br /&gt;
 mount --move . /&lt;br /&gt;
 exec chroot . &amp;quot;$@&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Here, typically INIT=/sbin/init RUNLEVEL=3. The 'exec' causes switch_root to take the place of the parent process having PID=1. In system calls, the switch_root looks similar to this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chdir(&amp;quot;/mnt&amp;quot;);&lt;br /&gt;
/* &amp;lt;insert code to unlink/rmdir all initrd files/directories&lt;br /&gt;
 *  installed in rootfs / without crossing filesystems &amp;gt; */&lt;br /&gt;
mount(&amp;quot;.&amp;quot;, &amp;quot;/&amp;quot;, NULL, MS_MOVE, NULL);&lt;br /&gt;
chroot(&amp;quot;.&amp;quot;);&lt;br /&gt;
chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
execl(&amp;quot;/sbin/init&amp;quot;, &amp;quot;3&amp;quot;, (char*) NULL );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The kernel's rootfs / that contained initrd is never actually unmounted (it can't be) because it is built into the kernel and always exists as at least a tiny ramfs or tmpfs, so you can continue to see it in /proc/mounts. When you give lilo root=/dev/ram0 (a ramfs device), the kernel will actually use the internal rootfs, which is an instance of a tmpfs (if your kernel config includes tmpfs) or ramfs. The rootfs that is a tmpfs can by default use up to half of system ram. If rootfs is a ramfs, it can use up to almost all of system ram until the system panics. Typically, tmpfs is built into the kernel, and so depending on how much ram your computer has, the initrd-tree can probably be up to about half that size.&lt;br /&gt;
&lt;br /&gt;
Quite a lot of notes... now to continue on...&lt;br /&gt;
&lt;br /&gt;
Setup mkinitrd:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/mkinitrd.conf.sample /etc/mkinitrd.conf&lt;br /&gt;
vi /etc/mkinitrd.conf&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Edit it to look like this (other defaults should be ok):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 MODULE_LIST=&amp;quot;sym53c8xx:ext4:e1000:zfs:9p:9pnet_virtio&amp;quot;&lt;br /&gt;
 ROOTDEV=&amp;quot;zfs-root&amp;quot;&lt;br /&gt;
 ROOTFS=&amp;quot;zfs&amp;quot;&lt;br /&gt;
#Module sym53c8xx is the driver for qemu's if=scsi drive device.&lt;br /&gt;
#Module ext4 for /boot.&lt;br /&gt;
#Module e1000 for eth0 net device.&lt;br /&gt;
#Module zfs for ZFSonLinux.&lt;br /&gt;
#Modules 9p and 9pnet_virtio for mounting qemu -virtfs mount_tag.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These 9p modules could be useful from the rescue command line inside the initrd to get needed files that are on the host.&lt;br /&gt;
&lt;br /&gt;
All dependent modules will also be included automatically into /boot/initrd-tree, which is packaged as /boot/initrd.gz. For example, to see the dependent modules of zfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
modprobe --show-depends zfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All listed modules will also be in the initrd. Now, make a /boot/initrd-tree that we can begin to look at and edit:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkinitrd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create an empty /etc/mtab or else zpool import fails (zfs expects /etc/mtab to exists already, it won't make it):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
touch /boot/initrd-tree/etc/mtab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Copy in the fstab.initrd that was made earlier while on the installer. This provides all the mount options for a simple &amp;quot;mount zfs-root&amp;quot; onto /mnt:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/fstab.initrd /boot/initrd-tree/etc/fstab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More package installing! This time into an alternate root, the root of the initrd, /boot/initrd-tree. This is how you can put whatever packages you like into your initrd. These installations work independent of your normal installations. You can install, upgrade, and remove packages using an altroot:&lt;br /&gt;
&lt;br /&gt;
If spl and zfs are on your customized dvd:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/addon/spl-*.txz&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/addon/zfs-*.txz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Otherwise, repeat same procedure but you mount your 9p mount_tag and get them installed.&lt;br /&gt;
&lt;br /&gt;
More regular packages from the dvd:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/kmod-*.txz&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/coreutils-*.txz&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/gptfdisk-*.txz&lt;br /&gt;
&lt;br /&gt;
# A bash script is in /boot/initrd-tree/lib/udev/, so we need it or udev rules have problems:&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/bash-*.txz&lt;br /&gt;
# Bash needs this:&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/l/libtermcap-*.txz&lt;br /&gt;
&lt;br /&gt;
# Install net-tools to ensure that /etc/HOSTNAME, /etc/hosts, and potentially, /etc/hostid are handled proper.&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/n/net-tools-*.txz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When ZFS has to import a zpool while the initrd is running (this can be avoided by not exporting and keeping /etc/zfs/zpool.cache inside the initrd), ZFS will refuse to import a pool if it thinks that the pool may be in use by another system. ZFS was designed for network attached storage (NAS) where multiple hosts might have access to the same disks but ZFS cannot support two hosts importing and using a ZFS pool at the same time (that requires a &amp;quot;cluster&amp;quot; fs). ZFS checks a value called &amp;quot;hostid&amp;quot; to determine this kind of conflict, and it can be a tricky issue with an initrd boot process. The value of hostid is returned by the gethostid() function or the hostid command. This function will return the hostid from /etc/hostid if that file exists and has a valid id in it, or else if the file doesn't exist it obtains a hostid number based on the hostname and ip address assigned to hostname found in /etc/hosts or in DNS. If the hostid trying to import a pool is not the same as the hostid that imported it last time, ZFS will not import the pool unless &amp;quot;zpool import -f zfs-root&amp;quot; is used to force the import. This force option is not recommended to use, so it is best to configure your initrd with matching /etc/HOSTNAME and /etc/hosts as on the root installation and ensure what your system looks like on the initrd matches the booted root system. The hostid can also be passed to the SPL module with the module parameter &amp;lt;code&amp;gt;spl.spl_hostid=0xHHHHHHHH&amp;lt;/code&amp;gt; where the Hs are a hexadecimal hostid value and this overrides any /etc/hostid or hostname/IP-based hostid value.&lt;br /&gt;
&lt;br /&gt;
Edit /boot/initrd-tree/init (this is the main system startup script on the initrd, responsible for configuring your block devices, mounting root at /mnt, and booting root):&lt;br /&gt;
&lt;br /&gt;
Inside init, right near the top of the file after the PATH= line, add this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/bin/hostname -F /etc/HOSTNAME&lt;br /&gt;
/bin/hostname $( /bin/hostname -s )&lt;br /&gt;
#/sbin/chhostid 13371400&lt;br /&gt;
# you can make your hostid whatever, but this didn't work right with ZFS, so it is commented out&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This sets the name reported by the hostname command (the default is &amp;quot;darkstar&amp;quot;) to be what is contained in /etc/HOSTNAME. The hostname is modified in the next line to be the short hostname. These lines will help ZFS to properly identify your host when importing pools.&lt;br /&gt;
&lt;br /&gt;
Inside init, right after it runs &amp;quot;mdadm&amp;quot; commands as used for raid setup, we like it to setup ZFS, so add:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/sbin/zpool import zfs-root&lt;br /&gt;
/sbin/zfs set readonly=on zfs-root&lt;br /&gt;
mount zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
We want to make sure the default is to mount readonly, then it mounts using defaults from /etc/fstab inside the initrd.&lt;br /&gt;
&lt;br /&gt;
Inside init, close to the bottom, where it &amp;quot;Switch to real root partition&amp;quot;, comment out 1 line that normally does the mount:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# mount -o ro -t $ROOTFS $ROOTDEV /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
We have already mounted zfs-root, and we don't want to use any mount options because we should be using a properly set /etc/fstab inside the initrd for the zfs-root mount options onto /mnt.&lt;br /&gt;
&lt;br /&gt;
During a normal startup we want a readonly mount.&lt;br /&gt;
&lt;br /&gt;
Note: we are going to setup with using &amp;quot;zpool import&amp;quot; and &amp;quot;zpool export&amp;quot; commands at startup and shutdown. But later, you can experiment having /etc/zfs/zpool.cache stored in the initrd and commenting out the zpool import/export lines. Using zpool import/export is safer than using a zpool.cache, so we try to setup that way preferably.&lt;br /&gt;
&lt;br /&gt;
As mentioned, the zpool import command may sometimes fail, and give the message: &amp;quot;pool may be in use from another system&amp;quot;. This is nothing serious in this test situation. When this happens, zfs-root will not get mounted to /mnt and the init script will detect this and drop you into a rescue command line where you may manually do:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool import -f zfs-root&lt;br /&gt;
mount zfs-root&lt;br /&gt;
exit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This will force import, overriding the conflict that zfs thinks may be happening. Next is mount. After this, exit to let the init script continue on to boot the system normally.&lt;br /&gt;
&lt;br /&gt;
To avoid this problem we copy some files in (assuming you first edit /etc/HOSTNAME to hold the hostname you like to see on your command prompts, and edited /etc/hosts to have hostname on your loopback or other local ip address):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/HOSTNAME /etc/hosts /boot/initrd-tree/etc&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The value reported by the hostid command is what ZFS sees as your hostid (the SPL module actually tries to run the hostid command to get this value or it uses the spl.spl_hostid value that is given to it). In this setup so far, the value is based on the ip assigned to your hostname. If your hostname is on the line in /etc/hosts for ip address 192.168.13.37, then your hostid will be hex numbers C0.A8.0D.25 rearranged as A8C0250D (pairs of bytes are swapped). This is a ip-based hostid value, a 32bit hexadecimal number. The hostid has to be the same each boot or import will need a -f option to force it. Simply setting the hostid using the function sethostid() which writes a /etc/hostid file doesn't seem to agree with ZFS and you'd have to force the import, so this setup now assumes that you do not have or have deleted /etc/hostid.&lt;br /&gt;
&lt;br /&gt;
You can sometimes see what has been happening to a zpool by using the command &amp;quot;zpool history -li zfs-root&amp;quot; to see a log of commands.&lt;br /&gt;
&lt;br /&gt;
Once again, you can do away with the import and export commands by trying to have /etc/zfs/zpool.cache inside your initrd. To create zpool.cache, while on the installer or in the rescue shell of the initrd (at lilo &amp;quot;boot: vmlinuz rescue&amp;quot;):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on installer or initrd rescue shell)&lt;br /&gt;
zpool import zfs-root&lt;br /&gt;
zfs set readonly=off zfs-root&lt;br /&gt;
mount zfs-root&lt;br /&gt;
cp /etc/zfs/zpool.cache /mnt/etc/zfs/zpool.cache-initrd&lt;br /&gt;
cp /mnt/etc/zfs/zpool.cache-initrd /mnt/boot/initrd-tree/etc/zfs/zpool.cache&lt;br /&gt;
umount /mnt&lt;br /&gt;
zfs set readonly=on zfs-root&lt;br /&gt;
#mount zfs-root&lt;br /&gt;
#exit (to continue boot process onto rootfs mounted at /mnt)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Words of caution, again: Doing this zpool.cache approach is not necessary, and some talk suggests this is deprecated or discouraged. Although /etc/hostid setup fails to import without -f option, ip-based (hosts|dns) hostid works on booting and import works without -f option and may be the more proper way to do shutdown and startup rather than using a cache file which could become invalid and cause a problem that is difficult to understand. The contents and exact function of the cache file are not well understood by many people. As will be spammed all over this wiki, using zpool.cache is not recommended if you can avoid it because it is potentially unsafe for your pool.&lt;br /&gt;
&lt;br /&gt;
Save /boot/initrd-tree/init and quit vi.&lt;br /&gt;
&lt;br /&gt;
Now, edit /etc/rc.d/rc.S and rc.6 to understand how to remount rw or ro as readonly property changes:&lt;br /&gt;
&lt;br /&gt;
In /etc/rc.d/rc.S:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# comment out the line&lt;br /&gt;
#    /sbin/mount -w -v -n -o remount /&lt;br /&gt;
#add the line&lt;br /&gt;
     /sbin/zfs set readonly=off zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If you are using &amp;lt;code&amp;gt;mountpoint=legacy&amp;lt;/code&amp;gt; for zfs-root, you do not need to make the above change.&lt;br /&gt;
&lt;br /&gt;
In /etc/rc.d/rc.6:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# before: echo &amp;quot;Unmounting local file systems.&amp;quot;&lt;br /&gt;
# add lines:&lt;br /&gt;
  rm -f /etc/zfs/zpool.cache&lt;br /&gt;
  echo &amp;quot;Removed /etc/zfs/zpool.cache&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Remove /etc/zfs/zpool.cache on shutdown. This is recommended because if it is present when you import a pool, it might use this old cache to determine the device filenames in the pool, which may have changed filenames since the last boot, especially the non-persistent /dev/sd* device filenames. It is safest to avoid any usage of the zpool.cache file at boot in initramfs, zfs module load, and at zpool import of other pools.&lt;br /&gt;
&lt;br /&gt;
In /etc/rc.d/rc.6:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# comment out the line:&lt;br /&gt;
#    /bin/mount -v -n -o remount,ro /&lt;br /&gt;
# add the line:&lt;br /&gt;
     /sbin/zfs set readonly=on zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If you are using &amp;lt;code&amp;gt;mountpoint=legacy&amp;lt;/code&amp;gt; for zfs-root, you do not need to make the above change.&lt;br /&gt;
&lt;br /&gt;
In /etc/rc.d/rc.6, near the bottom just before poweroff|reboot, add the following block of lines:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
########################&lt;br /&gt;
# Try to export zfs-root&lt;br /&gt;
/sbin/zpool export zfs-root&lt;br /&gt;
if [ $? -gt 0 ] ; then&lt;br /&gt;
 echo &amp;quot;ZFS export failed.&amp;quot;&lt;br /&gt;
 echo &amp;quot;Notice: if root fs is busy, then this is normal fail.&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;ZFS export successful.&amp;quot;&lt;br /&gt;
 echo &amp;quot;Warning: successful export is abnormal for root fs.&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
/bin/sleep 5&lt;br /&gt;
########################&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This attempts to export even though it cannot return success for the root pool. The attempt is still recorded in the zpool history, and even though it fails the pool may actually be marked as exported (not sure).&lt;br /&gt;
&lt;br /&gt;
For ZFS, you cannot run fsck on it. It doesn't support that kind of filesystem check. The rc.S script will complain a lot in many places about not being able to run fsck on the zfs-root. To disable all attempts to run fsck, we can simply create a file that acts as a flag in /etc/rc.d/rc.S to tell it to skip fsck:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
touch /etc/fastboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This fastboot file is normally a run-once temporary file, and it is deleted near the bottom inside rc.S. Edit rc.S and stop it from deleting /etc/fastboot. We would like it to always skip all fsck. Edit /etc/rc.d/rc.S, and find the &amp;quot;rm&amp;quot; of fastboot, and do not have it removed!&lt;br /&gt;
&lt;br /&gt;
An alternative to using /etc/fastboot is to make the file &amp;lt;code&amp;gt;/sbin/fsck.zfs&amp;lt;/code&amp;gt; that always just &amp;quot;does nothing successfully&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
exec /bin/true&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Or, it can be:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Or, just do:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ln -s /bin/true /sbin/fsck.zfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This fsck helper has the advantage that you do not need to alter &amp;lt;code&amp;gt;rc.S&amp;lt;/code&amp;gt; as much, or at all if you use zfs property &amp;lt;code&amp;gt;mountpoint=legacy&amp;lt;/code&amp;gt; and the regular &amp;lt;code&amp;gt;mount&amp;lt;/code&amp;gt; command on your zfs-root. With these ideas, no slackware /etc/rc.d/* files really need editing, but it is up to you how you want to experiment. I prefer to use &amp;lt;code&amp;gt;mountpoint=legacy&amp;lt;/code&amp;gt; and edit just the initrd init script as above, and edit rc.6 to remove /etc/zfs/zpool.cache and try to export.&lt;br /&gt;
&lt;br /&gt;
We are getting close, and have finished all editing, so make /boot/initrd.gz and install lilo:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkinitrd -F&lt;br /&gt;
lilo&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We finished! All that's left to do is clean up.&lt;br /&gt;
&lt;br /&gt;
Exit the chroot.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
exit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Try to umount everything:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
umount /mnt/proc&lt;br /&gt;
umount /mnt/sys&lt;br /&gt;
umount /mnt/dev&lt;br /&gt;
umount /mnt/boot&lt;br /&gt;
umount /mnt/mnt/cdrom&lt;br /&gt;
umount /mnt/root/packages&lt;br /&gt;
umount /mnt&lt;br /&gt;
zpool export zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note, that export stops a pool and frees devices, while import binds devices and starts a pool. It is somewhat like mdadm -A -s and mdadm -S -s, while /etc/zfs/zpool.cache might be somewhat like mdadm -E -s &amp;gt; /etc/mdadm.conf.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Remove the DVD or change boot order&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When you reboot, if all is good, you are booting properly onto a slackware installed on a ZFS root! Congrats!&lt;br /&gt;
&lt;br /&gt;
If this seems to go badly, and this might happen if the import fails as explained some before, then you will be on the initrd's rescue command line just before the part in init where it wants to mount zfs-root and switch_root to boot up. In this case, you typically got commands like these to do:&lt;br /&gt;
&lt;br /&gt;
If you get dumped to rescue because zpool import will not work and requires -f (force), then:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 zpool import -f zfs-root&lt;br /&gt;
 zpool export    zfs-root&lt;br /&gt;
 zpool import    zfs-root&lt;br /&gt;
 mount zfs-root&lt;br /&gt;
 exit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This can happen if hostname, hostid, or uname changes.&lt;br /&gt;
&lt;br /&gt;
If you get into a jam and need to boot into the initrd and skip zpool import etc, use the lilo prompt (or, boot the install-dvd):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
boot: vmlinuz rescue&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the rescue mode of the initrd, after you have mounted your zfs-root as readonly=on to /mnt, then &amp;quot;exit&amp;quot; to continue booting.&lt;br /&gt;
&lt;br /&gt;
In other emergency command lines, you might need to run the lines at the end of init starting from: &amp;lt;code&amp;gt;udevadm info --cleanup-db; udevadm control --exit&amp;lt;/code&amp;gt;&lt;br /&gt;
If you don't run those udevadm commands, two runs of udevd fight each other and it is slow; you have to wait 2 minutes twice for timeouts (4 minutes).&lt;br /&gt;
The last line in init is run like: &amp;lt;code&amp;gt;exec switch_root /mnt /sbin/init 1&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Warning: the switch_root command is kind of dangerous, so read the manual page about it. From what I can tell, everything except the new root &amp;quot;/mnt&amp;quot; is deleted, so you are giving a command that says what NOT to delete! Make sure nothing got mounted outside of &amp;quot;/mnt&amp;quot; before you run it. However, the deletes should not cross filesystems, but only delete the contents of initramfs.&lt;br /&gt;
&lt;br /&gt;
Also, in rescue command line or anytime you have finished making changes and are about to reboot in some abnormal situation, first run:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set readonly=on zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A bug in unpatched grep 2.13 build 1, found slackware 14.0rc1, causes problems when processing files stored on ZFS but rarely shows problems on other filesystems; the bug does not handle sparse files on zfs and btrfs correctly and results in chaos with slackpkg, compiling kernel modules, and possibly many other things. You must downgrade grep to 2.12 or use the patched grep 2.13 build 2 in slackware 14.0rc2 or later.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
Upgrading:&lt;br /&gt;
&lt;br /&gt;
From time to time you will want to upgrade the kernel to the new kernel in slackware64-current or in patches/. This will also necessitate a rebuild and reinstall or upgrade of spl and zfs. Below is an example of when both kernel and spl/zfs are being upgraded, to give an idea of the process:&lt;br /&gt;
&lt;br /&gt;
Using slackpkg, that is configured to use your local slackware mirror is a good option but you can also configure it to use a remote mirror.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slackpkg upgrade-all&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Assume slackpkg just upgraded your kernel, kernel-modules, kernel-headers, and kernel-source.&lt;br /&gt;
&lt;br /&gt;
Note: the first time you try to run on kernel-generic, setup kernel-huge in lilo as 2nd choice. Huge has all the hard drive controllers builtin, but generic has them all as modules. For example, run &amp;quot;modinfo mptsas&amp;quot; to see module options (maybe you have a LSISAS1068) for your hard drive controller. Add file /etc/modprobe.d/mptsas.conf to set options you want with a line: options mptsas ... Do this for all the device driver modules for your hardware. Do this setup while you are on the huge kernel, then setup to reboot to generic. Include all these modules you need into mkinitrd.conf MODULES_LIST. Check that /boot/initrd-tree/etc/modprobe.d/ has a copy of your customized module conf files because it is on the initrd where the modules will load and use the conf files. mkinitrd probably copies all /etc/modprobe.d/* files into the initrd-tree, but check it. Pay attention to /etc/modprobe.d/README and /lib/modprobe.d/* /lib/modprobe.d/* maybe not copied to initrd-tree but you might want to copy some of it into your initrd-tree yourself to use them.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Check that upgraded kernel-source is symlinked to /usr/src/linux (zfs build looks here). SPL/ZFS modules will install to the kernel version in /lib/modules/&amp;lt;/usr/src/linux kernel version&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /usr/local/src&lt;br /&gt;
tar xvzf ~/spl-*.tar.gz&lt;br /&gt;
tar xvzf ~/zfs-*.tar.gz&lt;br /&gt;
&lt;br /&gt;
###### upgrade spl 1st&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-*&lt;br /&gt;
./configure --prefix=/ --libexecdir=/usr/libexec --libdir=/lib64 --includedir=/usr/include --datarootdir=/usr/share&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=/usr/local/src/install&lt;br /&gt;
cd ../install&lt;br /&gt;
makepkg ../spl-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
upgradepkg spl-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
depmod &amp;lt;new kernel version&amp;gt;     (e.g. depmod 3.2.28, if .28 is new kernel upgrade; you currently run on old, maybe .27)&lt;br /&gt;
# this builds the module dependencies in /lib/modules/&amp;lt;new kernel version&amp;gt;&lt;br /&gt;
###### upgrade zfs 2nd&lt;br /&gt;
mkdir install&lt;br /&gt;
cd zfs-*&lt;br /&gt;
./configure --prefix=/ --libexecdir=/usr/libexec --libdir=/lib64 --includedir=/usr/include --datarootdir=/usr/share&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=/usr/local/src/install&lt;br /&gt;
cd ../install&lt;br /&gt;
makepkg ../zfs-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
upgradepkg zfs-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
depmod 3.2.28&lt;br /&gt;
####### upgrade spl/zfs inside altroot /boot/initrd-tree&lt;br /&gt;
ROOT=/boot/initrd-tree upgradepkg spl-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
ROOT=/boot/initrd-tree upgradepkg zfs-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
# note: ROOT is an environment variable, not a command line option to upgradepkg!&lt;br /&gt;
# note: do not worry about depmod inside initrd-tree, mkinitrd -F actually installs the modules&lt;br /&gt;
# note: this upgrade here is really to just upgrade the command line tools zpool, zfs etc&lt;br /&gt;
####### rebuild /boot/initrd.gz and reinstall lilo&lt;br /&gt;
vi /etc/mkinitrd.conf&lt;br /&gt;
# temporarily set KERNEL_VERSION to new version, but you are still running on old version&lt;br /&gt;
mkinitrd -F&lt;br /&gt;
lilo&lt;br /&gt;
vi /etc/mkinitrd.conf&lt;br /&gt;
# you can set KERNEL_VERSION back to $(uname -r) now&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After reboot you can remove any old /lib/modules/&amp;lt;old kernel version&amp;gt; directory.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
More about /etc/hostid. If you want to experiment changing your /etc/hostid file and seeing if you can use it and make zpool import work normally, here is a tool that might be helpful:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/* software product name: foobarz-chhostid.c&lt;br /&gt;
 * suggested binary name: chhostid&lt;br /&gt;
 * license              : BSD&lt;br /&gt;
 * license text:&lt;br /&gt;
Copyright (c) 2012, foobarz&lt;br /&gt;
All rights reserved.&lt;br /&gt;
&lt;br /&gt;
Redistribution and use in source and binary forms, with or without&lt;br /&gt;
modification, are permitted provided that the following conditions are met:&lt;br /&gt;
    * Redistributions of source code must retain the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer.&lt;br /&gt;
    * Redistributions in binary form must reproduce the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer in the&lt;br /&gt;
      documentation and/or other materials provided with the distribution.&lt;br /&gt;
    * Neither the name of the &amp;lt;organization&amp;gt; nor the&lt;br /&gt;
      names of its contributors may be used to endorse or promote products&lt;br /&gt;
      derived from this software without specific prior written permission.&lt;br /&gt;
&lt;br /&gt;
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &amp;quot;AS IS&amp;quot; AND&lt;br /&gt;
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED&lt;br /&gt;
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE&lt;br /&gt;
DISCLAIMED. IN NO EVENT SHALL &amp;lt;COPYRIGHT HOLDER&amp;gt; BE LIABLE FOR ANY&lt;br /&gt;
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES&lt;br /&gt;
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;&lt;br /&gt;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND&lt;br /&gt;
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT&lt;br /&gt;
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS&lt;br /&gt;
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#define FOOBARZ_CHHOSTID_VERSION &amp;quot;1.0.5&amp;quot;&lt;br /&gt;
#include &amp;lt;sys/socket.h&amp;gt;&lt;br /&gt;
#include &amp;lt;netinet/in.h&amp;gt;&lt;br /&gt;
#include &amp;lt;arpa/inet.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;endian.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sysexits.h&amp;gt;&lt;br /&gt;
/* note: if include stdlib then sethostid fails even with _BSD_SOURCE defined */&lt;br /&gt;
&lt;br /&gt;
long swapbytes(long abcd) {&lt;br /&gt;
  long badc;&lt;br /&gt;
  unsigned char addr_a;&lt;br /&gt;
  unsigned char addr_b;&lt;br /&gt;
  unsigned char addr_c;&lt;br /&gt;
  unsigned char addr_d;&lt;br /&gt;
  addr_a = (unsigned char) (abcd &amp;gt;&amp;gt; 24);&lt;br /&gt;
  addr_b = (unsigned char) (abcd &amp;gt;&amp;gt; 16);&lt;br /&gt;
  addr_c = (unsigned char) (abcd &amp;gt;&amp;gt;  8);&lt;br /&gt;
  addr_d = (unsigned char) (abcd);&lt;br /&gt;
  return badc = ( (addr_b &amp;lt;&amp;lt; 24) | (addr_a &amp;lt;&amp;lt; 16) | (addr_d &amp;lt;&amp;lt; 8) | addr_c );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[])&lt;br /&gt;
{&lt;br /&gt;
 long newhostid;&lt;br /&gt;
 struct in_addr addr;&lt;br /&gt;
 char* invalidchar;&lt;br /&gt;
&lt;br /&gt;
 /*********** check command line */&lt;br /&gt;
 if(!( ((argc==3) &amp;amp;&amp;amp; ( (strcmp(argv[1],&amp;quot;-h&amp;quot;)==0) ||&lt;br /&gt;
                       (strcmp(argv[1],&amp;quot;-i&amp;quot;)==0) ||&lt;br /&gt;
                       (strcmp(argv[1],&amp;quot;-l&amp;quot;)==0) )) ||&lt;br /&gt;
       ((argc==2) &amp;amp;&amp;amp; ( (strcmp(argv[1],&amp;quot;-s&amp;quot;)==0) ))&lt;br /&gt;
     )&lt;br /&gt;
   ) {&lt;br /&gt;
                 /*01234567890123456789012345678901234567890123456789012345678901234567890123456789*/&lt;br /&gt;
  fprintf(stderr, &amp;quot;foobarz-chhostid, version %s. License: BSD.\n&amp;quot;, FOOBARZ_CHHOSTID_VERSION);&lt;br /&gt;
  fprintf(stderr, &amp;quot;foobarz-chhostid, (c) 2012, foobarz; all rights reserved.\n&amp;quot;);&lt;br /&gt;
  fprintf(stderr, &amp;quot;descr: %s change system hostid (in /etc/hostid).\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -h &amp;lt;new hostid&amp;gt;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        Change system hostid to &amp;lt;new hostid&amp;gt;;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        &amp;lt;new hostid&amp;gt; must be 32bit 8-digit hex number xxxxxxxx, each x in 0-f|F.\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        The ip corresponding to &amp;lt;new hostid&amp;gt; is also listed for reference only.\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -i &amp;lt;dotted ip address&amp;gt;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        Change system hostid to hostid corresponding to &amp;lt;dotted ip address&amp;gt;.\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -l &amp;lt;dotted ip address&amp;gt;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        List hostid corresponding to &amp;lt;dotted ip address&amp;gt;;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        no change to system hostid.\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -s\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        List current system hostid and corresponding ip address;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        no change to system hostid.\n&amp;quot;, argv[0]);&lt;br /&gt;
  return EX_USAGE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -h &amp;lt;hostid&amp;gt; */&lt;br /&gt;
 if( strcmp(argv[1],&amp;quot;-h&amp;quot;) == 0 ) {&lt;br /&gt;
  if(strlen(argv[2]) != 8) { fprintf(stderr, &amp;quot;new hostid must be 8-digit hex number xxxxxxxx, each x in 0-f|F\n&amp;quot;); return EX_USAGE; }&lt;br /&gt;
&lt;br /&gt;
  newhostid = strtol(argv[2],&amp;amp;invalidchar,16);&lt;br /&gt;
  if( newhostid==LONG_MIN ) { perror(&amp;quot;strtol (underflow)&amp;quot;); return EX_USAGE; }&lt;br /&gt;
  if( newhostid==LONG_MAX ) { perror(&amp;quot;strtol (overflow)&amp;quot;); return EX_USAGE; }&lt;br /&gt;
  if(*invalidchar != '\0') { fprintf(stderr, &amp;quot;invalid hex number %c; must be in 0-f|F\n&amp;quot;, *invalidchar); return EX_USAGE; }&lt;br /&gt;
&lt;br /&gt;
  if( sethostid(newhostid) != 0 ) {&lt;br /&gt;
   perror(&amp;quot;sethostid&amp;quot;);&lt;br /&gt;
   if( errno == EPERM ) return EX_NOPERM;&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
  }&lt;br /&gt;
  printf(&amp;quot;System hostid changed.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  /* hostid is a byte-swapped ip like b.a.d.c */&lt;br /&gt;
  /* get ip by swapping to correct order a.b.c.d and save into in_addr struct */&lt;br /&gt;
  addr.s_addr = htonl(swapbytes(newhostid));&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -i or -l, then find hostid for &amp;lt;dotted ip address&amp;gt; */&lt;br /&gt;
 if( (strcmp(argv[1],&amp;quot;-i&amp;quot;) == 0) || (strcmp(argv[1],&amp;quot;-l&amp;quot;) == 0) ) {&lt;br /&gt;
  if( inet_aton(argv[2], &amp;amp;addr) == 0 ) { fprintf(stderr, &amp;quot;inet_aton: invalid dotted ip address: %s\n&amp;quot;, argv[2]); return EX_USAGE; }&lt;br /&gt;
&lt;br /&gt;
  /* hostid is a byte-swapped ip like b.a.d.c */&lt;br /&gt;
  /* get hostid by swapping bytes of ip a.b.c.d */&lt;br /&gt;
  newhostid = swapbytes(ntohl(addr.s_addr));&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -i &amp;lt;dotted ip address&amp;gt; */&lt;br /&gt;
 if( strcmp(argv[1],&amp;quot;-i&amp;quot;) == 0 ) {&lt;br /&gt;
  if( sethostid(newhostid) != 0 ) {&lt;br /&gt;
   perror(&amp;quot;sethostid&amp;quot;);&lt;br /&gt;
   if( errno == EPERM ) return EX_NOPERM;&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
  }&lt;br /&gt;
  printf(&amp;quot;System hostid changed.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -l &amp;lt;dotted ip address&amp;gt; */&lt;br /&gt;
 if(strcmp(argv[1],&amp;quot;-l&amp;quot;) == 0 ) {&lt;br /&gt;
   printf(&amp;quot;Listing hostid for ip. (no changes)\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -s */&lt;br /&gt;
 if(strcmp(argv[1],&amp;quot;-s&amp;quot;) == 0 ) {&lt;br /&gt;
   /* see if /etc/hostid exists and print info */&lt;br /&gt;
   if( access(&amp;quot;/etc/hostid&amp;quot;, F_OK) != 0 ) {&lt;br /&gt;
     printf(&amp;quot;Notice: /etc/hostid does not exist.\n&amp;quot;);&lt;br /&gt;
     perror(&amp;quot;Reason&amp;quot;);&lt;br /&gt;
     printf(&amp;quot;System hostid derived from ip of hostname found in hosts file or dns.\n&amp;quot;);&lt;br /&gt;
   } else {&lt;br /&gt;
     printf(&amp;quot;Notice: /etc/hostid exists.\n&amp;quot;&lt;br /&gt;
            &amp;quot;System hostid is obtained from hostid file.\n&amp;quot;);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
  errno=0;&lt;br /&gt;
  newhostid = gethostid();&lt;br /&gt;
  if(errno!=0) { perror(&amp;quot;gethostid&amp;quot;); return EX_UNAVAILABLE; }&lt;br /&gt;
&lt;br /&gt;
  /* hostid is a byte-swapped ip like b.a.d.c */&lt;br /&gt;
  /* get ip by swapping to correct order a.b.c.d and save into in_addr struct */&lt;br /&gt;
  addr.s_addr = htonl(swapbytes(newhostid));&lt;br /&gt;
&lt;br /&gt;
  printf(&amp;quot;Listing current system hostid. (no changes)\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** print info and return */&lt;br /&gt;
 printf(&amp;quot;ip dot: %s\n&amp;quot;, inet_ntoa(addr) );&lt;br /&gt;
 printf(&amp;quot;ip hex: %.8x\n&amp;quot;, ntohl(addr.s_addr) );&lt;br /&gt;
 printf(&amp;quot;hostid: %.8x\n&amp;quot;, newhostid );&lt;br /&gt;
 return EX_OK;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
----&lt;br /&gt;
Now available! &amp;quot;ZFS root (builtin)&amp;quot; wiki (aka &amp;quot;ZFS root, part II&amp;quot;):&lt;br /&gt;
http://slackwiki.com/ZFS_root_(builtin)&lt;br /&gt;
It is now possible to build the modules and a small initramfs into your kernel to have a fully-contained and bootable ZFS root kernel from a simple lilo entry. Good luck!&lt;/div&gt;</description>
			<pubDate>Wed, 19 Sep 2012 08:42:03 GMT</pubDate>
			<dc:creator>Foobarz</dc:creator>
			<comments>https://www.slackwiki.com/Talk:ZFS_root</comments>
		</item>
		<item>
			<title>ZFS root</title>
			<link>https://www.slackwiki.com/index.php?title=ZFS_root&amp;diff=796</link>
			<guid isPermaLink="false">https://www.slackwiki.com/index.php?title=ZFS_root&amp;diff=796</guid>
			<description>&lt;p&gt;Foobarz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Tutorials]]&lt;br /&gt;
If you have heard about the ZFS filesystem and you're curious to try it out, then you can try it on slackware64, thanks to the ZFSonLinux.org project!&lt;br /&gt;
&lt;br /&gt;
In this article, an example is shown of how to install slackware64 14.0 onto a ZFS root filesystem (zfs-root) inside a QEMU virtual machine for testing purposes. It is recommended that you install qemu and learn how to use it to test a ZFS installation before you decide to use it on real hardware. A slackbuild for qemu can be found on slackbuilds.org. If you have a processor that supports Intel VT-x or AMD AMD-V virtualization acceleration (try modprobe kvm-intel or modprobe kvm-amd), then use the slackbuild for qemu-kvm.&lt;br /&gt;
&lt;br /&gt;
This article isn't going to go into any detail on actually using ZFS or what kinds of installation options and settings might be optimal. This article just presents an example of how to get started with ZFS on slackware.&lt;br /&gt;
&lt;br /&gt;
At this time of writing, ZFSonLinux is at &amp;quot;release candidate&amp;quot; (version 0.6.0-rc10) development stage, and many issues can occur. See the ZFSonLinux.org web site and the issues tracker for an idea about the current issues. There is also an irc channel on irc.freenode.net, #zfsonlinux, for discussion of issues and help.&lt;br /&gt;
&lt;br /&gt;
Although not required, it is helpful to keep a local mirror of slackware64 on your system. Having a local mirror makes it easier to upgrade to slackware64-current or to patches/* in a release. To help manage your own local slackware mirror and generate your own CD and DVD slackware installers, see http://alien.slackbook.org/blog/local-slackware-mirror/.&lt;br /&gt;
&lt;br /&gt;
In this article, we use a slackware64-current DVD image file as the qemu cdrom device media for the installation of the slackware guest. This was tested at slackware64-current = slackware64 14.0rc2. You can obtain a slackware DVD image using a torrent, buy the DVD from slackware.com, or generate your own DVD image file using the mirror script. For an actual DVD, you can pass your DVD device (e.g., /dev/sr0) as the qemu cdrom device. For a DVD image file, pass the image file as the qemu cdrom device.&lt;br /&gt;
&lt;br /&gt;
The ZFSonLinux packages are not included in slackware at this time. There are two packages involved: spl and zfs. The first, spl, is &amp;quot;Solaris Porting Layer&amp;quot; and must be installed on the system before zfs can be compiled. The source code tarballs for these are at ZFSonLinux.org. At this time of writing, they are spl-0.6.0-rc10.tar.gz and zfs-0.6.0-rc10.tar.gz.&lt;br /&gt;
&lt;br /&gt;
At this point, it is assumed you have qemu installed, have obtained a slackware64-current/14.0 DVD, and have downloaded spl and zfs tarballs to your host system. The first step now is, if your host is not slackware64-current/14.0 (the same as the guest will be), then you need to create a minimal development slackware64 guest system in qemu for just the purpose of compiling and packaging the spl and zfs slackware packages and transferring a copy of these packages back onto your host system to use later to install onto zfs during the slackware install process.&lt;br /&gt;
&lt;br /&gt;
From this point onward, instructions become a bit terse and mostly limited to examples of the commands you might use to complete tasks. You are encouraged to examine what each command does by reading the command's man pages. For example, the command &amp;quot;man qemu&amp;quot; can show you most of what you need to know about running qemu on the command line.&lt;br /&gt;
&lt;br /&gt;
So, here's an example of how you might build the spl and zfs packages, starting in your home directory:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on host)&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir qemu&lt;br /&gt;
cd qemu&lt;br /&gt;
mkdir slackdevel&lt;br /&gt;
cd slackdevel&lt;br /&gt;
mkdir packages&lt;br /&gt;
cp ~/spl-*.tar.gz packages&lt;br /&gt;
cp ~/zfs-*.tar.gz packages&lt;br /&gt;
qemu-img create disk1.raw 10G&lt;br /&gt;
ln -s ~/slackware64-current-install-dvd.iso dvd.iso&lt;br /&gt;
qemu-kvm \&lt;br /&gt;
 -option-rom 8xx_64.rom,bootindex=1 \&lt;br /&gt;
 -no-quit \&lt;br /&gt;
 -no-shutdown \&lt;br /&gt;
 -boot order=cd,menu=on \&lt;br /&gt;
 -m 2G \&lt;br /&gt;
 -cpu host \&lt;br /&gt;
 -smp sockets=1,cores=4 \&lt;br /&gt;
 -net nic,model=e1000 -net user \&lt;br /&gt;
 -cdrom dvd.iso \&lt;br /&gt;
 -drive format=raw,media=disk,cache=none,aio=native,if=scsi,index=0,file=disk1.raw \&lt;br /&gt;
 -virtfs local,path=./packages/,security_model=none,mount_tag=hostpackages&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When you need to change boot to cd or disk, try changing &amp;quot;order=dc&amp;quot; or hitting F12 at boot prompt and select the CD/DVD boot option.&lt;br /&gt;
&lt;br /&gt;
Note: The support for booting drives using if=scsi is not included with current versions of qemu. Booting scsi requires the 8xx_64.rom option-rom, which can be downloaded at&lt;br /&gt;
[http://www.lsi.com/downloads/Public/Host%20Bus%20Adapters/Host%20Bus%20Adapters%20Common%20Files/lsi_bios.zip LSI.com]. Unzip it, and then:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp 8xx_64.rom /usr/share/qemu&lt;br /&gt;
# then run qemu-kvm with additional command line option: -option-rom 8xx_64.rom,bootindex=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Qemu should boot into the install-dvd, and now perform a very ordinary slackware64 install onto /dev/sda. Install d package set and most others, but package sets x, kde, xfce not really needed.&lt;br /&gt;
&lt;br /&gt;
First note: examples here use tools from the gptfdisk package (gdisk, sgdisk, cgdisk) to partition the disk with GUID partition table (GPT) format. GPT might not be too familiar to everyone, who mostly have only used MBR partitions with fdisk. In the slackware installations this author has tested in qemu, using GPT partitions has caused no problems with lilo or other tools used in slackware. GPT disk labels support creating up to 128 partitions and support disks larger than 2TB (the limit of MBR fdisk). LILO installs into the first 440 bytes on /dev/sda, inside a GPT &amp;quot;protective MBR&amp;quot; that serves to provide compatibility with MBR bootloaders like lilo. LILO uses LBA32 sector addressing and can see all 512-byte sectors inside the first 2TB of a disk. So long as the /boot partition is within the first 2TB of a disk, lilo can work on a disk larger than 2TB. Unlike the common default of fdisk to start the first partition at sector 63, which is not aligned with the 4KiB sector size of Advanced Format hard disks, gdisk's default is to start partitions at 2048 sector (1MiB) boundaries which are also 4KiB aligned. Using gdisk GPT works on all disks and is compatible with using Advanced Format hard disks larger than 2TB. More information about GPT disk label format can be found on wikipedia.org. For those that have used grub instead of lilo, grub installation is different with GPT than with MBR, and grub requires a GPT partition of type grub-bios or 0xEF02 &amp;quot;BIOS Boot Partition&amp;quot; of about 8MiB where it can install it's additional bootloader stages because grub cannot embed in sectors 1-62 on GPT where GPT keeps it's partition tables. On MBR, sectors 1-62 were normally reserved space for bootloaders to keep a 2nd stage.&lt;br /&gt;
&lt;br /&gt;
For this purpose of development guest, just create a simple 1-partition system, /dev/sda1, and do a simple slackware install on it. Don't bother with swap or separate /boot unless you want to:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on install-dvd)&lt;br /&gt;
cgdisk /dev/sda&lt;br /&gt;
setup&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When this simple development guest boots, login as root, and continue:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on qemu guest)&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir packages&lt;br /&gt;
mount hostpackages -t 9p -o trans=virtio packages&lt;br /&gt;
echo --prefix=/ --libexecdir=/usr/libexec --libdir=/lib64 --includedir=/usr/include --datarootdir=/usr/share &amp;gt; configure-options&lt;br /&gt;
mkdir src&lt;br /&gt;
cd src&lt;br /&gt;
&lt;br /&gt;
mkdir install&lt;br /&gt;
tar xvzf ~/packages/spl-*.tar.gz&lt;br /&gt;
cd spl-*&lt;br /&gt;
./configure $( cat ~/configure-options )&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../spl-&amp;lt;version&amp;gt;_&amp;lt;kernel_version&amp;gt;-x86_64-&amp;lt;build_id&amp;gt;.txz&lt;br /&gt;
(e.g., makepkg ../spl-0.6.0rc10_3.2.27-x86_64-1root.txz)&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
installpkg spl-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
cp spl-0.6.0rc10_3.2.27-x86_64-1root.txz ~/packages&lt;br /&gt;
&lt;br /&gt;
mkdir install&lt;br /&gt;
tar xvzf ~/packages/zfs-*.tar.gz&lt;br /&gt;
cd zfs-*&lt;br /&gt;
./configure $( cat ~/configure-options )&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../zfs-&amp;lt;version&amp;gt;_&amp;lt;kernel_version&amp;gt;-x86_64-&amp;lt;build_id&amp;gt;.txz&lt;br /&gt;
(e.g., makepkg ../zfs-0.6.0rc10_3.2.27-x86_64-1root.txz)&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
installpkg zfs-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
cp zfs-0.6.0rc10_3.2.27-x86_64-1root.txz ~/packages&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point spl and zfs packages are copied back to the host in the packages directory. Also, spl and zfs are installed in this simple development guest, so one could begin to experiment with zfs pools and datasets but while the root fs is whatever you made it during setup (probably the default, ext4). This development guest isn't really needed anymore, so it can be deleted:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
halt&lt;br /&gt;
(exit qemu: ctrl-alt-2 then enter quit at QEMU command prompt)&lt;br /&gt;
&lt;br /&gt;
(on host)&lt;br /&gt;
rm disk1.raw dvd.iso&lt;br /&gt;
mv packages ..&lt;br /&gt;
cd ..&lt;br /&gt;
rmdir slackdevel&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now that we have the spl and zfs packages on the host, it is possible to copy them into your local slackware64 mirror and then generate your own install DVD image that includes them. For example, change to the directory that contains the slackware README files, and create a &amp;quot;addon&amp;quot; directory and copy the spl and zfs slackware packages into there. Then, generate the DVD image using a command such as $( ./mirror-slackware-current.sh -i ) from where you have this script configured to maintain your local mirror. We can also just continue to access them inside the installer using qemu's virtfs option. When you are going to do a real installation onto real hardware, you need to generate and burn your own DVD that includes the packages.&lt;br /&gt;
&lt;br /&gt;
It is time to begin the installation of slackware64 on a ZFS root, assuming either you have regenerated dvd.iso with zfs packages in addon/* or we access the zfs packages while in the installer using qemu's virtfs to the host's packages directory. ZFS supports creating complex data storage configurations such as pools (similar to a volume group) backed by one or more of various kinds of virtual devices (similar to disks and raid arrays) and containing one or more datasets (similar to mounted filesystems, logical volume devices, or snapshots). But here, we keep it simple and will install on just a single disk device.&lt;br /&gt;
&lt;br /&gt;
Note: On a real ZFS installation, users will typically want to use the ZFS mirror or raidz virtual device (vdev) types for reliability against hard drive failures. For example, a good configuration might be to use a USB memory stick (and a backup stick) for /boot that is plugged into an on-motherboard &amp;quot;Type A&amp;quot; USB connector. Then, use four whole hard drives in a raidz2 vdev as the initial storage space in the root zpool. At a later time, to add more storage space, additional whole four-drive raidz2 vdevs of the same size could be added to the zpool. It is recommended to only add the same vdev type (disk, mirror, or raidz|1|2|3) and size to a zpool since zfs stripes across the vdevs, and vdevs of different types/sizes do not stripe together optimally. After adding a vdev to your zpool, you might need to copy the new /etc/zfs/zpool.cache to your initrd-tree or initramfs-source (and rebuild/reinstall them) if you are using the cachefile to import your zpool. Using mirror vdevs would be similar to a raid10. Using 4-disk raidz2 vdevs would give the same storage space as raid10 while fully reliable against any double-disk failure; however, the raidz2 parity calculations results in higher CPU usage and/or lower performance. Because raidz vdevs cannot be grown by adding hard drives to them, and vdevs in a zpool are striped, it is important with ZFS to decide what type and size of vdev will be used in a zpool as the units of add-on storage space; it could be difficult to alter this decision later. Finally, on a real installation with raidz, data scrub should be scheduled to actively search for &amp;quot;latent defects&amp;quot; on the hard drives so that unknown read/write errors do not become known later during a disk swap/rebuild and result in the zpool becoming faulted (lost).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on host)&lt;br /&gt;
mkdir slackzfs&lt;br /&gt;
mv packages slackzfs/&lt;br /&gt;
cd slackzfs&lt;br /&gt;
qemu-img create disk1.raw 10G&lt;br /&gt;
ln -s ~/slackware64-current-install-dvd.iso dvd.iso&lt;br /&gt;
qemu-kvm \&lt;br /&gt;
 -option-rom 8xx_64.rom,bootindex=1 \&lt;br /&gt;
 -no-quit \&lt;br /&gt;
 -no-shutdown \&lt;br /&gt;
 -boot order=cd,menu=on \&lt;br /&gt;
 -m 2G \&lt;br /&gt;
 -cpu host \&lt;br /&gt;
 -smp sockets=1,cores=4 \&lt;br /&gt;
 -net nic,model=e1000 -net user \&lt;br /&gt;
 -cdrom dvd.iso \&lt;br /&gt;
 -drive format=raw,media=disk,cache=none,aio=native,if=scsi,index=0,file=disk1.raw \&lt;br /&gt;
 -virtfs local,path=./packages/,security_model=none,mount_tag=hostpackages&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The install-dvd should boot, and then begin installation steps on the installer command line:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on install-dvd)&lt;br /&gt;
# mount the install-dvd&lt;br /&gt;
mkdir /dvd&lt;br /&gt;
mount /dev/sr0 /dvd&lt;br /&gt;
&lt;br /&gt;
# install coreutils, which provides the &amp;quot;hostid&amp;quot; command needed to load the spl module&lt;br /&gt;
installpkg /dvd/slackware64/a/coreutils-8.17-x86_64-1.txz&lt;br /&gt;
&lt;br /&gt;
# install kmod package which includes &amp;quot;depmod&amp;quot; command and others&lt;br /&gt;
installpkg /dvd/slackware64/a/kmod-9-x86_64-2.txz&lt;br /&gt;
depmod&lt;br /&gt;
&lt;br /&gt;
# install the full kernel modules so you can load 9p filesystem and use it if you want&lt;br /&gt;
# .. you might keep the zfs modules packages off the dvd and use a plain slack dvd&lt;br /&gt;
installpkg /dvd/slackware64/a/kernel-modules-*.txz&lt;br /&gt;
depmod&lt;br /&gt;
&lt;br /&gt;
# install bash and libtermcap because udev rules in zfs use bash scripts&lt;br /&gt;
installpkg /dvd/slackware64/a/bash-*.txz&lt;br /&gt;
installpkg /dvd/slackware64/l/libtermcap-*.txz&lt;br /&gt;
&lt;br /&gt;
# install spl and zfs that you have copied into the mirror before running the DVD creation&lt;br /&gt;
installpkg /dvd/addon/spl-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /dvd/addon/zfs-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
&lt;br /&gt;
#Or:&lt;br /&gt;
mkdir /packages&lt;br /&gt;
find /lib/modules/ | grep 9p&lt;br /&gt;
lsmod&lt;br /&gt;
# check that 9p modules load, mainly 9pnet_virtio&lt;br /&gt;
modprobe 9pnet_virtio&lt;br /&gt;
mount hostpackages -t 9p -o trans=virtio /packages&lt;br /&gt;
installpkg /packages/spl-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /packages/zfs-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
modprobe zfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now zfs tools: &amp;quot;zpool&amp;quot; and &amp;quot;zfs&amp;quot; should work in the live installer.&lt;br /&gt;
On the installer, there can be trouble seeing man pages, so install:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
installpkg /dvd/slackware64/ap/man-*.txz&lt;br /&gt;
installpkg /dvd/slackware64/ap/groff-*.txz&lt;br /&gt;
installpkg /dvd/slackware64/a/less-*.txz&lt;br /&gt;
export MANPATH=/usr/man:/usr/share/man&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The manual pages should be readable:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
man zpool&lt;br /&gt;
man zfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After seeing the man pages, we should be fully ready to continue to setup on ZFS.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(still on install-dvd)&lt;br /&gt;
ls -l /dev/sd*&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Make sure the disk devices you expect are there. We'll use sda and make boot (/boot on /dev/sda1) and root (/ on /dev/sda2) partitions.&lt;br /&gt;
&lt;br /&gt;
First, some background info: A ZFS filesystem is not supported by lilo as the filesystem containing /boot, which holds lilo's 2nd stage and the linux kernel files. The on-disk format of a ZFS filesystem is often a complex raid configuration where even if lilo understood ZFS it would likely require /boot to reside in only certain simple ZFS configurations to be plainly readable to lilo. As things are, a linux root installed in a partition with ZFS filesystem needs /boot to be on another partition with a filesystem that lilo understands, such as ext4 fs. In addition, because the spl and zfs modules are not built into the kernel, and the zfs startup requires some configuration to mount the zfs root, an initial ram/root filesystem (initrd) is needed. The initrd is a gzip compressed cpio archive file that contains a small linux root operating system that is decompressed into a ramfs block device at boot up and takes initial control of the system. The initrd contains an init script that configures devices in devtmpfs mounted at /dev. For example, if using mdadm, lvm, luks, losetup, and now zfs, this init script runs all the commands to create or start these devices (one of which is the root device), mounts the root device, and then transfers system control to the init script in the mounted root filesystem. The ramfs-based root environment on the booted install-dvd or booted initrd image (in rescue command line) are small slackware installations that exist only in ram and are temporary, but while inside them you can install, upgrade, and remove slackware packages inside them using the regular package management tools; this allows you access to any kernel modules and programs as needed inside these ramfs root. Packages can be installed, upgraded, or removed permanantly in the initrd image file to manage the programs and modules required during the initrd boot stage. Also from within these ramfs initial root environments, once the root device is mounted, chroot can be used to work on the mounted root system as if it were booted; this allows one to fix problems that are occuring in the root fs init scripts that cause normal booting to fail, or to install a kernel and/or modules etc. Now on to partitioning:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cgdisk /dev/sda&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, cgdisk looks just like cfdisk, but it makes GPT partitions.&lt;br /&gt;
&lt;br /&gt;
Make a partition for /boot that is about 512MiB of whatever partition type you like (8300 &amp;quot;Linux filesystem&amp;quot; is fine), or make it type bf07 &amp;quot;Solaris Reserved 1&amp;quot; if you want ZFS to maybe see the disk as if it was given as a whole disk to ZFS. Make a second partition using the remaining space with partition type bf01 &amp;quot;Solaris ZFS&amp;quot;. Currently, when ZFSonLinux is given a whole disk device like /dev/sdb to use, it will automatically GPT partition it with a bf01 partition #1 that is the whole disk except a small 8MiB type bf07 partition #9 at the end of the disk (/dev/sdb1 and /dev/sb9). The small 8MiB type bf07 partition #9 is most likely reserved for use by bootloaders, like lilo, to have a /boot or other boot-related files kept there. For example, you might have /dev/sda that is totally non-ZFS for booting and /dev/sdb passed to ZFS whole where it automatically partitions sdb, but you can just use one disk here and make partitions. Let's use type 8300 for /boot to be sure nothing is confused:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
We'll continue with this partitioning (numbers are in MiB):&lt;br /&gt;
  0 to   4: unused&lt;br /&gt;
  4 to 516: /dev/sda1 512MiB, type 8300&lt;br /&gt;
516 to 520: unused&lt;br /&gt;
520 to -96: /dev/sda2, type bf01&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The -96 means to count from the end of the disk so that 96MiB will remain unused at the end of the disk.&lt;br /&gt;
&lt;br /&gt;
Create a zpool called zfs-root:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool create -m none zfs-root /dev/sda2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A zpool created like this, the normal way, is a kernel-internal block device that contains already a zfs filesystem. There is normally no entry in /dev for this device. However, it can still be referenced as a mountable device similar to how devtmpfs, proc, and sysfs are also kernel-internal mountable block devices. The -m option told zpool not to automatically mount it anywhere, and without -m the default is to always automatically mount to /zfs-root. These kinds of details are explained better elsewhere. For this situation, we do not want it automounted.&lt;br /&gt;
&lt;br /&gt;
Because a zpool itself is a useable zfs fs, it has a full set of zfs &amp;quot;properties&amp;quot; to set options about the filesystem, perhaps similar to tune2fs. The &amp;quot;mountpoint=&amp;lt;some place to mount&amp;gt;&amp;quot; is one such property. We want it set to the special value &amp;quot;none&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs get mountpoint zfs-root&lt;br /&gt;
zfs set mountpoint=none zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also use &amp;quot;legacy&amp;quot; for the mountpoint and the management of mounting and unmounting the pool will be expected to be done using the regular &amp;quot;mount&amp;quot; and &amp;quot;umount&amp;quot; commands:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=legacy zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Later in the wiki, it is shown how to mount using &amp;quot;zfs mount&amp;quot; for mountpoint=none, and regular &amp;quot;mount&amp;quot; for mountpoint=legacy. Using mountpoint=legacy is probably the preferred setting for the zfs-root because you can use the normal mount and umount commands and do not have to change slackware /etc/rc.d/* scripts much, if any. The normal slackware scripts handle a root filesystem's mounting and remounting using the normal mount command.&lt;br /&gt;
&lt;br /&gt;
On creation, the zpool zfs-root is &amp;quot;imported&amp;quot; and has a zpool status that can be viewed:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool status zfs-root&lt;br /&gt;
&lt;br /&gt;
zpool export zfs-root&lt;br /&gt;
zpool status zfs-root&lt;br /&gt;
# Now there is no status.&lt;br /&gt;
&lt;br /&gt;
zpool import zfs-root&lt;br /&gt;
# Now it is back.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
When a zpool is imported, it has it's current configuration cached in a file /etc/zfs/zpool.cache. When a zpool is exported, then it's entries in the cache file are removed and the cache file is deleted if it becomes empty. So long as the zfs kernel modules see this cache file and valid cache data inside it, ZFS considers the described zpools in the cache file to be valid as imported zpools. If the zpool.cache file is present at the time the zfs modules are loaded, then there is no further need to use the import and export zpool commands at system startup and shutdown. With root on a zfs, it is not possible to export the pool that root is on, but this is not a problem. At shutdown, the safe procedure will be to set the zfs-root property readonly=on or remount read-only and sync disks.&lt;br /&gt;
&lt;br /&gt;
To avoid the requirement to import the zfs-root pool at startup, you can keep a copy of the zpool.cache file to later copy onto the initrd image to read at modules load time to have the pool reactivated without need to issue the zpool import command:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/zfs/zpool.cache /etc/zfs/zpool.cache-initrd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
A warning about the zpool.cache file: Having /etc/zfs/zpool.cache present at zfs module load or module init time can be unsafe if the device names in /dev have changed since the last boot. Especially dangerous is if two hard drives have swapped names, like /dev/sda and /dev/sdb have swapped names. It is safer to not have a zpool.cache file on the system at boot and zfs module load/init time to guard against the possibility that the cache file is no longer correct. This wiki will try to show how you can use zpool.cache to import your pool if the regular zpool import command seems to always require you to force it. This wiki will also show how to not need a zpool.cache file to import normally.&lt;br /&gt;
&lt;br /&gt;
A zfs filesystem will not normally allow you to mount over any files. The mountpoint is expected to be an empty directory. Remove any junk files inside the installer's /mnt because zfs won't mount over any files:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rm /mnt/README&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The directory /mnt is where the slackware setup expects you to mount your root for installation.&lt;br /&gt;
&lt;br /&gt;
Controlling whether a zfs fs is to be mounted read-only or read-write is best managed by setting the readonly property while it is not yet mounted:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set readonly=on zfs-root&lt;br /&gt;
zfs set readonly=off zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If you are using &amp;lt;code&amp;gt;mountpoint=legacy&amp;lt;/code&amp;gt; then the options for the mount command for ro or rw mounting will work as normal also and override whatever the readonly property is set to. The readonly property does serve as a default.&lt;br /&gt;
&lt;br /&gt;
Slackware expects root to be mounted readonly when /etc/rc.d/rc.S runs during normal startup, so later this is used to satisfy slackware's expectation to avoid rc.S complaining.&lt;br /&gt;
&lt;br /&gt;
The zfs-root can be mounted and unmounted in two different ways:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=/mnt zfs-root&lt;br /&gt;
zfs set mountpoint=none zfs-root&lt;br /&gt;
# or&lt;br /&gt;
mount zfs-root -t zfs /mnt&lt;br /&gt;
umount /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If it is already mounted and you want to change it to mount somewhere else, it is best to transition it to unmounted first, then mount it in the new place.&lt;br /&gt;
&lt;br /&gt;
The mount options &amp;lt;code&amp;gt;-o ro, -o rw, -o remount,ro, and -o remount,rw &amp;lt;/code&amp;gt; can also be used and will override the &amp;lt;code&amp;gt;readonly=on|off&amp;lt;/code&amp;gt; property without altering the property value. This can be confusing until you are familiar with how the two methods of mounting interact. When &amp;lt;code&amp;gt;mountpoint=legacy&amp;lt;/code&amp;gt; is set, zfs expects the regular mount and umount commands to be used to mount and unmount the dataset with the assistance of the mount.zfs helper. For now, we will continue with &amp;lt;code&amp;gt;mountpoint=none&amp;lt;/code&amp;gt;, but using legacy is also a good option.&lt;br /&gt;
&lt;br /&gt;
Now, let's continue some, and mount to /mnt using the current &amp;lt;code&amp;gt;readonly=off&amp;lt;/code&amp;gt; setting (rw mount):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=/mnt zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method of mounting will show the most detailed mount options in /etc/mtab. They are the mount options that zfs thinks are proper, and they are probably what should be kept in /etc/fstab for zfs-root until we know better.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cat /etc/mtab &amp;gt;&amp;gt; /etc/fstab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now edit /etc/fstab to make sure it looks right, and remove the &amp;quot;rw&amp;quot; mount option, because we want to let it use a default for that, which will come from how we set the readonly= property most of the time. Unmount again:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=none zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mount again, now using all options from /etc/fstab:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It should be mounted at /mnt, and touch /mnt/t should allow you to make the file t. Then rm it: rm /mnt/t&lt;br /&gt;
For installation, we want to make sure it is mounted read-write. After installation, it should mount readonly inside the initrd.&lt;br /&gt;
&lt;br /&gt;
Sometimes there can be problems using the mount command, and then you can try it with the -i option:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 mount -i zfs-root&lt;br /&gt;
 mount -i zfs-root -t zfs /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
but, you should not have to use -i. When using -i makes it work, it performs an &amp;quot;internal-only&amp;quot; mount and does not use any mount.&amp;lt;fstype&amp;gt; helper scripts that might be on the system. You can use &amp;lt;code&amp;gt;mountpoint=legacy&amp;quot;&amp;lt;/code&amp;gt; to avoid this small problem if you are preferring to use the regular mount and umount commands on your zfs-root.&lt;br /&gt;
&lt;br /&gt;
Setup the /boot device:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkfs.ext4 /dev/sda1&lt;br /&gt;
mkdir /mnt/boot&lt;br /&gt;
mount /dev/sda1 /mnt/boot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We have both root and boot mounted where the slackware installer expects them. Unmount the dvd so setup can find it normally:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
umount /dev/sr0&lt;br /&gt;
setup&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the setup, skip straight to TARGET selection for the root device, but the setup doesn't see or understand the zfs-root, so it is not listed. This does not matter because we have mounted it already. Just skip down to a slot that say to continue, and continue on with setup. Because TARGET is skipped, you may not see the ADDITIONAL prompt (or if so, skip it too) where normally you give /dev/sda1 and have it mounted as /boot. This is also okay because we have mounted /mnt/boot already.&lt;br /&gt;
Because we did not give TARGET the root device or say what device /boot is on, the lilo installation will fail, or you can skip it. Otherwise, this installation process is normal.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Finish installation and exit setup, but do NOT reboot!&lt;br /&gt;
# There is still a lot to do before rebooting.&lt;br /&gt;
umount /dev/sr0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point, it is assumed that the setup has completed installing into /mnt. Congrats! You've installed slackware into a ZFS root!&lt;br /&gt;
&lt;br /&gt;
The next steps are to prepare to use &amp;quot;chroot /mnt&amp;quot; and finish up the configuration on the installed root system and then be able to reboot onto the completed installation. Before doing chroot, copy some files from the setup environment into /mnt.&lt;br /&gt;
&lt;br /&gt;
Copy the current installer /etc/fstab for later use inside the initrd. This fstab is what is proper inside the initrd, except remove option &amp;quot;rw&amp;quot; (if not done already).&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/fstab /mnt/etc/fstab.initrd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The fstab.initrd will look like:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 proc /proc proc defaults 0 0&lt;br /&gt;
 zfs-root /mnt zfs defaults,atime,dev,exec,suid,xattr,nomand,zfsutil 0 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the initrd, we want zfs-root to mount to /mnt.&lt;br /&gt;
&lt;br /&gt;
Create /mnt/etc/fstab:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cat /etc/mtab &amp;gt;&amp;gt; /mnt/etc/fstab&lt;br /&gt;
vi /mnt/etc/fstab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using vi started above, edit /mnt/etc/fstab and make it have lines such as:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 zfs-root / zfs defaults,atime,dev,exec,suid,xattr,nomand,zfsutil 0 0&lt;br /&gt;
 /dev/sda1 /boot ext4 defaults 0 2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
These two lines in &amp;lt;code&amp;gt;/mnt/etc/fstab&amp;lt;/code&amp;gt; are how the mounts should be looking when root is booted. Although the fstab option for fs_passno is 0 and indicates that root (/) should not be fsck, this fs_passno option in fstab is ignored during system startup for / in rc.S because rc.S explicity runs &amp;quot;fsck /&amp;quot; which does not look at options inside fstab. Fsck doesn't work on a zfs fs, and we will deal with that problem in a moment (see below).&lt;br /&gt;
&lt;br /&gt;
Mount some special mounts before chroot:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount -t devtmpfs none /mnt/dev&lt;br /&gt;
mount -t proc none /mnt/proc&lt;br /&gt;
mount -t sysfs none /mnt/sys&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Make sure /boot is mounted:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount /dev/sda1 /mnt/boot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you had mounted a 9p fs share to access spl and zfs packages, then unmount that now:&lt;br /&gt;
umount /packages&lt;br /&gt;
&lt;br /&gt;
Ready, now:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chroot /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point, you should be on the installed system, and now try to configure mkinitrd and lilo. First, switch to use the generic kernel:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /boot&lt;br /&gt;
rm System.map config vmlinuz&lt;br /&gt;
ln -s System.map-gen* System.map&lt;br /&gt;
ln -s config-gen* config&lt;br /&gt;
ln -s vmlinuz-gen* vmlinuz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We installed spl and zfs inside the live ramfs install-dvd environment, but not yet have we installed them into the root system:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount /dev/sr0 /mnt/cdrom&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /mnt/cdrom/addon/spl-*.txz&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /mnt/cdrom/addon/zfs-*.txz&lt;br /&gt;
depmod&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If instead, you used a 9p share to access the spl and zfs packages, then repeat that procedure here to install them onto the root system.&lt;br /&gt;
&lt;br /&gt;
Setup lilo: edit /etc/lilo.conf so it is like:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  lba32&lt;br /&gt;
  append = &amp;quot; vt.default_utf8=1&amp;quot;&lt;br /&gt;
  boot = /dev/sda&lt;br /&gt;
  message = /boot/boot_message.txt&lt;br /&gt;
  prompt&lt;br /&gt;
  timeout = 1200&lt;br /&gt;
  change-rules&lt;br /&gt;
   reset&lt;br /&gt;
  vga = normal&lt;br /&gt;
  image = /boot/vmlinuz&lt;br /&gt;
   label = vmlinuz&lt;br /&gt;
   initrd = /boot/initrd.gz&lt;br /&gt;
   root = /dev/ram0&lt;br /&gt;
   read-write&lt;br /&gt;
# alternatively, the root and read-write lines&lt;br /&gt;
# can be this one line of kernel parameters:&lt;br /&gt;
#  addappend = &amp;quot; root=/dev/ram0 rw &amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A note about initrd: The /boot/initrd.gz is a gzipped cpio archive containing a minimal BusyBox-based slackware root system that is sourced from /boot/initrd-tree. The commands &amp;quot;mkinitrd&amp;quot; and &amp;quot;mkinitrd -F&amp;quot; generates /boot/initrd-tree and /boot/initrd.gz. When using a initrd, the initial root device is normally set to root=/dev/ram0 (a ramfs block device) and allowed read-write. The kernel refers to devices in terms of &amp;quot;major&amp;quot; and &amp;quot;minor&amp;quot; numbers, and the ram0 device is assigned the block device major 1 and minor 0. This ram0 major/minor is written in hexadecimal as 0x0100 (256 in decimal). This hexademical number makes an appearance in /boot/initrd-tree/int where it runs: &amp;quot;echo 0x0100 &amp;gt; /proc/sys/kernel/real-root-dev&amp;quot;. Echoing a device code to real-root-dev is part of a deprecated initrd mechanism, but is probably harmless to leave alone as slackware has it unless you know otherwise. More information about how initrd works can be found in:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/usr/src/linux/Documentation/devices.txt (info about major:minor device numbers)&lt;br /&gt;
/usr/src/linux/Documentation/initrd.txt  (mostly obsolete info on old initrd)&lt;br /&gt;
/usr/src/linux/Documentation/filesystems/ramfs-rootfs-initramfs.txt (current info on new initrd, called initramfs)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Advanced note about initrd: Slackware's mkinitrd package does not use the &amp;quot;pivot_root&amp;quot; command as documented in &amp;quot;initrd.txt&amp;quot;, but instead uses &amp;quot;switch_root&amp;quot; provided by a project called BusyBox. The switch_root command changes the effective root filesystem from the initrd (unpacked in rootfs at /) to the new root filesystem (zfs-root mounted at /mnt); it overmounts rootfs / with zfs-root /mnt. The switch_root works as follows: delete everything in rootfs / (one filesystem only) that held initrd to free up ram memory, then use mount, chroot, and chdir to make the effective root change. In concept (as a shell script), the command &amp;quot;exec switch_root /mnt $INIT $RUNLEVEL&amp;quot; is performed as follows:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 find / -xdev | xargs rm -rf&lt;br /&gt;
 cd &amp;quot;$1&amp;quot;&lt;br /&gt;
 shift&lt;br /&gt;
 mount --move . /&lt;br /&gt;
 exec chroot . &amp;quot;$@&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Here, typically INIT=/sbin/init RUNLEVEL=3. The 'exec' causes switch_root to take the place of the parent process having PID=1. In system calls, the switch_root looks similar to this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chdir(&amp;quot;/mnt&amp;quot;);&lt;br /&gt;
/* &amp;lt;insert code to unlink/rmdir all initrd files/directories&lt;br /&gt;
 *  installed in rootfs / without crossing filesystems &amp;gt; */&lt;br /&gt;
mount(&amp;quot;.&amp;quot;, &amp;quot;/&amp;quot;, NULL, MS_MOVE, NULL);&lt;br /&gt;
chroot(&amp;quot;.&amp;quot;);&lt;br /&gt;
chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
execl(&amp;quot;/sbin/init&amp;quot;, &amp;quot;3&amp;quot;, (char*) NULL );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The kernel's rootfs / that contained initrd is never actually unmounted (it can't be) because it is built into the kernel and always exists as at least a tiny ramfs or tmpfs, so you can continue to see it in /proc/mounts. When you give lilo root=/dev/ram0 (a ramfs device), the kernel will actually use the internal rootfs, which is an instance of a tmpfs (if your kernel config includes tmpfs) or ramfs. The rootfs that is a tmpfs can by default use up to half of system ram. If rootfs is a ramfs, it can use up to almost all of system ram until the system panics. Typically, tmpfs is built into the kernel, and so depending on how much ram your computer has, the initrd-tree can probably be up to about half that size.&lt;br /&gt;
&lt;br /&gt;
Quite a lot of notes... now to continue on...&lt;br /&gt;
&lt;br /&gt;
Setup mkinitrd:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/mkinitrd.conf.sample /etc/mkinitrd.conf&lt;br /&gt;
vi /etc/mkinitrd.conf&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Edit it to look like this (other defaults should be ok):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 MODULE_LIST=&amp;quot;sym53c8xx:ext4:e1000:zfs:9p:9pnet_virtio&amp;quot;&lt;br /&gt;
 ROOTDEV=&amp;quot;zfs-root&amp;quot;&lt;br /&gt;
 ROOTFS=&amp;quot;zfs&amp;quot;&lt;br /&gt;
#Module sym53c8xx is the driver for qemu's if=scsi drive device.&lt;br /&gt;
#Module ext4 for /boot.&lt;br /&gt;
#Module e1000 for eth0 net device.&lt;br /&gt;
#Module zfs for ZFSonLinux.&lt;br /&gt;
#Modules 9p and 9pnet_virtio for mounting qemu -virtfs mount_tag.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These 9p modules could be useful from the rescue command line inside the initrd to get needed files that are on the host.&lt;br /&gt;
&lt;br /&gt;
All dependent modules will also be included automatically into /boot/initrd-tree, which is packaged as /boot/initrd.gz. For example, to see the dependent modules of zfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
modprobe --show-depends zfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All listed modules will also be in the initrd. Now, make a /boot/initrd-tree that we can begin to look at and edit:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkinitrd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create an empty /etc/mtab or else zpool import fails (zfs expects /etc/mtab to exists already, it won't make it):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
touch /boot/initrd-tree/etc/mtab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Copy in the fstab.initrd that was made earlier while on the installer. This provides all the mount options for a simple &amp;quot;mount zfs-root&amp;quot; onto /mnt:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/fstab.initrd /boot/initrd-tree/etc/fstab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More package installing! This time into an alternate root, the root of the initrd, /boot/initrd-tree. This is how you can put whatever packages you like into your initrd. These installations work independent of your normal installations. You can install, upgrade, and remove packages using an altroot:&lt;br /&gt;
&lt;br /&gt;
If spl and zfs are on your customized dvd:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/addon/spl-*.txz&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/addon/zfs-*.txz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Otherwise, repeat same procedure but you mount your 9p mount_tag and get them installed.&lt;br /&gt;
&lt;br /&gt;
More regular packages from the dvd:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/kmod-*.txz&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/coreutils-*.txz&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/gptfdisk-*.txz&lt;br /&gt;
&lt;br /&gt;
# A bash script is in /boot/initrd-tree/lib/udev/, so we need it or udev rules have problems:&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/bash-*.txz&lt;br /&gt;
# Bash needs this:&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/l/libtermcap-*.txz&lt;br /&gt;
&lt;br /&gt;
# Install net-tools to ensure that /etc/HOSTNAME, /etc/hosts, and potentially, /etc/hostid are handled proper.&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/n/net-tools-*.txz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When ZFS has to import a zpool while the initrd is running (this can be avoided by not exporting and keeping /etc/zfs/zpool.cache inside the initrd), ZFS will refuse to import a pool if it thinks that the pool may be in use by another system. ZFS was designed for network attached storage (NAS) where multiple hosts might have access to the same disks but ZFS cannot support two hosts importing and using a ZFS pool at the same time (that requires a &amp;quot;cluster&amp;quot; fs). ZFS checks a value called &amp;quot;hostid&amp;quot; to determine this kind of conflict, and it can be a tricky issue with an initrd boot process. The value of hostid is returned by the gethostid() function or the hostid command. This function will return the hostid from /etc/hostid if that file exists and has a valid id in it, or else if the file doesn't exist it obtains a hostid number based on the hostname and ip address assigned to hostname found in /etc/hosts or in DNS. If the hostid trying to import a pool is not the same as the hostid that imported it last time, ZFS will not import the pool unless &amp;quot;zpool import -f zfs-root&amp;quot; is used to force the import. This force option is not recommended to use, so it is best to configure your initrd with matching /etc/HOSTNAME and /etc/hosts as on the root installation and ensure what your system looks like on the initrd matches the booted root system. The hostid can also be passed to the SPL module with the module parameter &amp;lt;code&amp;gt;spl.spl_hostid=0xHHHHHHHH&amp;lt;/code&amp;gt; where the Hs are a hexadecimal hostid value and this overrides any /etc/hostid or hostname/IP-based hostid value.&lt;br /&gt;
&lt;br /&gt;
Edit /boot/initrd-tree/init (this is the main system startup script on the initrd, responsible for configuring your block devices, mounting root at /mnt, and booting root):&lt;br /&gt;
&lt;br /&gt;
Inside init, right near the top of the file after the PATH= line, add this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/bin/hostname -F /etc/HOSTNAME&lt;br /&gt;
/bin/hostname $( /bin/hostname -s )&lt;br /&gt;
#/sbin/chhostid 13371400&lt;br /&gt;
# you can make your hostid whatever, but this didn't work right with ZFS, so it is commented out&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This sets the name reported by the hostname command (the default is &amp;quot;darkstar&amp;quot;) to be what is contained in /etc/HOSTNAME. The hostname is modified in the next line to be the short hostname. These lines will help ZFS to properly identify your host when importing pools.&lt;br /&gt;
&lt;br /&gt;
Inside init, right after it runs &amp;quot;mdadm&amp;quot; commands as used for raid setup, we like it to setup ZFS, so add:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/sbin/zpool import zfs-root&lt;br /&gt;
/sbin/zfs set readonly=on zfs-root&lt;br /&gt;
mount zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
We want to make sure the default is to mount readonly, then it mounts using defaults from /etc/fstab inside the initrd.&lt;br /&gt;
&lt;br /&gt;
Inside init, close to the bottom, where it &amp;quot;Switch to real root partition&amp;quot;, comment out 1 line that normally does the mount:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# mount -o ro -t $ROOTFS $ROOTDEV /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
We have already mounted zfs-root, and we don't want to use any mount options because we should be using a properly set /etc/fstab inside the initrd for the zfs-root mount options onto /mnt.&lt;br /&gt;
&lt;br /&gt;
During a normal startup we want a readonly mount.&lt;br /&gt;
&lt;br /&gt;
Note: we are going to setup with using &amp;quot;zpool import&amp;quot; and &amp;quot;zpool export&amp;quot; commands at startup and shutdown. But later, you can experiment having /etc/zfs/zpool.cache stored in the initrd and commenting out the zpool import/export lines. Using zpool import/export is safer than using a zpool.cache, so we try to setup that way preferably.&lt;br /&gt;
&lt;br /&gt;
As mentioned, the zpool import command may sometimes fail, and give the message: &amp;quot;pool may be in use from another system&amp;quot;. This is nothing serious in this test situation. When this happens, zfs-root will not get mounted to /mnt and the init script will detect this and drop you into a rescue command line where you may manually do:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool import -f zfs-root&lt;br /&gt;
mount zfs-root&lt;br /&gt;
exit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This will force import, overriding the conflict that zfs thinks may be happening. Next is mount. After this, exit to let the init script continue on to boot the system normally.&lt;br /&gt;
&lt;br /&gt;
To avoid this problem we copy some files in (assuming you first edit /etc/HOSTNAME to hold the hostname you like to see on your command prompts, and edited /etc/hosts to have hostname on your loopback or other local ip address):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/HOSTNAME /etc/hosts /boot/initrd-tree/etc&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The value reported by the hostid command is what ZFS sees as your hostid (the SPL module actually tries to run the hostid command to get this value or it uses the spl.spl_hostid value that is given to it). In this setup so far, the value is based on the ip assigned to your hostname. If your hostname is on the line in /etc/hosts for ip address 192.168.13.37, then your hostid will be hex numbers C0.A8.0D.25 rearranged as A8C0250D (pairs of bytes are swapped). This is a ip-based hostid value, a 32bit hexadecimal number. The hostid has to be the same each boot or import will need a -f option to force it. Simply setting the hostid using the function sethostid() which writes a /etc/hostid file doesn't seem to agree with ZFS and you'd have to force the import, so this setup now assumes that you do not have or have deleted /etc/hostid.&lt;br /&gt;
&lt;br /&gt;
You can sometimes see what has been happening to a zpool by using the command &amp;quot;zpool history -li zfs-root&amp;quot; to see a log of commands.&lt;br /&gt;
&lt;br /&gt;
Once again, you can do away with the import and export commands by trying to have /etc/zfs/zpool.cache inside your initrd. To create zpool.cache, while on the installer or in the rescue shell of the initrd (at lilo &amp;quot;boot: vmlinuz rescue&amp;quot;):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on installer or initrd rescue shell)&lt;br /&gt;
zpool import zfs-root&lt;br /&gt;
zfs set readonly=off zfs-root&lt;br /&gt;
mount zfs-root&lt;br /&gt;
cp /etc/zfs/zpool.cache /mnt/etc/zfs/zpool.cache-initrd&lt;br /&gt;
cp /mnt/etc/zfs/zpool.cache-initrd /mnt/boot/initrd-tree/etc/zfs/zpool.cache&lt;br /&gt;
umount /mnt&lt;br /&gt;
zfs set readonly=on zfs-root&lt;br /&gt;
#mount zfs-root&lt;br /&gt;
#exit (to continue boot process onto rootfs mounted at /mnt)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Words of caution, again: Doing this zpool.cache approach is not necessary, and some talk suggests this is deprecated or discouraged. Although /etc/hostid setup fails to import without -f option, ip-based (hosts|dns) hostid works on booting and import works without -f option and may be the more proper way to do shutdown and startup rather than using a cache file which could become invalid and cause a problem that is difficult to understand. The contents and exact function of the cache file are not well understood by many people. As will be spammed all over this wiki, using zpool.cache is not recommended if you can avoid it because it is potentially unsafe for your pool.&lt;br /&gt;
&lt;br /&gt;
Save /boot/initrd-tree/init and quit vi.&lt;br /&gt;
&lt;br /&gt;
Now, edit /etc/rc.d/rc.S and rc.6 to understand how to remount rw or ro as readonly property changes:&lt;br /&gt;
&lt;br /&gt;
In /etc/rc.d/rc.S:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# comment out the line&lt;br /&gt;
#    /sbin/mount -w -v -n -o remount /&lt;br /&gt;
#add the line&lt;br /&gt;
     /sbin/zfs set readonly=off zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If you are using &amp;lt;code&amp;gt;mountpoint=legacy&amp;lt;/code&amp;gt; for zfs-root, you do not need to make the above change.&lt;br /&gt;
&lt;br /&gt;
In /etc/rc.d/rc.6:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# before: echo &amp;quot;Unmounting local file systems.&amp;quot;&lt;br /&gt;
# add lines:&lt;br /&gt;
  rm -f /etc/zfs/zpool.cache&lt;br /&gt;
  echo &amp;quot;Removed /etc/zfs/zpool.cache&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Remove /etc/zfs/zpool.cache on shutdown. This is recommended because if it is present when you import a pool, it might use this old cache to determine the device filenames in the pool, which may have changed filenames since the last boot, especially the non-persistent /dev/sd* device filenames. It is safest to avoid any usage of the zpool.cache file at boot in initramfs, zfs module load, and at zpool import of other pools.&lt;br /&gt;
&lt;br /&gt;
In /etc/rc.d/rc.6:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# comment out the line:&lt;br /&gt;
#    /bin/mount -v -n -o remount,ro /&lt;br /&gt;
# add the line:&lt;br /&gt;
     /sbin/zfs set readonly=on zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If you are using &amp;lt;code&amp;gt;mountpoint=legacy&amp;lt;/code&amp;gt; for zfs-root, you do not need to make the above change.&lt;br /&gt;
&lt;br /&gt;
In /etc/rc.d/rc.6, near the bottom just before poweroff|reboot, add the following block of lines:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
########################&lt;br /&gt;
# Try to export zfs-root&lt;br /&gt;
/sbin/zpool export zfs-root&lt;br /&gt;
if [ $? -gt 0 ] ; then&lt;br /&gt;
 echo &amp;quot;ZFS export failed.&amp;quot;&lt;br /&gt;
 echo &amp;quot;Notice: if root fs is busy, then this is normal fail.&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;ZFS export successful.&amp;quot;&lt;br /&gt;
 echo &amp;quot;Warning: successful export is abnormal for root fs.&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
/bin/sleep 5&lt;br /&gt;
########################&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This attempts to export even though it cannot return success for the root pool. The attempt is still recorded in the zpool history, and even though it fails the pool may actually be marked as exported (not sure).&lt;br /&gt;
&lt;br /&gt;
For ZFS, you cannot run fsck on it. It doesn't support that kind of filesystem check. The rc.S script will complain a lot in many places about not being able to run fsck on the zfs-root. To disable all attempts to run fsck, we can simply create a file that acts as a flag in /etc/rc.d/rc.S to tell it to skip fsck:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
touch /etc/fastboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This fastboot file is normally a run-once temporary file, and it is deleted near the bottom inside rc.S. Edit rc.S and stop it from deleting /etc/fastboot. We would like it to always skip all fsck. Edit /etc/rc.d/rc.S, and find the &amp;quot;rm&amp;quot; of fastboot, and do not have it removed!&lt;br /&gt;
&lt;br /&gt;
An alternative to using /etc/fastboot is to make the file &amp;lt;code&amp;gt;/sbin/fsck.zfs&amp;lt;/code&amp;gt; that always just &amp;quot;does nothing successfully&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
exec /bin/true&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Or, it can be:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Or, just do:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ln -s /bin/true /sbin/fsck.zfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This fsck helper has the advantage that you do not need to alter &amp;lt;code&amp;gt;rc.S&amp;lt;/code&amp;gt; as much, or at all if you use zfs property &amp;lt;code&amp;gt;mountpoint=legacy&amp;lt;/code&amp;gt; and the regular &amp;lt;code&amp;gt;mount&amp;lt;/code&amp;gt; command on your zfs-root. With these ideas, no slackware /etc/rc.d/* files really need editing, but it is up to you how you want to experiment. I prefer to use &amp;lt;code&amp;gt;mountpoint=legacy&amp;lt;/code&amp;gt; and edit just the initrd init script as above, and edit rc.6 to remove /etc/zfs/zpool.cache and try to export.&lt;br /&gt;
&lt;br /&gt;
We are getting close, and have finished all editing, so make /boot/initrd.gz and install lilo:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkinitrd -F&lt;br /&gt;
lilo&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We finished! All that's left to do is clean up.&lt;br /&gt;
&lt;br /&gt;
Exit the chroot.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
exit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Try to umount everything:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
umount /mnt/proc&lt;br /&gt;
umount /mnt/sys&lt;br /&gt;
umount /mnt/dev&lt;br /&gt;
umount /mnt/boot&lt;br /&gt;
umount /mnt/mnt/cdrom&lt;br /&gt;
umount /mnt/root/packages&lt;br /&gt;
umount /mnt&lt;br /&gt;
zpool export zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note, that export stops a pool and frees devices, while import binds devices and starts a pool. It is somewhat like mdadm -A -s and mdadm -S -s, while /etc/zfs/zpool.cache might be somewhat like mdadm -E -s &amp;gt; /etc/mdadm.conf.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Remove the DVD or change boot order&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When you reboot, if all is good, you are booting properly onto a slackware installed on a ZFS root! Congrats!&lt;br /&gt;
&lt;br /&gt;
If this seems to go badly, and this might happen if the import fails as explained some before, then you will be on the initrd's rescue command line just before the part in init where it wants to mount zfs-root and switch_root to boot up. In this case, you typically got commands like these to do:&lt;br /&gt;
&lt;br /&gt;
If you get dumped to rescue because zpool import will not work and requires -f (force), then:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 zpool import -f zfs-root&lt;br /&gt;
 zpool export    zfs-root&lt;br /&gt;
 zpool import    zfs-root&lt;br /&gt;
 mount zfs-root&lt;br /&gt;
 exit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This can happen if hostname, hostid, or uname changes.&lt;br /&gt;
&lt;br /&gt;
If you get into a jam and need to boot into the initrd and skip zpool import etc, use the lilo prompt (or, boot the install-dvd):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
boot: vmlinuz rescue&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the rescue mode of the initrd, after you have mounted your zfs-root as readonly=on to /mnt, then &amp;quot;exit&amp;quot; to continue booting.&lt;br /&gt;
&lt;br /&gt;
In other emergency command lines, you might need to run the lines at the end of init starting from: &amp;lt;code&amp;gt;udevadm info --cleanup-db; udevadm control --exit&amp;lt;/code&amp;gt;&lt;br /&gt;
If you don't run those udevadm commands, two runs of udevd fight each other and it is slow; you have to wait 2 minutes twice for timeouts (4 minutes).&lt;br /&gt;
The last line in init is run like: &amp;lt;code&amp;gt;exec switch_root /mnt /sbin/init 1&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Warning: the switch_root command is kind of dangerous, so read the manual page about it. From what I can tell, everything except the new root &amp;quot;/mnt&amp;quot; is deleted, so you are giving a command that says what NOT to delete! Make sure nothing got mounted outside of &amp;quot;/mnt&amp;quot; before you run it. However, the deletes should not cross filesystems, but only delete the contents of initramfs.&lt;br /&gt;
&lt;br /&gt;
Also, in rescue command line or anytime you have finished making changes and are about to reboot in some abnormal situation, first run:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set readonly=on zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A bug in unpatched grep 2.13 build 1, found slackware 14.0rc1, causes problems when processing files stored on ZFS but rarely shows problems on other filesystems; the bug does not handle sparse files on zfs and btrfs correctly and results in chaos with slackpkg, compiling kernel modules, and possibly many other things. You must downgrade grep to 2.12 or use the patched grep 2.13 build 2 in slackware 14.0rc2 or later.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
Upgrading:&lt;br /&gt;
&lt;br /&gt;
From time to time you will want to upgrade the kernel to the new kernel in slackware64-current or in patches/. This will also necessitate a rebuild and reinstall or upgrade of spl and zfs. Below is an example of when both kernel and spl/zfs are being upgraded, to give an idea of the process:&lt;br /&gt;
&lt;br /&gt;
Using slackpkg, that is configured to use your local slackware mirror is a good option but you can also configure it to use a remote mirror.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slackpkg upgrade-all&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Assume slackpkg just upgraded your kernel, kernel-modules, kernel-headers, and kernel-source.&lt;br /&gt;
&lt;br /&gt;
Note: the first time you try to run on kernel-generic, setup kernel-huge in lilo as 2nd choice. Huge has all the hard drive controllers builtin, but generic has them all as modules. For example, run &amp;quot;modinfo mptsas&amp;quot; to see module options (maybe you have a LSISAS1068) for your hard drive controller. Add file /etc/modprobe.d/mptsas.conf to set options you want with a line: options mptsas ... Do this for all the device driver modules for your hardware. Do this setup while you are on the huge kernel, then setup to reboot to generic. Include all these modules you need into mkinitrd.conf MODULES_LIST. Check that /boot/initrd-tree/etc/modprobe.d/ has a copy of your customized module conf files because it is on the initrd where the modules will load and use the conf files. mkinitrd probably copies all /etc/modprobe.d/* files into the initrd-tree, but check it. Pay attention to /etc/modprobe.d/README and /lib/modprobe.d/* /lib/modprobe.d/* maybe not copied to initrd-tree but you might want to copy some of it into your initrd-tree yourself to use them.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Check that upgraded kernel-source is symlinked to /usr/src/linux (zfs build looks here). SPL/ZFS modules will install to the kernel version in /lib/modules/&amp;lt;/usr/src/linux kernel version&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /usr/local/src&lt;br /&gt;
tar xvzf ~/spl-*.tar.gz&lt;br /&gt;
tar xvzf ~/zfs-*.tar.gz&lt;br /&gt;
&lt;br /&gt;
###### upgrade spl 1st&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-*&lt;br /&gt;
./configure --prefix=/ --libexecdir=/usr/libexec --libdir=/lib64 --includedir=/usr/include --datarootdir=/usr/share&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=/usr/local/src/install&lt;br /&gt;
cd ../install&lt;br /&gt;
makepkg ../spl-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
upgradepkg spl-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
depmod &amp;lt;new kernel version&amp;gt;     (e.g. depmod 3.2.27, if .27 is new kernel upgrade; you currently run on old, maybe .26)&lt;br /&gt;
# this builds the module dependencies in /lib/modules/&amp;lt;new kernel version&amp;gt;&lt;br /&gt;
###### upgrade zfs 2nd&lt;br /&gt;
mkdir install&lt;br /&gt;
cd zfs-*&lt;br /&gt;
./configure --prefix=/ --libexecdir=/usr/libexec --libdir=/lib64 --includedir=/usr/include --datarootdir=/usr/share&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=/usr/local/src/install&lt;br /&gt;
cd ../install&lt;br /&gt;
makepkg ../zfs-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
upgradepkg zfs-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
depmod 3.2.27&lt;br /&gt;
####### upgrade spl/zfs inside altroot /boot/initrd-tree&lt;br /&gt;
ROOT=/boot/initrd-tree upgradepkg spl-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
ROOT=/boot/initrd-tree upgradepkg zfs-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
# note: ROOT is an environment variable, not a command line option to upgradepkg!&lt;br /&gt;
# note: do not worry about depmod inside initrd-tree, mkinitrd -F actually installs the modules&lt;br /&gt;
# note: this upgrade here is really to just upgrade the command line tools zpool, zfs etc&lt;br /&gt;
####### rebuild /boot/initrd.gz and reinstall lilo&lt;br /&gt;
vi /etc/mkinitrd.conf&lt;br /&gt;
# temporarily set KERNEL_VERSION to new version, but you are still running on old version&lt;br /&gt;
mkinitrd -F&lt;br /&gt;
lilo&lt;br /&gt;
vi /etc/mkinitrd.conf&lt;br /&gt;
# you can set KERNEL_VERSION back to $(uname -r) now&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After reboot you can remove any old /lib/modules/&amp;lt;old kernel version&amp;gt; directory.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
More about /etc/hostid. If you want to experiment changing your /etc/hostid file and seeing if you can use it and make zpool import work normally, here is a tool that might be helpful:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/* software product name: foobarz-chhostid.c&lt;br /&gt;
 * suggested binary name: chhostid&lt;br /&gt;
 * license              : BSD&lt;br /&gt;
 * license text:&lt;br /&gt;
Copyright (c) 2012, foobarz&lt;br /&gt;
All rights reserved.&lt;br /&gt;
&lt;br /&gt;
Redistribution and use in source and binary forms, with or without&lt;br /&gt;
modification, are permitted provided that the following conditions are met:&lt;br /&gt;
    * Redistributions of source code must retain the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer.&lt;br /&gt;
    * Redistributions in binary form must reproduce the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer in the&lt;br /&gt;
      documentation and/or other materials provided with the distribution.&lt;br /&gt;
    * Neither the name of the &amp;lt;organization&amp;gt; nor the&lt;br /&gt;
      names of its contributors may be used to endorse or promote products&lt;br /&gt;
      derived from this software without specific prior written permission.&lt;br /&gt;
&lt;br /&gt;
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &amp;quot;AS IS&amp;quot; AND&lt;br /&gt;
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED&lt;br /&gt;
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE&lt;br /&gt;
DISCLAIMED. IN NO EVENT SHALL &amp;lt;COPYRIGHT HOLDER&amp;gt; BE LIABLE FOR ANY&lt;br /&gt;
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES&lt;br /&gt;
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;&lt;br /&gt;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND&lt;br /&gt;
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT&lt;br /&gt;
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS&lt;br /&gt;
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#define FOOBARZ_CHHOSTID_VERSION &amp;quot;1.0.5&amp;quot;&lt;br /&gt;
#include &amp;lt;sys/socket.h&amp;gt;&lt;br /&gt;
#include &amp;lt;netinet/in.h&amp;gt;&lt;br /&gt;
#include &amp;lt;arpa/inet.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;endian.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sysexits.h&amp;gt;&lt;br /&gt;
/* note: if include stdlib then sethostid fails even with _BSD_SOURCE defined */&lt;br /&gt;
&lt;br /&gt;
long swapbytes(long abcd) {&lt;br /&gt;
  long badc;&lt;br /&gt;
  unsigned char addr_a;&lt;br /&gt;
  unsigned char addr_b;&lt;br /&gt;
  unsigned char addr_c;&lt;br /&gt;
  unsigned char addr_d;&lt;br /&gt;
  addr_a = (unsigned char) (abcd &amp;gt;&amp;gt; 24);&lt;br /&gt;
  addr_b = (unsigned char) (abcd &amp;gt;&amp;gt; 16);&lt;br /&gt;
  addr_c = (unsigned char) (abcd &amp;gt;&amp;gt;  8);&lt;br /&gt;
  addr_d = (unsigned char) (abcd);&lt;br /&gt;
  return badc = ( (addr_b &amp;lt;&amp;lt; 24) | (addr_a &amp;lt;&amp;lt; 16) | (addr_d &amp;lt;&amp;lt; 8) | addr_c );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[])&lt;br /&gt;
{&lt;br /&gt;
 long newhostid;&lt;br /&gt;
 struct in_addr addr;&lt;br /&gt;
 char* invalidchar;&lt;br /&gt;
&lt;br /&gt;
 /*********** check command line */&lt;br /&gt;
 if(!( ((argc==3) &amp;amp;&amp;amp; ( (strcmp(argv[1],&amp;quot;-h&amp;quot;)==0) ||&lt;br /&gt;
                       (strcmp(argv[1],&amp;quot;-i&amp;quot;)==0) ||&lt;br /&gt;
                       (strcmp(argv[1],&amp;quot;-l&amp;quot;)==0) )) ||&lt;br /&gt;
       ((argc==2) &amp;amp;&amp;amp; ( (strcmp(argv[1],&amp;quot;-s&amp;quot;)==0) ))&lt;br /&gt;
     )&lt;br /&gt;
   ) {&lt;br /&gt;
                 /*01234567890123456789012345678901234567890123456789012345678901234567890123456789*/&lt;br /&gt;
  fprintf(stderr, &amp;quot;foobarz-chhostid, version %s. License: BSD.\n&amp;quot;, FOOBARZ_CHHOSTID_VERSION);&lt;br /&gt;
  fprintf(stderr, &amp;quot;foobarz-chhostid, (c) 2012, foobarz; all rights reserved.\n&amp;quot;);&lt;br /&gt;
  fprintf(stderr, &amp;quot;descr: %s change system hostid (in /etc/hostid).\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -h &amp;lt;new hostid&amp;gt;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        Change system hostid to &amp;lt;new hostid&amp;gt;;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        &amp;lt;new hostid&amp;gt; must be 32bit 8-digit hex number xxxxxxxx, each x in 0-f|F.\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        The ip corresponding to &amp;lt;new hostid&amp;gt; is also listed for reference only.\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -i &amp;lt;dotted ip address&amp;gt;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        Change system hostid to hostid corresponding to &amp;lt;dotted ip address&amp;gt;.\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -l &amp;lt;dotted ip address&amp;gt;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        List hostid corresponding to &amp;lt;dotted ip address&amp;gt;;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        no change to system hostid.\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -s\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        List current system hostid and corresponding ip address;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        no change to system hostid.\n&amp;quot;, argv[0]);&lt;br /&gt;
  return EX_USAGE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -h &amp;lt;hostid&amp;gt; */&lt;br /&gt;
 if( strcmp(argv[1],&amp;quot;-h&amp;quot;) == 0 ) {&lt;br /&gt;
  if(strlen(argv[2]) != 8) { fprintf(stderr, &amp;quot;new hostid must be 8-digit hex number xxxxxxxx, each x in 0-f|F\n&amp;quot;); return EX_USAGE; }&lt;br /&gt;
&lt;br /&gt;
  newhostid = strtol(argv[2],&amp;amp;invalidchar,16);&lt;br /&gt;
  if( newhostid==LONG_MIN ) { perror(&amp;quot;strtol (underflow)&amp;quot;); return EX_USAGE; }&lt;br /&gt;
  if( newhostid==LONG_MAX ) { perror(&amp;quot;strtol (overflow)&amp;quot;); return EX_USAGE; }&lt;br /&gt;
  if(*invalidchar != '\0') { fprintf(stderr, &amp;quot;invalid hex number %c; must be in 0-f|F\n&amp;quot;, *invalidchar); return EX_USAGE; }&lt;br /&gt;
&lt;br /&gt;
  if( sethostid(newhostid) != 0 ) {&lt;br /&gt;
   perror(&amp;quot;sethostid&amp;quot;);&lt;br /&gt;
   if( errno == EPERM ) return EX_NOPERM;&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
  }&lt;br /&gt;
  printf(&amp;quot;System hostid changed.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  /* hostid is a byte-swapped ip like b.a.d.c */&lt;br /&gt;
  /* get ip by swapping to correct order a.b.c.d and save into in_addr struct */&lt;br /&gt;
  addr.s_addr = htonl(swapbytes(newhostid));&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -i or -l, then find hostid for &amp;lt;dotted ip address&amp;gt; */&lt;br /&gt;
 if( (strcmp(argv[1],&amp;quot;-i&amp;quot;) == 0) || (strcmp(argv[1],&amp;quot;-l&amp;quot;) == 0) ) {&lt;br /&gt;
  if( inet_aton(argv[2], &amp;amp;addr) == 0 ) { fprintf(stderr, &amp;quot;inet_aton: invalid dotted ip address: %s\n&amp;quot;, argv[2]); return EX_USAGE; }&lt;br /&gt;
&lt;br /&gt;
  /* hostid is a byte-swapped ip like b.a.d.c */&lt;br /&gt;
  /* get hostid by swapping bytes of ip a.b.c.d */&lt;br /&gt;
  newhostid = swapbytes(ntohl(addr.s_addr));&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -i &amp;lt;dotted ip address&amp;gt; */&lt;br /&gt;
 if( strcmp(argv[1],&amp;quot;-i&amp;quot;) == 0 ) {&lt;br /&gt;
  if( sethostid(newhostid) != 0 ) {&lt;br /&gt;
   perror(&amp;quot;sethostid&amp;quot;);&lt;br /&gt;
   if( errno == EPERM ) return EX_NOPERM;&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
  }&lt;br /&gt;
  printf(&amp;quot;System hostid changed.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -l &amp;lt;dotted ip address&amp;gt; */&lt;br /&gt;
 if(strcmp(argv[1],&amp;quot;-l&amp;quot;) == 0 ) {&lt;br /&gt;
   printf(&amp;quot;Listing hostid for ip. (no changes)\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -s */&lt;br /&gt;
 if(strcmp(argv[1],&amp;quot;-s&amp;quot;) == 0 ) {&lt;br /&gt;
   /* see if /etc/hostid exists and print info */&lt;br /&gt;
   if( access(&amp;quot;/etc/hostid&amp;quot;, F_OK) != 0 ) {&lt;br /&gt;
     printf(&amp;quot;Notice: /etc/hostid does not exist.\n&amp;quot;);&lt;br /&gt;
     perror(&amp;quot;Reason&amp;quot;);&lt;br /&gt;
     printf(&amp;quot;System hostid derived from ip of hostname found in hosts file or dns.\n&amp;quot;);&lt;br /&gt;
   } else {&lt;br /&gt;
     printf(&amp;quot;Notice: /etc/hostid exists.\n&amp;quot;&lt;br /&gt;
            &amp;quot;System hostid is obtained from hostid file.\n&amp;quot;);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
  errno=0;&lt;br /&gt;
  newhostid = gethostid();&lt;br /&gt;
  if(errno!=0) { perror(&amp;quot;gethostid&amp;quot;); return EX_UNAVAILABLE; }&lt;br /&gt;
&lt;br /&gt;
  /* hostid is a byte-swapped ip like b.a.d.c */&lt;br /&gt;
  /* get ip by swapping to correct order a.b.c.d and save into in_addr struct */&lt;br /&gt;
  addr.s_addr = htonl(swapbytes(newhostid));&lt;br /&gt;
&lt;br /&gt;
  printf(&amp;quot;Listing current system hostid. (no changes)\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** print info and return */&lt;br /&gt;
 printf(&amp;quot;ip dot: %s\n&amp;quot;, inet_ntoa(addr) );&lt;br /&gt;
 printf(&amp;quot;ip hex: %.8x\n&amp;quot;, ntohl(addr.s_addr) );&lt;br /&gt;
 printf(&amp;quot;hostid: %.8x\n&amp;quot;, newhostid );&lt;br /&gt;
 return EX_OK;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
----&lt;br /&gt;
Now available! &amp;quot;ZFS root (builtin)&amp;quot; wiki (aka &amp;quot;ZFS root, part II&amp;quot;):&lt;br /&gt;
http://slackwiki.com/ZFS_root_(builtin)&lt;br /&gt;
It is now possible to build the modules and a small initramfs into your kernel to have a fully-contained and bootable ZFS root kernel from a simple lilo entry. Good luck!&lt;/div&gt;</description>
			<pubDate>Sun, 16 Sep 2012 09:58:56 GMT</pubDate>
			<dc:creator>Foobarz</dc:creator>
			<comments>https://www.slackwiki.com/Talk:ZFS_root</comments>
		</item>
		<item>
			<title>ZFS root</title>
			<link>https://www.slackwiki.com/index.php?title=ZFS_root&amp;diff=795</link>
			<guid isPermaLink="false">https://www.slackwiki.com/index.php?title=ZFS_root&amp;diff=795</guid>
			<description>&lt;p&gt;Foobarz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Tutorials]]&lt;br /&gt;
If you have heard about the ZFS filesystem and you're curious to try it out, then you can try it on slackware64, thanks to the ZFSonLinux.org project!&lt;br /&gt;
&lt;br /&gt;
In this article, an example is shown of how to install slackware64 14.0 onto a ZFS root filesystem (zfs-root) inside a QEMU virtual machine for testing purposes. It is recommended that you install qemu and learn how to use it to test a ZFS installation before you decide to use it on real hardware. A slackbuild for qemu can be found on slackbuilds.org. If you have a processor that supports Intel VT-x or AMD AMD-V virtualization acceleration (try modprobe kvm-intel or modprobe kvm-amd), then use the slackbuild for qemu-kvm.&lt;br /&gt;
&lt;br /&gt;
This article isn't going to go into any detail on actually using ZFS or what kinds of installation options and settings might be optimal. This article just presents an example of how to get started with ZFS on slackware.&lt;br /&gt;
&lt;br /&gt;
At this time of writing, ZFSonLinux is at &amp;quot;release candidate&amp;quot; (version 0.6.0-rc10) development stage, and many issues can occur. See the ZFSonLinux.org web site and the issues tracker for an idea about the current issues. There is also an irc channel on irc.freenode.net, #zfsonlinux, for discussion of issues and help.&lt;br /&gt;
&lt;br /&gt;
Although not required, it is helpful to keep a local mirror of slackware64 on your system. Having a local mirror makes it easier to upgrade to slackware64-current or to patches/* in a release. To help manage your own local slackware mirror and generate your own CD and DVD slackware installers, see http://alien.slackbook.org/blog/local-slackware-mirror/.&lt;br /&gt;
&lt;br /&gt;
In this article, we use a slackware64-current DVD image file as the qemu cdrom device media for the installation of the slackware guest. This was tested at slackware64-current = slackware64 14.0rc2. You can obtain a slackware DVD image using a torrent, buy the DVD from slackware.com, or generate your own DVD image file using the mirror script. For an actual DVD, you can pass your DVD device (e.g., /dev/sr0) as the qemu cdrom device. For a DVD image file, pass the image file as the qemu cdrom device.&lt;br /&gt;
&lt;br /&gt;
The ZFSonLinux packages are not included in slackware at this time. There are two packages involved: spl and zfs. The first, spl, is &amp;quot;Solaris Porting Layer&amp;quot; and must be installed on the system before zfs can be compiled. The source code tarballs for these are at ZFSonLinux.org. At this time of writing, they are spl-0.6.0-rc10.tar.gz and zfs-0.6.0-rc10.tar.gz.&lt;br /&gt;
&lt;br /&gt;
At this point, it is assumed you have qemu installed, have obtained a slackware64-current/14.0 DVD, and have downloaded spl and zfs tarballs to your host system. The first step now is, if your host is not slackware64-current/14.0 (the same as the guest will be), then you need to create a minimal development slackware64 guest system in qemu for just the purpose of compiling and packaging the spl and zfs slackware packages and transferring a copy of these packages back onto your host system to use later to install onto zfs during the slackware install process.&lt;br /&gt;
&lt;br /&gt;
From this point onward, instructions become a bit terse and mostly limited to examples of the commands you might use to complete tasks. You are encouraged to examine what each command does by reading the command's man pages. For example, the command &amp;quot;man qemu&amp;quot; can show you most of what you need to know about running qemu on the command line.&lt;br /&gt;
&lt;br /&gt;
So, here's an example of how you might build the spl and zfs packages, starting in your home directory:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on host)&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir qemu&lt;br /&gt;
cd qemu&lt;br /&gt;
mkdir slackdevel&lt;br /&gt;
cd slackdevel&lt;br /&gt;
mkdir packages&lt;br /&gt;
cp ~/spl-*.tar.gz packages&lt;br /&gt;
cp ~/zfs-*.tar.gz packages&lt;br /&gt;
qemu-img create disk1.raw 10G&lt;br /&gt;
ln -s ~/slackware64-current-install-dvd.iso dvd.iso&lt;br /&gt;
qemu-kvm \&lt;br /&gt;
 -option-rom 8xx_64.rom,bootindex=1 \&lt;br /&gt;
 -no-quit \&lt;br /&gt;
 -no-shutdown \&lt;br /&gt;
 -boot order=cd,menu=on \&lt;br /&gt;
 -m 2G \&lt;br /&gt;
 -cpu host \&lt;br /&gt;
 -smp sockets=1,cores=4 \&lt;br /&gt;
 -net nic,model=e1000 -net user \&lt;br /&gt;
 -cdrom dvd.iso \&lt;br /&gt;
 -drive format=raw,media=disk,cache=none,aio=native,if=scsi,index=0,file=disk1.raw \&lt;br /&gt;
 -virtfs local,path=./packages/,security_model=none,mount_tag=hostpackages&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When you need to change boot to cd or disk, try changing &amp;quot;order=dc&amp;quot; or hitting F12 at boot prompt and select the CD/DVD boot option.&lt;br /&gt;
&lt;br /&gt;
Note: The support for booting drives using if=scsi is not included with current versions of qemu. Booting scsi requires the 8xx_64.rom option-rom, which can be downloaded at&lt;br /&gt;
[http://www.lsi.com/downloads/Public/Host%20Bus%20Adapters/Host%20Bus%20Adapters%20Common%20Files/lsi_bios.zip LSI.com]. Unzip it, and then:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp 8xx_64.rom /usr/share/qemu&lt;br /&gt;
# then run qemu-kvm with additional command line option: -option-rom 8xx_64.rom,bootindex=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Qemu should boot into the install-dvd, and now perform a very ordinary slackware64 install onto /dev/sda. Install d package set and most others, but package sets x, kde, xfce not really needed.&lt;br /&gt;
&lt;br /&gt;
First note: examples here use tools from the gptfdisk package (gdisk, sgdisk, cgdisk) to partition the disk with GUID partition table (GPT) format. GPT might not be too familiar to everyone, who mostly have only used MBR partitions with fdisk. In the slackware installations this author has tested in qemu, using GPT partitions has caused no problems with lilo or other tools used in slackware. GPT disk labels support creating up to 128 partitions and support disks larger than 2TB (the limit of MBR fdisk). LILO installs into the first 440 bytes on /dev/sda, inside a GPT &amp;quot;protective MBR&amp;quot; that serves to provide compatibility with MBR bootloaders like lilo. LILO uses LBA32 sector addressing and can see all 512-byte sectors inside the first 2TB of a disk. So long as the /boot partition is within the first 2TB of a disk, lilo can work on a disk larger than 2TB. Unlike the common default of fdisk to start the first partition at sector 63, which is not aligned with the 4KiB sector size of Advanced Format hard disks, gdisk's default is to start partitions at 2048 sector (1MiB) boundaries which are also 4KiB aligned. Using gdisk GPT works on all disks and is compatible with using Advanced Format hard disks larger than 2TB. More information about GPT disk label format can be found on wikipedia.org. For those that have used grub instead of lilo, grub installation is different with GPT than with MBR, and grub requires a GPT partition of type grub-bios or 0xEF02 &amp;quot;BIOS Boot Partition&amp;quot; of about 8MiB where it can install it's additional bootloader stages because grub cannot embed in sectors 1-62 on GPT where GPT keeps it's partition tables. On MBR, sectors 1-62 were normally reserved space for bootloaders to keep a 2nd stage.&lt;br /&gt;
&lt;br /&gt;
For this purpose of development guest, just create a simple 1-partition system, /dev/sda1, and do a simple slackware install on it. Don't bother with swap or separate /boot unless you want to:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on install-dvd)&lt;br /&gt;
cgdisk /dev/sda&lt;br /&gt;
setup&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When this simple development guest boots, login as root, and continue:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on qemu guest)&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir packages&lt;br /&gt;
mount hostpackages -t 9p -o trans=virtio packages&lt;br /&gt;
echo --prefix=/ --libexecdir=/usr/libexec --libdir=/lib64 --includedir=/usr/include --datarootdir=/usr/share &amp;gt; configure-options&lt;br /&gt;
mkdir src&lt;br /&gt;
cd src&lt;br /&gt;
&lt;br /&gt;
mkdir install&lt;br /&gt;
tar xvzf ~/packages/spl-*.tar.gz&lt;br /&gt;
cd spl-*&lt;br /&gt;
./configure $( cat ~/configure-options )&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../spl-&amp;lt;version&amp;gt;_&amp;lt;kernel_version&amp;gt;-x86_64-&amp;lt;build_id&amp;gt;.txz&lt;br /&gt;
(e.g., makepkg ../spl-0.6.0rc10_3.2.27-x86_64-1root.txz)&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
installpkg spl-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
cp spl-0.6.0rc10_3.2.27-x86_64-1root.txz ~/packages&lt;br /&gt;
&lt;br /&gt;
mkdir install&lt;br /&gt;
tar xvzf ~/packages/zfs-*.tar.gz&lt;br /&gt;
cd zfs-*&lt;br /&gt;
./configure $( cat ~/configure-options )&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../zfs-&amp;lt;version&amp;gt;_&amp;lt;kernel_version&amp;gt;-x86_64-&amp;lt;build_id&amp;gt;.txz&lt;br /&gt;
(e.g., makepkg ../zfs-0.6.0rc10_3.2.27-x86_64-1root.txz)&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
installpkg zfs-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
cp zfs-0.6.0rc10_3.2.27-x86_64-1root.txz ~/packages&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point spl and zfs packages are copied back to the host in the packages directory. Also, spl and zfs are installed in this simple development guest, so one could begin to experiment with zfs pools and datasets but while the root fs is whatever you made it during setup (probably the default, ext4). This development guest isn't really needed anymore, so it can be deleted:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
halt&lt;br /&gt;
(exit qemu: ctrl-alt-2 then enter quit at QEMU command prompt)&lt;br /&gt;
&lt;br /&gt;
(on host)&lt;br /&gt;
rm disk1.raw dvd.iso&lt;br /&gt;
mv packages ..&lt;br /&gt;
cd ..&lt;br /&gt;
rmdir slackdevel&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now that we have the spl and zfs packages on the host, it is possible to copy them into your local slackware64 mirror and then generate your own install DVD image that includes them. For example, change to the directory that contains the slackware README files, and create a &amp;quot;addon&amp;quot; directory and copy the spl and zfs slackware packages into there. Then, generate the DVD image using a command such as $( ./mirror-slackware-current.sh -i ) from where you have this script configured to maintain your local mirror. We can also just continue to access them inside the installer using qemu's virtfs option. When you are going to do a real installation onto real hardware, you need to generate and burn your own DVD that includes the packages.&lt;br /&gt;
&lt;br /&gt;
It is time to begin the installation of slackware64 on a ZFS root, assuming either you have regenerated dvd.iso with zfs packages in addon/* or we access the zfs packages while in the installer using qemu's virtfs to the host's packages directory. ZFS supports creating complex data storage configurations such as pools (similar to a volume group) backed by one or more of various kinds of virtual devices (similar to disks and raid arrays) and containing one or more datasets (similar to mounted filesystems, logical volume devices, or snapshots). But here, we keep it simple and will install on just a single disk device.&lt;br /&gt;
&lt;br /&gt;
Note: On a real ZFS installation, users will typically want to use the ZFS mirror or raidz virtual device (vdev) types for reliability against hard drive failures. For example, a good configuration might be to use a USB memory stick (and a backup stick) for /boot that is plugged into an on-motherboard &amp;quot;Type A&amp;quot; USB connector. Then, use four whole hard drives in a raidz2 vdev as the initial storage space in the root zpool. At a later time, to add more storage space, additional whole four-drive raidz2 vdevs of the same size could be added to the zpool. It is recommended to only add the same vdev type (disk, mirror, or raidz|1|2|3) and size to a zpool since zfs stripes across the vdevs, and vdevs of different types/sizes do not stripe together optimally. After adding a vdev to your zpool, you might need to copy the new /etc/zfs/zpool.cache to your initrd-tree or initramfs-source (and rebuild/reinstall them) if you are using the cachefile to import your zpool. Using mirror vdevs would be similar to a raid10. Using 4-disk raidz2 vdevs would give the same storage space as raid10 while fully reliable against any double-disk failure; however, the raidz2 parity calculations results in higher CPU usage and/or lower performance. Because raidz vdevs cannot be grown by adding hard drives to them, and vdevs in a zpool are striped, it is important with ZFS to decide what type and size of vdev will be used in a zpool as the units of add-on storage space; it could be difficult to alter this decision later. Finally, on a real installation with raidz, data scrub should be scheduled to actively search for &amp;quot;latent defects&amp;quot; on the hard drives so that unknown read/write errors do not become known later during a disk swap/rebuild and result in the zpool becoming faulted (lost).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on host)&lt;br /&gt;
mkdir slackzfs&lt;br /&gt;
mv packages slackzfs/&lt;br /&gt;
cd slackzfs&lt;br /&gt;
qemu-img create disk1.raw 10G&lt;br /&gt;
ln -s ~/slackware64-current-install-dvd.iso dvd.iso&lt;br /&gt;
qemu-kvm \&lt;br /&gt;
 -option-rom 8xx_64.rom,bootindex=1 \&lt;br /&gt;
 -no-quit \&lt;br /&gt;
 -no-shutdown \&lt;br /&gt;
 -boot order=cd,menu=on \&lt;br /&gt;
 -m 2G \&lt;br /&gt;
 -cpu host \&lt;br /&gt;
 -smp sockets=1,cores=4 \&lt;br /&gt;
 -net nic,model=e1000 -net user \&lt;br /&gt;
 -cdrom dvd.iso \&lt;br /&gt;
 -drive format=raw,media=disk,cache=none,aio=native,if=scsi,index=0,file=disk1.raw \&lt;br /&gt;
 -virtfs local,path=./packages/,security_model=none,mount_tag=hostpackages&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The install-dvd should boot, and then begin installation steps on the installer command line:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on install-dvd)&lt;br /&gt;
# mount the install-dvd&lt;br /&gt;
mkdir /dvd&lt;br /&gt;
mount /dev/sr0 /dvd&lt;br /&gt;
&lt;br /&gt;
# install coreutils, which provides the &amp;quot;hostid&amp;quot; command needed to load the spl module&lt;br /&gt;
installpkg /dvd/slackware64/a/coreutils-8.17-x86_64-1.txz&lt;br /&gt;
&lt;br /&gt;
# install kmod package which includes &amp;quot;depmod&amp;quot; command and others&lt;br /&gt;
installpkg /dvd/slackware64/a/kmod-9-x86_64-2.txz&lt;br /&gt;
depmod&lt;br /&gt;
&lt;br /&gt;
# install the full kernel modules so you can load 9p filesystem and use it if you want&lt;br /&gt;
# .. you might keep the zfs modules packages off the dvd and use a plain slack dvd&lt;br /&gt;
installpkg /dvd/slackware64/a/kernel-modules-*.txz&lt;br /&gt;
depmod&lt;br /&gt;
&lt;br /&gt;
# install bash and libtermcap because udev rules in zfs use bash scripts&lt;br /&gt;
installpkg /dvd/slackware64/a/bash-*.txz&lt;br /&gt;
installpkg /dvd/slackware64/l/libtermcap-*.txz&lt;br /&gt;
&lt;br /&gt;
# install spl and zfs that you have copied into the mirror before running the DVD creation&lt;br /&gt;
installpkg /dvd/addon/spl-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /dvd/addon/zfs-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
&lt;br /&gt;
#Or:&lt;br /&gt;
mkdir /packages&lt;br /&gt;
find /lib/modules/ | grep 9p&lt;br /&gt;
lsmod&lt;br /&gt;
# check that 9p modules load, mainly 9pnet_virtio&lt;br /&gt;
modprobe 9pnet_virtio&lt;br /&gt;
mount hostpackages -t 9p -o trans=virtio /packages&lt;br /&gt;
installpkg /packages/spl-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /packages/zfs-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
modprobe zfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now zfs tools: &amp;quot;zpool&amp;quot; and &amp;quot;zfs&amp;quot; should work in the live installer.&lt;br /&gt;
On the installer, there can be trouble seeing man pages, so install:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
installpkg /dvd/slackware64/ap/man-*.txz&lt;br /&gt;
installpkg /dvd/slackware64/ap/groff-*.txz&lt;br /&gt;
installpkg /dvd/slackware64/a/less-*.txz&lt;br /&gt;
export MANPATH=/usr/man:/usr/share/man&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The manual pages should be readable:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
man zpool&lt;br /&gt;
man zfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After seeing the man pages, we should be fully ready to continue to setup on ZFS.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(still on install-dvd)&lt;br /&gt;
ls -l /dev/sd*&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Make sure the disk devices you expect are there. We'll use sda and make boot (/boot on /dev/sda1) and root (/ on /dev/sda2) partitions.&lt;br /&gt;
&lt;br /&gt;
First, some background info: A ZFS filesystem is not supported by lilo as the filesystem containing /boot, which holds lilo's 2nd stage and the linux kernel files. The on-disk format of a ZFS filesystem is often a complex raid configuration where even if lilo understood ZFS it would likely require /boot to reside in only certain simple ZFS configurations to be plainly readable to lilo. As things are, a linux root installed in a partition with ZFS filesystem needs /boot to be on another partition with a filesystem that lilo understands, such as ext4 fs. In addition, because the spl and zfs modules are not built into the kernel, and the zfs startup requires some configuration to mount the zfs root, an initial ram/root filesystem (initrd) is needed. The initrd is a gzip compressed cpio archive file that contains a small linux root operating system that is decompressed into a ramfs block device at boot up and takes initial control of the system. The initrd contains an init script that configures devices in devtmpfs mounted at /dev. For example, if using mdadm, lvm, luks, losetup, and now zfs, this init script runs all the commands to create or start these devices (one of which is the root device), mounts the root device, and then transfers system control to the init script in the mounted root filesystem. The ramfs-based root environment on the booted install-dvd or booted initrd image (in rescue command line) are small slackware installations that exist only in ram and are temporary, but while inside them you can install, upgrade, and remove slackware packages inside them using the regular package management tools; this allows you access to any kernel modules and programs as needed inside these ramfs root. Packages can be installed, upgraded, or removed permanantly in the initrd image file to manage the programs and modules required during the initrd boot stage. Also from within these ramfs initial root environments, once the root device is mounted, chroot can be used to work on the mounted root system as if it were booted; this allows one to fix problems that are occuring in the root fs init scripts that cause normal booting to fail, or to install a kernel and/or modules etc. Now on to partitioning:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cgdisk /dev/sda&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, cgdisk looks just like cfdisk, but it makes GPT partitions.&lt;br /&gt;
&lt;br /&gt;
Make a partition for /boot that is about 512MiB of whatever partition type you like (8300 &amp;quot;Linux filesystem&amp;quot; is fine), or make it type bf07 &amp;quot;Solaris Reserved 1&amp;quot; if you want ZFS to maybe see the disk as if it was given as a whole disk to ZFS. Make a second partition using the remaining space with partition type bf01 &amp;quot;Solaris ZFS&amp;quot;. Currently, when ZFSonLinux is given a whole disk device like /dev/sdb to use, it will automatically GPT partition it with a bf01 partition #1 that is the whole disk except a small 8MiB type bf07 partition #9 at the end of the disk (/dev/sdb1 and /dev/sb9). The small 8MiB type bf07 partition #9 is most likely reserved for use by bootloaders, like lilo, to have a /boot or other boot-related files kept there. For example, you might have /dev/sda that is totally non-ZFS for booting and /dev/sdb passed to ZFS whole where it automatically partitions sdb, but you can just use one disk here and make partitions. Let's use type 8300 for /boot to be sure nothing is confused:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
We'll continue with this partitioning (numbers are in MiB):&lt;br /&gt;
  0 to   4: unused&lt;br /&gt;
  4 to 516: /dev/sda1 512MiB, type 8300&lt;br /&gt;
516 to 520: unused&lt;br /&gt;
520 to -96: /dev/sda2, type bf01&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The -96 means to count from the end of the disk so that 96MiB will remain unused at the end of the disk.&lt;br /&gt;
&lt;br /&gt;
Create a zpool called zfs-root:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool create -m none zfs-root /dev/sda2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A zpool created like this, the normal way, is a kernel-internal block device that contains already a zfs filesystem. There is normally no entry in /dev for this device. However, it can still be referenced as a mountable device similar to how devtmpfs, proc, and sysfs are also kernel-internal mountable block devices. The -m option told zpool not to automatically mount it anywhere, and without -m the default is to always automatically mount to /zfs-root. These kinds of details are explained better elsewhere. For this situation, we do not want it automounted.&lt;br /&gt;
&lt;br /&gt;
Because a zpool itself is a useable zfs fs, it has a full set of zfs &amp;quot;properties&amp;quot; to set options about the filesystem, perhaps similar to tune2fs. The &amp;quot;mountpoint=&amp;lt;some place to mount&amp;gt;&amp;quot; is one such property. We want it set to the special value &amp;quot;none&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs get mountpoint zfs-root&lt;br /&gt;
zfs set mountpoint=none zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also use &amp;quot;legacy&amp;quot; for the mountpoint and the management of mounting and unmounting the pool will be expected to be done using the regular &amp;quot;mount&amp;quot; and &amp;quot;umount&amp;quot; commands:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=legacy zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Later in the wiki, it is shown how to mount using &amp;quot;zfs mount&amp;quot; for mountpoint=none, and regular &amp;quot;mount&amp;quot; for mountpoint=legacy. Using mountpoint=legacy is probably the preferred setting for the zfs-root because you can use the normal mount and umount commands and do no have to change slackware /etc/rc.d/* scripts much, if any. The normal slackware scripts handle a root filesystem's mounting and remounting using the normal mount command.&lt;br /&gt;
&lt;br /&gt;
On creation, the zpool zfs-pool is &amp;quot;imported&amp;quot; and has a zpool status that can be viewed:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool status zfs-root&lt;br /&gt;
&lt;br /&gt;
zpool export zfs-root&lt;br /&gt;
zpool status zfs-root&lt;br /&gt;
# Now there is no status.&lt;br /&gt;
&lt;br /&gt;
zpool import zfs-root&lt;br /&gt;
# Now it is back.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
When a zpool is imported, it has it's current configuration cached in a file /etc/zfs/zpool.cache. When a zpool is exported, then it's entries in the cache file are removed and the cache file is deleted if it becomes empty. So long as the zfs kernel modules see this cache file and valid cache data inside it, ZFS considers the described zpools in the cache file to be valid as imported zpools. If the zpool.cache file is present at the time the zfs modules are loaded, then there is no further need to use the import and export zpool commands at system startup and shutdown. With root on a zfs, it is not possible to export the pool that root is on, but this is not a problem. At shutdown, the safe procedure will be to set the zfs-root property readonly=on or remount read-only and sync disks.&lt;br /&gt;
&lt;br /&gt;
To avoid the requirement to import the zfs-root pool at startup, you can keep a copy of the zpool.cache file to later copy onto the initrd image to read at modules load time to have the pool reactivated without need to issue the zpool import command:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/zfs/zpool.cache /etc/zfs/zpool.cache-initrd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
A warning about the zpool.cache file: Having /etc/zfs/zpool.cache present at zfs module load or module init time can be unsafe if the device names in /dev have changed since the last boot. Especially dangerous is if two hard drives have swapped names, like /dev/sda and /dev/sdb have swapped names. It is safer to not have a zpool.cache file on the system at boot and zfs module load/init time to guard against the possibility that the cache file is no longer correct. This wiki will try to show how you can use zpool.cache to import your pool if the regular zpool import command seems to always require you to force it. This wiki will also show how to not need a zpool.cache file to import normally.&lt;br /&gt;
&lt;br /&gt;
A zfs filesystem will not normally allow you to mount over any files. The mountpoint is expected to be an empty directory. Remove any junk files inside the installer's /mnt because zfs won't mount over any files:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rm /mnt/README&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The directory /mnt is where the slackware setup expects you to mount your root for installation.&lt;br /&gt;
&lt;br /&gt;
Controlling whether a zfs fs is to be mounted read-only or read-write is best managed by setting the readonly property while it is not yet mounted:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set readonly=on zfs-root&lt;br /&gt;
zfs set readonly=off zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If you are using &amp;lt;code&amp;gt;mountpoint=legacy&amp;lt;/code&amp;gt; then the options for the mount command for ro or rw mounting will work as normal also and override whatever the readonly property is set to. The readonly property does serve as a default.&lt;br /&gt;
&lt;br /&gt;
Slackware expects root to be mounted readonly when /etc/rc.d/rc.S runs during normal startup, so later this is used to satisfy slackware's expectation to avoid rc.S complaining.&lt;br /&gt;
&lt;br /&gt;
The zfs-root can be mounted and unmounted in two different ways:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=/mnt zfs-root&lt;br /&gt;
zfs set mountpoint=none zfs-root&lt;br /&gt;
# or&lt;br /&gt;
mount zfs-root -t zfs /mnt&lt;br /&gt;
umount /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If it is already mounted and you want to change it to mount somewhere else, it is best to transition it to unmounted first, then mount it in the new place.&lt;br /&gt;
&lt;br /&gt;
The mount options &amp;lt;code&amp;gt;-o ro, -o rw, -o remount,ro, and -o remount,rw &amp;lt;/code&amp;gt; can also be used and will override the &amp;lt;code&amp;gt;readonly=on|off&amp;lt;/code&amp;gt; property without altering the property value. This can be confusing until you are familiar with how the two methods of mounting interact. When &amp;lt;code&amp;gt;mountpoint=legacy&amp;lt;/code&amp;gt; is set, zfs expects the regular mount and umount commands to be used to mount and unmount the dataset with the assistance of the mount.zfs helper. For now, we will continue with &amp;lt;code&amp;gt;mountpoint=none&amp;lt;/code&amp;gt;, but using legacy is also a good option.&lt;br /&gt;
&lt;br /&gt;
Now, let's continue some, and mount to /mnt using the current &amp;lt;code&amp;gt;readonly=off&amp;lt;/code&amp;gt; setting (rw mount):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=/mnt zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method of mounting will show the most detailed mount options in /etc/mtab. They are the mount options that zfs thinks are proper, and they are probably what should be kept in /etc/fstab for zfs-root until we know better.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cat /etc/mtab &amp;gt;&amp;gt; /etc/fstab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now edit /etc/fstab to make sure it looks right, and remove the &amp;quot;rw&amp;quot; mount option, because we want to let it use a default for that, which will come from how we set the readonly= property most of the time. Unmount again:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=none zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mount again, now using all options from /etc/fstab:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It should be mounted at /mnt, and touch /mnt/t should allow you to make the file t. Then rm it: rm /mnt/t&lt;br /&gt;
For installation, we want to make sure it is mounted read-write. After installation, it should mount readonly inside the initrd.&lt;br /&gt;
&lt;br /&gt;
Sometimes there can be problems using the mount command, and then you can try it with the -i option:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 mount -i zfs-root&lt;br /&gt;
 mount -i zfs-root -t zfs /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
but, you should not have to use -i. When using -i makes it work, it performs an &amp;quot;internal-only&amp;quot; mount and does not use any mount.&amp;lt;fstype&amp;gt; helper scripts that might be on the system. You can use &amp;lt;code&amp;gt;mountpoint=legacy&amp;quot;&amp;lt;/code&amp;gt; to avoid this small problem if you are preferring to use the regular mount and umount commands on your zfs-root.&lt;br /&gt;
&lt;br /&gt;
Setup the /boot device:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkfs.ext4 /dev/sda1&lt;br /&gt;
mkdir /mnt/boot&lt;br /&gt;
mount /dev/sda1 /mnt/boot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We have both root and boot mounted where the slackware installer expects them. Unmount the dvd so setup can find it normally:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
umount /dev/sr0&lt;br /&gt;
setup&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the setup, skip straight to TARGET selection for the root device, but the setup doesn't see or understand the zfs-root, so it is not listed. This does not matter because we have mounted it already. Just skip down to a slot that say to continue, and continue on with setup. Because TARGET is skipped, you may not see the ADDITIONAL prompt (or if so, skip it too) where normally you give /dev/sda1 and have it mounted as /boot. This is also okay because we have mounted /mnt/boot already.&lt;br /&gt;
Because we did not give TARGET the root device or say what device /boot is on, the lilo installation will fail, or you can skip it. Otherwise, this installation process is normal.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Finish installation and exit setup, but do NOT reboot!&lt;br /&gt;
# There is still a lot to do before rebooting.&lt;br /&gt;
umount /dev/sr0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point, it is assumed that the setup has completed installing into /mnt. Congrats! You've installed slackware into a ZFS root!&lt;br /&gt;
&lt;br /&gt;
The next steps are to prepare to use &amp;quot;chroot /mnt&amp;quot; and finish up the configuration on the installed root system and then be able to reboot onto the completed installation. Before doing chroot, copy some files from the setup environment into /mnt.&lt;br /&gt;
&lt;br /&gt;
Copy the current installer /etc/fstab for later use inside the initrd. This fstab is what is proper inside the initrd, except remove option &amp;quot;rw&amp;quot; (if not done already).&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/fstab /mnt/etc/fstab.initrd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The fstab.initrd will look like:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 proc /proc proc defaults 0 0&lt;br /&gt;
 zfs-root /mnt zfs defaults,atime,dev,exec,suid,xattr,nomand,zfsutil 0 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the initrd, we want zfs-root to mount to /mnt.&lt;br /&gt;
&lt;br /&gt;
Create /mnt/etc/fstab:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cat /etc/mtab &amp;gt;&amp;gt; /mnt/etc/fstab&lt;br /&gt;
vi /mnt/etc/fstab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using vi started above, edit /mnt/etc/fstab and make it have lines such as:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 zfs-root / zfs defaults,atime,dev,exec,suid,xattr,nomand,zfsutil 0 0&lt;br /&gt;
 /dev/sda1 /boot ext4 defaults 0 2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
These two lines in &amp;lt;code&amp;gt;/mnt/etc/fstab&amp;lt;/code&amp;gt; are how the mounts should be looking when root is booted. Although the fstab option for fs_passno is 0 and indicates that root (/) should not be fsck, this fs_passno option in fstab is ignored during system startup for / in rc.S because rc.S explicity runs &amp;quot;fsck /&amp;quot; which does not look at options inside fstab. Fsck doesn't work on a zfs fs, and we will deal with that problem in a moment (see below).&lt;br /&gt;
&lt;br /&gt;
Mount some special mounts before chroot:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount -t devtmpfs none /mnt/dev&lt;br /&gt;
mount -t proc none /mnt/proc&lt;br /&gt;
mount -t sysfs none /mnt/sys&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Make sure /boot is mounted:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount /dev/sda1 /mnt/boot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you had mounted a 9p fs share to access spl and zfs packages, then unmount that now:&lt;br /&gt;
umount /packages&lt;br /&gt;
&lt;br /&gt;
Ready, now:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chroot /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point, you should be on the installed system, and now try to configure mkinitrd and lilo. First, switch to use the generic kernel:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /boot&lt;br /&gt;
rm System.map config vmlinuz&lt;br /&gt;
ln -s System.map-gen* System.map&lt;br /&gt;
ln -s config-gen* config&lt;br /&gt;
ln -s vmlinuz-gen* vmlinuz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We installed spl and zfs inside the live ramfs install-dvd environment, but not yet have we installed them into the root system:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount /dev/sr0 /mnt/cdrom&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /mnt/cdrom/addon/spl-*.txz&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /mnt/cdrom/addon/zfs-*.txz&lt;br /&gt;
depmod&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If instead, you used a 9p share to access the spl and zfs packages, then repeat that procedure here to install them onto the root system.&lt;br /&gt;
&lt;br /&gt;
Setup lilo: edit /etc/lilo.conf so it is like:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  lba32&lt;br /&gt;
  append = &amp;quot; vt.default_utf8=1&amp;quot;&lt;br /&gt;
  boot = /dev/sda&lt;br /&gt;
  message = /boot/boot_message.txt&lt;br /&gt;
  prompt&lt;br /&gt;
  timeout = 1200&lt;br /&gt;
  change-rules&lt;br /&gt;
   reset&lt;br /&gt;
  vga = normal&lt;br /&gt;
  image = /boot/vmlinuz&lt;br /&gt;
   label = vmlinuz&lt;br /&gt;
   initrd = /boot/initrd.gz&lt;br /&gt;
   root = /dev/ram0&lt;br /&gt;
   read-write&lt;br /&gt;
# alternatively, the root and read-write lines&lt;br /&gt;
# can be this one line of kernel parameters:&lt;br /&gt;
#  addappend = &amp;quot; root=/dev/ram0 rw &amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A note about initrd: The /boot/initrd.gz is a gzipped cpio archive containing a minimal BusyBox-based slackware root system that is sourced from /boot/initrd-tree. The commands &amp;quot;mkinitrd&amp;quot; and &amp;quot;mkinitrd -F&amp;quot; generates /boot/initrd-tree and /boot/initrd.gz. When using a initrd, the initial root device is normally set to root=/dev/ram0 (a ramfs block device) and allowed read-write. The kernel refers to devices in terms of &amp;quot;major&amp;quot; and &amp;quot;minor&amp;quot; numbers, and the ram0 device is assigned the block device major 1 and minor 0. This ram0 major/minor is written in hexadecimal as 0x0100 (256 in decimal). This hexademical number makes an appearance in /boot/initrd-tree/int where it runs: &amp;quot;echo 0x0100 &amp;gt; /proc/sys/kernel/real-root-dev&amp;quot;. Echoing a device code to real-root-dev is part of a deprecated initrd mechanism, but is probably harmless to leave alone as slackware has it unless you know otherwise. More information about how initrd works can be found in:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/usr/src/linux/Documentation/devices.txt (info about major:minor device numbers)&lt;br /&gt;
/usr/src/linux/Documentation/initrd.txt  (mostly obsolete info on old initrd)&lt;br /&gt;
/usr/src/linux/Documentation/filesystems/ramfs-rootfs-initramfs.txt (current info on new initrd, called initramfs)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Advanced note about initrd: Slackware's mkinitrd package does not use the &amp;quot;pivot_root&amp;quot; command as documented in &amp;quot;initrd.txt&amp;quot;, but instead uses &amp;quot;switch_root&amp;quot; provided by a project called BusyBox. The switch_root command changes the effective root filesystem from the initrd (unpacked in rootfs at /) to the new root filesystem (zfs-root mounted at /mnt); it overmounts rootfs / with zfs-root /mnt. The switch_root works as follows: delete everything in rootfs / (one filesystem only) that held initrd to free up ram memory, then use mount, chroot, and chdir to make the effective root change. In concept (as a shell script), the command &amp;quot;exec switch_root /mnt $INIT $RUNLEVEL&amp;quot; is performed as follows:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 find / -xdev | xargs rm -rf&lt;br /&gt;
 cd &amp;quot;$1&amp;quot;&lt;br /&gt;
 shift&lt;br /&gt;
 mount --move . /&lt;br /&gt;
 exec chroot . &amp;quot;$@&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Here, typically INIT=/sbin/init RUNLEVEL=3. The 'exec' causes switch_root to take the place of the parent process having PID=1. In system calls, the switch_root looks similar to this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chdir(&amp;quot;/mnt&amp;quot;);&lt;br /&gt;
/* &amp;lt;insert code to unlink/rmdir all initrd files/directories&lt;br /&gt;
 *  installed in rootfs / without crossing filesystems &amp;gt; */&lt;br /&gt;
mount(&amp;quot;.&amp;quot;, &amp;quot;/&amp;quot;, NULL, MS_MOVE, NULL);&lt;br /&gt;
chroot(&amp;quot;.&amp;quot;);&lt;br /&gt;
chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
execl(&amp;quot;/sbin/init&amp;quot;, &amp;quot;3&amp;quot;, (char*) NULL );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The kernel's rootfs / that contained initrd is never actually unmounted (it can't be) because it is built into the kernel and always exists as at least a tiny ramfs or tmpfs, so you can continue to see it in /proc/mounts. When you give lilo root=/dev/ram0 (a ramfs device), the kernel will actually use the internal rootfs, which is an instance of a tmpfs (if your kernel config includes tmpfs) or ramfs. The rootfs that is a tmpfs can by default use up to half of system ram. If rootfs is a ramfs, it can use up to almost all of system ram until the system panics. Typically, tmpfs is built into the kernel, and so depending on how much ram your computer has, the initrd-tree can probably be up to about half that size.&lt;br /&gt;
&lt;br /&gt;
Quite a lot of notes... now to continue on...&lt;br /&gt;
&lt;br /&gt;
Setup mkinitrd:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/mkinitrd.conf.sample /etc/mkinitrd.conf&lt;br /&gt;
vi /etc/mkinitrd.conf&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Edit it to look like this (other defaults should be ok):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 MODULE_LIST=&amp;quot;sym53c8xx:ext4:e1000:zfs:9p:9pnet_virtio&amp;quot;&lt;br /&gt;
 ROOTDEV=&amp;quot;zfs-root&amp;quot;&lt;br /&gt;
 ROOTFS=&amp;quot;zfs&amp;quot;&lt;br /&gt;
#Module sym53c8xx is the driver for qemu's if=scsi drive device.&lt;br /&gt;
#Module ext4 for /boot.&lt;br /&gt;
#Module e1000 for eth0 net device.&lt;br /&gt;
#Module zfs for ZFSonLinux.&lt;br /&gt;
#Modules 9p and 9pnet_virtio for mounting qemu -virtfs mount_tag.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These 9p modules could be useful from the rescue command line inside the initrd to get needed files that are on the host.&lt;br /&gt;
&lt;br /&gt;
All dependent modules will also be included automatically into /boot/initrd-tree, which is packaged as /boot/initrd.gz. For example, to see the dependent modules of zfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
modprobe --show-depends zfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All listed modules will also be in the initrd. Now, make a /boot/initrd-tree that we can begin to look at and edit:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkinitrd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create an empty /etc/mtab or else zpool import fails (zfs expects /etc/mtab to exists already, it won't make it):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
touch /boot/initrd-tree/etc/mtab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Copy in the fstab.initrd that was made earlier while on the installer. This provides all the mount options for a simple &amp;quot;mount zfs-root&amp;quot; onto /mnt:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/fstab.initrd /boot/initrd-tree/etc/fstab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More package installing! This time into an alternate root, the root of the initrd, /boot/initrd-tree. This is how you can put whatever packages you like into your initrd. These installations work independent of your normal installations. You can install, upgrade, and remove packages using an altroot:&lt;br /&gt;
&lt;br /&gt;
If spl and zfs are on your customized dvd:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/addon/spl-*.txz&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/addon/zfs-*.txz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Otherwise, repeat same procedure but you mount your 9p mount_tag and get them installed.&lt;br /&gt;
&lt;br /&gt;
More regular packages from the dvd:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/kmod-*.txz&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/coreutils-*.txz&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/gptfdisk-*.txz&lt;br /&gt;
&lt;br /&gt;
# A bash script is in /boot/initrd-tree/lib/udev/, so we need it or udev rules have problems:&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/bash-*.txz&lt;br /&gt;
# Bash needs this:&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/l/libtermcap-*.txz&lt;br /&gt;
&lt;br /&gt;
# Install net-tools to ensure that /etc/HOSTNAME, /etc/hosts, and potentially, /etc/hostid are handled proper.&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/n/net-tools-*.txz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When ZFS has to import a zpool while the initrd is running (this can be avoided by not exporting and keeping /etc/zfs/zpool.cache inside the initrd), ZFS will refuse to import a pool if it thinks that the pool may be in use by another system. ZFS was designed for network attached storage (NAS) where multiple hosts might have access to the same disks but ZFS cannot support two hosts importing and using a ZFS pool at the same time (that requires a &amp;quot;cluster&amp;quot; fs). ZFS checks a value called &amp;quot;hostid&amp;quot; to determine this kind of conflict, and it can be a tricky issue with an initrd boot process. The value of hostid is returned by the gethostid() function or the hostid command. This function will return the hostid from /etc/hostid if that file exists and has a valid id in it, or else if the file doesn't exist it obtains a hostid number based on the hostname and ip address assigned to hostname found in /etc/hosts or in DNS. If the hostid trying to import a pool is not the same as the hostid that imported it last time, ZFS will not import the pool unless &amp;quot;zpool import -f zfs-root&amp;quot; is used to force the import. This force option is not recommended to use, so it is best to configure your initrd with matching /etc/HOSTNAME and /etc/hosts as on the root installation and ensure what your system looks like on the initrd matches the booted root system. The hostid can also be passed to the SPL module with the module parameter &amp;lt;code&amp;gt;spl.spl_hostid=0xHHHHHHHH&amp;lt;/code&amp;gt; where the Hs are a hexadecimal hostid value and this overrides any /etc/hostid or hostname/IP-based hostid value.&lt;br /&gt;
&lt;br /&gt;
Edit /boot/initrd-tree/init (this is the main system startup script on the initrd, responsible for configuring your block devices, mounting root at /mnt, and booting root):&lt;br /&gt;
&lt;br /&gt;
Inside init, right near the top of the file after the PATH= line, add this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/bin/hostname -F /etc/HOSTNAME&lt;br /&gt;
/bin/hostname $( /bin/hostname -s )&lt;br /&gt;
#/sbin/chhostid 13371400&lt;br /&gt;
# you can make your hostid whatever, but this didn't work right with ZFS, so it is commented out&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This sets the name reported by the hostname command (the default is &amp;quot;darkstar&amp;quot;) to be what is contained in /etc/HOSTNAME. The hostname is modified in the next line to be the short hostname. These lines will help ZFS to properly identify your host when importing pools.&lt;br /&gt;
&lt;br /&gt;
Inside init, right after it runs &amp;quot;mdadm&amp;quot; commands as used for raid setup, we like it to setup ZFS, so add:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/sbin/zpool import zfs-root&lt;br /&gt;
/sbin/zfs set readonly=on zfs-root&lt;br /&gt;
mount zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
We want to make sure the default is to mount readonly, then it mounts using defaults from /etc/fstab inside the initrd.&lt;br /&gt;
&lt;br /&gt;
Inside init, close to the bottom, where it &amp;quot;Switch to real root partition&amp;quot;, comment out 1 line that normally does the mount:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# mount -o ro -t $ROOTFS $ROOTDEV /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
We have already mounted zfs-root, and we don't want to use any mount options because we should be using a properly set /etc/fstab inside the initrd for the zfs-root mount options onto /mnt.&lt;br /&gt;
&lt;br /&gt;
During a normal startup we want a readonly mount.&lt;br /&gt;
&lt;br /&gt;
Note: we are going to setup with using &amp;quot;zpool import&amp;quot; and &amp;quot;zpool export&amp;quot; commands at startup and shutdown. But later, you can experiment having /etc/zfs/zpool.cache stored in the initrd and commenting out the zpool import/export lines. Using zpool import/export is safer than using a zpool.cache, so we try to setup that way preferably.&lt;br /&gt;
&lt;br /&gt;
As mentioned, the zpool import command may sometimes fail, and give the message: &amp;quot;pool may be in use from another system&amp;quot;. This is nothing serious in this test situation. When this happens, zfs-root will not get mounted to /mnt and the init script will detect this and drop you into a rescue command line where you may manually do:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool import -f zfs-root&lt;br /&gt;
mount zfs-root&lt;br /&gt;
exit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This will force import, overriding the conflict that zfs thinks may be happening. Next is mount. After this, exit to let the init script continue on to boot the system normally.&lt;br /&gt;
&lt;br /&gt;
To avoid this problem we copy some files in (assuming you first edit /etc/HOSTNAME to hold the hostname you like to see on your command prompts, and edited /etc/hosts to have hostname on your loopback or other local ip address):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/HOSTNAME /etc/hosts /boot/initrd-tree/etc&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The value reported by the hostid command is what ZFS sees as your hostid (the SPL module actually tries to run the hostid command to get this value or it uses the spl.spl_hostid value that is given to it). In this setup so far, the value is based on the ip assigned to your hostname. If your hostname is on the line in /etc/hosts for ip address 192.168.13.37, then your hostid will be hex numbers C0.A8.0D.25 rearranged as A8C0250D (pairs of bytes are swapped). This is a ip-based hostid value, a 32bit hexadecimal number. The hostid has to be the same each boot or import will need a -f option to force it. Simply setting the hostid using the function sethostid() which writes a /etc/hostid file doesn't seem to agree with ZFS and you'd have to force the import, so this setup now assumes that you do not have or have deleted /etc/hostid.&lt;br /&gt;
&lt;br /&gt;
You can sometimes see what has been happening to a zpool by using the command &amp;quot;zpool history -li zfs-root&amp;quot; to see a log of commands.&lt;br /&gt;
&lt;br /&gt;
Once again, you can do away with the import and export commands by trying to have /etc/zfs/zpool.cache inside your initrd. To create zpool.cache, while on the installer or in the rescue shell of the initrd (at lilo &amp;quot;boot: vmlinuz rescue&amp;quot;):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on installer or initrd rescue shell)&lt;br /&gt;
zpool import zfs-root&lt;br /&gt;
zfs set readonly=off zfs-root&lt;br /&gt;
mount zfs-root&lt;br /&gt;
cp /etc/zfs/zpool.cache /mnt/etc/zfs/zpool.cache-initrd&lt;br /&gt;
cp /mnt/etc/zfs/zpool.cache-initrd /mnt/boot/initrd-tree/etc/zfs/zpool.cache&lt;br /&gt;
umount /mnt&lt;br /&gt;
zfs set readonly=on zfs-root&lt;br /&gt;
#mount zfs-root&lt;br /&gt;
#exit (to continue boot process onto rootfs mounted at /mnt)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Words of caution, again: Doing this zpool.cache approach is not necessary, and some talk suggests this is deprecated or discouraged. Although /etc/hostid setup fails to import without -f option, ip-based (hosts|dns) hostid works on booting and import works without -f option and may be the more proper way to do shutdown and startup rather than using a cache file which could become invalid and cause a problem that is difficult to understand. The contents and exact function of the cache file are not well understood by many people. As will be spammed all over this wiki, using zpool.cache is not recommended if you can avoid it because it is potentially unsafe for your pool.&lt;br /&gt;
&lt;br /&gt;
Save /boot/initrd-tree/init and quit vi.&lt;br /&gt;
&lt;br /&gt;
Now, edit /etc/rc.d/rc.S and rc.6 to understand how to remount rw or ro as readonly property changes:&lt;br /&gt;
&lt;br /&gt;
In /etc/rc.d/rc.S:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# comment out the line&lt;br /&gt;
#    /sbin/mount -w -v -n -o remount /&lt;br /&gt;
#add the line&lt;br /&gt;
     /sbin/zfs set readonly=off zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If you are using &amp;lt;code&amp;gt;mountpoint=legacy&amp;lt;/code&amp;gt; for zfs-root, you do not need to make the above change.&lt;br /&gt;
&lt;br /&gt;
In /etc/rc.d/rc.6:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# before: echo &amp;quot;Unmounting local file systems.&amp;quot;&lt;br /&gt;
# add lines:&lt;br /&gt;
  rm -f /etc/zfs/zpool.cache&lt;br /&gt;
  echo &amp;quot;Removed /etc/zfs/zpool.cache&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Remove /etc/zfs/zpool.cache on shutdown. This is recommended because if it is present when you import a pool, it might use this old cache to determine the device filenames in the pool, which may have changed filenames since the last boot, especially the non-persistent /dev/sd* device filenames. It is safest to avoid any usage of the zpool.cache file at boot in initramfs, zfs module load, and at zpool import of other pools.&lt;br /&gt;
&lt;br /&gt;
In /etc/rc.d/rc.6:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# comment out the line:&lt;br /&gt;
#    /bin/mount -v -n -o remount,ro /&lt;br /&gt;
# add the line:&lt;br /&gt;
     /sbin/zfs set readonly=on zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If you are using &amp;lt;code&amp;gt;mountpoint=legacy&amp;lt;/code&amp;gt; for zfs-root, you do not need to make the above change.&lt;br /&gt;
&lt;br /&gt;
In /etc/rc.d/rc.6, near the bottom just before poweroff|reboot, add the following block of lines:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
########################&lt;br /&gt;
# Try to export zfs-root&lt;br /&gt;
/sbin/zpool export zfs-root&lt;br /&gt;
if [ $? -gt 0 ] ; then&lt;br /&gt;
 echo &amp;quot;ZFS export failed.&amp;quot;&lt;br /&gt;
 echo &amp;quot;Notice: if root fs is busy, then this is normal fail.&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;ZFS export successful.&amp;quot;&lt;br /&gt;
 echo &amp;quot;Warning: successful export is abnormal for root fs.&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
/bin/sleep 5&lt;br /&gt;
########################&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This attempts to export even though it cannot return success for the root pool. The attempt is still recorded in the zpool history, and even though it fails the pool may actually be marked as exported (not sure).&lt;br /&gt;
&lt;br /&gt;
For ZFS, you cannot run fsck on it. It doesn't support that kind of filesystem check. The rc.S script will complain a lot in many places about not being able to run fsck on the zfs-root. To disable all attempts to run fsck, we can simply create a file that acts as a flag in /etc/rc.d/rc.S to tell it to skip fsck:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
touch /etc/fastboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This fastboot file is normally a run-once temporary file, and it is deleted near the bottom inside rc.S. Edit rc.S and stop it from deleting /etc/fastboot. We would like it to always skip all fsck. Edit /etc/rc.d/rc.S, and find the &amp;quot;rm&amp;quot; of fastboot, and do not have it removed!&lt;br /&gt;
&lt;br /&gt;
An alternative to using /etc/fastboot is to make the file &amp;lt;code&amp;gt;/sbin/fsck.zfs&amp;lt;/code&amp;gt; that always just &amp;quot;does nothing successfully&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
exec /bin/true&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Or, it can be:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Or, just do:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ln -s /bin/true /sbin/fsck.zfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This fsck helper has the advantage that you do not need to alter &amp;lt;code&amp;gt;rc.S&amp;lt;/code&amp;gt; as much, or at all if you use zfs property &amp;lt;code&amp;gt;mountpoint=legacy&amp;lt;/code&amp;gt; and the regular &amp;lt;code&amp;gt;mount&amp;lt;/code&amp;gt; command on your zfs-root. With these ideas, no slackware /etc/rc.d/* files really need editing, but it is up to you how you want to experiment. I prefer to use &amp;lt;code&amp;gt;mountpoint=legacy&amp;lt;/code&amp;gt; and edit just the initrd init script as above, and edit rc.6 to remove /etc/zfs/zpool.cache and try to export.&lt;br /&gt;
&lt;br /&gt;
We are getting close, and have finished all editing, so make /boot/initrd.gz and install lilo:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkinitrd -F&lt;br /&gt;
lilo&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We finished! All that's left to do is clean up.&lt;br /&gt;
&lt;br /&gt;
Exit the chroot.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
exit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Try to umount everything:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
umount /mnt/proc&lt;br /&gt;
umount /mnt/sys&lt;br /&gt;
umount /mnt/dev&lt;br /&gt;
umount /mnt/boot&lt;br /&gt;
umount /mnt/mnt/cdrom&lt;br /&gt;
umount /mnt/root/packages&lt;br /&gt;
umount /mnt&lt;br /&gt;
zpool export zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note, that export stops a pool and frees devices, while import binds devices and starts a pool. It is somewhat like mdadm -A -s and mdadm -S -s, while /etc/zfs/zpool.cache might be somewhat like mdadm -E -s &amp;gt; /etc/mdadm.conf.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Remove the DVD or change boot order&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When you reboot, if all is good, you are booting properly onto a slackware installed on a ZFS root! Congrats!&lt;br /&gt;
&lt;br /&gt;
If this seems to go badly, and this might happen if the import fails as explained some before, then you will be on the initrd's rescue command line just before the part in init where it wants to mount zfs-root and switch_root to boot up. In this case, you typically got commands like these to do:&lt;br /&gt;
&lt;br /&gt;
If you get dumped to rescue because zpool import will not work and requires -f (force), then:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 zpool import -f zfs-root&lt;br /&gt;
 zpool export    zfs-root&lt;br /&gt;
 zpool import    zfs-root&lt;br /&gt;
 mount zfs-root&lt;br /&gt;
 exit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This can happen if hostname, hostid, or uname changes.&lt;br /&gt;
&lt;br /&gt;
If you get into a jam and need to boot into the initrd and skip zpool import etc, use the lilo prompt (or, boot the install-dvd):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
boot: vmlinuz rescue&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the rescue mode of the initrd, after you have mounted your zfs-root as readonly=on to /mnt, then &amp;quot;exit&amp;quot; to continue booting.&lt;br /&gt;
&lt;br /&gt;
In other emergency command lines, you might need to run the lines at the end of init starting from: &amp;lt;code&amp;gt;udevadm info --cleanup-db; udevadm control --exit&amp;lt;/code&amp;gt;&lt;br /&gt;
If you don't run those udevadm commands, two runs of udevd fight each other and it is slow; you have to wait 2 minutes twice for timeouts (4 minutes).&lt;br /&gt;
The last line in init is run like: &amp;lt;code&amp;gt;exec switch_root /mnt /sbin/init 1&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Warning: the switch_root command is kind of dangerous, so read the manual page about it. From what I can tell, everything except the new root &amp;quot;/mnt&amp;quot; is deleted, so you are giving a command that says what NOT to delete! Make sure nothing got mounted outside of &amp;quot;/mnt&amp;quot; before you run it. However, the deletes should not cross filesystems, but only delete the contents of initramfs.&lt;br /&gt;
&lt;br /&gt;
Also, in rescue command line or anytime you have finished making changes and are about to reboot in some abnormal situation, first run:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set readonly=on zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A bug in unpatched grep 2.13 build 1, found slackware 14.0rc1, causes problems when processing files stored on ZFS but rarely shows problems on other filesystems; the bug does not handle sparse files on zfs and btrfs correctly and results in chaos with slackpkg, compiling kernel modules, and possibly many other things. You must downgrade grep to 2.12 or use the patched grep 2.13 build 2 in slackware 14.0rc2 or later.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
Upgrading:&lt;br /&gt;
&lt;br /&gt;
From time to time you will want to upgrade the kernel to the new kernel in slackware64-current or in patches/. This will also necessitate a rebuild and reinstall or upgrade of spl and zfs. Below is an example of when both kernel and spl/zfs are being upgraded, to give an idea of the process:&lt;br /&gt;
&lt;br /&gt;
Using slackpkg, that is configured to use your local slackware mirror is a good option but you can also configure it to use a remote mirror.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slackpkg upgrade-all&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Assume slackpkg just upgraded your kernel, kernel-modules, kernel-headers, and kernel-source.&lt;br /&gt;
&lt;br /&gt;
Note: the first time you try to run on kernel-generic, setup kernel-huge in lilo as 2nd choice. Huge has all the hard drive controllers builtin, but generic has them all as modules. For example, run &amp;quot;modinfo mptsas&amp;quot; to see module options (maybe you have a LSISAS1068) for your hard drive controller. Add file /etc/modprobe.d/mptsas.conf to set options you want with a line: options mptsas ... Do this for all the device driver modules for your hardware. Do this setup while you are on the huge kernel, then setup to reboot to generic. Include all these modules you need into mkinitrd.conf MODULES_LIST. Check that /boot/initrd-tree/etc/modprobe.d/ has a copy of your customized module conf files because it is on the initrd where the modules will load and use the conf files. mkinitrd probably copies all /etc/modprobe.d/* files into the initrd-tree, but check it. Pay attention to /etc/modprobe.d/README and /lib/modprobe.d/* /lib/modprobe.d/* maybe not copied to initrd-tree but you might want to copy some of it into your initrd-tree yourself to use them.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Check that upgraded kernel-source is symlinked to /usr/src/linux (zfs build looks here). SPL/ZFS modules will install to the kernel version in /lib/modules/&amp;lt;/usr/src/linux kernel version&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /usr/local/src&lt;br /&gt;
tar xvzf ~/spl-*.tar.gz&lt;br /&gt;
tar xvzf ~/zfs-*.tar.gz&lt;br /&gt;
&lt;br /&gt;
###### upgrade spl 1st&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-*&lt;br /&gt;
./configure --prefix=/ --libexecdir=/usr/libexec --libdir=/lib64 --includedir=/usr/include --datarootdir=/usr/share&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=/usr/local/src/install&lt;br /&gt;
cd ../install&lt;br /&gt;
makepkg ../spl-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
upgradepkg spl-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
depmod &amp;lt;new kernel version&amp;gt;     (e.g. depmod 3.2.27, if .27 is new kernel upgrade; you currently run on old, maybe .26)&lt;br /&gt;
# this builds the module dependencies in /lib/modules/&amp;lt;new kernel version&amp;gt;&lt;br /&gt;
###### upgrade zfs 2nd&lt;br /&gt;
mkdir install&lt;br /&gt;
cd zfs-*&lt;br /&gt;
./configure --prefix=/ --libexecdir=/usr/libexec --libdir=/lib64 --includedir=/usr/include --datarootdir=/usr/share&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=/usr/local/src/install&lt;br /&gt;
cd ../install&lt;br /&gt;
makepkg ../zfs-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
upgradepkg zfs-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
depmod 3.2.27&lt;br /&gt;
####### upgrade spl/zfs inside altroot /boot/initrd-tree&lt;br /&gt;
ROOT=/boot/initrd-tree upgradepkg spl-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
ROOT=/boot/initrd-tree upgradepkg zfs-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
# note: ROOT is an environment variable, not a command line option to upgradepkg!&lt;br /&gt;
# note: do not worry about depmod inside initrd-tree, mkinitrd -F actually installs the modules&lt;br /&gt;
# note: this upgrade here is really to just upgrade the command line tools zpool, zfs etc&lt;br /&gt;
####### rebuild /boot/initrd.gz and reinstall lilo&lt;br /&gt;
vi /etc/mkinitrd.conf&lt;br /&gt;
# temporarily set KERNEL_VERSION to new version, but you are still running on old version&lt;br /&gt;
mkinitrd -F&lt;br /&gt;
lilo&lt;br /&gt;
vi /etc/mkinitrd.conf&lt;br /&gt;
# you can set KERNEL_VERSION back to $(uname -r) now&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After reboot you can remove any old /lib/modules/&amp;lt;old kernel version&amp;gt; directory.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
More about /etc/hostid. If you want to experiment changing your /etc/hostid file and seeing if you can use it and make zpool import work normally, here is a tool that might be helpful:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/* software product name: foobarz-chhostid.c&lt;br /&gt;
 * suggested binary name: chhostid&lt;br /&gt;
 * license              : BSD&lt;br /&gt;
 * license text:&lt;br /&gt;
Copyright (c) 2012, foobarz&lt;br /&gt;
All rights reserved.&lt;br /&gt;
&lt;br /&gt;
Redistribution and use in source and binary forms, with or without&lt;br /&gt;
modification, are permitted provided that the following conditions are met:&lt;br /&gt;
    * Redistributions of source code must retain the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer.&lt;br /&gt;
    * Redistributions in binary form must reproduce the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer in the&lt;br /&gt;
      documentation and/or other materials provided with the distribution.&lt;br /&gt;
    * Neither the name of the &amp;lt;organization&amp;gt; nor the&lt;br /&gt;
      names of its contributors may be used to endorse or promote products&lt;br /&gt;
      derived from this software without specific prior written permission.&lt;br /&gt;
&lt;br /&gt;
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &amp;quot;AS IS&amp;quot; AND&lt;br /&gt;
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED&lt;br /&gt;
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE&lt;br /&gt;
DISCLAIMED. IN NO EVENT SHALL &amp;lt;COPYRIGHT HOLDER&amp;gt; BE LIABLE FOR ANY&lt;br /&gt;
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES&lt;br /&gt;
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;&lt;br /&gt;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND&lt;br /&gt;
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT&lt;br /&gt;
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS&lt;br /&gt;
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#define FOOBARZ_CHHOSTID_VERSION &amp;quot;1.0.5&amp;quot;&lt;br /&gt;
#include &amp;lt;sys/socket.h&amp;gt;&lt;br /&gt;
#include &amp;lt;netinet/in.h&amp;gt;&lt;br /&gt;
#include &amp;lt;arpa/inet.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;endian.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sysexits.h&amp;gt;&lt;br /&gt;
/* note: if include stdlib then sethostid fails even with _BSD_SOURCE defined */&lt;br /&gt;
&lt;br /&gt;
long swapbytes(long abcd) {&lt;br /&gt;
  long badc;&lt;br /&gt;
  unsigned char addr_a;&lt;br /&gt;
  unsigned char addr_b;&lt;br /&gt;
  unsigned char addr_c;&lt;br /&gt;
  unsigned char addr_d;&lt;br /&gt;
  addr_a = (unsigned char) (abcd &amp;gt;&amp;gt; 24);&lt;br /&gt;
  addr_b = (unsigned char) (abcd &amp;gt;&amp;gt; 16);&lt;br /&gt;
  addr_c = (unsigned char) (abcd &amp;gt;&amp;gt;  8);&lt;br /&gt;
  addr_d = (unsigned char) (abcd);&lt;br /&gt;
  return badc = ( (addr_b &amp;lt;&amp;lt; 24) | (addr_a &amp;lt;&amp;lt; 16) | (addr_d &amp;lt;&amp;lt; 8) | addr_c );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[])&lt;br /&gt;
{&lt;br /&gt;
 long newhostid;&lt;br /&gt;
 struct in_addr addr;&lt;br /&gt;
 char* invalidchar;&lt;br /&gt;
&lt;br /&gt;
 /*********** check command line */&lt;br /&gt;
 if(!( ((argc==3) &amp;amp;&amp;amp; ( (strcmp(argv[1],&amp;quot;-h&amp;quot;)==0) ||&lt;br /&gt;
                       (strcmp(argv[1],&amp;quot;-i&amp;quot;)==0) ||&lt;br /&gt;
                       (strcmp(argv[1],&amp;quot;-l&amp;quot;)==0) )) ||&lt;br /&gt;
       ((argc==2) &amp;amp;&amp;amp; ( (strcmp(argv[1],&amp;quot;-s&amp;quot;)==0) ))&lt;br /&gt;
     )&lt;br /&gt;
   ) {&lt;br /&gt;
                 /*01234567890123456789012345678901234567890123456789012345678901234567890123456789*/&lt;br /&gt;
  fprintf(stderr, &amp;quot;foobarz-chhostid, version %s. License: BSD.\n&amp;quot;, FOOBARZ_CHHOSTID_VERSION);&lt;br /&gt;
  fprintf(stderr, &amp;quot;foobarz-chhostid, (c) 2012, foobarz; all rights reserved.\n&amp;quot;);&lt;br /&gt;
  fprintf(stderr, &amp;quot;descr: %s change system hostid (in /etc/hostid).\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -h &amp;lt;new hostid&amp;gt;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        Change system hostid to &amp;lt;new hostid&amp;gt;;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        &amp;lt;new hostid&amp;gt; must be 32bit 8-digit hex number xxxxxxxx, each x in 0-f|F.\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        The ip corresponding to &amp;lt;new hostid&amp;gt; is also listed for reference only.\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -i &amp;lt;dotted ip address&amp;gt;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        Change system hostid to hostid corresponding to &amp;lt;dotted ip address&amp;gt;.\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -l &amp;lt;dotted ip address&amp;gt;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        List hostid corresponding to &amp;lt;dotted ip address&amp;gt;;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        no change to system hostid.\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -s\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        List current system hostid and corresponding ip address;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        no change to system hostid.\n&amp;quot;, argv[0]);&lt;br /&gt;
  return EX_USAGE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -h &amp;lt;hostid&amp;gt; */&lt;br /&gt;
 if( strcmp(argv[1],&amp;quot;-h&amp;quot;) == 0 ) {&lt;br /&gt;
  if(strlen(argv[2]) != 8) { fprintf(stderr, &amp;quot;new hostid must be 8-digit hex number xxxxxxxx, each x in 0-f|F\n&amp;quot;); return EX_USAGE; }&lt;br /&gt;
&lt;br /&gt;
  newhostid = strtol(argv[2],&amp;amp;invalidchar,16);&lt;br /&gt;
  if( newhostid==LONG_MIN ) { perror(&amp;quot;strtol (underflow)&amp;quot;); return EX_USAGE; }&lt;br /&gt;
  if( newhostid==LONG_MAX ) { perror(&amp;quot;strtol (overflow)&amp;quot;); return EX_USAGE; }&lt;br /&gt;
  if(*invalidchar != '\0') { fprintf(stderr, &amp;quot;invalid hex number %c; must be in 0-f|F\n&amp;quot;, *invalidchar); return EX_USAGE; }&lt;br /&gt;
&lt;br /&gt;
  if( sethostid(newhostid) != 0 ) {&lt;br /&gt;
   perror(&amp;quot;sethostid&amp;quot;);&lt;br /&gt;
   if( errno == EPERM ) return EX_NOPERM;&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
  }&lt;br /&gt;
  printf(&amp;quot;System hostid changed.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  /* hostid is a byte-swapped ip like b.a.d.c */&lt;br /&gt;
  /* get ip by swapping to correct order a.b.c.d and save into in_addr struct */&lt;br /&gt;
  addr.s_addr = htonl(swapbytes(newhostid));&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -i or -l, then find hostid for &amp;lt;dotted ip address&amp;gt; */&lt;br /&gt;
 if( (strcmp(argv[1],&amp;quot;-i&amp;quot;) == 0) || (strcmp(argv[1],&amp;quot;-l&amp;quot;) == 0) ) {&lt;br /&gt;
  if( inet_aton(argv[2], &amp;amp;addr) == 0 ) { fprintf(stderr, &amp;quot;inet_aton: invalid dotted ip address: %s\n&amp;quot;, argv[2]); return EX_USAGE; }&lt;br /&gt;
&lt;br /&gt;
  /* hostid is a byte-swapped ip like b.a.d.c */&lt;br /&gt;
  /* get hostid by swapping bytes of ip a.b.c.d */&lt;br /&gt;
  newhostid = swapbytes(ntohl(addr.s_addr));&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -i &amp;lt;dotted ip address&amp;gt; */&lt;br /&gt;
 if( strcmp(argv[1],&amp;quot;-i&amp;quot;) == 0 ) {&lt;br /&gt;
  if( sethostid(newhostid) != 0 ) {&lt;br /&gt;
   perror(&amp;quot;sethostid&amp;quot;);&lt;br /&gt;
   if( errno == EPERM ) return EX_NOPERM;&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
  }&lt;br /&gt;
  printf(&amp;quot;System hostid changed.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -l &amp;lt;dotted ip address&amp;gt; */&lt;br /&gt;
 if(strcmp(argv[1],&amp;quot;-l&amp;quot;) == 0 ) {&lt;br /&gt;
   printf(&amp;quot;Listing hostid for ip. (no changes)\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -s */&lt;br /&gt;
 if(strcmp(argv[1],&amp;quot;-s&amp;quot;) == 0 ) {&lt;br /&gt;
   /* see if /etc/hostid exists and print info */&lt;br /&gt;
   if( access(&amp;quot;/etc/hostid&amp;quot;, F_OK) != 0 ) {&lt;br /&gt;
     printf(&amp;quot;Notice: /etc/hostid does not exist.\n&amp;quot;);&lt;br /&gt;
     perror(&amp;quot;Reason&amp;quot;);&lt;br /&gt;
     printf(&amp;quot;System hostid derived from ip of hostname found in hosts file or dns.\n&amp;quot;);&lt;br /&gt;
   } else {&lt;br /&gt;
     printf(&amp;quot;Notice: /etc/hostid exists.\n&amp;quot;&lt;br /&gt;
            &amp;quot;System hostid is obtained from hostid file.\n&amp;quot;);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
  errno=0;&lt;br /&gt;
  newhostid = gethostid();&lt;br /&gt;
  if(errno!=0) { perror(&amp;quot;gethostid&amp;quot;); return EX_UNAVAILABLE; }&lt;br /&gt;
&lt;br /&gt;
  /* hostid is a byte-swapped ip like b.a.d.c */&lt;br /&gt;
  /* get ip by swapping to correct order a.b.c.d and save into in_addr struct */&lt;br /&gt;
  addr.s_addr = htonl(swapbytes(newhostid));&lt;br /&gt;
&lt;br /&gt;
  printf(&amp;quot;Listing current system hostid. (no changes)\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** print info and return */&lt;br /&gt;
 printf(&amp;quot;ip dot: %s\n&amp;quot;, inet_ntoa(addr) );&lt;br /&gt;
 printf(&amp;quot;ip hex: %.8x\n&amp;quot;, ntohl(addr.s_addr) );&lt;br /&gt;
 printf(&amp;quot;hostid: %.8x\n&amp;quot;, newhostid );&lt;br /&gt;
 return EX_OK;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
----&lt;br /&gt;
Now available! &amp;quot;ZFS root (builtin)&amp;quot; wiki (aka &amp;quot;ZFS root, part II&amp;quot;):&lt;br /&gt;
http://slackwiki.com/ZFS_root_(builtin)&lt;br /&gt;
It is now possible to build the modules and a small initramfs into your kernel to have a fully-contained and bootable ZFS root kernel from a simple lilo entry. Good luck!&lt;/div&gt;</description>
			<pubDate>Sun, 16 Sep 2012 08:07:20 GMT</pubDate>
			<dc:creator>Foobarz</dc:creator>
			<comments>https://www.slackwiki.com/Talk:ZFS_root</comments>
		</item>
		<item>
			<title>ZFS root (builtin)</title>
			<link>https://www.slackwiki.com/index.php?title=ZFS_root_(builtin)&amp;diff=794</link>
			<guid isPermaLink="false">https://www.slackwiki.com/index.php?title=ZFS_root_(builtin)&amp;diff=794</guid>
			<description>&lt;p&gt;Foobarz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Tutorials]]&lt;br /&gt;
The first [http://slackwiki.com/ZFS_root &amp;quot;ZFS root&amp;quot;] wiki explains the details of running ZFS as your root filesystem by using a fully modular generic kernel approach. Now, I can share how it can be done with the SPL and ZFS modules built into the kernel. This procedure is just an example and can use some fine tuning, but here goes:&lt;br /&gt;
&lt;br /&gt;
The steps below are to create a kernel with SPL and ZFS modules builtin. This kernel will be installed as an alternative kernel to boot in lilo, and it will have a separate kernel installation from the fully modular and working system kernel. This will allow testing the builtin kernel while able to boot back onto a working modular ZFS system. We start this procedure assuming you are on a working fully modular ZFS install as in the &amp;quot;ZFS root&amp;quot; wiki.&lt;br /&gt;
&lt;br /&gt;
Use mountpoint=legacy so that zfs will not expect &amp;lt;code&amp;gt;zfs mount&amp;lt;/code&amp;gt;, but instead expect standard &amp;lt;code&amp;gt;mount&amp;lt;/code&amp;gt; for mounting zfs-root:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=legacy zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Edit &amp;lt;code&amp;gt;/etc/rc.d/rc.S&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;rc.6&amp;lt;/code&amp;gt; to use regular &amp;lt;code&amp;gt;mount&amp;lt;/code&amp;gt; commands, remove &amp;lt;code&amp;gt;zfs&amp;lt;/code&amp;gt; commands. Edit &amp;lt;code&amp;gt;rc.6&amp;lt;/code&amp;gt; and remove or comment out &amp;lt;code&amp;gt;zpool export&amp;lt;/code&amp;gt; command. These edits undo changes made in the &amp;quot;ZFS root&amp;quot; wiki, but it shows the two different ways of mounting a zfs filesystem.&lt;br /&gt;
&lt;br /&gt;
You &amp;lt;i&amp;gt;might&amp;lt;/i&amp;gt; think to set &amp;lt;code&amp;gt;bootfs&amp;lt;/code&amp;gt; property like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool set bootfs=zfs-root zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
However, this will result in ZFS placing many restrictions on zfs-root as per how that option is used on Solaris systems:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; zfs-root must be VTOC (SMI) label, not GPT (EFI) label&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; zfs-root can only contain 1 vdev: either a plain disk, or a mirror&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
So, do &amp;lt;b&amp;gt;NOT&amp;lt;/b&amp;gt; set that property! If &amp;lt;code&amp;gt;bootfs&amp;lt;/code&amp;gt; is set, you would find that you cannot add vdevs to your zfs-root. If it is set already, then unset it like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool set bootfs= zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Make a directory to store files to be inside the initramfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkdir /boot/initramfs-source&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This directory will hold some files for the initial rootfs inside the kernel. Your &amp;lt;code&amp;gt;/boot&amp;lt;/code&amp;gt; should be on a small ext4 partition or on a mounted USB stick that you use to boot.&lt;br /&gt;
&lt;br /&gt;
Extract the slackware kernel-source package to obtain a copy of the kernel source, and make an initial kernel config for it:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir src&lt;br /&gt;
cd src&lt;br /&gt;
tar xvzf /mnt/cdrom/slackware64/k/kernel-source-*.txz&lt;br /&gt;
mv usr/src/linux-3.2.27 /usr/src/linux-3.2.27b&lt;br /&gt;
rm -r install&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make menuconfig&lt;br /&gt;
  General setup-&amp;gt;Local version - append to kernel release = b&lt;br /&gt;
  General setup-&amp;gt;Default hostname                         = slackzfs&lt;br /&gt;
  General setup-&amp;gt;Initramfs source files(s)                = /boot/initramfs-source&lt;br /&gt;
  Device Drivers-&amp;gt;SCSI device support-&amp;gt;SCSI low-level drivers-&amp;gt; &amp;lt;*&amp;gt; SYM53C8XX Version 2 SCSI support&lt;br /&gt;
  File systems -&amp;gt; &amp;lt;*&amp;gt; The Extended 4 (ext4) filesystem&lt;br /&gt;
  # build in any hard drive controllers and filesystems that you need for booting&lt;br /&gt;
  # then save the config&lt;br /&gt;
make prepare scripts&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The kernel source has been set to have a &amp;quot;Local version&amp;quot; &amp;lt;code&amp;gt;b&amp;lt;/code&amp;gt;. This will result in modules installed to &amp;lt;code&amp;gt;/lib/modules/3.2.27b&amp;lt;/code&amp;gt; and keeps this kernel's source and modules seperate from slackware's kernel-generic package installation. The &amp;lt;code&amp;gt;make prepare scripts&amp;lt;/code&amp;gt; command readies the kernel source as needed before we can install a copy of spl and zfs modules into the kernel source tree.&lt;br /&gt;
&lt;br /&gt;
Now proceed to configure and copy spl and zfs into the kernel source tree:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd ~/src&lt;br /&gt;
tar xvzf ~/spl-0.6.0-rc10.tar.gz&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-0.6.0-rc10&lt;br /&gt;
./configure \&lt;br /&gt;
    --prefix=/ \&lt;br /&gt;
    --libdir=/lib64 \&lt;br /&gt;
    --includedir=/usr/include \&lt;br /&gt;
    --datarootdir=/usr/share \&lt;br /&gt;
    --enable-linux-builtin=yes \&lt;br /&gt;
    --with-linux=/usr/src/linux-3.2.27b \&lt;br /&gt;
    --with-linux-obj=/usr/src/linux-3.2.27b&lt;br /&gt;
wget https://raw.github.com/zfsonlinux/spl/master/copy-builtin&lt;br /&gt;
chmod +x copy-builtin&lt;br /&gt;
./copy-builtin /usr/src/linux-3.2.27b&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../spl-0.6.0rc10_3.2.27b-x86_64-1root.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
&lt;br /&gt;
tar xvzf ~/zfs-0.6.0-rc10.tar.gz&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-0.6.0-rc10&lt;br /&gt;
./configure \&lt;br /&gt;
    --prefix=/ \&lt;br /&gt;
    --libdir=/lib64 \&lt;br /&gt;
    --includedir=/usr/include \&lt;br /&gt;
    --datarootdir=/usr/share \&lt;br /&gt;
    --enable-linux-builtin=yes \&lt;br /&gt;
    --with-linux=/usr/src/linux-3.2.27b \&lt;br /&gt;
    --with-linux-obj=/usr/src/linux-3.2.27b \&lt;br /&gt;
    --with-spl=/root/src/spl-0.6.0-rc10&lt;br /&gt;
wget https://raw.github.com/zfsonlinux/zfs/master/copy-builtin&lt;br /&gt;
chmod +x copy-builtin&lt;br /&gt;
./copy-builtin /usr/src/linux-3.2.27b&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../zfs-0.6.0rc10_3.2.27b-x86_64-1root.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
At this point, the &amp;lt;code&amp;gt;copy-builtin&amp;lt;/code&amp;gt; scripts have installed the configured spl and zfs modules source into the kernel source. The regular &amp;lt;code&amp;gt;make menuconfig&amp;lt;/code&amp;gt; in the kernel source should now show options for spl and zfs in the kernel config.&lt;br /&gt;
&lt;br /&gt;
As of this writing, the copy-builtin script places the spl and zfs modules into the kernel source in places where the modules may not initialize in the best order, &amp;lt;i&amp;gt;after&amp;lt;/i&amp;gt; all lower-level storage drivers are initialized. If spl and zfs initialize too soon, there is a chance they may not be able to see all of the storage devices. The order of initialization (as seen in dmesg) of modules that are builtin to the kernel is the order that the modules are linked into the kernel during kernel compilation. The order of link depends on where the module source files are located in the kernel source tree. To ensure that spl and zfs will initialize after all hardware drivers, we move them into the &amp;lt;code&amp;gt;drivers&amp;lt;/code&amp;gt; tree and after all other drivers:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
mkdir drivers/zfsonlinux&lt;br /&gt;
mv spl drivers/zfsonlinux&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  # remove references to spl&lt;br /&gt;
vi Makefile&lt;br /&gt;
  # remove references to spl&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/fs&lt;br /&gt;
mv zfs ../drivers/zfsonlinux&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  # remove references to zfs&lt;br /&gt;
vi Makefile&lt;br /&gt;
  # remove references to zfs&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  )# add line at end of menu, before &amp;quot;endmenu&amp;quot;:&lt;br /&gt;
  )source &amp;quot;drivers/zfsonlinux/Kconfig&amp;quot;&lt;br /&gt;
  )endmenu&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers&lt;br /&gt;
vi Makefile&lt;br /&gt;
  )# add line at very end of file:&lt;br /&gt;
  )obj-$(CONFIG_ZFSONLINUX) += zfsonlinux/&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers/zfsonlinux&lt;br /&gt;
cat &amp;gt; Kconfig &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
menuconfig ZFSONLINUX&lt;br /&gt;
	tristate &amp;quot;ZFSonLinux support&amp;quot;&lt;br /&gt;
&lt;br /&gt;
if ZFSONLINUX&lt;br /&gt;
&lt;br /&gt;
source &amp;quot;drivers/zfsonlinux/spl/Kconifg&amp;quot;&lt;br /&gt;
&lt;br /&gt;
source &amp;quot;drivers/zfsonlinux/zfs/Kconifg&amp;quot;&lt;br /&gt;
&lt;br /&gt;
endif&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/zfsonlinux&lt;br /&gt;
cat &amp;gt; Makefile &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
obj-$(CONFIG_SPL) += spl/&lt;br /&gt;
obj-$(CONFIG_ZFS) += zfs/&lt;br /&gt;
EOF&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This completes the move of the spl and zfs modules in the kernel source tree to be under &amp;lt;code&amp;gt;drivers/zfsonlinux&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Now, in kernel configuration, you can build in the modules as follows:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make menuconfig&lt;br /&gt;
   Device Drivers -&amp;gt;&lt;br /&gt;
    &amp;lt;*&amp;gt; ZFSonLinux support -&amp;gt;&lt;br /&gt;
      &amp;lt;*&amp;gt; Solaris Porting Layer (SPL)&lt;br /&gt;
      &amp;lt;*&amp;gt;     ZFS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the kernel config, we set &amp;lt;code&amp;gt;/boot/initramfs-source&amp;lt;/code&amp;gt; as source location of the contents to be linked into kernel's builtin initramfs (rootfs). Now, we create some files that are needed to be in the initramfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /boot/initramfs-source&lt;br /&gt;
&lt;br /&gt;
# make standard directories&lt;br /&gt;
mkdir -p proc dev sys mnt bin sbin etc/zfs&lt;br /&gt;
&lt;br /&gt;
# zfs seems to want mtab present, even if empty&lt;br /&gt;
touch etc/mtab&lt;br /&gt;
&lt;br /&gt;
# if zpool.cache file can be read by zfs at module init, it imports the pools in the cache&lt;br /&gt;
cp /etc/zfs/zpool.cache-initrd etc/zfs/zpool.cache&lt;br /&gt;
&lt;br /&gt;
# make initial console device node; otherwise, there is a problem at startup:&lt;br /&gt;
# &amp;quot;Warning: unable to open an initial console&amp;quot; and you'd have problems with console and tty login&lt;br /&gt;
# making these nodes from within /init is not early enough to avoid problem&lt;br /&gt;
mknod dev/console c 5 1   # system console&lt;br /&gt;
&lt;br /&gt;
# make memory device kmsg to &amp;quot;printk&amp;quot; kernel messages&lt;br /&gt;
# we can write to this file to send out messages&lt;br /&gt;
mknod dev/kmsg    c 1 11  # lines printed to kmsg enter kernel messages buffer&lt;br /&gt;
&lt;br /&gt;
# recommended loop0 device to mount fs images&lt;br /&gt;
mknod dev/loop0   b 7 0&lt;br /&gt;
&lt;br /&gt;
# make initial virtual terminal devices&lt;br /&gt;
mknod dev/tty     c 5 0   # current tty&lt;br /&gt;
mknod dev/tty0    c 4 0   # current virtual term&lt;br /&gt;
mknod dev/tty1    c 4 1   # login virtual term 1 (F1)&lt;br /&gt;
&lt;br /&gt;
# make alternative console=ttyS0 standard 8250/16550 UART serial port devices&lt;br /&gt;
#   useful with kernel parameter console=ttyS0&lt;br /&gt;
#          with qemu -nographic -option-rom sgabios.bin,bootindex=0&lt;br /&gt;
mknod dev/ttyS0   c 4 64  # COM1&lt;br /&gt;
mknod dev/ttyS1   c 4 65  # COM2&lt;br /&gt;
mknod dev/ttyS2   c 4 66  # COM3&lt;br /&gt;
mknod dev/ttyS3   c 4 67  $ COM4&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This should be enough device nodes initially in the initramfs. Once devtmpfs mounts over /dev inside initramfs, a lot more devices are available in it by default.&lt;br /&gt;
&lt;br /&gt;
The initramfs needs an &amp;lt;code&amp;gt;/init&amp;lt;/code&amp;gt; program that will be run automatically by the kernel as process id 1, the first program to run on the system. This program's task is to mount a root filesystem, switch it to be the new root (/), and then exec the init (&amp;lt;code&amp;gt;/sbin/init&amp;lt;/code&amp;gt;) program that is on the new root so that the new root system is booted.&lt;br /&gt;
&lt;br /&gt;
The common way to make /init is using busybox with files like these in /boot/initrd-tree or /boot/initramfs-source:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
bin/busybox&lt;br /&gt;
bin/ash -&amp;gt; busybox&lt;br /&gt;
bin/sh -&amp;gt; busybox&lt;br /&gt;
# run busybox to see what other &amp;quot;applets&amp;quot; can be symlinked to it&lt;br /&gt;
# when busybox is run as a different symlinked applet name, it runs as the applet&lt;br /&gt;
init&lt;br /&gt;
# init can be an ash script, see slackware's /boot/initrd-tree/init for example&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For example, as an ash script, slackware's init does the following:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;parse kernel parameters passed into it and set variables based on them&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;start udevd and trigger rules for block devices to setup initial /dev devices&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;load kernel modules and keyboard map&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;run mdadm, cryptsetup, lvm, zpool/zfs to setup more devices&lt;br /&gt;
     (any udev rules for them should do more /dev setup in the background)&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;mount the root filesystem read-only at /mnt&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;stat /mnt/sbin/init, and if not executable run a rescue shell /bin/sh&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;shutdown udevd so it can be restarted by root system when booted&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;mount --move {proc,sys,run,dev} to under /mnt&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;run: exec switch_root /mnt /sbin/init $RUNLEVEL&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The slackware mkinitrd package is a fully configured BusyBox installation that makes an external initramfs image file, initrd.gz, that is passed to the kernel by the bootloader (lilo). It could be changed to be internal to the kernel by just using initrd-tree as the CONFIG_INITRAMFS_SOURCE in the kernel config and removing initrd in the lilo.conf.&lt;br /&gt;
&lt;br /&gt;
The main purpose of most initramfs/initrd is to load and configure kernel modules and devices needed to mount a root filesystem. Because the spl/zfs modules are builtin, there isn't really a lot that needs to be done by an initramfs. What remains to be done is import the zfs-root pool, mount it, and exec the system /sbin/init. The kernel's &amp;quot;legacy&amp;quot; parameters &amp;lt;code&amp;gt;root=&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;rootfstype=&amp;lt;/code&amp;gt; that are able to directly boot a root disk do not work with ZFS at this time because ZFS pools always need to be imported before it is possible to mount and boot on them. The automatic import that ZFS can do by using a cachefile (/etc/zfs/zpool.cache) stored in initramfs still does not work with the legacy boot parameters because at an earlier stage of the boot process, the kernel ignores a rootfs that does not contain an &amp;lt;code&amp;gt;/init&amp;lt;/code&amp;gt; program, and/or the device type of an imported pool is not the device types recognized by the legacy boot as valid root devices.&lt;br /&gt;
&lt;br /&gt;
You could just continue to use slackware's mkinitrd package as in the &amp;quot;ZFS root&amp;quot; wiki and it works the same whether the modules are builtin or not. But, by building the spl/zfs modules in, aren't we really wanting to get rid of using the mkinitrd/initrd.gz? We'd like to have a kernel with everything in it to boot, and use a simple lilo image entry that has no initrd.&lt;br /&gt;
&lt;br /&gt;
We can do this, and not use the mkinitrd package, but we still need to finish our own initramfs &amp;lt;code&amp;gt;/init&amp;lt;/code&amp;gt; program to import, mount, switch root, and boot. Save the following c program to &amp;quot;foobarz-init.c&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/* software product name: foobarz-init.c&lt;br /&gt;
 * suggested binary name: /init (in initramfs-source, rootfs)&lt;br /&gt;
 * license              : BSD&lt;br /&gt;
 * license text:&lt;br /&gt;
Copyright (c) 2012, foobarz&lt;br /&gt;
All rights reserved.&lt;br /&gt;
&lt;br /&gt;
Redistribution and use in source and binary forms, with or without&lt;br /&gt;
modification, are permitted provided that the following conditions are met:&lt;br /&gt;
    * Redistributions of source code must retain the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer.&lt;br /&gt;
    * Redistributions in binary form must reproduce the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer in the&lt;br /&gt;
      documentation and/or other materials provided with the distribution.&lt;br /&gt;
    * Neither the name of the &amp;lt;organization&amp;gt; nor the&lt;br /&gt;
      names of its contributors may be used to endorse or promote products&lt;br /&gt;
      derived from this software without specific prior written permission.&lt;br /&gt;
&lt;br /&gt;
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &amp;quot;AS IS&amp;quot; AND&lt;br /&gt;
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED&lt;br /&gt;
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE&lt;br /&gt;
DISCLAIMED. IN NO EVENT SHALL &amp;lt;COPYRIGHT HOLDER&amp;gt; BE LIABLE FOR ANY&lt;br /&gt;
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES&lt;br /&gt;
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;&lt;br /&gt;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND&lt;br /&gt;
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT&lt;br /&gt;
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS&lt;br /&gt;
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
/* Your initramfs-source should contain the following&lt;br /&gt;
 *&lt;br /&gt;
 * cd /boot/initramfs-source&lt;br /&gt;
 * mkdir -p proc dev sys mnt bin sbin etc/zfs&lt;br /&gt;
 * touch etc/mtab&lt;br /&gt;
 * cp /etc/zfs/zpool.cache-initrd etc/zfs/zpool.cache&lt;br /&gt;
 * # zpool.cache is optional - zpool_import_ kernel params can be used instead&lt;br /&gt;
 * #  see below for details on using zpool_import&lt;br /&gt;
 * mknod dev/console c 5 1   # system console&lt;br /&gt;
 * mknod dev/kmsg    c 1 11  # lines printed to kmsg enter kernel messages buffer&lt;br /&gt;
 * mknod dev/loop0   b 7 0&lt;br /&gt;
 * mknod dev/tty     c 5 0   # current tty&lt;br /&gt;
 * mknod dev/tty0    c 4 0   # current virtual term&lt;br /&gt;
 * mknod dev/tty1    c 4 1   # login virtual term 1 (F1)&lt;br /&gt;
 * mknod dev/ttyS0   c 4 64  # COM1&lt;br /&gt;
 * mknod dev/ttyS1   c 4 65  # COM2&lt;br /&gt;
 * mknod dev/ttyS2   c 4 66  # COM3&lt;br /&gt;
 * mknod dev/ttyS3   c 4 67  $ COM4&lt;br /&gt;
 *&lt;br /&gt;
 * and this program compiled to /boot/initramfs-source/init&lt;br /&gt;
 *&lt;br /&gt;
 * Set kernel config option&lt;br /&gt;
 *  CONFIG_INITRAMFS_SOURCE=/boot/initramfs-source&lt;br /&gt;
 * to build the initramfs into your kernel image&lt;br /&gt;
 *  that also has builtin drivers (spl and zfs, etc).&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
#define FOOBARZ_INIT_VERSION &amp;quot;1.1.1&amp;quot;&lt;br /&gt;
#define _BSD_SOURCE&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdarg.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;fcntl.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/mount.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sysexits.h&amp;gt;&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
/* support for zpool import&lt;br /&gt;
 *&lt;br /&gt;
 * If -DINCLUDE_ZPOOL_IMPORT, then support to import a zpool is&lt;br /&gt;
 * enabled in the program. Enabling it will add many dependencies to the&lt;br /&gt;
 * compile and link; for example:&lt;br /&gt;
 *&lt;br /&gt;
 * gcc -static -DINCLUDE_ZPOOL_IMPORT \&lt;br /&gt;
 *    foobarz-init.c -include /usr/src/zfs-0.6.0-rc10/3.2.28/zfs_config.h \&lt;br /&gt;
 *   -o init \&lt;br /&gt;
 *   -I /usr/include/libspl -I /usr/include/libzfs \&lt;br /&gt;
 *   -lzfs -lnvpair -lzpool -luutil -luuid -lrt -lz -lm -lpthread \&lt;br /&gt;
 *   -I /usr/include/tirpc \&lt;br /&gt;
 *   -ltirpc&lt;br /&gt;
 *&lt;br /&gt;
 * Note that libtirpc is a drop-in replacement for the SunRPC functions that&lt;br /&gt;
 * used to be in glibc. No additional includes are needed, just the gcc -I and -l&lt;br /&gt;
 * options for tirpc.&lt;br /&gt;
 *&lt;br /&gt;
 * Otherwise, with -UINCLUDE_ZPOOL_IMPORT, the compile is just:&lt;br /&gt;
 * gcc -static foobarz-init.c -o init&lt;br /&gt;
 */&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
#include &amp;lt;libzfs.h&amp;gt;&lt;br /&gt;
#else&lt;br /&gt;
#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/stat.h&amp;gt;&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#define PARAM_REQ_NO 0&lt;br /&gt;
#define PARAM_REQ_YES 1&lt;br /&gt;
#define PARAM_SRC_DEFAULT 0&lt;br /&gt;
#define PARAM_SRC_CMDLINE 1&lt;br /&gt;
&lt;br /&gt;
void printk(char *fmt, ...) {&lt;br /&gt;
  FILE* f;&lt;br /&gt;
  int fd;&lt;br /&gt;
  va_list args;&lt;br /&gt;
&lt;br /&gt;
  f = fopen(&amp;quot;/dev/kmsg&amp;quot;, &amp;quot;w&amp;quot;);&lt;br /&gt;
  va_start(args, fmt);&lt;br /&gt;
  vfprintf(f, fmt, args);&lt;br /&gt;
  va_end(args);&lt;br /&gt;
  fflush(f);&lt;br /&gt;
  fclose(f);&lt;br /&gt;
  /* avoid flooding kmsg and having msgs suppressed; 20msgs/sec */&lt;br /&gt;
  usleep(50000);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[]) {&lt;br /&gt;
 /*** variables */&lt;br /&gt;
&lt;br /&gt;
 int i;&lt;br /&gt;
 int   fd = 0; /* file descriptor */&lt;br /&gt;
 unsigned long mountflags;&lt;br /&gt;
&lt;br /&gt;
 /* kernel command line */&lt;br /&gt;
 off_t cmdline_size;&lt;br /&gt;
 char* cmdline; /* to be malloc 4096B */&lt;br /&gt;
 char* cmdline_end;&lt;br /&gt;
 char* temp_end;&lt;br /&gt;
 char* src_msg; /* default or cmdline */&lt;br /&gt;
 int flag_param_missing = 0;&lt;br /&gt;
&lt;br /&gt;
 /* use to hold contents of a misc /proc/&amp;lt;file&amp;gt; */&lt;br /&gt;
 char* miscproc_buff; /* to be malloc 4096B */&lt;br /&gt;
 off_t miscproc_size;&lt;br /&gt;
&lt;br /&gt;
 /* note about environ, argv, and kernel cmdline for init:&lt;br /&gt;
  *   environ is not defined for init&lt;br /&gt;
  *   only argv[0] is set for init&lt;br /&gt;
  *   kernel command line parameters are accessed&lt;br /&gt;
  *   at /proc/cmdline&lt;br /&gt;
  */&lt;br /&gt;
&lt;br /&gt;
 /* kernel parameters expected to be name=value */&lt;br /&gt;
 /* do not use quotes or spaces in parameters   */&lt;br /&gt;
 /* you can add more params somwhere after root= */&lt;br /&gt;
 struct nv { char* n; char* v; char* v_end; int req; int src; };&lt;br /&gt;
 struct nv param[] = {&lt;br /&gt;
   { &amp;quot;root=&amp;quot;,       NULL, NULL, PARAM_REQ_YES, PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;rootfstype=&amp;quot;, NULL, NULL, PARAM_REQ_YES, PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;mountopt=&amp;quot;,   NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;init=&amp;quot;,       NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;runlevel=&amp;quot;,   NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;console=&amp;quot;,    NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT }&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
   ,&lt;br /&gt;
   { &amp;quot;zpool_import_name=&amp;quot;,    NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;zpool_import_guid=&amp;quot;,    NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;zpool_import_newname=&amp;quot;, NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;zpool_import_force=&amp;quot;,   NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT }&lt;br /&gt;
#endif&lt;br /&gt;
 };&lt;br /&gt;
 enum {&lt;br /&gt;
	 iroot,&lt;br /&gt;
	 irootfstype,&lt;br /&gt;
	 imountopt,&lt;br /&gt;
	 iinit,&lt;br /&gt;
	 irunlevel,&lt;br /&gt;
	 iconsole,&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
	 izpool_import_name,&lt;br /&gt;
	 izpool_import_guid,&lt;br /&gt;
	 izpool_import_newname,&lt;br /&gt;
	 izpool_import_force,&lt;br /&gt;
#endif&lt;br /&gt;
	 ilastparam&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
 libzfs_handle_t* libzfs = NULL;&lt;br /&gt;
 importargs_t iargs = { 0 };&lt;br /&gt;
 nvlist_t* pools = NULL;&lt;br /&gt;
 nvpair_t* pool = NULL;&lt;br /&gt;
 nvlist_t* config = NULL;&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
 /*** program */&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;foobarz-init, version %s: booting initramfs.\n&amp;quot;, FOOBARZ_INIT_VERSION);&lt;br /&gt;
&lt;br /&gt;
 cmdline       = (char*) malloc(4096);&lt;br /&gt;
 miscproc_buff = (char*) malloc(4096);&lt;br /&gt;
 if( (cmdline == NULL) || (miscproc_buff == NULL) ) {&lt;br /&gt;
   printk(&amp;quot;Unable to allocate buffer memory: malloc: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount proc /proc&lt;br /&gt;
  *  note: some /dev devices symlink into /proc&lt;br /&gt;
  *  proc contains info about processes, including cmdline etc. */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount proc /proc\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;proc&amp;quot;, &amp;quot;/proc&amp;quot;, &amp;quot;proc&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
   printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
   printk(&amp;quot;Mount proc successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount devtmpfs /dev&lt;br /&gt;
  *  note: This simple init program works if your root device is made from devices&lt;br /&gt;
  *  that are available by default in devtmpfs, such as /dev/sd*&lt;br /&gt;
  *&lt;br /&gt;
  *  For zfs, your root zfs pool should be created with default device nodes and&lt;br /&gt;
  *  then it should be mountable by this simple init program.&lt;br /&gt;
  *&lt;br /&gt;
  *  udev may be needed to configure device nodes and symlinks required&lt;br /&gt;
  *  to access a root device configuration made with such nodes and symlinks.&lt;br /&gt;
  *  If you need udevd, you can include it into your initramfs-source and&lt;br /&gt;
  *  modify this program to run it before attempting to mount your root device.&lt;br /&gt;
  *  However, if udevd is needed, a significant number of userspace programs may also be&lt;br /&gt;
  *  required by rules in /lib/udev/. You could install busybox + udev (about 5MB) or&lt;br /&gt;
  *  coreutils + util-linux + bash + udev (about 25MB) into initramfs-source. But, at that&lt;br /&gt;
  *  point you'd have ash or bash and many tools that are easier to use than this&lt;br /&gt;
  *  simple init program; it would then be easy to have /init as #!/bin/&amp;lt;b&amp;gt;ash script. */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount devtmpfs /dev\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;devtmpfs&amp;quot;, &amp;quot;/dev&amp;quot;, &amp;quot;devtmpfs&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
   printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
   printk(&amp;quot;Mount devtmpfs successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount sysfs /sys&lt;br /&gt;
  *  note: some kernel modules try to access /sys with userspace helpers to echo values into /sys variables;&lt;br /&gt;
  *  such modules expect a minimal userspace that contains coreutils or busybox */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount sysfs /sys\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;sysfs&amp;quot;, &amp;quot;/sys&amp;quot;, &amp;quot;sysfs&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
   printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
   printk(&amp;quot;Mount sysfs successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* process kernel command line */&lt;br /&gt;
 fd = open(&amp;quot;/proc/cmdline&amp;quot;, O_RDONLY);&lt;br /&gt;
 if( fd == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Cannot open /proc/cmdline: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 /* note, on /proc fs:&lt;br /&gt;
  *       lseek likely always returns error&lt;br /&gt;
  *       stat likely always returns st_size = 0&lt;br /&gt;
  *   so determining size of /proc file means just reading it;&lt;br /&gt;
  *   you have to read /proc files according to their documented&lt;br /&gt;
  *   maximum sizes; this is probably for performance reasons */&lt;br /&gt;
 cmdline_size = read(fd, cmdline, 4095);&lt;br /&gt;
 if( cmdline_size == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Failed to read /proc/cmdline: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 close(fd);&lt;br /&gt;
&lt;br /&gt;
 /* cmdline may be newline + null terminated, but make it null + null */&lt;br /&gt;
 cmdline[cmdline_size] = '\0';&lt;br /&gt;
 if( cmdline[cmdline_size-1] == '\n' ) {&lt;br /&gt;
   cmdline[cmdline_size-1] = '\0';&lt;br /&gt;
   cmdline_size--;&lt;br /&gt;
   cmdline_end = cmdline + cmdline_size;&lt;br /&gt;
 }&lt;br /&gt;
 printk(&amp;quot;Kernel cmdline size: %i\n&amp;quot;, cmdline_size);&lt;br /&gt;
 printk(&amp;quot;Kernel cmdline: \&amp;quot;%s\&amp;quot;\n&amp;quot;, cmdline);&lt;br /&gt;
&lt;br /&gt;
 /* find v and v_end of values in cmdline */&lt;br /&gt;
 for( i=iroot; i&amp;lt;ilastparam; i++ ) {&lt;br /&gt;
   param[i].v = strstr(cmdline, param[i].n);&lt;br /&gt;
   if( param[i].v != NULL ) {&lt;br /&gt;
     param[i].src = PARAM_SRC_CMDLINE;&lt;br /&gt;
     while( *(param[i].v) != '=' ) param[i].v++;&lt;br /&gt;
     param[i].v++;&lt;br /&gt;
     temp_end = param[i].v;&lt;br /&gt;
     while( !( (*temp_end == ' ') ||&lt;br /&gt;
               (*temp_end == '\n') ||&lt;br /&gt;
               (temp_end == cmdline_end)&lt;br /&gt;
	     ) ) temp_end++;&lt;br /&gt;
     if( temp_end == param[i].v ) {&lt;br /&gt;
       printk(&amp;quot;Kernel parameter %s: value missing.\n&amp;quot;, param[i].n);&lt;br /&gt;
       param[i].v = NULL;&lt;br /&gt;
     } else param[i].v_end = temp_end;&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 for( i=iroot; i&amp;lt;ilastparam; i++ ) {&lt;br /&gt;
   /* terminate value strings */&lt;br /&gt;
   if( param[i].v_end != NULL ) *(param[i].v_end) = '\0';&lt;br /&gt;
   /* set defaults if no value on cmdline */&lt;br /&gt;
   if( param[i].v == NULL ) {&lt;br /&gt;
     param[i].src = PARAM_SRC_DEFAULT;&lt;br /&gt;
     if( param[i].req == PARAM_REQ_YES ) flag_param_missing = 1;&lt;br /&gt;
     switch(i) {&lt;br /&gt;
       case iroot      : param[i].v = &amp;quot;&amp;lt;missing required param&amp;gt;&amp;quot; ; break;&lt;br /&gt;
       case irootfstype: param[i].v = &amp;quot;&amp;lt;missing required param&amp;gt;&amp;quot; ; break;&lt;br /&gt;
       case imountopt  : param[i].v = &amp;quot;ro&amp;quot;        ; break;&lt;br /&gt;
       case iinit      : param[i].v = &amp;quot;/sbin/init&amp;quot;; break;&lt;br /&gt;
       case irunlevel  : param[i].v = &amp;quot;3&amp;quot;         ; break;&lt;br /&gt;
       case iconsole   : param[i].v = &amp;quot;console&amp;quot;   ; break;&lt;br /&gt;
       default         : param[i].v = NULL;&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
   if(param[i].src == PARAM_SRC_DEFAULT) src_msg = &amp;quot;default&amp;quot;;&lt;br /&gt;
   else src_msg = &amp;quot;cmdline&amp;quot;;&lt;br /&gt;
   printk(&amp;quot;Using %s \&amp;quot;%s\&amp;quot; (source: %s)\n&amp;quot;, param[i].n, param[i].v, src_msg);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 if( flag_param_missing ) {&lt;br /&gt;
   printk(&amp;quot;Aborting boot process: missing required kernel parameter(s).\n&amp;quot;);&lt;br /&gt;
   return EX_USAGE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* generic nv pair kernel cmdline processing finished&lt;br /&gt;
  *  now, examine specific params for defaults and correctness */&lt;br /&gt;
&lt;br /&gt;
 /* param[irootfstype]: can be checked against /proc/filesystems: */&lt;br /&gt;
 fd = open(&amp;quot;/proc/filesystems&amp;quot;, O_RDONLY);&lt;br /&gt;
 if( fd == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Cannot open /proc/filesystems: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 miscproc_size = read(fd, miscproc_buff, 4095);&lt;br /&gt;
 if( miscproc_size == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Failed to read /proc/filesystems: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 close(fd);&lt;br /&gt;
 if( strstr(miscproc_buff, param[irootfstype].v) == NULL ) {&lt;br /&gt;
   printk(&amp;quot;%s \&amp;quot;%s\&amp;quot;: filesystem type not available.\n&amp;quot;, param[irootfstype].n, param[irootfstype].v);&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* zfs-specific */&lt;br /&gt;
 if( strcmp(param[irootfstype].v, &amp;quot;zfs&amp;quot;) == 0 ) {&lt;br /&gt;
   if( access(&amp;quot;/etc/zfs/zpool.cache&amp;quot;, F_OK) == 0 )&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/zfs/zpool.cache is present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
   else&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/zfs/zpool.cache not present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
&lt;br /&gt;
   if( access(&amp;quot;/etc/hostid&amp;quot;, F_OK) == 0 )&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/hostid is present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
   else&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/hostid not present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
   /* zpool import */&lt;br /&gt;
   if( (param[izpool_import_name].v != NULL) || (param[izpool_import_guid].v != NULL) ) {&lt;br /&gt;
	printk(&amp;quot;zpool_import: import requested.\n&amp;quot;);&lt;br /&gt;
	if( (param[izpool_import_name].v != NULL) &amp;amp;&amp;amp; (param[izpool_import_guid].v != NULL) ) {&lt;br /&gt;
		printk(&amp;quot;zpool_import: given both pool name and guid; using guid.\n&amp;quot;);&lt;br /&gt;
		param[izpool_import_name].v = NULL;&lt;br /&gt;
	}&lt;br /&gt;
	if( param[izpool_import_name].v != NULL )&lt;br /&gt;
		printk(&amp;quot;zpool_import: pool name: %s\n&amp;quot;, param[izpool_import_name].v );&lt;br /&gt;
	else&lt;br /&gt;
		printk(&amp;quot;zpool_import: pool guid: %s\n&amp;quot;, param[izpool_import_guid].v );&lt;br /&gt;
&lt;br /&gt;
	iargs.path = NULL;&lt;br /&gt;
	iargs.paths = 0;&lt;br /&gt;
	iargs.poolname = param[izpool_import_name].v;&lt;br /&gt;
	if( param[izpool_import_guid].v != NULL )&lt;br /&gt;
		iargs.guid = strtoull(param[izpool_import_guid].v, NULL, 10);&lt;br /&gt;
	else&lt;br /&gt;
		iargs.guid = 0;&lt;br /&gt;
	iargs.cachefile = NULL;&lt;br /&gt;
	if( (param[izpool_import_force].v != NULL) &amp;amp;&amp;amp; (strcmp(param[izpool_import_force].v, &amp;quot;1&amp;quot;) == 0) ) {&lt;br /&gt;
		iargs.can_be_active = 1;&lt;br /&gt;
		printk(&amp;quot;zpool_import: import forced.\n&amp;quot;);&lt;br /&gt;
	} else {&lt;br /&gt;
		iargs.can_be_active = 0;&lt;br /&gt;
		printk(&amp;quot;zpool_import: import not forced.\n&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
	iargs.unique = 1;&lt;br /&gt;
	iargs.exists = 1;&lt;br /&gt;
&lt;br /&gt;
	printk(&amp;quot;zpool_import: init libzfs.\n&amp;quot;);&lt;br /&gt;
	libzfs = libzfs_init();&lt;br /&gt;
	printk(&amp;quot;zpool_import: searching for pool.\n&amp;quot;);&lt;br /&gt;
	pools = zpool_search_import(libzfs, &amp;amp;iargs);&lt;br /&gt;
	if( (pools == NULL) || nvlist_empty(pools) )&lt;br /&gt;
		printk(&amp;quot;zpool_import: pool not available for import, or already imported by cachefile.\n&amp;quot;);&lt;br /&gt;
	else {&lt;br /&gt;
		printk(&amp;quot;zpool_import: getting pool information.\n&amp;quot;);&lt;br /&gt;
		pool = nvlist_next_nvpair(pools, pool);&lt;br /&gt;
		printk(&amp;quot;zpool_import: getting pool configuration.\n&amp;quot;);&lt;br /&gt;
		nvpair_value_nvlist(pool, &amp;amp;config);&lt;br /&gt;
		printk(&amp;quot;zpool_import: attempting pool import.\n&amp;quot;);&lt;br /&gt;
		if( zpool_import(libzfs, config, param[izpool_import_newname].v, NULL) != 0 ) {&lt;br /&gt;
			printk(&amp;quot;zpool_import: import failed.\n&amp;quot;);&lt;br /&gt;
			printk(&amp;quot;zpool_import: error description: %s\n&amp;quot;, libzfs_error_description(libzfs) );&lt;br /&gt;
			printk(&amp;quot;zpool_import: error action: %s\n&amp;quot;, libzfs_error_action(libzfs) );&lt;br /&gt;
		} else  printk(&amp;quot;zpool_import: import successful.\n&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
	printk(&amp;quot;zpool_import: fini libzfs.\n&amp;quot;);&lt;br /&gt;
	libzfs_fini(libzfs);&lt;br /&gt;
   }&lt;br /&gt;
#endif /* zpool_import */&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 if(      strcmp(param[imountopt].v, &amp;quot;ro&amp;quot;) == 0 ) mountflags = MS_RDONLY;&lt;br /&gt;
 else if( strcmp(param[imountopt].v, &amp;quot;rw&amp;quot;) == 0 ) mountflags = 0;&lt;br /&gt;
 else {&lt;br /&gt;
   printk(&amp;quot;%s \&amp;quot;%s\&amp;quot;: invalid parameter value; defaulting to \&amp;quot;ro\&amp;quot;.\n&amp;quot;, param[imountopt].n, param[imountopt].v);&lt;br /&gt;
   mountflags = MS_RDONLY;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* param[iroot]: nothing to check; if user gives bad root=device then mount fails */&lt;br /&gt;
&lt;br /&gt;
 /* try to mount root=device at /mnt&lt;br /&gt;
  *&lt;br /&gt;
  * note: for zfs, if a copy of /etc/zfs/zpool.cache (when pool is imported) is put in initramfs-source, then&lt;br /&gt;
  * the zfs module can read it and automatically import the pools described in the cache file; the imported&lt;br /&gt;
  * pools can be available to mount here if they were created using standard device names, otherwise&lt;br /&gt;
  * udevd may be required to run before mounting the pool */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount -t %s -o %s %s /mnt.\n&amp;quot;, param[irootfstype].v, param[imountopt].v, param[iroot].v);&lt;br /&gt;
 if( mount(param[iroot].v, &amp;quot;/mnt&amp;quot;, param[irootfstype].v, mountflags, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 printk(&amp;quot;%s mounted successfully.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
&lt;br /&gt;
 /* check to see if the mounted root filesystem has an executable init program */&lt;br /&gt;
 chdir(&amp;quot;/mnt&amp;quot;);&lt;br /&gt;
 if( access(param[iinit].v+1, X_OK) != 0 ) {&lt;br /&gt;
   chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
   printk(&amp;quot;access X_OK: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   printk(&amp;quot;The init program /mnt/%s is not present or not executable.\n&amp;quot;, param[iinit].v+1);&lt;br /&gt;
   printk(&amp;quot;Aborting boot process: no init program.\n&amp;quot;);&lt;br /&gt;
   printk(&amp;quot;Unmounting %s.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
   if( umount(&amp;quot;/mnt&amp;quot;) == -1 ) {&lt;br /&gt;
     printk(&amp;quot;umount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
     printk(&amp;quot;Failed to umount %s.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
   } else printk(&amp;quot;Successfully unmounted %s.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
 printk(&amp;quot;Init program /mnt/%s is present and executable.\n&amp;quot;, param[iinit].v+1);&lt;br /&gt;
&lt;br /&gt;
 /* switch the root / from initramfs to the mounted new root device at /mnt.&lt;br /&gt;
  *&lt;br /&gt;
  * note: after this switch, it is not possible to access the initramfs files anymore,&lt;br /&gt;
  * yet they consume ram memory unless they are deleted here before switching.&lt;br /&gt;
  * Any programs that are run after clearing the initramfs and switching root must exist on the new root.&lt;br /&gt;
  * This program may safely delete itself (/init) since it is already in ram and executing.&lt;br /&gt;
  * If you have installed additional files and programs in initramfs that consume significant ram,&lt;br /&gt;
  * then you need to insert additional code here to delete those files (carefully). */&lt;br /&gt;
&lt;br /&gt;
 /* delete files off of initramfs to free ram memory */&lt;br /&gt;
 printk(&amp;quot;Freeing memory from initramfs...\n&amp;quot;);&lt;br /&gt;
 if( unlink(argv[0]) != 0 ) printk(&amp;quot;unlink %s: %s\n&amp;quot;, argv[0], strerror(errno));&lt;br /&gt;
 else printk(&amp;quot;%s %s&amp;quot;, argv[0], &amp;quot;deleted from initramfs.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 /* switch root */&lt;br /&gt;
 printk(&amp;quot;Beginning switch root procedure.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(1) Attempting cmd: mount --move /dev /mnt/dev \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/dev&amp;quot;, &amp;quot;/mnt/dev&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(2) Attempting cmd: mount --move /proc /mnt/proc \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/proc&amp;quot;, &amp;quot;/mnt/proc&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(3) Attempting cmd: mount --move /sys /mnt/sys \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/sys&amp;quot;, &amp;quot;/mnt/sys&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(4) Attempting cmd: chdir /mnt \n&amp;quot;);&lt;br /&gt;
 if( chdir(&amp;quot;/mnt&amp;quot;) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: chdir: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(5) Attempting cmd: mount --move . / \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;.&amp;quot;, &amp;quot;/&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(6) Attempting cmd: chroot . \n&amp;quot;);&lt;br /&gt;
 if( chroot(&amp;quot;.&amp;quot;) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: chroot: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(7) Attempting cmd: chdir / \n&amp;quot;);&lt;br /&gt;
 if( chdir(&amp;quot;/&amp;quot;) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: chdir: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 printk(&amp;quot;Completed switch root procedure.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 /* check for &amp;quot;console=&amp;quot; kernel parameter and switch&lt;br /&gt;
  *  stdin, stdout, and stderr to named console device&lt;br /&gt;
  */&lt;br /&gt;
 if( param[iconsole].src == PARAM_SRC_CMDLINE ) {&lt;br /&gt;
   printk(&amp;quot;Console redirection to device %s requested.\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
   /* expect only basename of console device (e.g., ttyS0), so chdir /dev */&lt;br /&gt;
   chdir(&amp;quot;/dev&amp;quot;);&lt;br /&gt;
   if( access(param[iconsole].v, F_OK ) == 0 ) {&lt;br /&gt;
     printk(&amp;quot;Opening stdin, stdout, and stderr on %s.\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
     close(0);&lt;br /&gt;
     open(param[iconsole].v, O_RDWR);&lt;br /&gt;
     dup2(0, 1);&lt;br /&gt;
     dup2(0, 2);&lt;br /&gt;
   } else {&lt;br /&gt;
     printk(&amp;quot;access F_OK: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
     printk(&amp;quot;Could not access device: %s!\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
     printk(&amp;quot;Console redirection to device %s aborted!\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
   }&lt;br /&gt;
   chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;Execing: \&amp;quot;%s %s\&amp;quot; to boot mounted root system.\n&amp;quot;, param[iinit].v, param[irunlevel].v);&lt;br /&gt;
&lt;br /&gt;
 /* free resources held to this point */&lt;br /&gt;
 free(cmdline);&lt;br /&gt;
 free(miscproc_buff);&lt;br /&gt;
&lt;br /&gt;
 if( execl(param[iinit].v, param[irunlevel].v, (char *) NULL ) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: execl: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If foobarz-init is updated, you can find the latest version at [https://github.com/foobarz/foobarz-init github].&lt;br /&gt;
&lt;br /&gt;
The foobarz-init program can be compiled two ways as of v1.1.1. First, the simpler compile that does not support zpool_import but does support importing pools using a /etc/zfs/zpool.cache file in the initramfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gcc --static init.c -o init&lt;br /&gt;
strip init&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The second way to compile it adds support for zpool_import so that you do not have to include a &amp;lt;code&amp;gt;/etc/zfs/zpool.cache&amp;lt;/code&amp;gt; file in the initramfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gcc -static -DINCLUDE_ZPOOL_IMPORT \&lt;br /&gt;
     foobarz-init.c -include /usr/src/zfs-0.6.0-rc10/3.2.28/zfs_config.h \&lt;br /&gt;
    -o init \&lt;br /&gt;
    -I /usr/include/libspl -I /usr/include/libzfs \&lt;br /&gt;
    -lzfs -lnvpair -lzpool -luutil -luuid -lrt -lz -lm -lpthread \&lt;br /&gt;
    -I /usr/include/tirpc \&lt;br /&gt;
    -ltirpc&lt;br /&gt;
strip init&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Dependencies required before you can compile this second way:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Install [http://sourceforge.net/projects/libtirpc/ libtirpc]. The glibc package has removed the RPC-related functions from the static libc. The libtirpc is the new replacement as a separate library. You can make your own libtirpc package and install it to resolve these RPC-related functions. Without this, the compile fails because it cannot find many &amp;quot;xdr&amp;quot; functions.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Reinstall the [ftp://slackware.mirrors.tds.net/pub/slackware/slackware64-current/source/a/util-linux/ util-linux] package with static libraries enabled. Edit the &amp;lt;code&amp;gt;util-linux.SlackBuild&amp;lt;/code&amp;gt; and remove the line &amp;lt;code&amp;gt;--disable-static&amp;lt;/code&amp;gt;, then build it and use upgradepkg to install the new package. This resolves linking static to libuuid.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;code&amp;gt;zfs_config.h&amp;lt;/code&amp;gt; can be found in the kernel source when you have installed the builtin spl/zfs configuration; for example at &amp;lt;code&amp;gt;/usr/src/linux-3.2.27b/zfs_config.h&amp;lt;/code&amp;gt;. If you currently have installed the modular spl/zfs configuration, &amp;lt;code&amp;gt;zfs_config.h&amp;lt;/code&amp;gt; is found where the zfs module headers are installed; for example at &amp;lt;code&amp;gt;/usr/src/zfs-0.6.0-rc10/3.2.28/zfs_config.h&amp;lt;/code&amp;gt;. Wherever it is, &amp;lt;code&amp;gt;-include&amp;lt;/code&amp;gt; it as shown in the example gcc line above. zfs_config.h seems misplaced because it would seem that using libzfs shouldn't depend on modules header files.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;You may need to install the spl and zfs packages configured for --enable-linux-builtin=yes before compiling and linking to libzfs to make sure you are using the version of libzfs intended for builtin modules in case a difference between the two configurations exists. Currently, there seems to be no difference in the libzfs for either modular or builtin modules, but later there could be at least a small difference for detection of modules to load or builtin already. You may see a message that the ZFS modules stack load failed, but it can be ignored since the modules are builtin; this is just libzfs trying to load the modules even though they are builtin.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
With these dependencies, you can probably compile static with the zpool_import support. The exact location of &amp;quot;zfs_config.h&amp;quot; may vary depending on your zfs and kernel versions, so adjust accordingly.&lt;br /&gt;
&lt;br /&gt;
Read the foobarz-init source code to see how it uses kernel parameters. The params &amp;lt;code&amp;gt;root&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;rootfstype&amp;lt;/code&amp;gt; are always required to tell init what root pool name to mount and the filesystem type (e.g. zfs).&lt;br /&gt;
&lt;br /&gt;
For the zpool_import support: &amp;lt;code&amp;gt;zpool_import_name=poolname&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;zpool_import_guid=&amp;lt;guid of a pool&amp;gt;&amp;lt;/code&amp;gt; tells what pool to import. You can also import the pool with a new different name by also using &amp;lt;code&amp;gt;zpool_import_newname=newpoolname&amp;lt;/code&amp;gt;. If the import is not working, &amp;lt;code&amp;gt;zpool_import_force=1&amp;lt;/code&amp;gt; can be used to force import even if ZFS thinks the pool may be in use by another system.&lt;br /&gt;
&lt;br /&gt;
However you import the pool, either using zpool.cache or zpool_import support, the kernel param &amp;lt;code&amp;gt;root=&amp;lt;your poolname or newpoolname&amp;gt;&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;rootfstype=zfs&amp;lt;/code&amp;gt; needs to be given also. The zpool_import only imports, it does not say what to mount. What to mount is still told using root= and rootfstype=.&lt;br /&gt;
&lt;br /&gt;
Now copy the compiled static program into the initramfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp init /boot/initramfs-source/init&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Build and install kernel:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make -j8&lt;br /&gt;
make -j8 modules_install&lt;br /&gt;
cp arch/x86/boot/bzImage /boot/vm3.2.27b&lt;br /&gt;
cp System.map /boot/System.map-vm3.2.27b&lt;br /&gt;
# add new lilo menu entry for vm3.2.27b kernel&lt;br /&gt;
vi /etc/lilo.conf&lt;br /&gt;
  image = /boot/vm3.2.27b&lt;br /&gt;
   label = vm3.2.27b&lt;br /&gt;
   addappend = &amp;quot; spl.spl_hostid=0x007f0100 zfs.spa_config_path=/etc/zfs/zpool.cache root=zfs-root rootfstype=zfs&amp;quot;&lt;br /&gt;
lilo&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Note: If &amp;lt;code&amp;gt;spl.spl_hostid=0x007f0100&amp;lt;/code&amp;gt; is not included in addappend, then during boot SPL module will attempt to read /etc/hostid or run a user-space helper to write the &amp;lt;code&amp;gt;hostid&amp;lt;/code&amp;gt; into &amp;lt;code&amp;gt;/proc/sys/kernel/spl/hostid&amp;lt;/code&amp;gt;. Reading /etc/hostid fails unless you use foobarz-chhostid and make the file and copy it into /boot/initramfs-source/etc/hostid. The helper will fail because no &amp;lt;code&amp;gt;sh&amp;lt;/code&amp;gt; shell and no &amp;lt;code&amp;gt;hostid&amp;lt;/code&amp;gt; command are installed in the initramfs. The default hostid becomes 0xffffffff, which is considered an invalid hostid.&lt;br /&gt;
&lt;br /&gt;
Congrats! If this works, you can select the &amp;quot;vm3.2.27b&amp;quot; lilo entry to boot. If you are using the zpool_import support in the init program, you need to add at least the &amp;lt;code&amp;gt;zpool_import_name=zfs-root&amp;lt;/code&amp;gt; param to the addappend line in lilo.conf.&lt;br /&gt;
&lt;br /&gt;
Notes on kernel params (lilo append and addappend lines): root= and rootfstype= are used by both foorbarz-init and mkinitrd. The &amp;quot;ro&amp;quot; param is not used by foobarz-init, so instead use: mountopt=ro|rw. See &amp;quot;modinfo spl&amp;quot; and &amp;quot;modinfo zfs&amp;quot; to see all of the options those modules can take on the kernel command line. Notice the &amp;lt;code&amp;gt;spl.spl_hostid=0x007f0100&amp;lt;/code&amp;gt; param that works around the hostid mismatch problem while trying to import a pool; this param and hostname/ip set to use local loopback 127.0.0.1 in etc/hosts etc/HOSTNAME in initramfs will work most of the time, and if not the pool import needs to be forced.&lt;br /&gt;
&lt;br /&gt;
Notes on the spl and zfs packages to install: &amp;lt;i&amp;gt;If&amp;lt;/i&amp;gt; you have errors using zfs and zpool commands on booted system with builtin modules, then upgrade/switch to the 0.6.0rc10_3.2.27b builds, or you can make a custom package with the binaries renamed like zpoolb, zfsb etc for builtin.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
Using qemu's -nographic serial console (/usr/share/qemu/sgabios.bin): If you have a boot problem, you might want to run in qemu's -nographic console mode:&lt;br /&gt;
&lt;br /&gt;
First, edit /etc/inittab, and uncomment the line for local serial ports runlevel &amp;quot;s1&amp;quot; (ttyS0) for serial console login support. This is done in the guest (host does not need this):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Local serial lines:&lt;br /&gt;
s1:12345:respawn:/sbin/agetty -L ttyS0 38400 linux&lt;br /&gt;
#s1:12345:respawn:/sbin/agetty -L ttyS0 9600 vt100&lt;br /&gt;
#s2:12345:respawn:/sbin/agetty -L ttyS1 9600 vt100&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Second, edit /etc/securetty, and uncomment ttyS0 line:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ttyS0&lt;br /&gt;
#ttyS1&lt;br /&gt;
# ...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
You cannot login on ttyS0 without this change even though you get the login prompt!&lt;br /&gt;
&lt;br /&gt;
Then, run qemu such as:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
qemu-kvm &amp;lt;all regular options&amp;gt; -nographic -option-rom sgabios.bin,bootindex=0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Wait for the lilo prompt, it may take several seconds show up in this mode.&lt;br /&gt;
&lt;br /&gt;
In the lilo menu, select your kernel image with builtin spl/zfs, and use kernel params such as:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
boot: vm3.2.27b console=ttyS0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
At the lilo prompt, use kernel parameter: console=ttyS0 (do NOT say /dev/ttS0). Passing runlevel=s1 does not appear to be necessary.&lt;br /&gt;
&lt;br /&gt;
When you are in qemu's serial mode, the interface is a little different than in the normal graphical mode: use keypresses:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ctrl-a h    # for help&lt;br /&gt;
ctrl-a c    # toggle access to (QEMU) console / back to emulation&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If you cannot get a login: prompt, try ctrl-a c, then do (QEMU) sendkey ctrl-alt-delete. This will reboot cleanly back to lilo, then you can do (QEMU) quit.&lt;br /&gt;
&lt;br /&gt;
Once you login to the guest, the terminal size needs adjustment. On your host, in another xterm sized the same as your guest console terminal, get the size of the terminal:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo $LINES&lt;br /&gt;
echo $COLUMNS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Now, back in the guest terminal of same size:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export LINES &amp;lt;lines&amp;gt;&lt;br /&gt;
export COLUMNS &amp;lt;columns&amp;gt;&lt;br /&gt;
stty cols $COLUMNS rows $LINES&lt;br /&gt;
exec bash&lt;br /&gt;
reset&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
So, you set the environment variables and also set them with stty. Then, restart bash (exec, or else it is a child shell process).&lt;br /&gt;
&lt;br /&gt;
BECAREFUL not to start qemu twice on the same ZFS guest! Two simultaneous running qemu on the same ZFS will corrupt the pool and it will NOT recover - you lose your whole installation! Before running qemu, check ps -A, look for an already running qemu process incase it somehow entered into the background!&lt;br /&gt;
&lt;br /&gt;
BECAREFUL when using -nographic ttyS0 that you are not doing commands on the HOST! Only use -nographic to see kernel problems. Use regular console if booting is working normally.&lt;br /&gt;
&lt;br /&gt;
To use the qemu -drive if=scsi option, the linux module sym53c8xx should be loaded in the guest. You may need to use the qemu option:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-option-rom 8xx_64.rom,bootindex=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The file 8xx_64.rom used to be inside qemu, but in new versions it is missing. You can download it:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
wget http://www.lsi.com/downloads/Public/Host%20Bus%20Adapters/Host%20Bus%20Adapters%20Common%20Files/lsi_bios.zip&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Extract the zip and place 8xx_64.rom in /usr/share/qemu/.&lt;br /&gt;
&lt;br /&gt;
Good luck!&lt;/div&gt;</description>
			<pubDate>Fri, 14 Sep 2012 14:29:31 GMT</pubDate>
			<dc:creator>Foobarz</dc:creator>
			<comments>https://www.slackwiki.com/Talk:ZFS_root_(builtin)</comments>
		</item>
		<item>
			<title>ZFS root</title>
			<link>https://www.slackwiki.com/index.php?title=ZFS_root&amp;diff=793</link>
			<guid isPermaLink="false">https://www.slackwiki.com/index.php?title=ZFS_root&amp;diff=793</guid>
			<description>&lt;p&gt;Foobarz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Tutorials]]&lt;br /&gt;
If you have heard about the ZFS filesystem and you're curious to try it out, then you can try it on slackware64, thanks to the ZFSonLinux.org project!&lt;br /&gt;
&lt;br /&gt;
In this article, an example is shown of how to install slackware64 14.0 onto a ZFS root filesystem (zfs-root) inside a QEMU virtual machine for testing purposes. It is recommended that you install qemu and learn how to use it to test a ZFS installation before you decide to use it on real hardware. A slackbuild for qemu can be found on slackbuilds.org. If you have a processor that supports Intel VT-x or AMD AMD-V virtualization acceleration (try modprobe kvm-intel or modprobe kvm-amd), then use the slackbuild for qemu-kvm.&lt;br /&gt;
&lt;br /&gt;
This article isn't going to go into any detail on actually using ZFS or what kinds of installation options and settings might be optimal. This article just presents an example of how to get started with ZFS on slackware.&lt;br /&gt;
&lt;br /&gt;
At this time of writing, ZFSonLinux is at &amp;quot;release candidate&amp;quot; (version 0.6.0-rc10) development stage, and many issues can occur. See the ZFSonLinux.org web site and the issues tracker for an idea about the current issues. There is also an irc channel on irc.freenode.net, #zfsonlinux, for discussion of issues and help.&lt;br /&gt;
&lt;br /&gt;
Although not required, it is helpful to keep a local mirror of slackware64 on your system. Having a local mirror makes it easier to upgrade to slackware64-current or to patches/* in a release. To help manage your own local slackware mirror and generate your own CD and DVD slackware installers, see http://alien.slackbook.org/blog/local-slackware-mirror/.&lt;br /&gt;
&lt;br /&gt;
In this article, we use a slackware64-current DVD image file as the qemu cdrom device media for the installation of the slackware guest. This was tested at slackware64-current = slackware64 14.0rc2. You can obtain a slackware DVD image using a torrent, buy the DVD from slackware.com, or generate your own DVD image file using the mirror script. For an actual DVD, you can pass your DVD device (e.g., /dev/sr0) as the qemu cdrom device. For a DVD image file, pass the image file as the qemu cdrom device.&lt;br /&gt;
&lt;br /&gt;
The ZFSonLinux packages are not included in slackware at this time. There are two packages involved: spl and zfs. The first, spl, is &amp;quot;Solaris Porting Layer&amp;quot; and must be installed on the system before zfs can be compiled. The source code tarballs for these are at ZFSonLinux.org. At this time of writing, they are spl-0.6.0-rc10.tar.gz and zfs-0.6.0-rc10.tar.gz.&lt;br /&gt;
&lt;br /&gt;
At this point, it is assumed you have qemu installed, have obtained a slackware64-current/14.0 DVD, and have downloaded spl and zfs tarballs to your host system. The first step now is, if your host is not slackware64-current/14.0 (the same as the guest will be), then you need to create a minimal development slackware64 guest system in qemu for just the purpose of compiling and packaging the spl and zfs slackware packages and transferring a copy of these packages back onto your host system to use later to install onto zfs during the slackware install process.&lt;br /&gt;
&lt;br /&gt;
From this point onward, instructions become a bit terse and mostly limited to examples of the commands you might use to complete tasks. You are encouraged to examine what each command does by reading the command's man pages. For example, the command &amp;quot;man qemu&amp;quot; can show you most of what you need to know about running qemu on the command line.&lt;br /&gt;
&lt;br /&gt;
So, here's an example of how you might build the spl and zfs packages, starting in your home directory:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on host)&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir qemu&lt;br /&gt;
cd qemu&lt;br /&gt;
mkdir slackdevel&lt;br /&gt;
cd slackdevel&lt;br /&gt;
mkdir packages&lt;br /&gt;
cp ~/spl-*.tar.gz packages&lt;br /&gt;
cp ~/zfs-*.tar.gz packages&lt;br /&gt;
qemu-img create disk1.raw 10G&lt;br /&gt;
ln -s ~/slackware64-current-install-dvd.iso dvd.iso&lt;br /&gt;
qemu-kvm \&lt;br /&gt;
 -option-rom 8xx_64.rom,bootindex=1 \&lt;br /&gt;
 -no-quit \&lt;br /&gt;
 -no-shutdown \&lt;br /&gt;
 -boot order=cd,menu=on \&lt;br /&gt;
 -m 2G \&lt;br /&gt;
 -cpu host \&lt;br /&gt;
 -smp sockets=1,cores=4 \&lt;br /&gt;
 -net nic,model=e1000 -net user \&lt;br /&gt;
 -cdrom dvd.iso \&lt;br /&gt;
 -drive format=raw,media=disk,cache=none,aio=native,if=scsi,index=0,file=disk1.raw \&lt;br /&gt;
 -virtfs local,path=./packages/,security_model=none,mount_tag=hostpackages&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When you need to change boot to cd or disk, try changing &amp;quot;order=dc&amp;quot; or hitting F12 at boot prompt and select the CD/DVD boot option.&lt;br /&gt;
&lt;br /&gt;
Note: The support for booting drives using if=scsi is not included with current versions of qemu. Booting scsi requires the 8xx_64.rom option-rom, which can be downloaded at&lt;br /&gt;
[http://www.lsi.com/downloads/Public/Host%20Bus%20Adapters/Host%20Bus%20Adapters%20Common%20Files/lsi_bios.zip LSI.com]. Unzip it, and then:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp 8xx_64.rom /usr/share/qemu&lt;br /&gt;
# then run qemu-kvm with additional command line option: -option-rom 8xx_64.rom,bootindex=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Qemu should boot into the install-dvd, and now perform a very ordinary slackware64 install onto /dev/sda. Install d package set and most others, but package sets x, kde, xfce not really needed.&lt;br /&gt;
&lt;br /&gt;
First note: examples here use tools from the gptfdisk package (gdisk, sgdisk, cgdisk) to partition the disk with GUID partition table (GPT) format. GPT might not be too familiar to everyone, who mostly have only used MBR partitions with fdisk. In the slackware installations this author has tested in qemu, using GPT partitions has caused no problems with lilo or other tools used in slackware. GPT disk labels support creating up to 128 partitions and support disks larger than 2TB (the limit of MBR fdisk). LILO installs into the first 440 bytes on /dev/sda, inside a GPT &amp;quot;protective MBR&amp;quot; that serves to provide compatibility with MBR bootloaders like lilo. LILO uses LBA32 sector addressing and can see all 512-byte sectors inside the first 2TB of a disk. So long as the /boot partition is within the first 2TB of a disk, lilo can work on a disk larger than 2TB. Unlike the common default of fdisk to start the first partition at sector 63, which is not aligned with the 4KiB sector size of Advanced Format hard disks, gdisk's default is to start partitions at 2048 sector (1MiB) boundaries which are also 4KiB aligned. Using gdisk GPT works on all disks and is compatible with using Advanced Format hard disks larger than 2TB. More information about GPT disk label format can be found on wikipedia.org. For those that have used grub instead of lilo, grub installation is different with GPT than with MBR, and grub requires a GPT partition of type grub-bios or 0xEF02 &amp;quot;BIOS Boot Partition&amp;quot; of about 8MiB where it can install it's additional bootloader stages because grub cannot embed in sectors 1-62 on GPT where GPT keeps it's partition tables. On MBR, sectors 1-62 were normally reserved space for bootloaders to keep a 2nd stage.&lt;br /&gt;
&lt;br /&gt;
For this purpose of development guest, just create a simple 1-partition system, /dev/sda1, and do a simple slackware install on it. Don't bother with swap or separate /boot unless you want to:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on install-dvd)&lt;br /&gt;
cgdisk /dev/sda&lt;br /&gt;
setup&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When this simple development guest boots, login as root, and continue:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on qemu guest)&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir packages&lt;br /&gt;
mount hostpackages -t 9p -o trans=virtio packages&lt;br /&gt;
echo --prefix=/ --libexecdir=/usr/libexec --libdir=/lib64 --includedir=/usr/include --datarootdir=/usr/share &amp;gt; configure-options&lt;br /&gt;
mkdir src&lt;br /&gt;
cd src&lt;br /&gt;
&lt;br /&gt;
mkdir install&lt;br /&gt;
tar xvzf ~/packages/spl-*.tar.gz&lt;br /&gt;
cd spl-*&lt;br /&gt;
./configure $( cat ~/configure-options )&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../spl-&amp;lt;version&amp;gt;_&amp;lt;kernel_version&amp;gt;-x86_64-&amp;lt;build_id&amp;gt;.txz&lt;br /&gt;
(e.g., makepkg ../spl-0.6.0rc10_3.2.27-x86_64-1root.txz)&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
installpkg spl-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
cp spl-0.6.0rc10_3.2.27-x86_64-1root.txz ~/packages&lt;br /&gt;
&lt;br /&gt;
mkdir install&lt;br /&gt;
tar xvzf ~/packages/zfs-*.tar.gz&lt;br /&gt;
cd zfs-*&lt;br /&gt;
./configure $( cat ~/configure-options )&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../zfs-&amp;lt;version&amp;gt;_&amp;lt;kernel_version&amp;gt;-x86_64-&amp;lt;build_id&amp;gt;.txz&lt;br /&gt;
(e.g., makepkg ../zfs-0.6.0rc10_3.2.27-x86_64-1root.txz)&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
installpkg zfs-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
cp zfs-0.6.0rc10_3.2.27-x86_64-1root.txz ~/packages&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point spl and zfs packages are copied back to the host in the packages directory. Also, spl and zfs are installed in this simple development guest, so one could begin to experiment with zfs pools and datasets but while the root fs is whatever you made it during setup (probably the default, ext4). This development guest isn't really needed anymore, so it can be deleted:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
halt&lt;br /&gt;
(exit qemu: ctrl-alt-2 then enter quit at QEMU command prompt)&lt;br /&gt;
&lt;br /&gt;
(on host)&lt;br /&gt;
rm disk1.raw dvd.iso&lt;br /&gt;
mv packages ..&lt;br /&gt;
cd ..&lt;br /&gt;
rmdir slackdevel&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now that we have the spl and zfs packages on the host, it is possible to copy them into your local slackware64 mirror and then generate your own install DVD image that includes them. For example, change to the directory that contains the slackware README files, and create a &amp;quot;addon&amp;quot; directory and copy the spl and zfs slackware packages into there. Then, generate the DVD image using a command such as $( ./mirror-slackware-current.sh -i ) from where you have this script configured to maintain your local mirror. We can also just continue to access them inside the installer using qemu's virtfs option. When you are going to do a real installation onto real hardware, you need to generate and burn your own DVD that includes the packages.&lt;br /&gt;
&lt;br /&gt;
It is time to begin the installation of slackware64 on a ZFS root, assuming either you have regenerated dvd.iso with zfs packages in addon/* or we access the zfs packages while in the installer using qemu's virtfs to the host's packages directory. ZFS supports creating complex data storage configurations such as pools (similar to a volume group) backed by one or more of various kinds of virtual devices (similar to disks and raid arrays) and containing one or more datasets (similar to mounted filesystems, logical volume devices, or snapshots). But here, we keep it simple and will install on just a single disk device.&lt;br /&gt;
&lt;br /&gt;
Note: On a real ZFS installation, users will typically want to use the ZFS mirror or raidz virtual device (vdev) types for reliability against hard drive failures. For example, a good configuration might be to use a USB memory stick (and a backup stick) for /boot that is plugged into an on-motherboard &amp;quot;Type A&amp;quot; USB connector. Then, use four whole hard drives in a raidz2 vdev as the initial storage space in the root zpool. At a later time, to add more storage space, additional whole four-drive raidz2 vdevs of the same size could be added to the zpool. It is recommended to only add the same vdev type (disk, mirror, or raidz|1|2|3) and size to a zpool since zfs stripes across the vdevs, and vdevs of different types/sizes do not stripe together optimally. After adding a vdev to your zpool, you might need to copy the new /etc/zfs/zpool.cache to your initrd-tree or initramfs-source (and rebuild/reinstall them) if you are using the cachefile to import your zpool. Using mirror vdevs would be similar to a raid10. Using 4-disk raidz2 vdevs would give the same storage space as raid10 while fully reliable against any double-disk failure; however, the raidz2 parity calculations results in higher CPU usage and/or lower performance. Because raidz vdevs cannot be grown by adding hard drives to them, and vdevs in a zpool are striped, it is important with ZFS to decide what type and size of vdev will be used in a zpool as the units of add-on storage space; it could be difficult to alter this decision later. Finally, on a real installation with raidz, data scrub should be scheduled to actively search for &amp;quot;latent defects&amp;quot; on the hard drives so that unknown read/write errors do not become known later during a disk swap/rebuild and result in the zpool becoming faulted (lost).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on host)&lt;br /&gt;
mkdir slackzfs&lt;br /&gt;
mv packages slackzfs/&lt;br /&gt;
cd slackzfs&lt;br /&gt;
qemu-img create disk1.raw 10G&lt;br /&gt;
ln -s ~/slackware64-current-install-dvd.iso dvd.iso&lt;br /&gt;
qemu-kvm \&lt;br /&gt;
 -option-rom 8xx_64.rom,bootindex=1 \&lt;br /&gt;
 -no-quit \&lt;br /&gt;
 -no-shutdown \&lt;br /&gt;
 -boot order=cd,menu=on \&lt;br /&gt;
 -m 2G \&lt;br /&gt;
 -cpu host \&lt;br /&gt;
 -smp sockets=1,cores=4 \&lt;br /&gt;
 -net nic,model=e1000 -net user \&lt;br /&gt;
 -cdrom dvd.iso \&lt;br /&gt;
 -drive format=raw,media=disk,cache=none,aio=native,if=scsi,index=0,file=disk1.raw \&lt;br /&gt;
 -virtfs local,path=./packages/,security_model=none,mount_tag=hostpackages&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The install-dvd should boot, and then begin installation steps on the installer command line:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on install-dvd)&lt;br /&gt;
# mount the install-dvd&lt;br /&gt;
mkdir /dvd&lt;br /&gt;
mount /dev/sr0 /dvd&lt;br /&gt;
&lt;br /&gt;
# install coreutils, which provides the &amp;quot;hostid&amp;quot; command needed to load the spl module&lt;br /&gt;
installpkg /dvd/slackware64/a/coreutils-8.17-x86_64-1.txz&lt;br /&gt;
&lt;br /&gt;
# install kmod package which includes &amp;quot;depmod&amp;quot; command and others&lt;br /&gt;
installpkg /dvd/slackware64/a/kmod-9-x86_64-2.txz&lt;br /&gt;
depmod&lt;br /&gt;
&lt;br /&gt;
# install the full kernel modules so you can load 9p filesystem and use it if you want&lt;br /&gt;
# .. you might keep the zfs modules packages off the dvd and use a plain slack dvd&lt;br /&gt;
installpkg /dvd/slackware64/a/kernel-modules-*.txz&lt;br /&gt;
depmod&lt;br /&gt;
&lt;br /&gt;
# install bash and libtermcap because udev rules in zfs use bash scripts&lt;br /&gt;
installpkg /dvd/slackware64/a/bash-*.txz&lt;br /&gt;
installpkg /dvd/slackware64/l/libtermcap-*.txz&lt;br /&gt;
&lt;br /&gt;
# install spl and zfs that you have copied into the mirror before running the DVD creation&lt;br /&gt;
installpkg /dvd/addon/spl-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /dvd/addon/zfs-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
&lt;br /&gt;
#Or:&lt;br /&gt;
mkdir /packages&lt;br /&gt;
find /lib/modules/ | grep 9p&lt;br /&gt;
lsmod&lt;br /&gt;
# check that 9p modules load, mainly 9pnet_virtio&lt;br /&gt;
modprobe 9pnet_virtio&lt;br /&gt;
mount hostpackages -t 9p -o trans=virtio /packages&lt;br /&gt;
installpkg /packages/spl-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /packages/zfs-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
modprobe zfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now zfs tools: &amp;quot;zpool&amp;quot; and &amp;quot;zfs&amp;quot; should work in the live installer.&lt;br /&gt;
On the installer, there can be trouble seeing man pages, so install:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
installpkg /dvd/slackware64/ap/man-*.txz&lt;br /&gt;
installpkg /dvd/slackware64/ap/groff-*.txz&lt;br /&gt;
installpkg /dvd/slackware64/a/less-*.txz&lt;br /&gt;
export MANPATH=/usr/man:/usr/share/man&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The manual pages should be readable:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
man zpool&lt;br /&gt;
man zfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After seeing the man pages, we should be fully ready to continue to setup on ZFS.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(still on install-dvd)&lt;br /&gt;
ls -l /dev/sd*&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Make sure the disk devices you expect are there. We'll use sda and make boot (/boot on /dev/sda1) and root (/ on /dev/sda2) partitions.&lt;br /&gt;
&lt;br /&gt;
First, some background info: A ZFS filesystem is not supported by lilo as the filesystem containing /boot, which holds lilo's 2nd stage and the linux kernel files. The on-disk format of a ZFS filesystem is often a complex raid configuration where even if lilo understood ZFS it would likely require /boot to reside in only certain simple ZFS configurations to be plainly readable to lilo. As things are, a linux root installed in a partition with ZFS filesystem needs /boot to be on another partition with a filesystem that lilo understands, such as ext4 fs. In addition, because the spl and zfs modules are not built into the kernel, and the zfs startup requires some configuration to mount the zfs root, an initial ram/root filesystem (initrd) is needed. The initrd is a gzip compressed cpio archive file that contains a small linux root operating system that is decompressed into a ramfs block device at boot up and takes initial control of the system. The initrd contains an init script that configures devices in devtmpfs mounted at /dev. For example, if using mdadm, lvm, luks, losetup, and now zfs, this init script runs all the commands to create or start these devices (one of which is the root device), mounts the root device, and then transfers system control to the init script in the mounted root filesystem. The ramfs-based root environment on the booted install-dvd or booted initrd image (in rescue command line) are small slackware installations that exist only in ram and are temporary, but while inside them you can install, upgrade, and remove slackware packages inside them using the regular package management tools; this allows you access to any kernel modules and programs as needed inside these ramfs root. Packages can be installed, upgraded, or removed permanantly in the initrd image file to manage the programs and modules required during the initrd boot stage. Also from within these ramfs initial root environments, once the root device is mounted, chroot can be used to work on the mounted root system as if it were booted; this allows one to fix problems that are occuring in the root fs init scripts that cause normal booting to fail, or to install a kernel and/or modules etc. Now on to partitioning:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cgdisk /dev/sda&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, cgdisk looks just like cfdisk, but it makes GPT partitions.&lt;br /&gt;
&lt;br /&gt;
Make a partition for /boot that is about 512MiB of whatever partition type you like (8300 &amp;quot;Linux filesystem&amp;quot; is fine), or make it type bf07 &amp;quot;Solaris Reserved 1&amp;quot; if you want ZFS to maybe see the disk as if it was given as a whole disk to ZFS. Make a second partition using the remaining space with partition type bf01 &amp;quot;Solaris ZFS&amp;quot;. Currently, when ZFSonLinux is given a whole disk device like /dev/sdb to use, it will automatically GPT partition it with a bf01 partition #1 that is the whole disk except a small 8MiB type bf07 partition #9 at the end of the disk (/dev/sdb1 and /dev/sb9). The small 8MiB type bf07 partition #9 is most likely reserved for use by bootloaders, like lilo, to have a /boot or other boot-related files kept there. For example, you might have /dev/sda that is totally non-ZFS for booting and /dev/sdb passed to ZFS whole where it automatically partitions sdb, but you can just use one disk here and make partitions. Let's use type 8300 for /boot to be sure nothing is confused:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
We'll continue with this partitioning (numbers are in MiB):&lt;br /&gt;
  0 to   4: unused&lt;br /&gt;
  4 to 516: /dev/sda1 512MiB, type 8300&lt;br /&gt;
516 to 520: unused&lt;br /&gt;
520 to -96: /dev/sda2, type bf01&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The -96 means to count from the end of the disk so that 96MiB will remain unused at the end of the disk.&lt;br /&gt;
&lt;br /&gt;
Create a zpool called zfs-root:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool create -m none zfs-root /dev/sda2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A zpool created like this, the normal way, is a kernel-internal block device that contains already a zfs filesystem. There is normally no entry in /dev for this device. However, it can still be referenced as a mountable device similar to how devtmpfs, proc, and sysfs are also kernel-internal mountable block devices. The -m option told zpool not to automatically mount it anywhere, and without -m the default is to always automatically mount to /zfs-root. These kinds of details are explained better elsewhere. For this situation, we do not want it automounted.&lt;br /&gt;
&lt;br /&gt;
Because a zpool itself is a useable zfs fs, it has a full set of zfs &amp;quot;properties&amp;quot; to set options about the filesystem, perhaps similar to tune2fs. The &amp;quot;mountpoint=&amp;lt;some place to mount&amp;gt;&amp;quot; is one such property. We want it set to the special value &amp;quot;none&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs get mountpoint zfs-root&lt;br /&gt;
zfs set mountpoint=none zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On creation, the zpool zfs-pool is &amp;quot;imported&amp;quot; and has a zpool status that can be viewed:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool status zfs-root&lt;br /&gt;
&lt;br /&gt;
zpool export zfs-root&lt;br /&gt;
zpool status zfs-root&lt;br /&gt;
# Now there is no status.&lt;br /&gt;
&lt;br /&gt;
zpool import zfs-root&lt;br /&gt;
# Now it is back.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When a zpool is imported, it has it's current configuration cached in a file /etc/zfs/zpool.cache. When a zpool is exported, then it's entries in the cache file are removed and the cache file is deleted if it becomes empty. So long as the zfs kernel modules see this cache file and valid cache data inside it, ZFS considers the described zpools in the cache file to be valid as imported zpools. If the zpool.cache file is present at the time the zfs modules are loaded, then there is no further need to use the import and export zpool commands at system startup and shutdown. With root on a zfs, it is not possible to export the pool that root is on, but this is not a problem. At shutdown, the safe procedure will be to set the zfs-root property readonly=on and sync disks.&lt;br /&gt;
&lt;br /&gt;
To avoid the requirement to import the zfs-root pool at startup, keep a copy of the zpool.cache file to later copy onto the initrd image to read at modules load time to have the pool reactivated without need to issue the zpool import command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/zfs/zpool.cache /etc/zfs/zpool.cache-initrd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A zfs fs will not normally allow you to mount over any files. The mountpoint is expected to be an empty directory. Remove any junk files inside the installer's /mnt because zfs won't mount over any files:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rm /mnt/README&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The directory /mnt is where the slackware setup expects you to mount your root for installation.&lt;br /&gt;
&lt;br /&gt;
Controlling whether a zfs fs is to be mounted read-only or read-write is best managed by setting the readonly property while it is not yet mounted:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set readonly=on zfs-root&lt;br /&gt;
zfs set readonly=off zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Slackware expects root to be mounted readonly when /etc/rc.d/rc.S runs during normal startup, so later this is used to satisfy slackware's expectation to avoid rc.S complaining.&lt;br /&gt;
&lt;br /&gt;
The zfs-root can be mounted and unmounted in two different ways:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=/mnt zfs-root&lt;br /&gt;
zfs set mountpoint=none zfs-root&lt;br /&gt;
# or&lt;br /&gt;
mount zfs-root -t zfs /mnt&lt;br /&gt;
umount /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If it is already mounted and you want to change it to mount somewhere else, it is best to transition it to unmounted first, then mount it in the new place.&lt;br /&gt;
&lt;br /&gt;
The mount options &amp;lt;code&amp;gt;-o ro, -o rw, -o remount,ro, and -o remount,rw &amp;lt;/code&amp;gt; can also be used and will override the &amp;lt;code&amp;gt;readonly=on|off&amp;lt;/code&amp;gt; property without altering the property value. This can be confusing until you are familiar with how the two methods of mounting interact. When &amp;lt;code&amp;gt;mountpoint=legacy&amp;lt;/code&amp;gt; is set, zfs expects the regular mount and umount commands to be used to mount and unmount the dataset with the assistance of the mount.zfs helper. For now, we will continue with &amp;lt;code&amp;gt;mountpoint=none&amp;lt;/code&amp;gt;, but using legacy is also a good option.&lt;br /&gt;
&lt;br /&gt;
Now, let's continue some, and mount to /mnt using the current &amp;lt;code&amp;gt;readonly=off&amp;lt;/code&amp;gt; setting (rw mount):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=/mnt zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This method of mounting will show the most detailed mount options in /etc/mtab. They are the mount options that zfs thinks are proper, and they are probably what should be kept in /etc/fstab for zfs-root until we know better.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cat /etc/mtab &amp;gt;&amp;gt; /etc/fstab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now edit /etc/fstab to make sure it looks right, and remove the &amp;quot;rw&amp;quot; mount option, because we want to let it use a default for that, which will come from how we set the readonly= property most of the time. Unmount again:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=none zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mount again, now using all options from /etc/fstab:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It should be mounted at /mnt, and touch /mnt/t should allow you to make the file t. Then rm it: rm /mnt/t&lt;br /&gt;
For installation, we want to make sure it is mounted read-write. After installation, it should mount readonly inside the initrd.&lt;br /&gt;
&lt;br /&gt;
Sometimes there can be problems using the mount command, and then you can try it with the -i option:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 mount -i zfs-root&lt;br /&gt;
 mount -i zfs-root -t zfs /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
but, you should not have to use -i. When using -i makes it work, it performs an &amp;quot;internal-only&amp;quot; mount and does not use any mount.&amp;lt;fstype&amp;gt; helper scripts that might be on the system. You can use &amp;lt;code&amp;gt;mountpoint=legacy&amp;quot;&amp;lt;/code&amp;gt; to avoid this small problem if you are preferring to use the regular mount and umount commands on your zfs-root.&lt;br /&gt;
&lt;br /&gt;
Setup the /boot device:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkfs.ext4 /dev/sda1&lt;br /&gt;
mkdir /mnt/boot&lt;br /&gt;
mount /dev/sda1 /mnt/boot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We have both root and boot mounted where the slackware installer expects them. Unmount the dvd so setup can find it normally:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
umount /dev/sr0&lt;br /&gt;
setup&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the setup, skip straight to TARGET selection for the root device, but the setup doesn't see or understand the zfs-root, so it is not listed. This does not matter because we have mounted it already. Just skip down to a slot that say to continue, and continue on with setup. Because TARGET is skipped, you may not see the ADDITIONAL prompt (or if so, skip it too) where normally you give /dev/sda1 and have it mounted as /boot. This is also okay because we have mounted /mnt/boot already.&lt;br /&gt;
Because we did not give TARGET the root device or say what device /boot is on, the lilo installation will fail, or you can skip it. Otherwise, this installation process is normal.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Finish installation and exit setup, but do NOT reboot!&lt;br /&gt;
# There is still a lot to do before rebooting.&lt;br /&gt;
umount /dev/sr0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point, it is assumed that the setup has completed installing into /mnt. Congrats! You've installed slackware into a ZFS root!&lt;br /&gt;
&lt;br /&gt;
The next steps are to prepare to use &amp;quot;chroot /mnt&amp;quot; and finish up the configuration on the installed root system and then be able to reboot onto the completed installation. Before doing chroot, copy some files from the setup environment into /mnt.&lt;br /&gt;
&lt;br /&gt;
Copy the current installer /etc/fstab for later use inside the initrd. This fstab is what is proper inside the initrd, except remove option &amp;quot;rw&amp;quot; (if not done already).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/fstab /mnt/etc/fstab.initrd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The fstab.initrd will look like:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 proc /proc proc defaults 0 0&lt;br /&gt;
 zfs-root /mnt zfs defaults,atime,dev,exec,suid,xattr,nomand,zfsutil 0 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the initrd, we want zfs-root to mount to /mnt.&lt;br /&gt;
&lt;br /&gt;
Create /mnt/etc/fstab:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cat /etc/mtab &amp;gt;&amp;gt; /mnt/etc/fstab&lt;br /&gt;
vi /mnt/etc/fstab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using vi started above, edit /mnt/etc/fstab and make it have lines such as:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 zfs-root / zfs defaults,atime,dev,exec,suid,xattr,nomand,zfsutil 0 0&lt;br /&gt;
 /dev/sda1 /boot ext4 defaults 0 2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These two lines in &amp;lt;code&amp;gt;/mnt/etc/fstab&amp;lt;/code&amp;gt; are how the mounts should be looking when root is booted.&lt;br /&gt;
&lt;br /&gt;
Mount some special mounts before chroot:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount -t devtmpfs none /mnt/dev&lt;br /&gt;
mount -t proc none /mnt/proc&lt;br /&gt;
mount -t sysfs none /mnt/sys&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Make sure /boot is mounted:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount /dev/sda1 /mnt/boot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you had mounted a 9p fs share to access spl and zfs packages, then unmount that now:&lt;br /&gt;
umount /packages&lt;br /&gt;
&lt;br /&gt;
Ready, now:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chroot /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point, you should be on the installed system, and now try to configure mkinitrd and lilo. First, switch to use the generic kernel.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /boot&lt;br /&gt;
rm System.map config vmlinuz&lt;br /&gt;
ln -s System.map-gen* System.map&lt;br /&gt;
ln -s config-gen* config&lt;br /&gt;
ln -s vmlinuz-gen* vmlinuz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We installed spl and zfs inside the live ramfs install-dvd environment, but not yet have we installed them into the root system:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount /dev/sr0 /mnt/cdrom&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /mnt/cdrom/addon/spl-*.txz&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /mnt/cdrom/addon/zfs-*.txz&lt;br /&gt;
depmod&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If instead, you used a 9p share to access the spl and zfs packages, then repeat that procedure here to install them onto the root system.&lt;br /&gt;
&lt;br /&gt;
Setup lilo: edit /etc/lilo.conf so it is like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  lba32&lt;br /&gt;
  append = &amp;quot; vt.default_utf8=1&amp;quot;&lt;br /&gt;
  boot = /dev/sda&lt;br /&gt;
  message = /boot/boot_message.txt&lt;br /&gt;
  prompt&lt;br /&gt;
  timeout = 1200&lt;br /&gt;
  change-rules&lt;br /&gt;
   reset&lt;br /&gt;
  vga = normal&lt;br /&gt;
  image = /boot/vmlinuz&lt;br /&gt;
   label = vmlinuz&lt;br /&gt;
   initrd = /boot/initrd.gz&lt;br /&gt;
   root = /dev/ram0&lt;br /&gt;
   read-write&lt;br /&gt;
# alternatively, the root and read-write lines&lt;br /&gt;
# can be this one line of kernel parameters:&lt;br /&gt;
#  addappend = &amp;quot; root=/dev/ram0 rw &amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A note about initrd: The /boot/initrd.gz is a gzipped cpio archive containing a minimal BusyBox-based slackware root system that is sourced from /boot/initrd-tree. The commands &amp;quot;mkinitrd&amp;quot; and &amp;quot;mkinitrd -F&amp;quot; generates /boot/initrd-tree and /boot/initrd.gz. When using a initrd, the initial root device is normally set to root=/dev/ram0 (a ramfs block device) and allowed read-write. The kernel refers to devices in terms of &amp;quot;major&amp;quot; and &amp;quot;minor&amp;quot; numbers, and the ram0 device is assigned the block device major 1 and minor 0. This ram0 major/minor is written in hexadecimal as 0x0100 (256 in decimal). This hexademical number makes an appearance in /boot/initrd-tree/int where it runs: &amp;quot;echo 0x0100 &amp;gt; /proc/sys/kernel/real-root-dev&amp;quot;. Echoing a device code to real-root-dev is part of a deprecated initrd mechanism, but is probably harmless to leave alone as slackware has it unless you know otherwise. More information about how initrd works can be found in:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/usr/src/linux/Documentation/devices.txt (info about major:minor device numbers)&lt;br /&gt;
/usr/src/linux/Documentation/initrd.txt  (mostly obsolete info on old initrd)&lt;br /&gt;
/usr/src/linux/Documentation/filesystems/ramfs-rootfs-initramfs.txt (current info on new initrd, called initramfs)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Advanced note about initrd: Slackware's mkinitrd package does not use the &amp;quot;pivot_root&amp;quot; command as documented in &amp;quot;initrd.txt&amp;quot;, but instead uses &amp;quot;switch_root&amp;quot; provided by a project called BusyBox. The switch_root command changes the effective root filesystem from the initrd (unpacked in rootfs at /) to the new root filesystem (zfs-root mounted at /mnt); it overmounts rootfs / with zfs-root /mnt. The switch_root works as follows: delete everything in rootfs / (one filesystem only) that held initrd to free up ram memory, then use mount, chroot, and chdir to make the effective root change. In concept (as a shell script), the command &amp;quot;exec switch_root /mnt $INIT $RUNLEVEL&amp;quot; is performed as follows:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 find / -xdev | xargs rm -rf&lt;br /&gt;
 cd &amp;quot;$1&amp;quot;&lt;br /&gt;
 shift&lt;br /&gt;
 mount --move . /&lt;br /&gt;
 exec chroot . &amp;quot;$@&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Here, typically INIT=/sbin/init RUNLEVEL=3. The 'exec' causes switch_root to take the place of the parent process having PID=1. In system calls, the switch_root looks similar to this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chdir(&amp;quot;/mnt&amp;quot;);&lt;br /&gt;
/* &amp;lt;insert code to unlink/rmdir all initrd files/directories&lt;br /&gt;
 *  installed in rootfs / without crossing filesystems &amp;gt; */&lt;br /&gt;
mount(&amp;quot;.&amp;quot;, &amp;quot;/&amp;quot;, NULL, MS_MOVE, NULL);&lt;br /&gt;
chroot(&amp;quot;.&amp;quot;);&lt;br /&gt;
chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
execl(&amp;quot;/sbin/init&amp;quot;, &amp;quot;3&amp;quot;, (char*) NULL );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The kernel's rootfs / that contained initrd is never actually unmounted (it can't be) because it is built into the kernel and always exists as at least a tiny ramfs or tmpfs, so you can continue to see it in /proc/mounts. When you give lilo root=/dev/ram0 (a ramfs device), the kernel will actually use the internal rootfs, which is an instance of a tmpfs (if your kernel config includes tmpfs) or ramfs. The rootfs that is a tmpfs can by default use up to half of system ram. If rootfs is a ramfs, it can use up to almost all of system ram until the system panics. Typically, tmpfs is built into the kernel, and so depending on how much ram your computer has, the initrd-tree can probably be up to about half that size.&lt;br /&gt;
&lt;br /&gt;
Quite a lot of notes... now to continue on:&lt;br /&gt;
&lt;br /&gt;
Setup mkinitrd:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/mkinitrd.conf.sample /etc/mkinitrd.conf&lt;br /&gt;
vi /etc/mkinitrd.conf&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Edit it to look like this (other defaults should be ok):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 MODULE_LIST=&amp;quot;sym53c8xx:ext4:e1000:zfs:9p:9pnet_virtio&amp;quot;&lt;br /&gt;
 ROOTDEV=&amp;quot;zfs-root&amp;quot;&lt;br /&gt;
 ROOTFS=&amp;quot;zfs&amp;quot;&lt;br /&gt;
#Module sym53c8xx is the driver for qemu's if=scsi drive device.&lt;br /&gt;
#Module ext4 for /boot.&lt;br /&gt;
#Module e1000 for eth0 net device.&lt;br /&gt;
#Module zfs for ZFSonLinux.&lt;br /&gt;
#Modules 9p and 9pnet_virtio for mounting qemu -virtfs mount_tag.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These 9p modules could be useful from the rescue command line inside the initrd to get needed files that are on the host.&lt;br /&gt;
&lt;br /&gt;
All dependent modules will also be included automatically into /boot/initrd-tree, which is packaged as /boot/initrd.gz. For example, to see the dependent modules of zfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
modprobe --show-depends zfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All listed modules will also be in the initrd. Now, make a /boot/initrd-tree that we can begin to look at and edit.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkinitrd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create an empty /etc/mtab or else zpool import fails (zfs expects /etc/mtab to exists already, it won't make it).&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
touch /boot/initrd-tree/etc/mtab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Copy in the fstab.initrd that was made earlier while on the installer. This provides all the mount options for a simple &amp;quot;mount zfs-root&amp;quot; onto /mnt.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/fstab.initrd /boot/initrd-tree/etc/fstab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More package installing! This time into an alternate root, the root of the initrd, /boot/initrd-tree. This is how you can put whatever packages you like into your initrd. These installations work independent of your normal installations. You can install, upgrade, and remove packages using an altroot:&lt;br /&gt;
&lt;br /&gt;
If spl and zfs are on your customized dvd:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/addon/spl-*.txz&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/addon/zfs-*.txz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Otherwise, repeat same procedure but you mount your 9p mount_tag and get them installed.&lt;br /&gt;
&lt;br /&gt;
More regular packages from the dvd:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/kmod-*.txz&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/coreutils-*.txz&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/gptfdisk-*.txz&lt;br /&gt;
&lt;br /&gt;
# A bash script is in /boot/initrd-tree/lib/udev/, so we need it or udev rules have problems:&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/bash-*.txz&lt;br /&gt;
# Bash needs this:&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/l/libtermcap-*.txz&lt;br /&gt;
&lt;br /&gt;
# Install net-tools to ensure that /etc/HOSTNAME, /etc/hosts, and potentially, /etc/hostid are handled proper.&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/n/net-tools-*.txz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When ZFS has to import a zpool while the initrd is running (this can be avoided by not exporting and keeping /etc/zfs/zpool.cache inside the initrd), ZFS will refuse to import a pool if it thinks that the pool may be in use by another system. ZFS was designed for network attached storage where multiple hosts might have access to the same disks but ZFS cannot support two hosts importing and using a ZFS pool at the same time. ZFS checks a value called &amp;quot;hostid&amp;quot; to determine this kind of conflict, and it can be a tricky issue with an initrd boot process. The value of hostid is returned by a system call, the gethostid() function or the hostid command. This function will return the hostid from /etc/hostid if that file exists and has a valid id in it, or else if the file doesn't exist it obtains a hostid number based on the hostname and ip address assigned to hostname found in /etc/hosts or in DNS. If the hostid trying to import a pool is not the same as the hostid that imported it last time, ZFS will not import the pool unless &amp;quot;zpool import -f zfs-root&amp;quot; is used to force the import. This force option is not recommended to use, so it is best to configure your initrd with matching /etc/HOSTNAME and /etc/hosts as on the root installation and ensure what your system looks like on the initrd matches the booted root system.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Edit /boot/initrd-tree/init (this is the main system startup script on the initrd, responsibe for configuring your block devices and mount your root at /mnt and then booting root):&lt;br /&gt;
&lt;br /&gt;
Inside init, right near the top of the file after the PATH= line, add this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/bin/hostname -F /etc/HOSTNAME&lt;br /&gt;
/bin/hostname $( /bin/hostname -s )&lt;br /&gt;
#/sbin/chhostid 13371400&lt;br /&gt;
# you can make your hostid whatever, but this didn't work right with ZFS, so it is commented out&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This sets the name reported by the hostname command (the default is &amp;quot;darkstar&amp;quot;) to be what is contained in /etc/HOSTNAME. The hostname is modified in the next line to be the short name. These lines will help ZFS to properly identify your host when importing pools.&lt;br /&gt;
&lt;br /&gt;
Inside init, right after it runs &amp;quot;mdadm&amp;quot; commands as used for raid setup, we like it to setup ZFS, so add:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/sbin/zpool import zfs-root&lt;br /&gt;
/sbin/zfs set readonly=on zfs-root&lt;br /&gt;
mount zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Inside init, close to the bottom, where it &amp;quot;Switch to real root partition&amp;quot;, comment out 1 line that normally does the mount:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# mount -o ro -t $ROOTFS $ROOTDEV /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
We have already mounted zfs-root, and we don't want to use any mount options because we should be using a properly set /etc/fstab inside the initrd for the zfs-root mount options onto /mnt.&lt;br /&gt;
&lt;br /&gt;
During a normal startup we want a readonly mount.&lt;br /&gt;
&lt;br /&gt;
Note: we are going to setup with using &amp;quot;zpool import&amp;quot; and &amp;quot;zpool export&amp;quot; commands and startup and shutdown. But later, you can experiment having /etc/zfs/zpool.cache stored in the initrd and commenting out the zpool import/export lines.&lt;br /&gt;
&lt;br /&gt;
As mentioned, the zpool import command may sometimes fail, and give the message: &amp;quot;pool may be in use from another system&amp;quot;. This is nothing serious in this test situation. When this happens, zfs-root will not get mounted to /mnt and the init script will detect this and drop you into a rescue command line where you may manually &amp;quot;zpool import -f zfs-root&amp;quot;, &amp;quot;mount zfs-root&amp;quot;, and then &amp;quot;exit&amp;quot; to continue booting onto zfs-root.&lt;br /&gt;
&lt;br /&gt;
To avoid this problem we copy some files in (assuming you first edit /etc/HOSTNAME to hold the hostname you like to see on your command prompts, and edited /etc/hosts to have hostname on your loopback or other local ip address):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/HOSTNAME /etc/hosts /boot/initrd-tree/etc&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The value reported by the hostid command is what ZFS sees as your hostid. In this setup so far, the value is based on the ip assigned to your hostname. If your hostname is on the line in /etc/hosts for ip address 192.168.13.37, then your hostid will be hex numbers C0.A8.0D.25 rearranged as A8C0250D (pairs of bytes are swapped). This is a ip-based hostid value, a 32bit hexadecimal number. The hostid has to be the same each boot or import will need a -f option to force it. Simply setting the hostid using the system call sethostid() which writes a /etc/hostid file doesn't seem to agree with ZFS and you'd have to force the import, so this setup now assumes that you do not have or have deleted /etc/hostid.&lt;br /&gt;
&lt;br /&gt;
You can sometimes see what has been happening to a zpool by using the command &amp;quot;zpool history -li zfs-root&amp;quot; to see a log of commands.&lt;br /&gt;
&lt;br /&gt;
Once again, you can do away with the import and export commands by trying to have /etc/zfs/zpool.cache inside your initrd. To create zpool.cache, while on the installer or in the rescue shell of the initrd (at lilo &amp;quot;boot: vmlinuz rescue&amp;quot;), import only the pool for the root fs with mountpoint=none and readonly=on properties set, and while it is not mounted:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on installer or initrd rescue shell)&lt;br /&gt;
cp /etc/zfs/zpool.cache /etc/zfs/zpool.cache-initrd&lt;br /&gt;
zfs set readonly=off zfs-root&lt;br /&gt;
mount zfs-pool&lt;br /&gt;
cp /etc/zfs/zpool.cache-initrd /mnt/etc/zfs/&lt;br /&gt;
cp /mnt/etc/zfs/zpool.cache-initrd /mnt/boot/initrd-tree/etc/zfs/zpool.cache&lt;br /&gt;
umount /mnt&lt;br /&gt;
zfs set readonly=on zfs-root&lt;br /&gt;
#mount zfs-root&lt;br /&gt;
#exit (to continue boot process onto rootfs mounted at /mnt)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, doing this zpool.cache approach is not necessary, and some talk suggests this is deprecated or discouraged. Although /etc/hostid setup fails to import without -f option, ip-based (hosts|dns) hostid works on booting and import works without -f option and may be the more proper way to do shutdown and startup rather than using a cache file which could become invalid and cause a problem that is difficult to understand. The contents and exact function of the cache file are not well understood by many people.&lt;br /&gt;
&lt;br /&gt;
Save /boot/initrd-tree/init and quit vi.&lt;br /&gt;
&lt;br /&gt;
Now, edit /etc/rc.d/rc.S and rc.6 to understand how to &amp;quot;remount&amp;quot; rw or ro as readonly property changes. Note: if you use mountpoint=legacy, then you do not need to make the following changes:&lt;br /&gt;
&lt;br /&gt;
In /etc/rc.d/rc.S:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# comment out the line&lt;br /&gt;
#    /sbin/mount -w -v -n -o remount /&lt;br /&gt;
#add the line&lt;br /&gt;
     /sbin/zfs set readonly=off zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In /etc/rc.d/rc.6&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# comment out the line&lt;br /&gt;
#    /bin/mount -v -n -o remount,ro /&lt;br /&gt;
#add the line&lt;br /&gt;
     /sbin/zfs set readonly=on zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In /etc/rc.d/rc.6, near the bottom just before poweroff|reboot, add the following block of lines:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
########################&lt;br /&gt;
# Try to export zfs-root&lt;br /&gt;
/sbin/zpool export zfs-root&lt;br /&gt;
if [ $? -gt 0 ] ; then&lt;br /&gt;
 echo &amp;quot;ZFS export failed.&amp;quot;&lt;br /&gt;
 echo &amp;quot;Notice: if root fs is busy, then this is normal fail.&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;ZFS export successful.&amp;quot;&lt;br /&gt;
 echo &amp;quot;Warning: successful export is abnormal for root fs.&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
/bin/sleep 5&lt;br /&gt;
########################&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
For ZFS, you cannot run fsck on it. It doesn't support that kind of filesystem check. The rc.S script will complain a lot in many places about not being able to run fsck on the zfs-root. To disable all attempts to run fsck, we can simply create a file that acts as a flag in /etc/rc.d/rc.S to tell it to skip fsck:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
touch /etc/fastboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This fastboot file is normally a run-once temporary file, and it is deleted near the bottom inside rc.S. Edit rc.S and stop it from deleting /etc/fastboot. We would like it to always skip all fsck. Edit /etc/rc.d/rc.S, and find the &amp;quot;rm&amp;quot; of fastboot, and do not have it removed!&lt;br /&gt;
&lt;br /&gt;
An alternative to using /etc/fastboot is to make the file &amp;lt;code&amp;gt;/sbin/fsck.zfs&amp;lt;/code&amp;gt; that always just &amp;quot;does nothing successfully&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
exec /bin/true&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Or, it can be:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Or, you just do (LOL!):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ln -s /bin/true /sbin/fsck.zfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Got the idea, right!&lt;br /&gt;
&lt;br /&gt;
This fsck helper has the advantage that you do not need to alter &amp;lt;code&amp;gt;rc.S&amp;lt;/code&amp;gt; as much, or at all if you use zfs property &amp;lt;code&amp;gt;mountpoint=legacy&amp;lt;/code&amp;gt; and the regular &amp;lt;code&amp;gt;mount&amp;lt;/code&amp;gt; command on your zfs-root. With these ideas, no slackware /etc/rc.d/* files really need editing, but it is up to you how you want to experiment.&lt;br /&gt;
&lt;br /&gt;
We are getting close, and have finished all editing, so make /boot/initrd.gz and install lilo:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkinitrd -F&lt;br /&gt;
lilo&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We finished! All that's left to do is clean up.&lt;br /&gt;
&lt;br /&gt;
Exit the chroot.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
exit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Try to umount everything:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
umount /mnt/proc&lt;br /&gt;
umount /mnt/sys&lt;br /&gt;
umount /mnt/dev&lt;br /&gt;
umount /mnt/boot&lt;br /&gt;
umount /mnt/mnt/cdrom&lt;br /&gt;
umount /mnt/root/packages&lt;br /&gt;
umount /mnt&lt;br /&gt;
zpool export zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note, that export stops a pool and frees devices, while import binds devices and starts a pool. It is somewhat like mdadm -A -s and mdadm -S -s, while /etc/zfs/zpool.cache might be somewhat like mdadm -E -s &amp;gt; /etc/mdadm.conf.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Remove the DVD or change boot order&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When you reboot, if all is good, you are booting properly onto a slackware installed on a ZFS root! Congrats!&lt;br /&gt;
&lt;br /&gt;
If this seems to go badly, and this might happen if the import fails as explained some before, then you will be on the initrd's rescue command line just before the part in init where it wants to mount zfs-root and switch_root to boot up. In this case, you typically got commands like these to do:&lt;br /&gt;
&lt;br /&gt;
If you get dumped to rescue because zpool import will not work and requires -f (force), then:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 zpool import -f zfs-root&lt;br /&gt;
 zpool export    zfs-root&lt;br /&gt;
 zpool import    zfs-root&lt;br /&gt;
 mount zfs-root&lt;br /&gt;
 exit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This can happen if hostname, hostid, or uname changes.&lt;br /&gt;
&lt;br /&gt;
If you get into a jam and need to boot into the initrd and skip zpool import etc, use the lilo prompt (or, boot the install-dvd):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
boot: vmlinuz rescue&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the rescue mode of the initrd, after you have mounted your zfs-root as readonly=on to /mnt, then &amp;quot;exit&amp;quot; to continue booting.&lt;br /&gt;
&lt;br /&gt;
In other emergency command lines, you might need to run the lines at the end of init starting from: &amp;lt;code&amp;gt;udevadm info --cleanup-db; udevadm control --exit&amp;lt;/code&amp;gt;&lt;br /&gt;
If you don't run those udevadm commands, two runs of udevd fight each other and it is slow; you have to wait 2 minutes twice for timeouts (4 minutes).&lt;br /&gt;
The last line in init is run like: &amp;lt;code&amp;gt;exec switch_root /mnt /sbin/init 1&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Warning: the switch_root command is kind of dangerous, so read the manual page about it. From what I can tell, everything except the new root &amp;quot;/mnt&amp;quot; is deleted, so you are giving a command that says what NOT to delete! Make sure nothing got mounted outside of &amp;quot;/mnt&amp;quot; before you run it. However, the deletes should not cross filesystems, but only delete the contents of initramfs.&lt;br /&gt;
&lt;br /&gt;
Also, in rescue command line or anytime you have finished making changes and are about to reboot in some abnormal situation, first run:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set readonly=on zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A bug in unpatched grep 2.13 build 1, found slackware 14.0rc1, causes problems when processing files stored on ZFS but rarely shows problems on other filesystems; the bug does not handle sparse files on zfs and btrfs correctly and results in chaos with slackpkg, compiling kernel modules, and possibly many other things. You must downgrade grep to 2.12 or use the patched grep 2.13 build 2 in slackware 14.0rc2 or later.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
Upgrading:&lt;br /&gt;
&lt;br /&gt;
From time to time you will want to upgrade the kernel to the new kernel in slackware64-current or in patches/. This will also necessitate a rebuild and reinstall or upgrade of spl and zfs. Below is an example of when both kernel and spl/zfs are being upgraded, to give an idea of the process:&lt;br /&gt;
&lt;br /&gt;
Using slackpkg, that is configured to use your local slackware mirror is a good option but you can also configure it to use a remote mirror.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slackpkg upgrade-all&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Assume slackpkg just upgraded your kernel, kernel-modules, kernel-headers, and kernel-source.&lt;br /&gt;
&lt;br /&gt;
Note: the first time you try to run on kernel-generic, setup kernel-huge in lilo as 2nd choice. Huge has all the hard drive controllers builtin, but generic has them all as modules. For example, run &amp;quot;modinfo mptsas&amp;quot; to see module options (maybe you have a LSISAS1068) for your hard drive controller. Add file /etc/modprobe.d/mptsas.conf to set options you want with a line: options mptsas ... Do this for all the device driver modules for your hardware. Do this setup while you are on the huge kernel, then setup to reboot to generic. Include all these modules you need into mkinitrd.conf MODULES_LIST. Check that /boot/initrd-tree/etc/modprobe.d/ has a copy of your customized module conf files because it is on the initrd where the modules will load and use the conf files. mkinitrd probably copies all /etc/modprobe.d/* files into the initrd-tree, but check it. Pay attention to /etc/modprobe.d/README and /lib/modprobe.d/* /lib/modprobe.d/* maybe not copied to initrd-tree but you might want to copy some of it into your initrd-tree yourself to use them.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Check that upgraded kernel-source is symlinked to /usr/src/linux (zfs build looks here). SPL/ZFS modules will install to the kernel version in /lib/modules/&amp;lt;/usr/src/linux kernel version&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /usr/local/src&lt;br /&gt;
tar xvzf ~/spl-*.tar.gz&lt;br /&gt;
tar xvzf ~/zfs-*.tar.gz&lt;br /&gt;
&lt;br /&gt;
###### upgrade spl 1st&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-*&lt;br /&gt;
./configure --prefix=/ --libexecdir=/usr/libexec --libdir=/lib64 --includedir=/usr/include --datarootdir=/usr/share&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=/usr/local/src/install&lt;br /&gt;
cd ../install&lt;br /&gt;
makepkg ../spl-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
upgradepkg spl-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
depmod &amp;lt;new kernel version&amp;gt;     (e.g. depmod 3.2.27, if .27 is new kernel upgrade; you currently run on old, maybe .26)&lt;br /&gt;
# this builds the module dependencies in /lib/modules/&amp;lt;new kernel version&amp;gt;&lt;br /&gt;
###### upgrade zfs 2nd&lt;br /&gt;
mkdir install&lt;br /&gt;
cd zfs-*&lt;br /&gt;
./configure --prefix=/ --libexecdir=/usr/libexec --libdir=/lib64 --includedir=/usr/include --datarootdir=/usr/share&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=/usr/local/src/install&lt;br /&gt;
cd ../install&lt;br /&gt;
makepkg ../zfs-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
upgradepkg zfs-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
depmod 3.2.27&lt;br /&gt;
####### upgrade spl/zfs inside altroot /boot/initrd-tree&lt;br /&gt;
ROOT=/boot/initrd-tree upgradepkg spl-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
ROOT=/boot/initrd-tree upgradepkg zfs-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
# note: ROOT is an environment variable, not a command line option to upgradepkg!&lt;br /&gt;
# note: do not worry about depmod inside initrd-tree, mkinitrd -F actually installs the modules&lt;br /&gt;
# note: this upgrade here is really to just upgrade the command line tools zpool, zfs etc&lt;br /&gt;
####### rebuild /boot/initrd.gz and reinstall lilo&lt;br /&gt;
vi /etc/mkinitrd.conf&lt;br /&gt;
# temporarily set KERNEL_VERSION to new version, but you are still running on old version&lt;br /&gt;
mkinitrd -F&lt;br /&gt;
lilo&lt;br /&gt;
vi /etc/mkinitrd.conf&lt;br /&gt;
# you can set KERNEL_VERSION back to $(uname -r) now&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After reboot you can remove any old /lib/modules/&amp;lt;old kernel version&amp;gt; directory.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
More about /etc/hostid. If you want to experiment changing your /etc/hostid file and seeing if you can use it and make zpool import work normally, here is a tool that might be helpful:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/* software product name: foobarz-chhostid.c&lt;br /&gt;
 * suggested binary name: chhostid&lt;br /&gt;
 * license              : BSD&lt;br /&gt;
 * license text:&lt;br /&gt;
Copyright (c) 2012, foobarz&lt;br /&gt;
All rights reserved.&lt;br /&gt;
&lt;br /&gt;
Redistribution and use in source and binary forms, with or without&lt;br /&gt;
modification, are permitted provided that the following conditions are met:&lt;br /&gt;
    * Redistributions of source code must retain the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer.&lt;br /&gt;
    * Redistributions in binary form must reproduce the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer in the&lt;br /&gt;
      documentation and/or other materials provided with the distribution.&lt;br /&gt;
    * Neither the name of the &amp;lt;organization&amp;gt; nor the&lt;br /&gt;
      names of its contributors may be used to endorse or promote products&lt;br /&gt;
      derived from this software without specific prior written permission.&lt;br /&gt;
&lt;br /&gt;
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &amp;quot;AS IS&amp;quot; AND&lt;br /&gt;
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED&lt;br /&gt;
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE&lt;br /&gt;
DISCLAIMED. IN NO EVENT SHALL &amp;lt;COPYRIGHT HOLDER&amp;gt; BE LIABLE FOR ANY&lt;br /&gt;
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES&lt;br /&gt;
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;&lt;br /&gt;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND&lt;br /&gt;
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT&lt;br /&gt;
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS&lt;br /&gt;
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#define FOOBARZ_CHHOSTID_VERSION &amp;quot;1.0.5&amp;quot;&lt;br /&gt;
#include &amp;lt;sys/socket.h&amp;gt;&lt;br /&gt;
#include &amp;lt;netinet/in.h&amp;gt;&lt;br /&gt;
#include &amp;lt;arpa/inet.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;endian.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sysexits.h&amp;gt;&lt;br /&gt;
/* note: if include stdlib then sethostid fails even with _BSD_SOURCE defined */&lt;br /&gt;
&lt;br /&gt;
long swapbytes(long abcd) {&lt;br /&gt;
  long badc;&lt;br /&gt;
  unsigned char addr_a;&lt;br /&gt;
  unsigned char addr_b;&lt;br /&gt;
  unsigned char addr_c;&lt;br /&gt;
  unsigned char addr_d;&lt;br /&gt;
  addr_a = (unsigned char) (abcd &amp;gt;&amp;gt; 24);&lt;br /&gt;
  addr_b = (unsigned char) (abcd &amp;gt;&amp;gt; 16);&lt;br /&gt;
  addr_c = (unsigned char) (abcd &amp;gt;&amp;gt;  8);&lt;br /&gt;
  addr_d = (unsigned char) (abcd);&lt;br /&gt;
  return badc = ( (addr_b &amp;lt;&amp;lt; 24) | (addr_a &amp;lt;&amp;lt; 16) | (addr_d &amp;lt;&amp;lt; 8) | addr_c );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[])&lt;br /&gt;
{&lt;br /&gt;
 long newhostid;&lt;br /&gt;
 struct in_addr addr;&lt;br /&gt;
 char* invalidchar;&lt;br /&gt;
&lt;br /&gt;
 /*********** check command line */&lt;br /&gt;
 if(!( ((argc==3) &amp;amp;&amp;amp; ( (strcmp(argv[1],&amp;quot;-h&amp;quot;)==0) ||&lt;br /&gt;
                       (strcmp(argv[1],&amp;quot;-i&amp;quot;)==0) ||&lt;br /&gt;
                       (strcmp(argv[1],&amp;quot;-l&amp;quot;)==0) )) ||&lt;br /&gt;
       ((argc==2) &amp;amp;&amp;amp; ( (strcmp(argv[1],&amp;quot;-s&amp;quot;)==0) ))&lt;br /&gt;
     )&lt;br /&gt;
   ) {&lt;br /&gt;
                 /*01234567890123456789012345678901234567890123456789012345678901234567890123456789*/&lt;br /&gt;
  fprintf(stderr, &amp;quot;foobarz-chhostid, version %s. License: BSD.\n&amp;quot;, FOOBARZ_CHHOSTID_VERSION);&lt;br /&gt;
  fprintf(stderr, &amp;quot;foobarz-chhostid, (c) 2012, foobarz; all rights reserved.\n&amp;quot;);&lt;br /&gt;
  fprintf(stderr, &amp;quot;descr: %s change system hostid (in /etc/hostid).\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -h &amp;lt;new hostid&amp;gt;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        Change system hostid to &amp;lt;new hostid&amp;gt;;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        &amp;lt;new hostid&amp;gt; must be 32bit 8-digit hex number xxxxxxxx, each x in 0-f|F.\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        The ip corresponding to &amp;lt;new hostid&amp;gt; is also listed for reference only.\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -i &amp;lt;dotted ip address&amp;gt;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        Change system hostid to hostid corresponding to &amp;lt;dotted ip address&amp;gt;.\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -l &amp;lt;dotted ip address&amp;gt;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        List hostid corresponding to &amp;lt;dotted ip address&amp;gt;;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        no change to system hostid.\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -s\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        List current system hostid and corresponding ip address;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        no change to system hostid.\n&amp;quot;, argv[0]);&lt;br /&gt;
  return EX_USAGE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -h &amp;lt;hostid&amp;gt; */&lt;br /&gt;
 if( strcmp(argv[1],&amp;quot;-h&amp;quot;) == 0 ) {&lt;br /&gt;
  if(strlen(argv[2]) != 8) { fprintf(stderr, &amp;quot;new hostid must be 8-digit hex number xxxxxxxx, each x in 0-f|F\n&amp;quot;); return EX_USAGE; }&lt;br /&gt;
&lt;br /&gt;
  newhostid = strtol(argv[2],&amp;amp;invalidchar,16);&lt;br /&gt;
  if( newhostid==LONG_MIN ) { perror(&amp;quot;strtol (underflow)&amp;quot;); return EX_USAGE; }&lt;br /&gt;
  if( newhostid==LONG_MAX ) { perror(&amp;quot;strtol (overflow)&amp;quot;); return EX_USAGE; }&lt;br /&gt;
  if(*invalidchar != '\0') { fprintf(stderr, &amp;quot;invalid hex number %c; must be in 0-f|F\n&amp;quot;, *invalidchar); return EX_USAGE; }&lt;br /&gt;
&lt;br /&gt;
  if( sethostid(newhostid) != 0 ) {&lt;br /&gt;
   perror(&amp;quot;sethostid&amp;quot;);&lt;br /&gt;
   if( errno == EPERM ) return EX_NOPERM;&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
  }&lt;br /&gt;
  printf(&amp;quot;System hostid changed.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  /* hostid is a byte-swapped ip like b.a.d.c */&lt;br /&gt;
  /* get ip by swapping to correct order a.b.c.d and save into in_addr struct */&lt;br /&gt;
  addr.s_addr = htonl(swapbytes(newhostid));&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -i or -l, then find hostid for &amp;lt;dotted ip address&amp;gt; */&lt;br /&gt;
 if( (strcmp(argv[1],&amp;quot;-i&amp;quot;) == 0) || (strcmp(argv[1],&amp;quot;-l&amp;quot;) == 0) ) {&lt;br /&gt;
  if( inet_aton(argv[2], &amp;amp;addr) == 0 ) { fprintf(stderr, &amp;quot;inet_aton: invalid dotted ip address: %s\n&amp;quot;, argv[2]); return EX_USAGE; }&lt;br /&gt;
&lt;br /&gt;
  /* hostid is a byte-swapped ip like b.a.d.c */&lt;br /&gt;
  /* get hostid by swapping bytes of ip a.b.c.d */&lt;br /&gt;
  newhostid = swapbytes(ntohl(addr.s_addr));&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -i &amp;lt;dotted ip address&amp;gt; */&lt;br /&gt;
 if( strcmp(argv[1],&amp;quot;-i&amp;quot;) == 0 ) {&lt;br /&gt;
  if( sethostid(newhostid) != 0 ) {&lt;br /&gt;
   perror(&amp;quot;sethostid&amp;quot;);&lt;br /&gt;
   if( errno == EPERM ) return EX_NOPERM;&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
  }&lt;br /&gt;
  printf(&amp;quot;System hostid changed.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -l &amp;lt;dotted ip address&amp;gt; */&lt;br /&gt;
 if(strcmp(argv[1],&amp;quot;-l&amp;quot;) == 0 ) {&lt;br /&gt;
   printf(&amp;quot;Listing hostid for ip. (no changes)\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -s */&lt;br /&gt;
 if(strcmp(argv[1],&amp;quot;-s&amp;quot;) == 0 ) {&lt;br /&gt;
   /* see if /etc/hostid exists and print info */&lt;br /&gt;
   if( access(&amp;quot;/etc/hostid&amp;quot;, F_OK) != 0 ) {&lt;br /&gt;
     printf(&amp;quot;Notice: /etc/hostid does not exist.\n&amp;quot;);&lt;br /&gt;
     perror(&amp;quot;Reason&amp;quot;);&lt;br /&gt;
     printf(&amp;quot;System hostid derived from ip of hostname found in hosts file or dns.\n&amp;quot;);&lt;br /&gt;
   } else {&lt;br /&gt;
     printf(&amp;quot;Notice: /etc/hostid exists.\n&amp;quot;&lt;br /&gt;
            &amp;quot;System hostid is obtained from hostid file.\n&amp;quot;);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
  errno=0;&lt;br /&gt;
  newhostid = gethostid();&lt;br /&gt;
  if(errno!=0) { perror(&amp;quot;gethostid&amp;quot;); return EX_UNAVAILABLE; }&lt;br /&gt;
&lt;br /&gt;
  /* hostid is a byte-swapped ip like b.a.d.c */&lt;br /&gt;
  /* get ip by swapping to correct order a.b.c.d and save into in_addr struct */&lt;br /&gt;
  addr.s_addr = htonl(swapbytes(newhostid));&lt;br /&gt;
&lt;br /&gt;
  printf(&amp;quot;Listing current system hostid. (no changes)\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** print info and return */&lt;br /&gt;
 printf(&amp;quot;ip dot: %s\n&amp;quot;, inet_ntoa(addr) );&lt;br /&gt;
 printf(&amp;quot;ip hex: %.8x\n&amp;quot;, ntohl(addr.s_addr) );&lt;br /&gt;
 printf(&amp;quot;hostid: %.8x\n&amp;quot;, newhostid );&lt;br /&gt;
 return EX_OK;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
----&lt;br /&gt;
Now available! &amp;quot;ZFS root (builtin)&amp;quot; wiki (aka &amp;quot;ZFS root, part II&amp;quot;):&lt;br /&gt;
http://slackwiki.com/ZFS_root_(builtin)&lt;br /&gt;
It is now possible to build the modules and a small initramfs into your kernel to have a fully-contained and bootable ZFS root kernel from a simple lilo entry. Good luck!&lt;/div&gt;</description>
			<pubDate>Fri, 14 Sep 2012 07:59:36 GMT</pubDate>
			<dc:creator>Foobarz</dc:creator>
			<comments>https://www.slackwiki.com/Talk:ZFS_root</comments>
		</item>
		<item>
			<title>ZFS root</title>
			<link>https://www.slackwiki.com/index.php?title=ZFS_root&amp;diff=792</link>
			<guid isPermaLink="false">https://www.slackwiki.com/index.php?title=ZFS_root&amp;diff=792</guid>
			<description>&lt;p&gt;Foobarz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Tutorials]]&lt;br /&gt;
If you have heard about the ZFS filesystem and you're curious to try it out, then you can try it on slackware64, thanks to the ZFSonLinux.org project!&lt;br /&gt;
&lt;br /&gt;
In this article, an example is shown of how to install slackware64 14.0 onto a ZFS root filesystem (zfs-root) inside a QEMU virtual machine for testing purposes. It is recommended that you install qemu and learn how to use it to test a ZFS installation before you decide to use it on real hardware. A slackbuild for qemu can be found on slackbuilds.org. If you have a processor that supports Intel VT-x or AMD AMD-V virtualization acceleration (try modprobe kvm-intel or modprobe kvm-amd), then use the slackbuild for qemu-kvm.&lt;br /&gt;
&lt;br /&gt;
This article isn't going to go into any detail on actually using ZFS or what kinds of installation options and settings might be optimal. This article just presents an example of how to get started with ZFS on slackware.&lt;br /&gt;
&lt;br /&gt;
At this time of writing, ZFSonLinux is at &amp;quot;release candidate&amp;quot; (version 0.6.0-rc10) development stage, and many issues can occur. See the ZFSonLinux.org web site and the issues tracker for an idea about the current issues. There is also an irc channel on irc.freenode.net, #zfsonlinux, for discussion of issues and help.&lt;br /&gt;
&lt;br /&gt;
Although not required, it is helpful to keep a local mirror of slackware64 on your system. Having a local mirror makes it easier to upgrade to slackware64-current or to patches/* in a release. To help manage your own local slackware mirror and generate your own CD and DVD slackware installers, see http://alien.slackbook.org/blog/local-slackware-mirror/.&lt;br /&gt;
&lt;br /&gt;
In this article, we use a slackware64-current DVD image file as the qemu cdrom device media for the installation of the slackware guest. This was tested at slackware64-current = slackware64 14.0rc2. You can obtain a slackware DVD image using a torrent, buy the DVD from slackware.com, or generate your own DVD image file using the mirror script. For an actual DVD, you can pass your DVD device (e.g., /dev/sr0) as the qemu cdrom device. For a DVD image file, pass the image file as the qemu cdrom device.&lt;br /&gt;
&lt;br /&gt;
The ZFSonLinux packages are not included in slackware at this time. There are two packages involved: spl and zfs. The first, spl, is &amp;quot;Solaris Porting Layer&amp;quot; and must be installed on the system before zfs can be compiled. The source code tarballs for these are at ZFSonLinux.org. At this time of writing, they are spl-0.6.0-rc10.tar.gz and zfs-0.6.0-rc10.tar.gz.&lt;br /&gt;
&lt;br /&gt;
At this point, it is assumed you have qemu installed, have obtained a slackware64-current/14.0 DVD, and have downloaded spl and zfs tarballs to your host system. The first step now is, if your host is not slackware64-current/14.0 (the same as the guest will be), then you need to create a minimal development slackware64 guest system in qemu for just the purpose of compiling and packaging the spl and zfs slackware packages and transferring a copy of these packages back onto your host system to use later to install onto zfs during the slackware install process.&lt;br /&gt;
&lt;br /&gt;
From this point onward, instructions become a bit terse and mostly limited to examples of the commands you might use to complete tasks. You are encouraged to examine what each command does by reading the command's man pages. For example, the command &amp;quot;man qemu&amp;quot; can show you most of what you need to know about running qemu on the command line.&lt;br /&gt;
&lt;br /&gt;
So, here's an example of how you might build the spl and zfs packages, starting in your home directory:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on host)&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir qemu&lt;br /&gt;
cd qemu&lt;br /&gt;
mkdir slackdevel&lt;br /&gt;
cd slackdevel&lt;br /&gt;
mkdir packages&lt;br /&gt;
cp ~/spl-*.tar.gz packages&lt;br /&gt;
cp ~/zfs-*.tar.gz packages&lt;br /&gt;
qemu-img create disk1.raw 10G&lt;br /&gt;
ln -s ~/slackware64-current-install-dvd.iso dvd.iso&lt;br /&gt;
qemu-kvm \&lt;br /&gt;
 -option-rom 8xx_64.rom,bootindex=1 \&lt;br /&gt;
 -no-quit \&lt;br /&gt;
 -no-shutdown \&lt;br /&gt;
 -boot order=cd,menu=on \&lt;br /&gt;
 -m 2G \&lt;br /&gt;
 -cpu host \&lt;br /&gt;
 -smp sockets=1,cores=4 \&lt;br /&gt;
 -net nic,model=e1000 -net user \&lt;br /&gt;
 -cdrom dvd.iso \&lt;br /&gt;
 -drive format=raw,media=disk,cache=none,aio=native,if=scsi,index=0,file=disk1.raw \&lt;br /&gt;
 -virtfs local,path=./packages/,security_model=none,mount_tag=hostpackages&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When you need to change boot to cd or disk, try changing &amp;quot;order=dc&amp;quot; or hitting F12 at boot prompt and select the CD/DVD boot option.&lt;br /&gt;
&lt;br /&gt;
Note: The support for booting drives using if=scsi is not included with current versions of qemu. Booting scsi requires the 8xx_64.rom option-rom, which can be downloaded at&lt;br /&gt;
[http://www.lsi.com/downloads/Public/Host%20Bus%20Adapters/Host%20Bus%20Adapters%20Common%20Files/lsi_bios.zip LSI.com]. Unzip it, and then:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp 8xx_64.rom /usr/share/qemu&lt;br /&gt;
# then run qemu-kvm with additional command line option: -option-rom 8xx_64.rom,bootindex=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Qemu should boot into the install-dvd, and now perform a very ordinary slackware64 install onto /dev/sda. Install d package set and most others, but package sets x, kde, xfce not really needed.&lt;br /&gt;
&lt;br /&gt;
First note: examples here use tools from the gptfdisk package (gdisk, sgdisk, cgdisk) to partition the disk with GUID partition table (GPT) format. GPT might not be too familiar to everyone, who mostly have only used MBR partitions with fdisk. In the slackware installations this author has tested in qemu, using GPT partitions has caused no problems with lilo or other tools used in slackware. GPT disk labels support creating up to 128 partitions and support disks larger than 2TB (the limit of MBR fdisk). LILO installs into the first 440 bytes on /dev/sda, inside a GPT &amp;quot;protective MBR&amp;quot; that serves to provide compatibility with MBR bootloaders like lilo. LILO uses LBA32 sector addressing and can see all 512-byte sectors inside the first 2TB of a disk. So long as the /boot partition is within the first 2TB of a disk, lilo can work on a disk larger than 2TB. Unlike the common default of fdisk to start the first partition at sector 63, which is not aligned with the 4KiB sector size of Advanced Format hard disks, gdisk's default is to start partitions at 2048 sector (1MiB) boundaries which are also 4KiB aligned. Using gdisk GPT works on all disks and is compatible with using Advanced Format hard disks larger than 2TB. More information about GPT disk label format can be found on wikipedia.org. For those that have used grub instead of lilo, grub installation is different with GPT than with MBR, and grub requires a GPT partition of type grub-bios or 0xEF02 &amp;quot;BIOS Boot Partition&amp;quot; of about 8MiB where it can install it's additional bootloader stages because grub cannot embed in sectors 1-62 on GPT where GPT keeps it's partition tables. On MBR, sectors 1-62 were normally reserved space for bootloaders to keep a 2nd stage.&lt;br /&gt;
&lt;br /&gt;
For this purpose of development guest, just create a simple 1-partition system, /dev/sda1, and do a simple slackware install on it. Don't bother with swap or separate /boot unless you want to:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on install-dvd)&lt;br /&gt;
cgdisk /dev/sda&lt;br /&gt;
setup&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When this simple development guest boots, login as root, and continue:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on qemu guest)&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir packages&lt;br /&gt;
mount hostpackages -t 9p -o trans=virtio packages&lt;br /&gt;
echo --prefix=/ --libexecdir=/usr/libexec --libdir=/lib64 --includedir=/usr/include --datarootdir=/usr/share &amp;gt; configure-options&lt;br /&gt;
mkdir src&lt;br /&gt;
cd src&lt;br /&gt;
&lt;br /&gt;
mkdir install&lt;br /&gt;
tar xvzf ~/packages/spl-*.tar.gz&lt;br /&gt;
cd spl-*&lt;br /&gt;
./configure $( cat ~/configure-options )&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../spl-&amp;lt;version&amp;gt;_&amp;lt;kernel_version&amp;gt;-x86_64-&amp;lt;build_id&amp;gt;.txz&lt;br /&gt;
(e.g., makepkg ../spl-0.6.0rc10_3.2.27-x86_64-1root.txz)&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
installpkg spl-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
cp spl-0.6.0rc10_3.2.27-x86_64-1root.txz ~/packages&lt;br /&gt;
&lt;br /&gt;
mkdir install&lt;br /&gt;
tar xvzf ~/packages/zfs-*.tar.gz&lt;br /&gt;
cd zfs-*&lt;br /&gt;
./configure $( cat ~/configure-options )&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../zfs-&amp;lt;version&amp;gt;_&amp;lt;kernel_version&amp;gt;-x86_64-&amp;lt;build_id&amp;gt;.txz&lt;br /&gt;
(e.g., makepkg ../zfs-0.6.0rc10_3.2.27-x86_64-1root.txz)&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
installpkg zfs-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
cp zfs-0.6.0rc10_3.2.27-x86_64-1root.txz ~/packages&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point spl and zfs packages are copied back to the host in the packages directory. Also, spl and zfs are installed in this simple development guest, so one could begin to experiment with zfs pools and datasets but while the root fs is whatever you made it during setup (probably the default, ext4). This development guest isn't really needed anymore, so it can be deleted:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
halt&lt;br /&gt;
(exit qemu: ctrl-alt-2 then enter quit at QEMU command prompt)&lt;br /&gt;
&lt;br /&gt;
(on host)&lt;br /&gt;
rm disk1.raw dvd.iso&lt;br /&gt;
mv packages ..&lt;br /&gt;
cd ..&lt;br /&gt;
rmdir slackdevel&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now that we have the spl and zfs packages on the host, it is possible to copy them into your local slackware64 mirror and then generate your own install DVD image that includes them. For example, change to the directory that contains the slackware README files, and create a &amp;quot;addon&amp;quot; directory and copy the spl and zfs slackware packages into there. Then, generate the DVD image using a command such as $( ./mirror-slackware-current.sh -i ) from where you have this script configured to maintain your local mirror. We can also just continue to access them inside the installer using qemu's virtfs option. When you are going to do a real installation onto real hardware, you need to generate and burn your own DVD that includes the packages.&lt;br /&gt;
&lt;br /&gt;
It is time to begin the installation of slackware64 on a ZFS root, assuming either you have regenerated dvd.iso with zfs packages in addon/* or we access the zfs packages while in the installer using qemu's virtfs to the host's packages directory. ZFS supports creating complex data storage configurations such as pools (similar to a volume group) backed by one or more of various kinds of virtual devices (similar to disks and raid arrays) and containing one or more datasets (similar to mounted filesystems, logical volume devices, or snapshots). But here, we keep it simple and will install on just a single disk device.&lt;br /&gt;
&lt;br /&gt;
Note: On a real ZFS installation, users will typically want to use the ZFS mirror or raidz virtual device (vdev) types for reliability against hard drive failures. For example, a good configuration might be to use a USB memory stick (and a backup stick) for /boot that is plugged into an on-motherboard &amp;quot;Type A&amp;quot; USB connector. Then, use four whole hard drives in a raidz2 vdev as the initial storage space in the root zpool. At a later time, to add more storage space, additional whole four-drive raidz2 vdevs of the same size could be added to the zpool. It is recommended to only add the same vdev type (disk, mirror, or raidz|1|2|3) and size to a zpool since zfs stripes across the vdevs, and vdevs of different types/sizes do not stripe together optimally. After adding a vdev to your zpool, you might need to copy the new /etc/zfs/zpool.cache to your initrd-tree or initramfs-source (and rebuild/reinstall them) if you are using the cachefile to import your zpool. Using mirror vdevs would be similar to a raid10. Using 4-disk raidz2 vdevs would give the same storage space as raid10 while fully reliable against any double-disk failure; however, the raidz2 parity calculations results in higher CPU usage and/or lower performance. Because raidz vdevs cannot be grown by adding hard drives to them, and vdevs in a zpool are striped, it is important with ZFS to decide what type and size of vdev will be used in a zpool as the units of add-on storage space; it could be difficult to alter this decision later. Finally, on a real installation with raidz, data scrub should be scheduled to actively search for &amp;quot;latent defects&amp;quot; on the hard drives so that unknown read/write errors do not become known later during a disk swap/rebuild and result in the zpool becoming faulted (lost).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on host)&lt;br /&gt;
mkdir slackzfs&lt;br /&gt;
mv packages slackzfs/&lt;br /&gt;
cd slackzfs&lt;br /&gt;
qemu-img create disk1.raw 10G&lt;br /&gt;
ln -s ~/slackware64-current-install-dvd.iso dvd.iso&lt;br /&gt;
qemu-kvm \&lt;br /&gt;
 -option-rom 8xx_64.rom,bootindex=1 \&lt;br /&gt;
 -no-quit \&lt;br /&gt;
 -no-shutdown \&lt;br /&gt;
 -boot order=cd,menu=on \&lt;br /&gt;
 -m 2G \&lt;br /&gt;
 -cpu host \&lt;br /&gt;
 -smp sockets=1,cores=4 \&lt;br /&gt;
 -net nic,model=e1000 -net user \&lt;br /&gt;
 -cdrom dvd.iso \&lt;br /&gt;
 -drive format=raw,media=disk,cache=none,aio=native,if=scsi,index=0,file=disk1.raw \&lt;br /&gt;
 -virtfs local,path=./packages/,security_model=none,mount_tag=hostpackages&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The install-dvd should boot, and then begin installation steps on the installer command line:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on install-dvd)&lt;br /&gt;
# mount the install-dvd&lt;br /&gt;
mkdir /dvd&lt;br /&gt;
mount /dev/sr0 /dvd&lt;br /&gt;
&lt;br /&gt;
# install coreutils, which provides the &amp;quot;hostid&amp;quot; command needed to load the spl module&lt;br /&gt;
installpkg /dvd/slackware64/a/coreutils-8.17-x86_64-1.txz&lt;br /&gt;
&lt;br /&gt;
# install kmod package which includes &amp;quot;depmod&amp;quot; command and others&lt;br /&gt;
installpkg /dvd/slackware64/a/kmod-9-x86_64-2.txz&lt;br /&gt;
depmod&lt;br /&gt;
&lt;br /&gt;
# install the full kernel modules so you can load 9p filesystem and use it if you want&lt;br /&gt;
# .. you might keep the zfs modules packages off the dvd and use a plain slack dvd&lt;br /&gt;
installpkg /dvd/slackware64/a/kernel-modules-*.txz&lt;br /&gt;
depmod&lt;br /&gt;
&lt;br /&gt;
# install bash and libtermcap because udev rules in zfs use bash scripts&lt;br /&gt;
installpkg /dvd/slackware64/a/bash-*.txz&lt;br /&gt;
installpkg /dvd/slackware64/l/libtermcap-*.txz&lt;br /&gt;
&lt;br /&gt;
# install spl and zfs that you have copied into the mirror before running the DVD creation&lt;br /&gt;
installpkg /dvd/addon/spl-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /dvd/addon/zfs-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
&lt;br /&gt;
#Or:&lt;br /&gt;
mkdir /packages&lt;br /&gt;
find /lib/modules/ | grep 9p&lt;br /&gt;
lsmod&lt;br /&gt;
# check that 9p modules load, mainly 9pnet_virtio&lt;br /&gt;
modprobe 9pnet_virtio&lt;br /&gt;
mount hostpackages -t 9p -o trans=virtio /packages&lt;br /&gt;
installpkg /packages/spl-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /packages/zfs-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
modprobe zfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now zfs tools: &amp;quot;zpool&amp;quot; and &amp;quot;zfs&amp;quot; should work in the live installer.&lt;br /&gt;
On the installer, there can be trouble seeing man pages, so install:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
installpkg /dvd/slackware64/ap/man-*.txz&lt;br /&gt;
installpkg /dvd/slackware64/ap/groff-*.txz&lt;br /&gt;
installpkg /dvd/slackware64/a/less-*.txz&lt;br /&gt;
export MANPATH=/usr/man:/usr/share/man&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The manual pages should be readable:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
man zpool&lt;br /&gt;
man zfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After seeing the man pages, we should be fully ready to continue to setup on ZFS.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(still on install-dvd)&lt;br /&gt;
ls -l /dev/sd*&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Make sure the disk devices you expect are there. We'll use sda and make boot (/boot on /dev/sda1) and root (/ on /dev/sda2) partitions.&lt;br /&gt;
&lt;br /&gt;
First, some background info: A ZFS filesystem is not supported by lilo as the filesystem containing /boot, which holds lilo's 2nd stage and the linux kernel files. The on-disk format of a ZFS filesystem is often a complex raid configuration where even if lilo understood ZFS it would likely require /boot to reside in only certain simple ZFS configurations to be plainly readable to lilo. As things are, a linux root installed in a partition with ZFS filesystem needs /boot to be on another partition with a filesystem that lilo understands, such as ext4 fs. In addition, because the spl and zfs modules are not built into the kernel, and the zfs startup requires some configuration to mount the zfs root, an initial ram/root filesystem (initrd) is needed. The initrd is a gzip compressed cpio archive file that contains a small linux root operating system that is decompressed into a ramfs block device at boot up and takes initial control of the system. The initrd contains an init script that configures devices in devtmpfs mounted at /dev. For example, if using mdadm, lvm, luks, losetup, and now zfs, this init script runs all the commands to create or start these devices (one of which is the root device), mounts the root device, and then transfers system control to the init script in the mounted root filesystem. The ramfs-based root environment on the booted install-dvd or booted initrd image (in rescue command line) are small slackware installations that exist only in ram and are temporary, but while inside them you can install, upgrade, and remove slackware packages inside them using the regular package management tools; this allows you access to any kernel modules and programs as needed inside these ramfs root. Packages can be installed, upgraded, or removed permanantly in the initrd image file to manage the programs and modules required during the initrd boot stage. Also from within these ramfs initial root environments, once the root device is mounted, chroot can be used to work on the mounted root system as if it were booted; this allows one to fix problems that are occuring in the root fs init scripts that cause normal booting to fail, or to install a kernel and/or modules etc. Now on to partitioning:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cgdisk /dev/sda&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, cgdisk looks just like cfdisk, but it makes GPT partitions.&lt;br /&gt;
&lt;br /&gt;
Make a partition for /boot that is about 512MiB of whatever partition type you like (8300 &amp;quot;Linux filesystem&amp;quot; is fine), or make it type bf07 &amp;quot;Solaris Reserved 1&amp;quot; if you want ZFS to maybe see the disk as if it was given as a whole disk to ZFS. Make a second partition using the remaining space with partition type bf01 &amp;quot;Solaris ZFS&amp;quot;. Currently, when ZFSonLinux is given a whole disk device like /dev/sdb to use, it will automatically GPT partition it with a bf01 partition #1 that is the whole disk except a small 8MiB type bf07 partition #9 at the end of the disk (/dev/sdb1 and /dev/sb9). The small 8MiB type bf07 partition #9 is most likely reserved for use by bootloaders, like lilo, to have a /boot or other boot-related files kept there. For example, you might have /dev/sda that is totally non-ZFS for booting and /dev/sdb passed to ZFS whole where it automatically partitions sdb, but you can just use one disk here and make partitions. Let's use type 8300 for /boot to be sure nothing is confused:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
We'll continue with this partitioning (numbers are in MiB):&lt;br /&gt;
  0 to   4: unused&lt;br /&gt;
  4 to 516: /dev/sda1 512MiB, type 8300&lt;br /&gt;
516 to 520: unused&lt;br /&gt;
520 to -96: /dev/sda2, type bf01&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The -96 means to count from the end of the disk so that 96MiB will remain unused at the end of the disk.&lt;br /&gt;
&lt;br /&gt;
Create a zpool called zfs-root:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool create -m none zfs-root /dev/sda2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A zpool created like this, the normal way, is a kernel-internal block device that contains already a zfs filesystem. There is normally no entry in /dev for this device. However, it can still be referenced as a mountable device similar to how devtmpfs, proc, and sysfs are also kernel-internal mountable block devices. The -m option told zpool not to automatically mount it anywhere, and without -m the default is to always automatically mount to /zfs-root. These kinds of details are explained better elsewhere. For this situation, we do not want it automounted.&lt;br /&gt;
&lt;br /&gt;
Because a zpool itself is a useable zfs fs, it has a full set of zfs &amp;quot;properties&amp;quot; to set options about the filesystem, perhaps similar to tune2fs. The &amp;quot;mountpoint=&amp;lt;some place to mount&amp;gt;&amp;quot; is one such property. We want it set to the special value &amp;quot;none&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs get mountpoint zfs-root&lt;br /&gt;
zfs set mountpoint=none zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On creation, the zpool zfs-pool is &amp;quot;imported&amp;quot; and has a zpool status that can be viewed:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool status zfs-root&lt;br /&gt;
&lt;br /&gt;
zpool export zfs-root&lt;br /&gt;
zpool status zfs-root&lt;br /&gt;
# Now there is no status.&lt;br /&gt;
&lt;br /&gt;
zpool import zfs-root&lt;br /&gt;
# Now it is back.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When a zpool is imported, it has it's current configuration cached in a file /etc/zfs/zpool.cache. When a zpool is exported, then it's entries in the cache file are removed and the cache file is deleted if it becomes empty. So long as the zfs kernel modules see this cache file and valid cache data inside it, ZFS considers the described zpools in the cache file to be valid as imported zpools. If the zpool.cache file is present at the time the zfs modules are loaded, then there is no further need to use the import and export zpool commands at system startup and shutdown. With root on a zfs, it is not possible to export the pool that root is on, but this is not a problem. At shutdown, the safe procedure will be to set the zfs-root property readonly=on and sync disks.&lt;br /&gt;
&lt;br /&gt;
To avoid the requirement to import the zfs-root pool at startup, keep a copy of the zpool.cache file to later copy onto the initrd image to read at modules load time to have the pool reactivated without need to issue the zpool import command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/zfs/zpool.cache /etc/zfs/zpool.cache-initrd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A zfs fs will not normally allow you to mount over any files. The mountpoint is expected to be an empty directory. Remove any junk files inside the installer's /mnt because zfs won't mount over any files:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rm /mnt/README&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The directory /mnt is where the slackware setup expects you to mount your root for installation.&lt;br /&gt;
&lt;br /&gt;
Controlling whether a zfs fs is to be mounted read-only or read-write is best managed by setting the readonly property while it is not yet mounted:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set readonly=on zfs-root&lt;br /&gt;
zfs set readonly=off zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Slackware expects root to be mounted readonly when /etc/rc.d/rc.S runs during normal startup, so later this is used to satisfy slackware's expectation to avoid rc.S complaining.&lt;br /&gt;
&lt;br /&gt;
The zfs-root can be mounted and unmounted in two different ways:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=/mnt zfs-root&lt;br /&gt;
zfs set mountpoint=none zfs-root&lt;br /&gt;
# or&lt;br /&gt;
mount zfs-root -t zfs /mnt&lt;br /&gt;
umount /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If it is already mounted and you want to change it to mount somewhere else, it is best to transition it to unmounted first, then mount it in the new place.&lt;br /&gt;
&lt;br /&gt;
The mount options &amp;lt;code&amp;gt;-o ro, -o rw, -o remount,ro, and -o remount,rw &amp;lt;/code&amp;gt; can also be used and will override the &amp;lt;code&amp;gt;readonly=on|off&amp;lt;/code&amp;gt; property without altering the property value. This can be confusing until you are familiar with how the two methods of mounting interact. When &amp;lt;code&amp;gt;mountpoint=legacy&amp;lt;/code&amp;gt; is set, zfs expects the regular mount and umount commands to be used to mount and unmount the dataset with the assistance of the mount.zfs helper. For now, we will continue with &amp;lt;code&amp;gt;mountpoint=none&amp;lt;/code&amp;gt;, but using legacy is also a good option.&lt;br /&gt;
&lt;br /&gt;
Now, let's continue some, and mount to /mnt using the current &amp;lt;code&amp;gt;readonly=off&amp;lt;/code&amp;gt; setting (rw mount):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=/mnt zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This method of mounting will show the most detailed mount options in /etc/mtab. They are the mount options that zfs thinks are proper, and they are probably what should be kept in /etc/fstab for zfs-root until we know better.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cat /etc/mtab &amp;gt;&amp;gt; /etc/fstab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now edit /etc/fstab to make sure it looks right, and remove the &amp;quot;rw&amp;quot; mount option, because we want to let it use a default for that, which will come from how we set the readonly= property most of the time. Unmount again:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=none zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mount again, now using all options from /etc/fstab:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It should be mounted at /mnt, and touch /mnt/t should allow you to make the file t. Then rm it: rm /mnt/t&lt;br /&gt;
For installation, we want to make sure it is mounted read-write. After installation, it should mount readonly inside the initrd.&lt;br /&gt;
&lt;br /&gt;
Sometimes there can be problems using the mount command, and then you can try it with the -i option:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 mount -i zfs-root&lt;br /&gt;
 mount -i zfs-root -t zfs /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
but, you should not have to use -i. When using -i makes it work, it performs an &amp;quot;internal-only&amp;quot; mount and does not use any mount.&amp;lt;fstype&amp;gt; helper scripts that might be on the system. You can use &amp;lt;code&amp;gt;mountpoint=legacy&amp;quot;&amp;lt;/code&amp;gt; to avoid this small problem if you are preferring to use the regular mount and umount commands on your zfs-root.&lt;br /&gt;
&lt;br /&gt;
Setup the /boot device:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkfs.ext4 /dev/sda1&lt;br /&gt;
mkdir /mnt/boot&lt;br /&gt;
mount /dev/sda1 /mnt/boot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We have both root and boot mounted where the slackware installer expects them. Unmount the dvd so setup can find it normally:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
umount /dev/sr0&lt;br /&gt;
setup&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the setup, skip straight to TARGET selection for the root device, but the setup doesn't see or understand the zfs-root, so it is not listed. This does not matter because we have mounted it already. Just skip down to a slot that say to continue, and continue on with setup. Because TARGET is skipped, you may not see the ADDITIONAL prompt (or if so, skip it too) where normally you give /dev/sda1 and have it mounted as /boot. This is also okay because we have mounted /mnt/boot already.&lt;br /&gt;
Because we did not give TARGET the root device or say what device /boot is on, the lilo installation will fail, or you can skip it. Otherwise, this installation process is normal.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Finish installation and exit setup, but do NOT reboot!&lt;br /&gt;
# There is still a lot to do before rebooting.&lt;br /&gt;
umount /dev/sr0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point, it is assumed that the setup has completed installing into /mnt. Congrats! You've installed slackware into a ZFS root!&lt;br /&gt;
&lt;br /&gt;
The next steps are to prepare to use &amp;quot;chroot /mnt&amp;quot; and finish up the configuration on the installed root system and then be able to reboot onto the completed installation. Before doing chroot, copy some files from the setup environment into /mnt.&lt;br /&gt;
&lt;br /&gt;
Copy the current installer /etc/fstab for later use inside the initrd. This fstab is what is proper inside the initrd, except remove option &amp;quot;rw&amp;quot; (if not done already).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/fstab /mnt/etc/fstab.initrd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The fstab.initrd will look like:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 proc /proc proc defaults 0 0&lt;br /&gt;
 zfs-root /mnt zfs defaults,atime,dev,exec,suid,xattr,nomand,zfsutil 0 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the initrd, we want zfs-root to mount to /mnt.&lt;br /&gt;
&lt;br /&gt;
Create /mnt/etc/fstab:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cat /etc/mtab &amp;gt;&amp;gt; /mnt/etc/fstab&lt;br /&gt;
vi /mnt/etc/fstab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using vi started above, edit /mnt/etc/fstab and make it have lines such as:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 zfs-root / zfs defaults,atime,dev,exec,suid,xattr,nomand,zfsutil 0 0&lt;br /&gt;
 /dev/sda1 /boot ext4 defaults 0 2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These two lines in &amp;lt;code&amp;gt;/mnt/etc/fstab&amp;lt;/code&amp;gt; are how the mounts should be looking when root is booted.&lt;br /&gt;
&lt;br /&gt;
Mount some special mounts before chroot:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount -t devtmpfs none /mnt/dev&lt;br /&gt;
mount -t proc none /mnt/proc&lt;br /&gt;
mount -t sysfs none /mnt/sys&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Make sure /boot is mounted:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount /dev/sda1 /mnt/boot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you had mounted a 9p fs share to access spl and zfs packages, then unmount that now:&lt;br /&gt;
umount /packages&lt;br /&gt;
&lt;br /&gt;
Ready, now:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chroot /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point, you should be on the installed system, and now try to configure mkinitrd and lilo. First, switch to use the generic kernel.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /boot&lt;br /&gt;
rm System.map config vmlinuz&lt;br /&gt;
ln -s System.map-gen* System.map&lt;br /&gt;
ln -s config-gen* config&lt;br /&gt;
ln -s vmlinuz-gen* vmlinuz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We installed spl and zfs inside the live ramfs install-dvd environment, but not yet have we installed them into the root system:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount /dev/sr0 /mnt/cdrom&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /mnt/cdrom/addon/spl-*.txz&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /mnt/cdrom/addon/zfs-*.txz&lt;br /&gt;
depmod&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If instead, you used a 9p share to access the spl and zfs packages, then repeat that procedure here to install them onto the root system.&lt;br /&gt;
&lt;br /&gt;
Setup lilo: edit /etc/lilo.conf so it is like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  lba32&lt;br /&gt;
  append = &amp;quot; vt.default_utf8=1&amp;quot;&lt;br /&gt;
  boot = /dev/sda&lt;br /&gt;
  message = /boot/boot_message.txt&lt;br /&gt;
  prompt&lt;br /&gt;
  timeout = 1200&lt;br /&gt;
  change-rules&lt;br /&gt;
   reset&lt;br /&gt;
  vga = normal&lt;br /&gt;
  image = /boot/vmlinuz&lt;br /&gt;
   label = vmlinuz&lt;br /&gt;
   initrd = /boot/initrd.gz&lt;br /&gt;
   root = /dev/ram0&lt;br /&gt;
   read-write&lt;br /&gt;
# alternatively, the root and read-write lines&lt;br /&gt;
# can be this one line of kernel parameters:&lt;br /&gt;
#  addappend = &amp;quot; root=/dev/ram0 rw &amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A note about initrd: The /boot/initrd.gz is a gzipped cpio archive containing a minimal BusyBox-based slackware root system that is sourced from /boot/initrd-tree. The commands &amp;quot;mkinitrd&amp;quot; and &amp;quot;mkinitrd -F&amp;quot; generates /boot/initrd-tree and /boot/initrd.gz. When using a initrd, the initial root device is normally set to root=/dev/ram0 (a ramfs block device) and allowed read-write. The kernel refers to devices in terms of &amp;quot;major&amp;quot; and &amp;quot;minor&amp;quot; numbers, and the ram0 device is assigned the block device major 1 and minor 0. This ram0 major/minor is written in hexadecimal as 0x0100 (256 in decimal). This hexademical number makes an appearance in /boot/initrd-tree/int where it runs: &amp;quot;echo 0x0100 &amp;gt; /proc/sys/kernel/real-root-dev&amp;quot;. Echoing a device code to real-root-dev is part of a deprecated initrd mechanism, but is probably harmless to leave alone as slackware has it unless you know otherwise. More information about how initrd works can be found in:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/usr/src/linux/Documentation/devices.txt (info about major:minor device numbers)&lt;br /&gt;
/usr/src/linux/Documentation/initrd.txt  (mostly obsolete info on old initrd)&lt;br /&gt;
/usr/src/linux/Documentation/filesystems/ramfs-rootfs-initramfs.txt (current info on new initrd, called initramfs)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Advanced note about initrd: Slackware's mkinitrd package does not use the &amp;quot;pivot_root&amp;quot; command as documented in &amp;quot;initrd.txt&amp;quot;, but instead uses &amp;quot;switch_root&amp;quot; provided by a project called BusyBox. The switch_root command changes the effective root filesystem from the initrd (unpacked in rootfs at /) to the new root filesystem (zfs-root mounted at /mnt); it overmounts rootfs / with zfs-root /mnt. The switch_root works as follows: delete everything in rootfs / (one filesystem only) that held initrd to free up ram memory, then use mount, chroot, and chdir to make the effective root change. In concept (as a shell script), the command &amp;quot;exec switch_root /mnt $INIT $RUNLEVEL&amp;quot; is performed as follows:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 find / -xdev | xargs rm -rf&lt;br /&gt;
 cd &amp;quot;$1&amp;quot;&lt;br /&gt;
 shift&lt;br /&gt;
 mount --move . /&lt;br /&gt;
 exec chroot . &amp;quot;$@&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Here, typically INIT=/sbin/init RUNLEVEL=3. The 'exec' causes switch_root to take the place of the parent process having PID=1. In system calls, the switch_root looks similar to this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chdir(&amp;quot;/mnt&amp;quot;);&lt;br /&gt;
/* &amp;lt;insert code to unlink/rmdir all initrd files/directories&lt;br /&gt;
 *  installed in rootfs / without crossing filesystems &amp;gt; */&lt;br /&gt;
mount(&amp;quot;.&amp;quot;, &amp;quot;/&amp;quot;, NULL, MS_MOVE, NULL);&lt;br /&gt;
chroot(&amp;quot;.&amp;quot;);&lt;br /&gt;
chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
execl(&amp;quot;/sbin/init&amp;quot;, &amp;quot;3&amp;quot;, (char*) NULL );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The kernel's rootfs / that contained initrd is never actually unmounted (it can't be) because it is built into the kernel and always exists as at least a tiny ramfs or tmpfs, so you can continue to see it in /proc/mounts. When you give lilo root=/dev/ram0 (a ramfs device), the kernel will actually use the internal rootfs, which is an instance of a tmpfs (if your kernel config includes tmpfs) or ramfs. The rootfs that is a tmpfs can by default use up to half of system ram. If rootfs is a ramfs, it can use up to almost all of system ram until the system panics. Typically, tmpfs is built into the kernel, and so depending on how much ram your computer has, the initrd-tree can probably be up to about half that size.&lt;br /&gt;
&lt;br /&gt;
Quite a lot of notes... now to continue on:&lt;br /&gt;
&lt;br /&gt;
Setup mkinitrd:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/mkinitrd.conf.sample /etc/mkinitrd.conf&lt;br /&gt;
vi /etc/mkinitrd.conf&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Edit it to look like this (other defaults should be ok):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 MODULE_LIST=&amp;quot;sym53c8xx:ext4:e1000:zfs:9p:9pnet_virtio&amp;quot;&lt;br /&gt;
 ROOTDEV=&amp;quot;zfs-root&amp;quot;&lt;br /&gt;
 ROOTFS=&amp;quot;zfs&amp;quot;&lt;br /&gt;
#Module sym53c8xx is the driver for qemu's if=scsi drive device.&lt;br /&gt;
#Module ext4 for /boot.&lt;br /&gt;
#Module e1000 for eth0 net device.&lt;br /&gt;
#Module zfs for ZFSonLinux.&lt;br /&gt;
#Modules 9p and 9pnet_virtio for mounting qemu -virtfs mount_tag.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These 9p modules could be useful from the rescue command line inside the initrd to get needed files that are on the host.&lt;br /&gt;
&lt;br /&gt;
All dependent modules will also be included automatically into /boot/initrd-tree, which is packaged as /boot/initrd.gz. For example, to see the dependent modules of zfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
modprobe --show-depends zfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All listed modules will also be in the initrd. Now, make a /boot/initrd-tree that we can begin to look at and edit.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkinitrd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create an empty /etc/mtab or else zpool import fails (zfs expects /etc/mtab to exists already, it won't make it).&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
touch /boot/initrd-tree/etc/mtab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Copy in the fstab.initrd that was made earlier while on the installer. This provides all the mount options for a simple &amp;quot;mount zfs-root&amp;quot; onto /mnt.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/fstab.initrd /boot/initrd-tree/etc/fstab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More package installing! This time into an alternate root, the root of the initrd, /boot/initrd-tree. This is how you can put whatever packages you like into your initrd. These installations work independent of your normal installations. You can install, upgrade, and remove packages using an altroot:&lt;br /&gt;
&lt;br /&gt;
If spl and zfs are on your customized dvd:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/addon/spl-*.txz&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/addon/zfs-*.txz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Otherwise, repeat same procedure but you mount your 9p mount_tag and get them installed.&lt;br /&gt;
&lt;br /&gt;
More regular packages from the dvd:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/kmod-*.txz&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/coreutils-*.txz&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/gptfdisk-*.txz&lt;br /&gt;
&lt;br /&gt;
# A bash script is in /boot/initrd-tree/lib/udev/, so we need it or udev rules have problems:&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/bash-*.txz&lt;br /&gt;
# Bash needs this:&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/l/libtermcap-*.txz&lt;br /&gt;
&lt;br /&gt;
# Install net-tools to ensure that /etc/HOSTNAME, /etc/hosts, and potentially, /etc/hostid are handled proper.&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/n/net-tools-*.txz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When ZFS has to import a zpool while the initrd is running (this can be avoided by not exporting and keeping /etc/zfs/zpool.cache inside the initrd), ZFS will refuse to import a pool if it thinks that the pool may be in use by another system. ZFS was designed for network attached storage where multiple hosts might have access to the same disks but ZFS cannot support two hosts importing and using a ZFS pool at the same time. ZFS checks a value called &amp;quot;hostid&amp;quot; to determine this kind of conflict, and it can be a tricky issue with an initrd boot process. The value of hostid is returned by a system call, the gethostid() function or the hostid command. This function will return the hostid from /etc/hostid if that file exists and has a valid id in it, or else if the file doesn't exist it obtains a hostid number based on the hostname and ip address assigned to hostname found in /etc/hosts or in DNS. If the hostid trying to import a pool is not the same as the hostid that imported it last time, ZFS will not import the pool unless &amp;quot;zpool import -f zfs-root&amp;quot; is used to force the import. This force option is not recommended to use, so it is best to configure your initrd with matching /etc/HOSTNAME and /etc/hosts as on the root installation and ensure what your system looks like on the initrd matches the booted root system.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Edit /boot/initrd-tree/init (this is the main system startup script on the initrd, responsibe for configuring your block devices and mount your root at /mnt and then booting root):&lt;br /&gt;
&lt;br /&gt;
Inside init, right near the top of the file after the PATH= line, add this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/bin/hostname -F /etc/HOSTNAME&lt;br /&gt;
/bin/hostname $( /bin/hostname -s )&lt;br /&gt;
#/sbin/chhostid 13371400&lt;br /&gt;
# you can make your hostid whatever, but this didn't work right with ZFS, so it is commented out&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This sets the name reported by the hostname command (the default is &amp;quot;darkstar&amp;quot;) to be what is contained in /etc/HOSTNAME. The hostname is modified in the next line to be the short name. These lines will help ZFS to properly identify your host when importing pools.&lt;br /&gt;
&lt;br /&gt;
Inside init, right after it runs &amp;quot;mdadm&amp;quot; commands as used for raid setup, we like it to setup ZFS, so add:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/sbin/zpool import zfs-root&lt;br /&gt;
/sbin/zfs set readonly=on zfs-root&lt;br /&gt;
mount zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Inside init, close to the bottom, where it &amp;quot;Switch to real root partition&amp;quot;, comment out 1 line that normally does the mount:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# mount -o ro -t $ROOTFS $ROOTDEV /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
We have already mounted zfs-root, and we don't want to use any mount options because we should be using a properly set /etc/fstab inside the initrd for the zfs-root mount options onto /mnt.&lt;br /&gt;
&lt;br /&gt;
During a normal startup we want a readonly mount.&lt;br /&gt;
&lt;br /&gt;
Note: we are going to setup with using &amp;quot;zpool import&amp;quot; and &amp;quot;zpool export&amp;quot; commands and startup and shutdown. But later, you can experiment having /etc/zfs/zpool.cache stored in the initrd and commenting out the zpool import/export lines.&lt;br /&gt;
&lt;br /&gt;
As mentioned, the zpool import command may sometimes fail, and give the message: &amp;quot;pool may be in use from another system&amp;quot;. This is nothing serious in this test situation. When this happens, zfs-root will not get mounted to /mnt and the init script will detect this and drop you into a rescue command line where you may manually &amp;quot;zpool import -f zfs-root&amp;quot;, &amp;quot;mount zfs-root&amp;quot;, and then &amp;quot;exit&amp;quot; to continue booting onto zfs-root.&lt;br /&gt;
&lt;br /&gt;
To avoid this problem we copy some files in (assuming you first edit /etc/HOSTNAME to hold the hostname you like to see on your command prompts, and edited /etc/hosts to have hostname on your loopback or other local ip address):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/HOSTNAME /etc/hosts /boot/initrd-tree/etc&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The value reported by the hostid command is what ZFS sees as your hostid. In this setup so far, the value is based on the ip assigned to your hostname. If your hostname is on the line in /etc/hosts for ip address 192.168.13.37, then your hostid will be hex numbers C0.A8.0D.25 rearranged as A8C0250D (pairs of bytes are swapped). This is a ip-based hostid value, a 32bit hexadecimal number. The hostid has to be the same each boot or import will need a -f option to force it. Simply setting the hostid using the system call sethostid() which writes a /etc/hostid file doesn't seem to agree with ZFS and you'd have to force the import, so this setup now assumes that you do not have or have deleted /etc/hostid.&lt;br /&gt;
&lt;br /&gt;
You can sometimes see what has been happening to a zpool by using the command &amp;quot;zpool history -li zfs-root&amp;quot; to see a log of commands.&lt;br /&gt;
&lt;br /&gt;
Once again, you can do away with the import and export commands by trying to have /etc/zfs/zpool.cache inside your initrd. To create zpool.cache, while on the installer or in the rescue shell of the initrd (at lilo &amp;quot;boot: vmlinuz rescue&amp;quot;), import only the pool for the root fs with mountpoint=none and readonly=on properties set, and while it is not mounted:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on installer or initrd rescue shell)&lt;br /&gt;
cp /etc/zfs/zpool.cache /etc/zfs/zpool.cache-initrd&lt;br /&gt;
zfs set readonly=off zfs-root&lt;br /&gt;
mount zfs-pool&lt;br /&gt;
cp /etc/zfs/zpool.cache-initrd /mnt/etc/zfs/&lt;br /&gt;
cp /mnt/etc/zfs/zpool.cache-initrd /mnt/boot/initrd-tree/etc/zfs/zpool.cache&lt;br /&gt;
umount /mnt&lt;br /&gt;
zfs set readonly=on zfs-root&lt;br /&gt;
#mount zfs-root&lt;br /&gt;
#exit (to continue boot process onto rootfs mounted at /mnt)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, doing this zpool.cache approach is not necessary, and some talk suggests this is deprecated or discouraged. Although /etc/hostid setup fails to import without -f option, ip-based (hosts|dns) hostid works on booting and import works without -f option and may be the more proper way to do shutdown and startup rather than using a cache file which could become invalid and cause a problem that is difficult to understand. The contents and exact function of the cache file are not well understood by many people.&lt;br /&gt;
&lt;br /&gt;
Save /boot/initrd-tree/init and quit vi.&lt;br /&gt;
&lt;br /&gt;
Now, edit /etc/rc.d/rc.S and rc.6 to understand how to &amp;quot;remount&amp;quot; rw or ro as readonly property changes. Note: if you use mountpoint=legacy, then you do not need to make the following changes:&lt;br /&gt;
&lt;br /&gt;
In /etc/rc.d/rc.S:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# comment out the line&lt;br /&gt;
#    /sbin/mount -w -v -n -o remount /&lt;br /&gt;
#add the line&lt;br /&gt;
     /sbin/zfs set readonly=off zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In /etc/rc.d/rc.6&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# comment out the line&lt;br /&gt;
#    /bin/mount -v -n -o remount,ro /&lt;br /&gt;
#add the line&lt;br /&gt;
     /sbin/zfs set readonly=on zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In /etc/rc.d/rc.6, near the bottom just before poweroff|reboot, add the following block of lines:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
########################&lt;br /&gt;
# Try to export zfs-root&lt;br /&gt;
/sbin/zpool export zfs-root&lt;br /&gt;
if [ $? -gt 0 ] ; then&lt;br /&gt;
 echo &amp;quot;ZFS export failed.&amp;quot;&lt;br /&gt;
 echo &amp;quot;Notice: if root fs is busy, then this is normal fail.&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;ZFS export successful.&amp;quot;&lt;br /&gt;
 echo &amp;quot;Warning: successful export is abnormal for root fs.&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
/bin/sleep 5&lt;br /&gt;
########################&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
For ZFS, you cannot run fsck on it. It doesn't support that kind of filesystem check. The rc.S script will complain a lot in many places about not being able to run fsck on the zfs-root. To disable all attempts to run fsck, we can simply create a file that acts as a flag in /etc/rc.d/rc.S to tell it to skip fsck:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
touch /etc/fastboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This fastboot file is normally a run-once temporary file, and it is deleted near the bottom inside rc.S. Edit rc.S and stop it from deleting /etc/fastboot. We would like it to always skip all fsck. Edit /etc/rc.d/rc.S, and find the &amp;quot;rm&amp;quot; of fastboot, and do not have it removed!&lt;br /&gt;
&lt;br /&gt;
An alternative to using /etc/fastboot is to make the file &amp;lt;code&amp;gt;/sbin/fsck.zfs&amp;lt;/code&amp;gt; that always just &amp;quot;does nothing successfully&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
exec /usr/bin/true&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This fsck helper has the advantage that you do not need to alter &amp;lt;code&amp;gt;rc.S&amp;lt;/code&amp;gt; as much, or at all if you use zfs property &amp;lt;code&amp;gt;mountpoint=legacy&amp;lt;/code&amp;gt; and the regular &amp;lt;code&amp;gt;mount&amp;lt;/code&amp;gt; command on your zfs-root. With these ideas, no slackware /etc/rc.d/* files really need editing, but it is up to you how you want to experiment.&lt;br /&gt;
&lt;br /&gt;
We are getting close, and have finished all editing, so make /boot/initrd.gz and install lilo:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkinitrd -F&lt;br /&gt;
lilo&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We finished! All that's left to do is clean up.&lt;br /&gt;
&lt;br /&gt;
Exit the chroot.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
exit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Try to umount everything:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
umount /mnt/proc&lt;br /&gt;
umount /mnt/sys&lt;br /&gt;
umount /mnt/dev&lt;br /&gt;
umount /mnt/boot&lt;br /&gt;
umount /mnt/mnt/cdrom&lt;br /&gt;
umount /mnt/root/packages&lt;br /&gt;
umount /mnt&lt;br /&gt;
zpool export zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note, that export stops a pool and frees devices, while import binds devices and starts a pool. It is somewhat like mdadm -A -s and mdadm -S -s, while /etc/zfs/zpool.cache might be somewhat like mdadm -E -s &amp;gt; /etc/mdadm.conf.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Remove the DVD or change boot order&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When you reboot, if all is good, you are booting properly onto a slackware installed on a ZFS root! Congrats!&lt;br /&gt;
&lt;br /&gt;
If this seems to go badly, and this might happen if the import fails as explained some before, then you will be on the initrd's rescue command line just before the part in init where it wants to mount zfs-root and switch_root to boot up. In this case, you typically got commands like these to do:&lt;br /&gt;
&lt;br /&gt;
If you get dumped to rescue because zpool import will not work and requires -f (force), then:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 zpool import -f zfs-root&lt;br /&gt;
 zpool export    zfs-root&lt;br /&gt;
 zpool import    zfs-root&lt;br /&gt;
 mount zfs-root&lt;br /&gt;
 exit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This can happen if hostname, hostid, or uname changes.&lt;br /&gt;
&lt;br /&gt;
If you get into a jam and need to boot into the initrd and skip zpool import etc, use the lilo prompt (or, boot the install-dvd):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
boot: vmlinuz rescue&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the rescue mode of the initrd, after you have mounted your zfs-root as readonly=on to /mnt, then &amp;quot;exit&amp;quot; to continue booting.&lt;br /&gt;
&lt;br /&gt;
In other emergency command lines, you might need to run the lines at the end of init starting from: &amp;lt;code&amp;gt;udevadm info --cleanup-db; udevadm control --exit&amp;lt;/code&amp;gt;&lt;br /&gt;
If you don't run those udevadm commands, two runs of udevd fight each other and it is slow; you have to wait 2 minutes twice for timeouts (4 minutes).&lt;br /&gt;
The last line in init is run like: &amp;lt;code&amp;gt;exec switch_root /mnt /sbin/init 1&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Warning: the switch_root command is kind of dangerous, so read the manual page about it. From what I can tell, everything except the new root &amp;quot;/mnt&amp;quot; is deleted, so you are giving a command that says what NOT to delete! Make sure nothing got mounted outside of &amp;quot;/mnt&amp;quot; before you run it. However, the deletes should not cross filesystems, but only delete the contents of initramfs.&lt;br /&gt;
&lt;br /&gt;
Also, in rescue command line or anytime you have finished making changes and are about to reboot in some abnormal situation, first run:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set readonly=on zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A bug in unpatched grep 2.13 build 1, found slackware 14.0rc1, causes problems when processing files stored on ZFS but rarely shows problems on other filesystems; the bug does not handle sparse files on zfs and btrfs correctly and results in chaos with slackpkg, compiling kernel modules, and possibly many other things. You must downgrade grep to 2.12 or use the patched grep 2.13 build 2 in slackware 14.0rc2 or later.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
Upgrading:&lt;br /&gt;
&lt;br /&gt;
From time to time you will want to upgrade the kernel to the new kernel in slackware64-current or in patches/. This will also necessitate a rebuild and reinstall or upgrade of spl and zfs. Below is an example of when both kernel and spl/zfs are being upgraded, to give an idea of the process:&lt;br /&gt;
&lt;br /&gt;
Using slackpkg, that is configured to use your local slackware mirror is a good option but you can also configure it to use a remote mirror.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slackpkg upgrade-all&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Assume slackpkg just upgraded your kernel, kernel-modules, kernel-headers, and kernel-source.&lt;br /&gt;
&lt;br /&gt;
Note: the first time you try to run on kernel-generic, setup kernel-huge in lilo as 2nd choice. Huge has all the hard drive controllers builtin, but generic has them all as modules. For example, run &amp;quot;modinfo mptsas&amp;quot; to see module options (maybe you have a LSISAS1068) for your hard drive controller. Add file /etc/modprobe.d/mptsas.conf to set options you want with a line: options mptsas ... Do this for all the device driver modules for your hardware. Do this setup while you are on the huge kernel, then setup to reboot to generic. Include all these modules you need into mkinitrd.conf MODULES_LIST. Check that /boot/initrd-tree/etc/modprobe.d/ has a copy of your customized module conf files because it is on the initrd where the modules will load and use the conf files. mkinitrd probably copies all /etc/modprobe.d/* files into the initrd-tree, but check it. Pay attention to /etc/modprobe.d/README and /lib/modprobe.d/* /lib/modprobe.d/* maybe not copied to initrd-tree but you might want to copy some of it into your initrd-tree yourself to use them.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Check that upgraded kernel-source is symlinked to /usr/src/linux (zfs build looks here). SPL/ZFS modules will install to the kernel version in /lib/modules/&amp;lt;/usr/src/linux kernel version&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /usr/local/src&lt;br /&gt;
tar xvzf ~/spl-*.tar.gz&lt;br /&gt;
tar xvzf ~/zfs-*.tar.gz&lt;br /&gt;
&lt;br /&gt;
###### upgrade spl 1st&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-*&lt;br /&gt;
./configure --prefix=/ --libexecdir=/usr/libexec --libdir=/lib64 --includedir=/usr/include --datarootdir=/usr/share&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=/usr/local/src/install&lt;br /&gt;
cd ../install&lt;br /&gt;
makepkg ../spl-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
upgradepkg spl-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
depmod &amp;lt;new kernel version&amp;gt;     (e.g. depmod 3.2.27, if .27 is new kernel upgrade; you currently run on old, maybe .26)&lt;br /&gt;
# this builds the module dependencies in /lib/modules/&amp;lt;new kernel version&amp;gt;&lt;br /&gt;
###### upgrade zfs 2nd&lt;br /&gt;
mkdir install&lt;br /&gt;
cd zfs-*&lt;br /&gt;
./configure --prefix=/ --libexecdir=/usr/libexec --libdir=/lib64 --includedir=/usr/include --datarootdir=/usr/share&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=/usr/local/src/install&lt;br /&gt;
cd ../install&lt;br /&gt;
makepkg ../zfs-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
upgradepkg zfs-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
depmod 3.2.27&lt;br /&gt;
####### upgrade spl/zfs inside altroot /boot/initrd-tree&lt;br /&gt;
ROOT=/boot/initrd-tree upgradepkg spl-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
ROOT=/boot/initrd-tree upgradepkg zfs-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
# note: ROOT is an environment variable, not a command line option to upgradepkg!&lt;br /&gt;
# note: do not worry about depmod inside initrd-tree, mkinitrd -F actually installs the modules&lt;br /&gt;
# note: this upgrade here is really to just upgrade the command line tools zpool, zfs etc&lt;br /&gt;
####### rebuild /boot/initrd.gz and reinstall lilo&lt;br /&gt;
vi /etc/mkinitrd.conf&lt;br /&gt;
# temporarily set KERNEL_VERSION to new version, but you are still running on old version&lt;br /&gt;
mkinitrd -F&lt;br /&gt;
lilo&lt;br /&gt;
vi /etc/mkinitrd.conf&lt;br /&gt;
# you can set KERNEL_VERSION back to $(uname -r) now&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After reboot you can remove any old /lib/modules/&amp;lt;old kernel version&amp;gt; directory.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
More about /etc/hostid. If you want to experiment changing your /etc/hostid file and seeing if you can use it and make zpool import work normally, here is a tool that might be helpful:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/* software product name: foobarz-chhostid.c&lt;br /&gt;
 * suggested binary name: chhostid&lt;br /&gt;
 * license              : BSD&lt;br /&gt;
 * license text:&lt;br /&gt;
Copyright (c) 2012, foobarz&lt;br /&gt;
All rights reserved.&lt;br /&gt;
&lt;br /&gt;
Redistribution and use in source and binary forms, with or without&lt;br /&gt;
modification, are permitted provided that the following conditions are met:&lt;br /&gt;
    * Redistributions of source code must retain the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer.&lt;br /&gt;
    * Redistributions in binary form must reproduce the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer in the&lt;br /&gt;
      documentation and/or other materials provided with the distribution.&lt;br /&gt;
    * Neither the name of the &amp;lt;organization&amp;gt; nor the&lt;br /&gt;
      names of its contributors may be used to endorse or promote products&lt;br /&gt;
      derived from this software without specific prior written permission.&lt;br /&gt;
&lt;br /&gt;
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &amp;quot;AS IS&amp;quot; AND&lt;br /&gt;
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED&lt;br /&gt;
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE&lt;br /&gt;
DISCLAIMED. IN NO EVENT SHALL &amp;lt;COPYRIGHT HOLDER&amp;gt; BE LIABLE FOR ANY&lt;br /&gt;
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES&lt;br /&gt;
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;&lt;br /&gt;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND&lt;br /&gt;
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT&lt;br /&gt;
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS&lt;br /&gt;
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#define FOOBARZ_CHHOSTID_VERSION &amp;quot;1.0.5&amp;quot;&lt;br /&gt;
#include &amp;lt;sys/socket.h&amp;gt;&lt;br /&gt;
#include &amp;lt;netinet/in.h&amp;gt;&lt;br /&gt;
#include &amp;lt;arpa/inet.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;endian.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sysexits.h&amp;gt;&lt;br /&gt;
/* note: if include stdlib then sethostid fails even with _BSD_SOURCE defined */&lt;br /&gt;
&lt;br /&gt;
long swapbytes(long abcd) {&lt;br /&gt;
  long badc;&lt;br /&gt;
  unsigned char addr_a;&lt;br /&gt;
  unsigned char addr_b;&lt;br /&gt;
  unsigned char addr_c;&lt;br /&gt;
  unsigned char addr_d;&lt;br /&gt;
  addr_a = (unsigned char) (abcd &amp;gt;&amp;gt; 24);&lt;br /&gt;
  addr_b = (unsigned char) (abcd &amp;gt;&amp;gt; 16);&lt;br /&gt;
  addr_c = (unsigned char) (abcd &amp;gt;&amp;gt;  8);&lt;br /&gt;
  addr_d = (unsigned char) (abcd);&lt;br /&gt;
  return badc = ( (addr_b &amp;lt;&amp;lt; 24) | (addr_a &amp;lt;&amp;lt; 16) | (addr_d &amp;lt;&amp;lt; 8) | addr_c );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[])&lt;br /&gt;
{&lt;br /&gt;
 long newhostid;&lt;br /&gt;
 struct in_addr addr;&lt;br /&gt;
 char* invalidchar;&lt;br /&gt;
&lt;br /&gt;
 /*********** check command line */&lt;br /&gt;
 if(!( ((argc==3) &amp;amp;&amp;amp; ( (strcmp(argv[1],&amp;quot;-h&amp;quot;)==0) ||&lt;br /&gt;
                       (strcmp(argv[1],&amp;quot;-i&amp;quot;)==0) ||&lt;br /&gt;
                       (strcmp(argv[1],&amp;quot;-l&amp;quot;)==0) )) ||&lt;br /&gt;
       ((argc==2) &amp;amp;&amp;amp; ( (strcmp(argv[1],&amp;quot;-s&amp;quot;)==0) ))&lt;br /&gt;
     )&lt;br /&gt;
   ) {&lt;br /&gt;
                 /*01234567890123456789012345678901234567890123456789012345678901234567890123456789*/&lt;br /&gt;
  fprintf(stderr, &amp;quot;foobarz-chhostid, version %s. License: BSD.\n&amp;quot;, FOOBARZ_CHHOSTID_VERSION);&lt;br /&gt;
  fprintf(stderr, &amp;quot;foobarz-chhostid, (c) 2012, foobarz; all rights reserved.\n&amp;quot;);&lt;br /&gt;
  fprintf(stderr, &amp;quot;descr: %s change system hostid (in /etc/hostid).\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -h &amp;lt;new hostid&amp;gt;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        Change system hostid to &amp;lt;new hostid&amp;gt;;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        &amp;lt;new hostid&amp;gt; must be 32bit 8-digit hex number xxxxxxxx, each x in 0-f|F.\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        The ip corresponding to &amp;lt;new hostid&amp;gt; is also listed for reference only.\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -i &amp;lt;dotted ip address&amp;gt;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        Change system hostid to hostid corresponding to &amp;lt;dotted ip address&amp;gt;.\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -l &amp;lt;dotted ip address&amp;gt;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        List hostid corresponding to &amp;lt;dotted ip address&amp;gt;;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        no change to system hostid.\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -s\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        List current system hostid and corresponding ip address;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        no change to system hostid.\n&amp;quot;, argv[0]);&lt;br /&gt;
  return EX_USAGE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -h &amp;lt;hostid&amp;gt; */&lt;br /&gt;
 if( strcmp(argv[1],&amp;quot;-h&amp;quot;) == 0 ) {&lt;br /&gt;
  if(strlen(argv[2]) != 8) { fprintf(stderr, &amp;quot;new hostid must be 8-digit hex number xxxxxxxx, each x in 0-f|F\n&amp;quot;); return EX_USAGE; }&lt;br /&gt;
&lt;br /&gt;
  newhostid = strtol(argv[2],&amp;amp;invalidchar,16);&lt;br /&gt;
  if( newhostid==LONG_MIN ) { perror(&amp;quot;strtol (underflow)&amp;quot;); return EX_USAGE; }&lt;br /&gt;
  if( newhostid==LONG_MAX ) { perror(&amp;quot;strtol (overflow)&amp;quot;); return EX_USAGE; }&lt;br /&gt;
  if(*invalidchar != '\0') { fprintf(stderr, &amp;quot;invalid hex number %c; must be in 0-f|F\n&amp;quot;, *invalidchar); return EX_USAGE; }&lt;br /&gt;
&lt;br /&gt;
  if( sethostid(newhostid) != 0 ) {&lt;br /&gt;
   perror(&amp;quot;sethostid&amp;quot;);&lt;br /&gt;
   if( errno == EPERM ) return EX_NOPERM;&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
  }&lt;br /&gt;
  printf(&amp;quot;System hostid changed.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  /* hostid is a byte-swapped ip like b.a.d.c */&lt;br /&gt;
  /* get ip by swapping to correct order a.b.c.d and save into in_addr struct */&lt;br /&gt;
  addr.s_addr = htonl(swapbytes(newhostid));&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -i or -l, then find hostid for &amp;lt;dotted ip address&amp;gt; */&lt;br /&gt;
 if( (strcmp(argv[1],&amp;quot;-i&amp;quot;) == 0) || (strcmp(argv[1],&amp;quot;-l&amp;quot;) == 0) ) {&lt;br /&gt;
  if( inet_aton(argv[2], &amp;amp;addr) == 0 ) { fprintf(stderr, &amp;quot;inet_aton: invalid dotted ip address: %s\n&amp;quot;, argv[2]); return EX_USAGE; }&lt;br /&gt;
&lt;br /&gt;
  /* hostid is a byte-swapped ip like b.a.d.c */&lt;br /&gt;
  /* get hostid by swapping bytes of ip a.b.c.d */&lt;br /&gt;
  newhostid = swapbytes(ntohl(addr.s_addr));&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -i &amp;lt;dotted ip address&amp;gt; */&lt;br /&gt;
 if( strcmp(argv[1],&amp;quot;-i&amp;quot;) == 0 ) {&lt;br /&gt;
  if( sethostid(newhostid) != 0 ) {&lt;br /&gt;
   perror(&amp;quot;sethostid&amp;quot;);&lt;br /&gt;
   if( errno == EPERM ) return EX_NOPERM;&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
  }&lt;br /&gt;
  printf(&amp;quot;System hostid changed.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -l &amp;lt;dotted ip address&amp;gt; */&lt;br /&gt;
 if(strcmp(argv[1],&amp;quot;-l&amp;quot;) == 0 ) {&lt;br /&gt;
   printf(&amp;quot;Listing hostid for ip. (no changes)\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -s */&lt;br /&gt;
 if(strcmp(argv[1],&amp;quot;-s&amp;quot;) == 0 ) {&lt;br /&gt;
   /* see if /etc/hostid exists and print info */&lt;br /&gt;
   if( access(&amp;quot;/etc/hostid&amp;quot;, F_OK) != 0 ) {&lt;br /&gt;
     printf(&amp;quot;Notice: /etc/hostid does not exist.\n&amp;quot;);&lt;br /&gt;
     perror(&amp;quot;Reason&amp;quot;);&lt;br /&gt;
     printf(&amp;quot;System hostid derived from ip of hostname found in hosts file or dns.\n&amp;quot;);&lt;br /&gt;
   } else {&lt;br /&gt;
     printf(&amp;quot;Notice: /etc/hostid exists.\n&amp;quot;&lt;br /&gt;
            &amp;quot;System hostid is obtained from hostid file.\n&amp;quot;);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
  errno=0;&lt;br /&gt;
  newhostid = gethostid();&lt;br /&gt;
  if(errno!=0) { perror(&amp;quot;gethostid&amp;quot;); return EX_UNAVAILABLE; }&lt;br /&gt;
&lt;br /&gt;
  /* hostid is a byte-swapped ip like b.a.d.c */&lt;br /&gt;
  /* get ip by swapping to correct order a.b.c.d and save into in_addr struct */&lt;br /&gt;
  addr.s_addr = htonl(swapbytes(newhostid));&lt;br /&gt;
&lt;br /&gt;
  printf(&amp;quot;Listing current system hostid. (no changes)\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** print info and return */&lt;br /&gt;
 printf(&amp;quot;ip dot: %s\n&amp;quot;, inet_ntoa(addr) );&lt;br /&gt;
 printf(&amp;quot;ip hex: %.8x\n&amp;quot;, ntohl(addr.s_addr) );&lt;br /&gt;
 printf(&amp;quot;hostid: %.8x\n&amp;quot;, newhostid );&lt;br /&gt;
 return EX_OK;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
----&lt;br /&gt;
Now available! &amp;quot;ZFS root (builtin)&amp;quot; wiki (aka &amp;quot;ZFS root, part II&amp;quot;):&lt;br /&gt;
http://slackwiki.com/ZFS_root_(builtin)&lt;br /&gt;
It is now possible to build the modules and a small initramfs into your kernel to have a fully-contained and bootable ZFS root kernel from a simple lilo entry. Good luck!&lt;/div&gt;</description>
			<pubDate>Fri, 14 Sep 2012 06:50:06 GMT</pubDate>
			<dc:creator>Foobarz</dc:creator>
			<comments>https://www.slackwiki.com/Talk:ZFS_root</comments>
		</item>
		<item>
			<title>ZFS root (builtin)</title>
			<link>https://www.slackwiki.com/index.php?title=ZFS_root_(builtin)&amp;diff=791</link>
			<guid isPermaLink="false">https://www.slackwiki.com/index.php?title=ZFS_root_(builtin)&amp;diff=791</guid>
			<description>&lt;p&gt;Foobarz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Tutorials]]&lt;br /&gt;
The first [http://slackwiki.com/ZFS_root &amp;quot;ZFS root&amp;quot;] wiki explains the details of running ZFS as your root filesystem by using a fully modular generic kernel approach. Now, I can share how it can be done with the SPL and ZFS modules built into the kernel. This procedure is just an example and can use some fine tuning, but here goes:&lt;br /&gt;
&lt;br /&gt;
The steps below are to create a kernel with SPL and ZFS modules builtin. This kernel will be installed as an alternative kernel to boot in lilo, and it will have a separate kernel installation from the fully modular and working system kernel. This will allow testing the builtin kernel while able to boot back onto a working modular ZFS system. We start this procedure assuming you are on a working fully modular ZFS install as in the &amp;quot;ZFS root&amp;quot; wiki.&lt;br /&gt;
&lt;br /&gt;
Use mountpoint=legacy so that zfs will not expect &amp;lt;code&amp;gt;zfs mount&amp;lt;/code&amp;gt;, but instead expect standard &amp;lt;code&amp;gt;mount&amp;lt;/code&amp;gt; for mounting zfs-root:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=legacy zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Edit &amp;lt;code&amp;gt;/etc/rc.d/rc.S&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;rc.6&amp;lt;/code&amp;gt; to use regular &amp;lt;code&amp;gt;mount&amp;lt;/code&amp;gt; commands, remove &amp;lt;code&amp;gt;zfs&amp;lt;/code&amp;gt; commands. Edit &amp;lt;code&amp;gt;rc.6&amp;lt;/code&amp;gt; and remove or comment out &amp;lt;code&amp;gt;zfs export&amp;lt;/code&amp;gt; command. These edits undo changes made in the &amp;quot;ZFS root&amp;quot; wiki, but it shows the two different ways of mounting a zfs filesystem.&lt;br /&gt;
&lt;br /&gt;
You &amp;lt;i&amp;gt;might&amp;lt;/i&amp;gt; think to set &amp;lt;code&amp;gt;bootfs&amp;lt;/code&amp;gt; property like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool set bootfs=zfs-root zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
However, this will result in ZFS placing many restrictions on zfs-root as per how that option is used on Solaris systems:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; zfs-root must be VTOC (SMI) label, not GPT (EFI) label&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; zfs-root can only contain 1 vdev: either a plain disk, or a mirror&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
So, do &amp;lt;b&amp;gt;NOT&amp;lt;/b&amp;gt; set that property! If &amp;lt;code&amp;gt;bootfs&amp;lt;/code&amp;gt; is set, you would find that you cannot add vdevs to your zfs-root. If it is set already, then unset it like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool set bootfs= zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Make a directory to store files to be inside the initramfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkdir /boot/initramfs-source&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This directory will hold some files for the initial rootfs inside the kernel. Your &amp;lt;code&amp;gt;/boot&amp;lt;/code&amp;gt; should be on a small ext4 partition or on a mounted USB stick that you use to boot.&lt;br /&gt;
&lt;br /&gt;
Extract the slackware kernel-source package to obtain a copy of the kernel source, and make an initial kernel config for it:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir src&lt;br /&gt;
cd src&lt;br /&gt;
tar xvzf /mnt/cdrom/slackware64/k/kernel-source-*.txz&lt;br /&gt;
mv usr/src/linux-3.2.27 /usr/src/linux-3.2.27b&lt;br /&gt;
rm -r install&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make menuconfig&lt;br /&gt;
  General setup-&amp;gt;Local version - append to kernel release = b&lt;br /&gt;
  General setup-&amp;gt;Default hostname                         = slackzfs&lt;br /&gt;
  General setup-&amp;gt;Initramfs source files(s)                = /boot/initramfs-source&lt;br /&gt;
  Device Drivers-&amp;gt;SCSI device support-&amp;gt;SCSI low-level drivers-&amp;gt; &amp;lt;*&amp;gt; SYM53C8XX Version 2 SCSI support&lt;br /&gt;
  File systems -&amp;gt; &amp;lt;*&amp;gt; The Extended 4 (ext4) filesystem&lt;br /&gt;
  # build in any hard drive controllers and filesystems that you need for booting&lt;br /&gt;
  # then save the config&lt;br /&gt;
make prepare scripts&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The kernel source has been set to have a &amp;quot;Local version&amp;quot; &amp;lt;code&amp;gt;b&amp;lt;/code&amp;gt;. This will result in modules installed to &amp;lt;code&amp;gt;/lib/modules/3.2.27b&amp;lt;/code&amp;gt; and keeps this kernel's source and modules seperate from slackware's kernel-generic package installation. The &amp;lt;code&amp;gt;make prepare scripts&amp;lt;/code&amp;gt; command readies the kernel source as needed before we can install a copy of spl and zfs modules into the kernel source tree.&lt;br /&gt;
&lt;br /&gt;
Now proceed to configure and copy spl and zfs into the kernel source tree:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd ~/src&lt;br /&gt;
tar xvzf ~/spl-0.6.0-rc10.tar.gz&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-0.6.0-rc10&lt;br /&gt;
./configure \&lt;br /&gt;
    --prefix=/ \&lt;br /&gt;
    --libdir=/lib64 \&lt;br /&gt;
    --includedir=/usr/include \&lt;br /&gt;
    --datarootdir=/usr/share \&lt;br /&gt;
    --enable-linux-builtin=yes \&lt;br /&gt;
    --with-linux=/usr/src/linux-3.2.27b \&lt;br /&gt;
    --with-linux-obj=/usr/src/linux-3.2.27b&lt;br /&gt;
wget https://raw.github.com/zfsonlinux/spl/master/copy-builtin&lt;br /&gt;
chmod +x copy-builtin&lt;br /&gt;
./copy-builtin /usr/src/linux-3.2.27b&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../spl-0.6.0rc10_3.2.27b-x86_64-1root.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
&lt;br /&gt;
tar xvzf ~/zfs-0.6.0-rc10.tar.gz&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-0.6.0-rc10&lt;br /&gt;
./configure \&lt;br /&gt;
    --prefix=/ \&lt;br /&gt;
    --libdir=/lib64 \&lt;br /&gt;
    --includedir=/usr/include \&lt;br /&gt;
    --datarootdir=/usr/share \&lt;br /&gt;
    --enable-linux-builtin=yes \&lt;br /&gt;
    --with-linux=/usr/src/linux-3.2.27b \&lt;br /&gt;
    --with-linux-obj=/usr/src/linux-3.2.27b \&lt;br /&gt;
    --with-spl=/root/src/spl-0.6.0-rc10&lt;br /&gt;
wget https://raw.github.com/zfsonlinux/zfs/master/copy-builtin&lt;br /&gt;
chmod +x copy-builtin&lt;br /&gt;
./copy-builtin /usr/src/linux-3.2.27b&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../zfs-0.6.0rc10_3.2.27b-x86_64-1root.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
At this point, the &amp;lt;code&amp;gt;copy-builtin&amp;lt;/code&amp;gt; scripts have installed the configured spl and zfs modules source into the kernel source. The regular &amp;lt;code&amp;gt;make menuconfig&amp;lt;/code&amp;gt; in the kernel source should now show options for spl and zfs in the kernel config.&lt;br /&gt;
&lt;br /&gt;
As of this writing, the copy-builtin script places the spl and zfs modules into the kernel source in places where the modules may not initialize in the best order, &amp;lt;i&amp;gt;after&amp;lt;/i&amp;gt; all lower-level storage drivers are initialized. If spl and zfs initialize too soon, there is a chance they may not be able to see all of the storage devices. The order of initialization (as seen in dmesg) of modules that are builtin to the kernel is the order that the modules are linked into the kernel during kernel compilation. The order of link depends on where the module source files are located in the kernel source tree. To ensure that spl and zfs will initialize after all hardware drivers, we move them into the &amp;lt;code&amp;gt;drivers&amp;lt;/code&amp;gt; tree and after all other drivers:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
mkdir drivers/zfsonlinux&lt;br /&gt;
mv spl drivers/zfsonlinux&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  # remove references to spl&lt;br /&gt;
vi Makefile&lt;br /&gt;
  # remove references to spl&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/fs&lt;br /&gt;
mv zfs ../drivers/zfsonlinux&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  # remove references to zfs&lt;br /&gt;
vi Makefile&lt;br /&gt;
  # remove references to zfs&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  )# add line at end of menu, before &amp;quot;endmenu&amp;quot;:&lt;br /&gt;
  )source &amp;quot;drivers/zfsonlinux/Kconfig&amp;quot;&lt;br /&gt;
  )endmenu&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers&lt;br /&gt;
vi Makefile&lt;br /&gt;
  )# add line at very end of file:&lt;br /&gt;
  )obj-$(CONFIG_ZFSONLINUX) += zfsonlinux/&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers/zfsonlinux&lt;br /&gt;
cat &amp;gt; Kconfig &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
menuconfig ZFSONLINUX&lt;br /&gt;
	tristate &amp;quot;ZFSonLinux support&amp;quot;&lt;br /&gt;
&lt;br /&gt;
if ZFSONLINUX&lt;br /&gt;
&lt;br /&gt;
source &amp;quot;drivers/zfsonlinux/spl/Kconifg&amp;quot;&lt;br /&gt;
&lt;br /&gt;
source &amp;quot;drivers/zfsonlinux/zfs/Kconifg&amp;quot;&lt;br /&gt;
&lt;br /&gt;
endif&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/zfsonlinux&lt;br /&gt;
cat &amp;gt; Makefile &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
obj-$(CONFIG_SPL) += spl/&lt;br /&gt;
obj-$(CONFIG_ZFS) += zfs/&lt;br /&gt;
EOF&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This completes the move of the spl and zfs modules in the kernel source tree to be under &amp;lt;code&amp;gt;drivers/zfsonlinux&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Now, in kernel configuration, you can build in the modules as follows:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make menuconfig&lt;br /&gt;
   Device Drivers -&amp;gt;&lt;br /&gt;
    &amp;lt;*&amp;gt; ZFSonLinux support -&amp;gt;&lt;br /&gt;
      &amp;lt;*&amp;gt; Solaris Porting Layer (SPL)&lt;br /&gt;
      &amp;lt;*&amp;gt;     ZFS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the kernel config, we set &amp;lt;code&amp;gt;/boot/initramfs-source&amp;lt;/code&amp;gt; as source location of the contents to be linked into kernel's builtin initramfs (rootfs). Now, we create some files that are needed to be in the initramfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /boot/initramfs-source&lt;br /&gt;
&lt;br /&gt;
# make standard directories&lt;br /&gt;
mkdir -p proc dev sys mnt bin sbin etc/zfs&lt;br /&gt;
&lt;br /&gt;
# zfs seems to want mtab present, even if empty&lt;br /&gt;
touch etc/mtab&lt;br /&gt;
&lt;br /&gt;
# if zpool.cache file can be read by zfs at module init, it imports the pools in the cache&lt;br /&gt;
cp /etc/zfs/zpool.cache-initrd etc/zfs/zpool.cache&lt;br /&gt;
&lt;br /&gt;
# make initial console device node; otherwise, there is a problem at startup:&lt;br /&gt;
# &amp;quot;Warning: unable to open an initial console&amp;quot; and you'd have problems with console and tty login&lt;br /&gt;
# making these nodes from within /init is not early enough to avoid problem&lt;br /&gt;
mknod dev/console c 5 1   # system console&lt;br /&gt;
&lt;br /&gt;
# make memory device kmsg to &amp;quot;printk&amp;quot; kernel messages&lt;br /&gt;
# we can write to this file to send out messages&lt;br /&gt;
mknod dev/kmsg    c 1 11  # lines printed to kmsg enter kernel messages buffer&lt;br /&gt;
&lt;br /&gt;
# recommended loop0 device to mount fs images&lt;br /&gt;
mknod dev/loop0   b 7 0&lt;br /&gt;
&lt;br /&gt;
# make initial virtual terminal devices&lt;br /&gt;
mknod dev/tty     c 5 0   # current tty&lt;br /&gt;
mknod dev/tty0    c 4 0   # current virtual term&lt;br /&gt;
mknod dev/tty1    c 4 1   # login virtual term 1 (F1)&lt;br /&gt;
&lt;br /&gt;
# make alternative console=ttyS0 standard 8250/16550 UART serial port devices&lt;br /&gt;
#   useful with kernel parameter console=ttyS0&lt;br /&gt;
#          with qemu -nographic -option-rom sgabios.bin,bootindex=0&lt;br /&gt;
mknod dev/ttyS0   c 4 64  # COM1&lt;br /&gt;
mknod dev/ttyS1   c 4 65  # COM2&lt;br /&gt;
mknod dev/ttyS2   c 4 66  # COM3&lt;br /&gt;
mknod dev/ttyS3   c 4 67  $ COM4&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This should be enough device nodes initially in the initramfs. Once devtmpfs mounts over /dev inside initramfs, a lot more devices are available in it by default.&lt;br /&gt;
&lt;br /&gt;
The initramfs needs an &amp;lt;code&amp;gt;/init&amp;lt;/code&amp;gt; program that will be run automatically by the kernel as process id 1, the first program to run on the system. This program's task is to mount a root filesystem, switch it to be the new root (/), and then exec the init (&amp;lt;code&amp;gt;/sbin/init&amp;lt;/code&amp;gt;) program that is on the new root so that the new root system is booted.&lt;br /&gt;
&lt;br /&gt;
The common way to make /init is using busybox with files like these in /boot/initrd-tree or /boot/initramfs-source:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
bin/busybox&lt;br /&gt;
bin/ash -&amp;gt; busybox&lt;br /&gt;
bin/sh -&amp;gt; busybox&lt;br /&gt;
# run busybox to see what other &amp;quot;applets&amp;quot; can be symlinked to it&lt;br /&gt;
# when busybox is run as a different symlinked applet name, it runs as the applet&lt;br /&gt;
init&lt;br /&gt;
# init can be an ash script, see slackware's /boot/initrd-tree/init for example&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For example, as an ash script, slackware's init does the following:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;parse kernel parameters passed into it and set variables based on them&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;start udevd and trigger rules for block devices to setup initial /dev devices&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;load kernel modules and keyboard map&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;run mdadm, cryptsetup, lvm, zpool/zfs to setup more devices&lt;br /&gt;
     (any udev rules for them should do more /dev setup in the background)&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;mount the root filesystem read-only at /mnt&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;stat /mnt/sbin/init, and if not executable run a rescue shell /bin/sh&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;shutdown udevd so it can be restarted by root system when booted&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;mount --move {proc,sys,run,dev} to under /mnt&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;run: exec switch_root /mnt /sbin/init $RUNLEVEL&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The slackware mkinitrd package is a fully configured BusyBox installation that makes an external initramfs image file, initrd.gz, that is passed to the kernel by the bootloader (lilo). It could be changed to be internal to the kernel by just using initrd-tree as the CONFIG_INITRAMFS_SOURCE in the kernel config and removing initrd in the lilo.conf.&lt;br /&gt;
&lt;br /&gt;
The main purpose of most initramfs/initrd is to load and configure kernel modules and devices needed to mount a root filesystem. Because the spl/zfs modules are builtin, there isn't really a lot that needs to be done by an initramfs. What remains to be done is import the zfs-root pool, mount it, and exec the system /sbin/init. The kernel's &amp;quot;legacy&amp;quot; parameters &amp;lt;code&amp;gt;root=&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;rootfstype=&amp;lt;/code&amp;gt; that are able to directly boot a root disk do not work with ZFS at this time because ZFS pools always need to be imported before it is possible to mount and boot on them. The automatic import that ZFS can do by using a cachefile (/etc/zfs/zpool.cache) stored in initramfs still does not work with the legacy boot parameters because at an eariler stage of the boot process, the kernel ignores a rootfs that does not contain an &amp;lt;code&amp;gt;/init&amp;lt;/code&amp;gt; program, and/or the device type of an imported pool is not the device types recognized by the legacy boot as valid root devices.&lt;br /&gt;
&lt;br /&gt;
You could just continue to use slackware's mkinitrd package as in the &amp;quot;ZFS root&amp;quot; wiki and it works the same whether the modules are builtin or not. But, by building the spl/zfs modules in, aren't we really wanting to get rid of using the mkinitrd/initrd.gz? We'd like to have a kernel with everything in it to boot, and use a simple lilo image entry that has no initrd.&lt;br /&gt;
&lt;br /&gt;
We can do this, and not use the mkinitrd package, but we still need to finish our own initramfs &amp;lt;code&amp;gt;/init&amp;lt;/code&amp;gt; program to import, mount, switch root, and boot. Save the following c program to &amp;quot;foobarz-init.c&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/* software product name: foobarz-init.c&lt;br /&gt;
 * suggested binary name: /init (in initramfs-source, rootfs)&lt;br /&gt;
 * license              : BSD&lt;br /&gt;
 * license text:&lt;br /&gt;
Copyright (c) 2012, foobarz&lt;br /&gt;
All rights reserved.&lt;br /&gt;
&lt;br /&gt;
Redistribution and use in source and binary forms, with or without&lt;br /&gt;
modification, are permitted provided that the following conditions are met:&lt;br /&gt;
    * Redistributions of source code must retain the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer.&lt;br /&gt;
    * Redistributions in binary form must reproduce the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer in the&lt;br /&gt;
      documentation and/or other materials provided with the distribution.&lt;br /&gt;
    * Neither the name of the &amp;lt;organization&amp;gt; nor the&lt;br /&gt;
      names of its contributors may be used to endorse or promote products&lt;br /&gt;
      derived from this software without specific prior written permission.&lt;br /&gt;
&lt;br /&gt;
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &amp;quot;AS IS&amp;quot; AND&lt;br /&gt;
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED&lt;br /&gt;
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE&lt;br /&gt;
DISCLAIMED. IN NO EVENT SHALL &amp;lt;COPYRIGHT HOLDER&amp;gt; BE LIABLE FOR ANY&lt;br /&gt;
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES&lt;br /&gt;
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;&lt;br /&gt;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND&lt;br /&gt;
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT&lt;br /&gt;
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS&lt;br /&gt;
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
/* Your initramfs-source should contain the following&lt;br /&gt;
 *&lt;br /&gt;
 * cd /boot/initramfs-source&lt;br /&gt;
 * mkdir -p proc dev sys mnt bin sbin etc/zfs&lt;br /&gt;
 * touch etc/mtab&lt;br /&gt;
 * cp /etc/zfs/zpool.cache-initrd etc/zfs/zpool.cache&lt;br /&gt;
 * # zpool.cache is optional - zpool_import_ kernel params can be used instead&lt;br /&gt;
 * #  see below for details on using zpool_import&lt;br /&gt;
 * mknod dev/console c 5 1   # system console&lt;br /&gt;
 * mknod dev/kmsg    c 1 11  # lines printed to kmsg enter kernel messages buffer&lt;br /&gt;
 * mknod dev/loop0   b 7 0&lt;br /&gt;
 * mknod dev/tty     c 5 0   # current tty&lt;br /&gt;
 * mknod dev/tty0    c 4 0   # current virtual term&lt;br /&gt;
 * mknod dev/tty1    c 4 1   # login virtual term 1 (F1)&lt;br /&gt;
 * mknod dev/ttyS0   c 4 64  # COM1&lt;br /&gt;
 * mknod dev/ttyS1   c 4 65  # COM2&lt;br /&gt;
 * mknod dev/ttyS2   c 4 66  # COM3&lt;br /&gt;
 * mknod dev/ttyS3   c 4 67  $ COM4&lt;br /&gt;
 *&lt;br /&gt;
 * and this program compiled to /boot/initramfs-source/init&lt;br /&gt;
 *&lt;br /&gt;
 * Set kernel config option&lt;br /&gt;
 *  CONFIG_INITRAMFS_SOURCE=/boot/initramfs-source&lt;br /&gt;
 * to build the initramfs into your kernel image&lt;br /&gt;
 *  that also has builtin drivers (spl and zfs, etc).&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
#define FOOBARZ_INIT_VERSION &amp;quot;1.1.1&amp;quot;&lt;br /&gt;
#define _BSD_SOURCE&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdarg.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;fcntl.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/mount.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sysexits.h&amp;gt;&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
/* support for zpool import&lt;br /&gt;
 *&lt;br /&gt;
 * If -DINCLUDE_ZPOOL_IMPORT, then support to import a zpool is&lt;br /&gt;
 * enabled in the program. Enabling it will add many dependencies to the&lt;br /&gt;
 * compile and link; for example:&lt;br /&gt;
 *&lt;br /&gt;
 * gcc -static -DINCLUDE_ZPOOL_IMPORT \&lt;br /&gt;
 *    foobarz-init.c -include /usr/src/zfs-0.6.0-rc10/3.2.28/zfs_config.h \&lt;br /&gt;
 *   -o init \&lt;br /&gt;
 *   -I /usr/include/libspl -I /usr/include/libzfs \&lt;br /&gt;
 *   -lzfs -lnvpair -lzpool -luutil -luuid -lrt -lz -lm -lpthread \&lt;br /&gt;
 *   -I /usr/include/tirpc \&lt;br /&gt;
 *   -ltirpc&lt;br /&gt;
 *&lt;br /&gt;
 * Note that libtirpc is a drop-in replacement for the SunRPC functions that&lt;br /&gt;
 * used to be in glibc. No additional includes are needed, just the gcc -I and -l&lt;br /&gt;
 * options for tirpc.&lt;br /&gt;
 *&lt;br /&gt;
 * Otherwise, with -UINCLUDE_ZPOOL_IMPORT, the compile is just:&lt;br /&gt;
 * gcc -static foobarz-init.c -o init&lt;br /&gt;
 */&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
#include &amp;lt;libzfs.h&amp;gt;&lt;br /&gt;
#else&lt;br /&gt;
#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/stat.h&amp;gt;&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#define PARAM_REQ_NO 0&lt;br /&gt;
#define PARAM_REQ_YES 1&lt;br /&gt;
#define PARAM_SRC_DEFAULT 0&lt;br /&gt;
#define PARAM_SRC_CMDLINE 1&lt;br /&gt;
&lt;br /&gt;
void printk(char *fmt, ...) {&lt;br /&gt;
  FILE* f;&lt;br /&gt;
  int fd;&lt;br /&gt;
  va_list args;&lt;br /&gt;
&lt;br /&gt;
  f = fopen(&amp;quot;/dev/kmsg&amp;quot;, &amp;quot;w&amp;quot;);&lt;br /&gt;
  va_start(args, fmt);&lt;br /&gt;
  vfprintf(f, fmt, args);&lt;br /&gt;
  va_end(args);&lt;br /&gt;
  fflush(f);&lt;br /&gt;
  fclose(f);&lt;br /&gt;
  /* avoid flooding kmsg and having msgs suppressed; 20msgs/sec */&lt;br /&gt;
  usleep(50000);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[]) {&lt;br /&gt;
 /*** variables */&lt;br /&gt;
&lt;br /&gt;
 int i;&lt;br /&gt;
 int   fd = 0; /* file descriptor */&lt;br /&gt;
 unsigned long mountflags;&lt;br /&gt;
&lt;br /&gt;
 /* kernel command line */&lt;br /&gt;
 off_t cmdline_size;&lt;br /&gt;
 char* cmdline; /* to be malloc 4096B */&lt;br /&gt;
 char* cmdline_end;&lt;br /&gt;
 char* temp_end;&lt;br /&gt;
 char* src_msg; /* default or cmdline */&lt;br /&gt;
 int flag_param_missing = 0;&lt;br /&gt;
&lt;br /&gt;
 /* use to hold contents of a misc /proc/&amp;lt;file&amp;gt; */&lt;br /&gt;
 char* miscproc_buff; /* to be malloc 4096B */&lt;br /&gt;
 off_t miscproc_size;&lt;br /&gt;
&lt;br /&gt;
 /* note about environ, argv, and kernel cmdline for init:&lt;br /&gt;
  *   environ is not defined for init&lt;br /&gt;
  *   only argv[0] is set for init&lt;br /&gt;
  *   kernel command line parameters are accessed&lt;br /&gt;
  *   at /proc/cmdline&lt;br /&gt;
  */&lt;br /&gt;
&lt;br /&gt;
 /* kernel parameters expected to be name=value */&lt;br /&gt;
 /* do not use quotes or spaces in parameters   */&lt;br /&gt;
 /* you can add more params somwhere after root= */&lt;br /&gt;
 struct nv { char* n; char* v; char* v_end; int req; int src; };&lt;br /&gt;
 struct nv param[] = {&lt;br /&gt;
   { &amp;quot;root=&amp;quot;,       NULL, NULL, PARAM_REQ_YES, PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;rootfstype=&amp;quot;, NULL, NULL, PARAM_REQ_YES, PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;mountopt=&amp;quot;,   NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;init=&amp;quot;,       NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;runlevel=&amp;quot;,   NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;console=&amp;quot;,    NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT }&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
   ,&lt;br /&gt;
   { &amp;quot;zpool_import_name=&amp;quot;,    NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;zpool_import_guid=&amp;quot;,    NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;zpool_import_newname=&amp;quot;, NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;zpool_import_force=&amp;quot;,   NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT }&lt;br /&gt;
#endif&lt;br /&gt;
 };&lt;br /&gt;
 enum {&lt;br /&gt;
	 iroot,&lt;br /&gt;
	 irootfstype,&lt;br /&gt;
	 imountopt,&lt;br /&gt;
	 iinit,&lt;br /&gt;
	 irunlevel,&lt;br /&gt;
	 iconsole,&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
	 izpool_import_name,&lt;br /&gt;
	 izpool_import_guid,&lt;br /&gt;
	 izpool_import_newname,&lt;br /&gt;
	 izpool_import_force,&lt;br /&gt;
#endif&lt;br /&gt;
	 ilastparam&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
 libzfs_handle_t* libzfs = NULL;&lt;br /&gt;
 importargs_t iargs = { 0 };&lt;br /&gt;
 nvlist_t* pools = NULL;&lt;br /&gt;
 nvpair_t* pool = NULL;&lt;br /&gt;
 nvlist_t* config = NULL;&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
 /*** program */&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;foobarz-init, version %s: booting initramfs.\n&amp;quot;, FOOBARZ_INIT_VERSION);&lt;br /&gt;
&lt;br /&gt;
 cmdline       = (char*) malloc(4096);&lt;br /&gt;
 miscproc_buff = (char*) malloc(4096);&lt;br /&gt;
 if( (cmdline == NULL) || (miscproc_buff == NULL) ) {&lt;br /&gt;
   printk(&amp;quot;Unable to allocate buffer memory: malloc: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount proc /proc&lt;br /&gt;
  *  note: some /dev devices symlink into /proc&lt;br /&gt;
  *  proc contains info about processes, including cmdline etc. */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount proc /proc\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;proc&amp;quot;, &amp;quot;/proc&amp;quot;, &amp;quot;proc&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
   printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
   printk(&amp;quot;Mount proc successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount devtmpfs /dev&lt;br /&gt;
  *  note: This simple init program works if your root device is made from devices&lt;br /&gt;
  *  that are available by default in devtmpfs, such as /dev/sd*&lt;br /&gt;
  *&lt;br /&gt;
  *  For zfs, your root zfs pool should be created with default device nodes and&lt;br /&gt;
  *  then it should be mountable by this simple init program.&lt;br /&gt;
  *&lt;br /&gt;
  *  udev may be needed to configure device nodes and symlinks required&lt;br /&gt;
  *  to access a root device configuration made with such nodes and symlinks.&lt;br /&gt;
  *  If you need udevd, you can include it into your initramfs-source and&lt;br /&gt;
  *  modify this program to run it before attempting to mount your root device.&lt;br /&gt;
  *  However, if udevd is needed, a significant number of userspace programs may also be&lt;br /&gt;
  *  required by rules in /lib/udev/. You could install busybox + udev (about 5MB) or&lt;br /&gt;
  *  coreutils + util-linux + bash + udev (about 25MB) into initramfs-source. But, at that&lt;br /&gt;
  *  point you'd have ash or bash and many tools that are easier to use than this&lt;br /&gt;
  *  simple init program; it would then be easy to have /init as #!/bin/&amp;lt;b&amp;gt;ash script. */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount devtmpfs /dev\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;devtmpfs&amp;quot;, &amp;quot;/dev&amp;quot;, &amp;quot;devtmpfs&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
   printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
   printk(&amp;quot;Mount devtmpfs successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount sysfs /sys&lt;br /&gt;
  *  note: some kernel modules try to access /sys with userspace helpers to echo values into /sys variables;&lt;br /&gt;
  *  such modules expect a minimal userspace that contains coreutils or busybox */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount sysfs /sys\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;sysfs&amp;quot;, &amp;quot;/sys&amp;quot;, &amp;quot;sysfs&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
   printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
   printk(&amp;quot;Mount sysfs successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* process kernel command line */&lt;br /&gt;
 fd = open(&amp;quot;/proc/cmdline&amp;quot;, O_RDONLY);&lt;br /&gt;
 if( fd == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Cannot open /proc/cmdline: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 /* note, on /proc fs:&lt;br /&gt;
  *       lseek likely always returns error&lt;br /&gt;
  *       stat likely always returns st_size = 0&lt;br /&gt;
  *   so determining size of /proc file means just reading it;&lt;br /&gt;
  *   you have to read /proc files according to their documented&lt;br /&gt;
  *   maximum sizes; this is probably for performance reasons */&lt;br /&gt;
 cmdline_size = read(fd, cmdline, 4095);&lt;br /&gt;
 if( cmdline_size == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Failed to read /proc/cmdline: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 close(fd);&lt;br /&gt;
&lt;br /&gt;
 /* cmdline may be newline + null terminated, but make it null + null */&lt;br /&gt;
 cmdline[cmdline_size] = '\0';&lt;br /&gt;
 if( cmdline[cmdline_size-1] == '\n' ) {&lt;br /&gt;
   cmdline[cmdline_size-1] = '\0';&lt;br /&gt;
   cmdline_size--;&lt;br /&gt;
   cmdline_end = cmdline + cmdline_size;&lt;br /&gt;
 }&lt;br /&gt;
 printk(&amp;quot;Kernel cmdline size: %i\n&amp;quot;, cmdline_size);&lt;br /&gt;
 printk(&amp;quot;Kernel cmdline: \&amp;quot;%s\&amp;quot;\n&amp;quot;, cmdline);&lt;br /&gt;
&lt;br /&gt;
 /* find v and v_end of values in cmdline */&lt;br /&gt;
 for( i=iroot; i&amp;lt;ilastparam; i++ ) {&lt;br /&gt;
   param[i].v = strstr(cmdline, param[i].n);&lt;br /&gt;
   if( param[i].v != NULL ) {&lt;br /&gt;
     param[i].src = PARAM_SRC_CMDLINE;&lt;br /&gt;
     while( *(param[i].v) != '=' ) param[i].v++;&lt;br /&gt;
     param[i].v++;&lt;br /&gt;
     temp_end = param[i].v;&lt;br /&gt;
     while( !( (*temp_end == ' ') ||&lt;br /&gt;
               (*temp_end == '\n') ||&lt;br /&gt;
               (temp_end == cmdline_end)&lt;br /&gt;
	     ) ) temp_end++;&lt;br /&gt;
     if( temp_end == param[i].v ) {&lt;br /&gt;
       printk(&amp;quot;Kernel parameter %s: value missing.\n&amp;quot;, param[i].n);&lt;br /&gt;
       param[i].v = NULL;&lt;br /&gt;
     } else param[i].v_end = temp_end;&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 for( i=iroot; i&amp;lt;ilastparam; i++ ) {&lt;br /&gt;
   /* terminate value strings */&lt;br /&gt;
   if( param[i].v_end != NULL ) *(param[i].v_end) = '\0';&lt;br /&gt;
   /* set defaults if no value on cmdline */&lt;br /&gt;
   if( param[i].v == NULL ) {&lt;br /&gt;
     param[i].src = PARAM_SRC_DEFAULT;&lt;br /&gt;
     if( param[i].req == PARAM_REQ_YES ) flag_param_missing = 1;&lt;br /&gt;
     switch(i) {&lt;br /&gt;
       case iroot      : param[i].v = &amp;quot;&amp;lt;missing required param&amp;gt;&amp;quot; ; break;&lt;br /&gt;
       case irootfstype: param[i].v = &amp;quot;&amp;lt;missing required param&amp;gt;&amp;quot; ; break;&lt;br /&gt;
       case imountopt  : param[i].v = &amp;quot;ro&amp;quot;        ; break;&lt;br /&gt;
       case iinit      : param[i].v = &amp;quot;/sbin/init&amp;quot;; break;&lt;br /&gt;
       case irunlevel  : param[i].v = &amp;quot;3&amp;quot;         ; break;&lt;br /&gt;
       case iconsole   : param[i].v = &amp;quot;console&amp;quot;   ; break;&lt;br /&gt;
       default         : param[i].v = NULL;&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
   if(param[i].src == PARAM_SRC_DEFAULT) src_msg = &amp;quot;default&amp;quot;;&lt;br /&gt;
   else src_msg = &amp;quot;cmdline&amp;quot;;&lt;br /&gt;
   printk(&amp;quot;Using %s \&amp;quot;%s\&amp;quot; (source: %s)\n&amp;quot;, param[i].n, param[i].v, src_msg);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 if( flag_param_missing ) {&lt;br /&gt;
   printk(&amp;quot;Aborting boot process: missing required kernel parameter(s).\n&amp;quot;);&lt;br /&gt;
   return EX_USAGE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* generic nv pair kernel cmdline processing finished&lt;br /&gt;
  *  now, examine specific params for defaults and correctness */&lt;br /&gt;
&lt;br /&gt;
 /* param[irootfstype]: can be checked against /proc/filesystems: */&lt;br /&gt;
 fd = open(&amp;quot;/proc/filesystems&amp;quot;, O_RDONLY);&lt;br /&gt;
 if( fd == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Cannot open /proc/filesystems: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 miscproc_size = read(fd, miscproc_buff, 4095);&lt;br /&gt;
 if( miscproc_size == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Failed to read /proc/filesystems: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 close(fd);&lt;br /&gt;
 if( strstr(miscproc_buff, param[irootfstype].v) == NULL ) {&lt;br /&gt;
   printk(&amp;quot;%s \&amp;quot;%s\&amp;quot;: filesystem type not available.\n&amp;quot;, param[irootfstype].n, param[irootfstype].v);&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* zfs-specific */&lt;br /&gt;
 if( strcmp(param[irootfstype].v, &amp;quot;zfs&amp;quot;) == 0 ) {&lt;br /&gt;
   if( access(&amp;quot;/etc/zfs/zpool.cache&amp;quot;, F_OK) == 0 )&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/zfs/zpool.cache is present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
   else&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/zfs/zpool.cache not present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
&lt;br /&gt;
   if( access(&amp;quot;/etc/hostid&amp;quot;, F_OK) == 0 )&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/hostid is present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
   else&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/hostid not present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
   /* zpool import */&lt;br /&gt;
   if( (param[izpool_import_name].v != NULL) || (param[izpool_import_guid].v != NULL) ) {&lt;br /&gt;
	printk(&amp;quot;zpool_import: import requested.\n&amp;quot;);&lt;br /&gt;
	if( (param[izpool_import_name].v != NULL) &amp;amp;&amp;amp; (param[izpool_import_guid].v != NULL) ) {&lt;br /&gt;
		printk(&amp;quot;zpool_import: given both pool name and guid; using guid.\n&amp;quot;);&lt;br /&gt;
		param[izpool_import_name].v = NULL;&lt;br /&gt;
	}&lt;br /&gt;
	if( param[izpool_import_name].v != NULL )&lt;br /&gt;
		printk(&amp;quot;zpool_import: pool name: %s\n&amp;quot;, param[izpool_import_name].v );&lt;br /&gt;
	else&lt;br /&gt;
		printk(&amp;quot;zpool_import: pool guid: %s\n&amp;quot;, param[izpool_import_guid].v );&lt;br /&gt;
&lt;br /&gt;
	iargs.path = NULL;&lt;br /&gt;
	iargs.paths = 0;&lt;br /&gt;
	iargs.poolname = param[izpool_import_name].v;&lt;br /&gt;
	if( param[izpool_import_guid].v != NULL )&lt;br /&gt;
		iargs.guid = strtoull(param[izpool_import_guid].v, NULL, 10);&lt;br /&gt;
	else&lt;br /&gt;
		iargs.guid = 0;&lt;br /&gt;
	iargs.cachefile = NULL;&lt;br /&gt;
	if( (param[izpool_import_force].v != NULL) &amp;amp;&amp;amp; (strcmp(param[izpool_import_force].v, &amp;quot;1&amp;quot;) == 0) ) {&lt;br /&gt;
		iargs.can_be_active = 1;&lt;br /&gt;
		printk(&amp;quot;zpool_import: import forced.\n&amp;quot;);&lt;br /&gt;
	} else {&lt;br /&gt;
		iargs.can_be_active = 0;&lt;br /&gt;
		printk(&amp;quot;zpool_import: import not forced.\n&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
	iargs.unique = 1;&lt;br /&gt;
	iargs.exists = 1;&lt;br /&gt;
&lt;br /&gt;
	printk(&amp;quot;zpool_import: init libzfs.\n&amp;quot;);&lt;br /&gt;
	libzfs = libzfs_init();&lt;br /&gt;
	printk(&amp;quot;zpool_import: searching for pool.\n&amp;quot;);&lt;br /&gt;
	pools = zpool_search_import(libzfs, &amp;amp;iargs);&lt;br /&gt;
	if( (pools == NULL) || nvlist_empty(pools) )&lt;br /&gt;
		printk(&amp;quot;zpool_import: pool not available for import, or already imported by cachefile.\n&amp;quot;);&lt;br /&gt;
	else {&lt;br /&gt;
		printk(&amp;quot;zpool_import: getting pool information.\n&amp;quot;);&lt;br /&gt;
		pool = nvlist_next_nvpair(pools, pool);&lt;br /&gt;
		printk(&amp;quot;zpool_import: getting pool configuration.\n&amp;quot;);&lt;br /&gt;
		nvpair_value_nvlist(pool, &amp;amp;config);&lt;br /&gt;
		printk(&amp;quot;zpool_import: attempting pool import.\n&amp;quot;);&lt;br /&gt;
		if( zpool_import(libzfs, config, param[izpool_import_newname].v, NULL) != 0 ) {&lt;br /&gt;
			printk(&amp;quot;zpool_import: import failed.\n&amp;quot;);&lt;br /&gt;
			printk(&amp;quot;zpool_import: error description: %s\n&amp;quot;, libzfs_error_description(libzfs) );&lt;br /&gt;
			printk(&amp;quot;zpool_import: error action: %s\n&amp;quot;, libzfs_error_action(libzfs) );&lt;br /&gt;
		} else  printk(&amp;quot;zpool_import: import successful.\n&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
	printk(&amp;quot;zpool_import: fini libzfs.\n&amp;quot;);&lt;br /&gt;
	libzfs_fini(libzfs);&lt;br /&gt;
   }&lt;br /&gt;
#endif /* zpool_import */&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 if(      strcmp(param[imountopt].v, &amp;quot;ro&amp;quot;) == 0 ) mountflags = MS_RDONLY;&lt;br /&gt;
 else if( strcmp(param[imountopt].v, &amp;quot;rw&amp;quot;) == 0 ) mountflags = 0;&lt;br /&gt;
 else {&lt;br /&gt;
   printk(&amp;quot;%s \&amp;quot;%s\&amp;quot;: invalid parameter value; defaulting to \&amp;quot;ro\&amp;quot;.\n&amp;quot;, param[imountopt].n, param[imountopt].v);&lt;br /&gt;
   mountflags = MS_RDONLY;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* param[iroot]: nothing to check; if user gives bad root=device then mount fails */&lt;br /&gt;
&lt;br /&gt;
 /* try to mount root=device at /mnt&lt;br /&gt;
  *&lt;br /&gt;
  * note: for zfs, if a copy of /etc/zfs/zpool.cache (when pool is imported) is put in initramfs-source, then&lt;br /&gt;
  * the zfs module can read it and automatically import the pools described in the cache file; the imported&lt;br /&gt;
  * pools can be available to mount here if they were created using standard device names, otherwise&lt;br /&gt;
  * udevd may be required to run before mounting the pool */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount -t %s -o %s %s /mnt.\n&amp;quot;, param[irootfstype].v, param[imountopt].v, param[iroot].v);&lt;br /&gt;
 if( mount(param[iroot].v, &amp;quot;/mnt&amp;quot;, param[irootfstype].v, mountflags, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 printk(&amp;quot;%s mounted successfully.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
&lt;br /&gt;
 /* check to see if the mounted root filesystem has an executable init program */&lt;br /&gt;
 chdir(&amp;quot;/mnt&amp;quot;);&lt;br /&gt;
 if( access(param[iinit].v+1, X_OK) != 0 ) {&lt;br /&gt;
   chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
   printk(&amp;quot;access X_OK: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   printk(&amp;quot;The init program /mnt/%s is not present or not executable.\n&amp;quot;, param[iinit].v+1);&lt;br /&gt;
   printk(&amp;quot;Aborting boot process: no init program.\n&amp;quot;);&lt;br /&gt;
   printk(&amp;quot;Unmounting %s.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
   if( umount(&amp;quot;/mnt&amp;quot;) == -1 ) {&lt;br /&gt;
     printk(&amp;quot;umount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
     printk(&amp;quot;Failed to umount %s.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
   } else printk(&amp;quot;Successfully unmounted %s.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
 printk(&amp;quot;Init program /mnt/%s is present and executable.\n&amp;quot;, param[iinit].v+1);&lt;br /&gt;
&lt;br /&gt;
 /* switch the root / from initramfs to the mounted new root device at /mnt.&lt;br /&gt;
  *&lt;br /&gt;
  * note: after this switch, it is not possible to access the initramfs files anymore,&lt;br /&gt;
  * yet they consume ram memory unless they are deleted here before switching.&lt;br /&gt;
  * Any programs that are run after clearing the initramfs and switching root must exist on the new root.&lt;br /&gt;
  * This program may safely delete itself (/init) since it is already in ram and executing.&lt;br /&gt;
  * If you have installed additional files and programs in initramfs that consume significant ram,&lt;br /&gt;
  * then you need to insert additional code here to delete those files (carefully). */&lt;br /&gt;
&lt;br /&gt;
 /* delete files off of initramfs to free ram memory */&lt;br /&gt;
 printk(&amp;quot;Freeing memory from initramfs...\n&amp;quot;);&lt;br /&gt;
 if( unlink(argv[0]) != 0 ) printk(&amp;quot;unlink %s: %s\n&amp;quot;, argv[0], strerror(errno));&lt;br /&gt;
 else printk(&amp;quot;%s %s&amp;quot;, argv[0], &amp;quot;deleted from initramfs.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 /* switch root */&lt;br /&gt;
 printk(&amp;quot;Beginning switch root procedure.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(1) Attempting cmd: mount --move /dev /mnt/dev \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/dev&amp;quot;, &amp;quot;/mnt/dev&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(2) Attempting cmd: mount --move /proc /mnt/proc \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/proc&amp;quot;, &amp;quot;/mnt/proc&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(3) Attempting cmd: mount --move /sys /mnt/sys \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/sys&amp;quot;, &amp;quot;/mnt/sys&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(4) Attempting cmd: chdir /mnt \n&amp;quot;);&lt;br /&gt;
 if( chdir(&amp;quot;/mnt&amp;quot;) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: chdir: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(5) Attempting cmd: mount --move . / \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;.&amp;quot;, &amp;quot;/&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(6) Attempting cmd: chroot . \n&amp;quot;);&lt;br /&gt;
 if( chroot(&amp;quot;.&amp;quot;) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: chroot: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(7) Attempting cmd: chdir / \n&amp;quot;);&lt;br /&gt;
 if( chdir(&amp;quot;/&amp;quot;) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: chdir: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 printk(&amp;quot;Completed switch root procedure.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 /* check for &amp;quot;console=&amp;quot; kernel parameter and switch&lt;br /&gt;
  *  stdin, stdout, and stderr to named console device&lt;br /&gt;
  */&lt;br /&gt;
 if( param[iconsole].src == PARAM_SRC_CMDLINE ) {&lt;br /&gt;
   printk(&amp;quot;Console redirection to device %s requested.\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
   /* expect only basename of console device (e.g., ttyS0), so chdir /dev */&lt;br /&gt;
   chdir(&amp;quot;/dev&amp;quot;);&lt;br /&gt;
   if( access(param[iconsole].v, F_OK ) == 0 ) {&lt;br /&gt;
     printk(&amp;quot;Opening stdin, stdout, and stderr on %s.\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
     close(0);&lt;br /&gt;
     open(param[iconsole].v, O_RDWR);&lt;br /&gt;
     dup2(0, 1);&lt;br /&gt;
     dup2(0, 2);&lt;br /&gt;
   } else {&lt;br /&gt;
     printk(&amp;quot;access F_OK: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
     printk(&amp;quot;Could not access device: %s!\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
     printk(&amp;quot;Console redirection to device %s aborted!\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
   }&lt;br /&gt;
   chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;Execing: \&amp;quot;%s %s\&amp;quot; to boot mounted root system.\n&amp;quot;, param[iinit].v, param[irunlevel].v);&lt;br /&gt;
&lt;br /&gt;
 /* free resources held to this point */&lt;br /&gt;
 free(cmdline);&lt;br /&gt;
 free(miscproc_buff);&lt;br /&gt;
&lt;br /&gt;
 if( execl(param[iinit].v, param[irunlevel].v, (char *) NULL ) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: execl: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If foobarz-init is updated, you can find the latest version at [https://github.com/foobarz/foobarz-init github].&lt;br /&gt;
&lt;br /&gt;
The foobarz-init program can be compiled two ways as of v1.1.1. First, the simpler compile that does not support zpool_import but does support importing pools using a /etc/zfs/zpool.cache file in the initramfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gcc --static init.c -o init&lt;br /&gt;
strip init&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The second way to compile it adds support for zpool_import so that you do not have to include a &amp;lt;code&amp;gt;/etc/zfs/zpool.cache&amp;lt;/code&amp;gt; file in the initramfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gcc -static -DINCLUDE_ZPOOL_IMPORT \&lt;br /&gt;
     foobarz-init.c -include /usr/src/zfs-0.6.0-rc10/3.2.28/zfs_config.h \&lt;br /&gt;
    -o init \&lt;br /&gt;
    -I /usr/include/libspl -I /usr/include/libzfs \&lt;br /&gt;
    -lzfs -lnvpair -lzpool -luutil -luuid -lrt -lz -lm -lpthread \&lt;br /&gt;
    -I /usr/include/tirpc \&lt;br /&gt;
    -ltirpc&lt;br /&gt;
strip init&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Dependencies required before you can compile this second way:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Install [http://sourceforge.net/projects/libtirpc/ libtirpc]. The glibc package has removed the RPC-related functions from the static libc. The libtirpc is the new replacement as a separate library. You can make your own libtirpc package and install it to resolve these RPC-related functions. Without this, the compile fails because it cannot find many &amp;quot;xdr&amp;quot; functions.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Reinstall the [ftp://slackware.mirrors.tds.net/pub/slackware/slackware64-current/source/a/util-linux/ util-linux] package with static libraries enabled. Edit the &amp;lt;code&amp;gt;util-linux.SlackBuild&amp;lt;/code&amp;gt; and remove the line &amp;lt;code&amp;gt;--disable-static&amp;lt;/code&amp;gt;, then build it and use upgradepkg to install the new package. This resolves linking static to libuuid.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;code&amp;gt;zfs_config.h&amp;lt;/code&amp;gt; can be found in the kernel source when you have installed the builtin spl/zfs configuration; for example at &amp;lt;code&amp;gt;/usr/src/linux-3.2.27b/zfs_config.h&amp;lt;/code&amp;gt;. If you currently have installed the modular spl/zfs configuration, &amp;lt;code&amp;gt;zfs_config.h&amp;lt;/code&amp;gt; is found where the zfs module headers are installed; for example at &amp;lt;code&amp;gt;/usr/src/zfs-0.6.0-rc10/3.2.28/zfs_config.h&amp;lt;/code&amp;gt;. Wherever it is, &amp;lt;code&amp;gt;-include&amp;lt;/code&amp;gt; it as shown in the example gcc line above. zfs_config.h seems misplaced because it would seem that using libzfs shouldn't depend on modules header files.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;You may need to install the spl and zfs packages configured for --enable-linux-builtin=yes before compiling and linking to libzfs to make sure you are using the version of libzfs intended for builtin modules in case a difference between the two configurations exists. Currently, there seems to be no difference in the libzfs for either modular or builtin modules, but later there could be at least a small difference for detection of modules to load or builtin already. You may see a message that the ZFS modules stack load failed, but it can be ignored since the modules are builtin; this is just libzfs trying to load the modules even though they are builtin.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
With these dependencies, you can probably compile static with the zpool_import support. The exact location of &amp;quot;zfs_config.h&amp;quot; may vary depending on your zfs and kernel versions, so adjust accordingly.&lt;br /&gt;
&lt;br /&gt;
Read the foobarz-init source code to see how it uses kernel parameters. The params &amp;lt;code&amp;gt;root&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;rootfstype&amp;lt;/code&amp;gt; are always required to tell init what root pool name to mount and the filesystem type (e.g. zfs).&lt;br /&gt;
&lt;br /&gt;
For the zpool_import support: &amp;lt;code&amp;gt;zpool_import_name=poolname&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;zpool_import_guid=&amp;lt;guid of a pool&amp;gt;&amp;lt;/code&amp;gt; tells what pool to import. You can also import the pool with a new different name by also using &amp;lt;code&amp;gt;zpool_import_newname=newpoolname&amp;lt;/code&amp;gt;. If the import is not working, &amp;lt;code&amp;gt;zpool_import_force=1&amp;lt;/code&amp;gt; can be used to force import even if ZFS thinks the pool may be in use by another system.&lt;br /&gt;
&lt;br /&gt;
However you import the pool, either using zpool.cache or zpool_import support, the kernel param &amp;lt;code&amp;gt;root=&amp;lt;your poolname or newpoolname&amp;gt;&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;rootfstype=zfs&amp;lt;/code&amp;gt; needs to be given also. The zpool_import only imports, it does not say what to mount. What to mount is still told using root= and rootfstype=.&lt;br /&gt;
&lt;br /&gt;
Now copy the compiled static program into the initramfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp init /boot/initramfs-source/init&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Build and install kernel:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make -j8&lt;br /&gt;
make -j8 modules_install&lt;br /&gt;
cp arch/x86/boot/bzImage /boot/vm3.2.27b&lt;br /&gt;
cp System.map /boot/System.map-vm3.2.27b&lt;br /&gt;
# add new lilo menu entry for vm3.2.27b kernel&lt;br /&gt;
vi /etc/lilo.conf&lt;br /&gt;
  image = /boot/vm3.2.27b&lt;br /&gt;
   label = vm3.2.27b&lt;br /&gt;
   addappend = &amp;quot; spl.spl_hostid=0x007f0100 zfs.spa_config_path=/etc/zfs/zpool.cache root=zfs-root rootfstype=zfs&amp;quot;&lt;br /&gt;
lilo&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Congrats! If this works, you can select the &amp;quot;vm3.2.27b&amp;quot; lilo entry to boot. If you are using the zpool_import support in the init program, you need to add at least the &amp;lt;code&amp;gt;zpool_import_name=zfs-root&amp;lt;/code&amp;gt; param to the addappend line in lilo.conf.&lt;br /&gt;
&lt;br /&gt;
Notes on kernel params (lilo append and addappend lines): root= and rootfstype= are used by both foorbarz-init and mkinitrd. The &amp;quot;ro&amp;quot; param is not used by foobarz-init, so instead use: mountopt=ro|rw. See &amp;quot;modinfo spl&amp;quot; and &amp;quot;modinfo zfs&amp;quot; to see all of the options those modules can take on the kernel command line. Notice the &amp;lt;code&amp;gt;spl.spl_hostid=0x007f0100&amp;lt;/code&amp;gt; param that works around the hostid mismatch problem while trying to import a pool; this param and hostname/ip set to use local loopback 127.0.0.1 in etc/hosts etc/HOSTNAME in initramfs will work most of the time, and if not the pool import needs to be forced.&lt;br /&gt;
&lt;br /&gt;
Notes on the spl and zfs packages to install: &amp;lt;i&amp;gt;If&amp;lt;/i&amp;gt; you have errors using zfs and zpool commands on booted system with builtin modules, then upgrade/switch to the 0.6.0rc10_3.2.27b builds, or you can make a custom package with the binaries renamed like zpoolb, zfsb etc for builtin.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
Using qemu's -nographic serial console (/usr/share/qemu/sgabios.bin): If you have a boot problem, you might want to run in qemu's -nographic console mode:&lt;br /&gt;
&lt;br /&gt;
First, edit /etc/inittab, and uncomment the line for local serial ports runlevel &amp;quot;s1&amp;quot; (ttyS0) for serial console login support. This is done in the guest (host does not need this):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Local serial lines:&lt;br /&gt;
s1:12345:respawn:/sbin/agetty -L ttyS0 38400 linux&lt;br /&gt;
#s1:12345:respawn:/sbin/agetty -L ttyS0 9600 vt100&lt;br /&gt;
#s2:12345:respawn:/sbin/agetty -L ttyS1 9600 vt100&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Second, edit /etc/securetty, and uncomment ttyS0 line:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ttyS0&lt;br /&gt;
#ttyS1&lt;br /&gt;
# ...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
You cannot login on ttyS0 without this change even though you get the login prompt!&lt;br /&gt;
&lt;br /&gt;
Then, run qemu such as:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
qemu-kvm &amp;lt;all regular options&amp;gt; -nographic -option-rom sgabios.bin,bootindex=0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Wait for the lilo prompt, it may take several seconds show up in this mode.&lt;br /&gt;
&lt;br /&gt;
In the lilo menu, select your kernel image with builtin spl/zfs, and use kernel params such as:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
boot: vm3.2.27b console=ttyS0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
At the lilo prompt, use kernel parameter: console=ttyS0 (do NOT say /dev/ttS0). Passing runlevel=s1 does not appear to be necessary.&lt;br /&gt;
&lt;br /&gt;
When you are in qemu's serial mode, the interface is a little different than in the normal graphical mode: use keypresses:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ctrl-a h    # for help&lt;br /&gt;
ctrl-a c    # toggle access to (QEMU) console / back to emulation&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If you cannot get a login: prompt, try ctrl-a c, then do (QEMU) sendkey ctrl-alt-delete. This will reboot cleanly back to lilo, then you can do (QEMU) quit.&lt;br /&gt;
&lt;br /&gt;
Once you login to the guest, the terminal size needs adjustment. On your host, in another xterm sized the same as your guest console terminal, get the size of the terminal:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo $LINES&lt;br /&gt;
echo $COLUMNS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Now, back in the guest terminal of same size:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export LINES &amp;lt;lines&amp;gt;&lt;br /&gt;
export COLUMNS &amp;lt;columns&amp;gt;&lt;br /&gt;
stty cols $COLUMNS rows $LINES&lt;br /&gt;
exec bash&lt;br /&gt;
reset&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
So, you set the environment variables and also set them with stty. Then, restart bash (exec, or else it is a child shell process).&lt;br /&gt;
&lt;br /&gt;
BECAREFUL not to start qemu twice on the same ZFS guest! Two simultaneous running qemu on the same ZFS will corrupt the pool and it will NOT recover - you lose your whole installation! Before running qemu, check ps -A, look for an already running qemu process incase it somehow entered into the background!&lt;br /&gt;
&lt;br /&gt;
BECAREFUL when using -nographic ttyS0 that you are not doing commands on the HOST! Only use -nographic to see kernel problems. Use regular console if booting is working normally.&lt;br /&gt;
&lt;br /&gt;
To use the qemu -drive if=scsi option, the linux module sym53c8xx should be loaded in the guest. You may need to use the qemu option:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-option-rom 8xx_64.rom,bootindex=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The file 8xx_64.rom used to be inside qemu, but in new versions it is missing. You can download it:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
wget http://www.lsi.com/downloads/Public/Host%20Bus%20Adapters/Host%20Bus%20Adapters%20Common%20Files/lsi_bios.zip&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Extract the zip and place 8xx_64.rom in /usr/share/qemu/.&lt;br /&gt;
&lt;br /&gt;
Good luck!&lt;/div&gt;</description>
			<pubDate>Wed, 12 Sep 2012 22:50:19 GMT</pubDate>
			<dc:creator>Foobarz</dc:creator>
			<comments>https://www.slackwiki.com/Talk:ZFS_root_(builtin)</comments>
		</item>
		<item>
			<title>ZFS root (builtin)</title>
			<link>https://www.slackwiki.com/index.php?title=ZFS_root_(builtin)&amp;diff=790</link>
			<guid isPermaLink="false">https://www.slackwiki.com/index.php?title=ZFS_root_(builtin)&amp;diff=790</guid>
			<description>&lt;p&gt;Foobarz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Tutorials]]&lt;br /&gt;
The first [http://slackwiki.com/ZFS_root &amp;quot;ZFS root&amp;quot;] wiki explains the details of running ZFS as your root filesystem by using a fully modular generic kernel approach. Now, I can share how it can be done with the SPL and ZFS modules built into the kernel. This procedure is just an example and can use some fine tuning, but here goes:&lt;br /&gt;
&lt;br /&gt;
The steps below are to create a kernel with SPL and ZFS modules builtin. This kernel will be installed as an alternative kernel to boot in lilo, and it will have a separate kernel installation from the fully modular and working system kernel. This will allow testing the builtin kernel while able to boot back onto a working modular ZFS system. We start this procedure assuming you are on a working fully modular ZFS install as in the &amp;quot;ZFS root&amp;quot; wiki.&lt;br /&gt;
&lt;br /&gt;
Use mountpoint=legacy so that zfs will not expect &amp;lt;code&amp;gt;zfs mount&amp;lt;/code&amp;gt;, but instead expect standard &amp;lt;code&amp;gt;mount&amp;lt;/code&amp;gt; for mounting zfs-root:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=legacy zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Edit &amp;lt;code&amp;gt;/etc/rc.d/rc.S&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;rc.6&amp;lt;/code&amp;gt; to use regular &amp;lt;code&amp;gt;mount&amp;lt;/code&amp;gt; commands, remove &amp;lt;code&amp;gt;zfs&amp;lt;/code&amp;gt; commands. Edit &amp;lt;code&amp;gt;rc.6&amp;lt;/code&amp;gt; and remove or comment out &amp;lt;code&amp;gt;zfs export&amp;lt;/code&amp;gt; command. These edits undo changes made in the &amp;quot;ZFS root&amp;quot; wiki, but it shows the two different ways of mounting a zfs filesystem.&lt;br /&gt;
&lt;br /&gt;
You &amp;lt;i&amp;gt;might&amp;lt;/i&amp;gt; think to set &amp;lt;code&amp;gt;bootfs&amp;lt;/code&amp;gt; property like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool set bootfs=zfs-root zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
However, this will result in ZFS placing many restrictions on zfs-root as per how that option is used on Solaris systems:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; zfs-root must be VTOC (SMI) label, not GPT (EFI) label&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; zfs-root can only contain 1 vdev: either a plain disk, or a mirror&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
So, do &amp;lt;b&amp;gt;NOT&amp;lt;/b&amp;gt; set that property! If &amp;lt;code&amp;gt;bootfs&amp;lt;/code&amp;gt; is set, you would find that you cannot add vdevs to your zfs-root. If it is set already, then unset it like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool set bootfs= zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Make a directory to store files to be inside the initramfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkdir /boot/initramfs-source&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This directory will hold some files for the initial rootfs inside the kernel. Your &amp;lt;code&amp;gt;/boot&amp;lt;/code&amp;gt; should be on a small ext4 partition or on a mounted USB stick that you use to boot.&lt;br /&gt;
&lt;br /&gt;
Extract the slackware kernel-source package to obtain a copy of the kernel source, and make an initial kernel config for it:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir src&lt;br /&gt;
cd src&lt;br /&gt;
tar xvzf /mnt/cdrom/slackware64/k/kernel-source-*.txz&lt;br /&gt;
mv usr/src/linux-3.2.27 /usr/src/linux-3.2.27b&lt;br /&gt;
rm -r install&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make menuconfig&lt;br /&gt;
  General setup-&amp;gt;Local version - append to kernel release = b&lt;br /&gt;
  General setup-&amp;gt;Default hostname                         = slackzfs&lt;br /&gt;
  General setup-&amp;gt;Initramfs source files(s)                = /boot/initramfs-source&lt;br /&gt;
  Device Drivers-&amp;gt;SCSI device support-&amp;gt;SCSI low-level drivers-&amp;gt; &amp;lt;*&amp;gt; SYM53C8XX Version 2 SCSI support&lt;br /&gt;
  File systems -&amp;gt; &amp;lt;*&amp;gt; The Extended 4 (ext4) filesystem&lt;br /&gt;
  # build in any hard drive controllers and filesystems that you need for booting&lt;br /&gt;
  # then save the config&lt;br /&gt;
make prepare scripts&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The kernel source has been set to have a &amp;quot;Local version&amp;quot; &amp;lt;code&amp;gt;b&amp;lt;/code&amp;gt;. This will result in modules installed to &amp;lt;code&amp;gt;/lib/modules/3.2.27b&amp;lt;/code&amp;gt; and keeps this kernel's source and modules seperate from slackware's kernel-generic package installation. The &amp;lt;code&amp;gt;make prepare scripts&amp;lt;/code&amp;gt; command readies the kernel source as needed before we can install a copy of spl and zfs modules into the kernel source tree.&lt;br /&gt;
&lt;br /&gt;
Now proceed to configure and copy spl and zfs into the kernel source tree:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd ~/src&lt;br /&gt;
tar xvzf ~/spl-0.6.0-rc10.tar.gz&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-0.6.0-rc10&lt;br /&gt;
./configure \&lt;br /&gt;
    --prefix=/ \&lt;br /&gt;
    --libdir=/lib64 \&lt;br /&gt;
    --includedir=/usr/include \&lt;br /&gt;
    --datarootdir=/usr/share \&lt;br /&gt;
    --enable-linux-builtin=yes \&lt;br /&gt;
    --with-linux=/usr/src/linux-3.2.27b \&lt;br /&gt;
    --with-linux-obj=/usr/src/linux-3.2.27b&lt;br /&gt;
wget https://raw.github.com/zfsonlinux/spl/master/copy-builtin&lt;br /&gt;
chmod +x copy-builtin&lt;br /&gt;
./copy-builtin /usr/src/linux-3.2.27b&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../spl-0.6.0rc10_3.2.27b-x86_64-1root.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
&lt;br /&gt;
tar xvzf ~/zfs-0.6.0-rc10.tar.gz&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-0.6.0-rc10&lt;br /&gt;
./configure \&lt;br /&gt;
    --prefix=/ \&lt;br /&gt;
    --libdir=/lib64 \&lt;br /&gt;
    --includedir=/usr/include \&lt;br /&gt;
    --datarootdir=/usr/share \&lt;br /&gt;
    --enable-linux-builtin=yes \&lt;br /&gt;
    --with-linux=/usr/src/linux-3.2.27b \&lt;br /&gt;
    --with-linux-obj=/usr/src/linux-3.2.27b \&lt;br /&gt;
    --with-spl=/root/src/spl-0.6.0-rc10&lt;br /&gt;
wget https://raw.github.com/zfsonlinux/zfs/master/copy-builtin&lt;br /&gt;
chmod +x copy-builtin&lt;br /&gt;
./copy-builtin /usr/src/linux-3.2.27b&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../zfs-0.6.0rc10_3.2.27b-x86_64-1root.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
At this point, the &amp;lt;code&amp;gt;copy-builtin&amp;lt;/code&amp;gt; scripts have installed the configured spl and zfs modules source into the kernel source. The regular &amp;lt;code&amp;gt;make menuconfig&amp;lt;/code&amp;gt; in the kernel source should now show options for spl and zfs in the kernel config.&lt;br /&gt;
&lt;br /&gt;
As of this writing, the copy-builtin script places the spl and zfs modules into the kernel source in places where the modules may not initialize in the best order, &amp;lt;i&amp;gt;after&amp;lt;/i&amp;gt; all lower-level storage drivers are initialized. If spl and zfs initialize too soon, there is a chance they may not be able to see all of the storage devices. The order of initialization (as seen in dmesg) of modules that are builtin to the kernel is the order that the modules are linked into the kernel during kernel compilation. The order of link depends on where the module source files are located in the kernel source tree. To ensure that spl and zfs will initialize after all hardware drivers, we move them into the &amp;lt;code&amp;gt;drivers&amp;lt;/code&amp;gt; tree and after all other drivers:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
mkdir drivers/zfsonlinux&lt;br /&gt;
mv spl drivers/zfsonlinux&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  # remove references to spl&lt;br /&gt;
vi Makefile&lt;br /&gt;
  # remove references to spl&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/fs&lt;br /&gt;
mv zfs ../drivers/zfsonlinux&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  # remove references to zfs&lt;br /&gt;
vi Makefile&lt;br /&gt;
  # remove references to zfs&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  )# add line at end of menu, before &amp;quot;endmenu&amp;quot;:&lt;br /&gt;
  )source &amp;quot;drivers/zfsonlinux/Kconfig&amp;quot;&lt;br /&gt;
  )endmenu&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers&lt;br /&gt;
vi Makefile&lt;br /&gt;
  )# add line at very end of file:&lt;br /&gt;
  )obj-$(CONFIG_ZFSONLINUX) += zfsonlinux/&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers/zfsonlinux&lt;br /&gt;
cat &amp;gt; Kconfig &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
menuconfig ZFSONLINUX&lt;br /&gt;
	tristate &amp;quot;ZFSonLinux support&amp;quot;&lt;br /&gt;
&lt;br /&gt;
if ZFSONLINUX&lt;br /&gt;
&lt;br /&gt;
source &amp;quot;drivers/zfsonlinux/spl/Kconifg&amp;quot;&lt;br /&gt;
&lt;br /&gt;
source &amp;quot;drivers/zfsonlinux/zfs/Kconifg&amp;quot;&lt;br /&gt;
&lt;br /&gt;
endif&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/zfsonlinux&lt;br /&gt;
cat &amp;gt; Makefile &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
obj-$(CONFIG_SPL) += spl/&lt;br /&gt;
obj-$(CONFIG_ZFS) += zfs/&lt;br /&gt;
EOF&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This completes the move of the spl and zfs modules in the kernel source tree to be under &amp;lt;code&amp;gt;drivers/zfsonlinux&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Now, in kernel configuration, you can build in the modules as follows:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make menuconfig&lt;br /&gt;
   Device Drivers -&amp;gt;&lt;br /&gt;
    &amp;lt;*&amp;gt; ZFSonLinux support -&amp;gt;&lt;br /&gt;
      &amp;lt;*&amp;gt; Solaris Porting Layer (SPL)&lt;br /&gt;
      &amp;lt;*&amp;gt;     ZFS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the kernel config, we set &amp;lt;code&amp;gt;/boot/initramfs-source&amp;lt;/code&amp;gt; as source location of the contents to be linked into kernel's builtin initramfs (rootfs). Now, we create some files that are needed to be in the initramfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /boot/initramfs-source&lt;br /&gt;
&lt;br /&gt;
# make standard directories&lt;br /&gt;
mkdir -p proc dev sys mnt bin sbin etc/zfs&lt;br /&gt;
&lt;br /&gt;
# zfs seems to want mtab present, even if empty&lt;br /&gt;
touch etc/mtab&lt;br /&gt;
&lt;br /&gt;
# if zpool.cache file can be read by zfs at module init, it imports the pools in the cache&lt;br /&gt;
cp /etc/zfs/zpool.cache-initrd etc/zfs/zpool.cache&lt;br /&gt;
&lt;br /&gt;
# make initial console device node; otherwise, there is a problem at startup:&lt;br /&gt;
# &amp;quot;Warning: unable to open an initial console&amp;quot; and you'd have problems with console and tty login&lt;br /&gt;
# making these nodes from within /init is not early enough to avoid problem&lt;br /&gt;
mknod dev/console c 5 1   # system console&lt;br /&gt;
&lt;br /&gt;
# make memory device kmsg to &amp;quot;printk&amp;quot; kernel messages&lt;br /&gt;
# we can write to this file to send out messages&lt;br /&gt;
mknod dev/kmsg    c 1 11  # lines printed to kmsg enter kernel messages buffer&lt;br /&gt;
&lt;br /&gt;
# recommended loop0 device to mount fs images&lt;br /&gt;
mknod dev/loop0   b 7 0&lt;br /&gt;
&lt;br /&gt;
# make initial virtual terminal devices&lt;br /&gt;
mknod dev/tty     c 5 0   # current tty&lt;br /&gt;
mknod dev/tty0    c 4 0   # current virtual term&lt;br /&gt;
mknod dev/tty1    c 4 1   # login virtual term 1 (F1)&lt;br /&gt;
&lt;br /&gt;
# make alternative console=ttyS0 standard 8250/16550 UART serial port devices&lt;br /&gt;
#   useful with kernel parameter console=ttyS0&lt;br /&gt;
#          with qemu -nographic -option-rom sgabios.bin,bootindex=0&lt;br /&gt;
mknod dev/ttyS0   c 4 64  # COM1&lt;br /&gt;
mknod dev/ttyS1   c 4 65  # COM2&lt;br /&gt;
mknod dev/ttyS2   c 4 66  # COM3&lt;br /&gt;
mknod dev/ttyS3   c 4 67  $ COM4&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This should be enough device nodes initially in the initramfs. Once devtmpfs mounts over /dev inside initramfs, a lot more devices are available in it by default.&lt;br /&gt;
&lt;br /&gt;
The initramfs needs an &amp;lt;code&amp;gt;/init&amp;lt;/code&amp;gt; program that will be run automatically by the kernel as process id 1, the first program to run on the system. This program's task is to mount a root filesystem, switch it to be the new root (/), and then exec the init (&amp;lt;code&amp;gt;/sbin/init&amp;lt;/code&amp;gt;) program that is on the new root so that the new root system is booted.&lt;br /&gt;
&lt;br /&gt;
The common way to make /init is using busybox with files like these in /boot/initrd-tree or /boot/initramfs-source:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
bin/busybox&lt;br /&gt;
bin/ash -&amp;gt; busybox&lt;br /&gt;
bin/sh -&amp;gt; busybox&lt;br /&gt;
# run busybox to see what other &amp;quot;applets&amp;quot; can be symlinked to it&lt;br /&gt;
# when busybox is run as a different symlinked applet name, it runs as the applet&lt;br /&gt;
init&lt;br /&gt;
# init can be an ash script, see slackware's /boot/initrd-tree/init for example&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For example, as an ash script, slackware's init does the following:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;parse kernel parameters passed into it and set variables based on them&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;start udevd and trigger rules for block devices to setup initial /dev devices&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;load kernel modules and keyboard map&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;run mdadm, cryptsetup, lvm, zpool/zfs to setup more devices&lt;br /&gt;
     (any udev rules for them should do more /dev setup in the background)&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;mount the root filesystem read-only at /mnt&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;stat /mnt/sbin/init, and if not executable run a rescue shell /bin/sh&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;shutdown udevd so it can be restarted by root system when booted&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;mount --move {proc,sys,run,dev} to under /mnt&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;run: exec switch_root /mnt /sbin/init $RUNLEVEL&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The slackware mkinitrd package is a fully configured BusyBox installation that makes an external initramfs image file, initrd.gz, that is passed to the kernel by the bootloader (lilo). It could be changed to be internal to the kernel by just using initrd-tree as the CONFIG_INITRAMFS_SOURCE in the kernel config and removing initrd in the lilo.conf.&lt;br /&gt;
&lt;br /&gt;
The main purpose of most initramfs/initrd is to load and configure kernel modules and devices needed to mount a root filesystem. Because the spl/zfs modules are builtin, there isn't really a lot that needs to be done by an initramfs. What remains to be done is import the zfs-root pool, mount it, and exec the system /sbin/init. The kernel's &amp;quot;legacy&amp;quot; parameters &amp;lt;code&amp;gt;root=&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;rootfstype=&amp;lt;/code&amp;gt; that are able to directly boot a root disk do not work with ZFS at this time because ZFS pools always need to be imported before it is possible to mount and boot on them. The automatic import that ZFS can do by using a cachefile (/etc/zfs/zpool.cache) stored in initramfs still does not work with the legacy boot parameters because at an eariler stage of the boot process, the kernel ignores a rootfs that does not contain an &amp;lt;code&amp;gt;/init&amp;lt;/code&amp;gt; program, and/or the device type of an imported pool is not the device types recognized by the legacy boot as valid root devices.&lt;br /&gt;
&lt;br /&gt;
You could just continue to use slackware's mkinitrd package as in the &amp;quot;ZFS root&amp;quot; wiki and it works the same whether the modules are builtin or not. But, by building the spl/zfs modules in, aren't we really wanting to get rid of using the mkinitrd/initrd.gz? We'd like to have a kernel with everything in it to boot, and use a simple lilo image entry that has no initrd.&lt;br /&gt;
&lt;br /&gt;
We can do this, and not use the mkinitrd package, but we still need to finish our own initramfs &amp;lt;code&amp;gt;/init&amp;lt;/code&amp;gt; program to import, mount, switch root, and boot. Save the following c program to &amp;quot;foobarz-init.c&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/* software product name: foobarz-init.c&lt;br /&gt;
 * suggested binary name: /init (in initramfs-source, rootfs)&lt;br /&gt;
 * license              : BSD&lt;br /&gt;
 * license text:&lt;br /&gt;
Copyright (c) 2012, foobarz&lt;br /&gt;
All rights reserved.&lt;br /&gt;
&lt;br /&gt;
Redistribution and use in source and binary forms, with or without&lt;br /&gt;
modification, are permitted provided that the following conditions are met:&lt;br /&gt;
    * Redistributions of source code must retain the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer.&lt;br /&gt;
    * Redistributions in binary form must reproduce the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer in the&lt;br /&gt;
      documentation and/or other materials provided with the distribution.&lt;br /&gt;
    * Neither the name of the &amp;lt;organization&amp;gt; nor the&lt;br /&gt;
      names of its contributors may be used to endorse or promote products&lt;br /&gt;
      derived from this software without specific prior written permission.&lt;br /&gt;
&lt;br /&gt;
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &amp;quot;AS IS&amp;quot; AND&lt;br /&gt;
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED&lt;br /&gt;
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE&lt;br /&gt;
DISCLAIMED. IN NO EVENT SHALL &amp;lt;COPYRIGHT HOLDER&amp;gt; BE LIABLE FOR ANY&lt;br /&gt;
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES&lt;br /&gt;
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;&lt;br /&gt;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND&lt;br /&gt;
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT&lt;br /&gt;
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS&lt;br /&gt;
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
/* Your initramfs-source should contain the following&lt;br /&gt;
 *&lt;br /&gt;
 * cd /boot/initramfs-source&lt;br /&gt;
 * mkdir -p proc dev sys mnt bin sbin etc/zfs&lt;br /&gt;
 * touch etc/mtab&lt;br /&gt;
 * cp /etc/zfs/zpool.cache-initrd etc/zfs/zpool.cache&lt;br /&gt;
 * # zpool.cache is optional - zpool_import_ kernel params can be used instead&lt;br /&gt;
 * #  see below for details on using zpool_import&lt;br /&gt;
 * mknod dev/console c 5 1   # system console&lt;br /&gt;
 * mknod dev/kmsg    c 1 11  # lines printed to kmsg enter kernel messages buffer&lt;br /&gt;
 * mknod dev/loop0   b 7 0&lt;br /&gt;
 * mknod dev/tty     c 5 0   # current tty&lt;br /&gt;
 * mknod dev/tty0    c 4 0   # current virtual term&lt;br /&gt;
 * mknod dev/tty1    c 4 1   # login virtual term 1 (F1)&lt;br /&gt;
 * mknod dev/ttyS0   c 4 64  # COM1&lt;br /&gt;
 * mknod dev/ttyS1   c 4 65  # COM2&lt;br /&gt;
 * mknod dev/ttyS2   c 4 66  # COM3&lt;br /&gt;
 * mknod dev/ttyS3   c 4 67  $ COM4&lt;br /&gt;
 *&lt;br /&gt;
 * and this program compiled to /boot/initramfs-source/init&lt;br /&gt;
 *&lt;br /&gt;
 * Set kernel config option&lt;br /&gt;
 *  CONFIG_INITRAMFS_SOURCE=/boot/initramfs-source&lt;br /&gt;
 * to build the initramfs into your kernel image&lt;br /&gt;
 *  that also has builtin drivers (spl and zfs, etc).&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
#define FOOBARZ_INIT_VERSION &amp;quot;1.1.1&amp;quot;&lt;br /&gt;
#define _BSD_SOURCE&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdarg.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;fcntl.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/mount.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sysexits.h&amp;gt;&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
/* support for zpool import&lt;br /&gt;
 *&lt;br /&gt;
 * If -DINCLUDE_ZPOOL_IMPORT, then support to import a zpool is&lt;br /&gt;
 * enabled in the program. Enabling it will add many dependencies to the&lt;br /&gt;
 * compile and link; for example:&lt;br /&gt;
 *&lt;br /&gt;
 * gcc -static -DINCLUDE_ZPOOL_IMPORT \&lt;br /&gt;
 *    foobarz-init.c -include /usr/src/zfs-0.6.0-rc10/3.2.28/zfs_config.h \&lt;br /&gt;
 *   -o init \&lt;br /&gt;
 *   -I /usr/include/libspl -I /usr/include/libzfs \&lt;br /&gt;
 *   -lzfs -lnvpair -lzpool -luutil -luuid -lrt -lz -lm -lpthread \&lt;br /&gt;
 *   -I /usr/include/tirpc \&lt;br /&gt;
 *   -ltirpc&lt;br /&gt;
 *&lt;br /&gt;
 * Note that libtirpc is a drop-in replacement for the SunRPC functions that&lt;br /&gt;
 * used to be in glibc. No additional includes are needed, just the gcc -I and -l&lt;br /&gt;
 * options for tirpc.&lt;br /&gt;
 *&lt;br /&gt;
 * Otherwise, with -UINCLUDE_ZPOOL_IMPORT, the compile is just:&lt;br /&gt;
 * gcc -static foobarz-init.c -o init&lt;br /&gt;
 */&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
#include &amp;lt;libzfs.h&amp;gt;&lt;br /&gt;
#else&lt;br /&gt;
#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/stat.h&amp;gt;&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#define PARAM_REQ_NO 0&lt;br /&gt;
#define PARAM_REQ_YES 1&lt;br /&gt;
#define PARAM_SRC_DEFAULT 0&lt;br /&gt;
#define PARAM_SRC_CMDLINE 1&lt;br /&gt;
&lt;br /&gt;
void printk(char *fmt, ...) {&lt;br /&gt;
  FILE* f;&lt;br /&gt;
  int fd;&lt;br /&gt;
  va_list args;&lt;br /&gt;
&lt;br /&gt;
  f = fopen(&amp;quot;/dev/kmsg&amp;quot;, &amp;quot;w&amp;quot;);&lt;br /&gt;
  va_start(args, fmt);&lt;br /&gt;
  vfprintf(f, fmt, args);&lt;br /&gt;
  va_end(args);&lt;br /&gt;
  fflush(f);&lt;br /&gt;
  fclose(f);&lt;br /&gt;
  /* avoid flooding kmsg and having msgs suppressed; 20msgs/sec */&lt;br /&gt;
  usleep(50000);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[]) {&lt;br /&gt;
 /*** variables */&lt;br /&gt;
&lt;br /&gt;
 int i;&lt;br /&gt;
 int   fd = 0; /* file descriptor */&lt;br /&gt;
 unsigned long mountflags;&lt;br /&gt;
&lt;br /&gt;
 /* kernel command line */&lt;br /&gt;
 off_t cmdline_size;&lt;br /&gt;
 char* cmdline; /* to be malloc 4096B */&lt;br /&gt;
 char* cmdline_end;&lt;br /&gt;
 char* temp_end;&lt;br /&gt;
 char* src_msg; /* default or cmdline */&lt;br /&gt;
 int flag_param_missing = 0;&lt;br /&gt;
&lt;br /&gt;
 /* use to hold contents of a misc /proc/&amp;lt;file&amp;gt; */&lt;br /&gt;
 char* miscproc_buff; /* to be malloc 4096B */&lt;br /&gt;
 off_t miscproc_size;&lt;br /&gt;
&lt;br /&gt;
 /* note about environ, argv, and kernel cmdline for init:&lt;br /&gt;
  *   environ is not defined for init&lt;br /&gt;
  *   only argv[0] is set for init&lt;br /&gt;
  *   kernel command line parameters are accessed&lt;br /&gt;
  *   at /proc/cmdline&lt;br /&gt;
  */&lt;br /&gt;
&lt;br /&gt;
 /* kernel parameters expected to be name=value */&lt;br /&gt;
 /* do not use quotes or spaces in parameters   */&lt;br /&gt;
 /* you can add more params somwhere after root= */&lt;br /&gt;
 struct nv { char* n; char* v; char* v_end; int req; int src; };&lt;br /&gt;
 struct nv param[] = {&lt;br /&gt;
   { &amp;quot;root=&amp;quot;,       NULL, NULL, PARAM_REQ_YES, PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;rootfstype=&amp;quot;, NULL, NULL, PARAM_REQ_YES, PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;mountopt=&amp;quot;,   NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;init=&amp;quot;,       NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;runlevel=&amp;quot;,   NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;console=&amp;quot;,    NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT }&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
   ,&lt;br /&gt;
   { &amp;quot;zpool_import_name=&amp;quot;,    NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;zpool_import_guid=&amp;quot;,    NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;zpool_import_newname=&amp;quot;, NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;zpool_import_force=&amp;quot;,   NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT }&lt;br /&gt;
#endif&lt;br /&gt;
 };&lt;br /&gt;
 enum {&lt;br /&gt;
	 iroot,&lt;br /&gt;
	 irootfstype,&lt;br /&gt;
	 imountopt,&lt;br /&gt;
	 iinit,&lt;br /&gt;
	 irunlevel,&lt;br /&gt;
	 iconsole,&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
	 izpool_import_name,&lt;br /&gt;
	 izpool_import_guid,&lt;br /&gt;
	 izpool_import_newname,&lt;br /&gt;
	 izpool_import_force,&lt;br /&gt;
#endif&lt;br /&gt;
	 ilastparam&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
 libzfs_handle_t* libzfs = NULL;&lt;br /&gt;
 importargs_t iargs = { 0 };&lt;br /&gt;
 nvlist_t* pools = NULL;&lt;br /&gt;
 nvpair_t* pool = NULL;&lt;br /&gt;
 nvlist_t* config = NULL;&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
 /*** program */&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;foobarz-init, version %s: booting initramfs.\n&amp;quot;, FOOBARZ_INIT_VERSION);&lt;br /&gt;
&lt;br /&gt;
 cmdline       = (char*) malloc(4096);&lt;br /&gt;
 miscproc_buff = (char*) malloc(4096);&lt;br /&gt;
 if( (cmdline == NULL) || (miscproc_buff == NULL) ) {&lt;br /&gt;
   printk(&amp;quot;Unable to allocate buffer memory: malloc: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount proc /proc&lt;br /&gt;
  *  note: some /dev devices symlink into /proc&lt;br /&gt;
  *  proc contains info about processes, including cmdline etc. */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount proc /proc\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;proc&amp;quot;, &amp;quot;/proc&amp;quot;, &amp;quot;proc&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
   printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
   printk(&amp;quot;Mount proc successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount devtmpfs /dev&lt;br /&gt;
  *  note: This simple init program works if your root device is made from devices&lt;br /&gt;
  *  that are available by default in devtmpfs, such as /dev/sd*&lt;br /&gt;
  *&lt;br /&gt;
  *  For zfs, your root zfs pool should be created with default device nodes and&lt;br /&gt;
  *  then it should be mountable by this simple init program.&lt;br /&gt;
  *&lt;br /&gt;
  *  udev may be needed to configure device nodes and symlinks required&lt;br /&gt;
  *  to access a root device configuration made with such nodes and symlinks.&lt;br /&gt;
  *  If you need udevd, you can include it into your initramfs-source and&lt;br /&gt;
  *  modify this program to run it before attempting to mount your root device.&lt;br /&gt;
  *  However, if udevd is needed, a significant number of userspace programs may also be&lt;br /&gt;
  *  required by rules in /lib/udev/. You could install busybox + udev (about 5MB) or&lt;br /&gt;
  *  coreutils + util-linux + bash + udev (about 25MB) into initramfs-source. But, at that&lt;br /&gt;
  *  point you'd have ash or bash and many tools that are easier to use than this&lt;br /&gt;
  *  simple init program; it would then be easy to have /init as #!/bin/&amp;lt;b&amp;gt;ash script. */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount devtmpfs /dev\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;devtmpfs&amp;quot;, &amp;quot;/dev&amp;quot;, &amp;quot;devtmpfs&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
   printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
   printk(&amp;quot;Mount devtmpfs successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount sysfs /sys&lt;br /&gt;
  *  note: some kernel modules try to access /sys with userspace helpers to echo values into /sys variables;&lt;br /&gt;
  *  such modules expect a minimal userspace that contains coreutils or busybox */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount sysfs /sys\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;sysfs&amp;quot;, &amp;quot;/sys&amp;quot;, &amp;quot;sysfs&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
   printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
   printk(&amp;quot;Mount sysfs successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* process kernel command line */&lt;br /&gt;
 fd = open(&amp;quot;/proc/cmdline&amp;quot;, O_RDONLY);&lt;br /&gt;
 if( fd == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Cannot open /proc/cmdline: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 /* note, on /proc fs:&lt;br /&gt;
  *       lseek likely always returns error&lt;br /&gt;
  *       stat likely always returns st_size = 0&lt;br /&gt;
  *   so determining size of /proc file means just reading it;&lt;br /&gt;
  *   you have to read /proc files according to their documented&lt;br /&gt;
  *   maximum sizes; this is probably for performance reasons */&lt;br /&gt;
 cmdline_size = read(fd, cmdline, 4095);&lt;br /&gt;
 if( cmdline_size == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Failed to read /proc/cmdline: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 close(fd);&lt;br /&gt;
&lt;br /&gt;
 /* cmdline may be newline + null terminated, but make it null + null */&lt;br /&gt;
 cmdline[cmdline_size] = '\0';&lt;br /&gt;
 if( cmdline[cmdline_size-1] == '\n' ) {&lt;br /&gt;
   cmdline[cmdline_size-1] = '\0';&lt;br /&gt;
   cmdline_size--;&lt;br /&gt;
   cmdline_end = cmdline + cmdline_size;&lt;br /&gt;
 }&lt;br /&gt;
 printk(&amp;quot;Kernel cmdline size: %i\n&amp;quot;, cmdline_size);&lt;br /&gt;
 printk(&amp;quot;Kernel cmdline: \&amp;quot;%s\&amp;quot;\n&amp;quot;, cmdline);&lt;br /&gt;
&lt;br /&gt;
 /* find v and v_end of values in cmdline */&lt;br /&gt;
 for( i=iroot; i&amp;lt;ilastparam; i++ ) {&lt;br /&gt;
   param[i].v = strstr(cmdline, param[i].n);&lt;br /&gt;
   if( param[i].v != NULL ) {&lt;br /&gt;
     param[i].src = PARAM_SRC_CMDLINE;&lt;br /&gt;
     while( *(param[i].v) != '=' ) param[i].v++;&lt;br /&gt;
     param[i].v++;&lt;br /&gt;
     temp_end = param[i].v;&lt;br /&gt;
     while( !( (*temp_end == ' ') ||&lt;br /&gt;
               (*temp_end == '\n') ||&lt;br /&gt;
               (temp_end == cmdline_end)&lt;br /&gt;
	     ) ) temp_end++;&lt;br /&gt;
     if( temp_end == param[i].v ) {&lt;br /&gt;
       printk(&amp;quot;Kernel parameter %s: value missing.\n&amp;quot;, param[i].n);&lt;br /&gt;
       param[i].v = NULL;&lt;br /&gt;
     } else param[i].v_end = temp_end;&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 for( i=iroot; i&amp;lt;ilastparam; i++ ) {&lt;br /&gt;
   /* terminate value strings */&lt;br /&gt;
   if( param[i].v_end != NULL ) *(param[i].v_end) = '\0';&lt;br /&gt;
   /* set defaults if no value on cmdline */&lt;br /&gt;
   if( param[i].v == NULL ) {&lt;br /&gt;
     param[i].src = PARAM_SRC_DEFAULT;&lt;br /&gt;
     if( param[i].req == PARAM_REQ_YES ) flag_param_missing = 1;&lt;br /&gt;
     switch(i) {&lt;br /&gt;
       case iroot      : param[i].v = &amp;quot;&amp;lt;missing required param&amp;gt;&amp;quot; ; break;&lt;br /&gt;
       case irootfstype: param[i].v = &amp;quot;&amp;lt;missing required param&amp;gt;&amp;quot; ; break;&lt;br /&gt;
       case imountopt  : param[i].v = &amp;quot;ro&amp;quot;        ; break;&lt;br /&gt;
       case iinit      : param[i].v = &amp;quot;/sbin/init&amp;quot;; break;&lt;br /&gt;
       case irunlevel  : param[i].v = &amp;quot;3&amp;quot;         ; break;&lt;br /&gt;
       case iconsole   : param[i].v = &amp;quot;console&amp;quot;   ; break;&lt;br /&gt;
       default         : param[i].v = NULL;&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
   if(param[i].src == PARAM_SRC_DEFAULT) src_msg = &amp;quot;default&amp;quot;;&lt;br /&gt;
   else src_msg = &amp;quot;cmdline&amp;quot;;&lt;br /&gt;
   printk(&amp;quot;Using %s \&amp;quot;%s\&amp;quot; (source: %s)\n&amp;quot;, param[i].n, param[i].v, src_msg);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 if( flag_param_missing ) {&lt;br /&gt;
   printk(&amp;quot;Aborting boot process: missing required kernel parameter(s).\n&amp;quot;);&lt;br /&gt;
   return EX_USAGE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* generic nv pair kernel cmdline processing finished&lt;br /&gt;
  *  now, examine specific params for defaults and correctness */&lt;br /&gt;
&lt;br /&gt;
 /* param[irootfstype]: can be checked against /proc/filesystems: */&lt;br /&gt;
 fd = open(&amp;quot;/proc/filesystems&amp;quot;, O_RDONLY);&lt;br /&gt;
 if( fd == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Cannot open /proc/filesystems: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 miscproc_size = read(fd, miscproc_buff, 4095);&lt;br /&gt;
 if( miscproc_size == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Failed to read /proc/filesystems: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 close(fd);&lt;br /&gt;
 if( strstr(miscproc_buff, param[irootfstype].v) == NULL ) {&lt;br /&gt;
   printk(&amp;quot;%s \&amp;quot;%s\&amp;quot;: filesystem type not available.\n&amp;quot;, param[irootfstype].n, param[irootfstype].v);&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* zfs-specific */&lt;br /&gt;
 if( strcmp(param[irootfstype].v, &amp;quot;zfs&amp;quot;) == 0 ) {&lt;br /&gt;
   if( access(&amp;quot;/etc/zfs/zpool.cache&amp;quot;, F_OK) == 0 )&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/zfs/zpool.cache is present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
   else&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/zfs/zpool.cache not present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
&lt;br /&gt;
   if( access(&amp;quot;/etc/hostid&amp;quot;, F_OK) == 0 )&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/hostid is present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
   else&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/hostid not present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
   /* zpool import */&lt;br /&gt;
   if( (param[izpool_import_name].v != NULL) || (param[izpool_import_guid].v != NULL) ) {&lt;br /&gt;
	printk(&amp;quot;zpool_import: import requested.\n&amp;quot;);&lt;br /&gt;
	if( (param[izpool_import_name].v != NULL) &amp;amp;&amp;amp; (param[izpool_import_guid].v != NULL) ) {&lt;br /&gt;
		printk(&amp;quot;zpool_import: given both pool name and guid; using guid.\n&amp;quot;);&lt;br /&gt;
		param[izpool_import_name].v = NULL;&lt;br /&gt;
	}&lt;br /&gt;
	if( param[izpool_import_name].v != NULL )&lt;br /&gt;
		printk(&amp;quot;zpool_import: pool name: %s\n&amp;quot;, param[izpool_import_name].v );&lt;br /&gt;
	else&lt;br /&gt;
		printk(&amp;quot;zpool_import: pool guid: %s\n&amp;quot;, param[izpool_import_guid].v );&lt;br /&gt;
&lt;br /&gt;
	iargs.path = NULL;&lt;br /&gt;
	iargs.paths = 0;&lt;br /&gt;
	iargs.poolname = param[izpool_import_name].v;&lt;br /&gt;
	if( param[izpool_import_guid].v != NULL )&lt;br /&gt;
		iargs.guid = strtoull(param[izpool_import_guid].v, NULL, 10);&lt;br /&gt;
	else&lt;br /&gt;
		iargs.guid = 0;&lt;br /&gt;
	iargs.cachefile = NULL;&lt;br /&gt;
	if( (param[izpool_import_force].v != NULL) &amp;amp;&amp;amp; (strcmp(param[izpool_import_force].v, &amp;quot;1&amp;quot;) == 0) ) {&lt;br /&gt;
		iargs.can_be_active = 1;&lt;br /&gt;
		printk(&amp;quot;zpool_import: import forced.\n&amp;quot;);&lt;br /&gt;
	} else {&lt;br /&gt;
		iargs.can_be_active = 0;&lt;br /&gt;
		printk(&amp;quot;zpool_import: import not forced.\n&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
	iargs.unique = 1;&lt;br /&gt;
	iargs.exists = 1;&lt;br /&gt;
&lt;br /&gt;
	printk(&amp;quot;zpool_import: init libzfs.\n&amp;quot;);&lt;br /&gt;
	libzfs = libzfs_init();&lt;br /&gt;
	printk(&amp;quot;zpool_import: searching for pool.\n&amp;quot;);&lt;br /&gt;
	pools = zpool_search_import(libzfs, &amp;amp;iargs);&lt;br /&gt;
	if( (pools == NULL) || nvlist_empty(pools) )&lt;br /&gt;
		printk(&amp;quot;zpool_import: pool not available for import, or already imported by cachefile.\n&amp;quot;);&lt;br /&gt;
	else {&lt;br /&gt;
		printk(&amp;quot;zpool_import: getting pool information.\n&amp;quot;);&lt;br /&gt;
		pool = nvlist_next_nvpair(pools, pool);&lt;br /&gt;
		printk(&amp;quot;zpool_import: getting pool configuration.\n&amp;quot;);&lt;br /&gt;
		nvpair_value_nvlist(pool, &amp;amp;config);&lt;br /&gt;
		printk(&amp;quot;zpool_import: attempting pool import.\n&amp;quot;);&lt;br /&gt;
		if( zpool_import(libzfs, config, param[izpool_import_newname].v, NULL) != 0 ) {&lt;br /&gt;
			printk(&amp;quot;zpool_import: import failed.\n&amp;quot;);&lt;br /&gt;
			printk(&amp;quot;zpool_import: error description: %s\n&amp;quot;, libzfs_error_description(libzfs) );&lt;br /&gt;
			printk(&amp;quot;zpool_import: error action: %s\n&amp;quot;, libzfs_error_action(libzfs) );&lt;br /&gt;
		} else  printk(&amp;quot;zpool_import: import successful.\n&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
	printk(&amp;quot;zpool_import: fini libzfs.\n&amp;quot;);&lt;br /&gt;
	libzfs_fini(libzfs);&lt;br /&gt;
   }&lt;br /&gt;
#endif /* zpool_import */&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 if(      strcmp(param[imountopt].v, &amp;quot;ro&amp;quot;) == 0 ) mountflags = MS_RDONLY;&lt;br /&gt;
 else if( strcmp(param[imountopt].v, &amp;quot;rw&amp;quot;) == 0 ) mountflags = 0;&lt;br /&gt;
 else {&lt;br /&gt;
   printk(&amp;quot;%s \&amp;quot;%s\&amp;quot;: invalid parameter value; defaulting to \&amp;quot;ro\&amp;quot;.\n&amp;quot;, param[imountopt].n, param[imountopt].v);&lt;br /&gt;
   mountflags = MS_RDONLY;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* param[iroot]: nothing to check; if user gives bad root=device then mount fails */&lt;br /&gt;
&lt;br /&gt;
 /* try to mount root=device at /mnt&lt;br /&gt;
  *&lt;br /&gt;
  * note: for zfs, if a copy of /etc/zfs/zpool.cache (when pool is imported) is put in initramfs-source, then&lt;br /&gt;
  * the zfs module can read it and automatically import the pools described in the cache file; the imported&lt;br /&gt;
  * pools can be available to mount here if they were created using standard device names, otherwise&lt;br /&gt;
  * udevd may be required to run before mounting the pool */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount -t %s -o %s %s /mnt.\n&amp;quot;, param[irootfstype].v, param[imountopt].v, param[iroot].v);&lt;br /&gt;
 if( mount(param[iroot].v, &amp;quot;/mnt&amp;quot;, param[irootfstype].v, mountflags, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 printk(&amp;quot;%s mounted successfully.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
&lt;br /&gt;
 /* check to see if the mounted root filesystem has an executable init program */&lt;br /&gt;
 chdir(&amp;quot;/mnt&amp;quot;);&lt;br /&gt;
 if( access(param[iinit].v+1, X_OK) != 0 ) {&lt;br /&gt;
   chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
   printk(&amp;quot;access X_OK: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   printk(&amp;quot;The init program /mnt/%s is not present or not executable.\n&amp;quot;, param[iinit].v+1);&lt;br /&gt;
   printk(&amp;quot;Aborting boot process: no init program.\n&amp;quot;);&lt;br /&gt;
   printk(&amp;quot;Unmounting %s.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
   if( umount(&amp;quot;/mnt&amp;quot;) == -1 ) {&lt;br /&gt;
     printk(&amp;quot;umount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
     printk(&amp;quot;Failed to umount %s.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
   } else printk(&amp;quot;Successfully unmounted %s.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
 printk(&amp;quot;Init program /mnt/%s is present and executable.\n&amp;quot;, param[iinit].v+1);&lt;br /&gt;
&lt;br /&gt;
 /* switch the root / from initramfs to the mounted new root device at /mnt.&lt;br /&gt;
  *&lt;br /&gt;
  * note: after this switch, it is not possible to access the initramfs files anymore,&lt;br /&gt;
  * yet they consume ram memory unless they are deleted here before switching.&lt;br /&gt;
  * Any programs that are run after clearing the initramfs and switching root must exist on the new root.&lt;br /&gt;
  * This program may safely delete itself (/init) since it is already in ram and executing.&lt;br /&gt;
  * If you have installed additional files and programs in initramfs that consume significant ram,&lt;br /&gt;
  * then you need to insert additional code here to delete those files (carefully). */&lt;br /&gt;
&lt;br /&gt;
 /* delete files off of initramfs to free ram memory */&lt;br /&gt;
 printk(&amp;quot;Freeing memory from initramfs...\n&amp;quot;);&lt;br /&gt;
 if( unlink(argv[0]) != 0 ) printk(&amp;quot;unlink %s: %s\n&amp;quot;, argv[0], strerror(errno));&lt;br /&gt;
 else printk(&amp;quot;%s %s&amp;quot;, argv[0], &amp;quot;deleted from initramfs.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 /* switch root */&lt;br /&gt;
 printk(&amp;quot;Beginning switch root procedure.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(1) Attempting cmd: mount --move /dev /mnt/dev \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/dev&amp;quot;, &amp;quot;/mnt/dev&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(2) Attempting cmd: mount --move /proc /mnt/proc \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/proc&amp;quot;, &amp;quot;/mnt/proc&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(3) Attempting cmd: mount --move /sys /mnt/sys \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/sys&amp;quot;, &amp;quot;/mnt/sys&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(4) Attempting cmd: chdir /mnt \n&amp;quot;);&lt;br /&gt;
 if( chdir(&amp;quot;/mnt&amp;quot;) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: chdir: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(5) Attempting cmd: mount --move . / \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;.&amp;quot;, &amp;quot;/&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(6) Attempting cmd: chroot . \n&amp;quot;);&lt;br /&gt;
 if( chroot(&amp;quot;.&amp;quot;) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: chroot: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(7) Attempting cmd: chdir / \n&amp;quot;);&lt;br /&gt;
 if( chdir(&amp;quot;/&amp;quot;) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: chdir: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 printk(&amp;quot;Completed switch root procedure.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 /* check for &amp;quot;console=&amp;quot; kernel parameter and switch&lt;br /&gt;
  *  stdin, stdout, and stderr to named console device&lt;br /&gt;
  */&lt;br /&gt;
 if( param[iconsole].src == PARAM_SRC_CMDLINE ) {&lt;br /&gt;
   printk(&amp;quot;Console redirection to device %s requested.\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
   /* expect only basename of console device (e.g., ttyS0), so chdir /dev */&lt;br /&gt;
   chdir(&amp;quot;/dev&amp;quot;);&lt;br /&gt;
   if( access(param[iconsole].v, F_OK ) == 0 ) {&lt;br /&gt;
     printk(&amp;quot;Opening stdin, stdout, and stderr on %s.\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
     close(0);&lt;br /&gt;
     open(param[iconsole].v, O_RDWR);&lt;br /&gt;
     dup2(0, 1);&lt;br /&gt;
     dup2(0, 2);&lt;br /&gt;
   } else {&lt;br /&gt;
     printk(&amp;quot;access F_OK: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
     printk(&amp;quot;Could not access device: %s!\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
     printk(&amp;quot;Console redirection to device %s aborted!\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
   }&lt;br /&gt;
   chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;Execing: \&amp;quot;%s %s\&amp;quot; to boot mounted root system.\n&amp;quot;, param[iinit].v, param[irunlevel].v);&lt;br /&gt;
&lt;br /&gt;
 /* free resources held to this point */&lt;br /&gt;
 free(cmdline);&lt;br /&gt;
 free(miscproc_buff);&lt;br /&gt;
&lt;br /&gt;
 if( execl(param[iinit].v, param[irunlevel].v, (char *) NULL ) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: execl: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If foobarz-init is updated, you can find the latest version at [https://github.com/foobarz/foobarz-init github].&lt;br /&gt;
&lt;br /&gt;
The foobarz-init program can be compiled two ways as of v1.1.1. First, the simpler compile that does not support zpool_import but does support importing pools using a /etc/zfs/zpool.cache file in the initramfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gcc --static init.c -o init&lt;br /&gt;
strip init&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The second way to compile it adds support for zpool_import so that you do not have to include a &amp;lt;code&amp;gt;/etc/zfs/zpool.cache&amp;lt;/code&amp;gt; file in the initramfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gcc -static -DINCLUDE_ZPOOL_IMPORT \&lt;br /&gt;
     foobarz-init.c -include /usr/src/zfs-0.6.0-rc10/3.2.28/zfs_config.h \&lt;br /&gt;
    -o init \&lt;br /&gt;
    -I /usr/include/libspl -I /usr/include/libzfs \&lt;br /&gt;
    -lzfs -lnvpair -lzpool -luutil -luuid -lrt -lz -lm -lpthread \&lt;br /&gt;
    -I /usr/include/tirpc \&lt;br /&gt;
    -ltirpc&lt;br /&gt;
strip init&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Dependencies required before you can compile this second way:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Install [http://sourceforge.net/projects/libtirpc/ libtirpc]. The glibc package has removed the RPC-related functions from the static libc. The libtirpc is the new replacement as a separate library. You can make your own libtirpc package and install it to resolve these RPC-related functions. Without this, the compile fails because it cannot find many &amp;quot;xdr&amp;quot; functions.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Reinstall the [ftp://slackware.mirrors.tds.net/pub/slackware/slackware64-current/source/a/util-linux/ util-linux] package with static libraries enabled. Edit the &amp;lt;code&amp;gt;util-linux.SlackBuild&amp;lt;/code&amp;gt; and remove the line &amp;lt;code&amp;gt;--disable-static&amp;lt;/code&amp;gt;, then build it and use upgradepkg to install the new package. This resolves linking static to libuuid.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;You may need to install the spl and zfs packages configured for --enable-linux-builtin=yes before compiling and linking to libzfs to make sure you are using the version of libzfs intended for builtin modules in case a difference between the two configurations exists. Currently, there seems to be no difference in the libzfs for either modular or builtin modules, but later there could be at least a small difference for detection of modules to load or builtin already. You may see a message that the ZFS modules stack load failed, but it can be ignored since the modules are builtin; this is just libzfs trying to load the modules even though they are builtin.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
With these dependencies, you can probably compile static with the zpool_import support. The exact location of &amp;quot;zfs_config.h&amp;quot; may vary depending on your zfs and kernel versions, so adjust accordingly.&lt;br /&gt;
&lt;br /&gt;
Read the foobarz-init source code to see how it uses kernel parameters. The params &amp;lt;code&amp;gt;root&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;rootfstype&amp;lt;/code&amp;gt; are always required to tell init what root pool name to mount and the filesystem type (e.g. zfs).&lt;br /&gt;
&lt;br /&gt;
For the zpool_import support: &amp;lt;code&amp;gt;zpool_import_name=poolname&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;zpool_import_guid=&amp;lt;guid of a pool&amp;gt;&amp;lt;/code&amp;gt; tells what pool to import. You can also import the pool with a new different name by also using &amp;lt;code&amp;gt;zpool_import_newname=newpoolname&amp;lt;/code&amp;gt;. If the import is not working, &amp;lt;code&amp;gt;zpool_import_force=1&amp;lt;/code&amp;gt; can be used to force import even if ZFS thinks the pool may be in use by another system.&lt;br /&gt;
&lt;br /&gt;
However you import the pool, either using zpool.cache or zpool_import support, the kernel param &amp;lt;code&amp;gt;root=&amp;lt;your poolname or newpoolname&amp;gt;&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;rootfstype=zfs&amp;lt;/code&amp;gt; needs to be given also. The zpool_import only imports, it does not say what to mount. What to mount is still told using root= and rootfstype=.&lt;br /&gt;
&lt;br /&gt;
Now copy the compiled static program into the initramfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp init /boot/initramfs-source/init&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Build and install kernel:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make -j8&lt;br /&gt;
make -j8 modules_install&lt;br /&gt;
cp arch/x86/boot/bzImage /boot/vm3.2.27b&lt;br /&gt;
cp System.map /boot/System.map-vm3.2.27b&lt;br /&gt;
# add new lilo menu entry for vm3.2.27b kernel&lt;br /&gt;
vi /etc/lilo.conf&lt;br /&gt;
  image = /boot/vm3.2.27b&lt;br /&gt;
   label = vm3.2.27b&lt;br /&gt;
   addappend = &amp;quot; spl.spl_hostid=0x007f0100 zfs.spa_config_path=/etc/zfs/zpool.cache root=zfs-root rootfstype=zfs&amp;quot;&lt;br /&gt;
lilo&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Congrats! If this works, you can select the &amp;quot;vm3.2.27b&amp;quot; lilo entry to boot. If you are using the zpool_import support in the init program, you need to add at least the &amp;lt;code&amp;gt;zpool_import_name=zfs-root&amp;lt;/code&amp;gt; param to the addappend line in lilo.conf.&lt;br /&gt;
&lt;br /&gt;
Notes on kernel params (lilo append and addappend lines): root= and rootfstype= are used by both foorbarz-init and mkinitrd. The &amp;quot;ro&amp;quot; param is not used by foobarz-init, so instead use: mountopt=ro|rw. See &amp;quot;modinfo spl&amp;quot; and &amp;quot;modinfo zfs&amp;quot; to see all of the options those modules can take on the kernel command line. Notice the &amp;lt;code&amp;gt;spl.spl_hostid=0x007f0100&amp;lt;/code&amp;gt; param that works around the hostid mismatch problem while trying to import a pool; this param and hostname/ip set to use local loopback 127.0.0.1 in etc/hosts etc/HOSTNAME in initramfs will work most of the time, and if not the pool import needs to be forced.&lt;br /&gt;
&lt;br /&gt;
Notes on the spl and zfs packages to install: &amp;lt;i&amp;gt;If&amp;lt;/i&amp;gt; you have errors using zfs and zpool commands on booted system with builtin modules, then upgrade/switch to the 0.6.0rc10_3.2.27b builds, or you can make a custom package with the binaries renamed like zpoolb, zfsb etc for builtin.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
Using qemu's -nographic serial console (/usr/share/qemu/sgabios.bin): If you have a boot problem, you might want to run in qemu's -nographic console mode:&lt;br /&gt;
&lt;br /&gt;
First, edit /etc/inittab, and uncomment the line for local serial ports runlevel &amp;quot;s1&amp;quot; (ttyS0) for serial console login support. This is done in the guest (host does not need this):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Local serial lines:&lt;br /&gt;
s1:12345:respawn:/sbin/agetty -L ttyS0 38400 linux&lt;br /&gt;
#s1:12345:respawn:/sbin/agetty -L ttyS0 9600 vt100&lt;br /&gt;
#s2:12345:respawn:/sbin/agetty -L ttyS1 9600 vt100&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Second, edit /etc/securetty, and uncomment ttyS0 line:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ttyS0&lt;br /&gt;
#ttyS1&lt;br /&gt;
# ...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
You cannot login on ttyS0 without this change even though you get the login prompt!&lt;br /&gt;
&lt;br /&gt;
Then, run qemu such as:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
qemu-kvm &amp;lt;all regular options&amp;gt; -nographic -option-rom sgabios.bin,bootindex=0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Wait for the lilo prompt, it may take several seconds show up in this mode.&lt;br /&gt;
&lt;br /&gt;
In the lilo menu, select your kernel image with builtin spl/zfs, and use kernel params such as:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
boot: vm3.2.27b console=ttyS0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
At the lilo prompt, use kernel parameter: console=ttyS0 (do NOT say /dev/ttS0). Passing runlevel=s1 does not appear to be necessary.&lt;br /&gt;
&lt;br /&gt;
When you are in qemu's serial mode, the interface is a little different than in the normal graphical mode: use keypresses:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ctrl-a h    # for help&lt;br /&gt;
ctrl-a c    # toggle access to (QEMU) console / back to emulation&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If you cannot get a login: prompt, try ctrl-a c, then do (QEMU) sendkey ctrl-alt-delete. This will reboot cleanly back to lilo, then you can do (QEMU) quit.&lt;br /&gt;
&lt;br /&gt;
Once you login to the guest, the terminal size needs adjustment. On your host, in another xterm sized the same as your guest console terminal, get the size of the terminal:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo $LINES&lt;br /&gt;
echo $COLUMNS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Now, back in the guest terminal of same size:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export LINES &amp;lt;lines&amp;gt;&lt;br /&gt;
export COLUMNS &amp;lt;columns&amp;gt;&lt;br /&gt;
stty cols $COLUMNS rows $LINES&lt;br /&gt;
exec bash&lt;br /&gt;
reset&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
So, you set the environment variables and also set them with stty. Then, restart bash (exec, or else it is a child shell process).&lt;br /&gt;
&lt;br /&gt;
BECAREFUL not to start qemu twice on the same ZFS guest! Two simultaneous running qemu on the same ZFS will corrupt the pool and it will NOT recover - you lose your whole installation! Before running qemu, check ps -A, look for an already running qemu process incase it somehow entered into the background!&lt;br /&gt;
&lt;br /&gt;
BECAREFUL when using -nographic ttyS0 that you are not doing commands on the HOST! Only use -nographic to see kernel problems. Use regular console if booting is working normally.&lt;br /&gt;
&lt;br /&gt;
To use the qemu -drive if=scsi option, the linux module sym53c8xx should be loaded in the guest. You may need to use the qemu option:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-option-rom 8xx_64.rom,bootindex=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The file 8xx_64.rom used to be inside qemu, but in new versions it is missing. You can download it:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
wget http://www.lsi.com/downloads/Public/Host%20Bus%20Adapters/Host%20Bus%20Adapters%20Common%20Files/lsi_bios.zip&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Extract the zip and place 8xx_64.rom in /usr/share/qemu/.&lt;br /&gt;
&lt;br /&gt;
Good luck!&lt;/div&gt;</description>
			<pubDate>Wed, 12 Sep 2012 22:31:37 GMT</pubDate>
			<dc:creator>Foobarz</dc:creator>
			<comments>https://www.slackwiki.com/Talk:ZFS_root_(builtin)</comments>
		</item>
		<item>
			<title>ZFS root (builtin)</title>
			<link>https://www.slackwiki.com/index.php?title=ZFS_root_(builtin)&amp;diff=789</link>
			<guid isPermaLink="false">https://www.slackwiki.com/index.php?title=ZFS_root_(builtin)&amp;diff=789</guid>
			<description>&lt;p&gt;Foobarz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Tutorials]]&lt;br /&gt;
The first [http://slackwiki.com/ZFS_root &amp;quot;ZFS root&amp;quot;] wiki explains the details of running ZFS as your root filesystem by using a fully modular generic kernel approach. Now, I can share how it can be done with the SPL and ZFS modules built into the kernel. This procedure is just an example and can use some fine tuning, but here goes:&lt;br /&gt;
&lt;br /&gt;
The steps below are to create a kernel with SPL and ZFS modules builtin. This kernel will be installed as an alternative kernel to boot in lilo, and it will have a separate kernel installation from the fully modular and working system kernel. This will allow testing the builtin kernel while able to boot back onto a working modular ZFS system. We start this procedure assuming you are on a working fully modular ZFS install as in the &amp;quot;ZFS root&amp;quot; wiki.&lt;br /&gt;
&lt;br /&gt;
Use mountpoint=legacy so that zfs will not expect &amp;lt;code&amp;gt;zfs mount&amp;lt;/code&amp;gt;, but instead expect standard &amp;lt;code&amp;gt;mount&amp;lt;/code&amp;gt; for mounting zfs-root:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=legacy zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Edit &amp;lt;code&amp;gt;/etc/rc.d/rc.S&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;rc.6&amp;lt;/code&amp;gt; to use regular &amp;lt;code&amp;gt;mount&amp;lt;/code&amp;gt; commands, remove &amp;lt;code&amp;gt;zfs&amp;lt;/code&amp;gt; commands. Edit &amp;lt;code&amp;gt;rc.6&amp;lt;/code&amp;gt; and remove or comment out &amp;lt;code&amp;gt;zfs export&amp;lt;/code&amp;gt; command. These edits undo changes made in the &amp;quot;ZFS root&amp;quot; wiki, but it shows the two different ways of mounting a zfs filesystem.&lt;br /&gt;
&lt;br /&gt;
You &amp;lt;i&amp;gt;might&amp;lt;/i&amp;gt; think to set &amp;lt;code&amp;gt;bootfs&amp;lt;/code&amp;gt; property like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool set bootfs=zfs-root zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
However, this will result in ZFS placing many restrictions on zfs-root as per how that option is used on Solaris systems:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; zfs-root must be VTOC (SMI) label, not GPT (EFI) label&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; zfs-root can only contain 1 vdev: either a plain disk, or a mirror&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
So, do &amp;lt;b&amp;gt;NOT&amp;lt;/b&amp;gt; set that property! If &amp;lt;code&amp;gt;bootfs&amp;lt;/code&amp;gt; is set, you would find that you cannot add vdevs to your zfs-root. If it is set already, then unset it like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool set bootfs= zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Make a directory to store files to be inside the initramfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkdir /boot/initramfs-source&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This directory will hold some files for the initial rootfs inside the kernel. Your &amp;lt;code&amp;gt;/boot&amp;lt;/code&amp;gt; should be on a small ext4 partition or on a mounted USB stick that you use to boot.&lt;br /&gt;
&lt;br /&gt;
Extract the slackware kernel-source package to obtain a copy of the kernel source, and make an initial kernel config for it:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir src&lt;br /&gt;
cd src&lt;br /&gt;
tar xvzf /mnt/cdrom/slackware64/k/kernel-source-*.txz&lt;br /&gt;
mv usr/src/linux-3.2.27 /usr/src/linux-3.2.27b&lt;br /&gt;
rm -r install&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make menuconfig&lt;br /&gt;
  General setup-&amp;gt;Local version - append to kernel release = b&lt;br /&gt;
  General setup-&amp;gt;Default hostname                         = slackzfs&lt;br /&gt;
  General setup-&amp;gt;Initramfs source files(s)                = /boot/initramfs-source&lt;br /&gt;
  Device Drivers-&amp;gt;SCSI device support-&amp;gt;SCSI low-level drivers-&amp;gt; &amp;lt;*&amp;gt; SYM53C8XX Version 2 SCSI support&lt;br /&gt;
  File systems -&amp;gt; &amp;lt;*&amp;gt; The Extended 4 (ext4) filesystem&lt;br /&gt;
  # build in any hard drive controllers and filesystems that you need for booting&lt;br /&gt;
  # then save the config&lt;br /&gt;
make prepare scripts&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The kernel source has been set to have a &amp;quot;Local version&amp;quot; &amp;lt;code&amp;gt;b&amp;lt;/code&amp;gt;. This will result in modules installed to &amp;lt;code&amp;gt;/lib/modules/3.2.27b&amp;lt;/code&amp;gt; and keeps this kernel's source and modules seperate from slackware's kernel-generic package installation. The &amp;lt;code&amp;gt;make prepare scripts&amp;lt;/code&amp;gt; command readies the kernel source as needed before we can install a copy of spl and zfs modules into the kernel source tree.&lt;br /&gt;
&lt;br /&gt;
Now proceed to configure and copy spl and zfs into the kernel source tree:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd ~/src&lt;br /&gt;
tar xvzf ~/spl-0.6.0-rc10.tar.gz&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-0.6.0-rc10&lt;br /&gt;
./configure \&lt;br /&gt;
    --prefix=/ \&lt;br /&gt;
    --libdir=/lib64 \&lt;br /&gt;
    --includedir=/usr/include \&lt;br /&gt;
    --datarootdir=/usr/share \&lt;br /&gt;
    --enable-linux-builtin=yes \&lt;br /&gt;
    --with-linux=/usr/src/linux-3.2.27b \&lt;br /&gt;
    --with-linux-obj=/usr/src/linux-3.2.27b&lt;br /&gt;
wget https://raw.github.com/zfsonlinux/spl/master/copy-builtin&lt;br /&gt;
chmod +x copy-builtin&lt;br /&gt;
./copy-builtin /usr/src/linux-3.2.27b&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../spl-0.6.0rc10_3.2.27b-x86_64-1root.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
&lt;br /&gt;
tar xvzf ~/zfs-0.6.0-rc10.tar.gz&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-0.6.0-rc10&lt;br /&gt;
./configure \&lt;br /&gt;
    --prefix=/ \&lt;br /&gt;
    --libdir=/lib64 \&lt;br /&gt;
    --includedir=/usr/include \&lt;br /&gt;
    --datarootdir=/usr/share \&lt;br /&gt;
    --enable-linux-builtin=yes \&lt;br /&gt;
    --with-linux=/usr/src/linux-3.2.27b \&lt;br /&gt;
    --with-linux-obj=/usr/src/linux-3.2.27b \&lt;br /&gt;
    --with-spl=/root/src/spl-0.6.0-rc10&lt;br /&gt;
wget https://raw.github.com/zfsonlinux/zfs/master/copy-builtin&lt;br /&gt;
chmod +x copy-builtin&lt;br /&gt;
./copy-builtin /usr/src/linux-3.2.27b&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../zfs-0.6.0rc10_3.2.27b-x86_64-1root.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
At this point, the &amp;lt;code&amp;gt;copy-builtin&amp;lt;/code&amp;gt; scripts have installed the configured spl and zfs modules source into the kernel source. The regular &amp;lt;code&amp;gt;make menuconfig&amp;lt;/code&amp;gt; in the kernel source should now show options for spl and zfs in the kernel config.&lt;br /&gt;
&lt;br /&gt;
As of this writing, the copy-builtin script places the spl and zfs modules into the kernel source in places where the modules may not initialize in the best order, &amp;lt;i&amp;gt;after&amp;lt;/i&amp;gt; all lower-level storage drivers are initialized. If spl and zfs initialize too soon, there is a chance they may not be able to see all of the storage devices. The order of initialization (as seen in dmesg) of modules that are builtin to the kernel is the order that the modules are linked into the kernel during kernel compilation. The order of link depends on where the module source files are located in the kernel source tree. To ensure that spl and zfs will initialize after all hardware drivers, we move them into the &amp;lt;code&amp;gt;drivers&amp;lt;/code&amp;gt; tree and after all other drivers:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
mkdir drivers/zfsonlinux&lt;br /&gt;
mv spl drivers/zfsonlinux&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  # remove references to spl&lt;br /&gt;
vi Makefile&lt;br /&gt;
  # remove references to spl&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/fs&lt;br /&gt;
mv zfs ../drivers/zfsonlinux&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  # remove references to zfs&lt;br /&gt;
vi Makefile&lt;br /&gt;
  # remove references to zfs&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  )# add line at end of menu, before &amp;quot;endmenu&amp;quot;:&lt;br /&gt;
  )source &amp;quot;drivers/zfsonlinux/Kconfig&amp;quot;&lt;br /&gt;
  )endmenu&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers&lt;br /&gt;
vi Makefile&lt;br /&gt;
  )# add line at very end of file:&lt;br /&gt;
  )obj-$(CONFIG_ZFSONLINUX) += zfsonlinux/&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers/zfsonlinux&lt;br /&gt;
cat &amp;gt; Kconfig &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
menuconfig ZFSONLINUX&lt;br /&gt;
	tristate &amp;quot;ZFSonLinux support&amp;quot;&lt;br /&gt;
&lt;br /&gt;
if ZFSONLINUX&lt;br /&gt;
&lt;br /&gt;
source &amp;quot;drivers/zfsonlinux/spl/Kconifg&amp;quot;&lt;br /&gt;
&lt;br /&gt;
source &amp;quot;drivers/zfsonlinux/zfs/Kconifg&amp;quot;&lt;br /&gt;
&lt;br /&gt;
endif&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/zfsonlinux&lt;br /&gt;
cat &amp;gt; Makefile &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
obj-$(CONFIG_SPL) += spl/&lt;br /&gt;
obj-$(CONFIG_ZFS) += zfs/&lt;br /&gt;
EOF&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This completes the move of the spl and zfs modules in the kernel source tree to be under &amp;lt;code&amp;gt;drivers/zfsonlinux&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Now, in kernel configuration, you can build in the modules as follows:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make menuconfig&lt;br /&gt;
   Device Drivers -&amp;gt;&lt;br /&gt;
    &amp;lt;*&amp;gt; ZFSonLinux support -&amp;gt;&lt;br /&gt;
      &amp;lt;*&amp;gt; Solaris Porting Layer (SPL)&lt;br /&gt;
      &amp;lt;*&amp;gt;     ZFS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the kernel config, we set &amp;lt;code&amp;gt;/boot/initramfs-source&amp;lt;/code&amp;gt; as source location of the contents to be linked into kernel's builtin initramfs (rootfs). Now, we create some files that are needed to be in the initramfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /boot/initramfs-source&lt;br /&gt;
&lt;br /&gt;
# make standard directories&lt;br /&gt;
mkdir -p proc dev sys mnt bin sbin etc/zfs&lt;br /&gt;
&lt;br /&gt;
# zfs seems to want mtab present, even if empty&lt;br /&gt;
touch etc/mtab&lt;br /&gt;
&lt;br /&gt;
# if zpool.cache file can be read by zfs at module init, it imports the pools in the cache&lt;br /&gt;
cp /etc/zfs/zpool.cache-initrd etc/zfs/zpool.cache&lt;br /&gt;
&lt;br /&gt;
# make initial console device node; otherwise, there is a problem at startup:&lt;br /&gt;
# &amp;quot;Warning: unable to open an initial console&amp;quot; and you'd have problems with console and tty login&lt;br /&gt;
# making these nodes from within /init is not early enough to avoid problem&lt;br /&gt;
mknod dev/console c 5 1   # system console&lt;br /&gt;
&lt;br /&gt;
# make memory device kmsg to &amp;quot;printk&amp;quot; kernel messages&lt;br /&gt;
# we can write to this file to send out messages&lt;br /&gt;
mknod dev/kmsg    c 1 11  # lines printed to kmsg enter kernel messages buffer&lt;br /&gt;
&lt;br /&gt;
# recommended loop0 device to mount fs images&lt;br /&gt;
mknod dev/loop0   b 7 0&lt;br /&gt;
&lt;br /&gt;
# make initial virtual terminal devices&lt;br /&gt;
mknod dev/tty     c 5 0   # current tty&lt;br /&gt;
mknod dev/tty0    c 4 0   # current virtual term&lt;br /&gt;
mknod dev/tty1    c 4 1   # login virtual term 1 (F1)&lt;br /&gt;
&lt;br /&gt;
# make alternative console=ttyS0 standard 8250/16550 UART serial port devices&lt;br /&gt;
#   useful with kernel parameter console=ttyS0&lt;br /&gt;
#          with qemu -nographic -option-rom sgabios.bin,bootindex=0&lt;br /&gt;
mknod dev/ttyS0   c 4 64  # COM1&lt;br /&gt;
mknod dev/ttyS1   c 4 65  # COM2&lt;br /&gt;
mknod dev/ttyS2   c 4 66  # COM3&lt;br /&gt;
mknod dev/ttyS3   c 4 67  $ COM4&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This should be enough device nodes initially in the initramfs. Once devtmpfs mounts over /dev inside initramfs, a lot more devices are available in it by default.&lt;br /&gt;
&lt;br /&gt;
The initramfs needs an &amp;lt;code&amp;gt;/init&amp;lt;/code&amp;gt; program that will be run automatically by the kernel as process id 1, the first program to run on the system. This program's task is to mount a root filesystem, switch it to be the new root (/), and then exec the init (&amp;lt;code&amp;gt;/sbin/init&amp;lt;/code&amp;gt;) program that is on the new root so that the new root system is booted.&lt;br /&gt;
&lt;br /&gt;
The common way to make /init is using busybox with files like these in /boot/initrd-tree or /boot/initramfs-source:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
bin/busybox&lt;br /&gt;
bin/ash -&amp;gt; busybox&lt;br /&gt;
bin/sh -&amp;gt; busybox&lt;br /&gt;
# run busybox to see what other &amp;quot;applets&amp;quot; can be symlinked to it&lt;br /&gt;
# when busybox is run as a different symlinked applet name, it runs as the applet&lt;br /&gt;
init&lt;br /&gt;
# init can be an ash script, see slackware's /boot/initrd-tree/init for example&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For example, as an ash script, slackware's init does the following:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;parse kernel parameters passed into it and set variables based on them&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;start udevd and trigger rules for block devices to setup initial /dev devices&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;load kernel modules and keyboard map&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;run mdadm, cryptsetup, lvm, zpool/zfs to setup more devices&lt;br /&gt;
     (any udev rules for them should do more /dev setup in the background)&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;mount the root filesystem read-only at /mnt&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;stat /mnt/sbin/init, and if not executable run a rescue shell /bin/sh&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;shutdown udevd so it can be restarted by root system when booted&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;mount --move {proc,sys,run,dev} to under /mnt&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;run: exec switch_root /mnt /sbin/init $RUNLEVEL&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The slackware mkinitrd package is a fully configured BusyBox installation that makes an external initramfs image file, initrd.gz, that is passed to the kernel by the bootloader (lilo). It could be changed to be internal to the kernel by just using initrd-tree as the CONFIG_INITRAMFS_SOURCE in the kernel config and removing initrd in the lilo.conf.&lt;br /&gt;
&lt;br /&gt;
The main purpose of most initramfs/initrd is to load and configure kernel modules and devices needed to mount a root filesystem. Because the spl/zfs modules are builtin, there isn't really a lot that needs to be done by an initramfs. What remains to be done is import the zfs-root pool, mount it, and exec the system /sbin/init. The kernel's &amp;quot;legacy&amp;quot; parameters &amp;lt;code&amp;gt;root=&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;rootfstype=&amp;lt;/code&amp;gt; that are able to directly boot a root disk do not work with ZFS at this time because ZFS pools always need to be imported before it is possible to mount and boot on them. The automatic import that ZFS can do by using a cachefile (/etc/zfs/zpool.cache) stored in initramfs still does not work with the legacy boot parameters because at an eariler stage of the boot process, the kernel ignores a rootfs that does not contain an &amp;lt;code&amp;gt;/init&amp;lt;/code&amp;gt; program, and/or the device type of an imported pool is not the device types recognized by the legacy boot as valid root devices.&lt;br /&gt;
&lt;br /&gt;
You could just continue to use slackware's mkinitrd package as in the &amp;quot;ZFS root&amp;quot; wiki and it works the same whether the modules are builtin or not. But, by building the spl/zfs modules in, aren't we really wanting to get rid of using the mkinitrd/initrd.gz? We'd like to have a kernel with everything in it to boot, and use a simple lilo image entry that has no initrd.&lt;br /&gt;
&lt;br /&gt;
We can do this, and not use the mkinitrd package, but we still need to finish our own initramfs &amp;lt;code&amp;gt;/init&amp;lt;/code&amp;gt; program to import, mount, switch root, and boot. Save the following c program to &amp;quot;foobarz-init.c&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/* software product name: foobarz-init.c&lt;br /&gt;
 * suggested binary name: /init (in initramfs-source, rootfs)&lt;br /&gt;
 * license              : BSD&lt;br /&gt;
 * license text:&lt;br /&gt;
Copyright (c) 2012, foobarz&lt;br /&gt;
All rights reserved.&lt;br /&gt;
&lt;br /&gt;
Redistribution and use in source and binary forms, with or without&lt;br /&gt;
modification, are permitted provided that the following conditions are met:&lt;br /&gt;
    * Redistributions of source code must retain the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer.&lt;br /&gt;
    * Redistributions in binary form must reproduce the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer in the&lt;br /&gt;
      documentation and/or other materials provided with the distribution.&lt;br /&gt;
    * Neither the name of the &amp;lt;organization&amp;gt; nor the&lt;br /&gt;
      names of its contributors may be used to endorse or promote products&lt;br /&gt;
      derived from this software without specific prior written permission.&lt;br /&gt;
&lt;br /&gt;
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &amp;quot;AS IS&amp;quot; AND&lt;br /&gt;
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED&lt;br /&gt;
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE&lt;br /&gt;
DISCLAIMED. IN NO EVENT SHALL &amp;lt;COPYRIGHT HOLDER&amp;gt; BE LIABLE FOR ANY&lt;br /&gt;
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES&lt;br /&gt;
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;&lt;br /&gt;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND&lt;br /&gt;
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT&lt;br /&gt;
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS&lt;br /&gt;
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
/* Your initramfs-source should contain the following&lt;br /&gt;
 *&lt;br /&gt;
 * cd /boot/initramfs-source&lt;br /&gt;
 * mkdir -p proc dev sys mnt bin sbin etc/zfs&lt;br /&gt;
 * touch etc/mtab&lt;br /&gt;
 * cp /etc/zfs/zpool.cache-initrd etc/zfs/zpool.cache&lt;br /&gt;
 * # zpool.cache is optional - zpool_import_ kernel params can be used instead&lt;br /&gt;
 * #  see below for details on using zpool_import&lt;br /&gt;
 * mknod dev/console c 5 1   # system console&lt;br /&gt;
 * mknod dev/kmsg    c 1 11  # lines printed to kmsg enter kernel messages buffer&lt;br /&gt;
 * mknod dev/loop0   b 7 0&lt;br /&gt;
 * mknod dev/tty     c 5 0   # current tty&lt;br /&gt;
 * mknod dev/tty0    c 4 0   # current virtual term&lt;br /&gt;
 * mknod dev/tty1    c 4 1   # login virtual term 1 (F1)&lt;br /&gt;
 * mknod dev/ttyS0   c 4 64  # COM1&lt;br /&gt;
 * mknod dev/ttyS1   c 4 65  # COM2&lt;br /&gt;
 * mknod dev/ttyS2   c 4 66  # COM3&lt;br /&gt;
 * mknod dev/ttyS3   c 4 67  $ COM4&lt;br /&gt;
 *&lt;br /&gt;
 * and this program compiled to /boot/initramfs-source/init&lt;br /&gt;
 *&lt;br /&gt;
 * Set kernel config option&lt;br /&gt;
 *  CONFIG_INITRAMFS_SOURCE=/boot/initramfs-source&lt;br /&gt;
 * to build the initramfs into your kernel image&lt;br /&gt;
 *  that also has builtin drivers (spl and zfs, etc).&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
#define FOOBARZ_INIT_VERSION &amp;quot;1.1.1&amp;quot;&lt;br /&gt;
#define _BSD_SOURCE&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdarg.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;fcntl.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/mount.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sysexits.h&amp;gt;&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
/* support for zpool import&lt;br /&gt;
 *&lt;br /&gt;
 * If -DINCLUDE_ZPOOL_IMPORT, then support to import a zpool is&lt;br /&gt;
 * enabled in the program. Enabling it will add many dependencies to the&lt;br /&gt;
 * compile and link; for example:&lt;br /&gt;
 *&lt;br /&gt;
 * gcc -static -DINCLUDE_ZPOOL_IMPORT \&lt;br /&gt;
 *    foobarz-init.c -include /usr/src/zfs-0.6.0-rc10/3.2.28/zfs_config.h \&lt;br /&gt;
 *   -o init \&lt;br /&gt;
 *   -I /usr/include/libspl -I /usr/include/libzfs \&lt;br /&gt;
 *   -lzfs -lnvpair -lzpool -luutil -luuid -lrt -lz -lm -lpthread \&lt;br /&gt;
 *   -I /usr/include/tirpc \&lt;br /&gt;
 *   -ltirpc&lt;br /&gt;
 *&lt;br /&gt;
 * Note that libtirpc is a drop-in replacement for the SunRPC functions that&lt;br /&gt;
 * used to be in glibc. No additional includes are needed, just the gcc -I and -l&lt;br /&gt;
 * options for tirpc.&lt;br /&gt;
 *&lt;br /&gt;
 * Otherwise, with -UINCLUDE_ZPOOL_IMPORT, the compile is just:&lt;br /&gt;
 * gcc -static foobarz-init.c -o init&lt;br /&gt;
 */&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
#include &amp;lt;libzfs.h&amp;gt;&lt;br /&gt;
#else&lt;br /&gt;
#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/stat.h&amp;gt;&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#define PARAM_REQ_NO 0&lt;br /&gt;
#define PARAM_REQ_YES 1&lt;br /&gt;
#define PARAM_SRC_DEFAULT 0&lt;br /&gt;
#define PARAM_SRC_CMDLINE 1&lt;br /&gt;
&lt;br /&gt;
void printk(char *fmt, ...) {&lt;br /&gt;
  FILE* f;&lt;br /&gt;
  int fd;&lt;br /&gt;
  va_list args;&lt;br /&gt;
&lt;br /&gt;
  f = fopen(&amp;quot;/dev/kmsg&amp;quot;, &amp;quot;w&amp;quot;);&lt;br /&gt;
  va_start(args, fmt);&lt;br /&gt;
  vfprintf(f, fmt, args);&lt;br /&gt;
  va_end(args);&lt;br /&gt;
  fflush(f);&lt;br /&gt;
  fclose(f);&lt;br /&gt;
  /* avoid flooding kmsg and having msgs suppressed; 20msgs/sec */&lt;br /&gt;
  usleep(50000);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[]) {&lt;br /&gt;
 /*** variables */&lt;br /&gt;
&lt;br /&gt;
 int i;&lt;br /&gt;
 int   fd = 0; /* file descriptor */&lt;br /&gt;
 unsigned long mountflags;&lt;br /&gt;
&lt;br /&gt;
 /* kernel command line */&lt;br /&gt;
 off_t cmdline_size;&lt;br /&gt;
 char* cmdline; /* to be malloc 4096B */&lt;br /&gt;
 char* cmdline_end;&lt;br /&gt;
 char* temp_end;&lt;br /&gt;
 char* src_msg; /* default or cmdline */&lt;br /&gt;
 int flag_param_missing = 0;&lt;br /&gt;
&lt;br /&gt;
 /* use to hold contents of a misc /proc/&amp;lt;file&amp;gt; */&lt;br /&gt;
 char* miscproc_buff; /* to be malloc 4096B */&lt;br /&gt;
 off_t miscproc_size;&lt;br /&gt;
&lt;br /&gt;
 /* note about environ, argv, and kernel cmdline for init:&lt;br /&gt;
  *   environ is not defined for init&lt;br /&gt;
  *   only argv[0] is set for init&lt;br /&gt;
  *   kernel command line parameters are accessed&lt;br /&gt;
  *   at /proc/cmdline&lt;br /&gt;
  */&lt;br /&gt;
&lt;br /&gt;
 /* kernel parameters expected to be name=value */&lt;br /&gt;
 /* do not use quotes or spaces in parameters   */&lt;br /&gt;
 /* you can add more params somwhere after root= */&lt;br /&gt;
 struct nv { char* n; char* v; char* v_end; int req; int src; };&lt;br /&gt;
 struct nv param[] = {&lt;br /&gt;
   { &amp;quot;root=&amp;quot;,       NULL, NULL, PARAM_REQ_YES, PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;rootfstype=&amp;quot;, NULL, NULL, PARAM_REQ_YES, PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;mountopt=&amp;quot;,   NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;init=&amp;quot;,       NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;runlevel=&amp;quot;,   NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;console=&amp;quot;,    NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT }&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
   ,&lt;br /&gt;
   { &amp;quot;zpool_import_name=&amp;quot;,    NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;zpool_import_guid=&amp;quot;,    NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;zpool_import_newname=&amp;quot;, NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;zpool_import_force=&amp;quot;,   NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT }&lt;br /&gt;
#endif&lt;br /&gt;
 };&lt;br /&gt;
 enum {&lt;br /&gt;
	 iroot,&lt;br /&gt;
	 irootfstype,&lt;br /&gt;
	 imountopt,&lt;br /&gt;
	 iinit,&lt;br /&gt;
	 irunlevel,&lt;br /&gt;
	 iconsole,&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
	 izpool_import_name,&lt;br /&gt;
	 izpool_import_guid,&lt;br /&gt;
	 izpool_import_newname,&lt;br /&gt;
	 izpool_import_force,&lt;br /&gt;
#endif&lt;br /&gt;
	 ilastparam&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
 libzfs_handle_t* libzfs = NULL;&lt;br /&gt;
 importargs_t iargs = { 0 };&lt;br /&gt;
 nvlist_t* pools = NULL;&lt;br /&gt;
 nvpair_t* pool = NULL;&lt;br /&gt;
 nvlist_t* config = NULL;&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
 /*** program */&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;foobarz-init, version %s: booting initramfs.\n&amp;quot;, FOOBARZ_INIT_VERSION);&lt;br /&gt;
&lt;br /&gt;
 cmdline       = (char*) malloc(4096);&lt;br /&gt;
 miscproc_buff = (char*) malloc(4096);&lt;br /&gt;
 if( (cmdline == NULL) || (miscproc_buff == NULL) ) {&lt;br /&gt;
   printk(&amp;quot;Unable to allocate buffer memory: malloc: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount proc /proc&lt;br /&gt;
  *  note: some /dev devices symlink into /proc&lt;br /&gt;
  *  proc contains info about processes, including cmdline etc. */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount proc /proc\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;proc&amp;quot;, &amp;quot;/proc&amp;quot;, &amp;quot;proc&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
   printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
   printk(&amp;quot;Mount proc successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount devtmpfs /dev&lt;br /&gt;
  *  note: This simple init program works if your root device is made from devices&lt;br /&gt;
  *  that are available by default in devtmpfs, such as /dev/sd*&lt;br /&gt;
  *&lt;br /&gt;
  *  For zfs, your root zfs pool should be created with default device nodes and&lt;br /&gt;
  *  then it should be mountable by this simple init program.&lt;br /&gt;
  *&lt;br /&gt;
  *  udev may be needed to configure device nodes and symlinks required&lt;br /&gt;
  *  to access a root device configuration made with such nodes and symlinks.&lt;br /&gt;
  *  If you need udevd, you can include it into your initramfs-source and&lt;br /&gt;
  *  modify this program to run it before attempting to mount your root device.&lt;br /&gt;
  *  However, if udevd is needed, a significant number of userspace programs may also be&lt;br /&gt;
  *  required by rules in /lib/udev/. You could install busybox + udev (about 5MB) or&lt;br /&gt;
  *  coreutils + util-linux + bash + udev (about 25MB) into initramfs-source. But, at that&lt;br /&gt;
  *  point you'd have ash or bash and many tools that are easier to use than this&lt;br /&gt;
  *  simple init program; it would then be easy to have /init as #!/bin/&amp;lt;b&amp;gt;ash script. */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount devtmpfs /dev\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;devtmpfs&amp;quot;, &amp;quot;/dev&amp;quot;, &amp;quot;devtmpfs&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
   printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
   printk(&amp;quot;Mount devtmpfs successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount sysfs /sys&lt;br /&gt;
  *  note: some kernel modules try to access /sys with userspace helpers to echo values into /sys variables;&lt;br /&gt;
  *  such modules expect a minimal userspace that contains coreutils or busybox */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount sysfs /sys\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;sysfs&amp;quot;, &amp;quot;/sys&amp;quot;, &amp;quot;sysfs&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
   printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
   printk(&amp;quot;Mount sysfs successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* process kernel command line */&lt;br /&gt;
 fd = open(&amp;quot;/proc/cmdline&amp;quot;, O_RDONLY);&lt;br /&gt;
 if( fd == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Cannot open /proc/cmdline: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 /* note, on /proc fs:&lt;br /&gt;
  *       lseek likely always returns error&lt;br /&gt;
  *       stat likely always returns st_size = 0&lt;br /&gt;
  *   so determining size of /proc file means just reading it;&lt;br /&gt;
  *   you have to read /proc files according to their documented&lt;br /&gt;
  *   maximum sizes; this is probably for performance reasons */&lt;br /&gt;
 cmdline_size = read(fd, cmdline, 4095);&lt;br /&gt;
 if( cmdline_size == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Failed to read /proc/cmdline: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 close(fd);&lt;br /&gt;
&lt;br /&gt;
 /* cmdline may be newline + null terminated, but make it null + null */&lt;br /&gt;
 cmdline[cmdline_size] = '\0';&lt;br /&gt;
 if( cmdline[cmdline_size-1] == '\n' ) {&lt;br /&gt;
   cmdline[cmdline_size-1] = '\0';&lt;br /&gt;
   cmdline_size--;&lt;br /&gt;
   cmdline_end = cmdline + cmdline_size;&lt;br /&gt;
 }&lt;br /&gt;
 printk(&amp;quot;Kernel cmdline size: %i\n&amp;quot;, cmdline_size);&lt;br /&gt;
 printk(&amp;quot;Kernel cmdline: \&amp;quot;%s\&amp;quot;\n&amp;quot;, cmdline);&lt;br /&gt;
&lt;br /&gt;
 /* find v and v_end of values in cmdline */&lt;br /&gt;
 for( i=iroot; i&amp;lt;ilastparam; i++ ) {&lt;br /&gt;
   param[i].v = strstr(cmdline, param[i].n);&lt;br /&gt;
   if( param[i].v != NULL ) {&lt;br /&gt;
     param[i].src = PARAM_SRC_CMDLINE;&lt;br /&gt;
     while( *(param[i].v) != '=' ) param[i].v++;&lt;br /&gt;
     param[i].v++;&lt;br /&gt;
     temp_end = param[i].v;&lt;br /&gt;
     while( !( (*temp_end == ' ') ||&lt;br /&gt;
               (*temp_end == '\n') ||&lt;br /&gt;
               (temp_end == cmdline_end)&lt;br /&gt;
	     ) ) temp_end++;&lt;br /&gt;
     if( temp_end == param[i].v ) {&lt;br /&gt;
       printk(&amp;quot;Kernel parameter %s: value missing.\n&amp;quot;, param[i].n);&lt;br /&gt;
       param[i].v = NULL;&lt;br /&gt;
     } else param[i].v_end = temp_end;&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 for( i=iroot; i&amp;lt;ilastparam; i++ ) {&lt;br /&gt;
   /* terminate value strings */&lt;br /&gt;
   if( param[i].v_end != NULL ) *(param[i].v_end) = '\0';&lt;br /&gt;
   /* set defaults if no value on cmdline */&lt;br /&gt;
   if( param[i].v == NULL ) {&lt;br /&gt;
     param[i].src = PARAM_SRC_DEFAULT;&lt;br /&gt;
     if( param[i].req == PARAM_REQ_YES ) flag_param_missing = 1;&lt;br /&gt;
     switch(i) {&lt;br /&gt;
       case iroot      : param[i].v = &amp;quot;&amp;lt;missing required param&amp;gt;&amp;quot; ; break;&lt;br /&gt;
       case irootfstype: param[i].v = &amp;quot;&amp;lt;missing required param&amp;gt;&amp;quot; ; break;&lt;br /&gt;
       case imountopt  : param[i].v = &amp;quot;ro&amp;quot;        ; break;&lt;br /&gt;
       case iinit      : param[i].v = &amp;quot;/sbin/init&amp;quot;; break;&lt;br /&gt;
       case irunlevel  : param[i].v = &amp;quot;3&amp;quot;         ; break;&lt;br /&gt;
       case iconsole   : param[i].v = &amp;quot;console&amp;quot;   ; break;&lt;br /&gt;
       default         : param[i].v = NULL;&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
   if(param[i].src == PARAM_SRC_DEFAULT) src_msg = &amp;quot;default&amp;quot;;&lt;br /&gt;
   else src_msg = &amp;quot;cmdline&amp;quot;;&lt;br /&gt;
   printk(&amp;quot;Using %s \&amp;quot;%s\&amp;quot; (source: %s)\n&amp;quot;, param[i].n, param[i].v, src_msg);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 if( flag_param_missing ) {&lt;br /&gt;
   printk(&amp;quot;Aborting boot process: missing required kernel parameter(s).\n&amp;quot;);&lt;br /&gt;
   return EX_USAGE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* generic nv pair kernel cmdline processing finished&lt;br /&gt;
  *  now, examine specific params for defaults and correctness */&lt;br /&gt;
&lt;br /&gt;
 /* param[irootfstype]: can be checked against /proc/filesystems: */&lt;br /&gt;
 fd = open(&amp;quot;/proc/filesystems&amp;quot;, O_RDONLY);&lt;br /&gt;
 if( fd == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Cannot open /proc/filesystems: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 miscproc_size = read(fd, miscproc_buff, 4095);&lt;br /&gt;
 if( miscproc_size == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Failed to read /proc/filesystems: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 close(fd);&lt;br /&gt;
 if( strstr(miscproc_buff, param[irootfstype].v) == NULL ) {&lt;br /&gt;
   printk(&amp;quot;%s \&amp;quot;%s\&amp;quot;: filesystem type not available.\n&amp;quot;, param[irootfstype].n, param[irootfstype].v);&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* zfs-specific */&lt;br /&gt;
 if( strcmp(param[irootfstype].v, &amp;quot;zfs&amp;quot;) == 0 ) {&lt;br /&gt;
   if( access(&amp;quot;/etc/zfs/zpool.cache&amp;quot;, F_OK) == 0 )&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/zfs/zpool.cache is present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
   else&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/zfs/zpool.cache not present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
&lt;br /&gt;
   if( access(&amp;quot;/etc/hostid&amp;quot;, F_OK) == 0 )&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/hostid is present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
   else&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/hostid not present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
   /* zpool import */&lt;br /&gt;
   if( (param[izpool_import_name].v != NULL) || (param[izpool_import_guid].v != NULL) ) {&lt;br /&gt;
	printk(&amp;quot;zpool_import: import requested.\n&amp;quot;);&lt;br /&gt;
	if( (param[izpool_import_name].v != NULL) &amp;amp;&amp;amp; (param[izpool_import_guid].v != NULL) ) {&lt;br /&gt;
		printk(&amp;quot;zpool_import: given both pool name and guid; using guid.\n&amp;quot;);&lt;br /&gt;
		param[izpool_import_name].v = NULL;&lt;br /&gt;
	}&lt;br /&gt;
	if( param[izpool_import_name].v != NULL )&lt;br /&gt;
		printk(&amp;quot;zpool_import: pool name: %s\n&amp;quot;, param[izpool_import_name].v );&lt;br /&gt;
	else&lt;br /&gt;
		printk(&amp;quot;zpool_import: pool guid: %s\n&amp;quot;, param[izpool_import_guid].v );&lt;br /&gt;
&lt;br /&gt;
	iargs.path = NULL;&lt;br /&gt;
	iargs.paths = 0;&lt;br /&gt;
	iargs.poolname = param[izpool_import_name].v;&lt;br /&gt;
	if( param[izpool_import_guid].v != NULL )&lt;br /&gt;
		iargs.guid = strtoull(param[izpool_import_guid].v, NULL, 10);&lt;br /&gt;
	else&lt;br /&gt;
		iargs.guid = 0;&lt;br /&gt;
	iargs.cachefile = NULL;&lt;br /&gt;
	if( (param[izpool_import_force].v != NULL) &amp;amp;&amp;amp; (strcmp(param[izpool_import_force].v, &amp;quot;1&amp;quot;) == 0) ) {&lt;br /&gt;
		iargs.can_be_active = 1;&lt;br /&gt;
		printk(&amp;quot;zpool_import: import forced.\n&amp;quot;);&lt;br /&gt;
	} else {&lt;br /&gt;
		iargs.can_be_active = 0;&lt;br /&gt;
		printk(&amp;quot;zpool_import: import not forced.\n&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
	iargs.unique = 1;&lt;br /&gt;
	iargs.exists = 1;&lt;br /&gt;
&lt;br /&gt;
	printk(&amp;quot;zpool_import: init libzfs.\n&amp;quot;);&lt;br /&gt;
	libzfs = libzfs_init();&lt;br /&gt;
	printk(&amp;quot;zpool_import: searching for pool.\n&amp;quot;);&lt;br /&gt;
	pools = zpool_search_import(libzfs, &amp;amp;iargs);&lt;br /&gt;
	if( (pools == NULL) || nvlist_empty(pools) )&lt;br /&gt;
		printk(&amp;quot;zpool_import: pool not available for import, or already imported by cachefile.\n&amp;quot;);&lt;br /&gt;
	else {&lt;br /&gt;
		printk(&amp;quot;zpool_import: getting pool information.\n&amp;quot;);&lt;br /&gt;
		pool = nvlist_next_nvpair(pools, pool);&lt;br /&gt;
		printk(&amp;quot;zpool_import: getting pool configuration.\n&amp;quot;);&lt;br /&gt;
		nvpair_value_nvlist(pool, &amp;amp;config);&lt;br /&gt;
		printk(&amp;quot;zpool_import: attempting pool import.\n&amp;quot;);&lt;br /&gt;
		if( zpool_import(libzfs, config, param[izpool_import_newname].v, NULL) != 0 ) {&lt;br /&gt;
			printk(&amp;quot;zpool_import: import failed.\n&amp;quot;);&lt;br /&gt;
			printk(&amp;quot;zpool_import: error description: %s\n&amp;quot;, libzfs_error_description(libzfs) );&lt;br /&gt;
			printk(&amp;quot;zpool_import: error action: %s\n&amp;quot;, libzfs_error_action(libzfs) );&lt;br /&gt;
		} else  printk(&amp;quot;zpool_import: import successful.\n&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
	printk(&amp;quot;zpool_import: fini libzfs.\n&amp;quot;);&lt;br /&gt;
	libzfs_fini(libzfs);&lt;br /&gt;
   }&lt;br /&gt;
#endif /* zpool_import */&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 if(      strcmp(param[imountopt].v, &amp;quot;ro&amp;quot;) == 0 ) mountflags = MS_RDONLY;&lt;br /&gt;
 else if( strcmp(param[imountopt].v, &amp;quot;rw&amp;quot;) == 0 ) mountflags = 0;&lt;br /&gt;
 else {&lt;br /&gt;
   printk(&amp;quot;%s \&amp;quot;%s\&amp;quot;: invalid parameter value; defaulting to \&amp;quot;ro\&amp;quot;.\n&amp;quot;, param[imountopt].n, param[imountopt].v);&lt;br /&gt;
   mountflags = MS_RDONLY;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* param[iroot]: nothing to check; if user gives bad root=device then mount fails */&lt;br /&gt;
&lt;br /&gt;
 /* try to mount root=device at /mnt&lt;br /&gt;
  *&lt;br /&gt;
  * note: for zfs, if a copy of /etc/zfs/zpool.cache (when pool is imported) is put in initramfs-source, then&lt;br /&gt;
  * the zfs module can read it and automatically import the pools described in the cache file; the imported&lt;br /&gt;
  * pools can be available to mount here if they were created using standard device names, otherwise&lt;br /&gt;
  * udevd may be required to run before mounting the pool */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount -t %s -o %s %s /mnt.\n&amp;quot;, param[irootfstype].v, param[imountopt].v, param[iroot].v);&lt;br /&gt;
 if( mount(param[iroot].v, &amp;quot;/mnt&amp;quot;, param[irootfstype].v, mountflags, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 printk(&amp;quot;%s mounted successfully.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
&lt;br /&gt;
 /* check to see if the mounted root filesystem has an executable init program */&lt;br /&gt;
 chdir(&amp;quot;/mnt&amp;quot;);&lt;br /&gt;
 if( access(param[iinit].v+1, X_OK) != 0 ) {&lt;br /&gt;
   chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
   printk(&amp;quot;access X_OK: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   printk(&amp;quot;The init program /mnt/%s is not present or not executable.\n&amp;quot;, param[iinit].v+1);&lt;br /&gt;
   printk(&amp;quot;Aborting boot process: no init program.\n&amp;quot;);&lt;br /&gt;
   printk(&amp;quot;Unmounting %s.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
   if( umount(&amp;quot;/mnt&amp;quot;) == -1 ) {&lt;br /&gt;
     printk(&amp;quot;umount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
     printk(&amp;quot;Failed to umount %s.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
   } else printk(&amp;quot;Successfully unmounted %s.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
 printk(&amp;quot;Init program /mnt/%s is present and executable.\n&amp;quot;, param[iinit].v+1);&lt;br /&gt;
&lt;br /&gt;
 /* switch the root / from initramfs to the mounted new root device at /mnt.&lt;br /&gt;
  *&lt;br /&gt;
  * note: after this switch, it is not possible to access the initramfs files anymore,&lt;br /&gt;
  * yet they consume ram memory unless they are deleted here before switching.&lt;br /&gt;
  * Any programs that are run after clearing the initramfs and switching root must exist on the new root.&lt;br /&gt;
  * This program may safely delete itself (/init) since it is already in ram and executing.&lt;br /&gt;
  * If you have installed additional files and programs in initramfs that consume significant ram,&lt;br /&gt;
  * then you need to insert additional code here to delete those files (carefully). */&lt;br /&gt;
&lt;br /&gt;
 /* delete files off of initramfs to free ram memory */&lt;br /&gt;
 printk(&amp;quot;Freeing memory from initramfs...\n&amp;quot;);&lt;br /&gt;
 if( unlink(argv[0]) != 0 ) printk(&amp;quot;unlink %s: %s\n&amp;quot;, argv[0], strerror(errno));&lt;br /&gt;
 else printk(&amp;quot;%s %s&amp;quot;, argv[0], &amp;quot;deleted from initramfs.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 /* switch root */&lt;br /&gt;
 printk(&amp;quot;Beginning switch root procedure.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(1) Attempting cmd: mount --move /dev /mnt/dev \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/dev&amp;quot;, &amp;quot;/mnt/dev&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(2) Attempting cmd: mount --move /proc /mnt/proc \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/proc&amp;quot;, &amp;quot;/mnt/proc&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(3) Attempting cmd: mount --move /sys /mnt/sys \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/sys&amp;quot;, &amp;quot;/mnt/sys&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(4) Attempting cmd: chdir /mnt \n&amp;quot;);&lt;br /&gt;
 if( chdir(&amp;quot;/mnt&amp;quot;) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: chdir: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(5) Attempting cmd: mount --move . / \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;.&amp;quot;, &amp;quot;/&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(6) Attempting cmd: chroot . \n&amp;quot;);&lt;br /&gt;
 if( chroot(&amp;quot;.&amp;quot;) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: chroot: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(7) Attempting cmd: chdir / \n&amp;quot;);&lt;br /&gt;
 if( chdir(&amp;quot;/&amp;quot;) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: chdir: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 printk(&amp;quot;Completed switch root procedure.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 /* check for &amp;quot;console=&amp;quot; kernel parameter and switch&lt;br /&gt;
  *  stdin, stdout, and stderr to named console device&lt;br /&gt;
  */&lt;br /&gt;
 if( param[iconsole].src == PARAM_SRC_CMDLINE ) {&lt;br /&gt;
   printk(&amp;quot;Console redirection to device %s requested.\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
   /* expect only basename of console device (e.g., ttyS0), so chdir /dev */&lt;br /&gt;
   chdir(&amp;quot;/dev&amp;quot;);&lt;br /&gt;
   if( access(param[iconsole].v, F_OK ) == 0 ) {&lt;br /&gt;
     printk(&amp;quot;Opening stdin, stdout, and stderr on %s.\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
     close(0);&lt;br /&gt;
     open(param[iconsole].v, O_RDWR);&lt;br /&gt;
     dup2(0, 1);&lt;br /&gt;
     dup2(0, 2);&lt;br /&gt;
   } else {&lt;br /&gt;
     printk(&amp;quot;access F_OK: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
     printk(&amp;quot;Could not access device: %s!\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
     printk(&amp;quot;Console redirection to device %s aborted!\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
   }&lt;br /&gt;
   chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;Execing: \&amp;quot;%s %s\&amp;quot; to boot mounted root system.\n&amp;quot;, param[iinit].v, param[irunlevel].v);&lt;br /&gt;
&lt;br /&gt;
 /* free resources held to this point */&lt;br /&gt;
 free(cmdline);&lt;br /&gt;
 free(miscproc_buff);&lt;br /&gt;
&lt;br /&gt;
 if( execl(param[iinit].v, param[irunlevel].v, (char *) NULL ) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: execl: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If foobarz-init is updated, you can find the latest version at [https://github.com/foobarz/foobarz-init github].&lt;br /&gt;
&lt;br /&gt;
The foobarz-init program can be compiled two ways as of v1.1.1. First, the simpler compile that does not support zpool_import but does support importing pools using a /etc/zfs/zpool.cache file in the initramfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gcc --static init.c -o init&lt;br /&gt;
strip init&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The second way to compile it adds support for zpool_import so that you do not have to include a &amp;lt;code&amp;gt;/etc/zfs/zpool.cache&amp;lt;/code&amp;gt; file in the initramfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gcc -static -DINCLUDE_ZPOOL_IMPORT \&lt;br /&gt;
     foobarz-init.c -include /usr/src/zfs-0.6.0-rc10/3.2.28/zfs_config.h \&lt;br /&gt;
    -o init \&lt;br /&gt;
    -I /usr/include/libspl -I /usr/include/libzfs \&lt;br /&gt;
    -lzfs -lnvpair -lzpool -luutil -luuid -lrt -lz -lm -lpthread \&lt;br /&gt;
    -I /usr/include/tirpc \&lt;br /&gt;
    -ltirpc&lt;br /&gt;
strip init&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Dependencies required before you can compile this second way:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Install [http://sourceforge.net/projects/libtirpc/ libtirpc]. The glibc package has removed the RPC-related functions from the static libc. The libtirpc is the new replacement as a separate library. You can make your own libtirpc package and install it to resolve these RPC-related functions. Without this, the compile fails because it cannot find many &amp;quot;xdr&amp;quot; functions.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Reinstall the [ftp://slackware.mirrors.tds.net/pub/slackware/slackware64-current/source/a/util-linux/ util-linux] package with static libraries enabled. Edit the &amp;lt;code&amp;gt;util-linux.SlackBuild&amp;lt;/code&amp;gt; and remove the line &amp;lt;code&amp;gt;--disable-static&amp;lt;/code&amp;gt;, then build it and use upgradepkg to install the new package. This resolves linking static to libuuid.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
With these dependencies, you can probably compile static with the zpool_import support. The exact location of &amp;quot;zfs_config.h&amp;quot; may vary depending on your zfs and kernel versions, so adjust accordingly.&lt;br /&gt;
&lt;br /&gt;
Read the foobarz-init source code to see how it uses kernel parameters. The params &amp;lt;code&amp;gt;root&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;rootfstype&amp;lt;/code&amp;gt; are always required to tell init what root pool name to mount and the filesystem type (e.g. zfs).&lt;br /&gt;
&lt;br /&gt;
For the zpool_import support: &amp;lt;code&amp;gt;zpool_import_name=poolname&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;zpool_import_guid=&amp;lt;guid of a pool&amp;gt;&amp;lt;/code&amp;gt; tells what pool to import. You can also import the pool with a new different name by also using &amp;lt;code&amp;gt;zpool_import_newname=newpoolname&amp;lt;/code&amp;gt;. If the import is not working, &amp;lt;code&amp;gt;zpool_import_force=1&amp;lt;/code&amp;gt; can be used to force import even if ZFS thinks the pool may be in use by another system.&lt;br /&gt;
&lt;br /&gt;
However you import the pool, either using zpool.cache or zpool_import support, the kernel param &amp;lt;code&amp;gt;root=&amp;lt;your poolname or newpoolname&amp;gt;&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;rootfstype=zfs&amp;lt;/code&amp;gt; needs to be given also. The zpool_import only imports, it does not say what to mount. What to mount is still told using root= and rootfstype=.&lt;br /&gt;
&lt;br /&gt;
Now copy the compiled static program into the initramfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp init /boot/initramfs-source/init&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Build and install kernel:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make -j8&lt;br /&gt;
make -j8 modules_install&lt;br /&gt;
cp arch/x86/boot/bzImage /boot/vm3.2.27b&lt;br /&gt;
cp System.map /boot/System.map-vm3.2.27b&lt;br /&gt;
# add new lilo menu entry for vm3.2.27b kernel&lt;br /&gt;
vi /etc/lilo.conf&lt;br /&gt;
  image = /boot/vm3.2.27b&lt;br /&gt;
   label = vm3.2.27b&lt;br /&gt;
   addappend = &amp;quot; spl.spl_hostid=0x007f0100 zfs.spa_config_path=/etc/zfs/zpool.cache root=zfs-root rootfstype=zfs&amp;quot;&lt;br /&gt;
lilo&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Congrats! If this works, you can select the &amp;quot;vm3.2.27b&amp;quot; lilo entry to boot. If you are using the zpool_import support in the init program, you need to add at least the &amp;lt;code&amp;gt;zpool_import_name=zfs-root&amp;lt;/code&amp;gt; param to the addappend line in lilo.conf.&lt;br /&gt;
&lt;br /&gt;
Notes on kernel params (lilo append and addappend lines): root= and rootfstype= are used by both foorbarz-init and mkinitrd. The &amp;quot;ro&amp;quot; param is not used by foobarz-init, so instead use: mountopt=ro|rw. See &amp;quot;modinfo spl&amp;quot; and &amp;quot;modinfo zfs&amp;quot; to see all of the options those modules can take on the kernel command line. Notice the &amp;lt;code&amp;gt;spl.spl_hostid=0x007f0100&amp;lt;/code&amp;gt; param that works around the hostid mismatch problem while trying to import a pool; this param and hostname/ip set to use local loopback 127.0.0.1 in etc/hosts etc/HOSTNAME in initramfs will work most of the time, and if not the pool import needs to be forced.&lt;br /&gt;
&lt;br /&gt;
Notes on the spl and zfs packages to install: &amp;lt;i&amp;gt;If&amp;lt;/i&amp;gt; you have errors using zfs and zpool commands on booted system with builtin modules, then upgrade/switch to the 0.6.0rc10_3.2.27b builds, or you can make a custom package with the binaries renamed like zpoolb, zfsb etc for builtin.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
Using qemu's -nographic serial console (/usr/share/qemu/sgabios.bin): If you have a boot problem, you might want to run in qemu's -nographic console mode:&lt;br /&gt;
&lt;br /&gt;
First, edit /etc/inittab, and uncomment the line for local serial ports runlevel &amp;quot;s1&amp;quot; (ttyS0) for serial console login support. This is done in the guest (host does not need this):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Local serial lines:&lt;br /&gt;
s1:12345:respawn:/sbin/agetty -L ttyS0 38400 linux&lt;br /&gt;
#s1:12345:respawn:/sbin/agetty -L ttyS0 9600 vt100&lt;br /&gt;
#s2:12345:respawn:/sbin/agetty -L ttyS1 9600 vt100&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Second, edit /etc/securetty, and uncomment ttyS0 line:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ttyS0&lt;br /&gt;
#ttyS1&lt;br /&gt;
# ...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
You cannot login on ttyS0 without this change even though you get the login prompt!&lt;br /&gt;
&lt;br /&gt;
Then, run qemu such as:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
qemu-kvm &amp;lt;all regular options&amp;gt; -nographic -option-rom sgabios.bin,bootindex=0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Wait for the lilo prompt, it may take several seconds show up in this mode.&lt;br /&gt;
&lt;br /&gt;
In the lilo menu, select your kernel image with builtin spl/zfs, and use kernel params such as:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
boot: vm3.2.27b console=ttyS0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
At the lilo prompt, use kernel parameter: console=ttyS0 (do NOT say /dev/ttS0). Passing runlevel=s1 does not appear to be necessary.&lt;br /&gt;
&lt;br /&gt;
When you are in qemu's serial mode, the interface is a little different than in the normal graphical mode: use keypresses:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ctrl-a h    # for help&lt;br /&gt;
ctrl-a c    # toggle access to (QEMU) console / back to emulation&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If you cannot get a login: prompt, try ctrl-a c, then do (QEMU) sendkey ctrl-alt-delete. This will reboot cleanly back to lilo, then you can do (QEMU) quit.&lt;br /&gt;
&lt;br /&gt;
Once you login to the guest, the terminal size needs adjustment. On your host, in another xterm sized the same as your guest console terminal, get the size of the terminal:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo $LINES&lt;br /&gt;
echo $COLUMNS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Now, back in the guest terminal of same size:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export LINES &amp;lt;lines&amp;gt;&lt;br /&gt;
export COLUMNS &amp;lt;columns&amp;gt;&lt;br /&gt;
stty cols $COLUMNS rows $LINES&lt;br /&gt;
exec bash&lt;br /&gt;
reset&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
So, you set the environment variables and also set them with stty. Then, restart bash (exec, or else it is a child shell process).&lt;br /&gt;
&lt;br /&gt;
BECAREFUL not to start qemu twice on the same ZFS guest! Two simultaneous running qemu on the same ZFS will corrupt the pool and it will NOT recover - you lose your whole installation! Before running qemu, check ps -A, look for an already running qemu process incase it somehow entered into the background!&lt;br /&gt;
&lt;br /&gt;
BECAREFUL when using -nographic ttyS0 that you are not doing commands on the HOST! Only use -nographic to see kernel problems. Use regular console if booting is working normally.&lt;br /&gt;
&lt;br /&gt;
To use the qemu -drive if=scsi option, the linux module sym53c8xx should be loaded in the guest. You may need to use the qemu option:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-option-rom 8xx_64.rom,bootindex=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The file 8xx_64.rom used to be inside qemu, but in new versions it is missing. You can download it:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
wget http://www.lsi.com/downloads/Public/Host%20Bus%20Adapters/Host%20Bus%20Adapters%20Common%20Files/lsi_bios.zip&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Extract the zip and place 8xx_64.rom in /usr/share/qemu/.&lt;br /&gt;
&lt;br /&gt;
Good luck!&lt;/div&gt;</description>
			<pubDate>Wed, 12 Sep 2012 19:57:57 GMT</pubDate>
			<dc:creator>Foobarz</dc:creator>
			<comments>https://www.slackwiki.com/Talk:ZFS_root_(builtin)</comments>
		</item>
		<item>
			<title>ZFS root (builtin)</title>
			<link>https://www.slackwiki.com/index.php?title=ZFS_root_(builtin)&amp;diff=788</link>
			<guid isPermaLink="false">https://www.slackwiki.com/index.php?title=ZFS_root_(builtin)&amp;diff=788</guid>
			<description>&lt;p&gt;Foobarz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Tutorials]]&lt;br /&gt;
The first [http://slackwiki.com/ZFS_root &amp;quot;ZFS root&amp;quot;] wiki explains the details of running ZFS as your root filesystem by using a fully modular generic kernel approach. Now, I can share how it can be done with the SPL and ZFS modules built into the kernel. This procedure is just an example and can use some fine tuning, but here goes:&lt;br /&gt;
&lt;br /&gt;
The steps below are to create a kernel with SPL and ZFS modules builtin. This kernel will be installed as an alternative kernel to boot in lilo, and it will have a separate kernel installation from the fully modular and working system kernel. This will allow testing the builtin kernel while able to boot back onto a working modular ZFS system. We start this procedure assuming you are on a working fully modular ZFS install as in the &amp;quot;ZFS root&amp;quot; wiki.&lt;br /&gt;
&lt;br /&gt;
Use mountpoint=legacy so that zfs will not expect &amp;lt;code&amp;gt;zfs mount&amp;lt;/code&amp;gt;, but instead expect standard &amp;lt;code&amp;gt;mount&amp;lt;/code&amp;gt; for mounting zfs-root:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=legacy zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Edit &amp;lt;code&amp;gt;/etc/rc.d/rc.S&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;rc.6&amp;lt;/code&amp;gt; to use regular &amp;lt;code&amp;gt;mount&amp;lt;/code&amp;gt; commands, remove &amp;lt;code&amp;gt;zfs&amp;lt;/code&amp;gt; commands. Edit &amp;lt;code&amp;gt;rc.6&amp;lt;/code&amp;gt; and remove or comment out &amp;lt;code&amp;gt;zfs export&amp;lt;/code&amp;gt; command. These edits undo changes made in the &amp;quot;ZFS root&amp;quot; wiki, but it shows the two different ways of mounting a zfs filesystem.&lt;br /&gt;
&lt;br /&gt;
You &amp;lt;i&amp;gt;might&amp;lt;/i&amp;gt; think to set &amp;lt;code&amp;gt;bootfs&amp;lt;/code&amp;gt; property like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool set bootfs=zfs-root zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
However, this will result in ZFS placing many restrictions on zfs-root as per how that option is used on Solaris systems:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; zfs-root must be VTOC (SMI) label, not GPT (EFI) label&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; zfs-root can only contain 1 vdev: either a plain disk, or a mirror&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
So, do &amp;lt;b&amp;gt;NOT&amp;lt;/b&amp;gt; set that property! If &amp;lt;code&amp;gt;bootfs&amp;lt;/code&amp;gt; is set, you would find that you cannot add vdevs to your zfs-root. If it is set already, then unset it like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool set bootfs= zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Make a directory to store files to be inside the initramfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkdir /boot/initramfs-source&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This directory will hold some files for the initial rootfs inside the kernel. Your &amp;lt;code&amp;gt;/boot&amp;lt;/code&amp;gt; should be on a small ext4 partition or on a mounted USB stick that you use to boot.&lt;br /&gt;
&lt;br /&gt;
Extract the slackware kernel-source package to obtain a copy of the kernel source, and make an initial kernel config for it:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir src&lt;br /&gt;
cd src&lt;br /&gt;
tar xvzf /mnt/cdrom/slackware64/k/kernel-source-*.txz&lt;br /&gt;
mv usr/src/linux-3.2.27 /usr/src/linux-3.2.27b&lt;br /&gt;
rm -r install&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make menuconfig&lt;br /&gt;
  General setup-&amp;gt;Local version - append to kernel release = b&lt;br /&gt;
  General setup-&amp;gt;Default hostname                         = slackzfs&lt;br /&gt;
  General setup-&amp;gt;Initramfs source files(s)                = /boot/initramfs-source&lt;br /&gt;
  Device Drivers-&amp;gt;SCSI device support-&amp;gt;SCSI low-level drivers-&amp;gt; &amp;lt;*&amp;gt; SYM53C8XX Version 2 SCSI support&lt;br /&gt;
  File systems -&amp;gt; &amp;lt;*&amp;gt; The Extended 4 (ext4) filesystem&lt;br /&gt;
  # build in any hard drive controllers and filesystems that you need for booting&lt;br /&gt;
  # then save the config&lt;br /&gt;
make prepare scripts&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The kernel source has been set to have a &amp;quot;Local version&amp;quot; &amp;lt;code&amp;gt;b&amp;lt;/code&amp;gt;. This will result in modules installed to &amp;lt;code&amp;gt;/lib/modules/3.2.27b&amp;lt;/code&amp;gt; and keeps this kernel's source and modules seperate from slackware's kernel-generic package installation. The &amp;lt;code&amp;gt;make prepare scripts&amp;lt;/code&amp;gt; command readies the kernel source as needed before we can install a copy of spl and zfs modules into the kernel source tree.&lt;br /&gt;
&lt;br /&gt;
Now proceed to configure and copy spl and zfs into the kernel source tree:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd ~/src&lt;br /&gt;
tar xvzf ~/spl-0.6.0-rc10.tar.gz&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-0.6.0-rc10&lt;br /&gt;
./configure \&lt;br /&gt;
    --prefix=/ \&lt;br /&gt;
    --libdir=/lib64 \&lt;br /&gt;
    --includedir=/usr/include \&lt;br /&gt;
    --datarootdir=/usr/share \&lt;br /&gt;
    --enable-linux-builtin=yes \&lt;br /&gt;
    --with-linux=/usr/src/linux-3.2.27b \&lt;br /&gt;
    --with-linux-obj=/usr/src/linux-3.2.27b&lt;br /&gt;
wget https://raw.github.com/zfsonlinux/spl/master/copy-builtin&lt;br /&gt;
chmod +x copy-builtin&lt;br /&gt;
./copy-builtin /usr/src/linux-3.2.27b&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../spl-0.6.0rc10_3.2.27b-x86_64-1root.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
&lt;br /&gt;
tar xvzf ~/zfs-0.6.0-rc10.tar.gz&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-0.6.0-rc10&lt;br /&gt;
./configure \&lt;br /&gt;
    --prefix=/ \&lt;br /&gt;
    --libdir=/lib64 \&lt;br /&gt;
    --includedir=/usr/include \&lt;br /&gt;
    --datarootdir=/usr/share \&lt;br /&gt;
    --enable-linux-builtin=yes \&lt;br /&gt;
    --with-linux=/usr/src/linux-3.2.27b \&lt;br /&gt;
    --with-linux-obj=/usr/src/linux-3.2.27b \&lt;br /&gt;
    --with-spl=/root/src/spl-0.6.0-rc10&lt;br /&gt;
wget https://raw.github.com/zfsonlinux/zfs/master/copy-builtin&lt;br /&gt;
chmod +x copy-builtin&lt;br /&gt;
./copy-builtin /usr/src/linux-3.2.27b&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../zfs-0.6.0rc10_3.2.27b-x86_64-1root.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
At this point, the &amp;lt;code&amp;gt;copy-builtin&amp;lt;/code&amp;gt; scripts have installed the configured spl and zfs modules source into the kernel source. The regular &amp;lt;code&amp;gt;make menuconfig&amp;lt;/code&amp;gt; in the kernel source should now show options for spl and zfs in the kernel config.&lt;br /&gt;
&lt;br /&gt;
As of this writing, the copy-builtin script places the spl and zfs modules into the kernel source in places where the modules may not initialize in the best order, &amp;lt;i&amp;gt;after&amp;lt;/i&amp;gt; all lower-level storage drivers are initialized. If spl and zfs initialize too soon, there is a chance they may not be able to see all of the storage devices. The order of initialization (as seen in dmesg) of modules that are builtin to the kernel is the order that the modules are linked into the kernel during kernel compilation. The order of link depends on where the module source files are located in the kernel source tree. To ensure that spl and zfs will initialize after all hardware drivers, we move them into the &amp;lt;code&amp;gt;drivers&amp;lt;/code&amp;gt; tree and after all other drivers:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
mkdir drivers/zfsonlinux&lt;br /&gt;
mv spl drivers/zfsonlinux&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  # remove references to spl&lt;br /&gt;
vi Makefile&lt;br /&gt;
  # remove references to spl&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/fs&lt;br /&gt;
mv zfs ../drivers/zfsonlinux&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  # remove references to zfs&lt;br /&gt;
vi Makefile&lt;br /&gt;
  # remove references to zfs&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  )# add line at end of menu, before &amp;quot;endmenu&amp;quot;:&lt;br /&gt;
  )source &amp;quot;drivers/zfsonlinux/Kconfig&amp;quot;&lt;br /&gt;
  )endmenu&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers&lt;br /&gt;
vi Makefile&lt;br /&gt;
  )# add line at very end of file:&lt;br /&gt;
  )obj-$(CONFIG_ZFSONLINUX) += zfsonlinux/&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers/zfsonlinux&lt;br /&gt;
cat &amp;gt; Kconfig &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
menuconfig ZFSONLINUX&lt;br /&gt;
	tristate &amp;quot;ZFSonLinux support&amp;quot;&lt;br /&gt;
&lt;br /&gt;
if ZFSONLINUX&lt;br /&gt;
&lt;br /&gt;
source &amp;quot;drivers/zfsonlinux/spl/Kconifg&amp;quot;&lt;br /&gt;
&lt;br /&gt;
source &amp;quot;drivers/zfsonlinux/zfs/Kconifg&amp;quot;&lt;br /&gt;
&lt;br /&gt;
endif&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/zfsonlinux&lt;br /&gt;
cat &amp;gt; Makefile &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
obj-$(CONFIG_SPL) += spl/&lt;br /&gt;
obj-$(CONFIG_ZFS) += zfs/&lt;br /&gt;
EOF&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This completes the move of the spl and zfs modules in the kernel source tree to be under &amp;lt;code&amp;gt;drivers/zfsonlinux&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Now, in kernel configuration, you can build in the modules as follows:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make menuconfig&lt;br /&gt;
   Device Drivers -&amp;gt;&lt;br /&gt;
    &amp;lt;*&amp;gt; ZFSonLinux support -&amp;gt;&lt;br /&gt;
      &amp;lt;*&amp;gt; Solaris Porting Layer (SPL)&lt;br /&gt;
      &amp;lt;*&amp;gt;     ZFS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the kernel config, we set &amp;lt;code&amp;gt;/boot/initramfs-source&amp;lt;/code&amp;gt; as source location of the contents to be linked into kernel's builtin initramfs (rootfs). Now, we create some files that are needed to be in the initramfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /boot/initramfs-source&lt;br /&gt;
&lt;br /&gt;
# make standard directories&lt;br /&gt;
mkdir -p proc dev sys mnt bin sbin etc/zfs&lt;br /&gt;
&lt;br /&gt;
# zfs seems to want mtab present, even if empty&lt;br /&gt;
touch etc/mtab&lt;br /&gt;
&lt;br /&gt;
# if zpool.cache file can be read by zfs at module init, it imports the pools in the cache&lt;br /&gt;
cp /etc/zfs/zpool.cache-initrd etc/zfs/zpool.cache&lt;br /&gt;
&lt;br /&gt;
# make initial console device node; otherwise, there is a problem at startup:&lt;br /&gt;
# &amp;quot;Warning: unable to open an initial console&amp;quot; and you'd have problems with console and tty login&lt;br /&gt;
# making these nodes from within /init is not early enough to avoid problem&lt;br /&gt;
mknod dev/console c 5 1   # system console&lt;br /&gt;
&lt;br /&gt;
# make memory device kmsg to &amp;quot;printk&amp;quot; kernel messages&lt;br /&gt;
# we can write to this file to send out messages&lt;br /&gt;
mknod dev/kmsg    c 1 11  # lines printed to kmsg enter kernel messages buffer&lt;br /&gt;
&lt;br /&gt;
# recommended loop0 device to mount fs images&lt;br /&gt;
mknod dev/loop0   b 7 0&lt;br /&gt;
&lt;br /&gt;
# make initial virtual terminal devices&lt;br /&gt;
mknod dev/tty     c 5 0   # current tty&lt;br /&gt;
mknod dev/tty0    c 4 0   # current virtual term&lt;br /&gt;
mknod dev/tty1    c 4 1   # login virtual term 1 (F1)&lt;br /&gt;
&lt;br /&gt;
# make alternative console=ttyS0 standard 8250/16550 UART serial port devices&lt;br /&gt;
#   useful with kernel parameter console=ttyS0&lt;br /&gt;
#          with qemu -nographic -option-rom sgabios.bin,bootindex=0&lt;br /&gt;
mknod dev/ttyS0   c 4 64  # COM1&lt;br /&gt;
mknod dev/ttyS1   c 4 65  # COM2&lt;br /&gt;
mknod dev/ttyS2   c 4 66  # COM3&lt;br /&gt;
mknod dev/ttyS3   c 4 67  $ COM4&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This should be enough device nodes initially in the initramfs. Once devtmpfs mounts over /dev inside initramfs, a lot more devices are available in it by default.&lt;br /&gt;
&lt;br /&gt;
The initramfs needs an &amp;lt;code&amp;gt;/init&amp;lt;/code&amp;gt; program that will be run automatically by the kernel as process id 1, the first program to run on the system. This program's task is to mount a root filesystem, switch it to be the new root (/), and then exec the init (&amp;lt;code&amp;gt;/sbin/init&amp;lt;/code&amp;gt;) program that is on the new root so that the new root system is booted.&lt;br /&gt;
&lt;br /&gt;
The common way to make /init is using busybox with files like these in /boot/initrd-tree or /boot/initramfs-source:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
bin/busybox&lt;br /&gt;
bin/ash -&amp;gt; busybox&lt;br /&gt;
bin/sh -&amp;gt; busybox&lt;br /&gt;
# run busybox to see what other &amp;quot;applets&amp;quot; can be symlinked to it&lt;br /&gt;
# when busybox is run as a different symlinked applet name, it runs as the applet&lt;br /&gt;
init&lt;br /&gt;
# init can be an ash script, see slackware's /boot/initrd-tree/init for example&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For example, as an ash script, slackware's init does the following:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;parse kernel parameters passed into it and set variables based on them&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;start udevd and trigger rules for block devices to setup initial /dev devices&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;load kernel modules and keyboard map&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;run mdadm, cryptsetup, lvm, zpool/zfs to setup more devices&lt;br /&gt;
     (any udev rules for them should do more /dev setup in the background)&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;mount the root filesystem read-only at /mnt&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;stat /mnt/sbin/init, and if not executable run a rescue shell /bin/sh&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;shutdown udevd so it can be restarted by root system when booted&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;mount --move {proc,sys,run,dev} to under /mnt&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;run: exec switch_root /mnt /sbin/init $RUNLEVEL&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The slackware mkinitrd package is a fully configured BusyBox installation that makes an external initramfs image file, initrd.gz, that is passed to the kernel by the bootloader (lilo). It could be changed to be internal to the kernel by just using initrd-tree as the CONFIG_INITRAMFS_SOURCE in the kernel config and removing initrd in the lilo.conf.&lt;br /&gt;
&lt;br /&gt;
The main purpose of most initramfs/initrd is to load and configure kernel modules and devices needed to mount a root filesystem. Because the spl/zfs modules are builtin, there isn't really a lot that needs to be done by an initramfs. What remains to be done is import the zfs-root pool, mount it, and exec the system /sbin/init. The kernel's &amp;quot;legacy&amp;quot; parameters &amp;lt;code&amp;gt;root=&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;rootfstype=&amp;lt;/code&amp;gt; that are able to directly boot a root disk do not work with ZFS at this time because ZFS pools always need to be imported before it is possible to mount and boot on them. The automatic import that ZFS can do by using a cachefile (/etc/zfs/zpool.cache) stored in initramfs still does not work with the legacy boot parameters because at an eariler stage of the boot process, the kernel ignores a rootfs that does not contain an &amp;lt;code&amp;gt;/init&amp;lt;/code&amp;gt; program, and/or the device type of an imported pool is not the device types recognized by the legacy boot as valid root devices.&lt;br /&gt;
&lt;br /&gt;
You could just continue to use slackware's mkinitrd package as in the &amp;quot;ZFS root&amp;quot; wiki and it works the same whether the modules are builtin or not. But, by building the spl/zfs modules in, aren't we really wanting to get rid of using the mkinitrd/initrd.gz? We'd like to have a kernel with everything in it to boot, and use a simple lilo image entry that has no initrd.&lt;br /&gt;
&lt;br /&gt;
We can do this, and not use the mkinitrd package, but we still need to finish our own initramfs &amp;lt;code&amp;gt;/init&amp;lt;/code&amp;gt; program to import, mount, switch root, and boot. Save the following c program to &amp;quot;foobarz-init.c&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/* software product name: foobarz-init.c&lt;br /&gt;
 * suggested binary name: /init (in initramfs-source, rootfs)&lt;br /&gt;
 * license              : BSD&lt;br /&gt;
 * license text:&lt;br /&gt;
Copyright (c) 2012, foobarz&lt;br /&gt;
All rights reserved.&lt;br /&gt;
&lt;br /&gt;
Redistribution and use in source and binary forms, with or without&lt;br /&gt;
modification, are permitted provided that the following conditions are met:&lt;br /&gt;
    * Redistributions of source code must retain the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer.&lt;br /&gt;
    * Redistributions in binary form must reproduce the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer in the&lt;br /&gt;
      documentation and/or other materials provided with the distribution.&lt;br /&gt;
    * Neither the name of the &amp;lt;organization&amp;gt; nor the&lt;br /&gt;
      names of its contributors may be used to endorse or promote products&lt;br /&gt;
      derived from this software without specific prior written permission.&lt;br /&gt;
&lt;br /&gt;
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &amp;quot;AS IS&amp;quot; AND&lt;br /&gt;
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED&lt;br /&gt;
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE&lt;br /&gt;
DISCLAIMED. IN NO EVENT SHALL &amp;lt;COPYRIGHT HOLDER&amp;gt; BE LIABLE FOR ANY&lt;br /&gt;
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES&lt;br /&gt;
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;&lt;br /&gt;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND&lt;br /&gt;
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT&lt;br /&gt;
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS&lt;br /&gt;
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
/* Your initramfs-source should contain the following&lt;br /&gt;
 *&lt;br /&gt;
 * cd /boot/initramfs-source&lt;br /&gt;
 * mkdir -p proc dev sys mnt bin sbin etc/zfs&lt;br /&gt;
 * touch etc/mtab&lt;br /&gt;
 * cp /etc/zfs/zpool.cache-initrd etc/zfs/zpool.cache&lt;br /&gt;
 * # zpool.cache is optional - zpool_import_ kernel params can be used instead&lt;br /&gt;
 * #  see below for details on using zpool_import&lt;br /&gt;
 * mknod dev/console c 5 1   # system console&lt;br /&gt;
 * mknod dev/kmsg    c 1 11  # lines printed to kmsg enter kernel messages buffer&lt;br /&gt;
 * mknod dev/loop0   b 7 0&lt;br /&gt;
 * mknod dev/tty     c 5 0   # current tty&lt;br /&gt;
 * mknod dev/tty0    c 4 0   # current virtual term&lt;br /&gt;
 * mknod dev/tty1    c 4 1   # login virtual term 1 (F1)&lt;br /&gt;
 * mknod dev/ttyS0   c 4 64  # COM1&lt;br /&gt;
 * mknod dev/ttyS1   c 4 65  # COM2&lt;br /&gt;
 * mknod dev/ttyS2   c 4 66  # COM3&lt;br /&gt;
 * mknod dev/ttyS3   c 4 67  $ COM4&lt;br /&gt;
 *&lt;br /&gt;
 * and this program compiled to /boot/initramfs-source/init&lt;br /&gt;
 *&lt;br /&gt;
 * Set kernel config option&lt;br /&gt;
 *  CONFIG_INITRAMFS_SOURCE=/boot/initramfs-source&lt;br /&gt;
 * to build the initramfs into your kernel image&lt;br /&gt;
 *  that also has builtin drivers (spl and zfs, etc).&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
#define FOOBARZ_INIT_VERSION &amp;quot;1.1.1&amp;quot;&lt;br /&gt;
#define _BSD_SOURCE&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdarg.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;fcntl.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/mount.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sysexits.h&amp;gt;&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
/* support for zpool import&lt;br /&gt;
 *&lt;br /&gt;
 * If -DINCLUDE_ZPOOL_IMPORT, then support to import a zpool is&lt;br /&gt;
 * enabled in the program. Enabling it will add many dependencies to the&lt;br /&gt;
 * compile and link; for example:&lt;br /&gt;
 *&lt;br /&gt;
 * gcc -static -DINCLUDE_ZPOOL_IMPORT \&lt;br /&gt;
 *    foobarz-init.c -include /usr/src/zfs-0.6.0-rc10/3.2.28/zfs_config.h \&lt;br /&gt;
 *   -o init \&lt;br /&gt;
 *   -I /usr/include/libspl -I /usr/include/libzfs \&lt;br /&gt;
 *   -lzfs -lnvpair -lzpool -luutil -luuid -lrt -lz -lm -lpthread \&lt;br /&gt;
 *   -I /usr/include/tirpc \&lt;br /&gt;
 *   -ltirpc&lt;br /&gt;
 *&lt;br /&gt;
 * Note that libtirpc is a drop-in replacement for the SunRPC functions that&lt;br /&gt;
 * used to be in glibc. No additional includes are needed, just the gcc -I and -l&lt;br /&gt;
 * options for tirpc.&lt;br /&gt;
 *&lt;br /&gt;
 * Otherwise, with -UINCLUDE_ZPOOL_IMPORT, the compile is just:&lt;br /&gt;
 * gcc -static foobarz-init.c -o init&lt;br /&gt;
 */&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
#include &amp;lt;libzfs.h&amp;gt;&lt;br /&gt;
#else&lt;br /&gt;
#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/stat.h&amp;gt;&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#define PARAM_REQ_NO 0&lt;br /&gt;
#define PARAM_REQ_YES 1&lt;br /&gt;
#define PARAM_SRC_DEFAULT 0&lt;br /&gt;
#define PARAM_SRC_CMDLINE 1&lt;br /&gt;
&lt;br /&gt;
void printk(char *fmt, ...) {&lt;br /&gt;
  FILE* f;&lt;br /&gt;
  int fd;&lt;br /&gt;
  va_list args;&lt;br /&gt;
&lt;br /&gt;
  f = fopen(&amp;quot;/dev/kmsg&amp;quot;, &amp;quot;w&amp;quot;);&lt;br /&gt;
  va_start(args, fmt);&lt;br /&gt;
  vfprintf(f, fmt, args);&lt;br /&gt;
  va_end(args);&lt;br /&gt;
  fflush(f);&lt;br /&gt;
  fclose(f);&lt;br /&gt;
  /* avoid flooding kmsg and having msgs suppressed; 20msgs/sec */&lt;br /&gt;
  usleep(50000);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[]) {&lt;br /&gt;
 /*** variables */&lt;br /&gt;
&lt;br /&gt;
 int i;&lt;br /&gt;
 int   fd = 0; /* file descriptor */&lt;br /&gt;
 unsigned long mountflags;&lt;br /&gt;
&lt;br /&gt;
 /* kernel command line */&lt;br /&gt;
 off_t cmdline_size;&lt;br /&gt;
 char* cmdline; /* to be malloc 4096B */&lt;br /&gt;
 char* cmdline_end;&lt;br /&gt;
 char* temp_end;&lt;br /&gt;
 char* src_msg; /* default or cmdline */&lt;br /&gt;
 int flag_param_missing = 0;&lt;br /&gt;
&lt;br /&gt;
 /* use to hold contents of a misc /proc/&amp;lt;file&amp;gt; */&lt;br /&gt;
 char* miscproc_buff; /* to be malloc 4096B */&lt;br /&gt;
 off_t miscproc_size;&lt;br /&gt;
&lt;br /&gt;
 /* note about environ, argv, and kernel cmdline for init:&lt;br /&gt;
  *   environ is not defined for init&lt;br /&gt;
  *   only argv[0] is set for init&lt;br /&gt;
  *   kernel command line parameters are accessed&lt;br /&gt;
  *   at /proc/cmdline&lt;br /&gt;
  */&lt;br /&gt;
&lt;br /&gt;
 /* kernel parameters expected to be name=value */&lt;br /&gt;
 /* do not use quotes or spaces in parameters   */&lt;br /&gt;
 /* you can add more params somwhere after root= */&lt;br /&gt;
 struct nv { char* n; char* v; char* v_end; int req; int src; };&lt;br /&gt;
 struct nv param[] = {&lt;br /&gt;
   { &amp;quot;root=&amp;quot;,       NULL, NULL, PARAM_REQ_YES, PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;rootfstype=&amp;quot;, NULL, NULL, PARAM_REQ_YES, PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;mountopt=&amp;quot;,   NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;init=&amp;quot;,       NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;runlevel=&amp;quot;,   NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;console=&amp;quot;,    NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT }&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
   ,&lt;br /&gt;
   { &amp;quot;zpool_import_name=&amp;quot;,    NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;zpool_import_guid=&amp;quot;,    NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;zpool_import_newname=&amp;quot;, NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;zpool_import_force=&amp;quot;,   NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT }&lt;br /&gt;
#endif&lt;br /&gt;
 };&lt;br /&gt;
 enum {&lt;br /&gt;
	 iroot,&lt;br /&gt;
	 irootfstype,&lt;br /&gt;
	 imountopt,&lt;br /&gt;
	 iinit,&lt;br /&gt;
	 irunlevel,&lt;br /&gt;
	 iconsole,&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
	 izpool_import_name,&lt;br /&gt;
	 izpool_import_guid,&lt;br /&gt;
	 izpool_import_newname,&lt;br /&gt;
	 izpool_import_force,&lt;br /&gt;
#endif&lt;br /&gt;
	 ilastparam&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
 libzfs_handle_t* libzfs = NULL;&lt;br /&gt;
 importargs_t iargs = { 0 };&lt;br /&gt;
 nvlist_t* pools = NULL;&lt;br /&gt;
 nvpair_t* pool = NULL;&lt;br /&gt;
 nvlist_t* config = NULL;&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
 /*** program */&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;foobarz-init, version %s: booting initramfs.\n&amp;quot;, FOOBARZ_INIT_VERSION);&lt;br /&gt;
&lt;br /&gt;
 cmdline       = (char*) malloc(4096);&lt;br /&gt;
 miscproc_buff = (char*) malloc(4096);&lt;br /&gt;
 if( (cmdline == NULL) || (miscproc_buff == NULL) ) {&lt;br /&gt;
   printk(&amp;quot;Unable to allocate buffer memory: malloc: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount proc /proc&lt;br /&gt;
  *  note: some /dev devices symlink into /proc&lt;br /&gt;
  *  proc contains info about processes, including cmdline etc. */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount proc /proc\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;proc&amp;quot;, &amp;quot;/proc&amp;quot;, &amp;quot;proc&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
   printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
   printk(&amp;quot;Mount proc successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount devtmpfs /dev&lt;br /&gt;
  *  note: This simple init program works if your root device is made from devices&lt;br /&gt;
  *  that are available by default in devtmpfs, such as /dev/sd*&lt;br /&gt;
  *&lt;br /&gt;
  *  For zfs, your root zfs pool should be created with default device nodes and&lt;br /&gt;
  *  then it should be mountable by this simple init program.&lt;br /&gt;
  *&lt;br /&gt;
  *  udev may be needed to configure device nodes and symlinks required&lt;br /&gt;
  *  to access a root device configuration made with such nodes and symlinks.&lt;br /&gt;
  *  If you need udevd, you can include it into your initramfs-source and&lt;br /&gt;
  *  modify this program to run it before attempting to mount your root device.&lt;br /&gt;
  *  However, if udevd is needed, a significant number of userspace programs may also be&lt;br /&gt;
  *  required by rules in /lib/udev/. You could install busybox + udev (about 5MB) or&lt;br /&gt;
  *  coreutils + util-linux + bash + udev (about 25MB) into initramfs-source. But, at that&lt;br /&gt;
  *  point you'd have ash or bash and many tools that are easier to use than this&lt;br /&gt;
  *  simple init program; it would then be easy to have /init as #!/bin/&amp;lt;b&amp;gt;ash script. */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount devtmpfs /dev\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;devtmpfs&amp;quot;, &amp;quot;/dev&amp;quot;, &amp;quot;devtmpfs&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
   printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
   printk(&amp;quot;Mount devtmpfs successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount sysfs /sys&lt;br /&gt;
  *  note: some kernel modules try to access /sys with userspace helpers to echo values into /sys variables;&lt;br /&gt;
  *  such modules expect a minimal userspace that contains coreutils or busybox */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount sysfs /sys\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;sysfs&amp;quot;, &amp;quot;/sys&amp;quot;, &amp;quot;sysfs&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
   printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
   printk(&amp;quot;Mount sysfs successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* process kernel command line */&lt;br /&gt;
 fd = open(&amp;quot;/proc/cmdline&amp;quot;, O_RDONLY);&lt;br /&gt;
 if( fd == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Cannot open /proc/cmdline: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 /* note, on /proc fs:&lt;br /&gt;
  *       lseek likely always returns error&lt;br /&gt;
  *       stat likely always returns st_size = 0&lt;br /&gt;
  *   so determining size of /proc file means just reading it;&lt;br /&gt;
  *   you have to read /proc files according to their documented&lt;br /&gt;
  *   maximum sizes; this is probably for performance reasons */&lt;br /&gt;
 cmdline_size = read(fd, cmdline, 4095);&lt;br /&gt;
 if( cmdline_size == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Failed to read /proc/cmdline: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 close(fd);&lt;br /&gt;
&lt;br /&gt;
 /* cmdline may be newline + null terminated, but make it null + null */&lt;br /&gt;
 cmdline[cmdline_size] = '\0';&lt;br /&gt;
 if( cmdline[cmdline_size-1] == '\n' ) {&lt;br /&gt;
   cmdline[cmdline_size-1] = '\0';&lt;br /&gt;
   cmdline_size--;&lt;br /&gt;
   cmdline_end = cmdline + cmdline_size;&lt;br /&gt;
 }&lt;br /&gt;
 printk(&amp;quot;Kernel cmdline size: %i\n&amp;quot;, cmdline_size);&lt;br /&gt;
 printk(&amp;quot;Kernel cmdline: \&amp;quot;%s\&amp;quot;\n&amp;quot;, cmdline);&lt;br /&gt;
&lt;br /&gt;
 /* find v and v_end of values in cmdline */&lt;br /&gt;
 for( i=iroot; i&amp;lt;ilastparam; i++ ) {&lt;br /&gt;
   param[i].v = strstr(cmdline, param[i].n);&lt;br /&gt;
   if( param[i].v != NULL ) {&lt;br /&gt;
     param[i].src = PARAM_SRC_CMDLINE;&lt;br /&gt;
     while( *(param[i].v) != '=' ) param[i].v++;&lt;br /&gt;
     param[i].v++;&lt;br /&gt;
     temp_end = param[i].v;&lt;br /&gt;
     while( !( (*temp_end == ' ') ||&lt;br /&gt;
               (*temp_end == '\n') ||&lt;br /&gt;
               (temp_end == cmdline_end)&lt;br /&gt;
	     ) ) temp_end++;&lt;br /&gt;
     if( temp_end == param[i].v ) {&lt;br /&gt;
       printk(&amp;quot;Kernel parameter %s: value missing.\n&amp;quot;, param[i].n);&lt;br /&gt;
       param[i].v = NULL;&lt;br /&gt;
     } else param[i].v_end = temp_end;&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 for( i=iroot; i&amp;lt;ilastparam; i++ ) {&lt;br /&gt;
   /* terminate value strings */&lt;br /&gt;
   if( param[i].v_end != NULL ) *(param[i].v_end) = '\0';&lt;br /&gt;
   /* set defaults if no value on cmdline */&lt;br /&gt;
   if( param[i].v == NULL ) {&lt;br /&gt;
     param[i].src = PARAM_SRC_DEFAULT;&lt;br /&gt;
     if( param[i].req == PARAM_REQ_YES ) flag_param_missing = 1;&lt;br /&gt;
     switch(i) {&lt;br /&gt;
       case iroot      : param[i].v = &amp;quot;&amp;lt;missing required param&amp;gt;&amp;quot; ; break;&lt;br /&gt;
       case irootfstype: param[i].v = &amp;quot;&amp;lt;missing required param&amp;gt;&amp;quot; ; break;&lt;br /&gt;
       case imountopt  : param[i].v = &amp;quot;ro&amp;quot;        ; break;&lt;br /&gt;
       case iinit      : param[i].v = &amp;quot;/sbin/init&amp;quot;; break;&lt;br /&gt;
       case irunlevel  : param[i].v = &amp;quot;3&amp;quot;         ; break;&lt;br /&gt;
       case iconsole   : param[i].v = &amp;quot;console&amp;quot;   ; break;&lt;br /&gt;
       default         : param[i].v = NULL;&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
   if(param[i].src == PARAM_SRC_DEFAULT) src_msg = &amp;quot;default&amp;quot;;&lt;br /&gt;
   else src_msg = &amp;quot;cmdline&amp;quot;;&lt;br /&gt;
   printk(&amp;quot;Using %s \&amp;quot;%s\&amp;quot; (source: %s)\n&amp;quot;, param[i].n, param[i].v, src_msg);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 if( flag_param_missing ) {&lt;br /&gt;
   printk(&amp;quot;Aborting boot process: missing required kernel parameter(s).\n&amp;quot;);&lt;br /&gt;
   return EX_USAGE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* generic nv pair kernel cmdline processing finished&lt;br /&gt;
  *  now, examine specific params for defaults and correctness */&lt;br /&gt;
&lt;br /&gt;
 /* param[irootfstype]: can be checked against /proc/filesystems: */&lt;br /&gt;
 fd = open(&amp;quot;/proc/filesystems&amp;quot;, O_RDONLY);&lt;br /&gt;
 if( fd == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Cannot open /proc/filesystems: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 miscproc_size = read(fd, miscproc_buff, 4095);&lt;br /&gt;
 if( miscproc_size == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Failed to read /proc/filesystems: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 close(fd);&lt;br /&gt;
 if( strstr(miscproc_buff, param[irootfstype].v) == NULL ) {&lt;br /&gt;
   printk(&amp;quot;%s \&amp;quot;%s\&amp;quot;: filesystem type not available.\n&amp;quot;, param[irootfstype].n, param[irootfstype].v);&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* zfs-specific */&lt;br /&gt;
 if( strcmp(param[irootfstype].v, &amp;quot;zfs&amp;quot;) == 0 ) {&lt;br /&gt;
   if( access(&amp;quot;/etc/zfs/zpool.cache&amp;quot;, F_OK) == 0 )&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/zfs/zpool.cache is present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
   else&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/zfs/zpool.cache not present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
&lt;br /&gt;
   if( access(&amp;quot;/etc/hostid&amp;quot;, F_OK) == 0 )&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/hostid is present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
   else&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/hostid not present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
   /* zpool import */&lt;br /&gt;
   if( (param[izpool_import_name].v != NULL) || (param[izpool_import_guid].v != NULL) ) {&lt;br /&gt;
	printk(&amp;quot;zpool_import: import requested.\n&amp;quot;);&lt;br /&gt;
	if( (param[izpool_import_name].v != NULL) &amp;amp;&amp;amp; (param[izpool_import_guid].v != NULL) ) {&lt;br /&gt;
		printk(&amp;quot;zpool_import: given both pool name and guid; using guid.\n&amp;quot;);&lt;br /&gt;
		param[izpool_import_name].v = NULL;&lt;br /&gt;
	}&lt;br /&gt;
	if( param[izpool_import_name].v != NULL )&lt;br /&gt;
		printk(&amp;quot;zpool_import: pool name: %s\n&amp;quot;, param[izpool_import_name].v );&lt;br /&gt;
	else&lt;br /&gt;
		printk(&amp;quot;zpool_import: pool guid: %s\n&amp;quot;, param[izpool_import_guid].v );&lt;br /&gt;
&lt;br /&gt;
	iargs.path = NULL;&lt;br /&gt;
	iargs.paths = 0;&lt;br /&gt;
	iargs.poolname = param[izpool_import_name].v;&lt;br /&gt;
	if( param[izpool_import_guid].v != NULL )&lt;br /&gt;
		iargs.guid = strtoull(param[izpool_import_guid].v, NULL, 10);&lt;br /&gt;
	else&lt;br /&gt;
		iargs.guid = 0;&lt;br /&gt;
	iargs.cachefile = NULL;&lt;br /&gt;
	if( (param[izpool_import_force].v != NULL) &amp;amp;&amp;amp; (strcmp(param[izpool_import_force].v, &amp;quot;1&amp;quot;) == 0) ) {&lt;br /&gt;
		iargs.can_be_active = 1;&lt;br /&gt;
		printk(&amp;quot;zpool_import: import forced.\n&amp;quot;);&lt;br /&gt;
	} else {&lt;br /&gt;
		iargs.can_be_active = 0;&lt;br /&gt;
		printk(&amp;quot;zpool_import: import not forced.\n&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
	iargs.unique = 1;&lt;br /&gt;
	iargs.exists = 1;&lt;br /&gt;
&lt;br /&gt;
	printk(&amp;quot;zpool_import: init libzfs.\n&amp;quot;);&lt;br /&gt;
	libzfs = libzfs_init();&lt;br /&gt;
	printk(&amp;quot;zpool_import: searching for pool.\n&amp;quot;);&lt;br /&gt;
	pools = zpool_search_import(libzfs, &amp;amp;iargs);&lt;br /&gt;
	if( (pools == NULL) || nvlist_empty(pools) )&lt;br /&gt;
		printk(&amp;quot;zpool_import: pool not available for import, or already imported by cachefile.\n&amp;quot;);&lt;br /&gt;
	else {&lt;br /&gt;
		printk(&amp;quot;zpool_import: getting pool information.\n&amp;quot;);&lt;br /&gt;
		pool = nvlist_next_nvpair(pools, pool);&lt;br /&gt;
		printk(&amp;quot;zpool_import: getting pool configuration.\n&amp;quot;);&lt;br /&gt;
		nvpair_value_nvlist(pool, &amp;amp;config);&lt;br /&gt;
		printk(&amp;quot;zpool_import: attempting pool import.\n&amp;quot;);&lt;br /&gt;
		if( zpool_import(libzfs, config, param[izpool_import_newname].v, NULL) != 0 ) {&lt;br /&gt;
			printk(&amp;quot;zpool_import: import failed.\n&amp;quot;);&lt;br /&gt;
			printk(&amp;quot;zpool_import: error description: %s\n&amp;quot;, libzfs_error_description(libzfs) );&lt;br /&gt;
			printk(&amp;quot;zpool_import: error action: %s\n&amp;quot;, libzfs_error_action(libzfs) );&lt;br /&gt;
		} else  printk(&amp;quot;zpool_import: import successful.\n&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
	printk(&amp;quot;zpool_import: fini libzfs.\n&amp;quot;);&lt;br /&gt;
	libzfs_fini(libzfs);&lt;br /&gt;
   }&lt;br /&gt;
#endif /* zpool_import */&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 if(      strcmp(param[imountopt].v, &amp;quot;ro&amp;quot;) == 0 ) mountflags = MS_RDONLY;&lt;br /&gt;
 else if( strcmp(param[imountopt].v, &amp;quot;rw&amp;quot;) == 0 ) mountflags = 0;&lt;br /&gt;
 else {&lt;br /&gt;
   printk(&amp;quot;%s \&amp;quot;%s\&amp;quot;: invalid parameter value; defaulting to \&amp;quot;ro\&amp;quot;.\n&amp;quot;, param[imountopt].n, param[imountopt].v);&lt;br /&gt;
   mountflags = MS_RDONLY;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* param[iroot]: nothing to check; if user gives bad root=device then mount fails */&lt;br /&gt;
&lt;br /&gt;
 /* try to mount root=device at /mnt&lt;br /&gt;
  *&lt;br /&gt;
  * note: for zfs, if a copy of /etc/zfs/zpool.cache (when pool is imported) is put in initramfs-source, then&lt;br /&gt;
  * the zfs module can read it and automatically import the pools described in the cache file; the imported&lt;br /&gt;
  * pools can be available to mount here if they were created using standard device names, otherwise&lt;br /&gt;
  * udevd may be required to run before mounting the pool */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount -t %s -o %s %s /mnt.\n&amp;quot;, param[irootfstype].v, param[imountopt].v, param[iroot].v);&lt;br /&gt;
 if( mount(param[iroot].v, &amp;quot;/mnt&amp;quot;, param[irootfstype].v, mountflags, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 printk(&amp;quot;%s mounted successfully.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
&lt;br /&gt;
 /* check to see if the mounted root filesystem has an executable init program */&lt;br /&gt;
 chdir(&amp;quot;/mnt&amp;quot;);&lt;br /&gt;
 if( access(param[iinit].v+1, X_OK) != 0 ) {&lt;br /&gt;
   chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
   printk(&amp;quot;access X_OK: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   printk(&amp;quot;The init program /mnt/%s is not present or not executable.\n&amp;quot;, param[iinit].v+1);&lt;br /&gt;
   printk(&amp;quot;Aborting boot process: no init program.\n&amp;quot;);&lt;br /&gt;
   printk(&amp;quot;Unmounting %s.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
   if( umount(&amp;quot;/mnt&amp;quot;) == -1 ) {&lt;br /&gt;
     printk(&amp;quot;umount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
     printk(&amp;quot;Failed to umount %s.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
   } else printk(&amp;quot;Successfully unmounted %s.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
 printk(&amp;quot;Init program /mnt/%s is present and executable.\n&amp;quot;, param[iinit].v+1);&lt;br /&gt;
&lt;br /&gt;
 /* switch the root / from initramfs to the mounted new root device at /mnt.&lt;br /&gt;
  *&lt;br /&gt;
  * note: after this switch, it is not possible to access the initramfs files anymore,&lt;br /&gt;
  * yet they consume ram memory unless they are deleted here before switching.&lt;br /&gt;
  * Any programs that are run after clearing the initramfs and switching root must exist on the new root.&lt;br /&gt;
  * This program may safely delete itself (/init) since it is already in ram and executing.&lt;br /&gt;
  * If you have installed additional files and programs in initramfs that consume significant ram,&lt;br /&gt;
  * then you need to insert additional code here to delete those files (carefully). */&lt;br /&gt;
&lt;br /&gt;
 /* delete files off of initramfs to free ram memory */&lt;br /&gt;
 printk(&amp;quot;Freeing memory from initramfs...\n&amp;quot;);&lt;br /&gt;
 if( unlink(argv[0]) != 0 ) printk(&amp;quot;unlink %s: %s\n&amp;quot;, argv[0], strerror(errno));&lt;br /&gt;
 else printk(&amp;quot;%s %s&amp;quot;, argv[0], &amp;quot;deleted from initramfs.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 /* switch root */&lt;br /&gt;
 printk(&amp;quot;Beginning switch root procedure.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(1) Attempting cmd: mount --move /dev /mnt/dev \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/dev&amp;quot;, &amp;quot;/mnt/dev&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(2) Attempting cmd: mount --move /proc /mnt/proc \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/proc&amp;quot;, &amp;quot;/mnt/proc&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(3) Attempting cmd: mount --move /sys /mnt/sys \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/sys&amp;quot;, &amp;quot;/mnt/sys&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(4) Attempting cmd: chdir /mnt \n&amp;quot;);&lt;br /&gt;
 if( chdir(&amp;quot;/mnt&amp;quot;) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: chdir: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(5) Attempting cmd: mount --move . / \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;.&amp;quot;, &amp;quot;/&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(6) Attempting cmd: chroot . \n&amp;quot;);&lt;br /&gt;
 if( chroot(&amp;quot;.&amp;quot;) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: chroot: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(7) Attempting cmd: chdir / \n&amp;quot;);&lt;br /&gt;
 if( chdir(&amp;quot;/&amp;quot;) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: chdir: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 printk(&amp;quot;Completed switch root procedure.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 /* check for &amp;quot;console=&amp;quot; kernel parameter and switch&lt;br /&gt;
  *  stdin, stdout, and stderr to named console device&lt;br /&gt;
  */&lt;br /&gt;
 if( param[iconsole].src == PARAM_SRC_CMDLINE ) {&lt;br /&gt;
   printk(&amp;quot;Console redirection to device %s requested.\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
   /* expect only basename of console device (e.g., ttyS0), so chdir /dev */&lt;br /&gt;
   chdir(&amp;quot;/dev&amp;quot;);&lt;br /&gt;
   if( access(param[iconsole].v, F_OK ) == 0 ) {&lt;br /&gt;
     printk(&amp;quot;Opening stdin, stdout, and stderr on %s.\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
     close(0);&lt;br /&gt;
     open(param[iconsole].v, O_RDWR);&lt;br /&gt;
     dup2(0, 1);&lt;br /&gt;
     dup2(0, 2);&lt;br /&gt;
   } else {&lt;br /&gt;
     printk(&amp;quot;access F_OK: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
     printk(&amp;quot;Could not access device: %s!\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
     printk(&amp;quot;Console redirection to device %s aborted!\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
   }&lt;br /&gt;
   chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;Execing: \&amp;quot;%s %s\&amp;quot; to boot mounted root system.\n&amp;quot;, param[iinit].v, param[irunlevel].v);&lt;br /&gt;
&lt;br /&gt;
 /* free resources held to this point */&lt;br /&gt;
 free(cmdline);&lt;br /&gt;
 free(miscproc_buff);&lt;br /&gt;
&lt;br /&gt;
 if( execl(param[iinit].v, param[irunlevel].v, (char *) NULL ) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: execl: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If foobarz-init is updated, you can find the latest version at [https://github.com/foobarz/foobarz-init github].&lt;br /&gt;
&lt;br /&gt;
The foobarz-init program can be compiled two ways as of v1.1.1. First, the simpler compile that does not support zpool_import but does support importing pools using a /etc/zfs/zpool.cache file in the initramfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gcc --static init.c -o init&lt;br /&gt;
strip init&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The second way to compile it adds support for zpool_import so that you do not have to include a &amp;lt;code&amp;gt;/etc/zfs/zpool.cache&amp;lt;/code&amp;gt; file in the initramfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gcc -static -DINCLUDE_ZPOOL_IMPORT \&lt;br /&gt;
     foobarz-init.c -include /usr/src/zfs-0.6.0-rc10/3.2.28/zfs_config.h \&lt;br /&gt;
    -o init \&lt;br /&gt;
    -I /usr/include/libspl -I /usr/include/libzfs \&lt;br /&gt;
    -lzfs -lnvpair -lzpool -luutil -luuid -lrt -lz -lm -lpthread \&lt;br /&gt;
    -I /usr/include/tirpc \&lt;br /&gt;
    -ltirpc&lt;br /&gt;
strip init&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Note: the zpool_import support requires that you install [http://sourceforge.net/projects/libtirpc/ libtirpc] first.&lt;br /&gt;
&lt;br /&gt;
Read the foobarz-init source code to see how it uses kernel parameters. The params &amp;lt;code&amp;gt;root&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;rootfstype&amp;lt;/code&amp;gt; are always required to tell init what root pool name to mount and the filesystem type (e.g. zfs).&lt;br /&gt;
&lt;br /&gt;
For the zpool_import support: &amp;lt;code&amp;gt;zpool_import_name=poolname&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;zpool_import_guid=&amp;lt;guid of a pool&amp;gt;&amp;lt;/code&amp;gt; tells what pool to import. You can also import the pool with a new different name by also using &amp;lt;code&amp;gt;zpool_import_newname=newpoolname&amp;lt;/code&amp;gt;. If the import is not working, &amp;lt;code&amp;gt;zpool_import_force=1&amp;lt;/code&amp;gt; can be used to force import even if ZFS thinks the pool may be in use by another system.&lt;br /&gt;
&lt;br /&gt;
However you import the pool, either using zpool.cache or zpool_import support, the kernel param &amp;lt;code&amp;gt;root=&amp;lt;your poolname or newpoolname&amp;gt;&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;rootfstype=zfs&amp;lt;/code&amp;gt; needs to be given also. The zpool_import only imports, it does not say what to mount. What to mount is still told using root= and rootfstype=.&lt;br /&gt;
&lt;br /&gt;
Now copy the compiled static program into the initramfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp init /boot/initramfs-source/init&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Build and install kernel:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make -j8&lt;br /&gt;
make -j8 modules_install&lt;br /&gt;
cp arch/x86/boot/bzImage /boot/vm3.2.27b&lt;br /&gt;
cp System.map /boot/System.map-vm3.2.27b&lt;br /&gt;
# add new lilo menu entry for vm3.2.27b kernel&lt;br /&gt;
vi /etc/lilo.conf&lt;br /&gt;
  image = /boot/vm3.2.27b&lt;br /&gt;
   label = vm3.2.27b&lt;br /&gt;
   addappend = &amp;quot; spl.spl_hostid=0x007f0100 zfs.spa_config_path=/etc/zfs/zpool.cache root=zfs-root rootfstype=zfs&amp;quot;&lt;br /&gt;
lilo&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Congrats! If this works, you can select the &amp;quot;vm3.2.27b&amp;quot; lilo entry to boot. If you are using the zpool_import support in the init program, you need to add at least the &amp;lt;code&amp;gt;zpool_import_name=zfs-root&amp;lt;/code&amp;gt; param to the addappend line in lilo.conf.&lt;br /&gt;
&lt;br /&gt;
Notes on kernel params (lilo append and addappend lines): root= and rootfstype= are used by both foorbarz-init and mkinitrd. The &amp;quot;ro&amp;quot; param is not used by foobarz-init, so instead use: mountopt=ro|rw. See &amp;quot;modinfo spl&amp;quot; and &amp;quot;modinfo zfs&amp;quot; to see all of the options those modules can take on the kernel command line. Notice the &amp;lt;code&amp;gt;spl.spl_hostid=0x007f0100&amp;lt;/code&amp;gt; param that works around the hostid mismatch problem while trying to import a pool; this param and hostname/ip set to use local loopback 127.0.0.1 in etc/hosts etc/HOSTNAME in initramfs will work most of the time, and if not the pool import needs to be forced.&lt;br /&gt;
&lt;br /&gt;
Notes on the spl and zfs packages to install: &amp;lt;i&amp;gt;If&amp;lt;/i&amp;gt; you have errors using zfs and zpool commands on booted system with builtin modules, then upgrade/switch to the 0.6.0rc10_3.2.27b builds, or you can make a custom package with the binaries renamed like zpoolb, zfsb etc for builtin.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
Using qemu's -nographic serial console (/usr/share/qemu/sgabios.bin): If you have a boot problem, you might want to run in qemu's -nographic console mode:&lt;br /&gt;
&lt;br /&gt;
First, edit /etc/inittab, and uncomment the line for local serial ports runlevel &amp;quot;s1&amp;quot; (ttyS0) for serial console login support. This is done in the guest (host does not need this):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Local serial lines:&lt;br /&gt;
s1:12345:respawn:/sbin/agetty -L ttyS0 38400 linux&lt;br /&gt;
#s1:12345:respawn:/sbin/agetty -L ttyS0 9600 vt100&lt;br /&gt;
#s2:12345:respawn:/sbin/agetty -L ttyS1 9600 vt100&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Second, edit /etc/securetty, and uncomment ttyS0 line:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ttyS0&lt;br /&gt;
#ttyS1&lt;br /&gt;
# ...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
You cannot login on ttyS0 without this change even though you get the login prompt!&lt;br /&gt;
&lt;br /&gt;
Then, run qemu such as:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
qemu-kvm &amp;lt;all regular options&amp;gt; -nographic -option-rom sgabios.bin,bootindex=0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Wait for the lilo prompt, it may take several seconds show up in this mode.&lt;br /&gt;
&lt;br /&gt;
In the lilo menu, select your kernel image with builtin spl/zfs, and use kernel params such as:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
boot: vm3.2.27b console=ttyS0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
At the lilo prompt, use kernel parameter: console=ttyS0 (do NOT say /dev/ttS0). Passing runlevel=s1 does not appear to be necessary.&lt;br /&gt;
&lt;br /&gt;
When you are in qemu's serial mode, the interface is a little different than in the normal graphical mode: use keypresses:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ctrl-a h    # for help&lt;br /&gt;
ctrl-a c    # toggle access to (QEMU) console / back to emulation&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If you cannot get a login: prompt, try ctrl-a c, then do (QEMU) sendkey ctrl-alt-delete. This will reboot cleanly back to lilo, then you can do (QEMU) quit.&lt;br /&gt;
&lt;br /&gt;
Once you login to the guest, the terminal size needs adjustment. On your host, in another xterm sized the same as your guest console terminal, get the size of the terminal:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo $LINES&lt;br /&gt;
echo $COLUMNS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Now, back in the guest terminal of same size:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export LINES &amp;lt;lines&amp;gt;&lt;br /&gt;
export COLUMNS &amp;lt;columns&amp;gt;&lt;br /&gt;
stty cols $COLUMNS rows $LINES&lt;br /&gt;
exec bash&lt;br /&gt;
reset&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
So, you set the environment variables and also set them with stty. Then, restart bash (exec, or else it is a child shell process).&lt;br /&gt;
&lt;br /&gt;
BECAREFUL not to start qemu twice on the same ZFS guest! Two simultaneous running qemu on the same ZFS will corrupt the pool and it will NOT recover - you lose your whole installation! Before running qemu, check ps -A, look for an already running qemu process incase it somehow entered into the background!&lt;br /&gt;
&lt;br /&gt;
BECAREFUL when using -nographic ttyS0 that you are not doing commands on the HOST! Only use -nographic to see kernel problems. Use regular console if booting is working normally.&lt;br /&gt;
&lt;br /&gt;
To use the qemu -drive if=scsi option, the linux module sym53c8xx should be loaded in the guest. You may need to use the qemu option:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-option-rom 8xx_64.rom,bootindex=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The file 8xx_64.rom used to be inside qemu, but in new versions it is missing. You can download it:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
wget http://www.lsi.com/downloads/Public/Host%20Bus%20Adapters/Host%20Bus%20Adapters%20Common%20Files/lsi_bios.zip&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Extract the zip and place 8xx_64.rom in /usr/share/qemu/.&lt;br /&gt;
&lt;br /&gt;
Good luck!&lt;/div&gt;</description>
			<pubDate>Wed, 12 Sep 2012 07:24:49 GMT</pubDate>
			<dc:creator>Foobarz</dc:creator>
			<comments>https://www.slackwiki.com/Talk:ZFS_root_(builtin)</comments>
		</item>
		<item>
			<title>ZFS root (builtin)</title>
			<link>https://www.slackwiki.com/index.php?title=ZFS_root_(builtin)&amp;diff=787</link>
			<guid isPermaLink="false">https://www.slackwiki.com/index.php?title=ZFS_root_(builtin)&amp;diff=787</guid>
			<description>&lt;p&gt;Foobarz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Tutorials]]&lt;br /&gt;
The first [http://slackwiki.com/ZFS_root &amp;quot;ZFS root&amp;quot;] wiki explains the details of running ZFS at your root filesystem by using a fully modular generic kernel approach. Now, I can share how it can be done with the SPL and ZFS modules built into the kernel. This procedure is just an example and can use some fine tuning, but here goes:&lt;br /&gt;
&lt;br /&gt;
The steps below are to create kernel with SPL and ZFS modules builtin. This kernel will be installed as an alternatve kernel to boot in lilo, and it will have a separate kernel installation from the fully modular and working system kernel. This will allow testing the builtin kernel while able to boot back onto a working modular ZFS system. We start this procedure assuming you are on a working fully modular ZFS install as in the &amp;quot;ZFS root&amp;quot; wiki.&lt;br /&gt;
&lt;br /&gt;
Use mountpoint=legacy so that zfs will not expect &amp;lt;code&amp;gt;zfs mount&amp;lt;/code&amp;gt;, but instead expect standard &amp;lt;code&amp;gt;mount&amp;lt;/code&amp;gt; for mounting zfs-root:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=legacy zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Edit &amp;lt;code&amp;gt;/etc/rc.d/rc.S&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;rc.6&amp;lt;/code&amp;gt; to use regular &amp;lt;code&amp;gt;mount&amp;lt;/code&amp;gt; commands, remove &amp;lt;code&amp;gt;zfs&amp;lt;/code&amp;gt; commands. Edit &amp;lt;code&amp;gt;rc.6&amp;lt;/code&amp;gt; and remove or comment out &amp;lt;code&amp;gt;zfs export&amp;lt;/code&amp;gt; command. These edits undo changes made in the &amp;quot;ZFS root&amp;quot; wiki, but it shows the two different ways of mounting a zfs filesystem.&lt;br /&gt;
&lt;br /&gt;
You &amp;lt;i&amp;gt;might&amp;lt;/i&amp;gt; think to set &amp;lt;code&amp;gt;bootfs&amp;lt;/code&amp;gt; property like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool set bootfs=zfs-root zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
However, this will result in ZFS placing many restrictions on zfs-root as per how that option is used on Solaris systems:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; zfs-root must be VTOC (SMI) label, not GPT (EFI) label&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; zfs-root can only contain 1 vdev: either a plain disk, or a mirror&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
So, do &amp;lt;b&amp;gt;NOT&amp;lt;/b&amp;gt; set that property! If &amp;lt;code&amp;gt;bootfs&amp;lt;/code&amp;gt; is set, you would find that you cannot add vdevs to your zfs-root. If it is set already, then unset it like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool set bootfs= zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Make a directory to store files to be inside the initramfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkdir /boot/initramfs-source&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This directory will hold some files for the initial rootfs inside the kernel. Your &amp;lt;code&amp;gt;/boot&amp;lt;/code&amp;gt; should be on a small ext4 partition or on a mounted USB stick that you use to boot.&lt;br /&gt;
&lt;br /&gt;
Extract the slackware kernel-source package to obtain a copy of the kernel source, and make an initial kernel config for it:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir src&lt;br /&gt;
cd src&lt;br /&gt;
tar xvzf /mnt/cdrom/slackware64/k/kernel-source-*.txz&lt;br /&gt;
mv usr/src/linux-3.2.27 /usr/src/linux-3.2.27b&lt;br /&gt;
rm -r install&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make menuconfig&lt;br /&gt;
  General setup-&amp;gt;Local version - append to kernel release = b&lt;br /&gt;
  General setup-&amp;gt;Default hostname                         = slackzfs&lt;br /&gt;
  General setup-&amp;gt;Initramfs source files(s)                = /boot/initramfs-source&lt;br /&gt;
  Device Drivers-&amp;gt;SCSI device support-&amp;gt;SCSI low-level drivers-&amp;gt; &amp;lt;*&amp;gt; SYM53C8XX Version 2 SCSI support&lt;br /&gt;
  File systems -&amp;gt; &amp;lt;*&amp;gt; The Extended 4 (ext4) filesystem&lt;br /&gt;
  # build in any hard drive controllers and filesystems that you need for booting&lt;br /&gt;
  # then save the config&lt;br /&gt;
make prepare scripts&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The kernel source has been set to have a &amp;quot;Local version&amp;quot; &amp;lt;code&amp;gt;b&amp;lt;/code&amp;gt;. This will result in modules installed to &amp;lt;code&amp;gt;/lib/modules/3.2.27b&amp;lt;/code&amp;gt; and keeps this kernel's source and modules seperate from slackware's kernel-generic package installation. The &amp;lt;code&amp;gt;make prepare scripts&amp;lt;/code&amp;gt; command readies the kernel source as needed before we can install a copy of spl and zfs modules into the kernel source tree.&lt;br /&gt;
&lt;br /&gt;
Now proceed to configure and copy spl and zfs into the kernel source tree:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd ~/src&lt;br /&gt;
tar xvzf ~/spl-0.6.0-rc10.tar.gz&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-0.6.0-rc10&lt;br /&gt;
./configure \&lt;br /&gt;
    --prefix=/ \&lt;br /&gt;
    --libdir=/lib64 \&lt;br /&gt;
    --includedir=/usr/include \&lt;br /&gt;
    --datarootdir=/usr/share \&lt;br /&gt;
    --enable-linux-builtin=yes \&lt;br /&gt;
    --with-linux=/usr/src/linux-3.2.27b \&lt;br /&gt;
    --with-linux-obj=/usr/src/linux-3.2.27b&lt;br /&gt;
wget https://raw.github.com/zfsonlinux/spl/master/copy-builtin&lt;br /&gt;
chmod +x copy-builtin&lt;br /&gt;
./copy-builtin /usr/src/linux-3.2.27b&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../spl-0.6.0rc10_3.2.27b-x86_64-1root.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
&lt;br /&gt;
tar xvzf ~/zfs-0.6.0-rc10.tar.gz&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-0.6.0-rc10&lt;br /&gt;
./configure \&lt;br /&gt;
    --prefix=/ \&lt;br /&gt;
    --libdir=/lib64 \&lt;br /&gt;
    --includedir=/usr/include \&lt;br /&gt;
    --datarootdir=/usr/share \&lt;br /&gt;
    --enable-linux-builtin=yes \&lt;br /&gt;
    --with-linux=/usr/src/linux-3.2.27b \&lt;br /&gt;
    --with-linux-obj=/usr/src/linux-3.2.27b \&lt;br /&gt;
    --with-spl=/root/src/spl-0.6.0-rc10&lt;br /&gt;
wget https://raw.github.com/zfsonlinux/zfs/master/copy-builtin&lt;br /&gt;
chmod +x copy-builtin&lt;br /&gt;
./copy-builtin /usr/src/linux-3.2.27b&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../zfs-0.6.0rc10_3.2.27b-x86_64-1root.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
At this point, the &amp;lt;code&amp;gt;copy-builtin&amp;lt;/code&amp;gt; scripts have installed the configured spl and zfs modules source into the kernel source. The regular &amp;lt;code&amp;gt;make menuconfig&amp;lt;/code&amp;gt; in the kernel source should now show options for spl and zfs in the kernel config.&lt;br /&gt;
&lt;br /&gt;
As of this writing, the copy-builtin script places the spl and zfs modules into the kernel source in places where the modules may not initialize in the best order, &amp;lt;i&amp;gt;after&amp;lt;/i&amp;gt; all lower-level storage drivers are initialized. If spl and zfs initialize too soon, there is a chance they may not be able to see all of the storage devices. The order of initialization (as seen in dmesg) of modules that are builtin to the kernel is the order that the modules are linked into the kernel during kernel compilation. The order of link depends on where the module source files are located in the kernel source tree. To ensure that spl and zfs will initialize after all hardware drivers, we move them into the &amp;lt;code&amp;gt;drivers&amp;lt;/code&amp;gt; tree and after all other drivers:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
mkdir drivers/zfsonlinux&lt;br /&gt;
mv spl drivers/zfsonlinux&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  # remove references to spl&lt;br /&gt;
vi Makefile&lt;br /&gt;
  # remove references to spl&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/fs&lt;br /&gt;
mv zfs ../drivers/zfsonlinux&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  # remove references to zfs&lt;br /&gt;
vi Makefile&lt;br /&gt;
  # remove references to zfs&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  )# add line at end of menu, before &amp;quot;endmenu&amp;quot;:&lt;br /&gt;
  )source &amp;quot;drivers/zfsonlinux/Kconfig&amp;quot;&lt;br /&gt;
  )endmenu&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers&lt;br /&gt;
vi Makefile&lt;br /&gt;
  )# add line at very end of file:&lt;br /&gt;
  )obj-$(CONFIG_ZFSONLINUX) += zfsonlinux/&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers/zfsonlinux&lt;br /&gt;
cat &amp;gt; Kconfig &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
menuconfig ZFSONLINUX&lt;br /&gt;
	tristate &amp;quot;ZFSonLinux support&amp;quot;&lt;br /&gt;
&lt;br /&gt;
if ZFSONLINUX&lt;br /&gt;
&lt;br /&gt;
source &amp;quot;drivers/zfsonlinux/spl/Kconifg&amp;quot;&lt;br /&gt;
&lt;br /&gt;
source &amp;quot;drivers/zfsonlinux/zfs/Kconifg&amp;quot;&lt;br /&gt;
&lt;br /&gt;
endif&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/zfsonlinux&lt;br /&gt;
cat &amp;gt; Makefile &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
obj-$(CONFIG_SPL) += spl/&lt;br /&gt;
obj-$(CONFIG_ZFS) += zfs/&lt;br /&gt;
EOF&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This completes the move of the spl and zfs modules in the kernel source tree to be under &amp;lt;code&amp;gt;drivers/zfsonlinux&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Now, in kernel configuration, you can build in the modules as follows:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make menuconfig&lt;br /&gt;
   Device Drivers -&amp;gt;&lt;br /&gt;
    &amp;lt;*&amp;gt; ZFSonLinux support -&amp;gt;&lt;br /&gt;
      &amp;lt;*&amp;gt; Solaris Porting Layer (SPL)&lt;br /&gt;
      &amp;lt;*&amp;gt;     ZFS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the kernel config, we set &amp;lt;code&amp;gt;/boot/initramfs-source&amp;lt;/code&amp;gt; as source location of the contents to be linked into kernel's builtin initramfs (rootfs). Now, we create some files that are needed to be in the initramfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /boot/initramfs-source&lt;br /&gt;
&lt;br /&gt;
# make standard directories&lt;br /&gt;
mkdir -p proc dev sys mnt bin sbin etc/zfs&lt;br /&gt;
&lt;br /&gt;
# zfs seems to want mtab present, even if empty&lt;br /&gt;
touch etc/mtab&lt;br /&gt;
&lt;br /&gt;
# if zpool.cache file can be read by zfs at module init, it imports the pools in the cache&lt;br /&gt;
cp /etc/zfs/zpool.cache-initrd etc/zfs/zpool.cache&lt;br /&gt;
&lt;br /&gt;
# make initial console device node; otherwise, there is a problem at startup:&lt;br /&gt;
# &amp;quot;Warning: unable to open an initial console&amp;quot; and you'd have problems with console and tty login&lt;br /&gt;
# making these nodes from within /init is not early enough to avoid problem&lt;br /&gt;
mknod dev/console c 5 1   # system console&lt;br /&gt;
&lt;br /&gt;
# make memory device kmsg to &amp;quot;printk&amp;quot; kernel messages&lt;br /&gt;
# we can write to this file to send out messages&lt;br /&gt;
mknod dev/kmsg    c 1 11  # lines printed to kmsg enter kernel messages buffer&lt;br /&gt;
&lt;br /&gt;
# recommended loop0 device to mount fs images&lt;br /&gt;
mknod dev/loop0   b 7 0&lt;br /&gt;
&lt;br /&gt;
# make initial virtual terminal devices&lt;br /&gt;
mknod dev/tty     c 5 0   # current tty&lt;br /&gt;
mknod dev/tty0    c 4 0   # current virtual term&lt;br /&gt;
mknod dev/tty1    c 4 1   # login virtual term 1 (F1)&lt;br /&gt;
&lt;br /&gt;
# make alternative console=ttyS0 standard 8250/16550 UART serial port devices&lt;br /&gt;
#   useful with kernel parameter console=ttyS0&lt;br /&gt;
#          with qemu -nographic -option-rom sgabios.bin,bootindex=0&lt;br /&gt;
mknod dev/ttyS0   c 4 64  # COM1&lt;br /&gt;
mknod dev/ttyS1   c 4 65  # COM2&lt;br /&gt;
mknod dev/ttyS2   c 4 66  # COM3&lt;br /&gt;
mknod dev/ttyS3   c 4 67  $ COM4&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This should be enough device nodes initially in the initramfs. Once devtmpfs mounts over /dev inside initramfs, a lot more devices are available in it by default.&lt;br /&gt;
&lt;br /&gt;
The initramfs needs an &amp;lt;code&amp;gt;/init&amp;lt;/code&amp;gt; program that will be run automatically by the kernel as process id 1, the first program to run on the system. This program's task is to mount a root filesystem, switch it to be the new root (/), and then exec the init (&amp;lt;code&amp;gt;/sbin/init&amp;lt;/code&amp;gt;) program that is on the new root so that the new root system is booted.&lt;br /&gt;
&lt;br /&gt;
The common way to make /init is using busybox with files like these in /boot/initrd-tree or /boot/initramfs-source:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
bin/busybox&lt;br /&gt;
bin/ash -&amp;gt; busybox&lt;br /&gt;
bin/sh -&amp;gt; busybox&lt;br /&gt;
# run busybox to see what other &amp;quot;applets&amp;quot; can be symlinked to it&lt;br /&gt;
# when busybox is run as a different symlinked applet name, it runs as the applet&lt;br /&gt;
init&lt;br /&gt;
# init can be an ash script, see slackware's /boot/initrd-tree/init for example&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For example, as an ash script, slackware's init does the following:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;parse kernel parameters passed into it and set variables based on them&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;start udevd and trigger rules for block devices to setup initial /dev devices&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;load kernel modules and keyboard map&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;run mdadm, cryptsetup, lvm, zpool/zfs to setup more devices&lt;br /&gt;
     (any udev rules for them should do more /dev setup in the background)&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;mount the root filesystem read-only at /mnt&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;stat /mnt/sbin/init, and if not executable run a rescue shell /bin/sh&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;shutdown udevd so it can be restarted by root system when booted&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;mount --move {proc,sys,run,dev} to under /mnt&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;run: exec switch_root /mnt /sbin/init $RUNLEVEL&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The slackware mkinitrd package is a fully configured BusyBox installation that makes an external initramfs image file, initrd.gz, that is passed to the kernel by the bootloader (lilo). It could be changed to be internal to the kernel by just using initrd-tree as the CONFIG_INITRAMFS_SOURCE in the kernel config and removing initrd in the lilo.conf.&lt;br /&gt;
&lt;br /&gt;
The main purpose of most initramfs/initrd is to load and configure kernel modules and devices needed to mount a root filesystem. Because the spl/zfs modules are builtin, there isn't really a lot that needs to be done by an initramfs. What remains to be done is import the zfs-root pool, mount it, and exec the system /sbin/init. The kernel's &amp;quot;legacy&amp;quot; parameters &amp;lt;code&amp;gt;root=&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;rootfstype=&amp;lt;/code&amp;gt; that are able to directly boot a root disk do not work with ZFS at this time because ZFS pools always need to be imported before it is possible to mount and boot on them. The automatic import that ZFS can do by using a cachefile (/etc/zfs/zpool.cache) stored in initramfs still does not work with the legacy boot parameters because at an eariler stage of the boot process, the kernel ignores a rootfs that does not contain an &amp;lt;/code&amp;gt;/init&amp;lt;/code&amp;gt; program, and/or the device type of an imported pool is not the device types recognized by the legacy boot as valid root devices.&lt;br /&gt;
&lt;br /&gt;
You could just continue to use slackware's mkinitrd package as in the &amp;quot;ZFS root&amp;quot; wiki and it works the same whether the modules are builtin or not. But, by building the spl/zfs modules in, aren't we really wanting to get rid of using the mkinitrd/initrd.gz? We'd like to have a kernel with everything in it to boot, and use a simple lilo image entry that has no initrd.&lt;br /&gt;
&lt;br /&gt;
We can do this, and not use the mkinitrd package, but we still need to finish our own initramfs &amp;lt;code&amp;gt;/init&amp;lt;/code&amp;gt; program to import, mount, switch root, and boot. Save the following c program to &amp;quot;foobarz-init.c&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/* software product name: foobarz-init.c&lt;br /&gt;
 * suggested binary name: /init (in initramfs-source, rootfs)&lt;br /&gt;
 * license              : BSD&lt;br /&gt;
 * license text:&lt;br /&gt;
Copyright (c) 2012, foobarz&lt;br /&gt;
All rights reserved.&lt;br /&gt;
&lt;br /&gt;
Redistribution and use in source and binary forms, with or without&lt;br /&gt;
modification, are permitted provided that the following conditions are met:&lt;br /&gt;
    * Redistributions of source code must retain the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer.&lt;br /&gt;
    * Redistributions in binary form must reproduce the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer in the&lt;br /&gt;
      documentation and/or other materials provided with the distribution.&lt;br /&gt;
    * Neither the name of the &amp;lt;organization&amp;gt; nor the&lt;br /&gt;
      names of its contributors may be used to endorse or promote products&lt;br /&gt;
      derived from this software without specific prior written permission.&lt;br /&gt;
&lt;br /&gt;
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &amp;quot;AS IS&amp;quot; AND&lt;br /&gt;
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED&lt;br /&gt;
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE&lt;br /&gt;
DISCLAIMED. IN NO EVENT SHALL &amp;lt;COPYRIGHT HOLDER&amp;gt; BE LIABLE FOR ANY&lt;br /&gt;
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES&lt;br /&gt;
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;&lt;br /&gt;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND&lt;br /&gt;
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT&lt;br /&gt;
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS&lt;br /&gt;
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
/* Your initramfs-source should contain the following&lt;br /&gt;
 *&lt;br /&gt;
 * cd /boot/initramfs-source&lt;br /&gt;
 * mkdir -p proc dev sys mnt bin sbin etc/zfs&lt;br /&gt;
 * touch etc/mtab&lt;br /&gt;
 * cp /etc/zfs/zpool.cache-initrd etc/zfs/zpool.cache&lt;br /&gt;
 * # zpool.cache is optional - zpool_import_ kernel params can be used instead&lt;br /&gt;
 * #  see below for details on using zpool_import&lt;br /&gt;
 * mknod dev/console c 5 1   # system console&lt;br /&gt;
 * mknod dev/kmsg    c 1 11  # lines printed to kmsg enter kernel messages buffer&lt;br /&gt;
 * mknod dev/loop0   b 7 0&lt;br /&gt;
 * mknod dev/tty     c 5 0   # current tty&lt;br /&gt;
 * mknod dev/tty0    c 4 0   # current virtual term&lt;br /&gt;
 * mknod dev/tty1    c 4 1   # login virtual term 1 (F1)&lt;br /&gt;
 * mknod dev/ttyS0   c 4 64  # COM1&lt;br /&gt;
 * mknod dev/ttyS1   c 4 65  # COM2&lt;br /&gt;
 * mknod dev/ttyS2   c 4 66  # COM3&lt;br /&gt;
 * mknod dev/ttyS3   c 4 67  $ COM4&lt;br /&gt;
 *&lt;br /&gt;
 * and this program compiled to /boot/initramfs-source/init&lt;br /&gt;
 *&lt;br /&gt;
 * Set kernel config option&lt;br /&gt;
 *  CONFIG_INITRAMFS_SOURCE=/boot/initramfs-source&lt;br /&gt;
 * to build the initramfs into your kernel image&lt;br /&gt;
 *  that also has builtin drivers (spl and zfs, etc).&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
#define FOOBARZ_INIT_VERSION &amp;quot;1.1.1&amp;quot;&lt;br /&gt;
#define _BSD_SOURCE&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdarg.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;fcntl.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/mount.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sysexits.h&amp;gt;&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
/* support for zpool import&lt;br /&gt;
 *&lt;br /&gt;
 * If -DINCLUDE_ZPOOL_IMPORT, then support to import a zpool is&lt;br /&gt;
 * enabled in the program. Enabling it will add many dependencies to the&lt;br /&gt;
 * compile and link; for example:&lt;br /&gt;
 *&lt;br /&gt;
 * gcc -static -DINCLUDE_ZPOOL_IMPORT \&lt;br /&gt;
 *    foobarz-init.c -include /usr/src/zfs-0.6.0-rc10/3.2.28/zfs_config.h \&lt;br /&gt;
 *   -o init \&lt;br /&gt;
 *   -I /usr/include/libspl -I /usr/include/libzfs \&lt;br /&gt;
 *   -lzfs -lnvpair -lzpool -luutil -luuid -lrt -lz -lm -lpthread \&lt;br /&gt;
 *   -I /usr/include/tirpc \&lt;br /&gt;
 *   -ltirpc&lt;br /&gt;
 *&lt;br /&gt;
 * Note that libtirpc is a drop-in replacement for the SunRPC functions that&lt;br /&gt;
 * used to be in glibc. No additional includes are needed, just the gcc -I and -l&lt;br /&gt;
 * options for tirpc.&lt;br /&gt;
 *&lt;br /&gt;
 * Otherwise, with -UINCLUDE_ZPOOL_IMPORT, the compile is just:&lt;br /&gt;
 * gcc -static foobarz-init.c -o init&lt;br /&gt;
 */&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
#include &amp;lt;libzfs.h&amp;gt;&lt;br /&gt;
#else&lt;br /&gt;
#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/stat.h&amp;gt;&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#define PARAM_REQ_NO 0&lt;br /&gt;
#define PARAM_REQ_YES 1&lt;br /&gt;
#define PARAM_SRC_DEFAULT 0&lt;br /&gt;
#define PARAM_SRC_CMDLINE 1&lt;br /&gt;
&lt;br /&gt;
void printk(char *fmt, ...) {&lt;br /&gt;
  FILE* f;&lt;br /&gt;
  int fd;&lt;br /&gt;
  va_list args;&lt;br /&gt;
&lt;br /&gt;
  f = fopen(&amp;quot;/dev/kmsg&amp;quot;, &amp;quot;w&amp;quot;);&lt;br /&gt;
  va_start(args, fmt);&lt;br /&gt;
  vfprintf(f, fmt, args);&lt;br /&gt;
  va_end(args);&lt;br /&gt;
  fflush(f);&lt;br /&gt;
  fclose(f);&lt;br /&gt;
  /* avoid flooding kmsg and having msgs suppressed; 20msgs/sec */&lt;br /&gt;
  usleep(50000);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[]) {&lt;br /&gt;
 /*** variables */&lt;br /&gt;
&lt;br /&gt;
 int i;&lt;br /&gt;
 int   fd = 0; /* file descriptor */&lt;br /&gt;
 unsigned long mountflags;&lt;br /&gt;
&lt;br /&gt;
 /* kernel command line */&lt;br /&gt;
 off_t cmdline_size;&lt;br /&gt;
 char* cmdline; /* to be malloc 4096B */&lt;br /&gt;
 char* cmdline_end;&lt;br /&gt;
 char* temp_end;&lt;br /&gt;
 char* src_msg; /* default or cmdline */&lt;br /&gt;
 int flag_param_missing = 0;&lt;br /&gt;
&lt;br /&gt;
 /* use to hold contents of a misc /proc/&amp;lt;file&amp;gt; */&lt;br /&gt;
 char* miscproc_buff; /* to be malloc 4096B */&lt;br /&gt;
 off_t miscproc_size;&lt;br /&gt;
&lt;br /&gt;
 /* note about environ, argv, and kernel cmdline for init:&lt;br /&gt;
  *   environ is not defined for init&lt;br /&gt;
  *   only argv[0] is set for init&lt;br /&gt;
  *   kernel command line parameters are accessed&lt;br /&gt;
  *   at /proc/cmdline&lt;br /&gt;
  */&lt;br /&gt;
&lt;br /&gt;
 /* kernel parameters expected to be name=value */&lt;br /&gt;
 /* do not use quotes or spaces in parameters   */&lt;br /&gt;
 /* you can add more params somwhere after root= */&lt;br /&gt;
 struct nv { char* n; char* v; char* v_end; int req; int src; };&lt;br /&gt;
 struct nv param[] = {&lt;br /&gt;
   { &amp;quot;root=&amp;quot;,       NULL, NULL, PARAM_REQ_YES, PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;rootfstype=&amp;quot;, NULL, NULL, PARAM_REQ_YES, PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;mountopt=&amp;quot;,   NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;init=&amp;quot;,       NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;runlevel=&amp;quot;,   NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;console=&amp;quot;,    NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT }&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
   ,&lt;br /&gt;
   { &amp;quot;zpool_import_name=&amp;quot;,    NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;zpool_import_guid=&amp;quot;,    NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;zpool_import_newname=&amp;quot;, NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;zpool_import_force=&amp;quot;,   NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT }&lt;br /&gt;
#endif&lt;br /&gt;
 };&lt;br /&gt;
 enum {&lt;br /&gt;
	 iroot,&lt;br /&gt;
	 irootfstype,&lt;br /&gt;
	 imountopt,&lt;br /&gt;
	 iinit,&lt;br /&gt;
	 irunlevel,&lt;br /&gt;
	 iconsole,&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
	 izpool_import_name,&lt;br /&gt;
	 izpool_import_guid,&lt;br /&gt;
	 izpool_import_newname,&lt;br /&gt;
	 izpool_import_force,&lt;br /&gt;
#endif&lt;br /&gt;
	 ilastparam&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
 libzfs_handle_t* libzfs = NULL;&lt;br /&gt;
 importargs_t iargs = { 0 };&lt;br /&gt;
 nvlist_t* pools = NULL;&lt;br /&gt;
 nvpair_t* pool = NULL;&lt;br /&gt;
 nvlist_t* config = NULL;&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
 /*** program */&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;foobarz-init, version %s: booting initramfs.\n&amp;quot;, FOOBARZ_INIT_VERSION);&lt;br /&gt;
&lt;br /&gt;
 cmdline       = (char*) malloc(4096);&lt;br /&gt;
 miscproc_buff = (char*) malloc(4096);&lt;br /&gt;
 if( (cmdline == NULL) || (miscproc_buff == NULL) ) {&lt;br /&gt;
   printk(&amp;quot;Unable to allocate buffer memory: malloc: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount proc /proc&lt;br /&gt;
  *  note: some /dev devices symlink into /proc&lt;br /&gt;
  *  proc contains info about processes, including cmdline etc. */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount proc /proc\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;proc&amp;quot;, &amp;quot;/proc&amp;quot;, &amp;quot;proc&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
   printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
   printk(&amp;quot;Mount proc successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount devtmpfs /dev&lt;br /&gt;
  *  note: This simple init program works if your root device is made from devices&lt;br /&gt;
  *  that are available by default in devtmpfs, such as /dev/sd*&lt;br /&gt;
  *&lt;br /&gt;
  *  For zfs, your root zfs pool should be created with default device nodes and&lt;br /&gt;
  *  then it should be mountable by this simple init program.&lt;br /&gt;
  *&lt;br /&gt;
  *  udev may be needed to configure device nodes and symlinks required&lt;br /&gt;
  *  to access a root device configuration made with such nodes and symlinks.&lt;br /&gt;
  *  If you need udevd, you can include it into your initramfs-source and&lt;br /&gt;
  *  modify this program to run it before attempting to mount your root device.&lt;br /&gt;
  *  However, if udevd is needed, a significant number of userspace programs may also be&lt;br /&gt;
  *  required by rules in /lib/udev/. You could install busybox + udev (about 5MB) or&lt;br /&gt;
  *  coreutils + util-linux + bash + udev (about 25MB) into initramfs-source. But, at that&lt;br /&gt;
  *  point you'd have ash or bash and many tools that are easier to use than this&lt;br /&gt;
  *  simple init program; it would then be easy to have /init as #!/bin/&amp;lt;b&amp;gt;ash script. */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount devtmpfs /dev\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;devtmpfs&amp;quot;, &amp;quot;/dev&amp;quot;, &amp;quot;devtmpfs&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
   printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
   printk(&amp;quot;Mount devtmpfs successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount sysfs /sys&lt;br /&gt;
  *  note: some kernel modules try to access /sys with userspace helpers to echo values into /sys variables;&lt;br /&gt;
  *  such modules expect a minimal userspace that contains coreutils or busybox */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount sysfs /sys\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;sysfs&amp;quot;, &amp;quot;/sys&amp;quot;, &amp;quot;sysfs&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
   printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
   printk(&amp;quot;Mount sysfs successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* process kernel command line */&lt;br /&gt;
 fd = open(&amp;quot;/proc/cmdline&amp;quot;, O_RDONLY);&lt;br /&gt;
 if( fd == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Cannot open /proc/cmdline: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 /* note, on /proc fs:&lt;br /&gt;
  *       lseek likely always returns error&lt;br /&gt;
  *       stat likely always returns st_size = 0&lt;br /&gt;
  *   so determining size of /proc file means just reading it;&lt;br /&gt;
  *   you have to read /proc files according to their documented&lt;br /&gt;
  *   maximum sizes; this is probably for performance reasons */&lt;br /&gt;
 cmdline_size = read(fd, cmdline, 4095);&lt;br /&gt;
 if( cmdline_size == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Failed to read /proc/cmdline: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 close(fd);&lt;br /&gt;
&lt;br /&gt;
 /* cmdline may be newline + null terminated, but make it null + null */&lt;br /&gt;
 cmdline[cmdline_size] = '\0';&lt;br /&gt;
 if( cmdline[cmdline_size-1] == '\n' ) {&lt;br /&gt;
   cmdline[cmdline_size-1] = '\0';&lt;br /&gt;
   cmdline_size--;&lt;br /&gt;
   cmdline_end = cmdline + cmdline_size;&lt;br /&gt;
 }&lt;br /&gt;
 printk(&amp;quot;Kernel cmdline size: %i\n&amp;quot;, cmdline_size);&lt;br /&gt;
 printk(&amp;quot;Kernel cmdline: \&amp;quot;%s\&amp;quot;\n&amp;quot;, cmdline);&lt;br /&gt;
&lt;br /&gt;
 /* find v and v_end of values in cmdline */&lt;br /&gt;
 for( i=iroot; i&amp;lt;ilastparam; i++ ) {&lt;br /&gt;
   param[i].v = strstr(cmdline, param[i].n);&lt;br /&gt;
   if( param[i].v != NULL ) {&lt;br /&gt;
     param[i].src = PARAM_SRC_CMDLINE;&lt;br /&gt;
     while( *(param[i].v) != '=' ) param[i].v++;&lt;br /&gt;
     param[i].v++;&lt;br /&gt;
     temp_end = param[i].v;&lt;br /&gt;
     while( !( (*temp_end == ' ') ||&lt;br /&gt;
               (*temp_end == '\n') ||&lt;br /&gt;
               (temp_end == cmdline_end)&lt;br /&gt;
	     ) ) temp_end++;&lt;br /&gt;
     if( temp_end == param[i].v ) {&lt;br /&gt;
       printk(&amp;quot;Kernel parameter %s: value missing.\n&amp;quot;, param[i].n);&lt;br /&gt;
       param[i].v = NULL;&lt;br /&gt;
     } else param[i].v_end = temp_end;&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 for( i=iroot; i&amp;lt;ilastparam; i++ ) {&lt;br /&gt;
   /* terminate value strings */&lt;br /&gt;
   if( param[i].v_end != NULL ) *(param[i].v_end) = '\0';&lt;br /&gt;
   /* set defaults if no value on cmdline */&lt;br /&gt;
   if( param[i].v == NULL ) {&lt;br /&gt;
     param[i].src = PARAM_SRC_DEFAULT;&lt;br /&gt;
     if( param[i].req == PARAM_REQ_YES ) flag_param_missing = 1;&lt;br /&gt;
     switch(i) {&lt;br /&gt;
       case iroot      : param[i].v = &amp;quot;&amp;lt;missing required param&amp;gt;&amp;quot; ; break;&lt;br /&gt;
       case irootfstype: param[i].v = &amp;quot;&amp;lt;missing required param&amp;gt;&amp;quot; ; break;&lt;br /&gt;
       case imountopt  : param[i].v = &amp;quot;ro&amp;quot;        ; break;&lt;br /&gt;
       case iinit      : param[i].v = &amp;quot;/sbin/init&amp;quot;; break;&lt;br /&gt;
       case irunlevel  : param[i].v = &amp;quot;3&amp;quot;         ; break;&lt;br /&gt;
       case iconsole   : param[i].v = &amp;quot;console&amp;quot;   ; break;&lt;br /&gt;
       default         : param[i].v = NULL;&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
   if(param[i].src == PARAM_SRC_DEFAULT) src_msg = &amp;quot;default&amp;quot;;&lt;br /&gt;
   else src_msg = &amp;quot;cmdline&amp;quot;;&lt;br /&gt;
   printk(&amp;quot;Using %s \&amp;quot;%s\&amp;quot; (source: %s)\n&amp;quot;, param[i].n, param[i].v, src_msg);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 if( flag_param_missing ) {&lt;br /&gt;
   printk(&amp;quot;Aborting boot process: missing required kernel parameter(s).\n&amp;quot;);&lt;br /&gt;
   return EX_USAGE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* generic nv pair kernel cmdline processing finished&lt;br /&gt;
  *  now, examine specific params for defaults and correctness */&lt;br /&gt;
&lt;br /&gt;
 /* param[irootfstype]: can be checked against /proc/filesystems: */&lt;br /&gt;
 fd = open(&amp;quot;/proc/filesystems&amp;quot;, O_RDONLY);&lt;br /&gt;
 if( fd == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Cannot open /proc/filesystems: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 miscproc_size = read(fd, miscproc_buff, 4095);&lt;br /&gt;
 if( miscproc_size == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Failed to read /proc/filesystems: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 close(fd);&lt;br /&gt;
 if( strstr(miscproc_buff, param[irootfstype].v) == NULL ) {&lt;br /&gt;
   printk(&amp;quot;%s \&amp;quot;%s\&amp;quot;: filesystem type not available.\n&amp;quot;, param[irootfstype].n, param[irootfstype].v);&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* zfs-specific */&lt;br /&gt;
 if( strcmp(param[irootfstype].v, &amp;quot;zfs&amp;quot;) == 0 ) {&lt;br /&gt;
   if( access(&amp;quot;/etc/zfs/zpool.cache&amp;quot;, F_OK) == 0 )&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/zfs/zpool.cache is present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
   else&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/zfs/zpool.cache not present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
&lt;br /&gt;
   if( access(&amp;quot;/etc/hostid&amp;quot;, F_OK) == 0 )&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/hostid is present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
   else&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/hostid not present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
   /* zpool import */&lt;br /&gt;
   if( (param[izpool_import_name].v != NULL) || (param[izpool_import_guid].v != NULL) ) {&lt;br /&gt;
	printk(&amp;quot;zpool_import: import requested.\n&amp;quot;);&lt;br /&gt;
	if( (param[izpool_import_name].v != NULL) &amp;amp;&amp;amp; (param[izpool_import_guid].v != NULL) ) {&lt;br /&gt;
		printk(&amp;quot;zpool_import: given both pool name and guid; using guid.\n&amp;quot;);&lt;br /&gt;
		param[izpool_import_name].v = NULL;&lt;br /&gt;
	}&lt;br /&gt;
	if( param[izpool_import_name].v != NULL )&lt;br /&gt;
		printk(&amp;quot;zpool_import: pool name: %s\n&amp;quot;, param[izpool_import_name].v );&lt;br /&gt;
	else&lt;br /&gt;
		printk(&amp;quot;zpool_import: pool guid: %s\n&amp;quot;, param[izpool_import_guid].v );&lt;br /&gt;
&lt;br /&gt;
	iargs.path = NULL;&lt;br /&gt;
	iargs.paths = 0;&lt;br /&gt;
	iargs.poolname = param[izpool_import_name].v;&lt;br /&gt;
	if( param[izpool_import_guid].v != NULL )&lt;br /&gt;
		iargs.guid = strtoull(param[izpool_import_guid].v, NULL, 10);&lt;br /&gt;
	else&lt;br /&gt;
		iargs.guid = 0;&lt;br /&gt;
	iargs.cachefile = NULL;&lt;br /&gt;
	if( (param[izpool_import_force].v != NULL) &amp;amp;&amp;amp; (strcmp(param[izpool_import_force].v, &amp;quot;1&amp;quot;) == 0) ) {&lt;br /&gt;
		iargs.can_be_active = 1;&lt;br /&gt;
		printk(&amp;quot;zpool_import: import forced.\n&amp;quot;);&lt;br /&gt;
	} else {&lt;br /&gt;
		iargs.can_be_active = 0;&lt;br /&gt;
		printk(&amp;quot;zpool_import: import not forced.\n&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
	iargs.unique = 1;&lt;br /&gt;
	iargs.exists = 1;&lt;br /&gt;
&lt;br /&gt;
	printk(&amp;quot;zpool_import: init libzfs.\n&amp;quot;);&lt;br /&gt;
	libzfs = libzfs_init();&lt;br /&gt;
	printk(&amp;quot;zpool_import: searching for pool.\n&amp;quot;);&lt;br /&gt;
	pools = zpool_search_import(libzfs, &amp;amp;iargs);&lt;br /&gt;
	if( (pools == NULL) || nvlist_empty(pools) )&lt;br /&gt;
		printk(&amp;quot;zpool_import: pool not available for import, or already imported by cachefile.\n&amp;quot;);&lt;br /&gt;
	else {&lt;br /&gt;
		printk(&amp;quot;zpool_import: getting pool information.\n&amp;quot;);&lt;br /&gt;
		pool = nvlist_next_nvpair(pools, pool);&lt;br /&gt;
		printk(&amp;quot;zpool_import: getting pool configuration.\n&amp;quot;);&lt;br /&gt;
		nvpair_value_nvlist(pool, &amp;amp;config);&lt;br /&gt;
		printk(&amp;quot;zpool_import: attempting pool import.\n&amp;quot;);&lt;br /&gt;
		if( zpool_import(libzfs, config, param[izpool_import_newname].v, NULL) != 0 ) {&lt;br /&gt;
			printk(&amp;quot;zpool_import: import failed.\n&amp;quot;);&lt;br /&gt;
			printk(&amp;quot;zpool_import: error description: %s\n&amp;quot;, libzfs_error_description(libzfs) );&lt;br /&gt;
			printk(&amp;quot;zpool_import: error action: %s\n&amp;quot;, libzfs_error_action(libzfs) );&lt;br /&gt;
		} else  printk(&amp;quot;zpool_import: import successful.\n&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
	printk(&amp;quot;zpool_import: fini libzfs.\n&amp;quot;);&lt;br /&gt;
	libzfs_fini(libzfs);&lt;br /&gt;
   }&lt;br /&gt;
#endif /* zpool_import */&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 if(      strcmp(param[imountopt].v, &amp;quot;ro&amp;quot;) == 0 ) mountflags = MS_RDONLY;&lt;br /&gt;
 else if( strcmp(param[imountopt].v, &amp;quot;rw&amp;quot;) == 0 ) mountflags = 0;&lt;br /&gt;
 else {&lt;br /&gt;
   printk(&amp;quot;%s \&amp;quot;%s\&amp;quot;: invalid parameter value; defaulting to \&amp;quot;ro\&amp;quot;.\n&amp;quot;, param[imountopt].n, param[imountopt].v);&lt;br /&gt;
   mountflags = MS_RDONLY;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* param[iroot]: nothing to check; if user gives bad root=device then mount fails */&lt;br /&gt;
&lt;br /&gt;
 /* try to mount root=device at /mnt&lt;br /&gt;
  *&lt;br /&gt;
  * note: for zfs, if a copy of /etc/zfs/zpool.cache (when pool is imported) is put in initramfs-source, then&lt;br /&gt;
  * the zfs module can read it and automatically import the pools described in the cache file; the imported&lt;br /&gt;
  * pools can be available to mount here if they were created using standard device names, otherwise&lt;br /&gt;
  * udevd may be required to run before mounting the pool */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount -t %s -o %s %s /mnt.\n&amp;quot;, param[irootfstype].v, param[imountopt].v, param[iroot].v);&lt;br /&gt;
 if( mount(param[iroot].v, &amp;quot;/mnt&amp;quot;, param[irootfstype].v, mountflags, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 printk(&amp;quot;%s mounted successfully.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
&lt;br /&gt;
 /* check to see if the mounted root filesystem has an executable init program */&lt;br /&gt;
 chdir(&amp;quot;/mnt&amp;quot;);&lt;br /&gt;
 if( access(param[iinit].v+1, X_OK) != 0 ) {&lt;br /&gt;
   chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
   printk(&amp;quot;access X_OK: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   printk(&amp;quot;The init program /mnt/%s is not present or not executable.\n&amp;quot;, param[iinit].v+1);&lt;br /&gt;
   printk(&amp;quot;Aborting boot process: no init program.\n&amp;quot;);&lt;br /&gt;
   printk(&amp;quot;Unmounting %s.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
   if( umount(&amp;quot;/mnt&amp;quot;) == -1 ) {&lt;br /&gt;
     printk(&amp;quot;umount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
     printk(&amp;quot;Failed to umount %s.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
   } else printk(&amp;quot;Successfully unmounted %s.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
 printk(&amp;quot;Init program /mnt/%s is present and executable.\n&amp;quot;, param[iinit].v+1);&lt;br /&gt;
&lt;br /&gt;
 /* switch the root / from initramfs to the mounted new root device at /mnt.&lt;br /&gt;
  *&lt;br /&gt;
  * note: after this switch, it is not possible to access the initramfs files anymore,&lt;br /&gt;
  * yet they consume ram memory unless they are deleted here before switching.&lt;br /&gt;
  * Any programs that are run after clearing the initramfs and switching root must exist on the new root.&lt;br /&gt;
  * This program may safely delete itself (/init) since it is already in ram and executing.&lt;br /&gt;
  * If you have installed additional files and programs in initramfs that consume significant ram,&lt;br /&gt;
  * then you need to insert additional code here to delete those files (carefully). */&lt;br /&gt;
&lt;br /&gt;
 /* delete files off of initramfs to free ram memory */&lt;br /&gt;
 printk(&amp;quot;Freeing memory from initramfs...\n&amp;quot;);&lt;br /&gt;
 if( unlink(argv[0]) != 0 ) printk(&amp;quot;unlink %s: %s\n&amp;quot;, argv[0], strerror(errno));&lt;br /&gt;
 else printk(&amp;quot;%s %s&amp;quot;, argv[0], &amp;quot;deleted from initramfs.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 /* switch root */&lt;br /&gt;
 printk(&amp;quot;Beginning switch root procedure.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(1) Attempting cmd: mount --move /dev /mnt/dev \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/dev&amp;quot;, &amp;quot;/mnt/dev&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(2) Attempting cmd: mount --move /proc /mnt/proc \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/proc&amp;quot;, &amp;quot;/mnt/proc&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(3) Attempting cmd: mount --move /sys /mnt/sys \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/sys&amp;quot;, &amp;quot;/mnt/sys&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(4) Attempting cmd: chdir /mnt \n&amp;quot;);&lt;br /&gt;
 if( chdir(&amp;quot;/mnt&amp;quot;) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: chdir: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(5) Attempting cmd: mount --move . / \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;.&amp;quot;, &amp;quot;/&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(6) Attempting cmd: chroot . \n&amp;quot;);&lt;br /&gt;
 if( chroot(&amp;quot;.&amp;quot;) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: chroot: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(7) Attempting cmd: chdir / \n&amp;quot;);&lt;br /&gt;
 if( chdir(&amp;quot;/&amp;quot;) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: chdir: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 printk(&amp;quot;Completed switch root procedure.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 /* check for &amp;quot;console=&amp;quot; kernel parameter and switch&lt;br /&gt;
  *  stdin, stdout, and stderr to named console device&lt;br /&gt;
  */&lt;br /&gt;
 if( param[iconsole].src == PARAM_SRC_CMDLINE ) {&lt;br /&gt;
   printk(&amp;quot;Console redirection to device %s requested.\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
   /* expect only basename of console device (e.g., ttyS0), so chdir /dev */&lt;br /&gt;
   chdir(&amp;quot;/dev&amp;quot;);&lt;br /&gt;
   if( access(param[iconsole].v, F_OK ) == 0 ) {&lt;br /&gt;
     printk(&amp;quot;Opening stdin, stdout, and stderr on %s.\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
     close(0);&lt;br /&gt;
     open(param[iconsole].v, O_RDWR);&lt;br /&gt;
     dup2(0, 1);&lt;br /&gt;
     dup2(0, 2);&lt;br /&gt;
   } else {&lt;br /&gt;
     printk(&amp;quot;access F_OK: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
     printk(&amp;quot;Could not access device: %s!\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
     printk(&amp;quot;Console redirection to device %s aborted!\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
   }&lt;br /&gt;
   chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;Execing: \&amp;quot;%s %s\&amp;quot; to boot mounted root system.\n&amp;quot;, param[iinit].v, param[irunlevel].v);&lt;br /&gt;
&lt;br /&gt;
 /* free resources held to this point */&lt;br /&gt;
 free(cmdline);&lt;br /&gt;
 free(miscproc_buff);&lt;br /&gt;
&lt;br /&gt;
 if( execl(param[iinit].v, param[irunlevel].v, (char *) NULL ) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: execl: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If foobarz-init is updated, you can find the latest version at [https://github.com/foobarz/foobarz-init github].&lt;br /&gt;
&lt;br /&gt;
The foobarz-init program can be compiled two ways as of v1.1.1. First, the simpler compile that does not support zpool_import but does support importing pools using a /etc/zfs/zpool.cache file in the initramfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gcc --static init.c -o init&lt;br /&gt;
strip init&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The second way to compile it adds support for zpool_import so that you do not have to include a &amp;lt;code&amp;gt;/etc/zfs/zpool.cache&amp;lt;/code&amp;gt; file in the initramfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gcc -static -DINCLUDE_ZPOOL_IMPORT \&lt;br /&gt;
     foobarz-init.c -include /usr/src/zfs-0.6.0-rc10/3.2.28/zfs_config.h \&lt;br /&gt;
    -o init \&lt;br /&gt;
    -I /usr/include/libspl -I /usr/include/libzfs \&lt;br /&gt;
    -lzfs -lnvpair -lzpool -luutil -luuid -lrt -lz -lm -lpthread \&lt;br /&gt;
    -I /usr/include/tirpc \&lt;br /&gt;
    -ltirpc&lt;br /&gt;
strip init&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Note: the zpool_import support requires that you install [http://sourceforge.net/projects/libtirpc/ libtirpc] first.&lt;br /&gt;
&lt;br /&gt;
Read the foobarz-init source code to see how it uses kernel parameters. The params &amp;lt;code&amp;gt;root&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;rootfstype&amp;lt;/code&amp;gt; are always required to tell init what root pool name to mount and the filesystem type (e.g. zfs).&lt;br /&gt;
&lt;br /&gt;
For the zpool_import support: &amp;lt;code&amp;gt;zpool_import_name=poolname&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;zpool_import_guid=&amp;lt;guid of a pool&amp;gt;&amp;lt;/code&amp;gt; tells what pool to import. You can also import the pool with a new different name by also using &amp;lt;code&amp;gt;zpool_import_newname=newpoolname&amp;lt;/code&amp;gt;. If the import is not working, &amp;lt;code&amp;gt;zpool_import_force=1&amp;lt;/code&amp;gt; can be used to force import even if ZFS thinks the pool may be in use by another system.&lt;br /&gt;
&lt;br /&gt;
However you import the pool, either using zpool.cache or zpool_import support, the kernel param &amp;lt;code&amp;gt;root=&amp;lt;your poolname or newpoolname&amp;gt;&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;rootfstype=zfs&amp;lt;/code&amp;gt; needs to be given also. The zpool_import only imports, it does not say what to mount. What to mount is still told using root= and rootfstype=.&lt;br /&gt;
&lt;br /&gt;
Now copy the compiled static program into the initramfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp init /boot/initramfs-source/init&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Build and install kernel:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make -j8&lt;br /&gt;
make -j8 modules_install&lt;br /&gt;
cp arch/x86/boot/bzImage /boot/vm3.2.27b&lt;br /&gt;
cp System.map /boot/System.map-vm3.2.27b&lt;br /&gt;
# add new lilo menu entry for vm3.2.27b kernel&lt;br /&gt;
vi /etc/lilo.conf&lt;br /&gt;
  image = /boot/vm3.2.27b&lt;br /&gt;
   label = vm3.2.27b&lt;br /&gt;
   addappend = &amp;quot; spl.spl_hostid=0x007f0100 zfs.spa_config_path=/etc/zfs/zpool.cache root=zfs-root rootfstype=zfs&amp;quot;&lt;br /&gt;
lilo&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Congrats! If this works, you can select the &amp;quot;vm3.2.27b&amp;quot; lilo entry to boot. If you are using the zpool_import support in the init program, you need to add at least the &amp;lt;code&amp;gt;zpool_import_name=zfs-root&amp;lt;/code&amp;gt; param to the addappend line in lilo.conf.&lt;br /&gt;
&lt;br /&gt;
Notes on kernel params (lilo append and addappend lines): root= and rootfstype= are used by both foorbarz-init and mkinitrd. The &amp;quot;ro&amp;quot; param is not used by foobarz-init, so instead use: mountopt=ro|rw. See &amp;quot;modinfo spl&amp;quot; and &amp;quot;modinfo zfs&amp;quot; to see all of the options those modules can take on the kernel command line. Notice the &amp;lt;code&amp;gt;spl.spl_hostid=0x007f0100&amp;lt;/code&amp;gt; param that works around the hostid mismatch problem while trying to import a pool; this param and hostname/ip set to use local loopback 127.0.0.1 in etc/hosts etc/HOSTNAME in initramfs will work most of the time, and if not the pool import needs to be forced.&lt;br /&gt;
&lt;br /&gt;
Notes on the spl and zfs packages to install: &amp;lt;i&amp;gt;If&amp;lt;/i&amp;gt; you have errors using zfs and zpool commands on booted system with builtin modules, then upgrade/switch to the 0.6.0rc10_3.2.27b builds, or you can make a custom package with the binaries renamed like zpoolb, zfsb etc for builtin.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
Using qemu's -nographic serial console (/usr/share/qemu/sgabios.bin): If you have a boot problem, you might want to run in qemu's -nographic console mode:&lt;br /&gt;
&lt;br /&gt;
First, edit /etc/inittab, and uncomment the line for local serial ports runlevel &amp;quot;s1&amp;quot; (ttyS0) for serial console login support. This is done in the guest (host does not need this):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Local serial lines:&lt;br /&gt;
s1:12345:respawn:/sbin/agetty -L ttyS0 38400 linux&lt;br /&gt;
#s1:12345:respawn:/sbin/agetty -L ttyS0 9600 vt100&lt;br /&gt;
#s2:12345:respawn:/sbin/agetty -L ttyS1 9600 vt100&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Second, edit /etc/securetty, and uncomment ttyS0 line:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ttyS0&lt;br /&gt;
#ttyS1&lt;br /&gt;
# ...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
You cannot login on ttyS0 without this change even though you get the login prompt!&lt;br /&gt;
&lt;br /&gt;
Then, run qemu such as:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
qemu-kvm &amp;lt;all regular options&amp;gt; -nographic -option-rom sgabios.bin,bootindex=0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Wait for the lilo prompt, it may take several seconds show up in this mode.&lt;br /&gt;
&lt;br /&gt;
In the lilo menu, select your kernel image with builtin spl/zfs, and use kernel params such as:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
boot: vm3.2.27b console=ttyS0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
At the lilo prompt, use kernel parameter: console=ttyS0 (do NOT say /dev/ttS0). Passing runlevel=s1 does not appear to be necessary.&lt;br /&gt;
&lt;br /&gt;
When you are in qemu's serial mode, the interface is a little different than in the normal graphical mode: use keypresses:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ctrl-a h    # for help&lt;br /&gt;
ctrl-a c    # toggle access to (QEMU) console / back to emulation&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If you cannot get a login: prompt, try ctrl-a c, then do (QEMU) sendkey ctrl-alt-delete. This will reboot cleanly back to lilo, then you can do (QEMU) quit.&lt;br /&gt;
&lt;br /&gt;
Once you login to the guest, the terminal size needs adjustment. On your host, in another xterm sized the same as your guest console terminal, get the size of the terminal:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo $LINES&lt;br /&gt;
echo $COLUMNS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Now, back in the guest terminal of same size:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export LINES &amp;lt;lines&amp;gt;&lt;br /&gt;
export COLUMNS &amp;lt;columns&amp;gt;&lt;br /&gt;
stty cols $COLUMNS rows $LINES&lt;br /&gt;
exec bash&lt;br /&gt;
reset&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
So, you set the environment variables and also set them with stty. Then, restart bash (exec, or else it is a child shell process).&lt;br /&gt;
&lt;br /&gt;
BECAREFUL not to start qemu twice on the same ZFS guest! Two simultaneous running qemu on the same ZFS will corrupt the pool and it will NOT recover - you lose your whole installation! Before running qemu, check ps -A, look for an already running qemu process incase it somehow entered into the background!&lt;br /&gt;
&lt;br /&gt;
BECAREFUL when using -nographic ttyS0 that you are not doing commands on the HOST! Only use -nographic to see kernel problems. Use regular console of booting is working normally.&lt;br /&gt;
&lt;br /&gt;
To use the qemu -drive if=scsi option, the linux module sym53c8xx should be loaded in the guest. You may need to use the qemu option:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-option-rom 8xx_64.rom,bootindex=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The file 8xx_64.rom used to be inside qemu, but in new versions it is missing. You can download it:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
wget http://www.lsi.com/downloads/Public/Host%20Bus%20Adapters/Host%20Bus%20Adapters%20Common%20Files/lsi_bios.zip&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Extract the zip and place 8xx_64.rom in /usr/share/qemu/.&lt;br /&gt;
&lt;br /&gt;
Good luck!&lt;/div&gt;</description>
			<pubDate>Wed, 12 Sep 2012 03:47:29 GMT</pubDate>
			<dc:creator>Foobarz</dc:creator>
			<comments>https://www.slackwiki.com/Talk:ZFS_root_(builtin)</comments>
		</item>
		<item>
			<title>ZFS root (builtin)</title>
			<link>https://www.slackwiki.com/index.php?title=ZFS_root_(builtin)&amp;diff=786</link>
			<guid isPermaLink="false">https://www.slackwiki.com/index.php?title=ZFS_root_(builtin)&amp;diff=786</guid>
			<description>&lt;p&gt;Foobarz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Tutorials]]&lt;br /&gt;
The first &amp;quot;ZFS root&amp;quot; wiki explains the details of running ZFS at your root filesystem by using a fully modular generic kernel approach. Now, I can share how it can be done with the SPL and ZFS modules built into the kernel. This procedure is just an example and can use some fine tuning, but here goes:&lt;br /&gt;
&lt;br /&gt;
The steps below are to create kernel with SPL and ZFS modules builtin. This kernel will be installed as an alternatve kernel to boot in lilo, and it will have a separate kernel installation from the fully modular and working system kernel. This will allow testing the builtin kernel while able to boot back onto a working modular ZFS system. We start this procedure assuming you are on a working fully modular ZFS install as in the &amp;quot;ZFS root&amp;quot; wiki.&lt;br /&gt;
&lt;br /&gt;
Use mountpoint=legacy so that zfs will not expect &amp;lt;code&amp;gt;zfs mount&amp;lt;/code&amp;gt;, but instead expect standard &amp;lt;code&amp;gt;mount&amp;lt;/code&amp;gt; for mounting zfs-root:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=legacy zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Edit &amp;lt;code&amp;gt;/etc/rc.d/rc.S&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;rc.6&amp;lt;/code&amp;gt; to use regular &amp;lt;code&amp;gt;mount&amp;lt;/code&amp;gt; commands, remove &amp;lt;code&amp;gt;zfs&amp;lt;/code&amp;gt; commands. Edit &amp;lt;code&amp;gt;rc.6&amp;lt;/code&amp;gt; and remove or comment out &amp;lt;code&amp;gt;zfs export&amp;lt;/code&amp;gt; command. These edits undo changes made in the &amp;quot;ZFS root&amp;quot; wiki, but it shows the two different ways of mounting a zfs filesystem.&lt;br /&gt;
&lt;br /&gt;
You &amp;lt;i&amp;gt;might&amp;lt;/i&amp;gt; think to set &amp;lt;code&amp;gt;bootfs&amp;lt;/code&amp;gt; property like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool set bootfs=zfs-root zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
However, this will result in ZFS placing many restrictions on zfs-root as per how that option is used on Solaris systems:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; zfs-root must be VTOC (SMI) label, not GPT (EFI) label&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; zfs-root can only contain 1 vdev: either a plain disk, or a mirror&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
So, do &amp;lt;b&amp;gt;NOT&amp;lt;/b&amp;gt; set that property! If &amp;lt;code&amp;gt;bootfs&amp;lt;/code&amp;gt; is set, you would find that you cannot add vdevs to your zfs-root. If it is set already, then unset it like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool set bootfs= zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Make a directory to store files to be inside the initramfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkdir /boot/initramfs-source&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This directory will hold some files for the initial rootfs inside the kernel. Your &amp;lt;code&amp;gt;/boot&amp;lt;/code&amp;gt; should be on a small ext4 partition or on a mounted USB stick that you use to boot.&lt;br /&gt;
&lt;br /&gt;
Extract the slackware kernel-source package to obtain a copy of the kernel source, and make an initial kernel config for it:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir src&lt;br /&gt;
cd src&lt;br /&gt;
tar xvzf /mnt/cdrom/slackware64/k/kernel-source-*.txz&lt;br /&gt;
mv usr/src/linux-3.2.27 /usr/src/linux-3.2.27b&lt;br /&gt;
rm -r install&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make menuconfig&lt;br /&gt;
  General setup-&amp;gt;Local version - append to kernel release = b&lt;br /&gt;
  General setup-&amp;gt;Default hostname                         = slackzfs&lt;br /&gt;
  General setup-&amp;gt;Initramfs source files(s)                = /boot/initramfs-source&lt;br /&gt;
  Device Drivers-&amp;gt;SCSI device support-&amp;gt;SCSI low-level drivers-&amp;gt; &amp;lt;*&amp;gt; SYM53C8XX Version 2 SCSI support&lt;br /&gt;
  File systems -&amp;gt; &amp;lt;*&amp;gt; The Extended 4 (ext4) filesystem&lt;br /&gt;
  # build in any hard drive controllers and filesystems that you need for booting&lt;br /&gt;
  # then save the config&lt;br /&gt;
make prepare scripts&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The kernel source has been set to have a &amp;quot;Local version&amp;quot; &amp;lt;code&amp;gt;b&amp;lt;/code&amp;gt;. This will result in modules installed to &amp;lt;code&amp;gt;/lib/modules/3.2.27b&amp;lt;/code&amp;gt; and keeps this kernel's source and modules seperate from slackware's kernel-generic package installation. The &amp;lt;code&amp;gt;make prepare scripts&amp;lt;/code&amp;gt; command readies the kernel source as needed before we can install a copy of spl and zfs modules into the kernel source tree.&lt;br /&gt;
&lt;br /&gt;
Now proceed to configure and copy spl and zfs into the kernel source tree:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd ~/src&lt;br /&gt;
tar xvzf ~/spl-0.6.0-rc10.tar.gz&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-0.6.0-rc10&lt;br /&gt;
./configure \&lt;br /&gt;
    --prefix=/ \&lt;br /&gt;
    --libdir=/lib64 \&lt;br /&gt;
    --includedir=/usr/include \&lt;br /&gt;
    --datarootdir=/usr/share \&lt;br /&gt;
    --enable-linux-builtin=yes \&lt;br /&gt;
    --with-linux=/usr/src/linux-3.2.27b \&lt;br /&gt;
    --with-linux-obj=/usr/src/linux-3.2.27b&lt;br /&gt;
wget https://raw.github.com/zfsonlinux/spl/master/copy-builtin&lt;br /&gt;
chmod +x copy-builtin&lt;br /&gt;
./copy-builtin /usr/src/linux-3.2.27b&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../spl-0.6.0rc10_3.2.27b-x86_64-1root.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
&lt;br /&gt;
tar xvzf ~/zfs-0.6.0-rc10.tar.gz&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-0.6.0-rc10&lt;br /&gt;
./configure \&lt;br /&gt;
    --prefix=/ \&lt;br /&gt;
    --libdir=/lib64 \&lt;br /&gt;
    --includedir=/usr/include \&lt;br /&gt;
    --datarootdir=/usr/share \&lt;br /&gt;
    --enable-linux-builtin=yes \&lt;br /&gt;
    --with-linux=/usr/src/linux-3.2.27b \&lt;br /&gt;
    --with-linux-obj=/usr/src/linux-3.2.27b \&lt;br /&gt;
    --with-spl=/root/src/spl-0.6.0-rc10&lt;br /&gt;
wget https://raw.github.com/zfsonlinux/zfs/master/copy-builtin&lt;br /&gt;
chmod +x copy-builtin&lt;br /&gt;
./copy-builtin /usr/src/linux-3.2.27b&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../zfs-0.6.0rc10_3.2.27b-x86_64-1root.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
At this point, the &amp;lt;code&amp;gt;copy-builtin&amp;lt;/code&amp;gt; scripts have installed the configured spl and zfs modules source into the kernel source. The regular &amp;lt;code&amp;gt;make menuconfig&amp;lt;/code&amp;gt; in the kernel source should now show options for spl and zfs in the kernel config.&lt;br /&gt;
&lt;br /&gt;
As of this writing, the copy-builtin script places the spl and zfs modules into the kernel source in places where the modules may not initialize in the best order, &amp;lt;i&amp;gt;after&amp;lt;/i&amp;gt; all lower-level storage drivers are initialized. If spl and zfs initialize too soon, there is a chance they may not be able to see all of the storage devices. The order of initialization (as seen in dmesg) of modules that are builtin to the kernel is the order that the modules are linked into the kernel during kernel compilation. The order of link depends on where the module source files are located in the kernel source tree. To ensure that spl and zfs will initialize after all hardware drivers, we move them into the &amp;lt;code&amp;gt;drivers&amp;lt;/code&amp;gt; tree and after all other drivers:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
mkdir drivers/zfsonlinux&lt;br /&gt;
mv spl drivers/zfsonlinux&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  # remove references to spl&lt;br /&gt;
vi Makefile&lt;br /&gt;
  # remove references to spl&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/fs&lt;br /&gt;
mv zfs ../drivers/zfsonlinux&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  # remove references to zfs&lt;br /&gt;
vi Makefile&lt;br /&gt;
  # remove references to zfs&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  )# add line at end of menu, before &amp;quot;endmenu&amp;quot;:&lt;br /&gt;
  )source &amp;quot;drivers/zfsonlinux/Kconfig&amp;quot;&lt;br /&gt;
  )endmenu&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers&lt;br /&gt;
vi Makefile&lt;br /&gt;
  )# add line at very end of file:&lt;br /&gt;
  )obj-$(CONFIG_ZFSONLINUX) += zfsonlinux/&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers/zfsonlinux&lt;br /&gt;
cat &amp;gt; Kconfig &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
menuconfig ZFSONLINUX&lt;br /&gt;
	tristate &amp;quot;ZFSonLinux support&amp;quot;&lt;br /&gt;
&lt;br /&gt;
if ZFSONLINUX&lt;br /&gt;
&lt;br /&gt;
source &amp;quot;drivers/zfsonlinux/spl/Kconifg&amp;quot;&lt;br /&gt;
&lt;br /&gt;
source &amp;quot;drivers/zfsonlinux/zfs/Kconifg&amp;quot;&lt;br /&gt;
&lt;br /&gt;
endif&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/zfsonlinux&lt;br /&gt;
cat &amp;gt; Makefile &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
obj-$(CONFIG_SPL) += spl/&lt;br /&gt;
obj-$(CONFIG_ZFS) += zfs/&lt;br /&gt;
EOF&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This completes the move of the spl and zfs modules in the kernel source tree to be under &amp;lt;code&amp;gt;drivers/zfsonlinux&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Now, in kernel configuration, you can build in the modules as follows:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make menuconfig&lt;br /&gt;
   Device Drivers -&amp;gt;&lt;br /&gt;
    &amp;lt;*&amp;gt; ZFSonLinux support -&amp;gt;&lt;br /&gt;
      &amp;lt;*&amp;gt; Solaris Porting Layer (SPL)&lt;br /&gt;
      &amp;lt;*&amp;gt;     ZFS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the kernel config, we set &amp;lt;code&amp;gt;/boot/initramfs-source&amp;lt;/code&amp;gt; as source location of the contents to be linked into kernel's builtin initramfs (rootfs). Now, we create some files that are needed to be in the initramfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /boot/initramfs-source&lt;br /&gt;
&lt;br /&gt;
# make standard directories&lt;br /&gt;
mkdir -p proc dev sys mnt bin sbin etc/zfs&lt;br /&gt;
&lt;br /&gt;
# zfs seems to want mtab present, even if empty&lt;br /&gt;
touch etc/mtab&lt;br /&gt;
&lt;br /&gt;
# if zpool.cache file can be read by zfs at module init, it imports the pools in the cache&lt;br /&gt;
cp /etc/zfs/zpool.cache-initrd etc/zfs/zpool.cache&lt;br /&gt;
&lt;br /&gt;
# make initial console device node; otherwise, there is a problem at startup:&lt;br /&gt;
# &amp;quot;Warning: unable to open an initial console&amp;quot; and you'd have problems with console and tty login&lt;br /&gt;
# making these nodes from within /init is not early enough to avoid problem&lt;br /&gt;
mknod dev/console c 5 1   # system console&lt;br /&gt;
&lt;br /&gt;
# make memory device kmsg to &amp;quot;printk&amp;quot; kernel messages&lt;br /&gt;
# we can write to this file to send out messages&lt;br /&gt;
mknod dev/kmsg    c 1 11  # lines printed to kmsg enter kernel messages buffer&lt;br /&gt;
&lt;br /&gt;
# recommended loop0 device to mount fs images&lt;br /&gt;
mknod dev/loop0   b 7 0&lt;br /&gt;
&lt;br /&gt;
# make initial virtual terminal devices&lt;br /&gt;
mknod dev/tty     c 5 0   # current tty&lt;br /&gt;
mknod dev/tty0    c 4 0   # current virtual term&lt;br /&gt;
mknod dev/tty1    c 4 1   # login virtual term 1 (F1)&lt;br /&gt;
&lt;br /&gt;
# make alternative console=ttyS0 standard 8250/16550 UART serial port devices&lt;br /&gt;
#   useful with kernel parameter console=ttyS0&lt;br /&gt;
#          with qemu -nographic -option-rom sgabios.bin,bootindex=0&lt;br /&gt;
mknod dev/ttyS0   c 4 64  # COM1&lt;br /&gt;
mknod dev/ttyS1   c 4 65  # COM2&lt;br /&gt;
mknod dev/ttyS2   c 4 66  # COM3&lt;br /&gt;
mknod dev/ttyS3   c 4 67  $ COM4&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This should be enough device nodes initially in the initramfs. Once devtmpfs mounts over /dev inside initramfs, a lot more devices are available in it by default.&lt;br /&gt;
&lt;br /&gt;
The initramfs needs an &amp;lt;code&amp;gt;/init&amp;lt;/code&amp;gt; program that will be run automatically by the kernel as process id 1, the first program to run on the system. This program's task is to mount a root filesystem, switch it to be the new root (/), and then exec the init (&amp;lt;code&amp;gt;/sbin/init&amp;lt;/code&amp;gt;) program that is on the new root so that the new root system is booted.&lt;br /&gt;
&lt;br /&gt;
The common way to make /init is using busybox with files like these in /boot/initrd-tree or /boot/initramfs-source:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
bin/busybox&lt;br /&gt;
bin/ash -&amp;gt; busybox&lt;br /&gt;
bin/sh -&amp;gt; busybox&lt;br /&gt;
# run busybox to see what other &amp;quot;applets&amp;quot; can be symlinked to it&lt;br /&gt;
# when busybox is run as a different symlinked applet name, it runs as the applet&lt;br /&gt;
init&lt;br /&gt;
# init can be an ash script, see slackware's /boot/initrd-tree/init for example&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For example, as an ash script, slackware's init does the following:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;parse kernel parameters passed into it and set variables based on them&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;start udevd and trigger rules for block devices to setup initial /dev devices&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;load kernel modules and keyboard map&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;run mdadm, cryptsetup, lvm, zpool/zfs to setup more devices&lt;br /&gt;
     (any udev rules for them should do more /dev setup in the background)&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;mount the root filesystem read-only at /mnt&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;stat /mnt/sbin/init, and if not executable run a rescue shell /bin/sh&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;shutdown udevd so it can be restarted by root system when booted&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;mount --move {proc,sys,run,dev} to under /mnt&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;run: exec switch_root /mnt /sbin/init $RUNLEVEL&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The slackware mkinitrd package is a fully configured BusyBox installation that makes an external initramfs image file, initrd.gz, that is passed to the kernel by the bootloader (lilo). It could be changed to be internal to the kernel by just using initrd-tree as the CONFIG_INITRAMFS_SOURCE in the kernel config and removing initrd in the lilo.conf.&lt;br /&gt;
&lt;br /&gt;
The main purpose of most initramfs/initrd is to load and configure kernel modules and devices needed to mount a root filesystem. Because the spl/zfs modules are builtin, there isn't really a lot that needs to be done by an initramfs. What remains to be done is import the zfs-root pool, mount it, and exec the system /sbin/init. The kernel's &amp;quot;legacy&amp;quot; parameters &amp;lt;code&amp;gt;root=&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;rootfstype=&amp;lt;/code&amp;gt; that are able to directly boot a root disk do not work with ZFS at this time because ZFS pools always need to be imported before it is possible to mount and boot on them. The automatic import that ZFS can do by using a cachefile (/etc/zfs/zpool.cache) stored in initramfs still does not work with the legacy boot parameters because at an eariler stage of the boot process, the kernel ignores a rootfs that does not contain an &amp;lt;/code&amp;gt;/init&amp;lt;/code&amp;gt; program, and/or the device type of an imported pool is not the device types recognized by the legacy boot as valid root devices.&lt;br /&gt;
&lt;br /&gt;
You could just continue to use slackware's mkinitrd package as in the &amp;quot;ZFS root&amp;quot; wiki and it works the same whether the modules are builtin or not. But, by building the spl/zfs modules in, aren't we really wanting to get rid of using the mkinitrd/initrd.gz? We'd like to have a kernel with everything in it to boot, and use a simple lilo image entry that has no initrd.&lt;br /&gt;
&lt;br /&gt;
We can do this, and not use the mkinitrd package, but we still need to finish our own initramfs &amp;lt;code&amp;gt;/init&amp;lt;/code&amp;gt; program to import, mount, switch root, and boot. Save the following c program to &amp;quot;foobarz-init.c&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/* software product name: foobarz-init.c&lt;br /&gt;
 * suggested binary name: /init (in initramfs-source, rootfs)&lt;br /&gt;
 * license              : BSD&lt;br /&gt;
 * license text:&lt;br /&gt;
Copyright (c) 2012, foobarz&lt;br /&gt;
All rights reserved.&lt;br /&gt;
&lt;br /&gt;
Redistribution and use in source and binary forms, with or without&lt;br /&gt;
modification, are permitted provided that the following conditions are met:&lt;br /&gt;
    * Redistributions of source code must retain the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer.&lt;br /&gt;
    * Redistributions in binary form must reproduce the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer in the&lt;br /&gt;
      documentation and/or other materials provided with the distribution.&lt;br /&gt;
    * Neither the name of the &amp;lt;organization&amp;gt; nor the&lt;br /&gt;
      names of its contributors may be used to endorse or promote products&lt;br /&gt;
      derived from this software without specific prior written permission.&lt;br /&gt;
&lt;br /&gt;
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &amp;quot;AS IS&amp;quot; AND&lt;br /&gt;
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED&lt;br /&gt;
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE&lt;br /&gt;
DISCLAIMED. IN NO EVENT SHALL &amp;lt;COPYRIGHT HOLDER&amp;gt; BE LIABLE FOR ANY&lt;br /&gt;
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES&lt;br /&gt;
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;&lt;br /&gt;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND&lt;br /&gt;
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT&lt;br /&gt;
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS&lt;br /&gt;
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
/* Your initramfs-source should contain the following&lt;br /&gt;
 *&lt;br /&gt;
 * cd /boot/initramfs-source&lt;br /&gt;
 * mkdir -p proc dev sys mnt bin sbin etc/zfs&lt;br /&gt;
 * touch etc/mtab&lt;br /&gt;
 * cp /etc/zfs/zpool.cache-initrd etc/zfs/zpool.cache&lt;br /&gt;
 * # zpool.cache is optional - zpool_import_ kernel params can be used instead&lt;br /&gt;
 * #  see below for details on using zpool_import&lt;br /&gt;
 * mknod dev/console c 5 1   # system console&lt;br /&gt;
 * mknod dev/kmsg    c 1 11  # lines printed to kmsg enter kernel messages buffer&lt;br /&gt;
 * mknod dev/loop0   b 7 0&lt;br /&gt;
 * mknod dev/tty     c 5 0   # current tty&lt;br /&gt;
 * mknod dev/tty0    c 4 0   # current virtual term&lt;br /&gt;
 * mknod dev/tty1    c 4 1   # login virtual term 1 (F1)&lt;br /&gt;
 * mknod dev/ttyS0   c 4 64  # COM1&lt;br /&gt;
 * mknod dev/ttyS1   c 4 65  # COM2&lt;br /&gt;
 * mknod dev/ttyS2   c 4 66  # COM3&lt;br /&gt;
 * mknod dev/ttyS3   c 4 67  $ COM4&lt;br /&gt;
 *&lt;br /&gt;
 * and this program compiled to /boot/initramfs-source/init&lt;br /&gt;
 *&lt;br /&gt;
 * Set kernel config option&lt;br /&gt;
 *  CONFIG_INITRAMFS_SOURCE=/boot/initramfs-source&lt;br /&gt;
 * to build the initramfs into your kernel image&lt;br /&gt;
 *  that also has builtin drivers (spl and zfs, etc).&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
#define FOOBARZ_INIT_VERSION &amp;quot;1.1.1&amp;quot;&lt;br /&gt;
#define _BSD_SOURCE&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdarg.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;fcntl.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/mount.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sysexits.h&amp;gt;&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
/* support for zpool import&lt;br /&gt;
 *&lt;br /&gt;
 * If -DINCLUDE_ZPOOL_IMPORT, then support to import a zpool is&lt;br /&gt;
 * enabled in the program. Enabling it will add many dependencies to the&lt;br /&gt;
 * compile and link; for example:&lt;br /&gt;
 *&lt;br /&gt;
 * gcc -static -DINCLUDE_ZPOOL_IMPORT \&lt;br /&gt;
 *    foobarz-init.c -include /usr/src/zfs-0.6.0-rc10/3.2.28/zfs_config.h \&lt;br /&gt;
 *   -o init \&lt;br /&gt;
 *   -I /usr/include/libspl -I /usr/include/libzfs \&lt;br /&gt;
 *   -lzfs -lnvpair -lzpool -luutil -luuid -lrt -lz -lm -lpthread \&lt;br /&gt;
 *   -I /usr/include/tirpc \&lt;br /&gt;
 *   -ltirpc&lt;br /&gt;
 *&lt;br /&gt;
 * Note that libtirpc is a drop-in replacement for the SunRPC functions that&lt;br /&gt;
 * used to be in glibc. No additional includes are needed, just the gcc -I and -l&lt;br /&gt;
 * options for tirpc.&lt;br /&gt;
 *&lt;br /&gt;
 * Otherwise, with -UINCLUDE_ZPOOL_IMPORT, the compile is just:&lt;br /&gt;
 * gcc -static foobarz-init.c -o init&lt;br /&gt;
 */&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
#include &amp;lt;libzfs.h&amp;gt;&lt;br /&gt;
#else&lt;br /&gt;
#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/stat.h&amp;gt;&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#define PARAM_REQ_NO 0&lt;br /&gt;
#define PARAM_REQ_YES 1&lt;br /&gt;
#define PARAM_SRC_DEFAULT 0&lt;br /&gt;
#define PARAM_SRC_CMDLINE 1&lt;br /&gt;
&lt;br /&gt;
void printk(char *fmt, ...) {&lt;br /&gt;
  FILE* f;&lt;br /&gt;
  int fd;&lt;br /&gt;
  va_list args;&lt;br /&gt;
&lt;br /&gt;
  f = fopen(&amp;quot;/dev/kmsg&amp;quot;, &amp;quot;w&amp;quot;);&lt;br /&gt;
  va_start(args, fmt);&lt;br /&gt;
  vfprintf(f, fmt, args);&lt;br /&gt;
  va_end(args);&lt;br /&gt;
  fflush(f);&lt;br /&gt;
  fclose(f);&lt;br /&gt;
  /* avoid flooding kmsg and having msgs suppressed; 20msgs/sec */&lt;br /&gt;
  usleep(50000);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[]) {&lt;br /&gt;
 /*** variables */&lt;br /&gt;
&lt;br /&gt;
 int i;&lt;br /&gt;
 int   fd = 0; /* file descriptor */&lt;br /&gt;
 unsigned long mountflags;&lt;br /&gt;
&lt;br /&gt;
 /* kernel command line */&lt;br /&gt;
 off_t cmdline_size;&lt;br /&gt;
 char* cmdline; /* to be malloc 4096B */&lt;br /&gt;
 char* cmdline_end;&lt;br /&gt;
 char* temp_end;&lt;br /&gt;
 char* src_msg; /* default or cmdline */&lt;br /&gt;
 int flag_param_missing = 0;&lt;br /&gt;
&lt;br /&gt;
 /* use to hold contents of a misc /proc/&amp;lt;file&amp;gt; */&lt;br /&gt;
 char* miscproc_buff; /* to be malloc 4096B */&lt;br /&gt;
 off_t miscproc_size;&lt;br /&gt;
&lt;br /&gt;
 /* note about environ, argv, and kernel cmdline for init:&lt;br /&gt;
  *   environ is not defined for init&lt;br /&gt;
  *   only argv[0] is set for init&lt;br /&gt;
  *   kernel command line parameters are accessed&lt;br /&gt;
  *   at /proc/cmdline&lt;br /&gt;
  */&lt;br /&gt;
&lt;br /&gt;
 /* kernel parameters expected to be name=value */&lt;br /&gt;
 /* do not use quotes or spaces in parameters   */&lt;br /&gt;
 /* you can add more params somwhere after root= */&lt;br /&gt;
 struct nv { char* n; char* v; char* v_end; int req; int src; };&lt;br /&gt;
 struct nv param[] = {&lt;br /&gt;
   { &amp;quot;root=&amp;quot;,       NULL, NULL, PARAM_REQ_YES, PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;rootfstype=&amp;quot;, NULL, NULL, PARAM_REQ_YES, PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;mountopt=&amp;quot;,   NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;init=&amp;quot;,       NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;runlevel=&amp;quot;,   NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;console=&amp;quot;,    NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT }&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
   ,&lt;br /&gt;
   { &amp;quot;zpool_import_name=&amp;quot;,    NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;zpool_import_guid=&amp;quot;,    NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;zpool_import_newname=&amp;quot;, NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;zpool_import_force=&amp;quot;,   NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT }&lt;br /&gt;
#endif&lt;br /&gt;
 };&lt;br /&gt;
 enum {&lt;br /&gt;
	 iroot,&lt;br /&gt;
	 irootfstype,&lt;br /&gt;
	 imountopt,&lt;br /&gt;
	 iinit,&lt;br /&gt;
	 irunlevel,&lt;br /&gt;
	 iconsole,&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
	 izpool_import_name,&lt;br /&gt;
	 izpool_import_guid,&lt;br /&gt;
	 izpool_import_newname,&lt;br /&gt;
	 izpool_import_force,&lt;br /&gt;
#endif&lt;br /&gt;
	 ilastparam&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
 libzfs_handle_t* libzfs = NULL;&lt;br /&gt;
 importargs_t iargs = { 0 };&lt;br /&gt;
 nvlist_t* pools = NULL;&lt;br /&gt;
 nvpair_t* pool = NULL;&lt;br /&gt;
 nvlist_t* config = NULL;&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
 /*** program */&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;foobarz-init, version %s: booting initramfs.\n&amp;quot;, FOOBARZ_INIT_VERSION);&lt;br /&gt;
&lt;br /&gt;
 cmdline       = (char*) malloc(4096);&lt;br /&gt;
 miscproc_buff = (char*) malloc(4096);&lt;br /&gt;
 if( (cmdline == NULL) || (miscproc_buff == NULL) ) {&lt;br /&gt;
   printk(&amp;quot;Unable to allocate buffer memory: malloc: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount proc /proc&lt;br /&gt;
  *  note: some /dev devices symlink into /proc&lt;br /&gt;
  *  proc contains info about processes, including cmdline etc. */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount proc /proc\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;proc&amp;quot;, &amp;quot;/proc&amp;quot;, &amp;quot;proc&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
   printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
   printk(&amp;quot;Mount proc successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount devtmpfs /dev&lt;br /&gt;
  *  note: This simple init program works if your root device is made from devices&lt;br /&gt;
  *  that are available by default in devtmpfs, such as /dev/sd*&lt;br /&gt;
  *&lt;br /&gt;
  *  For zfs, your root zfs pool should be created with default device nodes and&lt;br /&gt;
  *  then it should be mountable by this simple init program.&lt;br /&gt;
  *&lt;br /&gt;
  *  udev may be needed to configure device nodes and symlinks required&lt;br /&gt;
  *  to access a root device configuration made with such nodes and symlinks.&lt;br /&gt;
  *  If you need udevd, you can include it into your initramfs-source and&lt;br /&gt;
  *  modify this program to run it before attempting to mount your root device.&lt;br /&gt;
  *  However, if udevd is needed, a significant number of userspace programs may also be&lt;br /&gt;
  *  required by rules in /lib/udev/. You could install busybox + udev (about 5MB) or&lt;br /&gt;
  *  coreutils + util-linux + bash + udev (about 25MB) into initramfs-source. But, at that&lt;br /&gt;
  *  point you'd have ash or bash and many tools that are easier to use than this&lt;br /&gt;
  *  simple init program; it would then be easy to have /init as #!/bin/&amp;lt;b&amp;gt;ash script. */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount devtmpfs /dev\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;devtmpfs&amp;quot;, &amp;quot;/dev&amp;quot;, &amp;quot;devtmpfs&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
   printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
   printk(&amp;quot;Mount devtmpfs successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount sysfs /sys&lt;br /&gt;
  *  note: some kernel modules try to access /sys with userspace helpers to echo values into /sys variables;&lt;br /&gt;
  *  such modules expect a minimal userspace that contains coreutils or busybox */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount sysfs /sys\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;sysfs&amp;quot;, &amp;quot;/sys&amp;quot;, &amp;quot;sysfs&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
   printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
   printk(&amp;quot;Mount sysfs successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* process kernel command line */&lt;br /&gt;
 fd = open(&amp;quot;/proc/cmdline&amp;quot;, O_RDONLY);&lt;br /&gt;
 if( fd == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Cannot open /proc/cmdline: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 /* note, on /proc fs:&lt;br /&gt;
  *       lseek likely always returns error&lt;br /&gt;
  *       stat likely always returns st_size = 0&lt;br /&gt;
  *   so determining size of /proc file means just reading it;&lt;br /&gt;
  *   you have to read /proc files according to their documented&lt;br /&gt;
  *   maximum sizes; this is probably for performance reasons */&lt;br /&gt;
 cmdline_size = read(fd, cmdline, 4095);&lt;br /&gt;
 if( cmdline_size == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Failed to read /proc/cmdline: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 close(fd);&lt;br /&gt;
&lt;br /&gt;
 /* cmdline may be newline + null terminated, but make it null + null */&lt;br /&gt;
 cmdline[cmdline_size] = '\0';&lt;br /&gt;
 if( cmdline[cmdline_size-1] == '\n' ) {&lt;br /&gt;
   cmdline[cmdline_size-1] = '\0';&lt;br /&gt;
   cmdline_size--;&lt;br /&gt;
   cmdline_end = cmdline + cmdline_size;&lt;br /&gt;
 }&lt;br /&gt;
 printk(&amp;quot;Kernel cmdline size: %i\n&amp;quot;, cmdline_size);&lt;br /&gt;
 printk(&amp;quot;Kernel cmdline: \&amp;quot;%s\&amp;quot;\n&amp;quot;, cmdline);&lt;br /&gt;
&lt;br /&gt;
 /* find v and v_end of values in cmdline */&lt;br /&gt;
 for( i=iroot; i&amp;lt;ilastparam; i++ ) {&lt;br /&gt;
   param[i].v = strstr(cmdline, param[i].n);&lt;br /&gt;
   if( param[i].v != NULL ) {&lt;br /&gt;
     param[i].src = PARAM_SRC_CMDLINE;&lt;br /&gt;
     while( *(param[i].v) != '=' ) param[i].v++;&lt;br /&gt;
     param[i].v++;&lt;br /&gt;
     temp_end = param[i].v;&lt;br /&gt;
     while( !( (*temp_end == ' ') ||&lt;br /&gt;
               (*temp_end == '\n') ||&lt;br /&gt;
               (temp_end == cmdline_end)&lt;br /&gt;
	     ) ) temp_end++;&lt;br /&gt;
     if( temp_end == param[i].v ) {&lt;br /&gt;
       printk(&amp;quot;Kernel parameter %s: value missing.\n&amp;quot;, param[i].n);&lt;br /&gt;
       param[i].v = NULL;&lt;br /&gt;
     } else param[i].v_end = temp_end;&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 for( i=iroot; i&amp;lt;ilastparam; i++ ) {&lt;br /&gt;
   /* terminate value strings */&lt;br /&gt;
   if( param[i].v_end != NULL ) *(param[i].v_end) = '\0';&lt;br /&gt;
   /* set defaults if no value on cmdline */&lt;br /&gt;
   if( param[i].v == NULL ) {&lt;br /&gt;
     param[i].src = PARAM_SRC_DEFAULT;&lt;br /&gt;
     if( param[i].req == PARAM_REQ_YES ) flag_param_missing = 1;&lt;br /&gt;
     switch(i) {&lt;br /&gt;
       case iroot      : param[i].v = &amp;quot;&amp;lt;missing required param&amp;gt;&amp;quot; ; break;&lt;br /&gt;
       case irootfstype: param[i].v = &amp;quot;&amp;lt;missing required param&amp;gt;&amp;quot; ; break;&lt;br /&gt;
       case imountopt  : param[i].v = &amp;quot;ro&amp;quot;        ; break;&lt;br /&gt;
       case iinit      : param[i].v = &amp;quot;/sbin/init&amp;quot;; break;&lt;br /&gt;
       case irunlevel  : param[i].v = &amp;quot;3&amp;quot;         ; break;&lt;br /&gt;
       case iconsole   : param[i].v = &amp;quot;console&amp;quot;   ; break;&lt;br /&gt;
       default         : param[i].v = NULL;&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
   if(param[i].src == PARAM_SRC_DEFAULT) src_msg = &amp;quot;default&amp;quot;;&lt;br /&gt;
   else src_msg = &amp;quot;cmdline&amp;quot;;&lt;br /&gt;
   printk(&amp;quot;Using %s \&amp;quot;%s\&amp;quot; (source: %s)\n&amp;quot;, param[i].n, param[i].v, src_msg);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 if( flag_param_missing ) {&lt;br /&gt;
   printk(&amp;quot;Aborting boot process: missing required kernel parameter(s).\n&amp;quot;);&lt;br /&gt;
   return EX_USAGE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* generic nv pair kernel cmdline processing finished&lt;br /&gt;
  *  now, examine specific params for defaults and correctness */&lt;br /&gt;
&lt;br /&gt;
 /* param[irootfstype]: can be checked against /proc/filesystems: */&lt;br /&gt;
 fd = open(&amp;quot;/proc/filesystems&amp;quot;, O_RDONLY);&lt;br /&gt;
 if( fd == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Cannot open /proc/filesystems: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 miscproc_size = read(fd, miscproc_buff, 4095);&lt;br /&gt;
 if( miscproc_size == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Failed to read /proc/filesystems: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 close(fd);&lt;br /&gt;
 if( strstr(miscproc_buff, param[irootfstype].v) == NULL ) {&lt;br /&gt;
   printk(&amp;quot;%s \&amp;quot;%s\&amp;quot;: filesystem type not available.\n&amp;quot;, param[irootfstype].n, param[irootfstype].v);&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* zfs-specific */&lt;br /&gt;
 if( strcmp(param[irootfstype].v, &amp;quot;zfs&amp;quot;) == 0 ) {&lt;br /&gt;
   if( access(&amp;quot;/etc/zfs/zpool.cache&amp;quot;, F_OK) == 0 )&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/zfs/zpool.cache is present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
   else&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/zfs/zpool.cache not present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
&lt;br /&gt;
   if( access(&amp;quot;/etc/hostid&amp;quot;, F_OK) == 0 )&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/hostid is present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
   else&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/hostid not present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
   /* zpool import */&lt;br /&gt;
   if( (param[izpool_import_name].v != NULL) || (param[izpool_import_guid].v != NULL) ) {&lt;br /&gt;
	printk(&amp;quot;zpool_import: import requested.\n&amp;quot;);&lt;br /&gt;
	if( (param[izpool_import_name].v != NULL) &amp;amp;&amp;amp; (param[izpool_import_guid].v != NULL) ) {&lt;br /&gt;
		printk(&amp;quot;zpool_import: given both pool name and guid; using guid.\n&amp;quot;);&lt;br /&gt;
		param[izpool_import_name].v = NULL;&lt;br /&gt;
	}&lt;br /&gt;
	if( param[izpool_import_name].v != NULL )&lt;br /&gt;
		printk(&amp;quot;zpool_import: pool name: %s\n&amp;quot;, param[izpool_import_name].v );&lt;br /&gt;
	else&lt;br /&gt;
		printk(&amp;quot;zpool_import: pool guid: %s\n&amp;quot;, param[izpool_import_guid].v );&lt;br /&gt;
&lt;br /&gt;
	iargs.path = NULL;&lt;br /&gt;
	iargs.paths = 0;&lt;br /&gt;
	iargs.poolname = param[izpool_import_name].v;&lt;br /&gt;
	if( param[izpool_import_guid].v != NULL )&lt;br /&gt;
		iargs.guid = strtoull(param[izpool_import_guid].v, NULL, 10);&lt;br /&gt;
	else&lt;br /&gt;
		iargs.guid = 0;&lt;br /&gt;
	iargs.cachefile = NULL;&lt;br /&gt;
	if( (param[izpool_import_force].v != NULL) &amp;amp;&amp;amp; (strcmp(param[izpool_import_force].v, &amp;quot;1&amp;quot;) == 0) ) {&lt;br /&gt;
		iargs.can_be_active = 1;&lt;br /&gt;
		printk(&amp;quot;zpool_import: import forced.\n&amp;quot;);&lt;br /&gt;
	} else {&lt;br /&gt;
		iargs.can_be_active = 0;&lt;br /&gt;
		printk(&amp;quot;zpool_import: import not forced.\n&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
	iargs.unique = 1;&lt;br /&gt;
	iargs.exists = 1;&lt;br /&gt;
&lt;br /&gt;
	printk(&amp;quot;zpool_import: init libzfs.\n&amp;quot;);&lt;br /&gt;
	libzfs = libzfs_init();&lt;br /&gt;
	printk(&amp;quot;zpool_import: searching for pool.\n&amp;quot;);&lt;br /&gt;
	pools = zpool_search_import(libzfs, &amp;amp;iargs);&lt;br /&gt;
	if( (pools == NULL) || nvlist_empty(pools) )&lt;br /&gt;
		printk(&amp;quot;zpool_import: pool not available for import, or already imported by cachefile.\n&amp;quot;);&lt;br /&gt;
	else {&lt;br /&gt;
		printk(&amp;quot;zpool_import: getting pool information.\n&amp;quot;);&lt;br /&gt;
		pool = nvlist_next_nvpair(pools, pool);&lt;br /&gt;
		printk(&amp;quot;zpool_import: getting pool configuration.\n&amp;quot;);&lt;br /&gt;
		nvpair_value_nvlist(pool, &amp;amp;config);&lt;br /&gt;
		printk(&amp;quot;zpool_import: attempting pool import.\n&amp;quot;);&lt;br /&gt;
		if( zpool_import(libzfs, config, param[izpool_import_newname].v, NULL) != 0 ) {&lt;br /&gt;
			printk(&amp;quot;zpool_import: import failed.\n&amp;quot;);&lt;br /&gt;
			printk(&amp;quot;zpool_import: error description: %s\n&amp;quot;, libzfs_error_description(libzfs) );&lt;br /&gt;
			printk(&amp;quot;zpool_import: error action: %s\n&amp;quot;, libzfs_error_action(libzfs) );&lt;br /&gt;
		} else  printk(&amp;quot;zpool_import: import successful.\n&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
	printk(&amp;quot;zpool_import: fini libzfs.\n&amp;quot;);&lt;br /&gt;
	libzfs_fini(libzfs);&lt;br /&gt;
   }&lt;br /&gt;
#endif /* zpool_import */&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 if(      strcmp(param[imountopt].v, &amp;quot;ro&amp;quot;) == 0 ) mountflags = MS_RDONLY;&lt;br /&gt;
 else if( strcmp(param[imountopt].v, &amp;quot;rw&amp;quot;) == 0 ) mountflags = 0;&lt;br /&gt;
 else {&lt;br /&gt;
   printk(&amp;quot;%s \&amp;quot;%s\&amp;quot;: invalid parameter value; defaulting to \&amp;quot;ro\&amp;quot;.\n&amp;quot;, param[imountopt].n, param[imountopt].v);&lt;br /&gt;
   mountflags = MS_RDONLY;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* param[iroot]: nothing to check; if user gives bad root=device then mount fails */&lt;br /&gt;
&lt;br /&gt;
 /* try to mount root=device at /mnt&lt;br /&gt;
  *&lt;br /&gt;
  * note: for zfs, if a copy of /etc/zfs/zpool.cache (when pool is imported) is put in initramfs-source, then&lt;br /&gt;
  * the zfs module can read it and automatically import the pools described in the cache file; the imported&lt;br /&gt;
  * pools can be available to mount here if they were created using standard device names, otherwise&lt;br /&gt;
  * udevd may be required to run before mounting the pool */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount -t %s -o %s %s /mnt.\n&amp;quot;, param[irootfstype].v, param[imountopt].v, param[iroot].v);&lt;br /&gt;
 if( mount(param[iroot].v, &amp;quot;/mnt&amp;quot;, param[irootfstype].v, mountflags, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 printk(&amp;quot;%s mounted successfully.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
&lt;br /&gt;
 /* check to see if the mounted root filesystem has an executable init program */&lt;br /&gt;
 chdir(&amp;quot;/mnt&amp;quot;);&lt;br /&gt;
 if( access(param[iinit].v+1, X_OK) != 0 ) {&lt;br /&gt;
   chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
   printk(&amp;quot;access X_OK: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   printk(&amp;quot;The init program /mnt/%s is not present or not executable.\n&amp;quot;, param[iinit].v+1);&lt;br /&gt;
   printk(&amp;quot;Aborting boot process: no init program.\n&amp;quot;);&lt;br /&gt;
   printk(&amp;quot;Unmounting %s.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
   if( umount(&amp;quot;/mnt&amp;quot;) == -1 ) {&lt;br /&gt;
     printk(&amp;quot;umount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
     printk(&amp;quot;Failed to umount %s.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
   } else printk(&amp;quot;Successfully unmounted %s.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
 printk(&amp;quot;Init program /mnt/%s is present and executable.\n&amp;quot;, param[iinit].v+1);&lt;br /&gt;
&lt;br /&gt;
 /* switch the root / from initramfs to the mounted new root device at /mnt.&lt;br /&gt;
  *&lt;br /&gt;
  * note: after this switch, it is not possible to access the initramfs files anymore,&lt;br /&gt;
  * yet they consume ram memory unless they are deleted here before switching.&lt;br /&gt;
  * Any programs that are run after clearing the initramfs and switching root must exist on the new root.&lt;br /&gt;
  * This program may safely delete itself (/init) since it is already in ram and executing.&lt;br /&gt;
  * If you have installed additional files and programs in initramfs that consume significant ram,&lt;br /&gt;
  * then you need to insert additional code here to delete those files (carefully). */&lt;br /&gt;
&lt;br /&gt;
 /* delete files off of initramfs to free ram memory */&lt;br /&gt;
 printk(&amp;quot;Freeing memory from initramfs...\n&amp;quot;);&lt;br /&gt;
 if( unlink(argv[0]) != 0 ) printk(&amp;quot;unlink %s: %s\n&amp;quot;, argv[0], strerror(errno));&lt;br /&gt;
 else printk(&amp;quot;%s %s&amp;quot;, argv[0], &amp;quot;deleted from initramfs.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 /* switch root */&lt;br /&gt;
 printk(&amp;quot;Beginning switch root procedure.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(1) Attempting cmd: mount --move /dev /mnt/dev \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/dev&amp;quot;, &amp;quot;/mnt/dev&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(2) Attempting cmd: mount --move /proc /mnt/proc \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/proc&amp;quot;, &amp;quot;/mnt/proc&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(3) Attempting cmd: mount --move /sys /mnt/sys \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/sys&amp;quot;, &amp;quot;/mnt/sys&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(4) Attempting cmd: chdir /mnt \n&amp;quot;);&lt;br /&gt;
 if( chdir(&amp;quot;/mnt&amp;quot;) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: chdir: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(5) Attempting cmd: mount --move . / \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;.&amp;quot;, &amp;quot;/&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(6) Attempting cmd: chroot . \n&amp;quot;);&lt;br /&gt;
 if( chroot(&amp;quot;.&amp;quot;) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: chroot: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(7) Attempting cmd: chdir / \n&amp;quot;);&lt;br /&gt;
 if( chdir(&amp;quot;/&amp;quot;) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: chdir: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 printk(&amp;quot;Completed switch root procedure.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 /* check for &amp;quot;console=&amp;quot; kernel parameter and switch&lt;br /&gt;
  *  stdin, stdout, and stderr to named console device&lt;br /&gt;
  */&lt;br /&gt;
 if( param[iconsole].src == PARAM_SRC_CMDLINE ) {&lt;br /&gt;
   printk(&amp;quot;Console redirection to device %s requested.\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
   /* expect only basename of console device (e.g., ttyS0), so chdir /dev */&lt;br /&gt;
   chdir(&amp;quot;/dev&amp;quot;);&lt;br /&gt;
   if( access(param[iconsole].v, F_OK ) == 0 ) {&lt;br /&gt;
     printk(&amp;quot;Opening stdin, stdout, and stderr on %s.\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
     close(0);&lt;br /&gt;
     open(param[iconsole].v, O_RDWR);&lt;br /&gt;
     dup2(0, 1);&lt;br /&gt;
     dup2(0, 2);&lt;br /&gt;
   } else {&lt;br /&gt;
     printk(&amp;quot;access F_OK: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
     printk(&amp;quot;Could not access device: %s!\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
     printk(&amp;quot;Console redirection to device %s aborted!\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
   }&lt;br /&gt;
   chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;Execing: \&amp;quot;%s %s\&amp;quot; to boot mounted root system.\n&amp;quot;, param[iinit].v, param[irunlevel].v);&lt;br /&gt;
&lt;br /&gt;
 /* free resources held to this point */&lt;br /&gt;
 free(cmdline);&lt;br /&gt;
 free(miscproc_buff);&lt;br /&gt;
&lt;br /&gt;
 if( execl(param[iinit].v, param[irunlevel].v, (char *) NULL ) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: execl: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If foobarz-init is updated, you can find the latest version at [https://github.com/foobarz/foobarz-init github].&lt;br /&gt;
&lt;br /&gt;
The foobarz-init program can be compiled two ways as of v1.1.1. First, the simpler compile that does not support zpool_import but does support importing pools using a /etc/zfs/zpool.cache file in the initramfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gcc --static init.c -o init&lt;br /&gt;
strip init&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The second way to compile it adds support for zpool_import so that you do not have to include a &amp;lt;code&amp;gt;/etc/zfs/zpool.cache&amp;lt;/code&amp;gt; file in the initramfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gcc -static -DINCLUDE_ZPOOL_IMPORT \&lt;br /&gt;
     foobarz-init.c -include /usr/src/zfs-0.6.0-rc10/3.2.28/zfs_config.h \&lt;br /&gt;
    -o init \&lt;br /&gt;
    -I /usr/include/libspl -I /usr/include/libzfs \&lt;br /&gt;
    -lzfs -lnvpair -lzpool -luutil -luuid -lrt -lz -lm -lpthread \&lt;br /&gt;
    -I /usr/include/tirpc \&lt;br /&gt;
    -ltirpc&lt;br /&gt;
strip init&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Note: the zpool_import support requires that you install [http://sourceforge.net/projects/libtirpc/ libtirpc] first.&lt;br /&gt;
&lt;br /&gt;
Read the foobarz-init source code to see how it uses kernel parameters. The params &amp;lt;code&amp;gt;root&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;rootfstype&amp;lt;/code&amp;gt; are always required to tell init what root pool name to mount and the filesystem type (e.g. zfs).&lt;br /&gt;
&lt;br /&gt;
For the zpool_import support: &amp;lt;code&amp;gt;zpool_import_name=poolname&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;zpool_import_guid=&amp;lt;guid of a pool&amp;gt;&amp;lt;/code&amp;gt; tells what pool to import. You can also import the pool with a new different name by also using &amp;lt;code&amp;gt;zpool_import_newname=newpoolname&amp;lt;/code&amp;gt;. If the import is not working, &amp;lt;code&amp;gt;zpool_import_force=1&amp;lt;/code&amp;gt; can be used to force import even if ZFS thinks the pool may be in use by another system.&lt;br /&gt;
&lt;br /&gt;
However you import the pool, either using zpool.cache or zpool_import support, the kernel param &amp;lt;code&amp;gt;root=&amp;lt;your poolname or newpoolname&amp;gt;&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;rootfstype=zfs&amp;lt;/code&amp;gt; needs to be given also. The zpool_import only imports, it does not say what to mount. What to mount is still told using root= and rootfstype=.&lt;br /&gt;
&lt;br /&gt;
Now copy the compiled static program into the initramfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp init /boot/initramfs-source/init&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Build and install kernel:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make -j8&lt;br /&gt;
make -j8 modules_install&lt;br /&gt;
cp arch/x86/boot/bzImage /boot/vm3.2.27b&lt;br /&gt;
cp System.map /boot/System.map-vm3.2.27b&lt;br /&gt;
# add new lilo menu entry for vm3.2.27b kernel&lt;br /&gt;
vi /etc/lilo.conf&lt;br /&gt;
  image = /boot/vm3.2.27b&lt;br /&gt;
   label = vm3.2.27b&lt;br /&gt;
   addappend = &amp;quot; spl.spl_hostid=0x007f0100 zfs.spa_config_path=/etc/zfs/zpool.cache root=zfs-root rootfstype=zfs&amp;quot;&lt;br /&gt;
lilo&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Congrats! If this works, you can select the &amp;quot;vm3.2.27b&amp;quot; lilo entry to boot. If you are using the zpool_import support in the init program, you need to add at least the &amp;lt;code&amp;gt;zpool_import_name=zfs-root&amp;lt;/code&amp;gt; param to the addappend line in lilo.conf.&lt;br /&gt;
&lt;br /&gt;
Notes on kernel params (lilo append and addappend lines): root= and rootfstype= are used by both foorbarz-init and mkinitrd. The &amp;quot;ro&amp;quot; param is not used by foobarz-init, so instead use: mountopt=ro|rw. See &amp;quot;modinfo spl&amp;quot; and &amp;quot;modinfo zfs&amp;quot; to see all of the options those modules can take on the kernel command line. Notice the &amp;lt;code&amp;gt;spl.spl_hostid=0x007f0100&amp;lt;/code&amp;gt; param that works around the hostid mismatch problem while trying to import a pool; this param and hostname/ip set to use local loopback 127.0.0.1 in etc/hosts etc/HOSTNAME in initramfs will work most of the time, and if not the pool import needs to be forced.&lt;br /&gt;
&lt;br /&gt;
Notes on the spl and zfs packages to install: &amp;lt;i&amp;gt;If&amp;lt;/i&amp;gt; you have errors using zfs and zpool commands on booted system with builtin modules, then upgrade/switch to the 0.6.0rc10_3.2.27b builds, or you can make a custom package with the binaries renamed like zpoolb, zfsb etc for builtin.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
Using qemu's -nographic serial console (/usr/share/qemu/sgabios.bin): If you have a boot problem, you might want to run in qemu's -nographic console mode:&lt;br /&gt;
&lt;br /&gt;
First, edit /etc/inittab, and uncomment the line for local serial ports runlevel &amp;quot;s1&amp;quot; (ttyS0) for serial console login support. This is done in the guest (host does not need this):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Local serial lines:&lt;br /&gt;
s1:12345:respawn:/sbin/agetty -L ttyS0 38400 linux&lt;br /&gt;
#s1:12345:respawn:/sbin/agetty -L ttyS0 9600 vt100&lt;br /&gt;
#s2:12345:respawn:/sbin/agetty -L ttyS1 9600 vt100&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Second, edit /etc/securetty, and uncomment ttyS0 line:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ttyS0&lt;br /&gt;
#ttyS1&lt;br /&gt;
# ...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
You cannot login on ttyS0 without this change even though you get the login prompt!&lt;br /&gt;
&lt;br /&gt;
Then, run qemu such as:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
qemu-kvm &amp;lt;all regular options&amp;gt; -nographic -option-rom sgabios.bin,bootindex=0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Wait for the lilo prompt, it may take several seconds show up in this mode.&lt;br /&gt;
&lt;br /&gt;
In the lilo menu, select your kernel image with builtin spl/zfs, and use kernel params such as:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
boot: vm3.2.27b console=ttyS0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
At the lilo prompt, use kernel parameter: console=ttyS0 (do NOT say /dev/ttS0). Passing runlevel=s1 does not appear to be necessary.&lt;br /&gt;
&lt;br /&gt;
When you are in qemu's serial mode, the interface is a little different than in the normal graphical mode: use keypresses:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ctrl-a h    # for help&lt;br /&gt;
ctrl-a c    # toggle access to (QEMU) console / back to emulation&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If you cannot get a login: prompt, try ctrl-a c, then do (QEMU) sendkey ctrl-alt-delete. This will reboot cleanly back to lilo, then you can do (QEMU) quit.&lt;br /&gt;
&lt;br /&gt;
Once you login to the guest, the terminal size needs adjustment. On your host, in another xterm sized the same as your guest console terminal, get the size of the terminal:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo $LINES&lt;br /&gt;
echo $COLUMNS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Now, back in the guest terminal of same size:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export LINES &amp;lt;lines&amp;gt;&lt;br /&gt;
export COLUMNS &amp;lt;columns&amp;gt;&lt;br /&gt;
stty cols $COLUMNS rows $LINES&lt;br /&gt;
exec bash&lt;br /&gt;
reset&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
So, you set the environment variables and also set them with stty. Then, restart bash (exec, or else it is a child shell process).&lt;br /&gt;
&lt;br /&gt;
BECAREFUL not to start qemu twice on the same ZFS guest! Two simultaneous running qemu on the same ZFS will corrupt the pool and it will NOT recover - you lose your whole installation! Before running qemu, check ps -A, look for an already running qemu process incase it somehow entered into the background!&lt;br /&gt;
&lt;br /&gt;
BECAREFUL when using -nographic ttyS0 that you are not doing commands on the HOST! Only use -nographic to see kernel problems. Use regular console of booting is working normally.&lt;br /&gt;
&lt;br /&gt;
To use the qemu -drive if=scsi option, the linux module sym53c8xx should be loaded in the guest. You may need to use the qemu option:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-option-rom 8xx_64.rom,bootindex=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The file 8xx_64.rom used to be inside qemu, but in new versions it is missing. You can download it:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
wget http://www.lsi.com/downloads/Public/Host%20Bus%20Adapters/Host%20Bus%20Adapters%20Common%20Files/lsi_bios.zip&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Extract the zip and place 8xx_64.rom in /usr/share/qemu/.&lt;br /&gt;
&lt;br /&gt;
Good luck!&lt;/div&gt;</description>
			<pubDate>Wed, 12 Sep 2012 03:44:07 GMT</pubDate>
			<dc:creator>Foobarz</dc:creator>
			<comments>https://www.slackwiki.com/Talk:ZFS_root_(builtin)</comments>
		</item>
		<item>
			<title>ZFS root (builtin)</title>
			<link>https://www.slackwiki.com/index.php?title=ZFS_root_(builtin)&amp;diff=785</link>
			<guid isPermaLink="false">https://www.slackwiki.com/index.php?title=ZFS_root_(builtin)&amp;diff=785</guid>
			<description>&lt;p&gt;Foobarz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Tutorials]]&lt;br /&gt;
The first &amp;quot;ZFS root&amp;quot; wiki explains the details of running ZFS at your root filesystem by using a fully modular generic kernel approach. Now, I can share how it can be done with the SPL and ZFS modules built into the kernel. This procedure is just an example and can use some fine tuning, but here goes:&lt;br /&gt;
&lt;br /&gt;
The steps below are to create kernel with SPL and ZFS modules builtin. This kernel will be installed as an alternatve kernel to boot in lilo, and it will have a separate kernel installation from the fully modular and working system kernel. This will allow testing the builtin kernel while able to boot back onto a working modular ZFS system. We start this procedure assuming you are on a working fully modular ZFS install as in the &amp;quot;ZFS root&amp;quot; wiki.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=legacy zfs-root&lt;br /&gt;
# use legacy so zfs will not expect zfs mount, but instead expect standard mount for this fs&lt;br /&gt;
# edit /etc/rc.d/rc.S and rc.6 to use regular &amp;quot;mount&amp;quot; commands, remove &amp;quot;zfs&amp;quot; commands&lt;br /&gt;
# edit rc.6 and remove or comment out zfs export command&lt;br /&gt;
&lt;br /&gt;
# You might think to set bootfs property like this:&lt;br /&gt;
#  zpool set bootfs=zfs-root zfs-root&lt;br /&gt;
# however, this will result in ZFS placing many restrictions on zfs-root as per how that option&lt;br /&gt;
#  is used on Solaris systems:&lt;br /&gt;
#  * zfs-root must be VTOC (SMI) label, not GPT (EFI) label&lt;br /&gt;
#  * zfs-root can only contain 1 vdev: either a plain disk, or a mirror&lt;br /&gt;
# so, do not set that property!&lt;br /&gt;
# If bootfs is set, you would find that you cannot add vdevs to your zfs-root.&lt;br /&gt;
# If it is set already, then unset it like this:&lt;br /&gt;
#  zpool set bootfs= zfs-root&lt;br /&gt;
&lt;br /&gt;
mkdir /boot/initramfs-source&lt;br /&gt;
# this will hold some files for rootfs inside kernel&lt;br /&gt;
&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir src&lt;br /&gt;
cd src&lt;br /&gt;
tar xvzf /mnt/cdrom/slackware64/k/kernel-source-*.txz&lt;br /&gt;
mv usr/src/linux-3.2.27 /usr/src/linux-3.2.27b&lt;br /&gt;
rm -r install&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make menuconfig&lt;br /&gt;
  General setup-&amp;gt;Local version - append to kernel release = b&lt;br /&gt;
  General setup-&amp;gt;Default hostname                         = slackzfs&lt;br /&gt;
  General setup-&amp;gt;Initramfs source files(s)                = /boot/initramfs-source&lt;br /&gt;
  #  make usre you made this directory or the kernel build fails&lt;br /&gt;
  Device Drivers-&amp;gt;SCSI device support-&amp;gt;SCSI low-level drivers-&amp;gt; &amp;lt;*&amp;gt; SYM53C8XX Version 2 SCSI support&lt;br /&gt;
  #  for qemu if=scsi -option-rom 8xx_64.rom,bootindex=1  hard disks&lt;br /&gt;
  # buildin any hard drive controllers etc that you need&lt;br /&gt;
  File systems -&amp;gt; &amp;lt;*&amp;gt; The Extended 4 (ext4) filesystem&lt;br /&gt;
  # /boot may use this ext4 fs&lt;br /&gt;
make prepare scripts&lt;br /&gt;
# this make command is what the spl and zfs copy-builtin scripts expect to be done before they are run&lt;br /&gt;
&lt;br /&gt;
cd ~/src&lt;br /&gt;
tar xvzf ~/spl-0.6.0-rc10.tar.gz&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-0.6.0-rc10&lt;br /&gt;
./configure \&lt;br /&gt;
    --prefix=/ \&lt;br /&gt;
    --libdir=/lib64 \&lt;br /&gt;
    --includedir=/usr/include \&lt;br /&gt;
    --datarootdir=/usr/share \&lt;br /&gt;
    --enable-linux-builtin=yes \&lt;br /&gt;
    --with-linux=/usr/src/linux-3.2.27b \&lt;br /&gt;
    --with-linux-obj=/usr/src/linux-3.2.27b&lt;br /&gt;
wget https://raw.github.com/zfsonlinux/spl/master/copy-builtin&lt;br /&gt;
chmod +x copy-builtin&lt;br /&gt;
./copy-builtin /usr/src/linux-3.2.27b&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../spl-0.6.0rc10_3.2.27b-x86_64-1root.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
&lt;br /&gt;
tar xvzf ~/zfs-0.6.0-rc10.tar.gz&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-0.6.0-rc10&lt;br /&gt;
./configure \&lt;br /&gt;
    --prefix=/ \&lt;br /&gt;
    --libdir=/lib64 \&lt;br /&gt;
    --includedir=/usr/include \&lt;br /&gt;
    --datarootdir=/usr/share \&lt;br /&gt;
    --enable-linux-builtin=yes \&lt;br /&gt;
    --with-linux=/usr/src/linux-3.2.27b \&lt;br /&gt;
    --with-linux-obj=/usr/src/linux-3.2.27b \&lt;br /&gt;
    --with-spl=/root/src/spl-0.6.0-rc10&lt;br /&gt;
wget https://raw.github.com/zfsonlinux/zfs/master/copy-builtin&lt;br /&gt;
chmod +x copy-builtin&lt;br /&gt;
./copy-builtin /usr/src/linux-3.2.27b&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../zfs-0.6.0rc10_3.2.27b-x86_64-1root.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
&lt;br /&gt;
### move zfs and spl modules inside kernel source to be at end of drivers:&lt;br /&gt;
### the order builtin modules init is the order they link into the kernel&lt;br /&gt;
### and we need zfs to init after all hard drive controllers&lt;br /&gt;
### zfs is more like a device driver layer over the lower-level hba drivers&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
mkdir drivers/zfsonlinux&lt;br /&gt;
mv spl drivers/zfsonlinux&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  # remove references to spl&lt;br /&gt;
vi Makefile&lt;br /&gt;
  # remove references to spl&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/fs&lt;br /&gt;
mv zfs ../drivers/zfsonlinux&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  # remove references to zfs&lt;br /&gt;
vi Makefile&lt;br /&gt;
  # remove references to zfs&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  )# add line at end of menu, before &amp;quot;endmenu&amp;quot;:&lt;br /&gt;
  )source &amp;quot;drivers/zfsonlinux/Kconfig&amp;quot;&lt;br /&gt;
  )endmenu&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers&lt;br /&gt;
vi Makefile&lt;br /&gt;
  )# add line at very end of file:&lt;br /&gt;
  )obj-$(CONFIG_ZFSONLINUX) += zfsonlinux/&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers/zfsonlinux&lt;br /&gt;
cat &amp;gt; Kconfig &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
menuconfig ZFSONLINUX&lt;br /&gt;
	tristate &amp;quot;ZFSonLinux support&amp;quot;&lt;br /&gt;
&lt;br /&gt;
if ZFSONLINUX&lt;br /&gt;
&lt;br /&gt;
source &amp;quot;drivers/zfsonlinux/spl/Kconifg&amp;quot;&lt;br /&gt;
&lt;br /&gt;
source &amp;quot;drivers/zfsonlinux/zfs/Kconifg&amp;quot;&lt;br /&gt;
&lt;br /&gt;
endif&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/zfsonlinux&lt;br /&gt;
cat &amp;gt; Makefile &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
obj-$(CONFIG_SPL) += spl/&lt;br /&gt;
obj-$(CONFIG_ZFS) += zfs/&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
### move complete&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make menuconfig&lt;br /&gt;
   Device Drivers -&amp;gt;&lt;br /&gt;
    &amp;lt;*&amp;gt; ZFSonLinux support -&amp;gt;&lt;br /&gt;
      &amp;lt;*&amp;gt; Solaris Porting Layer (SPL)&lt;br /&gt;
      &amp;lt;*&amp;gt;     ZFS&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
### prepare contents of initramfs&lt;br /&gt;
cd /boot/initramfs-source&lt;br /&gt;
&lt;br /&gt;
# make standard directories&lt;br /&gt;
mkdir -p proc dev sys mnt bin sbin etc/zfs&lt;br /&gt;
&lt;br /&gt;
# zfs seems to want mtab present, even if empty&lt;br /&gt;
touch etc/mtab&lt;br /&gt;
&lt;br /&gt;
# if zpool.cache file can be read by zfs at module init, it imports the pools in the cache&lt;br /&gt;
cp /etc/zfs/zpool.cache-initrd etc/zfs/zpool.cache&lt;br /&gt;
&lt;br /&gt;
# make initial console device node; otherwise, there is a problem at startup:&lt;br /&gt;
# &amp;quot;Warning: unable to open an initial console&amp;quot; and you'd have problems with console and tty login&lt;br /&gt;
# making these nodes from within /init is not early enough to avoid problem&lt;br /&gt;
mknod dev/console c 5 1   # system console&lt;br /&gt;
&lt;br /&gt;
# make memory device kmsg to &amp;quot;printk&amp;quot; kernel messages&lt;br /&gt;
# we can write to this file to send out messages&lt;br /&gt;
mknod dev/kmsg    c 1 11  # lines printed to kmsg enter kernel messages buffer&lt;br /&gt;
&lt;br /&gt;
# recommended loop0 device to mount fs images&lt;br /&gt;
mknod dev/loop0   b 7 0&lt;br /&gt;
&lt;br /&gt;
# make initial virtual terminal devices&lt;br /&gt;
mknod dev/tty     c 5 0   # current tty&lt;br /&gt;
mknod dev/tty0    c 4 0   # current virtual term&lt;br /&gt;
mknod dev/tty1    c 4 1   # login virtual term 1 (F1)&lt;br /&gt;
&lt;br /&gt;
# make alternative console=ttyS0 standard 8250/16550 UART serial port devices&lt;br /&gt;
#   useful with kernel parameter console=ttyS0&lt;br /&gt;
#          with qemu -nographic -option-rom sgabios.bin,bootindex=0&lt;br /&gt;
mknod dev/ttyS0   c 4 64  # COM1&lt;br /&gt;
mknod dev/ttyS1   c 4 65  # COM2&lt;br /&gt;
mknod dev/ttyS2   c 4 66  # COM3&lt;br /&gt;
mknod dev/ttyS3   c 4 67  $ COM4&lt;br /&gt;
&lt;br /&gt;
# this should be enough device nodes initially&lt;br /&gt;
# once devtmpfs mounts over /dev, a lot more is available in it by default&lt;br /&gt;
&lt;br /&gt;
cat &amp;gt; /init &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot; &amp;lt;some initial program PID=1 for the system to start on&amp;gt; EOF&lt;br /&gt;
# an initramfs-source/init program is required to mount and boot a root linux system&lt;br /&gt;
# the common way to make /init is using busybox with files like this:&lt;br /&gt;
#    /bin/busybox&lt;br /&gt;
#    /bin/ash -&amp;gt; busybox&lt;br /&gt;
#    /bin/sh -&amp;gt; busybox&lt;br /&gt;
#    # run busybox to see what other &amp;quot;applets&amp;quot; can be symlinked to it&lt;br /&gt;
#    # when busybox is run as a different symlinked applet name, it runs the applet&lt;br /&gt;
#    /init&lt;br /&gt;
#    # init is ash script, see slackware's /boot/initrd-tree/init for example&lt;br /&gt;
#    Inside this script:&lt;br /&gt;
#      1) parse kernel parameters passed into it and set variables based on them&lt;br /&gt;
#      2) start udevd and trigger rules for block devices to setup initial /dev devices&lt;br /&gt;
#      3) load kernel modules and keyboard map&lt;br /&gt;
#      4) run mdadm, cryptsetup, lvm, zpool/zfs to setup more devices&lt;br /&gt;
#         (any udev rules for them should do more /dev setup in the background)&lt;br /&gt;
#      5) mount the root filesystem read-only at /mnt&lt;br /&gt;
#      6) stat /mnt/sbin/init, and if not executable run a rescue shell /bin/sh&lt;br /&gt;
#      7) shutdown udevd so it can be restarted by root system when booted&lt;br /&gt;
#      8) mount --move {proc,sys,run,dev} to under /mnt&lt;br /&gt;
#      9) run: exec switch_root /mnt /sbin/init $RUNLEVEL&lt;br /&gt;
#    The slackware mkinitrd package is fully configured busybox installation&lt;br /&gt;
#      for an extern file initramfs initrd.gz image outside the kernel.&lt;br /&gt;
#    It could be changed to be inside the kernel easily by just using initrd-tree&lt;br /&gt;
#      as target of INITRAMFS_SOURCE in the kernel config and removing initrd in lilo.&lt;br /&gt;
&lt;br /&gt;
# Because the zfs modules are builtin, we really don't need busybox and the whole&lt;br /&gt;
# mkinitrd package. All we need to do is mount the zfs that is already imported&lt;br /&gt;
# because the zpool.cache is present in rootfs when the zfs module initializes, and&lt;br /&gt;
# then we do the switch root procedure to boot up on the mounted system.&lt;br /&gt;
# udevd rules will still be run when the root system starts udevd.&lt;br /&gt;
&lt;br /&gt;
# So, let's make a simple /init c program that will be all that we really need:&lt;br /&gt;
cat &amp;gt; init.c &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
/* software product name: foobarz-init.c&lt;br /&gt;
 * suggested binary name: /init (in initramfs-source, rootfs)&lt;br /&gt;
 * license              : BSD&lt;br /&gt;
 * license text:&lt;br /&gt;
Copyright (c) 2012, foobarz&lt;br /&gt;
All rights reserved.&lt;br /&gt;
&lt;br /&gt;
Redistribution and use in source and binary forms, with or without&lt;br /&gt;
modification, are permitted provided that the following conditions are met:&lt;br /&gt;
    * Redistributions of source code must retain the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer.&lt;br /&gt;
    * Redistributions in binary form must reproduce the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer in the&lt;br /&gt;
      documentation and/or other materials provided with the distribution.&lt;br /&gt;
    * Neither the name of the &amp;lt;organization&amp;gt; nor the&lt;br /&gt;
      names of its contributors may be used to endorse or promote products&lt;br /&gt;
      derived from this software without specific prior written permission.&lt;br /&gt;
&lt;br /&gt;
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &amp;quot;AS IS&amp;quot; AND&lt;br /&gt;
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED&lt;br /&gt;
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE&lt;br /&gt;
DISCLAIMED. IN NO EVENT SHALL &amp;lt;COPYRIGHT HOLDER&amp;gt; BE LIABLE FOR ANY&lt;br /&gt;
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES&lt;br /&gt;
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;&lt;br /&gt;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND&lt;br /&gt;
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT&lt;br /&gt;
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS&lt;br /&gt;
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
/* Your initramfs-source should contain the following&lt;br /&gt;
 *&lt;br /&gt;
 * cd /boot/initramfs-source&lt;br /&gt;
 * mkdir -p proc dev sys mnt bin sbin etc/zfs&lt;br /&gt;
 * touch etc/mtab&lt;br /&gt;
 * cp /etc/zfs/zpool.cache-initrd etc/zfs/zpool.cache&lt;br /&gt;
 * # zpool.cache is optional - zpool_import_ kernel params can be used instead&lt;br /&gt;
 * #  see below for details on using zpool_import&lt;br /&gt;
 * mknod dev/console c 5 1   # system console&lt;br /&gt;
 * mknod dev/kmsg    c 1 11  # lines printed to kmsg enter kernel messages buffer&lt;br /&gt;
 * mknod dev/loop0   b 7 0&lt;br /&gt;
 * mknod dev/tty     c 5 0   # current tty&lt;br /&gt;
 * mknod dev/tty0    c 4 0   # current virtual term&lt;br /&gt;
 * mknod dev/tty1    c 4 1   # login virtual term 1 (F1)&lt;br /&gt;
 * mknod dev/ttyS0   c 4 64  # COM1&lt;br /&gt;
 * mknod dev/ttyS1   c 4 65  # COM2&lt;br /&gt;
 * mknod dev/ttyS2   c 4 66  # COM3&lt;br /&gt;
 * mknod dev/ttyS3   c 4 67  $ COM4&lt;br /&gt;
 *&lt;br /&gt;
 * and this program compiled to /boot/initramfs-source/init&lt;br /&gt;
 *&lt;br /&gt;
 * Set kernel config option&lt;br /&gt;
 *  CONFIG_INITRAMFS_SOURCE=/boot/initramfs-source&lt;br /&gt;
 * to build the initramfs into your kernel image&lt;br /&gt;
 *  that also has builtin drivers (spl and zfs, etc).&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
#define FOOBARZ_INIT_VERSION &amp;quot;1.1.1&amp;quot;&lt;br /&gt;
#define _BSD_SOURCE&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdarg.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;fcntl.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/mount.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sysexits.h&amp;gt;&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
/* support for zpool import&lt;br /&gt;
 *&lt;br /&gt;
 * If -DINCLUDE_ZPOOL_IMPORT, then support to import a zpool is&lt;br /&gt;
 * enabled in the program. Enabling it will add many dependencies to the&lt;br /&gt;
 * compile and link; for example:&lt;br /&gt;
 *&lt;br /&gt;
 * gcc -static -DINCLUDE_ZPOOL_IMPORT \&lt;br /&gt;
 *    foobarz-init.c -include /usr/src/zfs-0.6.0-rc10/3.2.28/zfs_config.h \&lt;br /&gt;
 *   -o init \&lt;br /&gt;
 *   -I /usr/include/libspl -I /usr/include/libzfs \&lt;br /&gt;
 *   -lzfs -lnvpair -lzpool -luutil -luuid -lrt -lz -lm -lpthread \&lt;br /&gt;
 *   -I /usr/include/tirpc \&lt;br /&gt;
 *   -ltirpc&lt;br /&gt;
 *&lt;br /&gt;
 * Note that libtirpc is a drop-in replacement for the SunRPC functions that&lt;br /&gt;
 * used to be in glibc. No additional includes are needed, just the gcc -I and -l&lt;br /&gt;
 * options for tirpc.&lt;br /&gt;
 *&lt;br /&gt;
 * Otherwise, with -UINCLUDE_ZPOOL_IMPORT, the compile is just:&lt;br /&gt;
 * gcc -static foobarz-init.c -o init&lt;br /&gt;
 */&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
#include &amp;lt;libzfs.h&amp;gt;&lt;br /&gt;
#else&lt;br /&gt;
#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/stat.h&amp;gt;&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#define PARAM_REQ_NO 0&lt;br /&gt;
#define PARAM_REQ_YES 1&lt;br /&gt;
#define PARAM_SRC_DEFAULT 0&lt;br /&gt;
#define PARAM_SRC_CMDLINE 1&lt;br /&gt;
&lt;br /&gt;
void printk(char *fmt, ...) {&lt;br /&gt;
  FILE* f;&lt;br /&gt;
  int fd;&lt;br /&gt;
  va_list args;&lt;br /&gt;
&lt;br /&gt;
  f = fopen(&amp;quot;/dev/kmsg&amp;quot;, &amp;quot;w&amp;quot;);&lt;br /&gt;
  va_start(args, fmt);&lt;br /&gt;
  vfprintf(f, fmt, args);&lt;br /&gt;
  va_end(args);&lt;br /&gt;
  fflush(f);&lt;br /&gt;
  fclose(f);&lt;br /&gt;
  /* avoid flooding kmsg and having msgs suppressed; 20msgs/sec */&lt;br /&gt;
  usleep(50000);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[]) {&lt;br /&gt;
 /*** variables */&lt;br /&gt;
&lt;br /&gt;
 int i;&lt;br /&gt;
 int   fd = 0; /* file descriptor */&lt;br /&gt;
 unsigned long mountflags;&lt;br /&gt;
&lt;br /&gt;
 /* kernel command line */&lt;br /&gt;
 off_t cmdline_size;&lt;br /&gt;
 char* cmdline; /* to be malloc 4096B */&lt;br /&gt;
 char* cmdline_end;&lt;br /&gt;
 char* temp_end;&lt;br /&gt;
 char* src_msg; /* default or cmdline */&lt;br /&gt;
 int flag_param_missing = 0;&lt;br /&gt;
&lt;br /&gt;
 /* use to hold contents of a misc /proc/&amp;lt;file&amp;gt; */&lt;br /&gt;
 char* miscproc_buff; /* to be malloc 4096B */&lt;br /&gt;
 off_t miscproc_size;&lt;br /&gt;
&lt;br /&gt;
 /* note about environ, argv, and kernel cmdline for init:&lt;br /&gt;
  *   environ is not defined for init&lt;br /&gt;
  *   only argv[0] is set for init&lt;br /&gt;
  *   kernel command line parameters are accessed&lt;br /&gt;
  *   at /proc/cmdline&lt;br /&gt;
  */&lt;br /&gt;
&lt;br /&gt;
 /* kernel parameters expected to be name=value */&lt;br /&gt;
 /* do not use quotes or spaces in parameters   */&lt;br /&gt;
 /* you can add more params somwhere after root= */&lt;br /&gt;
 struct nv { char* n; char* v; char* v_end; int req; int src; };&lt;br /&gt;
 struct nv param[] = {&lt;br /&gt;
   { &amp;quot;root=&amp;quot;,       NULL, NULL, PARAM_REQ_YES, PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;rootfstype=&amp;quot;, NULL, NULL, PARAM_REQ_YES, PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;mountopt=&amp;quot;,   NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;init=&amp;quot;,       NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;runlevel=&amp;quot;,   NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;console=&amp;quot;,    NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT }&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
   ,&lt;br /&gt;
   { &amp;quot;zpool_import_name=&amp;quot;,    NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;zpool_import_guid=&amp;quot;,    NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;zpool_import_newname=&amp;quot;, NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;zpool_import_force=&amp;quot;,   NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT }&lt;br /&gt;
#endif&lt;br /&gt;
 };&lt;br /&gt;
 enum {&lt;br /&gt;
	 iroot,&lt;br /&gt;
	 irootfstype,&lt;br /&gt;
	 imountopt,&lt;br /&gt;
	 iinit,&lt;br /&gt;
	 irunlevel,&lt;br /&gt;
	 iconsole,&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
	 izpool_import_name,&lt;br /&gt;
	 izpool_import_guid,&lt;br /&gt;
	 izpool_import_newname,&lt;br /&gt;
	 izpool_import_force,&lt;br /&gt;
#endif&lt;br /&gt;
	 ilastparam&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
 libzfs_handle_t* libzfs = NULL;&lt;br /&gt;
 importargs_t iargs = { 0 };&lt;br /&gt;
 nvlist_t* pools = NULL;&lt;br /&gt;
 nvpair_t* pool = NULL;&lt;br /&gt;
 nvlist_t* config = NULL;&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
 /*** program */&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;foobarz-init, version %s: booting initramfs.\n&amp;quot;, FOOBARZ_INIT_VERSION);&lt;br /&gt;
&lt;br /&gt;
 cmdline       = (char*) malloc(4096);&lt;br /&gt;
 miscproc_buff = (char*) malloc(4096);&lt;br /&gt;
 if( (cmdline == NULL) || (miscproc_buff == NULL) ) {&lt;br /&gt;
   printk(&amp;quot;Unable to allocate buffer memory: malloc: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount proc /proc&lt;br /&gt;
  *  note: some /dev devices symlink into /proc&lt;br /&gt;
  *  proc contains info about processes, including cmdline etc. */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount proc /proc\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;proc&amp;quot;, &amp;quot;/proc&amp;quot;, &amp;quot;proc&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
   printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
   printk(&amp;quot;Mount proc successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount devtmpfs /dev&lt;br /&gt;
  *  note: This simple init program works if your root device is made from devices&lt;br /&gt;
  *  that are available by default in devtmpfs, such as /dev/sd*&lt;br /&gt;
  *&lt;br /&gt;
  *  For zfs, your root zfs pool should be created with default device nodes and&lt;br /&gt;
  *  then it should be mountable by this simple init program.&lt;br /&gt;
  *&lt;br /&gt;
  *  udev may be needed to configure device nodes and symlinks required&lt;br /&gt;
  *  to access a root device configuration made with such nodes and symlinks.&lt;br /&gt;
  *  If you need udevd, you can include it into your initramfs-source and&lt;br /&gt;
  *  modify this program to run it before attempting to mount your root device.&lt;br /&gt;
  *  However, if udevd is needed, a significant number of userspace programs may also be&lt;br /&gt;
  *  required by rules in /lib/udev/. You could install busybox + udev (about 5MB) or&lt;br /&gt;
  *  coreutils + util-linux + bash + udev (about 25MB) into initramfs-source. But, at that&lt;br /&gt;
  *  point you'd have ash or bash and many tools that are easier to use than this&lt;br /&gt;
  *  simple init program; it would then be easy to have /init as #!/bin/&amp;lt;b&amp;gt;ash script. */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount devtmpfs /dev\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;devtmpfs&amp;quot;, &amp;quot;/dev&amp;quot;, &amp;quot;devtmpfs&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
   printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
   printk(&amp;quot;Mount devtmpfs successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount sysfs /sys&lt;br /&gt;
  *  note: some kernel modules try to access /sys with userspace helpers to echo values into /sys variables;&lt;br /&gt;
  *  such modules expect a minimal userspace that contains coreutils or busybox */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount sysfs /sys\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;sysfs&amp;quot;, &amp;quot;/sys&amp;quot;, &amp;quot;sysfs&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
   printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
   printk(&amp;quot;Mount sysfs successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* process kernel command line */&lt;br /&gt;
 fd = open(&amp;quot;/proc/cmdline&amp;quot;, O_RDONLY);&lt;br /&gt;
 if( fd == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Cannot open /proc/cmdline: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 /* note, on /proc fs:&lt;br /&gt;
  *       lseek likely always returns error&lt;br /&gt;
  *       stat likely always returns st_size = 0&lt;br /&gt;
  *   so determining size of /proc file means just reading it;&lt;br /&gt;
  *   you have to read /proc files according to their documented&lt;br /&gt;
  *   maximum sizes; this is probably for performance reasons */&lt;br /&gt;
 cmdline_size = read(fd, cmdline, 4095);&lt;br /&gt;
 if( cmdline_size == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Failed to read /proc/cmdline: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 close(fd);&lt;br /&gt;
&lt;br /&gt;
 /* cmdline may be newline + null terminated, but make it null + null */&lt;br /&gt;
 cmdline[cmdline_size] = '\0';&lt;br /&gt;
 if( cmdline[cmdline_size-1] == '\n' ) {&lt;br /&gt;
   cmdline[cmdline_size-1] = '\0';&lt;br /&gt;
   cmdline_size--;&lt;br /&gt;
   cmdline_end = cmdline + cmdline_size;&lt;br /&gt;
 }&lt;br /&gt;
 printk(&amp;quot;Kernel cmdline size: %i\n&amp;quot;, cmdline_size);&lt;br /&gt;
 printk(&amp;quot;Kernel cmdline: \&amp;quot;%s\&amp;quot;\n&amp;quot;, cmdline);&lt;br /&gt;
&lt;br /&gt;
 /* find v and v_end of values in cmdline */&lt;br /&gt;
 for( i=iroot; i&amp;lt;ilastparam; i++ ) {&lt;br /&gt;
   param[i].v = strstr(cmdline, param[i].n);&lt;br /&gt;
   if( param[i].v != NULL ) {&lt;br /&gt;
     param[i].src = PARAM_SRC_CMDLINE;&lt;br /&gt;
     while( *(param[i].v) != '=' ) param[i].v++;&lt;br /&gt;
     param[i].v++;&lt;br /&gt;
     temp_end = param[i].v;&lt;br /&gt;
     while( !( (*temp_end == ' ') ||&lt;br /&gt;
               (*temp_end == '\n') ||&lt;br /&gt;
               (temp_end == cmdline_end)&lt;br /&gt;
	     ) ) temp_end++;&lt;br /&gt;
     if( temp_end == param[i].v ) {&lt;br /&gt;
       printk(&amp;quot;Kernel parameter %s: value missing.\n&amp;quot;, param[i].n);&lt;br /&gt;
       param[i].v = NULL;&lt;br /&gt;
     } else param[i].v_end = temp_end;&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 for( i=iroot; i&amp;lt;ilastparam; i++ ) {&lt;br /&gt;
   /* terminate value strings */&lt;br /&gt;
   if( param[i].v_end != NULL ) *(param[i].v_end) = '\0';&lt;br /&gt;
   /* set defaults if no value on cmdline */&lt;br /&gt;
   if( param[i].v == NULL ) {&lt;br /&gt;
     param[i].src = PARAM_SRC_DEFAULT;&lt;br /&gt;
     if( param[i].req == PARAM_REQ_YES ) flag_param_missing = 1;&lt;br /&gt;
     switch(i) {&lt;br /&gt;
       case iroot      : param[i].v = &amp;quot;&amp;lt;missing required param&amp;gt;&amp;quot; ; break;&lt;br /&gt;
       case irootfstype: param[i].v = &amp;quot;&amp;lt;missing required param&amp;gt;&amp;quot; ; break;&lt;br /&gt;
       case imountopt  : param[i].v = &amp;quot;ro&amp;quot;        ; break;&lt;br /&gt;
       case iinit      : param[i].v = &amp;quot;/sbin/init&amp;quot;; break;&lt;br /&gt;
       case irunlevel  : param[i].v = &amp;quot;3&amp;quot;         ; break;&lt;br /&gt;
       case iconsole   : param[i].v = &amp;quot;console&amp;quot;   ; break;&lt;br /&gt;
       default         : param[i].v = NULL;&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
   if(param[i].src == PARAM_SRC_DEFAULT) src_msg = &amp;quot;default&amp;quot;;&lt;br /&gt;
   else src_msg = &amp;quot;cmdline&amp;quot;;&lt;br /&gt;
   printk(&amp;quot;Using %s \&amp;quot;%s\&amp;quot; (source: %s)\n&amp;quot;, param[i].n, param[i].v, src_msg);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 if( flag_param_missing ) {&lt;br /&gt;
   printk(&amp;quot;Aborting boot process: missing required kernel parameter(s).\n&amp;quot;);&lt;br /&gt;
   return EX_USAGE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* generic nv pair kernel cmdline processing finished&lt;br /&gt;
  *  now, examine specific params for defaults and correctness */&lt;br /&gt;
&lt;br /&gt;
 /* param[irootfstype]: can be checked against /proc/filesystems: */&lt;br /&gt;
 fd = open(&amp;quot;/proc/filesystems&amp;quot;, O_RDONLY);&lt;br /&gt;
 if( fd == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Cannot open /proc/filesystems: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 miscproc_size = read(fd, miscproc_buff, 4095);&lt;br /&gt;
 if( miscproc_size == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Failed to read /proc/filesystems: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 close(fd);&lt;br /&gt;
 if( strstr(miscproc_buff, param[irootfstype].v) == NULL ) {&lt;br /&gt;
   printk(&amp;quot;%s \&amp;quot;%s\&amp;quot;: filesystem type not available.\n&amp;quot;, param[irootfstype].n, param[irootfstype].v);&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* zfs-specific */&lt;br /&gt;
 if( strcmp(param[irootfstype].v, &amp;quot;zfs&amp;quot;) == 0 ) {&lt;br /&gt;
   if( access(&amp;quot;/etc/zfs/zpool.cache&amp;quot;, F_OK) == 0 )&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/zfs/zpool.cache is present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
   else&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/zfs/zpool.cache not present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
&lt;br /&gt;
   if( access(&amp;quot;/etc/hostid&amp;quot;, F_OK) == 0 )&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/hostid is present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
   else&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/hostid not present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
&lt;br /&gt;
#if defined(INCLUDE_ZPOOL_IMPORT)&lt;br /&gt;
   /* zpool import */&lt;br /&gt;
   if( (param[izpool_import_name].v != NULL) || (param[izpool_import_guid].v != NULL) ) {&lt;br /&gt;
	printk(&amp;quot;zpool_import: import requested.\n&amp;quot;);&lt;br /&gt;
	if( (param[izpool_import_name].v != NULL) &amp;amp;&amp;amp; (param[izpool_import_guid].v != NULL) ) {&lt;br /&gt;
		printk(&amp;quot;zpool_import: given both pool name and guid; using guid.\n&amp;quot;);&lt;br /&gt;
		param[izpool_import_name].v = NULL;&lt;br /&gt;
	}&lt;br /&gt;
	if( param[izpool_import_name].v != NULL )&lt;br /&gt;
		printk(&amp;quot;zpool_import: pool name: %s\n&amp;quot;, param[izpool_import_name].v );&lt;br /&gt;
	else&lt;br /&gt;
		printk(&amp;quot;zpool_import: pool guid: %s\n&amp;quot;, param[izpool_import_guid].v );&lt;br /&gt;
&lt;br /&gt;
	iargs.path = NULL;&lt;br /&gt;
	iargs.paths = 0;&lt;br /&gt;
	iargs.poolname = param[izpool_import_name].v;&lt;br /&gt;
	if( param[izpool_import_guid].v != NULL )&lt;br /&gt;
		iargs.guid = strtoull(param[izpool_import_guid].v, NULL, 10);&lt;br /&gt;
	else&lt;br /&gt;
		iargs.guid = 0;&lt;br /&gt;
	iargs.cachefile = NULL;&lt;br /&gt;
	if( (param[izpool_import_force].v != NULL) &amp;amp;&amp;amp; (strcmp(param[izpool_import_force].v, &amp;quot;1&amp;quot;) == 0) ) {&lt;br /&gt;
		iargs.can_be_active = 1;&lt;br /&gt;
		printk(&amp;quot;zpool_import: import forced.\n&amp;quot;);&lt;br /&gt;
	} else {&lt;br /&gt;
		iargs.can_be_active = 0;&lt;br /&gt;
		printk(&amp;quot;zpool_import: import not forced.\n&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
	iargs.unique = 1;&lt;br /&gt;
	iargs.exists = 1;&lt;br /&gt;
&lt;br /&gt;
	printk(&amp;quot;zpool_import: init libzfs.\n&amp;quot;);&lt;br /&gt;
	libzfs = libzfs_init();&lt;br /&gt;
	printk(&amp;quot;zpool_import: searching for pool.\n&amp;quot;);&lt;br /&gt;
	pools = zpool_search_import(libzfs, &amp;amp;iargs);&lt;br /&gt;
	if( (pools == NULL) || nvlist_empty(pools) )&lt;br /&gt;
		printk(&amp;quot;zpool_import: pool not available for import, or already imported by cachefile.\n&amp;quot;);&lt;br /&gt;
	else {&lt;br /&gt;
		printk(&amp;quot;zpool_import: getting pool information.\n&amp;quot;);&lt;br /&gt;
		pool = nvlist_next_nvpair(pools, pool);&lt;br /&gt;
		printk(&amp;quot;zpool_import: getting pool configuration.\n&amp;quot;);&lt;br /&gt;
		nvpair_value_nvlist(pool, &amp;amp;config);&lt;br /&gt;
		printk(&amp;quot;zpool_import: attempting pool import.\n&amp;quot;);&lt;br /&gt;
		if( zpool_import(libzfs, config, param[izpool_import_newname].v, NULL) != 0 ) {&lt;br /&gt;
			printk(&amp;quot;zpool_import: import failed.\n&amp;quot;);&lt;br /&gt;
			printk(&amp;quot;zpool_import: error description: %s\n&amp;quot;, libzfs_error_description(libzfs) );&lt;br /&gt;
			printk(&amp;quot;zpool_import: error action: %s\n&amp;quot;, libzfs_error_action(libzfs) );&lt;br /&gt;
		} else  printk(&amp;quot;zpool_import: import successful.\n&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
	printk(&amp;quot;zpool_import: fini libzfs.\n&amp;quot;);&lt;br /&gt;
	libzfs_fini(libzfs);&lt;br /&gt;
   }&lt;br /&gt;
#endif /* zpool_import */&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 if(      strcmp(param[imountopt].v, &amp;quot;ro&amp;quot;) == 0 ) mountflags = MS_RDONLY;&lt;br /&gt;
 else if( strcmp(param[imountopt].v, &amp;quot;rw&amp;quot;) == 0 ) mountflags = 0;&lt;br /&gt;
 else {&lt;br /&gt;
   printk(&amp;quot;%s \&amp;quot;%s\&amp;quot;: invalid parameter value; defaulting to \&amp;quot;ro\&amp;quot;.\n&amp;quot;, param[imountopt].n, param[imountopt].v);&lt;br /&gt;
   mountflags = MS_RDONLY;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* param[iroot]: nothing to check; if user gives bad root=device then mount fails */&lt;br /&gt;
&lt;br /&gt;
 /* try to mount root=device at /mnt&lt;br /&gt;
  *&lt;br /&gt;
  * note: for zfs, if a copy of /etc/zfs/zpool.cache (when pool is imported) is put in initramfs-source, then&lt;br /&gt;
  * the zfs module can read it and automatically import the pools described in the cache file; the imported&lt;br /&gt;
  * pools can be available to mount here if they were created using standard device names, otherwise&lt;br /&gt;
  * udevd may be required to run before mounting the pool */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount -t %s -o %s %s /mnt.\n&amp;quot;, param[irootfstype].v, param[imountopt].v, param[iroot].v);&lt;br /&gt;
 if( mount(param[iroot].v, &amp;quot;/mnt&amp;quot;, param[irootfstype].v, mountflags, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 printk(&amp;quot;%s mounted successfully.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
&lt;br /&gt;
 /* check to see if the mounted root filesystem has an executable init program */&lt;br /&gt;
 chdir(&amp;quot;/mnt&amp;quot;);&lt;br /&gt;
 if( access(param[iinit].v+1, X_OK) != 0 ) {&lt;br /&gt;
   chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
   printk(&amp;quot;access X_OK: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   printk(&amp;quot;The init program /mnt/%s is not present or not executable.\n&amp;quot;, param[iinit].v+1);&lt;br /&gt;
   printk(&amp;quot;Aborting boot process: no init program.\n&amp;quot;);&lt;br /&gt;
   printk(&amp;quot;Unmounting %s.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
   if( umount(&amp;quot;/mnt&amp;quot;) == -1 ) {&lt;br /&gt;
     printk(&amp;quot;umount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
     printk(&amp;quot;Failed to umount %s.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
   } else printk(&amp;quot;Successfully unmounted %s.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
 printk(&amp;quot;Init program /mnt/%s is present and executable.\n&amp;quot;, param[iinit].v+1);&lt;br /&gt;
&lt;br /&gt;
 /* switch the root / from initramfs to the mounted new root device at /mnt.&lt;br /&gt;
  *&lt;br /&gt;
  * note: after this switch, it is not possible to access the initramfs files anymore,&lt;br /&gt;
  * yet they consume ram memory unless they are deleted here before switching.&lt;br /&gt;
  * Any programs that are run after clearing the initramfs and switching root must exist on the new root.&lt;br /&gt;
  * This program may safely delete itself (/init) since it is already in ram and executing.&lt;br /&gt;
  * If you have installed additional files and programs in initramfs that consume significant ram,&lt;br /&gt;
  * then you need to insert additional code here to delete those files (carefully). */&lt;br /&gt;
&lt;br /&gt;
 /* delete files off of initramfs to free ram memory */&lt;br /&gt;
 printk(&amp;quot;Freeing memory from initramfs...\n&amp;quot;);&lt;br /&gt;
 if( unlink(argv[0]) != 0 ) printk(&amp;quot;unlink %s: %s\n&amp;quot;, argv[0], strerror(errno));&lt;br /&gt;
 else printk(&amp;quot;%s %s&amp;quot;, argv[0], &amp;quot;deleted from initramfs.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 /* switch root */&lt;br /&gt;
 printk(&amp;quot;Beginning switch root procedure.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(1) Attempting cmd: mount --move /dev /mnt/dev \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/dev&amp;quot;, &amp;quot;/mnt/dev&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(2) Attempting cmd: mount --move /proc /mnt/proc \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/proc&amp;quot;, &amp;quot;/mnt/proc&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(3) Attempting cmd: mount --move /sys /mnt/sys \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/sys&amp;quot;, &amp;quot;/mnt/sys&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(4) Attempting cmd: chdir /mnt \n&amp;quot;);&lt;br /&gt;
 if( chdir(&amp;quot;/mnt&amp;quot;) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: chdir: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(5) Attempting cmd: mount --move . / \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;.&amp;quot;, &amp;quot;/&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(6) Attempting cmd: chroot . \n&amp;quot;);&lt;br /&gt;
 if( chroot(&amp;quot;.&amp;quot;) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: chroot: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(7) Attempting cmd: chdir / \n&amp;quot;);&lt;br /&gt;
 if( chdir(&amp;quot;/&amp;quot;) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: chdir: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 printk(&amp;quot;Completed switch root procedure.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 /* check for &amp;quot;console=&amp;quot; kernel parameter and switch&lt;br /&gt;
  *  stdin, stdout, and stderr to named console device&lt;br /&gt;
  */&lt;br /&gt;
 if( param[iconsole].src == PARAM_SRC_CMDLINE ) {&lt;br /&gt;
   printk(&amp;quot;Console redirection to device %s requested.\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
   /* expect only basename of console device (e.g., ttyS0), so chdir /dev */&lt;br /&gt;
   chdir(&amp;quot;/dev&amp;quot;);&lt;br /&gt;
   if( access(param[iconsole].v, F_OK ) == 0 ) {&lt;br /&gt;
     printk(&amp;quot;Opening stdin, stdout, and stderr on %s.\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
     close(0);&lt;br /&gt;
     open(param[iconsole].v, O_RDWR);&lt;br /&gt;
     dup2(0, 1);&lt;br /&gt;
     dup2(0, 2);&lt;br /&gt;
   } else {&lt;br /&gt;
     printk(&amp;quot;access F_OK: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
     printk(&amp;quot;Could not access device: %s!\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
     printk(&amp;quot;Console redirection to device %s aborted!\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
   }&lt;br /&gt;
   chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;Execing: \&amp;quot;%s %s\&amp;quot; to boot mounted root system.\n&amp;quot;, param[iinit].v, param[irunlevel].v);&lt;br /&gt;
&lt;br /&gt;
 /* free resources held to this point */&lt;br /&gt;
 free(cmdline);&lt;br /&gt;
 free(miscproc_buff);&lt;br /&gt;
&lt;br /&gt;
 if( execl(param[iinit].v, param[irunlevel].v, (char *) NULL ) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: execl: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
EOF&lt;br /&gt;
## end of rootfs /init&lt;br /&gt;
&lt;br /&gt;
# If foobarz-init is updated, you can find the latest version at:&lt;br /&gt;
# https://github.com/foobarz/foobarz-init&lt;br /&gt;
&lt;br /&gt;
# The foobarz-init program can be compiled two ways as of v1.1.1:&lt;br /&gt;
# First, the simple compile that does not support zpool_import but does support importing pools using a /etc/zfs/zpool.cache file in the initramfs:&lt;br /&gt;
&lt;br /&gt;
gcc --static init.c -o init&lt;br /&gt;
strip init&lt;br /&gt;
&lt;br /&gt;
# The second way to compile it adds support for zpool_import so that you do not have to include a /etc/zfs/zpool.cache file, but instead&lt;br /&gt;
# would add a kernel parameter: zpool_import_name=zfs-root, or zpool_import_guid=&amp;lt;guid of zfs-root&amp;gt;.&lt;br /&gt;
# You can import the root pool with a different name by also using zpool_import_newname=rpool.&lt;br /&gt;
# However you import, kernel param root=&amp;lt;your root pool name or newname&amp;gt; needs to be given also.&lt;br /&gt;
# The zpool_import only imports, it does not mount. What to mount is still told using root= and rootfstype=.&lt;br /&gt;
#&lt;br /&gt;
# If the import is not working, zpool_import_force=1 can be used to force it.&lt;br /&gt;
#&lt;br /&gt;
# This second way also requires you to install libtirpc first. Now here is an example gcc line:&lt;br /&gt;
&lt;br /&gt;
gcc -static -DINCLUDE_ZPOOL_IMPORT \&lt;br /&gt;
     foobarz-init.c -include /usr/src/zfs-0.6.0-rc10/3.2.28/zfs_config.h \&lt;br /&gt;
    -o init \&lt;br /&gt;
    -I /usr/include/libspl -I /usr/include/libzfs \&lt;br /&gt;
    -lzfs -lnvpair -lzpool -luutil -luuid -lrt -lz -lm -lpthread \&lt;br /&gt;
    -I /usr/include/tirpc \&lt;br /&gt;
    -ltirpc&lt;br /&gt;
&lt;br /&gt;
strip init&lt;br /&gt;
cp init /boot/initramfs-source/init&lt;br /&gt;
&lt;br /&gt;
## build and install kernel&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make -j8&lt;br /&gt;
make -j8 modules_install&lt;br /&gt;
cp arch/x86/boot/bzImage /boot/vm3.2.27b&lt;br /&gt;
cp System.map /boot/System.map-vm3.2.27b&lt;br /&gt;
# add new lilo menu entry for vm3.2.27b kernel&lt;br /&gt;
vi /etc/lilo.conf&lt;br /&gt;
  image = /boot/vm3.2.27b&lt;br /&gt;
   label = vm3.2.27b&lt;br /&gt;
   addappend = &amp;quot; spl.spl_hostid=0x007f0100 zfs.spa_config_path=/etc/zfs/zpool.cache root=zfs-root rootfstype=zfs&amp;quot;&lt;br /&gt;
lilo&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notes on kernel params (lilo append and addappend lines): root= and rootfstype= are used by both foorbarz-init and mkinitrd. The &amp;quot;ro&amp;quot; param is not used by foobarz-init, so instead use: mountopt=ro|rw. See &amp;quot;modinfo spl&amp;quot; and &amp;quot;modinfo zfs&amp;quot; to see all of the options those modules can take on the kernel command line.&lt;br /&gt;
&lt;br /&gt;
Notes on the spl and zfs packages to install: If you have errors using zfs and zpool commands on booted system with builtin modules, then upgrade/switch to the 0.6.0rc10_3.2.27b builds, or you can make a custom package with the binaries renamed like zpoolb, zfsb etc for builtin.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
Using qemu's -nographic serial console (/usr/share/qemu/sgabios.bin): If you have a boot problem, you might want to run in qemu's -nographic console mode:&lt;br /&gt;
&lt;br /&gt;
First, edit /etc/inittab, and uncomment the line for local serial ports runlevel &amp;quot;s1&amp;quot; (ttyS0) for serial console login support. This is done in the guest (host does not need this):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Local serial lines:&lt;br /&gt;
s1:12345:respawn:/sbin/agetty -L ttyS0 38400 linux&lt;br /&gt;
#s1:12345:respawn:/sbin/agetty -L ttyS0 9600 vt100&lt;br /&gt;
#s2:12345:respawn:/sbin/agetty -L ttyS1 9600 vt100&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Second, edit /etc/securetty, and uncomment ttyS0 line:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ttyS0&lt;br /&gt;
#ttyS1&lt;br /&gt;
# ...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
You cannot login on ttyS0 without this change even though you get the login prompt!&lt;br /&gt;
&lt;br /&gt;
Then, run qemu such as:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
qemu-kvm &amp;lt;all regular options&amp;gt; -nographic -option-rom sgabios.bin,bootindex=0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Wait for the lilo prompt, it may take several seconds show up in this mode.&lt;br /&gt;
&lt;br /&gt;
In the lilo menu, select your kernel image with builtin spl/zfs, and use kernel params such as:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
boot: vm3.2.27b console=ttyS0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
At the lilo prompt, use kernel parameter: console=ttyS0 (do NOT say /dev/ttS0). Passing runlevel=s1 does not appear to be necessary.&lt;br /&gt;
&lt;br /&gt;
When you are in qemu's serial mode, the interface is a little different than in the normal graphical mode: use keypresses:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ctrl-a h    # for help&lt;br /&gt;
ctrl-a c    # toggle access to (QEMU) console / back to emulation&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If you cannot get a login: prompt, try ctrl-a c, then do (QEMU) sendkey ctrl-alt-delete. This will reboot cleanly back to lilo, then you can do (QEMU) quit.&lt;br /&gt;
&lt;br /&gt;
Once you login to the guest, the terminal size needs adjustment. On your host, in another xterm sized the same as your guest console terminal, get the size of the terminal:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo $LINES&lt;br /&gt;
echo $COLUMNS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Now, back in the guest terminal of same size:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export LINES &amp;lt;lines&amp;gt;&lt;br /&gt;
export COLUMNS &amp;lt;columns&amp;gt;&lt;br /&gt;
stty cols $COLUMNS rows $LINES&lt;br /&gt;
exec bash&lt;br /&gt;
reset&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
So, you set the environment variables and also set them with stty. Then, restart bash (exec, or else it is a child shell process).&lt;br /&gt;
&lt;br /&gt;
BECAREFUL not to start qemu twice on the same ZFS guest! Two simultaneous running qemu on the same ZFS will corrupt the pool and it will NOT recover - you lose your whole installation! Before running qemu, check ps -A, look for an already running qemu process incase it somehow entered into the background!&lt;br /&gt;
&lt;br /&gt;
BECAREFUL when using -nographic ttyS0 that you are not doing commands on the HOST! Only use -nographic to see kernel problems. Use regular console of booting is working normally.&lt;br /&gt;
&lt;br /&gt;
To use the qemu -drive if=scsi option, the linux module sym53c8xx should be loaded in the guest. You may need to use the qemu option:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-option-rom 8xx_64.rom,bootindex=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The file 8xx_64.rom used to be inside qemu, but in new versions it is missing. You can download it:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
wget http://www.lsi.com/downloads/Public/Host%20Bus%20Adapters/Host%20Bus%20Adapters%20Common%20Files/lsi_bios.zip&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Extract the zip and place 8xx_64.rom in /usr/share/qemu/.&lt;br /&gt;
&lt;br /&gt;
Good luck!&lt;/div&gt;</description>
			<pubDate>Tue, 11 Sep 2012 03:41:19 GMT</pubDate>
			<dc:creator>Foobarz</dc:creator>
			<comments>https://www.slackwiki.com/Talk:ZFS_root_(builtin)</comments>
		</item>
		<item>
			<title>ZFS root (builtin)</title>
			<link>https://www.slackwiki.com/index.php?title=ZFS_root_(builtin)&amp;diff=784</link>
			<guid isPermaLink="false">https://www.slackwiki.com/index.php?title=ZFS_root_(builtin)&amp;diff=784</guid>
			<description>&lt;p&gt;Foobarz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Tutorials]]&lt;br /&gt;
The first &amp;quot;ZFS root&amp;quot; wiki explains the details of running ZFS at your root filesystem by using a fully modular generic kernel approach. Now, I can share how it can be done with the SPL and ZFS modules built into the kernel. This procedure is just an example and can use some fine tuning, but here goes:&lt;br /&gt;
&lt;br /&gt;
The steps below are to create kernel with SPL and ZFS modules builtin. This kernel will be installed as an alternatve kernel to boot in lilo, and it will have a separate kernel installation from the fully modular and working system kernel. This will allow testing the builtin kernel while able to boot back onto a working modular ZFS system. We start this procedure assuming you are on a working fully modular ZFS install as in the &amp;quot;ZFS root&amp;quot; wiki.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=legacy zfs-root&lt;br /&gt;
# use legacy so zfs will not expect zfs mount, but instead expect standard mount for this fs&lt;br /&gt;
# edit /etc/rc.d/rc.S and rc.6 to use regular &amp;quot;mount&amp;quot; commands, remove &amp;quot;zfs&amp;quot; commands&lt;br /&gt;
# edit rc.6 and remove or comment out zfs export command&lt;br /&gt;
&lt;br /&gt;
# You might think to set bootfs property like this:&lt;br /&gt;
#  zpool set bootfs=zfs-root zfs-root&lt;br /&gt;
# however, this will result in ZFS placing many restrictions on zfs-root as per how that option&lt;br /&gt;
#  is used on Solaris systems:&lt;br /&gt;
#  * zfs-root must be VTOC (SMI) label, not GPT (EFI) label&lt;br /&gt;
#  * zfs-root can only contain 1 vdev: either a plain disk, or a mirror&lt;br /&gt;
# so, do not set that property!&lt;br /&gt;
# If bootfs is set, you would find that you cannot add vdevs to your zfs-root.&lt;br /&gt;
# If it is set already, then unset it like this:&lt;br /&gt;
#  zpool set bootfs= zfs-root&lt;br /&gt;
&lt;br /&gt;
mkdir /boot/initramfs-source&lt;br /&gt;
# this will hold some files for rootfs inside kernel&lt;br /&gt;
&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir src&lt;br /&gt;
cd src&lt;br /&gt;
tar xvzf /mnt/cdrom/slackware64/k/kernel-source-*.txz&lt;br /&gt;
mv usr/src/linux-3.2.27 /usr/src/linux-3.2.27b&lt;br /&gt;
rm -r install&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make menuconfig&lt;br /&gt;
  General setup-&amp;gt;Local version - append to kernel release = b&lt;br /&gt;
  General setup-&amp;gt;Default hostname                         = slackzfs&lt;br /&gt;
  General setup-&amp;gt;Initramfs source files(s)                = /boot/initramfs-source&lt;br /&gt;
  #  make usre you made this directory or the kernel build fails&lt;br /&gt;
  Device Drivers-&amp;gt;SCSI device support-&amp;gt;SCSI low-level drivers-&amp;gt; &amp;lt;*&amp;gt; SYM53C8XX Version 2 SCSI support&lt;br /&gt;
  #  for qemu if=scsi -option-rom 8xx_64.rom,bootindex=1  hard disks&lt;br /&gt;
  # buildin any hard drive controllers etc that you need&lt;br /&gt;
  File systems -&amp;gt; &amp;lt;*&amp;gt; The Extended 4 (ext4) filesystem&lt;br /&gt;
  # /boot may use this ext4 fs&lt;br /&gt;
make prepare scripts&lt;br /&gt;
# this make command is what the spl and zfs copy-builtin scripts expect to be done before they are run&lt;br /&gt;
&lt;br /&gt;
cd ~/src&lt;br /&gt;
tar xvzf ~/spl-0.6.0-rc10.tar.gz&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-0.6.0-rc10&lt;br /&gt;
./configure \&lt;br /&gt;
    --prefix=/ \&lt;br /&gt;
    --libdir=/lib64 \&lt;br /&gt;
    --includedir=/usr/include \&lt;br /&gt;
    --datarootdir=/usr/share \&lt;br /&gt;
    --enable-linux-builtin=yes \&lt;br /&gt;
    --with-linux=/usr/src/linux-3.2.27b \&lt;br /&gt;
    --with-linux-obj=/usr/src/linux-3.2.27b&lt;br /&gt;
wget https://raw.github.com/zfsonlinux/spl/master/copy-builtin&lt;br /&gt;
chmod +x copy-builtin&lt;br /&gt;
./copy-builtin /usr/src/linux-3.2.27b&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../spl-0.6.0rc10_3.2.27b-x86_64-1root.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
&lt;br /&gt;
tar xvzf ~/zfs-0.6.0-rc10.tar.gz&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-0.6.0-rc10&lt;br /&gt;
./configure \&lt;br /&gt;
    --prefix=/ \&lt;br /&gt;
    --libdir=/lib64 \&lt;br /&gt;
    --includedir=/usr/include \&lt;br /&gt;
    --datarootdir=/usr/share \&lt;br /&gt;
    --enable-linux-builtin=yes \&lt;br /&gt;
    --with-linux=/usr/src/linux-3.2.27b \&lt;br /&gt;
    --with-linux-obj=/usr/src/linux-3.2.27b \&lt;br /&gt;
    --with-spl=/root/src/spl-0.6.0-rc10&lt;br /&gt;
wget https://raw.github.com/zfsonlinux/zfs/master/copy-builtin&lt;br /&gt;
chmod +x copy-builtin&lt;br /&gt;
./copy-builtin /usr/src/linux-3.2.27b&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../zfs-0.6.0rc10_3.2.27b-x86_64-1root.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
&lt;br /&gt;
### move zfs and spl modules inside kernel source to be at end of drivers:&lt;br /&gt;
### the order builtin modules init is the order they link into the kernel&lt;br /&gt;
### and we need zfs to init after all hard drive controllers&lt;br /&gt;
### zfs is more like a device driver layer over the lower-level hba drivers&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
mkdir drivers/zfsonlinux&lt;br /&gt;
mv spl drivers/zfsonlinux&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  # remove references to spl&lt;br /&gt;
vi Makefile&lt;br /&gt;
  # remove references to spl&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/fs&lt;br /&gt;
mv zfs ../drivers/zfsonlinux&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  # remove references to zfs&lt;br /&gt;
vi Makefile&lt;br /&gt;
  # remove references to zfs&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  )# add line at end of menu, before &amp;quot;endmenu&amp;quot;:&lt;br /&gt;
  )source &amp;quot;drivers/zfsonlinux/Kconfig&amp;quot;&lt;br /&gt;
  )endmenu&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers&lt;br /&gt;
vi Makefile&lt;br /&gt;
  )# add line at very end of file:&lt;br /&gt;
  )obj-$(CONFIG_ZFSONLINUX) += zfsonlinux/&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers/zfsonlinux&lt;br /&gt;
cat &amp;gt; Kconfig &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
menuconfig ZFSONLINUX&lt;br /&gt;
	tristate &amp;quot;ZFSonLinux support&amp;quot;&lt;br /&gt;
&lt;br /&gt;
if ZFSONLINUX&lt;br /&gt;
&lt;br /&gt;
source &amp;quot;drivers/zfsonlinux/spl/Kconifg&amp;quot;&lt;br /&gt;
&lt;br /&gt;
source &amp;quot;drivers/zfsonlinux/zfs/Kconifg&amp;quot;&lt;br /&gt;
&lt;br /&gt;
endif&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/zfsonlinux&lt;br /&gt;
cat &amp;gt; Makefile &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
obj-$(CONFIG_SPL) += spl/&lt;br /&gt;
obj-$(CONFIG_ZFS) += zfs/&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
### move complete&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make menuconfig&lt;br /&gt;
   Device Drivers -&amp;gt;&lt;br /&gt;
    &amp;lt;*&amp;gt; ZFSonLinux support -&amp;gt;&lt;br /&gt;
      &amp;lt;*&amp;gt; Solaris Porting Layer (SPL)&lt;br /&gt;
      &amp;lt;*&amp;gt;     ZFS&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
### prepare contents of initramfs&lt;br /&gt;
cd /boot/initramfs-source&lt;br /&gt;
&lt;br /&gt;
# make standard directories&lt;br /&gt;
mkdir -p proc dev sys mnt bin sbin etc/zfs&lt;br /&gt;
&lt;br /&gt;
# zfs seems to want mtab present, even if empty&lt;br /&gt;
touch etc/mtab&lt;br /&gt;
&lt;br /&gt;
# if zpool.cache file can be read by zfs at module init, it imports the pools in the cache&lt;br /&gt;
cp /etc/zfs/zpool.cache-initrd etc/zfs/zpool.cache&lt;br /&gt;
&lt;br /&gt;
# make initial console device node; otherwise, there is a problem at startup:&lt;br /&gt;
# &amp;quot;Warning: unable to open an initial console&amp;quot; and you'd have problems with console and tty login&lt;br /&gt;
# making these nodes from within /init is not early enough to avoid problem&lt;br /&gt;
mknod dev/console c 5 1   # system console&lt;br /&gt;
&lt;br /&gt;
# make memory device kmsg to &amp;quot;printk&amp;quot; kernel messages&lt;br /&gt;
# we can write to this file to send out messages&lt;br /&gt;
mknod dev/kmsg    c 1 11  # lines printed to kmsg enter kernel messages buffer&lt;br /&gt;
&lt;br /&gt;
# recommended loop0 device to mount fs images&lt;br /&gt;
mknod dev/loop0   b 7 0&lt;br /&gt;
&lt;br /&gt;
# make initial virtual terminal devices&lt;br /&gt;
mknod dev/tty     c 5 0   # current tty&lt;br /&gt;
mknod dev/tty0    c 4 0   # current virtual term&lt;br /&gt;
mknod dev/tty1    c 4 1   # login virtual term 1 (F1)&lt;br /&gt;
&lt;br /&gt;
# make alternative console=ttyS0 standard 8250/16550 UART serial port devices&lt;br /&gt;
#   useful with kernel parameter console=ttyS0&lt;br /&gt;
#          with qemu -nographic -option-rom sgabios.bin,bootindex=0&lt;br /&gt;
mknod dev/ttyS0   c 4 64  # COM1&lt;br /&gt;
mknod dev/ttyS1   c 4 65  # COM2&lt;br /&gt;
mknod dev/ttyS2   c 4 66  # COM3&lt;br /&gt;
mknod dev/ttyS3   c 4 67  $ COM4&lt;br /&gt;
&lt;br /&gt;
# this should be enough device nodes initially&lt;br /&gt;
# once devtmpfs mounts over /dev, a lot more is available in it by default&lt;br /&gt;
&lt;br /&gt;
cat &amp;gt; /init &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot; &amp;lt;some initial program PID=1 for the system to start on&amp;gt; EOF&lt;br /&gt;
# an initramfs-source/init program is required to mount and boot a root linux system&lt;br /&gt;
# the common way to make /init is using busybox with files like this:&lt;br /&gt;
#    /bin/busybox&lt;br /&gt;
#    /bin/ash -&amp;gt; busybox&lt;br /&gt;
#    /bin/sh -&amp;gt; busybox&lt;br /&gt;
#    # run busybox to see what other &amp;quot;applets&amp;quot; can be symlinked to it&lt;br /&gt;
#    # when busybox is run as a different symlinked applet name, it runs the applet&lt;br /&gt;
#    /init&lt;br /&gt;
#    # init is ash script, see slackware's /boot/initrd-tree/init for example&lt;br /&gt;
#    Inside this script:&lt;br /&gt;
#      1) parse kernel parameters passed into it and set variables based on them&lt;br /&gt;
#      2) start udevd and trigger rules for block devices to setup initial /dev devices&lt;br /&gt;
#      3) load kernel modules and keyboard map&lt;br /&gt;
#      4) run mdadm, cryptsetup, lvm, zpool/zfs to setup more devices&lt;br /&gt;
#         (any udev rules for them should do more /dev setup in the background)&lt;br /&gt;
#      5) mount the root filesystem read-only at /mnt&lt;br /&gt;
#      6) stat /mnt/sbin/init, and if not executable run a rescue shell /bin/sh&lt;br /&gt;
#      7) shutdown udevd so it can be restarted by root system when booted&lt;br /&gt;
#      8) mount --move {proc,sys,run,dev} to under /mnt&lt;br /&gt;
#      9) run: exec switch_root /mnt /sbin/init $RUNLEVEL&lt;br /&gt;
#    The slackware mkinitrd package is fully configured busybox installation&lt;br /&gt;
#      for an extern file initramfs initrd.gz image outside the kernel.&lt;br /&gt;
#    It could be changed to be inside the kernel easily by just using initrd-tree&lt;br /&gt;
#      as target of INITRAMFS_SOURCE in the kernel config and removing initrd in lilo.&lt;br /&gt;
&lt;br /&gt;
# Because the zfs modules are builtin, we really don't need busybox and the whole&lt;br /&gt;
# mkinitrd package. All we need to do is mount the zfs that is already imported&lt;br /&gt;
# because the zpool.cache is present in rootfs when the zfs module initializes, and&lt;br /&gt;
# then we do the switch root procedure to boot up on the mounted system.&lt;br /&gt;
# udevd rules will still be run when the root system starts udevd.&lt;br /&gt;
&lt;br /&gt;
# So, let's make a simple /init c program that will be all that we really need:&lt;br /&gt;
cat &amp;gt; init.c &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
/* software product name: foobarz-init.c&lt;br /&gt;
 * suggested binary name: /init (in initramfs-source, rootfs)&lt;br /&gt;
 * license              : BSD&lt;br /&gt;
 * license text:&lt;br /&gt;
Copyright (c) 2012, foobarz&lt;br /&gt;
All rights reserved.&lt;br /&gt;
&lt;br /&gt;
Redistribution and use in source and binary forms, with or without&lt;br /&gt;
modification, are permitted provided that the following conditions are met:&lt;br /&gt;
    * Redistributions of source code must retain the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer.&lt;br /&gt;
    * Redistributions in binary form must reproduce the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer in the&lt;br /&gt;
      documentation and/or other materials provided with the distribution.&lt;br /&gt;
    * Neither the name of the &amp;lt;organization&amp;gt; nor the&lt;br /&gt;
      names of its contributors may be used to endorse or promote products&lt;br /&gt;
      derived from this software without specific prior written permission.&lt;br /&gt;
&lt;br /&gt;
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &amp;quot;AS IS&amp;quot; AND&lt;br /&gt;
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED&lt;br /&gt;
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE&lt;br /&gt;
DISCLAIMED. IN NO EVENT SHALL &amp;lt;COPYRIGHT HOLDER&amp;gt; BE LIABLE FOR ANY&lt;br /&gt;
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES&lt;br /&gt;
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;&lt;br /&gt;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND&lt;br /&gt;
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT&lt;br /&gt;
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS&lt;br /&gt;
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#define FOOBARZ_INIT_VERSION &amp;quot;1.0.10rc1&amp;quot;&lt;br /&gt;
#define _BSD_SOURCE&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdarg.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/stat.h&amp;gt;&lt;br /&gt;
#include &amp;lt;fcntl.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/mount.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sysexits.h&amp;gt;&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define PARAM_REQ_NO 0&lt;br /&gt;
#define PARAM_REQ_YES 1&lt;br /&gt;
#define PARAM_SRC_DEFAULT 0&lt;br /&gt;
#define PARAM_SRC_CMDLINE 1&lt;br /&gt;
&lt;br /&gt;
/* Your initramfs-source should contain the following&lt;br /&gt;
 * cd /boot/initramfs-source&lt;br /&gt;
 * mkdir -p proc dev sys mnt bin sbin etc/zfs&lt;br /&gt;
 * touch etc/mtab&lt;br /&gt;
 * cp /etc/zfs/zpool.cache-initrd etc/zfs/zpool.cache&lt;br /&gt;
 * mknod dev/console c 5 1   # system console&lt;br /&gt;
 * mknod dev/kmsg    c 1 11  # lines printed to kmsg enter kernel messages buffer&lt;br /&gt;
 * mknod dev/loop0   b 7 0&lt;br /&gt;
 * mknod dev/tty     c 5 0   # current tty&lt;br /&gt;
 * mknod dev/tty0    c 4 0   # current virtual term&lt;br /&gt;
 * mknod dev/tty1    c 4 1   # login virtual term 1 (F1)&lt;br /&gt;
 * mknod dev/ttyS0   c 4 64  # COM1&lt;br /&gt;
 * mknod dev/ttyS1   c 4 65  # COM2&lt;br /&gt;
 * mknod dev/ttyS2   c 4 66  # COM3&lt;br /&gt;
 * mknod dev/ttyS3   c 4 67  $ COM4&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
void printk(char *fmt, ...) {&lt;br /&gt;
  FILE* f;&lt;br /&gt;
  int fd;&lt;br /&gt;
  va_list args;&lt;br /&gt;
&lt;br /&gt;
  f = fopen(&amp;quot;/dev/kmsg&amp;quot;, &amp;quot;w&amp;quot;);&lt;br /&gt;
  va_start(args, fmt);&lt;br /&gt;
  vfprintf(f, fmt, args);&lt;br /&gt;
  va_end(args);&lt;br /&gt;
  fflush(f);&lt;br /&gt;
  fclose(f);&lt;br /&gt;
  /* avoid flooding kmsg and having msgs suppressed; 20msgs/sec */&lt;br /&gt;
  usleep(50000);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[]) {&lt;br /&gt;
 /*** variables */&lt;br /&gt;
&lt;br /&gt;
 int i;&lt;br /&gt;
 int   fd = 0; /* file descriptor */&lt;br /&gt;
 unsigned long mountflags;&lt;br /&gt;
&lt;br /&gt;
 /* kernel command line */&lt;br /&gt;
 off_t cmdline_size;&lt;br /&gt;
 char* cmdline; /* to be malloc 4096B */&lt;br /&gt;
 char* cmdline_end;&lt;br /&gt;
 char* temp_end;&lt;br /&gt;
 char* src_msg; /* default or cmdline */&lt;br /&gt;
 int flag_param_missing = 0;&lt;br /&gt;
&lt;br /&gt;
 /* use to hold contents of a misc /proc/&amp;lt;file&amp;gt; */&lt;br /&gt;
 char* miscproc_buff; /* to be malloc 4096B */&lt;br /&gt;
 off_t miscproc_size;&lt;br /&gt;
&lt;br /&gt;
 /* note about environ, argv, and kernel cmdline for init:&lt;br /&gt;
  *   environ is not defined for init&lt;br /&gt;
  *   only argv[0] is set for init&lt;br /&gt;
  *   kernel command line parameters are accessed&lt;br /&gt;
  *   at /proc/cmdline&lt;br /&gt;
  */&lt;br /&gt;
&lt;br /&gt;
 /* kernel parameters expected to be name=value */&lt;br /&gt;
 /* do not use quotes or spaces in parameters   */&lt;br /&gt;
 /* you can add more params somwhere after root= */&lt;br /&gt;
 struct nv { char* n; char* v; char* v_end; int req; int src; };&lt;br /&gt;
 struct nv param[] = {&lt;br /&gt;
   { &amp;quot;root=&amp;quot;,       NULL, NULL, PARAM_REQ_YES, PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;rootfstype=&amp;quot;, NULL, NULL, PARAM_REQ_YES, PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;mountopt=&amp;quot;,   NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;init=&amp;quot;,       NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;runlevel=&amp;quot;,   NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;console=&amp;quot;,    NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT }&lt;br /&gt;
 };&lt;br /&gt;
 enum { iroot, irootfstype, imountopt, iinit, irunlevel, iconsole, ilastparam };&lt;br /&gt;
&lt;br /&gt;
 /*** program */&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;foobarz-init, version %s: booting initramfs.\n&amp;quot;, FOOBARZ_INIT_VERSION);&lt;br /&gt;
&lt;br /&gt;
 cmdline       = (char*) malloc(4096);&lt;br /&gt;
 miscproc_buff = (char*) malloc(4096);&lt;br /&gt;
 if( (cmdline == NULL) || (miscproc_buff == NULL) ) {&lt;br /&gt;
   printk(&amp;quot;Unable to allocate buffer memory: malloc: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount proc /proc&lt;br /&gt;
  *  note: some /dev devices symlink into /proc&lt;br /&gt;
  *  proc contains info about processes, including cmdline etc. */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount proc /proc\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;proc&amp;quot;, &amp;quot;/proc&amp;quot;, &amp;quot;proc&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
   printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
   printk(&amp;quot;Mount proc successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount devtmpfs /dev&lt;br /&gt;
  *  note: This simple init program works if your root device is made from devices&lt;br /&gt;
  *  that are available by default in devtmpfs, such as /dev/sd*&lt;br /&gt;
  *&lt;br /&gt;
  *  For zfs, your root zfs pool should be created with default device nodes and&lt;br /&gt;
  *  then it should be mountable by this simple init program.&lt;br /&gt;
  *&lt;br /&gt;
  *  udev may be needed to configure device nodes and symlinks required&lt;br /&gt;
  *  to access a root device configuration made with such nodes and symlinks.&lt;br /&gt;
  *  If you need udevd, you can include it into your initramfs-source and&lt;br /&gt;
  *  modify this program to run it before attempting to mount your root device.&lt;br /&gt;
  *  However, if udevd is needed, a significant number of userspace programs may also be&lt;br /&gt;
  *  required by rules in /lib/udev/. You could install busybox + udev (about 5MB) or&lt;br /&gt;
  *  coreutils + util-linux + bash + udev (about 25MB) into initramfs-source. But, at that&lt;br /&gt;
  *  point you'd have ash or bash and many tools that are easier to use than this&lt;br /&gt;
  *  simple init program; it would then be easy to have /init as #!/bin/&amp;lt;b&amp;gt;ash script. */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount devtmpfs /dev\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;devtmpfs&amp;quot;, &amp;quot;/dev&amp;quot;, &amp;quot;devtmpfs&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
   printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
   printk(&amp;quot;Mount devtmpfs successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount sysfs /sys&lt;br /&gt;
  *  note: some kernel modules try to access /sys with userspace helpers to echo values into /sys variables;&lt;br /&gt;
  *  such modules expect a minimal userspace that contains coreutils or busybox */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount sysfs /sys\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;sysfs&amp;quot;, &amp;quot;/sys&amp;quot;, &amp;quot;sysfs&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
   printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
   printk(&amp;quot;Mount sysfs successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* process kernel command line */&lt;br /&gt;
 fd = open(&amp;quot;/proc/cmdline&amp;quot;, O_RDONLY);&lt;br /&gt;
 if( fd == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Cannot open /proc/cmdline: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 /* note, on /proc fs:&lt;br /&gt;
  *       lseek likely always returns error&lt;br /&gt;
  *       stat likely always returns st_size = 0&lt;br /&gt;
  *   so determining size of /proc file means just reading it;&lt;br /&gt;
  *   you have to read /proc files according to their documented&lt;br /&gt;
  *   maximum sizes; this is probably for performance reasons */&lt;br /&gt;
 cmdline_size = read(fd, cmdline, 4095);&lt;br /&gt;
 if( cmdline_size == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Failed to read /proc/cmdline: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 close(fd);&lt;br /&gt;
&lt;br /&gt;
 /* cmdline may be newline + null terminated, but make it null + null */&lt;br /&gt;
 cmdline[cmdline_size] = '\0';&lt;br /&gt;
 if( cmdline[cmdline_size-1] == '\n' ) {&lt;br /&gt;
   cmdline[cmdline_size-1] = '\0';&lt;br /&gt;
   cmdline_size--;&lt;br /&gt;
   cmdline_end = cmdline + cmdline_size;&lt;br /&gt;
 }&lt;br /&gt;
 printk(&amp;quot;Kernel cmdline size: %i\n&amp;quot;, cmdline_size);&lt;br /&gt;
 printk(&amp;quot;Kernel cmdline: \&amp;quot;%s\&amp;quot;\n&amp;quot;, cmdline);&lt;br /&gt;
&lt;br /&gt;
 /* find v and v_end of values in cmdline */&lt;br /&gt;
 for( i=iroot; i&amp;lt;ilastparam; i++ ) {&lt;br /&gt;
   param[i].v = strstr(cmdline, param[i].n);&lt;br /&gt;
   if( param[i].v != NULL ) {&lt;br /&gt;
     param[i].src = PARAM_SRC_CMDLINE;&lt;br /&gt;
     while( *(param[i].v) != '=' ) param[i].v++;&lt;br /&gt;
     param[i].v++;&lt;br /&gt;
     temp_end = param[i].v;&lt;br /&gt;
     while( !( (*temp_end == ' ') ||&lt;br /&gt;
               (*temp_end == '\n') ||&lt;br /&gt;
               (temp_end == cmdline_end)&lt;br /&gt;
	     ) ) temp_end++;&lt;br /&gt;
     if( temp_end == param[i].v ) {&lt;br /&gt;
       printk(&amp;quot;Kernel parameter %s: value missing.\n&amp;quot;, param[i].n);&lt;br /&gt;
       param[i].v = NULL;&lt;br /&gt;
     } else param[i].v_end = temp_end;&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 for( i=iroot; i&amp;lt;ilastparam; i++ ) {&lt;br /&gt;
   /* terminate value strings */&lt;br /&gt;
   if( param[i].v_end != NULL ) *(param[i].v_end) = '\0';&lt;br /&gt;
   /* set defaults if no value on cmdline */&lt;br /&gt;
   if( param[i].v == NULL ) {&lt;br /&gt;
     param[i].src = PARAM_SRC_DEFAULT;&lt;br /&gt;
     if( param[i].req == PARAM_REQ_YES ) flag_param_missing = 1;&lt;br /&gt;
     switch(i) {&lt;br /&gt;
       case iroot      : param[i].v = &amp;quot;&amp;lt;missing required param&amp;gt;&amp;quot; ; break;&lt;br /&gt;
       case irootfstype: param[i].v = &amp;quot;&amp;lt;missing required param&amp;gt;&amp;quot; ; break;&lt;br /&gt;
       case imountopt  : param[i].v = &amp;quot;ro&amp;quot;        ; break;&lt;br /&gt;
       case iinit      : param[i].v = &amp;quot;/sbin/init&amp;quot;; break;&lt;br /&gt;
       case irunlevel  : param[i].v = &amp;quot;3&amp;quot;         ; break;&lt;br /&gt;
       case iconsole   : param[i].v = &amp;quot;console&amp;quot;   ; break;&lt;br /&gt;
       default         : param[i].v = &amp;quot;&amp;quot;;&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
   if(param[i].src == PARAM_SRC_DEFAULT) src_msg = &amp;quot;default&amp;quot;;&lt;br /&gt;
   else src_msg = &amp;quot;cmdline&amp;quot;;&lt;br /&gt;
   printk(&amp;quot;Using %s \&amp;quot;%s\&amp;quot; (source: %s)\n&amp;quot;, param[i].n, param[i].v, src_msg);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 if( flag_param_missing ) {&lt;br /&gt;
   printk(&amp;quot;Aborting boot process: missing required kernel parameter(s).\n&amp;quot;);&lt;br /&gt;
   return EX_USAGE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* generic nv pair kernel cmdline processing finished&lt;br /&gt;
  *  now, examine specific params for defaults and correctness */&lt;br /&gt;
&lt;br /&gt;
 /* param[irootfstype]: can be checked against /proc/filesystems: */&lt;br /&gt;
 fd = open(&amp;quot;/proc/filesystems&amp;quot;, O_RDONLY);&lt;br /&gt;
 if( fd == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Cannot open /proc/filesystems: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 miscproc_size = read(fd, miscproc_buff, 4095);&lt;br /&gt;
 if( miscproc_size == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Failed to read /proc/filesystems: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 close(fd);&lt;br /&gt;
 if( strstr(miscproc_buff, param[irootfstype].v) == NULL ) {&lt;br /&gt;
   printk(&amp;quot;%s \&amp;quot;%s\&amp;quot;: filesystem type not available.\n&amp;quot;, param[irootfstype].n, param[irootfstype].v);&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* zfs-specific informative checks */&lt;br /&gt;
 if( strcmp(param[irootfstype].v, &amp;quot;zfs&amp;quot;) == 0 ) {&lt;br /&gt;
   if( access(&amp;quot;/etc/zfs/zpool.cache&amp;quot;, F_OK) == 0 )&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/zfs/zpool.cache is present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
   else&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/zfs/zpool.cache not present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
&lt;br /&gt;
   if( access(&amp;quot;/etc/hostid&amp;quot;, F_OK) == 0 )&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/hostid is present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
   else&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/hostid not present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 if(      strcmp(param[imountopt].v, &amp;quot;ro&amp;quot;) == 0 ) mountflags = MS_RDONLY;&lt;br /&gt;
 else if( strcmp(param[imountopt].v, &amp;quot;rw&amp;quot;) == 0 ) mountflags = 0;&lt;br /&gt;
 else {&lt;br /&gt;
   printk(&amp;quot;%s \&amp;quot;%s\&amp;quot;: invalid parameter value; defaulting to \&amp;quot;ro\&amp;quot;.\n&amp;quot;, param[imountopt].n, param[imountopt].v);&lt;br /&gt;
   mountflags = MS_RDONLY;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* param[iroot]: nothing to check; if user gives bad root=device then mount fails */&lt;br /&gt;
&lt;br /&gt;
 /* try to mount root=device at /mnt&lt;br /&gt;
  *&lt;br /&gt;
  * note: for zfs, if a copy of /etc/zfs/zpool.cache (when pool is imported) is put in initramfs-source, then&lt;br /&gt;
  * the zfs module can read it and automatically import the pools described in the cache file; the imported&lt;br /&gt;
  * pools can be available to mount here if they were created using standard device names, otherwise&lt;br /&gt;
  * udevd may be required to run before mounting the pool */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount -t %s -o %s %s /mnt.\n&amp;quot;, param[irootfstype].v, param[imountopt].v, param[iroot].v);&lt;br /&gt;
 if( mount(param[iroot].v, &amp;quot;/mnt&amp;quot;, param[irootfstype].v, mountflags, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 printk(&amp;quot;%s mounted successfully.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
&lt;br /&gt;
 /* check to see if the mounted root filesystem has an executable init program */&lt;br /&gt;
 chdir(&amp;quot;/mnt&amp;quot;);&lt;br /&gt;
 if( access(param[iinit].v+1, X_OK) != 0 ) {&lt;br /&gt;
   chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
   printk(&amp;quot;access X_OK: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   printk(&amp;quot;The init program /mnt/%s is not present or not executable.\n&amp;quot;, param[iinit].v+1);&lt;br /&gt;
   printk(&amp;quot;Aborting boot process: no init program.\n&amp;quot;);&lt;br /&gt;
   printk(&amp;quot;Unmounting %s.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
   if( umount(&amp;quot;/mnt&amp;quot;) == -1 ) {&lt;br /&gt;
     printk(&amp;quot;umount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
     printk(&amp;quot;Failed to umount %s.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
   } else printk(&amp;quot;Successfully unmounted %s.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
 printk(&amp;quot;Init program /mnt/%s is present and executable.\n&amp;quot;, param[iinit].v+1);&lt;br /&gt;
&lt;br /&gt;
 /* switch the root / from initramfs to the mounted new root device at /mnt.&lt;br /&gt;
  *&lt;br /&gt;
  * note: after this switch, it is not possible to access the initramfs files anymore,&lt;br /&gt;
  * yet they consume ram memory unless they are deleted here before switching.&lt;br /&gt;
  * Any programs that are run after clearing the initramfs and switching root must exist on the new root.&lt;br /&gt;
  * This program may safely delete itself (/init) since it is already in ram and executing.&lt;br /&gt;
  * If you have installed additional files and programs in initramfs that consume significant ram,&lt;br /&gt;
  * then you need to insert additional code here to delete those files (carefully). */&lt;br /&gt;
&lt;br /&gt;
 /* delete files off of initramfs to free ram memory */&lt;br /&gt;
 printk(&amp;quot;Freeing memory from initramfs...\n&amp;quot;);&lt;br /&gt;
 if( unlink(argv[0]) != 0 ) printk(&amp;quot;unlink %s: %s\n&amp;quot;, argv[0], strerror(errno));&lt;br /&gt;
 else printk(&amp;quot;%s %s&amp;quot;, argv[0], &amp;quot;deleted from initramfs.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 /* switch root */&lt;br /&gt;
 printk(&amp;quot;Beginning switch root procedure.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(1) Attempting cmd: mount --move /dev /mnt/dev \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/dev&amp;quot;, &amp;quot;/mnt/dev&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(2) Attempting cmd: mount --move /proc /mnt/proc \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/proc&amp;quot;, &amp;quot;/mnt/proc&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(3) Attempting cmd: mount --move /sys /mnt/sys \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/sys&amp;quot;, &amp;quot;/mnt/sys&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(4) Attempting cmd: chdir /mnt \n&amp;quot;);&lt;br /&gt;
 if( chdir(&amp;quot;/mnt&amp;quot;) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: chdir: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(5) Attempting cmd: mount --move . / \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;.&amp;quot;, &amp;quot;/&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(6) Attempting cmd: chroot . \n&amp;quot;);&lt;br /&gt;
 if( chroot(&amp;quot;.&amp;quot;) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: chroot: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(7) Attempting cmd: chdir / \n&amp;quot;);&lt;br /&gt;
 if( chdir(&amp;quot;/&amp;quot;) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: chdir: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 printk(&amp;quot;Completed switch root procedure.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 /* check for &amp;quot;console=&amp;quot; kernel parameter and switch&lt;br /&gt;
  *  stdin, stdout, and stderr to named console device&lt;br /&gt;
  */&lt;br /&gt;
 if( param[iconsole].src == PARAM_SRC_CMDLINE ) {&lt;br /&gt;
   printk(&amp;quot;Console redirection to device %s requested.\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
   /* expect only basename of console device (e.g., ttyS0), so chdir /dev */&lt;br /&gt;
   chdir(&amp;quot;/dev&amp;quot;);&lt;br /&gt;
   if( access(param[iconsole].v, F_OK ) == 0 ) {&lt;br /&gt;
     printk(&amp;quot;Opening stdin, stdout, and stderr on %s.\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
     close(0);&lt;br /&gt;
     open(param[iconsole].v, O_RDWR);&lt;br /&gt;
     dup2(0, 1);&lt;br /&gt;
     dup2(0, 2);&lt;br /&gt;
   } else {&lt;br /&gt;
     printk(&amp;quot;access F_OK: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
     printk(&amp;quot;Could not access device: %s!\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
     printk(&amp;quot;Console redirection to device %s aborted!\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
   }&lt;br /&gt;
   chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;Execing: \&amp;quot;%s %s\&amp;quot; to boot mounted root system.\n&amp;quot;, param[iinit].v, param[irunlevel].v);&lt;br /&gt;
&lt;br /&gt;
 /* free resources held to this point */&lt;br /&gt;
 free(cmdline);&lt;br /&gt;
 free(miscproc_buff);&lt;br /&gt;
&lt;br /&gt;
 if( execl(param[iinit].v, param[irunlevel].v, (char *) NULL ) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: execl: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
EOF&lt;br /&gt;
## end of rootfs /init&lt;br /&gt;
&lt;br /&gt;
gcc --static init.c -o init&lt;br /&gt;
strip init&lt;br /&gt;
&lt;br /&gt;
## build and install kernel&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make -j8&lt;br /&gt;
make -j8 modules_install&lt;br /&gt;
cp arch/x86/boot/bzImage /boot/vm3.2.27b&lt;br /&gt;
cp System.map /boot/System.map-vm3.2.27b&lt;br /&gt;
# add new lilo menu entry for vm3.2.27b kernel&lt;br /&gt;
vi /etc/lilo.conf&lt;br /&gt;
  image = /boot/vm3.2.27b&lt;br /&gt;
   label = vm3.2.27b&lt;br /&gt;
   addappend = &amp;quot; spl.spl_hostid=0x007f0100 zfs.spa_config_path=/etc/zfs/zpool.cache root=zfs-root rootfstype=zfs&amp;quot;&lt;br /&gt;
lilo&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notes on kernel params (lilo append and addappend lines): root= and rootfstype= are used by both foorbarz-init and mkinitrd. The &amp;quot;ro&amp;quot; param is not used by foobarz-init, so instead use: mountopt=ro|rw. See &amp;quot;modinfo spl&amp;quot; and &amp;quot;modinfo zfs&amp;quot; to see all of the options those modules can take on the kernel command line.&lt;br /&gt;
&lt;br /&gt;
Notes on the spl and zfs packages to install: If you have errors using zfs and zpool commands on booted system with builtin modules, then upgrade/switch to the 0.6.0rc10_3.2.27b builds, or you can make a custom package with the binaries renamed like zpoolb, zfsb etc for builtin.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
Using qemu's -nographic serial console (/usr/share/qemu/sgabios.bin): If you have a boot problem, you might want to run in qemu's -nographic console mode:&lt;br /&gt;
&lt;br /&gt;
First, edit /etc/inittab, and uncomment the line for local serial ports runlevel &amp;quot;s1&amp;quot; (ttyS0) for serial console login support. This is done in the guest (host does not need this):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Local serial lines:&lt;br /&gt;
s1:12345:respawn:/sbin/agetty -L ttyS0 38400 linux&lt;br /&gt;
#s1:12345:respawn:/sbin/agetty -L ttyS0 9600 vt100&lt;br /&gt;
#s2:12345:respawn:/sbin/agetty -L ttyS1 9600 vt100&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Second, edit /etc/securetty, and uncomment ttyS0 line:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ttyS0&lt;br /&gt;
#ttyS1&lt;br /&gt;
# ...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
You cannot login on ttyS0 without this change even though you get the login prompt!&lt;br /&gt;
&lt;br /&gt;
Then, run qemu such as:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
qemu-kvm &amp;lt;all regular options&amp;gt; -nographic -option-rom sgabios.bin,bootindex=0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Wait for the lilo prompt, it may take several seconds show up in this mode.&lt;br /&gt;
&lt;br /&gt;
In the lilo menu, select your kernel image with builtin spl/zfs, and use kernel params such as:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
boot: vm3.2.27b console=ttyS0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
At the lilo prompt, use kernel parameter: console=ttyS0 (do NOT say /dev/ttS0). Passing runlevel=s1 does not appear to be necessary.&lt;br /&gt;
&lt;br /&gt;
When you are in qemu's serial mode, the interface is a little different than in the normal graphical mode: use keypresses:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ctrl-a h    # for help&lt;br /&gt;
ctrl-a c    # toggle access to (QEMU) console / back to emulation&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If you cannot get a login: prompt, try ctrl-a c, then do (QEMU) sendkey ctrl-alt-delete. This will reboot cleanly back to lilo, then you can do (QEMU) quit.&lt;br /&gt;
&lt;br /&gt;
Once you login to the guest, the terminal size needs adjustment. On your host, in another xterm sized the same as your guest console terminal, get the size of the terminal:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo $LINES&lt;br /&gt;
echo $COLUMNS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Now, back in the guest terminal of same size:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export LINES &amp;lt;lines&amp;gt;&lt;br /&gt;
export COLUMNS &amp;lt;columns&amp;gt;&lt;br /&gt;
stty cols $COLUMNS rows $LINES&lt;br /&gt;
exec bash&lt;br /&gt;
reset&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
So, you set the environment variables and also set them with stty. Then, restart bash (exec, or else it is a child shell process).&lt;br /&gt;
&lt;br /&gt;
BECAREFUL not to start qemu twice on the same ZFS guest! Two simultaneous running qemu on the same ZFS will corrupt the pool and it will NOT recover - you lose your whole installation! Before running qemu, check ps -A, look for an already running qemu process incase it somehow entered into the background!&lt;br /&gt;
&lt;br /&gt;
BECAREFUL when using -nographic ttyS0 that you are not doing commands on the HOST! Only use -nographic to see kernel problems. Use regular console of booting is working normally.&lt;br /&gt;
&lt;br /&gt;
To use the qemu -drive if=scsi option, the linux module sym53c8xx should be loaded in the guest. You may need to use the qemu option:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-option-rom 8xx_64.rom,bootindex=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The file 8xx_64.rom used to be inside qemu, but in new versions it is missing. You can download it:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
wget http://www.lsi.com/downloads/Public/Host%20Bus%20Adapters/Host%20Bus%20Adapters%20Common%20Files/lsi_bios.zip&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Extract the zip and place 8xx_64.rom in /usr/share/qemu/.&lt;br /&gt;
&lt;br /&gt;
Good luck!&lt;/div&gt;</description>
			<pubDate>Sun, 09 Sep 2012 04:31:02 GMT</pubDate>
			<dc:creator>Foobarz</dc:creator>
			<comments>https://www.slackwiki.com/Talk:ZFS_root_(builtin)</comments>
		</item>
		<item>
			<title>ZFS root</title>
			<link>https://www.slackwiki.com/index.php?title=ZFS_root&amp;diff=783</link>
			<guid isPermaLink="false">https://www.slackwiki.com/index.php?title=ZFS_root&amp;diff=783</guid>
			<description>&lt;p&gt;Foobarz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Tutorials]]&lt;br /&gt;
If you have heard about the ZFS filesystem and you're curious to try it out, then you can try it on slackware64, thanks to the ZFSonLinux.org project!&lt;br /&gt;
&lt;br /&gt;
In this article, an example is shown of how to install slackware64 14.0 onto a ZFS root filesystem (zfs-root) inside a QEMU virtual machine for testing purposes. It is recommended that you install qemu and learn how to use it to test a ZFS installation before you decide to use it on real hardware. A slackbuild for qemu can be found on slackbuilds.org. If you have a processor that supports Intel VT-x or AMD AMD-V virtualization acceleration (try modprobe kvm-intel or modprobe kvm-amd), then use the slackbuild for qemu-kvm.&lt;br /&gt;
&lt;br /&gt;
This article isn't going to go into any detail on actually using ZFS or what kinds of installation options and settings might be optimal. This article just presents an example of how to get started with ZFS on slackware.&lt;br /&gt;
&lt;br /&gt;
At this time of writing, ZFSonLinux is at &amp;quot;release candidate&amp;quot; (version 0.6.0-rc10) development stage, and many issues can occur. See the ZFSonLinux.org web site and the issues tracker for an idea about the current issues. There is also an irc channel on irc.freenode.net, #zfsonlinux, for discussion of issues and help.&lt;br /&gt;
&lt;br /&gt;
Although not required, it is helpful to keep a local mirror of slackware64 on your system. Having a local mirror makes it easier to upgrade to slackware64-current or to patches/* in a release. To help manage your own local slackware mirror and generate your own CD and DVD slackware installers, see http://alien.slackbook.org/blog/local-slackware-mirror/.&lt;br /&gt;
&lt;br /&gt;
In this article, we use a slackware64-current DVD image file as the qemu cdrom device media for the installation of the slackware guest. This was tested at slackware64-current = slackware64 14.0rc2. You can obtain a slackware DVD image using a torrent, buy the DVD from slackware.com, or generate your own DVD image file using the mirror script. For an actual DVD, you can pass your DVD device (e.g., /dev/sr0) as the qemu cdrom device. For a DVD image file, pass the image file as the qemu cdrom device.&lt;br /&gt;
&lt;br /&gt;
The ZFSonLinux packages are not included in slackware at this time. There are two packages involved: spl and zfs. The first, spl, is &amp;quot;Solaris Porting Layer&amp;quot; and must be installed on the system before zfs can be compiled. The source code tarballs for these are at ZFSonLinux.org. At this time of writing, they are spl-0.6.0-rc10.tar.gz and zfs-0.6.0-rc10.tar.gz.&lt;br /&gt;
&lt;br /&gt;
At this point, it is assumed you have qemu installed, have obtained a slackware64-current/14.0 DVD, and have downloaded spl and zfs tarballs to your host system. The first step now is, if your host is not slackware64-current/14.0 (the same as the guest will be), then you need to create a minimal development slackware64 guest system in qemu for just the purpose of compiling and packaging the spl and zfs slackware packages and transferring a copy of these packages back onto your host system to use later to install onto zfs during the slackware install process.&lt;br /&gt;
&lt;br /&gt;
From this point onward, instructions become a bit terse and mostly limited to examples of the commands you might use to complete tasks. You are encouraged to examine what each command does by reading the command's man pages. For example, the command &amp;quot;man qemu&amp;quot; can show you most of what you need to know about running qemu on the command line.&lt;br /&gt;
&lt;br /&gt;
So, here's an example of how you might build the spl and zfs packages, starting in your home directory:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on host)&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir qemu&lt;br /&gt;
cd qemu&lt;br /&gt;
mkdir slackdevel&lt;br /&gt;
cd slackdevel&lt;br /&gt;
mkdir packages&lt;br /&gt;
cp ~/spl-*.tar.gz packages&lt;br /&gt;
cp ~/zfs-*.tar.gz packages&lt;br /&gt;
qemu-img create disk1.raw 10G&lt;br /&gt;
ln -s ~/slackware64-current-install-dvd.iso dvd.iso&lt;br /&gt;
qemu-kvm \&lt;br /&gt;
 -option-rom 8xx_64.rom,bootindex=1 \&lt;br /&gt;
 -no-quit \&lt;br /&gt;
 -no-shutdown \&lt;br /&gt;
 -boot order=cd,menu=on \&lt;br /&gt;
 -m 2G \&lt;br /&gt;
 -cpu host \&lt;br /&gt;
 -smp sockets=1,cores=4 \&lt;br /&gt;
 -net nic,model=e1000 -net user \&lt;br /&gt;
 -cdrom dvd.iso \&lt;br /&gt;
 -drive format=raw,media=disk,cache=none,aio=native,if=scsi,index=0,file=disk1.raw \&lt;br /&gt;
 -virtfs local,path=./packages/,security_model=none,mount_tag=hostpackages&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When you need to change boot to cd or disk, try changing &amp;quot;order=dc&amp;quot; or hitting F12 at boot prompt and select the CD/DVD boot option.&lt;br /&gt;
&lt;br /&gt;
Note: The support for booting drives using if=scsi is not included with current versions of qemu. Booting scsi requires the 8xx_64.rom option-rom, which can be downloaded at&lt;br /&gt;
[http://www.lsi.com/downloads/Public/Host%20Bus%20Adapters/Host%20Bus%20Adapters%20Common%20Files/lsi_bios.zip LSI.com]. Unzip it, and then:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp 8xx_64.rom /usr/share/qemu&lt;br /&gt;
# then run qemu-kvm with additional command line option: -option-rom 8xx_64.rom,bootindex=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Qemu should boot into the install-dvd, and now perform a very ordinary slackware64 install onto /dev/sda. Install d package set and most others, but package sets x, kde, xfce not really needed.&lt;br /&gt;
&lt;br /&gt;
First note: examples here use tools from the gptfdisk package (gdisk, sgdisk, cgdisk) to partition the disk with GUID partition table (GPT) format. GPT might not be too familiar to everyone, who mostly have only used MBR partitions with fdisk. In the slackware installations this author has tested in qemu, using GPT partitions has caused no problems with lilo or other tools used in slackware. GPT disk labels support creating up to 128 partitions and support disks larger than 2TB (the limit of MBR fdisk). LILO installs into the first 440 bytes on /dev/sda, inside a GPT &amp;quot;protective MBR&amp;quot; that serves to provide compatibility with MBR bootloaders like lilo. LILO uses LBA32 sector addressing and can see all 512-byte sectors inside the first 2TB of a disk. So long as the /boot partition is within the first 2TB of a disk, lilo can work on a disk larger than 2TB. Unlike the common default of fdisk to start the first partition at sector 63, which is not aligned with the 4KiB sector size of Advanced Format hard disks, gdisk's default is to start partitions at 2048 sector (1MiB) boundaries which are also 4KiB aligned. Using gdisk GPT works on all disks and is compatible with using Advanced Format hard disks larger than 2TB. More information about GPT disk label format can be found on wikipedia.org. For those that have used grub instead of lilo, grub installation is different with GPT than with MBR, and grub requires a GPT partition of type grub-bios or 0xEF02 &amp;quot;BIOS Boot Partition&amp;quot; of about 8MiB where it can install it's additional bootloader stages because grub cannot embed in sectors 1-62 on GPT where GPT keeps it's partition tables. On MBR, sectors 1-62 were normally reserved space for bootloaders to keep a 2nd stage.&lt;br /&gt;
&lt;br /&gt;
For this purpose of development guest, just create a simple 1-partition system, /dev/sda1, and do a simple slackware install on it. Don't bother with swap or separate /boot unless you want to:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on install-dvd)&lt;br /&gt;
cgdisk /dev/sda&lt;br /&gt;
setup&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When this simple development guest boots, login as root, and continue:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on qemu guest)&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir packages&lt;br /&gt;
mount hostpackages -t 9p -o trans=virtio packages&lt;br /&gt;
echo --prefix=/ --libexecdir=/usr/libexec --libdir=/lib64 --includedir=/usr/include --datarootdir=/usr/share &amp;gt; configure-options&lt;br /&gt;
mkdir src&lt;br /&gt;
cd src&lt;br /&gt;
&lt;br /&gt;
mkdir install&lt;br /&gt;
tar xvzf ~/packages/spl-*.tar.gz&lt;br /&gt;
cd spl-*&lt;br /&gt;
./configure $( cat ~/configure-options )&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../spl-&amp;lt;version&amp;gt;_&amp;lt;kernel_version&amp;gt;-x86_64-&amp;lt;build_id&amp;gt;.txz&lt;br /&gt;
(e.g., makepkg ../spl-0.6.0rc10_3.2.27-x86_64-1root.txz)&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
installpkg spl-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
cp spl-0.6.0rc10_3.2.27-x86_64-1root.txz ~/packages&lt;br /&gt;
&lt;br /&gt;
mkdir install&lt;br /&gt;
tar xvzf ~/packages/zfs-*.tar.gz&lt;br /&gt;
cd zfs-*&lt;br /&gt;
./configure $( cat ~/configure-options )&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../zfs-&amp;lt;version&amp;gt;_&amp;lt;kernel_version&amp;gt;-x86_64-&amp;lt;build_id&amp;gt;.txz&lt;br /&gt;
(e.g., makepkg ../zfs-0.6.0rc10_3.2.27-x86_64-1root.txz)&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
installpkg zfs-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
cp zfs-0.6.0rc10_3.2.27-x86_64-1root.txz ~/packages&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point spl and zfs packages are copied back to the host in the packages directory. Also, spl and zfs are installed in this simple development guest, so one could begin to experiment with zfs pools and datasets but while the root fs is whatever you made it during setup (probably the default, ext4). This development guest isn't really needed anymore, so it can be deleted:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
halt&lt;br /&gt;
(exit qemu: ctrl-alt-2 then enter quit at QEMU command prompt)&lt;br /&gt;
&lt;br /&gt;
(on host)&lt;br /&gt;
rm disk1.raw dvd.iso&lt;br /&gt;
mv packages ..&lt;br /&gt;
cd ..&lt;br /&gt;
rmdir slackdevel&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now that we have the spl and zfs packages on the host, it is possible to copy them into your local slackware64 mirror and then generate your own install DVD image that includes them. For example, change to the directory that contains the slackware README files, and create a &amp;quot;addon&amp;quot; directory and copy the spl and zfs slackware packages into there. Then, generate the DVD image using a command such as $( ./mirror-slackware-current.sh -i ) from where you have this script configured to maintain your local mirror. We can also just continue to access them inside the installer using qemu's virtfs option. When you are going to do a real installation onto real hardware, you need to generate and burn your own DVD that includes the packages.&lt;br /&gt;
&lt;br /&gt;
It is time to begin the installation of slackware64 on a ZFS root, assuming either you have regenerated dvd.iso with zfs packages in addon/* or we access the zfs packages while in the installer using qemu's virtfs to the host's packages directory. ZFS supports creating complex data storage configurations such as pools (similar to a volume group) backed by one or more of various kinds of virtual devices (similar to disks and raid arrays) and containing one or more datasets (similar to mounted filesystems, logical volume devices, or snapshots). But here, we keep it simple and will install on just a single disk device.&lt;br /&gt;
&lt;br /&gt;
Note: On a real ZFS installation, users will typically want to use the ZFS mirror or raidz virtual device (vdev) types for reliability against hard drive failures. For example, a good configuration might be to use a USB memory stick (and a backup stick) for /boot that is plugged into an on-motherboard &amp;quot;Type A&amp;quot; USB connector. Then, use four whole hard drives in a raidz2 vdev as the initial storage space in the root zpool. At a later time, to add more storage space, additional whole four-drive raidz2 vdevs of the same size could be added to the zpool. It is recommended to only add the same vdev type (disk, mirror, or raidz|1|2|3) and size to a zpool since zfs stripes across the vdevs, and vdevs of different types/sizes do not stripe together optimally. After adding a vdev to your zpool, you might need to copy the new /etc/zfs/zpool.cache to your initrd-tree or initramfs-source (and rebuild/reinstall them) if you are using the cachefile to import your zpool. Using mirror vdevs would be similar to a raid10. Using 4-disk raidz2 vdevs would give the same storage space as raid10 while fully reliable against any double-disk failure; however, the raidz2 parity calculations results in higher CPU usage and/or lower performance. Because raidz vdevs cannot be grown by adding hard drives to them, and vdevs in a zpool are striped, it is important with ZFS to decide what type and size of vdev will be used in a zpool as the units of add-on storage space; it could be difficult to alter this decision later. Finally, on a real installation with raidz, data scrub should be scheduled to actively search for &amp;quot;latent defects&amp;quot; on the hard drives so that unknown read/write errors do not become known later during a disk swap/rebuild and result in the zpool becoming faulted (lost).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on host)&lt;br /&gt;
mkdir slackzfs&lt;br /&gt;
mv packages slackzfs/&lt;br /&gt;
cd slackzfs&lt;br /&gt;
qemu-img create disk1.raw 10G&lt;br /&gt;
ln -s ~/slackware64-current-install-dvd.iso dvd.iso&lt;br /&gt;
qemu-kvm \&lt;br /&gt;
 -option-rom 8xx_64.rom,bootindex=1 \&lt;br /&gt;
 -no-quit \&lt;br /&gt;
 -no-shutdown \&lt;br /&gt;
 -boot order=cd,menu=on \&lt;br /&gt;
 -m 2G \&lt;br /&gt;
 -cpu host \&lt;br /&gt;
 -smp sockets=1,cores=4 \&lt;br /&gt;
 -net nic,model=e1000 -net user \&lt;br /&gt;
 -cdrom dvd.iso \&lt;br /&gt;
 -drive format=raw,media=disk,cache=none,aio=native,if=scsi,index=0,file=disk1.raw \&lt;br /&gt;
 -virtfs local,path=./packages/,security_model=none,mount_tag=hostpackages&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The install-dvd should boot, and then begin installation steps on the installer command line:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on install-dvd)&lt;br /&gt;
# mount the install-dvd&lt;br /&gt;
mkdir /dvd&lt;br /&gt;
mount /dev/sr0 /dvd&lt;br /&gt;
&lt;br /&gt;
# install coreutils, which provides the &amp;quot;hostid&amp;quot; command needed to load the spl module&lt;br /&gt;
installpkg /dvd/slackware64/a/coreutils-8.17-x86_64-1.txz&lt;br /&gt;
&lt;br /&gt;
# install kmod package which includes &amp;quot;depmod&amp;quot; command and others&lt;br /&gt;
installpkg /dvd/slackware64/a/kmod-9-x86_64-2.txz&lt;br /&gt;
depmod&lt;br /&gt;
&lt;br /&gt;
# install the full kernel modules so you can load 9p filesystem and use it if you want&lt;br /&gt;
# .. you might keep the zfs modules packages off the dvd and use a plain slack dvd&lt;br /&gt;
installpkg /dvd/slackware64/a/kernel-modules-*.txz&lt;br /&gt;
depmod&lt;br /&gt;
&lt;br /&gt;
# install bash and libtermcap because udev rules in zfs use bash scripts&lt;br /&gt;
installpkg /dvd/slackware64/a/bash-*.txz&lt;br /&gt;
installpkg /dvd/slackware64/l/libtermcap-*.txz&lt;br /&gt;
&lt;br /&gt;
# install spl and zfs that you have copied into the mirror before running the DVD creation&lt;br /&gt;
installpkg /dvd/addon/spl-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /dvd/addon/zfs-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
&lt;br /&gt;
#Or:&lt;br /&gt;
mkdir /packages&lt;br /&gt;
find /lib/modules/ | grep 9p&lt;br /&gt;
lsmod&lt;br /&gt;
# check that 9p modules load, mainly 9pnet_virtio&lt;br /&gt;
modprobe 9pnet_virtio&lt;br /&gt;
mount hostpackages -t 9p -o trans=virtio /packages&lt;br /&gt;
installpkg /packages/spl-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /packages/zfs-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
modprobe zfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now zfs tools: &amp;quot;zpool&amp;quot; and &amp;quot;zfs&amp;quot; should work in the live installer.&lt;br /&gt;
On the installer, there can be trouble seeing man pages, so install:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
installpkg /dvd/slackware64/ap/man-*.txz&lt;br /&gt;
installpkg /dvd/slackware64/ap/groff-*.txz&lt;br /&gt;
installpkg /dvd/slackware64/a/less-*.txz&lt;br /&gt;
export MANPATH=/usr/man:/usr/share/man&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The manual pages should be readable:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
man zpool&lt;br /&gt;
man zfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After seeing the man pages, we should be fully ready to continue to setup on ZFS.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(still on install-dvd)&lt;br /&gt;
ls -l /dev/sd*&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Make sure the disk devices you expect are there. We'll use sda and make boot (/boot on /dev/sda1) and root (/ on /dev/sda2) partitions.&lt;br /&gt;
&lt;br /&gt;
First, some background info: A ZFS filesystem is not supported by lilo as the filesystem containing /boot, which holds lilo's 2nd stage and the linux kernel files. The on-disk format of a ZFS filesystem is often a complex raid configuration where even if lilo understood ZFS it would likely require /boot to reside in only certain simple ZFS configurations to be plainly readable to lilo. As things are, a linux root installed in a partition with ZFS filesystem needs /boot to be on another partition with a filesystem that lilo understands, such as ext4 fs. In addition, because the spl and zfs modules are not built into the kernel, and the zfs startup requires some configuration to mount the zfs root, an initial ram/root filesystem (initrd) is needed. The initrd is a gzip compressed cpio archive file that contains a small linux root operating system that is decompressed into a ramfs block device at boot up and takes initial control of the system. The initrd contains an init script that configures devices in devtmpfs mounted at /dev. For example, if using mdadm, lvm, luks, losetup, and now zfs, this init script runs all the commands to create or start these devices (one of which is the root device), mounts the root device, and then transfers system control to the init script in the mounted root filesystem. The ramfs-based root environment on the booted install-dvd or booted initrd image (in rescue command line) are small slackware installations that exist only in ram and are temporary, but while inside them you can install, upgrade, and remove slackware packages inside them using the regular package management tools; this allows you access to any kernel modules and programs as needed inside these ramfs root. Packages can be installed, upgraded, or removed permanantly in the initrd image file to manage the programs and modules required during the initrd boot stage. Also from within these ramfs initial root environments, once the root device is mounted, chroot can be used to work on the mounted root system as if it were booted; this allows one to fix problems that are occuring in the root fs init scripts that cause normal booting to fail, or to install a kernel and/or modules etc. Now on to partitioning:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cgdisk /dev/sda&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, cgdisk looks just like cfdisk, but it makes GPT partitions.&lt;br /&gt;
&lt;br /&gt;
Make a partition for /boot that is about 512MiB of whatever partition type you like (8300 &amp;quot;Linux filesystem&amp;quot; is fine), or make it type bf07 &amp;quot;Solaris Reserved 1&amp;quot; if you want ZFS to maybe see the disk as if it was given as a whole disk to ZFS. Make a second partition using the remaining space with partition type bf01 &amp;quot;Solaris ZFS&amp;quot;. Currently, when ZFSonLinux is given a whole disk device like /dev/sdb to use, it will automatically GPT partition it with a bf01 partition #1 that is the whole disk except a small 8MiB type bf07 partition #9 at the end of the disk (/dev/sdb1 and /dev/sb9). The small 8MiB type bf07 partition #9 is most likely reserved for use by bootloaders, like lilo, to have a /boot or other boot-related files kept there. For example, you might have /dev/sda that is totally non-ZFS for booting and /dev/sdb passed to ZFS whole where it automatically partitions sdb, but you can just use one disk here and make partitions. Let's use type 8300 for /boot to be sure nothing is confused:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
We'll continue with this partitioning (numbers are in MiB):&lt;br /&gt;
  0 to   4: unused&lt;br /&gt;
  4 to 516: /dev/sda1 512MiB, type 8300&lt;br /&gt;
516 to 520: unused&lt;br /&gt;
520 to -96: /dev/sda2, type bf01&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The -96 means to count from the end of the disk so that 96MiB will remain unused at the end of the disk.&lt;br /&gt;
&lt;br /&gt;
Create a zpool called zfs-root:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool create -m none zfs-root /dev/sda2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A zpool created like this, the normal way, is a kernel-internal block device that contains already a zfs filesystem. There is normally no entry in /dev for this device. However, it can still be referenced as a mountable device similar to how devtmpfs, proc, and sysfs are also kernel-internal mountable block devices. The -m option told zpool not to automatically mount it anywhere, and without -m the default is to always automatically mount to /zfs-root. These kinds of details are explained better elsewhere. For this situation, we do not want it automounted.&lt;br /&gt;
&lt;br /&gt;
Because a zpool itself is a useable zfs fs, it has a full set of zfs &amp;quot;properties&amp;quot; to set options about the filesystem, perhaps similar to tune2fs. The &amp;quot;mountpoint=&amp;lt;some place to mount&amp;gt;&amp;quot; is one such property. We want it set to the special value &amp;quot;none&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs get mountpoint zfs-root&lt;br /&gt;
zfs set mountpoint=none zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On creation, the zpool zfs-pool is &amp;quot;imported&amp;quot; and has a zpool status that can be viewed:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool status zfs-root&lt;br /&gt;
&lt;br /&gt;
zpool export zfs-root&lt;br /&gt;
zpool status zfs-root&lt;br /&gt;
# Now there is no status.&lt;br /&gt;
&lt;br /&gt;
zpool import zfs-root&lt;br /&gt;
# Now it is back.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When a zpool is imported, it has it's current configuration cached in a file /etc/zfs/zpool.cache. When a zpool is exported, then it's entries in the cache file are removed and the cache file is deleted if it becomes empty. So long as the zfs kernel modules see this cache file and valid cache data inside it, ZFS considers the described zpools in the cache file to be valid as imported zpools. If the zpool.cache file is present at the time the zfs modules are loaded, then there is no further need to use the import and export zpool commands at system startup and shutdown. With root on a zfs, it is not possible to export the pool that root is on, but this is not a problem. At shutdown, the safe procedure will be to set the zfs-root property readonly=on and sync disks.&lt;br /&gt;
&lt;br /&gt;
To avoid the requirement to import the zfs-root pool at startup, keep a copy of the zpool.cache file to later copy onto the initrd image to read at modules load time to have the pool reactivated without need to issue the zpool import command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/zfs/zpool.cache /etc/zfs/zpool.cache-initrd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A zfs fs will not normally allow you to mount over any files. The mountpoint is expected to be an empty directory. Remove any junk files inside the installer's /mnt because zfs won't mount over any files:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rm /mnt/README&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The directory /mnt is where the slackware setup expects you to mount your root for installation.&lt;br /&gt;
&lt;br /&gt;
Controlling whether a zfs fs is to be mounted read-only or read-write is best managed by setting the readonly property while it is not yet mounted:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set readonly=on zfs-root&lt;br /&gt;
zfs set readonly=off zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Slackware expects root to be mounted readonly when /etc/rc.d/rc.S runs during normal startup, so later this is used to satisfy slackware's expectation to avoid rc.S complaining.&lt;br /&gt;
&lt;br /&gt;
The zfs-root can be mounted and unmounted in two different ways:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=/mnt zfs-root&lt;br /&gt;
zfs set mountpoint=none zfs-root&lt;br /&gt;
# or&lt;br /&gt;
mount zfs-root -t zfs /mnt&lt;br /&gt;
umount /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If it is already mounted and you want to change it to mount somewhere else, it is best to transition it to unmounted first, then mount it in the new place.&lt;br /&gt;
&lt;br /&gt;
The mount options &amp;lt;code&amp;gt;-o ro, -o rw, -o remount,ro, and -o remount,rw &amp;lt;/code&amp;gt; can also be used and will override the &amp;lt;code&amp;gt;readonly=on|off&amp;lt;/code&amp;gt; property without altering the property value. This can be confusing until you are familiar with how the two methods of mounting interact. When &amp;lt;code&amp;gt;mountpoint=legacy&amp;lt;/code&amp;gt; is set, zfs expects the regular mount and umount commands to be used to mount and unmount the dataset with the assistance of the mount.zfs helper. For now, we will continue with &amp;lt;code&amp;gt;mountpoint=none&amp;lt;/code&amp;gt;, but using legacy is also a good option.&lt;br /&gt;
&lt;br /&gt;
Now, let's continue some, and mount to /mnt using the current &amp;lt;code&amp;gt;readonly=off&amp;lt;/code&amp;gt; setting (rw mount):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=/mnt zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This method of mounting will show the most detailed mount options in /etc/mtab. They are the mount options that zfs thinks are proper, and they are probably what should be kept in /etc/fstab for zfs-root until we know better.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cat /etc/mtab &amp;gt;&amp;gt; /etc/fstab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now edit /etc/fstab to make sure it looks right, and remove the &amp;quot;rw&amp;quot; mount option, because we want to let it use a default for that, which will come from how we set the readonly= property most of the time. Unmount again:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=none zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mount again, now using all options from /etc/fstab:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It should be mounted at /mnt, and touch /mnt/t should allow you to make the file t. Then rm it: rm /mnt/t&lt;br /&gt;
For installation, we want to make sure it is mounted read-write. After installation, it should mount readonly inside the initrd.&lt;br /&gt;
&lt;br /&gt;
Sometimes there can be problems using the mount command, and then you can try it with the -i option:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 mount -i zfs-root&lt;br /&gt;
 mount -i zfs-root -t zfs /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
but, you should not have to use -i. When using -i makes it work, it performs an &amp;quot;internal-only&amp;quot; mount and does not use any mount.&amp;lt;fstype&amp;gt; helper scripts that might be on the system. You can use &amp;lt;code&amp;gt;mountpoint=legacy&amp;quot;&amp;lt;/code&amp;gt; to avoid this small problem if you are preferring to use the regular mount and umount commands on your zfs-root.&lt;br /&gt;
&lt;br /&gt;
Setup the /boot device:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkfs.ext4 /dev/sda1&lt;br /&gt;
mkdir /mnt/boot&lt;br /&gt;
mount /dev/sda1 /mnt/boot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We have both root and boot mounted where the slackware installer expects them. Unmount the dvd so setup can find it normally:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
umount /dev/sr0&lt;br /&gt;
setup&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the setup, skip straight to TARGET selection for the root device, but the setup doesn't see or understand the zfs-root, so it is not listed. This does not matter because we have mounted it already. Just skip down to a slot that say to continue, and continue on with setup. Because TARGET is skipped, you may not see the ADDITIONAL prompt (or if so, skip it too) where normally you give /dev/sda1 and have it mounted as /boot. This is also okay because we have mounted /mnt/boot already.&lt;br /&gt;
Because we did not give TARGET the root device or say what device /boot is on, the lilo installation will fail, or you can skip it. Otherwise, this installation process is normal.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Finish installation and exit setup, but do NOT reboot!&lt;br /&gt;
# There is still a lot to do before rebooting.&lt;br /&gt;
umount /dev/sr0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point, it is assumed that the setup has completed installing into /mnt. Congrats! You've installed slackware into a ZFS root!&lt;br /&gt;
&lt;br /&gt;
The next steps are to prepare to use &amp;quot;chroot /mnt&amp;quot; and finish up the configuration on the installed root system and then be able to reboot onto the completed installation. Before doing chroot, copy some files from the setup environment into /mnt.&lt;br /&gt;
&lt;br /&gt;
Copy the current installer /etc/fstab for later use inside the initrd. This fstab is what is proper inside the initrd, except remove option &amp;quot;rw&amp;quot; (if not done already).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/fstab /mnt/etc/fstab.initrd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The fstab.initrd will look like:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 proc /proc proc defaults 0 0&lt;br /&gt;
 zfs-root /mnt zfs defaults,atime,dev,exec,suid,xattr,nomand,zfsutil 0 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the initrd, we want zfs-root to mount to /mnt.&lt;br /&gt;
&lt;br /&gt;
Create /mnt/etc/fstab:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cat /etc/mtab &amp;gt;&amp;gt; /mnt/etc/fstab&lt;br /&gt;
vi /mnt/etc/fstab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using vi started above, edit /mnt/etc/fstab and make it have lines such as:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 zfs-root / zfs defaults,atime,dev,exec,suid,xattr,nomand,zfsutil 0 0&lt;br /&gt;
 /dev/sda1 /boot ext4 defaults 0 2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These two lines in &amp;lt;code&amp;gt;/mnt/etc/fstab&amp;lt;/code&amp;gt; are how the mounts should be looking when root is booted.&lt;br /&gt;
&lt;br /&gt;
Mount some special mounts before chroot:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount -t devtmpfs none /mnt/dev&lt;br /&gt;
mount -t proc none /mnt/proc&lt;br /&gt;
mount -t sysfs none /mnt/sys&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Make sure /boot is mounted:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount /dev/sda1 /mnt/boot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you had mounted a 9p fs share to access spl and zfs packages, then unmount that now:&lt;br /&gt;
umount /packages&lt;br /&gt;
&lt;br /&gt;
Ready, now:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chroot /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point, you should be on the installed system, and now try to configure mkinitrd and lilo. First, switch to use the generic kernel.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /boot&lt;br /&gt;
rm System.map config vmlinuz&lt;br /&gt;
ln -s System.map-gen* System.map&lt;br /&gt;
ln -s config-gen* config&lt;br /&gt;
ln -s vmlinuz-gen* vmlinuz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We installed spl and zfs inside the live ramfs install-dvd environment, but not yet have we installed them into the root system:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount /dev/sr0 /mnt/cdrom&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /mnt/cdrom/addon/spl-*.txz&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /mnt/cdrom/addon/zfs-*.txz&lt;br /&gt;
depmod&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If instead, you used a 9p share to access the spl and zfs packages, then repeat that procedure here to install them onto the root system.&lt;br /&gt;
&lt;br /&gt;
Setup lilo: edit /etc/lilo.conf so it is like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  lba32&lt;br /&gt;
  append = &amp;quot; vt.default_utf8=1&amp;quot;&lt;br /&gt;
  boot = /dev/sda&lt;br /&gt;
  message = /boot/boot_message.txt&lt;br /&gt;
  prompt&lt;br /&gt;
  timeout = 1200&lt;br /&gt;
  change-rules&lt;br /&gt;
   reset&lt;br /&gt;
  vga = normal&lt;br /&gt;
  image = /boot/vmlinuz&lt;br /&gt;
   label = vmlinuz&lt;br /&gt;
   initrd = /boot/initrd.gz&lt;br /&gt;
   root = /dev/ram0&lt;br /&gt;
   read-write&lt;br /&gt;
# alternatively, the root and read-write lines&lt;br /&gt;
# can be this one line of kernel parameters:&lt;br /&gt;
#  addappend = &amp;quot; root=/dev/ram0 rw &amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A note about initrd: The /boot/initrd.gz is a gzipped cpio archive containing a minimal BusyBox-based slackware root system that is sourced from /boot/initrd-tree. The commands &amp;quot;mkinitrd&amp;quot; and &amp;quot;mkinitrd -F&amp;quot; generates /boot/initrd-tree and /boot/initrd.gz. When using a initrd, the initial root device is normally set to root=/dev/ram0 (a ramfs block device) and allowed read-write. The kernel refers to devices in terms of &amp;quot;major&amp;quot; and &amp;quot;minor&amp;quot; numbers, and the ram0 device is assigned the block device major 1 and minor 0. This ram0 major/minor is written in hexadecimal as 0x0100 (256 in decimal). This hexademical number makes an appearance in /boot/initrd-tree/int where it runs: &amp;quot;echo 0x0100 &amp;gt; /proc/sys/kernel/real-root-dev&amp;quot;. Echoing a device code to real-root-dev is part of a deprecated initrd mechanism, but is probably harmless to leave alone as slackware has it unless you know otherwise. More information about how initrd works can be found in:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/usr/src/linux/Documentation/devices.txt (info about major:minor device numbers)&lt;br /&gt;
/usr/src/linux/Documentation/initrd.txt  (mostly obsolete info on old initrd)&lt;br /&gt;
/usr/src/linux/Documentation/filesystems/ramfs-rootfs-initramfs.txt (current info on new initrd, called initramfs)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Advanced note about initrd: Slackware's mkinitrd package does not use the &amp;quot;pivot_root&amp;quot; command as documented in &amp;quot;initrd.txt&amp;quot;, but instead uses &amp;quot;switch_root&amp;quot; provided by a project called BusyBox. The switch_root command changes the effective root filesystem from the initrd (unpacked in rootfs at /) to the new root filesystem (zfs-root mounted at /mnt); it overmounts rootfs / with zfs-root /mnt. The switch_root works as follows: delete everything in rootfs / (one filesystem only) that held initrd to free up ram memory, then use mount, chroot, and chdir to make the effective root change. In concept (as a shell script), the command &amp;quot;exec switch_root /mnt $INIT $RUNLEVEL&amp;quot; is performed as follows:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 find / -xdev | xargs rm -rf&lt;br /&gt;
 cd &amp;quot;$1&amp;quot;&lt;br /&gt;
 shift&lt;br /&gt;
 mount --move . /&lt;br /&gt;
 exec chroot . &amp;quot;$@&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Here, typically INIT=/sbin/init RUNLEVEL=3. The 'exec' causes switch_root to take the place of the parent process having PID=1. In system calls, the switch_root looks similar to this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chdir(&amp;quot;/mnt&amp;quot;);&lt;br /&gt;
/* &amp;lt;insert code to unlink/rmdir all initrd files/directories&lt;br /&gt;
 *  installed in rootfs / without crossing filesystems &amp;gt; */&lt;br /&gt;
mount(&amp;quot;.&amp;quot;, &amp;quot;/&amp;quot;, NULL, MS_MOVE, NULL);&lt;br /&gt;
chroot(&amp;quot;.&amp;quot;);&lt;br /&gt;
chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
execl(&amp;quot;/sbin/init&amp;quot;, &amp;quot;3&amp;quot;, (char*) NULL );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The kernel's rootfs / that contained initrd is never actually unmounted (it can't be) because it is built into the kernel and always exists as at least a tiny ramfs or tmpfs, so you can continue to see it in /proc/mounts. When you give lilo root=/dev/ram0 (a ramfs device), the kernel will actually use the internal rootfs, which is an instance of a tmpfs (if your kernel config includes tmpfs) or ramfs. The rootfs that is a tmpfs can by default use up to half of system ram. If rootfs is a ramfs, it can use up to almost all of system ram until the system panics. Typically, tmpfs is built into the kernel, and so depending on how much ram your computer has, the initrd-tree can probably be up to about half that size.&lt;br /&gt;
&lt;br /&gt;
Quite a lot of notes... now to continue on:&lt;br /&gt;
&lt;br /&gt;
Setup mkinitrd:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/mkinitrd.conf.sample /etc/mkinitrd.conf&lt;br /&gt;
vi /etc/mkinitrd.conf&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Edit it to look like this (other defaults should be ok):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 MODULE_LIST=&amp;quot;sym53c8xx:ext4:e1000:zfs:9p:9pnet_virtio&amp;quot;&lt;br /&gt;
 ROOTDEV=&amp;quot;zfs-root&amp;quot;&lt;br /&gt;
 ROOTFS=&amp;quot;zfs&amp;quot;&lt;br /&gt;
#Module sym53c8xx is the driver for qemu's if=scsi drive device.&lt;br /&gt;
#Module ext4 for /boot.&lt;br /&gt;
#Module e1000 for eth0 net device.&lt;br /&gt;
#Module zfs for ZFSonLinux.&lt;br /&gt;
#Modules 9p and 9pnet_virtio for mounting qemu -virtfs mount_tag.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These 9p modules could be useful from the rescue command line inside the initrd to get needed files that are on the host.&lt;br /&gt;
&lt;br /&gt;
All dependent modules will also be included automatically into /boot/initrd-tree, which is packaged as /boot/initrd.gz. For example, to see the dependent modules of zfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
modprobe --show-depends zfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All listed modules will also be in the initrd. Now, make a /boot/initrd-tree that we can begin to look at and edit.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkinitrd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create an empty /etc/mtab or else zpool import fails (zfs expects /etc/mtab to exists already, it won't make it).&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
touch /boot/initrd-tree/etc/mtab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Copy in the fstab.initrd that was made earlier while on the installer. This provides all the mount options for a simple &amp;quot;mount zfs-root&amp;quot; onto /mnt.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/fstab.initrd /boot/initrd-tree/etc/fstab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More package installing! This time into an alternate root, the root of the initrd, /boot/initrd-tree. This is how you can put whatever packages you like into your initrd. These installations work independent of your normal installations. You can install, upgrade, and remove packages using an altroot:&lt;br /&gt;
&lt;br /&gt;
If spl and zfs are on your customized dvd:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/addon/spl-*.txz&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/addon/zfs-*.txz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Otherwise, repeat same procedure but you mount your 9p mount_tag and get them installed.&lt;br /&gt;
&lt;br /&gt;
More regular packages from the dvd:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/kmod-*.txz&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/coreutils-*.txz&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/gptfdisk-*.txz&lt;br /&gt;
&lt;br /&gt;
# A bash script is in /boot/initrd-tree/lib/udev/, so we need it or udev rules have problems:&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/bash-*.txz&lt;br /&gt;
# Bash needs this:&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/l/libtermcap-*.txz&lt;br /&gt;
&lt;br /&gt;
# Install net-tools to ensure that /etc/HOSTNAME, /etc/hosts, and potentially, /etc/hostid are handled proper.&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/n/net-tools-*.txz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When ZFS has to import a zpool while the initrd is running (this can be avoided by not exporting and keeping /etc/zfs/zpool.cache inside the initrd), ZFS will refuse to import a pool if it thinks that the pool may be in use by another system. ZFS was designed for network attached storage where multiple hosts might have access to the same disks but ZFS cannot support two hosts importing and using a ZFS pool at the same time. ZFS checks a value called &amp;quot;hostid&amp;quot; to determine this kind of conflict, and it can be a tricky issue with an initrd boot process. The value of hostid is returned by a system call, the gethostid() function or the hostid command. This function will return the hostid from /etc/hostid if that file exists and has a valid id in it, or else if the file doesn't exist it obtains a hostid number based on the hostname and ip address assigned to hostname found in /etc/hosts or in DNS. If the hostid trying to import a pool is not the same as the hostid that imported it last time, ZFS will not import the pool unless &amp;quot;zpool import -f zfs-root&amp;quot; is used to force the import. This force option is not recommended to use, so it is best to configure your initrd with matching /etc/HOSTNAME and /etc/hosts as on the root installation and ensure what your system looks like on the initrd matches the booted root system.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Edit /boot/initrd-tree/init (this is the main system startup script on the initrd, responsibe for configuring your block devices and mount your root at /mnt and then booting root):&lt;br /&gt;
&lt;br /&gt;
Inside init, right near the top of the file after the PATH= line, add this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/bin/hostname -F /etc/HOSTNAME&lt;br /&gt;
/bin/hostname $( /bin/hostname -s )&lt;br /&gt;
#/sbin/chhostid 13371400&lt;br /&gt;
# you can make your hostid whatever, but this didn't work right with ZFS, so it is commented out&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This sets the name reported by the hostname command (the default is &amp;quot;darkstar&amp;quot;) to be what is contained in /etc/HOSTNAME. The hostname is modified in the next line to be the short name. These lines will help ZFS to properly identify your host when importing pools.&lt;br /&gt;
&lt;br /&gt;
Inside init, right after it runs &amp;quot;mdadm&amp;quot; commands as used for raid setup, we like it to setup ZFS, so add:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/sbin/zpool import zfs-root&lt;br /&gt;
/sbin/zfs set readonly=on zfs-root&lt;br /&gt;
mount zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Inside init, close to the bottom, where it &amp;quot;Switch to real root partition&amp;quot;, comment out 1 line that normally does the mount:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# mount -o ro -t $ROOTFS $ROOTDEV /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
We have already mounted zfs-root, and we don't want to use any mount options because we should be using a properly set /etc/fstab inside the initrd for the zfs-root mount options onto /mnt.&lt;br /&gt;
&lt;br /&gt;
During a normal startup we want a readonly mount.&lt;br /&gt;
&lt;br /&gt;
Note: we are going to setup with using &amp;quot;zpool import&amp;quot; and &amp;quot;zpool export&amp;quot; commands and startup and shutdown. But later, you can experiment having /etc/zfs/zpool.cache stored in the initrd and commenting out the zpool import/export lines.&lt;br /&gt;
&lt;br /&gt;
As mentioned, the zpool import command may sometimes fail, and give the message: &amp;quot;pool may be in use from another system&amp;quot;. This is nothing serious in this test situation. When this happens, zfs-root will not get mounted to /mnt and the init script will detect this and drop you into a rescue command line where you may manually &amp;quot;zpool import -f zfs-root&amp;quot;, &amp;quot;mount zfs-root&amp;quot;, and then &amp;quot;exit&amp;quot; to continue booting onto zfs-root.&lt;br /&gt;
&lt;br /&gt;
To avoid this problem we copy some files in (assuming you first edit /etc/HOSTNAME to hold the hostname you like to see on your command prompts, and edited /etc/hosts to have hostname on your loopback or other local ip address):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/HOSTNAME /etc/hosts /boot/initrd-tree/etc&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The value reported by the hostid command is what ZFS sees as your hostid. In this setup so far, the value is based on the ip assigned to your hostname. If your hostname is on the line in /etc/hosts for ip address 192.168.13.37, then your hostid will be hex numbers C0.A8.0D.25 rearranged as A8C0250D (pairs of bytes are swapped). This is a ip-based hostid value, a 32bit hexadecimal number. The hostid has to be the same each boot or import will need a -f option to force it. Simply setting the hostid using the system call sethostid() which writes a /etc/hostid file doesn't seem to agree with ZFS and you'd have to force the import, so this setup now assumes that you do not have or have deleted /etc/hostid.&lt;br /&gt;
&lt;br /&gt;
You can sometimes see what has been happening to a zpool by using the command &amp;quot;zpool history -li zfs-root&amp;quot; to see a log of commands.&lt;br /&gt;
&lt;br /&gt;
Once again, you can do away with the import and export commands by trying to have /etc/zfs/zpool.cache inside your initrd. To create zpool.cache, while on the installer or in the rescue shell of the initrd (at lilo &amp;quot;boot: vmlinuz rescue&amp;quot;), import only the pool for the root fs with mountpoint=none and readonly=on properties set, and while it is not mounted:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on installer or initrd rescue shell)&lt;br /&gt;
cp /etc/zfs/zpool.cache /etc/zfs/zpool.cache-initrd&lt;br /&gt;
zfs set readonly=off zfs-root&lt;br /&gt;
mount zfs-pool&lt;br /&gt;
cp /etc/zfs/zpool.cache-initrd /mnt/etc/zfs/&lt;br /&gt;
cp /mnt/etc/zfs/zpool.cache-initrd /mnt/boot/initrd-tree/etc/zfs/zpool.cache&lt;br /&gt;
umount /mnt&lt;br /&gt;
zfs set readonly=on zfs-root&lt;br /&gt;
#mount zfs-root&lt;br /&gt;
#exit (to continue boot process onto rootfs mounted at /mnt)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, doing this zpool.cache approach is not necessary, and some talk suggests this is deprecated or discouraged. Although /etc/hostid setup fails to import without -f option, ip-based (hosts|dns) hostid works on booting and import works without -f option and may be the more proper way to do shutdown and startup rather than using a cache file which could become invalid and cause a problem that is difficult to understand. The contents and exact function of the cache file are not well understood by many people.&lt;br /&gt;
&lt;br /&gt;
Save /boot/initrd-tree/init and quit vi.&lt;br /&gt;
&lt;br /&gt;
Now, edit /etc/rc.d/rc.S and rc.6 to understand how to &amp;quot;remount&amp;quot; rw or ro as readonly property changes. Note: if you use mountpoint=legacy, then you do not need to make the following changes:&lt;br /&gt;
&lt;br /&gt;
In /etc/rc.d/rc.S:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# comment out the line&lt;br /&gt;
#    /sbin/mount -w -v -n -o remount /&lt;br /&gt;
#add the line&lt;br /&gt;
     /sbin/zfs set readonly=off zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In /etc/rc.d/rc.6&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# comment out the line&lt;br /&gt;
#    /bin/mount -v -n -o remount,ro /&lt;br /&gt;
#add the line&lt;br /&gt;
     /sbin/zfs set readonly=on zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In /etc/rc.d/rc.6, near the bottom just before poweroff|reboot, add the following block of lines:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
########################&lt;br /&gt;
# Try to export zfs-root&lt;br /&gt;
/sbin/zpool export zfs-root&lt;br /&gt;
if [ $? -gt 0 ] ; then&lt;br /&gt;
 echo &amp;quot;ZFS export failed.&amp;quot;&lt;br /&gt;
 echo &amp;quot;Notice: if root fs is busy, then this is normal fail.&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;ZFS export successful.&amp;quot;&lt;br /&gt;
 echo &amp;quot;Warning: successful export is abnormal for root fs.&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
/bin/sleep 5&lt;br /&gt;
########################&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
For ZFS, you cannot run fsck on it. It doesn't support that kind of filesystem check. The rc.S script will complain a lot in many places about not being able to run fsck on the zfs-root. To disable all attempts of run fsck, we can simply create a file that acts as a flag in /etc/rc.d/rc.S to tell it to skip fsck:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
touch /etc/fastboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This fastboot file is normally a run-once temporary file, and it is deleted near the bottom inside rc.S. Edit rc.S and stop it from deleting /etc/fastboot. We would like it to always skip all fsck. Edit /etc/rc.d/rc.S, and find the &amp;quot;rm&amp;quot; of fastboot, and do not have it removed!&lt;br /&gt;
&lt;br /&gt;
We are getting close, and have finished all editing, so make /boot/initrd.gz and install lilo:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkinitrd -F&lt;br /&gt;
lilo&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We finished! All that's left to do is clean up.&lt;br /&gt;
&lt;br /&gt;
Exit the chroot.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
exit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Try to umount everything:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
umount /mnt/proc&lt;br /&gt;
umount /mnt/sys&lt;br /&gt;
umount /mnt/dev&lt;br /&gt;
umount /mnt/boot&lt;br /&gt;
umount /mnt/mnt/cdrom&lt;br /&gt;
umount /mnt/root/packages&lt;br /&gt;
umount /mnt&lt;br /&gt;
zpool export zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note, that export stops a pool and frees devices, while import binds devices and starts a pool. It is somewhat like mdadm -A -s and mdadm -S -s, while /etc/zfs/zpool.cache might be somewhat like mdadm -E -s &amp;gt; /etc/mdadm.conf.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Remove the DVD or change boot order&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When you reboot, if all is good, you are booting properly onto a slackware installed on a ZFS root! Congrats!&lt;br /&gt;
&lt;br /&gt;
If this seems to go badly, and this might happen if the import fails as explained some before, then you will be on the initrd's rescue command line just before the part in init where it wants to mount zfs-root and switch_root to boot up. In this case, you typically got commands like these to do:&lt;br /&gt;
&lt;br /&gt;
If you get dumped to rescue because zpool import will not work and requires -f (force), then:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 zpool import -f zfs-root&lt;br /&gt;
 zpool export    zfs-root&lt;br /&gt;
 zpool import    zfs-root&lt;br /&gt;
 mount zfs-root&lt;br /&gt;
 exit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This can happen if hostname, hostid, or uname changes.&lt;br /&gt;
&lt;br /&gt;
If you get into a jam and need to boot into the initrd and skip zpool import etc, use the lilo prompt (or, boot the install-dvd):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
boot: vmlinuz rescue&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the rescue mode of the initrd, after you have mounted your zfs-root as readonly=on to /mnt, then &amp;quot;exit&amp;quot; to continue booting.&lt;br /&gt;
&lt;br /&gt;
In other emergency command lines, you might need to run the lines at the end of init starting from: &amp;lt;code&amp;gt;udevadm info --cleanup-db; udevadm control --exit&amp;lt;/code&amp;gt;&lt;br /&gt;
If you don't run those udevadm commands, two runs of udevd fight each other and it is slow; you have to wait 2 minutes twice for timeouts (4 minutes).&lt;br /&gt;
The last line in init is run like: &amp;lt;code&amp;gt;exec switch_root /mnt /sbin/init 1&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Warning: the switch_root command is kind of dangerous, so read the manual page about it. From what I can tell, everything except the new root &amp;quot;/mnt&amp;quot; is deleted, so you are giving a command that says what NOT to delete! Make sure nothing got mounted outside of &amp;quot;/mnt&amp;quot; before you run it. However, the deletes should not cross filesystems, but only delete the contents of initramfs.&lt;br /&gt;
&lt;br /&gt;
Also, in rescue command line or anytime you have finished making changes and are about to reboot in some abnormal situation, first run:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set readonly=on zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A bug in unpatched grep 2.13 build 1, found slackware 14.0rc1, causes problems when processing files stored on ZFS but rarely shows problems on other filesystems; the bug does not handle sparse files on zfs and btrfs correctly and results in chaos with slackpkg, compiling kernel modules, and possibly many other things. You must downgrade grep to 2.12 or use the patched grep 2.13 build 2 in slackware 14.0rc2 or later.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
Upgrading:&lt;br /&gt;
&lt;br /&gt;
From time to time you will want to upgrade the kernel to the new kernel in slackware64-current or in patches/. This will also necessitate a rebuild and reinstall or upgrade of spl and zfs. Below is an example of when both kernel and spl/zfs are being upgraded, to give an idea of the process:&lt;br /&gt;
&lt;br /&gt;
Using slackpkg, that is configured to use your local slackware mirror is a good option but you can also configure it to use a remote mirror.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slackpkg upgrade-all&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Assume slackpkg just upgraded your kernel, kernel-modules, kernel-headers, and kernel-source.&lt;br /&gt;
&lt;br /&gt;
Note: the first time you try to run on kernel-generic, setup kernel-huge in lilo as 2nd choice. Huge has all the hard drive controllers builtin, but generic has them all as modules. For example, run &amp;quot;modinfo mptsas&amp;quot; to see module options (maybe you have a LSISAS1068) for your hard drive controller. Add file /etc/modprobe.d/mptsas.conf to set options you want with a line: options mptsas ... Do this for all the device driver modules for your hardware. Do this setup while you are on the huge kernel, then setup to reboot to generic. Include all these modules you need into mkinitrd.conf MODULES_LIST. Check that /boot/initrd-tree/etc/modprobe.d/ has a copy of your customized module conf files because it is on the initrd where the modules will load and use the conf files. mkinitrd probably copies all /etc/modprobe.d/* files into the initrd-tree, but check it. Pay attention to /etc/modprobe.d/README and /lib/modprobe.d/* /lib/modprobe.d/* maybe not copied to initrd-tree but you might want to copy some of it into your initrd-tree yourself to use them.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Check that upgraded kernel-source is symlinked to /usr/src/linux (zfs build looks here). SPL/ZFS modules will install to the kernel version in /lib/modules/&amp;lt;/usr/src/linux kernel version&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /usr/local/src&lt;br /&gt;
tar xvzf ~/spl-*.tar.gz&lt;br /&gt;
tar xvzf ~/zfs-*.tar.gz&lt;br /&gt;
&lt;br /&gt;
###### upgrade spl 1st&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-*&lt;br /&gt;
./configure --prefix=/ --libexecdir=/usr/libexec --libdir=/lib64 --includedir=/usr/include --datarootdir=/usr/share&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=/usr/local/src/install&lt;br /&gt;
cd ../install&lt;br /&gt;
makepkg ../spl-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
upgradepkg spl-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
depmod &amp;lt;new kernel version&amp;gt;     (e.g. depmod 3.2.27, if .27 is new kernel upgrade; you currently run on old, maybe .26)&lt;br /&gt;
# this builds the module dependencies in /lib/modules/&amp;lt;new kernel version&amp;gt;&lt;br /&gt;
###### upgrade zfs 2nd&lt;br /&gt;
mkdir install&lt;br /&gt;
cd zfs-*&lt;br /&gt;
./configure --prefix=/ --libexecdir=/usr/libexec --libdir=/lib64 --includedir=/usr/include --datarootdir=/usr/share&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=/usr/local/src/install&lt;br /&gt;
cd ../install&lt;br /&gt;
makepkg ../zfs-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
upgradepkg zfs-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
depmod 3.2.27&lt;br /&gt;
####### upgrade spl/zfs inside altroot /boot/initrd-tree&lt;br /&gt;
ROOT=/boot/initrd-tree upgradepkg spl-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
ROOT=/boot/initrd-tree upgradepkg zfs-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
# note: ROOT is an environment variable, not a command line option to upgradepkg!&lt;br /&gt;
# note: do not worry about depmod inside initrd-tree, mkinitrd -F actually installs the modules&lt;br /&gt;
# note: this upgrade here is really to just upgrade the command line tools zpool, zfs etc&lt;br /&gt;
####### rebuild /boot/initrd.gz and reinstall lilo&lt;br /&gt;
vi /etc/mkinitrd.conf&lt;br /&gt;
# temporarily set KERNEL_VERSION to new version, but you are still running on old version&lt;br /&gt;
mkinitrd -F&lt;br /&gt;
lilo&lt;br /&gt;
vi /etc/mkinitrd.conf&lt;br /&gt;
# you can set KERNEL_VERSION back to $(uname -r) now&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After reboot you can remove any old /lib/modules/&amp;lt;old kernel version&amp;gt; directory.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
More about /etc/hostid. If you want to experiment changing your /etc/hostid file and seeing if you can use it and make zpool import work normally, here is a tool that might be helpful:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/* software product name: foobarz-chhostid.c&lt;br /&gt;
 * suggested binary name: chhostid&lt;br /&gt;
 * license              : BSD&lt;br /&gt;
 * license text:&lt;br /&gt;
Copyright (c) 2012, foobarz&lt;br /&gt;
All rights reserved.&lt;br /&gt;
&lt;br /&gt;
Redistribution and use in source and binary forms, with or without&lt;br /&gt;
modification, are permitted provided that the following conditions are met:&lt;br /&gt;
    * Redistributions of source code must retain the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer.&lt;br /&gt;
    * Redistributions in binary form must reproduce the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer in the&lt;br /&gt;
      documentation and/or other materials provided with the distribution.&lt;br /&gt;
    * Neither the name of the &amp;lt;organization&amp;gt; nor the&lt;br /&gt;
      names of its contributors may be used to endorse or promote products&lt;br /&gt;
      derived from this software without specific prior written permission.&lt;br /&gt;
&lt;br /&gt;
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &amp;quot;AS IS&amp;quot; AND&lt;br /&gt;
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED&lt;br /&gt;
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE&lt;br /&gt;
DISCLAIMED. IN NO EVENT SHALL &amp;lt;COPYRIGHT HOLDER&amp;gt; BE LIABLE FOR ANY&lt;br /&gt;
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES&lt;br /&gt;
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;&lt;br /&gt;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND&lt;br /&gt;
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT&lt;br /&gt;
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS&lt;br /&gt;
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#define FOOBARZ_CHHOSTID_VERSION &amp;quot;1.0.5&amp;quot;&lt;br /&gt;
#include &amp;lt;sys/socket.h&amp;gt;&lt;br /&gt;
#include &amp;lt;netinet/in.h&amp;gt;&lt;br /&gt;
#include &amp;lt;arpa/inet.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;endian.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sysexits.h&amp;gt;&lt;br /&gt;
/* note: if include stdlib then sethostid fails even with _BSD_SOURCE defined */&lt;br /&gt;
&lt;br /&gt;
long swapbytes(long abcd) {&lt;br /&gt;
  long badc;&lt;br /&gt;
  unsigned char addr_a;&lt;br /&gt;
  unsigned char addr_b;&lt;br /&gt;
  unsigned char addr_c;&lt;br /&gt;
  unsigned char addr_d;&lt;br /&gt;
  addr_a = (unsigned char) (abcd &amp;gt;&amp;gt; 24);&lt;br /&gt;
  addr_b = (unsigned char) (abcd &amp;gt;&amp;gt; 16);&lt;br /&gt;
  addr_c = (unsigned char) (abcd &amp;gt;&amp;gt;  8);&lt;br /&gt;
  addr_d = (unsigned char) (abcd);&lt;br /&gt;
  return badc = ( (addr_b &amp;lt;&amp;lt; 24) | (addr_a &amp;lt;&amp;lt; 16) | (addr_d &amp;lt;&amp;lt; 8) | addr_c );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[])&lt;br /&gt;
{&lt;br /&gt;
 long newhostid;&lt;br /&gt;
 struct in_addr addr;&lt;br /&gt;
 char* invalidchar;&lt;br /&gt;
&lt;br /&gt;
 /*********** check command line */&lt;br /&gt;
 if(!( ((argc==3) &amp;amp;&amp;amp; ( (strcmp(argv[1],&amp;quot;-h&amp;quot;)==0) ||&lt;br /&gt;
                       (strcmp(argv[1],&amp;quot;-i&amp;quot;)==0) ||&lt;br /&gt;
                       (strcmp(argv[1],&amp;quot;-l&amp;quot;)==0) )) ||&lt;br /&gt;
       ((argc==2) &amp;amp;&amp;amp; ( (strcmp(argv[1],&amp;quot;-s&amp;quot;)==0) ))&lt;br /&gt;
     )&lt;br /&gt;
   ) {&lt;br /&gt;
                 /*01234567890123456789012345678901234567890123456789012345678901234567890123456789*/&lt;br /&gt;
  fprintf(stderr, &amp;quot;foobarz-chhostid, version %s. License: BSD.\n&amp;quot;, FOOBARZ_CHHOSTID_VERSION);&lt;br /&gt;
  fprintf(stderr, &amp;quot;foobarz-chhostid, (c) 2012, foobarz; all rights reserved.\n&amp;quot;);&lt;br /&gt;
  fprintf(stderr, &amp;quot;descr: %s change system hostid (in /etc/hostid).\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -h &amp;lt;new hostid&amp;gt;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        Change system hostid to &amp;lt;new hostid&amp;gt;;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        &amp;lt;new hostid&amp;gt; must be 32bit 8-digit hex number xxxxxxxx, each x in 0-f|F.\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        The ip corresponding to &amp;lt;new hostid&amp;gt; is also listed for reference only.\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -i &amp;lt;dotted ip address&amp;gt;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        Change system hostid to hostid corresponding to &amp;lt;dotted ip address&amp;gt;.\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -l &amp;lt;dotted ip address&amp;gt;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        List hostid corresponding to &amp;lt;dotted ip address&amp;gt;;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        no change to system hostid.\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -s\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        List current system hostid and corresponding ip address;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        no change to system hostid.\n&amp;quot;, argv[0]);&lt;br /&gt;
  return EX_USAGE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -h &amp;lt;hostid&amp;gt; */&lt;br /&gt;
 if( strcmp(argv[1],&amp;quot;-h&amp;quot;) == 0 ) {&lt;br /&gt;
  if(strlen(argv[2]) != 8) { fprintf(stderr, &amp;quot;new hostid must be 8-digit hex number xxxxxxxx, each x in 0-f|F\n&amp;quot;); return EX_USAGE; }&lt;br /&gt;
&lt;br /&gt;
  newhostid = strtol(argv[2],&amp;amp;invalidchar,16);&lt;br /&gt;
  if( newhostid==LONG_MIN ) { perror(&amp;quot;strtol (underflow)&amp;quot;); return EX_USAGE; }&lt;br /&gt;
  if( newhostid==LONG_MAX ) { perror(&amp;quot;strtol (overflow)&amp;quot;); return EX_USAGE; }&lt;br /&gt;
  if(*invalidchar != '\0') { fprintf(stderr, &amp;quot;invalid hex number %c; must be in 0-f|F\n&amp;quot;, *invalidchar); return EX_USAGE; }&lt;br /&gt;
&lt;br /&gt;
  if( sethostid(newhostid) != 0 ) {&lt;br /&gt;
   perror(&amp;quot;sethostid&amp;quot;);&lt;br /&gt;
   if( errno == EPERM ) return EX_NOPERM;&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
  }&lt;br /&gt;
  printf(&amp;quot;System hostid changed.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  /* hostid is a byte-swapped ip like b.a.d.c */&lt;br /&gt;
  /* get ip by swapping to correct order a.b.c.d and save into in_addr struct */&lt;br /&gt;
  addr.s_addr = htonl(swapbytes(newhostid));&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -i or -l, then find hostid for &amp;lt;dotted ip address&amp;gt; */&lt;br /&gt;
 if( (strcmp(argv[1],&amp;quot;-i&amp;quot;) == 0) || (strcmp(argv[1],&amp;quot;-l&amp;quot;) == 0) ) {&lt;br /&gt;
  if( inet_aton(argv[2], &amp;amp;addr) == 0 ) { fprintf(stderr, &amp;quot;inet_aton: invalid dotted ip address: %s\n&amp;quot;, argv[2]); return EX_USAGE; }&lt;br /&gt;
&lt;br /&gt;
  /* hostid is a byte-swapped ip like b.a.d.c */&lt;br /&gt;
  /* get hostid by swapping bytes of ip a.b.c.d */&lt;br /&gt;
  newhostid = swapbytes(ntohl(addr.s_addr));&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -i &amp;lt;dotted ip address&amp;gt; */&lt;br /&gt;
 if( strcmp(argv[1],&amp;quot;-i&amp;quot;) == 0 ) {&lt;br /&gt;
  if( sethostid(newhostid) != 0 ) {&lt;br /&gt;
   perror(&amp;quot;sethostid&amp;quot;);&lt;br /&gt;
   if( errno == EPERM ) return EX_NOPERM;&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
  }&lt;br /&gt;
  printf(&amp;quot;System hostid changed.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -l &amp;lt;dotted ip address&amp;gt; */&lt;br /&gt;
 if(strcmp(argv[1],&amp;quot;-l&amp;quot;) == 0 ) {&lt;br /&gt;
   printf(&amp;quot;Listing hostid for ip. (no changes)\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -s */&lt;br /&gt;
 if(strcmp(argv[1],&amp;quot;-s&amp;quot;) == 0 ) {&lt;br /&gt;
   /* see if /etc/hostid exists and print info */&lt;br /&gt;
   if( access(&amp;quot;/etc/hostid&amp;quot;, F_OK) != 0 ) {&lt;br /&gt;
     printf(&amp;quot;Notice: /etc/hostid does not exist.\n&amp;quot;);&lt;br /&gt;
     perror(&amp;quot;Reason&amp;quot;);&lt;br /&gt;
     printf(&amp;quot;System hostid derived from ip of hostname found in hosts file or dns.\n&amp;quot;);&lt;br /&gt;
   } else {&lt;br /&gt;
     printf(&amp;quot;Notice: /etc/hostid exists.\n&amp;quot;&lt;br /&gt;
            &amp;quot;System hostid is obtained from hostid file.\n&amp;quot;);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
  errno=0;&lt;br /&gt;
  newhostid = gethostid();&lt;br /&gt;
  if(errno!=0) { perror(&amp;quot;gethostid&amp;quot;); return EX_UNAVAILABLE; }&lt;br /&gt;
&lt;br /&gt;
  /* hostid is a byte-swapped ip like b.a.d.c */&lt;br /&gt;
  /* get ip by swapping to correct order a.b.c.d and save into in_addr struct */&lt;br /&gt;
  addr.s_addr = htonl(swapbytes(newhostid));&lt;br /&gt;
&lt;br /&gt;
  printf(&amp;quot;Listing current system hostid. (no changes)\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** print info and return */&lt;br /&gt;
 printf(&amp;quot;ip dot: %s\n&amp;quot;, inet_ntoa(addr) );&lt;br /&gt;
 printf(&amp;quot;ip hex: %.8x\n&amp;quot;, ntohl(addr.s_addr) );&lt;br /&gt;
 printf(&amp;quot;hostid: %.8x\n&amp;quot;, newhostid );&lt;br /&gt;
 return EX_OK;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
----&lt;br /&gt;
Now available! &amp;quot;ZFS root (builtin)&amp;quot; wiki (aka &amp;quot;ZFS root, part II&amp;quot;):&lt;br /&gt;
http://slackwiki.com/ZFS_root_(builtin)&lt;br /&gt;
It is now possible to build the modules and a small initramfs into your kernel to have a fully-contained and bootable ZFS root kernel from a simple lilo entry. Good luck!&lt;/div&gt;</description>
			<pubDate>Sun, 09 Sep 2012 04:06:47 GMT</pubDate>
			<dc:creator>Foobarz</dc:creator>
			<comments>https://www.slackwiki.com/Talk:ZFS_root</comments>
		</item>
		<item>
			<title>ZFS root</title>
			<link>https://www.slackwiki.com/index.php?title=ZFS_root&amp;diff=782</link>
			<guid isPermaLink="false">https://www.slackwiki.com/index.php?title=ZFS_root&amp;diff=782</guid>
			<description>&lt;p&gt;Foobarz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Tutorials]]&lt;br /&gt;
If you have heard about the ZFS filesystem and you're curious to try it out, then you can try it on slackware64, thanks to the ZFSonLinux.org project!&lt;br /&gt;
&lt;br /&gt;
In this article, an example is shown of how to install slackware64 14.0 onto a ZFS root filesystem (zfs-root) inside a QEMU virtual machine for testing purposes. It is recommended that you install qemu and learn how to use it to test a ZFS installation before you decide to use it on real hardware. A slackbuild for qemu can be found on slackbuilds.org. If you have a processor that supports Intel VT-x or AMD AMD-V virtualization acceleration (try modprobe kvm-intel or modprobe kvm-amd), then use the slackbuild for qemu-kvm.&lt;br /&gt;
&lt;br /&gt;
This article isn't going to go into any detail on actually using ZFS or what kinds of installation options and settings might be optimal. This article just presents an example of how to get started with ZFS on slackware.&lt;br /&gt;
&lt;br /&gt;
At this time of writing, ZFSonLinux is at &amp;quot;release candidate&amp;quot; (version 0.6.0-rc10) development stage, and many issues can occur. See the ZFSonLinux.org web site and the issues tracker for an idea about the current issues. There is also an irc channel on irc.freenode.net, #zfsonlinux, for discussion of issues and help.&lt;br /&gt;
&lt;br /&gt;
Although not required, it is helpful to keep a local mirror of slackware64 on your system. Having a local mirror makes it easier to upgrade to slackware64-current or to patches/* in a release. To help manage your own local slackware mirror and generate your own CD and DVD slackware installers, see http://alien.slackbook.org/blog/local-slackware-mirror/.&lt;br /&gt;
&lt;br /&gt;
In this article, we use a slackware64-current DVD image file as the qemu cdrom device media for the installation of the slackware guest. This was tested at slackware64-current = slackware64 14.0rc2. You can obtain a slackware DVD image using a torrent, buy the DVD from slackware.com, or generate your own DVD image file using the mirror script. For an actual DVD, you can pass your DVD device (e.g., /dev/sr0) as the qemu cdrom device. For a DVD image file, pass the image file as the qemu cdrom device.&lt;br /&gt;
&lt;br /&gt;
The ZFSonLinux packages are not included in slackware at this time. There are two packages involved: spl and zfs. The first, spl, is &amp;quot;Solaris Porting Layer&amp;quot; and must be installed on the system before zfs can be compiled. The source code tarballs for these are at ZFSonLinux.org. At this time of writing, they are spl-0.6.0-rc10.tar.gz and zfs-0.6.0-rc10.tar.gz.&lt;br /&gt;
&lt;br /&gt;
At this point, it is assumed you have qemu installed, have obtained a slackware64-current/14.0 DVD, and have downloaded spl and zfs tarballs to your host system. The first step now is, if your host is not slackware64-current/14.0 (the same as the guest will be), then you need to create a minimal development slackware64 guest system in qemu for just the purpose of compiling and packaging the spl and zfs slackware packages and transferring a copy of these packages back onto your host system to use later to install onto zfs during the slackware install process.&lt;br /&gt;
&lt;br /&gt;
From this point onward, instructions become a bit terse and mostly limited to examples of the commands you might use to complete tasks. You are encouraged to examine what each command does by reading the command's man pages. For example, the command &amp;quot;man qemu&amp;quot; can show you most of what you need to know about running qemu on the command line.&lt;br /&gt;
&lt;br /&gt;
So, here's an example of how you might build the spl and zfs packages, starting in your home directory:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on host)&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir qemu&lt;br /&gt;
cd qemu&lt;br /&gt;
mkdir slackdevel&lt;br /&gt;
cd slackdevel&lt;br /&gt;
mkdir packages&lt;br /&gt;
cp ~/spl-*.tar.gz packages&lt;br /&gt;
cp ~/zfs-*.tar.gz packages&lt;br /&gt;
qemu-img create disk1.raw 10G&lt;br /&gt;
ln -s ~/slackware64-current-install-dvd.iso dvd.iso&lt;br /&gt;
qemu-kvm \&lt;br /&gt;
 -option-rom 8xx_64.rom,bootindex=1 \&lt;br /&gt;
 -no-quit \&lt;br /&gt;
 -no-shutdown \&lt;br /&gt;
 -boot order=cd,menu=on \&lt;br /&gt;
 -m 2G \&lt;br /&gt;
 -cpu host \&lt;br /&gt;
 -smp sockets=1,cores=4 \&lt;br /&gt;
 -net nic,model=e1000 -net user \&lt;br /&gt;
 -cdrom dvd.iso \&lt;br /&gt;
 -drive format=raw,media=disk,cache=none,aio=native,if=scsi,index=0,file=disk1.raw \&lt;br /&gt;
 -virtfs local,path=./packages/,security_model=none,mount_tag=hostpackages&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When you need to change boot to cd or disk, try changing &amp;quot;order=dc&amp;quot; or hitting F12 at boot prompt and select the CD/DVD boot option.&lt;br /&gt;
&lt;br /&gt;
Note: The support for booting drives using if=scsi is not included with current versions of qemu. Booting scsi requires the 8xx_64.rom option-rom, which can be downloaded at [http://www.lsi.com/downloads/Public/Host%20Bus%20Adapters/Host%20Bus%20Adapters%20Common%20Files/lsi_bios.zip LSI.com]. Unzip it, and then:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp 8xx_64.rom /usr/share/qemu&lt;br /&gt;
# then run qemu-kvm with additional command line option: -option-rom 8xx_64.rom,bootindex=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Qemu should boot into the install-dvd, and now perform a very ordinary slackware64 install onto /dev/sda. Install d package set and most others, but package sets x, kde, xfce not really needed.&lt;br /&gt;
&lt;br /&gt;
First note: examples here use tools from the gptfdisk package (gdisk, sgdisk, cgdisk) to partition the disk with GUID partition table (GPT) format. GPT might not be too familiar to everyone, who mostly have only used MBR partitions with fdisk. In the slackware installations this author has tested in qemu, using GPT partitions has caused no problems with lilo or other tools used in slackware. GPT disk labels support creating up to 128 partitions and support disks larger than 2TB (the limit of MBR fdisk). LILO installs into the first 440 bytes on /dev/sda, inside a GPT &amp;quot;protective MBR&amp;quot; that serves to provide compatibility with MBR bootloaders like lilo. LILO uses LBA32 sector addressing and can see all 512-byte sectors inside the first 2TB of a disk. So long as the /boot partition is within the first 2TB of a disk, lilo can work on a disk larger than 2TB. Unlike the common default of fdisk to start the first partition at sector 63, which is not aligned with the 4KiB sector size of Advanced Format hard disks, gdisk's default is to start partitions at 2048 sector (1MiB) boundaries which are also 4KiB aligned. Using gdisk GPT works on all disks and is compatible with using Advanced Format hard disks larger than 2TB. More information about GPT disk label format can be found on wikipedia.org. For those that have used grub instead of lilo, grub installation is different with GPT than with MBR, and grub requires a GPT partition of type grub-bios or 0xEF02 &amp;quot;BIOS Boot Partition&amp;quot; of about 8MiB where it can install it's additional bootloader stages because grub cannot embed in sectors 1-62 on GPT where GPT keeps it's partition tables. On MBR, sectors 1-62 were normally reserved space for bootloaders to keep a 2nd stage.&lt;br /&gt;
&lt;br /&gt;
For this purpose of development guest, just create a simple 1-partition system, /dev/sda1, and do a simple slackware install on it. Don't bother with swap or separate /boot unless you want to:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on install-dvd)&lt;br /&gt;
cgdisk /dev/sda&lt;br /&gt;
setup&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When this simple development guest boots, login as root, and continue:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on qemu guest)&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir packages&lt;br /&gt;
mount hostpackages -t 9p -o trans=virtio packages&lt;br /&gt;
echo --prefix=/ --libexecdir=/usr/libexec --libdir=/lib64 --includedir=/usr/include --datarootdir=/usr/share &amp;gt; configure-options&lt;br /&gt;
mkdir src&lt;br /&gt;
cd src&lt;br /&gt;
&lt;br /&gt;
mkdir install&lt;br /&gt;
tar xvzf ~/packages/spl-*.tar.gz&lt;br /&gt;
cd spl-*&lt;br /&gt;
./configure $( cat ~/configure-options )&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../spl-&amp;lt;version&amp;gt;_&amp;lt;kernel_version&amp;gt;-x86_64-&amp;lt;build_id&amp;gt;.txz&lt;br /&gt;
(e.g., makepkg ../spl-0.6.0rc10_3.2.27-x86_64-1root.txz)&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
installpkg spl-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
cp spl-0.6.0rc10_3.2.27-x86_64-1root.txz ~/packages&lt;br /&gt;
&lt;br /&gt;
mkdir install&lt;br /&gt;
tar xvzf ~/packages/zfs-*.tar.gz&lt;br /&gt;
cd zfs-*&lt;br /&gt;
./configure $( cat ~/configure-options )&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../zfs-&amp;lt;version&amp;gt;_&amp;lt;kernel_version&amp;gt;-x86_64-&amp;lt;build_id&amp;gt;.txz&lt;br /&gt;
(e.g., makepkg ../zfs-0.6.0rc10_3.2.27-x86_64-1root.txz)&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
installpkg zfs-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
cp zfs-0.6.0rc10_3.2.27-x86_64-1root.txz ~/packages&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point spl and zfs packages are copied back to the host in the packages directory. Also, spl and zfs are installed in this simple development guest, so one could begin to experiment with zfs pools and datasets but while the root fs is whatever you made it during setup (probably the default, ext4). This development guest isn't really needed anymore, so it can be deleted:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
halt&lt;br /&gt;
(exit qemu: ctrl-alt-2 then enter quit at QEMU command prompt)&lt;br /&gt;
&lt;br /&gt;
(on host)&lt;br /&gt;
rm disk1.raw dvd.iso&lt;br /&gt;
mv packages ..&lt;br /&gt;
cd ..&lt;br /&gt;
rmdir slackdevel&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now that we have the spl and zfs packages on the host, it is possible to copy them into your local slackware64 mirror and then generate your own install DVD image that includes them. For example, change to the directory that contains the slackware README files, and create a &amp;quot;addon&amp;quot; directory and copy the spl and zfs slackware packages into there. Then, generate the DVD image using a command such as $( ./mirror-slackware-current.sh -i ) from where you have this script configured to maintain your local mirror. We can also just continue to access them inside the installer using qemu's virtfs option. When you are going to do a real installation onto real hardware, you need to generate and burn your own DVD that includes the packages.&lt;br /&gt;
&lt;br /&gt;
It is time to begin the installation of slackware64 on a ZFS root, assuming either you have regenerated dvd.iso with zfs packages in addon/* or we access the zfs packages while in the installer using qemu's virtfs to the host's packages directory. ZFS supports creating complex data storage configurations such as pools (similar to a volume group) backed by one or more of various kinds of virtual devices (similar to disks and raid arrays) and containing one or more datasets (similar to mounted filesystems, logical volume devices, or snapshots). But here, we keep it simple and will install on just a single disk device. On a real ZFS installation, users will typically want to use the ZFS raidz1 or raidz2 virtual device types for reliability against hard drive failures.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on host)&lt;br /&gt;
mkdir slackzfs&lt;br /&gt;
mv packages slackzfs/&lt;br /&gt;
cd slackzfs&lt;br /&gt;
qemu-img create disk1.raw 10G&lt;br /&gt;
ln -s ~/slackware64-current-install-dvd.iso dvd.iso&lt;br /&gt;
qemu-kvm \&lt;br /&gt;
 -option-rom 8xx_64.rom,bootindex=1 \&lt;br /&gt;
 -no-quit \&lt;br /&gt;
 -no-shutdown \&lt;br /&gt;
 -boot order=cd,menu=on \&lt;br /&gt;
 -m 2G \&lt;br /&gt;
 -cpu host \&lt;br /&gt;
 -smp sockets=1,cores=4 \&lt;br /&gt;
 -net nic,model=e1000 -net user \&lt;br /&gt;
 -cdrom dvd.iso \&lt;br /&gt;
 -drive format=raw,media=disk,cache=none,aio=native,if=scsi,index=0,file=disk1.raw \&lt;br /&gt;
 -virtfs local,path=./packages/,security_model=none,mount_tag=hostpackages&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The install-dvd should boot, and then begin installation steps on the installer command line:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on install-dvd)&lt;br /&gt;
# mount the install-dvd&lt;br /&gt;
mkdir /dvd&lt;br /&gt;
mount /dev/sr0 /dvd&lt;br /&gt;
&lt;br /&gt;
# install coreutils, which provides the &amp;quot;hostid&amp;quot; command needed to load the spl module&lt;br /&gt;
installpkg /dvd/slackware64/a/coreutils-8.17-x86_64-1.txz&lt;br /&gt;
&lt;br /&gt;
# install kmod package which includes &amp;quot;depmod&amp;quot; command and others&lt;br /&gt;
installpkg /dvd/slackware64/a/kmod-9-x86_64-2.txz&lt;br /&gt;
depmod&lt;br /&gt;
&lt;br /&gt;
# install the full kernel modules so you can load 9p filesystem and use it if you want&lt;br /&gt;
# .. you might keep the zfs modules packages off the dvd and use a plain slack dvd&lt;br /&gt;
installpkg /dvd/slackware64/a/kernel-modules-*.txz&lt;br /&gt;
depmod&lt;br /&gt;
&lt;br /&gt;
# install bash and libtermcap because udev rules in zfs use bash scripts&lt;br /&gt;
installpkg /dvd/slackware64/a/bash-*.txz&lt;br /&gt;
installpkg /dvd/slackware64/l/libtermcap-*.txz&lt;br /&gt;
&lt;br /&gt;
# install spl and zfs that you have copied into the mirror before running the DVD creation&lt;br /&gt;
installpkg /dvd/addon/spl-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /dvd/addon/zfs-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
&lt;br /&gt;
#Or:&lt;br /&gt;
mkdir /packages&lt;br /&gt;
find /lib/modules/ | grep 9p&lt;br /&gt;
lsmod&lt;br /&gt;
# check that 9p modules load, mainly 9pnet_virtio&lt;br /&gt;
modprobe 9pnet_virtio&lt;br /&gt;
mount hostpackages -t 9p -o trans=virtio /packages&lt;br /&gt;
installpkg /packages/spl-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /packages/zfs-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
modprobe zfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now zfs tools: &amp;quot;zpool&amp;quot; and &amp;quot;zfs&amp;quot; should work in the live installer.&lt;br /&gt;
On the installer, there can be trouble seeing man pages, so install:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
installpkg /dvd/slackware64/ap/man-*.txz&lt;br /&gt;
installpkg /dvd/slackware64/ap/groff-*.txz&lt;br /&gt;
installpkg /dvd/slackware64/a/less-*.txz&lt;br /&gt;
export MANPATH=/usr/man:/usr/share/man&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The manual pages should be readable:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
man zpool&lt;br /&gt;
man zfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After seeing the man pages, we should be fully ready to continue to setup on ZFS.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(still on install-dvd)&lt;br /&gt;
ls -l /dev/sd*&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Make sure the disk devices you expect are there. We'll use sda and make boot (/boot on /dev/sda1) and root (/ on /dev/sda2) partitions.&lt;br /&gt;
&lt;br /&gt;
First, some background info: A ZFS filesystem is not supported by lilo as the filesystem containing /boot, which holds lilo's 2nd stage and the linux kernel files. The on-disk format of a ZFS filesystem is often a complex raid configuration where even if lilo understood ZFS it would likely require /boot to reside in only certain simple ZFS configurations to be plainly readable to lilo. As things are, a linux root installed in a partition with ZFS filesystem needs /boot to be on another partition with a filesystem that lilo understands, such as ext4 fs. In addition, because the spl and zfs modules are not built into the kernel, and the zfs startup requires some configuration to mount the zfs root, an initial ram/root filesystem (initrd) is needed. The initrd is a gzip compressed cpio archive file that contains a small linux root operating system that is decompressed into a ramfs block device at boot up and takes initial control of the system. The initrd contains an init script that configures devices in devtmpfs mounted at /dev. For example, if using mdadm, lvm, luks, losetup, and now zfs, this init script runs all the commands to create or start these devices (one of which is the root device), mounts the root device, and then transfers system control to the init script in the mounted root filesystem. The ramfs-based root environment on the booted install-dvd or booted initrd image (in rescue command line) are small slackware installations that exist only in ram and are temporary, but while inside them you can install, upgrade, and remove slackware packages inside them using the regular package management tools; this allows you access to any kernel modules and programs as needed inside these ramfs root. Packages can be installed, upgraded, or removed permanantly in the initrd image file to manage the programs and modules required during the initrd boot stage. Also from within these ramfs initial root environments, once the root device is mounted, chroot can be used to work on the mounted root system as if it were booted; this allows one to fix problems that are occuring in the root fs init scripts that cause normal booting to fail, or to install a kernel and/or modules etc. Now on to partitioning:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cgdisk /dev/sda&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, cgdisk looks just like cfdisk, but it makes GPT partitions.&lt;br /&gt;
&lt;br /&gt;
Make a partition for /boot that is about 512MiB of whatever partition type you like (8300 &amp;quot;Linux filesystem&amp;quot; is fine), or make it type bf07 &amp;quot;Solaris Reserved 1&amp;quot; if you want ZFS to maybe see the disk as if it was given as a whole disk to ZFS. Make a second partition using the remaining space with partition type bf01 &amp;quot;Solaris ZFS&amp;quot;. Currently, when ZFSonLinux is given a whole disk device like /dev/sdb to use, it will automatically GPT partition it with a bf01 partition #1 that is the whole disk except a small 8MiB type bf07 partition #9 at the end of the disk (/dev/sdb1 and /dev/sb9). The small 8MiB type bf07 partition #9 is most likely reserved for use by bootloaders, like lilo, to have a /boot or other boot-related files kept there. For example, you might have /dev/sda that is totally non-ZFS for booting and /dev/sdb passed to ZFS whole where it automatically partitions sdb, but you can just use one disk here and make partitions. Let's use type 8300 for /boot to be sure nothing is confused:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
We'll continue with this partitioning (numbers are in MiB):&lt;br /&gt;
  0 to   4: unused&lt;br /&gt;
  4 to 516: /dev/sda1 512MiB, type 8300&lt;br /&gt;
516 to 520: unused&lt;br /&gt;
520 to -96: /dev/sda2, type bf01&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The -96 means to count from the end of the disk so that 96MiB will remain unused at the end of the disk.&lt;br /&gt;
&lt;br /&gt;
Create a zpool called zfs-root:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool create -m none zfs-root /dev/sda2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A zpool created like this, the normal way, is a kernel-internal block device that contains already a zfs filesystem. There is normally no entry in /dev for this device. However, it can still be referenced as a mountable device similar to how devtmpfs, proc, and sysfs are also kernel-internal mountable block devices. The -m option told zpool not to automatically mount it anywhere, and without -m the default is to always automatically mount to /zfs-root. These kinds of details are explained better elsewhere. For this situation, we do not want it automounted.&lt;br /&gt;
&lt;br /&gt;
Because a zpool itself is a useable zfs fs, it has a full set of zfs &amp;quot;properties&amp;quot; to set options about the filesystem, perhaps similar to tune2fs. The &amp;quot;mountpoint=&amp;lt;some place to mount&amp;gt;&amp;quot; is one such property. We want it set to the special value &amp;quot;none&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs get mountpoint zfs-root&lt;br /&gt;
zfs set mountpoint=none zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On creation, the zpool zfs-pool is &amp;quot;imported&amp;quot; and has a zpool status that can be viewed:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool status zfs-root&lt;br /&gt;
&lt;br /&gt;
zpool export zfs-root&lt;br /&gt;
zpool status zfs-root&lt;br /&gt;
# Now there is no status.&lt;br /&gt;
&lt;br /&gt;
zpool import zfs-root&lt;br /&gt;
# Now it is back.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When a zpool is imported, it has it's current configuration cached in a file /etc/zfs/zpool.cache. When a zpool is exported, then it's entries in the cache file are removed and the cache file is deleted if it becomes empty. So long as the zfs kernel modules see this cache file and valid cache data inside it, ZFS considers the described zpools in the cache file to be valid as imported zpools. If the zpool.cache file is present at the time the zfs modules are loaded, then there is no further need to use the import and export zpool commands at system startup and shutdown. With root on a zfs, it is not possible to export the pool that root is on, but this is not a problem. At shutdown, the safe procedure will be to set the zfs-root property readonly=on and sync disks.&lt;br /&gt;
&lt;br /&gt;
To avoid the requirement to import the zfs-root pool at startup, keep a copy of the zpool.cache file to later copy onto the initrd image to read at modules load time to have the pool reactivated without need to issue the zpool import command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/zfs/zpool.cache /etc/zfs/zpool.cache-initrd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A zfs fs will not normally allow you to mount over any files. The mountpoint is expected to be an empty directory. Remove any junk files inside the installer's /mnt because zfs won't mount over any files:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rm /mnt/README&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The directory /mnt is where the slackware setup expects you to mount your root for installation.&lt;br /&gt;
&lt;br /&gt;
Controlling whether a zfs fs is to be mounted read-only or read-write is best managed by setting the readonly property while it is not yet mounted:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set readonly=on zfs-root&lt;br /&gt;
zfs set readonly=off zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Slackware expects root to be mounted readonly when /etc/rc.d/rc.S runs during normal startup, so later this is used to satisfy slackware's expectation to avoid rc.S complaining.&lt;br /&gt;
&lt;br /&gt;
The zfs-root can be mounted and unmounted in two different ways:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=/mnt zfs-root&lt;br /&gt;
zfs set mountpoint=none zfs-root&lt;br /&gt;
# or&lt;br /&gt;
mount zfs-root -t zfs /mnt&lt;br /&gt;
umount /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If it is already mounted and you want to change it to mount somewhere else, it is best to transition it to unmounted first, then mount it in the new place.&lt;br /&gt;
&lt;br /&gt;
The mount options &amp;lt;code&amp;gt;-o ro, -o rw, -o remount,ro, and -o remount,rw &amp;lt;/code&amp;gt; can also be used and will override the &amp;lt;code&amp;gt;readonly=on|off&amp;lt;/code&amp;gt; property without altering the property value. This can be confusing until you are familiar with how the two methods of mounting interact. When &amp;lt;code&amp;gt;mountpoint=legacy&amp;lt;/code&amp;gt; is set, zfs expects the regular mount and umount commands to be used to mount and unmount the dataset with the assistance of the mount.zfs helper. For now, we will continue with &amp;lt;code&amp;gt;mountpoint=none&amp;lt;/code&amp;gt;, but using legacy is also a good option.&lt;br /&gt;
&lt;br /&gt;
Now, let's continue some, and mount to /mnt using the current &amp;lt;code&amp;gt;readonly=off&amp;lt;/code&amp;gt; setting (rw mount):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=/mnt zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This method of mounting will show the most detailed mount options in /etc/mtab. They are the mount options that zfs thinks are proper, and they are probably what should be kept in /etc/fstab for zfs-root until we know better.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cat /etc/mtab &amp;gt;&amp;gt; /etc/fstab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now edit /etc/fstab to make sure it looks right, and remove the &amp;quot;rw&amp;quot; mount option, because we want to let it use a default for that, which will come from how we set the readonly= property most of the time. Unmount again:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=none zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mount again, now using all options from /etc/fstab:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It should be mounted at /mnt, and touch /mnt/t should allow you to make the file t. Then rm it: rm /mnt/t&lt;br /&gt;
For installation, we want to make sure it is mounted read-write. After installation, it should mount readonly inside the initrd.&lt;br /&gt;
&lt;br /&gt;
Sometimes there can be problems using the mount command, and then you can try it with the -i option:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 mount -i zfs-root&lt;br /&gt;
 mount -i zfs-root -t zfs /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
but, you should not have to use -i. When using -i makes it work, it performs an &amp;quot;internal-only&amp;quot; mount and does not use any mount.&amp;lt;fstype&amp;gt; helper scripts that might be on the system. You can use &amp;lt;code&amp;gt;mountpoint=legacy&amp;quot;&amp;lt;/code&amp;gt; to avoid this small problem if you are preferring to use the regular mount and umount commands on your zfs-root.&lt;br /&gt;
&lt;br /&gt;
Setup the /boot device:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkfs.ext4 /dev/sda1&lt;br /&gt;
mkdir /mnt/boot&lt;br /&gt;
mount /dev/sda1 /mnt/boot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We have both root and boot mounted where the slackware installer expects them. Unmount the dvd so setup can find it normally:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
umount /dev/sr0&lt;br /&gt;
setup&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the setup, skip straight to TARGET selection for the root device, but the setup doesn't see or understand the zfs-root, so it is not listed. This does not matter because we have mounted it already. Just skip down to a slot that say to continue, and continue on with setup. Because TARGET is skipped, you may not see the ADDITIONAL prompt (or if so, skip it too) where normally you give /dev/sda1 and have it mounted as /boot. This is also okay because we have mounted /mnt/boot already.&lt;br /&gt;
Because we did not give TARGET the root device or say what device /boot is on, the lilo installation will fail, or you can skip it. Otherwise, this installation process is normal.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Finish installation and exit setup, but do NOT reboot!&lt;br /&gt;
# There is still a lot to do before rebooting.&lt;br /&gt;
umount /dev/sr0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point, it is assumed that the setup has completed installing into /mnt. Congrats! You've installed slackware into a ZFS root!&lt;br /&gt;
&lt;br /&gt;
The next steps are to prepare to use &amp;quot;chroot /mnt&amp;quot; and finish up the configuration on the installed root system and then be able to reboot onto the completed installation. Before doing chroot, copy some files from the setup environment into /mnt.&lt;br /&gt;
&lt;br /&gt;
Copy the current installer /etc/fstab for later use inside the initrd. This fstab is what is proper inside the initrd, except remove option &amp;quot;rw&amp;quot; (if not done already).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/fstab /mnt/etc/fstab.initrd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The fstab.initrd will look like:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 proc /proc proc defaults 0 0&lt;br /&gt;
 zfs-root /mnt zfs defaults,atime,dev,exec,suid,xattr,nomand,zfsutil 0 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the initrd, we want zfs-root to mount to /mnt.&lt;br /&gt;
&lt;br /&gt;
Create /mnt/etc/fstab:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cat /etc/mtab &amp;gt;&amp;gt; /mnt/etc/fstab&lt;br /&gt;
vi /mnt/etc/fstab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using vi started above, edit /mnt/etc/fstab and make it have lines such as:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 zfs-root / zfs defaults,atime,dev,exec,suid,xattr,nomand,zfsutil 0 0&lt;br /&gt;
 /dev/sda1 /boot ext4 defaults 0 2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These two lines in &amp;lt;code&amp;gt;/mnt/etc/fstab&amp;lt;/code&amp;gt; are how the mounts should be looking when root is booted.&lt;br /&gt;
&lt;br /&gt;
Mount some special mounts before chroot:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount -t devtmpfs none /mnt/dev&lt;br /&gt;
mount -t proc none /mnt/proc&lt;br /&gt;
mount -t sysfs none /mnt/sys&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Make sure /boot is mounted:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount /dev/sda1 /mnt/boot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you had mounted a 9p fs share to access spl and zfs packages, then unmount that now:&lt;br /&gt;
umount /packages&lt;br /&gt;
&lt;br /&gt;
Ready, now:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chroot /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point, you should be on the installed system, and now try to configure mkinitrd and lilo. First, switch to use the generic kernel.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /boot&lt;br /&gt;
rm System.map config vmlinuz&lt;br /&gt;
ln -s System.map-gen* System.map&lt;br /&gt;
ln -s config-gen* config&lt;br /&gt;
ln -s vmlinuz-gen* vmlinuz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We installed spl and zfs inside the live ramfs install-dvd environment, but not yet have we installed them into the root system:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount /dev/sr0 /mnt/cdrom&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /mnt/cdrom/addon/spl-*.txz&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /mnt/cdrom/addon/zfs-*.txz&lt;br /&gt;
depmod&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If instead, you used a 9p share to access the spl and zfs packages, then repeat that procedure here to install them onto the root system.&lt;br /&gt;
&lt;br /&gt;
Setup lilo: edit /etc/lilo.conf so it is like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  lba32&lt;br /&gt;
  append = &amp;quot; vt.default_utf8=1&amp;quot;&lt;br /&gt;
  boot = /dev/sda&lt;br /&gt;
  message = /boot/boot_message.txt&lt;br /&gt;
  prompt&lt;br /&gt;
  timeout = 1200&lt;br /&gt;
  change-rules&lt;br /&gt;
   reset&lt;br /&gt;
  vga = normal&lt;br /&gt;
  image = /boot/vmlinuz&lt;br /&gt;
   label = vmlinuz&lt;br /&gt;
   initrd = /boot/initrd.gz&lt;br /&gt;
   root = /dev/ram0&lt;br /&gt;
   read-write&lt;br /&gt;
# alternatively, the root and read-write lines&lt;br /&gt;
# can be this one line of kernel parameters:&lt;br /&gt;
#  addappend = &amp;quot; root=/dev/ram0 rw &amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A note about initrd: The /boot/initrd.gz is a gzipped cpio archive containing a minimal BusyBox-based slackware root system that is sourced from /boot/initrd-tree. The commands &amp;quot;mkinitrd&amp;quot; and &amp;quot;mkinitrd -F&amp;quot; generates /boot/initrd-tree and /boot/initrd.gz. When using a initrd, the initial root device is normally set to root=/dev/ram0 (a ramfs block device) and allowed read-write. The kernel refers to devices in terms of &amp;quot;major&amp;quot; and &amp;quot;minor&amp;quot; numbers, and the ram0 device is assigned the block device major 1 and minor 0. This ram0 major/minor is written in hexadecimal as 0x0100 (256 in decimal). This hexademical number makes an appearance in /boot/initrd-tree/int where it runs: &amp;quot;echo 0x0100 &amp;gt; /proc/sys/kernel/real-root-dev&amp;quot;. Echoing a device code to real-root-dev is part of a deprecated initrd mechanism, but is probably harmless to leave alone as slackware has it unless you know otherwise. More information about how initrd works can be found in:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/usr/src/linux/Documentation/devices.txt (info about major:minor device numbers)&lt;br /&gt;
/usr/src/linux/Documentation/initrd.txt  (mostly obsolete info on old initrd)&lt;br /&gt;
/usr/src/linux/Documentation/filesystems/ramfs-rootfs-initramfs.txt (current info on new initrd, called initramfs)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Advanced note about initrd: Slackware's mkinitrd package does not use the &amp;quot;pivot_root&amp;quot; command as documented in &amp;quot;initrd.txt&amp;quot;, but instead uses &amp;quot;switch_root&amp;quot; provided by a project called BusyBox. The switch_root command changes the effective root filesystem from the initrd (unpacked in rootfs at /) to the new root filesystem (zfs-root mounted at /mnt); it overmounts rootfs / with zfs-root /mnt. The switch_root works as follows: delete everything in rootfs / (one filesystem only) that held initrd to free up ram memory, then use mount, chroot, and chdir to make the effective root change. In concept (as a shell script), the command &amp;quot;exec switch_root /mnt $INIT $RUNLEVEL&amp;quot; is performed as follows:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 find / -xdev | xargs rm -rf&lt;br /&gt;
 cd &amp;quot;$1&amp;quot;&lt;br /&gt;
 shift&lt;br /&gt;
 mount --move . /&lt;br /&gt;
 exec chroot . &amp;quot;$@&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Here, typically INIT=/sbin/init RUNLEVEL=3. The 'exec' causes switch_root to take the place of the parent process having PID=1. In system calls, the switch_root looks similar to this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chdir(&amp;quot;/mnt&amp;quot;);&lt;br /&gt;
/* &amp;lt;insert code to unlink/rmdir all initrd files/directories&lt;br /&gt;
 *  installed in rootfs / without crossing filesystems &amp;gt; */&lt;br /&gt;
mount(&amp;quot;.&amp;quot;, &amp;quot;/&amp;quot;, NULL, MS_MOVE, NULL);&lt;br /&gt;
chroot(&amp;quot;.&amp;quot;);&lt;br /&gt;
chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
execl(&amp;quot;/sbin/init&amp;quot;, &amp;quot;3&amp;quot;, (char*) NULL );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The kernel's rootfs / that contained initrd is never actually unmounted (it can't be) because it is built into the kernel and always exists as at least a tiny ramfs or tmpfs, so you can continue to see it in /proc/mounts. When you give lilo root=/dev/ram0 (a ramfs device), the kernel will actually use the internal rootfs, which is an instance of a tmpfs (if your kernel config includes tmpfs) or ramfs. The rootfs that is a tmpfs can by default use up to half of system ram. If rootfs is a ramfs, it can use up to almost all of system ram until the system panics. Typically, tmpfs is built into the kernel, and so depending on how much ram your computer has, the initrd-tree can probably be up to about half that size.&lt;br /&gt;
&lt;br /&gt;
Quite a lot of notes... now to continue on:&lt;br /&gt;
&lt;br /&gt;
Setup mkinitrd:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/mkinitrd.conf.sample /etc/mkinitrd.conf&lt;br /&gt;
vi /etc/mkinitrd.conf&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Edit it to look like this (other defaults should be ok):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 MODULE_LIST=&amp;quot;sym53c8xx:ext4:e1000:zfs:9p:9pnet_virtio&amp;quot;&lt;br /&gt;
 ROOTDEV=&amp;quot;zfs-root&amp;quot;&lt;br /&gt;
 ROOTFS=&amp;quot;zfs&amp;quot;&lt;br /&gt;
#Module sym53c8xx is the driver for qemu's if=scsi drive device.&lt;br /&gt;
#Module ext4 for /boot.&lt;br /&gt;
#Module e1000 for eth0 net device.&lt;br /&gt;
#Module zfs for ZFSonLinux.&lt;br /&gt;
#Modules 9p and 9pnet_virtio for mounting qemu -virtfs mount_tag.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These 9p modules could be useful from the rescue command line inside the initrd to get needed files that are on the host.&lt;br /&gt;
&lt;br /&gt;
All dependent modules will also be included automatically into /boot/initrd-tree, which is packaged as /boot/initrd.gz. For example, to see the dependent modules of zfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
modprobe --show-depends zfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All listed modules will also be in the initrd. Now, make a /boot/initrd-tree that we can begin to look at and edit.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkinitrd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create an empty /etc/mtab or else zpool import fails (zfs expects /etc/mtab to exists already, it won't make it).&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
touch /boot/initrd-tree/etc/mtab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Copy in the fstab.initrd that was made earlier while on the installer. This provides all the mount options for a simple &amp;quot;mount zfs-root&amp;quot; onto /mnt.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/fstab.initrd /boot/initrd-tree/etc/fstab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More package installing! This time into an alternate root, the root of the initrd, /boot/initrd-tree. This is how you can put whatever packages you like into your initrd. These installations work independent of your normal installations. You can install, upgrade, and remove packages using an altroot:&lt;br /&gt;
&lt;br /&gt;
If spl and zfs are on your customized dvd:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/addon/spl-*.txz&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/addon/zfs-*.txz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Otherwise, repeat same procedure but you mount your 9p mount_tag and get them installed.&lt;br /&gt;
&lt;br /&gt;
More regular packages from the dvd:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/kmod-*.txz&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/coreutils-*.txz&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/gptfdisk-*.txz&lt;br /&gt;
&lt;br /&gt;
# A bash script is in /boot/initrd-tree/lib/udev/, so we need it or udev rules have problems:&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/bash-*.txz&lt;br /&gt;
# Bash needs this:&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/l/libtermcap-*.txz&lt;br /&gt;
&lt;br /&gt;
# Install net-tools to ensure that /etc/HOSTNAME, /etc/hosts, and potentially, /etc/hostid are handled proper.&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/n/net-tools-*.txz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When ZFS has to import a zpool while the initrd is running (this can be avoided by not exporting and keeping /etc/zfs/zpool.cache inside the initrd), ZFS will refuse to import a pool if it thinks that the pool may be in use by another system. ZFS was designed for network attached storage where multiple hosts might have access to the same disks but ZFS cannot support two hosts importing and using a ZFS pool at the same time. ZFS checks a value called &amp;quot;hostid&amp;quot; to determine this kind of conflict, and it can be a tricky issue with an initrd boot process. The value of hostid is returned by a system call, the gethostid() function or the hostid command. This function will return the hostid from /etc/hostid if that file exists and has a valid id in it, or else if the file doesn't exist it obtains a hostid number based on the hostname and ip address assigned to hostname found in /etc/hosts or in DNS. If the hostid trying to import a pool is not the same as the hostid that imported it last time, ZFS will not import the pool unless &amp;quot;zpool import -f zfs-root&amp;quot; is used to force the import. This force option is not recommended to use, so it is best to configure your initrd with matching /etc/HOSTNAME and /etc/hosts as on the root installation and ensure what your system looks like on the initrd matches the booted root system.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Edit /boot/initrd-tree/init (this is the main system startup script on the initrd, responsibe for configuring your block devices and mount your root at /mnt and then booting root):&lt;br /&gt;
&lt;br /&gt;
Inside init, right near the top of the file after the PATH= line, add this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/bin/hostname -F /etc/HOSTNAME&lt;br /&gt;
/bin/hostname $( /bin/hostname -s )&lt;br /&gt;
#/sbin/chhostid 13371400&lt;br /&gt;
# you can make your hostid whatever, but this didn't work right with ZFS, so it is commented out&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This sets the name reported by the hostname command (the default is &amp;quot;darkstar&amp;quot;) to be what is contained in /etc/HOSTNAME. The hostname is modified in the next line to be the short name. These lines will help ZFS to properly identify your host when importing pools.&lt;br /&gt;
&lt;br /&gt;
Inside init, right after it runs &amp;quot;mdadm&amp;quot; commands as used for raid setup, we like it to setup ZFS, so add:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/sbin/zpool import zfs-root&lt;br /&gt;
/sbin/zfs set readonly=on zfs-root&lt;br /&gt;
mount zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Inside init, close to the bottom, where it &amp;quot;Switch to real root partition&amp;quot;, comment out 1 line that normally does the mount:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# mount -o ro -t $ROOTFS $ROOTDEV /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
We have already mounted zfs-root, and we don't want to use any mount options because we should be using a properly set /etc/fstab inside the initrd for the zfs-root mount options onto /mnt.&lt;br /&gt;
&lt;br /&gt;
During a normal startup we want a readonly mount.&lt;br /&gt;
&lt;br /&gt;
Note: we are going to setup with using &amp;quot;zpool import&amp;quot; and &amp;quot;zpool export&amp;quot; commands and startup and shutdown. But later, you can experiment having /etc/zfs/zpool.cache stored in the initrd and commenting out the zpool import/export lines.&lt;br /&gt;
&lt;br /&gt;
As mentioned, the zpool import command may sometimes fail, and give the message: &amp;quot;pool may be in use from another system&amp;quot;. This is nothing serious in this test situation. When this happens, zfs-root will not get mounted to /mnt and the init script will detect this and drop you into a rescue command line where you may manually &amp;quot;zpool import -f zfs-root&amp;quot;, &amp;quot;mount zfs-root&amp;quot;, and then &amp;quot;exit&amp;quot; to continue booting onto zfs-root.&lt;br /&gt;
&lt;br /&gt;
To avoid this problem we copy some files in (assuming you first edit /etc/HOSTNAME to hold the hostname you like to see on your command prompts, and edited /etc/hosts to have hostname on your loopback or other local ip address):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/HOSTNAME /etc/hosts /boot/initrd-tree/etc&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The value reported by the hostid command is what ZFS sees as your hostid. In this setup so far, the value is based on the ip assigned to your hostname. If your hostname is on the line in /etc/hosts for ip address 192.168.13.37, then your hostid will be hex numbers C0.A8.0D.25 rearranged as A8C0250D (pairs of bytes are swapped). This is a ip-based hostid value, a 32bit hexadecimal number. The hostid has to be the same each boot or import will need a -f option to force it. Simply setting the hostid using the system call sethostid() which writes a /etc/hostid file doesn't seem to agree with ZFS and you'd have to force the import, so this setup now assumes that you do not have or have deleted /etc/hostid.&lt;br /&gt;
&lt;br /&gt;
You can sometimes see what has been happening to a zpool by using the command &amp;quot;zpool history -li zfs-root&amp;quot; to see a log of commands.&lt;br /&gt;
&lt;br /&gt;
Once again, you can do away with the import and export commands by trying to have /etc/zfs/zpool.cache inside your initrd. To create zpool.cache, while on the installer or in the rescue shell of the initrd (at lilo &amp;quot;boot: vmlinuz rescue&amp;quot;), import only the pool for the root fs with mountpoint=none and readonly=on properties set, and while it is not mounted:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on installer or initrd rescue shell)&lt;br /&gt;
cp /etc/zfs/zpool.cache /etc/zfs/zpool.cache-initrd&lt;br /&gt;
zfs set readonly=off zfs-root&lt;br /&gt;
mount zfs-pool&lt;br /&gt;
cp /etc/zfs/zpool.cache-initrd /mnt/etc/zfs/&lt;br /&gt;
cp /mnt/etc/zfs/zpool.cache-initrd /mnt/boot/initrd-tree/etc/zfs/zpool.cache&lt;br /&gt;
umount /mnt&lt;br /&gt;
zfs set readonly=on zfs-root&lt;br /&gt;
#mount zfs-root&lt;br /&gt;
#exit (to continue boot process onto rootfs mounted at /mnt)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, doing this zpool.cache approach is not necessary, and some talk suggests this is deprecated or discouraged. Although /etc/hostid setup fails to import without -f option, ip-based (hosts|dns) hostid works on booting and import works without -f option and may be the more proper way to do shutdown and startup rather than using a cache file which could become invalid and cause a problem that is difficult to understand. The contents and exact function of the cache file are not well understood by many people.&lt;br /&gt;
&lt;br /&gt;
Save /boot/initrd-tree/init and quit vi.&lt;br /&gt;
&lt;br /&gt;
Now, edit /etc/rc.d/rc.S and rc.6 to understand how to &amp;quot;remount&amp;quot; rw or ro as readonly property changes. Note: if you use mountpoint=legacy, then you do not need to make the following changes:&lt;br /&gt;
&lt;br /&gt;
In /etc/rc.d/rc.S:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# comment out the line&lt;br /&gt;
#    /sbin/mount -w -v -n -o remount /&lt;br /&gt;
#add the line&lt;br /&gt;
     /sbin/zfs set readonly=off zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In /etc/rc.d/rc.6&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# comment out the line&lt;br /&gt;
#    /bin/mount -v -n -o remount,ro /&lt;br /&gt;
#add the line&lt;br /&gt;
     /sbin/zfs set readonly=on zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In /etc/rc.d/rc.6, near the bottom just before poweroff|reboot, add the following block of lines:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
########################&lt;br /&gt;
# Try to export zfs-root&lt;br /&gt;
/sbin/zpool export zfs-root&lt;br /&gt;
if [ $? -gt 0 ] ; then&lt;br /&gt;
 echo &amp;quot;ZFS export failed.&amp;quot;&lt;br /&gt;
 echo &amp;quot;Notice: if root fs is busy, then this is normal fail.&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;ZFS export successful.&amp;quot;&lt;br /&gt;
 echo &amp;quot;Warning: successful export is abnormal for root fs.&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
/bin/sleep 5&lt;br /&gt;
########################&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
For ZFS, you cannot run fsck on it. It doesn't support that kind of filesystem check. The rc.S script will complain a lot in many places about not being able to run fsck on the zfs-root. To disable all attempts of run fsck, we can simply create a file that acts as a flag in /etc/rc.d/rc.S to tell it to skip fsck:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
touch /etc/fastboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This fastboot file is normally a run-once temporary file, and it is deleted near the bottom inside rc.S. Edit rc.S and stop it from deleting /etc/fastboot. We would like it to always skip all fsck. Edit /etc/rc.d/rc.S, and find the &amp;quot;rm&amp;quot; of fastboot, and do not have it removed!&lt;br /&gt;
&lt;br /&gt;
We are getting close, and have finished all editing, so make /boot/initrd.gz and install lilo:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkinitrd -F&lt;br /&gt;
lilo&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We finished! All that's left to do is clean up.&lt;br /&gt;
&lt;br /&gt;
Exit the chroot.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
exit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Try to umount everything:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
umount /mnt/proc&lt;br /&gt;
umount /mnt/sys&lt;br /&gt;
umount /mnt/dev&lt;br /&gt;
umount /mnt/boot&lt;br /&gt;
umount /mnt/mnt/cdrom&lt;br /&gt;
umount /mnt/root/packages&lt;br /&gt;
umount /mnt&lt;br /&gt;
zpool export zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note, that export stops a pool and frees devices, while import binds devices and starts a pool. It is somewhat like mdadm -A -s and mdadm -S -s, while /etc/zfs/zpool.cache might be somewhat like mdadm -E -s &amp;gt; /etc/mdadm.conf.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Remove the DVD or change boot order&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When you reboot, if all is good, you are booting properly onto a slackware installed on a ZFS root! Congrats!&lt;br /&gt;
&lt;br /&gt;
If this seems to go badly, and this might happen if the import fails as explained some before, then you will be on the initrd's rescue command line just before the part in init where it wants to mount zfs-root and switch_root to boot up. In this case, you typically got commands like these to do:&lt;br /&gt;
&lt;br /&gt;
If you get dumped to rescue because zpool import will not work and requires -f (force), then:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 zpool import -f zfs-root&lt;br /&gt;
 zpool export    zfs-root&lt;br /&gt;
 zpool import    zfs-root&lt;br /&gt;
 mount zfs-root&lt;br /&gt;
 exit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This can happen if hostname, hostid, or uname changes.&lt;br /&gt;
&lt;br /&gt;
If you get into a jam and need to boot into the initrd and skip zpool import etc, use the lilo prompt (or, boot the install-dvd):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
boot: vmlinuz rescue&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the rescue mode of the initrd, after you have mounted your zfs-root as readonly=on to /mnt, then &amp;quot;exit&amp;quot; to continue booting.&lt;br /&gt;
&lt;br /&gt;
In other emergency command lines, you might need to run the lines at the end of init starting from: &amp;lt;code&amp;gt;udevadm info --cleanup-db; udevadm control --exit&amp;lt;/code&amp;gt;&lt;br /&gt;
If you don't run those udevadm commands, two runs of udevd fight each other and it is slow; you have to wait 2 minutes twice for timeouts (4 minutes).&lt;br /&gt;
The last line in init is run like: &amp;lt;code&amp;gt;exec switch_root /mnt /sbin/init 1&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Warning: the switch_root command is kind of dangerous, so read the manual page about it. From what I can tell, everything except the new root &amp;quot;/mnt&amp;quot; is deleted, so you are giving a command that says what NOT to delete! Make sure nothing got mounted outside of &amp;quot;/mnt&amp;quot; before you run it. However, the deletes should not cross filesystems, but only delete the contents of initramfs.&lt;br /&gt;
&lt;br /&gt;
Also, in rescue command line or anytime you have finished making changes and are about to reboot in some abnormal situation, first run:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set readonly=on zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A bug in unpatched grep 2.13 build 1, found slackware 14.0rc1, causes problems when processing files stored on ZFS but rarely shows problems on other filesystems; the bug does not handle sparse files on zfs and btrfs correctly and results in chaos with slackpkg, compiling kernel modules, and possibly many other things. You must downgrade grep to 2.12 or use the patched grep 2.13 build 2 in slackware 14.0rc2 or later.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
Upgrading:&lt;br /&gt;
&lt;br /&gt;
From time to time you will want to upgrade the kernel to the new kernel in slackware64-current or in patches/. This will also necessitate a rebuild and reinstall or upgrade of spl and zfs. Below is an example of when both kernel and spl/zfs are being upgraded, to give an idea of the process:&lt;br /&gt;
&lt;br /&gt;
Using slackpkg, that is configured to use your local slackware mirror is a good option but you can also configure it to use a remote mirror.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slackpkg upgrade-all&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Assume slackpkg just upgraded your kernel, kernel-modules, kernel-headers, and kernel-source.&lt;br /&gt;
&lt;br /&gt;
Note: the first time you try to run on kernel-generic, setup kernel-huge in lilo as 2nd choice. Huge has all the hard drive controllers builtin, but generic has them all as modules. For example, run &amp;quot;modinfo mptsas&amp;quot; to see module options (maybe you have a LSISAS1068) for your hard drive controller. Add file /etc/modprobe.d/mptsas.conf to set options you want with a line: options mptsas ... Do this for all the device driver modules for your hardware. Do this setup while you are on the huge kernel, then setup to reboot to generic. Include all these modules you need into mkinitrd.conf MODULES_LIST. Check that /boot/initrd-tree/etc/modprobe.d/ has a copy of your customized module conf files because it is on the initrd where the modules will load and use the conf files. mkinitrd probably copies all /etc/modprobe.d/* files into the initrd-tree, but check it. Pay attention to /etc/modprobe.d/README and /lib/modprobe.d/* /lib/modprobe.d/* maybe not copied to initrd-tree but you might want to copy some of it into your initrd-tree yourself to use them.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Check that upgraded kernel-source is symlinked to /usr/src/linux (zfs build looks here). SPL/ZFS modules will install to the kernel version in /lib/modules/&amp;lt;/usr/src/linux kernel version&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /usr/local/src&lt;br /&gt;
tar xvzf ~/spl-*.tar.gz&lt;br /&gt;
tar xvzf ~/zfs-*.tar.gz&lt;br /&gt;
&lt;br /&gt;
###### upgrade spl 1st&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-*&lt;br /&gt;
./configure --prefix=/ --libexecdir=/usr/libexec --libdir=/lib64 --includedir=/usr/include --datarootdir=/usr/share&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=/usr/local/src/install&lt;br /&gt;
cd ../install&lt;br /&gt;
makepkg ../spl-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
upgradepkg spl-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
depmod &amp;lt;new kernel version&amp;gt;     (e.g. depmod 3.2.27, if .27 is new kernel upgrade; you currently run on old, maybe .26)&lt;br /&gt;
# this builds the module dependencies in /lib/modules/&amp;lt;new kernel version&amp;gt;&lt;br /&gt;
###### upgrade zfs 2nd&lt;br /&gt;
mkdir install&lt;br /&gt;
cd zfs-*&lt;br /&gt;
./configure --prefix=/ --libexecdir=/usr/libexec --libdir=/lib64 --includedir=/usr/include --datarootdir=/usr/share&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=/usr/local/src/install&lt;br /&gt;
cd ../install&lt;br /&gt;
makepkg ../zfs-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
upgradepkg zfs-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
depmod 3.2.27&lt;br /&gt;
####### upgrade spl/zfs inside altroot /boot/initrd-tree&lt;br /&gt;
ROOT=/boot/initrd-tree upgradepkg spl-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
ROOT=/boot/initrd-tree upgradepkg zfs-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
# note: ROOT is an environment variable, not a command line option to upgradepkg!&lt;br /&gt;
# note: do not worry about depmod inside initrd-tree, mkinitrd -F actually installs the modules&lt;br /&gt;
# note: this upgrade here is really to just upgrade the command line tools zpool, zfs etc&lt;br /&gt;
####### rebuild /boot/initrd.gz and reinstall lilo&lt;br /&gt;
vi /etc/mkinitrd.conf&lt;br /&gt;
# temporarily set KERNEL_VERSION to new version, but you are still running on old version&lt;br /&gt;
mkinitrd -F&lt;br /&gt;
lilo&lt;br /&gt;
vi /etc/mkinitrd.conf&lt;br /&gt;
# you can set KERNEL_VERSION back to $(uname -r) now&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After reboot you can remove any old /lib/modules/&amp;lt;old kernel version&amp;gt; directory.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
More about /etc/hostid. If you want to experiment changing your /etc/hostid file and seeing if you can use it and make zpool import work normally, here is a tool that might be helpful:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/* software product name: foobarz-chhostid.c&lt;br /&gt;
 * suggested binary name: chhostid&lt;br /&gt;
 * license              : BSD&lt;br /&gt;
 * license text:&lt;br /&gt;
Copyright (c) 2012, foobarz&lt;br /&gt;
All rights reserved.&lt;br /&gt;
&lt;br /&gt;
Redistribution and use in source and binary forms, with or without&lt;br /&gt;
modification, are permitted provided that the following conditions are met:&lt;br /&gt;
    * Redistributions of source code must retain the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer.&lt;br /&gt;
    * Redistributions in binary form must reproduce the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer in the&lt;br /&gt;
      documentation and/or other materials provided with the distribution.&lt;br /&gt;
    * Neither the name of the &amp;lt;organization&amp;gt; nor the&lt;br /&gt;
      names of its contributors may be used to endorse or promote products&lt;br /&gt;
      derived from this software without specific prior written permission.&lt;br /&gt;
&lt;br /&gt;
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &amp;quot;AS IS&amp;quot; AND&lt;br /&gt;
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED&lt;br /&gt;
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE&lt;br /&gt;
DISCLAIMED. IN NO EVENT SHALL &amp;lt;COPYRIGHT HOLDER&amp;gt; BE LIABLE FOR ANY&lt;br /&gt;
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES&lt;br /&gt;
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;&lt;br /&gt;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND&lt;br /&gt;
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT&lt;br /&gt;
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS&lt;br /&gt;
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#define FOOBARZ_CHHOSTID_VERSION &amp;quot;1.0.5&amp;quot;&lt;br /&gt;
#include &amp;lt;sys/socket.h&amp;gt;&lt;br /&gt;
#include &amp;lt;netinet/in.h&amp;gt;&lt;br /&gt;
#include &amp;lt;arpa/inet.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;endian.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sysexits.h&amp;gt;&lt;br /&gt;
/* note: if include stdlib then sethostid fails even with _BSD_SOURCE defined */&lt;br /&gt;
&lt;br /&gt;
long swapbytes(long abcd) {&lt;br /&gt;
  long badc;&lt;br /&gt;
  unsigned char addr_a;&lt;br /&gt;
  unsigned char addr_b;&lt;br /&gt;
  unsigned char addr_c;&lt;br /&gt;
  unsigned char addr_d;&lt;br /&gt;
  addr_a = (unsigned char) (abcd &amp;gt;&amp;gt; 24);&lt;br /&gt;
  addr_b = (unsigned char) (abcd &amp;gt;&amp;gt; 16);&lt;br /&gt;
  addr_c = (unsigned char) (abcd &amp;gt;&amp;gt;  8);&lt;br /&gt;
  addr_d = (unsigned char) (abcd);&lt;br /&gt;
  return badc = ( (addr_b &amp;lt;&amp;lt; 24) | (addr_a &amp;lt;&amp;lt; 16) | (addr_d &amp;lt;&amp;lt; 8) | addr_c );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[])&lt;br /&gt;
{&lt;br /&gt;
 long newhostid;&lt;br /&gt;
 struct in_addr addr;&lt;br /&gt;
 char* invalidchar;&lt;br /&gt;
&lt;br /&gt;
 /*********** check command line */&lt;br /&gt;
 if(!( ((argc==3) &amp;amp;&amp;amp; ( (strcmp(argv[1],&amp;quot;-h&amp;quot;)==0) ||&lt;br /&gt;
                       (strcmp(argv[1],&amp;quot;-i&amp;quot;)==0) ||&lt;br /&gt;
                       (strcmp(argv[1],&amp;quot;-l&amp;quot;)==0) )) ||&lt;br /&gt;
       ((argc==2) &amp;amp;&amp;amp; ( (strcmp(argv[1],&amp;quot;-s&amp;quot;)==0) ))&lt;br /&gt;
     )&lt;br /&gt;
   ) {&lt;br /&gt;
                 /*01234567890123456789012345678901234567890123456789012345678901234567890123456789*/&lt;br /&gt;
  fprintf(stderr, &amp;quot;foobarz-chhostid, version %s. License: BSD.\n&amp;quot;, FOOBARZ_CHHOSTID_VERSION);&lt;br /&gt;
  fprintf(stderr, &amp;quot;foobarz-chhostid, (c) 2012, foobarz; all rights reserved.\n&amp;quot;);&lt;br /&gt;
  fprintf(stderr, &amp;quot;descr: %s change system hostid (in /etc/hostid).\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -h &amp;lt;new hostid&amp;gt;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        Change system hostid to &amp;lt;new hostid&amp;gt;;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        &amp;lt;new hostid&amp;gt; must be 32bit 8-digit hex number xxxxxxxx, each x in 0-f|F.\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        The ip corresponding to &amp;lt;new hostid&amp;gt; is also listed for reference only.\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -i &amp;lt;dotted ip address&amp;gt;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        Change system hostid to hostid corresponding to &amp;lt;dotted ip address&amp;gt;.\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -l &amp;lt;dotted ip address&amp;gt;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        List hostid corresponding to &amp;lt;dotted ip address&amp;gt;;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        no change to system hostid.\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -s\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        List current system hostid and corresponding ip address;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        no change to system hostid.\n&amp;quot;, argv[0]);&lt;br /&gt;
  return EX_USAGE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -h &amp;lt;hostid&amp;gt; */&lt;br /&gt;
 if( strcmp(argv[1],&amp;quot;-h&amp;quot;) == 0 ) {&lt;br /&gt;
  if(strlen(argv[2]) != 8) { fprintf(stderr, &amp;quot;new hostid must be 8-digit hex number xxxxxxxx, each x in 0-f|F\n&amp;quot;); return EX_USAGE; }&lt;br /&gt;
&lt;br /&gt;
  newhostid = strtol(argv[2],&amp;amp;invalidchar,16);&lt;br /&gt;
  if( newhostid==LONG_MIN ) { perror(&amp;quot;strtol (underflow)&amp;quot;); return EX_USAGE; }&lt;br /&gt;
  if( newhostid==LONG_MAX ) { perror(&amp;quot;strtol (overflow)&amp;quot;); return EX_USAGE; }&lt;br /&gt;
  if(*invalidchar != '\0') { fprintf(stderr, &amp;quot;invalid hex number %c; must be in 0-f|F\n&amp;quot;, *invalidchar); return EX_USAGE; }&lt;br /&gt;
&lt;br /&gt;
  if( sethostid(newhostid) != 0 ) {&lt;br /&gt;
   perror(&amp;quot;sethostid&amp;quot;);&lt;br /&gt;
   if( errno == EPERM ) return EX_NOPERM;&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
  }&lt;br /&gt;
  printf(&amp;quot;System hostid changed.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  /* hostid is a byte-swapped ip like b.a.d.c */&lt;br /&gt;
  /* get ip by swapping to correct order a.b.c.d and save into in_addr struct */&lt;br /&gt;
  addr.s_addr = htonl(swapbytes(newhostid));&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -i or -l, then find hostid for &amp;lt;dotted ip address&amp;gt; */&lt;br /&gt;
 if( (strcmp(argv[1],&amp;quot;-i&amp;quot;) == 0) || (strcmp(argv[1],&amp;quot;-l&amp;quot;) == 0) ) {&lt;br /&gt;
  if( inet_aton(argv[2], &amp;amp;addr) == 0 ) { fprintf(stderr, &amp;quot;inet_aton: invalid dotted ip address: %s\n&amp;quot;, argv[2]); return EX_USAGE; }&lt;br /&gt;
&lt;br /&gt;
  /* hostid is a byte-swapped ip like b.a.d.c */&lt;br /&gt;
  /* get hostid by swapping bytes of ip a.b.c.d */&lt;br /&gt;
  newhostid = swapbytes(ntohl(addr.s_addr));&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -i &amp;lt;dotted ip address&amp;gt; */&lt;br /&gt;
 if( strcmp(argv[1],&amp;quot;-i&amp;quot;) == 0 ) {&lt;br /&gt;
  if( sethostid(newhostid) != 0 ) {&lt;br /&gt;
   perror(&amp;quot;sethostid&amp;quot;);&lt;br /&gt;
   if( errno == EPERM ) return EX_NOPERM;&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
  }&lt;br /&gt;
  printf(&amp;quot;System hostid changed.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -l &amp;lt;dotted ip address&amp;gt; */&lt;br /&gt;
 if(strcmp(argv[1],&amp;quot;-l&amp;quot;) == 0 ) {&lt;br /&gt;
   printf(&amp;quot;Listing hostid for ip. (no changes)\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -s */&lt;br /&gt;
 if(strcmp(argv[1],&amp;quot;-s&amp;quot;) == 0 ) {&lt;br /&gt;
   /* see if /etc/hostid exists and print info */&lt;br /&gt;
   if( access(&amp;quot;/etc/hostid&amp;quot;, F_OK) != 0 ) {&lt;br /&gt;
     printf(&amp;quot;Notice: /etc/hostid does not exist.\n&amp;quot;);&lt;br /&gt;
     perror(&amp;quot;Reason&amp;quot;);&lt;br /&gt;
     printf(&amp;quot;System hostid derived from ip of hostname found in hosts file or dns.\n&amp;quot;);&lt;br /&gt;
   } else {&lt;br /&gt;
     printf(&amp;quot;Notice: /etc/hostid exists.\n&amp;quot;&lt;br /&gt;
            &amp;quot;System hostid is obtained from hostid file.\n&amp;quot;);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
  errno=0;&lt;br /&gt;
  newhostid = gethostid();&lt;br /&gt;
  if(errno!=0) { perror(&amp;quot;gethostid&amp;quot;); return EX_UNAVAILABLE; }&lt;br /&gt;
&lt;br /&gt;
  /* hostid is a byte-swapped ip like b.a.d.c */&lt;br /&gt;
  /* get ip by swapping to correct order a.b.c.d and save into in_addr struct */&lt;br /&gt;
  addr.s_addr = htonl(swapbytes(newhostid));&lt;br /&gt;
&lt;br /&gt;
  printf(&amp;quot;Listing current system hostid. (no changes)\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** print info and return */&lt;br /&gt;
 printf(&amp;quot;ip dot: %s\n&amp;quot;, inet_ntoa(addr) );&lt;br /&gt;
 printf(&amp;quot;ip hex: %.8x\n&amp;quot;, ntohl(addr.s_addr) );&lt;br /&gt;
 printf(&amp;quot;hostid: %.8x\n&amp;quot;, newhostid );&lt;br /&gt;
 return EX_OK;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
----&lt;br /&gt;
Now available! &amp;quot;ZFS root (builtin)&amp;quot; wiki (aka &amp;quot;ZFS root, part II&amp;quot;):&lt;br /&gt;
http://slackwiki.com/ZFS_root_(builtin)&lt;br /&gt;
It is now possible to build the modules and a small initramfs into your kernel to have a fully-contained and bootable ZFS root kernel from a simple lilo entry. Good luck!&lt;/div&gt;</description>
			<pubDate>Tue, 04 Sep 2012 17:54:28 GMT</pubDate>
			<dc:creator>Foobarz</dc:creator>
			<comments>https://www.slackwiki.com/Talk:ZFS_root</comments>
		</item>
		<item>
			<title>ZFS root</title>
			<link>https://www.slackwiki.com/index.php?title=ZFS_root&amp;diff=781</link>
			<guid isPermaLink="false">https://www.slackwiki.com/index.php?title=ZFS_root&amp;diff=781</guid>
			<description>&lt;p&gt;Foobarz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Tutorials]]&lt;br /&gt;
If you have heard about the ZFS filesystem and you're curious to try it out, then you can try it on slackware64, thanks to the ZFSonLinux.org project!&lt;br /&gt;
&lt;br /&gt;
In this article, an example is shown of how to install slackware64 14.0 onto a ZFS root filesystem (zfs-root) inside a QEMU virtual machine for testing purposes. It is recommended that you install qemu and learn how to use it to test a ZFS installation before you decide to use it on real hardware. A slackbuild for qemu can be found on slackbuilds.org. If you have a processor that supports Intel VT-x or AMD AMD-V virtualization acceleration (try modprobe kvm-intel or modprobe kvm-amd), then use the slackbuild for qemu-kvm.&lt;br /&gt;
&lt;br /&gt;
This article isn't going to go into any detail on actually using ZFS or what kinds of installation options and settings might be optimal. This article just presents an example of how to get started with ZFS on slackware.&lt;br /&gt;
&lt;br /&gt;
At this time of writing, ZFSonLinux is at &amp;quot;release candidate&amp;quot; (version 0.6.0-rc10) development stage, and many issues can occur. See the ZFSonLinux.org web site and the issues tracker for an idea about the current issues. There is also an irc channel on irc.freenode.net, #zfsonlinux, for discussion of issues and help.&lt;br /&gt;
&lt;br /&gt;
Although not required, it is helpful to keep a local mirror of slackware64 on your system. Having a local mirror makes it easier to upgrade to slackware64-current or to patches/* in a release. To help manage your own local slackware mirror and generate your own CD and DVD slackware installers, see http://alien.slackbook.org/blog/local-slackware-mirror/.&lt;br /&gt;
&lt;br /&gt;
In this article, we use a slackware64-current DVD image file as the qemu cdrom device media for the installation of the slackware guest. This was tested at slackware64-current = slackware64 14.0rc2. You can obtain a slackware DVD image using a torrent, buy the DVD from slackware.com, or generate your own DVD image file using the mirror script. For an actual DVD, you can pass your DVD device (e.g., /dev/sr0) as the qemu cdrom device. For a DVD image file, pass the image file as the qemu cdrom device.&lt;br /&gt;
&lt;br /&gt;
The ZFSonLinux packages are not included in slackware at this time. There are two packages involved: spl and zfs. The first, spl, is &amp;quot;Solaris Porting Layer&amp;quot; and must be installed on the system before zfs can be compiled. The source code tarballs for these are at ZFSonLinux.org. At this time of writing, they are spl-0.6.0-rc10.tar.gz and zfs-0.6.0-rc10.tar.gz.&lt;br /&gt;
&lt;br /&gt;
At this point, it is assumed you have qemu installed, have obtained a slackware64-current/14.0 DVD, and have downloaded spl and zfs tarballs to your host system. The first step now is, if your host is not slackware64-current/14.0 (the same as the guest will be), then you need to create a minimal development slackware64 guest system in qemu for just the purpose of compiling and packaging the spl and zfs slackware packages and transferring a copy of these packages back onto your host system to use later to install onto zfs during the slackware install process.&lt;br /&gt;
&lt;br /&gt;
From this point onward, instructions become a bit terse and mostly limited to examples of the commands you might use to complete tasks. You are encouraged to examine what each command does by reading the command's man pages. For example, the command &amp;quot;man qemu&amp;quot; can show you most of what you need to know about running qemu on the command line.&lt;br /&gt;
&lt;br /&gt;
So, here's an example of how you might build the spl and zfs packages, starting in your home directory:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on host)&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir qemu&lt;br /&gt;
cd qemu&lt;br /&gt;
mkdir slackdevel&lt;br /&gt;
cd slackdevel&lt;br /&gt;
mkdir packages&lt;br /&gt;
cp ~/spl-*.tar.gz packages&lt;br /&gt;
cp ~/zfs-*.tar.gz packages&lt;br /&gt;
qemu-img create disk1.raw 10G&lt;br /&gt;
ln -s ~/slackware64-current-install-dvd.iso dvd.iso&lt;br /&gt;
qemu-kvm \&lt;br /&gt;
 -option-rom 8xx_64.rom,bootindex=1 \&lt;br /&gt;
 -no-quit \&lt;br /&gt;
 -no-shutdown \&lt;br /&gt;
 -boot order=cd,menu=on \&lt;br /&gt;
 -m 2G \&lt;br /&gt;
 -cpu host \&lt;br /&gt;
 -smp sockets=1,cores=4 \&lt;br /&gt;
 -net nic,model=e1000 -net user \&lt;br /&gt;
 -cdrom dvd.iso \&lt;br /&gt;
 -drive format=raw,media=disk,cache=none,aio=native,if=scsi,index=0,file=disk1.raw \&lt;br /&gt;
 -virtfs local,path=./packages/,security_model=none,mount_tag=hostpackages&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When you need to change boot to cd or disk, try changing &amp;quot;order=dc&amp;quot; or hitting F12 at boot prompt and select the CD/DVD boot option.&lt;br /&gt;
&lt;br /&gt;
Note: The support for booting drives using if=scsi is not included with current versions of qemu. Booting scsi requires the 8xx_64.rom option-rom, which can be downloaded at http://www.lsi.com/downloads/Public/Host Bus Adapters/Host Bus Adapters Common Files/lsi_bios.zip. Unzip it, and then:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp 8xx_64.rom /usr/share/qemu&lt;br /&gt;
# then run qemu-kvm with additional command line option: -option-rom 8xx_64.rom,bootindex=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Qemu should boot into the install-dvd, and now perform a very ordinary slackware64 install onto /dev/sda. Install d package set and most others, but package sets x, kde, xfce not really needed.&lt;br /&gt;
&lt;br /&gt;
First note: examples here use tools from the gptfdisk package (gdisk, sgdisk, cgdisk) to partition the disk with GUID partition table (GPT) format. GPT might not be too familiar to everyone, who mostly have only used MBR partitions with fdisk. In the slackware installations this author has tested in qemu, using GPT partitions has caused no problems with lilo or other tools used in slackware. GPT disk labels support creating up to 128 partitions and support disks larger than 2TB (the limit of MBR fdisk). LILO installs into the first 440 bytes on /dev/sda, inside a GPT &amp;quot;protective MBR&amp;quot; that serves to provide compatibility with MBR bootloaders like lilo. LILO uses LBA32 sector addressing and can see all 512-byte sectors inside the first 2TB of a disk. So long as the /boot partition is within the first 2TB of a disk, lilo can work on a disk larger than 2TB. Unlike the common default of fdisk to start the first partition at sector 63, which is not aligned with the 4KiB sector size of Advanced Format hard disks, gdisk's default is to start partitions at 2048 sector (1MiB) boundaries which are also 4KiB aligned. Using gdisk GPT works on all disks and is compatible with using Advanced Format hard disks larger than 2TB. More information about GPT disk label format can be found on wikipedia.org. For those that have used grub instead of lilo, grub installation is different with GPT than with MBR, and grub requires a GPT partition of type grub-bios or 0xEF02 &amp;quot;BIOS Boot Partition&amp;quot; of about 8MiB where it can install it's additional bootloader stages because grub cannot embed in sectors 1-62 on GPT where GPT keeps it's partition tables. On MBR, sectors 1-62 were normally reserved space for bootloaders to keep a 2nd stage.&lt;br /&gt;
&lt;br /&gt;
For this purpose of development guest, just create a simple 1-partition system, /dev/sda1, and do a simple slackware install on it. Don't bother with swap or separate /boot unless you want to:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on install-dvd)&lt;br /&gt;
cgdisk /dev/sda&lt;br /&gt;
setup&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When this simple development guest boots, login as root, and continue:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on qemu guest)&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir packages&lt;br /&gt;
mount hostpackages -t 9p -o trans=virtio packages&lt;br /&gt;
echo --prefix=/ --libexecdir=/usr/libexec --libdir=/lib64 --includedir=/usr/include --datarootdir=/usr/share &amp;gt; configure-options&lt;br /&gt;
mkdir src&lt;br /&gt;
cd src&lt;br /&gt;
&lt;br /&gt;
mkdir install&lt;br /&gt;
tar xvzf ~/packages/spl-*.tar.gz&lt;br /&gt;
cd spl-*&lt;br /&gt;
./configure $( cat ~/configure-options )&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../spl-&amp;lt;version&amp;gt;_&amp;lt;kernel_version&amp;gt;-x86_64-&amp;lt;build_id&amp;gt;.txz&lt;br /&gt;
(e.g., makepkg ../spl-0.6.0rc10_3.2.27-x86_64-1root.txz)&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
installpkg spl-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
cp spl-0.6.0rc10_3.2.27-x86_64-1root.txz ~/packages&lt;br /&gt;
&lt;br /&gt;
mkdir install&lt;br /&gt;
tar xvzf ~/packages/zfs-*.tar.gz&lt;br /&gt;
cd zfs-*&lt;br /&gt;
./configure $( cat ~/configure-options )&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../zfs-&amp;lt;version&amp;gt;_&amp;lt;kernel_version&amp;gt;-x86_64-&amp;lt;build_id&amp;gt;.txz&lt;br /&gt;
(e.g., makepkg ../zfs-0.6.0rc10_3.2.27-x86_64-1root.txz)&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
installpkg zfs-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
cp zfs-0.6.0rc10_3.2.27-x86_64-1root.txz ~/packages&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point spl and zfs packages are copied back to the host in the packages directory. Also, spl and zfs are installed in this simple development guest, so one could begin to experiment with zfs pools and datasets but while the root fs is whatever you made it during setup (probably the default, ext4). This development guest isn't really needed anymore, so it can be deleted:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
halt&lt;br /&gt;
(exit qemu: ctrl-alt-2 then enter quit at QEMU command prompt)&lt;br /&gt;
&lt;br /&gt;
(on host)&lt;br /&gt;
rm disk1.raw dvd.iso&lt;br /&gt;
mv packages ..&lt;br /&gt;
cd ..&lt;br /&gt;
rmdir slackdevel&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now that we have the spl and zfs packages on the host, it is possible to copy them into your local slackware64 mirror and then generate your own install DVD image that includes them. For example, change to the directory that contains the slackware README files, and create a &amp;quot;addon&amp;quot; directory and copy the spl and zfs slackware packages into there. Then, generate the DVD image using a command such as $( ./mirror-slackware-current.sh -i ) from where you have this script configured to maintain your local mirror. We can also just continue to access them inside the installer using qemu's virtfs option. When you are going to do a real installation onto real hardware, you need to generate and burn your own DVD that includes the packages.&lt;br /&gt;
&lt;br /&gt;
It is time to begin the installation of slackware64 on a ZFS root, assuming either you have regenerated dvd.iso with zfs packages in addon/* or we access the zfs packages while in the installer using qemu's virtfs to the host's packages directory. ZFS supports creating complex data storage configurations such as pools (similar to a volume group) backed by one or more of various kinds of virtual devices (similar to disks and raid arrays) and containing one or more datasets (similar to mounted filesystems, logical volume devices, or snapshots). But here, we keep it simple and will install on just a single disk device. On a real ZFS installation, users will typically want to use the ZFS raidz1 or raidz2 virtual device types for reliability against hard drive failures.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on host)&lt;br /&gt;
mkdir slackzfs&lt;br /&gt;
mv packages slackzfs/&lt;br /&gt;
cd slackzfs&lt;br /&gt;
qemu-img create disk1.raw 10G&lt;br /&gt;
ln -s ~/slackware64-current-install-dvd.iso dvd.iso&lt;br /&gt;
qemu-kvm \&lt;br /&gt;
 -option-rom 8xx_64.rom,bootindex=1 \&lt;br /&gt;
 -no-quit \&lt;br /&gt;
 -no-shutdown \&lt;br /&gt;
 -boot order=cd,menu=on \&lt;br /&gt;
 -m 2G \&lt;br /&gt;
 -cpu host \&lt;br /&gt;
 -smp sockets=1,cores=4 \&lt;br /&gt;
 -net nic,model=e1000 -net user \&lt;br /&gt;
 -cdrom dvd.iso \&lt;br /&gt;
 -drive format=raw,media=disk,cache=none,aio=native,if=scsi,index=0,file=disk1.raw \&lt;br /&gt;
 -virtfs local,path=./packages/,security_model=none,mount_tag=hostpackages&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The install-dvd should boot, and then begin installation steps on the installer command line:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on install-dvd)&lt;br /&gt;
# mount the install-dvd&lt;br /&gt;
mkdir /dvd&lt;br /&gt;
mount /dev/sr0 /dvd&lt;br /&gt;
&lt;br /&gt;
# install coreutils, which provides the &amp;quot;hostid&amp;quot; command needed to load the spl module&lt;br /&gt;
installpkg /dvd/slackware64/a/coreutils-8.17-x86_64-1.txz&lt;br /&gt;
&lt;br /&gt;
# install kmod package which includes &amp;quot;depmod&amp;quot; command and others&lt;br /&gt;
installpkg /dvd/slackware64/a/kmod-9-x86_64-2.txz&lt;br /&gt;
depmod&lt;br /&gt;
&lt;br /&gt;
# install the full kernel modules so you can load 9p filesystem and use it if you want&lt;br /&gt;
# .. you might keep the zfs modules packages off the dvd and use a plain slack dvd&lt;br /&gt;
installpkg /dvd/slackware64/a/kernel-modules-*.txz&lt;br /&gt;
depmod&lt;br /&gt;
&lt;br /&gt;
# install bash and libtermcap because udev rules in zfs use bash scripts&lt;br /&gt;
installpkg /dvd/slackware64/a/bash-*.txz&lt;br /&gt;
installpkg /dvd/slackware64/l/libtermcap-*.txz&lt;br /&gt;
&lt;br /&gt;
# install spl and zfs that you have copied into the mirror before running the DVD creation&lt;br /&gt;
installpkg /dvd/addon/spl-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /dvd/addon/zfs-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
&lt;br /&gt;
#Or:&lt;br /&gt;
mkdir /packages&lt;br /&gt;
find /lib/modules/ | grep 9p&lt;br /&gt;
lsmod&lt;br /&gt;
# check that 9p modules load, mainly 9pnet_virtio&lt;br /&gt;
modprobe 9pnet_virtio&lt;br /&gt;
mount hostpackages -t 9p -o trans=virtio /packages&lt;br /&gt;
installpkg /packages/spl-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /packages/zfs-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
modprobe zfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now zfs tools: &amp;quot;zpool&amp;quot; and &amp;quot;zfs&amp;quot; should work in the live installer.&lt;br /&gt;
On the installer, there can be trouble seeing man pages, so install:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
installpkg /dvd/slackware64/ap/man-*.txz&lt;br /&gt;
installpkg /dvd/slackware64/ap/groff-*.txz&lt;br /&gt;
installpkg /dvd/slackware64/a/less-*.txz&lt;br /&gt;
export MANPATH=/usr/man:/usr/share/man&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The manual pages should be readable:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
man zpool&lt;br /&gt;
man zfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After seeing the man pages, we should be fully ready to continue to setup on ZFS.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(still on install-dvd)&lt;br /&gt;
ls -l /dev/sd*&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Make sure the disk devices you expect are there. We'll use sda and make boot (/boot on /dev/sda1) and root (/ on /dev/sda2) partitions.&lt;br /&gt;
&lt;br /&gt;
First, some background info: A ZFS filesystem is not supported by lilo as the filesystem containing /boot, which holds lilo's 2nd stage and the linux kernel files. The on-disk format of a ZFS filesystem is often a complex raid configuration where even if lilo understood ZFS it would likely require /boot to reside in only certain simple ZFS configurations to be plainly readable to lilo. As things are, a linux root installed in a partition with ZFS filesystem needs /boot to be on another partition with a filesystem that lilo understands, such as ext4 fs. In addition, because the spl and zfs modules are not built into the kernel, and the zfs startup requires some configuration to mount the zfs root, an initial ram/root filesystem (initrd) is needed. The initrd is a gzip compressed cpio archive file that contains a small linux root operating system that is decompressed into a ramfs block device at boot up and takes initial control of the system. The initrd contains an init script that configures devices in devtmpfs mounted at /dev. For example, if using mdadm, lvm, luks, losetup, and now zfs, this init script runs all the commands to create or start these devices (one of which is the root device), mounts the root device, and then transfers system control to the init script in the mounted root filesystem. The ramfs-based root environment on the booted install-dvd or booted initrd image (in rescue command line) are small slackware installations that exist only in ram and are temporary, but while inside them you can install, upgrade, and remove slackware packages inside them using the regular package management tools; this allows you access to any kernel modules and programs as needed inside these ramfs root. Packages can be installed, upgraded, or removed permanantly in the initrd image file to manage the programs and modules required during the initrd boot stage. Also from within these ramfs initial root environments, once the root device is mounted, chroot can be used to work on the mounted root system as if it were booted; this allows one to fix problems that are occuring in the root fs init scripts that cause normal booting to fail, or to install a kernel and/or modules etc. Now on to partitioning:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cgdisk /dev/sda&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, cgdisk looks just like cfdisk, but it makes GPT partitions.&lt;br /&gt;
&lt;br /&gt;
Make a partition for /boot that is about 512MiB of whatever partition type you like (8300 &amp;quot;Linux filesystem&amp;quot; is fine), or make it type bf07 &amp;quot;Solaris Reserved 1&amp;quot; if you want ZFS to maybe see the disk as if it was given as a whole disk to ZFS. Make a second partition using the remaining space with partition type bf01 &amp;quot;Solaris ZFS&amp;quot;. Currently, when ZFSonLinux is given a whole disk device like /dev/sdb to use, it will automatically GPT partition it with a bf01 partition #1 that is the whole disk except a small 8MiB type bf07 partition #9 at the end of the disk (/dev/sdb1 and /dev/sb9). The small 8MiB type bf07 partition #9 is most likely reserved for use by bootloaders, like lilo, to have a /boot or other boot-related files kept there. For example, you might have /dev/sda that is totally non-ZFS for booting and /dev/sdb passed to ZFS whole where it automatically partitions sdb, but you can just use one disk here and make partitions. Let's use type 8300 for /boot to be sure nothing is confused:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
We'll continue with this partitioning (numbers are in MiB):&lt;br /&gt;
  0 to   4: unused&lt;br /&gt;
  4 to 516: /dev/sda1 512MiB, type 8300&lt;br /&gt;
516 to 520: unused&lt;br /&gt;
520 to -96: /dev/sda2, type bf01&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The -96 means to count from the end of the disk so that 96MiB will remain unused at the end of the disk.&lt;br /&gt;
&lt;br /&gt;
Create a zpool called zfs-root:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool create -m none zfs-root /dev/sda2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A zpool created like this, the normal way, is a kernel-internal block device that contains already a zfs filesystem. There is normally no entry in /dev for this device. However, it can still be referenced as a mountable device similar to how devtmpfs, proc, and sysfs are also kernel-internal mountable block devices. The -m option told zpool not to automatically mount it anywhere, and without -m the default is to always automatically mount to /zfs-root. These kinds of details are explained better elsewhere. For this situation, we do not want it automounted.&lt;br /&gt;
&lt;br /&gt;
Because a zpool itself is a useable zfs fs, it has a full set of zfs &amp;quot;properties&amp;quot; to set options about the filesystem, perhaps similar to tune2fs. The &amp;quot;mountpoint=&amp;lt;some place to mount&amp;gt;&amp;quot; is one such property. We want it set to the special value &amp;quot;none&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs get mountpoint zfs-root&lt;br /&gt;
zfs set mountpoint=none zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On creation, the zpool zfs-pool is &amp;quot;imported&amp;quot; and has a zpool status that can be viewed:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool status zfs-root&lt;br /&gt;
&lt;br /&gt;
zpool export zfs-root&lt;br /&gt;
zpool status zfs-root&lt;br /&gt;
# Now there is no status.&lt;br /&gt;
&lt;br /&gt;
zpool import zfs-root&lt;br /&gt;
# Now it is back.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When a zpool is imported, it has it's current configuration cached in a file /etc/zfs/zpool.cache. When a zpool is exported, then it's entries in the cache file are removed and the cache file is deleted if it becomes empty. So long as the zfs kernel modules see this cache file and valid cache data inside it, ZFS considers the described zpools in the cache file to be valid as imported zpools. If the zpool.cache file is present at the time the zfs modules are loaded, then there is no further need to use the import and export zpool commands at system startup and shutdown. With root on a zfs, it is not possible to export the pool that root is on, but this is not a problem. At shutdown, the safe procedure will be to set the zfs-root property readonly=on and sync disks.&lt;br /&gt;
&lt;br /&gt;
To avoid the requirement to import the zfs-root pool at startup, keep a copy of the zpool.cache file to later copy onto the initrd image to read at modules load time to have the pool reactivated without need to issue the zpool import command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/zfs/zpool.cache /etc/zfs/zpool.cache-initrd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A zfs fs will not normally allow you to mount over any files. The mountpoint is expected to be an empty directory. Remove any junk files inside the installer's /mnt because zfs won't mount over any files:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rm /mnt/README&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The directory /mnt is where the slackware setup expects you to mount your root for installation.&lt;br /&gt;
&lt;br /&gt;
Controlling whether a zfs fs is to be mounted read-only or read-write is best managed by setting the readonly property while it is not yet mounted:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set readonly=on zfs-root&lt;br /&gt;
zfs set readonly=off zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Slackware expects root to be mounted readonly when /etc/rc.d/rc.S runs during normal startup, so later this is used to satisfy slackware's expectation to avoid rc.S complaining.&lt;br /&gt;
&lt;br /&gt;
The zfs-root can be mounted and unmounted in two different ways:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=/mnt zfs-root&lt;br /&gt;
zfs set mountpoint=none zfs-root&lt;br /&gt;
# or&lt;br /&gt;
mount zfs-root -t zfs /mnt&lt;br /&gt;
umount /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If it is already mounted and you want to change it to mount somewhere else, it is best to transition it to unmounted first, then mount it in the new place.&lt;br /&gt;
&lt;br /&gt;
The mount options &amp;lt;code&amp;gt;-o ro, -o rw, -o remount,ro, and -o remount,rw &amp;lt;/code&amp;gt; can also be used and will override the &amp;lt;code&amp;gt;readonly=on|off&amp;lt;/code&amp;gt; property without altering the property value. This can be confusing until you are familiar with how the two methods of mounting interact. When &amp;lt;code&amp;gt;mountpoint=legacy&amp;lt;/code&amp;gt; is set, zfs expects the regular mount and umount commands to be used to mount and unmount the dataset with the assistance of the mount.zfs helper. For now, we will continue with &amp;lt;code&amp;gt;mountpoint=none&amp;lt;/code&amp;gt;, but using legacy is also a good option.&lt;br /&gt;
&lt;br /&gt;
Now, let's continue some, and mount to /mnt using the current &amp;lt;code&amp;gt;readonly=off&amp;lt;/code&amp;gt; setting (rw mount):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=/mnt zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This method of mounting will show the most detailed mount options in /etc/mtab. They are the mount options that zfs thinks are proper, and they are probably what should be kept in /etc/fstab for zfs-root until we know better.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cat /etc/mtab &amp;gt;&amp;gt; /etc/fstab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now edit /etc/fstab to make sure it looks right, and remove the &amp;quot;rw&amp;quot; mount option, because we want to let it use a default for that, which will come from how we set the readonly= property most of the time. Unmount again:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=none zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mount again, now using all options from /etc/fstab:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It should be mounted at /mnt, and touch /mnt/t should allow you to make the file t. Then rm it: rm /mnt/t&lt;br /&gt;
For installation, we want to make sure it is mounted read-write. After installation, it should mount readonly inside the initrd.&lt;br /&gt;
&lt;br /&gt;
Sometimes there can be problems using the mount command, and then you can try it with the -i option:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 mount -i zfs-root&lt;br /&gt;
 mount -i zfs-root -t zfs /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
but, you should not have to use -i. When using -i makes it work, it performs an &amp;quot;internal-only&amp;quot; mount and does not use any mount.&amp;lt;fstype&amp;gt; helper scripts that might be on the system. You can use &amp;lt;code&amp;gt;mountpoint=legacy&amp;quot;&amp;lt;/code&amp;gt; to avoid this small problem if you are preferring to use the regular mount and umount commands on your zfs-root.&lt;br /&gt;
&lt;br /&gt;
Setup the /boot device:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkfs.ext4 /dev/sda1&lt;br /&gt;
mkdir /mnt/boot&lt;br /&gt;
mount /dev/sda1 /mnt/boot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We have both root and boot mounted where the slackware installer expects them. Unmount the dvd so setup can find it normally:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
umount /dev/sr0&lt;br /&gt;
setup&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the setup, skip straight to TARGET selection for the root device, but the setup doesn't see or understand the zfs-root, so it is not listed. This does not matter because we have mounted it already. Just skip down to a slot that say to continue, and continue on with setup. Because TARGET is skipped, you may not see the ADDITIONAL prompt (or if so, skip it too) where normally you give /dev/sda1 and have it mounted as /boot. This is also okay because we have mounted /mnt/boot already.&lt;br /&gt;
Because we did not give TARGET the root device or say what device /boot is on, the lilo installation will fail, or you can skip it. Otherwise, this installation process is normal.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Finish installation and exit setup, but do NOT reboot!&lt;br /&gt;
# There is still a lot to do before rebooting.&lt;br /&gt;
umount /dev/sr0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point, it is assumed that the setup has completed installing into /mnt. Congrats! You've installed slackware into a ZFS root!&lt;br /&gt;
&lt;br /&gt;
The next steps are to prepare to use &amp;quot;chroot /mnt&amp;quot; and finish up the configuration on the installed root system and then be able to reboot onto the completed installation. Before doing chroot, copy some files from the setup environment into /mnt.&lt;br /&gt;
&lt;br /&gt;
Copy the current installer /etc/fstab for later use inside the initrd. This fstab is what is proper inside the initrd, except remove option &amp;quot;rw&amp;quot; (if not done already).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/fstab /mnt/etc/fstab.initrd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The fstab.initrd will look like:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 proc /proc proc defaults 0 0&lt;br /&gt;
 zfs-root /mnt zfs defaults,atime,dev,exec,suid,xattr,nomand,zfsutil 0 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the initrd, we want zfs-root to mount to /mnt.&lt;br /&gt;
&lt;br /&gt;
Create /mnt/etc/fstab:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cat /etc/mtab &amp;gt;&amp;gt; /mnt/etc/fstab&lt;br /&gt;
vi /mnt/etc/fstab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using vi started above, edit /mnt/etc/fstab and make it have lines such as:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 zfs-root / zfs defaults,atime,dev,exec,suid,xattr,nomand,zfsutil 0 0&lt;br /&gt;
 /dev/sda1 /boot ext4 defaults 0 2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These two lines in &amp;lt;code&amp;gt;/mnt/etc/fstab&amp;lt;/code&amp;gt; are how the mounts should be looking when root is booted.&lt;br /&gt;
&lt;br /&gt;
Mount some special mounts before chroot:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount -t devtmpfs none /mnt/dev&lt;br /&gt;
mount -t proc none /mnt/proc&lt;br /&gt;
mount -t sysfs none /mnt/sys&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Make sure /boot is mounted:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount /dev/sda1 /mnt/boot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you had mounted a 9p fs share to access spl and zfs packages, then unmount that now:&lt;br /&gt;
umount /packages&lt;br /&gt;
&lt;br /&gt;
Ready, now:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chroot /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point, you should be on the installed system, and now try to configure mkinitrd and lilo. First, switch to use the generic kernel.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /boot&lt;br /&gt;
rm System.map config vmlinuz&lt;br /&gt;
ln -s System.map-gen* System.map&lt;br /&gt;
ln -s config-gen* config&lt;br /&gt;
ln -s vmlinuz-gen* vmlinuz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We installed spl and zfs inside the live ramfs install-dvd environment, but not yet have we installed them into the root system:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount /dev/sr0 /mnt/cdrom&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /mnt/cdrom/addon/spl-*.txz&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /mnt/cdrom/addon/zfs-*.txz&lt;br /&gt;
depmod&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If instead, you used a 9p share to access the spl and zfs packages, then repeat that procedure here to install them onto the root system.&lt;br /&gt;
&lt;br /&gt;
Setup lilo: edit /etc/lilo.conf so it is like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  lba32&lt;br /&gt;
  append = &amp;quot; vt.default_utf8=1&amp;quot;&lt;br /&gt;
  boot = /dev/sda&lt;br /&gt;
  message = /boot/boot_message.txt&lt;br /&gt;
  prompt&lt;br /&gt;
  timeout = 1200&lt;br /&gt;
  change-rules&lt;br /&gt;
   reset&lt;br /&gt;
  vga = normal&lt;br /&gt;
  image = /boot/vmlinuz&lt;br /&gt;
   label = vmlinuz&lt;br /&gt;
   initrd = /boot/initrd.gz&lt;br /&gt;
   root = /dev/ram0&lt;br /&gt;
   read-write&lt;br /&gt;
# alternatively, the root and read-write lines&lt;br /&gt;
# can be this one line of kernel parameters:&lt;br /&gt;
#  addappend = &amp;quot; root=/dev/ram0 rw &amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A note about initrd: The /boot/initrd.gz is a gzipped cpio archive containing a minimal BusyBox-based slackware root system that is sourced from /boot/initrd-tree. The commands &amp;quot;mkinitrd&amp;quot; and &amp;quot;mkinitrd -F&amp;quot; generates /boot/initrd-tree and /boot/initrd.gz. When using a initrd, the initial root device is normally set to root=/dev/ram0 (a ramfs block device) and allowed read-write. The kernel refers to devices in terms of &amp;quot;major&amp;quot; and &amp;quot;minor&amp;quot; numbers, and the ram0 device is assigned the block device major 1 and minor 0. This ram0 major/minor is written in hexadecimal as 0x0100 (256 in decimal). This hexademical number makes an appearance in /boot/initrd-tree/int where it runs: &amp;quot;echo 0x0100 &amp;gt; /proc/sys/kernel/real-root-dev&amp;quot;. Echoing a device code to real-root-dev is part of a deprecated initrd mechanism, but is probably harmless to leave alone as slackware has it unless you know otherwise. More information about how initrd works can be found in:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/usr/src/linux/Documentation/devices.txt (info about major:minor device numbers)&lt;br /&gt;
/usr/src/linux/Documentation/initrd.txt  (mostly obsolete info on old initrd)&lt;br /&gt;
/usr/src/linux/Documentation/filesystems/ramfs-rootfs-initramfs.txt (current info on new initrd, called initramfs)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Advanced note about initrd: Slackware's mkinitrd package does not use the &amp;quot;pivot_root&amp;quot; command as documented in &amp;quot;initrd.txt&amp;quot;, but instead uses &amp;quot;switch_root&amp;quot; provided by a project called BusyBox. The switch_root command changes the effective root filesystem from the initrd (unpacked in rootfs at /) to the new root filesystem (zfs-root mounted at /mnt); it overmounts rootfs / with zfs-root /mnt. The switch_root works as follows: delete everything in rootfs / (one filesystem only) that held initrd to free up ram memory, then use mount, chroot, and chdir to make the effective root change. In concept (as a shell script), the command &amp;quot;exec switch_root /mnt $INIT $RUNLEVEL&amp;quot; is performed as follows:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 find / -xdev | xargs rm -rf&lt;br /&gt;
 cd &amp;quot;$1&amp;quot;&lt;br /&gt;
 shift&lt;br /&gt;
 mount --move . /&lt;br /&gt;
 exec chroot . &amp;quot;$@&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Here, typically INIT=/sbin/init RUNLEVEL=3. The 'exec' causes switch_root to take the place of the parent process having PID=1. In system calls, the switch_root looks similar to this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chdir(&amp;quot;/mnt&amp;quot;);&lt;br /&gt;
/* &amp;lt;insert code to unlink/rmdir all initrd files/directories&lt;br /&gt;
 *  installed in rootfs / without crossing filesystems &amp;gt; */&lt;br /&gt;
mount(&amp;quot;.&amp;quot;, &amp;quot;/&amp;quot;, NULL, MS_MOVE, NULL);&lt;br /&gt;
chroot(&amp;quot;.&amp;quot;);&lt;br /&gt;
chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
execl(&amp;quot;/sbin/init&amp;quot;, &amp;quot;3&amp;quot;, (char*) NULL );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The kernel's rootfs / that contained initrd is never actually unmounted (it can't be) because it is built into the kernel and always exists as at least a tiny ramfs or tmpfs, so you can continue to see it in /proc/mounts. When you give lilo root=/dev/ram0 (a ramfs device), the kernel will actually use the internal rootfs, which is an instance of a tmpfs (if your kernel config includes tmpfs) or ramfs. The rootfs that is a tmpfs can by default use up to half of system ram. If rootfs is a ramfs, it can use up to almost all of system ram until the system panics. Typically, tmpfs is built into the kernel, and so depending on how much ram your computer has, the initrd-tree can probably be up to about half that size.&lt;br /&gt;
&lt;br /&gt;
Quite a lot of notes... now to continue on:&lt;br /&gt;
&lt;br /&gt;
Setup mkinitrd:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/mkinitrd.conf.sample /etc/mkinitrd.conf&lt;br /&gt;
vi /etc/mkinitrd.conf&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Edit it to look like this (other defaults should be ok):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 MODULE_LIST=&amp;quot;sym53c8xx:ext4:e1000:zfs:9p:9pnet_virtio&amp;quot;&lt;br /&gt;
 ROOTDEV=&amp;quot;zfs-root&amp;quot;&lt;br /&gt;
 ROOTFS=&amp;quot;zfs&amp;quot;&lt;br /&gt;
#Module sym53c8xx is the driver for qemu's if=scsi drive device.&lt;br /&gt;
#Module ext4 for /boot.&lt;br /&gt;
#Module e1000 for eth0 net device.&lt;br /&gt;
#Module zfs for ZFSonLinux.&lt;br /&gt;
#Modules 9p and 9pnet_virtio for mounting qemu -virtfs mount_tag.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These 9p modules could be useful from the rescue command line inside the initrd to get needed files that are on the host.&lt;br /&gt;
&lt;br /&gt;
All dependent modules will also be included automatically into /boot/initrd-tree, which is packaged as /boot/initrd.gz. For example, to see the dependent modules of zfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
modprobe --show-depends zfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All listed modules will also be in the initrd. Now, make a /boot/initrd-tree that we can begin to look at and edit.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkinitrd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create an empty /etc/mtab or else zpool import fails (zfs expects /etc/mtab to exists already, it won't make it).&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
touch /boot/initrd-tree/etc/mtab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Copy in the fstab.initrd that was made earlier while on the installer. This provides all the mount options for a simple &amp;quot;mount zfs-root&amp;quot; onto /mnt.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/fstab.initrd /boot/initrd-tree/etc/fstab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More package installing! This time into an alternate root, the root of the initrd, /boot/initrd-tree. This is how you can put whatever packages you like into your initrd. These installations work independent of your normal installations. You can install, upgrade, and remove packages using an altroot:&lt;br /&gt;
&lt;br /&gt;
If spl and zfs are on your customized dvd:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/addon/spl-*.txz&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/addon/zfs-*.txz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Otherwise, repeat same procedure but you mount your 9p mount_tag and get them installed.&lt;br /&gt;
&lt;br /&gt;
More regular packages from the dvd:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/kmod-*.txz&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/coreutils-*.txz&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/gptfdisk-*.txz&lt;br /&gt;
&lt;br /&gt;
# A bash script is in /boot/initrd-tree/lib/udev/, so we need it or udev rules have problems:&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/bash-*.txz&lt;br /&gt;
# Bash needs this:&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/l/libtermcap-*.txz&lt;br /&gt;
&lt;br /&gt;
# Install net-tools to ensure that /etc/HOSTNAME, /etc/hosts, and potentially, /etc/hostid are handled proper.&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/n/net-tools-*.txz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When ZFS has to import a zpool while the initrd is running (this can be avoided by not exporting and keeping /etc/zfs/zpool.cache inside the initrd), ZFS will refuse to import a pool if it thinks that the pool may be in use by another system. ZFS was designed for network attached storage where multiple hosts might have access to the same disks but ZFS cannot support two hosts importing and using a ZFS pool at the same time. ZFS checks a value called &amp;quot;hostid&amp;quot; to determine this kind of conflict, and it can be a tricky issue with an initrd boot process. The value of hostid is returned by a system call, the gethostid() function or the hostid command. This function will return the hostid from /etc/hostid if that file exists and has a valid id in it, or else if the file doesn't exist it obtains a hostid number based on the hostname and ip address assigned to hostname found in /etc/hosts or in DNS. If the hostid trying to import a pool is not the same as the hostid that imported it last time, ZFS will not import the pool unless &amp;quot;zpool import -f zfs-root&amp;quot; is used to force the import. This force option is not recommended to use, so it is best to configure your initrd with matching /etc/HOSTNAME and /etc/hosts as on the root installation and ensure what your system looks like on the initrd matches the booted root system.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Edit /boot/initrd-tree/init (this is the main system startup script on the initrd, responsibe for configuring your block devices and mount your root at /mnt and then booting root):&lt;br /&gt;
&lt;br /&gt;
Inside init, right near the top of the file after the PATH= line, add this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/bin/hostname -F /etc/HOSTNAME&lt;br /&gt;
/bin/hostname $( /bin/hostname -s )&lt;br /&gt;
#/sbin/chhostid 13371400&lt;br /&gt;
# you can make your hostid whatever, but this didn't work right with ZFS, so it is commented out&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This sets the name reported by the hostname command (the default is &amp;quot;darkstar&amp;quot;) to be what is contained in /etc/HOSTNAME. The hostname is modified in the next line to be the short name. These lines will help ZFS to properly identify your host when importing pools.&lt;br /&gt;
&lt;br /&gt;
Inside init, right after it runs &amp;quot;mdadm&amp;quot; commands as used for raid setup, we like it to setup ZFS, so add:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/sbin/zpool import zfs-root&lt;br /&gt;
/sbin/zfs set readonly=on zfs-root&lt;br /&gt;
mount zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Inside init, close to the bottom, where it &amp;quot;Switch to real root partition&amp;quot;, comment out 1 line that normally does the mount:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# mount -o ro -t $ROOTFS $ROOTDEV /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
We have already mounted zfs-root, and we don't want to use any mount options because we should be using a properly set /etc/fstab inside the initrd for the zfs-root mount options onto /mnt.&lt;br /&gt;
&lt;br /&gt;
During a normal startup we want a readonly mount.&lt;br /&gt;
&lt;br /&gt;
Note: we are going to setup with using &amp;quot;zpool import&amp;quot; and &amp;quot;zpool export&amp;quot; commands and startup and shutdown. But later, you can experiment having /etc/zfs/zpool.cache stored in the initrd and commenting out the zpool import/export lines.&lt;br /&gt;
&lt;br /&gt;
As mentioned, the zpool import command may sometimes fail, and give the message: &amp;quot;pool may be in use from another system&amp;quot;. This is nothing serious in this test situation. When this happens, zfs-root will not get mounted to /mnt and the init script will detect this and drop you into a rescue command line where you may manually &amp;quot;zpool import -f zfs-root&amp;quot;, &amp;quot;mount zfs-root&amp;quot;, and then &amp;quot;exit&amp;quot; to continue booting onto zfs-root.&lt;br /&gt;
&lt;br /&gt;
To avoid this problem we copy some files in (assuming you first edit /etc/HOSTNAME to hold the hostname you like to see on your command prompts, and edited /etc/hosts to have hostname on your loopback or other local ip address):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/HOSTNAME /etc/hosts /boot/initrd-tree/etc&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The value reported by the hostid command is what ZFS sees as your hostid. In this setup so far, the value is based on the ip assigned to your hostname. If your hostname is on the line in /etc/hosts for ip address 192.168.13.37, then your hostid will be hex numbers C0.A8.0D.25 rearranged as A8C0250D (pairs of bytes are swapped). This is a ip-based hostid value, a 32bit hexadecimal number. The hostid has to be the same each boot or import will need a -f option to force it. Simply setting the hostid using the system call sethostid() which writes a /etc/hostid file doesn't seem to agree with ZFS and you'd have to force the import, so this setup now assumes that you do not have or have deleted /etc/hostid.&lt;br /&gt;
&lt;br /&gt;
You can sometimes see what has been happening to a zpool by using the command &amp;quot;zpool history -li zfs-root&amp;quot; to see a log of commands.&lt;br /&gt;
&lt;br /&gt;
Once again, you can do away with the import and export commands by trying to have /etc/zfs/zpool.cache inside your initrd. To create zpool.cache, while on the installer or in the rescue shell of the initrd (at lilo &amp;quot;boot: vmlinuz rescue&amp;quot;), import only the pool for the root fs with mountpoint=none and readonly=on properties set, and while it is not mounted:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on installer or initrd rescue shell)&lt;br /&gt;
cp /etc/zfs/zpool.cache /etc/zfs/zpool.cache-initrd&lt;br /&gt;
zfs set readonly=off zfs-root&lt;br /&gt;
mount zfs-pool&lt;br /&gt;
cp /etc/zfs/zpool.cache-initrd /mnt/etc/zfs/&lt;br /&gt;
cp /mnt/etc/zfs/zpool.cache-initrd /mnt/boot/initrd-tree/etc/zfs/zpool.cache&lt;br /&gt;
umount /mnt&lt;br /&gt;
zfs set readonly=on zfs-root&lt;br /&gt;
#mount zfs-root&lt;br /&gt;
#exit (to continue boot process onto rootfs mounted at /mnt)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, doing this zpool.cache approach is not necessary, and some talk suggests this is deprecated or discouraged. Although /etc/hostid setup fails to import without -f option, ip-based (hosts|dns) hostid works on booting and import works without -f option and may be the more proper way to do shutdown and startup rather than using a cache file which could become invalid and cause a problem that is difficult to understand. The contents and exact function of the cache file are not well understood by many people.&lt;br /&gt;
&lt;br /&gt;
Save /boot/initrd-tree/init and quit vi.&lt;br /&gt;
&lt;br /&gt;
Now, edit /etc/rc.d/rc.S and rc.6 to understand how to &amp;quot;remount&amp;quot; rw or ro as readonly property changes. Note: if you use mountpoint=legacy, then you do not need to make the following changes:&lt;br /&gt;
&lt;br /&gt;
In /etc/rc.d/rc.S:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# comment out the line&lt;br /&gt;
#    /sbin/mount -w -v -n -o remount /&lt;br /&gt;
#add the line&lt;br /&gt;
     /sbin/zfs set readonly=off zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In /etc/rc.d/rc.6&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# comment out the line&lt;br /&gt;
#    /bin/mount -v -n -o remount,ro /&lt;br /&gt;
#add the line&lt;br /&gt;
     /sbin/zfs set readonly=on zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In /etc/rc.d/rc.6, near the bottom just before poweroff|reboot, add the following block of lines:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
########################&lt;br /&gt;
# Try to export zfs-root&lt;br /&gt;
/sbin/zpool export zfs-root&lt;br /&gt;
if [ $? -gt 0 ] ; then&lt;br /&gt;
 echo &amp;quot;ZFS export failed.&amp;quot;&lt;br /&gt;
 echo &amp;quot;Notice: if root fs is busy, then this is normal fail.&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;ZFS export successful.&amp;quot;&lt;br /&gt;
 echo &amp;quot;Warning: successful export is abnormal for root fs.&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
/bin/sleep 5&lt;br /&gt;
########################&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
For ZFS, you cannot run fsck on it. It doesn't support that kind of filesystem check. The rc.S script will complain a lot in many places about not being able to run fsck on the zfs-root. To disable all attempts of run fsck, we can simply create a file that acts as a flag in /etc/rc.d/rc.S to tell it to skip fsck:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
touch /etc/fastboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This fastboot file is normally a run-once temporary file, and it is deleted near the bottom inside rc.S. Edit rc.S and stop it from deleting /etc/fastboot. We would like it to always skip all fsck. Edit /etc/rc.d/rc.S, and find the &amp;quot;rm&amp;quot; of fastboot, and do not have it removed!&lt;br /&gt;
&lt;br /&gt;
We are getting close, and have finished all editing, so make /boot/initrd.gz and install lilo:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkinitrd -F&lt;br /&gt;
lilo&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We finished! All that's left to do is clean up.&lt;br /&gt;
&lt;br /&gt;
Exit the chroot.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
exit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Try to umount everything:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
umount /mnt/proc&lt;br /&gt;
umount /mnt/sys&lt;br /&gt;
umount /mnt/dev&lt;br /&gt;
umount /mnt/boot&lt;br /&gt;
umount /mnt/mnt/cdrom&lt;br /&gt;
umount /mnt/root/packages&lt;br /&gt;
umount /mnt&lt;br /&gt;
zpool export zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note, that export stops a pool and frees devices, while import binds devices and starts a pool. It is somewhat like mdadm -A -s and mdadm -S -s, while /etc/zfs/zpool.cache might be somewhat like mdadm -E -s &amp;gt; /etc/mdadm.conf.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Remove the DVD or change boot order&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When you reboot, if all is good, you are booting properly onto a slackware installed on a ZFS root! Congrats!&lt;br /&gt;
&lt;br /&gt;
If this seems to go badly, and this might happen if the import fails as explained some before, then you will be on the initrd's rescue command line just before the part in init where it wants to mount zfs-root and switch_root to boot up. In this case, you typically got commands like these to do:&lt;br /&gt;
&lt;br /&gt;
If you get dumped to rescue because zpool import will not work and requires -f (force), then:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 zpool import -f zfs-root&lt;br /&gt;
 zpool export    zfs-root&lt;br /&gt;
 zpool import    zfs-root&lt;br /&gt;
 mount zfs-root&lt;br /&gt;
 exit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This can happen if hostname, hostid, or uname changes.&lt;br /&gt;
&lt;br /&gt;
If you get into a jam and need to boot into the initrd and skip zpool import etc, use the lilo prompt (or, boot the install-dvd):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
boot: vmlinuz rescue&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the rescue mode of the initrd, after you have mounted your zfs-root as readonly=on to /mnt, then &amp;quot;exit&amp;quot; to continue booting.&lt;br /&gt;
&lt;br /&gt;
In other emergency command lines, you might need to run the lines at the end of init starting from: &amp;lt;code&amp;gt;udevadm info --cleanup-db; udevadm control --exit&amp;lt;/code&amp;gt;&lt;br /&gt;
If you don't run those udevadm commands, two runs of udevd fight each other and it is slow; you have to wait 2 minutes twice for timeouts (4 minutes).&lt;br /&gt;
The last line in init is run like: &amp;lt;code&amp;gt;exec switch_root /mnt /sbin/init 1&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Warning: the switch_root command is kind of dangerous, so read the manual page about it. From what I can tell, everything except the new root &amp;quot;/mnt&amp;quot; is deleted, so you are giving a command that says what NOT to delete! Make sure nothing got mounted outside of &amp;quot;/mnt&amp;quot; before you run it. However, the deletes should not cross filesystems, but only delete the contents of initramfs.&lt;br /&gt;
&lt;br /&gt;
Also, in rescue command line or anytime you have finished making changes and are about to reboot in some abnormal situation, first run:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set readonly=on zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A bug in unpatched grep 2.13 build 1, found slackware 14.0rc1, causes problems when processing files stored on ZFS but rarely shows problems on other filesystems; the bug does not handle sparse files on zfs and btrfs correctly and results in chaos with slackpkg, compiling kernel modules, and possibly many other things. You must downgrade grep to 2.12 or use the patched grep 2.13 build 2 in slackware 14.0rc2 or later.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
Upgrading:&lt;br /&gt;
&lt;br /&gt;
From time to time you will want to upgrade the kernel to the new kernel in slackware64-current or in patches/. This will also necessitate a rebuild and reinstall or upgrade of spl and zfs. Below is an example of when both kernel and spl/zfs are being upgraded, to give an idea of the process:&lt;br /&gt;
&lt;br /&gt;
Using slackpkg, that is configured to use your local slackware mirror is a good option but you can also configure it to use a remote mirror.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slackpkg upgrade-all&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Assume slackpkg just upgraded your kernel, kernel-modules, kernel-headers, and kernel-source.&lt;br /&gt;
&lt;br /&gt;
Note: the first time you try to run on kernel-generic, setup kernel-huge in lilo as 2nd choice. Huge has all the hard drive controllers builtin, but generic has them all as modules. For example, run &amp;quot;modinfo mptsas&amp;quot; to see module options (maybe you have a LSISAS1068) for your hard drive controller. Add file /etc/modprobe.d/mptsas.conf to set options you want with a line: options mptsas ... Do this for all the device driver modules for your hardware. Do this setup while you are on the huge kernel, then setup to reboot to generic. Include all these modules you need into mkinitrd.conf MODULES_LIST. Check that /boot/initrd-tree/etc/modprobe.d/ has a copy of your customized module conf files because it is on the initrd where the modules will load and use the conf files. mkinitrd probably copies all /etc/modprobe.d/* files into the initrd-tree, but check it. Pay attention to /etc/modprobe.d/README and /lib/modprobe.d/* /lib/modprobe.d/* maybe not copied to initrd-tree but you might want to copy some of it into your initrd-tree yourself to use them.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Check that upgraded kernel-source is symlinked to /usr/src/linux (zfs build looks here). SPL/ZFS modules will install to the kernel version in /lib/modules/&amp;lt;/usr/src/linux kernel version&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /usr/local/src&lt;br /&gt;
tar xvzf ~/spl-*.tar.gz&lt;br /&gt;
tar xvzf ~/zfs-*.tar.gz&lt;br /&gt;
&lt;br /&gt;
###### upgrade spl 1st&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-*&lt;br /&gt;
./configure --prefix=/ --libexecdir=/usr/libexec --libdir=/lib64 --includedir=/usr/include --datarootdir=/usr/share&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=/usr/local/src/install&lt;br /&gt;
cd ../install&lt;br /&gt;
makepkg ../spl-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
upgradepkg spl-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
depmod &amp;lt;new kernel version&amp;gt;     (e.g. depmod 3.2.27, if .27 is new kernel upgrade; you currently run on old, maybe .26)&lt;br /&gt;
# this builds the module dependencies in /lib/modules/&amp;lt;new kernel version&amp;gt;&lt;br /&gt;
###### upgrade zfs 2nd&lt;br /&gt;
mkdir install&lt;br /&gt;
cd zfs-*&lt;br /&gt;
./configure --prefix=/ --libexecdir=/usr/libexec --libdir=/lib64 --includedir=/usr/include --datarootdir=/usr/share&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=/usr/local/src/install&lt;br /&gt;
cd ../install&lt;br /&gt;
makepkg ../zfs-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
upgradepkg zfs-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
depmod 3.2.27&lt;br /&gt;
####### upgrade spl/zfs inside altroot /boot/initrd-tree&lt;br /&gt;
ROOT=/boot/initrd-tree upgradepkg spl-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
ROOT=/boot/initrd-tree upgradepkg zfs-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
# note: ROOT is an environment variable, not a command line option to upgradepkg!&lt;br /&gt;
# note: do not worry about depmod inside initrd-tree, mkinitrd -F actually installs the modules&lt;br /&gt;
# note: this upgrade here is really to just upgrade the command line tools zpool, zfs etc&lt;br /&gt;
####### rebuild /boot/initrd.gz and reinstall lilo&lt;br /&gt;
vi /etc/mkinitrd.conf&lt;br /&gt;
# temporarily set KERNEL_VERSION to new version, but you are still running on old version&lt;br /&gt;
mkinitrd -F&lt;br /&gt;
lilo&lt;br /&gt;
vi /etc/mkinitrd.conf&lt;br /&gt;
# you can set KERNEL_VERSION back to $(uname -r) now&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After reboot you can remove any old /lib/modules/&amp;lt;old kernel version&amp;gt; directory.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
More about /etc/hostid. If you want to experiment changing your /etc/hostid file and seeing if you can use it and make zpool import work normally, here is a tool that might be helpful:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/* software product name: foobarz-chhostid.c&lt;br /&gt;
 * suggested binary name: chhostid&lt;br /&gt;
 * license              : BSD&lt;br /&gt;
 * license text:&lt;br /&gt;
Copyright (c) 2012, foobarz&lt;br /&gt;
All rights reserved.&lt;br /&gt;
&lt;br /&gt;
Redistribution and use in source and binary forms, with or without&lt;br /&gt;
modification, are permitted provided that the following conditions are met:&lt;br /&gt;
    * Redistributions of source code must retain the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer.&lt;br /&gt;
    * Redistributions in binary form must reproduce the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer in the&lt;br /&gt;
      documentation and/or other materials provided with the distribution.&lt;br /&gt;
    * Neither the name of the &amp;lt;organization&amp;gt; nor the&lt;br /&gt;
      names of its contributors may be used to endorse or promote products&lt;br /&gt;
      derived from this software without specific prior written permission.&lt;br /&gt;
&lt;br /&gt;
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &amp;quot;AS IS&amp;quot; AND&lt;br /&gt;
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED&lt;br /&gt;
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE&lt;br /&gt;
DISCLAIMED. IN NO EVENT SHALL &amp;lt;COPYRIGHT HOLDER&amp;gt; BE LIABLE FOR ANY&lt;br /&gt;
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES&lt;br /&gt;
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;&lt;br /&gt;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND&lt;br /&gt;
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT&lt;br /&gt;
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS&lt;br /&gt;
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#define FOOBARZ_CHHOSTID_VERSION &amp;quot;1.0.5&amp;quot;&lt;br /&gt;
#include &amp;lt;sys/socket.h&amp;gt;&lt;br /&gt;
#include &amp;lt;netinet/in.h&amp;gt;&lt;br /&gt;
#include &amp;lt;arpa/inet.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;endian.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sysexits.h&amp;gt;&lt;br /&gt;
/* note: if include stdlib then sethostid fails even with _BSD_SOURCE defined */&lt;br /&gt;
&lt;br /&gt;
long swapbytes(long abcd) {&lt;br /&gt;
  long badc;&lt;br /&gt;
  unsigned char addr_a;&lt;br /&gt;
  unsigned char addr_b;&lt;br /&gt;
  unsigned char addr_c;&lt;br /&gt;
  unsigned char addr_d;&lt;br /&gt;
  addr_a = (unsigned char) (abcd &amp;gt;&amp;gt; 24);&lt;br /&gt;
  addr_b = (unsigned char) (abcd &amp;gt;&amp;gt; 16);&lt;br /&gt;
  addr_c = (unsigned char) (abcd &amp;gt;&amp;gt;  8);&lt;br /&gt;
  addr_d = (unsigned char) (abcd);&lt;br /&gt;
  return badc = ( (addr_b &amp;lt;&amp;lt; 24) | (addr_a &amp;lt;&amp;lt; 16) | (addr_d &amp;lt;&amp;lt; 8) | addr_c );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[])&lt;br /&gt;
{&lt;br /&gt;
 long newhostid;&lt;br /&gt;
 struct in_addr addr;&lt;br /&gt;
 char* invalidchar;&lt;br /&gt;
&lt;br /&gt;
 /*********** check command line */&lt;br /&gt;
 if(!( ((argc==3) &amp;amp;&amp;amp; ( (strcmp(argv[1],&amp;quot;-h&amp;quot;)==0) ||&lt;br /&gt;
                       (strcmp(argv[1],&amp;quot;-i&amp;quot;)==0) ||&lt;br /&gt;
                       (strcmp(argv[1],&amp;quot;-l&amp;quot;)==0) )) ||&lt;br /&gt;
       ((argc==2) &amp;amp;&amp;amp; ( (strcmp(argv[1],&amp;quot;-s&amp;quot;)==0) ))&lt;br /&gt;
     )&lt;br /&gt;
   ) {&lt;br /&gt;
                 /*01234567890123456789012345678901234567890123456789012345678901234567890123456789*/&lt;br /&gt;
  fprintf(stderr, &amp;quot;foobarz-chhostid, version %s. License: BSD.\n&amp;quot;, FOOBARZ_CHHOSTID_VERSION);&lt;br /&gt;
  fprintf(stderr, &amp;quot;foobarz-chhostid, (c) 2012, foobarz; all rights reserved.\n&amp;quot;);&lt;br /&gt;
  fprintf(stderr, &amp;quot;descr: %s change system hostid (in /etc/hostid).\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -h &amp;lt;new hostid&amp;gt;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        Change system hostid to &amp;lt;new hostid&amp;gt;;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        &amp;lt;new hostid&amp;gt; must be 32bit 8-digit hex number xxxxxxxx, each x in 0-f|F.\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        The ip corresponding to &amp;lt;new hostid&amp;gt; is also listed for reference only.\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -i &amp;lt;dotted ip address&amp;gt;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        Change system hostid to hostid corresponding to &amp;lt;dotted ip address&amp;gt;.\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -l &amp;lt;dotted ip address&amp;gt;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        List hostid corresponding to &amp;lt;dotted ip address&amp;gt;;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        no change to system hostid.\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -s\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        List current system hostid and corresponding ip address;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        no change to system hostid.\n&amp;quot;, argv[0]);&lt;br /&gt;
  return EX_USAGE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -h &amp;lt;hostid&amp;gt; */&lt;br /&gt;
 if( strcmp(argv[1],&amp;quot;-h&amp;quot;) == 0 ) {&lt;br /&gt;
  if(strlen(argv[2]) != 8) { fprintf(stderr, &amp;quot;new hostid must be 8-digit hex number xxxxxxxx, each x in 0-f|F\n&amp;quot;); return EX_USAGE; }&lt;br /&gt;
&lt;br /&gt;
  newhostid = strtol(argv[2],&amp;amp;invalidchar,16);&lt;br /&gt;
  if( newhostid==LONG_MIN ) { perror(&amp;quot;strtol (underflow)&amp;quot;); return EX_USAGE; }&lt;br /&gt;
  if( newhostid==LONG_MAX ) { perror(&amp;quot;strtol (overflow)&amp;quot;); return EX_USAGE; }&lt;br /&gt;
  if(*invalidchar != '\0') { fprintf(stderr, &amp;quot;invalid hex number %c; must be in 0-f|F\n&amp;quot;, *invalidchar); return EX_USAGE; }&lt;br /&gt;
&lt;br /&gt;
  if( sethostid(newhostid) != 0 ) {&lt;br /&gt;
   perror(&amp;quot;sethostid&amp;quot;);&lt;br /&gt;
   if( errno == EPERM ) return EX_NOPERM;&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
  }&lt;br /&gt;
  printf(&amp;quot;System hostid changed.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  /* hostid is a byte-swapped ip like b.a.d.c */&lt;br /&gt;
  /* get ip by swapping to correct order a.b.c.d and save into in_addr struct */&lt;br /&gt;
  addr.s_addr = htonl(swapbytes(newhostid));&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -i or -l, then find hostid for &amp;lt;dotted ip address&amp;gt; */&lt;br /&gt;
 if( (strcmp(argv[1],&amp;quot;-i&amp;quot;) == 0) || (strcmp(argv[1],&amp;quot;-l&amp;quot;) == 0) ) {&lt;br /&gt;
  if( inet_aton(argv[2], &amp;amp;addr) == 0 ) { fprintf(stderr, &amp;quot;inet_aton: invalid dotted ip address: %s\n&amp;quot;, argv[2]); return EX_USAGE; }&lt;br /&gt;
&lt;br /&gt;
  /* hostid is a byte-swapped ip like b.a.d.c */&lt;br /&gt;
  /* get hostid by swapping bytes of ip a.b.c.d */&lt;br /&gt;
  newhostid = swapbytes(ntohl(addr.s_addr));&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -i &amp;lt;dotted ip address&amp;gt; */&lt;br /&gt;
 if( strcmp(argv[1],&amp;quot;-i&amp;quot;) == 0 ) {&lt;br /&gt;
  if( sethostid(newhostid) != 0 ) {&lt;br /&gt;
   perror(&amp;quot;sethostid&amp;quot;);&lt;br /&gt;
   if( errno == EPERM ) return EX_NOPERM;&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
  }&lt;br /&gt;
  printf(&amp;quot;System hostid changed.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -l &amp;lt;dotted ip address&amp;gt; */&lt;br /&gt;
 if(strcmp(argv[1],&amp;quot;-l&amp;quot;) == 0 ) {&lt;br /&gt;
   printf(&amp;quot;Listing hostid for ip. (no changes)\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -s */&lt;br /&gt;
 if(strcmp(argv[1],&amp;quot;-s&amp;quot;) == 0 ) {&lt;br /&gt;
   /* see if /etc/hostid exists and print info */&lt;br /&gt;
   if( access(&amp;quot;/etc/hostid&amp;quot;, F_OK) != 0 ) {&lt;br /&gt;
     printf(&amp;quot;Notice: /etc/hostid does not exist.\n&amp;quot;);&lt;br /&gt;
     perror(&amp;quot;Reason&amp;quot;);&lt;br /&gt;
     printf(&amp;quot;System hostid derived from ip of hostname found in hosts file or dns.\n&amp;quot;);&lt;br /&gt;
   } else {&lt;br /&gt;
     printf(&amp;quot;Notice: /etc/hostid exists.\n&amp;quot;&lt;br /&gt;
            &amp;quot;System hostid is obtained from hostid file.\n&amp;quot;);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
  errno=0;&lt;br /&gt;
  newhostid = gethostid();&lt;br /&gt;
  if(errno!=0) { perror(&amp;quot;gethostid&amp;quot;); return EX_UNAVAILABLE; }&lt;br /&gt;
&lt;br /&gt;
  /* hostid is a byte-swapped ip like b.a.d.c */&lt;br /&gt;
  /* get ip by swapping to correct order a.b.c.d and save into in_addr struct */&lt;br /&gt;
  addr.s_addr = htonl(swapbytes(newhostid));&lt;br /&gt;
&lt;br /&gt;
  printf(&amp;quot;Listing current system hostid. (no changes)\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** print info and return */&lt;br /&gt;
 printf(&amp;quot;ip dot: %s\n&amp;quot;, inet_ntoa(addr) );&lt;br /&gt;
 printf(&amp;quot;ip hex: %.8x\n&amp;quot;, ntohl(addr.s_addr) );&lt;br /&gt;
 printf(&amp;quot;hostid: %.8x\n&amp;quot;, newhostid );&lt;br /&gt;
 return EX_OK;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
----&lt;br /&gt;
Now available! &amp;quot;ZFS root (builtin)&amp;quot; wiki (aka &amp;quot;ZFS root, part II&amp;quot;):&lt;br /&gt;
http://slackwiki.com/ZFS_root_(builtin)&lt;br /&gt;
It is now possible to build the modules and a small initramfs into your kernel to have a fully-contained and bootable ZFS root kernel from a simple lilo entry. Good luck!&lt;/div&gt;</description>
			<pubDate>Tue, 04 Sep 2012 17:40:07 GMT</pubDate>
			<dc:creator>Foobarz</dc:creator>
			<comments>https://www.slackwiki.com/Talk:ZFS_root</comments>
		</item>
		<item>
			<title>ZFS root</title>
			<link>https://www.slackwiki.com/index.php?title=ZFS_root&amp;diff=780</link>
			<guid isPermaLink="false">https://www.slackwiki.com/index.php?title=ZFS_root&amp;diff=780</guid>
			<description>&lt;p&gt;Foobarz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Tutorials]]&lt;br /&gt;
If you have heard about the ZFS filesystem and you're curious to try it out, then you can try it on slackware64, thanks to the ZFSonLinux.org project!&lt;br /&gt;
&lt;br /&gt;
In this article, an example is shown of how to install slackware64 14.0 onto a ZFS root filesystem (zfs-root) inside a QEMU virtual machine for testing purposes. It is recommended that you install qemu and learn how to use it to test a ZFS installation before you decide to use it on real hardware. A slackbuild for qemu can be found on slackbuilds.org. If you have a processor that supports Intel VT-x or AMD AMD-V virtualization acceleration (try modprobe kvm-intel or modprobe kvm-amd), then use the slackbuild for qemu-kvm.&lt;br /&gt;
&lt;br /&gt;
This article isn't going to go into any detail on actually using ZFS or what kinds of installation options and settings might be optimal. This article just presents an example of how to get started with ZFS on slackware.&lt;br /&gt;
&lt;br /&gt;
At this time of writing, ZFSonLinux is at &amp;quot;release candidate&amp;quot; (version 0.6.0-rc10) development stage, and many issues can occur. See the ZFSonLinux.org web site and the issues tracker for an idea about the current issues. There is also an irc channel on irc.freenode.net, #zfsonlinux, for discussion of issues and help.&lt;br /&gt;
&lt;br /&gt;
Although not required, it is helpful to keep a local mirror of slackware64 on your system. Having a local mirror makes it easier to upgrade to slackware64-current or to patches/* in a release. To help manage your own local slackware mirror and generate your own CD and DVD slackware installers, see http://alien.slackbook.org/blog/local-slackware-mirror/.&lt;br /&gt;
&lt;br /&gt;
In this article, we use a slackware64-current DVD image file as the qemu cdrom device media for the installation of the slackware guest. This was tested at slackware64-current = slackware64 14.0rc2. You can obtain a slackware DVD image using a torrent, buy the DVD from slackware.com, or generate your own DVD image file using the mirror script. For an actual DVD, you can pass your DVD device (e.g., /dev/sr0) as the qemu cdrom device. For a DVD image file, pass the image file as the qemu cdrom device.&lt;br /&gt;
&lt;br /&gt;
The ZFSonLinux packages are not included in slackware at this time. There are two packages involved: spl and zfs. The first, spl, is &amp;quot;Solaris Porting Layer&amp;quot; and must be installed on the system before zfs can be compiled. The source code tarballs for these are at ZFSonLinux.org. At this time of writing, they are spl-0.6.0-rc10.tar.gz and zfs-0.6.0-rc10.tar.gz.&lt;br /&gt;
&lt;br /&gt;
At this point, it is assumed you have qemu installed, have obtained a slackware64-current/14.0 DVD, and have downloaded spl and zfs tarballs to your host system. The first step now is, if your host is not slackware64-current/14.0 (the same as the guest will be), then you need to create a minimal development slackware64 guest system in qemu for just the purpose of compiling and packaging the spl and zfs slackware packages and transferring a copy of these packages back onto your host system to use later to install onto zfs during the slackware install process.&lt;br /&gt;
&lt;br /&gt;
From this point onward, instructions become a bit terse and mostly limited to examples of the commands you might use to complete tasks. You are encouraged to examine what each command does by reading the command's man pages. For example, the command &amp;quot;man qemu&amp;quot; can show you most of what you need to know about running qemu on the command line.&lt;br /&gt;
&lt;br /&gt;
So, here's an example of how you might build the spl and zfs packages, starting in your home directory:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on host)&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir qemu&lt;br /&gt;
cd qemu&lt;br /&gt;
mkdir slackdevel&lt;br /&gt;
cd slackdevel&lt;br /&gt;
mkdir packages&lt;br /&gt;
cp ~/spl-*.tar.gz packages&lt;br /&gt;
cp ~/zfs-*.tar.gz packages&lt;br /&gt;
qemu-img create disk1.raw 10G&lt;br /&gt;
ln -s ~/slackware64-current-install-dvd.iso dvd.iso&lt;br /&gt;
qemu-system-x86_64 \&lt;br /&gt;
 -no-quit \&lt;br /&gt;
 -no-shutdown \&lt;br /&gt;
 -boot order=cd,menu=on \&lt;br /&gt;
 -m 2G \&lt;br /&gt;
 -cpu host \&lt;br /&gt;
 -smp sockets=1,cores=4 \&lt;br /&gt;
 -net nic,model=rtl8139 -net user \&lt;br /&gt;
 -cdrom dvd.iso \&lt;br /&gt;
 -drive boot=on,format=raw,media=disk,cache=none,aio=native,if=scsi,bus=0,unit=0,file=disk1.raw \&lt;br /&gt;
 -virtfs local,path=./packages/,security_model=none,mount_tag=hostpackages&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When you need to change boot to cd or disk, add or remove &amp;quot;boot=on&amp;quot;, or change &amp;quot;order=dc&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Note: If you are using a newer version of qemu-kvm, the support for if=scsi might be missing the needed option-rom. You might need to download http://www.lsi.com/downloads/Public/Host Bus Adapters/Host Bus Adapters Common Files/lsi_bios.zip. Unzip it, and then:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp 8xx_64.rom /usr/share/qemu&lt;br /&gt;
# then run qemu-kvm with additional command line option: -option-rom 8xx_64.rom,bootindex=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Qemu should boot into the install-dvd, and now perform a very ordinary slackware64 install onto /dev/sda. Install d package set and most others, but package sets x, kde, xfce not really needed.&lt;br /&gt;
&lt;br /&gt;
First note: examples here use tools from the gptfdisk package (gdisk, sgdisk, cgdisk) to partition the disk with GUID partition table (GPT) format. GPT might not be too familiar to everyone, who mostly have only used MBR partitions with fdisk. In the slackware installations this author has tested in qemu, using GPT partitions has caused no problems with lilo or other tools used in slackware. GPT disk labels support creating up to 128 partitions and support disks larger than 2TB (the limit of MBR fdisk). LILO installs into the first 440 bytes on /dev/sda, inside a GPT &amp;quot;protective MBR&amp;quot; that serves to provide compatibility with MBR bootloaders like lilo. LILO uses LBA32 sector addressing and can see all 512-byte sectors side the first 2TB of a disk. So long as the /boot partition is within the first 2TB of a disk, lilo can work on a disk larger than 2TB. Unlike the common default of fdisk to start the first partition at sector 63, which is not aligned with the 4KiB sector size of Advanced Format hard disks, gdisk's default is to start partitions at 2048 sector (1MiB) boundaries which are also 4KiB aligned. Using gdisk GPT works on all disks and is compatible with using Advanced Format hard disks larger than 2TB. More information about GPT disk label format can be found on wikipedia.org. For those that have used grub instead of lilo, grub installation is different with GPT than with MBR, and grub requires a GPT partition of type grub-bios or 0xEF02 &amp;quot;BIOS Boot Partition&amp;quot; of about 8MiB where it can install it's additional bootloader stages because grub cannot embed in sectors 1-62 on GPT where GPT keeps it's partition tables. On MBR, sectors 1-62 were normally reserved space for bootloaders to keep a 2nd stage.&lt;br /&gt;
&lt;br /&gt;
For this purpose of development guest, just create a simple 1-partition system, /dev/sda1, and do a simple slackware install on it. Don't bother with swap or separate /boot unless you want to:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on install-dvd)&lt;br /&gt;
cgdisk /dev/sda&lt;br /&gt;
setup&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When this simple development guest boots, login as root, and continue:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on qemu guest)&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir packages&lt;br /&gt;
mount hostpackages -t 9p -o trans=virtio packages&lt;br /&gt;
echo --prefix=/ --libexecdir=/usr/libexec --libdir=/lib64 --includedir=/usr/include --datarootdir=/usr/share &amp;gt; configure-options&lt;br /&gt;
mkdir src&lt;br /&gt;
cd src&lt;br /&gt;
&lt;br /&gt;
mkdir install&lt;br /&gt;
tar xvzf ~/packages/spl-*.tar.gz&lt;br /&gt;
cd spl-*&lt;br /&gt;
./configure $( cat ~/configure-options )&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../spl-&amp;lt;version&amp;gt;_&amp;lt;kernel_version&amp;gt;-x86_64-&amp;lt;build_id&amp;gt;.txz&lt;br /&gt;
(e.g., makepkg ../spl-0.6.0rc10_3.2.27-x86_64-1root.txz)&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
installpkg spl-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
cp spl-0.6.0rc10_3.2.27-x86_64-1root.txz ~/packages&lt;br /&gt;
&lt;br /&gt;
mkdir install&lt;br /&gt;
tar xvzf ~/packages/zfs-*.tar.gz&lt;br /&gt;
cd zfs-*&lt;br /&gt;
./configure $( cat ~/configure-options )&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../zfs-&amp;lt;version&amp;gt;_&amp;lt;kernel_version&amp;gt;-x86_64-&amp;lt;build_id&amp;gt;.txz&lt;br /&gt;
(e.g., makepkg ../zfs-0.6.0rc10_3.2.27-x86_64-1root.txz)&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
installpkg zfs-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
cp zfs-0.6.0rc10_3.2.27-x86_64-1root.txz ~/packages&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point spl and zfs packages are copied back to the host in the packages directory. Also, spl and zfs are installed in this simple development guest, so one could begin to experiment with zfs pools and datasets but while the root fs is whatever you made it during setup (probably the default, ext4). This development guest isn't really needed anymore, so it can be deleted:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
halt&lt;br /&gt;
(exit qemu: ctrl-alt-2 then enter quit at QEMU command prompt)&lt;br /&gt;
&lt;br /&gt;
(on host)&lt;br /&gt;
rm disk1.raw dvd.iso&lt;br /&gt;
mv packages ..&lt;br /&gt;
cd ..&lt;br /&gt;
rmdir slackdevel&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now that we have the spl and zfs packages on the host, it is possible to copy them into your local slackware64 mirror and then generate your own install DVD image that includes them. For example, change to the directory that contains the slackware README files, and create a &amp;quot;addon&amp;quot; directory and copy the spl and zfs slackware packages into there. Then, generate the DVD image using a command such as $( ./mirror-slackware-current.sh -i ) from where you have this script configured to maintain your local mirror. We can also just continue to access them inside the installer using qemu's virtfs option. When you are going to do a real installation onto real hardware, you need to generate and burn your own DVD that includes the packages.&lt;br /&gt;
&lt;br /&gt;
It is time to begin the installation of slackware64 on a ZFS root, assuming either you have regenerated dvd.iso with zfs packages in addon/* or we access the zfs packages while in the installer using qemu's virtfs to the host's packages directory. ZFS supports creating complex data storage configurations such as pools (similar to a volume group) backed by one or more of various kinds of virtual devices (similar to disks and raid arrays) and containing one or more datasets (similar to mounted filesystems, logical volume devices, or snapshots). But here, we keep it simple and will install on just a single disk device. On a real ZFS installation, users will typically want to use the ZFS raidz1 or raidz2 virtual device types for reliability against hard drive failures.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on host)&lt;br /&gt;
mkdir slackzfs&lt;br /&gt;
mv packages slackzfs/&lt;br /&gt;
cd slackzfs&lt;br /&gt;
qemu-img create disk1.raw 10G&lt;br /&gt;
ln -s ~/slackware64-current-install-dvd.iso dvd.iso&lt;br /&gt;
qemu-system-x86_64 \&lt;br /&gt;
 -no-quit \&lt;br /&gt;
 -no-shutdown \&lt;br /&gt;
 -boot order=cd,menu=on \&lt;br /&gt;
 -m 2G \&lt;br /&gt;
 -cpu host \&lt;br /&gt;
 -smp sockets=1,cores=4 \&lt;br /&gt;
 -net nic,model=rtl8139 -net user \&lt;br /&gt;
 -cdrom dvd.iso \&lt;br /&gt;
 -drive boot=on,format=raw,media=disk,cache=none,aio=native,if=scsi,bus=0,unit=0,file=disk1.raw \&lt;br /&gt;
 -virtfs local,path=./packages/,security_model=none,mount_tag=hostpackages&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The install-dvd should boot, and then begin installation steps on the installer command line:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on install-dvd)&lt;br /&gt;
# mount the install-dvd&lt;br /&gt;
mkdir /dvd&lt;br /&gt;
mount /dev/sr0 /dvd&lt;br /&gt;
&lt;br /&gt;
# install coreutils, which provides the &amp;quot;hostid&amp;quot; command needed to load the spl module&lt;br /&gt;
installpkg /dvd/slackware64/a/coreutils-8.17-x86_64-1.txz&lt;br /&gt;
&lt;br /&gt;
# install kmod package which includes &amp;quot;depmod&amp;quot; command and others&lt;br /&gt;
installpkg /dvd/slackware64/a/kmod-9-x86_64-2.txz&lt;br /&gt;
depmod&lt;br /&gt;
&lt;br /&gt;
# install the full kernel modules so you can load 9p filesystem and use it if you want&lt;br /&gt;
# .. you might keep the zfs modules packages off the dvd and use a plain slack dvd&lt;br /&gt;
installpkg /dvd/slackware64/a/kernel-modules-*.txz&lt;br /&gt;
depmod&lt;br /&gt;
&lt;br /&gt;
# install bash and libtermcap because udev rules in zfs use bash scripts&lt;br /&gt;
installpkg /dvd/slackware64/a/bash-*.txz&lt;br /&gt;
installpkg /dvd/slackware64/l/libtermcap-*.txz&lt;br /&gt;
&lt;br /&gt;
# install spl and zfs that you have copied into the mirror before running the DVD creation&lt;br /&gt;
installpkg /dvd/addon/spl-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /dvd/addon/zfs-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
&lt;br /&gt;
#Or:&lt;br /&gt;
mkdir /packages&lt;br /&gt;
find /lib/modules/ | grep 9p&lt;br /&gt;
lsmod&lt;br /&gt;
# check that 9p modules load, mainly 9pnet_virtio&lt;br /&gt;
modprobe 9pnet_virtio&lt;br /&gt;
mount hostpackages -t 9p -o trans=virtio /packages&lt;br /&gt;
installpkg /packages/spl-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /packages/zfs-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
modprobe zfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now zfs tools: &amp;quot;zpool&amp;quot; and &amp;quot;zfs&amp;quot; should work in the live installer.&lt;br /&gt;
On the installer, there can be trouble seeing man pages, so install:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
installpkg /dvd/slackware64/ap/man-*.txz&lt;br /&gt;
installpkg /dvd/slackware64/ap/groff-*.txz&lt;br /&gt;
installpkg /dvd/slackware64/a/less-*.txz&lt;br /&gt;
export MANPATH=/usr/man:/usr/share/man&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The manual pages should be readable:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
man zpool&lt;br /&gt;
man zfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After seeing the man pages, we should be fully ready to continue to setup on ZFS.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(still on install-dvd)&lt;br /&gt;
ls -l /dev/sd*&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Make sure the disk devices you expect are there. We'll use sda and make boot (/boot on /dev/sda1) and root (/ on /dev/sda2) partitions.&lt;br /&gt;
&lt;br /&gt;
First, some background info: A ZFS filesystem is not supported by lilo as the filesystem containing /boot, which holds lilo's 2nd stage and the linux kernel files. The on-disk format of a ZFS filesystem is often a complex raid configuration where even if lilo understood ZFS it would likely require /boot to reside in only certain simple ZFS configurations to be plainly readable to lilo. As things are, a linux root installed in a partition with ZFS filesystem needs /boot to be on another partition with a filesystem that lilo understands, such as ext4 fs. In addition, because the spl and zfs modules are not built into the kernel, and the zfs startup requires some configuration to mount the zfs root, an initial ram/root filesystem (initrd) is needed. The initrd is a gzip compressed cpio archive file that contains a small linux root operating system that is decompressed into a ramfs block device at boot up and takes initial control of the system. The initrd contains an init script that configures devices in devtmpfs mounted at /dev. For example, if using mdadm, lvm, luks, losetup, and now zfs, this init script runs all the commands to create or start these devices (one of which is the root device), mounts the root device, and then transfers system control to the init script in the mounted root filesystem. The ramfs-based root environment on the booted install-dvd or booted initrd image (in rescue command line) are small slackware installations that exist only in ram and are temporary, but while inside them you can install, upgrade, and remove slackware packages inside them using the regular package management tools; this allows you access to any kernel modules and programs as needed inside these ramfs root. Packages can be installed, upgraded, or removed permanantly in the initrd image file to manage the programs and modules required during the initrd boot stage. Also from within these ramfs initial root environments, once the root device is mounted, chroot can be used to work on the mounted root system as if it were booted; this allows one to fix problems that are occuring in the root fs init scripts that cause normal booting to fail, or to install a kernel and/or modules etc. Now on to partitioning:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cgdisk /dev/sda&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, cgdisk looks just like cfdisk, but it makes GPT partitions.&lt;br /&gt;
&lt;br /&gt;
Make a partition for /boot that is about 512MiB of whatever partition type you like (8300 &amp;quot;Linux filesystem&amp;quot; is fine), or make it type bf07 &amp;quot;Solaris Reserved 1&amp;quot; if you want ZFS to maybe see the disk as if it was given as a whole disk to ZFS. Make a second partition using the remaining space with partition type bf01 &amp;quot;Solaris ZFS&amp;quot;. Currently, when ZFSonLinux is given a whole disk device like /dev/sdb to use, it will automatically GPT partition it with a bf01 partition #1 that is the whole disk except a small 8MiB type bf07 partition #9 at the end of the disk (/dev/sdb1 and /dev/sb9). The small 8MiB type bf07 partition #9 is mostly likely reserved for use by bootloaders, like lilo, to have a /boot or other boot-related files kept there. For example, you might have /dev/sda that is totally non-ZFS for booting and /dev/sdb passed to ZFS whole where it automatically partitions sdb, but you can just use one disk here and make partitions. Lets use type 8300 for /boot to be sure nothing is confused:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
We'll continue with this partitioning (numbers are in MiB):&lt;br /&gt;
  0 to   4: unused&lt;br /&gt;
  4 to 516: /dev/sda1 512MiB, type 8300&lt;br /&gt;
516 to 520: unused&lt;br /&gt;
520 to -96: /dev/sda2, type bf01&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The -96 means to count from the end of the disk so that 96MiB will remain unused at the end of the disk.&lt;br /&gt;
&lt;br /&gt;
Create a zpool called zfs-root:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool create -m none zfs-root /dev/sda2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A zpool created like this, the normal way, is a kernel-internal block device that contains already a zfs filesystem. There is normally no entry in /dev for this device. However, it can still be referenced as a mountable device similar to how devtmpfs, proc, and sysfs are also kernel-internal mountable block devices. The -m option told zpool not to automatically mount it anywhere, and without -m the default is to always automatically mount to /zfs-root. These kinds of details are explained better elsewhere. For this situation, we do not want it automounted.&lt;br /&gt;
&lt;br /&gt;
Because a zpool itself is a useable zfs fs, it has a full set of zfs &amp;quot;properties&amp;quot; to set options about the filesystem, perhaps similar to tune2fs. The &amp;quot;mountpoint=&amp;lt;some place to mount&amp;gt;&amp;quot; is one such property. We want it set to the special value &amp;quot;none&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs get mountpoint zfs-root&lt;br /&gt;
zfs set mountpoint=none zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On creation, the zpool zfs-pool is &amp;quot;imported&amp;quot; and has a zpool status that can be viewed:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool status zfs-root&lt;br /&gt;
&lt;br /&gt;
zpool export zfs-root&lt;br /&gt;
zpool status zfs-root&lt;br /&gt;
# Now there is no status.&lt;br /&gt;
&lt;br /&gt;
zpool import zfs-root&lt;br /&gt;
# Now it is back.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When a zpool is imported, it has it's current configuration cached in a file /etc/zfs/zpool.cache. When a zpool is exported, then it's entries in the cache file are removed and the cache file is deleted if it becomes empty. So long as the zfs kernel modules see this cache file and valid cache data inside it, ZFS considers the described zpools in the cache file to be valid as imported zpools. If the zpool.cache file is present at the time the zfs modules are loaded, then there is no further need to use the import and export commands at system startup and shutdown. With root on a zfs, it is not possible to export the pool that root is on, but this is not a problem. At shutdown, the safe procedure will be to set the zfs-root property readonly=on and sync disks.&lt;br /&gt;
&lt;br /&gt;
To avoid the requirement to import the zfs-root pool at startup, keep a copy of the zpool.cache file to later copy onto the initrd image to read at modules load time to have the pool reactived without need to issue the import command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/zfs/zpool.cache /etc/zfs/zpool.cache-initrd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A zfs fs will not normally allow you to mount over any files. The mountpoint is expected to be an empty directory. Remove any junk files inside the installer's /mnt because zfs won't mount over any files:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rm /mnt/README&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The directory /mnt is where the slackware setup expects you to mount your root for installation.&lt;br /&gt;
&lt;br /&gt;
Controlling whether a zfs fs is to be mounted read-only or read-write is best managed by setting the readonly property while it is not yet mounted:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set readonly=on zfs-root&lt;br /&gt;
zfs set readonly=off zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Slackware expects root to be mounted readonly when /etc/rc.d/rc.S runs during normal startup, so later this is used to satisfy slackware's expectation to avoid rc.S complaining.&lt;br /&gt;
&lt;br /&gt;
The zfs-root can be mounted and unmounted in two different ways:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=/mnt zfs-root&lt;br /&gt;
zfs set mountpoint=none zfs-root&lt;br /&gt;
# or&lt;br /&gt;
mount zfs-root -t zfs /mnt&lt;br /&gt;
umount /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If it is already mounted and you want to change it to mount somewhere else, it is best to transition it to unmounted first, then mount it in the new place.&lt;br /&gt;
&lt;br /&gt;
The mount options &amp;lt;code&amp;gt;-o ro, -o rw, -o remount,ro, and -o remount,rw &amp;lt;/code&amp;gt; can also be used and will override &amp;lt;code&amp;gt;readonly=on|off&amp;lt;/code&amp;gt; property without altering the property value. This can be confusing until you are familiar with how to the methods of mounting interact.&lt;br /&gt;
&lt;br /&gt;
Now, let's continue some, and mount to /mnt using the current &amp;lt;code&amp;gt;readonly=off&amp;lt;/code&amp;gt; setting (rw mount):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=/mnt zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This method of mounting will show the most detailed mount options in /etc/mtab. They are the mount options that zfs thinks are proper, and they are probably what should be kept in /etc/fstab for zfs-root until we know better.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cat /etc/mtab &amp;gt;&amp;gt; /etc/fstab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now edit /etc/fstab to make sure it looks right, and remove the &amp;quot;rw&amp;quot; mount option, because we want to let it use a default for that, which will come from how we set the readonly= property most of the time. Unmount again:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=none zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mount again, now using all options from /etc/fstab:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It should be mounted at /mnt, and touch /mnt/t should allow you to make the file t. Then rm it: rm /mnt/t&lt;br /&gt;
For installation, we want to make sure it is mounted read-write. After installation, it should mount readonly inside the initrd.&lt;br /&gt;
&lt;br /&gt;
Sometimes there can be problems using the mount command, and then you can try it with the -i option:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 mount -i zfs-root&lt;br /&gt;
 mount -i zfs-root -t zfs /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
but, you should not have to use -i. When using -i makes it work, it performs an &amp;quot;internal-only&amp;quot; mount and does not use any mount.&amp;lt;fstype&amp;gt; helper scripts that might be on the system.&lt;br /&gt;
&lt;br /&gt;
Setup the /boot device:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkfs.ext4 /dev/sda1&lt;br /&gt;
mkdir /mnt/boot&lt;br /&gt;
mount /dev/sda1 /mnt/boot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We have both root and boot mounted where the slackware installer expects them. Unmount the dvd so setup can find it normally:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
umount /dev/sr0&lt;br /&gt;
setup&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the setup, skip straight to TARGET selection for the root device, but the setup doesn't see or understand the zfs-root, so it is not listed. This does not matter because we have mounted it already. Just skip down to a slot that say to continue, and continue on with setup. Because TARGET is skipped, you may not see the ADDITIONAL prompt (or if so, skip it too) where normally you give /dev/sda1 and have it mounted as /boot. This is also okay because we have mounted /mnt/boot already.&lt;br /&gt;
Because we did not give TARGET the root device or say what device /boot is on, the lilo installation will fail, or you can skip it. Otherwise, this installation process it normal.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
umount /dev/sr0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point, it is assumed that the setup has completed installing into /mnt. Congrats! You've installed slackware into a ZFS root!&lt;br /&gt;
&lt;br /&gt;
The next steps are to prepare to use &amp;quot;chroot /mnt&amp;quot; and finish up the configuration on the installed root system and then be able to reboot onto the completed installation. Before doing chroot, copy some files from the setup environment into /mnt.&lt;br /&gt;
&lt;br /&gt;
Copy the current installer /etc/fstab for later use inside the initrd. This fstab is what is proper inside the initrd, except remove option &amp;quot;rw&amp;quot; (if not done already).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/fstab /mnt/etc/fstab.initrd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The fstab.initrd will look like:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 proc /proc proc defaults 0 0&lt;br /&gt;
 zfs-root /mnt zfs defaults,atime,dev,exec,suid,xattr,nomand,zfsutil 0 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the initrd, we want zfs-root to mount to /mnt.&lt;br /&gt;
&lt;br /&gt;
Create /mnt/etc/fstab:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cat /etc/mtab &amp;gt;&amp;gt; /mnt/etc/fstab&lt;br /&gt;
vi /mnt/etc/fstab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using vi started above, edit /mnt/etc/fstab and make it have lines such as:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 zfs-root / zfs defaults,atime,dev,exec,suid,xattr,nomand,zfsutil 0 0&lt;br /&gt;
 /dev/sda1 /boot ext4 defaults 0 2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These two lines in &amp;lt;code&amp;gt;/mnt/etc/fstab&amp;lt;/code&amp;gt; are how the mounts should be looking when root is booted.&lt;br /&gt;
&lt;br /&gt;
Mount some special mounts before chroot:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount -t devtmpfs none /mnt/dev&lt;br /&gt;
mount -t proc none /mnt/proc&lt;br /&gt;
mount -t sysfs none /mnt/sys&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Make sure /boot is mounted:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount /dev/sda1 /mnt/boot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you had mounted a 9p fs share to access spl and zfs packages, then unmount that now:&lt;br /&gt;
umount /packages&lt;br /&gt;
&lt;br /&gt;
Ready, now:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chroot /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point, you should be on the installed system, and now try to configure mkinitrd and lilo. First, switch to use the generic kernel.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /boot&lt;br /&gt;
rm System.map config vmlinuz&lt;br /&gt;
ln -s System.map-gen* System.map&lt;br /&gt;
ln -s config-gen* config&lt;br /&gt;
ln -s vmlinuz-gen* vmlinuz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We install spl and zfs inside the live ramfs install-dvd environment, but not yet have we installed them into the root system:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount /dev/sr0 /mnt/cdrom&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /mnt/cdrom/addon/spl-*.txz&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /mnt/cdrom/addon/zfs-*.txz&lt;br /&gt;
depmod&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If instead, you used a 9p share to access the spl and zfs packages, then repeat that procedure here to install them onto the root system.&lt;br /&gt;
&lt;br /&gt;
Setup lilo: edit /etc/lilo.conf so it is like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  lba32&lt;br /&gt;
  append = &amp;quot; vt.default_utf8=1&amp;quot;&lt;br /&gt;
  boot = /dev/sda&lt;br /&gt;
  message = /boot/boot_message.txt&lt;br /&gt;
  prompt&lt;br /&gt;
  timeout = 1200&lt;br /&gt;
  change-rules&lt;br /&gt;
   reset&lt;br /&gt;
  vga = normal&lt;br /&gt;
  image = /boot/vmlinuz&lt;br /&gt;
   label = vmlinuz&lt;br /&gt;
   initrd = /boot/initrd.gz&lt;br /&gt;
   root = /dev/ram0&lt;br /&gt;
   read-write&lt;br /&gt;
# alternatively, the root and read-write lines&lt;br /&gt;
# can be this one line of kernel parameters:&lt;br /&gt;
#  addappend = &amp;quot; root=/dev/ram0 rw &amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A note about initrd: The /boot/initrd.gz is a gzipped cpio archive containing a minimal BusyBox-based slackware root system that is sourced from /boot/initrd-tree. The commands &amp;quot;mkinitrd&amp;quot; and &amp;quot;mkinitrd -F&amp;quot; generates /boot/initrd-tree and /boot/initrd.gz. When using a initrd, the initial root device is normally set to root=/dev/ram0 (a ramfs block device) and allowed read-write. The kernel refers to devices in terms of &amp;quot;major&amp;quot; and &amp;quot;minor&amp;quot; numbers, and the ram0 device is assigned the block device major 1 and minor 0. This ram0 major/minor is written in hexadecimal as 0x0100 (256 in decimal). This hexademical number makes an appearance in /boot/initrd-tree/int where it runs: &amp;quot;echo 0x0100 &amp;gt; /proc/sys/kernel/real-root-dev&amp;quot;. Echoing a device code to real-root-dev is part of a deprecated initrd mechanism, but is probably harmless to leave alone as slackware has it unless you know otherwise. More information about how initrd works can be found in:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/usr/src/linux/Documentation/devices.txt (info about major:minor device numbers)&lt;br /&gt;
/usr/src/linux/Documentation/initrd.txt  (mostly obsolete info on old initrd)&lt;br /&gt;
/usr/src/linux/Documentation/filesystems/ramfs-rootfs-initramfs.txt (current info on new initrd, called initramfs)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Advanced note about initrd: Slackware's mkinitrd package does not use the &amp;quot;pivot_root&amp;quot; command as documented in &amp;quot;initrd.txt&amp;quot;, but instead uses &amp;quot;switch_root&amp;quot; provided by a project called BusyBox. The switch_root changes the effective root filesystem from the initrd (unpacked in rootfs at /) to new root filesystem (zfs-root mounted at /mnt); it overmounts rootfs / with zfs-root /mnt. The switch_root works as follows: delete everything in rootfs / (one filesystem only) that held initrd to free up ram memory, then use mount, chroot, and chdir to make the effective root change. In concept (as a shell script), the command &amp;quot;exec switch_root /mnt $INIT $RUNLEVEL&amp;quot; is performed as follows:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 find / -xdev | xargs rm -rf&lt;br /&gt;
 cd &amp;quot;$1&amp;quot;&lt;br /&gt;
 shift&lt;br /&gt;
 mount --move . /&lt;br /&gt;
 exec chroot . &amp;quot;$@&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Here, typically INIT=/sbin/init RUNLEVEL=3. The 'exec' causes switch_root to take the place of the parent process having PID=1. In system calls, the switch_root looks similar to this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chdir(&amp;quot;/mnt&amp;quot;);&lt;br /&gt;
/* &amp;lt;insert code to unlink/rmdir all initrd files/directories&lt;br /&gt;
 *  installed in rootfs / without crossing filesystems &amp;gt; */&lt;br /&gt;
mount(&amp;quot;.&amp;quot;, &amp;quot;/&amp;quot;, NULL, MS_MOVE, NULL);&lt;br /&gt;
chroot(&amp;quot;.&amp;quot;);&lt;br /&gt;
chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
execl(&amp;quot;/sbin/init&amp;quot;, &amp;quot;3&amp;quot;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The kernel startup rootfs / that contained initrd is never actually unmounted (it can't be) because it is built into the kernel and always exists as at least a tiny ramfs or tmpfs, so you can continue to see it in /proc/mounts. When you give lilo root=/dev/ram0 (a ramfs device), the kernel will actually use the internal rootfs, which is an instance of a tmpfs (if your kernel config includes tmpfs) or else an instance of a ramfs. The rootfs that is a tmpfs can by default use up to half of system ram. If rootfs is a ramfs, it can use up to almost all of system ram until the system panics. Typically, tmpfs is built into the kernel, and so depending on how much ram your computer has, the initrd-tree can probably be up to about half that size.&lt;br /&gt;
&lt;br /&gt;
Quite a lot of notes... now to continue on:&lt;br /&gt;
&lt;br /&gt;
Setup mkinitrd:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/mkinitrd.conf.sample /etc/mkinitrd.conf&lt;br /&gt;
vi /etc/mkinitrd.conf&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Edit it to look like this (other defaults should be ok):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 MODULE_LIST=&amp;quot;sym53c8xx:ext4:8139cp:zfs:9p:9pnet_virtio&amp;quot;&lt;br /&gt;
 ROOTDEV=&amp;quot;zfs-root&amp;quot;&lt;br /&gt;
 ROOTFS=&amp;quot;zfs&amp;quot;&lt;br /&gt;
#Module sym53c8xx is the driver for qemu's if=scsi drive device.&lt;br /&gt;
#Module ext4 for /boot.&lt;br /&gt;
#Module 8139cp for eth0 net device.&lt;br /&gt;
#Module zfs for ZFSonLinux.&lt;br /&gt;
#Modules 9p and 9pnet_virtio for mounting qemu -virtfs mount_tag.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These 9p could be useful from the rescue command line inside the initrd to get needed files that are on the host.&lt;br /&gt;
&lt;br /&gt;
All dependent modules will also be included automatically into /boot/initrd-tree, which is packaged as /boot/initrd.gz. For example, to see the dependent modules of zfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
modprobe --show-depends zfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All listed modules will also be in the initrd. Now, make a /boot/initrd-tree that we can begin to look at and edit.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkinitrd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create an empty /etc/mtab or else zpool import fails (zfs expects /etc/mtab to exists already, it won't make it).&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
touch /boot/initrd-tree/etc/mtab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Copy in the fstab.initrd that was made earlier while on the installer. This provides all the mount options for a simple &amp;quot;mount zfs-root&amp;quot; onto /mnt.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/fstab.initrd /boot/initrd-tree/etc/fstab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More package installing! This time into an alternate root, the root of the initrd, /boot/initrd-tree. This is how you can put whatever packages you like into your initrd. These installations work independent of your normal installations. You can install, upgrade, and remove packages using an altroot:&lt;br /&gt;
&lt;br /&gt;
If spl and zfs are on your customized dvd:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/addon/spl-*.txz&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/addon/zfs-*.txz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Otherwise, repeat same procedure but you mount your 9p mount_tag and get them installed.&lt;br /&gt;
&lt;br /&gt;
More regular packages from the dvd:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/kmod-*.txz&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/coreutils-*.txz&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/gptfdisk-*.txz&lt;br /&gt;
&lt;br /&gt;
# A bash script is in /boot/initrd-tree/lib/udev/, so we need it or udev rules have problems:&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/bash-*.txz&lt;br /&gt;
# Bash needs this:&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/l/libtermcap-*.txz&lt;br /&gt;
&lt;br /&gt;
# Install net-tools to ensure that /etc/HOSTNAME, /etc/hosts, and potentially, /etc/hostid are handled proper.&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/n/net-tools-*.txz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When ZFS has to import a zpool while the initrd is running (this can be avoided by not exporting and keeping /etc/zfs/zpool.cache inside the initrd), ZFS will refuse to import a pool if it thinks that the pool may be in use by another system. ZFS was designed for network attached storage where multiple hosts might have access to the same disks but ZFS cannot support two hosts importing and using a ZFS pool at the same time. ZFS checks a value called &amp;quot;hostid&amp;quot; to determine this kind of conflict, and it can be a tricky issue with an initrd boot process. The value of hostid is returned by a system call, the gethostid() function or the hostid command. This function will return the hostid from /etc/hostid if that file exists and has a valid id in it, or else if the file doesn't exist it obtains a hostid number based on the hostname and ip address address assigned to hostname found in /etc/hosts or in DNS. If the hostid trying to import a pool is not the same as the hostid that imported it last time, ZFS will not import the pool unless &amp;quot;zpool import -f zfs-root&amp;quot; is used to force the import. This force option is not recommended to use, so it is best to configure your initrd with matching /etc/HOSTNAME and /etc/hosts as on the root installation and ensure what your system looks like on the initrd matches the booted root system.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Edit /boot/initrd-tree/init (this is the main system startup script on the initrd, responsibe for configuring your block devices and mount your root at /mnt and then booting root):&lt;br /&gt;
&lt;br /&gt;
Inside init, right near the top of the file after the PATH= line, add this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/bin/hostname -F /etc/HOSTNAME&lt;br /&gt;
/bin/hostname $( /bin/hostname -s )&lt;br /&gt;
#/sbin/chhostid 13371400&lt;br /&gt;
# you can make your hostid whatever, but this didn't work right with ZFS, so it is commented out&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This sets the name reported by the hostname command (the default is &amp;quot;darkstar&amp;quot;) to be what is contained in /etc/HOSTNAME. The hostname is modified in the next line to be the short name. These lines will help ZFS to properly identify your host when importing pools.&lt;br /&gt;
&lt;br /&gt;
Inside init, right after it runs &amp;quot;mdadm&amp;quot; commands as used for raid setup, we like it to setup ZFS, so add:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/sbin/zpool import zfs-root&lt;br /&gt;
/sbin/zfs set readonly=on zfs-root&lt;br /&gt;
mount zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Inside init, close to the bottom, where it &amp;quot;Switch to real root partition&amp;quot;, comment out 1 line that normally does the mount:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# mount -o ro -t $ROOTFS $ROOTDEV /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
We have already mounted, and we don't want to use any mount options because we should be using a properly set /etc/fstab inside the initrd for zfs-root mount options onto /mnt.&lt;br /&gt;
&lt;br /&gt;
During a normal startup we want a readonly mount.&lt;br /&gt;
&lt;br /&gt;
Note: we are going to setup with using zpool import and export and startup and shutdown. But later, you can experiment having /etc/zfs/zpool.cache stored in the initrd and commenting out zpool import/export lines.&lt;br /&gt;
&lt;br /&gt;
As mentioned, the import command may sometimes fail, and give the message: &amp;quot;pool may be in use from another system&amp;quot;. This is nothing serious in this test situation. When this happens, root will not be mounted to /mnt and the init script will detect this and drop you into a rescue command line where you may manually &amp;quot;import -f&amp;quot; then &amp;quot;mount zfs-root&amp;quot; and then &amp;quot;exit&amp;quot; to continue on to booting the root.&lt;br /&gt;
&lt;br /&gt;
To avoid this problem we copy some files in (assuming you first edit /etc/HOSTNAME to hold the hostname you like to see on your command prompts, and edited /etc/hosts to have hostname on your loopback or other local ip address):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/HOSTNAME /etc/hosts /boot/initrd-tree/etc&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The value reported by the hostid command is what ZFS sees as your hostid. In this setup so far, the value is based on the ip found assigned to your hostname. If your hostname is on the line in /etc/hosts for ip address 192.168.13.37, then your hostid will be hex numbers C0.A8.0D.25 rearranged as A8C0250D (pairs of bytes are swapped). That is ip-based hostid value, a 32bit hexadecimal number. This has to be the same each boot or import will need a -f option to force it. Simply setting the hostid using the system call sethostid() which writes a /etc/hostid file doesn't seem to agree with ZFS and you'd have to force the import, so this setup now assumes that you do not have or have deleted /etc/hostid.&lt;br /&gt;
&lt;br /&gt;
You can sometimes see what has been happening to a zpool by using the command &amp;quot;zpool history -li zfs-root&amp;quot; to see a log of commands.&lt;br /&gt;
&lt;br /&gt;
Once again, you can do away with the import and export commands by trying to have /etc/zfs/zpool.cache inside your initrd. To create zpool.cache, while on the installer or in the rescue shell of the initrd (at lilo &amp;quot;boot: vmlinuz rescue&amp;quot;), import only the pool for the root fs with mountpoint=none and readonly=on properties set and while it is not mounted:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on installer or initrd rescue shell)&lt;br /&gt;
cp /etc/zfs/zpool.cache /etc/zfs/zpool.cache-initrd&lt;br /&gt;
zfs set readonly=off zfs-root&lt;br /&gt;
mount zfs-pool&lt;br /&gt;
cp /etc/zfs/zpool.cache-initrd /mnt/etc/zfs/&lt;br /&gt;
cp /mnt/etc/zfs/zpool.cache-initrd /mnt/boot/initrd-tree/etc/zfs/zpool.cache&lt;br /&gt;
umount /mnt&lt;br /&gt;
zfs set readonly=on zfs-root&lt;br /&gt;
#mount zfs-root&lt;br /&gt;
#exit (to continue boot process onto rootfs mounted at /mnt)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, doing this zpool.cache approach is not necessary, and some talk suggests this is deprecated or discouraged. Although /etc/hostid setup fails to import without -f option, ip-based (hosts|dns) hostid works on booting and import works without -f option and may be the more proper way to do shutdown and startup rather than using a cache file which could be come invalid and cause a problem that is difficult to understand. The contents and exact function of the cache file are not well understood by many people.&lt;br /&gt;
&lt;br /&gt;
Save /boot/initrd-tree/init and exit.&lt;br /&gt;
&lt;br /&gt;
Now, edit /etc/rc.d/rc.S and rc.6 to understand how to &amp;quot;remount&amp;quot; rw or ro as a readonly property changes&lt;br /&gt;
&lt;br /&gt;
In /etc/rc.d/rc.S:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# comment out the line&lt;br /&gt;
#    /sbin/mount -w -v -n -o remount /&lt;br /&gt;
#add the line&lt;br /&gt;
     /sbin/zfs set readonly=off zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In /etc/rc.d/rc.6&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# comment out the line&lt;br /&gt;
#    /bin/mount -v -n -o remount,ro /&lt;br /&gt;
#add the line&lt;br /&gt;
     /sbin/zfs set readonly=on zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In /etc/rc.d/rc.6, near the bottom just before poweroff|reboot, add the following block of lines:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
########################&lt;br /&gt;
# Try to export zfs-root&lt;br /&gt;
/sbin/zpool export zfs-root&lt;br /&gt;
if [ $? -gt 0 ] ; then&lt;br /&gt;
 echo &amp;quot;ZFS export failed.&amp;quot;&lt;br /&gt;
 echo &amp;quot;Notice: if root fs is busy, then this is normal fail.&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;ZFS export successful.&amp;quot;&lt;br /&gt;
 echo &amp;quot;Warning: successful export is abnormal for root fs.&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
/bin/sleep 5&lt;br /&gt;
########################&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
For ZFS, you cannot run fsck on it. It doesn't support that kind of filesystem checks. The rc.S script will complain a lot in many places about not being about to run fsck on the zfs-root. To disable all attempts of run fsck, we can simple create a file that acts as a flag in /etc/rc.d/rc.S to tell it to skip fsck:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
touch /etc/fastboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This fastboot file is normally a run-once temporary file, and it is deleted near the bottom inside rc.S. Edit rc.S and stop it from deleting /etc/fastboot. We would like it to always skip all fsck. Edit /etc/rc.d/rc.S, and find the &amp;quot;rm&amp;quot; of fastboot, and do not have it removed!&lt;br /&gt;
&lt;br /&gt;
We are getting close, and have finished all editing, so make /boot/initrd.gz and install lilo:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkinitrd -F&lt;br /&gt;
lilo&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We finished! All that's left to do is clean up.&lt;br /&gt;
&lt;br /&gt;
Exit the chroot.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
exit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Try to mount everything:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
umount /mnt/proc&lt;br /&gt;
umount /mnt/sys&lt;br /&gt;
umount /mnt/dev&lt;br /&gt;
umount /mnt/boot&lt;br /&gt;
umount /mnt/mnt/cdrom&lt;br /&gt;
umount /mnt/root/packages&lt;br /&gt;
umount /mnt&lt;br /&gt;
zpool export zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note, that export stops a pool and frees devices, while import binds devices and starts a pool. It is somewhat like mdadm -A -s and mdadm -S -s, while /etc/zfs/zpool.cache might be somewhat like mdadm -E -s &amp;gt; /etc/mdadm.conf.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Remove the DVD or change boot order&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When you reboot, if all is good, you are booting properly onto a slackware installed on a ZFS root! Congrat!&lt;br /&gt;
&lt;br /&gt;
If this seem to go badly, and this might happen if the import fails as explain some before, then you will be on the initrd's rescue command line just before the part in it's init where it wants to mount and switch_root to boot your root. Instead, you typically got commands like this to do:&lt;br /&gt;
&lt;br /&gt;
If you get dumped to rescue because import will not work and requires -f (force), then:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 zpool import -f zfs-root&lt;br /&gt;
 zpool export    zfs-root&lt;br /&gt;
 zpool import    zfs-root&lt;br /&gt;
 mount zfs-root&lt;br /&gt;
 exit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This can happen if hostname, hostid, or uname changes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you get into a jam and need to boot into the initrd and skip zfs import etc, use the lilo prompt (or, boot the install-dvd):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
boot: vmlinuz rescue&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the rescue mode of the initrd, after you have mounted your root as readonly=on to /mnt, then exit to continue.&lt;br /&gt;
&lt;br /&gt;
In other emergency modes, you might need to run the lines at end of init starting from: &amp;lt;code&amp;gt;udevadm info --cleanup-db; udevadm control --exit&amp;lt;/code&amp;gt;&lt;br /&gt;
If you don't run those udevadm commands, two runs of udevd fight each other and it is slow; you have to wait 2 minutes twice for timeouts (4 minutes).&lt;br /&gt;
The last line is run is: &amp;lt;code&amp;gt;exec switch_root /mnt /sbin/init 1&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Warning... this switch_root command is kind of dangerous, so read the manual page about it.&lt;br /&gt;
From what I can tell, everything except the new root &amp;quot;/mnt&amp;quot; is deleted, so you are giving a command that says what NOT to delete!&lt;br /&gt;
Make sure nothing got mounted outside of &amp;quot;/mnt&amp;quot; before you run it.&lt;br /&gt;
&lt;br /&gt;
Also, in rescue or anytime you have finished making changes and are about to reboot in some abnormal mode, first run:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set readonly=on zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A bug in unpatched grep 2.13 build 1, found slackware 14.0rc1, causes problems when processing files stored on ZFS but rarely shows problems on other filesystems; the bug does not handle sparse files on zfs and btrfs correctly and results in chaos with slackpkg, compiling kernel modules, and possibly many other things. You must downgrade grep to 2.12 or use the patched grep 2.13 build 2 in slackware 14.0rc2 or later.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Upgrading.&lt;br /&gt;
&lt;br /&gt;
From time to time you will want to upgrade the kernel to the new kernel in slackware64-current or in patches/. This will also necessitate a rebuilt and reinstall or upgrade of spl and zfs. Below is an example of when both kernel and spl/zfs are being upgraded, to give an idea of the process:&lt;br /&gt;
&lt;br /&gt;
Using slackpkg, that is configured to use your local slackware mirror is a good option but you can also configure it to use a remote mirror.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slackpkg upgrade-all&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Assume slackpkg just upgraded your kernel, kernel-modules, and kernel-headers.&lt;br /&gt;
&lt;br /&gt;
Note: the first time you try to run on kernel-generic, setup kernel-huge in lilo as 2nd choice. Huge has all the hard drive controllers builtin, but generic has them all as modules. For example, run &amp;quot;modinfo mptsas&amp;quot; to see module options (maybe you have a LSISAS1068) for your hard drive controller. Add file /etc/modprobe.d/mptsas.conf to set options you want with a line: options mptsas ... Do this for all the device driver modules for your hardware. Do this setup while you are on the huge kernel, then setup to reboot to generic. Include all these modules you need into mkinitrd.conf MODULES_LIST. Check that /boot/initrd-tree/etc/modprobe.d/ has a copy of your customized module conf files because it is on the initrd where the modules will load and use the conf files. mkinitrd probably copies all /etc/modprobe.d/* files into the initrd-tree, but check it. Pay attention to /etc/modprobe.d/README and /lib/modprobe.d/* /lib/modprobe.d/* maybe not copied to initrd-tree but you might want to copy some of it into your initrd-tree yourself to use them.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Check that upgraded kernel-source is symlinked to /usr/src/linux (zfs build looks here). SQL/ZFS modules will install to the kernel version in /lib/modules/&amp;lt;/usr/src/linux kernel version&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /usr/local/src&lt;br /&gt;
tar xvzf ~/spl-*.tar.gz&lt;br /&gt;
tar xvzf ~/zfs-*.tar.gz&lt;br /&gt;
&lt;br /&gt;
###### upgrade spl 1st&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-*&lt;br /&gt;
./configure --prefix=/ --libexecdir=/usr/libexec --libdir=/lib64 --includedir=/usr/include --datarootdir=/usr/share&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=/usr/local/src/install&lt;br /&gt;
cd ../install&lt;br /&gt;
makepkg ../spl-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
upgradepkg spl-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
depmod &amp;lt;new kernel version&amp;gt;     (e.g. depmod 3.2.27, if .27 is new kernel upgrade; you currently run on old, maybe .26)&lt;br /&gt;
# this builds the module dependencies in /lib/modules/&amp;lt;new kernel version&amp;gt;&lt;br /&gt;
###### upgrade zfs 2nd&lt;br /&gt;
mkdir install&lt;br /&gt;
cd zfs-*&lt;br /&gt;
./configure --prefix=/ --libexecdir=/usr/libexec --libdir=/lib64 --includedir=/usr/include --datarootdir=/usr/share&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=/usr/local/src/install&lt;br /&gt;
cd ../install&lt;br /&gt;
makepkg ../zfs-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
upgradepkg zfs-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
depmod 3.2.27&lt;br /&gt;
####### upgrade spl/zfs inside altroot /boot/initrd-tree&lt;br /&gt;
ROOT=/boot/initrd-tree upgradepkg spl-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
ROOT=/boot/initrd-tree upgradepkg zfs-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
# note: ROOT is an environment variable, not a command line option to upgradepkg!&lt;br /&gt;
# note: do not worry about depmod inside initrd-tree, mkinitrd -F actually installs the modules&lt;br /&gt;
# note: this upgrade here is really to just upgrade the command line tools zpool, zfs etc&lt;br /&gt;
####### rebuild /boot/initrd.gz and reinstall lilo&lt;br /&gt;
vi /etc/mkinitrd.conf&lt;br /&gt;
# temporarily set KERNEL_VERSION to new version, but you are still running on old version&lt;br /&gt;
mkinitrd -F&lt;br /&gt;
lilo&lt;br /&gt;
vi /etc/mkinitrd.conf&lt;br /&gt;
# you can set KERNEL_VERSION back to $(uname r) now&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After reboot you can remove any old /lib/modules/&amp;lt;old kernel version&amp;gt; directory.&lt;br /&gt;
&lt;br /&gt;
More about /etc/hostid. If you want to experiment changing your /etc/hostid file and seeing if you can use it and make zpool import work normally, here is a tool that might be helpful:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/* software product name: foobarz-chhostid.c&lt;br /&gt;
 * suggested binary name: chhostid&lt;br /&gt;
 * license              : BSD&lt;br /&gt;
 * license text:&lt;br /&gt;
Copyright (c) 2012, foobarz&lt;br /&gt;
All rights reserved.&lt;br /&gt;
&lt;br /&gt;
Redistribution and use in source and binary forms, with or without&lt;br /&gt;
modification, are permitted provided that the following conditions are met:&lt;br /&gt;
    * Redistributions of source code must retain the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer.&lt;br /&gt;
    * Redistributions in binary form must reproduce the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer in the&lt;br /&gt;
      documentation and/or other materials provided with the distribution.&lt;br /&gt;
    * Neither the name of the &amp;lt;organization&amp;gt; nor the&lt;br /&gt;
      names of its contributors may be used to endorse or promote products&lt;br /&gt;
      derived from this software without specific prior written permission.&lt;br /&gt;
&lt;br /&gt;
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &amp;quot;AS IS&amp;quot; AND&lt;br /&gt;
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED&lt;br /&gt;
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE&lt;br /&gt;
DISCLAIMED. IN NO EVENT SHALL &amp;lt;COPYRIGHT HOLDER&amp;gt; BE LIABLE FOR ANY&lt;br /&gt;
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES&lt;br /&gt;
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;&lt;br /&gt;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND&lt;br /&gt;
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT&lt;br /&gt;
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS&lt;br /&gt;
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#define FOOBARZ_CHHOSTID_VERSION &amp;quot;1.0.5&amp;quot;&lt;br /&gt;
#include &amp;lt;sys/socket.h&amp;gt;&lt;br /&gt;
#include &amp;lt;netinet/in.h&amp;gt;&lt;br /&gt;
#include &amp;lt;arpa/inet.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;endian.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sysexits.h&amp;gt;&lt;br /&gt;
/* note: if include stdlib then sethostid fails even with _BSD_SOURCE defined */&lt;br /&gt;
&lt;br /&gt;
long swapbytes(long abcd) {&lt;br /&gt;
  long badc;&lt;br /&gt;
  unsigned char addr_a;&lt;br /&gt;
  unsigned char addr_b;&lt;br /&gt;
  unsigned char addr_c;&lt;br /&gt;
  unsigned char addr_d;&lt;br /&gt;
  addr_a = (unsigned char) (abcd &amp;gt;&amp;gt; 24);&lt;br /&gt;
  addr_b = (unsigned char) (abcd &amp;gt;&amp;gt; 16);&lt;br /&gt;
  addr_c = (unsigned char) (abcd &amp;gt;&amp;gt;  8);&lt;br /&gt;
  addr_d = (unsigned char) (abcd);&lt;br /&gt;
  return badc = ( (addr_b &amp;lt;&amp;lt; 24) | (addr_a &amp;lt;&amp;lt; 16) | (addr_d &amp;lt;&amp;lt; 8) | addr_c );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[])&lt;br /&gt;
{&lt;br /&gt;
 long newhostid;&lt;br /&gt;
 struct in_addr addr;&lt;br /&gt;
 char* invalidchar;&lt;br /&gt;
&lt;br /&gt;
 /*********** check command line */&lt;br /&gt;
 if(!( ((argc==3) &amp;amp;&amp;amp; ( (strcmp(argv[1],&amp;quot;-h&amp;quot;)==0) ||&lt;br /&gt;
                       (strcmp(argv[1],&amp;quot;-i&amp;quot;)==0) ||&lt;br /&gt;
                       (strcmp(argv[1],&amp;quot;-l&amp;quot;)==0) )) ||&lt;br /&gt;
       ((argc==2) &amp;amp;&amp;amp; ( (strcmp(argv[1],&amp;quot;-s&amp;quot;)==0) ))&lt;br /&gt;
     )&lt;br /&gt;
   ) {&lt;br /&gt;
                 /*01234567890123456789012345678901234567890123456789012345678901234567890123456789*/&lt;br /&gt;
  fprintf(stderr, &amp;quot;foobarz-chhostid, version %s. License: BSD.\n&amp;quot;, FOOBARZ_CHHOSTID_VERSION);&lt;br /&gt;
  fprintf(stderr, &amp;quot;foobarz-chhostid, (c) 2012, foobarz; all rights reserved.\n&amp;quot;);&lt;br /&gt;
  fprintf(stderr, &amp;quot;descr: %s change system hostid (in /etc/hostid).\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -h &amp;lt;new hostid&amp;gt;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        Change system hostid to &amp;lt;new hostid&amp;gt;;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        &amp;lt;new hostid&amp;gt; must be 32bit 8-digit hex number xxxxxxxx, each x in 0-f|F.\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        The ip corresponding to &amp;lt;new hostid&amp;gt; is also listed for reference only.\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -i &amp;lt;dotted ip address&amp;gt;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        Change system hostid to hostid corresponding to &amp;lt;dotted ip address&amp;gt;.\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -l &amp;lt;dotted ip address&amp;gt;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        List hostid corresponding to &amp;lt;dotted ip address&amp;gt;;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        no change to system hostid.\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -s\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        List current system hostid and corresponding ip address;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        no change to system hostid.\n&amp;quot;, argv[0]);&lt;br /&gt;
  return EX_USAGE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -h &amp;lt;hostid&amp;gt; */&lt;br /&gt;
 if( strcmp(argv[1],&amp;quot;-h&amp;quot;) == 0 ) {&lt;br /&gt;
  if(strlen(argv[2]) != 8) { fprintf(stderr, &amp;quot;new hostid must be 8-digit hex number xxxxxxxx, each x in 0-f|F\n&amp;quot;); return EX_USAGE; }&lt;br /&gt;
&lt;br /&gt;
  newhostid = strtol(argv[2],&amp;amp;invalidchar,16);&lt;br /&gt;
  if( newhostid==LONG_MIN ) { perror(&amp;quot;strtol (underflow)&amp;quot;); return EX_USAGE; }&lt;br /&gt;
  if( newhostid==LONG_MAX ) { perror(&amp;quot;strtol (overflow)&amp;quot;); return EX_USAGE; }&lt;br /&gt;
  if(*invalidchar != '\0') { fprintf(stderr, &amp;quot;invalid hex number %c; must be in 0-f|F\n&amp;quot;, *invalidchar); return EX_USAGE; }&lt;br /&gt;
&lt;br /&gt;
  if( sethostid(newhostid) != 0 ) {&lt;br /&gt;
   perror(&amp;quot;sethostid&amp;quot;);&lt;br /&gt;
   if( errno == EPERM ) return EX_NOPERM;&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
  }&lt;br /&gt;
  printf(&amp;quot;System hostid changed.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  /* hostid is a byte-swapped ip like b.a.d.c */&lt;br /&gt;
  /* get ip by swapping to correct order a.b.c.d and save into in_addr struct */&lt;br /&gt;
  addr.s_addr = htonl(swapbytes(newhostid));&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -i or -l, then find hostid for &amp;lt;dotted ip address&amp;gt; */&lt;br /&gt;
 if( (strcmp(argv[1],&amp;quot;-i&amp;quot;) == 0) || (strcmp(argv[1],&amp;quot;-l&amp;quot;) == 0) ) {&lt;br /&gt;
  if( inet_aton(argv[2], &amp;amp;addr) == 0 ) { fprintf(stderr, &amp;quot;inet_aton: invalid dotted ip address: %s\n&amp;quot;, argv[2]); return EX_USAGE; }&lt;br /&gt;
&lt;br /&gt;
  /* hostid is a byte-swapped ip like b.a.d.c */&lt;br /&gt;
  /* get hostid by swapping bytes of ip a.b.c.d */&lt;br /&gt;
  newhostid = swapbytes(ntohl(addr.s_addr));&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -i &amp;lt;dotted ip address&amp;gt; */&lt;br /&gt;
 if( strcmp(argv[1],&amp;quot;-i&amp;quot;) == 0 ) {&lt;br /&gt;
  if( sethostid(newhostid) != 0 ) {&lt;br /&gt;
   perror(&amp;quot;sethostid&amp;quot;);&lt;br /&gt;
   if( errno == EPERM ) return EX_NOPERM;&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
  }&lt;br /&gt;
  printf(&amp;quot;System hostid changed.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -l &amp;lt;dotted ip address&amp;gt; */&lt;br /&gt;
 if(strcmp(argv[1],&amp;quot;-l&amp;quot;) == 0 ) {&lt;br /&gt;
   printf(&amp;quot;Listing hostid for ip. (no changes)\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -s */&lt;br /&gt;
 if(strcmp(argv[1],&amp;quot;-s&amp;quot;) == 0 ) {&lt;br /&gt;
   /* see if /etc/hostid exists and print info */&lt;br /&gt;
   if( access(&amp;quot;/etc/hostid&amp;quot;, F_OK) != 0 ) {&lt;br /&gt;
     printf(&amp;quot;Notice: /etc/hostid does not exist.\n&amp;quot;);&lt;br /&gt;
     perror(&amp;quot;Reason&amp;quot;);&lt;br /&gt;
     printf(&amp;quot;System hostid derived from ip of hostname found in hosts file or dns.\n&amp;quot;);&lt;br /&gt;
   } else {&lt;br /&gt;
     printf(&amp;quot;Notice: /etc/hostid exists.\n&amp;quot;&lt;br /&gt;
            &amp;quot;System hostid is obtained from hostid file.\n&amp;quot;);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
  errno=0;&lt;br /&gt;
  newhostid = gethostid();&lt;br /&gt;
  if(errno!=0) { perror(&amp;quot;gethostid&amp;quot;); return EX_UNAVAILABLE; }&lt;br /&gt;
&lt;br /&gt;
  /* hostid is a byte-swapped ip like b.a.d.c */&lt;br /&gt;
  /* get ip by swapping to correct order a.b.c.d and save into in_addr struct */&lt;br /&gt;
  addr.s_addr = htonl(swapbytes(newhostid));&lt;br /&gt;
&lt;br /&gt;
  printf(&amp;quot;Listing current system hostid. (no changes)\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** print info and return */&lt;br /&gt;
 printf(&amp;quot;ip dot: %s\n&amp;quot;, inet_ntoa(addr) );&lt;br /&gt;
 printf(&amp;quot;ip hex: %.8x\n&amp;quot;, ntohl(addr.s_addr) );&lt;br /&gt;
 printf(&amp;quot;hostid: %.8x\n&amp;quot;, newhostid );&lt;br /&gt;
 return EX_OK;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now available! &amp;quot;ZFS root (builtin)&amp;quot; wiki (aka &amp;quot;ZFS root, part II&amp;quot;):&lt;br /&gt;
http://slackwiki.com/ZFS_root_(builtin)&lt;br /&gt;
It is now possible to build the modules and a small initramfs into your kernel to have a fully-contained and bootable ZFS root kernel from a simple lilo entry. Good luck!&lt;/div&gt;</description>
			<pubDate>Mon, 03 Sep 2012 19:18:14 GMT</pubDate>
			<dc:creator>Foobarz</dc:creator>
			<comments>https://www.slackwiki.com/Talk:ZFS_root</comments>
		</item>
		<item>
			<title>ZFS root (builtin)</title>
			<link>https://www.slackwiki.com/index.php?title=ZFS_root_(builtin)&amp;diff=779</link>
			<guid isPermaLink="false">https://www.slackwiki.com/index.php?title=ZFS_root_(builtin)&amp;diff=779</guid>
			<description>&lt;p&gt;Foobarz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Tutorials]]&lt;br /&gt;
The first &amp;quot;ZFS root&amp;quot; wiki explains the details of running ZFS at your root filesystem by using a fully modular generic kernel approach. Now, I can share how it can be done with the SPL and ZFS modules built into the kernel. This procedure is just an example and can use some fine tuning, but here goes:&lt;br /&gt;
&lt;br /&gt;
The steps below are to create kernel with SPL and ZFS modules builtin. This kernel will be installed as an alternatve kernel to boot in lilo, and it will have a separate kernel installation from the fully modular and working system kernel. This will allow testing the builtin kernel while able to boot back onto a working modular ZFS system. We start this procedure assuming you are on a working fully modular ZFS install as in the &amp;quot;ZFS root&amp;quot; wiki.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=legacy zfs-root&lt;br /&gt;
# use legacy so zfs will not expect zfs mount, but instead expect standard mount for this fs&lt;br /&gt;
# edit /etc/rc.d/rc.S and rc.6 to use regular &amp;quot;mount&amp;quot; commands, remove &amp;quot;zfs&amp;quot; commands&lt;br /&gt;
# edit rc.6 and remove or comment out zfs export command&lt;br /&gt;
zpool set bootfs=zfs-root zfs-root&lt;br /&gt;
# this may help, but not really sure&lt;br /&gt;
&lt;br /&gt;
mkdir /boot/initramfs-source&lt;br /&gt;
# this will hold some files for rootfs inside kernel&lt;br /&gt;
&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir src&lt;br /&gt;
cd src&lt;br /&gt;
tar xvzf /mnt/cdrom/slackware64/k/kernel-source-*.txz&lt;br /&gt;
mv usr/src/linux-3.2.27 /usr/src/linux-3.2.27b&lt;br /&gt;
rm -r install&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make menuconfig&lt;br /&gt;
  General setup-&amp;gt;Local version - append to kernel release = b&lt;br /&gt;
  General setup-&amp;gt;Default hostname                         = slackzfs&lt;br /&gt;
  General setup-&amp;gt;Initramfs source files(s)                = /boot/initramfs-source&lt;br /&gt;
  #  make usre you made this directory or the kernel build fails&lt;br /&gt;
  Device Drivers-&amp;gt;SCSI device support-&amp;gt;SCSI low-level drivers-&amp;gt; &amp;lt;*&amp;gt; SYM53C8XX Version 2 SCSI support&lt;br /&gt;
  #  for qemu if=scsi -option-rom 8xx_64.rom,bootindex=1  hard disks&lt;br /&gt;
  # buildin any hard drive controllers etc that you need&lt;br /&gt;
  File systems -&amp;gt; &amp;lt;*&amp;gt; The Extended 4 (ext4) filesystem&lt;br /&gt;
  # /boot may use this ext4 fs&lt;br /&gt;
make prepare scripts&lt;br /&gt;
# this make command is what the spl and zfs copy-builtin scripts expect to be done before they are run&lt;br /&gt;
&lt;br /&gt;
cd ~/src&lt;br /&gt;
tar xvzf ~/spl-0.6.0-rc10.tar.gz&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-0.6.0-rc10&lt;br /&gt;
./configure \&lt;br /&gt;
    --prefix=/ \&lt;br /&gt;
    --libdir=/lib64 \&lt;br /&gt;
    --includedir=/usr/include \&lt;br /&gt;
    --datarootdir=/usr/share \&lt;br /&gt;
    --enable-linux-builtin=yes \&lt;br /&gt;
    --with-linux=/usr/src/linux-3.2.27b \&lt;br /&gt;
    --with-linux-obj=/usr/src/linux-3.2.27b&lt;br /&gt;
wget https://raw.github.com/zfsonlinux/spl/master/copy-builtin&lt;br /&gt;
chmod +x copy-builtin&lt;br /&gt;
./copy-builtin /usr/src/linux-3.2.27b&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../spl-0.6.0rc10_3.2.27b-x86_64-1root.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
&lt;br /&gt;
tar xvzf ~/zfs-0.6.0-rc10.tar.gz&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-0.6.0-rc10&lt;br /&gt;
./configure \&lt;br /&gt;
    --prefix=/ \&lt;br /&gt;
    --libdir=/lib64 \&lt;br /&gt;
    --includedir=/usr/include \&lt;br /&gt;
    --datarootdir=/usr/share \&lt;br /&gt;
    --enable-linux-builtin=yes \&lt;br /&gt;
    --with-linux=/usr/src/linux-3.2.27b \&lt;br /&gt;
    --with-linux-obj=/usr/src/linux-3.2.27b \&lt;br /&gt;
    --with-spl=/root/src/spl-0.6.0-rc10&lt;br /&gt;
wget https://raw.github.com/zfsonlinux/zfs/master/copy-builtin&lt;br /&gt;
chmod +x copy-builtin&lt;br /&gt;
./copy-builtin /usr/src/linux-3.2.27b&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../zfs-0.6.0rc10_3.2.27b-x86_64-1root.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
&lt;br /&gt;
### move zfs and spl modules inside kernel source to be at end of drivers:&lt;br /&gt;
### the order builtin modules init is the order they link into the kernel&lt;br /&gt;
### and we need zfs to init after all hard drive controllers&lt;br /&gt;
### zfs is more like a device driver layer over the lower-level hba drivers&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
mkdir drivers/zfsonlinux&lt;br /&gt;
mv spl drivers/zfsonlinux&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  # remove references to spl&lt;br /&gt;
vi Makefile&lt;br /&gt;
  # remove references to spl&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/fs&lt;br /&gt;
mv zfs ../drivers/zfsonlinux&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  # remove references to zfs&lt;br /&gt;
vi Makefile&lt;br /&gt;
  # remove references to zfs&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  )# add line at end of menu, before &amp;quot;endmenu&amp;quot;:&lt;br /&gt;
  )source &amp;quot;drivers/zfsonlinux/Kconfig&amp;quot;&lt;br /&gt;
  )endmenu&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers&lt;br /&gt;
vi Makefile&lt;br /&gt;
  )# add line at very end of file:&lt;br /&gt;
  )obj-$(CONFIG_ZFSONLINUX) += zfsonlinux/&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers/zfsonlinux&lt;br /&gt;
cat &amp;gt; Kconfig &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
menuconfig ZFSONLINUX&lt;br /&gt;
	tristate &amp;quot;ZFSonLinux support&amp;quot;&lt;br /&gt;
&lt;br /&gt;
if ZFSONLINUX&lt;br /&gt;
&lt;br /&gt;
source &amp;quot;drivers/zfsonlinux/spl/Kconifg&amp;quot;&lt;br /&gt;
&lt;br /&gt;
source &amp;quot;drivers/zfsonlinux/zfs/Kconifg&amp;quot;&lt;br /&gt;
&lt;br /&gt;
endif&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/zfsonlinux&lt;br /&gt;
cat &amp;gt; Makefile &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
obj-$(CONFIG_SPL) += spl/&lt;br /&gt;
obj-$(CONFIG_ZFS) += zfs/&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
### move complete&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make menuconfig&lt;br /&gt;
   Device Drivers -&amp;gt;&lt;br /&gt;
    &amp;lt;*&amp;gt; ZFSonLinux support -&amp;gt;&lt;br /&gt;
      &amp;lt;*&amp;gt; Solaris Porting Layer (SPL)&lt;br /&gt;
      &amp;lt;*&amp;gt;     ZFS&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
### prepare contents of initramfs&lt;br /&gt;
cd /boot/initramfs-source&lt;br /&gt;
&lt;br /&gt;
# make standard directories&lt;br /&gt;
mkdir -p proc dev sys mnt bin sbin etc/zfs&lt;br /&gt;
&lt;br /&gt;
# zfs seems to want mtab present, even if empty&lt;br /&gt;
touch etc/mtab&lt;br /&gt;
&lt;br /&gt;
# if zpool.cache file can be read by zfs at module init, it imports the pools in the cache&lt;br /&gt;
cp /etc/zfs/zpool.cache-initrd etc/zfs/zpool.cache&lt;br /&gt;
&lt;br /&gt;
# make initial console device node; otherwise, there is a problem at startup:&lt;br /&gt;
# &amp;quot;Warning: unable to open an initial console&amp;quot; and you'd have problems with console and tty login&lt;br /&gt;
# making these nodes from within /init is not early enough to avoid problem&lt;br /&gt;
mknod dev/console c 5 1   # system console&lt;br /&gt;
&lt;br /&gt;
# make memory device kmsg to &amp;quot;printk&amp;quot; kernel messages&lt;br /&gt;
# we can write to this file to send out messages&lt;br /&gt;
mknod dev/kmsg    c 1 11  # lines printed to kmsg enter kernel messages buffer&lt;br /&gt;
&lt;br /&gt;
# recommended loop0 device to mount fs images&lt;br /&gt;
mknod dev/loop0   b 7 0&lt;br /&gt;
&lt;br /&gt;
# make initial virtual terminal devices&lt;br /&gt;
mknod dev/tty     c 5 0   # current tty&lt;br /&gt;
mknod dev/tty0    c 4 0   # current virtual term&lt;br /&gt;
mknod dev/tty1    c 4 1   # login virtual term 1 (F1)&lt;br /&gt;
&lt;br /&gt;
# make alternative console=ttyS0 standard 8250/16550 UART serial port devices&lt;br /&gt;
#   useful with kernel parameter console=ttyS0&lt;br /&gt;
#          with qemu -nographic -option-rom sgabios.bin,bootindex=0&lt;br /&gt;
mknod dev/ttyS0   c 4 64  # COM1&lt;br /&gt;
mknod dev/ttyS1   c 4 65  # COM2&lt;br /&gt;
mknod dev/ttyS2   c 4 66  # COM3&lt;br /&gt;
mknod dev/ttyS3   c 4 67  $ COM4&lt;br /&gt;
&lt;br /&gt;
# this should be enough device nodes initially&lt;br /&gt;
# once devtmpfs mounts over /dev, a lot more is available in it by default&lt;br /&gt;
&lt;br /&gt;
cat &amp;gt; /init &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot; &amp;lt;some initial program PID=1 for the system to start on&amp;gt; EOF&lt;br /&gt;
# an initramfs-source/init program is required to mount and boot a root linux system&lt;br /&gt;
# the common way to make /init is using busybox with files like this:&lt;br /&gt;
#    /bin/busybox&lt;br /&gt;
#    /bin/ash -&amp;gt; busybox&lt;br /&gt;
#    /bin/sh -&amp;gt; busybox&lt;br /&gt;
#    # run busybox to see what other &amp;quot;applets&amp;quot; can be symlinked to it&lt;br /&gt;
#    # when busybox is run as a different symlinked applet name, it runs the applet&lt;br /&gt;
#    /init&lt;br /&gt;
#    # init is ash script, see slackware's /boot/initrd-tree/init for example&lt;br /&gt;
#    Inside this script:&lt;br /&gt;
#      1) parse kernel parameters passed into it and set variables based on them&lt;br /&gt;
#      2) start udevd and trigger rules for block devices to setup initial /dev devices&lt;br /&gt;
#      3) load kernel modules and keyboard map&lt;br /&gt;
#      4) run mdadm, cryptsetup, lvm, zpool/zfs to setup more devices&lt;br /&gt;
#         (any udev rules for them should do more /dev setup in the background)&lt;br /&gt;
#      5) mount the root filesystem read-only at /mnt&lt;br /&gt;
#      6) stat /mnt/sbin/init, and if not executable run a rescue shell /bin/sh&lt;br /&gt;
#      7) shutdown udevd so it can be restarted by root system when booted&lt;br /&gt;
#      8) mount --move {proc,sys,run,dev} to under /mnt&lt;br /&gt;
#      9) run: exec switch_root /mnt /sbin/init $RUNLEVEL&lt;br /&gt;
#    The slackware mkinitrd package is fully configured busybox installation&lt;br /&gt;
#      for an extern file initramfs initrd.gz image outside the kernel.&lt;br /&gt;
#    It could be changed to be inside the kernel easily by just using initrd-tree&lt;br /&gt;
#      as target of INITRAMFS_SOURCE in the kernel config and removing initrd in lilo.&lt;br /&gt;
&lt;br /&gt;
# Because the zfs modules are builtin, we really don't need busybox and the whole&lt;br /&gt;
# mkinitrd package. All we need to do is mount the zfs that is already imported&lt;br /&gt;
# because the zpool.cache is present in rootfs when the zfs module initializes, and&lt;br /&gt;
# then we do the switch root procedure to boot up on the mounted system.&lt;br /&gt;
# udevd rules will still be run when the root system starts udevd.&lt;br /&gt;
&lt;br /&gt;
# So, let's make a simple /init c program that will be all that we really need:&lt;br /&gt;
cat &amp;gt; init.c &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
/* software product name: foobarz-init.c&lt;br /&gt;
 * suggested binary name: /init (in initramfs-source, rootfs)&lt;br /&gt;
 * license              : BSD&lt;br /&gt;
 * license text:&lt;br /&gt;
Copyright (c) 2012, foobarz&lt;br /&gt;
All rights reserved.&lt;br /&gt;
&lt;br /&gt;
Redistribution and use in source and binary forms, with or without&lt;br /&gt;
modification, are permitted provided that the following conditions are met:&lt;br /&gt;
    * Redistributions of source code must retain the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer.&lt;br /&gt;
    * Redistributions in binary form must reproduce the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer in the&lt;br /&gt;
      documentation and/or other materials provided with the distribution.&lt;br /&gt;
    * Neither the name of the &amp;lt;organization&amp;gt; nor the&lt;br /&gt;
      names of its contributors may be used to endorse or promote products&lt;br /&gt;
      derived from this software without specific prior written permission.&lt;br /&gt;
&lt;br /&gt;
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &amp;quot;AS IS&amp;quot; AND&lt;br /&gt;
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED&lt;br /&gt;
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE&lt;br /&gt;
DISCLAIMED. IN NO EVENT SHALL &amp;lt;COPYRIGHT HOLDER&amp;gt; BE LIABLE FOR ANY&lt;br /&gt;
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES&lt;br /&gt;
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;&lt;br /&gt;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND&lt;br /&gt;
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT&lt;br /&gt;
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS&lt;br /&gt;
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#define FOOBARZ_INIT_VERSION &amp;quot;1.0.10rc1&amp;quot;&lt;br /&gt;
#define _BSD_SOURCE&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdarg.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/stat.h&amp;gt;&lt;br /&gt;
#include &amp;lt;fcntl.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/mount.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sysexits.h&amp;gt;&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define PARAM_REQ_NO 0&lt;br /&gt;
#define PARAM_REQ_YES 1&lt;br /&gt;
#define PARAM_SRC_DEFAULT 0&lt;br /&gt;
#define PARAM_SRC_CMDLINE 1&lt;br /&gt;
&lt;br /&gt;
/* Your initramfs-source should contain the following&lt;br /&gt;
 * cd /boot/initramfs-source&lt;br /&gt;
 * mkdir -p proc dev sys mnt bin sbin etc/zfs&lt;br /&gt;
 * touch etc/mtab&lt;br /&gt;
 * cp /etc/zfs/zpool.cache-initrd etc/zfs/zpool.cache&lt;br /&gt;
 * mknod dev/console c 5 1   # system console&lt;br /&gt;
 * mknod dev/kmsg    c 1 11  # lines printed to kmsg enter kernel messages buffer&lt;br /&gt;
 * mknod dev/loop0   b 7 0&lt;br /&gt;
 * mknod dev/tty     c 5 0   # current tty&lt;br /&gt;
 * mknod dev/tty0    c 4 0   # current virtual term&lt;br /&gt;
 * mknod dev/tty1    c 4 1   # login virtual term 1 (F1)&lt;br /&gt;
 * mknod dev/ttyS0   c 4 64  # COM1&lt;br /&gt;
 * mknod dev/ttyS1   c 4 65  # COM2&lt;br /&gt;
 * mknod dev/ttyS2   c 4 66  # COM3&lt;br /&gt;
 * mknod dev/ttyS3   c 4 67  $ COM4&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
void printk(char *fmt, ...) {&lt;br /&gt;
  FILE* f;&lt;br /&gt;
  int fd;&lt;br /&gt;
  va_list args;&lt;br /&gt;
&lt;br /&gt;
  f = fopen(&amp;quot;/dev/kmsg&amp;quot;, &amp;quot;w&amp;quot;);&lt;br /&gt;
  va_start(args, fmt);&lt;br /&gt;
  vfprintf(f, fmt, args);&lt;br /&gt;
  va_end(args);&lt;br /&gt;
  fflush(f);&lt;br /&gt;
  fclose(f);&lt;br /&gt;
  /* avoid flooding kmsg and having msgs suppressed; 20msgs/sec */&lt;br /&gt;
  usleep(50000);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[]) {&lt;br /&gt;
 /*** variables */&lt;br /&gt;
&lt;br /&gt;
 int i;&lt;br /&gt;
 int   fd = 0; /* file descriptor */&lt;br /&gt;
 unsigned long mountflags;&lt;br /&gt;
&lt;br /&gt;
 /* kernel command line */&lt;br /&gt;
 off_t cmdline_size;&lt;br /&gt;
 char* cmdline; /* to be malloc 4096B */&lt;br /&gt;
 char* cmdline_end;&lt;br /&gt;
 char* temp_end;&lt;br /&gt;
 char* src_msg; /* default or cmdline */&lt;br /&gt;
 int flag_param_missing = 0;&lt;br /&gt;
&lt;br /&gt;
 /* use to hold contents of a misc /proc/&amp;lt;file&amp;gt; */&lt;br /&gt;
 char* miscproc_buff; /* to be malloc 4096B */&lt;br /&gt;
 off_t miscproc_size;&lt;br /&gt;
&lt;br /&gt;
 /* note about environ, argv, and kernel cmdline for init:&lt;br /&gt;
  *   environ is not defined for init&lt;br /&gt;
  *   only argv[0] is set for init&lt;br /&gt;
  *   kernel command line parameters are accessed&lt;br /&gt;
  *   at /proc/cmdline&lt;br /&gt;
  */&lt;br /&gt;
&lt;br /&gt;
 /* kernel parameters expected to be name=value */&lt;br /&gt;
 /* do not use quotes or spaces in parameters   */&lt;br /&gt;
 /* you can add more params somwhere after root= */&lt;br /&gt;
 struct nv { char* n; char* v; char* v_end; int req; int src; };&lt;br /&gt;
 struct nv param[] = {&lt;br /&gt;
   { &amp;quot;root=&amp;quot;,       NULL, NULL, PARAM_REQ_YES, PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;rootfstype=&amp;quot;, NULL, NULL, PARAM_REQ_YES, PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;mountopt=&amp;quot;,   NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;init=&amp;quot;,       NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;runlevel=&amp;quot;,   NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;console=&amp;quot;,    NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT }&lt;br /&gt;
 };&lt;br /&gt;
 enum { iroot, irootfstype, imountopt, iinit, irunlevel, iconsole, ilastparam };&lt;br /&gt;
&lt;br /&gt;
 /*** program */&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;foobarz-init, version %s: booting initramfs.\n&amp;quot;, FOOBARZ_INIT_VERSION);&lt;br /&gt;
&lt;br /&gt;
 cmdline       = (char*) malloc(4096);&lt;br /&gt;
 miscproc_buff = (char*) malloc(4096);&lt;br /&gt;
 if( (cmdline == NULL) || (miscproc_buff == NULL) ) {&lt;br /&gt;
   printk(&amp;quot;Unable to allocate buffer memory: malloc: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount proc /proc&lt;br /&gt;
  *  note: some /dev devices symlink into /proc&lt;br /&gt;
  *  proc contains info about processes, including cmdline etc. */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount proc /proc\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;proc&amp;quot;, &amp;quot;/proc&amp;quot;, &amp;quot;proc&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
   printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
   printk(&amp;quot;Mount proc successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount devtmpfs /dev&lt;br /&gt;
  *  note: This simple init program works if your root device is made from devices&lt;br /&gt;
  *  that are available by default in devtmpfs, such as /dev/sd*&lt;br /&gt;
  *&lt;br /&gt;
  *  For zfs, your root zfs pool should be created with default device nodes and&lt;br /&gt;
  *  then it should be mountable by this simple init program.&lt;br /&gt;
  *&lt;br /&gt;
  *  udev may be needed to configure device nodes and symlinks required&lt;br /&gt;
  *  to access a root device configuration made with such nodes and symlinks.&lt;br /&gt;
  *  If you need udevd, you can include it into your initramfs-source and&lt;br /&gt;
  *  modify this program to run it before attempting to mount your root device.&lt;br /&gt;
  *  However, if udevd is needed, a significant number of userspace programs may also be&lt;br /&gt;
  *  required by rules in /lib/udev/. You could install busybox + udev (about 5MB) or&lt;br /&gt;
  *  coreutils + util-linux + bash + udev (about 25MB) into initramfs-source. But, at that&lt;br /&gt;
  *  point you'd have ash or bash and many tools that are easier to use than this&lt;br /&gt;
  *  simple init program; it would then be easy to have /init as #!/bin/&amp;lt;b&amp;gt;ash script. */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount devtmpfs /dev\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;devtmpfs&amp;quot;, &amp;quot;/dev&amp;quot;, &amp;quot;devtmpfs&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
   printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
   printk(&amp;quot;Mount devtmpfs successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount sysfs /sys&lt;br /&gt;
  *  note: some kernel modules try to access /sys with userspace helpers to echo values into /sys variables;&lt;br /&gt;
  *  such modules expect a minimal userspace that contains coreutils or busybox */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount sysfs /sys\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;sysfs&amp;quot;, &amp;quot;/sys&amp;quot;, &amp;quot;sysfs&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
   printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
   printk(&amp;quot;Mount sysfs successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* process kernel command line */&lt;br /&gt;
 fd = open(&amp;quot;/proc/cmdline&amp;quot;, O_RDONLY);&lt;br /&gt;
 if( fd == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Cannot open /proc/cmdline: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 /* note, on /proc fs:&lt;br /&gt;
  *       lseek likely always returns error&lt;br /&gt;
  *       stat likely always returns st_size = 0&lt;br /&gt;
  *   so determining size of /proc file means just reading it;&lt;br /&gt;
  *   you have to read /proc files according to their documented&lt;br /&gt;
  *   maximum sizes; this is probably for performance reasons */&lt;br /&gt;
 cmdline_size = read(fd, cmdline, 4095);&lt;br /&gt;
 if( cmdline_size == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Failed to read /proc/cmdline: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 close(fd);&lt;br /&gt;
&lt;br /&gt;
 /* cmdline may be newline + null terminated, but make it null + null */&lt;br /&gt;
 cmdline[cmdline_size] = '\0';&lt;br /&gt;
 if( cmdline[cmdline_size-1] == '\n' ) {&lt;br /&gt;
   cmdline[cmdline_size-1] = '\0';&lt;br /&gt;
   cmdline_size--;&lt;br /&gt;
   cmdline_end = cmdline + cmdline_size;&lt;br /&gt;
 }&lt;br /&gt;
 printk(&amp;quot;Kernel cmdline size: %i\n&amp;quot;, cmdline_size);&lt;br /&gt;
 printk(&amp;quot;Kernel cmdline: \&amp;quot;%s\&amp;quot;\n&amp;quot;, cmdline);&lt;br /&gt;
&lt;br /&gt;
 /* find v and v_end of values in cmdline */&lt;br /&gt;
 for( i=iroot; i&amp;lt;ilastparam; i++ ) {&lt;br /&gt;
   param[i].v = strstr(cmdline, param[i].n);&lt;br /&gt;
   if( param[i].v != NULL ) {&lt;br /&gt;
     param[i].src = PARAM_SRC_CMDLINE;&lt;br /&gt;
     while( *(param[i].v) != '=' ) param[i].v++;&lt;br /&gt;
     param[i].v++;&lt;br /&gt;
     temp_end = param[i].v;&lt;br /&gt;
     while( !( (*temp_end == ' ') ||&lt;br /&gt;
               (*temp_end == '\n') ||&lt;br /&gt;
               (temp_end == cmdline_end)&lt;br /&gt;
	     ) ) temp_end++;&lt;br /&gt;
     if( temp_end == param[i].v ) {&lt;br /&gt;
       printk(&amp;quot;Kernel parameter %s: value missing.\n&amp;quot;, param[i].n);&lt;br /&gt;
       param[i].v = NULL;&lt;br /&gt;
     } else param[i].v_end = temp_end;&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 for( i=iroot; i&amp;lt;ilastparam; i++ ) {&lt;br /&gt;
   /* terminate value strings */&lt;br /&gt;
   if( param[i].v_end != NULL ) *(param[i].v_end) = '\0';&lt;br /&gt;
   /* set defaults if no value on cmdline */&lt;br /&gt;
   if( param[i].v == NULL ) {&lt;br /&gt;
     param[i].src = PARAM_SRC_DEFAULT;&lt;br /&gt;
     if( param[i].req == PARAM_REQ_YES ) flag_param_missing = 1;&lt;br /&gt;
     switch(i) {&lt;br /&gt;
       case iroot      : param[i].v = &amp;quot;&amp;lt;missing required param&amp;gt;&amp;quot; ; break;&lt;br /&gt;
       case irootfstype: param[i].v = &amp;quot;&amp;lt;missing required param&amp;gt;&amp;quot; ; break;&lt;br /&gt;
       case imountopt  : param[i].v = &amp;quot;ro&amp;quot;        ; break;&lt;br /&gt;
       case iinit      : param[i].v = &amp;quot;/sbin/init&amp;quot;; break;&lt;br /&gt;
       case irunlevel  : param[i].v = &amp;quot;3&amp;quot;         ; break;&lt;br /&gt;
       case iconsole   : param[i].v = &amp;quot;console&amp;quot;   ; break;&lt;br /&gt;
       default         : param[i].v = &amp;quot;&amp;quot;;&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
   if(param[i].src == PARAM_SRC_DEFAULT) src_msg = &amp;quot;default&amp;quot;;&lt;br /&gt;
   else src_msg = &amp;quot;cmdline&amp;quot;;&lt;br /&gt;
   printk(&amp;quot;Using %s \&amp;quot;%s\&amp;quot; (source: %s)\n&amp;quot;, param[i].n, param[i].v, src_msg);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 if( flag_param_missing ) {&lt;br /&gt;
   printk(&amp;quot;Aborting boot process: missing required kernel parameter(s).\n&amp;quot;);&lt;br /&gt;
   return EX_USAGE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* generic nv pair kernel cmdline processing finished&lt;br /&gt;
  *  now, examine specific params for defaults and correctness */&lt;br /&gt;
&lt;br /&gt;
 /* param[irootfstype]: can be checked against /proc/filesystems: */&lt;br /&gt;
 fd = open(&amp;quot;/proc/filesystems&amp;quot;, O_RDONLY);&lt;br /&gt;
 if( fd == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Cannot open /proc/filesystems: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 miscproc_size = read(fd, miscproc_buff, 4095);&lt;br /&gt;
 if( miscproc_size == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Failed to read /proc/filesystems: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 close(fd);&lt;br /&gt;
 if( strstr(miscproc_buff, param[irootfstype].v) == NULL ) {&lt;br /&gt;
   printk(&amp;quot;%s \&amp;quot;%s\&amp;quot;: filesystem type not available.\n&amp;quot;, param[irootfstype].n, param[irootfstype].v);&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* zfs-specific informative checks */&lt;br /&gt;
 if( strcmp(param[irootfstype].v, &amp;quot;zfs&amp;quot;) == 0 ) {&lt;br /&gt;
   if( access(&amp;quot;/etc/zfs/zpool.cache&amp;quot;, F_OK) == 0 )&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/zfs/zpool.cache is present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
   else&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/zfs/zpool.cache not present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
&lt;br /&gt;
   if( access(&amp;quot;/etc/hostid&amp;quot;, F_OK) == 0 )&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/hostid is present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
   else&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/hostid not present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 if(      strcmp(param[imountopt].v, &amp;quot;ro&amp;quot;) == 0 ) mountflags = MS_RDONLY;&lt;br /&gt;
 else if( strcmp(param[imountopt].v, &amp;quot;rw&amp;quot;) == 0 ) mountflags = 0;&lt;br /&gt;
 else {&lt;br /&gt;
   printk(&amp;quot;%s \&amp;quot;%s\&amp;quot;: invalid parameter value; defaulting to \&amp;quot;ro\&amp;quot;.\n&amp;quot;, param[imountopt].n, param[imountopt].v);&lt;br /&gt;
   mountflags = MS_RDONLY;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* param[iroot]: nothing to check; if user gives bad root=device then mount fails */&lt;br /&gt;
&lt;br /&gt;
 /* try to mount root=device at /mnt&lt;br /&gt;
  *&lt;br /&gt;
  * note: for zfs, if a copy of /etc/zfs/zpool.cache (when pool is imported) is put in initramfs-source, then&lt;br /&gt;
  * the zfs module can read it and automatically import the pools described in the cache file; the imported&lt;br /&gt;
  * pools can be available to mount here if they were created using standard device names, otherwise&lt;br /&gt;
  * udevd may be required to run before mounting the pool */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount -t %s -o %s %s /mnt.\n&amp;quot;, param[irootfstype].v, param[imountopt].v, param[iroot].v);&lt;br /&gt;
 if( mount(param[iroot].v, &amp;quot;/mnt&amp;quot;, param[irootfstype].v, mountflags, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 printk(&amp;quot;%s mounted successfully.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
&lt;br /&gt;
 /* check to see if the mounted root filesystem has an executable init program */&lt;br /&gt;
 chdir(&amp;quot;/mnt&amp;quot;);&lt;br /&gt;
 if( access(param[iinit].v+1, X_OK) != 0 ) {&lt;br /&gt;
   chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
   printk(&amp;quot;access X_OK: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   printk(&amp;quot;The init program /mnt/%s is not present or not executable.\n&amp;quot;, param[iinit].v+1);&lt;br /&gt;
   printk(&amp;quot;Aborting boot process: no init program.\n&amp;quot;);&lt;br /&gt;
   printk(&amp;quot;Unmounting %s.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
   if( umount(&amp;quot;/mnt&amp;quot;) == -1 ) {&lt;br /&gt;
     printk(&amp;quot;umount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
     printk(&amp;quot;Failed to umount %s.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
   } else printk(&amp;quot;Successfully unmounted %s.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
 printk(&amp;quot;Init program /mnt/%s is present and executable.\n&amp;quot;, param[iinit].v+1);&lt;br /&gt;
&lt;br /&gt;
 /* switch the root / from initramfs to the mounted new root device at /mnt.&lt;br /&gt;
  *&lt;br /&gt;
  * note: after this switch, it is not possible to access the initramfs files anymore,&lt;br /&gt;
  * yet they consume ram memory unless they are deleted here before switching.&lt;br /&gt;
  * Any programs that are run after clearing the initramfs and switching root must exist on the new root.&lt;br /&gt;
  * This program may safely delete itself (/init) since it is already in ram and executing.&lt;br /&gt;
  * If you have installed additional files and programs in initramfs that consume significant ram,&lt;br /&gt;
  * then you need to insert additional code here to delete those files (carefully). */&lt;br /&gt;
&lt;br /&gt;
 /* delete files off of initramfs to free ram memory */&lt;br /&gt;
 printk(&amp;quot;Freeing memory from initramfs...\n&amp;quot;);&lt;br /&gt;
 if( unlink(argv[0]) != 0 ) printk(&amp;quot;unlink %s: %s\n&amp;quot;, argv[0], strerror(errno));&lt;br /&gt;
 else printk(&amp;quot;%s %s&amp;quot;, argv[0], &amp;quot;deleted from initramfs.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 /* switch root */&lt;br /&gt;
 printk(&amp;quot;Beginning switch root procedure.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(1) Attempting cmd: mount --move /dev /mnt/dev \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/dev&amp;quot;, &amp;quot;/mnt/dev&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(2) Attempting cmd: mount --move /proc /mnt/proc \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/proc&amp;quot;, &amp;quot;/mnt/proc&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(3) Attempting cmd: mount --move /sys /mnt/sys \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/sys&amp;quot;, &amp;quot;/mnt/sys&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(4) Attempting cmd: chdir /mnt \n&amp;quot;);&lt;br /&gt;
 if( chdir(&amp;quot;/mnt&amp;quot;) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: chdir: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(5) Attempting cmd: mount --move . / \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;.&amp;quot;, &amp;quot;/&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(6) Attempting cmd: chroot . \n&amp;quot;);&lt;br /&gt;
 if( chroot(&amp;quot;.&amp;quot;) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: chroot: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(7) Attempting cmd: chdir / \n&amp;quot;);&lt;br /&gt;
 if( chdir(&amp;quot;/&amp;quot;) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: chdir: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 printk(&amp;quot;Completed switch root procedure.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 /* check for &amp;quot;console=&amp;quot; kernel parameter and switch&lt;br /&gt;
  *  stdin, stdout, and stderr to named console device&lt;br /&gt;
  */&lt;br /&gt;
 if( param[iconsole].src == PARAM_SRC_CMDLINE ) {&lt;br /&gt;
   printk(&amp;quot;Console redirection to device %s requested.\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
   /* expect only basename of console device (e.g., ttyS0), so chdir /dev */&lt;br /&gt;
   chdir(&amp;quot;/dev&amp;quot;);&lt;br /&gt;
   if( access(param[iconsole].v, F_OK ) == 0 ) {&lt;br /&gt;
     printk(&amp;quot;Opening stdin, stdout, and stderr on %s.\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
     close(0);&lt;br /&gt;
     open(param[iconsole].v, O_RDWR);&lt;br /&gt;
     dup2(0, 1);&lt;br /&gt;
     dup2(0, 2);&lt;br /&gt;
   } else {&lt;br /&gt;
     printk(&amp;quot;access F_OK: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
     printk(&amp;quot;Could not access device: %s!\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
     printk(&amp;quot;Console redirection to device %s aborted!\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
   }&lt;br /&gt;
   chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;Execing: \&amp;quot;%s %s\&amp;quot; to boot mounted root system.\n&amp;quot;, param[iinit].v, param[irunlevel].v);&lt;br /&gt;
&lt;br /&gt;
 /* free resources held to this point */&lt;br /&gt;
 free(cmdline);&lt;br /&gt;
 free(miscproc_buff);&lt;br /&gt;
&lt;br /&gt;
 if( execl(param[iinit].v, param[irunlevel].v, (char *) NULL ) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: execl: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
EOF&lt;br /&gt;
## end of rootfs /init&lt;br /&gt;
&lt;br /&gt;
gcc --static init.c -o init&lt;br /&gt;
strip init&lt;br /&gt;
&lt;br /&gt;
## build and install kernel&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make -j8&lt;br /&gt;
make -j8 modules_install&lt;br /&gt;
cp arch/x86/boot/bzImage /boot/vm3.2.27b&lt;br /&gt;
cp System.map /boot/System.map-vm3.2.27b&lt;br /&gt;
# add new lilo menu entry for vm3.2.27b kernel&lt;br /&gt;
vi /etc/lilo.conf&lt;br /&gt;
  image = /boot/vm3.2.27b&lt;br /&gt;
   label = vm3.2.27b&lt;br /&gt;
   addappend = &amp;quot; spl.spl_hostid=0x007f0100 zfs.spa_config_path=/etc/zfs/zpool.cache root=zfs-root rootfstype=zfs&amp;quot;&lt;br /&gt;
lilo&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notes on kernel params (lilo append and addappend lines): root= and rootfstype= are used by both foorbarz-init and mkinitrd. The &amp;quot;ro&amp;quot; param is not used by foobarz-init, so instead use: mountopt=ro|rw. See &amp;quot;modinfo spl&amp;quot; and &amp;quot;modinfo zfs&amp;quot; to see all of the options those modules can take on the kernel command line.&lt;br /&gt;
&lt;br /&gt;
Notes on the spl and zfs packages to install: If you have errors using zfs and zpool commands on booted system with builtin modules, then upgrade/switch to the 0.6.0rc10_3.2.27b builds, or you can make a custom package with the binaries renamed like zpoolb, zfsb etc for builtin.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
Using qemu's -nographic serial console (/usr/share/qemu/sgabios.bin): If you have a boot problem, you might want to run in qemu's -nographic console mode:&lt;br /&gt;
&lt;br /&gt;
First, edit /etc/inittab, and uncomment the line for local serial ports runlevel &amp;quot;s1&amp;quot; (ttyS0) for serial console login support. This is done in the guest (host does not need this):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Local serial lines:&lt;br /&gt;
s1:12345:respawn:/sbin/agetty -L ttyS0 38400 linux&lt;br /&gt;
#s1:12345:respawn:/sbin/agetty -L ttyS0 9600 vt100&lt;br /&gt;
#s2:12345:respawn:/sbin/agetty -L ttyS1 9600 vt100&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Second, edit /etc/securetty, and uncomment ttyS0 line:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ttyS0&lt;br /&gt;
#ttyS1&lt;br /&gt;
# ...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
You cannot login on ttyS0 without this change even though you get the login prompt!&lt;br /&gt;
&lt;br /&gt;
Then, run qemu such as:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
qemu-kvm &amp;lt;all regular options&amp;gt; -nographic -option-rom sgabios.bin,bootindex=0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Wait for the lilo prompt, it may take several seconds show up in this mode.&lt;br /&gt;
&lt;br /&gt;
In the lilo menu, select your kernel image with builtin spl/zfs, and use kernel params such as:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
boot: vm3.2.27b console=ttyS0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
At the lilo prompt, use kernel parameter: console=ttyS0 (do NOT say /dev/ttS0). Passing runlevel=s1 does not appear to be necessary.&lt;br /&gt;
&lt;br /&gt;
When you are in qemu's serial mode, the interface is a little different than in the normal graphical mode: use keypresses:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ctrl-a h    # for help&lt;br /&gt;
ctrl-a c    # toggle access to (QEMU) console / back to emulation&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If you cannot get a login: prompt, try ctrl-a c, then do (QEMU) sendkey ctrl-alt-delete. This will reboot cleanly back to lilo, then you can do (QEMU) quit.&lt;br /&gt;
&lt;br /&gt;
Once you login to the guest, the terminal size needs adjustment. On your host, in another xterm sized the same as your guest console terminal, get the size of the terminal:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo $LINES&lt;br /&gt;
echo $COLUMNS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Now, back in the guest terminal of same size:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export LINES &amp;lt;lines&amp;gt;&lt;br /&gt;
export COLUMNS &amp;lt;columns&amp;gt;&lt;br /&gt;
stty cols $COLUMNS rows $LINES&lt;br /&gt;
exec bash&lt;br /&gt;
reset&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
So, you set the environment variables and also set them with stty. Then, restart bash (exec, or else it is a child shell process).&lt;br /&gt;
&lt;br /&gt;
BECAREFUL not to start qemu twice on the same ZFS guest! Two simultaneous running qemu on the same ZFS will corrupt the pool and it will NOT recover - you lose your whole installation! Before running qemu, check ps -A, look for an already running qemu process incase it somehow entered into the background!&lt;br /&gt;
&lt;br /&gt;
BECAREFUL when using -nographic ttyS0 that you are not doing commands on the HOST! Only use -nographic to see kernel problems. Use regular console of booting is working normally.&lt;br /&gt;
&lt;br /&gt;
To use the qemu -drive if=scsi option, the linux module sym53c8xx should be loaded in the guest. You may need to use the qemu option:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-option-rom 8xx_64.rom,bootindex=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The file 8xx_64.rom used to be inside qemu, but in new versions it is missing. You can download it:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
wget http://www.lsi.com/downloads/Public/Host%20Bus%20Adapters/Host%20Bus%20Adapters%20Common%20Files/lsi_bios.zip&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Extract the zip and place 8xx_64.rom in /usr/share/qemu/.&lt;br /&gt;
&lt;br /&gt;
Good luck!&lt;/div&gt;</description>
			<pubDate>Mon, 03 Sep 2012 18:33:43 GMT</pubDate>
			<dc:creator>Foobarz</dc:creator>
			<comments>https://www.slackwiki.com/Talk:ZFS_root_(builtin)</comments>
		</item>
		<item>
			<title>ZFS root (builtin)</title>
			<link>https://www.slackwiki.com/index.php?title=ZFS_root_(builtin)&amp;diff=752</link>
			<guid isPermaLink="false">https://www.slackwiki.com/index.php?title=ZFS_root_(builtin)&amp;diff=752</guid>
			<description>&lt;p&gt;Foobarz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Tutorials]]&lt;br /&gt;
The first &amp;quot;ZFS root&amp;quot; wiki explains the details of running ZFS at your root filesystem by using a fully modular generic kernel approach. Now, I can share how it can be done with the SPL and ZFS modules built into the kernel. This procedure is just an example and can use some fine tuning, but here goes:&lt;br /&gt;
&lt;br /&gt;
The steps below are to create kernel with SPL and ZFS modules builtin. This kernel will be installed as an alternatve kernel to boot in lilo, and it will have a separate installation from the fully modular and working system. This will allow testing the builtin kernel while able to boot back onto a working modular ZFS system. We start this procedure assuming you are on a working fully modular ZFS install as in the &amp;quot;ZFS root&amp;quot; wiki.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=legacy zfs-root&lt;br /&gt;
# use legacy so zfs will not expect zfs mount, but instead expect standard mount for this fs&lt;br /&gt;
# edit /etc/rc.d/rc.S and rc.6 to use regular &amp;quot;mount&amp;quot; commands, remove &amp;quot;zfs&amp;quot; commands&lt;br /&gt;
# edit rc.6 and remove or comment out zfs export command&lt;br /&gt;
zpool set bootfs=zfs-root zfs-root&lt;br /&gt;
# this may help, but not really sure&lt;br /&gt;
&lt;br /&gt;
mkdir /boot/initramfs-source&lt;br /&gt;
# this will hold some files for rootfs inside kernel&lt;br /&gt;
&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir src&lt;br /&gt;
cd src&lt;br /&gt;
tar xvzf /mnt/cdrom/slackware64/k/kernel-source-*.txz&lt;br /&gt;
mv usr/src/linux-3.2.27 /usr/src/linux-3.2.27b&lt;br /&gt;
rm -r install&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make menuconfig&lt;br /&gt;
  General setup-&amp;gt;Local version - append to kernel release = b&lt;br /&gt;
  General setup-&amp;gt;Default hostname                         = slackzfs&lt;br /&gt;
  General setup-&amp;gt;Initramfs source files(s)                = /boot/initramfs-source&lt;br /&gt;
  #  make usre you made this directory or the kernel build fails&lt;br /&gt;
  Device Drivers-&amp;gt;SCSI device support-&amp;gt;SCSI low-level drivers-&amp;gt; &amp;lt;*&amp;gt; SYM53C8XX Version 2 SCSI support&lt;br /&gt;
  #  for qemu if=scsi -option-rom 8xx_64.rom,bootindex=1  hard disks&lt;br /&gt;
  # buildin any hard drive controllers etc that you need&lt;br /&gt;
  File systems -&amp;gt; &amp;lt;*&amp;gt; The Extended 4 (ext4) filesystem&lt;br /&gt;
  # /boot may use this ext4 fs&lt;br /&gt;
make prepare scripts&lt;br /&gt;
# this make command is what the spl and zfs copy-builtin scripts expect to be done before they are run&lt;br /&gt;
&lt;br /&gt;
cd ~/src&lt;br /&gt;
tar xvzf ~/spl-0.6.0-rc10.tar.gz&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-0.6.0-rc10&lt;br /&gt;
./configure \&lt;br /&gt;
    --prefix=/ \&lt;br /&gt;
    --libdir=/lib64 \&lt;br /&gt;
    --includedir=/usr/include \&lt;br /&gt;
    --datarootdir=/usr/share \&lt;br /&gt;
    --enable-linux-builtin=yes \&lt;br /&gt;
    --with-linux=/usr/src/linux-3.2.27b \&lt;br /&gt;
    --with-linux-obj=/usr/src/linux-3.2.27b&lt;br /&gt;
wget https://raw.github.com/zfsonlinux/spl/master/copy-builtin&lt;br /&gt;
chmod +x copy-builtin&lt;br /&gt;
./copy-builtin /usr/src/linux-3.2.27b&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../spl-0.6.0rc10_3.2.27b-x86_64-1root.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
&lt;br /&gt;
tar xvzf ~/zfs-0.6.0-rc10.tar.gz&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-0.6.0-rc10&lt;br /&gt;
./configure \&lt;br /&gt;
    --prefix=/ \&lt;br /&gt;
    --libdir=/lib64 \&lt;br /&gt;
    --includedir=/usr/include \&lt;br /&gt;
    --datarootdir=/usr/share \&lt;br /&gt;
    --enable-linux-builtin=yes \&lt;br /&gt;
    --with-linux=/usr/src/linux-3.2.27b \&lt;br /&gt;
    --with-linux-obj=/usr/src/linux-3.2.27b \&lt;br /&gt;
    --with-spl=/root/src/spl-0.6.0-rc10&lt;br /&gt;
wget https://raw.github.com/zfsonlinux/zfs/master/copy-builtin&lt;br /&gt;
chmod +x copy-builtin&lt;br /&gt;
./copy-builtin /usr/src/linux-3.2.27b&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../zfs-0.6.0rc10_3.2.27b-x86_64-1root.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
&lt;br /&gt;
### move zfs and spl modules inside kernel source to be at end of drivers:&lt;br /&gt;
### the order builtin modules init is the order they link into the kernel&lt;br /&gt;
### and we need zfs to init after all hard drive controllers&lt;br /&gt;
### zfs is more like a device driver layer over the lower-level hba drivers&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
mkdir drivers/zfsonlinux&lt;br /&gt;
mv spl drivers/zfsonlinux&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  # remove references to spl&lt;br /&gt;
vi Makefile&lt;br /&gt;
  # remove references to spl&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/fs&lt;br /&gt;
mv zfs ../drivers/zfsonlinux&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  # remove references to zfs&lt;br /&gt;
vi Makefile&lt;br /&gt;
  # remove references to zfs&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  )# add line at end of menu, before &amp;quot;endmenu&amp;quot;:&lt;br /&gt;
  )source &amp;quot;drivers/zfsonlinux/Kconfig&amp;quot;&lt;br /&gt;
  )endmenu&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers&lt;br /&gt;
vi Makefile&lt;br /&gt;
  )# add line at very end of file:&lt;br /&gt;
  )obj-$(CONFIG_ZFSONLINUX) += zfsonlinux/&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers/zfsonlinux&lt;br /&gt;
cat &amp;gt; Kconfig &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
menuconfig ZFSONLINUX&lt;br /&gt;
	tristate &amp;quot;ZFSonLinux support&amp;quot;&lt;br /&gt;
&lt;br /&gt;
if ZFSONLINUX&lt;br /&gt;
&lt;br /&gt;
source &amp;quot;drivers/zfsonlinux/spl/Kconifg&amp;quot;&lt;br /&gt;
&lt;br /&gt;
source &amp;quot;drivers/zfsonlinux/zfs/Kconifg&amp;quot;&lt;br /&gt;
&lt;br /&gt;
endif&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/zfsonlinux&lt;br /&gt;
cat &amp;gt; Makefile &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
obj-$(CONFIG_SPL) += spl/&lt;br /&gt;
obj-$(CONFIG_ZFS) += zfs/&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
### move complete&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make menuconfig&lt;br /&gt;
   Device Drivers -&amp;gt;&lt;br /&gt;
    &amp;lt;*&amp;gt; ZFSonLinux support -&amp;gt;&lt;br /&gt;
      &amp;lt;*&amp;gt; Solaris Porting Layer (SPL)&lt;br /&gt;
      &amp;lt;*&amp;gt;     ZFS&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
### prepare contents of initramfs&lt;br /&gt;
cd /boot/initramfs-source&lt;br /&gt;
&lt;br /&gt;
# make standard directories&lt;br /&gt;
mkdir -p proc dev sys mnt bin sbin etc/zfs&lt;br /&gt;
&lt;br /&gt;
# zfs seems to want mtab present, even if empty&lt;br /&gt;
touch etc/mtab&lt;br /&gt;
&lt;br /&gt;
# if zpool.cache file can be read by zfs at module init, it imports the pools in the cache&lt;br /&gt;
cp /etc/zfs/zpool.cache-initrd etc/zfs/zpool.cache&lt;br /&gt;
&lt;br /&gt;
# make initial console device node; otherwise, there is a problem at startup:&lt;br /&gt;
# &amp;quot;Warning: unable to open an initial console&amp;quot; and you'd have problems with console and tty login&lt;br /&gt;
# making these nodes from within /init is not early enough to avoid problem&lt;br /&gt;
mknod dev/console c 5 1   # system console&lt;br /&gt;
&lt;br /&gt;
# make memory device kmsg to &amp;quot;printk&amp;quot; kernel messages&lt;br /&gt;
# we can write to this file to send out messages&lt;br /&gt;
mknod dev/kmsg    c 1 11  # lines printed to kmsg enter kernel messages buffer&lt;br /&gt;
&lt;br /&gt;
# recommended loop0 device to mount fs images&lt;br /&gt;
mknod dev/loop0   b 7 0&lt;br /&gt;
&lt;br /&gt;
# make initial virtual terminal devices&lt;br /&gt;
mknod dev/tty     c 5 0   # current tty&lt;br /&gt;
mknod dev/tty0    c 4 0   # current virtual term&lt;br /&gt;
mknod dev/tty1    c 4 1   # login virtual term 1 (F1)&lt;br /&gt;
&lt;br /&gt;
# make alternative console=ttyS0 standard 8250/16550 UART serial port devices&lt;br /&gt;
#   useful with kernel parameter console=ttyS0&lt;br /&gt;
#          with qemu -nographic -option-rom sgabios.bin,bootindex=0&lt;br /&gt;
mknod dev/ttyS0   c 4 64  # COM1&lt;br /&gt;
mknod dev/ttyS1   c 4 65  # COM2&lt;br /&gt;
mknod dev/ttyS2   c 4 66  # COM3&lt;br /&gt;
mknod dev/ttyS3   c 4 67  $ COM4&lt;br /&gt;
&lt;br /&gt;
# this should be enough device nodes initially&lt;br /&gt;
# once devtmpfs mounts over /dev, a lot more is available in it by default&lt;br /&gt;
&lt;br /&gt;
cat &amp;gt; /init &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot; &amp;lt;some initial program PID=1 for the system to start on&amp;gt; EOF&lt;br /&gt;
# an initramfs-source/init program is required to mount and boot a root linux system&lt;br /&gt;
# the common way to make /init is using busybox with files like this:&lt;br /&gt;
#    /bin/busybox&lt;br /&gt;
#    /bin/ash -&amp;gt; busybox&lt;br /&gt;
#    /bin/sh -&amp;gt; busybox&lt;br /&gt;
#    # run busybox to see what other &amp;quot;applets&amp;quot; can be symlinked to it&lt;br /&gt;
#    # when busybox is run as a different symlinked applet name, it runs the applet&lt;br /&gt;
#    /init&lt;br /&gt;
#    # init is ash script, see slackware's /boot/initrd-tree/init for example&lt;br /&gt;
#    Inside this script:&lt;br /&gt;
#      1) parse kernel parameters passed into it and set variables based on them&lt;br /&gt;
#      2) start udevd and trigger rules for block devices to setup initial /dev devices&lt;br /&gt;
#      3) load kernel modules and keyboard map&lt;br /&gt;
#      4) run mdadm, cryptsetup, lvm, zpool/zfs to setup more devices&lt;br /&gt;
#         (any udev rules for them should do more /dev setup in the background)&lt;br /&gt;
#      5) mount the root filesystem read-only at /mnt&lt;br /&gt;
#      6) stat /mnt/sbin/init, and if not executable run a rescue shell /bin/sh&lt;br /&gt;
#      7) shutdown udevd so it can be restarted by root system when booted&lt;br /&gt;
#      8) mount --move {proc,sys,run,dev} to under /mnt&lt;br /&gt;
#      9) run: exec switch_root /mnt /sbin/init $RUNLEVEL&lt;br /&gt;
#    The slackware mkinitrd package is fully configured busybox installation&lt;br /&gt;
#      for an extern file initramfs initrd.gz image outside the kernel.&lt;br /&gt;
#    It could be changed to be inside the kernel easily by just using initrd-tree&lt;br /&gt;
#      as target of INITRAMFS_SOURCE in the kernel config and removing initrd in lilo.&lt;br /&gt;
&lt;br /&gt;
# Because the zfs modules are builtin, we really don't need busybox and the whole&lt;br /&gt;
# mkinitrd package. All we need to do is mount the zfs that is already imported&lt;br /&gt;
# because the zpool.cache is present in rootfs when the zfs module initializes, and&lt;br /&gt;
# then we do the switch root procedure to boot up on the mounted system.&lt;br /&gt;
# udevd rules will still be run when the root system starts udevd.&lt;br /&gt;
&lt;br /&gt;
# So, let's make a simple /init c program that will be all that we really need:&lt;br /&gt;
cat &amp;gt; init.c &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
/* software product name: foobarz-init.c&lt;br /&gt;
 * suggested binary name: /init (in initramfs-source, rootfs)&lt;br /&gt;
 * license              : BSD&lt;br /&gt;
 * license text:&lt;br /&gt;
Copyright (c) 2012, foobarz&lt;br /&gt;
All rights reserved.&lt;br /&gt;
&lt;br /&gt;
Redistribution and use in source and binary forms, with or without&lt;br /&gt;
modification, are permitted provided that the following conditions are met:&lt;br /&gt;
    * Redistributions of source code must retain the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer.&lt;br /&gt;
    * Redistributions in binary form must reproduce the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer in the&lt;br /&gt;
      documentation and/or other materials provided with the distribution.&lt;br /&gt;
    * Neither the name of the &amp;lt;organization&amp;gt; nor the&lt;br /&gt;
      names of its contributors may be used to endorse or promote products&lt;br /&gt;
      derived from this software without specific prior written permission.&lt;br /&gt;
&lt;br /&gt;
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &amp;quot;AS IS&amp;quot; AND&lt;br /&gt;
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED&lt;br /&gt;
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE&lt;br /&gt;
DISCLAIMED. IN NO EVENT SHALL &amp;lt;COPYRIGHT HOLDER&amp;gt; BE LIABLE FOR ANY&lt;br /&gt;
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES&lt;br /&gt;
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;&lt;br /&gt;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND&lt;br /&gt;
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT&lt;br /&gt;
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS&lt;br /&gt;
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#define FOOBARZ_INIT_VERSION &amp;quot;1.0.9&amp;quot;&lt;br /&gt;
#define _BSD_SOURCE&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdarg.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/stat.h&amp;gt;&lt;br /&gt;
#include &amp;lt;fcntl.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/mount.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sysexits.h&amp;gt;&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define PARAM_REQ_NO 0&lt;br /&gt;
#define PARAM_REQ_YES 1&lt;br /&gt;
#define PARAM_SRC_DEFAULT 0&lt;br /&gt;
#define PARAM_SRC_CMDLINE 1&lt;br /&gt;
&lt;br /&gt;
/* Your initramfs-source should contain the following&lt;br /&gt;
 * cd /boot/initramfs-source&lt;br /&gt;
 * mkdir -p proc dev sys mnt bin sbin etc/zfs&lt;br /&gt;
 * touch etc/mtab&lt;br /&gt;
 * cp /etc/zfs/zpool.cache-initrd etc/zfs/zpool.cache&lt;br /&gt;
 * mknod dev/console c 5 1   # system console&lt;br /&gt;
 * mknod dev/kmsg    c 1 11  # lines printed to kmsg enter kernel messages buffer&lt;br /&gt;
 * mknod dev/loop0   b 7 0&lt;br /&gt;
 * mknod dev/tty     c 5 0   # current tty&lt;br /&gt;
 * mknod dev/tty0    c 4 0   # current virtual term&lt;br /&gt;
 * mknod dev/tty1    c 4 1   # login virtual term 1 (F1)&lt;br /&gt;
 * mknod dev/ttyS0   c 4 64  # COM1&lt;br /&gt;
 * mknod dev/ttyS1   c 4 65  # COM2&lt;br /&gt;
 * mknod dev/ttyS2   c 4 66  # COM3&lt;br /&gt;
 * mknod dev/ttyS3   c 4 67  $ COM4&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
void printk(char *fmt, ...) {&lt;br /&gt;
  FILE* f;&lt;br /&gt;
  int fd;&lt;br /&gt;
  va_list args;&lt;br /&gt;
&lt;br /&gt;
  f = fopen(&amp;quot;/dev/kmsg&amp;quot;, &amp;quot;w&amp;quot;);&lt;br /&gt;
  va_start(args, fmt);&lt;br /&gt;
  vfprintf(f, fmt, args);&lt;br /&gt;
  va_end(args);&lt;br /&gt;
  fflush(f);&lt;br /&gt;
  fclose(f);&lt;br /&gt;
  /* avoid flooding kmsg and having msgs suppressed; 20msgs/sec */&lt;br /&gt;
  usleep(50000);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[]) {&lt;br /&gt;
 /*** variables */&lt;br /&gt;
&lt;br /&gt;
 int i;&lt;br /&gt;
 int   fd = 0; /* file descriptor */&lt;br /&gt;
 unsigned long mountflags;&lt;br /&gt;
&lt;br /&gt;
 /* kernel command line */&lt;br /&gt;
 off_t cmdline_size;&lt;br /&gt;
 char* cmdline; /* to be malloc 4096B */&lt;br /&gt;
 char* cmdline_end;&lt;br /&gt;
 char* temp_end;&lt;br /&gt;
 char* src_msg; /* default or cmdline */&lt;br /&gt;
 int flag_param_missing = 0;&lt;br /&gt;
&lt;br /&gt;
 /* use to hold contents of a misc /proc/&amp;lt;file&amp;gt; */&lt;br /&gt;
 char* miscproc_buff; /* to be malloc 4096B */&lt;br /&gt;
 off_t miscproc_size;&lt;br /&gt;
&lt;br /&gt;
 /* note about environ, argv, and kernel cmdline for init:&lt;br /&gt;
  *   environ is not defined for init&lt;br /&gt;
  *   only argv[0] is set for init&lt;br /&gt;
  *   kernel command line parameters are accessed&lt;br /&gt;
  *   at /proc/cmdline&lt;br /&gt;
  */&lt;br /&gt;
&lt;br /&gt;
 /* kernel parameters expected to be name=value */&lt;br /&gt;
 /* do not use quotes or spaces in parameters   */&lt;br /&gt;
 /* you can add more params somwhere after root= */&lt;br /&gt;
 struct nv { char* n; char* v; char* v_end; int req; int src; };&lt;br /&gt;
 struct nv param[] = {&lt;br /&gt;
   { &amp;quot;root=&amp;quot;,       NULL, NULL, PARAM_REQ_YES, PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;rootfstype=&amp;quot;, NULL, NULL, PARAM_REQ_YES, PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;mountopt=&amp;quot;,   NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;init=&amp;quot;,       NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;runlevel=&amp;quot;,   NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;console=&amp;quot;,    NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT }&lt;br /&gt;
 };&lt;br /&gt;
 enum { iroot, irootfstype, imountopt, iinit, irunlevel, iconsole, ilastparam };&lt;br /&gt;
&lt;br /&gt;
 /*** program */&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;foobarz-init, version %s: booting initramfs.\n&amp;quot;, FOOBARZ_INIT_VERSION);&lt;br /&gt;
&lt;br /&gt;
 cmdline       = (char*) malloc(4096);&lt;br /&gt;
 miscproc_buff = (char*) malloc(4096);&lt;br /&gt;
 if( (cmdline == NULL) || (miscproc_buff == NULL) ) {&lt;br /&gt;
   printk(&amp;quot;Unable to allocate buffer memory: malloc: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount proc /proc&lt;br /&gt;
  *  note: some /dev devices symlink into /proc&lt;br /&gt;
  *  proc contains info about processes, including cmdline etc. */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount proc /proc\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;proc&amp;quot;, &amp;quot;/proc&amp;quot;, &amp;quot;proc&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
   printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
   printk(&amp;quot;Mount proc successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount devtmpfs /dev&lt;br /&gt;
  *  note: This simple init program works if your root device is made from devices&lt;br /&gt;
  *  that are available by default in devtmpfs, such as /dev/sd*&lt;br /&gt;
  *&lt;br /&gt;
  *  For zfs, your root zfs pool should be created with default device nodes and&lt;br /&gt;
  *  then it should be mountable by this simple init program.&lt;br /&gt;
  *&lt;br /&gt;
  *  udev may be needed to configure device nodes and symlinks required&lt;br /&gt;
  *  to access a root device configuration made with such nodes and symlinks.&lt;br /&gt;
  *  If you need udevd, you can include it into your initramfs-source and&lt;br /&gt;
  *  modify this program to run it before attempting to mount your root device.&lt;br /&gt;
  *  However, if udevd is needed, a significant number of userspace programs may also be&lt;br /&gt;
  *  required by rules in /lib/udev/. You could install busybox + udev (about 5MB) or&lt;br /&gt;
  *  coreutils + util-linux + bash + udev (about 25MB) into initramfs-source. But, at that&lt;br /&gt;
  *  point you'd have ash or bash and many tools that are easier to use than this&lt;br /&gt;
  *  simple init program; it would then be easy to have /init as #!/bin/&amp;lt;b&amp;gt;ash script. */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount devtmpfs /dev\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;devtmpfs&amp;quot;, &amp;quot;/dev&amp;quot;, &amp;quot;devtmpfs&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
   printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
   printk(&amp;quot;Mount devtmpfs successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount sysfs /sys&lt;br /&gt;
  *  note: some kernel modules try to access /sys with userspace helpers to echo values into /sys variables;&lt;br /&gt;
  *  such modules expect a minimal userspace that contains coreutils or busybox */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount sysfs /sys\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;sysfs&amp;quot;, &amp;quot;/sys&amp;quot;, &amp;quot;sysfs&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
   printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
   printk(&amp;quot;Mount sysfs successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* process kernel command line */&lt;br /&gt;
 fd = open(&amp;quot;/proc/cmdline&amp;quot;, O_RDONLY);&lt;br /&gt;
 if( fd == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Cannot open /proc/cmdline: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 /* note, on /proc fs:&lt;br /&gt;
  *       lseek likely always returns error&lt;br /&gt;
  *       stat likely always returns st_size = 0&lt;br /&gt;
  *   so determining size of /proc file means just reading it;&lt;br /&gt;
  *   you have to read /proc files according to their documented&lt;br /&gt;
  *   maximum sizes; this is probably for performance reasons */&lt;br /&gt;
 cmdline_size = read(fd, cmdline, 4095);&lt;br /&gt;
 if( cmdline_size == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Failed to read /proc/cmdline: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 close(fd);&lt;br /&gt;
&lt;br /&gt;
 /* cmdline may be newline + null terminated, but make it null + null */&lt;br /&gt;
 cmdline[cmdline_size] = '\0';&lt;br /&gt;
 if( cmdline[cmdline_size-1] == '\n' ) {&lt;br /&gt;
   cmdline[cmdline_size-1] = '\0';&lt;br /&gt;
   cmdline_size--;&lt;br /&gt;
   cmdline_end = cmdline + cmdline_size;&lt;br /&gt;
 }&lt;br /&gt;
 printk(&amp;quot;Kernel cmdline size: %i\n&amp;quot;, cmdline_size);&lt;br /&gt;
 printk(&amp;quot;Kernel cmdline: \&amp;quot;%s\&amp;quot;\n&amp;quot;, cmdline);&lt;br /&gt;
&lt;br /&gt;
 /* find v and v_end of values in cmdline */&lt;br /&gt;
 for( i=iroot; i&amp;lt;ilastparam; i++ ) {&lt;br /&gt;
   param[i].v = strstr(cmdline, param[i].n);&lt;br /&gt;
   if( param[i].v != NULL ) {&lt;br /&gt;
     param[i].src = PARAM_SRC_CMDLINE;&lt;br /&gt;
     while( *(param[i].v) != '=' ) param[i].v++;&lt;br /&gt;
     param[i].v++;&lt;br /&gt;
     temp_end = param[i].v;&lt;br /&gt;
     while( !( (*temp_end == ' ') ||&lt;br /&gt;
               (*temp_end == '\n') ||&lt;br /&gt;
               (temp_end == cmdline_end)&lt;br /&gt;
	     ) ) temp_end++;&lt;br /&gt;
     if( temp_end == param[i].v ) {&lt;br /&gt;
       printk(&amp;quot;Kernel parameter %s: value missing.\n&amp;quot;, param[i].n);&lt;br /&gt;
       param[i].v = NULL;&lt;br /&gt;
     } else param[i].v_end = temp_end;&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 for( i=iroot; i&amp;lt;ilastparam; i++ ) {&lt;br /&gt;
   /* terminate value strings */&lt;br /&gt;
   if( param[i].v_end != NULL ) *(param[i].v_end) = '\0';&lt;br /&gt;
   /* set defaults if no value on cmdline */&lt;br /&gt;
   if( param[i].v == NULL ) {&lt;br /&gt;
     param[i].src = PARAM_SRC_DEFAULT;&lt;br /&gt;
     if( param[i].req == PARAM_REQ_YES ) flag_param_missing = 1;&lt;br /&gt;
     switch(i) {&lt;br /&gt;
       case iroot      : param[i].v = &amp;quot;&amp;lt;missing required param&amp;gt;&amp;quot; ; break;&lt;br /&gt;
       case irootfstype: param[i].v = &amp;quot;&amp;lt;missing required param&amp;gt;&amp;quot; ; break;&lt;br /&gt;
       case imountopt  : param[i].v = &amp;quot;ro&amp;quot;        ; break;&lt;br /&gt;
       case iinit      : param[i].v = &amp;quot;/sbin/init&amp;quot;; break;&lt;br /&gt;
       case irunlevel  : param[i].v = &amp;quot;3&amp;quot;         ; break;&lt;br /&gt;
       case iconsole   : param[i].v = &amp;quot;console&amp;quot;   ; break;&lt;br /&gt;
       default         : param[i].v = &amp;quot;&amp;quot;;&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
   if(param[i].src == PARAM_SRC_DEFAULT) src_msg = &amp;quot;default&amp;quot;;&lt;br /&gt;
   else src_msg = &amp;quot;cmdline&amp;quot;;&lt;br /&gt;
   printk(&amp;quot;Using %s \&amp;quot;%s\&amp;quot; (source: %s)\n&amp;quot;, param[i].n, param[i].v, src_msg);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 if( flag_param_missing ) {&lt;br /&gt;
   printk(&amp;quot;Aborting boot process: missing required kernel parameter(s).\n&amp;quot;);&lt;br /&gt;
   return EX_USAGE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* generic nv pair kernel cmdline processing finished&lt;br /&gt;
  *  now, examine specific params for defaults and correctness */&lt;br /&gt;
&lt;br /&gt;
 /* param[irootfstype]: can be checked against /proc/filesystems: */&lt;br /&gt;
 fd = open(&amp;quot;/proc/filesystems&amp;quot;, O_RDONLY);&lt;br /&gt;
 if( fd == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Cannot open /proc/filesystems: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 miscproc_size = read(fd, miscproc_buff, 4095);&lt;br /&gt;
 if( miscproc_size == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Failed to read /proc/filesystems: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 close(fd);&lt;br /&gt;
 if( strstr(miscproc_buff, param[irootfstype].v) == NULL ) {&lt;br /&gt;
   printk(&amp;quot;%s \&amp;quot;%s\&amp;quot;: filesystem type not available.\n&amp;quot;, param[irootfstype].n, param[irootfstype].v);&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* zfs-specific informative checks */&lt;br /&gt;
 if( strcmp(param[irootfstype].v, &amp;quot;zfs&amp;quot;) == 0 ) {&lt;br /&gt;
   if( access(&amp;quot;/etc/zfs/zpool.cache&amp;quot;, F_OK) == 0 )&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/zfs/zpool.cache is present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
   else&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/zfs/zpool.cache not present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
&lt;br /&gt;
   if( access(&amp;quot;/etc/hostid&amp;quot;, F_OK) == 0 )&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/hostid is present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
   else&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/hostid not present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 if(      strcmp(param[imountopt].v, &amp;quot;ro&amp;quot;) == 0 ) mountflags = MS_RDONLY;&lt;br /&gt;
 else if( strcmp(param[imountopt].v, &amp;quot;rw&amp;quot;) == 0 ) mountflags = 0;&lt;br /&gt;
 else {&lt;br /&gt;
   printk(&amp;quot;%s \&amp;quot;%s\&amp;quot;: invalid parameter value; defaulting to \&amp;quot;ro\&amp;quot;.\n&amp;quot;, param[imountopt].n, param[imountopt].v);&lt;br /&gt;
   mountflags = MS_RDONLY;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* param[iroot]: nothing to check; if user gives bad root=device then mount fails */&lt;br /&gt;
&lt;br /&gt;
 /* try to mount root=device at /mnt&lt;br /&gt;
  *&lt;br /&gt;
  * note: for zfs, if a copy of /etc/zfs/zpool.cache (when pool is imported) is put in initramfs-source, then&lt;br /&gt;
  * the zfs module can read it and automatically import the pools described in the cache file; the imported&lt;br /&gt;
  * pools can be available to mount here if they were created using standard device names, otherwise&lt;br /&gt;
  * udevd may be required to run before mounting the pool */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount -t %s -o %s %s /mnt.\n&amp;quot;, param[irootfstype].v, param[imountopt].v, param[iroot].v);&lt;br /&gt;
 if( mount(param[iroot].v, &amp;quot;/mnt&amp;quot;, param[irootfstype].v, mountflags, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 printk(&amp;quot;%s mounted successfully.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
&lt;br /&gt;
 /* check to see if the mounted root filesystem has an executable init program */&lt;br /&gt;
 chdir(&amp;quot;/mnt&amp;quot;);&lt;br /&gt;
 if( access(param[iinit].v+1, X_OK) != 0 ) {&lt;br /&gt;
   chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
   printk(&amp;quot;access X_OK: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   printk(&amp;quot;The init program /mnt/%s is not present or not executable.\n&amp;quot;, param[iinit].v+1);&lt;br /&gt;
   printk(&amp;quot;Aborting boot process: no init program.\n&amp;quot;);&lt;br /&gt;
   printk(&amp;quot;Unmounting %s.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
   if( umount(&amp;quot;/mnt&amp;quot;) == -1 ) {&lt;br /&gt;
     printk(&amp;quot;umount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
     printk(&amp;quot;Failed to umount %s.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
   } else printk(&amp;quot;Successfully unmounted %s.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
 printk(&amp;quot;Init program /mnt/%s is present and executable.\n&amp;quot;, param[iinit].v+1);&lt;br /&gt;
&lt;br /&gt;
 /* switch the root / from initramfs to the mounted new root device at /mnt.&lt;br /&gt;
  *&lt;br /&gt;
  * note: after this switch, it is not possible to access the initramfs files anymore,&lt;br /&gt;
  * yet they consume ram memory unless they are deleted here before switching.&lt;br /&gt;
  * Any programs that are run after clearing the initramfs and switching root must exist on the new root.&lt;br /&gt;
  * This program may safely delete itself (/init) since it is already in ram and executing.&lt;br /&gt;
  * If you have installed additional files and programs in initramfs that consume significant ram,&lt;br /&gt;
  * then you need to insert additional code here to delete those files (carefully). */&lt;br /&gt;
&lt;br /&gt;
 /* delete files off of initramfs to free ram memory */&lt;br /&gt;
 printk(&amp;quot;Freeing memory from initramfs...\n&amp;quot;);&lt;br /&gt;
 if( unlink(&amp;quot;/init&amp;quot;) != 0 ) printk(&amp;quot;unlink %s: %s\n&amp;quot;, &amp;quot;/init&amp;quot;, strerror(errno));&lt;br /&gt;
 else printk(&amp;quot;/init %s&amp;quot;, &amp;quot;deleted from initramfs.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 /* switch root */&lt;br /&gt;
 printk(&amp;quot;Beginning switch root procedure.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(1) Attempting cmd: mount --move /dev /mnt/dev \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/dev&amp;quot;, &amp;quot;/mnt/dev&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(2) Attempting cmd: mount --move /proc /mnt/proc \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/proc&amp;quot;, &amp;quot;/mnt/proc&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(3) Attempting cmd: mount --move /sys /mnt/sys \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/sys&amp;quot;, &amp;quot;/mnt/sys&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(4) Attempting cmd: chdir /mnt \n&amp;quot;);&lt;br /&gt;
 if( chdir(&amp;quot;/mnt&amp;quot;) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: chdir: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(5) Attempting cmd: mount --move . / \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;.&amp;quot;, &amp;quot;/&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(6) Attempting cmd: chroot . \n&amp;quot;);&lt;br /&gt;
 if( chroot(&amp;quot;.&amp;quot;) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: chroot: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(7) Attempting cmd: chdir / \n&amp;quot;);&lt;br /&gt;
 if( chdir(&amp;quot;/&amp;quot;) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: chdir: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 printk(&amp;quot;Completed switch root procedure.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 /* check for &amp;quot;console=&amp;quot; kernel parameter and switch&lt;br /&gt;
  *  stdin, stdout, and stderr to named console device&lt;br /&gt;
  */&lt;br /&gt;
 if( param[iconsole].src == PARAM_SRC_CMDLINE ) {&lt;br /&gt;
   printk(&amp;quot;Console redirection to device %s requested.\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
   /* expect only basename of console device (e.g., ttyS0), so chdir /dev */&lt;br /&gt;
   chdir(&amp;quot;/dev&amp;quot;);&lt;br /&gt;
   if( access(param[iconsole].v, F_OK ) == 0 ) {&lt;br /&gt;
     printk(&amp;quot;Opening stdin, stdout, and stderr on %s.\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
     close(0);&lt;br /&gt;
     open(param[iconsole].v, O_RDWR);&lt;br /&gt;
     dup2(0, 1);&lt;br /&gt;
     dup2(0, 2);&lt;br /&gt;
   } else {&lt;br /&gt;
     printk(&amp;quot;access F_OK: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
     printk(&amp;quot;Could not access device: %s!\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
     printk(&amp;quot;Console redirection to device %s aborted!\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
   }&lt;br /&gt;
   chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;Execing: \&amp;quot;%s %s\&amp;quot; to boot mounted root system.\n&amp;quot;, param[iinit].v, param[irunlevel].v);&lt;br /&gt;
&lt;br /&gt;
 /* free resources held to this point */&lt;br /&gt;
 free(cmdline);&lt;br /&gt;
 free(miscproc_buff);&lt;br /&gt;
&lt;br /&gt;
 if( execl(param[iinit].v, param[irunlevel].v, (char *) NULL ) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: execl: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
EOF&lt;br /&gt;
## end of rootfs /init&lt;br /&gt;
&lt;br /&gt;
gcc --static init.c -o init&lt;br /&gt;
strip init&lt;br /&gt;
&lt;br /&gt;
## build and install kernel&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make -j8&lt;br /&gt;
make -j8 modules_install&lt;br /&gt;
cp arch/x86/boot/bzImage /boot/vm3.2.27b&lt;br /&gt;
cp System.map /boot/System.map-vm3.2.27b&lt;br /&gt;
# add new lilo menu entry for vm3.2.27b kernel&lt;br /&gt;
vi /etc/lilo.conf&lt;br /&gt;
  image = /boot/vm3.2.27b&lt;br /&gt;
   label = vm3.2.27b&lt;br /&gt;
   addappend = &amp;quot; spl.spl_hostid=0x007f0100 zfs.spa_config_path=/etc/zfs/zpool.cache root=zfs-root ro rootfstype=zfs rootwait &amp;quot;&lt;br /&gt;
lilo&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notes on kernel params (lilo append and addappend lines): root= and rootfstype= are used by both foorbarz-init and mkinitrd. The &amp;quot;ro&amp;quot; param is not used by foobarz-init, so instead use: mountopt=ro|rw. See &amp;quot;modinfo spl&amp;quot; and &amp;quot;modinfo zfs&amp;quot; to see all of the options those modules can take on the kernel command line.&lt;br /&gt;
&lt;br /&gt;
Notes on the spl and zfs packages to install: If you have errors using zfs and zpool commands on booted system with builtin modules, then upgrade/switch to the 0.6.0rc10_3.2.27b builds, or you can make a custom package with the binaries renamed like zpoolb, zfsb etc for builtin.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
Using qemu's -nographic serial console (/usr/share/qemu/sgabios.bin): If you have a boot problem, you might want to run in qemu's -nographic console mode:&lt;br /&gt;
&lt;br /&gt;
First, edit /etc/inittab, and uncomment the line for local serial ports runlevel &amp;quot;s1&amp;quot; (ttyS0) for serial console login support. This is done in the guest (host does not need this):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Local serial lines:&lt;br /&gt;
s1:12345:respawn:/sbin/agetty -L ttyS0 38400 linux&lt;br /&gt;
#s1:12345:respawn:/sbin/agetty -L ttyS0 9600 vt100&lt;br /&gt;
#s2:12345:respawn:/sbin/agetty -L ttyS1 9600 vt100&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Second, edit /etc/securetty, and uncomment ttyS0 line:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ttyS0&lt;br /&gt;
#ttyS1&lt;br /&gt;
# ...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
You cannot login on ttyS0 without this change even though you get the login prompt!&lt;br /&gt;
&lt;br /&gt;
Then, run qemu such as:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
qemu-kvm &amp;lt;all regular options&amp;gt; -nographic -option-rom sgabios.bin,bootindex=0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Wait for the lilo prompt, it may take several seconds show up in this mode.&lt;br /&gt;
&lt;br /&gt;
In the lilo menu, select your kernel image with builtin spl/zfs, and use kernel params such as:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
boot: vm3.2.27b console=ttyS0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
At the lilo prompt, use kernel parameter: console=ttyS0 (do NOT say /dev/ttS0). Passing runlevel=s1 does not appear to be necessary.&lt;br /&gt;
&lt;br /&gt;
When you are in qemu's serial mode, the interface is a little different than in the normal graphical mode: use keypresses:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ctrl-a h    # for help&lt;br /&gt;
ctrl-a c    # toggle access to (QEMU) console / back to emulation&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If you cannot get a login: prompt, try ctrl-a c, then do (QEMU) sendkey ctrl-alt-delete. This will reboot cleanly back to lilo, then you can do (QEMU) quit.&lt;br /&gt;
&lt;br /&gt;
Once you login to the guest, the terminal size needs adjustment. On your host, in another xterm sized the same as your guest console terminal, get the size of the terminal:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo $LINES&lt;br /&gt;
echo $COLUMNS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Now, back in the guest terminal of same size:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export LINES &amp;lt;lines&amp;gt;&lt;br /&gt;
export COLUMNS &amp;lt;columns&amp;gt;&lt;br /&gt;
stty cols $COLUMNS rows $LINES&lt;br /&gt;
exec bash&lt;br /&gt;
reset&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
So, you set the environment variables and also set them with stty. Then, restart bash (exec, or else it is a child shell process).&lt;br /&gt;
&lt;br /&gt;
BECAREFUL not to start qemu twice on the same ZFS guest! Two simultaneous running qemu on the same ZFS will corrupt the pool and it will NOT recover - you lose your whole installation! Before running qemu, check ps -A, look for an already running qemu process incase it somehow entered into the background!&lt;br /&gt;
&lt;br /&gt;
BECAREFUL when using -nographic ttyS0 that you are not doing commands on the HOST! Only use -nographic to see kernel problems. Use regular console of booting is working normally.&lt;br /&gt;
&lt;br /&gt;
To use the qemu -drive if=scsi option, the linux module sym53c8xx should be loaded in the guest. You may need to use the qemu option:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-option-rom 8xx_64.rom,bootindex=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The file 8xx_64.com used to be inside qemu, but in new versions it is missing. You can download it:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
wget http://www.lsi.com/downloads/Public/Host%20Bus%20Adapters/Host%20Bus%20Adapters%20Common%20Files/lsi_bios.zip&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Extract the zip and place 8xx_64.rom in /usr/share/qemu/.&lt;br /&gt;
&lt;br /&gt;
Good luck!&lt;/div&gt;</description>
			<pubDate>Sat, 25 Aug 2012 15:02:03 GMT</pubDate>
			<dc:creator>Foobarz</dc:creator>
			<comments>https://www.slackwiki.com/Talk:ZFS_root_(builtin)</comments>
		</item>
		<item>
			<title>ZFS root (builtin)</title>
			<link>https://www.slackwiki.com/index.php?title=ZFS_root_(builtin)&amp;diff=751</link>
			<guid isPermaLink="false">https://www.slackwiki.com/index.php?title=ZFS_root_(builtin)&amp;diff=751</guid>
			<description>&lt;p&gt;Foobarz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Tutorials]]&lt;br /&gt;
The first &amp;quot;ZFS root&amp;quot; wiki explains the details of running ZFS at your root filesystem by using a fully modular generic kernel approach. Now, I can share how it can be done with the SPL and ZFS modules built into the kernel. This procedure is just an example and can use some fine tuning, but here goes:&lt;br /&gt;
&lt;br /&gt;
The steps below are to create kernel with SPL and ZFS modules builtin. This kernel will be installed as an alternatve kernel to boot in lilo, and it will have a separate installation from the fully modular and working system. This will allow testing the builtin kernel while able to boot back onto a working modular ZFS system. We start this procedure assuming you are on a working fully modular ZFS install as in the &amp;quot;ZFS root&amp;quot; wiki.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=legacy zfs-root&lt;br /&gt;
# use legacy so zfs will not expect zfs mount, but instead expect standard mount for this fs&lt;br /&gt;
# edit /etc/rc.d/rc.S and rc.6 to use regular &amp;quot;mount&amp;quot; commands, remove &amp;quot;zfs&amp;quot; commands&lt;br /&gt;
# edit rc.6 and remove or comment out zfs export command&lt;br /&gt;
zpool set bootfs=zfs-root zfs-root&lt;br /&gt;
# this may help, but not really sure&lt;br /&gt;
&lt;br /&gt;
mkdir /boot/initramfs-source&lt;br /&gt;
# this will hold some files for rootfs inside kernel&lt;br /&gt;
&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir src&lt;br /&gt;
cd src&lt;br /&gt;
tar xvzf /mnt/cdrom/slackware64/k/kernel-source-*.txz&lt;br /&gt;
mv usr/src/linux-3.2.27 /usr/src/linux-3.2.27b&lt;br /&gt;
rm -r install&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make menuconfig&lt;br /&gt;
  General setup-&amp;gt;Local version - append to kernel release = b&lt;br /&gt;
  General setup-&amp;gt;Default hostname                         = slackzfs&lt;br /&gt;
  General setup-&amp;gt;Initramfs source files(s)                = /boot/initramfs-source&lt;br /&gt;
  #  make usre you made this directory or the kernel build fails&lt;br /&gt;
  Device Drivers-&amp;gt;SCSI device support-&amp;gt;SCSI low-level drivers-&amp;gt; &amp;lt;*&amp;gt; SYM53C8XX Version 2 SCSI support&lt;br /&gt;
  #  for qemu if=scsi -option-rom 8xx_64.rom,bootindex=1  hard disks&lt;br /&gt;
  # buildin any hard drive controllers etc that you need&lt;br /&gt;
  File systems -&amp;gt; &amp;lt;*&amp;gt; The Extended 4 (ext4) filesystem&lt;br /&gt;
  # /boot may use this ext4 fs&lt;br /&gt;
make prepare scripts&lt;br /&gt;
# this make command is what the spl and zfs copy-builtin scripts expect to be done before they are run&lt;br /&gt;
&lt;br /&gt;
cd ~/src&lt;br /&gt;
tar xvzf ~/spl-0.6.0-rc10.tar.gz&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-0.6.0-rc10&lt;br /&gt;
./configure \&lt;br /&gt;
    --prefix=/ \&lt;br /&gt;
    --libdir=/lib64 \&lt;br /&gt;
    --includedir=/usr/include \&lt;br /&gt;
    --datarootdir=/usr/share \&lt;br /&gt;
    --enable-linux-builtin=yes \&lt;br /&gt;
    --with-linux=/usr/src/linux-3.2.27b \&lt;br /&gt;
    --with-linux-obj=/usr/src/linux-3.2.27b&lt;br /&gt;
wget https://raw.github.com/zfsonlinux/spl/master/copy-builtin&lt;br /&gt;
chmod +x copy-builtin&lt;br /&gt;
./copy-builtin /usr/src/linux-3.2.27b&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../spl-0.6.0rc10_3.2.27b-x86_64-1root.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
&lt;br /&gt;
tar xvzf ~/zfs-0.6.0-rc10.tar.gz&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-0.6.0-rc10&lt;br /&gt;
./configure \&lt;br /&gt;
    --prefix=/ \&lt;br /&gt;
    --libdir=/lib64 \&lt;br /&gt;
    --includedir=/usr/include \&lt;br /&gt;
    --datarootdir=/usr/share \&lt;br /&gt;
    --enable-linux-builtin=yes \&lt;br /&gt;
    --with-linux=/usr/src/linux-3.2.27b \&lt;br /&gt;
    --with-linux-obj=/usr/src/linux-3.2.27b \&lt;br /&gt;
    --with-spl=/root/src/spl-0.6.0-rc10&lt;br /&gt;
wget https://raw.github.com/zfsonlinux/zfs/master/copy-builtin&lt;br /&gt;
chmod +x copy-builtin&lt;br /&gt;
./copy-builtin /usr/src/linux-3.2.27b&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../zfs-0.6.0rc10_3.2.27b-x86_64-1root.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
&lt;br /&gt;
### move zfs and spl modules inside kernel source to be at end of drivers:&lt;br /&gt;
### the order builtin modules init is the order they link into the kernel&lt;br /&gt;
### and we need zfs to init after all hard drive controllers&lt;br /&gt;
### zfs is more like a device driver layer over the lower-level hba drivers&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
mkdir drivers/zfsonlinux&lt;br /&gt;
mv spl drivers/zfsonlinux&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  # remove references to spl&lt;br /&gt;
vi Makefile&lt;br /&gt;
  # remove references to spl&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/fs&lt;br /&gt;
mv zfs ../drivers/zfsonlinux&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  # remove references to zfs&lt;br /&gt;
vi Makefile&lt;br /&gt;
  # remove references to zfs&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  )# add line at end of menu, before &amp;quot;endmenu&amp;quot;:&lt;br /&gt;
  )source &amp;quot;drivers/zfsonlinux/Kconfig&amp;quot;&lt;br /&gt;
  )endmenu&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers&lt;br /&gt;
vi Makefile&lt;br /&gt;
  )# add line at very end of file:&lt;br /&gt;
  )obj-$(CONFIG_ZFSONLINUX) += zfsonlinux/&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers/zfsonlinux&lt;br /&gt;
cat &amp;gt; Kconfig &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
menuconfig ZFSONLINUX&lt;br /&gt;
	tristate &amp;quot;ZFSonLinux support&amp;quot;&lt;br /&gt;
&lt;br /&gt;
if ZFSONLINUX&lt;br /&gt;
&lt;br /&gt;
source &amp;quot;drivers/zfsonlinux/spl/Kconifg&amp;quot;&lt;br /&gt;
&lt;br /&gt;
source &amp;quot;drivers/zfsonlinux/zfs/Kconifg&amp;quot;&lt;br /&gt;
&lt;br /&gt;
endif&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/zfsonlinux&lt;br /&gt;
cat &amp;gt; Makefile &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
obj-$(CONFIG_SPL) += spl/&lt;br /&gt;
obj-$(CONFIG_ZFS) += zfs/&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
### move complete&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make menuconfig&lt;br /&gt;
   Device Drivers -&amp;gt;&lt;br /&gt;
    &amp;lt;*&amp;gt; ZFSonLinux support -&amp;gt;&lt;br /&gt;
      &amp;lt;*&amp;gt; Solaris Porting Layer (SPL)&lt;br /&gt;
      &amp;lt;*&amp;gt;     ZFS&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
### prepare contents of initramfs&lt;br /&gt;
cd /boot/initramfs-source&lt;br /&gt;
&lt;br /&gt;
# make standard directories&lt;br /&gt;
mkdir -p proc dev sys mnt bin sbin etc/zfs&lt;br /&gt;
&lt;br /&gt;
# zfs seems to want mtab present, even if empty&lt;br /&gt;
touch etc/mtab&lt;br /&gt;
&lt;br /&gt;
# if zpool.cache file can be read by zfs at module init, it imports the pools in the cache&lt;br /&gt;
cp /etc/zfs/zpool.cache-initrd etc/zfs/zpool.cache&lt;br /&gt;
&lt;br /&gt;
# make initial console device node; otherwise, there is a problem at startup:&lt;br /&gt;
# &amp;quot;Warning: unable to open an initial console&amp;quot; and you'd have problems with console and tty login&lt;br /&gt;
# making these nodes from within /init is not early enough to avoid problem&lt;br /&gt;
mknod dev/console c 5 1   # system console&lt;br /&gt;
&lt;br /&gt;
# make memory device kmsg to &amp;quot;printk&amp;quot; kernel messages&lt;br /&gt;
# we can write to this file to send out messages&lt;br /&gt;
mknod dev/kmsg    c 1 11  # lines printed to kmsg enter kernel messages buffer&lt;br /&gt;
&lt;br /&gt;
# recommended loop0 device to mount fs images&lt;br /&gt;
mknod dev/loop0   b 7 0&lt;br /&gt;
&lt;br /&gt;
# make initial virtual terminal devices&lt;br /&gt;
mknod dev/tty     c 5 0   # current tty&lt;br /&gt;
mknod dev/tty0    c 4 0   # current virtual term&lt;br /&gt;
mknod dev/tty1    c 4 1   # login virtual term 1 (F1)&lt;br /&gt;
&lt;br /&gt;
# make alternative console=ttyS0 standard 8250/16550 UART serial port devices&lt;br /&gt;
#   useful with kernel parameter console=ttyS0&lt;br /&gt;
#          with qemu -nographic -option-rom sgabios.bin,bootindex=0&lt;br /&gt;
mknod dev/ttyS0   c 4 64  # COM1&lt;br /&gt;
mknod dev/ttyS1   c 4 65  # COM2&lt;br /&gt;
mknod dev/ttyS2   c 4 66  # COM3&lt;br /&gt;
mknod dev/ttyS3   c 4 67  $ COM4&lt;br /&gt;
&lt;br /&gt;
# this should be enough device nodes initially&lt;br /&gt;
# once devtmpfs mounts over /dev, a lot more is available in it by default&lt;br /&gt;
&lt;br /&gt;
cat &amp;gt; /init &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot; &amp;lt;some initial program PID=1 for the system to start on&amp;gt; EOF&lt;br /&gt;
# an initramfs-source/init program is required to mount and boot a root linux system&lt;br /&gt;
# the common way to make /init is using busybox with files like this:&lt;br /&gt;
#    /bin/busybox&lt;br /&gt;
#    /bin/ash -&amp;gt; busybox&lt;br /&gt;
#    /bin/sh -&amp;gt; busybox&lt;br /&gt;
#    # run busybox to see what other &amp;quot;applets&amp;quot; can be symlinked to it&lt;br /&gt;
#    # when busybox is run as a different symlinked applet name, it runs the applet&lt;br /&gt;
#    /init&lt;br /&gt;
#    # init is ash script, see slackware's /boot/initrd-tree/init for example&lt;br /&gt;
#    Inside this script:&lt;br /&gt;
#      1) parse kernel parameters passed into it and set variables based on them&lt;br /&gt;
#      2) start udevd and trigger rules for block devices to setup initial /dev devices&lt;br /&gt;
#      3) load kernel modules and keyboard map&lt;br /&gt;
#      4) run mdadm, cryptsetup, lvm, zpool/zfs to setup more devices&lt;br /&gt;
#         (any udev rules for them should do more /dev setup in the background)&lt;br /&gt;
#      5) mount the root filesystem read-only at /mnt&lt;br /&gt;
#      6) stat /mnt/sbin/init, and if not executable run a rescue shell /bin/sh&lt;br /&gt;
#      7) shutdown udevd so it can be restarted by root system when booted&lt;br /&gt;
#      8) mount --move {proc,sys,run,dev} to under /mnt&lt;br /&gt;
#      9) run: exec switch_root /mnt /sbin/init $RUNLEVEL&lt;br /&gt;
#    The slackware mkinitrd package is fully configured busybox installation&lt;br /&gt;
#      for an extern file initramfs initrd.gz image outside the kernel.&lt;br /&gt;
#    It could be changed to be inside the kernel easily by just using initrd-tree&lt;br /&gt;
#      as target of INITRAMFS_SOURCE in the kernel config and removing initrd in lilo.&lt;br /&gt;
&lt;br /&gt;
# Because the zfs modules are builtin, we really don't need busybox and the whole&lt;br /&gt;
# mkinitrd package. All we need to do is mount the zfs that is already imported&lt;br /&gt;
# because the zpool.cache is present in rootfs when the zfs module initializes, and&lt;br /&gt;
# then we do the switch root procedure to boot up on the mounted system.&lt;br /&gt;
# udevd rules will still be run when the root system starts udevd.&lt;br /&gt;
&lt;br /&gt;
# So, let's make a simple /init c program that will be all that we really need:&lt;br /&gt;
cat &amp;gt; init.c &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
/* software product name: foobarz-init.c&lt;br /&gt;
 * suggested binary name: /init (in initramfs-source, rootfs)&lt;br /&gt;
 * license              : BSD&lt;br /&gt;
 * license text:&lt;br /&gt;
Copyright (c) 2012, foobarz&lt;br /&gt;
All rights reserved.&lt;br /&gt;
&lt;br /&gt;
Redistribution and use in source and binary forms, with or without&lt;br /&gt;
modification, are permitted provided that the following conditions are met:&lt;br /&gt;
    * Redistributions of source code must retain the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer.&lt;br /&gt;
    * Redistributions in binary form must reproduce the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer in the&lt;br /&gt;
      documentation and/or other materials provided with the distribution.&lt;br /&gt;
    * Neither the name of the &amp;lt;organization&amp;gt; nor the&lt;br /&gt;
      names of its contributors may be used to endorse or promote products&lt;br /&gt;
      derived from this software without specific prior written permission.&lt;br /&gt;
&lt;br /&gt;
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &amp;quot;AS IS&amp;quot; AND&lt;br /&gt;
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED&lt;br /&gt;
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE&lt;br /&gt;
DISCLAIMED. IN NO EVENT SHALL &amp;lt;COPYRIGHT HOLDER&amp;gt; BE LIABLE FOR ANY&lt;br /&gt;
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES&lt;br /&gt;
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;&lt;br /&gt;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND&lt;br /&gt;
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT&lt;br /&gt;
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS&lt;br /&gt;
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#define FOOBARZ_INIT_VERSION &amp;quot;1.0.8&amp;quot;&lt;br /&gt;
#define _BSD_SOURCE&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdarg.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/stat.h&amp;gt;&lt;br /&gt;
#include &amp;lt;fcntl.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/mount.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sysexits.h&amp;gt;&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define PARAM_REQ_NO 0&lt;br /&gt;
#define PARAM_REQ_YES 1&lt;br /&gt;
#define PARAM_SRC_DEFAULT 0&lt;br /&gt;
#define PARAM_SRC_LOCAL 1&lt;br /&gt;
&lt;br /&gt;
/* Your initramfs-source should contain the following&lt;br /&gt;
 * cd /boot/initramfs-source&lt;br /&gt;
 * mkdir -p proc dev sys mnt bin sbin etc/zfs&lt;br /&gt;
 * touch etc/mtab&lt;br /&gt;
 * cp /etc/zfs/zpool.cache-initrd etc/zfs/zpool.cache&lt;br /&gt;
 * mknod dev/console c 5 1   # system console&lt;br /&gt;
 * mknod dev/kmsg    c 1 11  # lines printed to kmsg enter kernel messages buffer&lt;br /&gt;
 * mknod dev/loop0   b 7 0&lt;br /&gt;
 * mknod dev/tty     c 5 0   # current tty&lt;br /&gt;
 * mknod dev/tty0    c 4 0   # current virtual term&lt;br /&gt;
 * mknod dev/tty1    c 4 1   # login virtual term 1 (F1)&lt;br /&gt;
 * mknod dev/ttyS0   c 4 64  # COM1&lt;br /&gt;
 * mknod dev/ttyS1   c 4 65  # COM2&lt;br /&gt;
 * mknod dev/ttyS2   c 4 66  # COM3&lt;br /&gt;
 * mknod dev/ttyS3   c 4 67  $ COM4&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
void printk(char *fmt, ...) {&lt;br /&gt;
  FILE* f;&lt;br /&gt;
  va_list args;&lt;br /&gt;
&lt;br /&gt;
  f = fopen(&amp;quot;/dev/kmsg&amp;quot;, &amp;quot;w&amp;quot;);&lt;br /&gt;
  va_start(args, fmt);&lt;br /&gt;
  vfprintf(f, fmt, args);&lt;br /&gt;
  va_end(args);&lt;br /&gt;
  fflush(f);&lt;br /&gt;
  fclose(f);&lt;br /&gt;
  usleep(50000);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[]) {&lt;br /&gt;
 /***** variables&lt;br /&gt;
  *&lt;br /&gt;
  */&lt;br /&gt;
 int i;&lt;br /&gt;
 int   fd = 0; /* file descriptor */&lt;br /&gt;
 unsigned long mountflags;&lt;br /&gt;
&lt;br /&gt;
 /* kernel command line */&lt;br /&gt;
 off_t cmdline_size;&lt;br /&gt;
 char* cmdline; /* to be malloc 4096B */&lt;br /&gt;
 char* cmdline_end;&lt;br /&gt;
 char* temp_end;&lt;br /&gt;
 char* src_msg; /* default or local */&lt;br /&gt;
 int flag_param_missing = 0;&lt;br /&gt;
&lt;br /&gt;
 /* use to hold contents of a misc /proc/&amp;lt;file&amp;gt; */&lt;br /&gt;
 char* miscproc_buff; /* to be malloc 4096B */&lt;br /&gt;
 off_t miscproc_size;&lt;br /&gt;
&lt;br /&gt;
 /* note about environ, argv, and kernel cmdline for init:&lt;br /&gt;
  *   environ is not defined for init&lt;br /&gt;
  *   only argv[0] is set for init&lt;br /&gt;
  *   kernel command line parameters are accessed&lt;br /&gt;
  *   at /proc/cmdline&lt;br /&gt;
  */&lt;br /&gt;
&lt;br /&gt;
 /* kernel parameters expected to be name=value */&lt;br /&gt;
 /* do not use quotes or spaces in parameters   */&lt;br /&gt;
 /* you can add more params somwhere after root= */&lt;br /&gt;
 struct nv { char* n; char* v; char* v_end; int req; int src; };&lt;br /&gt;
 struct nv param[] = {&lt;br /&gt;
   { &amp;quot;root=&amp;quot;,       NULL, NULL, PARAM_REQ_YES, PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;rootfstype=&amp;quot;, NULL, NULL, PARAM_REQ_YES, PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;mountopt=&amp;quot;,   NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;init=&amp;quot;,       NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;runlevel=&amp;quot;,   NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT },&lt;br /&gt;
   { &amp;quot;console=&amp;quot;,    NULL, NULL, PARAM_REQ_NO , PARAM_SRC_DEFAULT }&lt;br /&gt;
 };&lt;br /&gt;
 enum { iroot, irootfstype, imountopt, iinit, irunlevel, iconsole, ilastparam };&lt;br /&gt;
&lt;br /&gt;
 /***** program&lt;br /&gt;
  *&lt;br /&gt;
  */&lt;br /&gt;
 printk(&amp;quot;foobarz-init, version %s: booting initramfs.\n&amp;quot;, FOOBARZ_INIT_VERSION);&lt;br /&gt;
&lt;br /&gt;
 cmdline       = (char*) malloc(4096);&lt;br /&gt;
 miscproc_buff = (char*) malloc(4096);&lt;br /&gt;
 if( (cmdline == NULL) || (miscproc_buff == NULL) ) {&lt;br /&gt;
   printk(&amp;quot;Unable to allocate buffer memory: malloc: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount proc before dev since some devices&lt;br /&gt;
  * symlink into proc */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount proc /proc\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;proc&amp;quot;, &amp;quot;/proc&amp;quot;, &amp;quot;proc&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
   printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
   printk(&amp;quot;Mount proc successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount devtmpfs as expected by an init program&lt;br /&gt;
  * and maybe required to mount zfs */&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount devtmpfs /dev\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;devtmpfs&amp;quot;, &amp;quot;/dev&amp;quot;, &amp;quot;devtmpfs&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
   printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
   printk(&amp;quot;Mount devtmpfs successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
 /* it is assumed that all required devices are in devtmpfs&lt;br /&gt;
  * and if not, there will be boot problems&lt;br /&gt;
  *&lt;br /&gt;
  * if you need a more complex device setup, then you might need&lt;br /&gt;
  * udevd and run it with a larger full initrd package from your distro&lt;br /&gt;
  */&lt;br /&gt;
&lt;br /&gt;
 /* process kernel command line */&lt;br /&gt;
 fd = open(&amp;quot;/proc/cmdline&amp;quot;, O_RDONLY);&lt;br /&gt;
 if( fd == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Cannot open /proc/cmdline: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 /* note, on /proc fs:&lt;br /&gt;
  *       lseek likely always returns error&lt;br /&gt;
  *       stat likely always returns st_size = 0&lt;br /&gt;
  *   so determining size of /proc file means just reading it;&lt;br /&gt;
  *   you have to read /proc files according to their documented&lt;br /&gt;
  *   maximum sizes; this is probably for performance reasons */&lt;br /&gt;
 cmdline_size = read(fd, cmdline, 4095);&lt;br /&gt;
 if( cmdline_size == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Failed to read /proc/cmdline: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 close(fd);&lt;br /&gt;
&lt;br /&gt;
 /* cmdline may be newline + null terminated, but make it null + null */&lt;br /&gt;
 cmdline[cmdline_size] = '\0';&lt;br /&gt;
 if( cmdline[cmdline_size-1] == '\n' ) {&lt;br /&gt;
   cmdline[cmdline_size-1] = '\0';&lt;br /&gt;
   cmdline_size--;&lt;br /&gt;
   cmdline_end = cmdline + cmdline_size;&lt;br /&gt;
 }&lt;br /&gt;
 printk(&amp;quot;Kernel cmdline size: %i\n&amp;quot;, cmdline_size);&lt;br /&gt;
 printk(&amp;quot;Kernel cmdline: \&amp;quot;%s\&amp;quot;\n&amp;quot;, cmdline);&lt;br /&gt;
&lt;br /&gt;
 /* find v and v_end of values in cmdline */&lt;br /&gt;
 for( i=iroot; i&amp;lt;ilastparam; i++ ) {&lt;br /&gt;
   param[i].v = strstr(cmdline, param[i].n);&lt;br /&gt;
   if( param[i].v != NULL ) {&lt;br /&gt;
     param[i].src = PARAM_SRC_LOCAL; /* value src: local */&lt;br /&gt;
     while( *(param[i].v) != '=' ) param[i].v++;&lt;br /&gt;
     param[i].v++;&lt;br /&gt;
     temp_end = param[i].v;&lt;br /&gt;
     while( !( (*temp_end == ' ') ||&lt;br /&gt;
               (*temp_end == '\n') ||&lt;br /&gt;
               (temp_end == cmdline_end)&lt;br /&gt;
	     ) ) temp_end++;&lt;br /&gt;
     if( temp_end == param[i].v ) {&lt;br /&gt;
       printk(&amp;quot;Kernel parameter %s: value missing.\n&amp;quot;, param[i].n);&lt;br /&gt;
       param[i].v = NULL;&lt;br /&gt;
     } else param[i].v_end = temp_end;&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 for( i=iroot; i&amp;lt;ilastparam; i++ ) {&lt;br /&gt;
   /* terminate value strings */&lt;br /&gt;
   if( param[i].v_end != NULL ) *(param[i].v_end) = '\0';&lt;br /&gt;
   /* set defaults if no value on cmdline */&lt;br /&gt;
   if( param[i].v == NULL ) {&lt;br /&gt;
     param[i].src = PARAM_SRC_DEFAULT; /* value src: default */&lt;br /&gt;
     if( param[i].req == PARAM_REQ_YES ) flag_param_missing = 1;&lt;br /&gt;
     switch(i) {&lt;br /&gt;
       case iroot      : param[i].v = &amp;quot;&amp;lt;missing required param&amp;gt;&amp;quot; ; break;&lt;br /&gt;
       case irootfstype: param[i].v = &amp;quot;&amp;lt;missing required param&amp;gt;&amp;quot; ; break;&lt;br /&gt;
       case imountopt  : param[i].v = &amp;quot;ro&amp;quot;        ; break;&lt;br /&gt;
       case iinit      : param[i].v = &amp;quot;/sbin/init&amp;quot;; break;&lt;br /&gt;
       case irunlevel  : param[i].v = &amp;quot;3&amp;quot;         ; break;&lt;br /&gt;
       case iconsole   : param[i].v = &amp;quot;console&amp;quot;   ; break;&lt;br /&gt;
       default         : param[i].v = &amp;quot;&amp;quot;;&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
   if(param[i].src == PARAM_SRC_DEFAULT) src_msg = &amp;quot;default&amp;quot;;&lt;br /&gt;
   else src_msg = &amp;quot;cmdline&amp;quot;;&lt;br /&gt;
   printk(&amp;quot;Using %s \&amp;quot;%s\&amp;quot; (source: %s)\n&amp;quot;, param[i].n, param[i].v, src_msg);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 if( flag_param_missing ) {&lt;br /&gt;
   printk(&amp;quot;Aborting boot process: missing required kernel parameter(s).\n&amp;quot;);&lt;br /&gt;
   return EX_USAGE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* generic nv pair kernel cmdline processing finished&lt;br /&gt;
  *  now, examine specific params for defaults and correctness&lt;br /&gt;
  */&lt;br /&gt;
&lt;br /&gt;
 /* param[iroot]: nothing to do, if user put bad device in then we fail */&lt;br /&gt;
&lt;br /&gt;
 /* param[irootfstype]: can be checked against /proc/filesystems: */&lt;br /&gt;
 /* required, so should have value */&lt;br /&gt;
 fd = open(&amp;quot;/proc/filesystems&amp;quot;, O_RDONLY);&lt;br /&gt;
 if( fd == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Cannot open /proc/filesystems: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 miscproc_size = read(fd, miscproc_buff, 4095);&lt;br /&gt;
 if( miscproc_size == -1 ) {&lt;br /&gt;
   printk(&amp;quot;Failed to read /proc/filesystems: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 close(fd);&lt;br /&gt;
 if( strstr(miscproc_buff, param[irootfstype].v) == NULL ) {&lt;br /&gt;
   printk(&amp;quot;%s \&amp;quot;%s\&amp;quot;: filesystem type not available.\n&amp;quot;, param[irootfstype].n, param[irootfstype].v);&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 if( strcmp(param[irootfstype].v, &amp;quot;zfs&amp;quot;) == 0 ) {&lt;br /&gt;
   if( access(&amp;quot;/etc/zfs/zpool.cache&amp;quot;, F_OK) == 0 )&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/zfs/zpool.cache is present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
   else&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/zfs/zpool.cache not present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
   if( access(&amp;quot;/etc/hostid&amp;quot;, F_OK) == 0 )&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/hostid is present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
   else&lt;br /&gt;
     printk(&amp;quot;rootfstype=%s: /etc/hostid not present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 if(      strcmp(param[imountopt].v, &amp;quot;ro&amp;quot;) == 0 ) mountflags = MS_RDONLY;&lt;br /&gt;
 else if( strcmp(param[imountopt].v, &amp;quot;rw&amp;quot;) == 0 ) mountflags = 0;&lt;br /&gt;
 else {&lt;br /&gt;
   printk(&amp;quot;%s \&amp;quot;%s\&amp;quot;: invalid parameter value; defaulting to \&amp;quot;ro\&amp;quot;.\n&amp;quot;, param[imountopt].n, param[imountopt].v);&lt;br /&gt;
   mountflags = MS_RDONLY;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;Attempting cmd: mount -t %s -o %s %s /mnt.\n&amp;quot;, param[irootfstype].v, param[imountopt].v, param[iroot].v);&lt;br /&gt;
 if( mount(param[iroot].v, &amp;quot;/mnt&amp;quot;, param[irootfstype].v, mountflags, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 printk(&amp;quot;%s mounted successfully.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
&lt;br /&gt;
 chdir(&amp;quot;/mnt&amp;quot;);&lt;br /&gt;
 if( access(param[iinit].v+1, X_OK) != 0 ) {&lt;br /&gt;
   chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
   printk(&amp;quot;access X_OK: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   printk(&amp;quot;The init program /mnt/%s is not present or not executable.\n&amp;quot;, param[iinit].v+1);&lt;br /&gt;
   printk(&amp;quot;Aborting boot process: no init program.\n&amp;quot;);&lt;br /&gt;
   printk(&amp;quot;Unmounting %s.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
   if( umount(&amp;quot;/mnt&amp;quot;) == -1 ) {&lt;br /&gt;
     printk(&amp;quot;umount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
     printk(&amp;quot;Failed to umount %s.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
   } else printk(&amp;quot;Successfully unmounted %s.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;Init program /mnt/%s is present and executable.\n&amp;quot;, param[iinit].v+1);&lt;br /&gt;
 printk(&amp;quot;Beginning switch root procedure.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(1) Attempting cmd: mount --move /dev /mnt/dev \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/dev&amp;quot;, &amp;quot;/mnt/dev&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(2) Attempting cmd: mount --move /proc /mnt/proc \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/proc&amp;quot;, &amp;quot;/mnt/proc&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(3) Attempting cmd: chdir /mnt \n&amp;quot;);&lt;br /&gt;
 if( chdir(&amp;quot;/mnt&amp;quot;) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: chdir: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(4) Attempting cmd: mount --move . / \n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;.&amp;quot;, &amp;quot;/&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(5) Attempting cmd: chroot . \n&amp;quot;);&lt;br /&gt;
 if( chroot(&amp;quot;.&amp;quot;) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: chroot: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;(6) Attempting cmd: chdir / \n&amp;quot;);&lt;br /&gt;
 if( chdir(&amp;quot;/&amp;quot;) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: chdir: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 printk(&amp;quot;Completed switch root procedure.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 /* check for &amp;quot;console=&amp;quot; kernel parameter and switch&lt;br /&gt;
  *  stdin, stdout, and stderr to named console device&lt;br /&gt;
  */&lt;br /&gt;
 if( param[iconsole].src == PARAM_SRC_LOCAL ) {&lt;br /&gt;
   printk(&amp;quot;Console redirection to device %s requested.\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
   /* expect only basename of console device (e.g., ttyS0), so chdir /dev */&lt;br /&gt;
   chdir(&amp;quot;/dev&amp;quot;);&lt;br /&gt;
   if( access(param[iconsole].v, F_OK ) == 0 ) {&lt;br /&gt;
     printk(&amp;quot;Opening stdin, stdout, and stderr on %s.\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
     close(0);&lt;br /&gt;
     open(param[iconsole].v, O_RDWR);&lt;br /&gt;
     dup2(0, 1);&lt;br /&gt;
     dup2(0, 2);&lt;br /&gt;
   } else {&lt;br /&gt;
     printk(&amp;quot;access F_OK: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
     printk(&amp;quot;Could not access device: %s!\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
     printk(&amp;quot;Console redirection to device %s aborted!\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
   }&lt;br /&gt;
   chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 printk(&amp;quot;Execing: \&amp;quot;%s %s\&amp;quot; to boot mounted root system.\n&amp;quot;, param[iinit].v, param[irunlevel].v);&lt;br /&gt;
&lt;br /&gt;
 /* free resources held to this point */&lt;br /&gt;
 free(cmdline);&lt;br /&gt;
 free(miscproc_buff);&lt;br /&gt;
&lt;br /&gt;
 if( execl(param[iinit].v, param[irunlevel].v, (char *) NULL ) != 0 ) {&lt;br /&gt;
  printk(&amp;quot;time to panic: execl: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
EOF&lt;br /&gt;
## end of rootfs /init&lt;br /&gt;
&lt;br /&gt;
gcc --static init.c -o init&lt;br /&gt;
strip init&lt;br /&gt;
&lt;br /&gt;
## build and install kernel&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make -j8&lt;br /&gt;
make -j8 modules_install&lt;br /&gt;
cp arch/x86/boot/bzImage /boot/vm3.2.27b&lt;br /&gt;
cp System.map /boot/System.map-vm3.2.27b&lt;br /&gt;
# add new lilo menu entry for vm3.2.27b kernel&lt;br /&gt;
vi /etc/lilo.conf&lt;br /&gt;
  image = /boot/vm3.2.27b&lt;br /&gt;
   label = vm3.2.27b&lt;br /&gt;
   addappend = &amp;quot; spl.spl_hostid=0x007f0100 zfs.spa_config_path=/etc/zfs/zpool.cache root=zfs-root ro rootfstype=zfs rootwait &amp;quot;&lt;br /&gt;
lilo&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notes on kernel params (lilo append and addappend lines): root= and rootfstype= are used by both foorbarz-init and mkinitrd. The &amp;quot;ro&amp;quot; param is not used by foobarz-init, so instead use: mountopt=ro|rw. See &amp;quot;modinfo spl&amp;quot; and &amp;quot;modinfo zfs&amp;quot; to see all of the options those modules can take on the kernel command line.&lt;br /&gt;
&lt;br /&gt;
Notes on the spl and zfs packages to install: If you have errors using zfs and zpool commands on booted system with builtin modules, then upgrade/switch to the 0.6.0rc10_3.2.27b builds, or you can make a custom package with the binaries renamed like zpoolb, zfsb etc for builtin.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
Using qemu's -nographic serial console (/usr/share/qemu/sgabios.bin): If you have a boot problem, you might want to run in qemu's -nographic console mode:&lt;br /&gt;
&lt;br /&gt;
First, edit /etc/inittab, and uncomment the line for local serial ports runlevel &amp;quot;s1&amp;quot; (ttyS0) for serial console login support. This is done in the guest (host does not need this):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Local serial lines:&lt;br /&gt;
s1:12345:respawn:/sbin/agetty -L ttyS0 38400 linux&lt;br /&gt;
#s1:12345:respawn:/sbin/agetty -L ttyS0 9600 vt100&lt;br /&gt;
#s2:12345:respawn:/sbin/agetty -L ttyS1 9600 vt100&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Second, edit /etc/securetty, and uncomment ttyS0 line:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ttyS0&lt;br /&gt;
#ttyS1&lt;br /&gt;
# ...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
You cannot login on ttyS0 without this change even though you get the login prompt!&lt;br /&gt;
&lt;br /&gt;
Then, run qemu such as:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
qemu-kvm &amp;lt;all regular options&amp;gt; -nographic -option-rom sgabios.bin,bootindex=0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Wait for the lilo prompt, it may take several seconds show up in this mode.&lt;br /&gt;
&lt;br /&gt;
In the lilo menu, select your kernel image with builtin spl/zfs, and use kernel params such as:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
boot: vm3.2.27b console=ttyS0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
At the lilo prompt, use kernel parameter: console=ttyS0 (do NOT say /dev/ttS0). Passing runlevel=s1 does not appear to be necessary.&lt;br /&gt;
&lt;br /&gt;
When you are in qemu's serial graphics mode, the interface is a little different than in the normal graphical SQL-based mode: use keypresses:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ctrl-a h    # for help&lt;br /&gt;
ctrl-a c    # toggle access to (QEMU) console / back to emulation&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If you cannot get a login: prompt, try ctrl-a c, then do (QEMU) sendkey ctrl-alt-delete. This will reboot cleanly back to lilo, then you can do (QEMU) quit.&lt;br /&gt;
&lt;br /&gt;
Once you login to the guest, the terminal size needs adjustment. On your host, in another xterm sized the same as your guest console terminal, get the size of the terminal:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo $LINES&lt;br /&gt;
echo $COLUMNS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Now, back in the guest terminal of same size:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export LINES &amp;lt;lines&amp;gt;&lt;br /&gt;
export COLUMNS &amp;lt;columns&amp;gt;&lt;br /&gt;
stty cols $COLUMNS rows $LINES&lt;br /&gt;
exec bash&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
So, you set the environment variables and also set them with stty. Then, restart bash (exec, or else it is a child shell process).&lt;br /&gt;
&lt;br /&gt;
BECAREFUL not to start qemu twice on the same ZFS guest! Two simultaneous running qemu on the same ZFS will corrupt the pool and it will NOT recover - you lose your whole installation! Before running qemu, check ps -A, look for an already running qemu process incase it somehow entered into the background!&lt;br /&gt;
&lt;br /&gt;
BECAREFUL when using -nographic ttyS0 that you are not doing commands on the HOST! Only use -nographic to see kernel problems. Use regular console of booting is working normally.&lt;br /&gt;
&lt;br /&gt;
To use the qemu -drive if=scsi option, the linux module sym53c8xx should be loaded in the guest. You may need to use the qemu option:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-option-rom 8xx_64.rom,bootindex=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The file 8xx_64.com used to be inside qemu, but in new versions it is missing. You can download it:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
wget http://www.lsi.com/downloads/Public/Host%20Bus%20Adapters/Host%20Bus%20Adapters%20Common%20Files/lsi_bios.zip&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Extract the zip and place 8xx_64.rom in /usr/share/qemu/.&lt;br /&gt;
&lt;br /&gt;
Good luck!&lt;/div&gt;</description>
			<pubDate>Fri, 24 Aug 2012 11:42:16 GMT</pubDate>
			<dc:creator>Foobarz</dc:creator>
			<comments>https://www.slackwiki.com/Talk:ZFS_root_(builtin)</comments>
		</item>
		<item>
			<title>ZFS root (builtin)</title>
			<link>https://www.slackwiki.com/index.php?title=ZFS_root_(builtin)&amp;diff=750</link>
			<guid isPermaLink="false">https://www.slackwiki.com/index.php?title=ZFS_root_(builtin)&amp;diff=750</guid>
			<description>&lt;p&gt;Foobarz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Tutorials]]&lt;br /&gt;
The first &amp;quot;ZFS root&amp;quot; wiki explains the details of running ZFS at your root filesystem by using a fully modular generic kernel approach. Now, I can share how it can be done with the SPL and ZFS modules built into the kernel. This procedure is just an example and can use some fine tuning, but here goes:&lt;br /&gt;
&lt;br /&gt;
The steps below are to create kernel with SPL and ZFS modules builtin. This kernel will be installed as an alternatve kernel to boot in lilo, and it will have a separate installation from the fully modular and working system. This will allow testing the builtin kernel while able to boot back onto a working modular ZFS system. We start this procedure assuming you are on a working fully modular ZFS install as in the &amp;quot;ZFS root&amp;quot; wiki.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=legacy zfs-root&lt;br /&gt;
# use legacy so zfs will not expect zfs mount, but instead expect standard mount for this fs&lt;br /&gt;
# edit /etc/rc.d/rc.S and rc.6 to use regular &amp;quot;mount&amp;quot; commands, remove &amp;quot;zfs&amp;quot; commands&lt;br /&gt;
# edit rc.6 and remove or comment out zfs export command&lt;br /&gt;
zpool set bootfs=zfs-root zfs-root&lt;br /&gt;
# this may help, but not really sure&lt;br /&gt;
&lt;br /&gt;
mkdir /boot/initramfs-source&lt;br /&gt;
# this will hold some files for rootfs inside kernel&lt;br /&gt;
&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir src&lt;br /&gt;
cd src&lt;br /&gt;
tar xvzf /mnt/cdrom/slackware64/k/kernel-source-*.txz&lt;br /&gt;
mv usr/src/linux-3.2.27 /usr/src/linux-3.2.27b&lt;br /&gt;
rm -r install&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make menuconfig&lt;br /&gt;
  General setup-&amp;gt;Local version - append to kernel release = b&lt;br /&gt;
  General setup-&amp;gt;Default hostname                         = slackzfs&lt;br /&gt;
  General setup-&amp;gt;Initramfs source files(s)                = /boot/initramfs-source&lt;br /&gt;
  #  make usre you made this directory or the kernel build fails&lt;br /&gt;
  Device Drivers-&amp;gt;SCSI device support-&amp;gt;SCSI low-level drivers-&amp;gt; &amp;lt;*&amp;gt; SYM53C8XX Version 2 SCSI support&lt;br /&gt;
  #  for qemu if=scsi -option-rom 8xx_64.rom,bootindex=1  hard disks&lt;br /&gt;
  # buildin any hard drive controllers etc that you need&lt;br /&gt;
  File systems -&amp;gt; &amp;lt;*&amp;gt; The Extended 4 (ext4) filesystem&lt;br /&gt;
  # /boot may use this ext4 fs&lt;br /&gt;
make prepare scripts&lt;br /&gt;
# this make command is what the spl and zfs copy-builtin scripts expect to be done before they are run&lt;br /&gt;
&lt;br /&gt;
cd ~/src&lt;br /&gt;
tar xvzf ~/spl-0.6.0-rc10.tar.gz&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-0.6.0-rc10&lt;br /&gt;
./configure \&lt;br /&gt;
    --prefix=/ \&lt;br /&gt;
    --libdir=/lib64 \&lt;br /&gt;
    --includedir=/usr/include \&lt;br /&gt;
    --datarootdir=/usr/share \&lt;br /&gt;
    --enable-linux-builtin=yes \&lt;br /&gt;
    --with-linux=/usr/src/linux-3.2.27b \&lt;br /&gt;
    --with-linux-obj=/usr/src/linux-3.2.27b&lt;br /&gt;
wget https://raw.github.com/zfsonlinux/spl/master/copy-builtin&lt;br /&gt;
chmod +x copy-builtin&lt;br /&gt;
./copy-builtin /usr/src/linux-3.2.27b&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../spl-0.6.0rc10_3.2.27b-x86_64-1root.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
&lt;br /&gt;
tar xvzf ~/zfs-0.6.0-rc10.tar.gz&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-0.6.0-rc10&lt;br /&gt;
./configure \&lt;br /&gt;
    --prefix=/ \&lt;br /&gt;
    --libdir=/lib64 \&lt;br /&gt;
    --includedir=/usr/include \&lt;br /&gt;
    --datarootdir=/usr/share \&lt;br /&gt;
    --enable-linux-builtin=yes \&lt;br /&gt;
    --with-linux=/usr/src/linux-3.2.27b \&lt;br /&gt;
    --with-linux-obj=/usr/src/linux-3.2.27b \&lt;br /&gt;
    --with-spl=/root/src/spl-0.6.0-rc10&lt;br /&gt;
wget https://raw.github.com/zfsonlinux/zfs/master/copy-builtin&lt;br /&gt;
chmod +x copy-builtin&lt;br /&gt;
./copy-builtin /usr/src/linux-3.2.27b&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../zfs-0.6.0rc10_3.2.27b-x86_64-1root.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
&lt;br /&gt;
### move zfs and spl modules inside kernel source to be at end of drivers:&lt;br /&gt;
### the order builtin modules init is the order they link into the kernel&lt;br /&gt;
### and we need zfs to init after all hard drive controllers&lt;br /&gt;
### zfs is more like a device driver layer over the lower-level hba drivers&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
mkdir drivers/zfsonlinux&lt;br /&gt;
mv spl drivers/zfsonlinux&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  # remove references to spl&lt;br /&gt;
vi Makefile&lt;br /&gt;
  # remove references to spl&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/fs&lt;br /&gt;
mv zfs ../drivers/zfsonlinux&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  # remove references to zfs&lt;br /&gt;
vi Makefile&lt;br /&gt;
  # remove references to zfs&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  )# add line at end of menu, before &amp;quot;endmenu&amp;quot;:&lt;br /&gt;
  )source &amp;quot;drivers/zfsonlinux/Kconfig&amp;quot;&lt;br /&gt;
  )endmenu&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers&lt;br /&gt;
vi Makefile&lt;br /&gt;
  )# add line at very end of file:&lt;br /&gt;
  )obj-$(CONFIG_ZFSONLINUX) += zfsonlinux/&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers/zfsonlinux&lt;br /&gt;
cat &amp;gt; Kconfig &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
menuconfig ZFSONLINUX&lt;br /&gt;
	tristate &amp;quot;ZFSonLinux support&amp;quot;&lt;br /&gt;
&lt;br /&gt;
if ZFSONLINUX&lt;br /&gt;
&lt;br /&gt;
source &amp;quot;drivers/zfsonlinux/spl/Kconifg&amp;quot;&lt;br /&gt;
&lt;br /&gt;
source &amp;quot;drivers/zfsonlinux/zfs/Kconifg&amp;quot;&lt;br /&gt;
&lt;br /&gt;
endif&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/zfsonlinux&lt;br /&gt;
cat &amp;gt; Makefile &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
obj-$(CONFIG_SPL) += spl/&lt;br /&gt;
obj-$(CONFIG_ZFS) += zfs/&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
### move complete&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make menuconfig&lt;br /&gt;
   Device Drivers -&amp;gt;&lt;br /&gt;
    &amp;lt;*&amp;gt; ZFSonLinux support -&amp;gt;&lt;br /&gt;
      &amp;lt;*&amp;gt; Solaris Porting Layer (SPL)&lt;br /&gt;
      &amp;lt;*&amp;gt;     ZFS&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
### prepare contents of initramfs&lt;br /&gt;
cd /boot/initramfs-source&lt;br /&gt;
&lt;br /&gt;
# make standard directories&lt;br /&gt;
mkdir -p proc dev sys mnt bin sbin etc/zfs&lt;br /&gt;
&lt;br /&gt;
# zfs seems to want mtab present, even if empty&lt;br /&gt;
touch etc/mtab&lt;br /&gt;
&lt;br /&gt;
# if zpool.cache file can be read by zfs at module init, it imports the pools in the cache&lt;br /&gt;
cp /etc/zfs/zpool.cache-initrd etc/zfs/zpool.cache&lt;br /&gt;
&lt;br /&gt;
# make initial console device node; otherwise, there is a problem at startup:&lt;br /&gt;
# &amp;quot;Warning: unable to open an initial console&amp;quot; and you'd have problems with console and tty login&lt;br /&gt;
# making these nodes from within /init is not early enough to avoid problem&lt;br /&gt;
mknod dev/console c 5 1   # system console&lt;br /&gt;
&lt;br /&gt;
# make memory device kmsg to &amp;quot;printk&amp;quot; kernel messages&lt;br /&gt;
# we can write to this file to send out messages&lt;br /&gt;
mknod dev/kmsg    c 1 11  # lines printed to kmsg enter kernel messages buffer&lt;br /&gt;
&lt;br /&gt;
# recommended loop0 device to mount fs images&lt;br /&gt;
mknod dev/loop0   b 7 0&lt;br /&gt;
&lt;br /&gt;
# make initial virtual terminal devices&lt;br /&gt;
mknod dev/tty     c 5 0   # current tty&lt;br /&gt;
mknod dev/tty0    c 4 0   # current virtual term&lt;br /&gt;
mknod dev/tty1    c 4 1   # login virtual term 1 (F1)&lt;br /&gt;
&lt;br /&gt;
# make alternative console=ttyS0 standard 8250/16550 UART serial port devices&lt;br /&gt;
#   useful with kernel parameter console=ttyS0&lt;br /&gt;
#          with qemu -nographic -option-rom sgabios.bin,bootindex=0&lt;br /&gt;
mknod dev/ttyS0   c 4 64  # COM1&lt;br /&gt;
mknod dev/ttyS1   c 4 65  # COM2&lt;br /&gt;
mknod dev/ttyS2   c 4 66  # COM3&lt;br /&gt;
mknod dev/ttyS3   c 4 67  $ COM4&lt;br /&gt;
&lt;br /&gt;
# this should be enough device nodes initially&lt;br /&gt;
# once devtmpfs mounts over /dev, a lot more is available in it by default&lt;br /&gt;
&lt;br /&gt;
cat &amp;gt; /init &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot; &amp;lt;some initial program PID=1 for the system to start on&amp;gt; EOF&lt;br /&gt;
# an initramfs-source/init program is required to mount and boot a root linux system&lt;br /&gt;
# the common way to make /init is using busybox with files like this:&lt;br /&gt;
#    /bin/busybox&lt;br /&gt;
#    /bin/ash -&amp;gt; busybox&lt;br /&gt;
#    /bin/sh -&amp;gt; busybox&lt;br /&gt;
#    # run busybox to see what other &amp;quot;applets&amp;quot; can be symlinked to it&lt;br /&gt;
#    # when busybox is run as a different symlinked applet name, it runs the applet&lt;br /&gt;
#    /init&lt;br /&gt;
#    # init is ash script, see slackware's /boot/initrd-tree/init for example&lt;br /&gt;
#    Inside this script:&lt;br /&gt;
#      1) parse kernel parameters passed into it and set variables based on them&lt;br /&gt;
#      2) start udevd and trigger rules for block devices to setup initial /dev devices&lt;br /&gt;
#      3) load kernel modules and keyboard map&lt;br /&gt;
#      4) run mdadm, cryptsetup, lvm, zpool/zfs to setup more devices&lt;br /&gt;
#         (any udev rules for them should do more /dev setup in the background)&lt;br /&gt;
#      5) mount the root filesystem read-only at /mnt&lt;br /&gt;
#      6) stat /mnt/sbin/init, and if not executable run a rescue shell /bin/sh&lt;br /&gt;
#      7) shutdown udevd so it can be restarted by root system when booted&lt;br /&gt;
#      8) mount --move {proc,sys,run,dev} to under /mnt&lt;br /&gt;
#      9) run: exec switch_root /mnt /sbin/init $RUNLEVEL&lt;br /&gt;
#    The slackware mkinitrd package is fully configured busybox installation&lt;br /&gt;
#      for an extern file initramfs initrd.gz image outside the kernel.&lt;br /&gt;
#    It could be changed to be inside the kernel easily by just using initrd-tree&lt;br /&gt;
#      as target of INITRAMFS_SOURCE in the kernel config and removing initrd in lilo.&lt;br /&gt;
&lt;br /&gt;
# Because the zfs modules are builtin, we really don't need busybox and the whole&lt;br /&gt;
# mkinitrd package. All we need to do is mount the zfs that is already imported&lt;br /&gt;
# because the zpool.cache is present in rootfs when the zfs module initializes, and&lt;br /&gt;
# then we do the switch root procedure to boot up on the mounted system.&lt;br /&gt;
# udevd rules will still be run when the root system starts udevd.&lt;br /&gt;
&lt;br /&gt;
# So, let's make a simple /init c program that will be all that we really need:&lt;br /&gt;
cat &amp;gt; init.c &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
/* software product name: foobarz-init.c&lt;br /&gt;
 * suggested binary name: /init (in initramfs-source, rootfs)&lt;br /&gt;
 * license              : BSD&lt;br /&gt;
 * license text:&lt;br /&gt;
Copyright (c) 2012, foobarz&lt;br /&gt;
All rights reserved.&lt;br /&gt;
&lt;br /&gt;
Redistribution and use in source and binary forms, with or without&lt;br /&gt;
modification, are permitted provided that the following conditions are met:&lt;br /&gt;
    * Redistributions of source code must retain the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer.&lt;br /&gt;
    * Redistributions in binary form must reproduce the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer in the&lt;br /&gt;
      documentation and/or other materials provided with the distribution.&lt;br /&gt;
    * Neither the name of the &amp;lt;organization&amp;gt; nor the&lt;br /&gt;
      names of its contributors may be used to endorse or promote products&lt;br /&gt;
      derived from this software without specific prior written permission.&lt;br /&gt;
&lt;br /&gt;
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &amp;quot;AS IS&amp;quot; AND&lt;br /&gt;
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED&lt;br /&gt;
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE&lt;br /&gt;
DISCLAIMED. IN NO EVENT SHALL &amp;lt;COPYRIGHT HOLDER&amp;gt; BE LIABLE FOR ANY&lt;br /&gt;
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES&lt;br /&gt;
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;&lt;br /&gt;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND&lt;br /&gt;
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT&lt;br /&gt;
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS&lt;br /&gt;
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#define FOOBARZ_INIT_VERSION &amp;quot;1.0.1&amp;quot;&lt;br /&gt;
#define _BSD_SOURCE&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/stat.h&amp;gt;&lt;br /&gt;
#include &amp;lt;fcntl.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/mount.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sysexits.h&amp;gt;&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/* Your initramfs-source should contain the following&lt;br /&gt;
 * cd /boot/initramfs-source&lt;br /&gt;
 * mkdir -p proc dev sys mnt bin sbin etc/zfs&lt;br /&gt;
 * touch etc/mtab&lt;br /&gt;
 * cp /etc/zfs/zpool.cache-initrd etc/zfs/zpool.cache&lt;br /&gt;
 * mknod dev/console c 5 1   # system console&lt;br /&gt;
 * mknod dev/kmsg    c 1 11  # lines printed to kmsg enter kernel messages buffer&lt;br /&gt;
 * mknod dev/loop0   b 7 0&lt;br /&gt;
 * mknod dev/tty     c 5 0   # current tty&lt;br /&gt;
 * mknod dev/tty0    c 4 0   # current virtual term&lt;br /&gt;
 * mknod dev/tty1    c 4 1   # login virtual term 1 (F1)&lt;br /&gt;
 * mknod dev/ttyS0   c 4 64  # COM1&lt;br /&gt;
 * mknod dev/ttyS1   c 4 65  # COM2&lt;br /&gt;
 * mknod dev/ttyS2   c 4 66  # COM3&lt;br /&gt;
 * mknod dev/ttyS3   c 4 67  $ COM4&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[]) {&lt;br /&gt;
 /***** variables&lt;br /&gt;
  *&lt;br /&gt;
  */&lt;br /&gt;
 int i;&lt;br /&gt;
 FILE* kmsg = NULL;&lt;br /&gt;
 int   fd = 0; /* file descriptor */&lt;br /&gt;
 unsigned long mountflags;&lt;br /&gt;
&lt;br /&gt;
 /* kernel command line */&lt;br /&gt;
 off_t cmdline_size;&lt;br /&gt;
 char* cmdline; /* to be malloc 4096B */&lt;br /&gt;
 char* cmdline_end;&lt;br /&gt;
 char* temp_end;&lt;br /&gt;
 int usage = EX_OK;&lt;br /&gt;
&lt;br /&gt;
 /* use to hold contents of a misc /proc/&amp;lt;file&amp;gt; */&lt;br /&gt;
 char* miscproc_buff; /* to be malloc 4096B */&lt;br /&gt;
 off_t miscproc_size;&lt;br /&gt;
&lt;br /&gt;
 /* note about environ, argv, and kernel cmdline for init:&lt;br /&gt;
  *   environ is not defined for init&lt;br /&gt;
  *   only argv[0] is set for init&lt;br /&gt;
  *   kernel command line parameters are accessed&lt;br /&gt;
  *   at /proc/cmdline&lt;br /&gt;
  */&lt;br /&gt;
&lt;br /&gt;
 /* kernel parameters expected to be name=value */&lt;br /&gt;
 /* do not use quotes or spaces in parameters   */&lt;br /&gt;
 /* you can add more params somwhere after root= */&lt;br /&gt;
 struct nv { char* n; char* v; char* v_end; int req; };&lt;br /&gt;
 struct nv param[] = {&lt;br /&gt;
   { &amp;quot;root=&amp;quot;, NULL, NULL, 1 },      /* required; root device to boot */&lt;br /&gt;
   { &amp;quot;rootfstype=&amp;quot;, NULL, NULL, 1 },    /* required; root filesystem type */&lt;br /&gt;
   { &amp;quot;mountopt=&amp;quot;, NULL, NULL, 0 },  /* optional; mount option ro or rw; default ro */&lt;br /&gt;
   { &amp;quot;init=&amp;quot;, NULL, NULL, 0 },      /* optional; alt. init prgm; default /sbin/init */&lt;br /&gt;
   { &amp;quot;runlevel=&amp;quot;, NULL, NULL, 0 },  /* optional; runlevel 0123456Ss; default 3 multiuser */&lt;br /&gt;
   { &amp;quot;console=&amp;quot;, NULL, NULL, 0 }          /* optional; alt. console; e.g. ttyS0 */&lt;br /&gt;
 };&lt;br /&gt;
 enum { iroot, irootfstype, imountopt, iinit, irunlevel, iconsole, ilastparam };&lt;br /&gt;
&lt;br /&gt;
 /***** program&lt;br /&gt;
  *&lt;br /&gt;
  */&lt;br /&gt;
 kmsg = fopen(&amp;quot;/dev/kmsg&amp;quot;, &amp;quot;w&amp;quot;);&lt;br /&gt;
 fprintf(kmsg, &amp;quot;foobarz-init, version %s: booting initramfs.\n&amp;quot;, FOOBARZ_INIT_VERSION);&lt;br /&gt;
&lt;br /&gt;
 cmdline = (char*) malloc(4096);&lt;br /&gt;
 miscproc_buff = (char*) malloc(4096);&lt;br /&gt;
 if( (cmdline == NULL) || (miscproc_buff == NULL) ) {&lt;br /&gt;
   fprintf(kmsg, &amp;quot;Unable to allocate buffer memory: malloc: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount proc before dev since some devices&lt;br /&gt;
  * symlink into proc */&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting mount proc /proc\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;proc&amp;quot;, &amp;quot;/proc&amp;quot;, &amp;quot;proc&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;Mount proc successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount devtmpfs as expected by an init program&lt;br /&gt;
  * and maybe required to mount zfs */&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting mount devtmpfs /dev\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;devtmpfs&amp;quot;, &amp;quot;/dev&amp;quot;, &amp;quot;devtmpfs&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;Mount devtmpfs successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
 /* it is assumed that all required devices are in devtmpfs&lt;br /&gt;
  * and if not, there will be boot problems&lt;br /&gt;
  *&lt;br /&gt;
  * if you need a more complex device setup, then you might need&lt;br /&gt;
  * udevd and run it with a larger full initrd package from your distro&lt;br /&gt;
  */&lt;br /&gt;
&lt;br /&gt;
 /* process kernel command line */&lt;br /&gt;
 fd = open(&amp;quot;/proc/cmdline&amp;quot;, O_RDONLY);&lt;br /&gt;
 if( fd == -1 ) {&lt;br /&gt;
   fprintf(kmsg, &amp;quot;Cannot open /proc/cmdline: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 /* note, on /proc fs:&lt;br /&gt;
  *       lseek likely always returns error&lt;br /&gt;
  *       stat likely always returns st_size = 0&lt;br /&gt;
  *   so determining size of /proc file means just reading it;&lt;br /&gt;
  *   you have to read /proc files according to their documented&lt;br /&gt;
  *   maximum sizes; this is probably for performance reasons */&lt;br /&gt;
 cmdline_size = read(fd, cmdline, 4095);&lt;br /&gt;
 if( cmdline_size == -1 ) {&lt;br /&gt;
   fprintf(kmsg, &amp;quot;Failed to read /proc/cmdline: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 close(fd);&lt;br /&gt;
&lt;br /&gt;
 /* cmdline may be newline + null terminated, but make it null + null */&lt;br /&gt;
 cmdline[cmdline_size] = '\0';&lt;br /&gt;
 if( cmdline[cmdline_size-1] == '\n' ) {&lt;br /&gt;
   cmdline[cmdline_size-1] = '\0';&lt;br /&gt;
   cmdline_size--;&lt;br /&gt;
   cmdline_end = cmdline + cmdline_size;&lt;br /&gt;
 }&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Kernel cmdline size: %i\n&amp;quot;, cmdline_size);&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Kernel cmdline: \&amp;quot;%s\&amp;quot;\n&amp;quot;, cmdline);&lt;br /&gt;
&lt;br /&gt;
 for( i=iroot; i&amp;lt;ilastparam; i++ ) {&lt;br /&gt;
   param[i].v = strstr(cmdline, param[i].n);&lt;br /&gt;
   if( param[i].v != NULL ) {&lt;br /&gt;
     while( *(param[i].v) != '=' ) param[i].v++;&lt;br /&gt;
     param[i].v++;&lt;br /&gt;
     temp_end = param[i].v;&lt;br /&gt;
     while( !( (*temp_end == ' ') ||&lt;br /&gt;
               (*temp_end == '\n') ||&lt;br /&gt;
               (temp_end == cmdline_end)&lt;br /&gt;
	     ) ) temp_end++;&lt;br /&gt;
     if( temp_end == param[i].v ) {&lt;br /&gt;
       fprintf(kmsg, &amp;quot;Kernel parameter %s: value missing.\n&amp;quot;, param[i].n);&lt;br /&gt;
     } else param[i].v_end = temp_end;&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* set defaults on non-required params, except for console */&lt;br /&gt;
 if( param[imountopt].v == NULL ) param[imountopt].v = &amp;quot;ro&amp;quot;;&lt;br /&gt;
 if( param[iinit].v == NULL )     param[iinit].v = &amp;quot;/sbin/init&amp;quot;;&lt;br /&gt;
 if( param[irunlevel].v == NULL ) param[irunlevel].v = &amp;quot;3&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
 for( i=iroot; i&amp;lt;ilastparam; i++ ) {&lt;br /&gt;
   if( param[i].v_end != NULL ) *(param[i].v_end) = '\0';&lt;br /&gt;
   fprintf(kmsg, &amp;quot;Using %s \&amp;quot;%s\&amp;quot;\n&amp;quot;, param[i].n, param[i].v);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 for( i=iroot; i&amp;lt;ilastparam; i++ ) {&lt;br /&gt;
   if( (param[i].req == 1) &amp;amp;&amp;amp; (param[i].v == NULL) ) {&lt;br /&gt;
     printf(&amp;quot;Error: missing required kernel parameter: %s\n&amp;quot;, param[i].n);&lt;br /&gt;
     usage = EX_USAGE;&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 if( usage != EX_OK ) {&lt;br /&gt;
   printf(&amp;quot;Aborting boot process. Missing required kernel parameter(s).\n&amp;quot;);&lt;br /&gt;
   return usage;&lt;br /&gt;
 }&lt;br /&gt;
 /* generic nv pair kernel cmdline processing finished&lt;br /&gt;
  *  now, examine specific params for defaults and correctness&lt;br /&gt;
  */&lt;br /&gt;
&lt;br /&gt;
 /* param[iroot]: nothing to do, if user put bad device in then we fail */&lt;br /&gt;
&lt;br /&gt;
 /* param[irootfstype]: can be checked against /proc/filesystems: */&lt;br /&gt;
 /* required, so should have value */&lt;br /&gt;
 fd = open(&amp;quot;/proc/filesystems&amp;quot;, O_RDONLY);&lt;br /&gt;
 if( fd == -1 ) {&lt;br /&gt;
   fprintf(kmsg, &amp;quot;Cannot open /proc/filesystems: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 miscproc_size = read(fd, miscproc_buff, 4095);&lt;br /&gt;
 if( miscproc_size == -1 ) {&lt;br /&gt;
   fprintf(kmsg, &amp;quot;Failed to read /proc/filesystems: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 close(fd);&lt;br /&gt;
 if( strstr(miscproc_buff, param[irootfstype].v) == NULL ) {&lt;br /&gt;
   fprintf(kmsg, &amp;quot;%s \&amp;quot;%s\&amp;quot;: filesystem type not available.\n&amp;quot;,&lt;br /&gt;
	   param[irootfstype].n, param[irootfstype].v);&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 if( strcmp(param[irootfstype].v, &amp;quot;zfs&amp;quot;) == 0 ) {&lt;br /&gt;
   if( access(&amp;quot;/etc/zfs/zpool.cache&amp;quot;, F_OK) == 0 )&lt;br /&gt;
     fprintf(kmsg, &amp;quot;%s: /etc/zfs/zpool.cache is present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
   else&lt;br /&gt;
     fprintf(kmsg, &amp;quot;%s: /etc/zfs/zpool.cache not present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
   if( access(&amp;quot;/etc/hostid&amp;quot;, F_OK) == 0 )&lt;br /&gt;
     fprintf(kmsg, &amp;quot;%s: /etc/hostid is present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
   else&lt;br /&gt;
     fprintf(kmsg, &amp;quot;%s: /etc/hostid not present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 if(      strcmp(param[imountopt].v, &amp;quot;ro&amp;quot;) == 0 ) mountflags = MS_RDONLY;&lt;br /&gt;
 else if( strcmp(param[imountopt].v, &amp;quot;rw&amp;quot;) == 0 ) mountflags = 0;&lt;br /&gt;
 else {&lt;br /&gt;
   fprintf(kmsg, &amp;quot;% \&amp;quot;%\&amp;quot;: invalid parameter value;\n&amp;quot;&lt;br /&gt;
		 &amp;quot;   use \&amp;quot;ro\&amp;quot; or \&amp;quot;rw\&amp;quot; (no quotes or spaces);\n&amp;quot;&lt;br /&gt;
		 &amp;quot;   defaulting to \&amp;quot;ro\&amp;quot;.\n&amp;quot;,&lt;br /&gt;
		 param[imountopt].n, param[imountopt].v&lt;br /&gt;
	  );&lt;br /&gt;
   mountflags = MS_RDONLY;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting %s %s mount %s /mnt.\n&amp;quot;,&lt;br /&gt;
	 param[irootfstype].v, param[imountopt].v, param[iroot].v);&lt;br /&gt;
 if( mount(param[iroot].v, &amp;quot;/mnt&amp;quot;, param[irootfstype].v, mountflags, NULL) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 fprintf(kmsg, &amp;quot;%s mounted successfully.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting mount --move /dev /mnt/dev\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/dev&amp;quot;, &amp;quot;/mnt/dev&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting mount --move /proc /mnt/proc\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/proc&amp;quot;, &amp;quot;/mnt/proc&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Beginning switch root procedure.\n&amp;quot;);&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting chdir from / to /mnt\n&amp;quot;);&lt;br /&gt;
 if( chdir(&amp;quot;/mnt&amp;quot;) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: chdir: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting mount-move . to /\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;.&amp;quot;, &amp;quot;/&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting chroot to .\n&amp;quot;);&lt;br /&gt;
 if( chroot(&amp;quot;.&amp;quot;) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: chroot: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting chdir to /\n&amp;quot;);&lt;br /&gt;
 if( chdir(&amp;quot;/&amp;quot;) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: chdir: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Completed switch root procedure.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 /* check for &amp;quot;console=&amp;quot; kernel parameter and switch&lt;br /&gt;
  *  stdin, stdout, and stderr to named console device&lt;br /&gt;
  */&lt;br /&gt;
 if( param[iconsole].v != NULL ) {&lt;br /&gt;
   fprintf(kmsg, &amp;quot;Console redirection to device %s requested.\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
   fprintf(kmsg, &amp;quot;Opening stdin, stdout, and stderr on %s.\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
   close(0);&lt;br /&gt;
   /* expect only basename of device (e.g., ttyS0), so chdir /dev */&lt;br /&gt;
   chdir(&amp;quot;/dev&amp;quot;);&lt;br /&gt;
   open(param[iconsole].v, O_RDWR);&lt;br /&gt;
   dup2(0, 1);&lt;br /&gt;
   dup2(0, 2);&lt;br /&gt;
   chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Execing: \&amp;quot;%s %s\&amp;quot; to boot mounted root system.\n&amp;quot;,&lt;br /&gt;
	 param[iinit].v, param[irunlevel].v);&lt;br /&gt;
&lt;br /&gt;
 /* free resources held to this point */&lt;br /&gt;
 fclose(kmsg);&lt;br /&gt;
 free(cmdline);&lt;br /&gt;
 free(miscproc_buff);&lt;br /&gt;
&lt;br /&gt;
 if( execl(param[iinit].v, param[irunlevel].v, (char *) NULL ) != 0 ) {&lt;br /&gt;
  kmsg = fopen(&amp;quot;/dev/kmsg&amp;quot;, &amp;quot;w&amp;quot;);&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: execl: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  fclose(kmsg);&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
EOF&lt;br /&gt;
## end of rootfs /init&lt;br /&gt;
&lt;br /&gt;
gcc --static init.c -o init&lt;br /&gt;
strip init&lt;br /&gt;
&lt;br /&gt;
## build and install kernel&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make -j8&lt;br /&gt;
make -j8 modules_install&lt;br /&gt;
cp arch/x86/boot/bzImage /boot/vm3.2.27b&lt;br /&gt;
cp System.map /boot/System.map-vm3.2.27b&lt;br /&gt;
# add new lilo menu entry for vm3.2.27b kernel&lt;br /&gt;
vi /etc/lilo.conf&lt;br /&gt;
  image = /boot/vm3.2.27b&lt;br /&gt;
   label = vm3.2.27b&lt;br /&gt;
   addappend = &amp;quot; spl.spl_hostid=0x007f0100 zfs.spa_config_path=/etc/zfs/zpool.cache root=zfs-root ro rootfstype=zfs rootwait &amp;quot;&lt;br /&gt;
lilo&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notes on kernel params (lilo append and addappend lines): root= and rootfstype= are used by both foorbarz-init and mkinitrd. The &amp;quot;ro&amp;quot; param is not used by foobarz-init, so instead use: mountopt=ro|rw. See &amp;quot;modinfo spl&amp;quot; and &amp;quot;modinfo zfs&amp;quot; to see all of the options those modules can take on the kernel command line.&lt;br /&gt;
&lt;br /&gt;
Notes on the spl and zfs packages to install: If you have errors using zfs and zpool commands on booted system with builtin modules, then upgrade/switch to the 0.6.0rc10_3.2.27b builds, or you can make a custom package with the binaries renamed like zpoolb, zfsb etc for builtin.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
Using qemu's -nographic serial console (/usr/share/qemu/sgabios.bin): If you have a boot problem, you might want to run in qemu's -nographic console mode:&lt;br /&gt;
&lt;br /&gt;
First, edit /etc/inittab, and uncomment the line for local serial ports runlevel &amp;quot;s1&amp;quot; (ttyS0) for serial console login support. This is done in the guest (host does not need this):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Local serial lines:&lt;br /&gt;
s1:12345:respawn:/sbin/agetty -L ttyS0 38400 linux&lt;br /&gt;
#s1:12345:respawn:/sbin/agetty -L ttyS0 9600 vt100&lt;br /&gt;
#s2:12345:respawn:/sbin/agetty -L ttyS1 9600 vt100&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Second, edit /etc/securetty, and uncomment ttyS0 line:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ttyS0&lt;br /&gt;
#ttyS1&lt;br /&gt;
# ...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
You cannot login on ttyS0 without this change even though you get the login prompt!&lt;br /&gt;
&lt;br /&gt;
Then, run qemu such as:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
qemu-kvm &amp;lt;all regular options&amp;gt; -nographic -option-rom sgabios.bin,bootindex=0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Wait for the lilo prompt, it may take several seconds show up in this mode.&lt;br /&gt;
&lt;br /&gt;
In the lilo menu, select your kernel image with builtin spl/zfs, and use kernel params such as:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
boot: vm3.2.27b console=ttyS0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
At the lilo prompt, use kernel parameter: console=ttyS0 (do NOT say /dev/ttS0). Passing runlevel=s1 does not appear to be necessary.&lt;br /&gt;
&lt;br /&gt;
When you are in qemu's serial graphics mode, the interface is a little different than in the normal graphical SQL-based mode: use keypresses:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ctrl-a h    # for help&lt;br /&gt;
ctrl-a c    # toggle access to (QEMU) console / back to emulation&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If you cannot get a login: prompt, try ctrl-a c, then do (QEMU) sendkey ctrl-alt-delete. This will reboot cleanly back to lilo, then you can do (QEMU) quit.&lt;br /&gt;
&lt;br /&gt;
BECAREFUL not to start qemu twice on the same ZFS guest! Two simultaneous running qemu on the same ZFS will corrupt the pool and it will NOT recover - you lose your whole installation! Before running qemu, check ps -A, look for an already running qemu process incase it somehow entered into the background!&lt;br /&gt;
&lt;br /&gt;
BECAREFUL when using -nographic ttyS0 that you are not doing commands on the HOST! Only use -nographic to see kernel problems. Use regular console of booting is working normally.&lt;br /&gt;
&lt;br /&gt;
To use the qemu -drive if=scsi option, the linux module sym53c8xx should be loaded in the guest. You may need to use the qemu option:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-option-rom 8xx_64.rom,bootindex=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The file 8xx_64.com used to be inside qemu, but in new versions it is missing. You can download it:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
wget http://www.lsi.com/downloads/Public/Host%20Bus%20Adapters/Host%20Bus%20Adapters%20Common%20Files/lsi_bios.zip&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Extract the zip and place 8xx_64.rom in /usr/share/qemu/.&lt;br /&gt;
&lt;br /&gt;
Good luck!&lt;/div&gt;</description>
			<pubDate>Fri, 24 Aug 2012 03:38:08 GMT</pubDate>
			<dc:creator>Foobarz</dc:creator>
			<comments>https://www.slackwiki.com/Talk:ZFS_root_(builtin)</comments>
		</item>
		<item>
			<title>ZFS root (builtin)</title>
			<link>https://www.slackwiki.com/index.php?title=ZFS_root_(builtin)&amp;diff=749</link>
			<guid isPermaLink="false">https://www.slackwiki.com/index.php?title=ZFS_root_(builtin)&amp;diff=749</guid>
			<description>&lt;p&gt;Foobarz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Tutorials]]&lt;br /&gt;
The first &amp;quot;ZFS root&amp;quot; wiki explains the details of running ZFS at your root filesystem by using a fully modular generic kernel approach. Now, I can share how it can be done with the SPL and ZFS modules built into the kernel. This procedure is just an example and can use some fine tuning, but here goes:&lt;br /&gt;
&lt;br /&gt;
The steps below are to create kernel with SPL and ZFS modules builtin. This kernel will be installed as an alternatve kernel to boot in lilo, and it will have a separate installation from the fully modular and working system. This will allow testing the builtin kernel while able to boot back onto a working modular ZFS system. We start this procedure assuming you are on a working fully modular ZFS install as in the &amp;quot;ZFS root&amp;quot; wiki.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=legacy zfs-root&lt;br /&gt;
# use legacy so zfs will not expect zfs mount, but instead expect standard mount for this fs&lt;br /&gt;
# edit /etc/rc.d/rc.S and rc.6 to use regular &amp;quot;mount&amp;quot; commands, remove &amp;quot;zfs&amp;quot; commands&lt;br /&gt;
# edit rc.6 and remove or comment out zfs export command&lt;br /&gt;
zpool set bootfs=zfs-root zfs-root&lt;br /&gt;
# this may help, but not really sure&lt;br /&gt;
&lt;br /&gt;
mkdir /boot/initramfs-source&lt;br /&gt;
# this will hold some files for rootfs inside kernel&lt;br /&gt;
&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir src&lt;br /&gt;
cd src&lt;br /&gt;
tar xvzf /mnt/cdrom/slackware64/k/kernel-source-*.txz&lt;br /&gt;
mv usr/src/linux-3.2.27 /usr/src/linux-3.2.27b&lt;br /&gt;
rm -r install&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make menuconfig&lt;br /&gt;
  General setup-&amp;gt;Local version - append to kernel release = b&lt;br /&gt;
  General setup-&amp;gt;Default hostname                         = slackzfs&lt;br /&gt;
  General setup-&amp;gt;Initramfs source files(s)                = /boot/initramfs-source&lt;br /&gt;
  #  make usre you made this directory or the kernel build fails&lt;br /&gt;
  Device Drivers-&amp;gt;SCSI device support-&amp;gt;SCSI low-level drivers-&amp;gt; &amp;lt;*&amp;gt; SYM53C8XX Version 2 SCSI support&lt;br /&gt;
  #  for qemu if=scsi -option-rom 8xx_64.rom,bootindex=1  hard disks&lt;br /&gt;
  # buildin any hard drive controllers etc that you need&lt;br /&gt;
  File systems -&amp;gt; &amp;lt;*&amp;gt; The Extended 4 (ext4) filesystem&lt;br /&gt;
  # /boot may use this ext4 fs&lt;br /&gt;
make prepare scripts&lt;br /&gt;
# this make command is what the spl and zfs copy-builtin scripts expect to be done before they are run&lt;br /&gt;
&lt;br /&gt;
cd ~/src&lt;br /&gt;
tar xvzf ~/spl-0.6.0-rc10.tar.gz&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-0.6.0-rc10&lt;br /&gt;
./configure \&lt;br /&gt;
    --prefix=/ \&lt;br /&gt;
    --libdir=/lib64 \&lt;br /&gt;
    --includedir=/usr/include \&lt;br /&gt;
    --datarootdir=/usr/share \&lt;br /&gt;
    --enable-linux-builtin=yes \&lt;br /&gt;
    --with-linux=/usr/src/linux-3.2.27b \&lt;br /&gt;
    --with-linux-obj=/usr/src/linux-3.2.27b&lt;br /&gt;
wget https://raw.github.com/zfsonlinux/spl/master/copy-builtin&lt;br /&gt;
chmod +x copy-builtin&lt;br /&gt;
./copy-builtin /usr/src/linux-3.2.27b&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../spl-0.6.0rc10_3.2.27b-x86_64-1root.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
&lt;br /&gt;
tar xvzf ~/zfs-0.6.0-rc10.tar.gz&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-0.6.0-rc10&lt;br /&gt;
./configure \&lt;br /&gt;
    --prefix=/ \&lt;br /&gt;
    --libdir=/lib64 \&lt;br /&gt;
    --includedir=/usr/include \&lt;br /&gt;
    --datarootdir=/usr/share \&lt;br /&gt;
    --enable-linux-builtin=yes \&lt;br /&gt;
    --with-linux=/usr/src/linux-3.2.27b \&lt;br /&gt;
    --with-linux-obj=/usr/src/linux-3.2.27b \&lt;br /&gt;
    --with-spl=/root/src/spl-0.6.0-rc10&lt;br /&gt;
wget https://raw.github.com/zfsonlinux/zfs/master/copy-builtin&lt;br /&gt;
chmod +x copy-builtin&lt;br /&gt;
./copy-builtin /usr/src/linux-3.2.27b&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../zfs-0.6.0rc10_3.2.27b-x86_64-1root.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
&lt;br /&gt;
### move zfs and spl modules inside kernel source to be at end of drivers:&lt;br /&gt;
### the order builtin modules init is the order they link into the kernel&lt;br /&gt;
### and we need zfs to init after all hard drive controllers&lt;br /&gt;
### zfs is more like a device driver layer over the lower-level hba drivers&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
mkdir drivers/zfsonlinux&lt;br /&gt;
mv spl drivers/zfsonlinux&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  # remove references to spl&lt;br /&gt;
vi Makefile&lt;br /&gt;
  # remove references to spl&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/fs&lt;br /&gt;
mv zfs ../drivers/zfsonlinux&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  # remove references to zfs&lt;br /&gt;
vi Makefile&lt;br /&gt;
  # remove references to zfs&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  )# add line at end of menu, before &amp;quot;endmenu&amp;quot;:&lt;br /&gt;
  )source &amp;quot;drivers/zfsonlinux/Kconfig&amp;quot;&lt;br /&gt;
  )endmenu&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers&lt;br /&gt;
vi Makefile&lt;br /&gt;
  )# add line at very end of file:&lt;br /&gt;
  )obj-$(CONFIG_ZFSONLINUX) += zfsonlinux/&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers/zfsonlinux&lt;br /&gt;
cat &amp;gt; Kconfig &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
menuconfig ZFSONLINUX&lt;br /&gt;
	tristate &amp;quot;ZFSonLinux support&amp;quot;&lt;br /&gt;
&lt;br /&gt;
if ZFSONLINUX&lt;br /&gt;
&lt;br /&gt;
source &amp;quot;drivers/zfsonlinux/spl/Kconifg&amp;quot;&lt;br /&gt;
&lt;br /&gt;
source &amp;quot;drivers/zfsonlinux/zfs/Kconifg&amp;quot;&lt;br /&gt;
&lt;br /&gt;
endif&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/zfsonlinux&lt;br /&gt;
cat &amp;gt; Makefile &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
obj-$(CONFIG_SPL) += spl/&lt;br /&gt;
obj-$(CONFIG_ZFS) += zfs/&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
### move complete&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make menuconfig&lt;br /&gt;
   Device Drivers -&amp;gt;&lt;br /&gt;
    &amp;lt;*&amp;gt; ZFSonLinux support -&amp;gt;&lt;br /&gt;
      &amp;lt;*&amp;gt; Solaris Porting Layer (SPL)&lt;br /&gt;
      &amp;lt;*&amp;gt;     ZFS&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
### prepare contents of initramfs&lt;br /&gt;
cd /boot/initramfs-source&lt;br /&gt;
&lt;br /&gt;
# make standard directories&lt;br /&gt;
mkdir -p proc dev sys mnt bin sbin etc/zfs&lt;br /&gt;
&lt;br /&gt;
# zfs seems to want mtab present, even if empty&lt;br /&gt;
touch etc/mtab&lt;br /&gt;
&lt;br /&gt;
# if zpool.cache file can be read by zfs at module init, it imports the pools in the cache&lt;br /&gt;
cp /etc/zfs/zpool.cache-initrd etc/zfs/zpool.cache&lt;br /&gt;
&lt;br /&gt;
# make initial console device node; otherwise, there is a problem at startup:&lt;br /&gt;
# &amp;quot;Warning: unable to open an initial console&amp;quot; and you'd have problems with console and tty login&lt;br /&gt;
# making these nodes from within /init is not early enough to avoid problem&lt;br /&gt;
mknod dev/console c 5 1   # system console&lt;br /&gt;
&lt;br /&gt;
# make memory device kmsg to &amp;quot;printk&amp;quot; kernel messages&lt;br /&gt;
# we can write to this file to send out messages&lt;br /&gt;
mknod dev/kmsg    c 1 11  # lines printed to kmsg enter kernel messages buffer&lt;br /&gt;
&lt;br /&gt;
# recommended loop0 device to mount fs images&lt;br /&gt;
mknod dev/loop0   b 7 0&lt;br /&gt;
&lt;br /&gt;
# make initial virtual terminal devices&lt;br /&gt;
mknod dev/tty     c 5 0   # current tty&lt;br /&gt;
mknod dev/tty0    c 4 0   # current virtual term&lt;br /&gt;
mknod dev/tty1    c 4 1   # login virtual term 1 (F1)&lt;br /&gt;
&lt;br /&gt;
# make alternative console=ttyS0 standard 8250/16550 UART serial port devices&lt;br /&gt;
#   useful with kernel parameter console=ttyS0&lt;br /&gt;
#          with qemu -nographic -option-rom sgabios.bin,bootindex=0&lt;br /&gt;
mknod dev/ttyS0   c 4 64  # COM1&lt;br /&gt;
mknod dev/ttyS1   c 4 65  # COM2&lt;br /&gt;
mknod dev/ttyS2   c 4 66  # COM3&lt;br /&gt;
mknod dev/ttyS3   c 4 67  $ COM4&lt;br /&gt;
&lt;br /&gt;
# this should be enough device nodes initially&lt;br /&gt;
# once devtmpfs mounts over /dev, a lot more is available in it by default&lt;br /&gt;
&lt;br /&gt;
cat &amp;gt; /init &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot; &amp;lt;some initial program PID=1 for the system to start on&amp;gt; EOF&lt;br /&gt;
# an initramfs-source/init program is required to mount and boot a root linux system&lt;br /&gt;
# the common way to make /init is using busybox with files like this:&lt;br /&gt;
#    /bin/busybox&lt;br /&gt;
#    /bin/ash -&amp;gt; busybox&lt;br /&gt;
#    /bin/sh -&amp;gt; busybox&lt;br /&gt;
#    # run busybox to see what other &amp;quot;applets&amp;quot; can be symlinked to it&lt;br /&gt;
#    # when busybox is run as a different symlinked applet name, it runs the applet&lt;br /&gt;
#    /init&lt;br /&gt;
#    # init is ash script, see slackware's /boot/initrd-tree/init for example&lt;br /&gt;
#    Inside this script:&lt;br /&gt;
#      1) parse kernel parameters passed into it and set variables based on them&lt;br /&gt;
#      2) start udevd and trigger rules for block devices to setup initial /dev devices&lt;br /&gt;
#      3) load kernel modules and keyboard map&lt;br /&gt;
#      4) run mdadm, cryptsetup, lvm, zpool/zfs to setup more devices&lt;br /&gt;
#         (any udev rules for them should do more /dev setup in the background)&lt;br /&gt;
#      5) mount the root filesystem read-only at /mnt&lt;br /&gt;
#      6) stat /mnt/sbin/init, and if not executable run a rescue shell /bin/sh&lt;br /&gt;
#      7) shutdown udevd so it can be restarted by root system when booted&lt;br /&gt;
#      8) mount --move {proc,sys,run,dev} to under /mnt&lt;br /&gt;
#      9) run: exec switch_root /mnt /sbin/init $RUNLEVEL&lt;br /&gt;
#    The slackware mkinitrd package is fully configured busybox installation&lt;br /&gt;
#      for an extern file initramfs initrd.gz image outside the kernel.&lt;br /&gt;
#    It could be changed to be inside the kernel easily by just using initrd-tree&lt;br /&gt;
#      as target of INITRAMFS_SOURCE in the kernel config and removing initrd in lilo.&lt;br /&gt;
&lt;br /&gt;
# Because the zfs modules are builtin, we really don't need busybox and the whole&lt;br /&gt;
# mkinitrd package. All we need to do is mount the zfs that is already imported&lt;br /&gt;
# because the zpool.cache is present in rootfs when the zfs module initializes, and&lt;br /&gt;
# then we do the switch root procedure to boot up on the mounted system.&lt;br /&gt;
# udevd rules will still be run when the root system starts udevd.&lt;br /&gt;
&lt;br /&gt;
# So, let's make a simple /init c program that will be all that we really need:&lt;br /&gt;
cat &amp;gt; init.c &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
/* software product name: foobarz-init.c&lt;br /&gt;
 * suggested binary name: /init (in initramfs-source, rootfs)&lt;br /&gt;
 * license              : BSD&lt;br /&gt;
 * license text:&lt;br /&gt;
Copyright (c) 2012, foobarz&lt;br /&gt;
All rights reserved.&lt;br /&gt;
&lt;br /&gt;
Redistribution and use in source and binary forms, with or without&lt;br /&gt;
modification, are permitted provided that the following conditions are met:&lt;br /&gt;
    * Redistributions of source code must retain the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer.&lt;br /&gt;
    * Redistributions in binary form must reproduce the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer in the&lt;br /&gt;
      documentation and/or other materials provided with the distribution.&lt;br /&gt;
    * Neither the name of the &amp;lt;organization&amp;gt; nor the&lt;br /&gt;
      names of its contributors may be used to endorse or promote products&lt;br /&gt;
      derived from this software without specific prior written permission.&lt;br /&gt;
&lt;br /&gt;
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &amp;quot;AS IS&amp;quot; AND&lt;br /&gt;
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED&lt;br /&gt;
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE&lt;br /&gt;
DISCLAIMED. IN NO EVENT SHALL &amp;lt;COPYRIGHT HOLDER&amp;gt; BE LIABLE FOR ANY&lt;br /&gt;
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES&lt;br /&gt;
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;&lt;br /&gt;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND&lt;br /&gt;
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT&lt;br /&gt;
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS&lt;br /&gt;
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#define FOOBARZ_INIT_VERSION &amp;quot;1.0.1&amp;quot;&lt;br /&gt;
#define _BSD_SOURCE&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/stat.h&amp;gt;&lt;br /&gt;
#include &amp;lt;fcntl.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/mount.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sysexits.h&amp;gt;&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/* Your initramfs-source should contain the following&lt;br /&gt;
 * cd /boot/initramfs-source&lt;br /&gt;
 * mkdir -p proc dev sys mnt bin sbin etc/zfs&lt;br /&gt;
 * touch etc/mtab&lt;br /&gt;
 * cp /etc/zfs/zpool.cache-initrd etc/zfs/zpool.cache&lt;br /&gt;
 * mknod dev/console c 5 1   # system console&lt;br /&gt;
 * mknod dev/kmsg    c 1 11  # lines printed to kmsg enter kernel messages buffer&lt;br /&gt;
 * mknod dev/loop0   b 7 0&lt;br /&gt;
 * mknod dev/tty     c 5 0   # current tty&lt;br /&gt;
 * mknod dev/tty0    c 4 0   # current virtual term&lt;br /&gt;
 * mknod dev/tty1    c 4 1   # login virtual term 1 (F1)&lt;br /&gt;
 * mknod dev/ttyS0   c 4 64  # COM1&lt;br /&gt;
 * mknod dev/ttyS1   c 4 65  # COM2&lt;br /&gt;
 * mknod dev/ttyS2   c 4 66  # COM3&lt;br /&gt;
 * mknod dev/ttyS3   c 4 67  $ COM4&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[]) {&lt;br /&gt;
 /***** variables&lt;br /&gt;
  *&lt;br /&gt;
  */&lt;br /&gt;
 int i;&lt;br /&gt;
 FILE* kmsg = NULL;&lt;br /&gt;
 int   fd = 0; /* file descriptor */&lt;br /&gt;
 unsigned long mountflags;&lt;br /&gt;
&lt;br /&gt;
 /* kernel command line */&lt;br /&gt;
 off_t cmdline_size;&lt;br /&gt;
 char* cmdline; /* to be malloc 4096B */&lt;br /&gt;
 char* cmdline_end;&lt;br /&gt;
 char* temp_end;&lt;br /&gt;
 int usage = EX_OK;&lt;br /&gt;
&lt;br /&gt;
 /* use to hold contents of a misc /proc/&amp;lt;file&amp;gt; */&lt;br /&gt;
 char* miscproc_buff; /* to be malloc 4096B */&lt;br /&gt;
 off_t miscproc_size;&lt;br /&gt;
&lt;br /&gt;
 /* note about environ, argv, and kernel cmdline for init:&lt;br /&gt;
  *   environ is not defined for init&lt;br /&gt;
  *   only argv[0] is set for init&lt;br /&gt;
  *   kernel command line parameters are accessed&lt;br /&gt;
  *   at /proc/cmdline&lt;br /&gt;
  */&lt;br /&gt;
&lt;br /&gt;
 /* kernel parameters expected to be name=value */&lt;br /&gt;
 /* do not use quotes or spaces in parameters   */&lt;br /&gt;
 /* you can add more params somwhere after root= */&lt;br /&gt;
 struct nv { char* n; char* v; char* v_end; int req; };&lt;br /&gt;
 struct nv param[] = {&lt;br /&gt;
   { &amp;quot;root=&amp;quot;, NULL, NULL, 1 },      /* required; root device to boot */&lt;br /&gt;
   { &amp;quot;rootfstype=&amp;quot;, NULL, NULL, 1 },    /* required; root filesystem type */&lt;br /&gt;
   { &amp;quot;mountopt=&amp;quot;, NULL, NULL, 0 },  /* optional; mount option ro or rw; default ro */&lt;br /&gt;
   { &amp;quot;init=&amp;quot;, NULL, NULL, 0 },      /* optional; alt. init prgm; default /sbin/init */&lt;br /&gt;
   { &amp;quot;runlevel=&amp;quot;, NULL, NULL, 0 },  /* optional; runlevel 0123456Ss; default 3 multiuser */&lt;br /&gt;
   { &amp;quot;console=&amp;quot;, NULL, NULL, 0 }          /* optional; alt. console; e.g. ttyS0 */&lt;br /&gt;
 };&lt;br /&gt;
 enum { iroot, irootfstype, imountopt, iinit, irunlevel, iconsole, ilastparam };&lt;br /&gt;
&lt;br /&gt;
 /***** program&lt;br /&gt;
  *&lt;br /&gt;
  */&lt;br /&gt;
 kmsg = fopen(&amp;quot;/dev/kmsg&amp;quot;, &amp;quot;w&amp;quot;);&lt;br /&gt;
 fprintf(kmsg, &amp;quot;foobarz-init, version %s: booting initramfs.\n&amp;quot;, FOOBARZ_INIT_VERSION);&lt;br /&gt;
&lt;br /&gt;
 cmdline = (char*) malloc(4096);&lt;br /&gt;
 miscproc_buff = (char*) malloc(4096);&lt;br /&gt;
 if( (cmdline == NULL) || (miscproc_buff == NULL) ) {&lt;br /&gt;
   fprintf(kmsg, &amp;quot;Unable to allocate buffer memory: malloc: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount proc before dev since some devices&lt;br /&gt;
  * symlink into proc */&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting mount proc /proc\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;proc&amp;quot;, &amp;quot;/proc&amp;quot;, &amp;quot;proc&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;Mount proc successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount devtmpfs as expected by an init program&lt;br /&gt;
  * and maybe required to mount zfs */&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting mount devtmpfs /dev\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;devtmpfs&amp;quot;, &amp;quot;/dev&amp;quot;, &amp;quot;devtmpfs&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;Mount devtmpfs successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
 /* it is assumed that all required devices are in devtmpfs&lt;br /&gt;
  * and if not, there will be boot problems&lt;br /&gt;
  *&lt;br /&gt;
  * if you need a more complex device setup, then you might need&lt;br /&gt;
  * udevd and run it with a larger full initrd package from your distro&lt;br /&gt;
  */&lt;br /&gt;
&lt;br /&gt;
 /* process kernel command line */&lt;br /&gt;
 fd = open(&amp;quot;/proc/cmdline&amp;quot;, O_RDONLY);&lt;br /&gt;
 if( fd == -1 ) {&lt;br /&gt;
   fprintf(kmsg, &amp;quot;Cannot open /proc/cmdline: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 /* note, on /proc fs:&lt;br /&gt;
  *       lseek likely always returns error&lt;br /&gt;
  *       stat likely always returns st_size = 0&lt;br /&gt;
  *   so determining size of /proc file means just reading it;&lt;br /&gt;
  *   you have to read /proc files according to their documented&lt;br /&gt;
  *   maximum sizes; this is probably for performance reasons */&lt;br /&gt;
 cmdline_size = read(fd, cmdline, 4095);&lt;br /&gt;
 if( cmdline_size == -1 ) {&lt;br /&gt;
   fprintf(kmsg, &amp;quot;Failed to read /proc/cmdline: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 close(fd);&lt;br /&gt;
&lt;br /&gt;
 /* cmdline may be newline + null terminated, but make it null + null */&lt;br /&gt;
 cmdline[cmdline_size] = '\0';&lt;br /&gt;
 if( cmdline[cmdline_size-1] == '\n' ) {&lt;br /&gt;
   cmdline[cmdline_size-1] = '\0';&lt;br /&gt;
   cmdline_size--;&lt;br /&gt;
   cmdline_end = cmdline + cmdline_size;&lt;br /&gt;
 }&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Kernel cmdline size: %i\n&amp;quot;, cmdline_size);&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Kernel cmdline: \&amp;quot;%s\&amp;quot;\n&amp;quot;, cmdline);&lt;br /&gt;
&lt;br /&gt;
 for( i=iroot; i&amp;lt;ilastparam; i++ ) {&lt;br /&gt;
   param[i].v = strstr(cmdline, param[i].n);&lt;br /&gt;
   if( param[i].v != NULL ) {&lt;br /&gt;
     while( *(param[i].v) != '=' ) param[i].v++;&lt;br /&gt;
     param[i].v++;&lt;br /&gt;
     temp_end = param[i].v;&lt;br /&gt;
     while( !( (*temp_end == ' ') ||&lt;br /&gt;
               (*temp_end == '\n') ||&lt;br /&gt;
               (temp_end == cmdline_end)&lt;br /&gt;
	     ) ) temp_end++;&lt;br /&gt;
     if( temp_end == param[i].v ) {&lt;br /&gt;
       fprintf(kmsg, &amp;quot;Kernel parameter %s: value missing.\n&amp;quot;, param[i].n);&lt;br /&gt;
     } else param[i].v_end = temp_end;&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* set defaults on non-required params, except for console */&lt;br /&gt;
 if( param[imountopt].v == NULL ) param[imountopt].v = &amp;quot;ro&amp;quot;;&lt;br /&gt;
 if( param[iinit].v == NULL )     param[iinit].v = &amp;quot;/sbin/init&amp;quot;;&lt;br /&gt;
 if( param[irunlevel].v == NULL ) param[irunlevel].v = &amp;quot;3&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
 for( i=iroot; i&amp;lt;ilastparam; i++ ) {&lt;br /&gt;
   if( param[i].v_end != NULL ) *(param[i].v_end) = '\0';&lt;br /&gt;
   fprintf(kmsg, &amp;quot;Using %s \&amp;quot;%s\&amp;quot;\n&amp;quot;, param[i].n, param[i].v);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 for( i=iroot; i&amp;lt;ilastparam; i++ ) {&lt;br /&gt;
   if( (param[i].req == 1) &amp;amp;&amp;amp; (param[i].v == NULL) ) {&lt;br /&gt;
     printf(&amp;quot;Error: missing required kernel parameter: %s\n&amp;quot;, param[i].n);&lt;br /&gt;
     usage = EX_USAGE;&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 if( usage != EX_OK ) {&lt;br /&gt;
   printf(&amp;quot;Aborting boot process. Missing required kernel parameter(s).\n&amp;quot;);&lt;br /&gt;
   return usage;&lt;br /&gt;
 }&lt;br /&gt;
 /* generic nv pair kernel cmdline processing finished&lt;br /&gt;
  *  now, examine specific params for defaults and correctness&lt;br /&gt;
  */&lt;br /&gt;
&lt;br /&gt;
 /* param[iroot]: nothing to do, if user put bad device in then we fail */&lt;br /&gt;
&lt;br /&gt;
 /* param[irootfstype]: can be checked against /proc/filesystems: */&lt;br /&gt;
 /* required, so should have value */&lt;br /&gt;
 fd = open(&amp;quot;/proc/filesystems&amp;quot;, O_RDONLY);&lt;br /&gt;
 if( fd == -1 ) {&lt;br /&gt;
   fprintf(kmsg, &amp;quot;Cannot open /proc/filesystems: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 miscproc_size = read(fd, miscproc_buff, 4095);&lt;br /&gt;
 if( miscproc_size == -1 ) {&lt;br /&gt;
   fprintf(kmsg, &amp;quot;Failed to read /proc/filesystems: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 close(fd);&lt;br /&gt;
 if( strstr(miscproc_buff, param[irootfstype].v) == NULL ) {&lt;br /&gt;
   fprintf(kmsg, &amp;quot;%s \&amp;quot;%s\&amp;quot;: filesystem type not available.\n&amp;quot;,&lt;br /&gt;
	   param[irootfstype].n, param[irootfstype].v);&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 if( strcmp(param[irootfstype].v, &amp;quot;zfs&amp;quot;) == 0 ) {&lt;br /&gt;
   if( access(&amp;quot;/etc/zfs/zpool.cache&amp;quot;, F_OK) == 0 )&lt;br /&gt;
     fprintf(kmsg, &amp;quot;%s: /etc/zfs/zpool.cache is present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
   else&lt;br /&gt;
     fprintf(kmsg, &amp;quot;%s: /etc/zfs/zpool.cache not present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
   if( access(&amp;quot;/etc/hostid&amp;quot;, F_OK) == 0 )&lt;br /&gt;
     fprintf(kmsg, &amp;quot;%s: /etc/hostid is present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
   else&lt;br /&gt;
     fprintf(kmsg, &amp;quot;%s: /etc/hostid not present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 if(      strcmp(param[imountopt].v, &amp;quot;ro&amp;quot;) == 0 ) mountflags = MS_RDONLY;&lt;br /&gt;
 else if( strcmp(param[imountopt].v, &amp;quot;rw&amp;quot;) == 0 ) mountflags = 0;&lt;br /&gt;
 else {&lt;br /&gt;
   fprintf(kmsg, &amp;quot;% \&amp;quot;%\&amp;quot;: invalid parameter value;\n&amp;quot;&lt;br /&gt;
		 &amp;quot;   use \&amp;quot;ro\&amp;quot; or \&amp;quot;rw\&amp;quot; (no quotes or spaces);\n&amp;quot;&lt;br /&gt;
		 &amp;quot;   defaulting to \&amp;quot;ro\&amp;quot;.\n&amp;quot;,&lt;br /&gt;
		 param[imountopt].n, param[imountopt].v&lt;br /&gt;
	  );&lt;br /&gt;
   mountflags = MS_RDONLY;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting %s %s mount %s /mnt.\n&amp;quot;,&lt;br /&gt;
	 param[irootfstype].v, param[imountopt].v, param[iroot].v);&lt;br /&gt;
 if( mount(param[iroot].v, &amp;quot;/mnt&amp;quot;, param[irootfstype].v, mountflags, NULL) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 fprintf(kmsg, &amp;quot;%s mounted successfully.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting mount --move /dev /mnt/dev\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/dev&amp;quot;, &amp;quot;/mnt/dev&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting mount --move /proc /mnt/proc\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/proc&amp;quot;, &amp;quot;/mnt/proc&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Beginning switch root procedure.\n&amp;quot;);&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting chdir from / to /mnt\n&amp;quot;);&lt;br /&gt;
 if( chdir(&amp;quot;/mnt&amp;quot;) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: chdir: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting mount-move . to /\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;.&amp;quot;, &amp;quot;/&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting chroot to .\n&amp;quot;);&lt;br /&gt;
 if( chroot(&amp;quot;.&amp;quot;) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: chroot: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting chdir to /\n&amp;quot;);&lt;br /&gt;
 if( chdir(&amp;quot;/&amp;quot;) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: chdir: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Completed switch root procedure.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 /* check for &amp;quot;console=&amp;quot; kernel parameter and switch&lt;br /&gt;
  *  stdin, stdout, and stderr to named console device&lt;br /&gt;
  */&lt;br /&gt;
 if( param[iconsole].v != NULL ) {&lt;br /&gt;
   fprintf(kmsg, &amp;quot;Console redirection to device %s requested.\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
   fprintf(kmsg, &amp;quot;Opening stdin, stdout, and stderr on %s.\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
   close(0);&lt;br /&gt;
   /* expect only basename of device (e.g., ttyS0), so chdir /dev */&lt;br /&gt;
   chdir(&amp;quot;/dev&amp;quot;);&lt;br /&gt;
   open(param[iconsole].v, O_RDWR);&lt;br /&gt;
   dup2(0, 1);&lt;br /&gt;
   dup2(0, 2);&lt;br /&gt;
   chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Execing: \&amp;quot;%s %s\&amp;quot; to boot mounted root system.\n&amp;quot;,&lt;br /&gt;
	 param[iinit].v, param[irunlevel].v);&lt;br /&gt;
&lt;br /&gt;
 /* free resources held to this point */&lt;br /&gt;
 fclose(kmsg);&lt;br /&gt;
 free(cmdline);&lt;br /&gt;
 free(miscproc_buff);&lt;br /&gt;
&lt;br /&gt;
 if( execl(param[iinit].v, param[irunlevel].v, (char *) NULL ) != 0 ) {&lt;br /&gt;
  kmsg = fopen(&amp;quot;/dev/kmsg&amp;quot;, &amp;quot;w&amp;quot;);&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: execl: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  fclose(kmsg);&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
EOF&lt;br /&gt;
## end of rootfs /init&lt;br /&gt;
&lt;br /&gt;
gcc --static init.c -o init&lt;br /&gt;
strip init&lt;br /&gt;
&lt;br /&gt;
## build and install kernel&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make -j8&lt;br /&gt;
make -j8 modules_install&lt;br /&gt;
cp arch/x86/boot/bzImage /boot/vm3.2.27b&lt;br /&gt;
cp System.map /boot/System.map-vm3.2.27b&lt;br /&gt;
# add new lilo menu entry for vm3.2.27b kernel&lt;br /&gt;
vi /etc/lilo.conf&lt;br /&gt;
  image = /boot/vm3.2.27b&lt;br /&gt;
   label = vm3.2.27b&lt;br /&gt;
   addappend = &amp;quot; spl.spl_hostid=0x007f0100 zfs.spa_config_path=/etc/zfs/zpool.cache root=zfs-root ro rootfstype=zfs rootwait &amp;quot;&lt;br /&gt;
lilo&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notes on kernel params (lilo append and addappend lines): root= and rootfstype= are used by both foorbarz-init and mkinitrd. The &amp;quot;ro&amp;quot; param is not used by foobarz-init, so instead use: mountopt=ro|rw. See &amp;quot;modinfo spl&amp;quot; and &amp;quot;modinfo zfs&amp;quot; to see all of the options those modules can take on the kernel command line.&lt;br /&gt;
&lt;br /&gt;
Notes on the spl and zfs packages to install: If you have errors using zfs and zpool commands on booted system with builtin modules, then upgrade/switch to the 0.6.0rc10_3.2.27b builds, or you can make a custom package with the binaries renamed like zpoolb, zfsb etc for builtin.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
Using qemu's -nographic serial console (/usr/share/qemu/sgabios.bin): If you have a boot problem, you might want to run in qemu's -nographic console mode:&lt;br /&gt;
&lt;br /&gt;
First, edit /etc/inittab, and uncomment the line for local serial ports runlevel &amp;quot;s1&amp;quot; (ttyS0) for serial console login support. This is done in the guest (host does not need this):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Local serial lines:&lt;br /&gt;
s1:12345:respawn:/sbin/agetty -L ttyS0 38400 linux&lt;br /&gt;
#s1:12345:respawn:/sbin/agetty -L ttyS0 9600 vt100&lt;br /&gt;
#s2:12345:respawn:/sbin/agetty -L ttyS1 9600 vt100&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Second, edit /etc/securetty, and uncomment ttyS0 line:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ttyS0&lt;br /&gt;
#ttyS1&lt;br /&gt;
# ...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
You cannot login on ttyS0 without this change even though you get the login prompt!&lt;br /&gt;
&lt;br /&gt;
Then, run qemu such as:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
qemu-kvm &amp;lt;all regular options&amp;gt; -nographic -option-rom sgabios.bin,bootindex=0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Wait for the lilo prompt, it may take several seconds show up in this mode.&lt;br /&gt;
&lt;br /&gt;
In the lilo menu, select your kernel image with builtin spl/zfs, and use kernel params such as:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
boot: vm3.2.27b console=ttyS0 runlevel=s1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
At the lilo prompt, use kernel parameter: console=ttyS0 (do NOT say /dev/ttS0).&lt;br /&gt;
&lt;br /&gt;
When you are in qemu's serial graphics mode, the interface is a little different than in the normal graphical SQL-based mode: use keypresses:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ctrl-a h    # for help&lt;br /&gt;
ctrl-a c    # toggle access to (QEMU) console / back to emulation&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If you cannot get a login: prompt, try ctrl-a c, then do (QEMU) sendkey ctrl-alt-delete. This will reboot cleanly back to lilo, then you can do (QEMU) quit.&lt;br /&gt;
&lt;br /&gt;
BECAREFUL not to start qemu twice on the same ZFS guest! Two simultaneous running qemu on the same ZFS will corrupt the pool and it will NOT recover - you lose your whole installation! Before running qemu, check ps -A, look for an already running qemu process incase it somehow entered into the background!&lt;br /&gt;
&lt;br /&gt;
BECAREFUL when using -nographic ttyS0 that you are not doing commands on the HOST! Only use -nographic to see kernel problems. Use regular console of booting is working normally.&lt;br /&gt;
&lt;br /&gt;
To use the qemu -drive if=scsi option, the linux module sym53c8xx should be loaded in the guest. You may need to use the qemu option:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-option-rom 8xx_64.rom,bootindex=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The file 8xx_64.com used to be inside qemu, but in new versions it is missing. You can download it:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
wget http://www.lsi.com/downloads/Public/Host%20Bus%20Adapters/Host%20Bus%20Adapters%20Common%20Files/lsi_bios.zip&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Extract the zip and place 8xx_64.rom in /usr/share/qemu/.&lt;br /&gt;
&lt;br /&gt;
Good luck!&lt;/div&gt;</description>
			<pubDate>Fri, 24 Aug 2012 03:32:59 GMT</pubDate>
			<dc:creator>Foobarz</dc:creator>
			<comments>https://www.slackwiki.com/Talk:ZFS_root_(builtin)</comments>
		</item>
		<item>
			<title>ZFS root (builtin)</title>
			<link>https://www.slackwiki.com/index.php?title=ZFS_root_(builtin)&amp;diff=748</link>
			<guid isPermaLink="false">https://www.slackwiki.com/index.php?title=ZFS_root_(builtin)&amp;diff=748</guid>
			<description>&lt;p&gt;Foobarz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Tutorials]]&lt;br /&gt;
The first &amp;quot;ZFS root&amp;quot; wiki explains the details of running ZFS at your root filesystem by using a fully modular generic kernel approach. Now, I can share how it can be done with the SPL and ZFS modules built into the kernel. This procedure is just an example and can use some fine tuning, but here goes:&lt;br /&gt;
&lt;br /&gt;
The steps below are to create kernel with SPL and ZFS modules builtin. This kernel will be installed as an alternatve kernel to boot in lilo, and it will have a separate installation from the fully modular and working system. This will allow testing the builtin kernel while able to boot back onto a working modular ZFS system. We start this procedure assuming you are on a working fully modular ZFS install as in the &amp;quot;ZFS root&amp;quot; wiki.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=legacy zfs-root&lt;br /&gt;
# use legacy so zfs will not expect zfs mount, but instead expect standard mount for this fs&lt;br /&gt;
# edit /etc/rc.d/rc.S and rc.6 to use regular &amp;quot;mount&amp;quot; commands, remove &amp;quot;zfs&amp;quot; commands&lt;br /&gt;
# edit rc.6 and remove or comment out zfs export command&lt;br /&gt;
zpool set bootfs=zfs-root zfs-root&lt;br /&gt;
# this may help, but not really sure&lt;br /&gt;
&lt;br /&gt;
mkdir /boot/initramfs-source&lt;br /&gt;
# this will hold some files for rootfs inside kernel&lt;br /&gt;
&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir src&lt;br /&gt;
cd src&lt;br /&gt;
tar xvzf /mnt/cdrom/slackware64/k/kernel-source-*.txz&lt;br /&gt;
mv usr/src/linux-3.2.27 /usr/src/linux-3.2.27b&lt;br /&gt;
rm -r install&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make menuconfig&lt;br /&gt;
  General setup-&amp;gt;Local version - append to kernel release = b&lt;br /&gt;
  General setup-&amp;gt;Default hostname                         = slackzfs&lt;br /&gt;
  General setup-&amp;gt;Initramfs source files(s)                = /boot/initramfs-source&lt;br /&gt;
  #  make usre you made this directory or the kernel build fails&lt;br /&gt;
  Device Drivers-&amp;gt;SCSI device support-&amp;gt;SCSI low-level drivers-&amp;gt; &amp;lt;*&amp;gt; SYM53C8XX Version 2 SCSI support&lt;br /&gt;
  #  for qemu if=scsi -option-rom 8xx_64.rom,bootindex=1  hard disks&lt;br /&gt;
  # buildin any hard drive controllers etc that you need&lt;br /&gt;
  File systems -&amp;gt; &amp;lt;*&amp;gt; The Extended 4 (ext4) filesystem&lt;br /&gt;
  # /boot may use this ext4 fs&lt;br /&gt;
make prepare scripts&lt;br /&gt;
# this make command is what the spl and zfs copy-builtin scripts expect to be done before they are run&lt;br /&gt;
&lt;br /&gt;
cd ~/src&lt;br /&gt;
tar xvzf ~/spl-0.6.0-rc10.tar.gz&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-0.6.0-rc10&lt;br /&gt;
./configure \&lt;br /&gt;
    --prefix=/ \&lt;br /&gt;
    --libdir=/lib64 \&lt;br /&gt;
    --includedir=/usr/include \&lt;br /&gt;
    --datarootdir=/usr/share \&lt;br /&gt;
    --enable-linux-builtin=yes \&lt;br /&gt;
    --with-linux=/usr/src/linux-3.2.27b \&lt;br /&gt;
    --with-linux-obj=/usr/src/linux-3.2.27b&lt;br /&gt;
wget https://raw.github.com/zfsonlinux/spl/master/copy-builtin&lt;br /&gt;
chmod +x copy-builtin&lt;br /&gt;
./copy-builtin /usr/src/linux-3.2.27b&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../spl-0.6.0rc10_3.2.27b-x86_64-1root.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
&lt;br /&gt;
tar xvzf ~/zfs-0.6.0-rc10.tar.gz&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-0.6.0-rc10&lt;br /&gt;
./configure \&lt;br /&gt;
    --prefix=/ \&lt;br /&gt;
    --libdir=/lib64 \&lt;br /&gt;
    --includedir=/usr/include \&lt;br /&gt;
    --datarootdir=/usr/share \&lt;br /&gt;
    --enable-linux-builtin=yes \&lt;br /&gt;
    --with-linux=/usr/src/linux-3.2.27b \&lt;br /&gt;
    --with-linux-obj=/usr/src/linux-3.2.27b \&lt;br /&gt;
    --with-spl=/root/src/spl-0.6.0-rc10&lt;br /&gt;
wget https://raw.github.com/zfsonlinux/zfs/master/copy-builtin&lt;br /&gt;
chmod +x copy-builtin&lt;br /&gt;
./copy-builtin /usr/src/linux-3.2.27b&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../zfs-0.6.0rc10_3.2.27b-x86_64-1root.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
&lt;br /&gt;
### move zfs and spl modules inside kernel source to be at end of drivers:&lt;br /&gt;
### the order builtin modules init is the order they link into the kernel&lt;br /&gt;
### and we need zfs to init after all hard drive controllers&lt;br /&gt;
### zfs is more like a device driver layer over the lower-level hba drivers&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
mkdir drivers/zfsonlinux&lt;br /&gt;
mv spl drivers/zfsonlinux&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  # remove references to spl&lt;br /&gt;
vi Makefile&lt;br /&gt;
  # remove references to spl&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/fs&lt;br /&gt;
mv zfs ../drivers/zfsonlinux&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  # remove references to zfs&lt;br /&gt;
vi Makefile&lt;br /&gt;
  # remove references to zfs&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  )# add line at end of menu, before &amp;quot;endmenu&amp;quot;:&lt;br /&gt;
  )source &amp;quot;drivers/zfsonlinux/Kconfig&amp;quot;&lt;br /&gt;
  )endmenu&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers&lt;br /&gt;
vi Makefile&lt;br /&gt;
  )# add line at very end of file:&lt;br /&gt;
  )obj-$(CONFIG_ZFSONLINUX) += zfsonlinux/&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers/zfsonlinux&lt;br /&gt;
cat &amp;gt; Kconfig &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
menuconfig ZFSONLINUX&lt;br /&gt;
	tristate &amp;quot;ZFSonLinux support&amp;quot;&lt;br /&gt;
&lt;br /&gt;
if ZFSONLINUX&lt;br /&gt;
&lt;br /&gt;
source &amp;quot;drivers/zfsonlinux/spl/Kconifg&amp;quot;&lt;br /&gt;
&lt;br /&gt;
source &amp;quot;drivers/zfsonlinux/zfs/Kconifg&amp;quot;&lt;br /&gt;
&lt;br /&gt;
endif&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/zfsonlinux&lt;br /&gt;
cat &amp;gt; Makefile &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
obj-$(CONFIG_SPL) += spl/&lt;br /&gt;
obj-$(CONFIG_ZFS) += zfs/&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
### move complete&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make menuconfig&lt;br /&gt;
   Device Drivers -&amp;gt;&lt;br /&gt;
    &amp;lt;*&amp;gt; ZFSonLinux support -&amp;gt;&lt;br /&gt;
      &amp;lt;*&amp;gt; Solaris Porting Layer (SPL)&lt;br /&gt;
      &amp;lt;*&amp;gt;     ZFS&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
### prepare contents of initramfs&lt;br /&gt;
cd /boot/initramfs-source&lt;br /&gt;
&lt;br /&gt;
# make standard directories&lt;br /&gt;
mkdir -p proc dev sys mnt bin sbin etc/zfs&lt;br /&gt;
&lt;br /&gt;
# zfs seems to want mtab present, even if empty&lt;br /&gt;
touch etc/mtab&lt;br /&gt;
&lt;br /&gt;
# if zpool.cache file can be read by zfs at module init, it imports the pools in the cache&lt;br /&gt;
cp /etc/zfs/zpool.cache-initrd etc/zfs/zpool.cache&lt;br /&gt;
&lt;br /&gt;
# make initial console device node; otherwise, there is a problem at startup:&lt;br /&gt;
# &amp;quot;Warning: unable to open an initial console&amp;quot; and you'd have problems with console and tty login&lt;br /&gt;
# making these nodes from within /init is not early enough to avoid problem&lt;br /&gt;
mknod dev/console c 5 1   # system console&lt;br /&gt;
&lt;br /&gt;
# make memory device kmsg to &amp;quot;printk&amp;quot; kernel messages&lt;br /&gt;
# we can write to this file to send out messages&lt;br /&gt;
mknod dev/kmsg    c 1 11  # lines printed to kmsg enter kernel messages buffer&lt;br /&gt;
&lt;br /&gt;
# recommended loop0 device to mount fs images&lt;br /&gt;
mknod dev/loop0   b 7 0&lt;br /&gt;
&lt;br /&gt;
# make initial virtual terminal devices&lt;br /&gt;
mknod dev/tty     c 5 0   # current tty&lt;br /&gt;
mknod dev/tty0    c 4 0   # current virtual term&lt;br /&gt;
mknod dev/tty1    c 4 1   # login virtual term 1 (F1)&lt;br /&gt;
&lt;br /&gt;
# make alternative console=ttyS0 standard 8250/16550 UART serial port devices&lt;br /&gt;
#   useful with kernel parameter console=ttyS0&lt;br /&gt;
#          with qemu -nographic -option-rom sgabios.bin,bootindex=0&lt;br /&gt;
mknod dev/ttyS0   c 4 64  # COM1&lt;br /&gt;
mknod dev/ttyS1   c 4 65  # COM2&lt;br /&gt;
mknod dev/ttyS2   c 4 66  # COM3&lt;br /&gt;
mknod dev/ttyS3   c 4 67  $ COM4&lt;br /&gt;
&lt;br /&gt;
# this should be enough device nodes initially&lt;br /&gt;
# once devtmpfs mounts over /dev, a lot more is available in it by default&lt;br /&gt;
&lt;br /&gt;
cat &amp;gt; /init &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot; &amp;lt;some initial program PID=1 for the system to start on&amp;gt; EOF&lt;br /&gt;
# an initramfs-source/init program is required to mount and boot a root linux system&lt;br /&gt;
# the common way to make /init is using busybox with files like this:&lt;br /&gt;
#    /bin/busybox&lt;br /&gt;
#    /bin/ash -&amp;gt; busybox&lt;br /&gt;
#    /bin/sh -&amp;gt; busybox&lt;br /&gt;
#    # run busybox to see what other &amp;quot;applets&amp;quot; can be symlinked to it&lt;br /&gt;
#    # when busybox is run as a different symlinked applet name, it runs the applet&lt;br /&gt;
#    /init&lt;br /&gt;
#    # init is ash script, see slackware's /boot/initrd-tree/init for example&lt;br /&gt;
#    Inside this script:&lt;br /&gt;
#      1) parse kernel parameters passed into it and set variables based on them&lt;br /&gt;
#      2) start udevd and trigger rules for block devices to setup initial /dev devices&lt;br /&gt;
#      3) load kernel modules and keyboard map&lt;br /&gt;
#      4) run mdadm, cryptsetup, lvm, zpool/zfs to setup more devices&lt;br /&gt;
#         (any udev rules for them should do more /dev setup in the background)&lt;br /&gt;
#      5) mount the root filesystem read-only at /mnt&lt;br /&gt;
#      6) stat /mnt/sbin/init, and if not executable run a rescue shell /bin/sh&lt;br /&gt;
#      7) shutdown udevd so it can be restarted by root system when booted&lt;br /&gt;
#      8) mount --move {proc,sys,run,dev} to under /mnt&lt;br /&gt;
#      9) run: exec switch_root /mnt /sbin/init $RUNLEVEL&lt;br /&gt;
#    The slackware mkinitrd package is fully configured busybox installation&lt;br /&gt;
#      for an extern file initramfs initrd.gz image outside the kernel.&lt;br /&gt;
#    It could be changed to be inside the kernel easily by just using initrd-tree&lt;br /&gt;
#      as target of INITRAMFS_SOURCE in the kernel config and removing initrd in lilo.&lt;br /&gt;
&lt;br /&gt;
# Because the zfs modules are builtin, we really don't need busybox and the whole&lt;br /&gt;
# mkinitrd package. All we need to do is mount the zfs that is already imported&lt;br /&gt;
# because the zpool.cache is present in rootfs when the zfs module initializes, and&lt;br /&gt;
# then we do the switch root procedure to boot up on the mounted system.&lt;br /&gt;
# udevd rules will still be run when the root system starts udevd.&lt;br /&gt;
&lt;br /&gt;
# So, let's make a simple /init c program that will be all that we really need:&lt;br /&gt;
cat &amp;gt; init.c &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
/* software product name: foobarz-init.c&lt;br /&gt;
 * suggested binary name: /init (in initramfs-source, rootfs)&lt;br /&gt;
 * license              : BSD&lt;br /&gt;
 * license text:&lt;br /&gt;
Copyright (c) 2012, foobarz&lt;br /&gt;
All rights reserved.&lt;br /&gt;
&lt;br /&gt;
Redistribution and use in source and binary forms, with or without&lt;br /&gt;
modification, are permitted provided that the following conditions are met:&lt;br /&gt;
    * Redistributions of source code must retain the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer.&lt;br /&gt;
    * Redistributions in binary form must reproduce the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer in the&lt;br /&gt;
      documentation and/or other materials provided with the distribution.&lt;br /&gt;
    * Neither the name of the &amp;lt;organization&amp;gt; nor the&lt;br /&gt;
      names of its contributors may be used to endorse or promote products&lt;br /&gt;
      derived from this software without specific prior written permission.&lt;br /&gt;
&lt;br /&gt;
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &amp;quot;AS IS&amp;quot; AND&lt;br /&gt;
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED&lt;br /&gt;
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE&lt;br /&gt;
DISCLAIMED. IN NO EVENT SHALL &amp;lt;COPYRIGHT HOLDER&amp;gt; BE LIABLE FOR ANY&lt;br /&gt;
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES&lt;br /&gt;
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;&lt;br /&gt;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND&lt;br /&gt;
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT&lt;br /&gt;
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS&lt;br /&gt;
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#define FOOBARZ_INIT_VERSION &amp;quot;1.0.1&amp;quot;&lt;br /&gt;
#define _BSD_SOURCE&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/stat.h&amp;gt;&lt;br /&gt;
#include &amp;lt;fcntl.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/mount.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sysexits.h&amp;gt;&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/* Your initramfs-source should contain the following&lt;br /&gt;
 * cd /boot/initramfs-source&lt;br /&gt;
 * mkdir -p proc dev sys mnt bin sbin etc/zfs&lt;br /&gt;
 * touch etc/mtab&lt;br /&gt;
 * cp /etc/zfs/zpool.cache-initrd etc/zfs/zpool.cache&lt;br /&gt;
 * mknod dev/console c 5 1   # system console&lt;br /&gt;
 * mknod dev/kmsg    c 1 11  # lines printed to kmsg enter kernel messages buffer&lt;br /&gt;
 * mknod dev/loop0   b 7 0&lt;br /&gt;
 * mknod dev/tty     c 5 0   # current tty&lt;br /&gt;
 * mknod dev/tty0    c 4 0   # current virtual term&lt;br /&gt;
 * mknod dev/tty1    c 4 1   # login virtual term 1 (F1)&lt;br /&gt;
 * mknod dev/ttyS0   c 4 64  # COM1&lt;br /&gt;
 * mknod dev/ttyS1   c 4 65  # COM2&lt;br /&gt;
 * mknod dev/ttyS2   c 4 66  # COM3&lt;br /&gt;
 * mknod dev/ttyS3   c 4 67  $ COM4&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[]) {&lt;br /&gt;
 /***** variables&lt;br /&gt;
  *&lt;br /&gt;
  */&lt;br /&gt;
 int i;&lt;br /&gt;
 FILE* kmsg = NULL;&lt;br /&gt;
 int   fd = 0; /* file descriptor */&lt;br /&gt;
 unsigned long mountflags;&lt;br /&gt;
&lt;br /&gt;
 /* kernel command line */&lt;br /&gt;
 off_t cmdline_size;&lt;br /&gt;
 char* cmdline; /* to be malloc 4096B */&lt;br /&gt;
 char* cmdline_end;&lt;br /&gt;
 char* temp_end;&lt;br /&gt;
 int usage = EX_OK;&lt;br /&gt;
&lt;br /&gt;
 /* use to hold contents of a misc /proc/&amp;lt;file&amp;gt; */&lt;br /&gt;
 char* miscproc_buff; /* to be malloc 4096B */&lt;br /&gt;
 off_t miscproc_size;&lt;br /&gt;
&lt;br /&gt;
 /* note about environ, argv, and kernel cmdline for init:&lt;br /&gt;
  *   environ is not defined for init&lt;br /&gt;
  *   only argv[0] is set for init&lt;br /&gt;
  *   kernel command line parameters are accessed&lt;br /&gt;
  *   at /proc/cmdline&lt;br /&gt;
  */&lt;br /&gt;
&lt;br /&gt;
 /* kernel parameters expected to be name=value */&lt;br /&gt;
 /* do not use quotes or spaces in parameters   */&lt;br /&gt;
 /* you can add more params somwhere after root= */&lt;br /&gt;
 struct nv { char* n; char* v; char* v_end; int req; };&lt;br /&gt;
 struct nv param[] = {&lt;br /&gt;
   { &amp;quot;root=&amp;quot;, NULL, NULL, 1 },      /* required; root device to boot */&lt;br /&gt;
   { &amp;quot;rootfstype=&amp;quot;, NULL, NULL, 1 },    /* required; root filesystem type */&lt;br /&gt;
   { &amp;quot;mountopt=&amp;quot;, NULL, NULL, 0 },  /* optional; mount option ro or rw; default ro */&lt;br /&gt;
   { &amp;quot;init=&amp;quot;, NULL, NULL, 0 },      /* optional; alt. init prgm; default /sbin/init */&lt;br /&gt;
   { &amp;quot;runlevel=&amp;quot;, NULL, NULL, 0 },  /* optional; runlevel 0123456Ss; default 3 multiuser */&lt;br /&gt;
   { &amp;quot;console=&amp;quot;, NULL, NULL, 0 }          /* optional; alt. console; e.g. ttyS0 */&lt;br /&gt;
 };&lt;br /&gt;
 enum { iroot, irootfstype, imountopt, iinit, irunlevel, iconsole, ilastparam };&lt;br /&gt;
&lt;br /&gt;
 /***** program&lt;br /&gt;
  *&lt;br /&gt;
  */&lt;br /&gt;
 kmsg = fopen(&amp;quot;/dev/kmsg&amp;quot;, &amp;quot;w&amp;quot;);&lt;br /&gt;
 fprintf(kmsg, &amp;quot;foobarz-init, version %s: booting initramfs.\n&amp;quot;, FOOBARZ_INIT_VERSION);&lt;br /&gt;
&lt;br /&gt;
 cmdline = (char*) malloc(4096);&lt;br /&gt;
 miscproc_buff = (char*) malloc(4096);&lt;br /&gt;
 if( (cmdline == NULL) || (miscproc_buff == NULL) ) {&lt;br /&gt;
   fprintf(kmsg, &amp;quot;Unable to allocate buffer memory: malloc: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount proc before dev since some devices&lt;br /&gt;
  * symlink into proc */&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting mount proc /proc\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;proc&amp;quot;, &amp;quot;/proc&amp;quot;, &amp;quot;proc&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;Mount proc successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount devtmpfs as expected by an init program&lt;br /&gt;
  * and maybe required to mount zfs */&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting mount devtmpfs /dev\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;devtmpfs&amp;quot;, &amp;quot;/dev&amp;quot;, &amp;quot;devtmpfs&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;Mount devtmpfs successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
 /* it is assumed that all required devices are in devtmpfs&lt;br /&gt;
  * and if not, there will be boot problems&lt;br /&gt;
  *&lt;br /&gt;
  * if you need a more complex device setup, then you might need&lt;br /&gt;
  * udevd and run it with a larger full initrd package from your distro&lt;br /&gt;
  */&lt;br /&gt;
&lt;br /&gt;
 /* process kernel command line */&lt;br /&gt;
 fd = open(&amp;quot;/proc/cmdline&amp;quot;, O_RDONLY);&lt;br /&gt;
 if( fd == -1 ) {&lt;br /&gt;
   fprintf(kmsg, &amp;quot;Cannot open /proc/cmdline: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 /* note, on /proc fs:&lt;br /&gt;
  *       lseek likely always returns error&lt;br /&gt;
  *       stat likely always returns st_size = 0&lt;br /&gt;
  *   so determining size of /proc file means just reading it;&lt;br /&gt;
  *   you have to read /proc files according to their documented&lt;br /&gt;
  *   maximum sizes; this is probably for performance reasons */&lt;br /&gt;
 cmdline_size = read(fd, cmdline, 4095);&lt;br /&gt;
 if( cmdline_size == -1 ) {&lt;br /&gt;
   fprintf(kmsg, &amp;quot;Failed to read /proc/cmdline: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 close(fd);&lt;br /&gt;
&lt;br /&gt;
 /* cmdline may be newline + null terminated, but make it null + null */&lt;br /&gt;
 cmdline[cmdline_size] = '\0';&lt;br /&gt;
 if( cmdline[cmdline_size-1] == '\n' ) {&lt;br /&gt;
   cmdline[cmdline_size-1] = '\0';&lt;br /&gt;
   cmdline_size--;&lt;br /&gt;
   cmdline_end = cmdline + cmdline_size;&lt;br /&gt;
 }&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Kernel cmdline size: %i\n&amp;quot;, cmdline_size);&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Kernel cmdline: \&amp;quot;%s\&amp;quot;\n&amp;quot;, cmdline);&lt;br /&gt;
&lt;br /&gt;
 for( i=iroot; i&amp;lt;ilastparam; i++ ) {&lt;br /&gt;
   param[i].v = strstr(cmdline, param[i].n);&lt;br /&gt;
   if( param[i].v != NULL ) {&lt;br /&gt;
     while( *(param[i].v) != '=' ) param[i].v++;&lt;br /&gt;
     param[i].v++;&lt;br /&gt;
     temp_end = param[i].v;&lt;br /&gt;
     while( !( (*temp_end == ' ') ||&lt;br /&gt;
               (*temp_end == '\n') ||&lt;br /&gt;
               (temp_end == cmdline_end)&lt;br /&gt;
	     ) ) temp_end++;&lt;br /&gt;
     if( temp_end == param[i].v ) {&lt;br /&gt;
       fprintf(kmsg, &amp;quot;Kernel parameter %s: value missing.\n&amp;quot;, param[i].n);&lt;br /&gt;
     } else param[i].v_end = temp_end;&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* set defaults on non-required params, except for console */&lt;br /&gt;
 if( param[imountopt].v == NULL ) param[imountopt].v = &amp;quot;ro&amp;quot;;&lt;br /&gt;
 if( param[iinit].v == NULL )     param[iinit].v = &amp;quot;/sbin/init&amp;quot;;&lt;br /&gt;
 if( param[irunlevel].v == NULL ) param[irunlevel].v = &amp;quot;3&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
 for( i=iroot; i&amp;lt;ilastparam; i++ ) {&lt;br /&gt;
   if( param[i].v_end != NULL ) *(param[i].v_end) = '\0';&lt;br /&gt;
   fprintf(kmsg, &amp;quot;Using %s \&amp;quot;%s\&amp;quot;\n&amp;quot;, param[i].n, param[i].v);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 for( i=iroot; i&amp;lt;ilastparam; i++ ) {&lt;br /&gt;
   if( (param[i].req == 1) &amp;amp;&amp;amp; (param[i].v == NULL) ) {&lt;br /&gt;
     printf(&amp;quot;Error: missing required kernel parameter: %s\n&amp;quot;, param[i].n);&lt;br /&gt;
     usage = EX_USAGE;&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 if( usage != EX_OK ) {&lt;br /&gt;
   printf(&amp;quot;Aborting boot process. Missing required kernel parameter(s).\n&amp;quot;);&lt;br /&gt;
   return usage;&lt;br /&gt;
 }&lt;br /&gt;
 /* generic nv pair kernel cmdline processing finished&lt;br /&gt;
  *  now, examine specific params for defaults and correctness&lt;br /&gt;
  */&lt;br /&gt;
&lt;br /&gt;
 /* param[iroot]: nothing to do, if user put bad device in then we fail */&lt;br /&gt;
&lt;br /&gt;
 /* param[irootfstype]: can be checked against /proc/filesystems: */&lt;br /&gt;
 /* required, so should have value */&lt;br /&gt;
 fd = open(&amp;quot;/proc/filesystems&amp;quot;, O_RDONLY);&lt;br /&gt;
 if( fd == -1 ) {&lt;br /&gt;
   fprintf(kmsg, &amp;quot;Cannot open /proc/filesystems: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 miscproc_size = read(fd, miscproc_buff, 4095);&lt;br /&gt;
 if( miscproc_size == -1 ) {&lt;br /&gt;
   fprintf(kmsg, &amp;quot;Failed to read /proc/filesystems: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 close(fd);&lt;br /&gt;
 if( strstr(miscproc_buff, param[irootfstype].v) == NULL ) {&lt;br /&gt;
   fprintf(kmsg, &amp;quot;%s \&amp;quot;%s\&amp;quot;: filesystem type not available.\n&amp;quot;,&lt;br /&gt;
	   param[irootfstype].n, param[irootfstype].v);&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 if( strcmp(param[irootfstype].v, &amp;quot;zfs&amp;quot;) == 0 ) {&lt;br /&gt;
   if( access(&amp;quot;/etc/zfs/zpool.cache&amp;quot;, F_OK) == 0 )&lt;br /&gt;
     fprintf(kmsg, &amp;quot;%s: /etc/zfs/zpool.cache is present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
   else&lt;br /&gt;
     fprintf(kmsg, &amp;quot;%s: /etc/zfs/zpool.cache not present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
   if( access(&amp;quot;/etc/hostid&amp;quot;, F_OK) == 0 )&lt;br /&gt;
     fprintf(kmsg, &amp;quot;%s: /etc/hostid is present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
   else&lt;br /&gt;
     fprintf(kmsg, &amp;quot;%s: /etc/hostid not present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 if(      strcmp(param[imountopt].v, &amp;quot;ro&amp;quot;) == 0 ) mountflags = MS_RDONLY;&lt;br /&gt;
 else if( strcmp(param[imountopt].v, &amp;quot;rw&amp;quot;) == 0 ) mountflags = 0;&lt;br /&gt;
 else {&lt;br /&gt;
   fprintf(kmsg, &amp;quot;% \&amp;quot;%\&amp;quot;: invalid parameter value;\n&amp;quot;&lt;br /&gt;
		 &amp;quot;   use \&amp;quot;ro\&amp;quot; or \&amp;quot;rw\&amp;quot; (no quotes or spaces);\n&amp;quot;&lt;br /&gt;
		 &amp;quot;   defaulting to \&amp;quot;ro\&amp;quot;.\n&amp;quot;,&lt;br /&gt;
		 param[imountopt].n, param[imountopt].v&lt;br /&gt;
	  );&lt;br /&gt;
   mountflags = MS_RDONLY;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting %s %s mount %s /mnt.\n&amp;quot;,&lt;br /&gt;
	 param[irootfstype].v, param[imountopt].v, param[iroot].v);&lt;br /&gt;
 if( mount(param[iroot].v, &amp;quot;/mnt&amp;quot;, param[irootfstype].v, mountflags, NULL) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 fprintf(kmsg, &amp;quot;%s mounted successfully.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting mount --move /dev /mnt/dev\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/dev&amp;quot;, &amp;quot;/mnt/dev&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting mount --move /proc /mnt/proc\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/proc&amp;quot;, &amp;quot;/mnt/proc&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Beginning switch root procedure.\n&amp;quot;);&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting chdir from / to /mnt\n&amp;quot;);&lt;br /&gt;
 if( chdir(&amp;quot;/mnt&amp;quot;) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: chdir: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting mount-move . to /\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;.&amp;quot;, &amp;quot;/&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting chroot to .\n&amp;quot;);&lt;br /&gt;
 if( chroot(&amp;quot;.&amp;quot;) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: chroot: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting chdir to /\n&amp;quot;);&lt;br /&gt;
 if( chdir(&amp;quot;/&amp;quot;) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: chdir: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Completed switch root procedure.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 /* check for &amp;quot;console=&amp;quot; kernel parameter and switch&lt;br /&gt;
  *  stdin, stdout, and stderr to named console device&lt;br /&gt;
  */&lt;br /&gt;
 if( param[iconsole].v != NULL ) {&lt;br /&gt;
   fprintf(kmsg, &amp;quot;Console redirection to device %s requested.\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
   fprintf(kmsg, &amp;quot;Opening stdin, stdout, and stderr on %s.\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
   close(0);&lt;br /&gt;
   /* expect only basename of device (e.g., ttyS0), so chdir /dev */&lt;br /&gt;
   chdir(&amp;quot;/dev&amp;quot;);&lt;br /&gt;
   open(param[iconsole].v, O_RDWR);&lt;br /&gt;
   dup2(0, 1);&lt;br /&gt;
   dup2(0, 2);&lt;br /&gt;
   chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Execing: \&amp;quot;%s %s\&amp;quot; to boot mounted root system.\n&amp;quot;,&lt;br /&gt;
	 param[iinit].v, param[irunlevel].v);&lt;br /&gt;
&lt;br /&gt;
 /* free resources held to this point */&lt;br /&gt;
 fclose(kmsg);&lt;br /&gt;
 free(cmdline);&lt;br /&gt;
 free(miscproc_buff);&lt;br /&gt;
&lt;br /&gt;
 if( execl(param[iinit].v, param[irunlevel].v, (char *) NULL ) != 0 ) {&lt;br /&gt;
  kmsg = fopen(&amp;quot;/dev/kmsg&amp;quot;, &amp;quot;w&amp;quot;);&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: execl: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  fclose(kmsg);&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
EOF&lt;br /&gt;
## end of rootfs /init&lt;br /&gt;
&lt;br /&gt;
gcc --static init.c -o init&lt;br /&gt;
strip init&lt;br /&gt;
&lt;br /&gt;
## build and install kernel&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make -j8&lt;br /&gt;
make -j8 modules_install&lt;br /&gt;
cp arch/x86/boot/bzImage /boot/vm3.2.27b&lt;br /&gt;
cp System.map /boot/System.map-vm3.2.27b&lt;br /&gt;
# add new lilo menu entry for vm3.2.27b kernel&lt;br /&gt;
vi /etc/lilo.conf&lt;br /&gt;
  image = /boot/vm3.2.27b&lt;br /&gt;
   label = vm3.2.27b&lt;br /&gt;
   addappend = &amp;quot; spl.spl_hostid=0x007f0100 zfs.spa_config_path=/etc/zfs/zpool.cache root=zfs-root ro rootfstype=zfs rootwait &amp;quot;&lt;br /&gt;
lilo&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notes on kernel params (lilo append and addappend lines): root= and rootfstype= are used by both foorbarz-init and mkinitrd. The &amp;quot;ro&amp;quot; param is not used by foobarz-init, so instead use: mountopt=ro|rw. See &amp;quot;modinfo spl&amp;quot; and &amp;quot;modinfo zfs&amp;quot; to see all of the options those modules can take on the kernel command line.&lt;br /&gt;
&lt;br /&gt;
Notes on the spl and zfs packages to install: If you have errors using zfs and zpool commands on booted system with builtin modules, then upgrade/switch to the 0.6.0rc10_3.2.27b builds, or you can make a custom package with the binaries renamed like zpoolb, zfsb etc for builtin.&lt;br /&gt;
&lt;br /&gt;
Using qemu's -nographic serial console (/usr/share/qemu/sgabios.bin): If you have a boot problem, you might want to run in qemu's -nographic console mode:&lt;br /&gt;
&lt;br /&gt;
First, edit /etc/inittab, and uncomment the line for local serial ports runlevels &amp;quot;s1&amp;quot; (ttyS0) and &amp;quot;s2&amp;quot; (ttyS1) for serial console login support. This is done in the guest (host does not need this):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Local serial lines:&lt;br /&gt;
s1:12345:respawn:/sbin/agetty -L ttyS0 9600 vt100&lt;br /&gt;
s2:12345:respawn:/sbin/agetty -L ttyS1 9600 vt100&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, run qemu such as:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
qemu-kvm &amp;lt;all regular options&amp;gt; -nographic -option-rom sgabios.bin,bootindex=0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Wait for the lilo prompt, it may take several seconds show up in this mode.&lt;br /&gt;
&lt;br /&gt;
In the lilo menu, select your kernel image with builtin spl/zfs, and use kernel params such as:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
boot: vm3.2.27b console=ttyS0 runlevel=s1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
At the lilo prompt, use kernel parameter: console=ttyS0 (do NOT say /dev/ttS0).&lt;br /&gt;
&lt;br /&gt;
When you are in qemu's serial graphics mode, the interface is a little different than in the normal graphical SQL-based mode: use keypresses:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ctrl-a h    # for help&lt;br /&gt;
ctrl-a c    # toggle access to (QEMU) console / back to emulation&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If you cannot get a login: prompt, try ctrl-a c, then do (QEMU) sendkey ctrl-alt-delete. This will reboot cleanly back to lilo, then you can do (QEMU) quit.&lt;br /&gt;
&lt;br /&gt;
BECAREFUL not to start qemu twice on the same ZFS guest! Two simultaneous running qemu on the same ZFS will corrupt the pool and it will NOT recover - you lose your whole installation! Before running qemu, check ps -A, look for an already running qemu process incase it somehow entered into the background!&lt;br /&gt;
&lt;br /&gt;
BECAREFUL when using -nographic ttyS0 that you are not doing commands on the HOST! Only use -nographic to see kernel problems. Use regular console of booting is working normally.&lt;br /&gt;
&lt;br /&gt;
To use the qemu -drive if=scsi option, the linux module sym53c8xx should be loaded in the guest. You may need to use the qemu option:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-option-rom 8xx_64.rom,bootindex=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The file 8xx_64.com used to be inside qemu, but in new versions it is missing. You can download it:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
wget http://www.lsi.com/downloads/Public/Host%20Bus%20Adapters/Host%20Bus%20Adapters%20Common%20Files/lsi_bios.zip&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Extract the zip and place 8xx_64.rom in /usr/share/qemu/.&lt;br /&gt;
&lt;br /&gt;
Good luck!&lt;/div&gt;</description>
			<pubDate>Fri, 24 Aug 2012 02:57:16 GMT</pubDate>
			<dc:creator>Foobarz</dc:creator>
			<comments>https://www.slackwiki.com/Talk:ZFS_root_(builtin)</comments>
		</item>
		<item>
			<title>ZFS root (builtin)</title>
			<link>https://www.slackwiki.com/index.php?title=ZFS_root_(builtin)&amp;diff=747</link>
			<guid isPermaLink="false">https://www.slackwiki.com/index.php?title=ZFS_root_(builtin)&amp;diff=747</guid>
			<description>&lt;p&gt;Foobarz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Tutorials]]&lt;br /&gt;
The first &amp;quot;ZFS root&amp;quot; wiki explains the details of running ZFS at your root filesystem by using a fully modular generic kernel approach. Now, I can share how it can be done with the SPL and ZFS modules built into the kernel. This procedure is just an example and can use some fine tuning, but here goes:&lt;br /&gt;
&lt;br /&gt;
The steps below are to create kernel with SPL and ZFS modules builtin. This kernel will be installed as an alternatve kernel to boot in lilo, and it will have a separate installation from the fully modular and working system. This will allow testing the builtin kernel while able to boot back onto a working modular ZFS system. We start this procedure assuming you are on a working fully modular ZFS install as in the &amp;quot;ZFS root&amp;quot; wiki.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=legacy zfs-root&lt;br /&gt;
# use legacy so zfs will not expect zfs mount, but instead expect standard mount for this fs&lt;br /&gt;
# edit /etc/rc.d/rc.S and rc.6 to use regular &amp;quot;mount&amp;quot; commands, remove &amp;quot;zfs&amp;quot; commands&lt;br /&gt;
# edit rc.6 and remove or comment out zfs export command&lt;br /&gt;
zpool set bootfs=zfs-root zfs-root&lt;br /&gt;
# this may help, but not really sure&lt;br /&gt;
&lt;br /&gt;
mkdir /boot/initramfs-source&lt;br /&gt;
# this will hold some files for rootfs inside kernel&lt;br /&gt;
&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir src&lt;br /&gt;
cd src&lt;br /&gt;
tar xvzf /mnt/cdrom/slackware64/k/kernel-source-*.txz&lt;br /&gt;
mv usr/src/linux-3.2.27 /usr/src/linux-3.2.27b&lt;br /&gt;
rm -r install&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make menuconfig&lt;br /&gt;
  General setup-&amp;gt;Local version - append to kernel release = b&lt;br /&gt;
  General setup-&amp;gt;Default hostname                         = slackzfs&lt;br /&gt;
  General setup-&amp;gt;Initramfs source files(s)                = /boot/initramfs-source&lt;br /&gt;
  #  make usre you made this directory or the kernel build fails&lt;br /&gt;
  Device Drivers-&amp;gt;SCSI device support-&amp;gt;SCSI low-level drivers-&amp;gt; &amp;lt;*&amp;gt; SYM53C8XX Version 2 SCSI support&lt;br /&gt;
  #  for qemu if=scsi -option-rom 8xx_64.rom,bootindex=1  hard disks&lt;br /&gt;
  # buildin any hard drive controllers etc that you need&lt;br /&gt;
  File systems -&amp;gt; &amp;lt;*&amp;gt; The Extended 4 (ext4) filesystem&lt;br /&gt;
  # /boot may use this ext4 fs&lt;br /&gt;
make prepare scripts&lt;br /&gt;
# this make command is what the spl and zfs copy-builtin scripts expect to be done before they are run&lt;br /&gt;
&lt;br /&gt;
cd ~/src&lt;br /&gt;
tar xvzf ~/spl-0.6.0-rc10.tar.gz&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-0.6.0-rc10&lt;br /&gt;
./configure \&lt;br /&gt;
    --prefix=/ \&lt;br /&gt;
    --libdir=/lib64 \&lt;br /&gt;
    --includedir=/usr/include \&lt;br /&gt;
    --datarootdir=/usr/share \&lt;br /&gt;
    --enable-linux-builtin=yes \&lt;br /&gt;
    --with-linux=/usr/src/linux-3.2.27b \&lt;br /&gt;
    --with-linux-obj=/usr/src/linux-3.2.27b&lt;br /&gt;
wget https://raw.github.com/zfsonlinux/spl/master/copy-builtin&lt;br /&gt;
chmod +x copy-builtin&lt;br /&gt;
./copy-builtin /usr/src/linux-3.2.27b&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../spl-0.6.0rc10_3.2.27b-x86_64-1root.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
&lt;br /&gt;
tar xvzf ~/zfs-0.6.0-rc10.tar.gz&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-0.6.0-rc10&lt;br /&gt;
./configure \&lt;br /&gt;
    --prefix=/ \&lt;br /&gt;
    --libdir=/lib64 \&lt;br /&gt;
    --includedir=/usr/include \&lt;br /&gt;
    --datarootdir=/usr/share \&lt;br /&gt;
    --enable-linux-builtin=yes \&lt;br /&gt;
    --with-linux=/usr/src/linux-3.2.27b \&lt;br /&gt;
    --with-linux-obj=/usr/src/linux-3.2.27b \&lt;br /&gt;
    --with-spl=/root/src/spl-0.6.0-rc10&lt;br /&gt;
wget https://raw.github.com/zfsonlinux/zfs/master/copy-builtin&lt;br /&gt;
chmod +x copy-builtin&lt;br /&gt;
./copy-builtin /usr/src/linux-3.2.27b&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../zfs-0.6.0rc10_3.2.27b-x86_64-1root.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
&lt;br /&gt;
### move zfs and spl modules inside kernel source to be at end of drivers:&lt;br /&gt;
### the order builtin modules init is the order they link into the kernel&lt;br /&gt;
### and we need zfs to init after all hard drive controllers&lt;br /&gt;
### zfs is more like a device driver layer over the lower-level hba drivers&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
mkdir drivers/zfsonlinux&lt;br /&gt;
mv spl drivers/zfsonlinux&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  # remove references to spl&lt;br /&gt;
vi Makefile&lt;br /&gt;
  # remove references to spl&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/fs&lt;br /&gt;
mv zfs ../drivers/zfsonlinux&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  # remove references to zfs&lt;br /&gt;
vi Makefile&lt;br /&gt;
  # remove references to zfs&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  )# add line at end of menu, before &amp;quot;endmenu&amp;quot;:&lt;br /&gt;
  )source &amp;quot;drivers/zfsonlinux/Kconfig&amp;quot;&lt;br /&gt;
  )endmenu&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers&lt;br /&gt;
vi Makefile&lt;br /&gt;
  )# add line at very end of file:&lt;br /&gt;
  )obj-$(CONFIG_ZFSONLINUX) += zfsonlinux/&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers/zfsonlinux&lt;br /&gt;
cat &amp;gt; Kconfig &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
menuconfig ZFSONLINUX&lt;br /&gt;
	tristate &amp;quot;ZFSonLinux support&amp;quot;&lt;br /&gt;
&lt;br /&gt;
if ZFSONLINUX&lt;br /&gt;
&lt;br /&gt;
source &amp;quot;drivers/zfsonlinux/spl/Kconifg&amp;quot;&lt;br /&gt;
&lt;br /&gt;
source &amp;quot;drivers/zfsonlinux/zfs/Kconifg&amp;quot;&lt;br /&gt;
&lt;br /&gt;
endif&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/zfsonlinux&lt;br /&gt;
cat &amp;gt; Makefile &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
obj-$(CONFIG_SPL) += spl/&lt;br /&gt;
obj-$(CONFIG_ZFS) += zfs/&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
### move complete&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make menuconfig&lt;br /&gt;
   Device Drivers -&amp;gt;&lt;br /&gt;
    &amp;lt;*&amp;gt; ZFSonLinux support -&amp;gt;&lt;br /&gt;
      &amp;lt;*&amp;gt; Solaris Porting Layer (SPL)&lt;br /&gt;
      &amp;lt;*&amp;gt;     ZFS&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
### prepare contents of initramfs&lt;br /&gt;
cd /boot/initramfs-source&lt;br /&gt;
&lt;br /&gt;
# make standard directories&lt;br /&gt;
mkdir -p proc dev sys mnt bin sbin etc/zfs&lt;br /&gt;
&lt;br /&gt;
# zfs seems to want mtab present, even if empty&lt;br /&gt;
touch etc/mtab&lt;br /&gt;
&lt;br /&gt;
# if zpool.cache file can be read by zfs at module init, it imports the pools in the cache&lt;br /&gt;
cp /etc/zfs/zpool.cache-initrd etc/zfs/zpool.cache&lt;br /&gt;
&lt;br /&gt;
# make initial console device node; otherwise, there is a problem at startup:&lt;br /&gt;
# &amp;quot;Warning: unable to open an initial console&amp;quot; and you'd have problems with console and tty login&lt;br /&gt;
# making these nodes from within /init is not early enough to avoid problem&lt;br /&gt;
mknod dev/console c 5 1   # system console&lt;br /&gt;
&lt;br /&gt;
# make memory device kmsg to &amp;quot;printk&amp;quot; kernel messages&lt;br /&gt;
# we can write to this file to send out messages&lt;br /&gt;
mknod dev/kmsg    c 1 11  # lines printed to kmsg enter kernel messages buffer&lt;br /&gt;
&lt;br /&gt;
# recommended loop0 device to mount fs images&lt;br /&gt;
mknod dev/loop0   b 7 0&lt;br /&gt;
&lt;br /&gt;
# make initial virtual terminal devices&lt;br /&gt;
mknod dev/tty     c 5 0   # current tty&lt;br /&gt;
mknod dev/tty0    c 4 0   # current virtual term&lt;br /&gt;
mknod dev/tty1    c 4 1   # login virtual term 1 (F1)&lt;br /&gt;
&lt;br /&gt;
# make alternative console=ttyS0 standard 8250/16550 UART serial port devices&lt;br /&gt;
#   useful with kernel parameter console=ttyS0&lt;br /&gt;
#          with qemu -nographic -option-rom sgabios.bin,bootindex=0&lt;br /&gt;
mknod dev/ttyS0   c 4 64  # COM1&lt;br /&gt;
mknod dev/ttyS1   c 4 65  # COM2&lt;br /&gt;
mknod dev/ttyS2   c 4 66  # COM3&lt;br /&gt;
mknod dev/ttyS3   c 4 67  $ COM4&lt;br /&gt;
&lt;br /&gt;
# this should be enough device nodes initially&lt;br /&gt;
# once devtmpfs mounts over /dev, a lot more is available in it by default&lt;br /&gt;
&lt;br /&gt;
cat &amp;gt; /init &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot; &amp;lt;some initial program PID=1 for the system to start on&amp;gt; EOF&lt;br /&gt;
# an initramfs-source/init program is required to mount and boot a root linux system&lt;br /&gt;
# the common way to make /init is using busybox with files like this:&lt;br /&gt;
#    /bin/busybox&lt;br /&gt;
#    /bin/ash -&amp;gt; busybox&lt;br /&gt;
#    /bin/sh -&amp;gt; busybox&lt;br /&gt;
#    # run busybox to see what other &amp;quot;applets&amp;quot; can be symlinked to it&lt;br /&gt;
#    # when busybox is run as a different symlinked applet name, it runs the applet&lt;br /&gt;
#    /init&lt;br /&gt;
#    # init is ash script, see slackware's /boot/initrd-tree/init for example&lt;br /&gt;
#    Inside this script:&lt;br /&gt;
#      1) parse kernel parameters passed into it and set variables based on them&lt;br /&gt;
#      2) start udevd and trigger rules for block devices to setup initial /dev devices&lt;br /&gt;
#      3) load kernel modules and keyboard map&lt;br /&gt;
#      4) run mdadm, cryptsetup, lvm, zpool/zfs to setup more devices&lt;br /&gt;
#         (any udev rules for them should do more /dev setup in the background)&lt;br /&gt;
#      5) mount the root filesystem read-only at /mnt&lt;br /&gt;
#      6) stat /mnt/sbin/init, and if not executable run a rescue shell /bin/sh&lt;br /&gt;
#      7) shutdown udevd so it can be restarted by root system when booted&lt;br /&gt;
#      8) mount --move {proc,sys,run,dev} to under /mnt&lt;br /&gt;
#      9) run: exec switch_root /mnt /sbin/init $RUNLEVEL&lt;br /&gt;
#    The slackware mkinitrd package is fully configured busybox installation&lt;br /&gt;
#      for an extern file initramfs initrd.gz image outside the kernel.&lt;br /&gt;
#    It could be changed to be inside the kernel easily by just using initrd-tree&lt;br /&gt;
#      as target of INITRAMFS_SOURCE in the kernel config and removing initrd in lilo.&lt;br /&gt;
&lt;br /&gt;
# Because the zfs modules are builtin, we really don't need busybox and the whole&lt;br /&gt;
# mkinitrd package. All we need to do is mount the zfs that is already imported&lt;br /&gt;
# because the zpool.cache is present in rootfs when the zfs module initializes, and&lt;br /&gt;
# then we do the switch root procedure to boot up on the mounted system.&lt;br /&gt;
# udevd rules will still be run when the root system starts udevd.&lt;br /&gt;
&lt;br /&gt;
# So, let's make a simple /init c program that will be all that we really need:&lt;br /&gt;
cat &amp;gt; init.c &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
/* software product name: foobarz-init.c&lt;br /&gt;
 * suggested binary name: /init (in initramfs-source, rootfs)&lt;br /&gt;
 * license              : BSD&lt;br /&gt;
 * license text:&lt;br /&gt;
Copyright (c) 2012, foobarz&lt;br /&gt;
All rights reserved.&lt;br /&gt;
&lt;br /&gt;
Redistribution and use in source and binary forms, with or without&lt;br /&gt;
modification, are permitted provided that the following conditions are met:&lt;br /&gt;
    * Redistributions of source code must retain the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer.&lt;br /&gt;
    * Redistributions in binary form must reproduce the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer in the&lt;br /&gt;
      documentation and/or other materials provided with the distribution.&lt;br /&gt;
    * Neither the name of the &amp;lt;organization&amp;gt; nor the&lt;br /&gt;
      names of its contributors may be used to endorse or promote products&lt;br /&gt;
      derived from this software without specific prior written permission.&lt;br /&gt;
&lt;br /&gt;
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &amp;quot;AS IS&amp;quot; AND&lt;br /&gt;
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED&lt;br /&gt;
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE&lt;br /&gt;
DISCLAIMED. IN NO EVENT SHALL &amp;lt;COPYRIGHT HOLDER&amp;gt; BE LIABLE FOR ANY&lt;br /&gt;
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES&lt;br /&gt;
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;&lt;br /&gt;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND&lt;br /&gt;
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT&lt;br /&gt;
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS&lt;br /&gt;
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#define FOOBARZ_INIT_VERSION &amp;quot;1.0.1&amp;quot;&lt;br /&gt;
#define _BSD_SOURCE&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/stat.h&amp;gt;&lt;br /&gt;
#include &amp;lt;fcntl.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/mount.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sysexits.h&amp;gt;&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/* Your initramfs-source should contain the following&lt;br /&gt;
 * cd /boot/initramfs-source&lt;br /&gt;
 * mkdir -p proc dev sys mnt bin sbin etc/zfs&lt;br /&gt;
 * touch etc/mtab&lt;br /&gt;
 * cp /etc/zfs/zpool.cache-initrd etc/zfs/zpool.cache&lt;br /&gt;
 * mknod dev/console c 5 1   # system console&lt;br /&gt;
 * mknod dev/kmsg    c 1 11  # lines printed to kmsg enter kernel messages buffer&lt;br /&gt;
 * mknod dev/loop0   b 7 0&lt;br /&gt;
 * mknod dev/tty     c 5 0   # current tty&lt;br /&gt;
 * mknod dev/tty0    c 4 0   # current virtual term&lt;br /&gt;
 * mknod dev/tty1    c 4 1   # login virtual term 1 (F1)&lt;br /&gt;
 * mknod dev/ttyS0   c 4 64  # COM1&lt;br /&gt;
 * mknod dev/ttyS1   c 4 65  # COM2&lt;br /&gt;
 * mknod dev/ttyS2   c 4 66  # COM3&lt;br /&gt;
 * mknod dev/ttyS3   c 4 67  $ COM4&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[]) {&lt;br /&gt;
 /***** variables&lt;br /&gt;
  *&lt;br /&gt;
  */&lt;br /&gt;
 int i;&lt;br /&gt;
 FILE* kmsg = NULL;&lt;br /&gt;
 int   fd = 0; /* file descriptor */&lt;br /&gt;
 unsigned long mountflags;&lt;br /&gt;
&lt;br /&gt;
 /* kernel command line */&lt;br /&gt;
 off_t cmdline_size;&lt;br /&gt;
 char* cmdline; /* to be malloc 4096B */&lt;br /&gt;
 char* cmdline_end;&lt;br /&gt;
 char* temp_end;&lt;br /&gt;
 int usage = EX_OK;&lt;br /&gt;
&lt;br /&gt;
 /* use to hold contents of a misc /proc/&amp;lt;file&amp;gt; */&lt;br /&gt;
 char* miscproc_buff; /* to be malloc 4096B */&lt;br /&gt;
 off_t miscproc_size;&lt;br /&gt;
&lt;br /&gt;
 /* note about environ, argv, and kernel cmdline for init:&lt;br /&gt;
  *   environ is not defined for init&lt;br /&gt;
  *   only argv[0] is set for init&lt;br /&gt;
  *   kernel command line parameters are accessed&lt;br /&gt;
  *   at /proc/cmdline&lt;br /&gt;
  */&lt;br /&gt;
&lt;br /&gt;
 /* kernel parameters expected to be name=value */&lt;br /&gt;
 /* do not use quotes or spaces in parameters   */&lt;br /&gt;
 /* you can add more params somwhere after root= */&lt;br /&gt;
 struct nv { char* n; char* v; char* v_end; int req; };&lt;br /&gt;
 struct nv param[] = {&lt;br /&gt;
   { &amp;quot;root=&amp;quot;, NULL, NULL, 1 },      /* required; root device to boot */&lt;br /&gt;
   { &amp;quot;rootfstype=&amp;quot;, NULL, NULL, 1 },    /* required; root filesystem type */&lt;br /&gt;
   { &amp;quot;mountopt=&amp;quot;, NULL, NULL, 0 },  /* optional; mount option ro or rw; default ro */&lt;br /&gt;
   { &amp;quot;init=&amp;quot;, NULL, NULL, 0 },      /* optional; alt. init prgm; default /sbin/init */&lt;br /&gt;
   { &amp;quot;runlevel=&amp;quot;, NULL, NULL, 0 },  /* optional; runlevel 0123456Ss; default 3 multiuser */&lt;br /&gt;
   { &amp;quot;console=&amp;quot;, NULL, NULL, 0 }          /* optional; alt. console; e.g. ttyS0 */&lt;br /&gt;
 };&lt;br /&gt;
 enum { iroot, irootfstype, imountopt, iinit, irunlevel, iconsole, ilastparam };&lt;br /&gt;
&lt;br /&gt;
 /***** program&lt;br /&gt;
  *&lt;br /&gt;
  */&lt;br /&gt;
 kmsg = fopen(&amp;quot;/dev/kmsg&amp;quot;, &amp;quot;w&amp;quot;);&lt;br /&gt;
 fprintf(kmsg, &amp;quot;foobarz-init, version %s: booting initramfs.\n&amp;quot;, FOOBARZ_INIT_VERSION);&lt;br /&gt;
&lt;br /&gt;
 cmdline = (char*) malloc(4096);&lt;br /&gt;
 miscproc_buff = (char*) malloc(4096);&lt;br /&gt;
 if( (cmdline == NULL) || (miscproc_buff == NULL) ) {&lt;br /&gt;
   fprintf(kmsg, &amp;quot;Unable to allocate buffer memory: malloc: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount proc before dev since some devices&lt;br /&gt;
  * symlink into proc */&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting mount proc /proc\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;proc&amp;quot;, &amp;quot;/proc&amp;quot;, &amp;quot;proc&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;Mount proc successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount devtmpfs as expected by an init program&lt;br /&gt;
  * and maybe required to mount zfs */&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting mount devtmpfs /dev\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;devtmpfs&amp;quot;, &amp;quot;/dev&amp;quot;, &amp;quot;devtmpfs&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;Mount devtmpfs successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
 /* it is assumed that all required devices are in devtmpfs&lt;br /&gt;
  * and if not, there will be boot problems&lt;br /&gt;
  *&lt;br /&gt;
  * if you need a more complex device setup, then you might need&lt;br /&gt;
  * udevd and run it with a larger full initrd package from your distro&lt;br /&gt;
  */&lt;br /&gt;
&lt;br /&gt;
 /* process kernel command line */&lt;br /&gt;
 fd = open(&amp;quot;/proc/cmdline&amp;quot;, O_RDONLY);&lt;br /&gt;
 if( fd == -1 ) {&lt;br /&gt;
   fprintf(kmsg, &amp;quot;Cannot open /proc/cmdline: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 /* note, on /proc fs:&lt;br /&gt;
  *       lseek likely always returns error&lt;br /&gt;
  *       stat likely always returns st_size = 0&lt;br /&gt;
  *   so determining size of /proc file means just reading it;&lt;br /&gt;
  *   you have to read /proc files according to their documented&lt;br /&gt;
  *   maximum sizes; this is probably for performance reasons */&lt;br /&gt;
 cmdline_size = read(fd, cmdline, 4095);&lt;br /&gt;
 if( cmdline_size == -1 ) {&lt;br /&gt;
   fprintf(kmsg, &amp;quot;Failed to read /proc/cmdline: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 close(fd);&lt;br /&gt;
&lt;br /&gt;
 /* cmdline may be newline + null terminated, but make it null + null */&lt;br /&gt;
 cmdline[cmdline_size] = '\0';&lt;br /&gt;
 if( cmdline[cmdline_size-1] == '\n' ) {&lt;br /&gt;
   cmdline[cmdline_size-1] = '\0';&lt;br /&gt;
   cmdline_size--;&lt;br /&gt;
   cmdline_end = cmdline + cmdline_size;&lt;br /&gt;
 }&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Kernel cmdline size: %i\n&amp;quot;, cmdline_size);&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Kernel cmdline: \&amp;quot;%s\&amp;quot;\n&amp;quot;, cmdline);&lt;br /&gt;
&lt;br /&gt;
 for( i=iroot; i&amp;lt;ilastparam; i++ ) {&lt;br /&gt;
   param[i].v = strstr(cmdline, param[i].n);&lt;br /&gt;
   if( param[i].v != NULL ) {&lt;br /&gt;
     while( *(param[i].v) != '=' ) param[i].v++;&lt;br /&gt;
     param[i].v++;&lt;br /&gt;
     temp_end = param[i].v;&lt;br /&gt;
     while( !( (*temp_end == ' ') ||&lt;br /&gt;
               (*temp_end == '\n') ||&lt;br /&gt;
               (temp_end == cmdline_end)&lt;br /&gt;
	     ) ) temp_end++;&lt;br /&gt;
     if( temp_end == param[i].v ) {&lt;br /&gt;
       fprintf(kmsg, &amp;quot;Kernel parameter %s: value missing.\n&amp;quot;, param[i].n);&lt;br /&gt;
     } else param[i].v_end = temp_end;&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* set defaults on non-required params, except for console */&lt;br /&gt;
 if( param[imountopt].v == NULL ) param[imountopt].v = &amp;quot;ro&amp;quot;;&lt;br /&gt;
 if( param[iinit].v == NULL )     param[iinit].v = &amp;quot;/sbin/init&amp;quot;;&lt;br /&gt;
 if( param[irunlevel].v == NULL ) param[irunlevel].v = &amp;quot;3&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
 for( i=iroot; i&amp;lt;ilastparam; i++ ) {&lt;br /&gt;
   if( param[i].v_end != NULL ) *(param[i].v_end) = '\0';&lt;br /&gt;
   fprintf(kmsg, &amp;quot;Using %s \&amp;quot;%s\&amp;quot;\n&amp;quot;, param[i].n, param[i].v);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 for( i=iroot; i&amp;lt;ilastparam; i++ ) {&lt;br /&gt;
   if( (param[i].req == 1) &amp;amp;&amp;amp; (param[i].v == NULL) ) {&lt;br /&gt;
     printf(&amp;quot;Error: missing required kernel parameter: %s\n&amp;quot;, param[i].n);&lt;br /&gt;
     usage = EX_USAGE;&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 if( usage != EX_OK ) {&lt;br /&gt;
   printf(&amp;quot;Aborting boot process. Missing required kernel parameter(s).\n&amp;quot;);&lt;br /&gt;
   return usage;&lt;br /&gt;
 }&lt;br /&gt;
 /* generic nv pair kernel cmdline processing finished&lt;br /&gt;
  *  now, examine specific params for defaults and correctness&lt;br /&gt;
  */&lt;br /&gt;
&lt;br /&gt;
 /* param[iroot]: nothing to do, if user put bad device in then we fail */&lt;br /&gt;
&lt;br /&gt;
 /* param[irootfstype]: can be checked against /proc/filesystems: */&lt;br /&gt;
 /* required, so should have value */&lt;br /&gt;
 fd = open(&amp;quot;/proc/filesystems&amp;quot;, O_RDONLY);&lt;br /&gt;
 if( fd == -1 ) {&lt;br /&gt;
   fprintf(kmsg, &amp;quot;Cannot open /proc/filesystems: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 miscproc_size = read(fd, miscproc_buff, 4095);&lt;br /&gt;
 if( miscproc_size == -1 ) {&lt;br /&gt;
   fprintf(kmsg, &amp;quot;Failed to read /proc/filesystems: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 close(fd);&lt;br /&gt;
 if( strstr(miscproc_buff, param[irootfstype].v) == NULL ) {&lt;br /&gt;
   fprintf(kmsg, &amp;quot;%s \&amp;quot;%s\&amp;quot;: filesystem type not available.\n&amp;quot;,&lt;br /&gt;
	   param[irootfstype].n, param[irootfstype].v);&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 if( strcmp(param[irootfstype].v, &amp;quot;zfs&amp;quot;) == 0 ) {&lt;br /&gt;
   if( access(&amp;quot;/etc/zfs/zpool.cache&amp;quot;, F_OK) == 0 )&lt;br /&gt;
     fprintf(kmsg, &amp;quot;%s: /etc/zfs/zpool.cache is present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
   else&lt;br /&gt;
     fprintf(kmsg, &amp;quot;%s: /etc/zfs/zpool.cache not present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
   if( access(&amp;quot;/etc/hostid&amp;quot;, F_OK) == 0 )&lt;br /&gt;
     fprintf(kmsg, &amp;quot;%s: /etc/hostid is present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
   else&lt;br /&gt;
     fprintf(kmsg, &amp;quot;%s: /etc/hostid not present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 if(      strcmp(param[imountopt].v, &amp;quot;ro&amp;quot;) == 0 ) mountflags = MS_RDONLY;&lt;br /&gt;
 else if( strcmp(param[imountopt].v, &amp;quot;rw&amp;quot;) == 0 ) mountflags = 0;&lt;br /&gt;
 else {&lt;br /&gt;
   fprintf(kmsg, &amp;quot;% \&amp;quot;%\&amp;quot;: invalid parameter value;\n&amp;quot;&lt;br /&gt;
		 &amp;quot;   use \&amp;quot;ro\&amp;quot; or \&amp;quot;rw\&amp;quot; (no quotes or spaces);\n&amp;quot;&lt;br /&gt;
		 &amp;quot;   defaulting to \&amp;quot;ro\&amp;quot;.\n&amp;quot;,&lt;br /&gt;
		 param[imountopt].n, param[imountopt].v&lt;br /&gt;
	  );&lt;br /&gt;
   mountflags = MS_RDONLY;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting %s %s mount %s /mnt.\n&amp;quot;,&lt;br /&gt;
	 param[irootfstype].v, param[imountopt].v, param[iroot].v);&lt;br /&gt;
 if( mount(param[iroot].v, &amp;quot;/mnt&amp;quot;, param[irootfstype].v, mountflags, NULL) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 fprintf(kmsg, &amp;quot;%s mounted successfully.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting mount --move /dev /mnt/dev\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/dev&amp;quot;, &amp;quot;/mnt/dev&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting mount --move /proc /mnt/proc\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/proc&amp;quot;, &amp;quot;/mnt/proc&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Beginning switch root procedure.\n&amp;quot;);&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting chdir from / to /mnt\n&amp;quot;);&lt;br /&gt;
 if( chdir(&amp;quot;/mnt&amp;quot;) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: chdir: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting mount-move . to /\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;.&amp;quot;, &amp;quot;/&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting chroot to .\n&amp;quot;);&lt;br /&gt;
 if( chroot(&amp;quot;.&amp;quot;) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: chroot: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting chdir to /\n&amp;quot;);&lt;br /&gt;
 if( chdir(&amp;quot;/&amp;quot;) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: chdir: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Completed switch root procedure.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 /* check for &amp;quot;console=&amp;quot; kernel parameter and switch&lt;br /&gt;
  *  stdin, stdout, and stderr to named console device&lt;br /&gt;
  */&lt;br /&gt;
 if( param[iconsole].v != NULL ) {&lt;br /&gt;
   fprintf(kmsg, &amp;quot;Console redirection to device %s requested.\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
   fprintf(kmsg, &amp;quot;Opening stdin, stdout, and stderr on %s.\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
   close(0);&lt;br /&gt;
   /* expect only basename of device (e.g., ttyS0), so chdir /dev */&lt;br /&gt;
   chdir(&amp;quot;/dev&amp;quot;);&lt;br /&gt;
   open(param[iconsole].v, O_RDWR);&lt;br /&gt;
   dup2(0, 1);&lt;br /&gt;
   dup2(0, 2);&lt;br /&gt;
   chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Execing: \&amp;quot;%s %s\&amp;quot; to boot mounted root system.\n&amp;quot;,&lt;br /&gt;
	 param[iinit].v, param[irunlevel].v);&lt;br /&gt;
&lt;br /&gt;
 /* free resources held to this point */&lt;br /&gt;
 fclose(kmsg);&lt;br /&gt;
 free(cmdline);&lt;br /&gt;
 free(miscproc_buff);&lt;br /&gt;
&lt;br /&gt;
 if( execl(param[iinit].v, param[irunlevel].v, (char *) NULL ) != 0 ) {&lt;br /&gt;
  kmsg = fopen(&amp;quot;/dev/kmsg&amp;quot;, &amp;quot;w&amp;quot;);&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: execl: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  fclose(kmsg);&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
EOF&lt;br /&gt;
## end of rootfs /init&lt;br /&gt;
&lt;br /&gt;
gcc --static init.c -o init&lt;br /&gt;
strip init&lt;br /&gt;
&lt;br /&gt;
## build and install kernel&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make -j8&lt;br /&gt;
make -j8 modules_install&lt;br /&gt;
cp arch/x86/boot/bzImage /boot/vm3.2.27b&lt;br /&gt;
cp System.map /boot/System.map-vm3.2.27b&lt;br /&gt;
# add new lilo menu entry for vm3.2.27b kernel&lt;br /&gt;
vi /etc/lilo.conf&lt;br /&gt;
  image = /boot/vm3.2.27b&lt;br /&gt;
   label = vm3.2.27b&lt;br /&gt;
   addappend = &amp;quot; spl.spl_hostid=0x007f0100 zfs.spa_config_path=/etc/zfs/zpool.cache root=zfs-root ro rootfstype=zfs rootwait &amp;quot;&lt;br /&gt;
lilo&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notes on kernel params (lilo append and addappend lines): root= and rootfstype= are used by both foorbarz-init and mkinitrd. The &amp;quot;ro&amp;quot; param is not used by foobarz-init, so instead use: mountopt=ro|rw. See &amp;quot;modinfo spl&amp;quot; and &amp;quot;modinfo zfs&amp;quot; to see all of the options those modules can take on the kernel command line.&lt;br /&gt;
&lt;br /&gt;
Notes on the spl and zfs packages to install: If you have errors using zfs and zpool commands on booted system with builtin modules, then upgrade/switch to the 0.6.0rc10_3.2.27b builds, or you can make a custom package with the binaries renamed like zpoolb, zfsb etc for builtin.&lt;br /&gt;
&lt;br /&gt;
Using qemu's -nographic serial console (/usr/share/qemu/sgabios.bin): If you have a boot problem, you might want to run in qemu's -nographic console mode:&lt;br /&gt;
&lt;br /&gt;
First, edit /etc/inittab, and uncomment the line for local serial ports runlevels &amp;quot;s1&amp;quot; (ttyS0) and &amp;quot;s2&amp;quot; (ttyS1) for serial console login support:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Local serial lines:&lt;br /&gt;
s1:12345:respawn:/sbin/agetty -L ttyS0 9600 vt100&lt;br /&gt;
s2:12345:respawn:/sbin/agetty -L ttyS1 9600 vt100&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, run qemu such as:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
qemu-kvm &amp;lt;all regular options&amp;gt; -nographic -option-rom sgabios.bin,bootindex=0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Wait for the lilo prompt, it may take several seconds show up in this mode.&lt;br /&gt;
&lt;br /&gt;
In the lilo menu, select your kernel image with builtin spl/zfs, and use kernel params such as:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
boot: vm3.2.27b console=ttyS0 runlevel=s1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
At the lilo prompt, use kernel parameter: console=ttyS0 (do NOT say /dev/ttS0).&lt;br /&gt;
&lt;br /&gt;
When you are in qemu's serial graphics mode, the interface is a little different than in the normal graphical SQL-based mode: use keypresses:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ctrl-a h    # for help&lt;br /&gt;
ctrl-a c    # toggle access to (QEMU) console / back to emulation&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If you cannot get a login: prompt, try ctrl-a c, then do (QEMU) sendkey ctrl-alt-delete. This will reboot cleanly back to lilo, then you can do (QEMU) quit.&lt;br /&gt;
&lt;br /&gt;
BECAREFUL not to start qemu twice on the same ZFS guest! Two simultaneous running qemu on the same ZFS will corrupt the pool and it will NOT recover - you lose your whole installation! Before running qemu, check ps -A, look for an already running qemu process incase it somehow entered into the background!&lt;br /&gt;
&lt;br /&gt;
BECAREFUL when using -nographic ttyS0 that you are not doing commands on the HOST! Only use -nographic to see kernel problems. Use regular console of booting is working normally.&lt;br /&gt;
&lt;br /&gt;
To use the qemu -drive if=scsi option, the linux module sym53c8xx should be loaded in the guest. You may need to use the qemu option:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-option-rom 8xx_64.rom,bootindex=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The file 8xx_64.com used to be inside qemu, but in new versions it is missing. You can download it:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
wget http://www.lsi.com/downloads/Public/Host%20Bus%20Adapters/Host%20Bus%20Adapters%20Common%20Files/lsi_bios.zip&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Extract the zip and place 8xx_64.rom in /usr/share/qemu/.&lt;br /&gt;
&lt;br /&gt;
Good luck!&lt;/div&gt;</description>
			<pubDate>Fri, 24 Aug 2012 02:55:37 GMT</pubDate>
			<dc:creator>Foobarz</dc:creator>
			<comments>https://www.slackwiki.com/Talk:ZFS_root_(builtin)</comments>
		</item>
		<item>
			<title>ZFS root (builtin)</title>
			<link>https://www.slackwiki.com/index.php?title=ZFS_root_(builtin)&amp;diff=746</link>
			<guid isPermaLink="false">https://www.slackwiki.com/index.php?title=ZFS_root_(builtin)&amp;diff=746</guid>
			<description>&lt;p&gt;Foobarz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Tutorials]]&lt;br /&gt;
The first &amp;quot;ZFS root&amp;quot; wiki explains the details of running ZFS at your root filesystem by using a fully modular generic kernel approach. Now, I can share how it can be done with the SPL and ZFS modules built into the kernel. This procedure is just an example and can use some fine tuning, but here goes:&lt;br /&gt;
&lt;br /&gt;
The steps below are to create kernel with SPL and ZFS modules builtin. This kernel will be installed as an alternatve kernel to boot in lilo, and it will have a separate installation from the fully modular and working system. This will allow testing the builtin kernel while able to boot back onto a working modular ZFS system. We start this procedure assuming you are on a working fully modular ZFS install as in the &amp;quot;ZFS root&amp;quot; wiki.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=legacy zfs-root&lt;br /&gt;
# use legacy so zfs will not expect zfs mount, but instead expect standard mount for this fs&lt;br /&gt;
# edit /etc/rc.d/rc.S and rc.6 to use regular &amp;quot;mount&amp;quot; commands, remove &amp;quot;zfs&amp;quot; commands&lt;br /&gt;
# edit rc.6 and remove or comment out zfs export command&lt;br /&gt;
zpool set bootfs=zfs-root zfs-root&lt;br /&gt;
# this may help, but not really sure&lt;br /&gt;
&lt;br /&gt;
mkdir /boot/initramfs-source&lt;br /&gt;
# this will hold some files for rootfs inside kernel&lt;br /&gt;
&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir src&lt;br /&gt;
cd src&lt;br /&gt;
tar xvzf /mnt/cdrom/slackware64/k/kernel-source-*.txz&lt;br /&gt;
mv usr/src/linux-3.2.27 /usr/src/linux-3.2.27b&lt;br /&gt;
rm -r install&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make menuconfig&lt;br /&gt;
  General setup-&amp;gt;Local version - append to kernel release = b&lt;br /&gt;
  General setup-&amp;gt;Default hostname                         = slackzfs&lt;br /&gt;
  General setup-&amp;gt;Initramfs source files(s)                = /boot/initramfs-source&lt;br /&gt;
  #  make usre you made this directory or the kernel build fails&lt;br /&gt;
  Device Drivers-&amp;gt;SCSI device support-&amp;gt;SCSI low-level drivers-&amp;gt; &amp;lt;*&amp;gt; SYM53C8XX Version 2 SCSI support&lt;br /&gt;
  #  for qemu if=scsi -option-rom 8xx_64.rom,bootindex=1  hard disks&lt;br /&gt;
  # buildin any hard drive controllers etc that you need&lt;br /&gt;
  File systems -&amp;gt; &amp;lt;*&amp;gt; The Extended 4 (ext4) filesystem&lt;br /&gt;
  # /boot may use this ext4 fs&lt;br /&gt;
make prepare scripts&lt;br /&gt;
# this make command is what the spl and zfs copy-builtin scripts expect to be done before they are run&lt;br /&gt;
&lt;br /&gt;
cd ~/src&lt;br /&gt;
tar xvzf ~/spl-0.6.0-rc10.tar.gz&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-0.6.0-rc10&lt;br /&gt;
./configure \&lt;br /&gt;
    --prefix=/ \&lt;br /&gt;
    --libdir=/lib64 \&lt;br /&gt;
    --includedir=/usr/include \&lt;br /&gt;
    --datarootdir=/usr/share \&lt;br /&gt;
    --enable-linux-builtin=yes \&lt;br /&gt;
    --with-linux=/usr/src/linux-3.2.27b \&lt;br /&gt;
    --with-linux-obj=/usr/src/linux-3.2.27b&lt;br /&gt;
wget https://raw.github.com/zfsonlinux/spl/master/copy-builtin&lt;br /&gt;
chmod +x copy-builtin&lt;br /&gt;
./copy-builtin /usr/src/linux-3.2.27b&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../spl-0.6.0rc10_3.2.27b-x86_64-1root.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
&lt;br /&gt;
tar xvzf ~/zfs-0.6.0-rc10.tar.gz&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-0.6.0-rc10&lt;br /&gt;
./configure \&lt;br /&gt;
    --prefix=/ \&lt;br /&gt;
    --libdir=/lib64 \&lt;br /&gt;
    --includedir=/usr/include \&lt;br /&gt;
    --datarootdir=/usr/share \&lt;br /&gt;
    --enable-linux-builtin=yes \&lt;br /&gt;
    --with-linux=/usr/src/linux-3.2.27b \&lt;br /&gt;
    --with-linux-obj=/usr/src/linux-3.2.27b \&lt;br /&gt;
    --with-spl=/root/src/spl-0.6.0-rc10&lt;br /&gt;
wget https://raw.github.com/zfsonlinux/zfs/master/copy-builtin&lt;br /&gt;
chmod +x copy-builtin&lt;br /&gt;
./copy-builtin /usr/src/linux-3.2.27b&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../zfs-0.6.0rc10_3.2.27b-x86_64-1root.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
&lt;br /&gt;
### move zfs and spl modules inside kernel source to be at end of drivers:&lt;br /&gt;
### the order builtin modules init is the order they link into the kernel&lt;br /&gt;
### and we need zfs to init after all hard drive controllers&lt;br /&gt;
### zfs is more like a device driver layer over the lower-level hba drivers&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
mkdir drivers/zfsonlinux&lt;br /&gt;
mv spl drivers/zfsonlinux&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  # remove references to spl&lt;br /&gt;
vi Makefile&lt;br /&gt;
  # remove references to spl&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/fs&lt;br /&gt;
mv zfs ../drivers/zfsonlinux&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  # remove references to zfs&lt;br /&gt;
vi Makefile&lt;br /&gt;
  # remove references to zfs&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  )# add line at end of menu, before &amp;quot;endmenu&amp;quot;:&lt;br /&gt;
  )source &amp;quot;drivers/zfsonlinux/Kconfig&amp;quot;&lt;br /&gt;
  )endmenu&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers&lt;br /&gt;
vi Makefile&lt;br /&gt;
  )# add line at very end of file:&lt;br /&gt;
  )obj-$(CONFIG_ZFSONLINUX) += zfsonlinux/&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers/zfsonlinux&lt;br /&gt;
cat &amp;gt; Kconfig &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
menuconfig ZFSONLINUX&lt;br /&gt;
	tristate &amp;quot;ZFSonLinux support&amp;quot;&lt;br /&gt;
&lt;br /&gt;
if ZFSONLINUX&lt;br /&gt;
&lt;br /&gt;
source &amp;quot;drivers/zfsonlinux/spl/Kconifg&amp;quot;&lt;br /&gt;
&lt;br /&gt;
source &amp;quot;drivers/zfsonlinux/zfs/Kconifg&amp;quot;&lt;br /&gt;
&lt;br /&gt;
endif&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/zfsonlinux&lt;br /&gt;
cat &amp;gt; Makefile &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
obj-$(CONFIG_SPL) += spl/&lt;br /&gt;
obj-$(CONFIG_ZFS) += zfs/&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
### move complete&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make menuconfig&lt;br /&gt;
   Device Drivers -&amp;gt;&lt;br /&gt;
    &amp;lt;*&amp;gt; ZFSonLinux support -&amp;gt;&lt;br /&gt;
      &amp;lt;*&amp;gt; Solaris Porting Layer (SPL)&lt;br /&gt;
      &amp;lt;*&amp;gt;     ZFS&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
### prepare contents of initramfs&lt;br /&gt;
cd /boot/initramfs-source&lt;br /&gt;
&lt;br /&gt;
# make standard directories&lt;br /&gt;
mkdir -p proc dev sys mnt bin sbin etc/zfs&lt;br /&gt;
&lt;br /&gt;
# zfs seems to want mtab present, even if empty&lt;br /&gt;
touch etc/mtab&lt;br /&gt;
&lt;br /&gt;
# if zpool.cache file can be read by zfs at module init, it imports the pools in the cache&lt;br /&gt;
cp /etc/zfs/zpool.cache-initrd etc/zfs/zpool.cache&lt;br /&gt;
&lt;br /&gt;
# make initial console device node; otherwise, there is a problem at startup:&lt;br /&gt;
# &amp;quot;Warning: unable to open an initial console&amp;quot; and you'd have problems with console and tty login&lt;br /&gt;
# making these nodes from within /init is not early enough to avoid problem&lt;br /&gt;
mknod dev/console c 5 1   # system console&lt;br /&gt;
&lt;br /&gt;
# make memory device kmsg to &amp;quot;printk&amp;quot; kernel messages&lt;br /&gt;
# we can write to this file to send out messages&lt;br /&gt;
mknod dev/kmsg    c 1 11  # lines printed to kmsg enter kernel messages buffer&lt;br /&gt;
&lt;br /&gt;
# recommended loop0 device to mount fs images&lt;br /&gt;
mknod dev/loop0   b 7 0&lt;br /&gt;
&lt;br /&gt;
# make initial virtual terminal devices&lt;br /&gt;
mknod dev/tty     c 5 0   # current tty&lt;br /&gt;
mknod dev/tty0    c 4 0   # current virtual term&lt;br /&gt;
mknod dev/tty1    c 4 1   # login virtual term 1 (F1)&lt;br /&gt;
&lt;br /&gt;
# make alternative console=ttyS0 standard 8250/16550 UART serial port devices&lt;br /&gt;
#   useful with kernel parameter console=ttyS0&lt;br /&gt;
#          with qemu -nographic -option-rom sgabios.bin,bootindex=0&lt;br /&gt;
mknod dev/ttyS0   c 4 64  # COM1&lt;br /&gt;
mknod dev/ttyS1   c 4 65  # COM2&lt;br /&gt;
mknod dev/ttyS2   c 4 66  # COM3&lt;br /&gt;
mknod dev/ttyS3   c 4 67  $ COM4&lt;br /&gt;
&lt;br /&gt;
# this should be enough device nodes initially&lt;br /&gt;
# once devtmpfs mounts over /dev, a lot more is available in it by default&lt;br /&gt;
&lt;br /&gt;
cat &amp;gt; /init &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot; &amp;lt;some initial program PID=1 for the system to start on&amp;gt; EOF&lt;br /&gt;
# an initramfs-source/init program is required to mount and boot a root linux system&lt;br /&gt;
# the common way to make /init is using busybox with files like this:&lt;br /&gt;
#    /bin/busybox&lt;br /&gt;
#    /bin/ash -&amp;gt; busybox&lt;br /&gt;
#    /bin/sh -&amp;gt; busybox&lt;br /&gt;
#    # run busybox to see what other &amp;quot;applets&amp;quot; can be symlinked to it&lt;br /&gt;
#    # when busybox is run as a different symlinked applet name, it runs the applet&lt;br /&gt;
#    /init&lt;br /&gt;
#    # init is ash script, see slackware's /boot/initrd-tree/init for example&lt;br /&gt;
#    Inside this script:&lt;br /&gt;
#      1) parse kernel parameters passed into it and set variables based on them&lt;br /&gt;
#      2) start udevd and trigger rules for block devices to setup initial /dev devices&lt;br /&gt;
#      3) load kernel modules and keyboard map&lt;br /&gt;
#      4) run mdadm, cryptsetup, lvm, zpool/zfs to setup more devices&lt;br /&gt;
#         (any udev rules for them should do more /dev setup in the background)&lt;br /&gt;
#      5) mount the root filesystem read-only at /mnt&lt;br /&gt;
#      6) stat /mnt/sbin/init, and if not executable run a rescue shell /bin/sh&lt;br /&gt;
#      7) shutdown udevd so it can be restarted by root system when booted&lt;br /&gt;
#      8) mount --move {proc,sys,run,dev} to under /mnt&lt;br /&gt;
#      9) run: exec switch_root /mnt /sbin/init $RUNLEVEL&lt;br /&gt;
#    The slackware mkinitrd package is fully configured busybox installation&lt;br /&gt;
#      for an extern file initramfs initrd.gz image outside the kernel.&lt;br /&gt;
#    It could be changed to be inside the kernel easily by just using initrd-tree&lt;br /&gt;
#      as target of INITRAMFS_SOURCE in the kernel config and removing initrd in lilo.&lt;br /&gt;
&lt;br /&gt;
# Because the zfs modules are builtin, we really don't need busybox and the whole&lt;br /&gt;
# mkinitrd package. All we need to do is mount the zfs that is already imported&lt;br /&gt;
# because the zpool.cache is present in rootfs when the zfs module initializes, and&lt;br /&gt;
# then we do the switch root procedure to boot up on the mounted system.&lt;br /&gt;
# udevd rules will still be run when the root system starts udevd.&lt;br /&gt;
&lt;br /&gt;
# So, let's make a simple /init c program that will be all that we really need:&lt;br /&gt;
cat &amp;gt; init.c &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
/* software product name: foobarz-init.c&lt;br /&gt;
 * suggested binary name: /init (in initramfs-source, rootfs)&lt;br /&gt;
 * license              : BSD&lt;br /&gt;
 * license text:&lt;br /&gt;
Copyright (c) 2012, foobarz&lt;br /&gt;
All rights reserved.&lt;br /&gt;
&lt;br /&gt;
Redistribution and use in source and binary forms, with or without&lt;br /&gt;
modification, are permitted provided that the following conditions are met:&lt;br /&gt;
    * Redistributions of source code must retain the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer.&lt;br /&gt;
    * Redistributions in binary form must reproduce the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer in the&lt;br /&gt;
      documentation and/or other materials provided with the distribution.&lt;br /&gt;
    * Neither the name of the &amp;lt;organization&amp;gt; nor the&lt;br /&gt;
      names of its contributors may be used to endorse or promote products&lt;br /&gt;
      derived from this software without specific prior written permission.&lt;br /&gt;
&lt;br /&gt;
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &amp;quot;AS IS&amp;quot; AND&lt;br /&gt;
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED&lt;br /&gt;
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE&lt;br /&gt;
DISCLAIMED. IN NO EVENT SHALL &amp;lt;COPYRIGHT HOLDER&amp;gt; BE LIABLE FOR ANY&lt;br /&gt;
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES&lt;br /&gt;
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;&lt;br /&gt;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND&lt;br /&gt;
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT&lt;br /&gt;
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS&lt;br /&gt;
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#define FOOBARZ_INIT_VERSION &amp;quot;1.0.1&amp;quot;&lt;br /&gt;
#define _BSD_SOURCE&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/stat.h&amp;gt;&lt;br /&gt;
#include &amp;lt;fcntl.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/mount.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sysexits.h&amp;gt;&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/* Your initramfs-source should contain the following&lt;br /&gt;
 * cd /boot/initramfs-source&lt;br /&gt;
 * mkdir -p proc dev sys mnt bin sbin etc/zfs&lt;br /&gt;
 * touch etc/mtab&lt;br /&gt;
 * cp /etc/zfs/zpool.cache-initrd etc/zfs/zpool.cache&lt;br /&gt;
 * mknod dev/console c 5 1   # system console&lt;br /&gt;
 * mknod dev/kmsg    c 1 11  # lines printed to kmsg enter kernel messages buffer&lt;br /&gt;
 * mknod dev/loop0   b 7 0&lt;br /&gt;
 * mknod dev/tty     c 5 0   # current tty&lt;br /&gt;
 * mknod dev/tty0    c 4 0   # current virtual term&lt;br /&gt;
 * mknod dev/tty1    c 4 1   # login virtual term 1 (F1)&lt;br /&gt;
 * mknod dev/ttyS0   c 4 64  # COM1&lt;br /&gt;
 * mknod dev/ttyS1   c 4 65  # COM2&lt;br /&gt;
 * mknod dev/ttyS2   c 4 66  # COM3&lt;br /&gt;
 * mknod dev/ttyS3   c 4 67  $ COM4&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[]) {&lt;br /&gt;
 /***** variables&lt;br /&gt;
  *&lt;br /&gt;
  */&lt;br /&gt;
 int i;&lt;br /&gt;
 FILE* kmsg = NULL;&lt;br /&gt;
 int   fd = 0; /* file descriptor */&lt;br /&gt;
 unsigned long mountflags;&lt;br /&gt;
&lt;br /&gt;
 /* kernel command line */&lt;br /&gt;
 off_t cmdline_size;&lt;br /&gt;
 char* cmdline; /* to be malloc 4096B */&lt;br /&gt;
 char* cmdline_end;&lt;br /&gt;
 char* temp_end;&lt;br /&gt;
 int usage = EX_OK;&lt;br /&gt;
&lt;br /&gt;
 /* use to hold contents of a misc /proc/&amp;lt;file&amp;gt; */&lt;br /&gt;
 char* miscproc_buff; /* to be malloc 4096B */&lt;br /&gt;
 off_t miscproc_size;&lt;br /&gt;
&lt;br /&gt;
 /* note about environ, argv, and kernel cmdline for init:&lt;br /&gt;
  *   environ is not defined for init&lt;br /&gt;
  *   only argv[0] is set for init&lt;br /&gt;
  *   kernel command line parameters are accessed&lt;br /&gt;
  *   at /proc/cmdline&lt;br /&gt;
  */&lt;br /&gt;
&lt;br /&gt;
 /* kernel parameters expected to be name=value */&lt;br /&gt;
 /* do not use quotes or spaces in parameters   */&lt;br /&gt;
 /* you can add more params somwhere after root= */&lt;br /&gt;
 struct nv { char* n; char* v; char* v_end; int req; };&lt;br /&gt;
 struct nv param[] = {&lt;br /&gt;
   { &amp;quot;root=&amp;quot;, NULL, NULL, 1 },      /* required; root device to boot */&lt;br /&gt;
   { &amp;quot;rootfstype=&amp;quot;, NULL, NULL, 1 },    /* required; root filesystem type */&lt;br /&gt;
   { &amp;quot;mountopt=&amp;quot;, NULL, NULL, 0 },  /* optional; mount option ro or rw; default ro */&lt;br /&gt;
   { &amp;quot;init=&amp;quot;, NULL, NULL, 0 },      /* optional; alt. init prgm; default /sbin/init */&lt;br /&gt;
   { &amp;quot;runlevel=&amp;quot;, NULL, NULL, 0 },  /* optional; runlevel 0123456Ss; default 3 multiuser */&lt;br /&gt;
   { &amp;quot;console=&amp;quot;, NULL, NULL, 0 }          /* optional; alt. console; e.g. ttyS0 */&lt;br /&gt;
 };&lt;br /&gt;
 enum { iroot, irootfstype, imountopt, iinit, irunlevel, iconsole, ilastparam };&lt;br /&gt;
&lt;br /&gt;
 /***** program&lt;br /&gt;
  *&lt;br /&gt;
  */&lt;br /&gt;
 kmsg = fopen(&amp;quot;/dev/kmsg&amp;quot;, &amp;quot;w&amp;quot;);&lt;br /&gt;
 fprintf(kmsg, &amp;quot;foobarz-init, version %s: booting initramfs.\n&amp;quot;, FOOBARZ_INIT_VERSION);&lt;br /&gt;
&lt;br /&gt;
 cmdline = (char*) malloc(4096);&lt;br /&gt;
 miscproc_buff = (char*) malloc(4096);&lt;br /&gt;
 if( (cmdline == NULL) || (miscproc_buff == NULL) ) {&lt;br /&gt;
   fprintf(kmsg, &amp;quot;Unable to allocate buffer memory: malloc: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount proc before dev since some devices&lt;br /&gt;
  * symlink into proc */&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting mount proc /proc\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;proc&amp;quot;, &amp;quot;/proc&amp;quot;, &amp;quot;proc&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;Mount proc successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount devtmpfs as expected by an init program&lt;br /&gt;
  * and maybe required to mount zfs */&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting mount devtmpfs /dev\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;devtmpfs&amp;quot;, &amp;quot;/dev&amp;quot;, &amp;quot;devtmpfs&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;Mount devtmpfs successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
 /* it is assumed that all required devices are in devtmpfs&lt;br /&gt;
  * and if not, there will be boot problems&lt;br /&gt;
  *&lt;br /&gt;
  * if you need a more complex device setup, then you might need&lt;br /&gt;
  * udevd and run it with a larger full initrd package from your distro&lt;br /&gt;
  */&lt;br /&gt;
&lt;br /&gt;
 /* process kernel command line */&lt;br /&gt;
 fd = open(&amp;quot;/proc/cmdline&amp;quot;, O_RDONLY);&lt;br /&gt;
 if( fd == -1 ) {&lt;br /&gt;
   fprintf(kmsg, &amp;quot;Cannot open /proc/cmdline: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 /* note, on /proc fs:&lt;br /&gt;
  *       lseek likely always returns error&lt;br /&gt;
  *       stat likely always returns st_size = 0&lt;br /&gt;
  *   so determining size of /proc file means just reading it;&lt;br /&gt;
  *   you have to read /proc files according to their documented&lt;br /&gt;
  *   maximum sizes; this is probably for performance reasons */&lt;br /&gt;
 cmdline_size = read(fd, cmdline, 4095);&lt;br /&gt;
 if( cmdline_size == -1 ) {&lt;br /&gt;
   fprintf(kmsg, &amp;quot;Failed to read /proc/cmdline: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 close(fd);&lt;br /&gt;
&lt;br /&gt;
 /* cmdline may be newline + null terminated, but make it null + null */&lt;br /&gt;
 cmdline[cmdline_size] = '\0';&lt;br /&gt;
 if( cmdline[cmdline_size-1] == '\n' ) {&lt;br /&gt;
   cmdline[cmdline_size-1] = '\0';&lt;br /&gt;
   cmdline_size--;&lt;br /&gt;
   cmdline_end = cmdline + cmdline_size;&lt;br /&gt;
 }&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Kernel cmdline size: %i\n&amp;quot;, cmdline_size);&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Kernel cmdline: \&amp;quot;%s\&amp;quot;\n&amp;quot;, cmdline);&lt;br /&gt;
&lt;br /&gt;
 for( i=iroot; i&amp;lt;ilastparam; i++ ) {&lt;br /&gt;
   param[i].v = strstr(cmdline, param[i].n);&lt;br /&gt;
   if( param[i].v != NULL ) {&lt;br /&gt;
     while( *(param[i].v) != '=' ) param[i].v++;&lt;br /&gt;
     param[i].v++;&lt;br /&gt;
     temp_end = param[i].v;&lt;br /&gt;
     while( !( (*temp_end == ' ') ||&lt;br /&gt;
               (*temp_end == '\n') ||&lt;br /&gt;
               (temp_end == cmdline_end)&lt;br /&gt;
	     ) ) temp_end++;&lt;br /&gt;
     if( temp_end == param[i].v ) {&lt;br /&gt;
       fprintf(kmsg, &amp;quot;Kernel parameter %s: value missing.\n&amp;quot;, param[i].n);&lt;br /&gt;
     } else param[i].v_end = temp_end;&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* set defaults on non-required params, except for console */&lt;br /&gt;
 if( param[imountopt].v == NULL ) param[imountopt].v = &amp;quot;ro&amp;quot;;&lt;br /&gt;
 if( param[iinit].v == NULL )     param[iinit].v = &amp;quot;/sbin/init&amp;quot;;&lt;br /&gt;
 if( param[irunlevel].v == NULL ) param[irunlevel].v = &amp;quot;3&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
 for( i=iroot; i&amp;lt;ilastparam; i++ ) {&lt;br /&gt;
   if( param[i].v_end != NULL ) *(param[i].v_end) = '\0';&lt;br /&gt;
   fprintf(kmsg, &amp;quot;Using %s \&amp;quot;%s\&amp;quot;\n&amp;quot;, param[i].n, param[i].v);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 for( i=iroot; i&amp;lt;ilastparam; i++ ) {&lt;br /&gt;
   if( (param[i].req == 1) &amp;amp;&amp;amp; (param[i].v == NULL) ) {&lt;br /&gt;
     printf(&amp;quot;Error: missing required kernel parameter: %s\n&amp;quot;, param[i].n);&lt;br /&gt;
     usage = EX_USAGE;&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 if( usage != EX_OK ) {&lt;br /&gt;
   printf(&amp;quot;Aborting boot process. Missing required kernel parameter(s).\n&amp;quot;);&lt;br /&gt;
   return usage;&lt;br /&gt;
 }&lt;br /&gt;
 /* generic nv pair kernel cmdline processing finished&lt;br /&gt;
  *  now, examine specific params for defaults and correctness&lt;br /&gt;
  */&lt;br /&gt;
&lt;br /&gt;
 /* param[iroot]: nothing to do, if user put bad device in then we fail */&lt;br /&gt;
&lt;br /&gt;
 /* param[irootfstype]: can be checked against /proc/filesystems: */&lt;br /&gt;
 /* required, so should have value */&lt;br /&gt;
 fd = open(&amp;quot;/proc/filesystems&amp;quot;, O_RDONLY);&lt;br /&gt;
 if( fd == -1 ) {&lt;br /&gt;
   fprintf(kmsg, &amp;quot;Cannot open /proc/filesystems: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 miscproc_size = read(fd, miscproc_buff, 4095);&lt;br /&gt;
 if( miscproc_size == -1 ) {&lt;br /&gt;
   fprintf(kmsg, &amp;quot;Failed to read /proc/filesystems: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 close(fd);&lt;br /&gt;
 if( strstr(miscproc_buff, param[irootfstype].v) == NULL ) {&lt;br /&gt;
   fprintf(kmsg, &amp;quot;%s \&amp;quot;%s\&amp;quot;: filesystem type not available.\n&amp;quot;,&lt;br /&gt;
	   param[irootfstype].n, param[irootfstype].v);&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 if( strcmp(param[irootfstype].v, &amp;quot;zfs&amp;quot;) == 0 ) {&lt;br /&gt;
   if( access(&amp;quot;/etc/zfs/zpool.cache&amp;quot;, F_OK) == 0 )&lt;br /&gt;
     fprintf(kmsg, &amp;quot;%s: /etc/zfs/zpool.cache is present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
   else&lt;br /&gt;
     fprintf(kmsg, &amp;quot;%s: /etc/zfs/zpool.cache not present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
   if( access(&amp;quot;/etc/hostid&amp;quot;, F_OK) == 0 )&lt;br /&gt;
     fprintf(kmsg, &amp;quot;%s: /etc/hostid is present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
   else&lt;br /&gt;
     fprintf(kmsg, &amp;quot;%s: /etc/hostid not present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 if(      strcmp(param[imountopt].v, &amp;quot;ro&amp;quot;) == 0 ) mountflags = MS_RDONLY;&lt;br /&gt;
 else if( strcmp(param[imountopt].v, &amp;quot;rw&amp;quot;) == 0 ) mountflags = 0;&lt;br /&gt;
 else {&lt;br /&gt;
   fprintf(kmsg, &amp;quot;% \&amp;quot;%\&amp;quot;: invalid parameter value;\n&amp;quot;&lt;br /&gt;
		 &amp;quot;   use \&amp;quot;ro\&amp;quot; or \&amp;quot;rw\&amp;quot; (no quotes or spaces);\n&amp;quot;&lt;br /&gt;
		 &amp;quot;   defaulting to \&amp;quot;ro\&amp;quot;.\n&amp;quot;,&lt;br /&gt;
		 param[imountopt].n, param[imountopt].v&lt;br /&gt;
	  );&lt;br /&gt;
   mountflags = MS_RDONLY;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting %s %s mount %s /mnt.\n&amp;quot;,&lt;br /&gt;
	 param[irootfstype].v, param[imountopt].v, param[iroot].v);&lt;br /&gt;
 if( mount(param[iroot].v, &amp;quot;/mnt&amp;quot;, param[irootfstype].v, mountflags, NULL) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 fprintf(kmsg, &amp;quot;%s mounted successfully.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting mount --move /dev /mnt/dev\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/dev&amp;quot;, &amp;quot;/mnt/dev&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting mount --move /proc /mnt/proc\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/proc&amp;quot;, &amp;quot;/mnt/proc&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Beginning switch root procedure.\n&amp;quot;);&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting chdir from / to /mnt\n&amp;quot;);&lt;br /&gt;
 if( chdir(&amp;quot;/mnt&amp;quot;) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: chdir: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting mount-move . to /\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;.&amp;quot;, &amp;quot;/&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting chroot to .\n&amp;quot;);&lt;br /&gt;
 if( chroot(&amp;quot;.&amp;quot;) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: chroot: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting chdir to /\n&amp;quot;);&lt;br /&gt;
 if( chdir(&amp;quot;/&amp;quot;) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: chdir: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Completed switch root procedure.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 /* check for &amp;quot;console=&amp;quot; kernel parameter and switch&lt;br /&gt;
  *  stdin, stdout, and stderr to named console device&lt;br /&gt;
  */&lt;br /&gt;
 if( param[iconsole].v != NULL ) {&lt;br /&gt;
   fprintf(kmsg, &amp;quot;Console redirection to device %s requested.\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
   fprintf(kmsg, &amp;quot;Opening stdin, stdout, and stderr on %s.\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
   close(0);&lt;br /&gt;
   /* expect only basename of device (e.g., ttyS0), so chdir /dev */&lt;br /&gt;
   chdir(&amp;quot;/dev&amp;quot;);&lt;br /&gt;
   open(param[iconsole].v, O_RDWR);&lt;br /&gt;
   dup2(0, 1);&lt;br /&gt;
   dup2(0, 2);&lt;br /&gt;
   chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Execing: \&amp;quot;%s %s\&amp;quot; to boot mounted root system.\n&amp;quot;,&lt;br /&gt;
	 param[iinit].v, param[irunlevel].v);&lt;br /&gt;
&lt;br /&gt;
 /* free resources held to this point */&lt;br /&gt;
 fclose(kmsg);&lt;br /&gt;
 free(cmdline);&lt;br /&gt;
 free(miscproc_buff);&lt;br /&gt;
&lt;br /&gt;
 if( execl(param[iinit].v, param[irunlevel].v, (char *) NULL ) != 0 ) {&lt;br /&gt;
  kmsg = fopen(&amp;quot;/dev/kmsg&amp;quot;, &amp;quot;w&amp;quot;);&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: execl: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  fclose(kmsg);&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
EOF&lt;br /&gt;
## end of rootfs /init&lt;br /&gt;
&lt;br /&gt;
gcc --static init.c -o init&lt;br /&gt;
strip init&lt;br /&gt;
&lt;br /&gt;
## build and install kernel&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make -j8&lt;br /&gt;
make -j8 modules_install&lt;br /&gt;
cp arch/x86/boot/bzImage /boot/vm3.2.27b&lt;br /&gt;
cp System.map /boot/System.map-vm3.2.27b&lt;br /&gt;
# add new lilo menu entry for vm3.2.27b kernel&lt;br /&gt;
vi /etc/lilo.conf&lt;br /&gt;
  image = /boot/vm3.2.27b&lt;br /&gt;
   label = vm3.2.27b&lt;br /&gt;
   addappend = &amp;quot; spl.spl_hostid=0x007f0100 zfs.spa_config_path=/etc/zfs/zpool.cache root=zfs-root ro rootfstype=zfs rootwait &amp;quot;&lt;br /&gt;
lilo&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notes on kernel params (lilo append and addappend lines): root= and rootfstype= are used by both foorbarz-init and mkinitrd. The &amp;quot;ro&amp;quot; param is not used by foobarz-init, so instead use: mountopt=ro|rw. See &amp;quot;modinfo spl&amp;quot; and &amp;quot;modinfo zfs&amp;quot; to see all of the options those modules can take on the kernel command line.&lt;br /&gt;
&lt;br /&gt;
Notes on the spl and zfs packages to install: If you have errors using zfs and zpool commands on booted system with builtin modules, then upgrade/switch to the 0.6.0rc10_3.2.27b builds, or you can make a custom package with the binaries renamed like zpoolb, zfsb etc for builtin.&lt;br /&gt;
&lt;br /&gt;
Using qemu's -nographic serial console (/usr/share/qemu/sgabios.bin): If you have a boot problem, you might want to run in qemu's -nographic console mode:&lt;br /&gt;
&lt;br /&gt;
First, edit /etc/inittab, and uncomment the line for local serial ports runlevels &amp;quot;s1&amp;quot; (ttyS0) and &amp;quot;s2&amp;quot; (ttyS1) for serial console login support.&lt;br /&gt;
&lt;br /&gt;
Then, run qemu such as:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
qemu-kvm &amp;lt;all regular options&amp;gt; -nographic -option-rom sgabios.bin,bootindex=0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Wait for the lilo prompt, it may take several seconds show up in this mode.&lt;br /&gt;
&lt;br /&gt;
In the lilo menu, select your kernel image with builtin spl/zfs, and use kernel params such as:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
boot: vm3.2.27b console=ttyS0 runlevel=s1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
At the lilo prompt, use kernel parameter: console=ttyS0 (do NOT say /dev/ttS0).&lt;br /&gt;
&lt;br /&gt;
When you are in qemu's serial graphics mode, the interface is a little different than in the normal graphical SQL-based mode: use keypresses:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ctrl-a h    # for help&lt;br /&gt;
ctrl-a c    # toggle access to (QEMU) console / back to emulation&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If you cannot get a login: prompt, try ctrl-a c, then do (QEMU) sendkey ctrl-alt-delete. This will reboot cleanly back to lilo, then you can do (QEMU) quit.&lt;br /&gt;
&lt;br /&gt;
BECAREFUL not to start qemu twice on the same ZFS guest! Two simultaneous running qemu on the same ZFS will corrupt the pool and it will NOT recover - you lose your whole installation! Before running qemu, check ps -A, look for an already running qemu process incase it somehow entered into the background!&lt;br /&gt;
&lt;br /&gt;
BECAREFUL when using -nographic ttyS0 that you are not doing commands on the HOST! Only use -nographic to see kernel problems. Use regular console of booting is working normally.&lt;br /&gt;
&lt;br /&gt;
To use the qemu -drive if=scsi option, the linux module sym53c8xx should be loaded in the guest. You may need to use the qemu option:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-option-rom 8xx_64.rom,bootindex=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The file 8xx_64.com used to be inside qemu, but in new versions it is missing. You can download it:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
wget http://www.lsi.com/downloads/Public/Host%20Bus%20Adapters/Host%20Bus%20Adapters%20Common%20Files/lsi_bios.zip&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Extract the zip and place 8xx_64.rom in /usr/share/qemu/.&lt;br /&gt;
&lt;br /&gt;
Good luck!&lt;/div&gt;</description>
			<pubDate>Fri, 24 Aug 2012 02:44:35 GMT</pubDate>
			<dc:creator>Foobarz</dc:creator>
			<comments>https://www.slackwiki.com/Talk:ZFS_root_(builtin)</comments>
		</item>
		<item>
			<title>ZFS root (builtin)</title>
			<link>https://www.slackwiki.com/index.php?title=ZFS_root_(builtin)&amp;diff=745</link>
			<guid isPermaLink="false">https://www.slackwiki.com/index.php?title=ZFS_root_(builtin)&amp;diff=745</guid>
			<description>&lt;p&gt;Foobarz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Tutorials]]&lt;br /&gt;
The first &amp;quot;ZFS root&amp;quot; wiki explains the details of running ZFS at your root filesystem by using a fully modular generic kernel approach. Now, I can share how it can be done with the SPL and ZFS modules built into the kernel. This procedure is just an example and can use some fine tuning, but here goes:&lt;br /&gt;
&lt;br /&gt;
The steps below are to create kernel with SPL and ZFS modules builtin. This kernel will be installed as an alternatve kernel to boot in lilo, and it will have a separate installation from the fully modular and working system. This will allow testing the builtin kernel while able to boot back onto a working modular ZFS system. We start this procedure assuming you are on a working fully modular ZFS install as in the &amp;quot;ZFS root&amp;quot; wiki.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=legacy zfs-root&lt;br /&gt;
# use legacy so zfs will not expect zfs mount, but instead expect standard mount for this fs&lt;br /&gt;
# edit /etc/rc.d/rc.S and rc.6 to use regular &amp;quot;mount&amp;quot; commands, remove &amp;quot;zfs&amp;quot; commands&lt;br /&gt;
# edit rc.6 and remove or comment out zfs export command&lt;br /&gt;
zpool set bootfs=zfs-root zfs-root&lt;br /&gt;
# this may help, but not really sure&lt;br /&gt;
&lt;br /&gt;
mkdir /boot/initramfs-source&lt;br /&gt;
# this will hold some files for rootfs inside kernel&lt;br /&gt;
&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir src&lt;br /&gt;
cd src&lt;br /&gt;
tar xvzf /mnt/cdrom/slackware64/k/kernel-source-*.txz&lt;br /&gt;
mv usr/src/linux-3.2.27 /usr/src/linux-3.2.27b&lt;br /&gt;
rm -r install&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make menuconfig&lt;br /&gt;
  General setup-&amp;gt;Local version - append to kernel release = b&lt;br /&gt;
  General setup-&amp;gt;Default hostname                         = slackzfs&lt;br /&gt;
  General setup-&amp;gt;Initramfs source files(s)                = /boot/initramfs-source&lt;br /&gt;
  #  make usre you made this directory or the kernel build fails&lt;br /&gt;
  Device Drivers-&amp;gt;SCSI device support-&amp;gt;SCSI low-level drivers-&amp;gt; &amp;lt;*&amp;gt; SYM53C8XX Version 2 SCSI support&lt;br /&gt;
  #  for qemu if=scsi -option-rom 8xx_64.rom,bootindex=1  hard disks&lt;br /&gt;
  # buildin any hard drive controllers etc that you need&lt;br /&gt;
  File systems -&amp;gt; &amp;lt;*&amp;gt; The Extended 4 (ext4) filesystem&lt;br /&gt;
  # /boot may use this ext4 fs&lt;br /&gt;
make prepare scripts&lt;br /&gt;
# this make command is what the spl and zfs copy-builtin scripts expect to be done before they are run&lt;br /&gt;
&lt;br /&gt;
cd ~/src&lt;br /&gt;
tar xvzf ~/spl-0.6.0-rc10.tar.gz&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-0.6.0-rc10&lt;br /&gt;
./configure \&lt;br /&gt;
    --prefix=/ \&lt;br /&gt;
    --libdir=/lib64 \&lt;br /&gt;
    --includedir=/usr/include \&lt;br /&gt;
    --datarootdir=/usr/share \&lt;br /&gt;
    --enable-linux-builtin=yes \&lt;br /&gt;
    --with-linux=/usr/src/linux-3.2.27b \&lt;br /&gt;
    --with-linux-obj=/usr/src/linux-3.2.27b&lt;br /&gt;
wget https://raw.github.com/zfsonlinux/spl/master/copy-builtin&lt;br /&gt;
chmod +x copy-builtin&lt;br /&gt;
./copy-builtin /usr/src/linux-3.2.27b&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../spl-0.6.0rc10_3.2.27b-x86_64-1root.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
&lt;br /&gt;
tar xvzf ~/zfs-0.6.0-rc10.tar.gz&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-0.6.0-rc10&lt;br /&gt;
./configure \&lt;br /&gt;
    --prefix=/ \&lt;br /&gt;
    --libdir=/lib64 \&lt;br /&gt;
    --includedir=/usr/include \&lt;br /&gt;
    --datarootdir=/usr/share \&lt;br /&gt;
    --enable-linux-builtin=yes \&lt;br /&gt;
    --with-linux=/usr/src/linux-3.2.27b \&lt;br /&gt;
    --with-linux-obj=/usr/src/linux-3.2.27b \&lt;br /&gt;
    --with-spl=/root/src/spl-0.6.0-rc10&lt;br /&gt;
wget https://raw.github.com/zfsonlinux/zfs/master/copy-builtin&lt;br /&gt;
chmod +x copy-builtin&lt;br /&gt;
./copy-builtin /usr/src/linux-3.2.27b&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../zfs-0.6.0rc10_3.2.27b-x86_64-1root.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
&lt;br /&gt;
### move zfs and spl modules inside kernel source to be at end of drivers:&lt;br /&gt;
### the order builtin modules init is the order they link into the kernel&lt;br /&gt;
### and we need zfs to init after all hard drive controllers&lt;br /&gt;
### zfs is more like a device driver layer over the lower-level hba drivers&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
mkdir drivers/zfsonlinux&lt;br /&gt;
mv spl drivers/zfsonlinux&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  # remove references to spl&lt;br /&gt;
vi Makefile&lt;br /&gt;
  # remove references to spl&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/fs&lt;br /&gt;
mv zfs ../drivers/zfsonlinux&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  # remove references to zfs&lt;br /&gt;
vi Makefile&lt;br /&gt;
  # remove references to zfs&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  )# add line at end of menu, before &amp;quot;endmenu&amp;quot;:&lt;br /&gt;
  )source &amp;quot;drivers/zfsonlinux/Kconfig&amp;quot;&lt;br /&gt;
  )endmenu&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers&lt;br /&gt;
vi Makefile&lt;br /&gt;
  )# add line at very end of file:&lt;br /&gt;
  )obj-$(CONFIG_ZFSONLINUX) += zfsonlinux/&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers/zfsonlinux&lt;br /&gt;
cat &amp;gt; Kconfig &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
menuconfig ZFSONLINUX&lt;br /&gt;
	tristate &amp;quot;ZFSonLinux support&amp;quot;&lt;br /&gt;
&lt;br /&gt;
if ZFSONLINUX&lt;br /&gt;
&lt;br /&gt;
source &amp;quot;drivers/zfsonlinux/spl/Kconifg&amp;quot;&lt;br /&gt;
&lt;br /&gt;
source &amp;quot;drivers/zfsonlinux/zfs/Kconifg&amp;quot;&lt;br /&gt;
&lt;br /&gt;
endif&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/zfsonlinux&lt;br /&gt;
cat &amp;gt; Makefile &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
obj-$(CONFIG_SPL) += spl/&lt;br /&gt;
obj-$(CONFIG_ZFS) += zfs/&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
### move complete&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make menuconfig&lt;br /&gt;
   Device Drivers -&amp;gt;&lt;br /&gt;
    &amp;lt;*&amp;gt; ZFSonLinux support -&amp;gt;&lt;br /&gt;
      &amp;lt;*&amp;gt; Solaris Porting Layer (SPL)&lt;br /&gt;
      &amp;lt;*&amp;gt;     ZFS&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
### prepare contents of initramfs&lt;br /&gt;
cd /boot/initramfs-source&lt;br /&gt;
&lt;br /&gt;
# make standard directories&lt;br /&gt;
mkdir -p proc dev sys mnt bin sbin etc/zfs&lt;br /&gt;
&lt;br /&gt;
# zfs seems to want mtab present, even if empty&lt;br /&gt;
touch etc/mtab&lt;br /&gt;
&lt;br /&gt;
# if zpool.cache file can be read by zfs at module init, it imports the pools in the cache&lt;br /&gt;
cp /etc/zfs/zpool.cache-initrd etc/zfs/zpool.cache&lt;br /&gt;
&lt;br /&gt;
# make initial console device node; otherwise, there is a problem at startup:&lt;br /&gt;
# &amp;quot;Warning: unable to open an initial console&amp;quot; and you'd have problems with console and tty login&lt;br /&gt;
# making these nodes from within /init is not early enough to avoid problem&lt;br /&gt;
mknod dev/console c 5 1   # system console&lt;br /&gt;
&lt;br /&gt;
# make memory device kmsg to &amp;quot;printk&amp;quot; kernel messages&lt;br /&gt;
# we can write to this file to send out messages&lt;br /&gt;
mknod dev/kmsg    c 1 11  # lines printed to kmsg enter kernel messages buffer&lt;br /&gt;
&lt;br /&gt;
# recommended loop0 device to mount fs images&lt;br /&gt;
mknod dev/loop0   b 7 0&lt;br /&gt;
&lt;br /&gt;
# make initial virtual terminal devices&lt;br /&gt;
mknod dev/tty     c 5 0   # current tty&lt;br /&gt;
mknod dev/tty0    c 4 0   # current virtual term&lt;br /&gt;
mknod dev/tty1    c 4 1   # login virtual term 1 (F1)&lt;br /&gt;
&lt;br /&gt;
# make alternative console=ttyS0 standard 8250/16550 UART serial port devices&lt;br /&gt;
#   useful with kernel parameter console=ttyS0&lt;br /&gt;
#          with qemu -nographic -option-rom sgabios.bin,bootindex=0&lt;br /&gt;
mknod dev/ttyS0   c 4 64  # COM1&lt;br /&gt;
mknod dev/ttyS1   c 4 65  # COM2&lt;br /&gt;
mknod dev/ttyS2   c 4 66  # COM3&lt;br /&gt;
mknod dev/ttyS3   c 4 67  $ COM4&lt;br /&gt;
&lt;br /&gt;
# this should be enough device nodes initially&lt;br /&gt;
# once devtmpfs mounts over /dev, a lot more is available in it by default&lt;br /&gt;
&lt;br /&gt;
cat &amp;gt; /init &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot; &amp;lt;some initial program PID=1 for the system to start on&amp;gt; EOF&lt;br /&gt;
# an initramfs-source/init program is required to mount and boot a root linux system&lt;br /&gt;
# the common way to make /init is using busybox with files like this:&lt;br /&gt;
#    /bin/busybox&lt;br /&gt;
#    /bin/ash -&amp;gt; busybox&lt;br /&gt;
#    /bin/sh -&amp;gt; busybox&lt;br /&gt;
#    # run busybox to see what other &amp;quot;applets&amp;quot; can be symlinked to it&lt;br /&gt;
#    # when busybox is run as a different symlinked applet name, it runs the applet&lt;br /&gt;
#    /init&lt;br /&gt;
#    # init is ash script, see slackware's /boot/initrd-tree/init for example&lt;br /&gt;
#    Inside this script:&lt;br /&gt;
#      1) parse kernel parameters passed into it and set variables based on them&lt;br /&gt;
#      2) start udevd and trigger rules for block devices to setup initial /dev devices&lt;br /&gt;
#      3) load kernel modules and keyboard map&lt;br /&gt;
#      4) run mdadm, cryptsetup, lvm, zpool/zfs to setup more devices&lt;br /&gt;
#         (any udev rules for them should do more /dev setup in the background)&lt;br /&gt;
#      5) mount the root filesystem read-only at /mnt&lt;br /&gt;
#      6) stat /mnt/sbin/init, and if not executable run a rescue shell /bin/sh&lt;br /&gt;
#      7) shutdown udevd so it can be restarted by root system when booted&lt;br /&gt;
#      8) mount --move {proc,sys,run,dev} to under /mnt&lt;br /&gt;
#      9) run: exec switch_root /mnt /sbin/init $RUNLEVEL&lt;br /&gt;
#    The slackware mkinitrd package is fully configured busybox installation&lt;br /&gt;
#      for an extern file initramfs initrd.gz image outside the kernel.&lt;br /&gt;
#    It could be changed to be inside the kernel easily by just using initrd-tree&lt;br /&gt;
#      as target of INITRAMFS_SOURCE in the kernel config and removing initrd in lilo.&lt;br /&gt;
&lt;br /&gt;
# Because the zfs modules are builtin, we really don't need busybox and the whole&lt;br /&gt;
# mkinitrd package. All we need to do is mount the zfs that is already imported&lt;br /&gt;
# because the zpool.cache is present in rootfs when the zfs module initializes, and&lt;br /&gt;
# then we do the switch root procedure to boot up on the mounted system.&lt;br /&gt;
# udevd rules will still be run when the root system starts udevd.&lt;br /&gt;
&lt;br /&gt;
# So, let's make a simple /init c program that will be all that we really need:&lt;br /&gt;
cat &amp;gt; init.c &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
/* software product name: foobarz-init.c&lt;br /&gt;
 * suggested binary name: /init (in initramfs-source, rootfs)&lt;br /&gt;
 * license              : BSD&lt;br /&gt;
 * license text:&lt;br /&gt;
Copyright (c) 2012, foobarz&lt;br /&gt;
All rights reserved.&lt;br /&gt;
&lt;br /&gt;
Redistribution and use in source and binary forms, with or without&lt;br /&gt;
modification, are permitted provided that the following conditions are met:&lt;br /&gt;
    * Redistributions of source code must retain the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer.&lt;br /&gt;
    * Redistributions in binary form must reproduce the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer in the&lt;br /&gt;
      documentation and/or other materials provided with the distribution.&lt;br /&gt;
    * Neither the name of the &amp;lt;organization&amp;gt; nor the&lt;br /&gt;
      names of its contributors may be used to endorse or promote products&lt;br /&gt;
      derived from this software without specific prior written permission.&lt;br /&gt;
&lt;br /&gt;
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &amp;quot;AS IS&amp;quot; AND&lt;br /&gt;
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED&lt;br /&gt;
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE&lt;br /&gt;
DISCLAIMED. IN NO EVENT SHALL &amp;lt;COPYRIGHT HOLDER&amp;gt; BE LIABLE FOR ANY&lt;br /&gt;
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES&lt;br /&gt;
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;&lt;br /&gt;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND&lt;br /&gt;
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT&lt;br /&gt;
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS&lt;br /&gt;
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#define FOOBARZ_INIT_VERSION &amp;quot;1.0.1&amp;quot;&lt;br /&gt;
#define _BSD_SOURCE&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/stat.h&amp;gt;&lt;br /&gt;
#include &amp;lt;fcntl.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/mount.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sysexits.h&amp;gt;&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/* Your initramfs-source should contain the following&lt;br /&gt;
 * cd /boot/initramfs-source&lt;br /&gt;
 * mkdir -p proc dev sys mnt bin sbin etc/zfs&lt;br /&gt;
 * touch etc/mtab&lt;br /&gt;
 * cp /etc/zfs/zpool.cache-initrd etc/zfs/zpool.cache&lt;br /&gt;
 * mknod dev/console c 5 1   # system console&lt;br /&gt;
 * mknod dev/kmsg    c 1 11  # lines printed to kmsg enter kernel messages buffer&lt;br /&gt;
 * mknod dev/loop0   b 7 0&lt;br /&gt;
 * mknod dev/tty     c 5 0   # current tty&lt;br /&gt;
 * mknod dev/tty0    c 4 0   # current virtual term&lt;br /&gt;
 * mknod dev/tty1    c 4 1   # login virtual term 1 (F1)&lt;br /&gt;
 * mknod dev/ttyS0   c 4 64  # COM1&lt;br /&gt;
 * mknod dev/ttyS1   c 4 65  # COM2&lt;br /&gt;
 * mknod dev/ttyS2   c 4 66  # COM3&lt;br /&gt;
 * mknod dev/ttyS3   c 4 67  $ COM4&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[]) {&lt;br /&gt;
 /***** variables&lt;br /&gt;
  *&lt;br /&gt;
  */&lt;br /&gt;
 int i;&lt;br /&gt;
 FILE* kmsg = NULL;&lt;br /&gt;
 int   fd = 0; /* file descriptor */&lt;br /&gt;
 unsigned long mountflags;&lt;br /&gt;
&lt;br /&gt;
 /* kernel command line */&lt;br /&gt;
 off_t cmdline_size;&lt;br /&gt;
 char* cmdline; /* to be malloc 4096B */&lt;br /&gt;
 char* cmdline_end;&lt;br /&gt;
 char* temp_end;&lt;br /&gt;
 int usage = EX_OK;&lt;br /&gt;
&lt;br /&gt;
 /* use to hold contents of a misc /proc/&amp;lt;file&amp;gt; */&lt;br /&gt;
 char* miscproc_buff; /* to be malloc 4096B */&lt;br /&gt;
 off_t miscproc_size;&lt;br /&gt;
&lt;br /&gt;
 /* note about environ, argv, and kernel cmdline for init:&lt;br /&gt;
  *   environ is not defined for init&lt;br /&gt;
  *   only argv[0] is set for init&lt;br /&gt;
  *   kernel command line parameters are accessed&lt;br /&gt;
  *   at /proc/cmdline&lt;br /&gt;
  */&lt;br /&gt;
&lt;br /&gt;
 /* kernel parameters expected to be name=value */&lt;br /&gt;
 /* do not use quotes or spaces in parameters   */&lt;br /&gt;
 /* you can add more params somwhere after root= */&lt;br /&gt;
 struct nv { char* n; char* v; char* v_end; int req; };&lt;br /&gt;
 struct nv param[] = {&lt;br /&gt;
   { &amp;quot;root=&amp;quot;, NULL, NULL, 1 },      /* required; root device to boot */&lt;br /&gt;
   { &amp;quot;rootfstype=&amp;quot;, NULL, NULL, 1 },    /* required; root filesystem type */&lt;br /&gt;
   { &amp;quot;mountopt=&amp;quot;, NULL, NULL, 0 },  /* optional; mount option ro or rw; default ro */&lt;br /&gt;
   { &amp;quot;init=&amp;quot;, NULL, NULL, 0 },      /* optional; alt. init prgm; default /sbin/init */&lt;br /&gt;
   { &amp;quot;runlevel=&amp;quot;, NULL, NULL, 0 },  /* optional; runlevel 0123456Ss; default 3 multiuser */&lt;br /&gt;
   { &amp;quot;console=&amp;quot;, NULL, NULL, 0 }          /* optional; alt. console; e.g. ttyS0 */&lt;br /&gt;
 };&lt;br /&gt;
 enum { iroot, irootfstype, imountopt, iinit, irunlevel, iconsole, ilastparam };&lt;br /&gt;
&lt;br /&gt;
 /***** program&lt;br /&gt;
  *&lt;br /&gt;
  */&lt;br /&gt;
 kmsg = fopen(&amp;quot;/dev/kmsg&amp;quot;, &amp;quot;w&amp;quot;);&lt;br /&gt;
 fprintf(kmsg, &amp;quot;foobarz-init, version %s: booting initramfs.\n&amp;quot;, FOOBARZ_INIT_VERSION);&lt;br /&gt;
&lt;br /&gt;
 cmdline = (char*) malloc(4096);&lt;br /&gt;
 miscproc_buff = (char*) malloc(4096);&lt;br /&gt;
 if( (cmdline == NULL) || (miscproc_buff == NULL) ) {&lt;br /&gt;
   fprintf(kmsg, &amp;quot;Unable to allocate buffer memory: malloc: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount proc before dev since some devices&lt;br /&gt;
  * symlink into proc */&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting mount proc /proc\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;proc&amp;quot;, &amp;quot;/proc&amp;quot;, &amp;quot;proc&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;Mount proc successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount devtmpfs as expected by an init program&lt;br /&gt;
  * and maybe required to mount zfs */&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting mount devtmpfs /dev\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;devtmpfs&amp;quot;, &amp;quot;/dev&amp;quot;, &amp;quot;devtmpfs&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;Mount devtmpfs successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
 /* it is assumed that all required devices are in devtmpfs&lt;br /&gt;
  * and if not, there will be boot problems&lt;br /&gt;
  *&lt;br /&gt;
  * if you need a more complex device setup, then you might need&lt;br /&gt;
  * udevd and run it with a larger full initrd package from your distro&lt;br /&gt;
  */&lt;br /&gt;
&lt;br /&gt;
 /* process kernel command line */&lt;br /&gt;
 fd = open(&amp;quot;/proc/cmdline&amp;quot;, O_RDONLY);&lt;br /&gt;
 if( fd == -1 ) {&lt;br /&gt;
   fprintf(kmsg, &amp;quot;Cannot open /proc/cmdline: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 /* note, on /proc fs:&lt;br /&gt;
  *       lseek likely always returns error&lt;br /&gt;
  *       stat likely always returns st_size = 0&lt;br /&gt;
  *   so determining size of /proc file means just reading it;&lt;br /&gt;
  *   you have to read /proc files according to their documented&lt;br /&gt;
  *   maximum sizes; this is probably for performance reasons */&lt;br /&gt;
 cmdline_size = read(fd, cmdline, 4095);&lt;br /&gt;
 if( cmdline_size == -1 ) {&lt;br /&gt;
   fprintf(kmsg, &amp;quot;Failed to read /proc/cmdline: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 close(fd);&lt;br /&gt;
&lt;br /&gt;
 /* cmdline may be newline + null terminated, but make it null + null */&lt;br /&gt;
 cmdline[cmdline_size] = '\0';&lt;br /&gt;
 if( cmdline[cmdline_size-1] == '\n' ) {&lt;br /&gt;
   cmdline[cmdline_size-1] = '\0';&lt;br /&gt;
   cmdline_size--;&lt;br /&gt;
   cmdline_end = cmdline + cmdline_size;&lt;br /&gt;
 }&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Kernel cmdline size: %i\n&amp;quot;, cmdline_size);&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Kernel cmdline: \&amp;quot;%s\&amp;quot;\n&amp;quot;, cmdline);&lt;br /&gt;
&lt;br /&gt;
 for( i=iroot; i&amp;lt;ilastparam; i++ ) {&lt;br /&gt;
   param[i].v = strstr(cmdline, param[i].n);&lt;br /&gt;
   if( param[i].v != NULL ) {&lt;br /&gt;
     while( *(param[i].v) != '=' ) param[i].v++;&lt;br /&gt;
     param[i].v++;&lt;br /&gt;
     temp_end = param[i].v;&lt;br /&gt;
     while( !( (*temp_end == ' ') ||&lt;br /&gt;
               (*temp_end == '\n') ||&lt;br /&gt;
               (temp_end == cmdline_end)&lt;br /&gt;
	     ) ) temp_end++;&lt;br /&gt;
     if( temp_end == param[i].v ) {&lt;br /&gt;
       fprintf(kmsg, &amp;quot;Kernel parameter %s: value missing.\n&amp;quot;, param[i].n);&lt;br /&gt;
     } else param[i].v_end = temp_end;&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* set defaults on non-required params, except for console */&lt;br /&gt;
 if( param[imountopt].v == NULL ) param[imountopt].v = &amp;quot;ro&amp;quot;;&lt;br /&gt;
 if( param[iinit].v == NULL )     param[iinit].v = &amp;quot;/sbin/init&amp;quot;;&lt;br /&gt;
 if( param[irunlevel].v == NULL ) param[irunlevel].v = &amp;quot;3&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
 for( i=iroot; i&amp;lt;ilastparam; i++ ) {&lt;br /&gt;
   if( param[i].v_end != NULL ) *(param[i].v_end) = '\0';&lt;br /&gt;
   fprintf(kmsg, &amp;quot;Using %s \&amp;quot;%s\&amp;quot;\n&amp;quot;, param[i].n, param[i].v);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 for( i=iroot; i&amp;lt;ilastparam; i++ ) {&lt;br /&gt;
   if( (param[i].req == 1) &amp;amp;&amp;amp; (param[i].v == NULL) ) {&lt;br /&gt;
     printf(&amp;quot;Error: missing required kernel parameter: %s\n&amp;quot;, param[i].n);&lt;br /&gt;
     usage = EX_USAGE;&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 if( usage != EX_OK ) {&lt;br /&gt;
   printf(&amp;quot;Aborting boot process. Missing required kernel parameter(s).\n&amp;quot;);&lt;br /&gt;
   return usage;&lt;br /&gt;
 }&lt;br /&gt;
 /* generic nv pair kernel cmdline processing finished&lt;br /&gt;
  *  now, examine specific params for defaults and correctness&lt;br /&gt;
  */&lt;br /&gt;
&lt;br /&gt;
 /* param[iroot]: nothing to do, if user put bad device in then we fail */&lt;br /&gt;
&lt;br /&gt;
 /* param[irootfstype]: can be checked against /proc/filesystems: */&lt;br /&gt;
 /* required, so should have value */&lt;br /&gt;
 fd = open(&amp;quot;/proc/filesystems&amp;quot;, O_RDONLY);&lt;br /&gt;
 if( fd == -1 ) {&lt;br /&gt;
   fprintf(kmsg, &amp;quot;Cannot open /proc/filesystems: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 miscproc_size = read(fd, miscproc_buff, 4095);&lt;br /&gt;
 if( miscproc_size == -1 ) {&lt;br /&gt;
   fprintf(kmsg, &amp;quot;Failed to read /proc/filesystems: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 close(fd);&lt;br /&gt;
 if( strstr(miscproc_buff, param[irootfstype].v) == NULL ) {&lt;br /&gt;
   fprintf(kmsg, &amp;quot;%s \&amp;quot;%s\&amp;quot;: filesystem type not available.\n&amp;quot;,&lt;br /&gt;
	   param[irootfstype].n, param[irootfstype].v);&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 if( strcmp(param[irootfstype].v, &amp;quot;zfs&amp;quot;) == 0 ) {&lt;br /&gt;
   if( access(&amp;quot;/etc/zfs/zpool.cache&amp;quot;, F_OK) == 0 )&lt;br /&gt;
     fprintf(kmsg, &amp;quot;%s: /etc/zfs/zpool.cache is present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
   else&lt;br /&gt;
     fprintf(kmsg, &amp;quot;%s: /etc/zfs/zpool.cache not present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
   if( access(&amp;quot;/etc/hostid&amp;quot;, F_OK) == 0 )&lt;br /&gt;
     fprintf(kmsg, &amp;quot;%s: /etc/hostid is present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
   else&lt;br /&gt;
     fprintf(kmsg, &amp;quot;%s: /etc/hostid not present in initramfs.\n&amp;quot;, param[irootfstype].v);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 if(      strcmp(param[imountopt].v, &amp;quot;ro&amp;quot;) == 0 ) mountflags = MS_RDONLY;&lt;br /&gt;
 else if( strcmp(param[imountopt].v, &amp;quot;rw&amp;quot;) == 0 ) mountflags = 0;&lt;br /&gt;
 else {&lt;br /&gt;
   fprintf(kmsg, &amp;quot;% \&amp;quot;%\&amp;quot;: invalid parameter value;\n&amp;quot;&lt;br /&gt;
		 &amp;quot;   use \&amp;quot;ro\&amp;quot; or \&amp;quot;rw\&amp;quot; (no quotes or spaces);\n&amp;quot;&lt;br /&gt;
		 &amp;quot;   defaulting to \&amp;quot;ro\&amp;quot;.\n&amp;quot;,&lt;br /&gt;
		 param[imountopt].n, param[imountopt].v&lt;br /&gt;
	  );&lt;br /&gt;
   mountflags = MS_RDONLY;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting %s %s mount %s /mnt.\n&amp;quot;,&lt;br /&gt;
	 param[irootfstype].v, param[imountopt].v, param[iroot].v);&lt;br /&gt;
 if( mount(param[iroot].v, &amp;quot;/mnt&amp;quot;, param[irootfstype].v, mountflags, NULL) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 fprintf(kmsg, &amp;quot;%s mounted successfully.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting mount --move /dev /mnt/dev\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/dev&amp;quot;, &amp;quot;/mnt/dev&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting mount --move /proc /mnt/proc\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/proc&amp;quot;, &amp;quot;/mnt/proc&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Beginning switch root procedure.\n&amp;quot;);&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting chdir from / to /mnt\n&amp;quot;);&lt;br /&gt;
 if( chdir(&amp;quot;/mnt&amp;quot;) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: chdir: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting mount-move . to /\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;.&amp;quot;, &amp;quot;/&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting chroot to .\n&amp;quot;);&lt;br /&gt;
 if( chroot(&amp;quot;.&amp;quot;) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: chroot: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting chdir to /\n&amp;quot;);&lt;br /&gt;
 if( chdir(&amp;quot;/&amp;quot;) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: chdir: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Completed switch root procedure.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 /* check for &amp;quot;console=&amp;quot; kernel parameter and switch&lt;br /&gt;
  *  stdin, stdout, and stderr to named console device&lt;br /&gt;
  */&lt;br /&gt;
 if( param[iconsole].v != NULL ) {&lt;br /&gt;
   fprintf(kmsg, &amp;quot;Console redirection to device %s requested.\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
   fprintf(kmsg, &amp;quot;Opening stdin, stdout, and stderr on %s.\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
   close(0);&lt;br /&gt;
   /* expect only basename of device (e.g., ttyS0), so chdir /dev */&lt;br /&gt;
   chdir(&amp;quot;/dev&amp;quot;);&lt;br /&gt;
   open(param[iconsole].v, O_RDWR);&lt;br /&gt;
   dup2(0, 1);&lt;br /&gt;
   dup2(0, 2);&lt;br /&gt;
   chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Execing: \&amp;quot;%s %s\&amp;quot; to boot mounted root system.\n&amp;quot;,&lt;br /&gt;
	 param[iinit].v, param[irunlevel].v);&lt;br /&gt;
&lt;br /&gt;
 /* free resources held to this point */&lt;br /&gt;
 fclose(kmsg);&lt;br /&gt;
 free(cmdline);&lt;br /&gt;
 free(miscproc_buff);&lt;br /&gt;
&lt;br /&gt;
 if( execl(param[iinit].v, param[irunlevel].v, (char *) NULL ) != 0 ) {&lt;br /&gt;
  kmsg = fopen(&amp;quot;/dev/kmsg&amp;quot;, &amp;quot;w&amp;quot;);&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: execl: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  fclose(kmsg);&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
EOF&lt;br /&gt;
## end of rootfs /init&lt;br /&gt;
&lt;br /&gt;
gcc --static init.c -o init&lt;br /&gt;
strip init&lt;br /&gt;
&lt;br /&gt;
## build and install kernel&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make -j8&lt;br /&gt;
make -j8 modules_install&lt;br /&gt;
cp arch/x86/boot/bzImage /boot/vm3.2.27b&lt;br /&gt;
cp System.map /boot/System.map-vm3.2.27b&lt;br /&gt;
# add new lilo menu entry for vm3.2.27b kernel&lt;br /&gt;
vi /etc/lilo.conf&lt;br /&gt;
  image = /boot/vm3.2.27b&lt;br /&gt;
   label = vm3.2.27b&lt;br /&gt;
   addappend = &amp;quot; spl.spl_hostid=0x007f0100 zfs.spa_config_path=/etc/zfs/zpool.cache root=zfs-root ro rootfstype=zfs rootwait &amp;quot;&lt;br /&gt;
lilo&lt;br /&gt;
reboot&lt;br /&gt;
# note: root=, rootfstype, ro, rootwait are &amp;quot;legacy&amp;quot; kernel boot options and are not really being used here&lt;br /&gt;
#       so, they probably can be removed but are not hurting&lt;br /&gt;
&lt;br /&gt;
# if you have errors using zfs and zpool commands on booted system with builtin modules, then&lt;br /&gt;
# upgrade/switch to the 0.6.0rc10_3.2.27b builds, or you can make a custom package with the binaries&lt;br /&gt;
# renamed like zpoolb, zfsb etc for builtin&lt;br /&gt;
&lt;br /&gt;
# if you have boot problem, you might want to run in qemu's -nographic console mode:&lt;br /&gt;
qemu-kvm &amp;lt;all regular options&amp;gt; -nographic -option-rom sgabios.bin,bootindex=0&lt;br /&gt;
# wait for the lilo prompt, it takes time to show up&lt;br /&gt;
boot: vm3.2.27b console=ttyS0&lt;br /&gt;
# ctrl-a h    for help&lt;br /&gt;
# ctrl-a c    for (QEMU) console&lt;br /&gt;
&lt;br /&gt;
# BECAREFUL not to start qemu twice on the same ZFS guest&lt;br /&gt;
#  two simultaneous running qemu on the same ZFS will corrupt the pool&lt;br /&gt;
#  then it will NOT recover... you lose your whole installation!&lt;br /&gt;
# BECAREFUL when using -nographic ttyS0 that you are not doing commands on the HOST!&lt;br /&gt;
# only use -nographic to see kernel problems then quit it...&lt;br /&gt;
# qemu or slackware is buggy with this it gets stuck right before you get the tty1 prompt.&lt;br /&gt;
&lt;br /&gt;
# to use if=scsi, linux module sym53c8xx, may need to use the qemu option:&lt;br /&gt;
#       -option-rom 8xx_64.rom,bootindex=1&lt;br /&gt;
# download it here:&lt;br /&gt;
# http://www.lsi.com/downloads/Public/Host%20Bus%20Adapters/Host%20Bus%20Adapters%20Common%20Files/lsi_bios.zip&lt;br /&gt;
# extract 8xx_64.rom to /usr/share/qemu/&lt;br /&gt;
&lt;br /&gt;
Then, at the lilo prompt, use kernel parameter: console=ttyS0     (do NOT say /dev/ttS0)&lt;br /&gt;
There is a delay before you see LILO so be patient. You should see full messages of kernel.&lt;br /&gt;
The purpose of sgabios is that it is the &amp;quot;serial graphics adapter&amp;quot; video BIOS that sends all its text mode I/O over ttyS0.&lt;br /&gt;
The -nographic option redirects the guest's ttyS0 to your console.&lt;br /&gt;
The purpose of 8xx_64.rom is the SCSI interface firmware, and it boots after the SGABIOS so that everything will be visible.&lt;br /&gt;
For QEMU help, press ctrl-a then hit h.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Good luck!&lt;/div&gt;</description>
			<pubDate>Thu, 23 Aug 2012 10:35:58 GMT</pubDate>
			<dc:creator>Foobarz</dc:creator>
			<comments>https://www.slackwiki.com/Talk:ZFS_root_(builtin)</comments>
		</item>
		<item>
			<title>ZFS root (builtin)</title>
			<link>https://www.slackwiki.com/index.php?title=ZFS_root_(builtin)&amp;diff=744</link>
			<guid isPermaLink="false">https://www.slackwiki.com/index.php?title=ZFS_root_(builtin)&amp;diff=744</guid>
			<description>&lt;p&gt;Foobarz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Tutorials]]&lt;br /&gt;
The first &amp;quot;ZFS root&amp;quot; wiki explains the details of running ZFS at your root filesystem by using a fully modular generic kernel approach. Now, I can share how it can be done with the SPL and ZFS modules built into the kernel. This procedure is just an example and can use some fine tuning, but here goes:&lt;br /&gt;
&lt;br /&gt;
The steps below are to create kernel with SPL and ZFS modules builtin. This kernel will be installed as an alternatve kernel to boot in lilo, and it will have a separate installation from the fully modular and working system. This will allow testing the builtin kernel while able to boot back onto a working modular ZFS system. We start this procedure assuming you are on a working fully modular ZFS install as in the &amp;quot;ZFS root&amp;quot; wiki.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=legacy zfs-root&lt;br /&gt;
# use legacy so zfs will not expect zfs mount, but instead expect standard mount for this fs&lt;br /&gt;
# edit /etc/rc.d/rc.S and rc.6 to use regular &amp;quot;mount&amp;quot; commands, remove &amp;quot;zfs&amp;quot; commands&lt;br /&gt;
# edit rc.6 and remove or comment out zfs export command&lt;br /&gt;
zpool set bootfs=zfs-root zfs-root&lt;br /&gt;
# this may help, but not really sure&lt;br /&gt;
&lt;br /&gt;
mkdir /boot/initramfs-source&lt;br /&gt;
# this will hold some files for rootfs inside kernel&lt;br /&gt;
&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir src&lt;br /&gt;
cd src&lt;br /&gt;
tar xvzf /mnt/cdrom/slackware64/k/kernel-source-*.txz&lt;br /&gt;
mv usr/src/linux-3.2.27 /usr/src/linux-3.2.27b&lt;br /&gt;
rm -r install&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make menuconfig&lt;br /&gt;
  General setup-&amp;gt;Local version - append to kernel release = b&lt;br /&gt;
  General setup-&amp;gt;Default hostname                         = slackzfs&lt;br /&gt;
  General setup-&amp;gt;Initramfs source files(s)                = /boot/initramfs-source&lt;br /&gt;
  #  make usre you made this directory or the kernel build fails&lt;br /&gt;
  Device Drivers-&amp;gt;SCSI device support-&amp;gt;SCSI low-level drivers-&amp;gt; &amp;lt;*&amp;gt; SYM53C8XX Version 2 SCSI support&lt;br /&gt;
  #  for qemu if=scsi -option-rom 8xx_64.rom,bootindex=1  hard disks&lt;br /&gt;
  # buildin any hard drive controllers etc that you need&lt;br /&gt;
  File systems -&amp;gt; &amp;lt;*&amp;gt; The Extended 4 (ext4) filesystem&lt;br /&gt;
  # /boot may use this ext4 fs&lt;br /&gt;
make prepare scripts&lt;br /&gt;
# this make command is what the spl and zfs copy-builtin scripts expect to be done before they are run&lt;br /&gt;
&lt;br /&gt;
cd ~/src&lt;br /&gt;
tar xvzf ~/spl-0.6.0-rc10.tar.gz&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-0.6.0-rc10&lt;br /&gt;
./configure \&lt;br /&gt;
    --prefix=/ \&lt;br /&gt;
    --libdir=/lib64 \&lt;br /&gt;
    --includedir=/usr/include \&lt;br /&gt;
    --datarootdir=/usr/share \&lt;br /&gt;
    --enable-linux-builtin=yes \&lt;br /&gt;
    --with-linux=/usr/src/linux-3.2.27b \&lt;br /&gt;
    --with-linux-obj=/usr/src/linux-3.2.27b&lt;br /&gt;
wget https://raw.github.com/zfsonlinux/spl/master/copy-builtin&lt;br /&gt;
chmod +x copy-builtin&lt;br /&gt;
./copy-builtin /usr/src/linux-3.2.27b&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../spl-0.6.0rc10_3.2.27b-x86_64-1root.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
&lt;br /&gt;
tar xvzf ~/zfs-0.6.0-rc10.tar.gz&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-0.6.0-rc10&lt;br /&gt;
./configure \&lt;br /&gt;
    --prefix=/ \&lt;br /&gt;
    --libdir=/lib64 \&lt;br /&gt;
    --includedir=/usr/include \&lt;br /&gt;
    --datarootdir=/usr/share \&lt;br /&gt;
    --enable-linux-builtin=yes \&lt;br /&gt;
    --with-linux=/usr/src/linux-3.2.27b \&lt;br /&gt;
    --with-linux-obj=/usr/src/linux-3.2.27b \&lt;br /&gt;
    --with-spl=/root/src/spl-0.6.0-rc10&lt;br /&gt;
wget https://raw.github.com/zfsonlinux/zfs/master/copy-builtin&lt;br /&gt;
chmod +x copy-builtin&lt;br /&gt;
./copy-builtin /usr/src/linux-3.2.27b&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../zfs-0.6.0rc10_3.2.27b-x86_64-1root.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
&lt;br /&gt;
### move zfs and spl modules inside kernel source to be at end of drivers:&lt;br /&gt;
### the order builtin modules init is the order they link into the kernel&lt;br /&gt;
### and we need zfs to init after all hard drive controllers&lt;br /&gt;
### zfs is more like a device driver layer over the lower-level hba drivers&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
mkdir drivers/zfsonlinux&lt;br /&gt;
mv spl drivers/zfsonlinux&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  # remove references to spl&lt;br /&gt;
vi Makefile&lt;br /&gt;
  # remove references to spl&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/fs&lt;br /&gt;
mv zfs ../drivers/zfsonlinux&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  # remove references to zfs&lt;br /&gt;
vi Makefile&lt;br /&gt;
  # remove references to zfs&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  )# add line at end of menu, before &amp;quot;endmenu&amp;quot;:&lt;br /&gt;
  )source &amp;quot;drivers/zfsonlinux/Kconfig&amp;quot;&lt;br /&gt;
  )endmenu&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers&lt;br /&gt;
vi Makefile&lt;br /&gt;
  )# add line at very end of file:&lt;br /&gt;
  )obj-$(CONFIG_ZFSONLINUX) += zfsonlinux/&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers/zfsonlinux&lt;br /&gt;
cat &amp;gt; Kconfig &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
menuconfig ZFSONLINUX&lt;br /&gt;
	tristate &amp;quot;ZFSonLinux support&amp;quot;&lt;br /&gt;
&lt;br /&gt;
if ZFSONLINUX&lt;br /&gt;
&lt;br /&gt;
source &amp;quot;drivers/zfsonlinux/spl/Kconifg&amp;quot;&lt;br /&gt;
&lt;br /&gt;
source &amp;quot;drivers/zfsonlinux/zfs/Kconifg&amp;quot;&lt;br /&gt;
&lt;br /&gt;
endif&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/zfsonlinux&lt;br /&gt;
cat &amp;gt; Makefile &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
obj-$(CONFIG_SPL) += spl/&lt;br /&gt;
obj-$(CONFIG_ZFS) += zfs/&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
### move complete&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make menuconfig&lt;br /&gt;
   Device Drivers -&amp;gt;&lt;br /&gt;
    &amp;lt;*&amp;gt; ZFSonLinux support -&amp;gt;&lt;br /&gt;
      &amp;lt;*&amp;gt; Solaris Porting Layer (SPL)&lt;br /&gt;
      &amp;lt;*&amp;gt;     ZFS&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
### prepare contents of initramfs&lt;br /&gt;
cd /boot/initramfs-source&lt;br /&gt;
&lt;br /&gt;
# make standard directories&lt;br /&gt;
mkdir -p proc dev sys mnt bin sbin etc/zfs&lt;br /&gt;
&lt;br /&gt;
# zfs seems to want mtab present, even if empty&lt;br /&gt;
touch etc/mtab&lt;br /&gt;
&lt;br /&gt;
# if zpool.cache file can be read by zfs at module init, it imports the pools in the cache&lt;br /&gt;
cp /etc/zfs/zpool.cache-initrd etc/zfs/zpool.cache&lt;br /&gt;
&lt;br /&gt;
# make initial console device node; otherwise, there is a problem at startup:&lt;br /&gt;
# &amp;quot;Warning: unable to open an initial console&amp;quot; and you'd have problems with console and tty login&lt;br /&gt;
# making these nodes from within /init is not early enough to avoid problem&lt;br /&gt;
mknod dev/console c 5 1   # system console&lt;br /&gt;
&lt;br /&gt;
# make memory device kmsg to &amp;quot;printk&amp;quot; kernel messages&lt;br /&gt;
# we can write to this file to send out messages&lt;br /&gt;
mknod dev/kmsg    c 1 11  # lines printed to kmsg enter kernel messages buffer&lt;br /&gt;
&lt;br /&gt;
# recommended loop0 device to mount fs images&lt;br /&gt;
mknod dev/loop0   b 7 0&lt;br /&gt;
&lt;br /&gt;
# make initial virtual terminal devices&lt;br /&gt;
mknod dev/tty     c 5 0   # current tty&lt;br /&gt;
mknod dev/tty0    c 4 0   # current virtual term&lt;br /&gt;
mknod dev/tty1    c 4 1   # login virtual term 1 (F1)&lt;br /&gt;
&lt;br /&gt;
# make alternative console=ttyS0 standard 8250/16550 UART serial port devices&lt;br /&gt;
#   useful with kernel parameter console=ttyS0&lt;br /&gt;
#          with qemu -nographic -option-rom sgabios.bin,bootindex=0&lt;br /&gt;
mknod dev/ttyS0   c 4 64  # COM1&lt;br /&gt;
mknod dev/ttyS1   c 4 65  # COM2&lt;br /&gt;
mknod dev/ttyS2   c 4 66  # COM3&lt;br /&gt;
mknod dev/ttyS3   c 4 67  $ COM4&lt;br /&gt;
&lt;br /&gt;
# this should be enough device nodes initially&lt;br /&gt;
# once devtmpfs mounts over /dev, a lot more is available in it by default&lt;br /&gt;
&lt;br /&gt;
cat &amp;gt; /init &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot; &amp;lt;some initial program PID=1 for the system to start on&amp;gt; EOF&lt;br /&gt;
# an initramfs-source/init program is required to mount and boot a root linux system&lt;br /&gt;
# the common way to make /init is using busybox with files like this:&lt;br /&gt;
#    /bin/busybox&lt;br /&gt;
#    /bin/ash -&amp;gt; busybox&lt;br /&gt;
#    /bin/sh -&amp;gt; busybox&lt;br /&gt;
#    # run busybox to see what other &amp;quot;applets&amp;quot; can be symlinked to it&lt;br /&gt;
#    # when busybox is run as a different symlinked applet name, it runs the applet&lt;br /&gt;
#    /init&lt;br /&gt;
#    # init is ash script, see slackware's /boot/initrd-tree/init for example&lt;br /&gt;
#    Inside this script:&lt;br /&gt;
#      1) parse kernel parameters passed into it and set variables based on them&lt;br /&gt;
#      2) start udevd and trigger rules for block devices to setup initial /dev devices&lt;br /&gt;
#      3) load kernel modules and keyboard map&lt;br /&gt;
#      4) run mdadm, cryptsetup, lvm, zpool/zfs to setup more devices&lt;br /&gt;
#         (any udev rules for them should do more /dev setup in the background)&lt;br /&gt;
#      5) mount the root filesystem read-only at /mnt&lt;br /&gt;
#      6) stat /mnt/sbin/init, and if not executable run a rescue shell /bin/sh&lt;br /&gt;
#      7) shutdown udevd so it can be restarted by root system when booted&lt;br /&gt;
#      8) mount --move {proc,sys,run,dev} to under /mnt&lt;br /&gt;
#      9) run: exec switch_root /mnt /sbin/init $RUNLEVEL&lt;br /&gt;
#    The slackware mkinitrd package is fully configured busybox installation&lt;br /&gt;
#      for an extern file initramfs initrd.gz image outside the kernel.&lt;br /&gt;
#    It could be changed to be inside the kernel easily by just using initrd-tree&lt;br /&gt;
#      as target of INITRAMFS_SOURCE in the kernel config and removing initrd in lilo.&lt;br /&gt;
&lt;br /&gt;
# Because the zfs modules are builtin, we really don't need busybox and the whole&lt;br /&gt;
# mkinitrd package. All we need to do is mount the zfs that is already imported&lt;br /&gt;
# because the zpool.cache is present in rootfs when the zfs module initializes, and&lt;br /&gt;
# then we do the switch root procedure to boot up on the mounted system.&lt;br /&gt;
# udevd rules will still be run when the root system starts udevd.&lt;br /&gt;
&lt;br /&gt;
# So, let's make a simple /init c program that will be all that we really need:&lt;br /&gt;
cat &amp;gt; init.c &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
/* software product name: foobarz-init.c&lt;br /&gt;
 * suggested binary name: /init (in initramfs-source, rootfs)&lt;br /&gt;
 * license              : BSD&lt;br /&gt;
 * license text:&lt;br /&gt;
Copyright (c) 2012, foobarz&lt;br /&gt;
All rights reserved.&lt;br /&gt;
&lt;br /&gt;
Redistribution and use in source and binary forms, with or without&lt;br /&gt;
modification, are permitted provided that the following conditions are met:&lt;br /&gt;
    * Redistributions of source code must retain the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer.&lt;br /&gt;
    * Redistributions in binary form must reproduce the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer in the&lt;br /&gt;
      documentation and/or other materials provided with the distribution.&lt;br /&gt;
    * Neither the name of the &amp;lt;organization&amp;gt; nor the&lt;br /&gt;
      names of its contributors may be used to endorse or promote products&lt;br /&gt;
      derived from this software without specific prior written permission.&lt;br /&gt;
&lt;br /&gt;
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &amp;quot;AS IS&amp;quot; AND&lt;br /&gt;
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED&lt;br /&gt;
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE&lt;br /&gt;
DISCLAIMED. IN NO EVENT SHALL &amp;lt;COPYRIGHT HOLDER&amp;gt; BE LIABLE FOR ANY&lt;br /&gt;
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES&lt;br /&gt;
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;&lt;br /&gt;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND&lt;br /&gt;
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT&lt;br /&gt;
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS&lt;br /&gt;
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#define FOOBARZ_INIT_VERSION &amp;quot;1.0.0&amp;quot;&lt;br /&gt;
#define _BSD_SOURCE&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/stat.h&amp;gt;&lt;br /&gt;
#include &amp;lt;fcntl.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/mount.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sysexits.h&amp;gt;&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/* Your initramfs-source should contain the following&lt;br /&gt;
 * cd /boot/initramfs-source&lt;br /&gt;
 * mkdir -p proc dev sys mnt bin sbin etc/zfs&lt;br /&gt;
 * touch etc/mtab&lt;br /&gt;
 * cp /etc/zfs/zpool.cache-initrd etc/zfs/zpool.cache&lt;br /&gt;
 * mknod dev/console c 5 1   # system console&lt;br /&gt;
 * mknod dev/kmsg    c 1 11  # lines printed to kmsg enter kernel messages buffer&lt;br /&gt;
 * mknod dev/loop0   b 7 0&lt;br /&gt;
 * mknod dev/tty     c 5 0   # current tty&lt;br /&gt;
 * mknod dev/tty0    c 4 0   # current virtual term&lt;br /&gt;
 * mknod dev/tty1    c 4 1   # login virtual term 1 (F1)&lt;br /&gt;
 * mknod dev/ttyS0   c 4 64  # COM1&lt;br /&gt;
 * mknod dev/ttyS1   c 4 65  # COM2&lt;br /&gt;
 * mknod dev/ttyS2   c 4 66  # COM3&lt;br /&gt;
 * mknod dev/ttyS3   c 4 67  $ COM4&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[]) {&lt;br /&gt;
 /***** variables&lt;br /&gt;
  *&lt;br /&gt;
  */&lt;br /&gt;
 int i;&lt;br /&gt;
 FILE* kmsg = NULL;&lt;br /&gt;
 int   fd = 0; /* file descriptor */&lt;br /&gt;
 unsigned long mountflags;&lt;br /&gt;
&lt;br /&gt;
 /* kernel command line */&lt;br /&gt;
 off_t cmdline_size;&lt;br /&gt;
 char* cmdline; /* to be malloc 4096B */&lt;br /&gt;
 char* cmdline_end;&lt;br /&gt;
 char* temp_end;&lt;br /&gt;
 int usage = EX_OK;&lt;br /&gt;
&lt;br /&gt;
 /* use to hold contents of a misc /proc/&amp;lt;file&amp;gt; */&lt;br /&gt;
 char* miscproc_buff; /* to be malloc 4096B */&lt;br /&gt;
 off_t miscproc_size;&lt;br /&gt;
&lt;br /&gt;
 /* note about environ, argv, and kernel cmdline for init:&lt;br /&gt;
  *   environ is not defined for init&lt;br /&gt;
  *   only argv[0] is set for init&lt;br /&gt;
  *   kernel command line parameters are accessed&lt;br /&gt;
  *   at /proc/cmdline&lt;br /&gt;
  */&lt;br /&gt;
&lt;br /&gt;
 /* kernel parameters expected to be name=value */&lt;br /&gt;
 /* do not use quotes or spaces in parameters   */&lt;br /&gt;
 /* you can add more params somwhere after root= */&lt;br /&gt;
 struct nv { char* n; char* v; char* v_end; int req; };&lt;br /&gt;
 struct nv param[] = {&lt;br /&gt;
   { &amp;quot;root=&amp;quot;, NULL, NULL, 1 },      /* required; root device to boot */&lt;br /&gt;
   { &amp;quot;rootfs=&amp;quot;, NULL, NULL, 1 },    /* required; root filesystem type */&lt;br /&gt;
   { &amp;quot;mountopt=&amp;quot;, NULL, NULL, 0 },  /* optional; mount option ro or rw; default ro */&lt;br /&gt;
   { &amp;quot;init=&amp;quot;, NULL, NULL, 0 },      /* optional; alt. init prgm; default /sbin/init */&lt;br /&gt;
   { &amp;quot;runlevel=&amp;quot;, NULL, NULL, 0 },  /* optional; runlevel 0123456Ss; default 3 multiuser */&lt;br /&gt;
   { &amp;quot;console=&amp;quot;, NULL, NULL, 0 }          /* optional; alt. console; e.g. ttyS0 */&lt;br /&gt;
 };&lt;br /&gt;
 enum { iroot, irootfs, imountopt, iinit, irunlevel, iconsole, ilastparam };&lt;br /&gt;
&lt;br /&gt;
 /***** program&lt;br /&gt;
  *&lt;br /&gt;
  */&lt;br /&gt;
 kmsg = fopen(&amp;quot;/dev/kmsg&amp;quot;, &amp;quot;w&amp;quot;);&lt;br /&gt;
 fprintf(kmsg, &amp;quot;foobarz-init, version %s: booting initramfs.\n&amp;quot;, FOOBARZ_INIT_VERSION);&lt;br /&gt;
&lt;br /&gt;
 cmdline = (char*) malloc(4096);&lt;br /&gt;
 miscproc_buff = (char*) malloc(4096);&lt;br /&gt;
 if( (cmdline == NULL) || (miscproc_buff == NULL) ) {&lt;br /&gt;
   fprintf(kmsg, &amp;quot;Unable to allocate buffer memory: malloc: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount proc before dev since some devices&lt;br /&gt;
  * symlink into proc */&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting mount proc /proc\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;proc&amp;quot;, &amp;quot;/proc&amp;quot;, &amp;quot;proc&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;Mount proc successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount devtmpfs as expected by an init program&lt;br /&gt;
  * and maybe required to mount zfs */&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting mount devtmpfs /dev\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;devtmpfs&amp;quot;, &amp;quot;/dev&amp;quot;, &amp;quot;devtmpfs&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;Mount devtmpfs successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
 /* it is assumed that all required devices are in devtmpfs&lt;br /&gt;
  * and if not, there will be boot problems&lt;br /&gt;
  *&lt;br /&gt;
  * if you need a more complex device setup, then you might need&lt;br /&gt;
  * udevd and run it with a larger full initrd package from your distro&lt;br /&gt;
  */&lt;br /&gt;
&lt;br /&gt;
 /* process kernel command line */&lt;br /&gt;
 fd = open(&amp;quot;/proc/cmdline&amp;quot;, O_RDONLY);&lt;br /&gt;
 if( fd == -1 ) {&lt;br /&gt;
   fprintf(kmsg, &amp;quot;Cannot open /proc/cmdline: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 /* note, on /proc fs:&lt;br /&gt;
  *       lseek likely always returns error&lt;br /&gt;
  *       stat likely always returns st_size = 0&lt;br /&gt;
  *   so determining size of /proc file means just reading it;&lt;br /&gt;
  *   you have to read /proc files according to their documented&lt;br /&gt;
  *   maximum sizes; this is probably for performance reasons */&lt;br /&gt;
 cmdline_size = read(fd, cmdline, 4095);&lt;br /&gt;
 if( cmdline_size == -1 ) {&lt;br /&gt;
   fprintf(kmsg, &amp;quot;Failed to read /proc/cmdline: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 close(fd);&lt;br /&gt;
&lt;br /&gt;
 /* cmdline may be newline + null terminated, but make it null + null */&lt;br /&gt;
 cmdline[cmdline_size] = '\0';&lt;br /&gt;
 if( cmdline[cmdline_size-1] == '\n' ) {&lt;br /&gt;
   cmdline[cmdline_size-1] = '\0';&lt;br /&gt;
   cmdline_size--;&lt;br /&gt;
   cmdline_end = cmdline + cmdline_size;&lt;br /&gt;
 }&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Kernel cmdline size: %i\n&amp;quot;, cmdline_size);&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Kernel cmdline: \&amp;quot;%s\&amp;quot;\n&amp;quot;, cmdline);&lt;br /&gt;
&lt;br /&gt;
 for( i=iroot; i&amp;lt;ilastparam; i++ ) {&lt;br /&gt;
   param[i].v = strstr(cmdline, param[i].n);&lt;br /&gt;
   if( param[i].v != NULL ) {&lt;br /&gt;
     while( *(param[i].v) != '=' ) param[i].v++;&lt;br /&gt;
     param[i].v++;&lt;br /&gt;
     temp_end = param[i].v;&lt;br /&gt;
     while( !( (*temp_end == ' ') ||&lt;br /&gt;
               (*temp_end == '\n') ||&lt;br /&gt;
               (temp_end == cmdline_end)&lt;br /&gt;
	     ) ) temp_end++;&lt;br /&gt;
     if( temp_end == param[i].v ) {&lt;br /&gt;
       fprintf(kmsg, &amp;quot;Kernel parameter %s: value missing.\n&amp;quot;, param[i].n);&lt;br /&gt;
     } else param[i].v_end = temp_end;&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* set defaults on non-required params, except for console */&lt;br /&gt;
 if( param[imountopt].v == NULL ) param[imountopt].v = &amp;quot;ro&amp;quot;;&lt;br /&gt;
 if( param[iinit].v == NULL )     param[iinit].v = &amp;quot;/sbin/init&amp;quot;;&lt;br /&gt;
 if( param[irunlevel].v == NULL ) param[irunlevel].v = &amp;quot;3&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
 for( i=iroot; i&amp;lt;ilastparam; i++ ) {&lt;br /&gt;
   if( param[i].v_end != NULL ) *(param[i].v_end) = '\0';&lt;br /&gt;
   fprintf(kmsg, &amp;quot;Using %s \&amp;quot;%s\&amp;quot;\n&amp;quot;, param[i].n, param[i].v);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 for( i=iroot; i&amp;lt;ilastparam; i++ ) {&lt;br /&gt;
   if( (param[i].req == 1) &amp;amp;&amp;amp; (param[i].v == NULL) ) {&lt;br /&gt;
     printf(&amp;quot;Error: missing required kernel parameter: %s\n&amp;quot;, param[i].n);&lt;br /&gt;
     usage = EX_USAGE;&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 if( usage != EX_OK ) {&lt;br /&gt;
   printf(&amp;quot;Aborting boot process. Missing required kernel parameter(s).\n&amp;quot;);&lt;br /&gt;
   return usage;&lt;br /&gt;
 }&lt;br /&gt;
 /* generic nv pair kernel cmdline processing finished&lt;br /&gt;
  *  now, examine specific params for defaults and correctness&lt;br /&gt;
  */&lt;br /&gt;
&lt;br /&gt;
 /* param[iroot]: nothing to do, if user put bad device in then we fail */&lt;br /&gt;
&lt;br /&gt;
 /* param[irootfs]: can be checked against /proc/filesystems: */&lt;br /&gt;
 /* required, so should have value */&lt;br /&gt;
 fd = open(&amp;quot;/proc/filesystems&amp;quot;, O_RDONLY);&lt;br /&gt;
 if( fd == -1 ) {&lt;br /&gt;
   fprintf(kmsg, &amp;quot;Cannot open /proc/filesystems: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 miscproc_size = read(fd, miscproc_buff, 4095);&lt;br /&gt;
 if( miscproc_size == -1 ) {&lt;br /&gt;
   fprintf(kmsg, &amp;quot;Failed to read /proc/filesystems: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 close(fd);&lt;br /&gt;
 if( strstr(miscproc_buff, param[irootfs].v) == NULL ) {&lt;br /&gt;
   fprintf(kmsg, &amp;quot;%s \&amp;quot;%s\&amp;quot;: filesystem type not available.\n&amp;quot;,&lt;br /&gt;
	   param[irootfs].n, param[irootfs].v);&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 if( strcmp(param[irootfs].v, &amp;quot;zfs&amp;quot;) == 0 ) {&lt;br /&gt;
   if( access(&amp;quot;/etc/zfs/zpool.cache&amp;quot;, F_OK) == 0 )&lt;br /&gt;
     fprintf(kmsg, &amp;quot;%s: /etc/zfs/zpool.cache is present in initramfs.\n&amp;quot;, param[irootfs].v);&lt;br /&gt;
   else&lt;br /&gt;
     fprintf(kmsg, &amp;quot;%s: /etc/zfs/zpool.cache not present in initramfs.\n&amp;quot;, param[irootfs].v);&lt;br /&gt;
   if( access(&amp;quot;/etc/hostid&amp;quot;, F_OK) == 0 )&lt;br /&gt;
     fprintf(kmsg, &amp;quot;%s: /etc/hostid is present in initramfs.\n&amp;quot;, param[irootfs].v);&lt;br /&gt;
   else&lt;br /&gt;
     fprintf(kmsg, &amp;quot;%s: /etc/hostid not present in initramfs.\n&amp;quot;, param[irootfs].v);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 if(      strcmp(param[imountopt].v, &amp;quot;ro&amp;quot;) == 0 ) mountflags = MS_RDONLY;&lt;br /&gt;
 else if( strcmp(param[imountopt].v, &amp;quot;rw&amp;quot;) == 0 ) mountflags = 0;&lt;br /&gt;
 else {&lt;br /&gt;
   fprintf(kmsg, &amp;quot;% \&amp;quot;%\&amp;quot;: invalid parameter value;\n&amp;quot;&lt;br /&gt;
		 &amp;quot;   use \&amp;quot;ro\&amp;quot; or \&amp;quot;rw\&amp;quot; (no quotes or spaces);\n&amp;quot;&lt;br /&gt;
		 &amp;quot;   defaulting to \&amp;quot;ro\&amp;quot;.\n&amp;quot;,&lt;br /&gt;
		 param[imountopt].n, param[imountopt].v&lt;br /&gt;
	  );&lt;br /&gt;
   mountflags = MS_RDONLY;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting %s %s mount %s /mnt.\n&amp;quot;,&lt;br /&gt;
	 param[irootfs].v, param[imountopt].v, param[iroot].v);&lt;br /&gt;
 if( mount(param[iroot].v, &amp;quot;/mnt&amp;quot;, param[irootfs].v, mountflags, NULL) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 fprintf(kmsg, &amp;quot;%s mounted successfully.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting mount --move /dev /mnt/dev\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/dev&amp;quot;, &amp;quot;/mnt/dev&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting mount --move /proc /mnt/proc\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/proc&amp;quot;, &amp;quot;/mnt/proc&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Beginning switch root procedure.\n&amp;quot;);&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting chdir from / to /mnt\n&amp;quot;);&lt;br /&gt;
 if( chdir(&amp;quot;/mnt&amp;quot;) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: chdir: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting mount-move . to /\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;.&amp;quot;, &amp;quot;/&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting chroot to .\n&amp;quot;);&lt;br /&gt;
 if( chroot(&amp;quot;.&amp;quot;) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: chroot: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting chdir to /\n&amp;quot;);&lt;br /&gt;
 if( chdir(&amp;quot;/&amp;quot;) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: chdir: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Completed switch root procedure.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 /* check for &amp;quot;console=&amp;quot; kernel parameter and switch&lt;br /&gt;
  *  stdin, stdout, and stderr to named console device&lt;br /&gt;
  */&lt;br /&gt;
 if( param[iconsole].v != NULL ) {&lt;br /&gt;
   fprintf(kmsg, &amp;quot;Console redirection to device %s requested.\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
   fprintf(kmsg, &amp;quot;Opening stdin, stdout, and stderr on %s.\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
   close(0);&lt;br /&gt;
   /* expect only basename of device (e.g., ttyS0), so chdir /dev */&lt;br /&gt;
   chdir(&amp;quot;/dev&amp;quot;);&lt;br /&gt;
   open(param[iconsole].v, O_RDWR);&lt;br /&gt;
   dup2(0, 1);&lt;br /&gt;
   dup2(0, 2);&lt;br /&gt;
   chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Execing: \&amp;quot;%s %s\&amp;quot; to boot mounted root system.\n&amp;quot;,&lt;br /&gt;
	 param[iinit].v, param[irunlevel].v);&lt;br /&gt;
&lt;br /&gt;
 /* free resources held to this point */&lt;br /&gt;
 fclose(kmsg);&lt;br /&gt;
 free(cmdline);&lt;br /&gt;
 free(miscproc_buff);&lt;br /&gt;
&lt;br /&gt;
 if( execl(param[iinit].v, param[irunlevel].v, (char *) NULL ) != 0 ) {&lt;br /&gt;
  kmsg = fopen(&amp;quot;/dev/kmsg&amp;quot;, &amp;quot;w&amp;quot;);&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: execl: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  fclose(kmsg);&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
EOF&lt;br /&gt;
## end of rootfs /init&lt;br /&gt;
&lt;br /&gt;
gcc --static init.c -o init&lt;br /&gt;
strip init&lt;br /&gt;
&lt;br /&gt;
## build and install kernel&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make -j8&lt;br /&gt;
make -j8 modules_install&lt;br /&gt;
cp arch/x86/boot/bzImage /boot/vm3.2.27b&lt;br /&gt;
cp System.map /boot/System.map-vm3.2.27b&lt;br /&gt;
# add new lilo menu entry for vm3.2.27b kernel&lt;br /&gt;
vi /etc/lilo.conf&lt;br /&gt;
  image = /boot/vm3.2.27b&lt;br /&gt;
   label = vm3.2.27b&lt;br /&gt;
   addappend = &amp;quot; spl.spl_hostid=0x007f0100 zfs.spa_config_path=/etc/zfs/zpool.cache root=zfs-root ro rootfstype=zfs rootwait &amp;quot;&lt;br /&gt;
lilo&lt;br /&gt;
reboot&lt;br /&gt;
# note: root=, rootfstype, ro, rootwait are &amp;quot;legacy&amp;quot; kernel boot options and are not really being used here&lt;br /&gt;
#       so, they probably can be removed but are not hurting&lt;br /&gt;
&lt;br /&gt;
# if you have errors using zfs and zpool commands on booted system with builtin modules, then&lt;br /&gt;
# upgrade/switch to the 0.6.0rc10_3.2.27b builds, or you can make a custom package with the binaries&lt;br /&gt;
# renamed like zpoolb, zfsb etc for builtin&lt;br /&gt;
&lt;br /&gt;
# if you have boot problem, you might want to run in qemu's -nographic console mode:&lt;br /&gt;
qemu-kvm &amp;lt;all regular options&amp;gt; -nographic -option-rom sgabios.bin,bootindex=0&lt;br /&gt;
# wait for the lilo prompt, it takes time to show up&lt;br /&gt;
boot: vm3.2.27b console=ttyS0&lt;br /&gt;
# ctrl-a h    for help&lt;br /&gt;
# ctrl-a c    for (QEMU) console&lt;br /&gt;
&lt;br /&gt;
# BECAREFUL not to start qemu twice on the same ZFS guest&lt;br /&gt;
#  two simultaneous running qemu on the same ZFS will corrupt the pool&lt;br /&gt;
#  then it will NOT recover... you lose your whole installation!&lt;br /&gt;
# BECAREFUL when using -nographic ttyS0 that you are not doing commands on the HOST!&lt;br /&gt;
# only use -nographic to see kernel problems then quit it...&lt;br /&gt;
# qemu or slackware is buggy with this it gets stuck right before you get the tty1 prompt.&lt;br /&gt;
&lt;br /&gt;
# to use if=scsi, linux module sym53c8xx, may need to use the qemu option:&lt;br /&gt;
#       -option-rom 8xx_64.rom,bootindex=1&lt;br /&gt;
# download it here:&lt;br /&gt;
# http://www.lsi.com/downloads/Public/Host%20Bus%20Adapters/Host%20Bus%20Adapters%20Common%20Files/lsi_bios.zip&lt;br /&gt;
# extract 8xx_64.rom to /usr/share/qemu/&lt;br /&gt;
&lt;br /&gt;
Then, at the lilo prompt, use kernel parameter: console=ttyS0     (do NOT say /dev/ttS0)&lt;br /&gt;
There is a delay before you see LILO so be patient. You should see full messages of kernel.&lt;br /&gt;
The purpose of sgabios is that it is the &amp;quot;serial graphics adapter&amp;quot; video BIOS that sends all its text mode I/O over ttyS0.&lt;br /&gt;
The -nographic option redirects the guest's ttyS0 to your console.&lt;br /&gt;
The purpose of 8xx_64.rom is the SCSI interface firmware, and it boots after the SGABIOS so that everything will be visible.&lt;br /&gt;
For QEMU help, press ctrl-a then hit h.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Good luck!&lt;/div&gt;</description>
			<pubDate>Thu, 23 Aug 2012 10:17:30 GMT</pubDate>
			<dc:creator>Foobarz</dc:creator>
			<comments>https://www.slackwiki.com/Talk:ZFS_root_(builtin)</comments>
		</item>
		<item>
			<title>ZFS root (builtin)</title>
			<link>https://www.slackwiki.com/index.php?title=ZFS_root_(builtin)&amp;diff=743</link>
			<guid isPermaLink="false">https://www.slackwiki.com/index.php?title=ZFS_root_(builtin)&amp;diff=743</guid>
			<description>&lt;p&gt;Foobarz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Tutorials]]&lt;br /&gt;
The first &amp;quot;ZFS root&amp;quot; wiki explains the details of running ZFS at your root filesystem by using a fully modular generic kernel approach. Now, I can share how it can be done with the SPL and ZFS modules built into the kernel. This procedure is just an example and can use some fine tuning, but here goes:&lt;br /&gt;
&lt;br /&gt;
The steps below are to create kernel with SPL and ZFS modules builtin. This kernel will be installed as an alternatve kernel to boot in lilo, and it will have a separate installation from the fully modular and working system. This will allow testing the builtin kernel while able to boot back onto a working modular ZFS system. We start this procedure assuming you are on a working fully modular ZFS install as in the &amp;quot;ZFS root&amp;quot; wiki.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=legacy zfs-root&lt;br /&gt;
# use legacy so zfs will not expect zfs mount, but instead expect standard mount for this fs&lt;br /&gt;
# edit /etc/rc.d/rc.S and rc.6 to use regular &amp;quot;mount&amp;quot; commands, remove &amp;quot;zfs&amp;quot; commands&lt;br /&gt;
# edit rc.6 and remove or comment out zfs export command&lt;br /&gt;
zpool set bootfs=zfs-root zfs-root&lt;br /&gt;
# this may help, but not really sure&lt;br /&gt;
&lt;br /&gt;
mkdir /boot/initramfs-source&lt;br /&gt;
# this will hold some files for rootfs inside kernel&lt;br /&gt;
&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir src&lt;br /&gt;
cd src&lt;br /&gt;
tar xvzf /mnt/cdrom/slackware64/k/kernel-source-*.txz&lt;br /&gt;
mv usr/src/linux-3.2.27 /usr/src/linux-3.2.27b&lt;br /&gt;
rm -r install&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make menuconfig&lt;br /&gt;
  General setup-&amp;gt;Local version - append to kernel release = b&lt;br /&gt;
  General setup-&amp;gt;Default hostname                         = slackzfs&lt;br /&gt;
  General setup-&amp;gt;Initramfs source files(s)                = /boot/initramfs-source&lt;br /&gt;
  #  make usre you made this directory or the kernel build fails&lt;br /&gt;
  Device Drivers-&amp;gt;SCSI device support-&amp;gt;SCSI low-level drivers-&amp;gt; &amp;lt;*&amp;gt; SYM53C8XX Version 2 SCSI support&lt;br /&gt;
  #  for qemu if=scsi -option-rom 8xx_64.rom,bootindex=1  hard disks&lt;br /&gt;
  # buildin any hard drive controllers etc that you need&lt;br /&gt;
  File systems -&amp;gt; &amp;lt;*&amp;gt; The Extended 4 (ext4) filesystem&lt;br /&gt;
  # /boot may use this ext4 fs&lt;br /&gt;
make prepare scripts&lt;br /&gt;
# this make command is what the spl and zfs copy-builtin scripts expect to be done before they are run&lt;br /&gt;
&lt;br /&gt;
cd ~/src&lt;br /&gt;
tar xvzf ~/spl-0.6.0-rc10.tar.gz&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-0.6.0-rc10&lt;br /&gt;
./configure \&lt;br /&gt;
    --prefix=/ \&lt;br /&gt;
    --libdir=/lib64 \&lt;br /&gt;
    --includedir=/usr/include \&lt;br /&gt;
    --datarootdir=/usr/share \&lt;br /&gt;
    --enable-linux-builtin=yes \&lt;br /&gt;
    --with-linux=/usr/src/linux-3.2.27b \&lt;br /&gt;
    --with-linux-obj=/usr/src/linux-3.2.27b&lt;br /&gt;
wget https://raw.github.com/zfsonlinux/spl/master/copy-builtin&lt;br /&gt;
chmod +x copy-builtin&lt;br /&gt;
./copy-builtin /usr/src/linux-3.2.27b&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../spl-0.6.0rc10_3.2.27b-x86_64-1root.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
&lt;br /&gt;
tar xvzf ~/zfs-0.6.0-rc10.tar.gz&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-0.6.0-rc10&lt;br /&gt;
./configure \&lt;br /&gt;
    --prefix=/ \&lt;br /&gt;
    --libdir=/lib64 \&lt;br /&gt;
    --includedir=/usr/include \&lt;br /&gt;
    --datarootdir=/usr/share \&lt;br /&gt;
    --enable-linux-builtin=yes \&lt;br /&gt;
    --with-linux=/usr/src/linux-3.2.27b \&lt;br /&gt;
    --with-linux-obj=/usr/src/linux-3.2.27b \&lt;br /&gt;
    --with-spl=/root/src/spl-0.6.0-rc10&lt;br /&gt;
wget https://raw.github.com/zfsonlinux/zfs/master/copy-builtin&lt;br /&gt;
chmod +x copy-builtin&lt;br /&gt;
./copy-builtin /usr/src/linux-3.2.27b&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../zfs-0.6.0rc10_3.2.27b-x86_64-1root.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
&lt;br /&gt;
### move zfs and spl modules inside kernel source to be at end of drivers:&lt;br /&gt;
### the order builtin modules init is the order they link into the kernel&lt;br /&gt;
### and we need zfs to init after all hard drive controllers&lt;br /&gt;
### zfs is more like a device driver layer over the lower-level hba drivers&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
mkdir drivers/zfsonlinux&lt;br /&gt;
mv spl drivers/zfsonlinux&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  # remove references to spl&lt;br /&gt;
vi Makefile&lt;br /&gt;
  # remove references to spl&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/fs&lt;br /&gt;
mv zfs ../drivers/zfsonlinux&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  # remove references to zfs&lt;br /&gt;
vi Makefile&lt;br /&gt;
  # remove references to zfs&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  )# add line at end of menu, before &amp;quot;endmenu&amp;quot;:&lt;br /&gt;
  )source &amp;quot;drivers/zfsonlinux/Kconfig&amp;quot;&lt;br /&gt;
  )endmenu&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers&lt;br /&gt;
vi Makefile&lt;br /&gt;
  )# add line at very end of file:&lt;br /&gt;
  )obj-$(CONFIG_ZFSONLINUX) += zfsonlinux/&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers/zfsonlinux&lt;br /&gt;
cat &amp;gt; Kconfig &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
menuconfig ZFSONLINUX&lt;br /&gt;
	tristate &amp;quot;ZFSonLinux support&amp;quot;&lt;br /&gt;
&lt;br /&gt;
if ZFSONLINUX&lt;br /&gt;
&lt;br /&gt;
source &amp;quot;drivers/zfsonlinux/spl/Kconifg&amp;quot;&lt;br /&gt;
&lt;br /&gt;
source &amp;quot;drivers/zfsonlinux/zfs/Kconifg&amp;quot;&lt;br /&gt;
&lt;br /&gt;
endif&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/zfsonlinux&lt;br /&gt;
cat &amp;gt; Makefile &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
obj-$(CONFIG_SPL) += spl/&lt;br /&gt;
obj-$(CONFIG_ZFS) += zfs/&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
### move complete&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make menuconfig&lt;br /&gt;
   Device Drivers -&amp;gt;&lt;br /&gt;
    &amp;lt;*&amp;gt; ZFSonLinux support -&amp;gt;&lt;br /&gt;
      &amp;lt;*&amp;gt; Solaris Porting Layer (SPL)&lt;br /&gt;
      &amp;lt;*&amp;gt;     ZFS&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
### prepare contents of initramfs&lt;br /&gt;
cd /boot/initramfs-source&lt;br /&gt;
&lt;br /&gt;
# make standard directories&lt;br /&gt;
mkdir -p proc dev sys mnt bin sbin etc/zfs&lt;br /&gt;
&lt;br /&gt;
# zfs seems to want mtab present, even if empty&lt;br /&gt;
touch etc/mtab&lt;br /&gt;
&lt;br /&gt;
# if zpool.cache file can be read by zfs at module init, it imports the pools in the cache&lt;br /&gt;
cp /etc/zfs/zpool.cache-initrd etc/zfs/zpool.cache&lt;br /&gt;
&lt;br /&gt;
# make initial console device node; otherwise, there is a problem at startup:&lt;br /&gt;
# &amp;quot;Warning: unable to open an initial console&amp;quot; and you'd have problems with console and tty login&lt;br /&gt;
# making these nodes from within /init is not early enough to avoid problem&lt;br /&gt;
mknod dev/console c 5 1   # system console&lt;br /&gt;
&lt;br /&gt;
# make memory device kmsg to &amp;quot;printk&amp;quot; kernel messages&lt;br /&gt;
# we can write to this file to send out messages&lt;br /&gt;
mknod dev/kmsg    c 1 11  # lines printed to kmsg enter kernel messages buffer&lt;br /&gt;
&lt;br /&gt;
# recommended loop0 device to mount fs images&lt;br /&gt;
mknod dev/loop0   b 7 0&lt;br /&gt;
&lt;br /&gt;
# make initial virtual terminal devices&lt;br /&gt;
mknod dev/tty     c 5 0   # current tty&lt;br /&gt;
mknod dev/tty0    c 4 0   # current virtual term&lt;br /&gt;
mknod dev/tty1    c 4 1   # login virtual term 1 (F1)&lt;br /&gt;
&lt;br /&gt;
# make alternative console=ttyS0 standard 8250/16550 UART serial port devices&lt;br /&gt;
#   useful with kernel parameter console=ttyS0&lt;br /&gt;
#          with qemu -nographic -option-rom sgabios.bin,bootindex=0&lt;br /&gt;
mknod dev/ttyS0   c 4 64  # COM1&lt;br /&gt;
mknod dev/ttyS1   c 4 65  # COM2&lt;br /&gt;
mknod dev/ttyS2   c 4 66  # COM3&lt;br /&gt;
mknod dev/ttyS3   c 4 67  $ COM4&lt;br /&gt;
&lt;br /&gt;
# this should be enough device nodes initially&lt;br /&gt;
# once devtmpfs mounts over /dev, a lot more is available in it by default&lt;br /&gt;
&lt;br /&gt;
cat &amp;gt; /init &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot; &amp;lt;some initial program PID=1 for the system to start on&amp;gt; EOF&lt;br /&gt;
# an initramfs-source/init program is required to mount and boot a root linux system&lt;br /&gt;
# the common way to make /init is using busybox with files like this:&lt;br /&gt;
#    /bin/busybox&lt;br /&gt;
#    /bin/ash -&amp;gt; busybox&lt;br /&gt;
#    /bin/sh -&amp;gt; busybox&lt;br /&gt;
#    # run busybox to see what other &amp;quot;applets&amp;quot; can be symlinked to it&lt;br /&gt;
#    # when busybox is run as a different symlinked applet name, it runs the applet&lt;br /&gt;
#    /init&lt;br /&gt;
#    # init is ash script, see slackware's /boot/initrd-tree/init for example&lt;br /&gt;
#    Inside this script:&lt;br /&gt;
#      1) parse kernel parameters passed into it and set variables based on them&lt;br /&gt;
#      2) start udevd and trigger rules for block devices to setup initial /dev devices&lt;br /&gt;
#      3) load kernel modules and keyboard map&lt;br /&gt;
#      4) run mdadm, cryptsetup, lvm, zpool/zfs to setup more devices&lt;br /&gt;
#         (any udev rules for them should do more /dev setup in the background)&lt;br /&gt;
#      5) mount the root filesystem read-only at /mnt&lt;br /&gt;
#      6) stat /mnt/sbin/init, and if not executable run a rescue shell /bin/sh&lt;br /&gt;
#      7) shutdown udevd so it can be restarted by root system when booted&lt;br /&gt;
#      8) mount --move {proc,sys,run,dev} to under /mnt&lt;br /&gt;
#      9) run: exec switch_root /mnt /sbin/init $RUNLEVEL&lt;br /&gt;
#    The slackware mkinitrd package is fully configured busybox installation&lt;br /&gt;
#      for an extern file initramfs initrd.gz image outside the kernel.&lt;br /&gt;
#    It could be changed to be inside the kernel easily by just using initrd-tree&lt;br /&gt;
#      as target of INITRAMFS_SOURCE in the kernel config and removing initrd in lilo.&lt;br /&gt;
&lt;br /&gt;
# Because the zfs modules are builtin, we really don't need busybox and the whole&lt;br /&gt;
# mkinitrd package. All we need to do is mount the zfs that is already imported&lt;br /&gt;
# because the zpool.cache is present in rootfs when the zfs module initializes, and&lt;br /&gt;
# then we do the switch root procedure to boot up on the mounted system.&lt;br /&gt;
# udevd rules will still be run when the root system starts udevd.&lt;br /&gt;
&lt;br /&gt;
# So, let's make a simple /init c program that will be all that we really need:&lt;br /&gt;
cat &amp;gt; init.c &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
/* software product name: foobarz-init.c&lt;br /&gt;
 * suggested binary name: /init (in initramfs-source, rootfs)&lt;br /&gt;
 * license              : BSD&lt;br /&gt;
 * license text:&lt;br /&gt;
Copyright (c) 2012, foobarz&lt;br /&gt;
All rights reserved.&lt;br /&gt;
&lt;br /&gt;
Redistribution and use in source and binary forms, with or without&lt;br /&gt;
modification, are permitted provided that the following conditions are met:&lt;br /&gt;
    * Redistributions of source code must retain the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer.&lt;br /&gt;
    * Redistributions in binary form must reproduce the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer in the&lt;br /&gt;
      documentation and/or other materials provided with the distribution.&lt;br /&gt;
    * Neither the name of the &amp;lt;organization&amp;gt; nor the&lt;br /&gt;
      names of its contributors may be used to endorse or promote products&lt;br /&gt;
      derived from this software without specific prior written permission.&lt;br /&gt;
&lt;br /&gt;
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &amp;quot;AS IS&amp;quot; AND&lt;br /&gt;
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED&lt;br /&gt;
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE&lt;br /&gt;
DISCLAIMED. IN NO EVENT SHALL &amp;lt;COPYRIGHT HOLDER&amp;gt; BE LIABLE FOR ANY&lt;br /&gt;
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES&lt;br /&gt;
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;&lt;br /&gt;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND&lt;br /&gt;
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT&lt;br /&gt;
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS&lt;br /&gt;
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#define FOOBARZ_INIT_VERSION &amp;quot;1.0.0&amp;quot;&lt;br /&gt;
#define _BSD_SOURCE&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/stat.h&amp;gt;&lt;br /&gt;
#include &amp;lt;fcntl.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/mount.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sysexits.h&amp;gt;&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/* Your initramfs-source should contain the following&lt;br /&gt;
 * cd /boot/initramfs-source&lt;br /&gt;
 * mkdir -p proc dev sys mnt bin sbin etc/zfs&lt;br /&gt;
 * touch etc/mtab&lt;br /&gt;
 * cp /etc/zfs/zpool.cache-initrd etc/zfs/zpool.cache&lt;br /&gt;
 * mknod dev/console c 5 1   # system console&lt;br /&gt;
 * mknod dev/kmsg    c 1 11  # lines printed to kmsg enter kernel messages buffer&lt;br /&gt;
 * mknod dev/loop0   b 7 0&lt;br /&gt;
 * mknod dev/tty     c 5 0   # current tty&lt;br /&gt;
 * mknod dev/tty0    c 4 0   # current virtual term&lt;br /&gt;
 * mknod dev/tty1    c 4 1   # login virtual term 1 (F1)&lt;br /&gt;
 * mknod dev/ttyS0   c 4 64  # COM1&lt;br /&gt;
 * mknod dev/ttyS1   c 4 65  # COM2&lt;br /&gt;
 * mknod dev/ttyS2   c 4 66  # COM3&lt;br /&gt;
 * mknod dev/ttyS3   c 4 67  $ COM4&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[]) {&lt;br /&gt;
 /***** variables&lt;br /&gt;
  *&lt;br /&gt;
  */&lt;br /&gt;
 int i;&lt;br /&gt;
 FILE* kmsg = NULL;&lt;br /&gt;
 int   fd = 0; /* file descriptor */&lt;br /&gt;
 unsigned long mountflags;&lt;br /&gt;
&lt;br /&gt;
 /* kernel command line */&lt;br /&gt;
 off_t cmdline_size;&lt;br /&gt;
 char* cmdline; /* to be malloc 4096B */&lt;br /&gt;
 char* cmdline_end;&lt;br /&gt;
 char* temp_end;&lt;br /&gt;
 int usage = EX_OK;&lt;br /&gt;
&lt;br /&gt;
 /* use to hold contents of a misc /proc/&amp;lt;file&amp;gt; */&lt;br /&gt;
 char* miscproc_buff; /* to be malloc 4096B */&lt;br /&gt;
 off_t miscproc_size;&lt;br /&gt;
&lt;br /&gt;
 /* note about environ, argv, and kernel cmdline for init:&lt;br /&gt;
  *   environ is not defined for init&lt;br /&gt;
  *   only argv[0] is set for init&lt;br /&gt;
  *   kernel command line parameters are accessed&lt;br /&gt;
  *   at /proc/cmdline&lt;br /&gt;
  */&lt;br /&gt;
&lt;br /&gt;
 /* kernel parameters expected to be name=value */&lt;br /&gt;
 /* do not use quotes or spaces in parameters   */&lt;br /&gt;
 /* you can add more params somwhere after root= */&lt;br /&gt;
 struct nv { char* n; char* v; char* v_end; int req; };&lt;br /&gt;
 struct nv param[] = {&lt;br /&gt;
   { &amp;quot;root=&amp;quot;, NULL, NULL, 1 },      /* required; root device to boot */&lt;br /&gt;
   { &amp;quot;rootfs=&amp;quot;, NULL, NULL, 1 },    /* required; root filesystem type */&lt;br /&gt;
   { &amp;quot;mountopt=&amp;quot;, NULL, NULL, 0 },  /* optional; mount option ro or rw; default ro */&lt;br /&gt;
   { &amp;quot;init=&amp;quot;, NULL, NULL, 0 },      /* optional; alt. init prgm; default /sbin/init */&lt;br /&gt;
   { &amp;quot;runlevel=&amp;quot;, NULL, NULL, 0 },  /* optional; runlevel 0123456Ss; default 3 multiuser */&lt;br /&gt;
   { &amp;quot;console=&amp;quot;, NULL, NULL, 0 }          /* optional; alt. console; e.g. ttyS0 */&lt;br /&gt;
 };&lt;br /&gt;
 enum { iroot, irootfs, imountopt, iinit, irunlevel, iconsole, ilastparam };&lt;br /&gt;
&lt;br /&gt;
 /***** program&lt;br /&gt;
  *&lt;br /&gt;
  */&lt;br /&gt;
 kmsg = fopen(&amp;quot;/dev/kmsg&amp;quot;, &amp;quot;w&amp;quot;);&lt;br /&gt;
 fprintf(kmsg, &amp;quot;foobarz-init, version %s: booting initramfs.\n&amp;quot;, FOOBARZ_INIT_VERSION);&lt;br /&gt;
&lt;br /&gt;
 cmdline = (char*) malloc(4096);&lt;br /&gt;
 miscproc_buff = (char*) malloc(4096);&lt;br /&gt;
 if( (cmdline == NULL) || (miscproc_buff == NULL) ) {&lt;br /&gt;
   fprintf(kmsg, &amp;quot;Unable to allocate buffer memory: malloc: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount proc before dev since some devices&lt;br /&gt;
  * symlink into proc */&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting mount proc /proc\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;proc&amp;quot;, &amp;quot;/proc&amp;quot;, &amp;quot;proc&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;Mount proc successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* mount devtmpfs as expected by an init program&lt;br /&gt;
  * and maybe required to mount zfs */&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting mount devtmpfs /dev\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;devtmpfs&amp;quot;, &amp;quot;/dev&amp;quot;, &amp;quot;devtmpfs&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;Mount devtmpfs successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
 /* it is assumed that all required devices are in devtmpfs&lt;br /&gt;
  * and if not, there will be boot problems&lt;br /&gt;
  *&lt;br /&gt;
  * if you need a more complex device setup, then you might need&lt;br /&gt;
  * udevd and run it with a larger full initrd package from your distro&lt;br /&gt;
  */&lt;br /&gt;
&lt;br /&gt;
 /* process kernel command line */&lt;br /&gt;
 fd = open(&amp;quot;/proc/cmdline&amp;quot;, O_RDONLY);&lt;br /&gt;
 if( fd == -1 ) {&lt;br /&gt;
   fprintf(kmsg, &amp;quot;Cannot open /proc/cmdline: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 /* note, on /proc fs:&lt;br /&gt;
  *       lseek likely always returns error&lt;br /&gt;
  *       stat likely always returns st_size = 0&lt;br /&gt;
  *   so determining size of /proc file means just reading it;&lt;br /&gt;
  *   you have to read /proc files according to their documented&lt;br /&gt;
  *   maximum sizes; this is probably for performance reasons */&lt;br /&gt;
 cmdline_size = read(fd, cmdline, 4095);&lt;br /&gt;
 if( cmdline_size == -1 ) {&lt;br /&gt;
   fprintf(kmsg, &amp;quot;Failed to read /proc/cmdline: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 close(fd);&lt;br /&gt;
&lt;br /&gt;
 /* cmdline may be newline + null terminated, but make it null + null */&lt;br /&gt;
 cmdline[cmdline_size] = '\0';&lt;br /&gt;
 if( cmdline[cmdline_size-1] == '\n' ) {&lt;br /&gt;
   cmdline[cmdline_size-1] = '\0';&lt;br /&gt;
   cmdline_size--;&lt;br /&gt;
   cmdline_end = cmdline + cmdline_size;&lt;br /&gt;
 }&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Kernel cmdline size: %i\n&amp;quot;, cmdline_size);&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Kernel cmdline: \&amp;quot;%s\&amp;quot;\n&amp;quot;, cmdline);&lt;br /&gt;
&lt;br /&gt;
 for( i=iroot; i&amp;lt;ilastparam; i++ ) {&lt;br /&gt;
   param[i].v = strstr(cmdline, param[i].n);&lt;br /&gt;
   if( param[i].v != NULL ) {&lt;br /&gt;
     while( *(param[i].v) != '=' ) param[i].v++;&lt;br /&gt;
     param[i].v++;&lt;br /&gt;
     temp_end = param[i].v;&lt;br /&gt;
     while( !( (*temp_end == ' ') ||&lt;br /&gt;
               (*temp_end == '\n') ||&lt;br /&gt;
               (temp_end == cmdline_end)&lt;br /&gt;
	     ) ) temp_end++;&lt;br /&gt;
     if( temp_end == param[i].v ) {&lt;br /&gt;
       fprintf(kmsg, &amp;quot;Kernel parameter %s: value missing.\n&amp;quot;, param[i].n);&lt;br /&gt;
     } else param[i].v_end = temp_end;&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /* set defaults on non-required params, except for console */&lt;br /&gt;
 if( param[imountopt].v == NULL ) param[imountopt].v = &amp;quot;ro&amp;quot;;&lt;br /&gt;
 if( param[iinit].v == NULL )     param[iinit].v = &amp;quot;/sbin/init&amp;quot;;&lt;br /&gt;
 if( param[irunlevel].v == NULL ) param[irunlevel].v = &amp;quot;3&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
 for( i=iroot; i&amp;lt;ilastparam; i++ ) {&lt;br /&gt;
   if( param[i].v_end != NULL ) *(param[i].v_end) = '\0';&lt;br /&gt;
   fprintf(kmsg, &amp;quot;Using %s \&amp;quot;%s\&amp;quot;\n&amp;quot;, param[i].n, param[i].v);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 for( i=iroot; i&amp;lt;ilastparam; i++ ) {&lt;br /&gt;
   if( (param[i].req == 1) &amp;amp;&amp;amp; (param[i].v == NULL) ) {&lt;br /&gt;
     printf(&amp;quot;Error: missing required kernel parameter: %s\n&amp;quot;, param[i].n);&lt;br /&gt;
     usage = EX_USAGE;&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 if( usage != EX_OK ) {&lt;br /&gt;
   printf(&amp;quot;Aborting boot process. Missing required kernel parameter(s).\n&amp;quot;);&lt;br /&gt;
   return usage;&lt;br /&gt;
 }&lt;br /&gt;
 /* generic nv pair kernel cmdline processing finished&lt;br /&gt;
  *  now, examine specific params for defaults and correctness&lt;br /&gt;
  */&lt;br /&gt;
&lt;br /&gt;
 /* param[iroot]: nothing to do, if user put bad device in then we fail */&lt;br /&gt;
&lt;br /&gt;
 /* param[irootfs]: can be checked against /proc/filesystems: */&lt;br /&gt;
 /* required, so should have value */&lt;br /&gt;
 fd = open(&amp;quot;/proc/filesystems&amp;quot;, O_RDONLY);&lt;br /&gt;
 if( fd == -1 ) {&lt;br /&gt;
   fprintf(kmsg, &amp;quot;Cannot open /proc/filesystems: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 miscproc_size = read(fd, miscproc_buff, 4095);&lt;br /&gt;
 if( miscproc_size == -1 ) {&lt;br /&gt;
   fprintf(kmsg, &amp;quot;Failed to read /proc/filesystems: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 close(fd);&lt;br /&gt;
 if( strstr(miscproc_buff, param[irootfs].v) == NULL ) {&lt;br /&gt;
   fprintf(kmsg, &amp;quot;%s \&amp;quot;%s\&amp;quot;: filesystem type not available.\n&amp;quot;,&lt;br /&gt;
	   param[irootfs].n, param[irootfs].v);&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 if( strcmp(param[irootfs].v, &amp;quot;zfs&amp;quot;) == 0 ) {&lt;br /&gt;
   if( access(&amp;quot;/etc/zfs/zpool.cache&amp;quot;, F_OK) == 0 )&lt;br /&gt;
     fprintf(kmsg, &amp;quot;%s: /etc/zfs/zpool.cache is present in initramfs.\n&amp;quot;, param[irootfs].v);&lt;br /&gt;
   else&lt;br /&gt;
     fprintf(kmsg, &amp;quot;%s: /etc/zfs/zpool.cache not present in initramfs.\n&amp;quot;, param[irootfs].v);&lt;br /&gt;
   if( access(&amp;quot;/etc/hostid&amp;quot;, F_OK) == 0 )&lt;br /&gt;
     fprintf(kmsg, &amp;quot;%s: /etc/hostid is present in initramfs.\n&amp;quot;, param[irootfs].v);&lt;br /&gt;
   else&lt;br /&gt;
     fprintf(kmsg, &amp;quot;%s: /etc/hostid not present in initramfs.\n&amp;quot;, param[irootfs].v);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 if(      strcmp(param[imountopt].v, &amp;quot;ro&amp;quot;) == 0 ) mountflags = MS_RDONLY;&lt;br /&gt;
 else if( strcmp(param[imountopt].v, &amp;quot;rw&amp;quot;) == 0 ) mountflags = 0;&lt;br /&gt;
 else {&lt;br /&gt;
   fprintf(kmsg, &amp;quot;% \&amp;quot;%\&amp;quot;: invalid parameter value;\n&amp;quot;&lt;br /&gt;
		 &amp;quot;   use \&amp;quot;ro\&amp;quot; or \&amp;quot;rw\&amp;quot; (no quotes or spaces);\n&amp;quot;&lt;br /&gt;
		 &amp;quot;   defaulting to \&amp;quot;ro\&amp;quot;.\n&amp;quot;,&lt;br /&gt;
		 param[imountopt].n, param[imountopt].v&lt;br /&gt;
	  );&lt;br /&gt;
   mountflags = MS_RDONLY;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting %s %s mount %s /mnt.\n&amp;quot;,&lt;br /&gt;
	 param[irootfs].v, param[imountopt].v, param[iroot].v);&lt;br /&gt;
 if( mount(param[iroot].v, &amp;quot;/mnt&amp;quot;, param[irootfs].v, mountflags, NULL) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 fprintf(kmsg, &amp;quot;%s mounted successfully.\n&amp;quot;, param[iroot].v);&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting mount --move /dev /mnt/dev\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/dev&amp;quot;, &amp;quot;/mnt/dev&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting mount --move /proc /mnt/proc\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/proc&amp;quot;, &amp;quot;/mnt/proc&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Beginning switch root procedure.\n&amp;quot;);&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting chdir from / to /mnt\n&amp;quot;);&lt;br /&gt;
 if( chdir(&amp;quot;/mnt&amp;quot;) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: chdir: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting mount-move . to /\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;.&amp;quot;, &amp;quot;/&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting chroot to .\n&amp;quot;);&lt;br /&gt;
 if( chroot(&amp;quot;.&amp;quot;) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: chroot: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting chdir to /\n&amp;quot;);&lt;br /&gt;
 if( chdir(&amp;quot;/&amp;quot;) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: chdir: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Completed switch root procedure.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 /* check for &amp;quot;console=&amp;quot; kernel parameter and switch&lt;br /&gt;
  *  stdin, stdout, and stderr to named console device&lt;br /&gt;
  */&lt;br /&gt;
 if( param[iconsole].v != NULL ) {&lt;br /&gt;
   fprintf(kmsg, &amp;quot;Console redirection to device %s requested.\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
   fprintf(kmsg, &amp;quot;Opening stdin, stdout, and stderr on %s.\n&amp;quot;, param[iconsole].v);&lt;br /&gt;
   close(0);&lt;br /&gt;
   /* expect only basename of device (e.g., ttyS0), so chdir /dev */&lt;br /&gt;
   chdir(&amp;quot;/dev&amp;quot;);&lt;br /&gt;
   open(param[iconsole].v, O_RDWR);&lt;br /&gt;
   dup2(0, 1);&lt;br /&gt;
   dup2(0, 2);&lt;br /&gt;
   chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Execing: \&amp;quot;%s %s\&amp;quot; to boot mounted root system.\n&amp;quot;,&lt;br /&gt;
	 param[iinit].v, param[irunlevel].v);&lt;br /&gt;
&lt;br /&gt;
 /* free resources held to this point */&lt;br /&gt;
 fclose(kmsg);&lt;br /&gt;
 free(cmdline);&lt;br /&gt;
 free(miscproc_buff);&lt;br /&gt;
&lt;br /&gt;
 if( execl(param[iinit].v, param[irunlevel].v, (char *) NULL ) != 0 ) {&lt;br /&gt;
  kmsg = fopen(&amp;quot;/dev/kmsg&amp;quot;, &amp;quot;w&amp;quot;);&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: execl: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  fclose(kmsg);&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
EOF&lt;br /&gt;
## end of rootfs /init&lt;br /&gt;
&lt;br /&gt;
gcc --static init.c -o init&lt;br /&gt;
strip init&lt;br /&gt;
&lt;br /&gt;
## build and install kernel&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make -j8&lt;br /&gt;
make -j8 modules_install&lt;br /&gt;
cp arch/x86/boot/bzImage /boot/vm3.2.27b&lt;br /&gt;
cp System.map /boot/System.map-vm3.2.27b&lt;br /&gt;
# add new lilo menu entry for vm3.2.27b kernel&lt;br /&gt;
vi /etc/lilo.conf&lt;br /&gt;
  image = /boot/vm3.2.27b&lt;br /&gt;
   label = vm3.2.27b&lt;br /&gt;
   addappend = &amp;quot; spl.spl_hostid=0x007f0100 zfs.spa_config_path=/etc/zfs/zpool.cache root=zfs-root ro rootfstype=zfs rootwait &amp;quot;&lt;br /&gt;
lilo&lt;br /&gt;
reboot&lt;br /&gt;
# note: root=, rootfstype, ro, rootwait are &amp;quot;legacy&amp;quot; kernel boot options and are not really being used here&lt;br /&gt;
#       so, they probably can be removed but are not hurting&lt;br /&gt;
&lt;br /&gt;
# if you have errors using zfs and zpool commands on booted system with builtin modules, then&lt;br /&gt;
# upgrade/switch to the 0.6.0rc10_3.2.27b builds, or you can make a custom package with the binaries&lt;br /&gt;
# renamed like zpoolb, zfsb etc for builtin&lt;br /&gt;
&lt;br /&gt;
# if you have boot problem, you might want to run in qemu's -nographic console mode:&lt;br /&gt;
qemu-kvm &amp;lt;all regular options&amp;gt; -nographic -option-rom sgabios.bin,bootindex=0&lt;br /&gt;
# wait for the lilo prompt, it takes time to show up&lt;br /&gt;
boot: vm3.2.27b console=ttyS0&lt;br /&gt;
# ctrl-a h    for help&lt;br /&gt;
# ctrl-a c    for (QEMU) console&lt;br /&gt;
# BECAREFUL not to start qemu twice on the same ZFS guest&lt;br /&gt;
#  two simultaneous running qemu on the same ZFS will corrupt the pool&lt;br /&gt;
#  then it will NOT recover... you lose your whole installation!&lt;br /&gt;
# BECAREFUL when using -nographic ttyS0 that you are not doing commands on the HOST!&lt;br /&gt;
# only use -nographic to see kernel problems then quit it&lt;br /&gt;
# Doing this is only useful until the kernel panics because additional console switching needs&lt;br /&gt;
# to be done still. If it does boot, then ctrl-a c, and quit (sorry) and reboot normal&lt;br /&gt;
# The console switching part missing in init would look similar to this:&lt;br /&gt;
#&lt;br /&gt;
#if (console) {&lt;br /&gt;
#		close(0);&lt;br /&gt;
#		xopen(console, O_RDWR);&lt;br /&gt;
#		xdup2(0, 1);&lt;br /&gt;
#		xdup2(0, 2);&lt;br /&gt;
#	}&lt;br /&gt;
&lt;br /&gt;
# to use if=scsi, linux module sym53c8xx, may need to use the qemu option:&lt;br /&gt;
#       -option-rom 8xx_64.rom,bootindex=1&lt;br /&gt;
# download it here:&lt;br /&gt;
# http://www.lsi.com/downloads/Public/Host%20Bus%20Adapters/Host%20Bus%20Adapters%20Common%20Files/lsi_bios.zip&lt;br /&gt;
# extract 8xx_64.rom to /usr/share/qemu/&lt;br /&gt;
&lt;br /&gt;
Then, at the lilo prompt, use kernel parameter: console=ttyS0     (do NOT say /dev/ttS0)&lt;br /&gt;
There is a delay before you see LILO so be patient. You should see full messages of kernel.&lt;br /&gt;
The purpose of sgabios is that it is the &amp;quot;serial graphics adapter&amp;quot; video BIOS that sends all its text mode I/O over ttyS0.&lt;br /&gt;
The -nographic option redirects the guest's ttyS0 to your console.&lt;br /&gt;
The purpose of 8xx_64.rom is the SCSI interface firmware, and it boots after the SGABIOS so that everything will be visible.&lt;br /&gt;
For QEMU help, press ctrl-a then hit h.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Good luck!&lt;/div&gt;</description>
			<pubDate>Thu, 23 Aug 2012 10:15:14 GMT</pubDate>
			<dc:creator>Foobarz</dc:creator>
			<comments>https://www.slackwiki.com/Talk:ZFS_root_(builtin)</comments>
		</item>
		<item>
			<title>ZFS root (builtin)</title>
			<link>https://www.slackwiki.com/index.php?title=ZFS_root_(builtin)&amp;diff=742</link>
			<guid isPermaLink="false">https://www.slackwiki.com/index.php?title=ZFS_root_(builtin)&amp;diff=742</guid>
			<description>&lt;p&gt;Foobarz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Tutorials]]&lt;br /&gt;
The first &amp;quot;ZFS root&amp;quot; wiki explains the details of running ZFS at your root filesystem by using a fully modular generic kernel approach. Now, I can share how it can be done with the SPL and ZFS modules built into the kernel. This procedure is just an example and can use some fine tuning, but here goes:&lt;br /&gt;
&lt;br /&gt;
The steps below are to create kernel with SPL and ZFS modules builtin. This kernel will be installed as an alternatve kernel to boot in lilo, and it will have a separate installation from the fully modular and working system. This will allow testing the builtin kernel while able to boot back onto a working modular ZFS system. We start this procedure assuming you are on a working fully modular ZFS install as in the &amp;quot;ZFS root&amp;quot; wiki.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=legacy zfs-root&lt;br /&gt;
# use legacy so zfs will not expect zfs mount, but instead expect standard mount for this fs&lt;br /&gt;
# edit /etc/rc.d/rc.S and rc.6 to use regular &amp;quot;mount&amp;quot; commands, remove &amp;quot;zfs&amp;quot; commands&lt;br /&gt;
# edit rc.6 and remove or comment out zfs export command&lt;br /&gt;
zpool set bootfs=zfs-root zfs-root&lt;br /&gt;
# this may help, but not really sure&lt;br /&gt;
&lt;br /&gt;
mkdir /boot/initramfs-source&lt;br /&gt;
# this will hold some files for rootfs inside kernel&lt;br /&gt;
&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir src&lt;br /&gt;
cd src&lt;br /&gt;
tar xvzf /mnt/cdrom/slackware64/k/kernel-source-*.txz&lt;br /&gt;
mv usr/src/linux-3.2.27 /usr/src/linux-3.2.27b&lt;br /&gt;
rm -r install&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make menuconfig&lt;br /&gt;
  General setup-&amp;gt;Local version - append to kernel release = b&lt;br /&gt;
  General setup-&amp;gt;Default hostname                         = slackzfs&lt;br /&gt;
  General setup-&amp;gt;Initramfs source files(s)                = /boot/initramfs-source&lt;br /&gt;
  #  make usre you made this directory or the kernel build fails&lt;br /&gt;
  Device Drivers-&amp;gt;SCSI device support-&amp;gt;SCSI low-level drivers-&amp;gt; &amp;lt;*&amp;gt; SYM53C8XX Version 2 SCSI support&lt;br /&gt;
  #  for qemu if=scsi -option-rom 8xx_64.rom,bootindex=1  hard disks&lt;br /&gt;
  # buildin any hard drive controllers etc that you need&lt;br /&gt;
  File systems -&amp;gt; &amp;lt;*&amp;gt; The Extended 4 (ext4) filesystem&lt;br /&gt;
  # /boot may use this ext4 fs&lt;br /&gt;
make prepare scripts&lt;br /&gt;
# this make command is what the spl and zfs copy-builtin scripts expect to be done before they are run&lt;br /&gt;
&lt;br /&gt;
cd ~/src&lt;br /&gt;
tar xvzf ~/spl-0.6.0-rc10.tar.gz&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-0.6.0-rc10&lt;br /&gt;
./configure --prefix=/ --libdir=/lib64 --includedir=/usr/include --datarootdir=/usr/share --enable-linux-builtin=yes --with-linux=/usr/src/linux-3.2.27b --with-linux-obj=/usr/src/linux-3.2.27b&lt;br /&gt;
wget https://raw.github.com/zfsonlinux/spl/master/copy-builtin&lt;br /&gt;
chmod +x copy-builtin&lt;br /&gt;
./copy-builtin /usr/src/linux-3.2.27b&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../spl-0.6.0rc10_3.2.27b-x86_64-1root.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
&lt;br /&gt;
tar xvzf ~/zfs-0.6.0-rc10.tar.gz&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-0.6.0-rc10&lt;br /&gt;
./configure --prefix=/ --libdir=/lib64 --includedir=/usr/include --datarootdir=/usr/share --enable-linux-builtin=yes --with-linux=/usr/src/linux-3.2.27b --with-linux-obj=/usr/src/linux-3.2.27b --with-spl=/root/src/spl-0.6.0-rc10&lt;br /&gt;
wget https://raw.github.com/zfsonlinux/zfs/master/copy-builtin&lt;br /&gt;
chmod +x copy-builtin&lt;br /&gt;
./copy-builtin /usr/src/linux-3.2.27b&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../zfs-0.6.0rc10_3.2.27b-x86_64-1root.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
&lt;br /&gt;
### move zfs and spl modules inside kernel source to be at end of drivers:&lt;br /&gt;
### the order builtin modules init is the order they link into the kernel&lt;br /&gt;
### and we need zfs to init after all hard drive controllers&lt;br /&gt;
### zfs is more like a device driver layer over the lower-level hba drivers&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
mkdir drivers/zfsonlinux&lt;br /&gt;
mv spl drivers/zfsonlinux&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  # remove references to spl&lt;br /&gt;
vi Makefile&lt;br /&gt;
  # remove references to spl&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/fs&lt;br /&gt;
mv zfs ../drivers/zfsonlinux&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  # remove references to zfs&lt;br /&gt;
vi Makefile&lt;br /&gt;
  # remove references to zfs&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  )# add line at end of menu, before &amp;quot;endmenu&amp;quot;:&lt;br /&gt;
  )source &amp;quot;drivers/zfsonlinux/Kconfig&amp;quot;&lt;br /&gt;
  )endmenu&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers&lt;br /&gt;
vi Makefile&lt;br /&gt;
  )# add line at very end of file:&lt;br /&gt;
  )obj-$(CONFIG_ZFSONLINUX) += zfsonlinux/&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers/zfsonlinux&lt;br /&gt;
cat &amp;gt; Kconfig &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
menuconfig ZFSONLINUX&lt;br /&gt;
	tristate &amp;quot;ZFSonLinux support&amp;quot;&lt;br /&gt;
&lt;br /&gt;
if ZFSONLINUX&lt;br /&gt;
&lt;br /&gt;
source &amp;quot;drivers/zfsonlinux/spl/Kconifg&amp;quot;&lt;br /&gt;
&lt;br /&gt;
source &amp;quot;drivers/zfsonlinux/zfs/Kconifg&amp;quot;&lt;br /&gt;
&lt;br /&gt;
endif&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/zfsonlinux&lt;br /&gt;
cat &amp;gt; Makefile &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
obj-$(CONFIG_SPL) += spl/&lt;br /&gt;
obj-$(CONFIG_ZFS) += zfs/&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
### move complete&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make menuconfig&lt;br /&gt;
   Device Drivers -&amp;gt;&lt;br /&gt;
    &amp;lt;*&amp;gt; ZFSonLinux support -&amp;gt;&lt;br /&gt;
      &amp;lt;*&amp;gt; Solaris Porting Layer (SPL)&lt;br /&gt;
      &amp;lt;*&amp;gt;     ZFS&lt;br /&gt;
&lt;br /&gt;
cd /boot/initramfs-source&lt;br /&gt;
mkdir -p etc/zfs dev mnt&lt;br /&gt;
touch etc/mtab&lt;br /&gt;
cp /etc/zfs/zpool.cache-initrd etc/zfs/zpool.cache&lt;br /&gt;
&lt;br /&gt;
### make the rootfs /init program&lt;br /&gt;
cat &amp;gt; init.c &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
#define _BSD_SOURCE&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/stat.h&amp;gt;&lt;br /&gt;
#include &amp;lt;fcntl.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/mount.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sysexits.h&amp;gt;&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[]) {&lt;br /&gt;
 FILE* kmsg = NULL;&lt;br /&gt;
 char* fnkmsg = &amp;quot;/dev/kmsg&amp;quot;;&lt;br /&gt;
 mknod(fnkmsg, S_IFCHR , makedev(1,11) );&lt;br /&gt;
 kmsg = fopen(fnkmsg, &amp;quot;w&amp;quot;);&lt;br /&gt;
 fprintf(kmsg, &amp;quot;foobarz-zinit starting.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting mount devtmpfs to /dev\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;devtmpfs&amp;quot;, &amp;quot;/dev&amp;quot;, &amp;quot;devtmpfs&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;Mount devtmpfs successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 if( access(&amp;quot;/dev/zfs&amp;quot;, F_OK) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;File /dev/zfs does not exist; making nod.\n&amp;quot;);&lt;br /&gt;
  mknod(&amp;quot;/dev/zfs&amp;quot;, S_IFCHR , makedev(10,58) );&lt;br /&gt;
 } else {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;File /dev/zfs already exists. Good.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 if( access(&amp;quot;/dev/sda1&amp;quot;, F_OK) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;Files /dev/sd{a,a1} do not exist; making nods.\n&amp;quot;);&lt;br /&gt;
  mknod(&amp;quot;/dev/sda&amp;quot;, S_IFBLK , makedev(8,0) );&lt;br /&gt;
  mknod(&amp;quot;/dev/sda1&amp;quot;, S_IFBLK , makedev(8,1) );&lt;br /&gt;
 } else {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;Files /dev/sd{a,a1} already exist. Good.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting mount-ro newroot to /mnt\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;zfs-root&amp;quot;, &amp;quot;/mnt&amp;quot;, &amp;quot;zfs&amp;quot;, MS_RDONLY, NULL) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting mount-move /dev to /mnt/dev\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/dev&amp;quot;, &amp;quot;/mnt/dev&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Beginning switch root procedure.\n&amp;quot;);&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting chdir from / to /mnt\n&amp;quot;);&lt;br /&gt;
 if( chdir(&amp;quot;/mnt&amp;quot;) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: chdir: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting mount-move . to /\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;.&amp;quot;, &amp;quot;/&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting chroot to .\n&amp;quot;);&lt;br /&gt;
 if( chroot(&amp;quot;.&amp;quot;) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: chroot: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting chdir to /\n&amp;quot;);&lt;br /&gt;
 if( chdir(&amp;quot;/&amp;quot;) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: chdir: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Completed switch root procedure.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Execing root system /sbin/init.\n&amp;quot;);&lt;br /&gt;
 if( execl(&amp;quot;/sbin/init&amp;quot;, &amp;quot;3&amp;quot;, (char *) NULL ) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: execl: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
EOF&lt;br /&gt;
## end of rootfs /init&lt;br /&gt;
&lt;br /&gt;
gcc --static init.c -o init&lt;br /&gt;
strip init&lt;br /&gt;
&lt;br /&gt;
## build and install kernel&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make -j8&lt;br /&gt;
make -j8 modules_install&lt;br /&gt;
cp arch/x86/boot/bzImage /boot/vm3.2.27b&lt;br /&gt;
cp System.map /boot/System.map-vm3.2.27b&lt;br /&gt;
# add new lilo menu entry for vm3.2.27b kernel&lt;br /&gt;
vi /etc/lilo.conf&lt;br /&gt;
  image = /boot/vm3.2.27b&lt;br /&gt;
   label = vm3.2.27b&lt;br /&gt;
   addappend = &amp;quot; spl.spl_hostid=0x007f0100 zfs.spa_config_path=/etc/zfs/zpool.cache root=zfs-root ro rootfstype=zfs rootwait &amp;quot;&lt;br /&gt;
lilo&lt;br /&gt;
reboot&lt;br /&gt;
# note: root=, rootfstype, ro, rootwait are &amp;quot;legacy&amp;quot; kernel boot options and are not really being used here&lt;br /&gt;
#       so, they probably can be removed but are not hurting&lt;br /&gt;
&lt;br /&gt;
# if you have errors using zfs and zpool commands on booted system with builtin modules, then&lt;br /&gt;
# upgrade/switch to the 0.6.0rc10_3.2.27b builds, or you can make a custom package with the binaries&lt;br /&gt;
# renamed like zpoolb, zfsb etc for builtin&lt;br /&gt;
&lt;br /&gt;
# if you have boot problem, you might want to run in qemu's -nographic console mode:&lt;br /&gt;
qemu-kvm &amp;lt;all regular options&amp;gt; -nographic -option-rom sgabios.bin,bootindex=0&lt;br /&gt;
# wait for the lilo prompt, it takes time to show up&lt;br /&gt;
boot: vm3.2.27b console=ttyS0&lt;br /&gt;
# ctrl-a h    for help&lt;br /&gt;
# ctrl-a c    for (QEMU) console&lt;br /&gt;
# BECAREFUL not to start qemu twice on the same ZFS guest&lt;br /&gt;
#  two simultaneous running qemu on the same ZFS will corrupt the pool&lt;br /&gt;
#  then it will NOT recover... you lose your whole installation!&lt;br /&gt;
# BECAREFUL when using -nographic ttyS0 that you are not doing commands on the HOST!&lt;br /&gt;
# only use -nographic to see kernel problems then quit it&lt;br /&gt;
# Doing this is only useful until the kernel panics because additional console switching needs&lt;br /&gt;
# to be done still. If it does boot, then ctrl-a c, and quit (sorry) and reboot normal&lt;br /&gt;
# The console switching part missing in init would look similar to this:&lt;br /&gt;
#&lt;br /&gt;
#if (console) {&lt;br /&gt;
#		close(0);&lt;br /&gt;
#		xopen(console, O_RDWR);&lt;br /&gt;
#		xdup2(0, 1);&lt;br /&gt;
#		xdup2(0, 2);&lt;br /&gt;
#	}&lt;br /&gt;
&lt;br /&gt;
# to use if=scsi, linux module sym53c8xx, may need to use the qemu option:&lt;br /&gt;
#       -option-rom 8xx_64.rom,bootindex=1&lt;br /&gt;
# download it here:&lt;br /&gt;
# http://www.lsi.com/downloads/Public/Host%20Bus%20Adapters/Host%20Bus%20Adapters%20Common%20Files/lsi_bios.zip&lt;br /&gt;
# extract 8xx_64.rom to /usr/share/qemu/&lt;br /&gt;
&lt;br /&gt;
Then, at the lilo prompt, use kernel parameter: console=ttyS0     (do NOT say /dev/ttS0)&lt;br /&gt;
There is a delay before you see LILO so be patient. You should see full messages of kernel.&lt;br /&gt;
The purpose of sgabios is that it is the &amp;quot;serial graphics adapter&amp;quot; video BIOS that sends all its text mode I/O over ttyS0.&lt;br /&gt;
The -nographic option redirects the guest's ttyS0 to your console.&lt;br /&gt;
The purpose of 8xx_64.rom is the SCSI interface firmware, and it boots after the SGABIOS so that everything will be visible.&lt;br /&gt;
For QEMU help, press ctrl-a then hit h.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Good luck!&lt;/div&gt;</description>
			<pubDate>Tue, 21 Aug 2012 18:36:20 GMT</pubDate>
			<dc:creator>Foobarz</dc:creator>
			<comments>https://www.slackwiki.com/Talk:ZFS_root_(builtin)</comments>
		</item>
		<item>
			<title>ZFS root (builtin)</title>
			<link>https://www.slackwiki.com/index.php?title=ZFS_root_(builtin)&amp;diff=741</link>
			<guid isPermaLink="false">https://www.slackwiki.com/index.php?title=ZFS_root_(builtin)&amp;diff=741</guid>
			<description>&lt;p&gt;Foobarz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Tutorials]]&lt;br /&gt;
The first &amp;quot;ZFS root&amp;quot; wiki explains the details of running ZFS at your root filesystem by using a fully modular generic kernel approach. Now, I can share how it can be done with the SPL and ZFS modules built into the kernel. This procedure is just an example and can use some fine tuning, but here goes:&lt;br /&gt;
&lt;br /&gt;
The steps below are to create kernel with SPL and ZFS modules builtin. This kernel will be installed as an alternatve kernel to boot in lilo, and it will have a separate installation from the fully modular and working system. This will allow testing the builtin kernel while able to boot back onto a working modular ZFS system. We start this procedure assuming you are on a working fully modular ZFS install as in the &amp;quot;ZFS root&amp;quot; wiki.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=legacy zfs-root&lt;br /&gt;
# use legacy so zfs will not expect zfs mount, but instead expect standard mount for this fs&lt;br /&gt;
# edit /etc/rc.d/rc.S and rc.6 to use regular &amp;quot;mount&amp;quot; commands, remove &amp;quot;zfs&amp;quot; commands&lt;br /&gt;
# edit rc.6 and remove or comment out zfs export command&lt;br /&gt;
zpool set bootfs=zfs-root zfs-root&lt;br /&gt;
# this may help, but not really sure&lt;br /&gt;
&lt;br /&gt;
mkdir /boot/initramfs-source&lt;br /&gt;
# this will hold some files for rootfs inside kernel&lt;br /&gt;
&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir src&lt;br /&gt;
cd src&lt;br /&gt;
tar xvzf /mnt/cdrom/slackware64/k/kernel-source-*.txz&lt;br /&gt;
mv usr/src/linux-3.2.27 /usr/src/linux-3.2.27b&lt;br /&gt;
rm -r install&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make menuconfig&lt;br /&gt;
  General setup-&amp;gt;Local version - append to kernel release = b&lt;br /&gt;
  General setup-&amp;gt;Default hostname                         = slackzfs&lt;br /&gt;
  General setup-&amp;gt;Initramfs source files(s)                = /boot/initramfs-source&lt;br /&gt;
  #  make usre you made this directory or the kernel build fails&lt;br /&gt;
  Device Drivers-&amp;gt;SCSI device support-&amp;gt;SCSI low-level drivers-&amp;gt; &amp;lt;*&amp;gt; SYM53C8XX Version 2 SCSI support&lt;br /&gt;
  #  for qemu if=scsi -option-rom 8xx_64.rom,bootindex=1  hard disks&lt;br /&gt;
  # buildin any hard drive controllers etc that you need&lt;br /&gt;
  File systems -&amp;gt; &amp;lt;*&amp;gt; The Extended 4 (ext4) filesystem&lt;br /&gt;
  # /boot may use this ext4 fs&lt;br /&gt;
make prepare scripts&lt;br /&gt;
# this make command is what the spl and zfs copy-builtin scripts expect to be done before they are run&lt;br /&gt;
&lt;br /&gt;
cd ~/src&lt;br /&gt;
tar xvzf ~/spl-0.6.0-rc10.tar.gz&lt;br /&gt;
cd spl-0.6.0-rc10&lt;br /&gt;
mkdir install&lt;br /&gt;
./configure --prefix=/ --libdir=/lib64 --includedir=/usr/include --datarootdir=/usr/share --enable-linux-builtin=yes --with-linux=/usr/src/linux-3.2.27b --with-linux-obj=/usr/src/linux-3.2.27b&lt;br /&gt;
wget https://raw.github.com/zfsonlinux/spl/master/copy-builtin&lt;br /&gt;
chmod +x copy-builtin&lt;br /&gt;
./copy-builtin /usr/src/linux-3.2.27b&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../spl-0.6.0rc10_3.2.27b-x86_64-1root.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
&lt;br /&gt;
tar xvzf ~/zfs-0.6.0-rc10.tar.gz&lt;br /&gt;
cd spl-0.6.0-rc10&lt;br /&gt;
mkdir install&lt;br /&gt;
./configure --prefix=/ --libdir=/lib64 --includedir=/usr/include --datarootdir=/usr/share --enable-linux-builtin=yes --with-linux=/usr/src/linux-3.2.27b --with-linux-obj=/usr/src/linux-3.2.27b --with-spl=/root/src/spl-0.6.0-rc10&lt;br /&gt;
wget https://raw.github.com/zfsonlinux/zfs/master/copy-builtin&lt;br /&gt;
chmod +x copy-builtin&lt;br /&gt;
./copy-builtin /usr/src/linux-3.2.27b&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../zfs-0.6.0rc10_3.2.27b-x86_64-1root.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
&lt;br /&gt;
### move zfs and spl modules inside kernel source to be at end of drivers:&lt;br /&gt;
### the order builtin modules init is the order they link into the kernel&lt;br /&gt;
### and we need zfs to init after all hard drive controllers&lt;br /&gt;
### zfs is more like a device driver layer over the lower-level hba drivers&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
mkdir drivers/zfsonlinux&lt;br /&gt;
mv spl drivers/zfsonlinux&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  # remove references to spl&lt;br /&gt;
vi Makefile&lt;br /&gt;
  # remove references to spl&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/fs&lt;br /&gt;
mv zfs ../drivers/zfsonlinux&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  # remove references to zfs&lt;br /&gt;
vi Makefile&lt;br /&gt;
  # remove references to zfs&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  )# add line at end of menu, before &amp;quot;endmenu&amp;quot;:&lt;br /&gt;
  )source &amp;quot;drivers/zfsonlinux/Kconfig&amp;quot;&lt;br /&gt;
  )endmenu&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers&lt;br /&gt;
vi Makefile&lt;br /&gt;
  )# add line at very end of file:&lt;br /&gt;
  )obj-$(CONFIG_ZFSONLINUX) += zfsonlinux/&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers/zfsonlinux&lt;br /&gt;
cat &amp;gt; Kconfig &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
menuconfig ZFSONLINUX&lt;br /&gt;
	tristate &amp;quot;ZFSonLinux support&amp;quot;&lt;br /&gt;
&lt;br /&gt;
if ZFSONLINUX&lt;br /&gt;
&lt;br /&gt;
source &amp;quot;drivers/zfsonlinux/spl/Kconifg&amp;quot;&lt;br /&gt;
&lt;br /&gt;
source &amp;quot;drivers/zfsonlinux/zfs/Kconifg&amp;quot;&lt;br /&gt;
&lt;br /&gt;
endif&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/zfsonlinux&lt;br /&gt;
cat &amp;gt; Makefile &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
obj-$(CONFIG_SPL) += spl/&lt;br /&gt;
obj-$(CONFIG_ZFS) += zfs/&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
### move complete&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make menuconfig&lt;br /&gt;
   Device Drivers -&amp;gt;&lt;br /&gt;
    &amp;lt;*&amp;gt; ZFSonLinux support -&amp;gt;&lt;br /&gt;
      &amp;lt;*&amp;gt; Solaris Porting Layer (SPL)&lt;br /&gt;
      &amp;lt;*&amp;gt;     ZFS&lt;br /&gt;
&lt;br /&gt;
cd /boot/initramfs-source&lt;br /&gt;
mkdir -p etc/zfs dev mnt&lt;br /&gt;
touch etc/mtab&lt;br /&gt;
cp /etc/zfs/zpool.cache-initrd etc/zfs/zpool.cache&lt;br /&gt;
&lt;br /&gt;
### make the rootfs /init program&lt;br /&gt;
cat &amp;gt; init.c &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
#define _BSD_SOURCE&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/stat.h&amp;gt;&lt;br /&gt;
#include &amp;lt;fcntl.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/mount.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sysexits.h&amp;gt;&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[]) {&lt;br /&gt;
 FILE* kmsg = NULL;&lt;br /&gt;
 char* fnkmsg = &amp;quot;/dev/kmsg&amp;quot;;&lt;br /&gt;
 mknod(fnkmsg, S_IFCHR , makedev(1,11) );&lt;br /&gt;
 kmsg = fopen(fnkmsg, &amp;quot;w&amp;quot;);&lt;br /&gt;
 fprintf(kmsg, &amp;quot;foobarz-zinit starting.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting mount devtmpfs to /dev\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;devtmpfs&amp;quot;, &amp;quot;/dev&amp;quot;, &amp;quot;devtmpfs&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;Mount devtmpfs successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 if( access(&amp;quot;/dev/zfs&amp;quot;, F_OK) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;File /dev/zfs does not exist; making nod.\n&amp;quot;);&lt;br /&gt;
  mknod(&amp;quot;/dev/zfs&amp;quot;, S_IFCHR , makedev(10,58) );&lt;br /&gt;
 } else {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;File /dev/zfs already exists. Good.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 if( access(&amp;quot;/dev/sda1&amp;quot;, F_OK) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;Files /dev/sd{a,a1} do not exist; making nods.\n&amp;quot;);&lt;br /&gt;
  mknod(&amp;quot;/dev/sda&amp;quot;, S_IFBLK , makedev(8,0) );&lt;br /&gt;
  mknod(&amp;quot;/dev/sda1&amp;quot;, S_IFBLK , makedev(8,1) );&lt;br /&gt;
 } else {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;Files /dev/sd{a,a1} already exist. Good.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting mount-ro newroot to /mnt\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;zfs-root&amp;quot;, &amp;quot;/mnt&amp;quot;, &amp;quot;zfs&amp;quot;, MS_RDONLY, NULL) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting mount-move /dev to /mnt/dev\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/dev&amp;quot;, &amp;quot;/mnt/dev&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Beginning switch root procedure.\n&amp;quot;);&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting chdir from / to /mnt\n&amp;quot;);&lt;br /&gt;
 if( chdir(&amp;quot;/mnt&amp;quot;) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: chdir: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting mount-move . to /\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;.&amp;quot;, &amp;quot;/&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting chroot to .\n&amp;quot;);&lt;br /&gt;
 if( chroot(&amp;quot;.&amp;quot;) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: chroot: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting chdir to /\n&amp;quot;);&lt;br /&gt;
 if( chdir(&amp;quot;/&amp;quot;) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: chdir: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Completed switch root procedure.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Execing root system /sbin/init.\n&amp;quot;);&lt;br /&gt;
 if( execl(&amp;quot;/sbin/init&amp;quot;, &amp;quot;3&amp;quot;, (char *) NULL ) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: execl: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
EOF&lt;br /&gt;
## end of rootfs /init&lt;br /&gt;
&lt;br /&gt;
gcc --static init.c -o init&lt;br /&gt;
strip init&lt;br /&gt;
&lt;br /&gt;
## build and install kernel&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make -j8&lt;br /&gt;
make -j8 modules_install&lt;br /&gt;
cp arch/x86/boot/bzImage /boot/vm3.2.27b&lt;br /&gt;
cp System.map /boot/System.map-vm3.2.27b&lt;br /&gt;
# add new lilo menu entry for vm3.2.27b kernel&lt;br /&gt;
vi /etc/lilo.conf&lt;br /&gt;
  image = /boot/vm3.2.27b&lt;br /&gt;
   label = vm3.2.27b&lt;br /&gt;
   addappend = &amp;quot; spl.spl_hostid=0x007f0100 zfs.spa_config_path=/etc/zfs/zpool.cache root=zfs-root ro rootfstype=zfs rootwait &amp;quot;&lt;br /&gt;
lilo&lt;br /&gt;
reboot&lt;br /&gt;
# note: root=, rootfstype, ro, rootwait are &amp;quot;legacy&amp;quot; kernel boot options and are not really being used here&lt;br /&gt;
#       so, they probably can be removed but are not hurting&lt;br /&gt;
&lt;br /&gt;
# if you have errors using zfs and zpool commands on booted system with builtin modules, then&lt;br /&gt;
# upgrade/switch to the 0.6.0rc10_3.2.27b builds, or you can make a custom package with the binaries&lt;br /&gt;
# renamed like zpoolb, zfsb etc for builtin&lt;br /&gt;
&lt;br /&gt;
# if you have boot problem, you might want to run in qemu's -nographic console mode:&lt;br /&gt;
qemu-kvm &amp;lt;all regular options&amp;gt; -nographic -option-rom sgabios.bin,bootindex=0&lt;br /&gt;
# wait for the lilo prompt, it takes time to show up&lt;br /&gt;
boot: vm3.2.27b console=ttyS0&lt;br /&gt;
# ctrl-a h    for help&lt;br /&gt;
# ctrl-a c    for (QEMU) console&lt;br /&gt;
# BECAREFUL not to start qemu twice on the same ZFS guest&lt;br /&gt;
#  two simultaneous running qemu on the same ZFS will corrupt the pool&lt;br /&gt;
#  then it will NOT recover... you lose your whole installation!&lt;br /&gt;
# BECAREFUL when using -nographic ttyS0 that you are not doing commands on the HOST!&lt;br /&gt;
# only use -nographic to see kernel problems then quit it&lt;br /&gt;
# Doing this is only useful until the kernel panics because additional console switching needs&lt;br /&gt;
# to be done still. If it does boot, then ctrl-a c, and quit (sorry) and reboot normal&lt;br /&gt;
# The console switching part missing in init would look similar to this:&lt;br /&gt;
#&lt;br /&gt;
#if (console) {&lt;br /&gt;
#		close(0);&lt;br /&gt;
#		xopen(console, O_RDWR);&lt;br /&gt;
#		xdup2(0, 1);&lt;br /&gt;
#		xdup2(0, 2);&lt;br /&gt;
#	}&lt;br /&gt;
&lt;br /&gt;
# to use if=scsi, linux module sym53c8xx, may need to use the qemu option:&lt;br /&gt;
#       -option-rom 8xx_64.rom,bootindex=1&lt;br /&gt;
# download it here:&lt;br /&gt;
# http://www.lsi.com/downloads/Public/Host%20Bus%20Adapters/Host%20Bus%20Adapters%20Common%20Files/lsi_bios.zip&lt;br /&gt;
# extract 8xx_64.rom to /usr/share/qemu/&lt;br /&gt;
&lt;br /&gt;
Then, at the lilo prompt, use kernel parameter: console=ttyS0     (do NOT say /dev/ttS0)&lt;br /&gt;
There is a delay before you see LILO so be patient. You should see full messages of kernel.&lt;br /&gt;
The purpose of sgabios is that it is the &amp;quot;serial graphics adapter&amp;quot; video BIOS that sends all its text mode I/O over ttyS0.&lt;br /&gt;
The -nographic option redirects the guest's ttyS0 to your console.&lt;br /&gt;
The purpose of 8xx_64.rom is the SCSI interface firmware, and it boots after the SGABIOS so that everything will be visible.&lt;br /&gt;
For QEMU help, press ctrl-a then hit h.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Good luck!&lt;/div&gt;</description>
			<pubDate>Tue, 21 Aug 2012 18:35:03 GMT</pubDate>
			<dc:creator>Foobarz</dc:creator>
			<comments>https://www.slackwiki.com/Talk:ZFS_root_(builtin)</comments>
		</item>
		<item>
			<title>ZFS root (builtin)</title>
			<link>https://www.slackwiki.com/index.php?title=ZFS_root_(builtin)&amp;diff=740</link>
			<guid isPermaLink="false">https://www.slackwiki.com/index.php?title=ZFS_root_(builtin)&amp;diff=740</guid>
			<description>&lt;p&gt;Foobarz: how to run ZFS root with builtin modules and minimal initramfs&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Tutorials]]&lt;br /&gt;
The first &amp;quot;ZFS root&amp;quot; wiki explains the details of running ZFS at your root filesystem by using a fully modular generic kernel approach. Now, I can share how it can be done with the SPL and ZFS modules built into the kernel. This procedure is just an example and can use some fine tuning, but here goes:&lt;br /&gt;
&lt;br /&gt;
The steps below are to create kernel with SPL and ZFS modules builtin. This kernel will be installed as an alternatve kernel to boot in lilo, and it will have a separate installation from the fully modular and working system. This will allow testing the builtin kernel while able to boot back onto a working modular ZFS system. We start this procedure assuming you are on a working fully modular ZFS install as in the &amp;quot;ZFS root&amp;quot; wiki.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=legacy zfs-root&lt;br /&gt;
# use legacy so zfs will not expect zfs mount, but instead expect standard mount for this fs&lt;br /&gt;
# edit /etc/rc.d/rc.S and rc.6 to use regular &amp;quot;mount&amp;quot; commands, remove &amp;quot;zfs&amp;quot; commands&lt;br /&gt;
# edit rc.6 and remove or comment out zfs export command&lt;br /&gt;
zpool set bootfs=zfs-root zfs-root&lt;br /&gt;
# this may help, but not really sure&lt;br /&gt;
&lt;br /&gt;
mkdir /boot/initramfs-source&lt;br /&gt;
# this will hold some files for rootfs inside kernel&lt;br /&gt;
&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir src&lt;br /&gt;
cd src&lt;br /&gt;
tar xvzf /mnt/cdrom/slackware64/k/kernel-source-*.txz&lt;br /&gt;
mv usr/src/linux-3.2.27 /usr/src/linux-3.2.27b&lt;br /&gt;
rm -r install&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make menuconfig&lt;br /&gt;
  General setup-&amp;gt;Local version - append to kernel release = b&lt;br /&gt;
  General setup-&amp;gt;Default hostname                         = slackzfs&lt;br /&gt;
  General setup-&amp;gt;Initramfs source files(s)                = /boot/initramfs-source&lt;br /&gt;
  #  make usre you made this directory or the kernel build fails&lt;br /&gt;
  Device Drivers-&amp;gt;SCSI device support-&amp;gt;SCSI low-level drivers-&amp;gt; &amp;lt;*&amp;gt; SYM53C8XX Version 2 SCSI support&lt;br /&gt;
  #  for qemu if=scsi -option-rom 8xx_64.rom,bootindex=1  hard disks&lt;br /&gt;
  # buildin any hard drive controllers etc that you need&lt;br /&gt;
  File systems -&amp;gt; &amp;lt;*&amp;gt; The Extended 4 (ext4) filesystem&lt;br /&gt;
  # /boot may use this ext4 fs&lt;br /&gt;
make prepare scripts&lt;br /&gt;
# this make command is what the spl and zfs copy-builtin scripts expect to be done before they are run&lt;br /&gt;
~/src&lt;br /&gt;
&lt;br /&gt;
tar xvzf ~/spl-0.6.0-rc10.tar.gz&lt;br /&gt;
cd spl-0.6.0-rc10&lt;br /&gt;
mkdir install&lt;br /&gt;
./configure --prefix=/ --libdir=/lib64 --includedir=/usr/include --datarootdir=/usr/share --enable-linux-builtin=yes --with-linux=/usr/src/linux-3.2.27b --with-linux-obj=/usr/src/linux-3.2.27b&lt;br /&gt;
wget https://raw.github.com/zfsonlinux/spl/master/copy-builtin&lt;br /&gt;
chmod +x copy-builtin&lt;br /&gt;
./copy-builtin /usr/src/linux-3.2.27b&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../spl-0.6.0rc10_3.2.27b-x86_64-1root.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
&lt;br /&gt;
tar xvzf ~/zfs-0.6.0-rc10.tar.gz&lt;br /&gt;
cd spl-0.6.0-rc10&lt;br /&gt;
mkdir install&lt;br /&gt;
./configure --prefix=/ --libdir=/lib64 --includedir=/usr/include --datarootdir=/usr/share --enable-linux-builtin=yes --with-linux=/usr/src/linux-3.2.27b --with-linux-obj=/usr/src/linux-3.2.27b --with-spl=/root/src/spl-0.6.0-rc10&lt;br /&gt;
wget https://raw.github.com/zfsonlinux/zfs/master/copy-builtin&lt;br /&gt;
chmod +x copy-builtin&lt;br /&gt;
./copy-builtin /usr/src/linux-3.2.27b&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../zfs-0.6.0rc10_3.2.27b-x86_64-1root.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
&lt;br /&gt;
### move zfs and spl modules inside kernel source to be at end of drivers:&lt;br /&gt;
### the order builtin modules init is the order they link into the kernel&lt;br /&gt;
### and we need zfs to init after all hard drive controllers&lt;br /&gt;
### zfs is more like a device driver layer over the lower-level hba drivers&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
mkdir drivers/zfsonlinux&lt;br /&gt;
mv spl drivers/zfsonlinux&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  # remove references to spl&lt;br /&gt;
vi Makefile&lt;br /&gt;
  # remove references to spl&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/fs&lt;br /&gt;
mv zfs ../drivers/zfsonlinux&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  # remove references to zfs&lt;br /&gt;
vi Makefile&lt;br /&gt;
  # remove references to zfs&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers&lt;br /&gt;
vi Kconfig&lt;br /&gt;
  )# add line at end of menu, before &amp;quot;endmenu&amp;quot;:&lt;br /&gt;
  )source &amp;quot;drivers/zfsonlinux/Kconfig&amp;quot;&lt;br /&gt;
  )endmenu&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers&lt;br /&gt;
vi Makefile&lt;br /&gt;
  )# add line at very end of file:&lt;br /&gt;
  )obj-$(CONFIG_ZFSONLINUX) += zfsonlinux/&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/drivers/zfsonlinux&lt;br /&gt;
cat &amp;gt; Kconfig &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
menuconfig ZFSONLINUX&lt;br /&gt;
	tristate &amp;quot;ZFSonLinux support&amp;quot;&lt;br /&gt;
&lt;br /&gt;
if ZFSONLINUX&lt;br /&gt;
&lt;br /&gt;
source &amp;quot;drivers/zfsonlinux/spl/Kconifg&amp;quot;&lt;br /&gt;
&lt;br /&gt;
source &amp;quot;drivers/zfsonlinux/zfs/Kconifg&amp;quot;&lt;br /&gt;
&lt;br /&gt;
endif&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b/zfsonlinux&lt;br /&gt;
cat &amp;gt; Makefile &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
obj-$(CONFIG_SPL) += spl/&lt;br /&gt;
obj-$(CONFIG_ZFS) += zfs/&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
### move complete&lt;br /&gt;
&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make menuconfig&lt;br /&gt;
   Device Drivers -&amp;gt;&lt;br /&gt;
    &amp;lt;*&amp;gt; ZFSonLinux support -&amp;gt;&lt;br /&gt;
      &amp;lt;*&amp;gt; Solaris Porting Layer (SPL)&lt;br /&gt;
      &amp;lt;*&amp;gt;     ZFS&lt;br /&gt;
&lt;br /&gt;
cd /boot/initramfs-source&lt;br /&gt;
mkdir -p etc/zfs dev mnt&lt;br /&gt;
touch etc/mtab&lt;br /&gt;
cp /etc/zfs/zpool.cache-initrd etc/zfs/zpool.cache&lt;br /&gt;
&lt;br /&gt;
### make the rootfs /init program&lt;br /&gt;
cat &amp;gt; init.c &amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&lt;br /&gt;
#define _BSD_SOURCE&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/stat.h&amp;gt;&lt;br /&gt;
#include &amp;lt;fcntl.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/mount.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sysexits.h&amp;gt;&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[]) {&lt;br /&gt;
 FILE* kmsg = NULL;&lt;br /&gt;
 char* fnkmsg = &amp;quot;/dev/kmsg&amp;quot;;&lt;br /&gt;
 mknod(fnkmsg, S_IFCHR , makedev(1,11) );&lt;br /&gt;
 kmsg = fopen(fnkmsg, &amp;quot;w&amp;quot;);&lt;br /&gt;
 fprintf(kmsg, &amp;quot;foobarz-zinit starting.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting mount devtmpfs to /dev\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;devtmpfs&amp;quot;, &amp;quot;/dev&amp;quot;, &amp;quot;devtmpfs&amp;quot;, 0, NULL) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 } else {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;Mount devtmpfs successful.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 if( access(&amp;quot;/dev/zfs&amp;quot;, F_OK) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;File /dev/zfs does not exist; making nod.\n&amp;quot;);&lt;br /&gt;
  mknod(&amp;quot;/dev/zfs&amp;quot;, S_IFCHR , makedev(10,58) );&lt;br /&gt;
 } else {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;File /dev/zfs already exists. Good.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 if( access(&amp;quot;/dev/sda1&amp;quot;, F_OK) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;Files /dev/sd{a,a1} do not exist; making nods.\n&amp;quot;);&lt;br /&gt;
  mknod(&amp;quot;/dev/sda&amp;quot;, S_IFBLK , makedev(8,0) );&lt;br /&gt;
  mknod(&amp;quot;/dev/sda1&amp;quot;, S_IFBLK , makedev(8,1) );&lt;br /&gt;
 } else {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;Files /dev/sd{a,a1} already exist. Good.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting mount-ro newroot to /mnt\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;zfs-root&amp;quot;, &amp;quot;/mnt&amp;quot;, &amp;quot;zfs&amp;quot;, MS_RDONLY, NULL) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting mount-move /dev to /mnt/dev\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;/dev&amp;quot;, &amp;quot;/mnt/dev&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Beginning switch root procedure.\n&amp;quot;);&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting chdir from / to /mnt\n&amp;quot;);&lt;br /&gt;
 if( chdir(&amp;quot;/mnt&amp;quot;) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: chdir: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting mount-move . to /\n&amp;quot;);&lt;br /&gt;
 if( mount(&amp;quot;.&amp;quot;, &amp;quot;/&amp;quot;, NULL, MS_MOVE, NULL) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: mount: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting chroot to .\n&amp;quot;);&lt;br /&gt;
 if( chroot(&amp;quot;.&amp;quot;) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: chroot: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Attempting chdir to /\n&amp;quot;);&lt;br /&gt;
 if( chdir(&amp;quot;/&amp;quot;) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: chdir: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Completed switch root procedure.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 fprintf(kmsg, &amp;quot;Execing root system /sbin/init.\n&amp;quot;);&lt;br /&gt;
 if( execl(&amp;quot;/sbin/init&amp;quot;, &amp;quot;3&amp;quot;, (char *) NULL ) != 0 ) {&lt;br /&gt;
  fprintf(kmsg, &amp;quot;time to panic: execl: %s\n&amp;quot;, strerror(errno));&lt;br /&gt;
  return EX_UNAVAILABLE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
EOF&lt;br /&gt;
## end of rootfs /init&lt;br /&gt;
&lt;br /&gt;
gcc --static init.c -o init&lt;br /&gt;
strip init&lt;br /&gt;
&lt;br /&gt;
## build and install kernel&lt;br /&gt;
cd /usr/src/linux-3.2.27b&lt;br /&gt;
make -j8&lt;br /&gt;
make -j8 modules_install&lt;br /&gt;
cp arch/x86/boot/bzImage /boot/vm3.2.27b&lt;br /&gt;
cp System.map /boot/System.map-vm3.2.27b&lt;br /&gt;
# add new lilo menu entry for vm3.2.27b kernel&lt;br /&gt;
vi /etc/lilo.conf&lt;br /&gt;
  image = /boot/vm3.2.27b&lt;br /&gt;
   label = vm3.2.27b&lt;br /&gt;
   addappend = &amp;quot; spl.spl_hostid=0x007f0100 zfs.spa_config_path=/etc/zfs/zpool.cache root=zfs-root ro rootfstype=zfs rootwait &amp;quot;&lt;br /&gt;
lilo&lt;br /&gt;
reboot&lt;br /&gt;
# note: root=, rootfstype, ro, rootwait are &amp;quot;legacy&amp;quot; kernel boot options and are not really being used here&lt;br /&gt;
#       so, they probably can be removed but are not hurting&lt;br /&gt;
&lt;br /&gt;
# if you have errors using zfs and zpool commands on booted system with builtin modules, then&lt;br /&gt;
# upgrade/switch to the 0.6.0rc10_3.2.27b builds, or you can make a custom package with the binaries&lt;br /&gt;
# renamed like zpoolb, zfsb etc for builtin&lt;br /&gt;
&lt;br /&gt;
# if you have boot problem, you might want to run in qemu's -nographic console mode:&lt;br /&gt;
qemu-kvm &amp;lt;all regular options&amp;gt; -nographic -option-rom sgabios.bin,bootindex=0&lt;br /&gt;
# wait for the lilo prompt, it takes time to show up&lt;br /&gt;
boot: vm3.2.27b console=ttyS0&lt;br /&gt;
# ctrl-a h    for help&lt;br /&gt;
# ctrl-a c    for (QEMU) console&lt;br /&gt;
# BECAREFUL not to start qemu twice on the same ZFS guest&lt;br /&gt;
#  two simultaneous running qemu on the same ZFS will corrupt the pool&lt;br /&gt;
#  then it will NOT recover... you lose your whole installation!&lt;br /&gt;
# BECAREFUL when using -nographic ttyS0 that you are not doing commands on the HOST!&lt;br /&gt;
# only use -nographic to see kernel problems then quit it&lt;br /&gt;
# Doing this is only useful until the kernel panics because additional console switching needs&lt;br /&gt;
# to be done still. If it does boot, then ctrl-a c, and quit (sorry) and reboot normal&lt;br /&gt;
# The console switching part missing in init would look similar to this:&lt;br /&gt;
#&lt;br /&gt;
#if (console) {&lt;br /&gt;
#		close(0);&lt;br /&gt;
#		xopen(console, O_RDWR);&lt;br /&gt;
#		xdup2(0, 1);&lt;br /&gt;
#		xdup2(0, 2);&lt;br /&gt;
#	}&lt;br /&gt;
&lt;br /&gt;
# to use if=scsi, linux module sym53c8xx, may need to use the qemu option:&lt;br /&gt;
#       -option-rom 8xx_64.rom,bootindex=1&lt;br /&gt;
# download it here:&lt;br /&gt;
# http://www.lsi.com/downloads/Public/Host%20Bus%20Adapters/Host%20Bus%20Adapters%20Common%20Files/lsi_bios.zip&lt;br /&gt;
# extract 8xx_64.rom to /usr/share/qemu/&lt;br /&gt;
&lt;br /&gt;
Then, at the lilo prompt, use kernel parameter: console=ttyS0     (do NOT say /dev/ttS0)&lt;br /&gt;
There is a delay before you see LILO so be patient. You should see full messages of kernel.&lt;br /&gt;
The purpose of sgabios is that it is the &amp;quot;serial graphics adapter&amp;quot; video BIOS that sends all its text mode I/O over ttyS0.&lt;br /&gt;
The -nographic option redirects the guest's ttyS0 to your console.&lt;br /&gt;
The purpose of 8xx_64.rom is the SCSI interface firmware, and it boots after the SGABIOS so that everything will be visible.&lt;br /&gt;
For QEMU help, press ctrl-a then hit h.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Good luck!&lt;/div&gt;</description>
			<pubDate>Tue, 21 Aug 2012 18:28:52 GMT</pubDate>
			<dc:creator>Foobarz</dc:creator>
			<comments>https://www.slackwiki.com/Talk:ZFS_root_(builtin)</comments>
		</item>
		<item>
			<title>ZFS root</title>
			<link>https://www.slackwiki.com/index.php?title=ZFS_root&amp;diff=739</link>
			<guid isPermaLink="false">https://www.slackwiki.com/index.php?title=ZFS_root&amp;diff=739</guid>
			<description>&lt;p&gt;Foobarz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Tutorials]]&lt;br /&gt;
If you have heard about the ZFS filesystem and you're curious to try it out, then you can try it on slackware64, thanks to the ZFSonLinux.org project!&lt;br /&gt;
&lt;br /&gt;
In this article, an example is shown of how to install slackware64 14.0 onto a ZFS root filesystem (zfs-root) inside a QEMU virtual machine for testing purposes. It is recommended that you install qemu and learn how to use it to test a ZFS installation before you decide to use it on real hardware. A slackbuild for qemu can be found on slackbuilds.org. If you have a processor that supports Intel VT-x or AMD AMD-V virtualization acceleration (try modprobe kvm-intel or modprobe kvm-amd), then use the slackbuild for qemu-kvm.&lt;br /&gt;
&lt;br /&gt;
This article isn't going to go into any detail on actually using ZFS or what kinds of installation options and settings might be optimal. This article just presents an example of how to get started with ZFS on slackware.&lt;br /&gt;
&lt;br /&gt;
At this time of writing, ZFSonLinux is at &amp;quot;release candidate&amp;quot; (version 0.6.0-rc10) development stage, and many issues can occur. See the ZFSonLinux.org web site and the issues tracker for an idea about the current issues. There is also an irc channel on irc.freenode.net, #zfsonlinux, for discussion of issues and help.&lt;br /&gt;
&lt;br /&gt;
Although not required, it is helpful to keep a local mirror of slackware64 on your system. Having a local mirror makes it easier to upgrade to slackware64-current or to patches/* in a release. To help manage your own local slackware mirror and generate your own CD and DVD slackware installers, see http://alien.slackbook.org/blog/local-slackware-mirror/.&lt;br /&gt;
&lt;br /&gt;
In this article, we use a slackware64-current DVD image file as the qemu cdrom device media for the installation of the slackware guest. This was tested at slackware64-current = slackware64 14.0rc2. You can obtain a slackware DVD image using a torrent, buy the DVD from slackware.com, or generate your own DVD image file using the mirror script. For an actual DVD, you can pass your DVD device (e.g., /dev/sr0) as the qemu cdrom device. For a DVD image file, pass the image file as the qemu cdrom device.&lt;br /&gt;
&lt;br /&gt;
The ZFSonLinux packages are not included in slackware at this time. There are two packages involved: spl and zfs. The first, spl, is &amp;quot;Solaris Porting Layer&amp;quot; and must be installed on the system before zfs can be compiled. The source code tarballs for these are at ZFSonLinux.org. At this time of writing, they are spl-0.6.0-rc10.tar.gz and zfs-0.6.0-rc10.tar.gz.&lt;br /&gt;
&lt;br /&gt;
At this point, it is assumed you have qemu installed, have obtained a slackware64-current/14.0 DVD, and have downloaded spl and zfs tarballs to your host system. The first step now is, if your host is not slackware64-current/14.0 (the same as the guest will be), then you need to create a minimal development slackware64 guest system in qemu for just the purpose of compiling and packaging the spl and zfs slackware packages and transferring a copy of these packages back onto your host system to use later to install onto zfs during the slackware install process.&lt;br /&gt;
&lt;br /&gt;
From this point onward, instructions become a bit terse and mostly limited to examples of the commands you might use to complete tasks. You are encouraged to examine what each command does by reading the command's man pages. For example, the command &amp;quot;man qemu&amp;quot; can show you most of what you need to know about running qemu on the command line.&lt;br /&gt;
&lt;br /&gt;
So, here's an example of how you might build the spl and zfs packages, starting in your home directory:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on host)&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir qemu&lt;br /&gt;
cd qemu&lt;br /&gt;
mkdir slackdevel&lt;br /&gt;
cd slackdevel&lt;br /&gt;
mkdir packages&lt;br /&gt;
cp ~/spl-*.tar.gz packages&lt;br /&gt;
cp ~/zfs-*.tar.gz packages&lt;br /&gt;
qemu-img create disk1.raw 10G&lt;br /&gt;
ln -s ~/slackware64-current-install-dvd.iso dvd.iso&lt;br /&gt;
qemu-system-x86_64 \&lt;br /&gt;
 -no-quit \&lt;br /&gt;
 -no-shutdown \&lt;br /&gt;
 -boot order=cd,menu=on \&lt;br /&gt;
 -m 2G \&lt;br /&gt;
 -cpu host \&lt;br /&gt;
 -smp sockets=1,cores=4 \&lt;br /&gt;
 -net nic,model=rtl8139 -net user \&lt;br /&gt;
 -cdrom dvd.iso \&lt;br /&gt;
 -drive boot=on,format=raw,media=disk,cache=none,aio=native,if=scsi,bus=0,unit=0,file=disk1.raw \&lt;br /&gt;
 -virtfs local,path=./packages/,security_model=none,mount_tag=hostpackages&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When you need to change boot to cd or disk, add or remove &amp;quot;boot=on&amp;quot;, or change &amp;quot;order=dc&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Qemu should boot into the install-dvd, and now perform a very ordinary slackware64 install onto /dev/sda. Install d package set and most others, but package sets x, kde, xfce not really needed.&lt;br /&gt;
&lt;br /&gt;
First note: examples here use tools from the gptfdisk package (gdisk, sgdisk, cgdisk) to partition the disk with GUID partition table (GPT) format. GPT might not be too familiar to everyone, who mostly have only used MBR partitions with fdisk. In the slackware installations this author has tested in qemu, using GPT partitions has caused no problems with lilo or other tools used in slackware. GPT disk labels support creating up to 128 partitions and support disks larger than 2TB (the limit of MBR fdisk). LILO installs into the first 440 bytes on /dev/sda, inside a GPT &amp;quot;protective MBR&amp;quot; that serves to provide compatibility with MBR bootloaders like lilo. LILO uses LBA32 sector addressing and can see all 512-byte sectors side the first 2TB of a disk. So long as the /boot partition is within the first 2TB of a disk, lilo can work on a disk larger than 2TB. Unlike the common default of fdisk to start the first partition at sector 63, which is not aligned with the 4KiB sector size of Advanced Format hard disks, gdisk's default is to start partitions at 2048 sector (1MiB) boundaries which are also 4KiB aligned. Using gdisk GPT works on all disks and is compatible with using Advanced Format hard disks larger than 2TB. More information about GPT disk label format can be found on wikipedia.org. For those that have used grub instead of lilo, grub installation is different with GPT than with MBR, and grub requires a GPT partition of type grub-bios or 0xEF02 &amp;quot;BIOS Boot Partition&amp;quot; of about 8MiB where it can install it's additional bootloader stages because grub cannot embed in sectors 1-62 on GPT where GPT keeps it's partition tables. On MBR, sectors 1-62 were normally reserved space for bootloaders to keep a 2nd stage.&lt;br /&gt;
&lt;br /&gt;
For this purpose of development guest, just create a simple 1-partition system, /dev/sda1, and do a simple slackware install on it. Don't bother with swap or separate /boot unless you want to:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on install-dvd)&lt;br /&gt;
cgdisk /dev/sda&lt;br /&gt;
setup&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When this simple development guest boots, login as root, and continue:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on qemu guest)&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir packages&lt;br /&gt;
mount hostpackages -t 9p -o trans=virtio packages&lt;br /&gt;
echo --prefix=/ --libexecdir=/usr/libexec --libdir=/lib64 --includedir=/usr/include --datarootdir=/usr/share &amp;gt; configure-options&lt;br /&gt;
mkdir src&lt;br /&gt;
cd src&lt;br /&gt;
&lt;br /&gt;
mkdir install&lt;br /&gt;
tar xvzf ~/packages/spl-*.tar.gz&lt;br /&gt;
cd spl-*&lt;br /&gt;
./configure $( cat ~/configure-options )&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../spl-&amp;lt;version&amp;gt;_&amp;lt;kernel_version&amp;gt;-x86_64-&amp;lt;build_id&amp;gt;.txz&lt;br /&gt;
(e.g., makepkg ../spl-0.6.0rc10_3.2.27-x86_64-1root.txz)&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
installpkg spl-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
cp spl-0.6.0rc10_3.2.27-x86_64-1root.txz ~/packages&lt;br /&gt;
&lt;br /&gt;
mkdir install&lt;br /&gt;
tar xvzf ~/packages/zfs-*.tar.gz&lt;br /&gt;
cd zfs-*&lt;br /&gt;
./configure $( cat ~/configure-options )&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../zfs-&amp;lt;version&amp;gt;_&amp;lt;kernel_version&amp;gt;-x86_64-&amp;lt;build_id&amp;gt;.txz&lt;br /&gt;
(e.g., makepkg ../zfs-0.6.0rc10_3.2.27-x86_64-1root.txz)&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
installpkg zfs-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
cp zfs-0.6.0rc10_3.2.27-x86_64-1root.txz ~/packages&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point spl and zfs packages are copied back to the host in the packages directory. Also, spl and zfs are installed in this simple development guest, so one could begin to experiment with zfs pools and datasets but while the root fs is whatever you made it during setup (probably the default, ext4). This development guest isn't really needed anymore, so it can be deleted:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
halt&lt;br /&gt;
(exit qemu: ctrl-alt-2 then enter quit at QEMU command prompt)&lt;br /&gt;
&lt;br /&gt;
(on host)&lt;br /&gt;
rm disk1.raw dvd.iso&lt;br /&gt;
mv packages ..&lt;br /&gt;
cd ..&lt;br /&gt;
rmdir slackdevel&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now that we have the spl and zfs packages on the host, it is possible to copy them into your local slackware64 mirror and then generate your own install DVD image that includes them. For example, change to the directory that contains the slackware README files, and create a &amp;quot;addon&amp;quot; directory and copy the spl and zfs slackware packages into there. Then, generate the DVD image using a command such as $( ./mirror-slackware-current.sh -i ) from where you have this script configured to maintain your local mirror. We can also just continue to access them inside the installer using qemu's virtfs option. When you are going to do a real installation onto real hardware, you need to generate and burn your own DVD that includes the packages.&lt;br /&gt;
&lt;br /&gt;
It is time to begin the installation of slackware64 on a ZFS root, assuming either you have regenerated dvd.iso with zfs packages in addon/* or we access the zfs packages while in the installer using qemu's virtfs to the host's packages directory. ZFS supports creating complex data storage configurations such as pools (similar to a volume group) backed by one or more of various kinds of virtual devices (similar to disks and raid arrays) and containing one or more datasets (similar to mounted filesystems, logical volume devices, or snapshots). But here, we keep it simple and will install on just a single disk device. On a real ZFS installation, users will typically want to use the ZFS raidz1 or raidz2 virtual device types for reliability against hard drive failures.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on host)&lt;br /&gt;
mkdir slackzfs&lt;br /&gt;
mv packages slackzfs/&lt;br /&gt;
cd slackzfs&lt;br /&gt;
qemu-img create disk1.raw 10G&lt;br /&gt;
ln -s ~/slackware64-current-install-dvd.iso dvd.iso&lt;br /&gt;
qemu-system-x86_64 \&lt;br /&gt;
 -no-quit \&lt;br /&gt;
 -no-shutdown \&lt;br /&gt;
 -boot order=cd,menu=on \&lt;br /&gt;
 -m 2G \&lt;br /&gt;
 -cpu host \&lt;br /&gt;
 -smp sockets=1,cores=4 \&lt;br /&gt;
 -net nic,model=rtl8139 -net user \&lt;br /&gt;
 -cdrom dvd.iso \&lt;br /&gt;
 -drive boot=on,format=raw,media=disk,cache=none,aio=native,if=scsi,bus=0,unit=0,file=disk1.raw \&lt;br /&gt;
 -virtfs local,path=./packages/,security_model=none,mount_tag=hostpackages&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The install-dvd should boot, and then begin installation steps on the installer command line:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on install-dvd)&lt;br /&gt;
# mount the install-dvd&lt;br /&gt;
mkdir /dvd&lt;br /&gt;
mount /dev/sr0 /dvd&lt;br /&gt;
&lt;br /&gt;
# install coreutils, which provides the &amp;quot;hostid&amp;quot; command needed to load the spl module&lt;br /&gt;
installpkg /dvd/slackware64/a/coreutils-8.17-x86_64-1.txz&lt;br /&gt;
&lt;br /&gt;
# install kmod package which includes &amp;quot;depmod&amp;quot; command and others&lt;br /&gt;
installpkg /dvd/slackware64/a/kmod-9-x86_64-2.txz&lt;br /&gt;
depmod&lt;br /&gt;
&lt;br /&gt;
# install the full kernel modules so you can load 9p filesystem and use it if you want&lt;br /&gt;
# .. you might keep the zfs modules packages off the dvd and use a plain slack dvd&lt;br /&gt;
installpkg /dvd/slackware64/a/kernel-modules-*.txz&lt;br /&gt;
depmod&lt;br /&gt;
&lt;br /&gt;
# install bash and libtermcap because udev rules in zfs use bash scripts&lt;br /&gt;
installpkg /dvd/slackware64/a/bash-*.txz&lt;br /&gt;
installpkg /dvd/slackware64/l/libtermcap-*.txz&lt;br /&gt;
&lt;br /&gt;
# install spl and zfs that you have copied into the mirror before running the DVD creation&lt;br /&gt;
installpkg /dvd/addon/spl-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /dvd/addon/zfs-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
&lt;br /&gt;
#Or:&lt;br /&gt;
mkdir /packages&lt;br /&gt;
find /lib/modules/ | grep 9p&lt;br /&gt;
lsmod&lt;br /&gt;
# check that 9p modules load, mainly 9pnet_virtio&lt;br /&gt;
modprobe 9pnet_virtio&lt;br /&gt;
mount hostpackages -t 9p -o trans=virtio /packages&lt;br /&gt;
installpkg /packages/spl-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /packages/zfs-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
modprobe zfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now zfs tools: &amp;quot;zpool&amp;quot; and &amp;quot;zfs&amp;quot; should work in the live installer.&lt;br /&gt;
On the installer, there can be trouble seeing man pages, so install:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
installpkg /dvd/slackware64/ap/man-*.txz&lt;br /&gt;
installpkg /dvd/slackware64/ap/groff-*.txz&lt;br /&gt;
installpkg /dvd/slackware64/a/less-*.txz&lt;br /&gt;
export MANPATH=/usr/man:/usr/share/man&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The manual pages should be readable:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
man zpool&lt;br /&gt;
man zfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After seeing the man pages, we should be fully ready to continue to setup on ZFS.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(still on install-dvd)&lt;br /&gt;
ls -l /dev/sd*&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Make sure the disk devices you expect are there. We'll use sda and make boot (/boot on /dev/sda1) and root (/ on /dev/sda2) partitions.&lt;br /&gt;
&lt;br /&gt;
First, some background info: A ZFS filesystem is not supported by lilo as the filesystem containing /boot, which holds lilo's 2nd stage and the linux kernel files. The on-disk format of a ZFS filesystem is often a complex raid configuration where even if lilo understood ZFS it would likely require /boot to reside in only certain simple ZFS configurations to be plainly readable to lilo. As things are, a linux root installed in a partition with ZFS filesystem needs /boot to be on another partition with a filesystem that lilo understands, such as ext4 fs. In addition, because the spl and zfs modules are not built into the kernel, and the zfs startup requires some configuration to mount the zfs root, an initial ram/root filesystem (initrd) is needed. The initrd is a gzip compressed cpio archive file that contains a small linux root operating system that is decompressed into a ramfs block device at boot up and takes initial control of the system. The initrd contains an init script that configures devices in devtmpfs mounted at /dev. For example, if using mdadm, lvm, luks, losetup, and now zfs, this init script runs all the commands to create or start these devices (one of which is the root device), mounts the root device, and then transfers system control to the init script in the mounted root filesystem. The ramfs-based root environment on the booted install-dvd or booted initrd image (in rescue command line) are small slackware installations that exist only in ram and are temporary, but while inside them you can install, upgrade, and remove slackware packages inside them using the regular package management tools; this allows you access to any kernel modules and programs as needed inside these ramfs root. Packages can be installed, upgraded, or removed permanantly in the initrd image file to manage the programs and modules required during the initrd boot stage. Also from within these ramfs initial root environments, once the root device is mounted, chroot can be used to work on the mounted root system as if it were booted; this allows one to fix problems that are occuring in the root fs init scripts that cause normal booting to fail, or to install a kernel and/or modules etc. Now on to partitioning:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cgdisk /dev/sda&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, cgdisk looks just like cfdisk, but it makes GPT partitions.&lt;br /&gt;
&lt;br /&gt;
Make a partition for /boot that is about 512MiB of whatever partition type you like (8300 &amp;quot;Linux filesystem&amp;quot; is fine), or make it type bf07 &amp;quot;Solaris Reserved 1&amp;quot; if you want ZFS to maybe see the disk as if it was given as a whole disk to ZFS. Make a second partition using the remaining space with partition type bf01 &amp;quot;Solaris ZFS&amp;quot;. Currently, when ZFSonLinux is given a whole disk device like /dev/sdb to use, it will automatically GPT partition it with a bf01 partition #1 that is the whole disk except a small 8MiB type bf07 partition #9 at the end of the disk (/dev/sdb1 and /dev/sb9). The small 8MiB type bf07 partition #9 is mostly likely reserved for use by bootloaders, like lilo, to have a /boot or other boot-related files kept there. For example, you might have /dev/sda that is totally non-ZFS for booting and /dev/sdb passed to ZFS whole where it automatically partitions sdb, but you can just use one disk here and make partitions. Lets use type 8300 for /boot to be sure nothing is confused:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
We'll continue with this partitioning (numbers are in MiB):&lt;br /&gt;
  0 to   4: unused&lt;br /&gt;
  4 to 516: /dev/sda1 512MiB, type 8300&lt;br /&gt;
516 to 520: unused&lt;br /&gt;
520 to -96: /dev/sda2, type bf01&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The -96 means to count from the end of the disk so that 96MiB will remain unused at the end of the disk.&lt;br /&gt;
&lt;br /&gt;
Create a zpool called zfs-root:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool create -m none zfs-root /dev/sda2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A zpool created like this, the normal way, is a kernel-internal block device that contains already a zfs filesystem. There is normally no entry in /dev for this device. However, it can still be referenced as a mountable device similar to how devtmpfs, proc, and sysfs are also kernel-internal mountable block devices. The -m option told zpool not to automatically mount it anywhere, and without -m the default is to always automatically mount to /zfs-root. These kinds of details are explained better elsewhere. For this situation, we do not want it automounted.&lt;br /&gt;
&lt;br /&gt;
Because a zpool itself is a useable zfs fs, it has a full set of zfs &amp;quot;properties&amp;quot; to set options about the filesystem, perhaps similar to tune2fs. The &amp;quot;mountpoint=&amp;lt;some place to mount&amp;gt;&amp;quot; is one such property. We want it set to the special value &amp;quot;none&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs get mountpoint zfs-root&lt;br /&gt;
zfs set mountpoint=none zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On creation, the zpool zfs-pool is &amp;quot;imported&amp;quot; and has a zpool status that can be viewed:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool status zfs-root&lt;br /&gt;
&lt;br /&gt;
zpool export zfs-root&lt;br /&gt;
zpool status zfs-root&lt;br /&gt;
# Now there is no status.&lt;br /&gt;
&lt;br /&gt;
zpool import zfs-root&lt;br /&gt;
# Now it is back.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When a zpool is imported, it has it's current configuration cached in a file /etc/zfs/zpool.cache. When a zpool is exported, then it's entries in the cache file are removed and the cache file is deleted if it becomes empty. So long as the zfs kernel modules see this cache file and valid cache data inside it, ZFS considers the described zpools in the cache file to be valid as imported zpools. If the zpool.cache file is present at the time the zfs modules are loaded, then there is no further need to use the import and export commands at system startup and shutdown. With root on a zfs, it is not possible to export the pool that root is on, but this is not a problem. At shutdown, the safe procedure will be to set the zfs-root property readonly=on and sync disks.&lt;br /&gt;
&lt;br /&gt;
To avoid the requirement to import the zfs-root pool at startup, keep a copy of the zpool.cache file to later copy onto the initrd image to read at modules load time to have the pool reactived without need to issue the import command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/zfs/zpool.cache /etc/zfs/zpool.cache-initrd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A zfs fs will not normally allow you to mount over any files. The mountpoint is expected to be an empty directory. Remove any junk files inside the installer's /mnt because zfs won't mount over any files:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rm /mnt/README&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The directory /mnt is where the slackware setup expects you to mount your root for installation.&lt;br /&gt;
&lt;br /&gt;
Controlling whether a zfs fs is to be mounted read-only or read-write is best managed by setting the readonly property while it is not yet mounted:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set readonly=on zfs-root&lt;br /&gt;
zfs set readonly=off zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Slackware expects root to be mounted readonly when /etc/rc.d/rc.S runs during normal startup, so later this is used to satisfy slackware's expectation to avoid rc.S complaining.&lt;br /&gt;
&lt;br /&gt;
The zfs-root can be mounted and unmounted in two different ways:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=/mnt zfs-root&lt;br /&gt;
zfs set mountpoint=none zfs-root&lt;br /&gt;
# or&lt;br /&gt;
mount zfs-root -t zfs /mnt&lt;br /&gt;
umount /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If it is already mounted and you want to change it to mount somewhere else, it is best to transition it to unmounted first, then mount it in the new place.&lt;br /&gt;
&lt;br /&gt;
The mount options &amp;lt;code&amp;gt;-o ro, -o rw, -o remount,ro, and -o remount,rw &amp;lt;/code&amp;gt; can also be used and will override &amp;lt;code&amp;gt;readonly=on|off&amp;lt;/code&amp;gt; property without altering the property value. This can be confusing until you are familiar with how to the methods of mounting interact.&lt;br /&gt;
&lt;br /&gt;
Now, let's continue some, and mount to /mnt using the current &amp;lt;code&amp;gt;readonly=off&amp;lt;/code&amp;gt; setting (rw mount):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=/mnt zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This method of mounting will show the most detailed mount options in /etc/mtab. They are the mount options that zfs thinks are proper, and they are probably what should be kept in /etc/fstab for zfs-root until we know better.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cat /etc/mtab &amp;gt;&amp;gt; /etc/fstab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now edit /etc/fstab to make sure it looks right, and remove the &amp;quot;rw&amp;quot; mount option, because we want to let it use a default for that, which will come from how we set the readonly= property most of the time. Unmount again:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=none zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mount again, now using all options from /etc/fstab:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It should be mounted at /mnt, and touch /mnt/t should allow you to make the file t. Then rm it: rm /mnt/t&lt;br /&gt;
For installation, we want to make sure it is mounted read-write. After installation, it should mount readonly inside the initrd.&lt;br /&gt;
&lt;br /&gt;
Sometimes there can be problems using the mount command, and then you can try it with the -i option:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 mount -i zfs-root&lt;br /&gt;
 mount -i zfs-root -t zfs /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
but, you should not have to use -i. When using -i makes it work, it performs an &amp;quot;internal-only&amp;quot; mount and does not use any mount.&amp;lt;fstype&amp;gt; helper scripts that might be on the system.&lt;br /&gt;
&lt;br /&gt;
Setup the /boot device:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkfs.ext4 /dev/sda1&lt;br /&gt;
mkdir /mnt/boot&lt;br /&gt;
mount /dev/sda1 /mnt/boot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We have both root and boot mounted where the slackware installer expects them. Unmount the dvd so setup can find it normally:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
umount /dev/sr0&lt;br /&gt;
setup&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the setup, skip straight to TARGET selection for the root device, but the setup doesn't see or understand the zfs-root, so it is not listed. This does not matter because we have mounted it already. Just skip down to a slot that say to continue, and continue on with setup. Because TARGET is skipped, you may not see the ADDITIONAL prompt (or if so, skip it too) where normally you give /dev/sda1 and have it mounted as /boot. This is also okay because we have mounted /mnt/boot already.&lt;br /&gt;
Because we did not give TARGET the root device or say what device /boot is on, the lilo installation will fail, or you can skip it. Otherwise, this installation process it normal.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
umount /dev/sr0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point, it is assumed that the setup has completed installing into /mnt. Congrats! You've installed slackware into a ZFS root!&lt;br /&gt;
&lt;br /&gt;
The next steps are to prepare to use &amp;quot;chroot /mnt&amp;quot; and finish up the configuration on the installed root system and then be able to reboot onto the completed installation. Before doing chroot, copy some files from the setup environment into /mnt.&lt;br /&gt;
&lt;br /&gt;
Copy the current installer /etc/fstab for later use inside the initrd. This fstab is what is proper inside the initrd, except remove option &amp;quot;rw&amp;quot; (if not done already).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/fstab /mnt/etc/fstab.initrd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The fstab.initrd will look like:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 proc /proc proc defaults 0 0&lt;br /&gt;
 zfs-root /mnt zfs defaults,atime,dev,exec,suid,xattr,nomand,zfsutil 0 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the initrd, we want zfs-root to mount to /mnt.&lt;br /&gt;
&lt;br /&gt;
Create /mnt/etc/fstab:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cat /etc/mtab &amp;gt;&amp;gt; /mnt/etc/fstab&lt;br /&gt;
vi /mnt/etc/fstab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using vi started above, edit /mnt/etc/fstab and make it have lines such as:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 zfs-root / zfs defaults,atime,dev,exec,suid,xattr,nomand,zfsutil 0 0&lt;br /&gt;
 /dev/sda1 /boot ext4 defaults 0 2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These two lines in &amp;lt;code&amp;gt;/mnt/etc/fstab&amp;lt;/code&amp;gt; are how the mounts should be looking when root is booted.&lt;br /&gt;
&lt;br /&gt;
Mount some special mounts before chroot:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount -t devtmpfs none /mnt/dev&lt;br /&gt;
mount -t proc none /mnt/proc&lt;br /&gt;
mount -t sysfs none /mnt/sys&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Make sure /boot is mounted:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount /dev/sda1 /mnt/boot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you had mounted a 9p fs share to access spl and zfs packages, then unmount that now:&lt;br /&gt;
umount /packages&lt;br /&gt;
&lt;br /&gt;
Ready, now:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chroot /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point, you should be on the installed system, and now try to configure mkinitrd and lilo. First, switch to use the generic kernel.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /boot&lt;br /&gt;
rm System.map config vmlinuz&lt;br /&gt;
ln -s System.map-gen* System.map&lt;br /&gt;
ln -s config-gen* config&lt;br /&gt;
ln -s vmlinuz-gen* vmlinuz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We install spl and zfs inside the live ramfs install-dvd environment, but not yet have we installed them into the root system:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount /dev/sr0 /mnt/cdrom&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /mnt/cdrom/addon/spl-*.txz&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /mnt/cdrom/addon/zfs-*.txz&lt;br /&gt;
depmod&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If instead, you used a 9p share to access the spl and zfs packages, then repeat that procedure here to install them onto the root system.&lt;br /&gt;
&lt;br /&gt;
Setup lilo: edit /etc/lilo.conf so it is like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  lba32&lt;br /&gt;
  append = &amp;quot; vt.default_utf8=1&amp;quot;&lt;br /&gt;
  boot = /dev/sda&lt;br /&gt;
  message = /boot/boot_message.txt&lt;br /&gt;
  prompt&lt;br /&gt;
  timeout = 1200&lt;br /&gt;
  change-rules&lt;br /&gt;
   reset&lt;br /&gt;
  vga = normal&lt;br /&gt;
  image = /boot/vmlinuz&lt;br /&gt;
   label = vmlinuz&lt;br /&gt;
   initrd = /boot/initrd.gz&lt;br /&gt;
   root = /dev/ram0&lt;br /&gt;
   read-write&lt;br /&gt;
# alternatively, the root and read-write lines&lt;br /&gt;
# can be this one line of kernel parameters:&lt;br /&gt;
#  addappend = &amp;quot; root=/dev/ram0 rw &amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A note about initrd: The /boot/initrd.gz is a gzipped cpio archive containing a minimal BusyBox-based slackware root system that is sourced from /boot/initrd-tree. The commands &amp;quot;mkinitrd&amp;quot; and &amp;quot;mkinitrd -F&amp;quot; generates /boot/initrd-tree and /boot/initrd.gz. When using a initrd, the initial root device is normally set to root=/dev/ram0 (a ramfs block device) and allowed read-write. The kernel refers to devices in terms of &amp;quot;major&amp;quot; and &amp;quot;minor&amp;quot; numbers, and the ram0 device is assigned the block device major 1 and minor 0. This ram0 major/minor is written in hexadecimal as 0x0100 (256 in decimal). This hexademical number makes an appearance in /boot/initrd-tree/int where it runs: &amp;quot;echo 0x0100 &amp;gt; /proc/sys/kernel/real-root-dev&amp;quot;. Echoing a device code to real-root-dev is part of a deprecated initrd mechanism, but is probably harmless to leave alone as slackware has it unless you know otherwise. More information about how initrd works can be found in:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/usr/src/linux/Documentation/devices.txt (info about major:minor device numbers)&lt;br /&gt;
/usr/src/linux/Documentation/initrd.txt  (mostly obsolete info on old initrd)&lt;br /&gt;
/usr/src/linux/Documentation/filesystems/ramfs-rootfs-initramfs.txt (current info on new initrd, called initramfs)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Advanced note about initrd: Slackware's mkinitrd package does not use the &amp;quot;pivot_root&amp;quot; command as documented in &amp;quot;initrd.txt&amp;quot;, but instead uses &amp;quot;switch_root&amp;quot; provided by a project called BusyBox. The switch_root changes the effective root filesystem from the initrd (unpacked in rootfs at /) to new root filesystem (zfs-root mounted at /mnt); it overmounts rootfs / with zfs-root /mnt. The switch_root works as follows: delete everything in rootfs / (one filesystem only) that held initrd to free up ram memory, then use mount, chroot, and chdir to make the effective root change. In concept (as a shell script), the command &amp;quot;exec switch_root /mnt $INIT $RUNLEVEL&amp;quot; is performed as follows:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 find / -xdev | xargs rm -rf&lt;br /&gt;
 cd &amp;quot;$1&amp;quot;&lt;br /&gt;
 shift&lt;br /&gt;
 mount --move . /&lt;br /&gt;
 exec chroot . &amp;quot;$@&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Here, typically INIT=/sbin/init RUNLEVEL=3. The 'exec' causes switch_root to take the place of the parent process having PID=1. In system calls, the switch_root looks similar to this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chdir(&amp;quot;/mnt&amp;quot;);&lt;br /&gt;
/* &amp;lt;insert code to unlink/rmdir all initrd files/directories&lt;br /&gt;
 *  installed in rootfs / without crossing filesystems &amp;gt; */&lt;br /&gt;
mount(&amp;quot;.&amp;quot;, &amp;quot;/&amp;quot;, NULL, MS_MOVE, NULL);&lt;br /&gt;
chroot(&amp;quot;.&amp;quot;);&lt;br /&gt;
chdir(&amp;quot;/&amp;quot;);&lt;br /&gt;
execl(&amp;quot;/sbin/init&amp;quot;, &amp;quot;3&amp;quot;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The kernel startup rootfs / that contained initrd is never actually unmounted (it can't be) because it is built into the kernel and always exists as at least a tiny ramfs or tmpfs, so you can continue to see it in /proc/mounts. When you give lilo root=/dev/ram0 (a ramfs device), the kernel will actually use the internal rootfs, which is an instance of a tmpfs (if your kernel config includes tmpfs) or else an instance of a ramfs. The rootfs that is a tmpfs can by default use up to half of system ram. If rootfs is a ramfs, it can use up to almost all of system ram until the system panics. Typically, tmpfs is built into the kernel, and so depending on how much ram your computer has, the initrd-tree can probably be up to about half that size.&lt;br /&gt;
&lt;br /&gt;
Quite a lot of notes... now to continue on:&lt;br /&gt;
&lt;br /&gt;
Setup mkinitrd:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/mkinitrd.conf.sample /etc/mkinitrd.conf&lt;br /&gt;
vi /etc/mkinitrd.conf&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Edit it to look like this (other defaults should be ok):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 MODULE_LIST=&amp;quot;sym53c8xx:ext4:8139cp:zfs:9p:9pnet_virtio&amp;quot;&lt;br /&gt;
 ROOTDEV=&amp;quot;zfs-root&amp;quot;&lt;br /&gt;
 ROOTFS=&amp;quot;zfs&amp;quot;&lt;br /&gt;
#Module sym53c8xx is the driver for qemu's if=scsi drive device.&lt;br /&gt;
#Module ext4 for /boot.&lt;br /&gt;
#Module 8139cp for eth0 net device.&lt;br /&gt;
#Module zfs for ZFSonLinux.&lt;br /&gt;
#Modules 9p and 9pnet_virtio for mounting qemu -virtfs mount_tag.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These 9p could be useful from the rescue command line inside the initrd to get needed files that are on the host.&lt;br /&gt;
&lt;br /&gt;
All dependent modules will also be included automatically into /boot/initrd-tree, which is packaged as /boot/initrd.gz. For example, to see the dependent modules of zfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
modprobe --show-depends zfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All listed modules will also be in the initrd. Now, make a /boot/initrd-tree that we can begin to look at and edit.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkinitrd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create an empty /etc/mtab or else zpool import fails (zfs expects /etc/mtab to exists already, it won't make it).&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
touch /boot/initrd-tree/etc/mtab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Copy in the fstab.initrd that was made earlier while on the installer. This provides all the mount options for a simple &amp;quot;mount zfs-root&amp;quot; onto /mnt.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/fstab.initrd /boot/initrd-tree/etc/fstab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More package installing! This time into an alternate root, the root of the initrd, /boot/initrd-tree. This is how you can put whatever packages you like into your initrd. These installations work independent of your normal installations. You can install, upgrade, and remove packages using an altroot:&lt;br /&gt;
&lt;br /&gt;
If spl and zfs are on your customized dvd:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/addon/spl-*.txz&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/addon/zfs-*.txz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Otherwise, repeat same procedure but you mount your 9p mount_tag and get them installed.&lt;br /&gt;
&lt;br /&gt;
More regular packages from the dvd:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/kmod-*.txz&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/coreutils-*.txz&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/gptfdisk-*.txz&lt;br /&gt;
&lt;br /&gt;
# A bash script is in /boot/initrd-tree/lib/udev/, so we need it or udev rules have problems:&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/bash-*.txz&lt;br /&gt;
# Bash needs this:&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/l/libtermcap-*.txz&lt;br /&gt;
&lt;br /&gt;
# Install net-tools to ensure that /etc/HOSTNAME, /etc/hosts, and potentially, /etc/hostid are handled proper.&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/n/net-tools-*.txz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When ZFS has to import a zpool while the initrd is running (this can be avoided by not exporting and keeping /etc/zfs/zpool.cache inside the initrd), ZFS will refuse to import a pool if it thinks that the pool may be in use by another system. ZFS was designed for network attached storage where multiple hosts might have access to the same disks but ZFS cannot support two hosts importing and using a ZFS pool at the same time. ZFS checks a value called &amp;quot;hostid&amp;quot; to determine this kind of conflict, and it can be a tricky issue with an initrd boot process. The value of hostid is returned by a system call, the gethostid() function or the hostid command. This function will return the hostid from /etc/hostid if that file exists and has a valid id in it, or else if the file doesn't exist it obtains a hostid number based on the hostname and ip address address assigned to hostname found in /etc/hosts or in DNS. If the hostid trying to import a pool is not the same as the hostid that imported it last time, ZFS will not import the pool unless &amp;quot;zpool import -f zfs-root&amp;quot; is used to force the import. This force option is not recommended to use, so it is best to configure your initrd with matching /etc/HOSTNAME and /etc/hosts as on the root installation and ensure what your system looks like on the initrd matches the booted root system.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Edit /boot/initrd-tree/init (this is the main system startup script on the initrd, responsibe for configuring your block devices and mount your root at /mnt and then booting root):&lt;br /&gt;
&lt;br /&gt;
Inside init, right near the top of the file after the PATH= line, add this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/bin/hostname -F /etc/HOSTNAME&lt;br /&gt;
/bin/hostname $( /bin/hostname -s )&lt;br /&gt;
#/sbin/chhostid 13371400&lt;br /&gt;
# you can make your hostid whatever, but this didn't work right with ZFS, so it is commented out&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This sets the name reported by the hostname command (the default is &amp;quot;darkstar&amp;quot;) to be what is contained in /etc/HOSTNAME. The hostname is modified in the next line to be the short name. These lines will help ZFS to properly identify your host when importing pools.&lt;br /&gt;
&lt;br /&gt;
Inside init, right after it runs &amp;quot;mdadm&amp;quot; commands as used for raid setup, we like it to setup ZFS, so add:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/sbin/zpool import zfs-root&lt;br /&gt;
/sbin/zfs set readonly=on zfs-root&lt;br /&gt;
mount zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Inside init, close to the bottom, where it &amp;quot;Switch to real root partition&amp;quot;, comment out 1 line that normally does the mount:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# mount -o ro -t $ROOTFS $ROOTDEV /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
We have already mounted, and we don't want to use any mount options because we should be using a properly set /etc/fstab inside the initrd for zfs-root mount options onto /mnt.&lt;br /&gt;
&lt;br /&gt;
During a normal startup we want a readonly mount.&lt;br /&gt;
&lt;br /&gt;
Note: we are going to setup with using zpool import and export and startup and shutdown. But later, you can experiment having /etc/zfs/zpool.cache stored in the initrd and commenting out zpool import/export lines.&lt;br /&gt;
&lt;br /&gt;
As mentioned, the import command may sometimes fail, and give the message: &amp;quot;pool may be in use from another system&amp;quot;. This is nothing serious in this test situation. When this happens, root will not be mounted to /mnt and the init script will detect this and drop you into a rescue command line where you may manually &amp;quot;import -f&amp;quot; then &amp;quot;mount zfs-root&amp;quot; and then &amp;quot;exit&amp;quot; to continue on to booting the root.&lt;br /&gt;
&lt;br /&gt;
To avoid this problem we copy some files in (assuming you first edit /etc/HOSTNAME to hold the hostname you like to see on your command prompts, and edited /etc/hosts to have hostname on your loopback or other local ip address):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/HOSTNAME /etc/hosts /boot/initrd-tree/etc&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The value reported by the hostid command is what ZFS sees as your hostid. In this setup so far, the value is based on the ip found assigned to your hostname. If your hostname is on the line in /etc/hosts for ip address 192.168.13.37, then your hostid will be hex numbers C0.A8.0D.25 rearranged as A8C0250D (pairs of bytes are swapped). That is ip-based hostid value, a 32bit hexadecimal number. This has to be the same each boot or import will need a -f option to force it. Simply setting the hostid using the system call sethostid() which writes a /etc/hostid file doesn't seem to agree with ZFS and you'd have to force the import, so this setup now assumes that you do not have or have deleted /etc/hostid.&lt;br /&gt;
&lt;br /&gt;
You can sometimes see what has been happening to a zpool by using the command &amp;quot;zpool history -li zfs-root&amp;quot; to see a log of commands.&lt;br /&gt;
&lt;br /&gt;
Once again, you can do away with the import and export commands by trying to have /etc/zfs/zpool.cache inside your initrd. To create zpool.cache, while on the installer or in the rescue shell of the initrd (at lilo &amp;quot;boot: vmlinuz rescue&amp;quot;), import only the pool for the root fs with mountpoint=none and readonly=on properties set and while it is not mounted:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on installer or initrd rescue shell)&lt;br /&gt;
cp /etc/zfs/zpool.cache /etc/zfs/zpool.cache-initrd&lt;br /&gt;
zfs set readonly=off zfs-root&lt;br /&gt;
mount zfs-pool&lt;br /&gt;
cp /etc/zfs/zpool.cache-initrd /mnt/etc/zfs/&lt;br /&gt;
cp /mnt/etc/zfs/zpool.cache-initrd /mnt/boot/initrd-tree/etc/zfs/zpool.cache&lt;br /&gt;
umount /mnt&lt;br /&gt;
zfs set readonly=on zfs-root&lt;br /&gt;
#mount zfs-root&lt;br /&gt;
#exit (to continue boot process onto rootfs mounted at /mnt)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, doing this zpool.cache approach is not necessary, and some talk suggests this is deprecated or discouraged. Although /etc/hostid setup fails to import without -f option, ip-based (hosts|dns) hostid works on booting and import works without -f option and may be the more proper way to do shutdown and startup rather than using a cache file which could be come invalid and cause a problem that is difficult to understand. The contents and exact function of the cache file are not well understood by many people.&lt;br /&gt;
&lt;br /&gt;
Save /boot/initrd-tree/init and exit.&lt;br /&gt;
&lt;br /&gt;
Now, edit /etc/rc.d/rc.S and rc.6 to understand how to &amp;quot;remount&amp;quot; rw or ro as a readonly property changes&lt;br /&gt;
&lt;br /&gt;
In /etc/rc.d/rc.S:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# comment out the line&lt;br /&gt;
#    /sbin/mount -w -v -n -o remount /&lt;br /&gt;
#add the line&lt;br /&gt;
     /sbin/zfs set readonly=off zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In /etc/rc.d/rc.6&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# comment out the line&lt;br /&gt;
#    /bin/mount -v -n -o remount,ro /&lt;br /&gt;
#add the line&lt;br /&gt;
     /sbin/zfs set readonly=on zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In /etc/rc.d/rc.6, near the bottom just before poweroff|reboot, add the following block of lines:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
########################&lt;br /&gt;
# Try to export zfs-root&lt;br /&gt;
/sbin/zpool export zfs-root&lt;br /&gt;
if [ $? -gt 0 ] ; then&lt;br /&gt;
 echo &amp;quot;ZFS export failed.&amp;quot;&lt;br /&gt;
 echo &amp;quot;Notice: if root fs is busy, then this is normal fail.&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;ZFS export successful.&amp;quot;&lt;br /&gt;
 echo &amp;quot;Warning: successful export is abnormal for root fs.&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
/bin/sleep 5&lt;br /&gt;
########################&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
For ZFS, you cannot run fsck on it. It doesn't support that kind of filesystem checks. The rc.S script will complain a lot in many places about not being about to run fsck on the zfs-root. To disable all attempts of run fsck, we can simple create a file that acts as a flag in /etc/rc.d/rc.S to tell it to skip fsck:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
touch /etc/fastboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This fastboot file is normally a run-once temporary file, and it is deleted near the bottom inside rc.S. Edit rc.S and stop it from deleting /etc/fastboot. We would like it to always skip all fsck. Edit /etc/rc.d/rc.S, and find the &amp;quot;rm&amp;quot; of fastboot, and do not have it removed!&lt;br /&gt;
&lt;br /&gt;
We are getting close, and have finished all editing, so make /boot/initrd.gz and install lilo:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkinitrd -F&lt;br /&gt;
lilo&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We finished! All that's left to do is clean up.&lt;br /&gt;
&lt;br /&gt;
Exit the chroot.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
exit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Try to mount everything:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
umount /mnt/proc&lt;br /&gt;
umount /mnt/sys&lt;br /&gt;
umount /mnt/dev&lt;br /&gt;
umount /mnt/boot&lt;br /&gt;
umount /mnt/mnt/cdrom&lt;br /&gt;
umount /mnt/root/packages&lt;br /&gt;
umount /mnt&lt;br /&gt;
zpool export zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note, that export stops a pool and frees devices, while import binds devices and starts a pool. It is somewhat like mdadm -A -s and mdadm -S -s, while /etc/zfs/zpool.cache might be somewhat like mdadm -E -s &amp;gt; /etc/mdadm.conf.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Remove the DVD or change boot order&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When you reboot, if all is good, you are booting properly onto a slackware installed on a ZFS root! Congrat!&lt;br /&gt;
&lt;br /&gt;
If this seem to go badly, and this might happen if the import fails as explain some before, then you will be on the initrd's rescue command line just before the part in it's init where it wants to mount and switch_root to boot your root. Instead, you typically got commands like this to do:&lt;br /&gt;
&lt;br /&gt;
If you get dumped to rescue because import will not work and requires -f (force), then:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 zpool import -f zfs-root&lt;br /&gt;
 zpool export    zfs-root&lt;br /&gt;
 zpool import    zfs-root&lt;br /&gt;
 mount zfs-root&lt;br /&gt;
 exit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This can happen if hostname, hostid, or uname changes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you get into a jam and need to boot into the initrd and skip zfs import etc, use the lilo prompt (or, boot the install-dvd):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
boot: vmlinuz rescue&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the rescue mode of the initrd, after you have mounted your root as readonly=on to /mnt, then exit to continue.&lt;br /&gt;
&lt;br /&gt;
In other emergency modes, you might need to run the lines at end of init starting from: &amp;lt;code&amp;gt;udevadm info --cleanup-db; udevadm control --exit&amp;lt;/code&amp;gt;&lt;br /&gt;
If you don't run those udevadm commands, two runs of udevd fight each other and it is slow; you have to wait 2 minutes twice for timeouts (4 minutes).&lt;br /&gt;
The last line is run is: &amp;lt;code&amp;gt;exec switch_root /mnt /sbin/init 1&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Warning... this switch_root command is kind of dangerous, so read the manual page about it.&lt;br /&gt;
From what I can tell, everything except the new root &amp;quot;/mnt&amp;quot; is deleted, so you are giving a command that says what NOT to delete!&lt;br /&gt;
Make sure nothing got mounted outside of &amp;quot;/mnt&amp;quot; before you run it.&lt;br /&gt;
&lt;br /&gt;
Also, in rescue or anytime you have finished making changes and are about to reboot in some abnormal mode, first run:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set readonly=on zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A bug in unpatched grep 2.13 build 1, found slackware 14.0rc1, causes problems when processing files stored on ZFS but rarely shows problems on other filesystems; the bug does not handle sparse files on zfs and btrfs correctly and results in chaos with slackpkg, compiling kernel modules, and possibly many other things. You must downgrade grep to 2.12 or use the patched grep 2.13 build 2 in slackware 14.0rc2 or later.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Upgrading.&lt;br /&gt;
&lt;br /&gt;
From time to time you will want to upgrade the kernel to the new kernel in slackware64-current or in patches/. This will also necessitate a rebuilt and reinstall or upgrade of spl and zfs. Below is an example of when both kernel and spl/zfs are being upgraded, to give an idea of the process:&lt;br /&gt;
&lt;br /&gt;
Using slackpkg, that is configured to use your local slackware mirror is a good option but you can also configure it to use a remote mirror.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slackpkg upgrade-all&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Assume slackpkg just upgraded your kernel, kernel-modules, and kernel-headers.&lt;br /&gt;
&lt;br /&gt;
Note: the first time you try to run on kernel-generic, setup kernel-huge in lilo as 2nd choice. Huge has all the hard drive controllers builtin, but generic has them all as modules. For example, run &amp;quot;modinfo mptsas&amp;quot; to see module options (maybe you have a LSISAS1068) for your hard drive controller. Add file /etc/modprobe.d/mptsas.conf to set options you want with a line: options mptsas ... Do this for all the device driver modules for your hardware. Do this setup while you are on the huge kernel, then setup to reboot to generic. Include all these modules you need into mkinitrd.conf MODULES_LIST. Check that /boot/initrd-tree/etc/modprobe.d/ has a copy of your customized module conf files because it is on the initrd where the modules will load and use the conf files. mkinitrd probably copies all /etc/modprobe.d/* files into the initrd-tree, but check it. Pay attention to /etc/modprobe.d/README and /lib/modprobe.d/* /lib/modprobe.d/* maybe not copied to initrd-tree but you might want to copy some of it into your initrd-tree yourself to use them.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Check that upgraded kernel-source is symlinked to /usr/src/linux (zfs build looks here). SQL/ZFS modules will install to the kernel version in /lib/modules/&amp;lt;/usr/src/linux kernel version&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /usr/local/src&lt;br /&gt;
tar xvzf ~/spl-*.tar.gz&lt;br /&gt;
tar xvzf ~/zfs-*.tar.gz&lt;br /&gt;
&lt;br /&gt;
###### upgrade spl 1st&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-*&lt;br /&gt;
./configure --prefix=/ --libexecdir=/usr/libexec --libdir=/lib64 --includedir=/usr/include --datarootdir=/usr/share&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=/usr/local/src/install&lt;br /&gt;
cd ../install&lt;br /&gt;
makepkg ../spl-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
upgradepkg spl-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
depmod &amp;lt;new kernel version&amp;gt;     (e.g. depmod 3.2.27, if .27 is new kernel upgrade; you currently run on old, maybe .26)&lt;br /&gt;
# this builds the module dependencies in /lib/modules/&amp;lt;new kernel version&amp;gt;&lt;br /&gt;
###### upgrade zfs 2nd&lt;br /&gt;
mkdir install&lt;br /&gt;
cd zfs-*&lt;br /&gt;
./configure --prefix=/ --libexecdir=/usr/libexec --libdir=/lib64 --includedir=/usr/include --datarootdir=/usr/share&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=/usr/local/src/install&lt;br /&gt;
cd ../install&lt;br /&gt;
makepkg ../zfs-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
upgradepkg zfs-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
depmod 3.2.27&lt;br /&gt;
####### upgrade spl/zfs inside altroot /boot/initrd-tree&lt;br /&gt;
ROOT=/boot/initrd-tree upgradepkg spl-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
ROOT=/boot/initrd-tree upgradepkg zfs-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
# note: ROOT is an environment variable, not a command line option to upgradepkg!&lt;br /&gt;
# note: do not worry about depmod inside initrd-tree, mkinitrd -F actually installs the modules&lt;br /&gt;
# note: this upgrade here is really to just upgrade the command line tools zpool, zfs etc&lt;br /&gt;
####### rebuild /boot/initrd.gz and reinstall lilo&lt;br /&gt;
vi /etc/mkinitrd.conf&lt;br /&gt;
# temporarily set KERNEL_VERSION to new version, but you are still running on old version&lt;br /&gt;
mkinitrd -F&lt;br /&gt;
lilo&lt;br /&gt;
vi /etc/mkinitrd.conf&lt;br /&gt;
# you can set KERNEL_VERSION back to $(uname r) now&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After reboot you can remove any old /lib/modules/&amp;lt;old kernel version&amp;gt; directory.&lt;br /&gt;
&lt;br /&gt;
More about /etc/hostid. If you want to experiment changing your /etc/hostid file and seeing if you can use it and make zpool import work normally, here is a tool that might be helpful:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/* software product name: foobarz-chhostid.c&lt;br /&gt;
 * suggested binary name: chhostid&lt;br /&gt;
 * license              : BSD&lt;br /&gt;
 * license text:&lt;br /&gt;
Copyright (c) 2012, foobarz&lt;br /&gt;
All rights reserved.&lt;br /&gt;
&lt;br /&gt;
Redistribution and use in source and binary forms, with or without&lt;br /&gt;
modification, are permitted provided that the following conditions are met:&lt;br /&gt;
    * Redistributions of source code must retain the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer.&lt;br /&gt;
    * Redistributions in binary form must reproduce the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer in the&lt;br /&gt;
      documentation and/or other materials provided with the distribution.&lt;br /&gt;
    * Neither the name of the &amp;lt;organization&amp;gt; nor the&lt;br /&gt;
      names of its contributors may be used to endorse or promote products&lt;br /&gt;
      derived from this software without specific prior written permission.&lt;br /&gt;
&lt;br /&gt;
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &amp;quot;AS IS&amp;quot; AND&lt;br /&gt;
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED&lt;br /&gt;
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE&lt;br /&gt;
DISCLAIMED. IN NO EVENT SHALL &amp;lt;COPYRIGHT HOLDER&amp;gt; BE LIABLE FOR ANY&lt;br /&gt;
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES&lt;br /&gt;
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;&lt;br /&gt;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND&lt;br /&gt;
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT&lt;br /&gt;
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS&lt;br /&gt;
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#define FOOBARZ_CHHOSTID_VERSION &amp;quot;1.0.5&amp;quot;&lt;br /&gt;
#include &amp;lt;sys/socket.h&amp;gt;&lt;br /&gt;
#include &amp;lt;netinet/in.h&amp;gt;&lt;br /&gt;
#include &amp;lt;arpa/inet.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;endian.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sysexits.h&amp;gt;&lt;br /&gt;
/* note: if include stdlib then sethostid fails even with _BSD_SOURCE defined */&lt;br /&gt;
&lt;br /&gt;
long swapbytes(long abcd) {&lt;br /&gt;
  long badc;&lt;br /&gt;
  unsigned char addr_a;&lt;br /&gt;
  unsigned char addr_b;&lt;br /&gt;
  unsigned char addr_c;&lt;br /&gt;
  unsigned char addr_d;&lt;br /&gt;
  addr_a = (unsigned char) (abcd &amp;gt;&amp;gt; 24);&lt;br /&gt;
  addr_b = (unsigned char) (abcd &amp;gt;&amp;gt; 16);&lt;br /&gt;
  addr_c = (unsigned char) (abcd &amp;gt;&amp;gt;  8);&lt;br /&gt;
  addr_d = (unsigned char) (abcd);&lt;br /&gt;
  return badc = ( (addr_b &amp;lt;&amp;lt; 24) | (addr_a &amp;lt;&amp;lt; 16) | (addr_d &amp;lt;&amp;lt; 8) | addr_c );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[])&lt;br /&gt;
{&lt;br /&gt;
 long newhostid;&lt;br /&gt;
 struct in_addr addr;&lt;br /&gt;
 char* invalidchar;&lt;br /&gt;
&lt;br /&gt;
 /*********** check command line */&lt;br /&gt;
 if(!( ((argc==3) &amp;amp;&amp;amp; ( (strcmp(argv[1],&amp;quot;-h&amp;quot;)==0) ||&lt;br /&gt;
                       (strcmp(argv[1],&amp;quot;-i&amp;quot;)==0) ||&lt;br /&gt;
                       (strcmp(argv[1],&amp;quot;-l&amp;quot;)==0) )) ||&lt;br /&gt;
       ((argc==2) &amp;amp;&amp;amp; ( (strcmp(argv[1],&amp;quot;-s&amp;quot;)==0) ))&lt;br /&gt;
     )&lt;br /&gt;
   ) {&lt;br /&gt;
                 /*01234567890123456789012345678901234567890123456789012345678901234567890123456789*/&lt;br /&gt;
  fprintf(stderr, &amp;quot;foobarz-chhostid, version %s. License: BSD.\n&amp;quot;, FOOBARZ_CHHOSTID_VERSION);&lt;br /&gt;
  fprintf(stderr, &amp;quot;foobarz-chhostid, (c) 2012, foobarz; all rights reserved.\n&amp;quot;);&lt;br /&gt;
  fprintf(stderr, &amp;quot;descr: %s change system hostid (in /etc/hostid).\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -h &amp;lt;new hostid&amp;gt;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        Change system hostid to &amp;lt;new hostid&amp;gt;;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        &amp;lt;new hostid&amp;gt; must be 32bit 8-digit hex number xxxxxxxx, each x in 0-f|F.\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        The ip corresponding to &amp;lt;new hostid&amp;gt; is also listed for reference only.\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -i &amp;lt;dotted ip address&amp;gt;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        Change system hostid to hostid corresponding to &amp;lt;dotted ip address&amp;gt;.\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -l &amp;lt;dotted ip address&amp;gt;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        List hostid corresponding to &amp;lt;dotted ip address&amp;gt;;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        no change to system hostid.\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -s\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        List current system hostid and corresponding ip address;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        no change to system hostid.\n&amp;quot;, argv[0]);&lt;br /&gt;
  return EX_USAGE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -h &amp;lt;hostid&amp;gt; */&lt;br /&gt;
 if( strcmp(argv[1],&amp;quot;-h&amp;quot;) == 0 ) {&lt;br /&gt;
  if(strlen(argv[2]) != 8) { fprintf(stderr, &amp;quot;new hostid must be 8-digit hex number xxxxxxxx, each x in 0-f|F\n&amp;quot;); return EX_USAGE; }&lt;br /&gt;
&lt;br /&gt;
  newhostid = strtol(argv[2],&amp;amp;invalidchar,16);&lt;br /&gt;
  if( newhostid==LONG_MIN ) { perror(&amp;quot;strtol (underflow)&amp;quot;); return EX_USAGE; }&lt;br /&gt;
  if( newhostid==LONG_MAX ) { perror(&amp;quot;strtol (overflow)&amp;quot;); return EX_USAGE; }&lt;br /&gt;
  if(*invalidchar != '\0') { fprintf(stderr, &amp;quot;invalid hex number %c; must be in 0-f|F\n&amp;quot;, *invalidchar); return EX_USAGE; }&lt;br /&gt;
&lt;br /&gt;
  if( sethostid(newhostid) != 0 ) {&lt;br /&gt;
   perror(&amp;quot;sethostid&amp;quot;);&lt;br /&gt;
   if( errno == EPERM ) return EX_NOPERM;&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
  }&lt;br /&gt;
  printf(&amp;quot;System hostid changed.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  /* hostid is a byte-swapped ip like b.a.d.c */&lt;br /&gt;
  /* get ip by swapping to correct order a.b.c.d and save into in_addr struct */&lt;br /&gt;
  addr.s_addr = htonl(swapbytes(newhostid));&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -i or -l, then find hostid for &amp;lt;dotted ip address&amp;gt; */&lt;br /&gt;
 if( (strcmp(argv[1],&amp;quot;-i&amp;quot;) == 0) || (strcmp(argv[1],&amp;quot;-l&amp;quot;) == 0) ) {&lt;br /&gt;
  if( inet_aton(argv[2], &amp;amp;addr) == 0 ) { fprintf(stderr, &amp;quot;inet_aton: invalid dotted ip address: %s\n&amp;quot;, argv[2]); return EX_USAGE; }&lt;br /&gt;
&lt;br /&gt;
  /* hostid is a byte-swapped ip like b.a.d.c */&lt;br /&gt;
  /* get hostid by swapping bytes of ip a.b.c.d */&lt;br /&gt;
  newhostid = swapbytes(ntohl(addr.s_addr));&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -i &amp;lt;dotted ip address&amp;gt; */&lt;br /&gt;
 if( strcmp(argv[1],&amp;quot;-i&amp;quot;) == 0 ) {&lt;br /&gt;
  if( sethostid(newhostid) != 0 ) {&lt;br /&gt;
   perror(&amp;quot;sethostid&amp;quot;);&lt;br /&gt;
   if( errno == EPERM ) return EX_NOPERM;&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
  }&lt;br /&gt;
  printf(&amp;quot;System hostid changed.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -l &amp;lt;dotted ip address&amp;gt; */&lt;br /&gt;
 if(strcmp(argv[1],&amp;quot;-l&amp;quot;) == 0 ) {&lt;br /&gt;
   printf(&amp;quot;Listing hostid for ip. (no changes)\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -s */&lt;br /&gt;
 if(strcmp(argv[1],&amp;quot;-s&amp;quot;) == 0 ) {&lt;br /&gt;
   /* see if /etc/hostid exists and print info */&lt;br /&gt;
   if( access(&amp;quot;/etc/hostid&amp;quot;, F_OK) != 0 ) {&lt;br /&gt;
     printf(&amp;quot;Notice: /etc/hostid does not exist.\n&amp;quot;);&lt;br /&gt;
     perror(&amp;quot;Reason&amp;quot;);&lt;br /&gt;
     printf(&amp;quot;System hostid derived from ip of hostname found in hosts file or dns.\n&amp;quot;);&lt;br /&gt;
   } else {&lt;br /&gt;
     printf(&amp;quot;Notice: /etc/hostid exists.\n&amp;quot;&lt;br /&gt;
            &amp;quot;System hostid is obtained from hostid file.\n&amp;quot;);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
  errno=0;&lt;br /&gt;
  newhostid = gethostid();&lt;br /&gt;
  if(errno!=0) { perror(&amp;quot;gethostid&amp;quot;); return EX_UNAVAILABLE; }&lt;br /&gt;
&lt;br /&gt;
  /* hostid is a byte-swapped ip like b.a.d.c */&lt;br /&gt;
  /* get ip by swapping to correct order a.b.c.d and save into in_addr struct */&lt;br /&gt;
  addr.s_addr = htonl(swapbytes(newhostid));&lt;br /&gt;
&lt;br /&gt;
  printf(&amp;quot;Listing current system hostid. (no changes)\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** print info and return */&lt;br /&gt;
 printf(&amp;quot;ip dot: %s\n&amp;quot;, inet_ntoa(addr) );&lt;br /&gt;
 printf(&amp;quot;ip hex: %.8x\n&amp;quot;, ntohl(addr.s_addr) );&lt;br /&gt;
 printf(&amp;quot;hostid: %.8x\n&amp;quot;, newhostid );&lt;br /&gt;
 return EX_OK;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</description>
			<pubDate>Mon, 20 Aug 2012 02:22:17 GMT</pubDate>
			<dc:creator>Foobarz</dc:creator>
			<comments>https://www.slackwiki.com/Talk:ZFS_root</comments>
		</item>
		<item>
			<title>ZFS root</title>
			<link>https://www.slackwiki.com/index.php?title=ZFS_root&amp;diff=738</link>
			<guid isPermaLink="false">https://www.slackwiki.com/index.php?title=ZFS_root&amp;diff=738</guid>
			<description>&lt;p&gt;Foobarz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Tutorials]]&lt;br /&gt;
If you have heard about the ZFS filesystem and you're curious to try it out, then you can try it on slackware64, thanks to the ZFSonLinux.org project!&lt;br /&gt;
&lt;br /&gt;
In this article, an example is shown of how to install slackware64 14.0 onto a ZFS root filesystem (zfs-root) inside a QEMU virtual machine for testing purposes. It is recommended that you install qemu and learn how to use it to test a ZFS installation before you decide to use it on real hardware. A slackbuild for qemu can be found on slackbuilds.org. If you have a processor that supports Intel VT-x or AMD AMD-V virtualization acceleration (try modprobe kvm-intel or modprobe kvm-amd), then use the slackbuild for qemu-kvm.&lt;br /&gt;
&lt;br /&gt;
This article isn't going to go into any detail on actually using ZFS or what kinds of installation options and settings might be optimal. This article just presents an example of how to get started with ZFS on slackware.&lt;br /&gt;
&lt;br /&gt;
At this time of writing, ZFSonLinux is at &amp;quot;release candidate&amp;quot; (version 0.6.0-rc10) development stage, and many issues can occur. See the ZFSonLinux.org web site and the issues tracker for an idea about the current issues. There is also an irc channel on irc.freenode.net, #zfsonlinux, for discussion of issues and help.&lt;br /&gt;
&lt;br /&gt;
Although not required, it is helpful to keep a local mirror of slackware64 on your system. Having a local mirror makes it easier to upgrade to slackware64-current or to patches/* in a release. To help manage your own local slackware mirror and generate your own CD and DVD slackware installers, see http://alien.slackbook.org/blog/local-slackware-mirror/.&lt;br /&gt;
&lt;br /&gt;
In this article, we use a slackware64-current DVD image file as the qemu cdrom device media for the installation of the slackware guest. This was tested at slackware64-current = slackware64 14.0rc2. You can obtain a slackware DVD image using a torrent, buy the DVD from slackware.com, or generate your own DVD image file using the mirror script. For an actual DVD, you can pass your DVD device (e.g., /dev/sr0) as the qemu cdrom device. For a DVD image file, pass the image file as the qemu cdrom device.&lt;br /&gt;
&lt;br /&gt;
The ZFSonLinux packages are not included in slackware at this time. There are two packages involved: spl and zfs. The first, spl, is &amp;quot;Solaris Porting Layer&amp;quot; and must be installed on the system before zfs can be compiled. The source code tarballs for these are at ZFSonLinux.org. At this time of writing, they are spl-0.6.0-rc10.tar.gz and zfs-0.6.0-rc10.tar.gz.&lt;br /&gt;
&lt;br /&gt;
At this point, it is assumed you have qemu installed, have obtained a slackware64-current/14.0 DVD, and have downloaded spl and zfs tarballs to your host system. The first step now is, if your host is not slackware64-current/14.0 (the same as the guest will be), then you need to create a minimal development slackware64 guest system in qemu for just the purpose of compiling and packaging the spl and zfs slackware packages and transferring a copy of these packages back onto your host system to use later to install onto zfs during the slackware install process.&lt;br /&gt;
&lt;br /&gt;
From this point onward, instructions become a bit terse and mostly limited to examples of the commands you might use to complete tasks. You are encouraged to examine what each command does by reading the command's man pages. For example, the command &amp;quot;man qemu&amp;quot; can show you most of what you need to know about running qemu on the command line.&lt;br /&gt;
&lt;br /&gt;
So, here's an example of how you might build the spl and zfs packages, starting in your home directory:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on host)&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir qemu&lt;br /&gt;
cd qemu&lt;br /&gt;
mkdir slackdevel&lt;br /&gt;
cd slackdevel&lt;br /&gt;
mkdir packages&lt;br /&gt;
cp ~/spl-*.tar.gz packages&lt;br /&gt;
cp ~/zfs-*.tar.gz packages&lt;br /&gt;
qemu-img create disk1.raw 10G&lt;br /&gt;
ln -s ~/slackware64-current-install-dvd.iso dvd.iso&lt;br /&gt;
qemu-system-x86_64 \&lt;br /&gt;
 -no-quit \&lt;br /&gt;
 -no-shutdown \&lt;br /&gt;
 -boot order=cd,menu=on \&lt;br /&gt;
 -m 2G \&lt;br /&gt;
 -cpu host \&lt;br /&gt;
 -smp sockets=1,cores=4 \&lt;br /&gt;
 -net nic,model=rtl8139 -net user \&lt;br /&gt;
 -cdrom dvd.iso \&lt;br /&gt;
 -drive boot=on,format=raw,media=disk,cache=none,aio=native,if=scsi,bus=0,unit=0,file=disk1.raw \&lt;br /&gt;
 -virtfs local,path=./packages/,security_model=none,mount_tag=hostpackages&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When you need to change boot to cd or disk, add or remove &amp;quot;boot=on&amp;quot;, or change &amp;quot;order=dc&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Qemu should boot into the install-dvd, and now perform a very ordinary slackware64 install onto /dev/sda. Install d package set and most others, but package sets x, kde, xfce not really needed.&lt;br /&gt;
&lt;br /&gt;
First note: examples here use tools from the gptfdisk package (gdisk, sgdisk, cgdisk) to partition the disk with GUID partition table (GPT) format. GPT might not be too familiar to everyone, who mostly have only used MBR partitions with fdisk. In the slackware installations this author has tested in qemu, using GPT partitions has caused no problems with lilo or other tools used in slackware. GPT disk labels support creating up to 128 partitions and support disks larger than 2TB (the limit of MBR fdisk). LILO installs into the first 440 bytes on /dev/sda, inside a GPT &amp;quot;protective MBR&amp;quot; that serves to provide compatibility with MBR bootloaders like lilo. LILO uses LBA32 sector addressing and can see all 512-byte sectors side the first 2TB of a disk. So long as the /boot partition is within the first 2TB of a disk, lilo can work on a disk larger than 2TB. Unlike the common default of fdisk to start the first partition at sector 63, which is not aligned with the 4KiB sector size of Advanced Format hard disks, gdisk's default is to start partitions at 2048 sector (1MiB) boundaries which are also 4KiB aligned. Using gdisk GPT works on all disks and is compatible with using Advanced Format hard disks larger than 2TB. More information about GPT disk label format can be found on wikipedia.org. For those that have used grub instead of lilo, grub installation is different with GPT than with MBR, and grub requires a GPT partition of type grub-bios or 0xEF02 &amp;quot;BIOS Boot Partition&amp;quot; of about 8MiB where it can install it's additional bootloader stages because grub cannot embed in sectors 1-62 on GPT where GPT keeps it's partition tables. On MBR, sectors 1-62 were normally reserved space for bootloaders to keep a 2nd stage.&lt;br /&gt;
&lt;br /&gt;
For this purpose of development guest, just create a simple 1-partition system, /dev/sda1, and do a simple slackware install on it. Don't bother with swap or separate /boot unless you want to:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on install-dvd)&lt;br /&gt;
cgdisk /dev/sda&lt;br /&gt;
setup&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When this simple development guest boots, login as root, and continue:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on qemu guest)&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir packages&lt;br /&gt;
mount hostpackages -t 9p -o trans=virtio packages&lt;br /&gt;
echo --prefix=/ --libexecdir=/usr/libexec --libdir=/lib64 --includedir=/usr/include --datarootdir=/usr/share &amp;gt; configure-options&lt;br /&gt;
mkdir src&lt;br /&gt;
cd src&lt;br /&gt;
&lt;br /&gt;
mkdir install&lt;br /&gt;
tar xvzf ~/packages/spl-*.tar.gz&lt;br /&gt;
cd spl-*&lt;br /&gt;
./configure $( cat ~/configure-options )&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../spl-&amp;lt;version&amp;gt;_&amp;lt;kernel_version&amp;gt;-x86_64-&amp;lt;build_id&amp;gt;.txz&lt;br /&gt;
(e.g., makepkg ../spl-0.6.0rc10_3.2.27-x86_64-1root.txz)&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
installpkg spl-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
cp spl-0.6.0rc10_3.2.27-x86_64-1root.txz ~/packages&lt;br /&gt;
&lt;br /&gt;
mkdir install&lt;br /&gt;
tar xvzf ~/packages/zfs-*.tar.gz&lt;br /&gt;
cd zfs-*&lt;br /&gt;
./configure $( cat ~/configure-options )&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../zfs-&amp;lt;version&amp;gt;_&amp;lt;kernel_version&amp;gt;-x86_64-&amp;lt;build_id&amp;gt;.txz&lt;br /&gt;
(e.g., makepkg ../zfs-0.6.0rc10_3.2.27-x86_64-1root.txz)&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
installpkg zfs-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
cp zfs-0.6.0rc10_3.2.27-x86_64-1root.txz ~/packages&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point spl and zfs packages are copied back to the host in the packages directory. Also, spl and zfs are installed in this simple development guest, so one could begin to experiment with zfs pools and datasets but while the root fs is whatever you made it during setup (probably the default, ext4). This development guest isn't really needed anymore, so it can be deleted:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
halt&lt;br /&gt;
(exit qemu: ctrl-alt-2 then enter quit at QEMU command prompt)&lt;br /&gt;
&lt;br /&gt;
(on host)&lt;br /&gt;
rm disk1.raw dvd.iso&lt;br /&gt;
mv packages ..&lt;br /&gt;
cd ..&lt;br /&gt;
rmdir slackdevel&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now that we have the spl and zfs packages on the host, it is possible to copy them into your local slackware64 mirror and then generate your own install DVD image that includes them. For example, change to the directory that contains the slackware README files, and create a &amp;quot;addon&amp;quot; directory and copy the spl and zfs slackware packages into there. Then, generate the DVD image using a command such as $( ./mirror-slackware-current.sh -i ) from where you have this script configured to maintain your local mirror. We can also just continue to access them inside the installer using qemu's virtfs option. When you are going to do a real installation onto real hardware, you need to generate and burn your own DVD that includes the packages.&lt;br /&gt;
&lt;br /&gt;
It is time to begin the installation of slackware64 on a ZFS root, assuming either you have regenerated dvd.iso with zfs packages in addon/* or we access the zfs packages while in the installer using qemu's virtfs to the host's packages directory. ZFS supports creating complex data storage configurations such as pools (similar to a volume group) backed by one or more of various kinds of virtual devices (similar to disks and raid arrays) and containing one or more datasets (similar to mounted filesystems, logical volume devices, or snapshots). But here, we keep it simple and will install on just a single disk device. On a real ZFS installation, users will typically want to use the ZFS raidz1 or raidz2 virtual device types for reliability against hard drive failures.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on host)&lt;br /&gt;
mkdir slackzfs&lt;br /&gt;
mv packages slackzfs/&lt;br /&gt;
cd slackzfs&lt;br /&gt;
qemu-img create disk1.raw 10G&lt;br /&gt;
ln -s ~/slackware64-current-install-dvd.iso dvd.iso&lt;br /&gt;
qemu-system-x86_64 \&lt;br /&gt;
 -no-quit \&lt;br /&gt;
 -no-shutdown \&lt;br /&gt;
 -boot order=cd,menu=on \&lt;br /&gt;
 -m 2G \&lt;br /&gt;
 -cpu host \&lt;br /&gt;
 -smp sockets=1,cores=4 \&lt;br /&gt;
 -net nic,model=rtl8139 -net user \&lt;br /&gt;
 -cdrom dvd.iso \&lt;br /&gt;
 -drive boot=on,format=raw,media=disk,cache=none,aio=native,if=scsi,bus=0,unit=0,file=disk1.raw \&lt;br /&gt;
 -virtfs local,path=./packages/,security_model=none,mount_tag=hostpackages&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The install-dvd should boot, and then begin installation steps on the installer command line:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on install-dvd)&lt;br /&gt;
# mount the install-dvd&lt;br /&gt;
mkdir /dvd&lt;br /&gt;
mount /dev/sr0 /dvd&lt;br /&gt;
&lt;br /&gt;
# install coreutils, which provides the &amp;quot;hostid&amp;quot; command needed to load the spl module&lt;br /&gt;
installpkg /dvd/slackware64/a/coreutils-8.17-x86_64-1.txz&lt;br /&gt;
&lt;br /&gt;
# install kmod package which includes &amp;quot;depmod&amp;quot; command and others&lt;br /&gt;
installpkg /dvd/slackware64/a/kmod-9-x86_64-2.txz&lt;br /&gt;
depmod&lt;br /&gt;
&lt;br /&gt;
# install the full kernel modules so you can load 9p filesystem and use it if you want&lt;br /&gt;
# .. you might keep the zfs modules packages off the dvd and use a plain slack dvd&lt;br /&gt;
installpkg /dvd/slackware64/a/kernel-modules-*.txz&lt;br /&gt;
depmod&lt;br /&gt;
&lt;br /&gt;
# install bash and libtermcap because udev rules in zfs use bash scripts&lt;br /&gt;
installpkg /dvd/slackware64/a/bash-*.txz&lt;br /&gt;
installpkg /dvd/slackware64/l/libtermcap-*.txz&lt;br /&gt;
&lt;br /&gt;
# install spl and zfs that you have copied into the mirror before running the DVD creation&lt;br /&gt;
installpkg /dvd/addon/spl-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /dvd/addon/zfs-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
&lt;br /&gt;
#Or:&lt;br /&gt;
mkdir /packages&lt;br /&gt;
find /lib/modules/ | grep 9p&lt;br /&gt;
lsmod&lt;br /&gt;
# check that 9p modules load, mainly 9pnet_virtio&lt;br /&gt;
modprobe 9pnet_virtio&lt;br /&gt;
mount hostpackages -t 9p -o trans=virtio /packages&lt;br /&gt;
installpkg /packages/spl-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /packages/zfs-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
modprobe zfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now zfs tools: &amp;quot;zpool&amp;quot; and &amp;quot;zfs&amp;quot; should work in the live installer.&lt;br /&gt;
On the installer, there can be trouble seeing man pages, so install:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
installpkg /dvd/slackware64/ap/man-*.txz&lt;br /&gt;
installpkg /dvd/slackware64/ap/groff-*.txz&lt;br /&gt;
installpkg /dvd/slackware64/a/less-*.txz&lt;br /&gt;
export MANPATH=/usr/man:/usr/share/man&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The manual pages should be readable:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
man zpool&lt;br /&gt;
man zfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After seeing the man pages, we should be fully ready to continue to setup on ZFS.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(still on install-dvd)&lt;br /&gt;
ls -l /dev/sd*&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Make sure the disk devices you expect are there. We'll use sda and make boot (/boot on /dev/sda1) and root (/ on /dev/sda2) partitions.&lt;br /&gt;
&lt;br /&gt;
First, some background info: A ZFS filesystem is not supported by lilo as the filesystem containing /boot, which holds lilo's 2nd stage and the linux kernel files. The on-disk format of a ZFS filesystem is often a complex raid configuration where even if lilo understood ZFS it would likely require /boot to reside in only certain simple ZFS configurations to be plainly readable to lilo. As things are, a linux root installed in a partition with ZFS filesystem needs /boot to be on another partition with a filesystem that lilo understands, such as ext4 fs. In addition, because the spl and zfs modules are not built into the kernel, and the zfs startup requires some configuration to mount the zfs root, an initial ram/root filesystem (initrd) is needed. The initrd is a gzip compressed cpio archive file that contains a small linux root operating system that is decompressed into a ramfs block device at boot up and takes initial control of the system. The initrd contains an init script that configures devices in devtmpfs mounted at /dev. For example, if using mdadm, lvm, luks, losetup, and now zfs, this init script runs all the commands to create or start these devices (one of which is the root device), mounts the root device, and then transfers system control to the init script in the mounted root filesystem. The ramfs-based root environment on the booted install-dvd or booted initrd image (in rescue command line) are small slackware installations that exist only in ram and are temporary, but while inside them you can install, upgrade, and remove slackware packages inside them using the regular package management tools; this allows you access to any kernel modules and programs as needed inside these ramfs root. Packages can be installed, upgraded, or removed permanantly in the initrd image file to manage the programs and modules required during the initrd boot stage. Also from within these ramfs initial root environments, once the root device is mounted, chroot can be used to work on the mounted root system as if it were booted; this allows one to fix problems that are occuring in the root fs init scripts that cause normal booting to fail, or to install a kernel and/or modules etc. Now on to partitioning:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cgdisk /dev/sda&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, cgdisk looks just like cfdisk, but it makes GPT partitions.&lt;br /&gt;
&lt;br /&gt;
Make a partition for /boot that is about 512MiB of whatever partition type you like (8300 &amp;quot;Linux filesystem&amp;quot; is fine), or make it type bf07 &amp;quot;Solaris Reserved 1&amp;quot; if you want ZFS to maybe see the disk as if it was given as a whole disk to ZFS. Make a second partition using the remaining space with partition type bf01 &amp;quot;Solaris ZFS&amp;quot;. Currently, when ZFSonLinux is given a whole disk device like /dev/sdb to use, it will automatically GPT partition it with a bf01 partition #1 that is the whole disk except a small 8MiB type bf07 partition #9 at the end of the disk (/dev/sdb1 and /dev/sb9). The small 8MiB type bf07 partition #9 is mostly likely reserved for use by bootloaders, like lilo, to have a /boot or other boot-related files kept there. For example, you might have /dev/sda that is totally non-ZFS for booting and /dev/sdb passed to ZFS whole where it automatically partitions sdb, but you can just use one disk here and make partitions. Lets use type 8300 for /boot to be sure nothing is confused:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
We'll continue with this partitioning (numbers are in MiB):&lt;br /&gt;
  0 to   4: unused&lt;br /&gt;
  4 to 516: /dev/sda1 512MiB, type 8300&lt;br /&gt;
516 to 520: unused&lt;br /&gt;
520 to -96: /dev/sda2, type bf01&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The -96 means to count from the end of the disk so that 96MiB will remain unused at the end of the disk.&lt;br /&gt;
&lt;br /&gt;
Create a zpool called zfs-root:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool create -m none zfs-root /dev/sda2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A zpool created like this, the normal way, is a kernel-internal block device that contains already a zfs filesystem. There is normally no entry in /dev for this device. However, it can still be referenced as a mountable device similar to how devtmpfs, proc, and sysfs are also kernel-internal mountable block devices. The -m option told zpool not to automatically mount it anywhere, and without -m the default is to always automatically mount to /zfs-root. These kinds of details are explained better elsewhere. For this situation, we do not want it automounted.&lt;br /&gt;
&lt;br /&gt;
Because a zpool itself is a useable zfs fs, it has a full set of zfs &amp;quot;properties&amp;quot; to set options about the filesystem, perhaps similar to tune2fs. The &amp;quot;mountpoint=&amp;lt;some place to mount&amp;gt;&amp;quot; is one such property. We want it set to the special value &amp;quot;none&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs get mountpoint zfs-root&lt;br /&gt;
zfs set mountpoint=none zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On creation, the zpool zfs-pool is &amp;quot;imported&amp;quot; and has a zpool status that can be viewed:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool status zfs-root&lt;br /&gt;
&lt;br /&gt;
zpool export zfs-root&lt;br /&gt;
zpool status zfs-root&lt;br /&gt;
# Now there is no status.&lt;br /&gt;
&lt;br /&gt;
zpool import zfs-root&lt;br /&gt;
# Now it is back.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When a zpool is imported, it has it's current configuration cached in a file /etc/zfs/zpool.cache. When a zpool is exported, then it's entries in the cache file are removed and the cache file is deleted if it becomes empty. So long as the zfs kernel modules see this cache file and valid cache data inside it, ZFS considers the described zpools in the cache file to be valid as imported zpools. If the zpool.cache file is present at the time the zfs modules are loaded, then there is no further need to use the import and export commands at system startup and shutdown. With root on a zfs, it is not possible to export the pool that root is on, but this is not a problem. At shutdown, the safe procedure will be to set the zfs-root property readonly=on and sync disks.&lt;br /&gt;
&lt;br /&gt;
To avoid the requirement to import the zfs-root pool at startup, keep a copy of the zpool.cache file to later copy onto the initrd image to read at modules load time to have the pool reactived without need to issue the import command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/zfs/zpool.cache /etc/zfs/zpool.cache-initrd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A zfs fs will not normally allow you to mount over any files. The mountpoint is expected to be an empty directory. Remove any junk files inside the installer's /mnt because zfs won't mount over any files:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rm /mnt/README&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The directory /mnt is where the slackware setup expects you to mount your root for installation.&lt;br /&gt;
&lt;br /&gt;
Controlling whether a zfs fs is to be mounted read-only or read-write is best managed by setting the readonly property while it is not yet mounted:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set readonly=on zfs-root&lt;br /&gt;
zfs set readonly=off zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Slackware expects root to be mounted readonly when /etc/rc.d/rc.S runs during normal startup, so later this is used to satisfy slackware's expectation to avoid rc.S complaining.&lt;br /&gt;
&lt;br /&gt;
The zfs-root can be mounted and unmounted in two different ways:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=/mnt zfs-root&lt;br /&gt;
zfs set mountpoint=none zfs-root&lt;br /&gt;
# or&lt;br /&gt;
mount zfs-root -t zfs /mnt&lt;br /&gt;
umount /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If it is already mounted and you want to change it to mount somewhere else, it is best to transition it to unmounted first, then mount it in the new place.&lt;br /&gt;
&lt;br /&gt;
The mount options &amp;lt;code&amp;gt;-o ro, -o rw, -o remount,ro, and -o remount,rw &amp;lt;/code&amp;gt; can also be used and will override &amp;lt;code&amp;gt;readonly=on|off&amp;lt;/code&amp;gt; property without altering the property value. This can be confusing until you are familiar with how to the methods of mounting interact.&lt;br /&gt;
&lt;br /&gt;
Now, let's continue some, and mount to /mnt using the current &amp;lt;code&amp;gt;readonly=off&amp;lt;/code&amp;gt; setting (rw mount):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=/mnt zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This method of mounting will show the most detailed mount options in /etc/mtab. They are the mount options that zfs thinks are proper, and they are probably what should be kept in /etc/fstab for zfs-root until we know better.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cat /etc/mtab &amp;gt;&amp;gt; /etc/fstab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now edit /etc/fstab to make sure it looks right, and remove the &amp;quot;rw&amp;quot; mount option, because we want to let it use a default for that, which will come from how we set the readonly= property most of the time. Unmount again:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=none zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mount again, now using all options from /etc/fstab:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It should be mounted at /mnt, and touch /mnt/t should allow you to make the file t. Then rm it: rm /mnt/t&lt;br /&gt;
For installation, we want to make sure it is mounted read-write. After installation, it should mount readonly inside the initrd.&lt;br /&gt;
&lt;br /&gt;
Sometimes there can be problems using the mount command, and then you can try it with the -i option:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 mount -i zfs-root&lt;br /&gt;
 mount -i zfs-root -t zfs /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
but, you should not have to use -i. When using -i makes it work, it performs an &amp;quot;internal-only&amp;quot; mount and does not use any mount.&amp;lt;fstype&amp;gt; helper scripts that might be on the system.&lt;br /&gt;
&lt;br /&gt;
Setup the /boot device:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkfs.ext4 /dev/sda1&lt;br /&gt;
mkdir /mnt/boot&lt;br /&gt;
mount /dev/sda1 /mnt/boot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We have both root and boot mounted where the slackware installer expects them. Unmount the dvd so setup can find it normally:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
umount /dev/sr0&lt;br /&gt;
setup&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the setup, skip straight to TARGET selection for the root device, but the setup doesn't see or understand the zfs-root, so it is not listed. This does not matter because we have mounted it already. Just skip down to a slot that say to continue, and continue on with setup. Because TARGET is skipped, you may not see the ADDITIONAL prompt (or if so, skip it too) where normally you give /dev/sda1 and have it mounted as /boot. This is also okay because we have mounted /mnt/boot already.&lt;br /&gt;
Because we did not give TARGET the root device or say what device /boot is on, the lilo installation will fail, or you can skip it. Otherwise, this installation process it normal.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
umount /dev/sr0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point, it is assumed that the setup has completed installing into /mnt. Congrats! You've installed slackware into a ZFS root!&lt;br /&gt;
&lt;br /&gt;
The next steps are to prepare to use &amp;quot;chroot /mnt&amp;quot; and finish up the configuration on the installed root system and then be able to reboot onto the completed installation. Before doing chroot, copy some files from the setup environment into /mnt.&lt;br /&gt;
&lt;br /&gt;
Copy the current installer /etc/fstab for later use inside the initrd. This fstab is what is proper inside the initrd, except remove option &amp;quot;rw&amp;quot; (if not done already).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/fstab /mnt/etc/fstab.initrd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The fstab.initrd will look like:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 proc /proc proc defaults 0 0&lt;br /&gt;
 zfs-root /mnt zfs defaults,atime,dev,exec,suid,xattr,nomand,zfsutil 0 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the initrd, we want zfs-root to mount to /mnt.&lt;br /&gt;
&lt;br /&gt;
Create /mnt/etc/fstab:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cat /etc/mtab &amp;gt;&amp;gt; /mnt/etc/fstab&lt;br /&gt;
vi /mnt/etc/fstab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using vi started above, edit /mnt/etc/fstab and make it have lines such as:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 zfs-root / zfs defaults,atime,dev,exec,suid,xattr,nomand,zfsutil 0 0&lt;br /&gt;
 /dev/sda1 /boot ext4 defaults 0 2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These two lines in &amp;lt;code&amp;gt;/mnt/etc/fstab&amp;lt;/code&amp;gt; are how the mounts should be looking when root is booted.&lt;br /&gt;
&lt;br /&gt;
Mount some special mounts before chroot:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount -t devtmpfs none /mnt/dev&lt;br /&gt;
mount -t proc none /mnt/proc&lt;br /&gt;
mount -t sysfs none /mnt/sys&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Make sure /boot is mounted:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount /dev/sda1 /mnt/boot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you had mounted a 9p fs share to access spl and zfs packages, then unmount that now:&lt;br /&gt;
umount /packages&lt;br /&gt;
&lt;br /&gt;
Ready, now:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chroot /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point, you should be on the installed system, and now try to configure mkinitrd and lilo. First, switch to use the generic kernel.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /boot&lt;br /&gt;
rm System.map config vmlinuz&lt;br /&gt;
ln -s System.map-gen* System.map&lt;br /&gt;
ln -s config-gen* config&lt;br /&gt;
ln -s vmlinuz-gen* vmlinuz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We install spl and zfs inside the live ramfs install-dvd environment, but not yet have we installed them into the root system:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount /dev/sr0 /mnt/cdrom&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /mnt/cdrom/addon/spl-*.txz&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /mnt/cdrom/addon/zfs-*.txz&lt;br /&gt;
depmod&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If instead, you used a 9p share to access the spl and zfs packages, then repeat that procedure here to install them onto the root system.&lt;br /&gt;
&lt;br /&gt;
Setup lilo: edit /etc/lilo.conf so it is like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  lba32&lt;br /&gt;
  append = &amp;quot; vt.default_utf8=1&amp;quot;&lt;br /&gt;
  boot = /dev/sda&lt;br /&gt;
  message = /boot/boot_message.txt&lt;br /&gt;
  prompt&lt;br /&gt;
  timeout = 1200&lt;br /&gt;
  change-rules&lt;br /&gt;
   reset&lt;br /&gt;
  vga = normal&lt;br /&gt;
  image = /boot/vmlinuz&lt;br /&gt;
   label = vmlinuz&lt;br /&gt;
   initrd = /boot/initrd.gz&lt;br /&gt;
   root = /dev/ram0&lt;br /&gt;
   read-write&lt;br /&gt;
# alternatively, the root and read-write lines&lt;br /&gt;
# can be this one line of kernel parameters:&lt;br /&gt;
#  addappend = &amp;quot; root=/dev/ram0 rw &amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: when using a initrd (see /usr/src/linux/Documentation/initrd.txt), the initial root device is normally set to root=/dev/ram0 (a ramfs block device) and allowed read-write. The kernel refers to devices in terms of &amp;quot;major&amp;quot; and &amp;quot;minor&amp;quot; numbers, and the ram0 device is assigned the block device major 1 and minor 0 (see /usr/src/linux/Documentation/devices.txt). This ram0 major/minor is written in hexadecimal as 0x0100 (256 in decimal). This hexademical number makes an appearance in /boot/initrd-tree/int where it runs: &amp;quot;echo 0x0100 &amp;gt; /proc/sys/kernel/real-root-dev&amp;quot;. Echoing a device code to real-root-dev is part of a deprecated initrd mechanism, but is probably harmless to leave alone as slackware has it unless you know otherwise.&lt;br /&gt;
&lt;br /&gt;
Setup mkinitrd:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/mkinitrd.conf.sample /etc/mkinitrd.conf&lt;br /&gt;
vi /etc/mkinitrd.conf&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Edit it to look like this (other defaults should be ok):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 MODULE_LIST=&amp;quot;sym53c8xx:ext4:8139cp:zfs:9p:9pnet_virtio&amp;quot;&lt;br /&gt;
 ROOTDEV=&amp;quot;zfs-root&amp;quot;&lt;br /&gt;
 ROOTFS=&amp;quot;zfs&amp;quot;&lt;br /&gt;
#Module sym53c8xx is the driver for qemu's if=scsi drive device.&lt;br /&gt;
#Module ext4 for /boot.&lt;br /&gt;
#Module 8139cp for eth0 net device.&lt;br /&gt;
#Module zfs for ZFSonLinux.&lt;br /&gt;
#Modules 9p and 9pnet_virtio for mounting qemu -virtfs mount_tag.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These 9p could be useful from the rescue command line inside the initrd to get needed files that are on the host.&lt;br /&gt;
&lt;br /&gt;
All dependent modules will also be included automatically into /boot/initrd-tree, which is packaged as /boot/initrd.gz. For example, to see the dependent modules of zfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
modprobe --show-depends zfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All listed modules will also be in the initrd. Now, make a /boot/initrd-tree that we can begin to look at and edit.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkinitrd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create an empty /etc/mtab or else zpool import fails (zfs expects /etc/mtab to exists already, it won't make it).&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
touch /boot/initrd-tree/etc/mtab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Copy in the fstab.initrd that was made earlier while on the installer. This provides all the mount options for a simple &amp;quot;mount zfs-root&amp;quot; onto /mnt.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/fstab.initrd /boot/initrd-tree/etc/fstab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More package installing! This time into an alternate root, the root of the initrd, /boot/initrd-tree. This is how you can put whatever packages you like into your initrd. These installations work independent of your normal installations. You can install, upgrade, and remove packages using an altroot:&lt;br /&gt;
&lt;br /&gt;
If spl and zfs are on your customized dvd:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/addon/spl-*.txz&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/addon/zfs-*.txz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Otherwise, repeat same procedure but you mount your 9p mount_tag and get them installed.&lt;br /&gt;
&lt;br /&gt;
More regular packages from the dvd:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/kmod-*.txz&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/coreutils-*.txz&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/gptfdisk-*.txz&lt;br /&gt;
&lt;br /&gt;
# A bash script is in /boot/initrd-tree/lib/udev/, so we need it or udev rules have problems:&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/bash-*.txz&lt;br /&gt;
# Bash needs this:&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/l/libtermcap-*.txz&lt;br /&gt;
&lt;br /&gt;
# Install net-tools to ensure that /etc/HOSTNAME, /etc/hosts, and potentially, /etc/hostid are handled proper.&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/n/net-tools-*.txz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When ZFS has to import a zpool while the initrd is running (this can be avoided by not exporting and keeping /etc/zfs/zpool.cache inside the initrd), ZFS will refuse to import a pool if it thinks that the pool may be in use by another system. ZFS was designed for network attached storage where multiple hosts might have access to the same disks but ZFS cannot support two hosts importing and using a ZFS pool at the same time. ZFS checks a value called &amp;quot;hostid&amp;quot; to determine this kind of conflict, and it can be a tricky issue with an initrd boot process. The value of hostid is returned by a system call, the gethostid() function or the hostid command. This function will return the hostid from /etc/hostid if that file exists and has a valid id in it, or else if the file doesn't exist it obtains a hostid number based on the hostname and ip address address assigned to hostname found in /etc/hosts or in DNS. If the hostid trying to import a pool is not the same as the hostid that imported it last time, ZFS will not import the pool unless &amp;quot;zpool import -f zfs-root&amp;quot; is used to force the import. This force option is not recommended to use, so it is best to configure your initrd with matching /etc/HOSTNAME and /etc/hosts as on the root installation and ensure what your system looks like on the initrd matches the booted root system.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Edit /boot/initrd-tree/init (this is the main system startup script on the initrd, responsibe for configuring your block devices and mount your root at /mnt and then booting root):&lt;br /&gt;
&lt;br /&gt;
Inside init, right near the top of the file after the PATH= line, add this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/bin/hostname -F /etc/HOSTNAME&lt;br /&gt;
/bin/hostname $( /bin/hostname -s )&lt;br /&gt;
#/sbin/chhostid 13371400&lt;br /&gt;
# you can make your hostid whatever, but this didn't work right with ZFS, so it is commented out&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This sets the name reported by the hostname command (the default is &amp;quot;darkstar&amp;quot;) to be what is contained in /etc/HOSTNAME. The hostname is modified in the next line to be the short name. These lines will help ZFS to properly identify your host when importing pools.&lt;br /&gt;
&lt;br /&gt;
Inside init, right after it runs &amp;quot;mdadm&amp;quot; commands as used for raid setup, we like it to setup ZFS, so add:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/sbin/zpool import zfs-root&lt;br /&gt;
/sbin/zfs set readonly=on zfs-root&lt;br /&gt;
mount zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Inside init, close to the bottom, where it &amp;quot;Switch to real root partition&amp;quot;, comment out 1 line that normally does the mount:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# mount -o ro -t $ROOTFS $ROOTDEV /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
We have already mounted, and we don't want to use any mount options because we should be using a properly set /etc/fstab inside the initrd for zfs-root mount options onto /mnt.&lt;br /&gt;
&lt;br /&gt;
During a normal startup we want a readonly mount.&lt;br /&gt;
&lt;br /&gt;
Note: we are going to setup with using zpool import and export and startup and shutdown. But later, you can experiment having /etc/zfs/zpool.cache stored in the initrd and commenting out zpool import/export lines.&lt;br /&gt;
&lt;br /&gt;
As mentioned, the import command may sometimes fail, and give the message: &amp;quot;pool may be in use from another system&amp;quot;. This is nothing serious in this test situation. When this happens, root will not be mounted to /mnt and the init script will detect this and drop you into a rescue command line where you may manually &amp;quot;import -f&amp;quot; then &amp;quot;mount zfs-root&amp;quot; and then &amp;quot;exit&amp;quot; to continue on to booting the root.&lt;br /&gt;
&lt;br /&gt;
To avoid this problem we copy some files in (assuming you first edit /etc/HOSTNAME to hold the hostname you like to see on your command prompts, and edited /etc/hosts to have hostname on your loopback or other local ip address):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/HOSTNAME /etc/hosts /boot/initrd-tree/etc&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The value reported by the hostid command is what ZFS sees as your hostid. In this setup so far, the value is based on the ip found assigned to your hostname. If your hostname is on the line in /etc/hosts for ip address 192.168.13.37, then your hostid will be hex numbers C0.A8.0D.25 rearranged as A8C0250D (pairs of bytes are swapped). That is ip-based hostid value, a 32bit hexadecimal number. This has to be the same each boot or import will need a -f option to force it. Simply setting the hostid using the system call sethostid() which writes a /etc/hostid file doesn't seem to agree with ZFS and you'd have to force the import, so this setup now assumes that you do not have or have deleted /etc/hostid.&lt;br /&gt;
&lt;br /&gt;
You can sometimes see what has been happening to a zpool by using the command &amp;quot;zpool history -li zfs-root&amp;quot; to see a log of commands.&lt;br /&gt;
&lt;br /&gt;
Once again, you can do away with the import and export commands by trying to have /etc/zfs/zpool.cache inside your initrd. To create zpool.cache, while on the installer or in the rescue shell of the initrd (at lilo &amp;quot;boot: vmlinuz rescue&amp;quot;), import only the pool for the root fs with mountpoint=none and readonly=on properties set and while it is not mounted:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on installer or initrd rescue shell)&lt;br /&gt;
cp /etc/zfs/zpool.cache /etc/zfs/zpool.cache-initrd&lt;br /&gt;
zfs set readonly=off zfs-root&lt;br /&gt;
mount zfs-pool&lt;br /&gt;
cp /etc/zfs/zpool.cache-initrd /mnt/etc/zfs/&lt;br /&gt;
cp /mnt/etc/zfs/zpool.cache-initrd /mnt/boot/initrd-tree/etc/zfs/zpool.cache&lt;br /&gt;
umount /mnt&lt;br /&gt;
zfs set readonly=on zfs-root&lt;br /&gt;
#mount zfs-root&lt;br /&gt;
#exit (to continue boot process onto rootfs mounted at /mnt)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, doing this zpool.cache approach is not necessary, and some talk suggests this is deprecated or discouraged. Although /etc/hostid setup fails to import without -f option, ip-based (hosts|dns) hostid works on booting and import works without -f option and may be the more proper way to do shutdown and startup rather than using a cache file which could be come invalid and cause a problem that is difficult to understand. The contents and exact function of the cache file are not well understood by many people.&lt;br /&gt;
&lt;br /&gt;
Save /boot/initrd-tree/init and exit.&lt;br /&gt;
&lt;br /&gt;
Now, edit /etc/rc.d/rc.S and rc.6 to understand how to &amp;quot;remount&amp;quot; rw or ro as a readonly property changes&lt;br /&gt;
&lt;br /&gt;
In /etc/rc.d/rc.S:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# comment out the line&lt;br /&gt;
#    /sbin/mount -w -v -n -o remount /&lt;br /&gt;
#add the line&lt;br /&gt;
     /sbin/zfs set readonly=off zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In /etc/rc.d/rc.6&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# comment out the line&lt;br /&gt;
#    /bin/mount -v -n -o remount,ro /&lt;br /&gt;
#add the line&lt;br /&gt;
     /sbin/zfs set readonly=on zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In /etc/rc.d/rc.6, near the bottom just before poweroff|reboot, add the following block of lines:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
########################&lt;br /&gt;
# Try to export zfs-root&lt;br /&gt;
/sbin/zpool export zfs-root&lt;br /&gt;
if [ $? -gt 0 ] ; then&lt;br /&gt;
 echo &amp;quot;ZFS export failed.&amp;quot;&lt;br /&gt;
 echo &amp;quot;Notice: if root fs is busy, then this is normal fail.&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;ZFS export successful.&amp;quot;&lt;br /&gt;
 echo &amp;quot;Warning: successful export is abnormal for root fs.&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
/bin/sleep 5&lt;br /&gt;
########################&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
For ZFS, you cannot run fsck on it. It doesn't support that kind of filesystem checks. The rc.S script will complain a lot in many places about not being about to run fsck on the zfs-root. To disable all attempts of run fsck, we can simple create a file that acts as a flag in /etc/rc.d/rc.S to tell it to skip fsck:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
touch /etc/fastboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This fastboot file is normally a run-once temporary file, and it is deleted near the bottom inside rc.S. Edit rc.S and stop it from deleting /etc/fastboot. We would like it to always skip all fsck. Edit /etc/rc.d/rc.S, and find the &amp;quot;rm&amp;quot; of fastboot, and do not have it removed!&lt;br /&gt;
&lt;br /&gt;
We are getting close, and have finished all editing, so make /boot/initrd.gz and install lilo:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkinitrd -F&lt;br /&gt;
lilo&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We finished! All that's left to do is clean up.&lt;br /&gt;
&lt;br /&gt;
Exit the chroot.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
exit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Try to mount everything:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
umount /mnt/proc&lt;br /&gt;
umount /mnt/sys&lt;br /&gt;
umount /mnt/dev&lt;br /&gt;
umount /mnt/boot&lt;br /&gt;
umount /mnt/mnt/cdrom&lt;br /&gt;
umount /mnt/root/packages&lt;br /&gt;
umount /mnt&lt;br /&gt;
zpool export zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note, that export stops a pool and frees devices, while import binds devices and starts a pool. It is somewhat like mdadm -A -s and mdadm -S -s, while /etc/zfs/zpool.cache might be somewhat like mdadm -E -s &amp;gt; /etc/mdadm.conf.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Remove the DVD or change boot order&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When you reboot, if all is good, you are booting properly onto a slackware installed on a ZFS root! Congrat!&lt;br /&gt;
&lt;br /&gt;
If this seem to go badly, and this might happen if the import fails as explain some before, then you will be on the initrd's rescue command line just before the part in it's init where it wants to mount and switch_root to boot your root. Instead, you typically got commands like this to do:&lt;br /&gt;
&lt;br /&gt;
If you get dumped to rescue because import will not work and requires -f (force), then:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 zpool import -f zfs-root&lt;br /&gt;
 zpool export    zfs-root&lt;br /&gt;
 zpool import    zfs-root&lt;br /&gt;
 mount zfs-root&lt;br /&gt;
 exit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This can happen if hostname, hostid, or uname changes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you get into a jam and need to boot into the initrd and skip zfs import etc, use the lilo prompt (or, boot the install-dvd):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
boot: vmlinuz rescue&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the rescue mode of the initrd, after you have mounted your root as readonly=on to /mnt, then exit to continue.&lt;br /&gt;
&lt;br /&gt;
In other emergency modes, you might need to run the lines at end of init starting from: &amp;lt;code&amp;gt;udevadm info --cleanup-db; udevadm control --exit&amp;lt;/code&amp;gt;&lt;br /&gt;
If you don't run those udevadm commands, two runs of udevd fight each other and it is slow; you have to wait 2 minutes twice for timeouts (4 minutes).&lt;br /&gt;
The last line is run is: &amp;lt;code&amp;gt;exec switch_root /mnt /sbin/init 1&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Warning... this switch_root command is kind of dangerous, so read the manual page about it.&lt;br /&gt;
From what I can tell, everything except the new root &amp;quot;/mnt&amp;quot; is deleted, so you are giving a command that says what NOT to delete!&lt;br /&gt;
Make sure nothing got mounted outside of &amp;quot;/mnt&amp;quot; before you run it.&lt;br /&gt;
&lt;br /&gt;
Also, in rescue or anytime you have finished making changes and are about to reboot in some abnormal mode, first run:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set readonly=on zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A bug in unpatched grep 2.13 build 1, found slackware 14.0rc1, causes problems when processing files stored on ZFS but rarely shows problems on other filesystems; the bug does not handle sparse files on zfs and btrfs correctly and results in chaos with slackpkg, compiling kernel modules, and possibly many other things. You must downgrade grep to 2.12 or use the patched grep 2.13 build 2 in slackware 14.0rc2 or later.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Upgrading.&lt;br /&gt;
&lt;br /&gt;
From time to time you will want to upgrade the kernel to the new kernel in slackware64-current or in patches/. This will also necessitate a rebuilt and reinstall or upgrade of spl and zfs. Below is an example of when both kernel and spl/zfs are being upgraded, to give an idea of the process:&lt;br /&gt;
&lt;br /&gt;
Using slackpkg, that is configured to use your local slackware mirror is a good option but you can also configure it to use a remote mirror.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slackpkg upgrade-all&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Assume slackpkg just upgraded your kernel, kernel-modules, and kernel-headers.&lt;br /&gt;
&lt;br /&gt;
Note: the first time you try to run on kernel-generic, setup kernel-huge in lilo as 2nd choice. Huge has all the hard drive controllers builtin, but generic has them all as modules. For example, run &amp;quot;modinfo mptsas&amp;quot; to see module options (maybe you have a LSISAS1068) for your hard drive controller. Add file /etc/modprobe.d/mptsas.conf to set options you want with a line: options mptsas ... Do this for all the device driver modules for your hardware. Do this setup while you are on the huge kernel, then setup to reboot to generic. Include all these modules you need into mkinitrd.conf MODULES_LIST. Check that /boot/initrd-tree/etc/modprobe.d/ has a copy of your customized module conf files because it is on the initrd where the modules will load and use the conf files. mkinitrd probably copies all /etc/modprobe.d/* files into the initrd-tree, but check it. Pay attention to /etc/modprobe.d/README and /lib/modprobe.d/* /lib/modprobe.d/* maybe not copied to initrd-tree but you might want to copy some of it into your initrd-tree yourself to use them.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Check that upgraded kernel-source is symlinked to /usr/src/linux (zfs build looks here). SQL/ZFS modules will install to the kernel version in /lib/modules/&amp;lt;/usr/src/linux kernel version&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /usr/local/src&lt;br /&gt;
tar xvzf ~/spl-*.tar.gz&lt;br /&gt;
tar xvzf ~/zfs-*.tar.gz&lt;br /&gt;
&lt;br /&gt;
###### upgrade spl 1st&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-*&lt;br /&gt;
./configure --prefix=/ --libexecdir=/usr/libexec --libdir=/lib64 --includedir=/usr/include --datarootdir=/usr/share&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=/usr/local/src/install&lt;br /&gt;
cd ../install&lt;br /&gt;
makepkg ../spl-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
upgradepkg spl-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
depmod &amp;lt;new kernel version&amp;gt;     (e.g. depmod 3.2.27, if .27 is new kernel upgrade; you currently run on old, maybe .26)&lt;br /&gt;
# this builds the module dependencies in /lib/modules/&amp;lt;new kernel version&amp;gt;&lt;br /&gt;
###### upgrade zfs 2nd&lt;br /&gt;
mkdir install&lt;br /&gt;
cd zfs-*&lt;br /&gt;
./configure --prefix=/ --libexecdir=/usr/libexec --libdir=/lib64 --includedir=/usr/include --datarootdir=/usr/share&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=/usr/local/src/install&lt;br /&gt;
cd ../install&lt;br /&gt;
makepkg ../zfs-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
upgradepkg zfs-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
depmod 3.2.27&lt;br /&gt;
####### upgrade spl/zfs inside altroot /boot/initrd-tree&lt;br /&gt;
ROOT=/boot/initrd-tree upgradepkg spl-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
ROOT=/boot/initrd-tree upgradepkg zfs-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
# note: ROOT is an environment variable, not a command line option to upgradepkg!&lt;br /&gt;
# note: do not worry about depmod inside initrd-tree, mkinitrd -F actually installs the modules&lt;br /&gt;
# note: this upgrade here is really to just upgrade the command line tools zpool, zfs etc&lt;br /&gt;
####### rebuild /boot/initrd.gz and reinstall lilo&lt;br /&gt;
vi /etc/mkinitrd.conf&lt;br /&gt;
# temporarily set KERNEL_VERSION to new version, but you are still running on old version&lt;br /&gt;
mkinitrd -F&lt;br /&gt;
lilo&lt;br /&gt;
vi /etc/mkinitrd.conf&lt;br /&gt;
# you can set KERNEL_VERSION back to $(uname r) now&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After reboot you can remove any old /lib/modules/&amp;lt;old kernel version&amp;gt; directory.&lt;br /&gt;
&lt;br /&gt;
More about /etc/hostid. If you want to experiment changing your /etc/hostid file and seeing if you can use it and make zpool import work normally, here is a tool that might be helpful:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/* software product name: foobarz-chhostid.c&lt;br /&gt;
 * suggested binary name: chhostid&lt;br /&gt;
 * license              : BSD&lt;br /&gt;
 * license text:&lt;br /&gt;
Copyright (c) 2012, foobarz&lt;br /&gt;
All rights reserved.&lt;br /&gt;
&lt;br /&gt;
Redistribution and use in source and binary forms, with or without&lt;br /&gt;
modification, are permitted provided that the following conditions are met:&lt;br /&gt;
    * Redistributions of source code must retain the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer.&lt;br /&gt;
    * Redistributions in binary form must reproduce the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer in the&lt;br /&gt;
      documentation and/or other materials provided with the distribution.&lt;br /&gt;
    * Neither the name of the &amp;lt;organization&amp;gt; nor the&lt;br /&gt;
      names of its contributors may be used to endorse or promote products&lt;br /&gt;
      derived from this software without specific prior written permission.&lt;br /&gt;
&lt;br /&gt;
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &amp;quot;AS IS&amp;quot; AND&lt;br /&gt;
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED&lt;br /&gt;
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE&lt;br /&gt;
DISCLAIMED. IN NO EVENT SHALL &amp;lt;COPYRIGHT HOLDER&amp;gt; BE LIABLE FOR ANY&lt;br /&gt;
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES&lt;br /&gt;
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;&lt;br /&gt;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND&lt;br /&gt;
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT&lt;br /&gt;
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS&lt;br /&gt;
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#define FOOBARZ_CHHOSTID_VERSION &amp;quot;1.0.5&amp;quot;&lt;br /&gt;
#include &amp;lt;sys/socket.h&amp;gt;&lt;br /&gt;
#include &amp;lt;netinet/in.h&amp;gt;&lt;br /&gt;
#include &amp;lt;arpa/inet.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;endian.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sysexits.h&amp;gt;&lt;br /&gt;
/* note: if include stdlib then sethostid fails even with _BSD_SOURCE defined */&lt;br /&gt;
&lt;br /&gt;
long swapbytes(long abcd) {&lt;br /&gt;
  long badc;&lt;br /&gt;
  unsigned char addr_a;&lt;br /&gt;
  unsigned char addr_b;&lt;br /&gt;
  unsigned char addr_c;&lt;br /&gt;
  unsigned char addr_d;&lt;br /&gt;
  addr_a = (unsigned char) (abcd &amp;gt;&amp;gt; 24);&lt;br /&gt;
  addr_b = (unsigned char) (abcd &amp;gt;&amp;gt; 16);&lt;br /&gt;
  addr_c = (unsigned char) (abcd &amp;gt;&amp;gt;  8);&lt;br /&gt;
  addr_d = (unsigned char) (abcd);&lt;br /&gt;
  return badc = ( (addr_b &amp;lt;&amp;lt; 24) | (addr_a &amp;lt;&amp;lt; 16) | (addr_d &amp;lt;&amp;lt; 8) | addr_c );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[])&lt;br /&gt;
{&lt;br /&gt;
 long newhostid;&lt;br /&gt;
 struct in_addr addr;&lt;br /&gt;
 char* invalidchar;&lt;br /&gt;
&lt;br /&gt;
 /*********** check command line */&lt;br /&gt;
 if(!( ((argc==3) &amp;amp;&amp;amp; ( (strcmp(argv[1],&amp;quot;-h&amp;quot;)==0) ||&lt;br /&gt;
                       (strcmp(argv[1],&amp;quot;-i&amp;quot;)==0) ||&lt;br /&gt;
                       (strcmp(argv[1],&amp;quot;-l&amp;quot;)==0) )) ||&lt;br /&gt;
       ((argc==2) &amp;amp;&amp;amp; ( (strcmp(argv[1],&amp;quot;-s&amp;quot;)==0) ))&lt;br /&gt;
     )&lt;br /&gt;
   ) {&lt;br /&gt;
                 /*01234567890123456789012345678901234567890123456789012345678901234567890123456789*/&lt;br /&gt;
  fprintf(stderr, &amp;quot;foobarz-chhostid, version %s. License: BSD.\n&amp;quot;, FOOBARZ_CHHOSTID_VERSION);&lt;br /&gt;
  fprintf(stderr, &amp;quot;foobarz-chhostid, (c) 2012, foobarz; all rights reserved.\n&amp;quot;);&lt;br /&gt;
  fprintf(stderr, &amp;quot;descr: %s change system hostid (in /etc/hostid).\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -h &amp;lt;new hostid&amp;gt;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        Change system hostid to &amp;lt;new hostid&amp;gt;;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        &amp;lt;new hostid&amp;gt; must be 32bit 8-digit hex number xxxxxxxx, each x in 0-f|F.\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        The ip corresponding to &amp;lt;new hostid&amp;gt; is also listed for reference only.\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -i &amp;lt;dotted ip address&amp;gt;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        Change system hostid to hostid corresponding to &amp;lt;dotted ip address&amp;gt;.\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -l &amp;lt;dotted ip address&amp;gt;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        List hostid corresponding to &amp;lt;dotted ip address&amp;gt;;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        no change to system hostid.\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -s\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        List current system hostid and corresponding ip address;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        no change to system hostid.\n&amp;quot;, argv[0]);&lt;br /&gt;
  return EX_USAGE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -h &amp;lt;hostid&amp;gt; */&lt;br /&gt;
 if( strcmp(argv[1],&amp;quot;-h&amp;quot;) == 0 ) {&lt;br /&gt;
  if(strlen(argv[2]) != 8) { fprintf(stderr, &amp;quot;new hostid must be 8-digit hex number xxxxxxxx, each x in 0-f|F\n&amp;quot;); return EX_USAGE; }&lt;br /&gt;
&lt;br /&gt;
  newhostid = strtol(argv[2],&amp;amp;invalidchar,16);&lt;br /&gt;
  if( newhostid==LONG_MIN ) { perror(&amp;quot;strtol (underflow)&amp;quot;); return EX_USAGE; }&lt;br /&gt;
  if( newhostid==LONG_MAX ) { perror(&amp;quot;strtol (overflow)&amp;quot;); return EX_USAGE; }&lt;br /&gt;
  if(*invalidchar != '\0') { fprintf(stderr, &amp;quot;invalid hex number %c; must be in 0-f|F\n&amp;quot;, *invalidchar); return EX_USAGE; }&lt;br /&gt;
&lt;br /&gt;
  if( sethostid(newhostid) != 0 ) {&lt;br /&gt;
   perror(&amp;quot;sethostid&amp;quot;);&lt;br /&gt;
   if( errno == EPERM ) return EX_NOPERM;&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
  }&lt;br /&gt;
  printf(&amp;quot;System hostid changed.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  /* hostid is a byte-swapped ip like b.a.d.c */&lt;br /&gt;
  /* get ip by swapping to correct order a.b.c.d and save into in_addr struct */&lt;br /&gt;
  addr.s_addr = htonl(swapbytes(newhostid));&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -i or -l, then find hostid for &amp;lt;dotted ip address&amp;gt; */&lt;br /&gt;
 if( (strcmp(argv[1],&amp;quot;-i&amp;quot;) == 0) || (strcmp(argv[1],&amp;quot;-l&amp;quot;) == 0) ) {&lt;br /&gt;
  if( inet_aton(argv[2], &amp;amp;addr) == 0 ) { fprintf(stderr, &amp;quot;inet_aton: invalid dotted ip address: %s\n&amp;quot;, argv[2]); return EX_USAGE; }&lt;br /&gt;
&lt;br /&gt;
  /* hostid is a byte-swapped ip like b.a.d.c */&lt;br /&gt;
  /* get hostid by swapping bytes of ip a.b.c.d */&lt;br /&gt;
  newhostid = swapbytes(ntohl(addr.s_addr));&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -i &amp;lt;dotted ip address&amp;gt; */&lt;br /&gt;
 if( strcmp(argv[1],&amp;quot;-i&amp;quot;) == 0 ) {&lt;br /&gt;
  if( sethostid(newhostid) != 0 ) {&lt;br /&gt;
   perror(&amp;quot;sethostid&amp;quot;);&lt;br /&gt;
   if( errno == EPERM ) return EX_NOPERM;&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
  }&lt;br /&gt;
  printf(&amp;quot;System hostid changed.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -l &amp;lt;dotted ip address&amp;gt; */&lt;br /&gt;
 if(strcmp(argv[1],&amp;quot;-l&amp;quot;) == 0 ) {&lt;br /&gt;
   printf(&amp;quot;Listing hostid for ip. (no changes)\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -s */&lt;br /&gt;
 if(strcmp(argv[1],&amp;quot;-s&amp;quot;) == 0 ) {&lt;br /&gt;
   /* see if /etc/hostid exists and print info */&lt;br /&gt;
   if( access(&amp;quot;/etc/hostid&amp;quot;, F_OK) != 0 ) {&lt;br /&gt;
     printf(&amp;quot;Notice: /etc/hostid does not exist.\n&amp;quot;);&lt;br /&gt;
     perror(&amp;quot;Reason&amp;quot;);&lt;br /&gt;
     printf(&amp;quot;System hostid derived from ip of hostname found in hosts file or dns.\n&amp;quot;);&lt;br /&gt;
   } else {&lt;br /&gt;
     printf(&amp;quot;Notice: /etc/hostid exists.\n&amp;quot;&lt;br /&gt;
            &amp;quot;System hostid is obtained from hostid file.\n&amp;quot;);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
  errno=0;&lt;br /&gt;
  newhostid = gethostid();&lt;br /&gt;
  if(errno!=0) { perror(&amp;quot;gethostid&amp;quot;); return EX_UNAVAILABLE; }&lt;br /&gt;
&lt;br /&gt;
  /* hostid is a byte-swapped ip like b.a.d.c */&lt;br /&gt;
  /* get ip by swapping to correct order a.b.c.d and save into in_addr struct */&lt;br /&gt;
  addr.s_addr = htonl(swapbytes(newhostid));&lt;br /&gt;
&lt;br /&gt;
  printf(&amp;quot;Listing current system hostid. (no changes)\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** print info and return */&lt;br /&gt;
 printf(&amp;quot;ip dot: %s\n&amp;quot;, inet_ntoa(addr) );&lt;br /&gt;
 printf(&amp;quot;ip hex: %.8x\n&amp;quot;, ntohl(addr.s_addr) );&lt;br /&gt;
 printf(&amp;quot;hostid: %.8x\n&amp;quot;, newhostid );&lt;br /&gt;
 return EX_OK;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</description>
			<pubDate>Sun, 19 Aug 2012 01:51:42 GMT</pubDate>
			<dc:creator>Foobarz</dc:creator>
			<comments>https://www.slackwiki.com/Talk:ZFS_root</comments>
		</item>
		<item>
			<title>ZFS root</title>
			<link>https://www.slackwiki.com/index.php?title=ZFS_root&amp;diff=737</link>
			<guid isPermaLink="false">https://www.slackwiki.com/index.php?title=ZFS_root&amp;diff=737</guid>
			<description>&lt;p&gt;Foobarz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Tutorials]]&lt;br /&gt;
If you have heard about the ZFS filesystem and you're curious to try it out, then you can try it on slackware64, thanks to the ZFSonLinux.org project!&lt;br /&gt;
&lt;br /&gt;
In this article, an example is shown of how to install slackware64 14.0 onto a ZFS root filesystem (zfs-root) inside a QEMU virtual machine for testing purposes. It is recommended that you install qemu and learn how to use it to test a ZFS installation before you decide to use it on real hardware. A slackbuild for qemu can be found on slackbuilds.org. If you have a processor that supports Intel VT-x or AMD AMD-V virtualization acceleration (try modprobe kvm-intel or modprobe kvm-amd), then use the slackbuild for qemu-kvm.&lt;br /&gt;
&lt;br /&gt;
This article isn't going to go into any detail on actually using ZFS or what kinds of installation options and settings might be optimal. This article just presents an example of how to get started with ZFS on slackware.&lt;br /&gt;
&lt;br /&gt;
At this time of writing, ZFSonLinux is at &amp;quot;release candidate&amp;quot; (version 0.6.0-rc10) development stage, and many issues can occur. See the ZFSonLinux.org web site and the issues tracker for an idea about the current issues. There is also an irc channel on irc.freenode.net, #zfsonlinux, for discussion of issues and help.&lt;br /&gt;
&lt;br /&gt;
Although not required, it is helpful to keep a local mirror of slackware64 on your system. Having a local mirror makes it easier to upgrade to slackware64-current or to patches/* in a release. To help manage your own local slackware mirror and generate your own CD and DVD slackware installers, see http://alien.slackbook.org/blog/local-slackware-mirror/.&lt;br /&gt;
&lt;br /&gt;
In this article, we use a slackware64-current DVD image file as the qemu cdrom device media for the installation of the slackware guest. This was tested at slackware64-current = slackware64 14.0rc2. You can obtain a slackware DVD image using a torrent, buy the DVD from slackware.com, or generate your own DVD image file using the mirror script. For an actual DVD, you can pass your DVD device (e.g., /dev/sr0) as the qemu cdrom device. For a DVD image file, pass the image file as the qemu cdrom device.&lt;br /&gt;
&lt;br /&gt;
The ZFSonLinux packages are not included in slackware at this time. There are two packages involved: spl and zfs. The first, spl, is &amp;quot;Solaris Porting Layer&amp;quot; and must be installed on the system before zfs can be compiled. The source code tarballs for these are at ZFSonLinux.org. At this time of writing, they are spl-0.6.0-rc10.tar.gz and zfs-0.6.0-rc10.tar.gz.&lt;br /&gt;
&lt;br /&gt;
At this point, it is assumed you have qemu installed, have obtained a slackware64-current/14.0 DVD, and have downloaded spl and zfs tarballs to your host system. The first step now is, if your host is not slackware64-current/14.0 (the same as the guest will be), then you need to create a minimal development slackware64 guest system in qemu for just the purpose of compiling and packaging the spl and zfs slackware packages and transferring a copy of these packages back onto your host system to use later to install onto zfs during the slackware install process.&lt;br /&gt;
&lt;br /&gt;
From this point onward, instructions become a bit terse and mostly limited to examples of the commands you might use to complete tasks. You are encouraged to examine what each command does by reading the command's man pages. For example, the command &amp;quot;man qemu&amp;quot; can show you most of what you need to know about running qemu on the command line.&lt;br /&gt;
&lt;br /&gt;
So, here's an example of how you might build the spl and zfs packages, starting in your home directory:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on host)&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir qemu&lt;br /&gt;
cd qemu&lt;br /&gt;
mkdir slackdevel&lt;br /&gt;
cd slackdevel&lt;br /&gt;
mkdir packages&lt;br /&gt;
cp ~/spl-*.tar.gz packages&lt;br /&gt;
cp ~/zfs-*.tar.gz packages&lt;br /&gt;
qemu-img create disk1.raw 10G&lt;br /&gt;
ln -s ~/slackware64-current-install-dvd.iso dvd.iso&lt;br /&gt;
qemu-system-x86_64 \&lt;br /&gt;
 -no-quit \&lt;br /&gt;
 -no-shutdown \&lt;br /&gt;
 -boot order=cd,menu=on \&lt;br /&gt;
 -m 2G \&lt;br /&gt;
 -cpu host \&lt;br /&gt;
 -smp sockets=1,cores=4 \&lt;br /&gt;
 -net nic,model=rtl8139 -net user \&lt;br /&gt;
 -cdrom dvd.iso \&lt;br /&gt;
 -drive boot=on,format=raw,media=disk,cache=none,aio=native,if=scsi,bus=0,unit=0,file=disk1.raw \&lt;br /&gt;
 -virtfs local,path=./packages/,security_model=none,mount_tag=hostpackages&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When you need to change boot to cd or disk, add or remove &amp;quot;boot=on&amp;quot;, or change &amp;quot;order=dc&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Qemu should boot into the install-dvd, and now perform a very ordinary slackware64 install onto /dev/sda. Install d package set and most others, but package sets x, kde, xfce not really needed.&lt;br /&gt;
&lt;br /&gt;
First note: examples here use tools from the gptfdisk package (gdisk, sgdisk, cgdisk) to partition the disk with GUID partition table (GPT) format. GPT might not be too familiar to everyone, who mostly have only used MBR partitions with fdisk. In the slackware installations this author has tested in qemu, using GPT partitions has caused no problems with lilo or other tools used in slackware. GPT disk labels support creating up to 128 partitions and support disks larger than 2TB (the limit of MBR fdisk). LILO installs into the first 440 bytes on /dev/sda, inside a GPT &amp;quot;protective MBR&amp;quot; that serves to provide compatibility with MBR bootloaders like lilo. LILO uses LBA32 sector addressing and can see all 512-byte sectors side the first 2TB of a disk. So long as the /boot partition is within the first 2TB of a disk, lilo can work on a disk larger than 2TB. Unlike the common default of fdisk to start the first partition at sector 63, which is not aligned with the 4KiB sector size of Advanced Format hard disks, gdisk's default is to start partitions at 2048 sector (1MiB) boundaries which are also 4KiB aligned. Using gdisk GPT works on all disks and is compatible with using Advanced Format hard disks larger than 2TB. More information about GPT disk label format can be found on wikipedia.org. For those that have used grub instead of lilo, grub installation is different with GPT than with MBR, and grub requires a GPT partition of type grub-bios or 0xEF02 &amp;quot;BIOS Boot Partition&amp;quot; of about 8MiB where it can install it's additional bootloader stages because grub cannot embed in sectors 1-62 on GPT where GPT keeps it's partition tables. On MBR, sectors 1-62 were normally reserved space for bootloaders to keep a 2nd stage.&lt;br /&gt;
&lt;br /&gt;
For this purpose of development guest, just create a simple 1-partition system, /dev/sda1, and do a simple slackware install on it. Don't bother with swap or separate /boot unless you want to:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on install-dvd)&lt;br /&gt;
cgdisk /dev/sda&lt;br /&gt;
setup&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When this simple development guest boots, login as root, and continue:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on qemu guest)&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir packages&lt;br /&gt;
mount hostpackages -t 9p -o trans=virtio packages&lt;br /&gt;
echo --prefix=/ --libexecdir=/usr/libexec --libdir=/lib64 --includedir=/usr/include --datarootdir=/usr/share &amp;gt; configure-options&lt;br /&gt;
mkdir src&lt;br /&gt;
cd src&lt;br /&gt;
&lt;br /&gt;
mkdir install&lt;br /&gt;
tar xvzf ~/packages/spl-*.tar.gz&lt;br /&gt;
cd spl-*&lt;br /&gt;
./configure $( cat ~/configure-options )&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../spl-&amp;lt;version&amp;gt;_&amp;lt;kernel_version&amp;gt;-x86_64-&amp;lt;build_id&amp;gt;.txz&lt;br /&gt;
(e.g., makepkg ../spl-0.6.0rc10_3.2.27-x86_64-1root.txz)&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
installpkg spl-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
cp spl-0.6.0rc10_3.2.27-x86_64-1root.txz ~/packages&lt;br /&gt;
&lt;br /&gt;
mkdir install&lt;br /&gt;
tar xvzf ~/packages/zfs-*.tar.gz&lt;br /&gt;
cd zfs-*&lt;br /&gt;
./configure $( cat ~/configure-options )&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../zfs-&amp;lt;version&amp;gt;_&amp;lt;kernel_version&amp;gt;-x86_64-&amp;lt;build_id&amp;gt;.txz&lt;br /&gt;
(e.g., makepkg ../zfs-0.6.0rc10_3.2.27-x86_64-1root.txz)&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
installpkg zfs-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
cp zfs-0.6.0rc10_3.2.27-x86_64-1root.txz ~/packages&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point spl and zfs packages are copied back to the host in the packages directory. Also, spl and zfs are installed in this simple development guest, so one could begin to experiment with zfs pools and datasets but while the root fs is whatever you made it during setup (probably the default, ext4). This development guest isn't really needed anymore, so it can be deleted:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
halt&lt;br /&gt;
(exit qemu: ctrl-alt-2 then enter quit at QEMU command prompt)&lt;br /&gt;
&lt;br /&gt;
(on host)&lt;br /&gt;
rm disk1.raw dvd.iso&lt;br /&gt;
mv packages ..&lt;br /&gt;
cd ..&lt;br /&gt;
rmdir slackdevel&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now that we have the spl and zfs packages on the host, it is possible to copy them into your local slackware64 mirror and then generate your own install DVD image that includes them. For example, change to the directory that contains the slackware README files, and create a &amp;quot;addon&amp;quot; directory and copy the spl and zfs slackware packages into there. Then, generate the DVD image using a command such as $( ./mirror-slackware-current.sh -i ) from where you have this script configured to maintain your local mirror. We can also just continue to access them inside the installer using qemu's virtfs option. When you are going to do a real installation onto real hardware, you need to generate and burn your own DVD that includes the packages.&lt;br /&gt;
&lt;br /&gt;
It is time to begin the installation of slackware64 on a ZFS root, assuming either you have regenerated dvd.iso with zfs packages in addon/* or we access the zfs packages while in the installer using qemu's virtfs to the host's packages directory. ZFS supports creating complex data storage configurations such as pools (similar to a volume group) backed by one or more of various kinds of virtual devices (similar to disks and raid arrays) and containing one or more datasets (similar to mounted filesystems, logical volume devices, or snapshots). But here, we keep it simple and will install on just a single disk device. On a real ZFS installation, users will typically want to use the ZFS raidz1 or raidz2 virtual device types for reliability against hard drive failures.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on host)&lt;br /&gt;
mkdir slackzfs&lt;br /&gt;
mv packages slackzfs/&lt;br /&gt;
cd slackzfs&lt;br /&gt;
qemu-img create disk1.raw 10G&lt;br /&gt;
ln -s ~/slackware64-current-install-dvd.iso dvd.iso&lt;br /&gt;
qemu-system-x86_64 \&lt;br /&gt;
 -no-quit \&lt;br /&gt;
 -no-shutdown \&lt;br /&gt;
 -boot order=cd,menu=on \&lt;br /&gt;
 -m 2G \&lt;br /&gt;
 -cpu host \&lt;br /&gt;
 -smp sockets=1,cores=4 \&lt;br /&gt;
 -net nic,model=rtl8139 -net user \&lt;br /&gt;
 -cdrom dvd.iso \&lt;br /&gt;
 -drive boot=on,format=raw,media=disk,cache=none,aio=native,if=scsi,bus=0,unit=0,file=disk1.raw \&lt;br /&gt;
 -virtfs local,path=./packages/,security_model=none,mount_tag=hostpackages&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The install-dvd should boot, and then begin installation steps on the installer command line:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on install-dvd)&lt;br /&gt;
# mount the install-dvd&lt;br /&gt;
mkdir /dvd&lt;br /&gt;
mount /dev/sr0 /dvd&lt;br /&gt;
&lt;br /&gt;
# install coreutils, which provides the &amp;quot;hostid&amp;quot; command needed to load the spl module&lt;br /&gt;
installpkg /dvd/slackware64/a/coreutils-8.17-x86_64-1.txz&lt;br /&gt;
&lt;br /&gt;
# install kmod package which includes &amp;quot;depmod&amp;quot; command and others&lt;br /&gt;
installpkg /dvd/slackware64/a/kmod-9-x86_64-2.txz&lt;br /&gt;
depmod&lt;br /&gt;
&lt;br /&gt;
# install the full kernel modules so you can load 9p filesystem and use it if you want&lt;br /&gt;
# .. you might keep the zfs modules packages off the dvd and use a plain slack dvd&lt;br /&gt;
installpkg /dvd/slackware64/a/kernel-modules-*.txz&lt;br /&gt;
depmod&lt;br /&gt;
&lt;br /&gt;
# install bash and libtermcap because udev rules in zfs use bash scripts&lt;br /&gt;
installpkg /dvd/slackware64/a/bash-*.txz&lt;br /&gt;
installpkg /dvd/slackware64/l/libtermcap-*.txz&lt;br /&gt;
&lt;br /&gt;
# install spl and zfs that you have copied into the mirror before running the DVD creation&lt;br /&gt;
installpkg /dvd/addon/spl-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /dvd/addon/zfs-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
&lt;br /&gt;
#Or:&lt;br /&gt;
mkdir /packages&lt;br /&gt;
find /lib/modules/ | grep 9p&lt;br /&gt;
lsmod&lt;br /&gt;
# check that 9p modules load, mainly 9pnet_virtio&lt;br /&gt;
modprobe 9pnet_virtio&lt;br /&gt;
mount hostpackages -t 9p -o trans=virtio /packages&lt;br /&gt;
installpkg /packages/spl-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /packages/zfs-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
modprobe zfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now zfs tools: &amp;quot;zpool&amp;quot; and &amp;quot;zfs&amp;quot; should work in the live installer.&lt;br /&gt;
On the installer, there can be trouble seeing man pages, so install:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
installpkg /dvd/slackware64/ap/man-*.txz&lt;br /&gt;
installpkg /dvd/slackware64/ap/groff-*.txz&lt;br /&gt;
installpkg /dvd/slackware64/a/less-*.txz&lt;br /&gt;
export MANPATH=/usr/man:/usr/share/man&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The manual pages should be readable:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
man zpool&lt;br /&gt;
man zfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After seeing the man pages, we should be fully ready to continue to setup on ZFS.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(still on install-dvd)&lt;br /&gt;
ls -l /dev/sd*&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Make sure the disk devices you expect are there. We'll use sda and make boot (/boot on /dev/sda1) and root (/ on /dev/sda2) partitions.&lt;br /&gt;
&lt;br /&gt;
First, some background info: A ZFS filesystem is not supported by lilo as the filesystem containing /boot, which holds lilo's 2nd stage and the linux kernel files. The on-disk format of a ZFS filesystem is often a complex raid configuration where even if lilo understood ZFS it would likely require /boot to reside in only certain simple ZFS configurations to be plainly readable to lilo. As things are, a linux root installed in a partition with ZFS filesystem needs /boot to be on another partition with a filesystem that lilo understands, such as ext4 fs. In addition, because the spl and zfs modules are not built into the kernel, and the zfs startup requires some configuration to mount the zfs root, an initial ram/root filesystem (initrd) is needed. The initrd is a gzip compressed cpio archive file that contains a small linux root operating system that is decompressed into a ramfs block device at boot up and takes initial control of the system. The initrd contains an init script that configures devices in devtmpfs mounted at /dev. For example, if using mdadm, lvm, luks, losetup, and now zfs, this init script runs all the commands to create or start these devices (one of which is the root device), mounts the root device, and then transfers system control to the init script in the mounted root filesystem. The ramfs-based root environment on the booted install-dvd or booted initrd image (in rescue command line) are small slackware installations that exist only in ram and are temporary, but while inside them you can install, upgrade, and remove slackware packages inside them using the regular package management tools; this allows you access to any kernel modules and programs as needed inside these ramfs root. Packages can be installed, upgraded, or removed permanantly in the initrd image file to manage the programs and modules required during the initrd boot stage. Also from within these ramfs initial root environments, once the root device is mounted, chroot can be used to work on the mounted root system as if it were booted; this allows one to fix problems that are occuring in the root fs init scripts that cause normal booting to fail, or to install a kernel and/or modules etc. Now on to partitioning:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cgdisk /dev/sda&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, cgdisk looks just like cfdisk, but it makes GPT partitions.&lt;br /&gt;
&lt;br /&gt;
Make a partition for /boot that is about 512MiB of whatever partition type you like (8300 &amp;quot;Linux filesystem&amp;quot; is fine), or make it type bf07 &amp;quot;Solaris Reserved 1&amp;quot; if you want ZFS to maybe see the disk as if it was given as a whole disk to ZFS. Make a second partition using the remaining space with partition type bf01 &amp;quot;Solaris ZFS&amp;quot;. Currently, when ZFSonLinux is given a whole disk device like /dev/sdb to use, it will automatically GPT partition it with a bf01 partition #1 that is the whole disk except a small 8MiB type bf07 partition #9 at the end of the disk (/dev/sdb1 and /dev/sb9). The small 8MiB type bf07 partition #9 is mostly likely reserved for use by bootloaders, like lilo, to have a /boot or other boot-related files kept there. For example, you might have /dev/sda that is totally non-ZFS for booting and /dev/sdb passed to ZFS whole where it automatically partitions sdb, but you can just use one disk here and make partitions. Lets use type 8300 for /boot to be sure nothing is confused:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
We'll continue with this partitioning (numbers are in MiB):&lt;br /&gt;
  0 to   4: unused&lt;br /&gt;
  4 to 516: /dev/sda1 512MiB, type 8300&lt;br /&gt;
516 to 520: unused&lt;br /&gt;
520 to -96: /dev/sda2, type bf01&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The -96 means to count from the end of the disk so that 96MiB will remain unused at the end of the disk.&lt;br /&gt;
&lt;br /&gt;
Create a zpool called zfs-root:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool create -m none zfs-root /dev/sda2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A zpool created like this, the normal way, is a kernel-internal block device that contains already a zfs filesystem. There is normally no entry in /dev for this device. However, it can still be referenced as a mountable device similar to how devtmpfs, proc, and sysfs are also kernel-internal mountable block devices. The -m option told zpool not to automatically mount it anywhere, and without -m the default is to always automatically mount to /zfs-root. These kinds of details are explained better elsewhere. For this situation, we do not want it automounted.&lt;br /&gt;
&lt;br /&gt;
Because a zpool itself is a useable zfs fs, it has a full set of zfs &amp;quot;properties&amp;quot; to set options about the filesystem, perhaps similar to tune2fs. The &amp;quot;mountpoint=&amp;lt;some place to mount&amp;gt;&amp;quot; is one such property. We want it set to the special value &amp;quot;none&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs get mountpoint zfs-root&lt;br /&gt;
zfs set mountpoint=none zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On creation, the zpool zfs-pool is &amp;quot;imported&amp;quot; and has a zpool status that can be viewed:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool status zfs-root&lt;br /&gt;
&lt;br /&gt;
zpool export zfs-root&lt;br /&gt;
zpool status zfs-root&lt;br /&gt;
# Now there is no status.&lt;br /&gt;
&lt;br /&gt;
zpool import zfs-root&lt;br /&gt;
# Now it is back.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When a zpool is imported, it has it's current configuration cached in a file /etc/zfs/zpool.cache. When a zpool is exported, then it's entries in the cache file are removed and the cache file is deleted if it becomes empty. So long as the zfs kernel modules see this cache file and valid cache data inside it, ZFS considers the described zpools in the cache file to be valid as imported zpools. If the zpool.cache file is present at the time the zfs modules are loaded, then there is no further need to use the import and export commands at system startup and shutdown. With root on a zfs, it is not possible to export the pool that root is on, but this is not a problem. At shutdown, the safe procedure will be to set the zfs-root property readonly=on and sync disks.&lt;br /&gt;
&lt;br /&gt;
To avoid the requirement to import the zfs-root pool at startup, keep a copy of the zpool.cache file to later copy onto the initrd image to read at modules load time to have the pool reactived without need to issue the import command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/zfs/zpool.cache /etc/zfs/zpool.cache-initrd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A zfs fs will not normally allow you to mount over any files. The mountpoint is expected to be an empty directory. Remove any junk files inside the installer's /mnt because zfs won't mount over any files:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rm /mnt/README&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The directory /mnt is where the slackware setup expects you to mount your root for installation.&lt;br /&gt;
&lt;br /&gt;
Controlling whether a zfs fs is to be mounted read-only or read-write is best managed by setting the readonly property while it is not yet mounted:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set readonly=on zfs-root&lt;br /&gt;
zfs set readonly=off zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Slackware expects root to be mounted readonly when /etc/rc.d/rc.S runs during normal startup, so later this is used to satisfy slackware's expectation to avoid rc.S complaining.&lt;br /&gt;
&lt;br /&gt;
The zfs-root can be mounted and unmounted in two different ways:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=/mnt zfs-root&lt;br /&gt;
zfs set mountpoint=none zfs-root&lt;br /&gt;
# or&lt;br /&gt;
mount zfs-root -t zfs /mnt&lt;br /&gt;
umount /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If it is already mounted and you want to change it to mount somewhere else, it is best to transition it to unmounted first, then mount it in the new place.&lt;br /&gt;
&lt;br /&gt;
The mount options &amp;lt;code&amp;gt;-o ro, -o rw, -o remount,ro, and -o remount,rw &amp;lt;/code&amp;gt; can also be used and will override &amp;lt;code&amp;gt;readonly=on|off&amp;lt;/code&amp;gt; property without altering the property value. This can be confusing until you are familiar with how to the methods of mounting interact.&lt;br /&gt;
&lt;br /&gt;
Now, let's continue some, and mount to /mnt using the current &amp;lt;code&amp;gt;readonly=off&amp;lt;/code&amp;gt; setting (rw mount):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=/mnt zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This method of mounting will show the most detailed mount options in /etc/mtab. They are the mount options that zfs thinks are proper, and they are probably what should be kept in /etc/fstab for zfs-root until we know better.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cat /etc/mtab &amp;gt;&amp;gt; /etc/fstab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now edit /etc/fstab to make sure it looks right, and remove the &amp;quot;rw&amp;quot; mount option, because we want to let it use a default for that, which will come from how we set the readonly= property most of the time. Unmount again:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=none zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mount again, now using all options from /etc/fstab:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It should be mounted at /mnt, and touch /mnt/t should allow you to make the file t. Then rm it: rm /mnt/t&lt;br /&gt;
For installation, we want to make sure it is mounted read-write. After installation, it should mount readonly inside the initrd.&lt;br /&gt;
&lt;br /&gt;
Sometimes there can be problems using the mount command, and then you can try it with the -i option:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 mount -i zfs-root &lt;br /&gt;
 mount -i zfs-root -t zfs /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
but, you should not have to use -i. When using -i makes it work, it performs an &amp;quot;internal-only&amp;quot; mount and does not use any mount.&amp;lt;fstype&amp;gt; helper scripts that might be on the system.&lt;br /&gt;
&lt;br /&gt;
Setup the /boot device:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkfs.ext4 /dev/sda1&lt;br /&gt;
mkdir /mnt/boot&lt;br /&gt;
mount /dev/sda1 /mnt/boot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We have both root and boot mounted where the slackware installer expects them. Unmount the dvd so setup can find it normally:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
umount /dev/sr0&lt;br /&gt;
setup&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the setup, skip straight to TARGET selection for the root device, but the setup doesn't see or understand the zfs-root, so it is not listed. This does not matter because we have mounted it already. Just skip down to a slot that say to continue, and continue on with setup. Because TARGET is skipped, you may not see the ADDITIONAL prompt (or if so, skip it too) where normally you give /dev/sda1 and have it mounted as /boot. This is also okay because we have mounted /mnt/boot already.&lt;br /&gt;
Because we did not give TARGET the root device or say what device /boot is on, the lilo installation will fail, or you can skip it. Otherwise, this installation process it normal.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
umount /dev/sr0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point, it is assumed that the setup has completed installing into /mnt. Congrats! You've installed slackware into a ZFS root!&lt;br /&gt;
&lt;br /&gt;
The next steps are to prepare to use &amp;quot;chroot /mnt&amp;quot; and finish up the configuration on the installed root system and then be able to reboot onto the completed installation. Before doing chroot, copy some files from the setup environment into /mnt.&lt;br /&gt;
&lt;br /&gt;
Copy the current installer /etc/fstab for later use inside the initrd. This fstab is what is proper inside the initrd, except remove option &amp;quot;rw&amp;quot; (if not done already).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/fstab /mnt/etc/fstab.initrd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The fstab.initrd will look like:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 proc /proc proc defaults 0 0&lt;br /&gt;
 zfs-root /mnt zfs defaults,atime,dev,exec,suid,xattr,nomand,zfsutil 0 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the initrd, we want zfs-root to mount to /mnt.&lt;br /&gt;
&lt;br /&gt;
Create /mnt/etc/fstab:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cat /etc/mtab &amp;gt;&amp;gt; /mnt/etc/fstab&lt;br /&gt;
vi /mnt/etc/fstab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using vi started above, edit /mnt/etc/fstab and make it have lines such as:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 zfs-root / zfs defaults,atime,dev,exec,suid,xattr,nomand,zfsutil 0 0&lt;br /&gt;
 /dev/sda1 /boot ext4 defaults 0 2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These two lines in &amp;lt;code&amp;gt;/mnt/etc/fstab&amp;lt;/code&amp;gt; are how the mounts should be looking when root is booted.&lt;br /&gt;
&lt;br /&gt;
Mount some special mounts before chroot:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount -t devtmpfs none /mnt/dev&lt;br /&gt;
mount -t proc none /mnt/proc&lt;br /&gt;
mount -t sysfs none /mnt/sys&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Make sure /boot is mounted:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount /dev/sda1 /mnt/boot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you had mounted a 9p fs share to access spl and zfs packages, then unmount that now:&lt;br /&gt;
umount /packages&lt;br /&gt;
&lt;br /&gt;
Ready, now:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chroot /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point, you should be on the installed system, and now try to configure mkinitrd and lilo. First, switch to use the generic kernel.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /boot&lt;br /&gt;
rm System.map config vmlinuz&lt;br /&gt;
ln -s System.map-gen* System.map&lt;br /&gt;
ln -s config-gen* config&lt;br /&gt;
ln -s vmlinuz-gen* vmlinuz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We install spl and zfs inside the live ramfs install-dvd environment, but not yet have we installed them into the root system:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount /dev/sr0 /mnt/cdrom&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /mnt/cdrom/addon/spl-*.txz&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /mnt/cdrom/addon/zfs-*.txz&lt;br /&gt;
depmod&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If instead, you used a 9p share to access the spl and zfs packages, then repeat that procedure here to install them onto the root system.&lt;br /&gt;
&lt;br /&gt;
Setup lilo: edit /etc/lilo.conf so it is like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  lba32&lt;br /&gt;
  append = &amp;quot; vt.default_utf8=1&amp;quot;&lt;br /&gt;
  boot = /dev/sda&lt;br /&gt;
  message = /boot/boot_message.txt&lt;br /&gt;
  prompt&lt;br /&gt;
  timeout = 1200&lt;br /&gt;
  change-rules&lt;br /&gt;
   reset&lt;br /&gt;
  vga = normal&lt;br /&gt;
  image = /boot/vmlinuz&lt;br /&gt;
   initrd = /boot/initrd.gz&lt;br /&gt;
   root = /dev/sda1&lt;br /&gt;
   label = vmlinuz&lt;br /&gt;
   read-only&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The line, root = /dev/sda1, is not really a true statement but lilo needs a device there that it at least understands. This root = line is a kernel parameter, but since the initrd is what is actually the root, initially, then the root = line is probably useless here. It might even be okay to just delete the root line.&lt;br /&gt;
&lt;br /&gt;
Setup mkinitrd:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/mkinitrd.conf.sample /etc/mkinitrd.conf&lt;br /&gt;
vi /etc/mkinitrd.conf&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Edit it to look like this (other defaults should be ok):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 MODULE_LIST=&amp;quot;sym53c8xx:ext4:8139cp:zfs:9p:9pnet_virtio&amp;quot;&lt;br /&gt;
 ROOTDEV=&amp;quot;zfs-root&amp;quot;&lt;br /&gt;
 ROOTFS=&amp;quot;zfs&amp;quot;&lt;br /&gt;
#Module sym53c8xx is the driver for qemu's if=scsi drive device.&lt;br /&gt;
#Module ext4 for /boot.&lt;br /&gt;
#Module 8139cp for eth0 net device.&lt;br /&gt;
#Module zfs for ZFSonLinux.&lt;br /&gt;
#Modules 9p and 9pnet_virtio for mounting qemu -virtfs mount_tag.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These 9p could be useful from the rescue command line inside the initrd to get needed files that are on the host.&lt;br /&gt;
&lt;br /&gt;
All dependent modules will also be included automatically into /boot/initrd-tree, which is packaged as /boot/initrd.gz. For example, to see the dependent modules of zfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
modprobe --show-depends zfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All listed modules will also be in the initrd. Now, make a /boot/initrd-tree that we can begin to look at and edit.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkinitrd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create an empty /etc/mtab or else zpool import fails (zfs expects /etc/mtab to exists already, it won't make it).&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
touch /boot/initrd-tree/etc/mtab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Copy in the fstab.initrd that was made earlier while on the installer. This provides all the mount options for a simple &amp;quot;mount zfs-root&amp;quot; onto /mnt.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/fstab.initrd /boot/initrd-tree/etc/fstab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More package installing! This time into an alternate root, the root of the initrd, /boot/initrd-tree. This is how you can put whatever packages you like into your initrd. These installations work independent of your normal installations. You can install, upgrade, and remove packages using an altroot:&lt;br /&gt;
&lt;br /&gt;
If spl and zfs are on your customized dvd:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/addon/spl-*.txz&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/addon/zfs-*.txz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Otherwise, repeat same procedure but you mount your 9p mount_tag and get them installed.&lt;br /&gt;
&lt;br /&gt;
More regular packages from the dvd:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/kmod-*.txz&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/coreutils-*.txz&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/gptfdisk-*.txz&lt;br /&gt;
&lt;br /&gt;
# A bash script is in /boot/initrd-tree/lib/udev/, so we need it or udev rules have problems:&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/bash-*.txz&lt;br /&gt;
# Bash needs this:&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/l/libtermcap-*.txz&lt;br /&gt;
&lt;br /&gt;
# Install net-tools to ensure that /etc/HOSTNAME, /etc/hosts, and potentially, /etc/hostid are handled proper.&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/n/net-tools-*.txz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When ZFS has to import a zpool while the initrd is running (this can be avoided by not exporting and keeping /etc/zfs/zpool.cache inside the initrd), ZFS will refuse to import a pool if it thinks that the pool may be in use by another system. ZFS was designed for network attached storage where multiple hosts might have access to the same disks but ZFS cannot support two hosts importing and using a ZFS pool at the same time. ZFS checks a value called &amp;quot;hostid&amp;quot; to determine this kind of conflict, and it can be a tricky issue with an initrd boot process. The value of hostid is returned by a system call, the gethostid() function or the hostid command. This function will return the hostid from /etc/hostid if that file exists and has a valid id in it, or else if the file doesn't exist it obtains a hostid number based on the hostname and ip address address assigned to hostname found in /etc/hosts or in DNS. If the hostid trying to import a pool is not the same as the hostid that imported it last time, ZFS will not import the pool unless &amp;quot;zpool import -f zfs-root&amp;quot; is used to force the import. This force option is not recommended to use, so it is best to configure your initrd with matching /etc/HOSTNAME and /etc/hosts as on the root installation and ensure what your system looks like on the initrd matches the booted root system.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Edit /boot/initrd-tree/init (this is the main system startup script on the initrd, responsibe for configuring your block devices and mount your root at /mnt and then booting root):&lt;br /&gt;
&lt;br /&gt;
Inside init, right near the top of the file after the PATH= line, add this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/bin/hostname -F /etc/HOSTNAME&lt;br /&gt;
/bin/hostname $( /bin/hostname -s )&lt;br /&gt;
#/sbin/chhostid 13371400&lt;br /&gt;
# you can make your hostid whatever, but this didn't work right with ZFS, so it is commented out&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This sets the name reported by the hostname command (the default is &amp;quot;darkstar&amp;quot;) to be what is contained in /etc/HOSTNAME. The hostname is modified in the next line to be the short name. These lines will help ZFS to properly identify your host when importing pools.&lt;br /&gt;
&lt;br /&gt;
Inside init, right after it runs &amp;quot;mdadm&amp;quot; commands as used for raid setup, we like it to setup ZFS, so add:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/sbin/zpool import zfs-root&lt;br /&gt;
/sbin/zfs set readonly=on zfs-root&lt;br /&gt;
mount zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Inside init, close to the bottom, where it &amp;quot;Switch to real root partition&amp;quot;, comment out 1 line that normally does the mount:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# mount -o ro -t $ROOTFS $ROOTDEV /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
We have already mounted, and we don't want to use any mount options because we should be using a properly set /etc/fstab inside the initrd for zfs-root mount options onto /mnt.&lt;br /&gt;
&lt;br /&gt;
During a normal startup we want a readonly mount.&lt;br /&gt;
&lt;br /&gt;
Note: we are going to setup with using zpool import and export and startup and shutdown. But later, you can experiment having /etc/zfs/zpool.cache stored in the initrd and commenting out zpool import/export lines.&lt;br /&gt;
&lt;br /&gt;
As mentioned, the import command may sometimes fail, and give the message: &amp;quot;pool may be in use from another system&amp;quot;. This is nothing serious in this test situation. When this happens, root will not be mounted to /mnt and the init script will detect this and drop you into a rescue command line where you may manually &amp;quot;import -f&amp;quot; then &amp;quot;mount zfs-root&amp;quot; and then &amp;quot;exit&amp;quot; to continue on to booting the root.&lt;br /&gt;
&lt;br /&gt;
To avoid this problem we copy some files in (assuming you first edit /etc/HOSTNAME to hold the hostname you like to see on your command prompts, and edited /etc/hosts to have hostname on your loopback or other local ip address):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/HOSTNAME /etc/hosts /boot/initrd-tree/etc&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The value reported by the hostid command is what ZFS sees as your hostid. In this setup so far, the value is based on the ip found assigned to your hostname. If your hostname is on the line in /etc/hosts for ip address 192.168.13.37, then your hostid will be hex numbers C0.A8.0D.25 rearranged as A8C0250D (pairs of bytes are swapped). That is ip-based hostid value, a 32bit hexadecimal number. This has to be the same each boot or import will need a -f option to force it. Simply setting the hostid using the system call sethostid() which writes a /etc/hostid file doesn't seem to agree with ZFS and you'd have to force the import, so this setup now assumes that you do not have or have deleted /etc/hostid.&lt;br /&gt;
&lt;br /&gt;
You can sometimes see what has been happening to a zpool by using the command &amp;quot;zpool history -li zfs-root&amp;quot; to see a log of commands.&lt;br /&gt;
&lt;br /&gt;
Once again, you can do away with the import and export commands by trying to have /etc/zfs/zpool.cache inside your initrd. To create zpool.cache, while on the installer or in the rescue shell of the initrd (at lilo &amp;quot;boot: vmlinuz rescue&amp;quot;), import only the pool for the root fs with mountpoint=none and readonly=on properties set and while it is not mounted:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on installer or initrd rescue shell)&lt;br /&gt;
cp /etc/zfs/zpool.cache /etc/zfs/zpool.cache-initrd&lt;br /&gt;
zfs set readonly=off zfs-root&lt;br /&gt;
mount zfs-pool&lt;br /&gt;
cp /etc/zfs/zpool.cache-initrd /mnt/etc/zfs/&lt;br /&gt;
cp /mnt/etc/zfs/zpool.cache-initrd /mnt/boot/initrd-tree/etc/zfs/zpool.cache&lt;br /&gt;
umount /mnt&lt;br /&gt;
zfs set readonly=on zfs-root&lt;br /&gt;
#mount zfs-root&lt;br /&gt;
#exit (to continue boot process onto rootfs mounted at /mnt)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, doing this zpool.cache approach is not necessary, and some talk suggests this is deprecated or discouraged. Although /etc/hostid setup fails to import without -f option, ip-based (hosts|dns) hostid works on booting and import works without -f option and may be the more proper way to do shutdown and startup rather than using a cache file which could be come invalid and cause a problem that is difficult to understand. The contents and exact function of the cache file are not well understood by many people.&lt;br /&gt;
&lt;br /&gt;
Save /boot/initrd-tree/init and exit.&lt;br /&gt;
&lt;br /&gt;
Now, edit /etc/rc.d/rc.S and rc.6 to understand how to &amp;quot;remount&amp;quot; rw or ro as a readonly property changes&lt;br /&gt;
&lt;br /&gt;
In /etc/rc.d/rc.S:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# comment out the line&lt;br /&gt;
#    /sbin/mount -w -v -n -o remount /&lt;br /&gt;
#add the line&lt;br /&gt;
     /sbin/zfs set readonly=off zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In /etc/rc.d/rc.6&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# comment out the line&lt;br /&gt;
#    /bin/mount -v -n -o remount,ro /&lt;br /&gt;
#add the line&lt;br /&gt;
     /sbin/zfs set readonly=on zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In /etc/rc.d/rc.6, near the bottom just before poweroff|reboot, add the following block of lines:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
########################&lt;br /&gt;
# Try to export zfs-root&lt;br /&gt;
/sbin/zpool export zfs-root&lt;br /&gt;
if [ $? -gt 0 ] ; then&lt;br /&gt;
 echo &amp;quot;ZFS export failed.&amp;quot;&lt;br /&gt;
 echo &amp;quot;Notice: if root fs is busy, then this is normal fail.&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;ZFS export successful.&amp;quot;&lt;br /&gt;
 echo &amp;quot;Warning: successful export is abnormal for root fs.&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
/bin/sleep 5&lt;br /&gt;
########################&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
For ZFS, you cannot run fsck on it. It doesn't support that kind of filesystem checks. The rc.S script will complain a lot in many places about not being about to run fsck on the zfs-root. To disable all attempts of run fsck, we can simple create a file that acts as a flag in /etc/rc.d/rc.S to tell it to skip fsck:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
touch /etc/fastboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This fastboot file is normally a run-once temporary file, and it is deleted near the bottom inside rc.S. Edit rc.S and stop it from deleting /etc/fastboot. We would like it to always skip all fsck. Edit /etc/rc.d/rc.S, and find the &amp;quot;rm&amp;quot; of fastboot, and do not have it removed!&lt;br /&gt;
&lt;br /&gt;
We are getting close, and have finished all editing, so make /boot/initrd.gz and install lilo:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkinitrd -F&lt;br /&gt;
lilo&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We finished! All that's left to do is clean up.&lt;br /&gt;
&lt;br /&gt;
Exit the chroot.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
exit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Try to mount everything:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
umount /mnt/proc&lt;br /&gt;
umount /mnt/sys&lt;br /&gt;
umount /mnt/dev&lt;br /&gt;
umount /mnt/boot&lt;br /&gt;
umount /mnt/mnt/cdrom&lt;br /&gt;
umount /mnt/root/packages&lt;br /&gt;
umount /mnt&lt;br /&gt;
zpool export zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note, that export stops a pool and frees devices, while import binds devices and starts a pool. It is somewhat like mdadm -A -s and mdadm -S -s, while /etc/zfs/zpool.cache might be somewhat like mdadm -E -s &amp;gt; /etc/mdadm.conf.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Remove the DVD or change boot order&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When you reboot, if all is good, you are booting properly onto a slackware installed on a ZFS root! Congrat!&lt;br /&gt;
&lt;br /&gt;
If this seem to go badly, and this might happen if the import fails as explain some before, then you will be on the initrd's rescue command line just before the part in it's init where it wants to mount and switch_root to boot your root. Instead, you typically got commands like this to do:&lt;br /&gt;
&lt;br /&gt;
If you get dumped to rescue because import will not work and requires -f (force), then:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 zpool import -f zfs-root&lt;br /&gt;
 zpool export    zfs-root&lt;br /&gt;
 zpool import    zfs-root&lt;br /&gt;
 mount zfs-root&lt;br /&gt;
 exit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This can happen if hostname, hostid, or uname changes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you get into a jam and need to boot into the initrd and skip zfs import etc, use the lilo prompt (or, boot the install-dvd):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
boot: vmlinuz rescue&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the rescue mode of the initrd, after you have mounted your root as readonly=on to /mnt, then exit to continue.&lt;br /&gt;
&lt;br /&gt;
In other emergency modes, you might need to run the lines at end of init starting from: &amp;lt;code&amp;gt;udevadm info --cleanup-db; udevadm control --exit&amp;lt;/code&amp;gt;&lt;br /&gt;
If you don't run those udevadm commands, two runs of udevd fight each other and it is slow; you have to wait 2 minutes twice for timeouts (4 minutes).&lt;br /&gt;
The last line is run is: &amp;lt;code&amp;gt;exec switch_root /mnt /sbin/init 1&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Warning... this switch_root command is kind of dangerous, so read the manual page about it.&lt;br /&gt;
From what I can tell, everything except the new root &amp;quot;/mnt&amp;quot; is deleted, so you are giving a command that says what NOT to delete!&lt;br /&gt;
Make sure nothing got mounted outside of &amp;quot;/mnt&amp;quot; before you run it.&lt;br /&gt;
&lt;br /&gt;
Also, in rescue or anytime you have finished making changes and are about to reboot in some abnormal mode, first run:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set readonly=on zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A bug in unpatched grep 2.13 build 1, found slackware 14.0rc1, causes problems when processing files stored on ZFS but rarely shows problems on other filesystems; the bug does not handle sparse files on zfs and btrfs correctly and results in chaos with slackpkg, compiling kernel modules, and possibly many other things. You must downgrade grep to 2.12 or use the patched grep 2.13 build 2 in slackware 14.0rc2 or later.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Upgrading.&lt;br /&gt;
&lt;br /&gt;
From time to time you will want to upgrade the kernel to the new kernel in slackware64-current or in patches/. This will also necessitate a rebuilt and reinstall or upgrade of spl and zfs. Below is an example of when both kernel and spl/zfs are being upgraded, to give an idea of the process:&lt;br /&gt;
&lt;br /&gt;
Using slackpkg, that is configured to use your local slackware mirror is a good option but you can also configure it to use a remote mirror.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slackpkg upgrade-all&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Assume slackpkg just upgraded your kernel, kernel-modules, and kernel-headers.&lt;br /&gt;
&lt;br /&gt;
Note: the first time you try to run on kernel-generic, setup kernel-huge in lilo as 2nd choice. Huge has all the hard drive controllers builtin, but generic has them all as modules. For example, run &amp;quot;modinfo mptsas&amp;quot; to see module options (maybe you have a LSISAS1068) for your hard drive controller. Add file /etc/modprobe.d/mptsas.conf to set options you want with a line: options mptsas ... Do this for all the device driver modules for your hardware. Do this setup while you are on the huge kernel, then setup to reboot to generic. Include all these modules you need into mkinitrd.conf MODULES_LIST. Check that /boot/initrd-tree/etc/modprobe.d/ has a copy of your customized module conf files because it is on the initrd where the modules will load and use the conf files. mkinitrd probably copies all /etc/modprobe.d/* files into the initrd-tree, but check it. Pay attention to /etc/modprobe.d/README and /lib/modprobe.d/* /lib/modprobe.d/* maybe not copied to initrd-tree but you might want to copy some of it into your initrd-tree yourself to use them.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Check that upgraded kernel-source is symlinked to /usr/src/linux (zfs build looks here). SQL/ZFS modules will install to the kernel version in /lib/modules/&amp;lt;/usr/src/linux kernel version&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /usr/local/src&lt;br /&gt;
tar xvzf ~/spl-*.tar.gz&lt;br /&gt;
tar xvzf ~/zfs-*.tar.gz&lt;br /&gt;
&lt;br /&gt;
###### upgrade spl 1st&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-*&lt;br /&gt;
./configure --prefix=/ --libexecdir=/usr/libexec --libdir=/lib64 --includedir=/usr/include --datarootdir=/usr/share&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=/usr/local/src/install&lt;br /&gt;
cd ../install&lt;br /&gt;
makepkg ../spl-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
upgradepkg spl-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
depmod &amp;lt;new kernel version&amp;gt;     (e.g. depmod 3.2.27, if .27 is new kernel upgrade; you currently run on old, maybe .26)&lt;br /&gt;
# this builds the module dependencies in /lib/modules/&amp;lt;new kernel version&amp;gt;&lt;br /&gt;
###### upgrade zfs 2nd&lt;br /&gt;
mkdir install&lt;br /&gt;
cd zfs-*&lt;br /&gt;
./configure --prefix=/ --libexecdir=/usr/libexec --libdir=/lib64 --includedir=/usr/include --datarootdir=/usr/share&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=/usr/local/src/install&lt;br /&gt;
cd ../install&lt;br /&gt;
makepkg ../zfs-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
upgradepkg zfs-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
depmod 3.2.27&lt;br /&gt;
####### upgrade spl/zfs inside altroot /boot/initrd-tree&lt;br /&gt;
ROOT=/boot/initrd-tree upgradepkg spl-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
ROOT=/boot/initrd-tree upgradepkg zfs-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
# note: ROOT is an environment variable, not a command line option to upgradepkg!&lt;br /&gt;
# note: do not worry about depmod inside initrd-tree, mkinitrd -F actually installs the modules&lt;br /&gt;
# note: this upgrade here is really to just upgrade the command line tools zpool, zfs etc&lt;br /&gt;
####### rebuild /boot/initrd.gz and reinstall lilo&lt;br /&gt;
vi /etc/mkinitrd.conf&lt;br /&gt;
# temporarily set KERNEL_VERSION to new version, but you are still running on old version&lt;br /&gt;
mkinitrd -F&lt;br /&gt;
lilo&lt;br /&gt;
vi /etc/mkinitrd.conf&lt;br /&gt;
# you can set KERNEL_VERSION back to $(uname r) now&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After reboot you can remove any old /lib/modules/&amp;lt;old kernel version&amp;gt; directory.&lt;br /&gt;
&lt;br /&gt;
More about /etc/hostid. If you want to experiment changing your /etc/hostid file and seeing if you can use it and make zpool import work normally, here is a tool that might be helpful:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/* software product name: foobarz-chhostid.c&lt;br /&gt;
 * suggested binary name: chhostid&lt;br /&gt;
 * license              : BSD&lt;br /&gt;
 * license text:&lt;br /&gt;
Copyright (c) 2012, foobarz&lt;br /&gt;
All rights reserved.&lt;br /&gt;
&lt;br /&gt;
Redistribution and use in source and binary forms, with or without&lt;br /&gt;
modification, are permitted provided that the following conditions are met:&lt;br /&gt;
    * Redistributions of source code must retain the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer.&lt;br /&gt;
    * Redistributions in binary form must reproduce the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer in the&lt;br /&gt;
      documentation and/or other materials provided with the distribution.&lt;br /&gt;
    * Neither the name of the &amp;lt;organization&amp;gt; nor the&lt;br /&gt;
      names of its contributors may be used to endorse or promote products&lt;br /&gt;
      derived from this software without specific prior written permission.&lt;br /&gt;
&lt;br /&gt;
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &amp;quot;AS IS&amp;quot; AND&lt;br /&gt;
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED&lt;br /&gt;
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE&lt;br /&gt;
DISCLAIMED. IN NO EVENT SHALL &amp;lt;COPYRIGHT HOLDER&amp;gt; BE LIABLE FOR ANY&lt;br /&gt;
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES&lt;br /&gt;
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;&lt;br /&gt;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND&lt;br /&gt;
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT&lt;br /&gt;
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS&lt;br /&gt;
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#define FOOBARZ_CHHOSTID_VERSION &amp;quot;1.0.5&amp;quot;&lt;br /&gt;
#include &amp;lt;sys/socket.h&amp;gt;&lt;br /&gt;
#include &amp;lt;netinet/in.h&amp;gt;&lt;br /&gt;
#include &amp;lt;arpa/inet.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;endian.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sysexits.h&amp;gt;&lt;br /&gt;
/* note: if include stdlib then sethostid fails even with _BSD_SOURCE defined */&lt;br /&gt;
&lt;br /&gt;
long swapbytes(long abcd) {&lt;br /&gt;
  long badc;&lt;br /&gt;
  unsigned char addr_a;&lt;br /&gt;
  unsigned char addr_b;&lt;br /&gt;
  unsigned char addr_c;&lt;br /&gt;
  unsigned char addr_d;&lt;br /&gt;
  addr_a = (unsigned char) (abcd &amp;gt;&amp;gt; 24);&lt;br /&gt;
  addr_b = (unsigned char) (abcd &amp;gt;&amp;gt; 16);&lt;br /&gt;
  addr_c = (unsigned char) (abcd &amp;gt;&amp;gt;  8);&lt;br /&gt;
  addr_d = (unsigned char) (abcd);&lt;br /&gt;
  return badc = ( (addr_b &amp;lt;&amp;lt; 24) | (addr_a &amp;lt;&amp;lt; 16) | (addr_d &amp;lt;&amp;lt; 8) | addr_c );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[])&lt;br /&gt;
{&lt;br /&gt;
 long newhostid;&lt;br /&gt;
 struct in_addr addr;&lt;br /&gt;
 char* invalidchar;&lt;br /&gt;
&lt;br /&gt;
 /*********** check command line */&lt;br /&gt;
 if(!( ((argc==3) &amp;amp;&amp;amp; ( (strcmp(argv[1],&amp;quot;-h&amp;quot;)==0) ||&lt;br /&gt;
                       (strcmp(argv[1],&amp;quot;-i&amp;quot;)==0) ||&lt;br /&gt;
                       (strcmp(argv[1],&amp;quot;-l&amp;quot;)==0) )) ||&lt;br /&gt;
       ((argc==2) &amp;amp;&amp;amp; ( (strcmp(argv[1],&amp;quot;-s&amp;quot;)==0) ))&lt;br /&gt;
     )&lt;br /&gt;
   ) {&lt;br /&gt;
                 /*01234567890123456789012345678901234567890123456789012345678901234567890123456789*/&lt;br /&gt;
  fprintf(stderr, &amp;quot;foobarz-chhostid, version %s. License: BSD.\n&amp;quot;, FOOBARZ_CHHOSTID_VERSION);&lt;br /&gt;
  fprintf(stderr, &amp;quot;foobarz-chhostid, (c) 2012, foobarz; all rights reserved.\n&amp;quot;);&lt;br /&gt;
  fprintf(stderr, &amp;quot;descr: %s change system hostid (in /etc/hostid).\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -h &amp;lt;new hostid&amp;gt;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        Change system hostid to &amp;lt;new hostid&amp;gt;;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        &amp;lt;new hostid&amp;gt; must be 32bit 8-digit hex number xxxxxxxx, each x in 0-f|F.\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        The ip corresponding to &amp;lt;new hostid&amp;gt; is also listed for reference only.\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -i &amp;lt;dotted ip address&amp;gt;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        Change system hostid to hostid corresponding to &amp;lt;dotted ip address&amp;gt;.\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -l &amp;lt;dotted ip address&amp;gt;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        List hostid corresponding to &amp;lt;dotted ip address&amp;gt;;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        no change to system hostid.\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -s\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        List current system hostid and corresponding ip address;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        no change to system hostid.\n&amp;quot;, argv[0]);&lt;br /&gt;
  return EX_USAGE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -h &amp;lt;hostid&amp;gt; */&lt;br /&gt;
 if( strcmp(argv[1],&amp;quot;-h&amp;quot;) == 0 ) {&lt;br /&gt;
  if(strlen(argv[2]) != 8) { fprintf(stderr, &amp;quot;new hostid must be 8-digit hex number xxxxxxxx, each x in 0-f|F\n&amp;quot;); return EX_USAGE; }&lt;br /&gt;
&lt;br /&gt;
  newhostid = strtol(argv[2],&amp;amp;invalidchar,16);&lt;br /&gt;
  if( newhostid==LONG_MIN ) { perror(&amp;quot;strtol (underflow)&amp;quot;); return EX_USAGE; }&lt;br /&gt;
  if( newhostid==LONG_MAX ) { perror(&amp;quot;strtol (overflow)&amp;quot;); return EX_USAGE; }&lt;br /&gt;
  if(*invalidchar != '\0') { fprintf(stderr, &amp;quot;invalid hex number %c; must be in 0-f|F\n&amp;quot;, *invalidchar); return EX_USAGE; }&lt;br /&gt;
&lt;br /&gt;
  if( sethostid(newhostid) != 0 ) {&lt;br /&gt;
   perror(&amp;quot;sethostid&amp;quot;);&lt;br /&gt;
   if( errno == EPERM ) return EX_NOPERM;&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
  }&lt;br /&gt;
  printf(&amp;quot;System hostid changed.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  /* hostid is a byte-swapped ip like b.a.d.c */&lt;br /&gt;
  /* get ip by swapping to correct order a.b.c.d and save into in_addr struct */&lt;br /&gt;
  addr.s_addr = htonl(swapbytes(newhostid));&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -i or -l, then find hostid for &amp;lt;dotted ip address&amp;gt; */&lt;br /&gt;
 if( (strcmp(argv[1],&amp;quot;-i&amp;quot;) == 0) || (strcmp(argv[1],&amp;quot;-l&amp;quot;) == 0) ) {&lt;br /&gt;
  if( inet_aton(argv[2], &amp;amp;addr) == 0 ) { fprintf(stderr, &amp;quot;inet_aton: invalid dotted ip address: %s\n&amp;quot;, argv[2]); return EX_USAGE; }&lt;br /&gt;
&lt;br /&gt;
  /* hostid is a byte-swapped ip like b.a.d.c */&lt;br /&gt;
  /* get hostid by swapping bytes of ip a.b.c.d */&lt;br /&gt;
  newhostid = swapbytes(ntohl(addr.s_addr));&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -i &amp;lt;dotted ip address&amp;gt; */&lt;br /&gt;
 if( strcmp(argv[1],&amp;quot;-i&amp;quot;) == 0 ) {&lt;br /&gt;
  if( sethostid(newhostid) != 0 ) {&lt;br /&gt;
   perror(&amp;quot;sethostid&amp;quot;);&lt;br /&gt;
   if( errno == EPERM ) return EX_NOPERM;&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
  }&lt;br /&gt;
  printf(&amp;quot;System hostid changed.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -l &amp;lt;dotted ip address&amp;gt; */&lt;br /&gt;
 if(strcmp(argv[1],&amp;quot;-l&amp;quot;) == 0 ) {&lt;br /&gt;
   printf(&amp;quot;Listing hostid for ip. (no changes)\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -s */&lt;br /&gt;
 if(strcmp(argv[1],&amp;quot;-s&amp;quot;) == 0 ) {&lt;br /&gt;
   /* see if /etc/hostid exists and print info */&lt;br /&gt;
   if( access(&amp;quot;/etc/hostid&amp;quot;, F_OK) != 0 ) {&lt;br /&gt;
     printf(&amp;quot;Notice: /etc/hostid does not exist.\n&amp;quot;);&lt;br /&gt;
     perror(&amp;quot;Reason&amp;quot;);&lt;br /&gt;
     printf(&amp;quot;System hostid derived from ip of hostname found in hosts file or dns.\n&amp;quot;);&lt;br /&gt;
   } else {&lt;br /&gt;
     printf(&amp;quot;Notice: /etc/hostid exists.\n&amp;quot;&lt;br /&gt;
            &amp;quot;System hostid is obtained from hostid file.\n&amp;quot;);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
  errno=0;&lt;br /&gt;
  newhostid = gethostid();&lt;br /&gt;
  if(errno!=0) { perror(&amp;quot;gethostid&amp;quot;); return EX_UNAVAILABLE; }&lt;br /&gt;
&lt;br /&gt;
  /* hostid is a byte-swapped ip like b.a.d.c */&lt;br /&gt;
  /* get ip by swapping to correct order a.b.c.d and save into in_addr struct */&lt;br /&gt;
  addr.s_addr = htonl(swapbytes(newhostid));&lt;br /&gt;
&lt;br /&gt;
  printf(&amp;quot;Listing current system hostid. (no changes)\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** print info and return */&lt;br /&gt;
 printf(&amp;quot;ip dot: %s\n&amp;quot;, inet_ntoa(addr) );&lt;br /&gt;
 printf(&amp;quot;ip hex: %.8x\n&amp;quot;, ntohl(addr.s_addr) );&lt;br /&gt;
 printf(&amp;quot;hostid: %.8x\n&amp;quot;, newhostid );&lt;br /&gt;
 return EX_OK;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</description>
			<pubDate>Sat, 18 Aug 2012 19:38:56 GMT</pubDate>
			<dc:creator>Foobarz</dc:creator>
			<comments>https://www.slackwiki.com/Talk:ZFS_root</comments>
		</item>
		<item>
			<title>ZFS root</title>
			<link>https://www.slackwiki.com/index.php?title=ZFS_root&amp;diff=736</link>
			<guid isPermaLink="false">https://www.slackwiki.com/index.php?title=ZFS_root&amp;diff=736</guid>
			<description>&lt;p&gt;Foobarz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;If you have heard about the ZFS filesystem and you're curious to try it out, then you can try it on slackware64, thanks to the ZFSonLinux.org project!&lt;br /&gt;
&lt;br /&gt;
In this article, an example is shown of how to install slackware64 14.0 onto a ZFS root filesystem (zfs-root) inside a QEMU virtual machine for testing purposes. It is recommended that you install qemu and learn how to use it to test a ZFS installation before you decide to use it on real hardware. A slackbuild for qemu can be found on slackbuilds.org. If you have a processor that supports Intel VT-x or AMD AMD-V virtualization acceleration (try modprobe kvm-intel or modprobe kvm-amd), then use the slackbuild for qemu-kvm.&lt;br /&gt;
&lt;br /&gt;
This article isn't going to go into any detail on actually using ZFS or what kinds of installation options and settings might be optimal. This article just presents an example of how to get started with ZFS on slackware.&lt;br /&gt;
&lt;br /&gt;
At this time of writing, ZFSonLinux is at &amp;quot;release candidate&amp;quot; (version 0.6.0-rc10) development stage, and many issues can occur. See the ZFSonLinux.org web site and the issues tracker for an idea about the current issues. There is also an irc channel on irc.freenode.net, #zfsonlinux, for discussion of issues and help.&lt;br /&gt;
&lt;br /&gt;
Although not required, it is helpful to keep a local mirror of slackware64 on your system. Having a local mirror makes it easier to upgrade to slackware64-current or to patches/* in a release. To help manage your own local slackware mirror and generate your own CD and DVD slackware installers, see http://alien.slackbook.org/blog/local-slackware-mirror/.&lt;br /&gt;
&lt;br /&gt;
In this article, we use a slackware64-current DVD image file as the qemu cdrom device media for the installation of the slackware guest. This was tested at slackware64-current = slackware64 14.0rc2. You can obtain a slackware DVD image using a torrent, buy the DVD from slackware.com, or generate your own DVD image file using the mirror script. For an actual DVD, you can pass your DVD device (e.g., /dev/sr0) as the qemu cdrom device. For a DVD image file, pass the image file as the qemu cdrom device.&lt;br /&gt;
&lt;br /&gt;
The ZFSonLinux packages are not included in slackware at this time. There are two packages involved: spl and zfs. The first, spl, is &amp;quot;Solaris Porting Layer&amp;quot; and must be installed on the system before zfs can be compiled. The source code tarballs for these are at ZFSonLinux.org. At this time of writing, they are spl-0.6.0-rc10.tar.gz and zfs-0.6.0-rc10.tar.gz.&lt;br /&gt;
&lt;br /&gt;
At this point, it is assumed you have qemu installed, have obtained a slackware64-current/14.0 DVD, and have downloaded spl and zfs tarballs to your host system. The first step now is, if your host is not slackware64-current/14.0 (the same as the guest will be), then you need to create a minimal development slackware64 guest system in qemu for just the purpose of compiling and packaging the spl and zfs slackware packages and transferring a copy of these packages back onto your host system to use later to install onto zfs during the slackware install process.&lt;br /&gt;
&lt;br /&gt;
From this point onward, instructions become a bit terse and mostly limited to examples of the commands you might use to complete tasks. You are encouraged to examine what each command does by reading the command's man pages. For example, the command &amp;quot;man qemu&amp;quot; can show you most of what you need to know about running qemu on the command line.&lt;br /&gt;
&lt;br /&gt;
So, here's an example of how you might build the spl and zfs packages, starting in your home directory:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on host)&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir qemu&lt;br /&gt;
cd qemu&lt;br /&gt;
mkdir slackdevel&lt;br /&gt;
cd slackdevel&lt;br /&gt;
mkdir packages&lt;br /&gt;
cp ~/spl-*.tar.gz packages&lt;br /&gt;
cp ~/zfs-*.tar.gz packages&lt;br /&gt;
qemu-img create disk1.raw 10G&lt;br /&gt;
ln -s ~/slackware64-current-install-dvd.iso dvd.iso&lt;br /&gt;
qemu-system-x86_64 \&lt;br /&gt;
 -no-quit \&lt;br /&gt;
 -no-shutdown \&lt;br /&gt;
 -boot order=cd,menu=on \&lt;br /&gt;
 -m 2G \&lt;br /&gt;
 -cpu host \&lt;br /&gt;
 -smp sockets=1,cores=4 \&lt;br /&gt;
 -net nic,model=rtl8139 -net user \&lt;br /&gt;
 -cdrom dvd.iso \&lt;br /&gt;
 -drive boot=on,format=raw,media=disk,cache=none,aio=native,if=scsi,bus=0,unit=0,file=disk1.raw \&lt;br /&gt;
 -virtfs local,path=./packages/,security_model=none,mount_tag=hostpackages&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When you need to change boot to cd or disk, add or remove &amp;quot;boot=on&amp;quot;, or change &amp;quot;order=dc&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Qemu should boot into the install-dvd, and now perform a very ordinary slackware64 install onto /dev/sda. Install d package set and most others, but package sets x, kde, xfce not really needed.&lt;br /&gt;
&lt;br /&gt;
First note: examples here use tools from the gptfdisk package (gdisk, sgdisk, cgdisk) to partition the disk with GUID partition table (GPT) format. GPT might not be too familiar to everyone, who mostly have only used MBR partitions with fdisk. In the slackware installations this author has tested in qemu, using GPT partitions has caused no problems with lilo or other tools used in slackware. GPT disk labels support creating up to 128 partitions and support disks larger than 2TB (the limit of MBR fdisk). LILO installs into the first 440 bytes on /dev/sda, inside a GPT &amp;quot;protective MBR&amp;quot; that serves to provide compatibility with MBR bootloaders like lilo. LILO uses LBA32 sector addressing and can see all 512-byte sectors side the first 2TB of a disk. So long as the /boot partition is within the first 2TB of a disk, lilo can work on a disk larger than 2TB. Unlike the common default of fdisk to start the first partition at sector 63, which is not aligned with the 4KiB sector size of Advanced Format hard disks, gdisk's default is to start partitions at 2048 sector (1MiB) boundaries which are also 4KiB aligned. Using gdisk GPT works on all disks and is compatible with using Advanced Format hard disks larger than 2TB. More information about GPT disk label format can be found on wikipedia.org. For those that have used grub instead of lilo, grub installation is different with GPT than with MBR, and grub requires a GPT partition of type grub-bios or 0xEF02 &amp;quot;BIOS Boot Partition&amp;quot; of about 8MiB where it can install it's additional bootloader stages because grub cannot embed in sectors 1-62 on GPT where GPT keeps it's partition tables. On MBR, sectors 1-62 were normally reserved space for bootloaders to keep a 2nd stage.&lt;br /&gt;
&lt;br /&gt;
For this purpose of development guest, just create a simple 1-partition system, /dev/sda1, and do a simple slackware install on it. Don't bother with swap or separate /boot unless you want to:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on install-dvd)&lt;br /&gt;
cgdisk /dev/sda&lt;br /&gt;
setup&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When this simple development guest boots, login as root, and continue:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on qemu guest)&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir packages&lt;br /&gt;
mount hostpackages -t 9p -o trans=virtio packages&lt;br /&gt;
echo --prefix=/ --libexecdir=/usr/libexec --libdir=/lib64 --includedir=/usr/include --datarootdir=/usr/share &amp;gt; configure-options&lt;br /&gt;
mkdir src&lt;br /&gt;
cd src&lt;br /&gt;
&lt;br /&gt;
mkdir install&lt;br /&gt;
tar xvzf ~/packages/spl-*.tar.gz&lt;br /&gt;
cd spl-*&lt;br /&gt;
./configure $( cat ~/configure-options )&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../spl-&amp;lt;version&amp;gt;_&amp;lt;kernel_version&amp;gt;-x86_64-&amp;lt;build_id&amp;gt;.txz&lt;br /&gt;
(e.g., makepkg ../spl-0.6.0rc10_3.2.27-x86_64-1root.txz)&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
installpkg spl-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
cp spl-0.6.0rc10_3.2.27-x86_64-1root.txz ~/packages&lt;br /&gt;
&lt;br /&gt;
mkdir install&lt;br /&gt;
tar xvzf ~/packages/zfs-*.tar.gz&lt;br /&gt;
cd zfs-*&lt;br /&gt;
./configure $( cat ~/configure-options )&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../zfs-&amp;lt;version&amp;gt;_&amp;lt;kernel_version&amp;gt;-x86_64-&amp;lt;build_id&amp;gt;.txz&lt;br /&gt;
(e.g., makepkg ../zfs-0.6.0rc10_3.2.27-x86_64-1root.txz)&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
installpkg zfs-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
cp zfs-0.6.0rc10_3.2.27-x86_64-1root.txz ~/packages&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point spl and zfs packages are copied back to the host in the packages directory. Also, spl and zfs are installed in this simple development guest, so one could begin to experiment with zfs pools and datasets but while the root fs is whatever you made it during setup (probably the default, ext4). This development guest isn't really needed anymore, so it can be deleted:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
halt&lt;br /&gt;
(exit qemu: ctrl-alt-2 then enter quit at QEMU command prompt)&lt;br /&gt;
&lt;br /&gt;
(on host)&lt;br /&gt;
rm disk1.raw dvd.iso&lt;br /&gt;
mv packages ..&lt;br /&gt;
cd ..&lt;br /&gt;
rmdir slackdevel&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now that we have the spl and zfs packages on the host, it is possible to copy them into your local slackware64 mirror and then generate your own install DVD image that includes them. For example, change to the directory that contains the slackware README files, and create a &amp;quot;addon&amp;quot; directory and copy the spl and zfs slackware packages into there. Then, generate the DVD image using a command such as $( ./mirror-slackware-current.sh -i ) from where you have this script configured to maintain your local mirror. We can also just continue to access them inside the installer using qemu's virtfs option. When you are going to do a real installation onto real hardware, you need to generate and burn your own DVD that includes the packages.&lt;br /&gt;
&lt;br /&gt;
It is time to begin the installation of slackware64 on a ZFS root, assuming either you have regenerated dvd.iso with zfs packages in addon/* or we access the zfs packages while in the installer using qemu's virtfs to the host's packages directory. ZFS supports creating complex data storage configurations such as pools (similar to a volume group) backed by one or more of various kinds of virtual devices (similar to disks and raid arrays) and containing one or more datasets (similar to mounted filesystems, logical volume devices, or snapshots). But here, we keep it simple and will install on just a single disk device. On a real ZFS installation, users will typically want to use the ZFS raidz1 or raidz2 virtual device types for reliability against hard drive failures.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on host)&lt;br /&gt;
mkdir slackzfs&lt;br /&gt;
mv packages slackzfs/&lt;br /&gt;
cd slackzfs&lt;br /&gt;
qemu-img create disk1.raw 10G&lt;br /&gt;
ln -s ~/slackware64-current-install-dvd.iso dvd.iso&lt;br /&gt;
qemu-system-x86_64 \&lt;br /&gt;
 -no-quit \&lt;br /&gt;
 -no-shutdown \&lt;br /&gt;
 -boot order=cd,menu=on \&lt;br /&gt;
 -m 2G \&lt;br /&gt;
 -cpu host \&lt;br /&gt;
 -smp sockets=1,cores=4 \&lt;br /&gt;
 -net nic,model=rtl8139 -net user \&lt;br /&gt;
 -cdrom dvd.iso \&lt;br /&gt;
 -drive boot=on,format=raw,media=disk,cache=none,aio=native,if=scsi,bus=0,unit=0,file=disk1.raw \&lt;br /&gt;
 -virtfs local,path=./packages/,security_model=none,mount_tag=hostpackages&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The install-dvd should boot, and then begin installation steps on the installer command line:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on install-dvd)&lt;br /&gt;
# mount the install-dvd&lt;br /&gt;
mkdir /dvd&lt;br /&gt;
mount /dev/sr0 /dvd&lt;br /&gt;
&lt;br /&gt;
# install coreutils, which provides the &amp;quot;hostid&amp;quot; command needed to load the spl module&lt;br /&gt;
installpkg /dvd/slackware64/a/coreutils-8.17-x86_64-1.txz&lt;br /&gt;
&lt;br /&gt;
# install kmod package which includes &amp;quot;depmod&amp;quot; command and others&lt;br /&gt;
installpkg /dvd/slackware64/a/kmod-9-x86_64-2.txz&lt;br /&gt;
depmod&lt;br /&gt;
&lt;br /&gt;
# install the full kernel modules so you can load 9p filesystem and use it if you want&lt;br /&gt;
# .. you might keep the zfs modules packages off the dvd and use a plain slack dvd&lt;br /&gt;
installpkg /dvd/slackware64/a/kernel-modules-*.txz&lt;br /&gt;
depmod&lt;br /&gt;
&lt;br /&gt;
# install bash and libtermcap because udev rules in zfs use bash scripts&lt;br /&gt;
installpkg /dvd/slackware64/a/bash-*.txz&lt;br /&gt;
installpkg /dvd/slackware64/l/libtermcap-*.txz&lt;br /&gt;
&lt;br /&gt;
# install spl and zfs that you have copied into the mirror before running the DVD creation&lt;br /&gt;
installpkg /dvd/addon/spl-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /dvd/addon/zfs-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
&lt;br /&gt;
#Or:&lt;br /&gt;
mkdir /packages&lt;br /&gt;
find /lib/modules/ | grep 9p&lt;br /&gt;
lsmod&lt;br /&gt;
# check that 9p modules load, mainly 9pnet_virtio&lt;br /&gt;
modprobe 9pnet_virtio&lt;br /&gt;
mount hostpackages -t 9p -o trans=virtio /packages&lt;br /&gt;
installpkg /packages/spl-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /packages/zfs-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
modprobe zfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now zfs tools: &amp;quot;zpool&amp;quot; and &amp;quot;zfs&amp;quot; should work in the live installer.&lt;br /&gt;
On the installer, there can be trouble seeing man pages, so install:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
installpkg /dvd/slackware64/ap/man-*.txz&lt;br /&gt;
installpkg /dvd/slackware64/ap/groff-*.txz&lt;br /&gt;
installpkg /dvd/slackware64/a/less-*.txz&lt;br /&gt;
export MANPATH=/usr/man:/usr/share/man&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The manual pages should be readable:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
man zpool&lt;br /&gt;
man zfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After seeing the man pages, we should be fully ready to continue to setup on ZFS.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(still on install-dvd)&lt;br /&gt;
ls -l /dev/sd*&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Make sure the disk devices you expect are there. We'll use sda and make boot (/boot on /dev/sda1) and root (/ on /dev/sda2) partitions.&lt;br /&gt;
&lt;br /&gt;
First, some background info: A ZFS filesystem is not supported by lilo as the filesystem containing /boot, which holds lilo's 2nd stage and the linux kernel files. The on-disk format of a ZFS filesystem is often a complex raid configuration where even if lilo understood ZFS it would likely require /boot to reside in only certain simple ZFS configurations to be plainly readable to lilo. As things are, a linux root installed in a partition with ZFS filesystem needs /boot to be on another partition with a filesystem that lilo understands, such as ext4 fs. In addition, because the spl and zfs modules are not built into the kernel, and the zfs startup requires some configuration to mount the zfs root, an initial ram/root filesystem (initrd) is needed. The initrd is a gzip compressed cpio archive file that contains a small linux root operating system that is decompressed into a ramfs block device at boot up and takes initial control of the system. The initrd contains an init script that configures devices in devtmpfs mounted at /dev. For example, if using mdadm, lvm, luks, losetup, and now zfs, this init script runs all the commands to create or start these devices (one of which is the root device), mounts the root device, and then transfers system control to the init script in the mounted root filesystem. The ramfs-based root environment on the booted install-dvd or booted initrd image (in rescue command line) are small slackware installations that exist only in ram and are temporary, but while inside them you can install, upgrade, and remove slackware packages inside them using the regular package management tools; this allows you access to any kernel modules and programs as needed inside these ramfs root. Packages can be installed, upgraded, or removed permanantly in the initrd image file to manage the programs and modules required during the initrd boot stage. Also from within these ramfs initial root environments, once the root device is mounted, chroot can be used to work on the mounted root system as if it were booted; this allows one to fix problems that are occuring in the root fs init scripts that cause normal booting to fail, or to install a kernel and/or modules etc. Now on to partitioning:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cgdisk /dev/sda&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, cgdisk looks just like cfdisk, but it makes GPT partitions.&lt;br /&gt;
&lt;br /&gt;
Make a partition for /boot that is about 512MiB of whatever partition type you like (8300 &amp;quot;Linux filesystem&amp;quot; is fine), or make it type bf07 &amp;quot;Solaris Reserved 1&amp;quot; if you want ZFS to maybe see the disk as if it was given as a whole disk to ZFS. Make a second partition using the remaining space with partition type bf01 &amp;quot;Solaris ZFS&amp;quot;. Currently, when ZFSonLinux is given a whole disk device like /dev/sdb to use, it will automatically GPT partition it with a bf01 partition #1 that is the whole disk except a small 8MiB type bf07 partition #9 at the end of the disk (/dev/sdb1 and /dev/sb9). The small 8MiB type bf07 partition #9 is mostly likely reserved for use by bootloaders, like lilo, to have a /boot or other boot-related files kept there. For example, you might have /dev/sda that is totally non-ZFS for booting and /dev/sdb passed to ZFS whole where it automatically partitions sdb, but you can just use one disk here and make partitions. Lets use type 8300 for /boot to be sure nothing is confused:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
We'll continue with this partitioning (numbers are in MiB):&lt;br /&gt;
  0 to   4: unused&lt;br /&gt;
  4 to 516: /dev/sda1 512MiB, type 8300&lt;br /&gt;
516 to 520: unused&lt;br /&gt;
520 to -96: /dev/sda2, type bf01&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The -96 means to count from the end of the disk so that 96MiB will remain unused at the end of the disk.&lt;br /&gt;
&lt;br /&gt;
Create a zpool called zfs-root:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool create -m none zfs-root /dev/sda2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A zpool created like this, the normal way, is a kernel-internal block device that contains already a zfs filesystem. There is normally no entry in /dev for this device. However, it can still be referenced as a mountable device similar to how devtmpfs, proc, and sysfs are also kernel-internal mountable block devices. The -m option told zpool not to automatically mount it anywhere, and without -m the default is to always automatically mount to /zfs-root. These kinds of details are explained better elsewhere. For this situation, we do not want it automounted.&lt;br /&gt;
&lt;br /&gt;
Because a zpool itself is a useable zfs fs, it has a full set of zfs &amp;quot;properties&amp;quot; to set options about the filesystem, perhaps similar to tune2fs. The &amp;quot;mountpoint=&amp;lt;some place to mount&amp;gt;&amp;quot; is one such property. We want it set to the special value &amp;quot;none&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs get mountpoint zfs-root&lt;br /&gt;
zfs set mountpoint=none zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On creation, the zpool zfs-pool is &amp;quot;imported&amp;quot; and has a zpool status that can be viewed:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool status zfs-root&lt;br /&gt;
&lt;br /&gt;
zpool export zfs-root&lt;br /&gt;
zpool status zfs-root&lt;br /&gt;
# Now there is no status.&lt;br /&gt;
&lt;br /&gt;
zpool import zfs-root&lt;br /&gt;
# Now it is back.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When a zpool is imported, it has it's current configuration cached in a file /etc/zfs/zpool.cache. When a zpool is exported, then it's entries in the cache file are removed and the cache file is deleted if it becomes empty. So long as the zfs kernel modules see this cache file and valid cache data inside it, ZFS considers the described zpools in the cache file to be valid as imported zpools. If the zpool.cache file is present at the time the zfs modules are loaded, then there is no further need to use the import and export commands at system startup and shutdown. With root on a zfs, it is not possible to export the pool that root is on, but this is not a problem. At shutdown, the safe procedure will be to set the zfs-root property readonly=on and sync disks.&lt;br /&gt;
&lt;br /&gt;
To avoid the requirement to import the zfs-root pool at startup, keep a copy of the zpool.cache file to later copy onto the initrd image to read at modules load time to have the pool reactived without need to issue the import command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/zfs/zpool.cache /etc/zfs/zpool.cache-initrd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A zfs fs will not normally allow you to mount over any files. The mountpoint is expected to be an empty directory. Remove any junk files inside the installer's /mnt because zfs won't mount over any files:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rm /mnt/README&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The directory /mnt is where the slackware setup expects you to mount your root for installation.&lt;br /&gt;
&lt;br /&gt;
Controlling whether a zfs fs is to be mounted read-only or read-write is best managed by setting the readonly property while it is not yet mounted:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set readonly=on zfs-root&lt;br /&gt;
zfs set readonly=off zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Slackware expects root to be mounted readonly when /etc/rc.d/rc.S runs during normal startup, so later this is used to satisfy slackware's expectation to avoid rc.S complaining.&lt;br /&gt;
&lt;br /&gt;
The zfs-root can be mounted and unmounted in two different ways:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=/mnt zfs-root&lt;br /&gt;
zfs set mountpoint=none zfs-root&lt;br /&gt;
# or&lt;br /&gt;
mount zfs-root -t zfs /mnt&lt;br /&gt;
umount /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If it is already mounted and you want to change it to mount somewhere else, it is best to transition it to unmounted first, then mount it in the new place.&lt;br /&gt;
&lt;br /&gt;
The mount options &amp;lt;code&amp;gt;-o ro, -o rw, -o remount,ro, and -o remount,rw &amp;lt;/code&amp;gt; can also be used and will override &amp;lt;code&amp;gt;readonly=on|off&amp;lt;/code&amp;gt; property without altering the property value. This can be confusing until you are familiar with how to the methods of mounting interact.&lt;br /&gt;
&lt;br /&gt;
Now, let's continue some, and mount to /mnt using the current &amp;lt;code&amp;gt;readonly=off&amp;lt;/code&amp;gt; setting (rw mount):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=/mnt zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This method of mounting will show the most detailed mount options in /etc/mtab. They are the mount options that zfs thinks are proper, and they are probably what should be kept in /etc/fstab for zfs-root until we know better.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cat /etc/mtab &amp;gt;&amp;gt; /etc/fstab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now edit /etc/fstab to make sure it looks right, and remove the &amp;quot;rw&amp;quot; mount option, because we want to let it use a default for that, which will come from how we set the readonly= property most of the time. Unmount again:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=none zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mount again, now using all options from /etc/fstab:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It should be mounted at /mnt, and touch /mnt/t should allow you to make the file t. Then rm it: rm /mnt/t&lt;br /&gt;
For installation, we want to make sure it is mounted read-write. After installation, it should mount readonly inside the initrd.&lt;br /&gt;
&lt;br /&gt;
Sometimes there can be problems using the mount command, and then you can try it with the -i option:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 mount -i zfs-root &lt;br /&gt;
 mount -i zfs-root -t zfs /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
but, you should not have to use -i. When using -i makes it work, it performs an &amp;quot;internal-only&amp;quot; mount and does not use any mount.&amp;lt;fstype&amp;gt; helper scripts that might be on the system.&lt;br /&gt;
&lt;br /&gt;
Setup the /boot device:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkfs.ext4 /dev/sda1&lt;br /&gt;
mkdir /mnt/boot&lt;br /&gt;
mount /dev/sda1 /mnt/boot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We have both root and boot mounted where the slackware installer expects them. Unmount the dvd so setup can find it normally:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
umount /dev/sr0&lt;br /&gt;
setup&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the setup, skip straight to TARGET selection for the root device, but the setup doesn't see or understand the zfs-root, so it is not listed. This does not matter because we have mounted it already. Just skip down to a slot that say to continue, and continue on with setup. Because TARGET is skipped, you may not see the ADDITIONAL prompt (or if so, skip it too) where normally you give /dev/sda1 and have it mounted as /boot. This is also okay because we have mounted /mnt/boot already.&lt;br /&gt;
Because we did not give TARGET the root device or say what device /boot is on, the lilo installation will fail, or you can skip it. Otherwise, this installation process it normal.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
umount /dev/sr0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point, it is assumed that the setup has completed installing into /mnt. Congrats! You've installed slackware into a ZFS root!&lt;br /&gt;
&lt;br /&gt;
The next steps are to prepare to use &amp;quot;chroot /mnt&amp;quot; and finish up the configuration on the installed root system and then be able to reboot onto the completed installation. Before doing chroot, copy some files from the setup environment into /mnt.&lt;br /&gt;
&lt;br /&gt;
Copy the current installer /etc/fstab for later use inside the initrd. This fstab is what is proper inside the initrd, except remove option &amp;quot;rw&amp;quot; (if not done already).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/fstab /mnt/etc/fstab.initrd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The fstab.initrd will look like:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 proc /proc proc defaults 0 0&lt;br /&gt;
 zfs-root /mnt zfs defaults,atime,dev,exec,suid,xattr,nomand,zfsutil 0 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the initrd, we want zfs-root to mount to /mnt.&lt;br /&gt;
&lt;br /&gt;
Create /mnt/etc/fstab:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cat /etc/mtab &amp;gt;&amp;gt; /mnt/etc/fstab&lt;br /&gt;
vi /mnt/etc/fstab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using vi started above, edit /mnt/etc/fstab and make it have lines such as:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 zfs-root / zfs defaults,atime,dev,exec,suid,xattr,nomand,zfsutil 0 0&lt;br /&gt;
 /dev/sda1 /boot ext4 defaults 0 2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These two lines in &amp;lt;code&amp;gt;/mnt/etc/fstab&amp;lt;/code&amp;gt; are how the mounts should be looking when root is booted.&lt;br /&gt;
&lt;br /&gt;
Mount some special mounts before chroot:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount -t devtmpfs none /mnt/dev&lt;br /&gt;
mount -t proc none /mnt/proc&lt;br /&gt;
mount -t sysfs none /mnt/sys&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Make sure /boot is mounted:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount /dev/sda1 /mnt/boot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you had mounted a 9p fs share to access spl and zfs packages, then unmount that now:&lt;br /&gt;
umount /packages&lt;br /&gt;
&lt;br /&gt;
Ready, now:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chroot /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point, you should be on the installed system, and now try to configure mkinitrd and lilo. First, switch to use the generic kernel.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /boot&lt;br /&gt;
rm System.map config vmlinuz&lt;br /&gt;
ln -s System.map-gen* System.map&lt;br /&gt;
ln -s config-gen* config&lt;br /&gt;
ln -s vmlinuz-gen* vmlinuz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We install spl and zfs inside the live ramfs install-dvd environment, but not yet have we installed them into the root system:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount /dev/sr0 /mnt/cdrom&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /mnt/cdrom/addon/spl-*.txz&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /mnt/cdrom/addon/zfs-*.txz&lt;br /&gt;
depmod&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If instead, you used a 9p share to access the spl and zfs packages, then repeat that procedure here to install them onto the root system.&lt;br /&gt;
&lt;br /&gt;
Setup lilo: edit /etc/lilo.conf so it is like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  lba32&lt;br /&gt;
  append = &amp;quot; vt.default_utf8=1&amp;quot;&lt;br /&gt;
  boot = /dev/sda&lt;br /&gt;
  message = /boot/boot_message.txt&lt;br /&gt;
  prompt&lt;br /&gt;
  timeout = 1200&lt;br /&gt;
  change-rules&lt;br /&gt;
   reset&lt;br /&gt;
  vga = normal&lt;br /&gt;
  image = /boot/vmlinuz&lt;br /&gt;
   initrd = /boot/initrd.gz&lt;br /&gt;
   root = /dev/sda1&lt;br /&gt;
   label = vmlinuz&lt;br /&gt;
   read-only&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The line, root = /dev/sda1, is not really a true statement but lilo needs a device there that it at least understands. This root = line is a kernel parameter, but since the initrd is what is actually the root, initially, then the root = line is probably useless here. It might even be okay to just delete the root line.&lt;br /&gt;
&lt;br /&gt;
Setup mkinitrd:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/mkinitrd.conf.sample /etc/mkinitrd.conf&lt;br /&gt;
vi /etc/mkinitrd.conf&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Edit it to look like this (other defaults should be ok):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 MODULE_LIST=&amp;quot;sym53c8xx:ext4:8139cp:zfs:9p:9pnet_virtio&amp;quot;&lt;br /&gt;
 ROOTDEV=&amp;quot;zfs-root&amp;quot;&lt;br /&gt;
 ROOTFS=&amp;quot;zfs&amp;quot;&lt;br /&gt;
#Module sym53c8xx is the driver for qemu's if=scsi drive device.&lt;br /&gt;
#Module ext4 for /boot.&lt;br /&gt;
#Module 8139cp for eth0 net device.&lt;br /&gt;
#Module zfs for ZFSonLinux.&lt;br /&gt;
#Modules 9p and 9pnet_virtio for mounting qemu -virtfs mount_tag.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These 9p could be useful from the rescue command line inside the initrd to get needed files that are on the host.&lt;br /&gt;
&lt;br /&gt;
All dependent modules will also be included automatically into /boot/initrd-tree, which is packaged as /boot/initrd.gz. For example, to see the dependent modules of zfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
modprobe --show-depends zfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All listed modules will also be in the initrd. Now, make a /boot/initrd-tree that we can begin to look at and edit.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkinitrd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create an empty /etc/mtab or else zpool import fails (zfs expects /etc/mtab to exists already, it won't make it).&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
touch /boot/initrd-tree/etc/mtab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Copy in the fstab.initrd that was made earlier while on the installer. This provides all the mount options for a simple &amp;quot;mount zfs-root&amp;quot; onto /mnt.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/fstab.initrd /boot/initrd-tree/etc/fstab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More package installing! This time into an alternate root, the root of the initrd, /boot/initrd-tree. This is how you can put whatever packages you like into your initrd. These installations work independent of your normal installations. You can install, upgrade, and remove packages using an altroot:&lt;br /&gt;
&lt;br /&gt;
If spl and zfs are on your customized dvd:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/addon/spl-*.txz&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/addon/zfs-*.txz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Otherwise, repeat same procedure but you mount your 9p mount_tag and get them installed.&lt;br /&gt;
&lt;br /&gt;
More regular packages from the dvd:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/kmod-*.txz&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/coreutils-*.txz&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/gptfdisk-*.txz&lt;br /&gt;
&lt;br /&gt;
# A bash script is in /boot/initrd-tree/lib/udev/, so we need it or udev rules have problems:&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/bash-*.txz&lt;br /&gt;
# Bash needs this:&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/l/libtermcap-*.txz&lt;br /&gt;
&lt;br /&gt;
# Install net-tools to ensure that /etc/HOSTNAME, /etc/hosts, and potentially, /etc/hostid are handled proper.&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/n/net-tools-*.txz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When ZFS has to import a zpool while the initrd is running (this can be avoided by not exporting and keeping /etc/zfs/zpool.cache inside the initrd), ZFS will refuse to import a pool if it thinks that the pool may be in use by another system. ZFS was designed for network attached storage where multiple hosts might have access to the same disks but ZFS cannot support two hosts importing and using a ZFS pool at the same time. ZFS checks a value called &amp;quot;hostid&amp;quot; to determine this kind of conflict, and it can be a tricky issue with an initrd boot process. The value of hostid is returned by a system call, the gethostid() function or the hostid command. This function will return the hostid from /etc/hostid if that file exists and has a valid id in it, or else if the file doesn't exist it obtains a hostid number based on the hostname and ip address address assigned to hostname found in /etc/hosts or in DNS. If the hostid trying to import a pool is not the same as the hostid that imported it last time, ZFS will not import the pool unless &amp;quot;zpool import -f zfs-root&amp;quot; is used to force the import. This force option is not recommended to use, so it is best to configure your initrd with matching /etc/HOSTNAME and /etc/hosts as on the root installation and ensure what your system looks like on the initrd matches the booted root system.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Edit /boot/initrd-tree/init (this is the main system startup script on the initrd, responsibe for configuring your block devices and mount your root at /mnt and then booting root):&lt;br /&gt;
&lt;br /&gt;
Inside init, right near the top of the file after the PATH= line, add this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/bin/hostname -F /etc/HOSTNAME&lt;br /&gt;
/bin/hostname $( /bin/hostname -s )&lt;br /&gt;
#/sbin/chhostid 13371400&lt;br /&gt;
# you can make your hostid whatever, but this didn't work right with ZFS, so it is commented out&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This sets the name reported by the hostname command (the default is &amp;quot;darkstar&amp;quot;) to be what is contained in /etc/HOSTNAME. The hostname is modified in the next line to be the short name. These lines will help ZFS to properly identify your host when importing pools.&lt;br /&gt;
&lt;br /&gt;
Inside init, right after it runs &amp;quot;mdadm&amp;quot; commands as used for raid setup, we like it to setup ZFS, so add:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/sbin/zpool import zfs-root&lt;br /&gt;
/sbin/zfs set readonly=on zfs-root&lt;br /&gt;
mount zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Inside init, close to the bottom, where it &amp;quot;Switch to real root partition&amp;quot;, comment out 1 line that normally does the mount:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# mount -o ro -t $ROOTFS $ROOTDEV /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
We have already mounted, and we don't want to use any mount options because we should be using a properly set /etc/fstab inside the initrd for zfs-root mount options onto /mnt.&lt;br /&gt;
&lt;br /&gt;
During a normal startup we want a readonly mount.&lt;br /&gt;
&lt;br /&gt;
Note: we are going to setup with using zpool import and export and startup and shutdown. But later, you can experiment having /etc/zfs/zpool.cache stored in the initrd and commenting out zpool import/export lines.&lt;br /&gt;
&lt;br /&gt;
As mentioned, the import command may sometimes fail, and give the message: &amp;quot;pool may be in use from another system&amp;quot;. This is nothing serious in this test situation. When this happens, root will not be mounted to /mnt and the init script will detect this and drop you into a rescue command line where you may manually &amp;quot;import -f&amp;quot; then &amp;quot;mount zfs-root&amp;quot; and then &amp;quot;exit&amp;quot; to continue on to booting the root.&lt;br /&gt;
&lt;br /&gt;
To avoid this problem we copy some files in (assuming you first edit /etc/HOSTNAME to hold the hostname you like to see on your command prompts, and edited /etc/hosts to have hostname on your loopback or other local ip address):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/HOSTNAME /etc/hosts /boot/initrd-tree/etc&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The value reported by the hostid command is what ZFS sees as your hostid. In this setup so far, the value is based on the ip found assigned to your hostname. If your hostname is on the line in /etc/hosts for ip address 192.168.13.37, then your hostid will be hex numbers C0.A8.0D.25 rearranged as A8C0250D (pairs of bytes are swapped). That is ip-based hostid value, a 32bit hexadecimal number. This has to be the same each boot or import will need a -f option to force it. Simply setting the hostid using the system call sethostid() which writes a /etc/hostid file doesn't seem to agree with ZFS and you'd have to force the import, so this setup now assumes that you do not have or have deleted /etc/hostid.&lt;br /&gt;
&lt;br /&gt;
You can sometimes see what has been happening to a zpool by using the command &amp;quot;zpool history -li zfs-root&amp;quot; to see a log of commands.&lt;br /&gt;
&lt;br /&gt;
Once again, you can do away with the import and export commands by trying to have /etc/zfs/zpool.cache inside your initrd. To create zpool.cache, while on the installer or in the rescue shell of the initrd (at lilo &amp;quot;boot: vmlinuz rescue&amp;quot;), import only the pool for the root fs with mountpoint=none and readonly=on properties set and while it is not mounted:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on installer or initrd rescue shell)&lt;br /&gt;
cp /etc/zfs/zpool.cache /etc/zfs/zpool.cache-initrd&lt;br /&gt;
zfs set readonly=off zfs-root&lt;br /&gt;
mount zfs-pool&lt;br /&gt;
cp /etc/zfs/zpool.cache-initrd /mnt/etc/zfs/&lt;br /&gt;
cp /mnt/etc/zfs/zpool.cache-initrd /mnt/boot/initrd-tree/etc/zfs/zpool.cache&lt;br /&gt;
umount /mnt&lt;br /&gt;
zfs set readonly=on zfs-root&lt;br /&gt;
#mount zfs-root&lt;br /&gt;
#exit (to continue boot process onto rootfs mounted at /mnt)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, doing this zpool.cache approach is not necessary, and some talk suggests this is deprecated or discouraged. Although /etc/hostid setup fails to import without -f option, ip-based (hosts|dns) hostid works on booting and import works without -f option and may be the more proper way to do shutdown and startup rather than using a cache file which could be come invalid and cause a problem that is difficult to understand. The contents and exact function of the cache file are not well understood by many people.&lt;br /&gt;
&lt;br /&gt;
Save /boot/initrd-tree/init and exit.&lt;br /&gt;
&lt;br /&gt;
Now, edit /etc/rc.d/rc.S and rc.6 to understand how to &amp;quot;remount&amp;quot; rw or ro as a readonly property changes&lt;br /&gt;
&lt;br /&gt;
In /etc/rc.d/rc.S:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# comment out the line&lt;br /&gt;
#    /sbin/mount -w -v -n -o remount /&lt;br /&gt;
#add the line&lt;br /&gt;
     /sbin/zfs set readonly=off zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In /etc/rc.d/rc.6&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# comment out the line&lt;br /&gt;
#    /bin/mount -v -n -o remount,ro /&lt;br /&gt;
#add the line&lt;br /&gt;
     /sbin/zfs set readonly=on zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In /etc/rc.d/rc.6, near the bottom just before poweroff|reboot, add the following block of lines:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
########################&lt;br /&gt;
# Try to export zfs-root&lt;br /&gt;
/sbin/zpool export zfs-root&lt;br /&gt;
if [ $? -gt 0 ] ; then&lt;br /&gt;
 echo &amp;quot;ZFS export failed.&amp;quot;&lt;br /&gt;
 echo &amp;quot;Notice: if root fs is busy, then this is normal fail.&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;ZFS export successful.&amp;quot;&lt;br /&gt;
 echo &amp;quot;Warning: successful export is abnormal for root fs.&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
/bin/sleep 5&lt;br /&gt;
########################&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
For ZFS, you cannot run fsck on it. It doesn't support that kind of filesystem checks. The rc.S script will complain a lot in many places about not being about to run fsck on the zfs-root. To disable all attempts of run fsck, we can simple create a file that acts as a flag in /etc/rc.d/rc.S to tell it to skip fsck:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
touch /etc/fastboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This fastboot file is normally a run-once temporary file, and it is deleted near the bottom inside rc.S. Edit rc.S and stop it from deleting /etc/fastboot. We would like it to always skip all fsck. Edit /etc/rc.d/rc.S, and find the &amp;quot;rm&amp;quot; of fastboot, and do not have it removed!&lt;br /&gt;
&lt;br /&gt;
We are getting close, and have finished all editing, so make /boot/initrd.gz and install lilo:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkinitrd -F&lt;br /&gt;
lilo&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We finished! All that's left to do is clean up.&lt;br /&gt;
&lt;br /&gt;
Exit the chroot.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
exit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Try to mount everything:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
umount /mnt/proc&lt;br /&gt;
umount /mnt/sys&lt;br /&gt;
umount /mnt/dev&lt;br /&gt;
umount /mnt/boot&lt;br /&gt;
umount /mnt/mnt/cdrom&lt;br /&gt;
umount /mnt/root/packages&lt;br /&gt;
umount /mnt&lt;br /&gt;
zpool export zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note, that export stops a pool and frees devices, while import binds devices and starts a pool. It is somewhat like mdadm -A -s and mdadm -S -s, while /etc/zfs/zpool.cache might be somewhat like mdadm -E -s &amp;gt; /etc/mdadm.conf.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Remove the DVD or change boot order&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When you reboot, if all is good, you are booting properly onto a slackware installed on a ZFS root! Congrat!&lt;br /&gt;
&lt;br /&gt;
If this seem to go badly, and this might happen if the import fails as explain some before, then you will be on the initrd's rescue command line just before the part in it's init where it wants to mount and switch_root to boot your root. Instead, you typically got commands like this to do:&lt;br /&gt;
&lt;br /&gt;
If you get dumped to rescue because import will not work and requires -f (force), then:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 zpool import -f zfs-root&lt;br /&gt;
 zpool export    zfs-root&lt;br /&gt;
 zpool import    zfs-root&lt;br /&gt;
 mount zfs-root&lt;br /&gt;
 exit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This can happen if hostname, hostid, or uname changes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you get into a jam and need to boot into the initrd and skip zfs import etc, use the lilo prompt (or, boot the install-dvd):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
boot: vmlinuz rescue&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the rescue mode of the initrd, after you have mounted your root as readonly=on to /mnt, then exit to continue.&lt;br /&gt;
&lt;br /&gt;
In other emergency modes, you might need to run the lines at end of init starting from: &amp;lt;code&amp;gt;udevadm info --cleanup-db; udevadm control --exit&amp;lt;/code&amp;gt;&lt;br /&gt;
If you don't run those udevadm commands, two runs of udevd fight each other and it is slow; you have to wait 2 minutes twice for timeouts (4 minutes).&lt;br /&gt;
The last line is run is: &amp;lt;code&amp;gt;exec switch_root /mnt /sbin/init 1&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Warning... this switch_root command is kind of dangerous, so read the manual page about it.&lt;br /&gt;
From what I can tell, everything except the new root &amp;quot;/mnt&amp;quot; is deleted, so you are giving a command that says what NOT to delete!&lt;br /&gt;
Make sure nothing got mounted outside of &amp;quot;/mnt&amp;quot; before you run it.&lt;br /&gt;
&lt;br /&gt;
Also, in rescue or anytime you have finished making changes and are about to reboot in some abnormal mode, first run:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set readonly=on zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A bug in unpatched grep 2.13 build 1, found slackware 14.0rc1, causes problems when processing files stored on ZFS but rarely shows problems on other filesystems; the bug does not handle sparse files on zfs and btrfs correctly and results in chaos with slackpkg, compiling kernel modules, and possibly many other things. You must downgrade grep to 2.12 or use the patched grep 2.13 build 2 in slackware 14.0rc2 or later.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Upgrading.&lt;br /&gt;
&lt;br /&gt;
From time to time you will want to upgrade the kernel to the new kernel in slackware64-current or in patches/. This will also necessitate a rebuilt and reinstall or upgrade of spl and zfs. Below is an example of when both kernel and spl/zfs are being upgraded, to give an idea of the process:&lt;br /&gt;
&lt;br /&gt;
Using slackpkg, that is configured to use your local slackware mirror is a good option but you can also configure it to use a remote mirror.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slackpkg upgrade-all&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Assume slackpkg just upgraded your kernel, kernel-modules, and kernel-headers.&lt;br /&gt;
&lt;br /&gt;
Note: the first time you try to run on kernel-generic, setup kernel-huge in lilo as 2nd choice. Huge has all the hard drive controllers builtin, but generic has them all as modules. For example, run &amp;quot;modinfo mptsas&amp;quot; to see module options (maybe you have a LSISAS1068) for your hard drive controller. Add file /etc/modprobe.d/mptsas.conf to set options you want with a line: options mptsas ... Do this for all the device driver modules for your hardware. Do this setup while you are on the huge kernel, then setup to reboot to generic. Include all these modules you need into mkinitrd.conf MODULES_LIST. Check that /boot/initrd-tree/etc/modprobe.d/ has a copy of your customized module conf files because it is on the initrd where the modules will load and use the conf files. mkinitrd probably copies all /etc/modprobe.d/* files into the initrd-tree, but check it. Pay attention to /etc/modprobe.d/README and /lib/modprobe.d/* /lib/modprobe.d/* maybe not copied to initrd-tree but you might want to copy some of it into your initrd-tree yourself to use them.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Check that upgraded kernel-source is symlinked to /usr/src/linux (zfs build looks here). SQL/ZFS modules will install to the kernel version in /lib/modules/&amp;lt;/usr/src/linux kernel version&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /usr/local/src&lt;br /&gt;
tar xvzf ~/spl-*.tar.gz&lt;br /&gt;
tar xvzf ~/zfs-*.tar.gz&lt;br /&gt;
&lt;br /&gt;
###### upgrade spl 1st&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-*&lt;br /&gt;
./configure --prefix=/ --libexecdir=/usr/libexec --libdir=/lib64 --includedir=/usr/include --datarootdir=/usr/share&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=/usr/local/src/install&lt;br /&gt;
cd ../install&lt;br /&gt;
makepkg ../spl-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
upgradepkg spl-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
depmod &amp;lt;new kernel version&amp;gt;     (e.g. depmod 3.2.27, if .27 is new kernel upgrade; you currently run on old, maybe .26)&lt;br /&gt;
# this builds the module dependencies in /lib/modules/&amp;lt;new kernel version&amp;gt;&lt;br /&gt;
###### upgrade zfs 2nd&lt;br /&gt;
mkdir install&lt;br /&gt;
cd zfs-*&lt;br /&gt;
./configure --prefix=/ --libexecdir=/usr/libexec --libdir=/lib64 --includedir=/usr/include --datarootdir=/usr/share&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=/usr/local/src/install&lt;br /&gt;
cd ../install&lt;br /&gt;
makepkg ../zfs-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
upgradepkg zfs-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
depmod 3.2.27&lt;br /&gt;
####### upgrade spl/zfs inside altroot /boot/initrd-tree&lt;br /&gt;
ROOT=/boot/initrd-tree upgradepkg spl-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
ROOT=/boot/initrd-tree upgradepkg zfs-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
# note: ROOT is an environment variable, not a command line option to upgradepkg!&lt;br /&gt;
# note: do not worry about depmod inside initrd-tree, mkinitrd -F actually installs the modules&lt;br /&gt;
# note: this upgrade here is really to just upgrade the command line tools zpool, zfs etc&lt;br /&gt;
####### rebuild /boot/initrd.gz and reinstall lilo&lt;br /&gt;
vi /etc/mkinitrd.conf&lt;br /&gt;
# temporarily set KERNEL_VERSION to new version, but you are still running on old version&lt;br /&gt;
mkinitrd -F&lt;br /&gt;
lilo&lt;br /&gt;
vi /etc/mkinitrd.conf&lt;br /&gt;
# you can set KERNEL_VERSION back to $(uname r) now&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After reboot you can remove any old /lib/modules/&amp;lt;old kernel version&amp;gt; directory.&lt;br /&gt;
&lt;br /&gt;
More about /etc/hostid. If you want to experiment changing your /etc/hostid file and seeing if you can use it and make zpool import work normally, here is a tool that might be helpful:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/* software product name: foobarz-chhostid.c&lt;br /&gt;
 * suggested binary name: chhostid&lt;br /&gt;
 * license              : BSD&lt;br /&gt;
 * license text:&lt;br /&gt;
Copyright (c) 2012, foobarz&lt;br /&gt;
All rights reserved.&lt;br /&gt;
&lt;br /&gt;
Redistribution and use in source and binary forms, with or without&lt;br /&gt;
modification, are permitted provided that the following conditions are met:&lt;br /&gt;
    * Redistributions of source code must retain the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer.&lt;br /&gt;
    * Redistributions in binary form must reproduce the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer in the&lt;br /&gt;
      documentation and/or other materials provided with the distribution.&lt;br /&gt;
    * Neither the name of the &amp;lt;organization&amp;gt; nor the&lt;br /&gt;
      names of its contributors may be used to endorse or promote products&lt;br /&gt;
      derived from this software without specific prior written permission.&lt;br /&gt;
&lt;br /&gt;
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &amp;quot;AS IS&amp;quot; AND&lt;br /&gt;
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED&lt;br /&gt;
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE&lt;br /&gt;
DISCLAIMED. IN NO EVENT SHALL &amp;lt;COPYRIGHT HOLDER&amp;gt; BE LIABLE FOR ANY&lt;br /&gt;
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES&lt;br /&gt;
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;&lt;br /&gt;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND&lt;br /&gt;
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT&lt;br /&gt;
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS&lt;br /&gt;
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#define FOOBARZ_CHHOSTID_VERSION &amp;quot;1.0.5&amp;quot;&lt;br /&gt;
#include &amp;lt;sys/socket.h&amp;gt;&lt;br /&gt;
#include &amp;lt;netinet/in.h&amp;gt;&lt;br /&gt;
#include &amp;lt;arpa/inet.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;endian.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sysexits.h&amp;gt;&lt;br /&gt;
/* note: if include stdlib then sethostid fails even with _BSD_SOURCE defined */&lt;br /&gt;
&lt;br /&gt;
long swapbytes(long abcd) {&lt;br /&gt;
  long badc;&lt;br /&gt;
  unsigned char addr_a;&lt;br /&gt;
  unsigned char addr_b;&lt;br /&gt;
  unsigned char addr_c;&lt;br /&gt;
  unsigned char addr_d;&lt;br /&gt;
  addr_a = (unsigned char) (abcd &amp;gt;&amp;gt; 24);&lt;br /&gt;
  addr_b = (unsigned char) (abcd &amp;gt;&amp;gt; 16);&lt;br /&gt;
  addr_c = (unsigned char) (abcd &amp;gt;&amp;gt;  8);&lt;br /&gt;
  addr_d = (unsigned char) (abcd);&lt;br /&gt;
  return badc = ( (addr_b &amp;lt;&amp;lt; 24) | (addr_a &amp;lt;&amp;lt; 16) | (addr_d &amp;lt;&amp;lt; 8) | addr_c );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[])&lt;br /&gt;
{&lt;br /&gt;
 long newhostid;&lt;br /&gt;
 struct in_addr addr;&lt;br /&gt;
 char* invalidchar;&lt;br /&gt;
&lt;br /&gt;
 /*********** check command line */&lt;br /&gt;
 if(!( ((argc==3) &amp;amp;&amp;amp; ( (strcmp(argv[1],&amp;quot;-h&amp;quot;)==0) ||&lt;br /&gt;
                       (strcmp(argv[1],&amp;quot;-i&amp;quot;)==0) ||&lt;br /&gt;
                       (strcmp(argv[1],&amp;quot;-l&amp;quot;)==0) )) ||&lt;br /&gt;
       ((argc==2) &amp;amp;&amp;amp; ( (strcmp(argv[1],&amp;quot;-s&amp;quot;)==0) ))&lt;br /&gt;
     )&lt;br /&gt;
   ) {&lt;br /&gt;
                 /*01234567890123456789012345678901234567890123456789012345678901234567890123456789*/&lt;br /&gt;
  fprintf(stderr, &amp;quot;foobarz-chhostid, version %s. License: BSD.\n&amp;quot;, FOOBARZ_CHHOSTID_VERSION);&lt;br /&gt;
  fprintf(stderr, &amp;quot;foobarz-chhostid, (c) 2012, foobarz; all rights reserved.\n&amp;quot;);&lt;br /&gt;
  fprintf(stderr, &amp;quot;descr: %s change system hostid (in /etc/hostid).\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -h &amp;lt;new hostid&amp;gt;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        Change system hostid to &amp;lt;new hostid&amp;gt;;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        &amp;lt;new hostid&amp;gt; must be 32bit 8-digit hex number xxxxxxxx, each x in 0-f|F.\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        The ip corresponding to &amp;lt;new hostid&amp;gt; is also listed for reference only.\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -i &amp;lt;dotted ip address&amp;gt;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        Change system hostid to hostid corresponding to &amp;lt;dotted ip address&amp;gt;.\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -l &amp;lt;dotted ip address&amp;gt;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        List hostid corresponding to &amp;lt;dotted ip address&amp;gt;;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        no change to system hostid.\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -s\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        List current system hostid and corresponding ip address;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        no change to system hostid.\n&amp;quot;, argv[0]);&lt;br /&gt;
  return EX_USAGE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -h &amp;lt;hostid&amp;gt; */&lt;br /&gt;
 if( strcmp(argv[1],&amp;quot;-h&amp;quot;) == 0 ) {&lt;br /&gt;
  if(strlen(argv[2]) != 8) { fprintf(stderr, &amp;quot;new hostid must be 8-digit hex number xxxxxxxx, each x in 0-f|F\n&amp;quot;); return EX_USAGE; }&lt;br /&gt;
&lt;br /&gt;
  newhostid = strtol(argv[2],&amp;amp;invalidchar,16);&lt;br /&gt;
  if( newhostid==LONG_MIN ) { perror(&amp;quot;strtol (underflow)&amp;quot;); return EX_USAGE; }&lt;br /&gt;
  if( newhostid==LONG_MAX ) { perror(&amp;quot;strtol (overflow)&amp;quot;); return EX_USAGE; }&lt;br /&gt;
  if(*invalidchar != '\0') { fprintf(stderr, &amp;quot;invalid hex number %c; must be in 0-f|F\n&amp;quot;, *invalidchar); return EX_USAGE; }&lt;br /&gt;
&lt;br /&gt;
  if( sethostid(newhostid) != 0 ) {&lt;br /&gt;
   perror(&amp;quot;sethostid&amp;quot;);&lt;br /&gt;
   if( errno == EPERM ) return EX_NOPERM;&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
  }&lt;br /&gt;
  printf(&amp;quot;System hostid changed.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  /* hostid is a byte-swapped ip like b.a.d.c */&lt;br /&gt;
  /* get ip by swapping to correct order a.b.c.d and save into in_addr struct */&lt;br /&gt;
  addr.s_addr = htonl(swapbytes(newhostid));&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -i or -l, then find hostid for &amp;lt;dotted ip address&amp;gt; */&lt;br /&gt;
 if( (strcmp(argv[1],&amp;quot;-i&amp;quot;) == 0) || (strcmp(argv[1],&amp;quot;-l&amp;quot;) == 0) ) {&lt;br /&gt;
  if( inet_aton(argv[2], &amp;amp;addr) == 0 ) { fprintf(stderr, &amp;quot;inet_aton: invalid dotted ip address: %s\n&amp;quot;, argv[2]); return EX_USAGE; }&lt;br /&gt;
&lt;br /&gt;
  /* hostid is a byte-swapped ip like b.a.d.c */&lt;br /&gt;
  /* get hostid by swapping bytes of ip a.b.c.d */&lt;br /&gt;
  newhostid = swapbytes(ntohl(addr.s_addr));&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -i &amp;lt;dotted ip address&amp;gt; */&lt;br /&gt;
 if( strcmp(argv[1],&amp;quot;-i&amp;quot;) == 0 ) {&lt;br /&gt;
  if( sethostid(newhostid) != 0 ) {&lt;br /&gt;
   perror(&amp;quot;sethostid&amp;quot;);&lt;br /&gt;
   if( errno == EPERM ) return EX_NOPERM;&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
  }&lt;br /&gt;
  printf(&amp;quot;System hostid changed.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -l &amp;lt;dotted ip address&amp;gt; */&lt;br /&gt;
 if(strcmp(argv[1],&amp;quot;-l&amp;quot;) == 0 ) {&lt;br /&gt;
   printf(&amp;quot;Listing hostid for ip. (no changes)\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -s */&lt;br /&gt;
 if(strcmp(argv[1],&amp;quot;-s&amp;quot;) == 0 ) {&lt;br /&gt;
   /* see if /etc/hostid exists and print info */&lt;br /&gt;
   if( access(&amp;quot;/etc/hostid&amp;quot;, F_OK) != 0 ) {&lt;br /&gt;
     printf(&amp;quot;Notice: /etc/hostid does not exist.\n&amp;quot;);&lt;br /&gt;
     perror(&amp;quot;Reason&amp;quot;);&lt;br /&gt;
     printf(&amp;quot;System hostid derived from ip of hostname found in hosts file or dns.\n&amp;quot;);&lt;br /&gt;
   } else {&lt;br /&gt;
     printf(&amp;quot;Notice: /etc/hostid exists.\n&amp;quot;&lt;br /&gt;
            &amp;quot;System hostid is obtained from hostid file.\n&amp;quot;);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
  errno=0;&lt;br /&gt;
  newhostid = gethostid();&lt;br /&gt;
  if(errno!=0) { perror(&amp;quot;gethostid&amp;quot;); return EX_UNAVAILABLE; }&lt;br /&gt;
&lt;br /&gt;
  /* hostid is a byte-swapped ip like b.a.d.c */&lt;br /&gt;
  /* get ip by swapping to correct order a.b.c.d and save into in_addr struct */&lt;br /&gt;
  addr.s_addr = htonl(swapbytes(newhostid));&lt;br /&gt;
&lt;br /&gt;
  printf(&amp;quot;Listing current system hostid. (no changes)\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** print info and return */&lt;br /&gt;
 printf(&amp;quot;ip dot: %s\n&amp;quot;, inet_ntoa(addr) );&lt;br /&gt;
 printf(&amp;quot;ip hex: %.8x\n&amp;quot;, ntohl(addr.s_addr) );&lt;br /&gt;
 printf(&amp;quot;hostid: %.8x\n&amp;quot;, newhostid );&lt;br /&gt;
 return EX_OK;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</description>
			<pubDate>Sat, 18 Aug 2012 19:07:24 GMT</pubDate>
			<dc:creator>Foobarz</dc:creator>
			<comments>https://www.slackwiki.com/Talk:ZFS_root</comments>
		</item>
		<item>
			<title>ZFS root</title>
			<link>https://www.slackwiki.com/index.php?title=ZFS_root&amp;diff=735</link>
			<guid isPermaLink="false">https://www.slackwiki.com/index.php?title=ZFS_root&amp;diff=735</guid>
			<description>&lt;p&gt;Foobarz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;If you have heard about the ZFS filesystem and you're curious to try it out, then you can try it on slackware64, thanks to the ZFSonLinux.org project!&lt;br /&gt;
&lt;br /&gt;
In this article, an example is shown of how to install slackware64 14.0 onto a ZFS root filesystem (zfs-root) inside a QEMU virtual machine for testing purposes. It is recommended that you install qemu and learn how to use it to test a ZFS installation before you decide to use it on real hardware. A slackbuild for qemu can be found on slackbuilds.org. If you have a processor that supports Intel VT-x or AMD AMD-V virtualization acceleration (try modprobe kvm-intel or modprobe kvm-amd), then use the slackbuild for qemu-kvm.&lt;br /&gt;
&lt;br /&gt;
This article isn't going to go into any detail on actually using ZFS or what kinds of installation options and settings might be optimal. This article just presents an example of how to get started with ZFS on slackware.&lt;br /&gt;
&lt;br /&gt;
At this time of writing, ZFSonLinux is at &amp;quot;release candidate&amp;quot; (version 0.6.0-rc10) development stage, and many issues can occur. See the ZFSonLinux.org web site and the issues tracker for an idea about the current issues. There is also an irc channel on irc.freenode.net, #zfsonlinux, for discussion of issues and help.&lt;br /&gt;
&lt;br /&gt;
Although not required, it is helpful to keep a local mirror of slackware64 on your system. Having a local mirror makes it easier to upgrade to slackware64-current or to patches/* in a release. To help manage your own local slackware mirror and generate your own CD and DVD slackware installers, see http://alien.slackbook.org/blog/local-slackware-mirror/.&lt;br /&gt;
&lt;br /&gt;
In this article, we use a slackware64-current DVD image file as the qemu cdrom device media for the installation of the slackware guest. This was tested at slackware64-current = slackware64 14.0rc2. You can obtain a slackware DVD image using a torrent, buy the DVD from slackware.com, or generate your own DVD image file using the mirror script. For an actual DVD, you can pass your DVD device (e.g., /dev/sr0) as the qemu cdrom device. For a DVD image file, pass the image file as the qemu cdrom device.&lt;br /&gt;
&lt;br /&gt;
The ZFSonLinux packages are not included in slackware at this time. There are two packages involved: spl and zfs. The first, spl, is &amp;quot;Solaris Porting Layer&amp;quot; and must be installed on the system before zfs can be compiled. The source code tarballs for these are at ZFSonLinux.org. At this time of writing, they are spl-0.6.0-rc10.tar.gz and zfs-0.6.0-rc10.tar.gz.&lt;br /&gt;
&lt;br /&gt;
At this point, it is assumed you have qemu installed, have obtained a slackware64-current/14.0 DVD, and have downloaded spl and zfs tarballs to your host system. The first step now is, if your host is not slackware64-current/14.0 (the same as the guest will be), then you need to create a minimal development slackware64 guest system in qemu for just the purpose of compiling and packaging the spl and zfs slackware packages and transferring a copy of these packages back onto your host system to use later to install onto zfs during the slackware install process.&lt;br /&gt;
&lt;br /&gt;
From this point onward, instructions become a bit terse and mostly limited to examples of the commands you might use to complete tasks. You are encouraged to examine what each command does by reading the command's man pages. For example, the command &amp;quot;man qemu&amp;quot; can show you most of what you need to know about running qemu on the command line.&lt;br /&gt;
&lt;br /&gt;
So, here's an example of how you might build the spl and zfs packages, starting in your home directory:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on host)&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir qemu&lt;br /&gt;
cd qemu&lt;br /&gt;
mkdir slackdevel&lt;br /&gt;
cd slackdevel&lt;br /&gt;
mkdir packages&lt;br /&gt;
cp ~/spl-*.tar.gz packages&lt;br /&gt;
cp ~/zfs-*.tar.gz packages&lt;br /&gt;
qemu-img create disk1.raw 10G&lt;br /&gt;
ln -s ~/slackware64-current-install-dvd.iso dvd.iso&lt;br /&gt;
qemu-system-x86_64 \&lt;br /&gt;
 -no-quit \&lt;br /&gt;
 -no-shutdown \&lt;br /&gt;
 -boot order=cd,menu=on \&lt;br /&gt;
 -m 2G \&lt;br /&gt;
 -cpu host \&lt;br /&gt;
 -smp sockets=1,cores=4 \&lt;br /&gt;
 -net nic,model=rtl8139 -net user \&lt;br /&gt;
 -cdrom dvd.iso \&lt;br /&gt;
 -drive boot=on,format=raw,media=disk,cache=none,aio=native,if=scsi,bus=0,unit=0,file=disk1.raw \&lt;br /&gt;
 -virtfs local,path=./packages/,security_model=none,mount_tag=hostpackages&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When you need to change boot to cd or disk, add or remove &amp;quot;boot=on&amp;quot;, or change &amp;quot;order=dc&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Qemu should boot into the install-dvd, and now perform a very ordinary slackware64 install onto /dev/sda. Install d package set and most others, but package sets x, kde, xfce not really needed.&lt;br /&gt;
&lt;br /&gt;
First note: examples here use tools from the gptfdisk package (gdisk, sgdisk, cgdisk) to partition the disk with GUID partition table (GPT) format. GPT might not be too familiar to everyone, who mostly have only used MBR partitions with fdisk. In the slackware installations this author has tested in qemu, using GPT partitions has caused no problems with lilo or other tools used in slackware. GPT disk labels support creating up to 128 partitions and support disks larger than 2TB (the limit of MBR fdisk). LILO installs into the first 440 bytes on /dev/sda, inside a GPT &amp;quot;protective MBR&amp;quot; that serves to provide compatibility with MBR bootloaders like lilo. LILO uses LBA32 sector addressing and can see all 512-byte sectors side the first 2TB of a disk. So long as the /boot partition is within the first 2TB of a disk, lilo can work on a disk larger than 2TB. Unlike the common default of fdisk to start the first partition at sector 63, which is not aligned with the 4KiB sector size of Advanced Format hard disks, gdisk's default is to start partitions at 2048 sector (1MiB) boundaries which are also 4KiB aligned. Using gdisk GPT works on all disks and is compatible with using Advanced Format hard disks larger than 2TB. More information about GPT disk label format can be found on wikipedia.org. For those that have used grub instead of lilo, grub installation is different with GPT than with MBR, and grub requires a GPT partition of type grub-bios or 0xEF02 &amp;quot;BIOS Boot Partition&amp;quot; of about 8MiB where it can install it's additional bootloader stages because grub cannot embed in sectors 1-62 on GPT where GPT keeps it's partition tables. On MBR, sectors 1-62 were normally reserved space for bootloaders to keep a 2nd stage.&lt;br /&gt;
&lt;br /&gt;
For this purpose of development guest, just create a simple 1-partition system, /dev/sda1, and do a simple slackware install on it. Don't bother with swap or separate /boot unless you want to:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on install-dvd)&lt;br /&gt;
cgdisk /dev/sda&lt;br /&gt;
setup&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When this simple development guest boots, login as root, and continue:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on qemu guest)&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir packages&lt;br /&gt;
mount hostpackages -t 9p -o trans=virtio packages&lt;br /&gt;
echo --prefix=/ --libexecdir=/usr/libexec --libdir=/lib64 --includedir=/usr/include --datarootdir=/usr/share &amp;gt; configure-options&lt;br /&gt;
mkdir src&lt;br /&gt;
cd src&lt;br /&gt;
&lt;br /&gt;
mkdir install&lt;br /&gt;
tar xvzf ~/packages/spl-*.tar.gz&lt;br /&gt;
cd spl-*&lt;br /&gt;
./configure $( cat ~/configure-options )&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../spl-&amp;lt;version&amp;gt;_&amp;lt;kernel_version&amp;gt;-x86_64-&amp;lt;build_id&amp;gt;.txz&lt;br /&gt;
(e.g., makepkg ../spl-0.6.0rc10_3.2.27-x86_64-1root.txz)&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
installpkg spl-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
cp spl-0.6.0rc10_3.2.27-x86_64-1root.txz ~/packages&lt;br /&gt;
&lt;br /&gt;
mkdir install&lt;br /&gt;
tar xvzf ~/packages/zfs-*.tar.gz&lt;br /&gt;
cd zfs-*&lt;br /&gt;
./configure $( cat ~/configure-options )&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../zfs-&amp;lt;version&amp;gt;_&amp;lt;kernel_version&amp;gt;-x86_64-&amp;lt;build_id&amp;gt;.txz&lt;br /&gt;
(e.g., makepkg ../zfs-0.6.0rc10_3.2.27-x86_64-1root.txz)&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
installpkg zfs-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
cp zfs-0.6.0rc10_3.2.27-x86_64-1root.txz ~/packages&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point spl and zfs packages are copied back to the host in the packages directory. Also, spl and zfs are installed in this simple development guest, so one could begin to experiment with zfs pools and datasets but while the root fs is whatever you made it during setup (probably the default, ext4). This development guest isn't really needed anymore, so it can be deleted:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
halt&lt;br /&gt;
(exit qemu: ctrl-alt-2 then enter quit at QEMU command prompt)&lt;br /&gt;
&lt;br /&gt;
(on host)&lt;br /&gt;
rm disk1.raw dvd.iso&lt;br /&gt;
mv packages ..&lt;br /&gt;
cd ..&lt;br /&gt;
rmdir slackdevel&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now that we have the spl and zfs packages on the host, it is possible to copy them into your local slackware64 mirror and then generate your own install DVD image that includes them. For example, change to the directory that contains the slackware README files, and create a &amp;quot;addon&amp;quot; directory and copy the spl and zfs slackware packages into there. Then, generate the DVD image using a command such as $( ./mirror-slackware-current.sh -i ) from where you have this script configured to maintain your local mirror. We can also just continue to access them inside the installer using qemu's virtfs option. When you are going to do a real installation onto real hardware, you need to generate and burn your own DVD that includes the packages.&lt;br /&gt;
&lt;br /&gt;
It is time to begin the installation of slackware64 on a ZFS root, assuming either you have regenerated dvd.iso with zfs packages in addon/* or we access the zfs packages while in the installer using qemu's virtfs to the host's packages directory. ZFS supports creating complex data storage configurations such as pools (similar to a volume group) backed by one or more of various kinds of virtual devices (similar to disks and raid arrays) and containing one or more datasets (similar to mounted filesystems, logical volume devices, or snapshots). But here, we keep it simple and will install on just a single disk device. On a real ZFS installation, users will typically want to use the ZFS raidz1 or raidz2 virtual device types for reliability against hard drive failures.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on host)&lt;br /&gt;
mkdir slackzfs&lt;br /&gt;
mv packages slackzfs/&lt;br /&gt;
cd slackzfs&lt;br /&gt;
qemu-img create disk1.raw 10G&lt;br /&gt;
ln -s ~/slackware64-current-install-dvd.iso dvd.iso&lt;br /&gt;
qemu-system-x86_64 \&lt;br /&gt;
 -no-quit \&lt;br /&gt;
 -no-shutdown \&lt;br /&gt;
 -boot order=cd,menu=on \&lt;br /&gt;
 -m 2G \&lt;br /&gt;
 -cpu host \&lt;br /&gt;
 -smp sockets=1,cores=4 \&lt;br /&gt;
 -net nic,model=rtl8139 -net user \&lt;br /&gt;
 -cdrom dvd.iso \&lt;br /&gt;
 -drive boot=on,format=raw,media=disk,cache=none,aio=native,if=scsi,bus=0,unit=0,file=disk1.raw \&lt;br /&gt;
 -virtfs local,path=./packages/,security_model=none,mount_tag=hostpackages&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The install-dvd should boot, and then begin installation steps on the installer command line:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on install-dvd)&lt;br /&gt;
# mount the install-dvd&lt;br /&gt;
mkdir /dvd&lt;br /&gt;
mount /dev/sr0 /dvd&lt;br /&gt;
&lt;br /&gt;
# install coreutils, which provides the &amp;quot;hostid&amp;quot; command needed to load the spl module&lt;br /&gt;
installpkg /dvd/slackware64/a/coreutils-8.17-x86_64-1.txz&lt;br /&gt;
&lt;br /&gt;
# install kmod package which includes &amp;quot;depmod&amp;quot; command and others&lt;br /&gt;
installpkg /dvd/slackware64/a/kmod-9-x86_64-2.txz&lt;br /&gt;
depmod&lt;br /&gt;
&lt;br /&gt;
# install the full kernel modules so you can load 9p filesystem and use it if you want&lt;br /&gt;
# .. you might keep the zfs modules packages off the dvd and use a plain slack dvd&lt;br /&gt;
installpkg /dvd/slackware64/a/kernel-modules-*.txz&lt;br /&gt;
depmod&lt;br /&gt;
&lt;br /&gt;
# install bash and libtermcap because udev rules in zfs use bash scripts&lt;br /&gt;
installpkg /dvd/slackware64/a/bash-*.txz&lt;br /&gt;
installpkg /dvd/slackware64/l/libtermcap-*.txz&lt;br /&gt;
&lt;br /&gt;
# install spl and zfs that you have copied into the mirror before running the DVD creation&lt;br /&gt;
installpkg /dvd/addon/spl-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /dvd/addon/zfs-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
&lt;br /&gt;
#Or:&lt;br /&gt;
mkdir /packages&lt;br /&gt;
find /lib/modules/ | grep 9p&lt;br /&gt;
lsmod&lt;br /&gt;
# check that 9p modules load, mainly 9pnet_virtio&lt;br /&gt;
modprobe 9pnet_virtio&lt;br /&gt;
mount hostpackages -t 9p -o trans=virtio /packages&lt;br /&gt;
installpkg /packages/spl-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /packages/zfs-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
modprobe zfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now zfs tools: &amp;quot;zpool&amp;quot; and &amp;quot;zfs&amp;quot; should work in the live installer.&lt;br /&gt;
On the installer, there can be trouble seeing man pages, so install:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
installpkg /dvd/slackware64/ap/man-*.txz&lt;br /&gt;
installpkg /dvd/slackware64/ap/groff-*.txz&lt;br /&gt;
installpkg /dvd/slackware64/a/less-*.txz&lt;br /&gt;
export MANPATH=/usr/man:/usr/share/man&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The manual pages should be readable:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
man zpool&lt;br /&gt;
man zfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After seeing the man pages, we should be fully ready to continue to setup on ZFS.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(still on install-dvd)&lt;br /&gt;
ls -l /dev/sd*&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Make sure the disk devices you expect are there. We'll use sda and make boot (/boot on /dev/sda1) and root (/ on /dev/sda2) partitions.&lt;br /&gt;
&lt;br /&gt;
First, some background info: A ZFS filesystem is not supported by lilo as the filesystem containing /boot, which holds lilo's 2nd stage and the linux kernel files. The on-disk format of a ZFS filesystem is often a complex raid configuration where even if lilo understood ZFS it would likely require /boot to reside in only certain simple ZFS configurations to be plainly readable to lilo. As things are, a linux root installed in a partition with ZFS filesystem needs /boot to be on another partition with a filesystem that lilo understands, such as ext4 fs. In addition, because the spl and zfs modules are not built into the kernel, and the zfs startup requires some configuration to mount the zfs root, an initial ram/root filesystem (initrd) is needed. The initrd is a gzip compressed cpio archive file that contains a small linux root operating system that is decompressed into a ramfs block device at boot up and takes initial control of the system. The initrd contains an init script that configures devices in devtmpfs mounted at /dev. For example, if using mdadm, lvm, luks, losetup, and now zfs, this init script runs all the commands to create or start these devices (one of which is the root device), mounts the root device, and then transfers system control to the init script in the mounted root filesystem. The ramfs-based root environment on the booted install-dvd or booted initrd image (in rescue command line) are small slackware installations that exist only in ram and are temporary, but while inside them you can install, upgrade, and remove slackware packages inside them using the regular package management tools; this allows you access to any kernel modules and programs as needed inside these ramfs root. Packages can be installed, upgraded, or removed permanantly in the initrd image file to manage the programs and modules required during the initrd boot stage. Also from within these ramfs initial root environments, once the root device is mounted, chroot can be used to work on the mounted root system as if it were booted; this allows one to fix problems that are occuring in the root fs init scripts that cause normal booting to fail, or to install a kernel and/or modules etc. Now on to partitioning:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cgdisk /dev/sda&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, cgdisk looks just like cfdisk, but it makes GPT partitions.&lt;br /&gt;
&lt;br /&gt;
Make a partition for /boot that is about 512MiB of whatever partition type you like (8300 &amp;quot;Linux filesystem&amp;quot; is fine), or make it type bf07 &amp;quot;Solaris Reserved 1&amp;quot; if you want ZFS to maybe see the disk as if it was given as a whole disk to ZFS. Make a second partition using the remaining space with partition type bf01 &amp;quot;Solaris ZFS&amp;quot;. Currently, when ZFSonLinux is given a whole disk device like /dev/sdb to use, it will automatically GPT partition it with a bf01 partition #1 that is the whole disk except a small 8MiB type bf07 partition #9 at the end of the disk (/dev/sdb1 and /dev/sb9). The small 8MiB type bf07 partition #9 is mostly likely reserved for use by bootloaders, like lilo, to have a /boot or other boot-related files kept there. For example, you might have /dev/sda that is totally non-ZFS for booting and /dev/sdb passed to ZFS whole where it automatically partitions sdb, but you can just use one disk here and make partitions. Lets use type 8300 for /boot to be sure nothing is confused:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
We'll continue with this partitioning (numbers are in MiB):&lt;br /&gt;
  0 to   4: unused&lt;br /&gt;
  4 to 516: /dev/sda1 512MiB, type 8300&lt;br /&gt;
516 to 520: unused&lt;br /&gt;
520 to -96: /dev/sda2, type bf01&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The -96 means to count from the end of the disk so that 96MiB will remain unused at the end of the disk.&lt;br /&gt;
&lt;br /&gt;
Create a zpool called zfs-root:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool create -m none zfs-root /dev/sda2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A zpool created like this, the normal way, is a kernel-internal block device that contains already a zfs filesystem. There is normally no entry in /dev for this device. However, it can still be referenced as a mountable device similar to how devtmpfs, proc, and sysfs are also kernel-internal mountable block devices. The -m option told zpool not to automatically mount it anywhere, and without -m the default is to always automatically mount to /zfs-root. These kinds of details are explained better elsewhere. For this situation, we do not want it automounted.&lt;br /&gt;
&lt;br /&gt;
Because a zpool itself is a useable zfs fs, it has a full set of zfs &amp;quot;properties&amp;quot; to set options about the filesystem, perhaps similar to tune2fs. The &amp;quot;mountpoint=&amp;lt;some place to mount&amp;gt;&amp;quot; is one such property. We want it set to the special value &amp;quot;none&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs get mountpoint zfs-root&lt;br /&gt;
zfs set mountpoint=none zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On creation, the zpool zfs-pool is &amp;quot;imported&amp;quot; and has a zpool status that can be viewed:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool status zfs-root&lt;br /&gt;
&lt;br /&gt;
zpool export zfs-root&lt;br /&gt;
zpool status zfs-root&lt;br /&gt;
# Now there is no status.&lt;br /&gt;
&lt;br /&gt;
zpool import zfs-root&lt;br /&gt;
# Now it is back.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When a zpool is imported, it has it's current configuration cached in a file /etc/zfs/zpool.cache. When a zpool is exported, then it's entries in the cache file are removed and the cache file is deleted if it becomes empty. So long as the zfs kernel modules see this cache file and valid cache data inside it, ZFS considers the described zpools in the cache file to be valid as imported zpools. If the zpool.cache file is present at the time the zfs modules are loaded, then there is no further need to use the import and export commands at system startup and shutdown. With root on a zfs, it is not possible to export the pool that root is on, but this is not a problem. At shutdown, the safe procedure will be to set the zfs-root property readonly=on and sync disks.&lt;br /&gt;
&lt;br /&gt;
To avoid the requirement to import the zfs-root pool at startup, keep a copy of the zpool.cache file to later copy onto the initrd image to read at modules load time to have the pool reactived without need to issue the import command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/zfs/zpool.cache /etc/zfs/zpool.cache-initrd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A zfs fs will not normally allow you to mount over any files. The mountpoint is expected to be an empty directory. Remove any junk files inside the installer's /mnt because zfs won't mount over any files:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rm /mnt/README&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The directory /mnt is where the slackware setup expects you to mount your root for installation.&lt;br /&gt;
&lt;br /&gt;
Controlling whether a zfs fs is to be mounted read-only or read-write is best managed by setting the readonly property while it is not yet mounted:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set readonly=on zfs-root&lt;br /&gt;
zfs set readonly=off zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Slackware expects root to be mounted readonly when /etc/rc.S runs during normal startup, so later this is used to satisfy slackware's expectation to avoid rc.S complaining.&lt;br /&gt;
&lt;br /&gt;
The zfs-root can be mounted and unmounted in two different ways:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=/mnt zfs-root&lt;br /&gt;
zfs set mountpoint=none zfs-root&lt;br /&gt;
# or&lt;br /&gt;
mount zfs-root -t zfs /mnt&lt;br /&gt;
umount /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If it is already mounted and you want to change it to mount somewhere else, it is best to transition it to unmounted first, then mount it in the new place.&lt;br /&gt;
&lt;br /&gt;
The mount options &amp;lt;code&amp;gt;-o ro, -o rw, -o remount,ro, and -o remount,rw &amp;lt;/code&amp;gt; can also be used and will override &amp;lt;code&amp;gt;readonly=on|off&amp;lt;/code&amp;gt; property without altering the property value. This can be confusing until you are familiar with how to the methods of mounting interact.&lt;br /&gt;
&lt;br /&gt;
Now, let's continue some, and mount to /mnt using the current &amp;lt;code&amp;gt;readonly=off&amp;lt;/code&amp;gt; setting (rw mount):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=/mnt zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This method of mounting will show the most detailed mount options in /etc/mtab. They are the mount options that zfs thinks are proper, and they are probably what should be kept in /etc/fstab for zfs-root until we know better.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cat /etc/mtab &amp;gt;&amp;gt; /etc/fstab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now edit /etc/fstab to make sure it looks right, and remove the &amp;quot;rw&amp;quot; mount option, because we want to let it use a default for that, which will come from how we set the readonly= property most of the time. Unmount again:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=none zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mount again, now using all options from /etc/fstab:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It should be mounted at /mnt, and touch /mnt/t should allow you to make the file t. Then rm it: rm /mnt/t&lt;br /&gt;
For installation, we want to make sure it is mounted read-write. After installation, it should mount readonly inside the initrd.&lt;br /&gt;
&lt;br /&gt;
Sometimes there can be problems using the mount command, and then you can try it with the -i option:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 mount -i zfs-root &lt;br /&gt;
 mount -i zfs-root -t zfs /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
but, you should not have to use -i. When using -i makes it work, it performs an &amp;quot;internal-only&amp;quot; mount and does not use any mount.&amp;lt;fstype&amp;gt; helper scripts that might be on the system.&lt;br /&gt;
&lt;br /&gt;
Setup the /boot device:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkfs.ext4 /dev/sda1&lt;br /&gt;
mkdir /mnt/boot&lt;br /&gt;
mount /dev/sda1 /mnt/boot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We have both root and boot mounted where the slackware installer expects them. Unmount the dvd so setup can find it normally:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
umount /dev/sr0&lt;br /&gt;
setup&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the setup, skip straight to TARGET selection for the root device, but the setup doesn't see or understand the zfs-root, so it is not listed. This does not matter because we have mounted it already. Just skip down to a slot that say to continue, and continue on with setup. Because TARGET is skipped, you may not see the ADDITIONAL prompt (or if so, skip it too) where normally you give /dev/sda1 and have it mounted as /boot. This is also okay because we have mounted /mnt/boot already.&lt;br /&gt;
Because we did not give TARGET the root device or say what device /boot is on, the lilo installation will fail, or you can skip it. Otherwise, this installation process it normal.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
umount /dev/sr0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point, it is assumed that the setup has completed installing into /mnt. Congrats! You've installed slackware into a ZFS root!&lt;br /&gt;
&lt;br /&gt;
The next steps are to prepare to use &amp;quot;chroot /mnt&amp;quot; and finish up the configuration on the installed root system and then be able to reboot onto the completed installation. Before doing chroot, copy some files from the setup environment into /mnt.&lt;br /&gt;
&lt;br /&gt;
Copy the current installer /etc/fstab for later use inside the initrd. This fstab is what is proper inside the initrd, except remove option &amp;quot;rw&amp;quot; (if not done already).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/fstab /mnt/etc/fstab.initrd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The fstab.initrd will look like:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 proc /proc proc defaults 0 0&lt;br /&gt;
 zfs-root /mnt zfs defaults,atime,dev,exec,suid,xattr,nomand,zfsutil 0 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the initrd, we want zfs-root to mount to /mnt.&lt;br /&gt;
&lt;br /&gt;
Create /mnt/etc/fstab:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cat /etc/mtab &amp;gt;&amp;gt; /mnt/etc/fstab&lt;br /&gt;
vi /mnt/etc/fstab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using vi started above, edit /mnt/etc/fstab and make it have lines such as:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 zfs-root / zfs defaults,atime,dev,exec,suid,xattr,nomand,zfsutil 0 0&lt;br /&gt;
 /dev/sda1 /boot ext4 defaults 0 2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These two lines in &amp;lt;code&amp;gt;/mnt/etc/fstab&amp;lt;/code&amp;gt; are how the mounts should be looking when root is booted.&lt;br /&gt;
&lt;br /&gt;
Mount some special mounts before chroot:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount -t devtmpfs none /mnt/dev&lt;br /&gt;
mount -t proc none /mnt/proc&lt;br /&gt;
mount -t sysfs none /mnt/sys&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Make sure /boot is mounted:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount /dev/sda1 /mnt/boot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you had mounted a 9p fs share to access spl and zfs packages, then unmount that now:&lt;br /&gt;
umount /packages&lt;br /&gt;
&lt;br /&gt;
Ready, now:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chroot /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point, you should be on the installed system, and now try to configure mkinitrd and lilo. First, switch to use the generic kernel.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /boot&lt;br /&gt;
rm System.map config vmlinuz&lt;br /&gt;
ln -s System.map-gen* System.map&lt;br /&gt;
ln -s config-gen* config&lt;br /&gt;
ln -s vmlinuz-gen* vmlinuz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We install spl and zfs inside the live ramfs install-dvd environment, but not yet have we installed them into the root system:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount /dev/sr0 /mnt/cdrom&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /mnt/cdrom/addon/spl-*.txz&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /mnt/cdrom/addon/zfs-*.txz&lt;br /&gt;
depmod&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If instead, you used a 9p share to access the spl and zfs packages, then repeat that procedure here to install them onto the root system.&lt;br /&gt;
&lt;br /&gt;
Setup lilo: edit /etc/lilo.conf so it is like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  lba32&lt;br /&gt;
  append = &amp;quot; vt.default_utf8=1&amp;quot;&lt;br /&gt;
  boot = /dev/sda&lt;br /&gt;
  message = /boot/boot_message.txt&lt;br /&gt;
  prompt&lt;br /&gt;
  timeout = 1200&lt;br /&gt;
  change-rules&lt;br /&gt;
   reset&lt;br /&gt;
  vga = normal&lt;br /&gt;
  image = /boot/vmlinuz&lt;br /&gt;
   initrd = /boot/initrd.gz&lt;br /&gt;
   root = /dev/sda1&lt;br /&gt;
   label = vmlinuz&lt;br /&gt;
   read-only&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The line, root = /dev/sda1, is not really a true statement but lilo needs a device there that it at least understands. This root = line is a kernel parameter, but since the initrd is what is actually the root, initially, then the root = line is probably useless here. It might even be okay to just delete the root line.&lt;br /&gt;
&lt;br /&gt;
Setup mkinitrd:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/mkinitrd.conf.sample /etc/mkinitrd.conf&lt;br /&gt;
vi /etc/mkinitrd.conf&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Edit it to look like this (other defaults should be ok):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 MODULE_LIST=&amp;quot;sym53c8xx:ext4:8139cp:zfs:9p:9pnet_virtio&amp;quot;&lt;br /&gt;
 ROOTDEV=&amp;quot;zfs-root&amp;quot;&lt;br /&gt;
 ROOTFS=&amp;quot;zfs&amp;quot;&lt;br /&gt;
#Module sym53c8xx is the driver for qemu's if=scsi drive device.&lt;br /&gt;
#Module ext4 for /boot.&lt;br /&gt;
#Module 8139cp for eth0 net device.&lt;br /&gt;
#Module zfs for ZFSonLinux.&lt;br /&gt;
#Modules 9p and 9pnet_virtio for mounting qemu -virtfs mount_tag.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These 9p could be useful from the rescue command line inside the initrd to get needed files that are on the host.&lt;br /&gt;
&lt;br /&gt;
All dependent modules will also be included automatically into /boot/initrd-tree, which is packaged as /boot/initrd.gz. For example, to see the dependent modules of zfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
modprobe --show-depends zfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All listed modules will also be in the initrd. Now, make a /boot/initrd-tree that we can begin to look at and edit.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkinitrd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create an empty /etc/mtab or else zpool import fails (zfs expects /etc/mtab to exists already, it won't make it).&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
touch /boot/initrd-tree/etc/mtab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Copy in the fstab.initrd that was made earlier while on the installer. This provides all the mount options for a simple &amp;quot;mount zfs-root&amp;quot; onto /mnt.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/fstab.initrd /boot/initrd-tree/etc/fstab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More package installing! This time into an alternate root, the root of the initrd, /boot/initrd-tree. This is how you can put whatever packages you like into your initrd. These installations work independent of your normal installations. You can install, upgrade, and remove packages using an altroot:&lt;br /&gt;
&lt;br /&gt;
If spl and zfs are on your customized dvd:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/addon/spl-*.txz&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/addon/zfs-*.txz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Otherwise, repeat same procedure but you mount your 9p mount_tag and get them installed.&lt;br /&gt;
&lt;br /&gt;
More regular packages from the dvd:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/kmod-*.txz&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/coreutils-*.txz&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/gptfdisk-*.txz&lt;br /&gt;
&lt;br /&gt;
# A bash script is in /boot/initrd-tree/lib/udev/, so we need it or udev rules have problems:&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/bash-*.txz&lt;br /&gt;
# Bash needs this:&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/l/libtermcap-*.txz&lt;br /&gt;
&lt;br /&gt;
# Install net-tools to ensure that /etc/HOSTNAME, /etc/hosts, and potentially, /etc/hostid are handled proper.&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/n/net-tools-*.txz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When ZFS has to import a zpool while the initrd is running (this can be avoided by not exporting and keeping /etc/zfs/zpool.cache inside the initrd), ZFS will refuse to import a pool if it thinks that the pool may be in use by another system. ZFS was designed for network attached storage where multiple hosts might have access to the same disks but ZFS cannot support two hosts importing and using a ZFS pool at the same time. ZFS checks a value called &amp;quot;hostid&amp;quot; to determine this kind of conflict, and it can be a tricky issue with an initrd boot process. The value of hostid is returned by a system call, the gethostid() function or the hostid command. This function will return the hostid from /etc/hostid if that file exists and has a valid id in it, or else if the file doesn't exist it obtains a hostid number based on the hostname and ip address address assigned to hostname found in /etc/hosts or in DNS. If the hostid trying to import a pool is not the same as the hostid that imported it last time, ZFS will not import the pool unless &amp;quot;zpool import -f zfs-root&amp;quot; is used to force the import. This force option is not recommended to use, so it is best to configure your initrd with matching /etc/HOSTNAME and /etc/hosts as on the root installation and ensure what your system looks like on the initrd matches the booted root system.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Edit /boot/initrd-tree/init (this is the main system startup script on the initrd, responsibe for configuring your block devices and mount your root at /mnt and then booting root):&lt;br /&gt;
&lt;br /&gt;
Inside init, right near the top of the file after the PATH= line, add this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/bin/hostname -F /etc/HOSTNAME&lt;br /&gt;
/bin/hostname $( /bin/hostname -s )&lt;br /&gt;
#/sbin/chhostid 13371400&lt;br /&gt;
# you can make your hostid whatever, but this didn't work right with ZFS, so it is commented out&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This sets the name reported by the hostname command (the default is &amp;quot;darkstar&amp;quot;) to be what is contained in /etc/HOSTNAME. The hostname is modified in the next line to be the short name. These lines will help ZFS to properly identify your host when importing pools.&lt;br /&gt;
&lt;br /&gt;
Inside init, right after it runs &amp;quot;mdadm&amp;quot; commands as used for raid setup, we like it to setup ZFS, so add:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/sbin/zpool import zfs-root&lt;br /&gt;
/sbin/zfs set readonly=on zfs-root&lt;br /&gt;
mount zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Inside init, close to the bottom, where it &amp;quot;Switch to real root partition&amp;quot;, comment out 1 line that normally does the mount:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# mount -o ro -t $ROOTFS $ROOTDEV /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
We have already mounted, and we don't want to use any mount options because we should be using a properly set /etc/fstab inside the initrd for zfs-root mount options onto /mnt.&lt;br /&gt;
&lt;br /&gt;
During a normal startup we want a readonly mount.&lt;br /&gt;
&lt;br /&gt;
Note: we are going to setup with using zpool import and export and startup and shutdown. But later, you can experiment having /etc/zfs/zpool.cache stored in the initrd and commenting out zpool import/export lines.&lt;br /&gt;
&lt;br /&gt;
As mentioned, the import command may sometimes fail, and give the message: &amp;quot;pool may be in use from another system&amp;quot;. This is nothing serious in this test situation. When this happens, root will not be mounted to /mnt and the init script will detect this and drop you into a rescue command line where you may manually &amp;quot;import -f&amp;quot; then &amp;quot;mount zfs-root&amp;quot; and then &amp;quot;exit&amp;quot; to continue on to booting the root.&lt;br /&gt;
&lt;br /&gt;
To avoid this problem we copy some files in (assuming you first edit /etc/HOSTNAME to hold the hostname you like to see on your command prompts, and edited /etc/hosts to have hostname on your loopback or other local ip address):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/HOSTNAME /etc/hosts /boot/initrd-tree/etc&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The value reported by the hostid command is what ZFS sees as your hostid. In this setup so far, the value is based on the ip found assigned to your hostname. If your hostname is on the line in /etc/hosts for ip address 192.168.13.37, then your hostid will be hex numbers C0.A8.0D.25 rearranged as A8C0250D (pairs of bytes are swapped). That is ip-based hostid value, a 32bit hexadecimal number. This has to be the same each boot or import will need a -f option to force it. Simply setting the hostid using the system call sethostid() which writes a /etc/hostid file doesn't seem to agree with ZFS and you'd have to force the import, so this setup now assumes that you do not have or have deleted /etc/hostid.&lt;br /&gt;
&lt;br /&gt;
You can sometimes see what has been happening to a zpool by using the command &amp;quot;zpool history -li zfs-root&amp;quot; to see a log of commands.&lt;br /&gt;
&lt;br /&gt;
Once again, you can do away with the import and export commands by trying to have /etc/zfs/zpool.cache inside your initrd. To create zpool.cache, while on the installer or in the rescue shell of the initrd (at lilo &amp;quot;boot: vmlinuz rescue&amp;quot;), import only the pool for the root fs with mountpoint=none and readonly=on properties set and while it is not mounted:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on installer or initrd rescue shell)&lt;br /&gt;
cp /etc/zfs/zpool.cache /etc/zfs/zpool.cache-initrd&lt;br /&gt;
zfs set readonly=off zfs-root&lt;br /&gt;
mount zfs-pool&lt;br /&gt;
cp /etc/zfs/zpool.cache-initrd /mnt/etc/zfs/&lt;br /&gt;
cp /mnt/etc/zfs/zpool.cache-initrd /mnt/boot/initrd-tree/etc/zfs/zpool.cache&lt;br /&gt;
umount /mnt&lt;br /&gt;
zfs set readonly=on zfs-root&lt;br /&gt;
#mount zfs-root&lt;br /&gt;
#exit (to continue boot process onto rootfs mounted at /mnt)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, doing this zpool.cache approach is not necessary, and some talk suggests this is deprecated or discouraged. Although /etc/hostid setup fails to import without -f option, ip-based (hosts|dns) hostid works on booting and import works without -f option and may be the more proper way to do shutdown and startup rather than using a cache file which could be come invalid and cause a problem that is difficult to understand. The contents and exact function of the cache file are not well understood by many people.&lt;br /&gt;
&lt;br /&gt;
Save /boot/initrd-tree/init and exit.&lt;br /&gt;
&lt;br /&gt;
Now, edit /etc/rc.d/rc.S and rc.6 to understand how to &amp;quot;remount&amp;quot; rw or ro as a readonly property changes&lt;br /&gt;
&lt;br /&gt;
In /etc/rc.d/rc.S:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# comment out the line&lt;br /&gt;
#    /sbin/mount -w -v -n -o remount /&lt;br /&gt;
#add the line&lt;br /&gt;
     /sbin/zfs set readonly=off zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In /etc/rc.d/rc.6&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# comment out the line&lt;br /&gt;
#    /bin/mount -v -n -o remount,ro /&lt;br /&gt;
#add the line&lt;br /&gt;
     /sbin/zfs set readonly=on zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In /etc/rc.d/rc.6, near the bottom just before poweroff|reboot, add the following block of lines:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
########################&lt;br /&gt;
# Try to export zfs-root&lt;br /&gt;
/sbin/zpool export zfs-root&lt;br /&gt;
if [ $? -gt 0 ] ; then&lt;br /&gt;
 echo &amp;quot;ZFS export failed.&amp;quot;&lt;br /&gt;
 echo &amp;quot;Notice: if root fs is busy, then this is normal fail.&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;ZFS export successful.&amp;quot;&lt;br /&gt;
 echo &amp;quot;Warning: successful export is abnormal for root fs.&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
/bin/sleep 5&lt;br /&gt;
########################&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
For ZFS, you cannot run fsck on it. It doesn't support that kind of filesystem checks. The rc.S script will complain a lot in many places about not being about to run fsck on the zfs-root. To disable all attempts of run fsck, we can simple create a file that acts as a flag in /etc/rc.d/rc.S to tell it to skip fsck:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
touch /etc/fastboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This fastboot file is normally a run-once temporary file, and it is deleted near the bottom inside rc.S. Edit rc.S and stop it from deleting /etc/fastboot. We would like it to always skip all fsck. Edit /etc/rc.d/rc.S, and find the &amp;quot;rm&amp;quot; of fastboot, and do not have it removed!&lt;br /&gt;
&lt;br /&gt;
We are getting close, and have finished all editing, so make /boot/initrd.gz and install lilo:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkinitrd -F&lt;br /&gt;
lilo&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We finished! All that's left to do is clean up.&lt;br /&gt;
&lt;br /&gt;
Exit the chroot.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
exit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Try to mount everything:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
umount /mnt/proc&lt;br /&gt;
umount /mnt/sys&lt;br /&gt;
umount /mnt/dev&lt;br /&gt;
umount /mnt/boot&lt;br /&gt;
umount /mnt/mnt/cdrom&lt;br /&gt;
umount /mnt/root/packages&lt;br /&gt;
umount /mnt&lt;br /&gt;
zpool export zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note, that export stops a pool and frees devices, while import binds devices and starts a pool. It is somewhat like mdadm -A -s and mdadm -S -s, while /etc/zfs/zpool.cache might be somewhat like mdadm -E -s &amp;gt; /etc/mdadm.conf.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Remove the DVD or change boot order&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When you reboot, if all is good, you are booting properly onto a slackware installed on a ZFS root! Congrat!&lt;br /&gt;
&lt;br /&gt;
If this seem to go badly, and this might happen if the import fails as explain some before, then you will be on the initrd's rescue command line just before the part in it's init where it wants to mount and switch_root to boot your root. Instead, you typically got commands like this to do:&lt;br /&gt;
&lt;br /&gt;
If you get dumped to rescue because import will not work and requires -f (force), then:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 zpool import -f zfs-root&lt;br /&gt;
 zpool export    zfs-root&lt;br /&gt;
 zpool import    zfs-root&lt;br /&gt;
 mount zfs-root&lt;br /&gt;
 exit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This can happen if hostname, hostid, or uname changes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you get into a jam and need to boot into the initrd and skip zfs import etc, use the lilo prompt (or, boot the install-dvd):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
boot: vmlinuz rescue&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the rescue mode of the initrd, after you have mounted your root as readonly=on to /mnt, then exit to continue.&lt;br /&gt;
&lt;br /&gt;
In other emergency modes, you might need to run the lines at end of init starting from: &amp;lt;code&amp;gt;udevadm info --cleanup-db; udevadm control --exit&amp;lt;/code&amp;gt;&lt;br /&gt;
If you don't run those udevadm commands, two runs of udevd fight each other and it is slow; you have to wait 2 minutes twice for timeouts (4 minutes).&lt;br /&gt;
The last line is run is: &amp;lt;code&amp;gt;exec switch_root /mnt /sbin/init 1&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Warning... this switch_root command is kind of dangerous, so read the manual page about it.&lt;br /&gt;
From what I can tell, everything except the new root &amp;quot;/mnt&amp;quot; is deleted, so you are giving a command that says what NOT to delete!&lt;br /&gt;
Make sure nothing got mounted outside of &amp;quot;/mnt&amp;quot; before you run it.&lt;br /&gt;
&lt;br /&gt;
Also, in rescue or anytime you have finished making changes and are about to reboot in some abnormal mode, first run:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set readonly=on zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A bug in unpatched grep 2.13 build 1, found slackware 14.0rc1, causes problems when processing files stored on ZFS but rarely shows problems on other filesystems; the bug does not handle sparse files on zfs and btrfs correctly and results in chaos with slackpkg, compiling kernel modules, and possibly many other things. You must downgrade grep to 2.12 or use the patched grep 2.13 build 2 in slackware 14.0rc2 or later.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Upgrading.&lt;br /&gt;
&lt;br /&gt;
From time to time you will want to upgrade the kernel to the new kernel in slackware64-current or in patches/. This will also necessitate a rebuilt and reinstall or upgrade of spl and zfs. Below is an example of when both kernel and spl/zfs are being upgraded, to give an idea of the process:&lt;br /&gt;
&lt;br /&gt;
Using slackpkg, that is configured to use your local slackware mirror is a good option but you can also configure it to use a remote mirror.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slackpkg upgrade-all&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Assume slackpkg just upgraded your kernel, kernel-modules, and kernel-headers.&lt;br /&gt;
&lt;br /&gt;
Note: the first time you try to run on kernel-generic, setup kernel-huge in lilo as 2nd choice. Huge has all the hard drive controllers builtin, but generic has them all as modules. For example, run &amp;quot;modinfo mptsas&amp;quot; to see module options (maybe you have a LSISAS1068) for your hard drive controller. Add file /etc/modprobe.d/mptsas.conf to set options you want with a line: options mptsas ... Do this for all the device driver modules for your hardware. Do this setup while you are on the huge kernel, then setup to reboot to generic. Include all these modules you need into mkinitrd.conf MODULES_LIST. Check that /boot/initrd-tree/etc/modprobe.d/ has a copy of your customized module conf files because it is on the initrd where the modules will load and use the conf files. mkinitrd probably copies all /etc/modprobe.d/* files into the initrd-tree, but check it. Pay attention to /etc/modprobe.d/README and /lib/modprobe.d/* /lib/modprobe.d/* maybe not copied to initrd-tree but you might want to copy some of it into your initrd-tree yourself to use them.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Check that upgraded kernel-source is symlinked to /usr/src/linux (zfs build looks here). SQL/ZFS modules will install to the kernel version in /lib/modules/&amp;lt;/usr/src/linux kernel version&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /usr/local/src&lt;br /&gt;
tar xvzf ~/spl-*.tar.gz&lt;br /&gt;
tar xvzf ~/zfs-*.tar.gz&lt;br /&gt;
&lt;br /&gt;
###### upgrade spl 1st&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-*&lt;br /&gt;
./configure --prefix=/ --libexecdir=/usr/libexec --libdir=/lib64 --includedir=/usr/include --datarootdir=/usr/share&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=/usr/local/src/install&lt;br /&gt;
cd ../install&lt;br /&gt;
makepkg ../spl-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
upgradepkg spl-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
depmod &amp;lt;new kernel version&amp;gt;     (e.g. depmod 3.2.27, if .27 is new kernel upgrade; you currently run on old, maybe .26)&lt;br /&gt;
# this builds the module dependencies in /lib/modules/&amp;lt;new kernel version&amp;gt;&lt;br /&gt;
###### upgrade zfs 2nd&lt;br /&gt;
mkdir install&lt;br /&gt;
cd zfs-*&lt;br /&gt;
./configure --prefix=/ --libexecdir=/usr/libexec --libdir=/lib64 --includedir=/usr/include --datarootdir=/usr/share&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=/usr/local/src/install&lt;br /&gt;
cd ../install&lt;br /&gt;
makepkg ../zfs-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
upgradepkg zfs-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
depmod 3.2.27&lt;br /&gt;
####### upgrade spl/zfs inside altroot /boot/initrd-tree&lt;br /&gt;
ROOT=/boot/initrd-tree upgradepkg spl-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
ROOT=/boot/initrd-tree upgradepkg zfs-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
# note: ROOT is an environment variable, not a command line option to upgradepkg!&lt;br /&gt;
# note: do not worry about depmod inside initrd-tree, mkinitrd -F actually installs the modules&lt;br /&gt;
# note: this upgrade here is really to just upgrade the command line tools zpool, zfs etc&lt;br /&gt;
####### rebuild /boot/initrd.gz and reinstall lilo&lt;br /&gt;
vi /etc/mkinitrd.conf&lt;br /&gt;
# temporarily set KERNEL_VERSION to new version, but you are still running on old version&lt;br /&gt;
mkinitrd -F&lt;br /&gt;
lilo&lt;br /&gt;
vi /etc/mkinitrd.conf&lt;br /&gt;
# you can set KERNEL_VERSION back to $(uname r) now&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After reboot you can remove any old /lib/modules/&amp;lt;old kernel version&amp;gt; directory.&lt;br /&gt;
&lt;br /&gt;
More about /etc/hostid. If you want to experiment changing your /etc/hostid file and seeing if you can use it and make zpool import work normally, here is a tool that might be helpful:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/* software product name: foobarz-chhostid.c&lt;br /&gt;
 * suggested binary name: chhostid&lt;br /&gt;
 * license              : BSD&lt;br /&gt;
 * license text:&lt;br /&gt;
Copyright (c) 2012, foobarz&lt;br /&gt;
All rights reserved.&lt;br /&gt;
&lt;br /&gt;
Redistribution and use in source and binary forms, with or without&lt;br /&gt;
modification, are permitted provided that the following conditions are met:&lt;br /&gt;
    * Redistributions of source code must retain the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer.&lt;br /&gt;
    * Redistributions in binary form must reproduce the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer in the&lt;br /&gt;
      documentation and/or other materials provided with the distribution.&lt;br /&gt;
    * Neither the name of the &amp;lt;organization&amp;gt; nor the&lt;br /&gt;
      names of its contributors may be used to endorse or promote products&lt;br /&gt;
      derived from this software without specific prior written permission.&lt;br /&gt;
&lt;br /&gt;
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &amp;quot;AS IS&amp;quot; AND&lt;br /&gt;
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED&lt;br /&gt;
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE&lt;br /&gt;
DISCLAIMED. IN NO EVENT SHALL &amp;lt;COPYRIGHT HOLDER&amp;gt; BE LIABLE FOR ANY&lt;br /&gt;
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES&lt;br /&gt;
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;&lt;br /&gt;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND&lt;br /&gt;
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT&lt;br /&gt;
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS&lt;br /&gt;
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#define FOOBARZ_CHHOSTID_VERSION &amp;quot;1.0.5&amp;quot;&lt;br /&gt;
#include &amp;lt;sys/socket.h&amp;gt;&lt;br /&gt;
#include &amp;lt;netinet/in.h&amp;gt;&lt;br /&gt;
#include &amp;lt;arpa/inet.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;endian.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sysexits.h&amp;gt;&lt;br /&gt;
/* note: if include stdlib then sethostid fails even with _BSD_SOURCE defined */&lt;br /&gt;
&lt;br /&gt;
long swapbytes(long abcd) {&lt;br /&gt;
  long badc;&lt;br /&gt;
  unsigned char addr_a;&lt;br /&gt;
  unsigned char addr_b;&lt;br /&gt;
  unsigned char addr_c;&lt;br /&gt;
  unsigned char addr_d;&lt;br /&gt;
  addr_a = (unsigned char) (abcd &amp;gt;&amp;gt; 24);&lt;br /&gt;
  addr_b = (unsigned char) (abcd &amp;gt;&amp;gt; 16);&lt;br /&gt;
  addr_c = (unsigned char) (abcd &amp;gt;&amp;gt;  8);&lt;br /&gt;
  addr_d = (unsigned char) (abcd);&lt;br /&gt;
  return badc = ( (addr_b &amp;lt;&amp;lt; 24) | (addr_a &amp;lt;&amp;lt; 16) | (addr_d &amp;lt;&amp;lt; 8) | addr_c );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[])&lt;br /&gt;
{&lt;br /&gt;
 long newhostid;&lt;br /&gt;
 struct in_addr addr;&lt;br /&gt;
 char* invalidchar;&lt;br /&gt;
&lt;br /&gt;
 /*********** check command line */&lt;br /&gt;
 if(!( ((argc==3) &amp;amp;&amp;amp; ( (strcmp(argv[1],&amp;quot;-h&amp;quot;)==0) ||&lt;br /&gt;
                       (strcmp(argv[1],&amp;quot;-i&amp;quot;)==0) ||&lt;br /&gt;
                       (strcmp(argv[1],&amp;quot;-l&amp;quot;)==0) )) ||&lt;br /&gt;
       ((argc==2) &amp;amp;&amp;amp; ( (strcmp(argv[1],&amp;quot;-s&amp;quot;)==0) ))&lt;br /&gt;
     )&lt;br /&gt;
   ) {&lt;br /&gt;
                 /*01234567890123456789012345678901234567890123456789012345678901234567890123456789*/&lt;br /&gt;
  fprintf(stderr, &amp;quot;foobarz-chhostid, version %s. License: BSD.\n&amp;quot;, FOOBARZ_CHHOSTID_VERSION);&lt;br /&gt;
  fprintf(stderr, &amp;quot;foobarz-chhostid, (c) 2012, foobarz; all rights reserved.\n&amp;quot;);&lt;br /&gt;
  fprintf(stderr, &amp;quot;descr: %s change system hostid (in /etc/hostid).\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -h &amp;lt;new hostid&amp;gt;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        Change system hostid to &amp;lt;new hostid&amp;gt;;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        &amp;lt;new hostid&amp;gt; must be 32bit 8-digit hex number xxxxxxxx, each x in 0-f|F.\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        The ip corresponding to &amp;lt;new hostid&amp;gt; is also listed for reference only.\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -i &amp;lt;dotted ip address&amp;gt;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        Change system hostid to hostid corresponding to &amp;lt;dotted ip address&amp;gt;.\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -l &amp;lt;dotted ip address&amp;gt;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        List hostid corresponding to &amp;lt;dotted ip address&amp;gt;;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        no change to system hostid.\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -s\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        List current system hostid and corresponding ip address;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        no change to system hostid.\n&amp;quot;, argv[0]);&lt;br /&gt;
  return EX_USAGE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -h &amp;lt;hostid&amp;gt; */&lt;br /&gt;
 if( strcmp(argv[1],&amp;quot;-h&amp;quot;) == 0 ) {&lt;br /&gt;
  if(strlen(argv[2]) != 8) { fprintf(stderr, &amp;quot;new hostid must be 8-digit hex number xxxxxxxx, each x in 0-f|F\n&amp;quot;); return EX_USAGE; }&lt;br /&gt;
&lt;br /&gt;
  newhostid = strtol(argv[2],&amp;amp;invalidchar,16);&lt;br /&gt;
  if( newhostid==LONG_MIN ) { perror(&amp;quot;strtol (underflow)&amp;quot;); return EX_USAGE; }&lt;br /&gt;
  if( newhostid==LONG_MAX ) { perror(&amp;quot;strtol (overflow)&amp;quot;); return EX_USAGE; }&lt;br /&gt;
  if(*invalidchar != '\0') { fprintf(stderr, &amp;quot;invalid hex number %c; must be in 0-f|F\n&amp;quot;, *invalidchar); return EX_USAGE; }&lt;br /&gt;
&lt;br /&gt;
  if( sethostid(newhostid) != 0 ) {&lt;br /&gt;
   perror(&amp;quot;sethostid&amp;quot;);&lt;br /&gt;
   if( errno == EPERM ) return EX_NOPERM;&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
  }&lt;br /&gt;
  printf(&amp;quot;System hostid changed.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  /* hostid is a byte-swapped ip like b.a.d.c */&lt;br /&gt;
  /* get ip by swapping to correct order a.b.c.d and save into in_addr struct */&lt;br /&gt;
  addr.s_addr = htonl(swapbytes(newhostid));&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -i or -l, then find hostid for &amp;lt;dotted ip address&amp;gt; */&lt;br /&gt;
 if( (strcmp(argv[1],&amp;quot;-i&amp;quot;) == 0) || (strcmp(argv[1],&amp;quot;-l&amp;quot;) == 0) ) {&lt;br /&gt;
  if( inet_aton(argv[2], &amp;amp;addr) == 0 ) { fprintf(stderr, &amp;quot;inet_aton: invalid dotted ip address: %s\n&amp;quot;, argv[2]); return EX_USAGE; }&lt;br /&gt;
&lt;br /&gt;
  /* hostid is a byte-swapped ip like b.a.d.c */&lt;br /&gt;
  /* get hostid by swapping bytes of ip a.b.c.d */&lt;br /&gt;
  newhostid = swapbytes(ntohl(addr.s_addr));&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -i &amp;lt;dotted ip address&amp;gt; */&lt;br /&gt;
 if( strcmp(argv[1],&amp;quot;-i&amp;quot;) == 0 ) {&lt;br /&gt;
  if( sethostid(newhostid) != 0 ) {&lt;br /&gt;
   perror(&amp;quot;sethostid&amp;quot;);&lt;br /&gt;
   if( errno == EPERM ) return EX_NOPERM;&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
  }&lt;br /&gt;
  printf(&amp;quot;System hostid changed.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -l &amp;lt;dotted ip address&amp;gt; */&lt;br /&gt;
 if(strcmp(argv[1],&amp;quot;-l&amp;quot;) == 0 ) {&lt;br /&gt;
   printf(&amp;quot;Listing hostid for ip. (no changes)\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -s */&lt;br /&gt;
 if(strcmp(argv[1],&amp;quot;-s&amp;quot;) == 0 ) {&lt;br /&gt;
   /* see if /etc/hostid exists and print info */&lt;br /&gt;
   if( access(&amp;quot;/etc/hostid&amp;quot;, F_OK) != 0 ) {&lt;br /&gt;
     printf(&amp;quot;Notice: /etc/hostid does not exist.\n&amp;quot;);&lt;br /&gt;
     perror(&amp;quot;Reason&amp;quot;);&lt;br /&gt;
     printf(&amp;quot;System hostid derived from ip of hostname found in hosts file or dns.\n&amp;quot;);&lt;br /&gt;
   } else {&lt;br /&gt;
     printf(&amp;quot;Notice: /etc/hostid exists.\n&amp;quot;&lt;br /&gt;
            &amp;quot;System hostid is obtained from hostid file.\n&amp;quot;);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
  errno=0;&lt;br /&gt;
  newhostid = gethostid();&lt;br /&gt;
  if(errno!=0) { perror(&amp;quot;gethostid&amp;quot;); return EX_UNAVAILABLE; }&lt;br /&gt;
&lt;br /&gt;
  /* hostid is a byte-swapped ip like b.a.d.c */&lt;br /&gt;
  /* get ip by swapping to correct order a.b.c.d and save into in_addr struct */&lt;br /&gt;
  addr.s_addr = htonl(swapbytes(newhostid));&lt;br /&gt;
&lt;br /&gt;
  printf(&amp;quot;Listing current system hostid. (no changes)\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** print info and return */&lt;br /&gt;
 printf(&amp;quot;ip dot: %s\n&amp;quot;, inet_ntoa(addr) );&lt;br /&gt;
 printf(&amp;quot;ip hex: %.8x\n&amp;quot;, ntohl(addr.s_addr) );&lt;br /&gt;
 printf(&amp;quot;hostid: %.8x\n&amp;quot;, newhostid );&lt;br /&gt;
 return EX_OK;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</description>
			<pubDate>Sat, 18 Aug 2012 19:02:24 GMT</pubDate>
			<dc:creator>Foobarz</dc:creator>
			<comments>https://www.slackwiki.com/Talk:ZFS_root</comments>
		</item>
		<item>
			<title>ZFS root</title>
			<link>https://www.slackwiki.com/index.php?title=ZFS_root&amp;diff=734</link>
			<guid isPermaLink="false">https://www.slackwiki.com/index.php?title=ZFS_root&amp;diff=734</guid>
			<description>&lt;p&gt;Foobarz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;If you have heard about the ZFS filesystem and you're curious to try it out, then you can try it on slackware64, thanks to the ZFSonLinux.org project!&lt;br /&gt;
&lt;br /&gt;
In this article, an example is shown of how to install slackware64 14.0 onto a ZFS root filesystem (zfs-root) inside a QEMU virtual machine for testing purposes. It is recommended that you install qemu and learn how to use it to test a ZFS installation before you decide to use it on real hardware. A slackbuild for qemu can be found on slackbuilds.org. If you have a processor that supports Intel VT-x or AMD AMD-V virtualization acceleration (try modprobe kvm-intel or modprobe kvm-amd), then use the slackbuild for qemu-kvm.&lt;br /&gt;
&lt;br /&gt;
This article isn't going to go into any detail on actually using ZFS or what kinds of installation options and settings might be optimal. This article just presents an example of how to get started with ZFS on slackware.&lt;br /&gt;
&lt;br /&gt;
At this time of writing, ZFSonLinux is at &amp;quot;release candidate&amp;quot; (version 0.6.0-rc10) development stage, and many issues can occur. See the ZFSonLinux.org web site and the issues tracker for an idea about the current issues. There is also an irc channel on irc.freenode.net, #zfsonlinux, for discussion of issues and help.&lt;br /&gt;
&lt;br /&gt;
Although not required, it is helpful to keep a local mirror of slackware64 on your system. Having a local mirror makes it easier to upgrade to slackware64-current or to patches/* in a release. To help manage your own local slackware mirror and generate your own CD and DVD slackware installers, see http://alien.slackbook.org/blog/local-slackware-mirror/.&lt;br /&gt;
&lt;br /&gt;
In this article, we use a slackware64-current DVD image file as the qemu cdrom device media for the installation of the slackware guest. This was tested at slackware64-current = slackware64 14.0rc2. You can obtain a slackware DVD image using a torrent, buy the DVD from slackware.com, or generate your own DVD image file using the mirror script. For an actual DVD, you can pass your DVD device (e.g., /dev/sr0) as the qemu cdrom device. For a DVD image file, pass the image file as the qemu cdrom device.&lt;br /&gt;
&lt;br /&gt;
The ZFSonLinux packages are not included in slackware at this time. There are two packages involved: spl and zfs. The first, spl, is &amp;quot;Solaris Porting Layer&amp;quot; and must be installed on the system before zfs can be compiled. The source code tarballs for these are at ZFSonLinux.org. At this time of writing, they are spl-0.6.0-rc10.tar.gz and zfs-0.6.0-rc10.tar.gz.&lt;br /&gt;
&lt;br /&gt;
At this point, it is assumed you have qemu installed, have obtained a slackware64-current/14.0 DVD, and have downloaded spl and zfs tarballs to your host system. The first step now is, if your host is not slackware64-current/14.0 (the same as the guest will be), then you need to create a minimal development slackware64 guest system in qemu for just the purpose of compiling and packaging the spl and zfs slackware packages and transferring a copy of these packages back onto your host system to use later to install onto zfs during the slackware install process.&lt;br /&gt;
&lt;br /&gt;
From this point onward, instructions become a bit terse and mostly limited to examples of the commands you might use to complete tasks. You are encouraged to examine what each command does by reading the command's man pages. For example, the command &amp;quot;man qemu&amp;quot; can show you most of what you need to know about running qemu on the command line.&lt;br /&gt;
&lt;br /&gt;
So, here's an example of how you might build the spl and zfs packages, starting in your home directory:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on host)&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir qemu&lt;br /&gt;
cd qemu&lt;br /&gt;
mkdir slackdevel&lt;br /&gt;
cd slackdevel&lt;br /&gt;
mkdir packages&lt;br /&gt;
cp ~/spl-*.tar.gz packages&lt;br /&gt;
cp ~/zfs-*.tar.gz packages&lt;br /&gt;
qemu-img create disk1.raw 10G&lt;br /&gt;
ln -s ~/slackware64-current-install-dvd.iso dvd.iso&lt;br /&gt;
qemu-system-x86_64 \&lt;br /&gt;
 -no-quit \&lt;br /&gt;
 -no-shutdown \&lt;br /&gt;
 -boot order=cd,menu=on \&lt;br /&gt;
 -m 2G \&lt;br /&gt;
 -cpu host \&lt;br /&gt;
 -smp sockets=1,cores=4 \&lt;br /&gt;
 -net nic,model=rtl8139 -net user \&lt;br /&gt;
 -cdrom dvd.iso \&lt;br /&gt;
 -drive boot=on,format=raw,media=disk,cache=none,aio=native,if=scsi,bus=0,unit=0,file=disk1.raw \&lt;br /&gt;
 -virtfs local,path=./packages/,security_model=none,mount_tag=hostpackages&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When you need to change boot to cd or disk, add or remove &amp;quot;boot=on&amp;quot;, or change &amp;quot;order=dc&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Qemu should boot into the install-dvd, and now perform a very ordinary slackware64 install onto /dev/sda. Install d package set and most others, but package sets x, kde, xfce not really needed.&lt;br /&gt;
&lt;br /&gt;
First note: examples here use tools from the gptfdisk package (gdisk, sgdisk, cgdisk) to partition the disk with GUID partition table (GPT) format. GPT might not be too familiar to everyone, who mostly have only used MBR partitions with fdisk. In the slackware installations this author has tested in qemu, using GPT partitions has caused no problems with lilo or other tools used in slackware. GPT disk labels support creating up to 128 partitions and support disks larger than 2TB (the limit of MBR fdisk). LILO installs into the first 440 bytes on /dev/sda, inside a GPT &amp;quot;protective MBR&amp;quot; that serves to provide compatibility with MBR bootloaders like lilo. LILO uses LBA32 sector addressing and can see all 512-byte sectors side the first 2TB of a disk. So long as the /boot partition is within the first 2TB of a disk, lilo can work on a disk larger than 2TB. Unlike the common default of fdisk to start the first partition at sector 63, which is not aligned with the 4KiB sector size of Advanced Format hard disks, gdisk's default is to start partitions at 2048 sector (1MiB) boundaries which are also 4KiB aligned. Using gdisk GPT works on all disks and is compatible with using Advanced Format hard disks larger than 2TB. More information about GPT disk label format can be found on wikipedia.org. For those that have used grub instead of lilo, grub installation is different with GPT than with MBR, and grub requires a GPT partition of type grub-bios or 0xEF02 &amp;quot;BIOS Boot Partition&amp;quot; of about 8MiB where it can install it's additional bootloader stages because grub cannot embed in sectors 1-62 on GPT where GPT keeps it's partition tables. On MBR, sectors 1-62 were normally reserved space for bootloaders to keep a 2nd stage.&lt;br /&gt;
&lt;br /&gt;
For this purpose of development guest, just create a simple 1-partition system, /dev/sda1, and do a simple slackware install on it. Don't bother with swap or separate /boot unless you want to:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on install-dvd)&lt;br /&gt;
cgdisk /dev/sda&lt;br /&gt;
setup&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When this simple development guest boots, login as root, and continue:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on qemu guest)&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir packages&lt;br /&gt;
mount hostpackages -t 9p -o trans=virtio packages&lt;br /&gt;
echo --prefix=/ --libexecdir=/usr/libexec --libdir=/lib64 --includedir=/usr/include --datarootdir=/usr/share &amp;gt; configure-options&lt;br /&gt;
mkdir src&lt;br /&gt;
cd src&lt;br /&gt;
&lt;br /&gt;
mkdir install&lt;br /&gt;
tar xvzf ~/packages/spl-*.tar.gz&lt;br /&gt;
cd spl-*&lt;br /&gt;
./configure $( cat ~/configure-options )&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../spl-&amp;lt;version&amp;gt;_&amp;lt;kernel_version&amp;gt;-x86_64-&amp;lt;build_id&amp;gt;.txz&lt;br /&gt;
(e.g., makepkg ../spl-0.6.0rc10_3.2.27-x86_64-1root.txz)&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
installpkg spl-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
cp spl-0.6.0rc10_3.2.27-x86_64-1root.txz ~/packages&lt;br /&gt;
&lt;br /&gt;
mkdir install&lt;br /&gt;
tar xvzf ~/packages/zfs-*.tar.gz&lt;br /&gt;
cd zfs-*&lt;br /&gt;
./configure $( cat ~/configure-options )&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../zfs-&amp;lt;version&amp;gt;_&amp;lt;kernel_version&amp;gt;-x86_64-&amp;lt;build_id&amp;gt;.txz&lt;br /&gt;
(e.g., makepkg ../zfs-0.6.0rc10_3.2.27-x86_64-1root.txz)&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
installpkg zfs-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
cp zfs-0.6.0rc10_3.2.27-x86_64-1root.txz ~/packages&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point spl and zfs packages are copied back to the host in the packages directory. Also, spl and zfs are installed in this simple development guest, so one could begin to experiment with zfs pools and datasets but while the root fs is whatever you made it during setup (probably the default, ext4). This development guest isn't really needed anymore, so it can be deleted:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
halt&lt;br /&gt;
(exit qemu: ctrl-alt-2 then enter quit at QEMU command prompt)&lt;br /&gt;
&lt;br /&gt;
(on host)&lt;br /&gt;
rm disk1.raw dvd.iso&lt;br /&gt;
mv packages ..&lt;br /&gt;
cd ..&lt;br /&gt;
rmdir slackdevel&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now that we have the spl and zfs packages on the host, it is possible to copy them into your local slackware64 mirror and then generate your own install DVD image that includes them. For example, change to the directory that contains the slackware README files, and create a &amp;quot;addon&amp;quot; directory and copy the spl and zfs slackware packages into there. Then, generate the DVD image using a command such as $( ./mirror-slackware-current.sh -i ) from where you have this script configured to maintain your local mirror. We can also just continue to access them inside the installer using qemu's virtfs option. When you are going to do a real installation onto real hardware, you need to generate and burn your own DVD that includes the packages.&lt;br /&gt;
&lt;br /&gt;
It is time to begin the installation of slackware64 on a ZFS root, assuming either you have regenerated dvd.iso with zfs packages in addon/* or we access the zfs packages while in the installer using qemu's virtfs to the host's packages directory. ZFS supports creating complex data storage configurations such as pools (similar to a volume group) backed by one or more of various kinds of virtual devices (similar to disks and raid arrays) and containing one or more datasets (similar to mounted filesystems, logical volume devices, or snapshots). But here, we keep it simple and will install on just a single disk device. On a real ZFS installation, users will typically want to use the ZFS raidz1 or raidz2 virtual device types for reliability against hard drive failures.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on host)&lt;br /&gt;
mkdir slackzfs&lt;br /&gt;
mv packages slackzfs/&lt;br /&gt;
cd slackzfs&lt;br /&gt;
qemu-img create disk1.raw 10G&lt;br /&gt;
ln -s ~/slackware64-current-install-dvd.iso dvd.iso&lt;br /&gt;
qemu-system-x86_64 \&lt;br /&gt;
 -no-quit \&lt;br /&gt;
 -no-shutdown \&lt;br /&gt;
 -boot order=cd,menu=on \&lt;br /&gt;
 -m 2G \&lt;br /&gt;
 -cpu host \&lt;br /&gt;
 -smp sockets=1,cores=4 \&lt;br /&gt;
 -net nic,model=rtl8139 -net user \&lt;br /&gt;
 -cdrom dvd.iso \&lt;br /&gt;
 -drive boot=on,format=raw,media=disk,cache=none,aio=native,if=scsi,bus=0,unit=0,file=disk1.raw \&lt;br /&gt;
 -virtfs local,path=./packages/,security_model=none,mount_tag=hostpackages&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The install-dvd should boot, and then begin installation steps on the installer command line:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on install-dvd)&lt;br /&gt;
# mount the install-dvd&lt;br /&gt;
mkdir /dvd&lt;br /&gt;
mount /dev/sr0 /dvd&lt;br /&gt;
&lt;br /&gt;
# install coreutils, which provides the &amp;quot;hostid&amp;quot; command needed to load the spl module&lt;br /&gt;
installpkg /dvd/slackware64/a/coreutils-8.17-x86_64-1.txz&lt;br /&gt;
&lt;br /&gt;
# install kmod package which includes &amp;quot;depmod&amp;quot; command and others&lt;br /&gt;
installpkg /dvd/slackware64/a/kmod-9-x86_64-2.txz&lt;br /&gt;
depmod&lt;br /&gt;
&lt;br /&gt;
# install the full kernel modules so you can load 9p filesystem and use it if you want&lt;br /&gt;
# .. you might keep the zfs modules packages off the dvd and use a plain slack dvd&lt;br /&gt;
installpkg /dvd/slackware64/a/kernel-modules-*.txz&lt;br /&gt;
depmod&lt;br /&gt;
&lt;br /&gt;
# install bash and libtermcap because udev rules in zfs use bash scripts&lt;br /&gt;
installpkg /dvd/slackware64/a/bash-*.txz&lt;br /&gt;
installpkg /dvd/slackware64/l/libtermcap-*.txz&lt;br /&gt;
&lt;br /&gt;
# install spl and zfs that you have copied into the mirror before running the DVD creation&lt;br /&gt;
installpkg /dvd/addon/spl-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /dvd/addon/zfs-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
&lt;br /&gt;
#Or:&lt;br /&gt;
mkdir /packages&lt;br /&gt;
find /lib/modules/ | grep 9p&lt;br /&gt;
lsmod&lt;br /&gt;
# check that 9p modules load, mainly 9pnet_virtio&lt;br /&gt;
modprobe 9pnet_virtio&lt;br /&gt;
mount hostpackages -t 9p -o trans=virtio /packages&lt;br /&gt;
installpkg /packages/spl-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /packages/zfs-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
modprobe zfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now zfs tools: &amp;quot;zpool&amp;quot; and &amp;quot;zfs&amp;quot; should work in the live installer.&lt;br /&gt;
On the installer, there can be trouble seeing man pages, so install:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
installpkg /dvd/slackware64/ap/man-*.txz&lt;br /&gt;
installpkg /dvd/slackware64/ap/groff-*.txz&lt;br /&gt;
installpkg /dvd/slackware64/a/less-*.txz&lt;br /&gt;
export MANPATH=/usr/man:/usr/share/man&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The manual pages should be readable:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
man zpool&lt;br /&gt;
man zfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After seeing the man pages, we should be fully ready to continue to setup on ZFS.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(still on install-dvd)&lt;br /&gt;
ls -l /dev/sd*&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Make sure the disk devices you expect are there. We'll use sda and make boot (/boot on /dev/sda1) and root (/ on /dev/sda2) partitions.&lt;br /&gt;
&lt;br /&gt;
First, some background info: A ZFS filesystem is not supported by lilo as the filesystem containing /boot, which holds lilo's 2nd stage and the linux kernel files. The on-disk format of a ZFS filesystem is often a complex raid configuration where even if lilo understood ZFS it would likely require /boot to reside in only certain simple ZFS configurations to be plainly readable to lilo. As things are, a linux root installed in a partition with ZFS filesystem needs /boot to be on another partition with a filesystem that lilo understands, such as ext4 fs. In addition, because the spl and zfs modules are not built into the kernel, and the zfs startup requires some configuration to mount the zfs root, an initial ram/root filesystem (initrd) is needed. The initrd is a gzip compressed cpio archive file that contains a small linux root operating system that is decompressed into a ramfs block device at boot up and takes initial control of the system. The initrd contains an init script that configures devices in devtmpfs mounted at /dev. For example, if using mdadm, lvm, luks, losetup, and now zfs, this init script runs all the commands to create or start these devices (one of which is the root device), mounts the root device, and then transfers system control to the init script in the mounted root filesystem. The ramfs-based root environment on the booted install-dvd or booted initrd image (in rescue command line) are small slackware installations that exist only in ram and are temporary, but while inside them you can install, upgrade, and remove slackware packages inside them using the regular package management tools; this allows you access to any kernel modules and programs as needed inside these ramfs root. Packages can be installed, upgraded, or removed permanantly in the initrd image file to manage the programs and modules required during the initrd boot stage. Also from within these ramfs initial root environments, once the root device is mounted, chroot can be used to work on the mounted root system as if it were booted; this allows one to fix problems that are occuring in the root fs init scripts that cause normal booting to fail, or to install a kernel and/or modules etc. Now on to partitioning:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cgdisk /dev/sda&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, cgdisk looks just like cfdisk, but it makes GPT partitions.&lt;br /&gt;
&lt;br /&gt;
Make a partition for /boot that is about 512MiB of whatever partition type you like (8300 &amp;quot;Linux filesystem&amp;quot; is fine), or make it type bf07 &amp;quot;Solaris Reserved 1&amp;quot; if you want ZFS to maybe see the disk as if it was given as a whole disk to ZFS. Make a second partition using the remaining space with partition type bf01 &amp;quot;Solaris ZFS&amp;quot;. Currently, when ZFSonLinux is given a whole disk device like /dev/sdb to use, it will automatically GPT partition it with a bf01 partition #1 that is the whole disk except a small 8MiB type bf07 partition #9 at the end of the disk (/dev/sdb1 and /dev/sb9). The small 8MiB type bf07 partition #9 is mostly likely reserved for use by bootloaders, like lilo, to have a /boot or other boot-related files kept there. For example, you might have /dev/sda that is totally non-ZFS for booting and /dev/sdb passed to ZFS whole where it automatically partitions sdb, but you can just use one disk here and make partitions. Lets use type 8300 for /boot to be sure nothing is confused:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
We'll continue with this partitioning (numbers are in MiB):&lt;br /&gt;
  0 to   4: unused&lt;br /&gt;
  4 to 516: /dev/sda1 512MiB, type 8300&lt;br /&gt;
516 to 520: unused&lt;br /&gt;
520 to -96: /dev/sda2, type bf01&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The -96 means to count from the end of the disk so that 96MiB will remain unused at the end of the disk.&lt;br /&gt;
&lt;br /&gt;
Create a zpool called zfs-root:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool create -m none zfs-root /dev/sda2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A zpool created like this, the normal way, is a kernel-internal block device that contains already a zfs filesystem. There is normally no entry in /dev for this device. However, it can still be referenced as a mountable device similar to how devtmpfs, proc, and sysfs are also kernel-internal mountable block devices. The -m option told zpool not to automatically mount it anywhere, and without -m the default is to always automatically mount to /zfs-root. These kinds of details are explained better elsewhere. For this situation, we do not want it automounted.&lt;br /&gt;
&lt;br /&gt;
Because a zpool itself is a useable zfs fs, it has a full set of zfs &amp;quot;properties&amp;quot; to set options about the filesystem, perhaps similar to tune2fs. The &amp;quot;mountpoint=&amp;lt;some place to mount&amp;gt;&amp;quot; is one such property. We want it set to the special value &amp;quot;none&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs get mountpoint zfs-root&lt;br /&gt;
zfs set mountpoint=none zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On creation, the zpool zfs-pool is &amp;quot;imported&amp;quot; and has a zpool status that can be viewed:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool status zfs-root&lt;br /&gt;
&lt;br /&gt;
zpool export zfs-root&lt;br /&gt;
zpool status zfs-root&lt;br /&gt;
# Now there is no status.&lt;br /&gt;
&lt;br /&gt;
zpool import zfs-root&lt;br /&gt;
# Now it is back.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When a zpool is imported, it has it's current configuration cached in a file /etc/zfs/zpool.cache. When a zpool is exported, then it's entries in the cache file are removed and the cache file is deleted if it becomes empty. So long as the zfs kernel modules see this cache file and valid cache data inside it, ZFS considers the described zpools in the cache file to be valid as imported zpools. If the zpool.cache file is present at the time the zfs modules are loaded, then there is no further need to use the import and export commands at system startup and shutdown. With root on a zfs, it is not possible to export the pool that root is on, but this is not a problem. At shutdown, the safe procedure will be to set the zfs-root property readonly=on and sync disks.&lt;br /&gt;
&lt;br /&gt;
To avoid the requirement to import the zfs-root pool at startup, keep a copy of the zpool.cache file to later copy onto the initrd image to read at modules load time to have the pool reactived without need to issue the import command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/zfs/zpool.cache /etc/zfs/zpool.cache-initrd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A zfs fs will not normally allow you to mount over any files. The mountpoint is expected to be an empty directory. Remove any junk files inside the installer's /mnt because zfs won't mount over any files:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rm /mnt/README&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The directory /mnt is where the slackware setup expects you to mount your root for installation.&lt;br /&gt;
&lt;br /&gt;
Controlling whether a zfs fs is to be mounted read-only or read-write is best managed by setting the readonly property while it is not yet mounted:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set readonly=on zfs-root&lt;br /&gt;
zfs set readonly=off zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Slackware expects root to be mounted readonly when /etc/rc.S runs during normal startup, so later this is used to satisfy slackware's expectation to avoid rc.S complaining.&lt;br /&gt;
&lt;br /&gt;
The zfs-root can be mounted and unmounted in two different ways:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=/mnt zfs-root&lt;br /&gt;
zfs set mountpoint=none zfs-root&lt;br /&gt;
# or&lt;br /&gt;
mount zfs-root -t zfs /mnt&lt;br /&gt;
umount /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If it is already mounted and you want to change it to mount somewhere else, it is best to transition it to unmounted first, then mount it in the new place.&lt;br /&gt;
&lt;br /&gt;
The mount options &amp;lt;code&amp;gt;-o ro, -o rw, -o remount,ro, and -o remount,rw &amp;lt;/code&amp;gt; can also be used and will override &amp;lt;code&amp;gt;readonly=on|off&amp;lt;/code&amp;gt; property without altering the property value. This can be confusing until you are familiar with how to the methods of mounting interact.&lt;br /&gt;
&lt;br /&gt;
Now, let's continue some, and mount to /mnt using the current &amp;lt;code&amp;gt;readonly=off&amp;lt;/code&amp;gt; setting (rw mount):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=/mnt zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This method of mounting will show the most detailed mount options in /etc/mtab. They are the mount options that zfs thinks are proper, and they are probably what should be kept in /etc/fstab for zfs-root until we know better.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cat /etc/mtab &amp;gt;&amp;gt; /etc/fstab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now edit /etc/fstab to make sure it looks right, and remove the &amp;quot;rw&amp;quot; mount option, because we want to let it use a default for that, which will come from how we set the readonly= property most of the time. Unmount again:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=none zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mount again, now using all options from /etc/fstab:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It should be mounted at /mnt, and touch /mnt/t should allow you to make the file t. Then rm it: rm /mnt/t&lt;br /&gt;
For installation, we want to make sure it is mounted read-write. After installation, it should mount readonly inside the initrd.&lt;br /&gt;
&lt;br /&gt;
Sometimes there can be problems using the mount command, and then you can try it with the -i option:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 mount -i zfs-root &lt;br /&gt;
 mount -i zfs-root -t zfs /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
but, you should not have to use -i. When using -i makes it work, it performs an &amp;quot;internal-only&amp;quot; mount and does not use any mount.&amp;lt;fstype&amp;gt; helper scripts that might be on the system.&lt;br /&gt;
&lt;br /&gt;
Setup the /boot device:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkfs.ext4 /dev/sda1&lt;br /&gt;
mkdir /mnt/boot&lt;br /&gt;
mount /dev/sda1 /mnt/boot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We have both root and boot mounted where the slackware installer expects them. Unmount the dvd so setup can find it normally:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
umount /dev/sr0&lt;br /&gt;
setup&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the setup, skip straight to TARGET selection for the root device, but the setup doesn't see or understand the zfs-root, so it is not listed. This does not matter because we have mounted it already. Just skip down to a slot that say to continue, and continue on with setup. Because TARGET is skipped, you may not see the ADDITIONAL prompt (or if so, skip it too) where normally you give /dev/sda1 and have it mounted as /boot. This is also okay because we have mounted /mnt/boot already.&lt;br /&gt;
Because we did not give TARGET the root device or say what device /boot is on, the lilo installation will fail, or you can skip it. Otherwise, this installation process it normal.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
umount /dev/sr0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point, it is assumed that the setup has completed installing into /mnt. Congrats! You've installed slackware into a ZFS root!&lt;br /&gt;
&lt;br /&gt;
The next steps are to prepare to use &amp;quot;chroot /mnt&amp;quot; and finish up the configuration on the installed root system and then be able to reboot onto the completed installation. Before doing chroot, copy some files from the setup environment into /mnt.&lt;br /&gt;
&lt;br /&gt;
Copy the current installer /etc/fstab for later use inside the initrd. This fstab is what is proper inside the initrd, except remove option &amp;quot;rw&amp;quot; (if not done already).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/fstab /mnt/etc/fstab.initrd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The fstab.initrd will look like:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 proc /proc proc defaults 0 0&lt;br /&gt;
 zfs-root /mnt zfs defaults,atime,dev,exec,suid,xattr,nomand,zfsutil 0 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the initrd, we want zfs-root to mount to /mnt.&lt;br /&gt;
&lt;br /&gt;
Create /mnt/etc/fstab:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cat /etc/mtab &amp;gt;&amp;gt; /mnt/etc/fstab&lt;br /&gt;
vi /mnt/etc/fstab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using vi started above, edit /mnt/etc/fstab and make it have lines such as:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 zfs-root / zfs defaults,atime,dev,exec,suid,xattr,nomand,zfsutil 0 0&lt;br /&gt;
 /dev/sda1 /boot ext4 defaults 0 2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These two lines in &amp;lt;code&amp;gt;/mnt/etc/fstab&amp;lt;/code&amp;gt; are how the mounts should be looking when root is booted.&lt;br /&gt;
&lt;br /&gt;
Mount some special mounts before chroot:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount -t devtmpfs none /mnt/dev&lt;br /&gt;
mount -t proc none /mnt/proc&lt;br /&gt;
mount -t sysfs none /mnt/sys&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Make sure /boot is mounted:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount /dev/sda1 /mnt/boot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you had mounted a 9p fs share to access spl and zfs packages, then unmount that now:&lt;br /&gt;
umount /packages&lt;br /&gt;
&lt;br /&gt;
Ready, now:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chroot /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point, you should be on the installed system, and now try to configure mkinitrd and lilo. First, switch to use the generic kernel.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /boot&lt;br /&gt;
rm System.map config vmlinuz&lt;br /&gt;
ln -s System.map-gen* System.map&lt;br /&gt;
ln -s config-gen* config&lt;br /&gt;
ln -s vmlinuz-gen* vmlinuz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We install spl and zfs inside the live ramfs install-dvd environment, but not yet have we installed them into the root system:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount /dev/sr0 /mnt/cdrom&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /mnt/cdrom/addon/spl-*.txz&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /mnt/cdrom/addon/zfs-*.txz&lt;br /&gt;
depmod&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If instead, you used a 9p share to access the spl and zfs packages, then repeat that procedure here to install them onto the root system.&lt;br /&gt;
&lt;br /&gt;
Setup lilo: edit /etc/lilo.conf so it is like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  lba32&lt;br /&gt;
  append = &amp;quot; vt.default_utf8=1&amp;quot;&lt;br /&gt;
  boot = /dev/sda&lt;br /&gt;
  message = /boot/boot_message.txt&lt;br /&gt;
  prompt&lt;br /&gt;
  timeout = 1200&lt;br /&gt;
  change-rules&lt;br /&gt;
   reset&lt;br /&gt;
  vga = normal&lt;br /&gt;
  image = /boot/vmlinuz&lt;br /&gt;
   initrd = /boot/initrd.gz&lt;br /&gt;
   root = /dev/sda1&lt;br /&gt;
   label = vmlinuz&lt;br /&gt;
   read-only&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The line, root = /dev/sda1, is not really a true statement but lilo needs a device there that it at least understands. This root = line is a kernel parameter, but since the initrd is what is actually the root, initially, then the root = line is probably useless here. It might even be okay to just delete the root line.&lt;br /&gt;
&lt;br /&gt;
Setup mkinitrd:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/mkinitrd.conf.sample /etc/mkinitrd.conf&lt;br /&gt;
vi /etc/mkinitrd.conf&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Edit it to look like this (other defaults should be ok):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 MODULE_LIST=&amp;quot;sym53c8xx:ext4:8139cp:zfs:9p:9pnet_virtio&amp;quot;&lt;br /&gt;
 ROOTDEV=&amp;quot;zfs-root&amp;quot;&lt;br /&gt;
 ROOTFS=&amp;quot;zfs&amp;quot;&lt;br /&gt;
#Module sym53c8xx is the driver for qemu's if=scsi drive device.&lt;br /&gt;
#Module ext4 for /boot.&lt;br /&gt;
#Module 8139cp for eth0 net device.&lt;br /&gt;
#Module zfs for ZFSonLinux.&lt;br /&gt;
#Modules 9p and 9pnet_virtio for mounting qemu -virtfs mount_tag.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These 9p could be useful from the rescue command line inside the initrd to get needed files that are on the host.&lt;br /&gt;
&lt;br /&gt;
All dependent modules will also be included automatically into /boot/initrd-tree, which is packaged as /boot/initrd.gz. For example, to see the dependent modules of zfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
modprobe --show-depends zfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All listed modules will also be in the initrd. Now, make a /boot/initrd-tree that we can begin to look at and edit.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkinitrd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create an empty /etc/mtab or else zpool import fails (zfs expects /etc/mtab to exists already, it won't make it).&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
touch /boot/initrd-tree/etc/mtab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Copy in the fstab.initrd that was made earlier while on the installer. This provides all the mount options for a simple &amp;quot;mount zfs-root&amp;quot; onto /mnt.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/fstab.initrd /boot/initrd-tree/etc/fstab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More package installing! This time into an alternate root, the root of the initrd, /boot/initrd-tree. This is how you can put whatever packages you like into your initrd. These installations work independent of your normal installations. You can install, upgrade, and remove packages using an altroot:&lt;br /&gt;
&lt;br /&gt;
If spl and zfs are on your customized dvd:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/addon/spl-*.txz&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/addon/zfs-*.txz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Otherwise, repeat same procedure but you mount your 9p mount_tag and get them installed.&lt;br /&gt;
&lt;br /&gt;
More regular packages from the dvd:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/kmod-*.txz&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/coreutils-*.txz&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/gptfdisk-*.txz&lt;br /&gt;
&lt;br /&gt;
# A bash script is in /boot/initrd-tree/lib/udev/, so we need it or udev rules have problems:&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/bash-*.txz&lt;br /&gt;
# Bash needs this:&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/l/libtermcap-*.txz&lt;br /&gt;
&lt;br /&gt;
# Install net-tools to ensure that /etc/HOSTNAME, /etc/hosts, and potentially, /etc/hostid are handled proper.&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/n/net-tools-*.txz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When ZFS has to import a zpool while the initrd is running (this can be avoided by not exporting and keeping /etc/zfs/zpool.cache inside the initrd), ZFS will refuse to import a pool if it thinks that the pool may be in use by another system. ZFS was designed for network attached storage where multiple hosts might have access to the same disks but ZFS cannot support two hosts importing and using a ZFS pool at the same time. ZFS checks a value called &amp;quot;hostid&amp;quot; to determine this kind of conflict, and it can be a tricky issue with an initrd boot process. The value of hostid is returned by a system call, the gethostid() function or the hostid command. This function will return the hostid from /etc/hostid if that file exists and has a valid id in it, or else if the file doesn't exist it obtains a hostid number based on the hostname and ip address address assigned to hostname found in /etc/hosts or in DNS. If the hostid trying to import a pool is not the same as the hostid that imported it last time, ZFS will not import the pool unless &amp;quot;zpool import -f zfs-root&amp;quot; is used to force the import. This force option is not recommended to use, so it is best to configure your initrd with matching /etc/HOSTNAME and /etc/hosts as on the root installation and ensure what your system looks like on the initrd matches the booted root system.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Edit /boot/initrd-tree/init (this is the main system startup script on the initrd, responsibe for configuring your block devices and mount your root at /mnt and then booting root):&lt;br /&gt;
&lt;br /&gt;
Inside init, right near the top of the file after the PATH= line, add this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/bin/hostname -F /etc/HOSTNAME&lt;br /&gt;
/bin/hostname $( /bin/hostname -s )&lt;br /&gt;
#/sbin/chhostid 13371400&lt;br /&gt;
# you can make your hostid whatever, but this didn't work right with ZFS, so it is commented out&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This sets the name reported by the hostname command (the default is &amp;quot;darkstar&amp;quot;) to be what is contained in /etc/HOSTNAME. The hostname is modified in the next line to be the short name. These lines will help ZFS to properly identify your host when importing pools.&lt;br /&gt;
&lt;br /&gt;
Inside init, right after it runs &amp;quot;mdadm&amp;quot; commands as used for raid setup, we like it to setup ZFS, so add:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/sbin/zpool import zfs-root&lt;br /&gt;
/sbin/zfs set readonly=on zfs-root&lt;br /&gt;
mount zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Inside init, close to the bottom, where it &amp;quot;Switch to real root partition&amp;quot;, comment out 1 line that normally does the mount:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# mount -o ro -t $ROOTFS $ROOTDEV /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
We have already mounted, and we don't want to use any mount options because we should be using a properly set /etc/fstab inside the initrd for zfs-root mount options onto /mnt.&lt;br /&gt;
&lt;br /&gt;
During a normal startup we want a readonly mount.&lt;br /&gt;
&lt;br /&gt;
Note: we are going to setup with using zpool import and export and startup and shutdown. But later, you can experiment having /etc/zfs/zpool.cache stored in the initrd and commenting out zpool import/export lines.&lt;br /&gt;
&lt;br /&gt;
As mentioned, the import command may sometimes fail, and give the message: &amp;quot;pool may be in use from another system&amp;quot;. This is nothing serious in this test situation. When this happens, root will not be mounted to /mnt and the init script will detect this and drop you into a rescue command line where you may manually &amp;quot;import -f&amp;quot; then &amp;quot;mount zfs-root&amp;quot; and then &amp;quot;exit&amp;quot; to continue on to booting the root.&lt;br /&gt;
&lt;br /&gt;
To avoid this problem we copy some files in (assuming you first edit /etc/HOSTNAME to hold the hostname you like to see on your command prompts, and edited /etc/hosts to have hostname on your loopback or other local ip address):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/HOSTNAME /etc/hosts /boot/initrd-tree/etc&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The value reported by the hostid command is what ZFS sees as your hostid. In this setup so far, the value is based on the ip found assigned to your hostname. If your hostname is on the line in /etc/hosts for ip address 192.168.13.37, then your hostid will be hex numbers C0.A8.0D.25 rearranged as A8C0250D (pairs of bytes are swapped). That is ip-based hostid value, a 32bit hexadecimal number. This has to be the same each boot or import will need a -f option to force it. Simply setting the hostid using the system call sethostid() which writes a /etc/hostid file doesn't seem to agree with ZFS and you'd have to force the import, so this setup now assumes that you do not have or have deleted /etc/hostid.&lt;br /&gt;
&lt;br /&gt;
You can sometimes see what has been happening to a zpool by using the command &amp;quot;zpool history -li zfs-root&amp;quot; to see a log of commands.&lt;br /&gt;
&lt;br /&gt;
Once again, you can do away with the import and export commands by trying to have /etc/zfs/zpool.cache inside your initrd. To create zpool.cache, while on the installer or in the rescue shell of the initrd (at lilo &amp;quot;boot: vmlinuz rescue&amp;quot;), import only the pool for the root fs with mountpoint=none and readonly=on properties set and while it is not mounted:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on installer or initrd rescue shell)&lt;br /&gt;
cp /etc/zfs/zpool.cache /etc/zfs/zpool.cache-initrd&lt;br /&gt;
zfs set readonly=off zfs-root&lt;br /&gt;
mount zfs-pool&lt;br /&gt;
cp /etc/zfs/zpool.cache-initrd /mnt/etc/zfs/&lt;br /&gt;
cp /mnt/etc/zfs/zpool.cache-initrd /mnt/boot/initrd-tree/etc/zfs/zpool.cache&lt;br /&gt;
umount /mnt&lt;br /&gt;
zfs set readonly=on zfs-root&lt;br /&gt;
#mount zfs-root&lt;br /&gt;
#exit (to continue boot process onto rootfs mounted at /mnt)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, doing this zpool.cache approach is not necessary, and some talk suggests this is deprecated or discouraged. Although /etc/hostid setup fails to import without -f option, ip-based (hosts|dns) hostid works on booting and import works without -f option and may be the more proper way to do shutdown and startup rather than using a cache file which could be come invalid and cause a problem that is difficult to understand. The contents and exact function of the cache file are not well understood by many people.&lt;br /&gt;
&lt;br /&gt;
Save /boot/initrd-tree/init and exit.&lt;br /&gt;
&lt;br /&gt;
Now, edit /etc/rc.d/rc.S and rc.6 to understand how to &amp;quot;remount&amp;quot; rw or ro as a readonly property changes&lt;br /&gt;
&lt;br /&gt;
In /etc/rc.d/rc.S:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# comment out the line&lt;br /&gt;
#    /sbin/mount -w -v -n -o remount /&lt;br /&gt;
#add the line&lt;br /&gt;
     /sbin/zfs set readonly=off zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In /etc/rc.d/rc.6&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# comment out the line&lt;br /&gt;
#    /bin/mount -v -n -o remount,ro /&lt;br /&gt;
#add the line&lt;br /&gt;
     /sbin/zfs set readonly=on zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In /etc/rc.d/rc.6, near the bottom just before poweroff|reboot, add the following block of lines:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
########################&lt;br /&gt;
# Try to export zfs-root&lt;br /&gt;
/sbin/zpool export zfs-root&lt;br /&gt;
if [ $? -gt 0 ] ; then&lt;br /&gt;
 echo &amp;quot;ZFS export failed.&amp;quot;&lt;br /&gt;
 echo &amp;quot;Notice: if root fs is busy, then this is normal fail.&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;ZFS export successful.&amp;quot;&lt;br /&gt;
 echo &amp;quot;Warning: successful export is abnormal for root fs.&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
/bin/sleep 5&lt;br /&gt;
########################&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
For ZFS, you cannot run fsck on it. It doesn't support that kind of filesystem checks. The rc.S script will complain a lot in many places about not being about to run fsck on the zfs-root. To disable all attempts of run fsck, we can simple create a file that acts as a flag in /etc/rc.d/rc.S to tell it to skip fsck:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
touch /etc/fastboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This fastboot file is normally a run-once temporary file, and it is deleted near the bottom inside rc.S. Edit rc.S and stop it from deleting /etc/fastboot. We would like it to always skip all fsck. Edit /etc/rc.d/rc.S, and find the &amp;quot;rm&amp;quot; of fastboot, and do not have it removed!&lt;br /&gt;
&lt;br /&gt;
We are getting close, and have finished all editing, so make /boot/initrd.gz and install lilo:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkinitrd -F&lt;br /&gt;
lilo&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We finished! All that's left to do is clean up.&lt;br /&gt;
&lt;br /&gt;
Exit the chroot.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
exit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Try to mount everything:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
umount /mnt/proc&lt;br /&gt;
umount /mnt/sys&lt;br /&gt;
umount /mnt/dev&lt;br /&gt;
umount /mnt/boot&lt;br /&gt;
umount /mnt/mnt/cdrom&lt;br /&gt;
umount /mnt/root/packages&lt;br /&gt;
umount /mnt&lt;br /&gt;
zpool export zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note, that export stops a pool and frees devices, while import binds devices and starts a pool. It is somewhat like mdadm -A -s and mdadm -S -s, while /etc/zfs/zpool.cache might be somewhat like mdadm -E -s &amp;gt; /etc/mdadm.conf.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Remove the DVD or change boot order&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When you reboot, if all is good, you are booting properly onto a slackware installed on a ZFS root! Congrat!&lt;br /&gt;
&lt;br /&gt;
If this seem to go badly, and this might happen if the import fails as explain some before, then you will be on the initrd's rescue command line just before the part in it's init where it wants to mount and switch_root to boot your root. Instead, you typically got commands like this to do:&lt;br /&gt;
&lt;br /&gt;
If you get dumped to rescue because import will not work and requires -f (force), then:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 zpool import -f zfs-root&lt;br /&gt;
 zpool export    zfs-root&lt;br /&gt;
 zpool import    zfs-root&lt;br /&gt;
 mount zfs-root&lt;br /&gt;
 exit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This can happen if hostname, hostid, or uname changes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you get into a jam and need to boot into the initrd and skip zfs import etc, use the lilo prompt (or, boot the install-dvd):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
boot: vmlinuz rescue&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the rescue mode of the initrd, after you have mounted your root as readonly=on to /mnt, then exit to continue.&lt;br /&gt;
&lt;br /&gt;
In other emergency modes, you might need to run the lines at end of init starting from: &amp;lt;code&amp;gt;udevadm info --cleanup-db; udevadm control --exit&amp;lt;/code&amp;gt;&lt;br /&gt;
If you don't run those udevadm commands, two runs of udevd fight each other and it is slow; you have to wait 2 minutes twice for timeouts (4 minutes).&lt;br /&gt;
The last line is run is: &amp;lt;code&amp;gt;exec switch_root /mnt /sbin/init 1&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Warning... this switch_root command is kind of dangerous, so read the manual page about it.&lt;br /&gt;
From what I can tell, everything except the new root &amp;quot;/mnt&amp;quot; is deleted, so you are giving a command that says what NOT to delete!&lt;br /&gt;
Make sure nothing got mounted outside of &amp;quot;/mnt&amp;quot; before you run it.&lt;br /&gt;
&lt;br /&gt;
Also, in rescue or anytime you have finished making changes and are about to reboot in some abnormal mode, first run:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set readonly=on zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A bug in unpatched grep 2.13 build 1, found slackware 14.0rc1, causes problems when processing files stored on ZFS but rarely shows problems on other filesystems; the bug does not handle sparse files on zfs and btrfs correctly and results in chaos with slackpkg, compiling kernel modules, and possibly many other things. You must downgrade grep to 2.12 or use the patched grep 2.13 build 2 in slackware 14.0rc2 or later.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Upgrading.&lt;br /&gt;
&lt;br /&gt;
From time to time you will want to upgrade the kernel to the new kernel in slackware64-current or in patches/. This will also necessitate a rebuilt and reinstall or upgrade of spl and zfs. Below is an example of when both kernel and spl/zfs are being upgraded, to give an idea of the process:&lt;br /&gt;
&lt;br /&gt;
Using slackpkg, that is configured to use your local slackware mirror is a good option but you can also configure it to use a remote mirror.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slackpkg upgrade-all&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Assume slackpkg just upgraded your kernel, kernel-modules, and kernel-headers.&lt;br /&gt;
&lt;br /&gt;
Note: the first time you try to run on kernel-generic, setup kernel-huge in lilo as 2nd choice. Huge has all the hard drive controllers builtin, but generic has them all as modules. For example, run &amp;quot;modinfo mptsas&amp;quot; to see module options (maybe you have a LSISAS1068) for your hard drive controller. Add file /etc/modprobe.d/mptsas.conf to set options you want with a line: options mptsas ... Do this for all the device driver modules for your hardware. Do this setup while you are on the huge kernel, then setup to reboot to generic. Include all these modules you need into mkinitrd.conf MODULES_LIST. Check that /boot/initrd-tree/etc/modprobe.d/ has a copy of your customized module conf files because it is on the initrd where the modules will load and use the conf files. mkinitrd probably copies all /etc/modprobe.d/* files into the initrd-tree, but check it. Pay attention to /etc/modprobe.d/README and /lib/modprobe.d/* /lib/modprobe.d/* maybe not copied to initrd-tree but you might want to copy some of it into your initrd-tree yourself to use them.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Check that upgraded kernel-source is symlinked to /usr/src/linux (zfs build looks here). SQL/ZFS modules will install to the kernel version in /lib/modules/&amp;lt;/usr/src/linux kernel version&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /usr/local/src&lt;br /&gt;
tar xvzf ~/spl-*.tar.gz&lt;br /&gt;
tar xvzf ~/zfs-*.tar.gz&lt;br /&gt;
&lt;br /&gt;
###### upgrade spl 1st&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-*&lt;br /&gt;
./configure --prefix=/ --libexecdir=/usr/libexec --libdir=/lib64 --includedir=/usr/include --datarootdir=/usr/share&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=/usr/local/src/install&lt;br /&gt;
cd ../install&lt;br /&gt;
makepkg ../spl-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
upgradepkg spl-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
depmod &amp;lt;new kernel version&amp;gt;     (e.g. depmod 3.2.27, if .27 is new kernel upgrade; you currently run on old, maybe .26)&lt;br /&gt;
# this builds the module dependencies in /lib/modules/&amp;lt;new kernel version&amp;gt;&lt;br /&gt;
###### upgrade zfs 2nd&lt;br /&gt;
mkdir install&lt;br /&gt;
cd zfs-*&lt;br /&gt;
./configure --prefix=/ --libexecdir=/usr/libexec --libdir=/lib64 --includedir=/usr/include --datarootdir=/usr/share&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=/usr/local/src/install&lt;br /&gt;
cd ../install&lt;br /&gt;
makepkg ../zfs-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
upgradepkg zfs-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
depmod 3.2.27&lt;br /&gt;
####### upgrade spl/zfs inside altroot /boot/initrd-tree&lt;br /&gt;
ROOT=/boot/initrd-tree upgradepkg spl-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
ROOT=/boot/initrd-tree upgradepkg zfs-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
# note: ROOT is an environment variable, not a command line option to upgradepkg!&lt;br /&gt;
# note: do not worry about depmod inside initrd-tree, mkinitrd -F actually installs the modules&lt;br /&gt;
# note: this upgrade here is really to just upgrade the command line tools zpool, zfs etc&lt;br /&gt;
####### rebuild /boot/initrd.gz and reinstall lilo&lt;br /&gt;
vi /etc/mkinitrd.conf&lt;br /&gt;
# temporarily set KERNEL_VERSION to new version, but you are still running on old version&lt;br /&gt;
mkinitrd -F&lt;br /&gt;
lilo&lt;br /&gt;
vi /etc/mkinitrd.conf&lt;br /&gt;
# you can set KERNEL_VERSION back to $(uname r) now&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After reboot you can remove any old /lib/modules/&amp;lt;old kernel version&amp;gt; directory.&lt;br /&gt;
&lt;br /&gt;
More about /etc/hostid. If you want to experiment changing your /etc/hostid file and seeing if you can use it and make zpool import work normally, here is a tool that might be helpful:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/* software product name: foobarz-chhostid.c&lt;br /&gt;
 * suggested binary name: chhostid&lt;br /&gt;
 * license              : BSD&lt;br /&gt;
 * license text:&lt;br /&gt;
Copyright (c) 2012, foobarz&lt;br /&gt;
All rights reserved.&lt;br /&gt;
&lt;br /&gt;
Redistribution and use in source and binary forms, with or without&lt;br /&gt;
modification, are permitted provided that the following conditions are met:&lt;br /&gt;
    * Redistributions of source code must retain the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer.&lt;br /&gt;
    * Redistributions in binary form must reproduce the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer in the&lt;br /&gt;
      documentation and/or other materials provided with the distribution.&lt;br /&gt;
    * Neither the name of the &amp;lt;organization&amp;gt; nor the&lt;br /&gt;
      names of its contributors may be used to endorse or promote products&lt;br /&gt;
      derived from this software without specific prior written permission.&lt;br /&gt;
&lt;br /&gt;
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &amp;quot;AS IS&amp;quot; AND&lt;br /&gt;
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED&lt;br /&gt;
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE&lt;br /&gt;
DISCLAIMED. IN NO EVENT SHALL &amp;lt;COPYRIGHT HOLDER&amp;gt; BE LIABLE FOR ANY&lt;br /&gt;
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES&lt;br /&gt;
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;&lt;br /&gt;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND&lt;br /&gt;
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT&lt;br /&gt;
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS&lt;br /&gt;
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#define FOOBARZ_CHHOSTID_VERSION &amp;quot;1.0.5&amp;quot;&lt;br /&gt;
#include &amp;lt;sys/socket.h&amp;gt;&lt;br /&gt;
#include &amp;lt;netinet/in.h&amp;gt;&lt;br /&gt;
#include &amp;lt;arpa/inet.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;endian.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sysexits.h&amp;gt;&lt;br /&gt;
/* note: if include stdlib then sethostid fails even with _BSD_SOURCE defined */&lt;br /&gt;
&lt;br /&gt;
long swapbytes(long abcd) {&lt;br /&gt;
  long badc;&lt;br /&gt;
  unsigned char addr_a;&lt;br /&gt;
  unsigned char addr_b;&lt;br /&gt;
  unsigned char addr_c;&lt;br /&gt;
  unsigned char addr_d;&lt;br /&gt;
  addr_a = (unsigned char) (abcd &amp;gt;&amp;gt; 24);&lt;br /&gt;
  addr_b = (unsigned char) (abcd &amp;gt;&amp;gt; 16);&lt;br /&gt;
  addr_c = (unsigned char) (abcd &amp;gt;&amp;gt;  8);&lt;br /&gt;
  addr_d = (unsigned char) (abcd);&lt;br /&gt;
  return badc = ( (addr_b &amp;lt;&amp;lt; 24) | (addr_a &amp;lt;&amp;lt; 16) | (addr_d &amp;lt;&amp;lt; 8) | addr_c );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[])&lt;br /&gt;
{&lt;br /&gt;
 long newhostid;&lt;br /&gt;
 struct in_addr addr;&lt;br /&gt;
 char* invalidchar;&lt;br /&gt;
&lt;br /&gt;
 /*********** check command line */&lt;br /&gt;
 if(!( ((argc==3) &amp;amp;&amp;amp; ( (strcmp(argv[1],&amp;quot;-h&amp;quot;)==0) ||&lt;br /&gt;
                       (strcmp(argv[1],&amp;quot;-i&amp;quot;)==0) ||&lt;br /&gt;
                       (strcmp(argv[1],&amp;quot;-l&amp;quot;)==0) )) ||&lt;br /&gt;
       ((argc==2) &amp;amp;&amp;amp; ( (strcmp(argv[1],&amp;quot;-s&amp;quot;)==0) ))&lt;br /&gt;
     )&lt;br /&gt;
   ) {&lt;br /&gt;
                 /*01234567890123456789012345678901234567890123456789012345678901234567890123456789*/&lt;br /&gt;
  fprintf(stderr, &amp;quot;foobarz-chhostid, version %s. License: BSD.\n&amp;quot;, FOOBARZ_CHHOSTID_VERSION);&lt;br /&gt;
  fprintf(stderr, &amp;quot;foobarz-chhostid, (c) 2012, foobarz; all rights reserved.\n&amp;quot;);&lt;br /&gt;
  fprintf(stderr, &amp;quot;descr: %s change system hostid (in /etc/hostid).\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -h &amp;lt;new hostid&amp;gt;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        Change system hostid to &amp;lt;new hostid&amp;gt;;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        &amp;lt;new hostid&amp;gt; must be 32bit 8-digit hex number xxxxxxxx, each x in 0-f|F.\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        The ip corresponding to &amp;lt;new hostid&amp;gt; is also listed for reference only.\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -i &amp;lt;dotted ip address&amp;gt;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        Change system hostid to hostid corresponding to &amp;lt;dotted ip address&amp;gt;.\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -l &amp;lt;dotted ip address&amp;gt;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        List hostid corresponding to &amp;lt;dotted ip address&amp;gt;;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        no change to system hostid.\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -s\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        List current system hostid and corresponding ip address;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        no change to system hostid.\n&amp;quot;, argv[0]);&lt;br /&gt;
  return EX_USAGE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -h &amp;lt;hostid&amp;gt; */&lt;br /&gt;
 if( strcmp(argv[1],&amp;quot;-h&amp;quot;) == 0 ) {&lt;br /&gt;
  if(strlen(argv[2]) != 8) { fprintf(stderr, &amp;quot;new hostid must be 8-digit hex number xxxxxxxx, each x in 0-f|F\n&amp;quot;); return EX_USAGE; }&lt;br /&gt;
&lt;br /&gt;
  newhostid = strtol(argv[2],&amp;amp;invalidchar,16);&lt;br /&gt;
  if( newhostid==LONG_MIN ) { perror(&amp;quot;strtol (underflow)&amp;quot;); return EX_USAGE; }&lt;br /&gt;
  if( newhostid==LONG_MAX ) { perror(&amp;quot;strtol (overflow)&amp;quot;); return EX_USAGE; }&lt;br /&gt;
  if(*invalidchar != '\0') { fprintf(stderr, &amp;quot;invalid hex number %c; must be in 0-f|F\n&amp;quot;, *invalidchar); return EX_USAGE; }&lt;br /&gt;
&lt;br /&gt;
  if( sethostid(newhostid) != 0 ) {&lt;br /&gt;
   perror(&amp;quot;sethostid&amp;quot;);&lt;br /&gt;
   if( errno == EPERM ) return EX_NOPERM;&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
  }&lt;br /&gt;
  printf(&amp;quot;System hostid changed.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  /* hostid is a byte-swapped ip like b.a.d.c */&lt;br /&gt;
  /* get ip by swapping to correct order a.b.c.d and save into in_addr struct */&lt;br /&gt;
  addr.s_addr = htonl(swapbytes(newhostid));&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -i or -l, then find hostid for &amp;lt;dotted ip address&amp;gt; */&lt;br /&gt;
 if( (strcmp(argv[1],&amp;quot;-i&amp;quot;) == 0) || (strcmp(argv[1],&amp;quot;-l&amp;quot;) == 0) ) {&lt;br /&gt;
  if( inet_aton(argv[2], &amp;amp;addr) == 0 ) { fprintf(stderr, &amp;quot;inet_aton: invalid dotted ip address: %s\n&amp;quot;, argv[2]); return EX_USAGE; }&lt;br /&gt;
&lt;br /&gt;
  /* hostid is a byte-swapped ip like b.a.d.c */&lt;br /&gt;
  /* get hostid by swapping bytes of ip a.b.c.d */&lt;br /&gt;
  newhostid = swapbytes(ntohl(addr.s_addr));&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -i &amp;lt;dotted ip address&amp;gt; */&lt;br /&gt;
 if( strcmp(argv[1],&amp;quot;-i&amp;quot;) == 0 ) {&lt;br /&gt;
  if( sethostid(newhostid) != 0 ) {&lt;br /&gt;
   perror(&amp;quot;sethostid&amp;quot;);&lt;br /&gt;
   if( errno == EPERM ) return EX_NOPERM;&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
  }&lt;br /&gt;
  printf(&amp;quot;System hostid changed.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -l &amp;lt;dotted ip address&amp;gt; */&lt;br /&gt;
 if(strcmp(argv[1],&amp;quot;-l&amp;quot;) == 0 ) {&lt;br /&gt;
   printf(&amp;quot;Listing hostid for ip. (no changes)\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -s */&lt;br /&gt;
 if(strcmp(argv[1],&amp;quot;-s&amp;quot;) == 0 ) {&lt;br /&gt;
   /* see if /etc/hostid exists and print info */&lt;br /&gt;
   if( access(&amp;quot;/etc/hostid&amp;quot;, F_OK) != 0 ) {&lt;br /&gt;
     printf(&amp;quot;Notice: /etc/hostid does not exist.\n&amp;quot;);&lt;br /&gt;
     perror(&amp;quot;Reason&amp;quot;);&lt;br /&gt;
     printf(&amp;quot;System hostid derived from ip of hostname found in hosts file or dns.\n&amp;quot;);&lt;br /&gt;
   } else {&lt;br /&gt;
     printf(&amp;quot;Notice: /etc/hostid exists.\n&amp;quot;&lt;br /&gt;
            &amp;quot;System hostid is obtained from hostid file.\n&amp;quot;);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
  errno=0;&lt;br /&gt;
  newhostid = gethostid();&lt;br /&gt;
  if(errno!=0) { perror(&amp;quot;gethostid&amp;quot;); return EX_UNAVAILABLE; }&lt;br /&gt;
&lt;br /&gt;
  /* hostid is a byte-swapped ip like b.a.d.c */&lt;br /&gt;
  /* get ip by swapping to correct order a.b.c.d and save into in_addr struct */&lt;br /&gt;
  addr.s_addr = htonl(swapbytes(newhostid));&lt;br /&gt;
&lt;br /&gt;
  printf(&amp;quot;Listing current system hostid. (no changes)\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** print info and return */&lt;br /&gt;
 printf(&amp;quot;ip dot: %s\n&amp;quot;, inet_ntoa(addr) );&lt;br /&gt;
 printf(&amp;quot;ip hex: %.8x\n&amp;quot;, ntohl(addr.s_addr) );&lt;br /&gt;
 printf(&amp;quot;hostid: %.8x\n&amp;quot;, newhostid );&lt;br /&gt;
 return EX_OK;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</description>
			<pubDate>Sat, 18 Aug 2012 19:00:07 GMT</pubDate>
			<dc:creator>Foobarz</dc:creator>
			<comments>https://www.slackwiki.com/Talk:ZFS_root</comments>
		</item>
		<item>
			<title>ZFS root</title>
			<link>https://www.slackwiki.com/index.php?title=ZFS_root&amp;diff=733</link>
			<guid isPermaLink="false">https://www.slackwiki.com/index.php?title=ZFS_root&amp;diff=733</guid>
			<description>&lt;p&gt;Foobarz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;If you have heard about the ZFS filesystem and you're curious to try it out, then you can try it on slackware64, thanks to the ZFSonLinux.org project!&lt;br /&gt;
&lt;br /&gt;
In this article, an example is shown of how to install slackware64 14.0 onto a ZFS root filesystem (zfs-root) inside a QEMU virtual machine for testing purposes. It is recommended that you install qemu and learn how to use it to test a ZFS installation before you decide to use it on real hardware. A slackbuild for qemu can be found on slackbuilds.org. If you have a processor that supports Intel VT-x or AMD AMD-V virtualization acceleration (try modprobe kvm-intel or modprobe kvm-amd), then use the slackbuild for qemu-kvm.&lt;br /&gt;
&lt;br /&gt;
This article isn't going to go into any detail on actually using ZFS or what kinds of installation options and settings might be optimal. This article just presents an example of how to get started with ZFS on slackware.&lt;br /&gt;
&lt;br /&gt;
At this time of writing, ZFSonLinux is at &amp;quot;release candidate&amp;quot; (version 0.6.0-rc10) development stage, and many issues can occur. See the ZFSonLinux.org web site and the issues tracker for an idea about the current issues. There is also an irc channel on irc.freenode.net, #zfsonlinux, for discussion of issues and help.&lt;br /&gt;
&lt;br /&gt;
Although not required, it is helpful to keep a local mirror of slackware64 on your system. Having a local mirror makes it easier to upgrade to slackware64-current or to patches/* in a release. To help manage your own local slackware mirror and generate your own CD and DVD slackware installers, see http://alien.slackbook.org/blog/local-slackware-mirror/.&lt;br /&gt;
&lt;br /&gt;
In this article, we use a slackware64-current DVD image file as the qemu cdrom device media for the installation of the slackware guest. This was tested at slackware64-current = slackware64 14.0rc2. You can obtain a slackware DVD image using a torrent, buy the DVD from slackware.com, or generate your own DVD image file using the mirror script. For an actual DVD, you can pass your DVD device (e.g., /dev/sr0) as the qemu cdrom device. For a DVD image file, pass the image file as the qemu cdrom device.&lt;br /&gt;
&lt;br /&gt;
The ZFSonLinux packages are not included in slackware at this time. There are two packages involved: spl and zfs. The first, spl, is &amp;quot;Solaris Porting Layer&amp;quot; and must be installed on the system before zfs can be compiled. The source code tarballs for these are at ZFSonLinux.org. At this time of writing, they are spl-0.6.0-rc10.tar.gz and zfs-0.6.0-rc10.tar.gz.&lt;br /&gt;
&lt;br /&gt;
At this point, it is assumed you have qemu installed, have obtained a slackware64-current/14.0 DVD, and have downloaded spl and zfs tarballs to your host system. The first step now is, if your host is not slackware64-current/14.0 (the same as the guest will be), then you need to create a minimal development slackware64 guest system in qemu for just the purpose of compiling and packaging the spl and zfs slackware packages and transferring a copy of these packages back onto your host system to use later to install onto zfs during the slackware install process.&lt;br /&gt;
&lt;br /&gt;
From this point onward, instructions become a bit terse and mostly limited to examples of the commands you might use to complete tasks. You are encouraged to examine what each command does by reading the command's man pages. For example, the command &amp;quot;man qemu&amp;quot; can show you most of what you need to know about running qemu on the command line.&lt;br /&gt;
&lt;br /&gt;
So, here's an example of how you might build the spl and zfs packages, starting in your home directory:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on host)&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir qemu&lt;br /&gt;
cd qemu&lt;br /&gt;
mkdir slackdevel&lt;br /&gt;
cd slackdevel&lt;br /&gt;
mkdir packages&lt;br /&gt;
cp ~/spl-*.tar.gz packages&lt;br /&gt;
cp ~/zfs-*.tar.gz packages&lt;br /&gt;
qemu-img create disk1.raw 10G&lt;br /&gt;
ln -s ~/slackware64-current-install-dvd.iso dvd.iso&lt;br /&gt;
qemu-system-x86_64 \&lt;br /&gt;
 -no-quit \&lt;br /&gt;
 -no-shutdown \&lt;br /&gt;
 -boot order=cd,menu=on \&lt;br /&gt;
 -m 2G \&lt;br /&gt;
 -cpu host \&lt;br /&gt;
 -smp sockets=1,cores=4 \&lt;br /&gt;
 -net nic,model=rtl8139 -net user \&lt;br /&gt;
 -cdrom dvd.iso \&lt;br /&gt;
 -drive boot=on,format=raw,media=disk,cache=none,aio=native,if=scsi,bus=0,unit=0,file=disk1.raw \&lt;br /&gt;
 -virtfs local,path=./packages/,security_model=none,mount_tag=hostpackages&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When you need to change boot to cd or disk, add or remove &amp;quot;boot=on&amp;quot;, or change &amp;quot;order=dc&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Qemu should boot into the install-dvd, and now perform a very ordinary slackware64 install onto /dev/sda. Install d package set and most others, but package sets x, kde, xfce not really needed.&lt;br /&gt;
&lt;br /&gt;
First note: examples here use tools from the gptfdisk package (gdisk, sgdisk, cgdisk) to partition the disk with GUID partition table (GPT) format. GPT might not be too familiar to everyone, who mostly have only used MBR partitions with fdisk. In the slackware installations this author has tested in qemu, using GPT partitions has caused no problems with lilo or other tools used in slackware. GPT disk labels support creating up to 128 partitions and support disks larger than 2TB (the limit of MBR fdisk). LILO installs into the first 440 bytes on /dev/sda, inside a GPT &amp;quot;protective MBR&amp;quot; that serves to provide compatibility with MBR bootloaders like lilo. LILO uses LBA32 sector addressing and can see all 512-byte sectors side the first 2TB of a disk. So long as the /boot partition is within the first 2TB of a disk, lilo can work on a disk larger than 2TB. Unlike the common default of fdisk to start the first partition at sector 63, which is not aligned with the 4KiB sector size of Advanced Format hard disks, gdisk's default is to start partitions at 2048 sector (1MiB) boundaries which are also 4KiB aligned. Using gdisk GPT works on all disks and is compatible with using Advanced Format hard disks larger than 2TB. More information about GPT disk label format can be found on wikipedia.org. For those that have used grub instead of lilo, grub installation is different with GPT than with MBR, and grub requires a GPT partition of type grub-bios or 0xEF02 &amp;quot;BIOS Boot Partition&amp;quot; of about 8MiB where it can install it's additional bootloader stages because grub cannot embed in sectors 1-62 on GPT where GPT keeps it's partition tables. On MBR, sectors 1-62 were normally reserved space for bootloaders to keep a 2nd stage.&lt;br /&gt;
&lt;br /&gt;
For this purpose of development guest, just create a simple 1-partition system, /dev/sda1, and do a simple slackware install on it. Don't bother with swap or separate /boot unless you want to:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on install-dvd)&lt;br /&gt;
cgdisk /dev/sda&lt;br /&gt;
setup&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When this simple development guest boots, login as root, and continue:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on qemu guest)&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir packages&lt;br /&gt;
mount hostpackages -t 9p -o trans=virtio packages&lt;br /&gt;
echo --prefix=/ --libexecdir=/usr/libexec --libdir=/lib64 --includedir=/usr/include --datarootdir=/usr/share &amp;gt; configure-options&lt;br /&gt;
mkdir src&lt;br /&gt;
cd src&lt;br /&gt;
&lt;br /&gt;
mkdir install&lt;br /&gt;
tar xvzf ~/packages/spl-*.tar.gz&lt;br /&gt;
cd spl-*&lt;br /&gt;
./configure $( cat ~/configure-options )&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../spl-&amp;lt;version&amp;gt;_&amp;lt;kernel_version&amp;gt;-x86_64-&amp;lt;build_id&amp;gt;.txz&lt;br /&gt;
(e.g., makepkg ../spl-0.6.0rc10_3.2.27-x86_64-1root.txz)&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
installpkg spl-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
cp spl-0.6.0rc10_3.2.27-x86_64-1root.txz ~/packages&lt;br /&gt;
&lt;br /&gt;
mkdir install&lt;br /&gt;
tar xvzf ~/packages/zfs-*.tar.gz&lt;br /&gt;
cd zfs-*&lt;br /&gt;
./configure $( cat ~/configure-options )&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../zfs-&amp;lt;version&amp;gt;_&amp;lt;kernel_version&amp;gt;-x86_64-&amp;lt;build_id&amp;gt;.txz&lt;br /&gt;
(e.g., makepkg ../zfs-0.6.0rc10_3.2.27-x86_64-1root.txz)&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
installpkg zfs-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
cp zfs-0.6.0rc10_3.2.27-x86_64-1root.txz ~/packages&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point spl and zfs packages are copied back to the host in the packages directory. Also, spl and zfs are installed in this simple development guest, so one could begin to experiment with zfs pools and datasets but while the root fs is whatever you made it during setup (probably the default, ext4). This development guest isn't really needed anymore, so it can be deleted:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
halt&lt;br /&gt;
(exit qemu: ctrl-alt-2 then enter quit at QEMU command prompt)&lt;br /&gt;
&lt;br /&gt;
(on host)&lt;br /&gt;
rm disk1.raw dvd.iso&lt;br /&gt;
mv packages ..&lt;br /&gt;
cd ..&lt;br /&gt;
rmdir slackdevel&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now that we have the spl and zfs packages on the host, it is possible to copy them into your local slackware64 mirror and then generate your own install DVD image that includes them. For example, change to the directory that contains the slackware README files, and create a &amp;quot;addon&amp;quot; directory and copy the spl and zfs slackware packages into there. Then, generate the DVD image using a command such as $( ./mirror-slackware-current.sh -i ) from where you have this script configured to maintain your local mirror. We can also just continue to access them inside the installer using qemu's virtfs option. When you are going to do a real installation onto real hardware, you need to generate and burn your own DVD that includes the packages.&lt;br /&gt;
&lt;br /&gt;
It is time to begin the installation of slackware64 on a ZFS root, assuming either you have regenerated dvd.iso with zfs packages in addon/* or we access the zfs packages while in the installer using qemu's virtfs to the host's packages directory. ZFS supports creating complex data storage configurations such as pools (similar to a volume group) backed by one or more of various kinds of virtual devices (similar to disks and raid arrays) and containing one or more datasets (similar to mounted filesystems, logical volume devices, or snapshots). But here, we keep it simple and will install on just a single disk device. On a real ZFS installation, users will typically want to use the ZFS raidz1 or raidz2 virtual device types for reliability against hard drive failures.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on host)&lt;br /&gt;
mkdir slackzfs&lt;br /&gt;
mv packages slackzfs/&lt;br /&gt;
cd slackzfs&lt;br /&gt;
qemu-img create disk1.raw 10G&lt;br /&gt;
ln -s ~/slackware64-current-install-dvd.iso dvd.iso&lt;br /&gt;
qemu-system-x86_64 \&lt;br /&gt;
 -no-quit \&lt;br /&gt;
 -no-shutdown \&lt;br /&gt;
 -boot order=cd,menu=on \&lt;br /&gt;
 -m 2G \&lt;br /&gt;
 -cpu host \&lt;br /&gt;
 -smp sockets=1,cores=4 \&lt;br /&gt;
 -net nic,model=rtl8139 -net user \&lt;br /&gt;
 -cdrom dvd.iso \&lt;br /&gt;
 -drive boot=on,format=raw,media=disk,cache=none,aio=native,if=scsi,bus=0,unit=0,file=disk1.raw \&lt;br /&gt;
 -virtfs local,path=./packages/,security_model=none,mount_tag=hostpackages&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The install-dvd should boot, and then begin installation steps on the installer command line:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on install-dvd)&lt;br /&gt;
# mount the install-dvd&lt;br /&gt;
mkdir /dvd&lt;br /&gt;
mount /dev/sr0 /dvd&lt;br /&gt;
&lt;br /&gt;
# install coreutils, which provides the &amp;quot;hostid&amp;quot; command needed to load the spl module&lt;br /&gt;
installpkg /dvd/slackware64/a/coreutils-8.17-x86_64-1.txz&lt;br /&gt;
&lt;br /&gt;
# install kmod package which includes &amp;quot;depmod&amp;quot; command and others&lt;br /&gt;
installpkg /dvd/slackware64/a/kmod-9-x86_64-2.txz&lt;br /&gt;
depmod&lt;br /&gt;
&lt;br /&gt;
# install the full kernel modules so you can load 9p filesystem and use it if you want&lt;br /&gt;
# .. you might keep the zfs modules packages off the dvd and use a plain slack dvd&lt;br /&gt;
installpkg /dvd/slackware64/a/kernel-modules-*.txz&lt;br /&gt;
depmod&lt;br /&gt;
&lt;br /&gt;
# install bash and libtermcap because udev rules in zfs use bash scripts&lt;br /&gt;
installpkg /dvd/slackware64/a/bash-*.txz&lt;br /&gt;
installpkg /dvd/slackware64/l/libtermcap-*.txz&lt;br /&gt;
&lt;br /&gt;
# install spl and zfs that you have copied into the mirror before running the DVD creation&lt;br /&gt;
installpkg /dvd/addon/spl-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /dvd/addon/zfs-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
&lt;br /&gt;
Or:&lt;br /&gt;
mkdir /packages&lt;br /&gt;
find /lib/modules/ | grep 9p&lt;br /&gt;
lsmod&lt;br /&gt;
# check that 9p modules load, mainly 9pnet_virtio&lt;br /&gt;
modprobe 9pnet_virtio&lt;br /&gt;
mount hostpackages -t 9p -o trans=virtio /packages&lt;br /&gt;
installpkg /packages/spl-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /packages/zfs-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
modprobe zfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now zfs tools: &amp;quot;zpool&amp;quot; and &amp;quot;zfs&amp;quot; should work in the live installer.&lt;br /&gt;
On the installer, there can be trouble seeing man pages, so install:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
installpkg /dvd/slackware64/ap/man-*.txz&lt;br /&gt;
installpkg /dvd/slackware64/ap/groff-*.txz&lt;br /&gt;
installpkg /dvd/slackware64/a/less-*.txz&lt;br /&gt;
export MANPATH=/usr/man:/usr/share/man&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The manual pages should be readable:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
man zpool&lt;br /&gt;
man zfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After seeing the man pages, we should be fully ready to continue to setup on ZFS.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(still on install-dvd)&lt;br /&gt;
ls -l /dev/sd*&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Make sure the disk devices you expect are there. We'll use sda and make boot (/boot on /dev/sda1) and root (/ on /dev/sda2) partitions.&lt;br /&gt;
&lt;br /&gt;
First, some background info: A ZFS filesystem is not supported by lilo as the filesystem containing /boot, which holds lilo's 2nd stage and the linux kernel files. The on-disk format of a ZFS filesystem is often a complex raid configuration where even if lilo understood ZFS it would likely require /boot to reside in only certain simple ZFS configurations to be plainly readable to lilo. As things are, a linux root installed in a partition with ZFS filesystem needs /boot to be on another partition with a filesystem that lilo understands, such as ext4 fs. In addition, because the spl and zfs modules are not built into the kernel, and the zfs startup requires some configuration to mount the zfs root, an initial ram/root filesystem (initrd) is needed. The initrd is a gzip compressed cpio archive file that contains a small linux root operating system that is decompressed into a ramfs block device at boot up and takes initial control of the system. The initrd contains an init script that configures devices in devtmpfs mounted at /dev. For example, if using mdadm, lvm, luks, losetup, and now zfs, this init script runs all the commands to create or start these devices (one of which is the root device), mounts the root device, and then transfers system control to the init script in the mounted root filesystem. The ramfs-based root environment on the booted install-dvd or booted initrd image (in rescue command line) are small slackware installations that exist only in ram and are temporary, but while inside them you can install, upgrade, and remove slackware packages inside them using the regular package management tools; this allows you access to any kernel modules and programs as needed inside these ramfs root. Packages can be installed, upgraded, or removed permanantly in the initrd image file to manage the programs and modules required during the initrd boot stage. Also from within these ramfs initial root environments, once the root device is mounted, chroot can be used to work on the mounted root system as if it were booted; this allows one to fix problems that are occuring in the root fs init scripts that cause normal booting to fail, or to install a kernel and/or modules etc. Now on to partitioning:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
cgdisk /dev/sda&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, cgdisk looks just like cfdisk, but it makes GPT partitions.&lt;br /&gt;
&lt;br /&gt;
Make a partition for /boot that is about 512MiB of whatever partition type you like (8300 &amp;quot;Linux filesystem&amp;quot; is fine), or make it type bf07 &amp;quot;Solaris Reserved 1&amp;quot; if you want ZFS to maybe see the disk as if it was given as a whole disk to ZFS. Make a second partition using the remaining space with partition type bf01 &amp;quot;Solaris ZFS&amp;quot;. Currently, when ZFSonLinux is given a whole disk device like /dev/sdb to use, it will automatically GPT partition it with a bf01 partition #1 that is the whole disk except a small 8MiB type bf07 partition #9 at the end of the disk (/dev/sdb1 and /dev/sb9). The small 8MiB type bf07 partition #9 is mostly likely reserved for use by bootloaders, like lilo, to have a /boot or other boot-related files kept there. For example, you might have /dev/sda that is totally non-ZFS for booting and /dev/sdb passed to ZFS whole where it automatically partitions sdb, but you can just use one disk here and make partitions. Lets use type 8300 for /boot to be sure nothing is confused:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
We'll continue with this partitioning (numbers are in MiB):&lt;br /&gt;
  0 to   4: unused&lt;br /&gt;
  4 to 516: /dev/sda1 512MiB, type 8300&lt;br /&gt;
516 to 520: unused&lt;br /&gt;
520 to -96: /dev/sda2, type bf01&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The -96 means to count from the end of the disk so that 96MiB will remain unused at the end of the disk.&lt;br /&gt;
&lt;br /&gt;
Create a zpool called zfs-root:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool create -m none zfs-root /dev/sda2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A zpool created like this, the normal way, is a kernel-internal block device that contains already a zfs filesystem. There is normally no entry in /dev for this device. However, it can still be referenced as a mountable device similar to how devtmpfs, proc, and sysfs are also kernel-internal mountable block devices. The -m option told zpool not to automatically mount it anywhere, and without -m the default is to always automatically mount to /zfs-root. These kinds of details are explained better elsewhere. For this situation, we do not want it automounted.&lt;br /&gt;
&lt;br /&gt;
Because a zpool itself is a useable zfs fs, it has a full set of zfs &amp;quot;properties&amp;quot; to set options about the filesystem, perhaps similar to tune2fs. The &amp;quot;mountpoint=&amp;lt;some place to mount&amp;gt;&amp;quot; is one such property. We want it set to the special value &amp;quot;none&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs get mountpoint zfs-root&lt;br /&gt;
zfs set mountpoint=none zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On creation, the zpool zfs-pool is &amp;quot;imported&amp;quot; and has a zpool status that can be viewed:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool status zfs-root&lt;br /&gt;
&lt;br /&gt;
zpool export zfs-root&lt;br /&gt;
zpool status zfs-root&lt;br /&gt;
# Now there is no status.&lt;br /&gt;
&lt;br /&gt;
zpool import zfs-root&lt;br /&gt;
# Now it is back.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When a zpool is imported, it has it's current configuration cached in a file /etc/zfs/zpool.cache. When a zpool is exported, then it's entries in the cache file are removed and the cache file is deleted if it becomes empty. So long as the zfs kernel modules see this cache file and valid cache data inside it, ZFS considers the described zpools in the cache file to be valid as imported zpools. If the zpool.cache file is present at the time the zfs modules are loaded, then there is no further need to use the import and export commands at system startup and shutdown. With root on a zfs, it is not possible to export the pool that root is on, but this is not a problem. At shutdown, the safe procedure will be to set the zfs-root property readonly=on and sync disks.&lt;br /&gt;
&lt;br /&gt;
To avoid the requirement to import the zfs-root pool at startup, keep a copy of the zpool.cache file to later copy onto the initrd image to read at modules load time to have the pool reactived without need to issue the import command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/zfs/zpool.cache /etc/zfs/zpool.cache-initrd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A zfs fs will not normally allow you to mount over any files. The mountpoint is expected to be an empty directory. Remove any junk files inside the installer's /mnt because zfs won't mount over any files:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rm /mnt/README&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The directory /mnt is where the slackware setup expects you to mount your root for installation.&lt;br /&gt;
&lt;br /&gt;
Controlling whether a zfs fs is to be mounted read-only or read-write is best managed by setting the readonly property while it is not yet mounted:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set readonly=on zfs-root&lt;br /&gt;
zfs set readonly=off zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Slackware expects root to be mounted readonly when /etc/rc.S runs during normal startup, so later this is used to satisfy slackware's expectation to avoid rc.S complaining.&lt;br /&gt;
&lt;br /&gt;
The zfs-root can be mounted and unmounted in two different ways:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=/mnt zfs-root&lt;br /&gt;
zfs set mountpoint=none zfs-root&lt;br /&gt;
# or&lt;br /&gt;
mount zfs-root -t zfs /mnt&lt;br /&gt;
umount /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If it is already mounted and you want to change it to mount somewhere else, it is best to transition it to unmounted first, then mount it in the new place.&lt;br /&gt;
&lt;br /&gt;
The mount options &amp;lt;code&amp;gt;-o ro, -o rw, -o remount,ro, and -o remount,rw &amp;lt;/code&amp;gt; can also be used and will override &amp;lt;code&amp;gt;readonly=on|off&amp;lt;/code&amp;gt; property without altering the property value. This can be confusing until you are familiar with how to the methods of mounting interact.&lt;br /&gt;
&lt;br /&gt;
Now, let's continue some, and mount to /mnt using the current &amp;lt;code&amp;gt;readonly=off&amp;lt;/code&amp;gt; setting (rw mount):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=/mnt zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This method of mounting will show the most detailed mount options in /etc/mtab. They are the mount options that zfs thinks are proper, and they are probably what should be kept in /etc/fstab for zfs-root until we know better.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cat /etc/mtab &amp;gt;&amp;gt; /etc/fstab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now edit /etc/fstab to make sure it looks right, and remove the &amp;quot;rw&amp;quot; mount option, because we want to let it use a default for that, which will come from how we set the readonly= property most of the time. Unmount again:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=none zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mount again, now using all options from /etc/fstab:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It should be mounted at /mnt, and touch /mnt/t should allow you to make the file t. Then rm it: rm /mnt/t&lt;br /&gt;
For installation, we want to make sure it is mounted read-write. After installation, it should mount readonly inside the initrd.&lt;br /&gt;
&lt;br /&gt;
Sometimes there can be problems using the mount command, and then you can try it with the -i option:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 mount -i zfs-root &lt;br /&gt;
 mount -i zfs-root -t zfs /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
but, you should not have to use -i. When using -i makes it work, it performs an &amp;quot;internal-only&amp;quot; mount and does not use any mount.&amp;lt;fstype&amp;gt; helper scripts that might be on the system.&lt;br /&gt;
&lt;br /&gt;
Setup the /boot device:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkfs.ext4 /dev/sda1&lt;br /&gt;
mkdir /mnt/boot&lt;br /&gt;
mount /dev/sda1 /mnt/boot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We have both root and boot mounted where the slackware installer expects them. Unmount the dvd so setup can find it normally:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
umount /dev/sr0&lt;br /&gt;
setup&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the setup, skip straight to TARGET selection for the root device, but the setup doesn't see or understand the zfs-root, so it is not listed. This does not matter because we have mounted it already. Just skip down to a slot that say to continue, and continue on with setup. Because TARGET is skipped, you may not see the ADDITIONAL prompt (or if so, skip it too) where normally you give /dev/sda1 and have it mounted as /boot. This is also okay because we have mounted /mnt/boot already.&lt;br /&gt;
Because we did not give TARGET the root device or say what device /boot is on, the lilo installation will fail, or you can skip it. Otherwise, this installation process it normal.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
umount /dev/sr0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point, it is assumed that the setup has completed installing into /mnt. Congrats! You've installed slackware into a ZFS root!&lt;br /&gt;
&lt;br /&gt;
The next steps are to prepare to use &amp;quot;chroot /mnt&amp;quot; and finish up the configuration on the installed root system and then be able to reboot onto the completed installation. Before doing chroot, copy some files from the setup environment into /mnt.&lt;br /&gt;
&lt;br /&gt;
Copy the current installer /etc/fstab for later use inside the initrd. This fstab is what is proper inside the initrd, except remove option &amp;quot;rw&amp;quot; (if not done already).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/fstab /mnt/etc/fstab.initrd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The fstab.initrd will look like:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 proc /proc proc defaults 0 0&lt;br /&gt;
 zfs-root /mnt zfs defaults,atime,dev,exec,suid,xattr,nomand,zfsutil 0 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the initrd, we want zfs-root to mount to /mnt.&lt;br /&gt;
&lt;br /&gt;
Create /mnt/etc/fstab:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cat /etc/mtab &amp;gt;&amp;gt; /mnt/etc/fstab&lt;br /&gt;
vi /mnt/etc/fstab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using vi started above, edit /mnt/etc/fstab and make it have lines such as:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 zfs-root / zfs defaults,atime,dev,exec,suid,xattr,nomand,zfsutil 0 0&lt;br /&gt;
 /dev/sda1 /boot ext4 defaults 0 2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These two lines in &amp;lt;code&amp;gt;/mnt/etc/fstab&amp;lt;/code&amp;gt; are how the mounts should be looking when root is booted.&lt;br /&gt;
&lt;br /&gt;
Mount some special mounts before chroot:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount -t devtmpfs none /mnt/dev&lt;br /&gt;
mount -t proc none /mnt/proc&lt;br /&gt;
mount -t sysfs none /mnt/sys&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Make sure /boot is mounted:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount /dev/sda1 /mnt/boot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you had mounted a 9p fs share to access spl and zfs packages, then unmount that now:&lt;br /&gt;
umount /packages&lt;br /&gt;
&lt;br /&gt;
Ready, now:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chroot /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point, you should be on the installed system, and now try to configure mkinitrd and lilo. First, switch to use the generic kernel.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /boot&lt;br /&gt;
rm System.map config vmlinuz&lt;br /&gt;
ln -s System.map-gen* System.map&lt;br /&gt;
ln -s config-gen* config&lt;br /&gt;
ln -s vmlinuz-gen* vmlinuz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We install spl and zfs inside the live ramfs install-dvd environment, but not yet have we installed them into the root system:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount /dev/sr0 /mnt/cdrom&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /mnt/cdrom/addon/spl-*.txz&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /mnt/cdrom/addon/zfs-*.txz&lt;br /&gt;
depmod&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If instead, you used a 9p share to access the spl and zfs packages, then repeat that procedure here to install them onto the root system.&lt;br /&gt;
&lt;br /&gt;
Setup lilo: edit /etc/lilo.conf so it is like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  lba32&lt;br /&gt;
  append = &amp;quot; vt.default_utf8=1&amp;quot;&lt;br /&gt;
  boot = /dev/sda&lt;br /&gt;
  message = /boot/boot_message.txt&lt;br /&gt;
  prompt&lt;br /&gt;
  timeout = 1200&lt;br /&gt;
  change-rules&lt;br /&gt;
   reset&lt;br /&gt;
  vga = normal&lt;br /&gt;
  image = /boot/vmlinuz&lt;br /&gt;
   initrd = /boot/initrd.gz&lt;br /&gt;
   root = /dev/sda1&lt;br /&gt;
   label = vmlinuz&lt;br /&gt;
   read-only&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The line, root = /dev/sda1, is not really a true statement but lilo needs a device there that it at least understands. This root = line is a kernel parameter, but since the initrd is what is actually the root, initially, then the root = line is probably useless here. It might even be okay to just delete the root line.&lt;br /&gt;
&lt;br /&gt;
Setup mkinitrd:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/mkinitrd.conf.sample /etc/mkinitrd.conf&lt;br /&gt;
vi /etc/mkinitrd.conf&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Edit it to look like this (other defaults should be ok):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 MODULE_LIST=&amp;quot;sym53c8xx:ext4:8139cp:zfs:9p:9pnet_virtio&amp;quot;&lt;br /&gt;
 ROOTDEV=&amp;quot;zfs-root&amp;quot;&lt;br /&gt;
 ROOTFS=&amp;quot;zfs&amp;quot;&lt;br /&gt;
#Module sym53c8xx is the driver for qemu's if=scsi drive device.&lt;br /&gt;
#Module ext4 for /boot.&lt;br /&gt;
#Module 8139cp for eth0 net device.&lt;br /&gt;
#Module zfs for ZFSonLinux.&lt;br /&gt;
#Modules 9p and 9pnet_virtio for mounting qemu -virtfs mount_tag.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These 9p could be useful from the rescue command line inside the initrd to get needed files that are on the host.&lt;br /&gt;
&lt;br /&gt;
All dependent modules will also be included automatically into /boot/initrd-tree, which is packaged as /boot/initrd.gz. For example, to see the dependent modules of zfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
modprobe --show-depends zfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All listed modules will also be in the initrd. Now, make a /boot/initrd-tree that we can begin to look at and edit.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkinitrd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create an empty /etc/mtab or else zpool import fails (zfs expects /etc/mtab to exists already, it won't make it).&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
touch /boot/initrd-tree/etc/mtab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Copy in the fstab.initrd that was made earlier while on the installer. This provides all the mount options for a simple &amp;quot;mount zfs-root&amp;quot; onto /mnt.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/fstab.initrd /boot/initrd-tree/etc/fstab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More package installing! This time into an alternate root, the root of the initrd, /boot/initrd-tree. This is how you can put whatever packages you like into your initrd. These installations work independent of your normal installations. You can install, upgrade, and remove packages using an altroot:&lt;br /&gt;
&lt;br /&gt;
If spl and zfs are on your customized dvd:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/addon/spl-*.txz&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/addon/zfs-*.txz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Otherwise, repeat same procedure but you mount your 9p mount_tag and get them installed.&lt;br /&gt;
&lt;br /&gt;
More regular packages from the dvd:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/kmod-*.txz&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/coreutils-*.txz&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/gptfdisk-*.txz&lt;br /&gt;
&lt;br /&gt;
# A bash script is in /boot/initrd-tree/lib/udev/, so we need it or udev rules have problems:&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/bash-*.txz&lt;br /&gt;
# Bash needs this:&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/l/libtermcap-*.txz&lt;br /&gt;
&lt;br /&gt;
# Install net-tools to ensure that /etc/HOSTNAME, /etc/hosts, and potentially, /etc/hostid are handled proper.&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/n/net-tools-*.txz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When ZFS has to import a zpool while the initrd is running (this can be avoided by not exporting and keeping /etc/zfs/zpool.cache inside the initrd), ZFS will refuse to import a pool if it thinks that the pool may be in use by another system. ZFS was designed for network attached storage where multiple hosts might have access to the same disks but ZFS cannot support two hosts importing and using a ZFS pool at the same time. ZFS checks a value called &amp;quot;hostid&amp;quot; to determine this kind of conflict, and it can be a tricky issue with an initrd boot process. The value of hostid is returned by a system call, the gethostid() function or the hostid command. This function will return the hostid from /etc/hostid if that file exists and has a valid id in it, or else if the file doesn't exist it obtains a hostid number based on the hostname and ip address address assigned to hostname found in /etc/hosts or in DNS. If the hostid trying to import a pool is not the same as the hostid that imported it last time, ZFS will not import the pool unless &amp;quot;zpool import -f zfs-root&amp;quot; is used to force the import. This force option is not recommended to use, so it is best to configure your initrd with matching /etc/HOSTNAME and /etc/hosts as on the root installation and ensure what your system looks like on the initrd matches the booted root system.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Edit /boot/initrd-tree/init (this is the main system startup script on the initrd, responsibe for configuring your block devices and mount your root at /mnt and then booting root):&lt;br /&gt;
&lt;br /&gt;
Inside init, right near the top of the file after the PATH= line, add this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/bin/hostname -F /etc/HOSTNAME&lt;br /&gt;
/bin/hostname $( /bin/hostname -s )&lt;br /&gt;
#/sbin/chhostid 13371400&lt;br /&gt;
# you can make your hostid whatever, but this didn't work right with ZFS, so it is commented out&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This sets the name reported by the hostname command (the default is &amp;quot;darkstar&amp;quot;) to be what is contained in /etc/HOSTNAME. The hostname is modified in the next line to be the short name. These lines will help ZFS to properly identify your host when importing pools.&lt;br /&gt;
&lt;br /&gt;
Inside init, right after it runs &amp;quot;mdadm&amp;quot; commands as used for raid setup, we like it to setup ZFS, so add:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/sbin/zpool import zfs-root&lt;br /&gt;
/sbin/zfs set readonly=on zfs-root&lt;br /&gt;
mount zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Inside init, close to the bottom, where it &amp;quot;Switch to real root partition&amp;quot;, comment out 1 line that normally does the mount:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# mount -o ro -t $ROOTFS $ROOTDEV /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
We have already mounted, and we don't want to use any mount options because we should be using a properly set /etc/fstab inside the initrd for zfs-root mount options onto /mnt.&lt;br /&gt;
&lt;br /&gt;
During a normal startup we want a readonly mount.&lt;br /&gt;
&lt;br /&gt;
Note: we are going to setup with using zpool import and export and startup and shutdown. But later, you can experiment having /etc/zfs/zpool.cache stored in the initrd and commenting out zpool import/export lines.&lt;br /&gt;
&lt;br /&gt;
As mentioned, the import command may sometimes fail, and give the message: &amp;quot;pool may be in use from another system&amp;quot;. This is nothing serious in this test situation. When this happens, root will not be mounted to /mnt and the init script will detect this and drop you into a rescue command line where you may manually &amp;quot;import -f&amp;quot; then &amp;quot;mount zfs-root&amp;quot; and then &amp;quot;exit&amp;quot; to continue on to booting the root.&lt;br /&gt;
&lt;br /&gt;
To avoid this problem we copy some files in (assuming you first edit /etc/HOSTNAME to hold the hostname you like to see on your command prompts, and edited /etc/hosts to have hostname on your loopback or other local ip address):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/HOSTNAME /etc/hosts /boot/initrd-tree/etc&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The value reported by the hostid command is what ZFS sees as your hostid. In this setup so far, the value is based on the ip found assigned to your hostname. If your hostname is on the line in /etc/hosts for ip address 192.168.13.37, then your hostid will be hex numbers C0.A8.0D.25 rearranged as A8C0250D (pairs of bytes are swapped). That is ip-based hostid value, a 32bit hexadecimal number. This has to be the same each boot or import will need a -f option to force it. Simply setting the hostid using the system call sethostid() which writes a /etc/hostid file doesn't seem to agree with ZFS and you'd have to force the import, so this setup now assumes that you do not have or have deleted /etc/hostid.&lt;br /&gt;
&lt;br /&gt;
You can sometimes see what has been happening to a zpool by using the command &amp;quot;zpool history -li zfs-root&amp;quot; to see a log of commands.&lt;br /&gt;
&lt;br /&gt;
Once again, you can do away with the import and export commands by trying to have /etc/zfs/zpool.cache inside your initrd. To create zpool.cache, while on the installer or in the rescue shell of the initrd (at lilo &amp;quot;boot: vmlinuz rescue&amp;quot;), import only the pool for the root fs with mountpoint=none and readonly=on properties set and while it is not mounted:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on installer or initrd rescue shell)&lt;br /&gt;
cp /etc/zfs/zpool.cache /etc/zfs/zpool.cache-initrd&lt;br /&gt;
zfs set readonly=off zfs-root&lt;br /&gt;
mount zfs-pool&lt;br /&gt;
cp /etc/zfs/zpool.cache-initrd /mnt/etc/zfs/&lt;br /&gt;
cp /mnt/etc/zfs/zpool.cache-initrd /mnt/boot/initrd-tree/etc/zfs/zpool.cache&lt;br /&gt;
umount /mnt&lt;br /&gt;
zfs set readonly=on zfs-root&lt;br /&gt;
#mount zfs-root&lt;br /&gt;
#exit (to continue boot process onto rootfs mounted at /mnt)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, doing this zpool.cache approach is not necessary, and some talk suggests this is deprecated or discouraged. Although /etc/hostid setup fails to import without -f option, ip-based (hosts|dns) hostid works on booting and import works without -f option and may be the more proper way to do shutdown and startup rather than using a cache file which could be come invalid and cause a problem that is difficult to understand. The contents and exact function of the cache file are not well understood by many people.&lt;br /&gt;
&lt;br /&gt;
Save /boot/initrd-tree/init and exit.&lt;br /&gt;
&lt;br /&gt;
Now, edit /etc/rc.d/rc.S and rc.6 to understand how to &amp;quot;remount&amp;quot; rw or ro as a readonly property changes&lt;br /&gt;
&lt;br /&gt;
In /etc/rc.d/rc.S:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# comment out the line&lt;br /&gt;
#    /sbin/mount -w -v -n -o remount /&lt;br /&gt;
#add the line&lt;br /&gt;
     /sbin/zfs set readonly=off zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In /etc/rc.d/rc.6&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# comment out the line&lt;br /&gt;
#    /bin/mount -v -n -o remount,ro /&lt;br /&gt;
#add the line&lt;br /&gt;
     /sbin/zfs set readonly=on zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In /etc/rc.d/rc.6, near the bottom just before poweroff|reboot, add the following block of lines:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
########################&lt;br /&gt;
# Try to export zfs-root&lt;br /&gt;
/sbin/zpool export zfs-root&lt;br /&gt;
if [ $? -gt 0 ] ; then&lt;br /&gt;
 echo &amp;quot;ZFS export failed.&amp;quot;&lt;br /&gt;
 echo &amp;quot;Notice: if root fs is busy, then this is normal fail.&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;ZFS export successful.&amp;quot;&lt;br /&gt;
 echo &amp;quot;Warning: successful export is abnormal for root fs.&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
/bin/sleep 5&lt;br /&gt;
########################&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
For ZFS, you cannot run fsck on it. It doesn't support that kind of filesystem checks. The rc.S script will complain a lot in many places about not being about to run fsck on the zfs-root. To disable all attempts of run fsck, we can simple create a file that acts as a flag in /etc/rc.d/rc.S to tell it to skip fsck:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
touch /etc/fastboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This fastboot file is normally a run-once temporary file, and it is deleted near the bottom inside rc.S. Edit rc.S and stop it from deleting /etc/fastboot. We would like it to always skip all fsck. Edit /etc/rc.d/rc.S, and find the &amp;quot;rm&amp;quot; of fastboot, and do not have it removed!&lt;br /&gt;
&lt;br /&gt;
We are getting close, and have finished all editing, so make /boot/initrd.gz and install lilo:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkinitrd -F&lt;br /&gt;
lilo&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We finished! All that's left to do is clean up.&lt;br /&gt;
&lt;br /&gt;
Exit the chroot.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
exit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Try to mount everything:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
umount /mnt/proc&lt;br /&gt;
umount /mnt/sys&lt;br /&gt;
umount /mnt/dev&lt;br /&gt;
umount /mnt/boot&lt;br /&gt;
umount /mnt/mnt/cdrom&lt;br /&gt;
umount /mnt/root/packages&lt;br /&gt;
umount /mnt&lt;br /&gt;
zpool export zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note, that export stops a pool and frees devices, while import binds devices and starts a pool. It is somewhat like mdadm -A -s and mdadm -S -s, while /etc/zfs/zpool.cache might be somewhat like mdadm -E -s &amp;gt; /etc/mdadm.conf.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Remove the DVD or change boot order&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When you reboot, if all is good, you are booting properly onto a slackware installed on a ZFS root! Congrat!&lt;br /&gt;
&lt;br /&gt;
If this seem to go badly, and this might happen if the import fails as explain some before, then you will be on the initrd's rescue command line just before the part in it's init where it wants to mount and switch_root to boot your root. Instead, you typically got commands like this to do:&lt;br /&gt;
&lt;br /&gt;
If you get dumped to rescue because import will not work and requires -f (force), then:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 zpool import -f zfs-root&lt;br /&gt;
 zpool export    zfs-root&lt;br /&gt;
 zpool import    zfs-root&lt;br /&gt;
 mount zfs-root&lt;br /&gt;
 exit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This can happen if hostname, hostid, or uname changes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you get into a jam and need to boot into the initrd and skip zfs import etc, use the lilo prompt (or, boot the install-dvd):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
boot: vmlinuz rescue&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the rescue mode of the initrd, after you have mounted your root as readonly=on to /mnt, then exit to continue.&lt;br /&gt;
&lt;br /&gt;
In other emergency modes, you might need to run the lines at end of init starting from: &amp;lt;code&amp;gt;udevadm info --cleanup-db; udevadm control --exit&amp;lt;/code&amp;gt;&lt;br /&gt;
If you don't run those udevadm commands, two runs of udevd fight each other and it is slow; you have to wait 2 minutes twice for timeouts (4 minutes).&lt;br /&gt;
The last line is run is: &amp;lt;code&amp;gt;exec switch_root /mnt /sbin/init 1&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Warning... this switch_root command is kind of dangerous, so read the manual page about it.&lt;br /&gt;
From what I can tell, everything except the new root &amp;quot;/mnt&amp;quot; is deleted, so you are giving a command that says what NOT to delete!&lt;br /&gt;
Make sure nothing got mounted outside of &amp;quot;/mnt&amp;quot; before you run it.&lt;br /&gt;
&lt;br /&gt;
Also, in rescue or anytime you have finished making changes and are about to reboot in some abnormal mode, first run:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set readonly=on zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A bug in unpatched grep 2.13 build 1, found slackware 14.0rc1, causes problems when processing files stored on ZFS but rarely shows problems on other filesystems; the bug does not handle sparse files on zfs and btrfs correctly and results in chaos with slackpkg, compiling kernel modules, and possibly many other things. You must downgrade grep to 2.12 or use the patched grep 2.13 build 2 in slackware 14.0rc2 or later.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Upgrading.&lt;br /&gt;
&lt;br /&gt;
From time to time you will want to upgrade the kernel to the new kernel in slackware64-current or in patches/. This will also necessitate a rebuilt and reinstall or upgrade of spl and zfs. Below is an example of when both kernel and spl/zfs are being upgraded, to give an idea of the process:&lt;br /&gt;
&lt;br /&gt;
Using slackpkg, that is configured to use your local slackware mirror is a good option but you can also configure it to use a remote mirror.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slackpkg upgrade-all&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Assume slackpkg just upgraded your kernel, kernel-modules, and kernel-headers.&lt;br /&gt;
&lt;br /&gt;
Note: the first time you try to run on kernel-generic, setup kernel-huge in lilo as 2nd choice. Huge has all the hard drive controllers builtin, but generic has them all as modules. For example, run &amp;quot;modinfo mptsas&amp;quot; to see module options (maybe you have a LSISAS1068) for your hard drive controller. Add file /etc/modprobe.d/mptsas.conf to set options you want with a line: options mptsas ... Do this for all the device driver modules for your hardware. Do this setup while you are on the huge kernel, then setup to reboot to generic. Include all these modules you need into mkinitrd.conf MODULES_LIST. Check that /boot/initrd-tree/etc/modprobe.d/ has a copy of your customized module conf files because it is on the initrd where the modules will load and use the conf files. mkinitrd probably copies all /etc/modprobe.d/* files into the initrd-tree, but check it. Pay attention to /etc/modprobe.d/README and /lib/modprobe.d/* /lib/modprobe.d/* maybe not copied to initrd-tree but you might want to copy some of it into your initrd-tree yourself to use them.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Check that upgraded kernel-source is symlinked to /usr/src/linux (zfs build looks here). SQL/ZFS modules will install to the kernel version in /lib/modules/&amp;lt;/usr/src/linux kernel version&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /usr/local/src&lt;br /&gt;
tar xvzf ~/spl-*.tar.gz&lt;br /&gt;
tar xvzf ~/zfs-*.tar.gz&lt;br /&gt;
&lt;br /&gt;
###### upgrade spl 1st&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-*&lt;br /&gt;
./configure --prefix=/ --libexecdir=/usr/libexec --libdir=/lib64 --includedir=/usr/include --datarootdir=/usr/share&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=/usr/local/src/install&lt;br /&gt;
cd ../install&lt;br /&gt;
makepkg ../spl-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
upgradepkg spl-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
depmod &amp;lt;new kernel version&amp;gt;     (e.g. depmod 3.2.27, if .27 is new kernel upgrade; you currently run on old, maybe .26)&lt;br /&gt;
# this builds the module dependencies in /lib/modules/&amp;lt;new kernel version&amp;gt;&lt;br /&gt;
###### upgrade zfs 2nd&lt;br /&gt;
mkdir install&lt;br /&gt;
cd zfs-*&lt;br /&gt;
./configure --prefix=/ --libexecdir=/usr/libexec --libdir=/lib64 --includedir=/usr/include --datarootdir=/usr/share&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=/usr/local/src/install&lt;br /&gt;
cd ../install&lt;br /&gt;
makepkg ../zfs-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
upgradepkg zfs-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
depmod 3.2.27&lt;br /&gt;
####### upgrade spl/zfs inside altroot /boot/initrd-tree&lt;br /&gt;
ROOT=/boot/initrd-tree upgradepkg spl-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
ROOT=/boot/initrd-tree upgradepkg zfs-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
# note: ROOT is an environment variable, not a command line option to upgradepkg!&lt;br /&gt;
# note: do not worry about depmod inside initrd-tree, mkinitrd -F actually installs the modules&lt;br /&gt;
# note: this upgrade here is really to just upgrade the command line tools zpool, zfs etc&lt;br /&gt;
####### rebuild /boot/initrd.gz and reinstall lilo&lt;br /&gt;
vi /etc/mkinitrd.conf&lt;br /&gt;
# temporarily set KERNEL_VERSION to new version, but you are still running on old version&lt;br /&gt;
mkinitrd -F&lt;br /&gt;
lilo&lt;br /&gt;
vi /etc/mkinitrd.conf&lt;br /&gt;
# you can set KERNEL_VERSION back to $(uname r) now&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After reboot you can remove any old /lib/modules/&amp;lt;old kernel version&amp;gt; directory.&lt;br /&gt;
&lt;br /&gt;
More about /etc/hostid. If you want to experiment changing your /etc/hostid file and seeing if you can use it and make zpool import work normally, here is a tool that might be helpful:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/* software product name: foobarz-chhostid.c&lt;br /&gt;
 * suggested binary name: chhostid&lt;br /&gt;
 * license              : BSD&lt;br /&gt;
 * license text:&lt;br /&gt;
Copyright (c) 2012, foobarz&lt;br /&gt;
All rights reserved.&lt;br /&gt;
&lt;br /&gt;
Redistribution and use in source and binary forms, with or without&lt;br /&gt;
modification, are permitted provided that the following conditions are met:&lt;br /&gt;
    * Redistributions of source code must retain the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer.&lt;br /&gt;
    * Redistributions in binary form must reproduce the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer in the&lt;br /&gt;
      documentation and/or other materials provided with the distribution.&lt;br /&gt;
    * Neither the name of the &amp;lt;organization&amp;gt; nor the&lt;br /&gt;
      names of its contributors may be used to endorse or promote products&lt;br /&gt;
      derived from this software without specific prior written permission.&lt;br /&gt;
&lt;br /&gt;
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &amp;quot;AS IS&amp;quot; AND&lt;br /&gt;
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED&lt;br /&gt;
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE&lt;br /&gt;
DISCLAIMED. IN NO EVENT SHALL &amp;lt;COPYRIGHT HOLDER&amp;gt; BE LIABLE FOR ANY&lt;br /&gt;
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES&lt;br /&gt;
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;&lt;br /&gt;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND&lt;br /&gt;
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT&lt;br /&gt;
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS&lt;br /&gt;
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#define FOOBARZ_CHHOSTID_VERSION &amp;quot;1.0.5&amp;quot;&lt;br /&gt;
#include &amp;lt;sys/socket.h&amp;gt;&lt;br /&gt;
#include &amp;lt;netinet/in.h&amp;gt;&lt;br /&gt;
#include &amp;lt;arpa/inet.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;endian.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sysexits.h&amp;gt;&lt;br /&gt;
/* note: if include stdlib then sethostid fails even with _BSD_SOURCE defined */&lt;br /&gt;
&lt;br /&gt;
long swapbytes(long abcd) {&lt;br /&gt;
  long badc;&lt;br /&gt;
  unsigned char addr_a;&lt;br /&gt;
  unsigned char addr_b;&lt;br /&gt;
  unsigned char addr_c;&lt;br /&gt;
  unsigned char addr_d;&lt;br /&gt;
  addr_a = (unsigned char) (abcd &amp;gt;&amp;gt; 24);&lt;br /&gt;
  addr_b = (unsigned char) (abcd &amp;gt;&amp;gt; 16);&lt;br /&gt;
  addr_c = (unsigned char) (abcd &amp;gt;&amp;gt;  8);&lt;br /&gt;
  addr_d = (unsigned char) (abcd);&lt;br /&gt;
  return badc = ( (addr_b &amp;lt;&amp;lt; 24) | (addr_a &amp;lt;&amp;lt; 16) | (addr_d &amp;lt;&amp;lt; 8) | addr_c );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[])&lt;br /&gt;
{&lt;br /&gt;
 long newhostid;&lt;br /&gt;
 struct in_addr addr;&lt;br /&gt;
 char* invalidchar;&lt;br /&gt;
&lt;br /&gt;
 /*********** check command line */&lt;br /&gt;
 if(!( ((argc==3) &amp;amp;&amp;amp; ( (strcmp(argv[1],&amp;quot;-h&amp;quot;)==0) ||&lt;br /&gt;
                       (strcmp(argv[1],&amp;quot;-i&amp;quot;)==0) ||&lt;br /&gt;
                       (strcmp(argv[1],&amp;quot;-l&amp;quot;)==0) )) ||&lt;br /&gt;
       ((argc==2) &amp;amp;&amp;amp; ( (strcmp(argv[1],&amp;quot;-s&amp;quot;)==0) ))&lt;br /&gt;
     )&lt;br /&gt;
   ) {&lt;br /&gt;
                 /*01234567890123456789012345678901234567890123456789012345678901234567890123456789*/&lt;br /&gt;
  fprintf(stderr, &amp;quot;foobarz-chhostid, version %s. License: BSD.\n&amp;quot;, FOOBARZ_CHHOSTID_VERSION);&lt;br /&gt;
  fprintf(stderr, &amp;quot;foobarz-chhostid, (c) 2012, foobarz; all rights reserved.\n&amp;quot;);&lt;br /&gt;
  fprintf(stderr, &amp;quot;descr: %s change system hostid (in /etc/hostid).\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -h &amp;lt;new hostid&amp;gt;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        Change system hostid to &amp;lt;new hostid&amp;gt;;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        &amp;lt;new hostid&amp;gt; must be 32bit 8-digit hex number xxxxxxxx, each x in 0-f|F.\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        The ip corresponding to &amp;lt;new hostid&amp;gt; is also listed for reference only.\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -i &amp;lt;dotted ip address&amp;gt;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        Change system hostid to hostid corresponding to &amp;lt;dotted ip address&amp;gt;.\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -l &amp;lt;dotted ip address&amp;gt;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        List hostid corresponding to &amp;lt;dotted ip address&amp;gt;;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        no change to system hostid.\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -s\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        List current system hostid and corresponding ip address;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        no change to system hostid.\n&amp;quot;, argv[0]);&lt;br /&gt;
  return EX_USAGE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -h &amp;lt;hostid&amp;gt; */&lt;br /&gt;
 if( strcmp(argv[1],&amp;quot;-h&amp;quot;) == 0 ) {&lt;br /&gt;
  if(strlen(argv[2]) != 8) { fprintf(stderr, &amp;quot;new hostid must be 8-digit hex number xxxxxxxx, each x in 0-f|F\n&amp;quot;); return EX_USAGE; }&lt;br /&gt;
&lt;br /&gt;
  newhostid = strtol(argv[2],&amp;amp;invalidchar,16);&lt;br /&gt;
  if( newhostid==LONG_MIN ) { perror(&amp;quot;strtol (underflow)&amp;quot;); return EX_USAGE; }&lt;br /&gt;
  if( newhostid==LONG_MAX ) { perror(&amp;quot;strtol (overflow)&amp;quot;); return EX_USAGE; }&lt;br /&gt;
  if(*invalidchar != '\0') { fprintf(stderr, &amp;quot;invalid hex number %c; must be in 0-f|F\n&amp;quot;, *invalidchar); return EX_USAGE; }&lt;br /&gt;
&lt;br /&gt;
  if( sethostid(newhostid) != 0 ) {&lt;br /&gt;
   perror(&amp;quot;sethostid&amp;quot;);&lt;br /&gt;
   if( errno == EPERM ) return EX_NOPERM;&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
  }&lt;br /&gt;
  printf(&amp;quot;System hostid changed.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  /* hostid is a byte-swapped ip like b.a.d.c */&lt;br /&gt;
  /* get ip by swapping to correct order a.b.c.d and save into in_addr struct */&lt;br /&gt;
  addr.s_addr = htonl(swapbytes(newhostid));&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -i or -l, then find hostid for &amp;lt;dotted ip address&amp;gt; */&lt;br /&gt;
 if( (strcmp(argv[1],&amp;quot;-i&amp;quot;) == 0) || (strcmp(argv[1],&amp;quot;-l&amp;quot;) == 0) ) {&lt;br /&gt;
  if( inet_aton(argv[2], &amp;amp;addr) == 0 ) { fprintf(stderr, &amp;quot;inet_aton: invalid dotted ip address: %s\n&amp;quot;, argv[2]); return EX_USAGE; }&lt;br /&gt;
&lt;br /&gt;
  /* hostid is a byte-swapped ip like b.a.d.c */&lt;br /&gt;
  /* get hostid by swapping bytes of ip a.b.c.d */&lt;br /&gt;
  newhostid = swapbytes(ntohl(addr.s_addr));&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -i &amp;lt;dotted ip address&amp;gt; */&lt;br /&gt;
 if( strcmp(argv[1],&amp;quot;-i&amp;quot;) == 0 ) {&lt;br /&gt;
  if( sethostid(newhostid) != 0 ) {&lt;br /&gt;
   perror(&amp;quot;sethostid&amp;quot;);&lt;br /&gt;
   if( errno == EPERM ) return EX_NOPERM;&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
  }&lt;br /&gt;
  printf(&amp;quot;System hostid changed.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -l &amp;lt;dotted ip address&amp;gt; */&lt;br /&gt;
 if(strcmp(argv[1],&amp;quot;-l&amp;quot;) == 0 ) {&lt;br /&gt;
   printf(&amp;quot;Listing hostid for ip. (no changes)\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -s */&lt;br /&gt;
 if(strcmp(argv[1],&amp;quot;-s&amp;quot;) == 0 ) {&lt;br /&gt;
   /* see if /etc/hostid exists and print info */&lt;br /&gt;
   if( access(&amp;quot;/etc/hostid&amp;quot;, F_OK) != 0 ) {&lt;br /&gt;
     printf(&amp;quot;Notice: /etc/hostid does not exist.\n&amp;quot;);&lt;br /&gt;
     perror(&amp;quot;Reason&amp;quot;);&lt;br /&gt;
     printf(&amp;quot;System hostid derived from ip of hostname found in hosts file or dns.\n&amp;quot;);&lt;br /&gt;
   } else {&lt;br /&gt;
     printf(&amp;quot;Notice: /etc/hostid exists.\n&amp;quot;&lt;br /&gt;
            &amp;quot;System hostid is obtained from hostid file.\n&amp;quot;);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
  errno=0;&lt;br /&gt;
  newhostid = gethostid();&lt;br /&gt;
  if(errno!=0) { perror(&amp;quot;gethostid&amp;quot;); return EX_UNAVAILABLE; }&lt;br /&gt;
&lt;br /&gt;
  /* hostid is a byte-swapped ip like b.a.d.c */&lt;br /&gt;
  /* get ip by swapping to correct order a.b.c.d and save into in_addr struct */&lt;br /&gt;
  addr.s_addr = htonl(swapbytes(newhostid));&lt;br /&gt;
&lt;br /&gt;
  printf(&amp;quot;Listing current system hostid. (no changes)\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** print info and return */&lt;br /&gt;
 printf(&amp;quot;ip dot: %s\n&amp;quot;, inet_ntoa(addr) );&lt;br /&gt;
 printf(&amp;quot;ip hex: %.8x\n&amp;quot;, ntohl(addr.s_addr) );&lt;br /&gt;
 printf(&amp;quot;hostid: %.8x\n&amp;quot;, newhostid );&lt;br /&gt;
 return EX_OK;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</description>
			<pubDate>Sat, 18 Aug 2012 18:44:38 GMT</pubDate>
			<dc:creator>Foobarz</dc:creator>
			<comments>https://www.slackwiki.com/Talk:ZFS_root</comments>
		</item>
		<item>
			<title>ZFS root</title>
			<link>https://www.slackwiki.com/index.php?title=ZFS_root&amp;diff=732</link>
			<guid isPermaLink="false">https://www.slackwiki.com/index.php?title=ZFS_root&amp;diff=732</guid>
			<description>&lt;p&gt;Foobarz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;If you have heard about the ZFS filesystem and you're curious to try it out, then you can try it on slackware64, thanks to the ZFSonLinux.org project!&lt;br /&gt;
&lt;br /&gt;
In this article, an example is shown of how to install slackware64 14.0 onto a ZFS root filesystem (zfs-root) inside a QEMU virtual machine for testing purposes. It is recommended that you install qemu and learn how to use it to test a ZFS installation before you decide to use it on real hardware. A slackbuild for qemu can be found on slackbuilds.org. If you have a processor that supports Intel VT-x or AMD AMD-V virtualization acceleration (try modprobe kvm-intel or modprobe kvm-amd), then use the slackbuild for qemu-kvm.&lt;br /&gt;
&lt;br /&gt;
This article isn't going to go into any detail on actually using ZFS or what kinds of installation options and settings might be optimal. This article just presents an example of how to get started with ZFS on slackware.&lt;br /&gt;
&lt;br /&gt;
At this time of writing, ZFSonLinux is at &amp;quot;release candidate&amp;quot; (version 0.6.0-rc10) development stage, and many issues can occur. See the ZFSonLinux.org web site and the issues tracker for an idea about the current issues. There is also an irc channel on irc.freenode.net, #zfsonlinux, for discussion of issues and help.&lt;br /&gt;
&lt;br /&gt;
Although not required, it is helpful to keep a local mirror of slackware64 on your system. Having a local mirror makes it easier to upgrade to slackware64-current or to patches/* in a release. To help manage your own local slackware mirror and generate your own CD and DVD slackware installers, see http://alien.slackbook.org/blog/local-slackware-mirror/.&lt;br /&gt;
&lt;br /&gt;
In this article, we use a slackware64-current DVD image file as the qemu cdrom device media for the installation of the slackware guest. This was tested at slackware64-current = slackware64 14.0rc2. You can obtain a slackware DVD image using a torrent, buy the DVD from slackware.com, or generate your own DVD image file using the mirror script. For an actual DVD, you can pass your DVD device (e.g., /dev/sr0) as the qemu cdrom device. For a DVD image file, pass the image file as the qemu cdrom device.&lt;br /&gt;
&lt;br /&gt;
The ZFSonLinux packages are not included in slackware at this time. There are two packages involved: spl and zfs. The first, spl, is &amp;quot;Solaris Porting Layer&amp;quot; and must be installed on the system before zfs can be compiled. The source code tarballs for these are at ZFSonLinux.org. At this time of writing, they are spl-0.6.0-rc10.tar.gz and zfs-0.6.0-rc10.tar.gz.&lt;br /&gt;
&lt;br /&gt;
At this point, it is assumed you have qemu installed, have obtained a slackware64-current/14.0 DVD, and have downloaded spl and zfs tarballs to your host system. The first step now is, if your host is not slackware64-current/14.0 (the same as the guest will be), then you need to create a minimal development slackware64 guest system in qemu for just the purpose of compiling and packaging the spl and zfs slackware packages and transferring a copy of these packages back onto your host system to use later to install onto zfs during the slackware install process.&lt;br /&gt;
&lt;br /&gt;
From this point onward, instructions become a bit terse and mostly limited to examples of the commands you might use to complete tasks. You are encouraged to examine what each command does by reading the command's man pages. For example, the command &amp;quot;man qemu&amp;quot; can show you most of what you need to know about running qemu on the command line.&lt;br /&gt;
&lt;br /&gt;
So, here's an example of how you might build the spl and zfs packages, starting in your home directory:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on host)&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir qemu&lt;br /&gt;
cd qemu&lt;br /&gt;
mkdir slackdevel&lt;br /&gt;
cd slackdevel&lt;br /&gt;
mkdir packages&lt;br /&gt;
cp ~/spl-*.tar.gz packages&lt;br /&gt;
cp ~/zfs-*.tar.gz packages&lt;br /&gt;
qemu-img create disk1.raw 10G&lt;br /&gt;
ln -s ~/slackware64-current-install-dvd.iso dvd.iso&lt;br /&gt;
qemu-system-x86_64 \&lt;br /&gt;
 -no-quit \&lt;br /&gt;
 -no-shutdown \&lt;br /&gt;
 -boot order=cd,menu=on \&lt;br /&gt;
 -m 2G \&lt;br /&gt;
 -cpu host \&lt;br /&gt;
 -smp sockets=1,cores=4 \&lt;br /&gt;
 -net nic,model=rtl8139 -net user \&lt;br /&gt;
 -cdrom dvd.iso \&lt;br /&gt;
 -drive boot=on,format=raw,media=disk,cache=none,aio=native,if=scsi,bus=0,unit=0,file=disk1.raw \&lt;br /&gt;
 -virtfs local,path=./packages/,security_model=none,mount_tag=hostpackages&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When you need to change boot to cd or disk, add or remove &amp;quot;boot=on&amp;quot;, or change &amp;quot;order=dc&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Qemu should boot into the install-dvd, and now perform a very ordinary slackware64 install onto /dev/sda. Install d package set and most others, but package sets x, kde, xfce not really needed.&lt;br /&gt;
&lt;br /&gt;
First note: examples here use tools from the gptfdisk package (gdisk, sgdisk, cgdisk) to partition the disk with GUID partition table (GPT) format. GPT might not be too familiar to everyone, who mostly have only used MBR partitions with fdisk. In the slackware installations this author has tested in qemu, using GPT partitions has caused no problems with lilo or other tools used in slackware. GPT disk labels support creating up to 128 partitions and support disks larger than 2TB (the limit of MBR fdisk). LILO installs into the first 440 bytes on /dev/sda, inside a GPT &amp;quot;protective MBR&amp;quot; that serves to provide compatibility with MBR bootloaders like lilo. LILO uses LBA32 sector addressing and can see all 512-byte sectors side the first 2TB of a disk. So long as the /boot partition is within the first 2TB of a disk, lilo can work on a disk larger than 2TB. Unlike the common default of fdisk to start the first partition at sector 63, which is not aligned with the 4KiB sector size of Advanced Format hard disks, gdisk's default is to start partitions at 2048 sector (1MiB) boundaries which are also 4KiB aligned. Using gdisk GPT works on all disks and is compatible with using Advanced Format hard disks larger than 2TB. More information about GPT disk label format can be found on wikipedia.org. For those that have used grub instead of lilo, grub installation is different with GPT than with MBR, and grub requires a GPT partition of type grub-bios or 0xEF02 &amp;quot;BIOS Boot Partition&amp;quot; of about 8MiB where it can install it's additional bootloader stages because grub cannot embed in sectors 1-62 on GPT where GPT keeps it's partition tables. On MBR, sectors 1-62 were normally reserved space for bootloaders to keep a 2nd stage.&lt;br /&gt;
&lt;br /&gt;
For this purpose of development guest, just create a simple 1-partition system, /dev/sda1, and do a simple slackware install on it. Don't bother with swap or separate /boot unless you want to:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on install-dvd)&lt;br /&gt;
cgdisk /dev/sda&lt;br /&gt;
setup&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When this simple development guest boots, login as root, and continue:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on qemu guest)&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir packages&lt;br /&gt;
mount hostpackages -t 9p -o trans=virtio packages&lt;br /&gt;
echo --prefix=/ --libexecdir=/usr/libexec --libdir=/lib64 --includedir=/usr/include --datarootdir=/usr/share &amp;gt; configure-options&lt;br /&gt;
mkdir src&lt;br /&gt;
cd src&lt;br /&gt;
&lt;br /&gt;
mkdir install&lt;br /&gt;
tar xvzf ~/packages/spl-*.tar.gz&lt;br /&gt;
cd spl-*&lt;br /&gt;
./configure $( cat ~/configure-options )&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../spl-&amp;lt;version&amp;gt;_&amp;lt;kernel_version&amp;gt;-x86_64-&amp;lt;build_id&amp;gt;.txz&lt;br /&gt;
(e.g., makepkg ../spl-0.6.0rc10_3.2.27-x86_64-1root.txz)&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
installpkg spl-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
cp spl-0.6.0rc10_3.2.27-x86_64-1root.txz ~/packages&lt;br /&gt;
&lt;br /&gt;
mkdir install&lt;br /&gt;
tar xvzf ~/packages/zfs-*.tar.gz&lt;br /&gt;
cd zfs-*&lt;br /&gt;
./configure $( cat ~/configure-options )&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../zfs-&amp;lt;version&amp;gt;_&amp;lt;kernel_version&amp;gt;-x86_64-&amp;lt;build_id&amp;gt;.txz&lt;br /&gt;
(e.g., makepkg ../zfs-0.6.0rc10_3.2.27-x86_64-1root.txz)&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
installpkg zfs-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
cp zfs-0.6.0rc10_3.2.27-x86_64-1root.txz ~/packages&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point spl and zfs packages are copied back to the host in the packages directory. Also, spl and zfs are installed in this simple development guest, so one could begin to experiment with zfs pools and datasets but while the root fs is whatever you made it during setup (probably the default, ext4). This development guest isn't really needed anymore, so it can be deleted:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
halt&lt;br /&gt;
(exit qemu: ctrl-alt-2 then enter quit at QEMU command prompt)&lt;br /&gt;
&lt;br /&gt;
(on host)&lt;br /&gt;
rm disk1.raw dvd.iso&lt;br /&gt;
mv packages ..&lt;br /&gt;
cd ..&lt;br /&gt;
rmdir slackdevel&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now that we have the spl and zfs packages on the host, it is possible to copy them into your local slackware64 mirror and then generate your own install DVD image that includes them. For example, change to the directory that contains the slackware README files, and create a &amp;quot;addon&amp;quot; directory and copy the spl and zfs slackware packages into there. Then, generate the DVD image using a command such as $( ./mirror-slackware-current.sh -i ) from where you have this script configured to maintain your local mirror. We can also just continue to access them inside the installer using qemu's virtfs option. When you are going to do a real installation onto real hardware, you need to generate and burn your own DVD that includes the packages.&lt;br /&gt;
&lt;br /&gt;
It is time to begin the installation of slackware64 on a ZFS root, assuming either you have regenerated dvd.iso with zfs packages in addon/* or we access the zfs packages while in the installer using qemu's virtfs to the host's packages directory. ZFS supports creating complex data storage configurations such as pools (similar to a volume group) backed by one or more of various kinds of virtual devices (similar to disks and raid arrays) and containing one or more datasets (similar to mounted filesystems, logical volume devices, or snapshots). But here, we keep it simple and will install on just a single disk device. On a real ZFS installation, users will typically want to use the ZFS raidz1 or raidz2 virtual device types for reliability against hard drive failures.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on host)&lt;br /&gt;
mkdir slackzfs&lt;br /&gt;
mv packages slackzfs/&lt;br /&gt;
cd slackzfs&lt;br /&gt;
qemu-img create disk1.raw 10G&lt;br /&gt;
ln -s ~/slackware64-current-install-dvd.iso dvd.iso&lt;br /&gt;
qemu-system-x86_64 \&lt;br /&gt;
 -no-quit \&lt;br /&gt;
 -no-shutdown \&lt;br /&gt;
 -boot order=cd,menu=on \&lt;br /&gt;
 -m 2G \&lt;br /&gt;
 -cpu host \&lt;br /&gt;
 -smp sockets=1,cores=4 \&lt;br /&gt;
 -net nic,model=rtl8139 -net user \&lt;br /&gt;
 -cdrom dvd.iso \&lt;br /&gt;
 -drive boot=on,format=raw,media=disk,cache=none,aio=native,if=scsi,bus=0,unit=0,file=disk1.raw \&lt;br /&gt;
 -virtfs local,path=./packages/,security_model=none,mount_tag=hostpackages&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The install-dvd should boot, and then begin installation steps on the installer command line:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on install-dvd)&lt;br /&gt;
# mount the install-dvd&lt;br /&gt;
mkdir /dvd&lt;br /&gt;
mount /dev/sr0 /dvd&lt;br /&gt;
&lt;br /&gt;
# install coreutils, which provides the &amp;quot;hostid&amp;quot; command needed to load the spl module&lt;br /&gt;
installpkg /dvd/slackware64/a/coreutils-8.17-x86_64-1.txz&lt;br /&gt;
&lt;br /&gt;
# install kmod package which includes &amp;quot;depmod&amp;quot; command and others&lt;br /&gt;
installpkg /dvd/slackware64/a/kmod-9-x86_64-2.txz&lt;br /&gt;
depmod&lt;br /&gt;
&lt;br /&gt;
# install the full kernel modules so you can load 9p filesystem and use it if you want&lt;br /&gt;
# .. you might keep the zfs modules packages off the dvd and use a plain slack dvd&lt;br /&gt;
installpkg /dvd/slackware64/a/kernel-modules-*.txz&lt;br /&gt;
depmod&lt;br /&gt;
&lt;br /&gt;
# install bash and libtermcap because udev rules in zfs use bash scripts&lt;br /&gt;
installpkg /dvd/slackware64/a/bash-*.txz&lt;br /&gt;
installpkg /dvd/slackware64/l/libtermcap-*.txz&lt;br /&gt;
&lt;br /&gt;
# install spl and zfs that you have copied into the mirror before running the DVD creation&lt;br /&gt;
installpkg /dvd/addon/spl-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /dvd/addon/zfs-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
&lt;br /&gt;
Or:&lt;br /&gt;
mkdir /packages&lt;br /&gt;
find /lib/modules/ | grep 9p&lt;br /&gt;
lsmod&lt;br /&gt;
# check that 9p modules load, mainly 9pnet_virtio&lt;br /&gt;
modprobe 9pnet_virtio&lt;br /&gt;
mount hostpackages -t 9p -o trans=virtio /packages&lt;br /&gt;
installpkg /packages/spl-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /packages/zfs-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
modprobe zfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now zfs tools: &amp;quot;zpool&amp;quot; and &amp;quot;zfs&amp;quot; should work in the live installer.&lt;br /&gt;
On the installer, there can be trouble seeing man pages, so install:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
installpkg /dvd/slackware64/ap/man-*.txz&lt;br /&gt;
installpkg /dvd/slackware64/ap/groff-*.txz&lt;br /&gt;
installpkg /dvd/slackware64/a/less-*.txz&lt;br /&gt;
export MANPATH=/usr/man:/usr/share/man&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The manual pages should be readable:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
man zpool&lt;br /&gt;
man zfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After seeing the man pages, we should be fully ready to continue to setup on ZFS.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(still on install-dvd)&lt;br /&gt;
ls -l /dev/sd*&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Make sure the disk devices you expect are there. We'll use sda and make boot (/boot on /dev/sda1) and root (/ on /dev/sda2) partitions.&lt;br /&gt;
&lt;br /&gt;
First, some background info: A ZFS filesystem is not supported by lilo as the filesystem containing /boot, which holds lilo's 2nd stage and the linux kernel files. The on-disk format of a ZFS filesystem is often a complex raid configuration where even if lilo understood ZFS it would likely require /boot to reside in only certain simple ZFS configurations to be plainly readable to lilo. As things are, a linux root installed in a partition with ZFS filesystem needs /boot to be on another partition with a filesystem that lilo understands, such as ext4 fs. In addition, because the spl and zfs modules are not built into the kernel, and the zfs startup requires some configuration to mount the zfs root, an initial ram/root filesystem (initrd) is needed. The initrd is a gzip compressed cpio archive file that contains a small linux root operating system that is decompressed into a ramfs block device at boot up and takes initial control of the system. The initrd contains an init script that configures devices in devtmpfs mounted at /dev. For example, if using mdadm, lvm, luks, losetup, and now zfs, this init script runs all the commands to create or start these devices (one of which is the root device), mounts the root device, and then transfers system control to the init script in the mounted root filesystem. The ramfs-based root environment on the booted install-dvd or booted initrd image (in rescue command line) are small slackware installations that exist only in ram and are temporary, but while inside them you can install, upgrade, and remove slackware packages inside them using the regular package management tools; this allows you access to any kernel modules and programs as needed inside these ramfs root. Packages can be installed, upgraded, or removed permanantly in the initrd image file to manage the programs and modules required during the initrd boot stage. Also from within these ramfs initial root environments, once the root device is mounted, chroot can be used to work on the mounted root system as if it were booted; this allows one to fix problems that are occuring in the root fs init scripts that cause normal booting to fail, or to install a kernel and/or modules etc. Now on to partitioning:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
cgdisk /dev/sda&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, cgdisk looks just like cfdisk, but it makes GPT partitions.&lt;br /&gt;
&lt;br /&gt;
Make a partition for /boot that is about 512MiB of whatever partition type you like (8300 &amp;quot;Linux filesystem&amp;quot; is fine), or make it type bf07 &amp;quot;Solaris Reserved 1&amp;quot; if you want ZFS to maybe see the disk as if it was given as a whole disk to ZFS. Make a second partition using the remaining space with partition type bf01 &amp;quot;Solaris ZFS&amp;quot;. Currently, when ZFSonLinux is given a whole disk device like /dev/sdb to use, it will automatically GPT partition it with a bf01 partition #1 that is the whole disk except a small 8MiB type bf07 partition #9 at the end of the disk (/dev/sdb1 and /dev/sb9). The small 8MiB type bf07 partition #9 is mostly likely reserved for use by bootloaders, like lilo, to have a /boot or other boot-related files kept there. For example, you might have /dev/sda that is totally non-ZFS for booting and /dev/sdb passed to ZFS whole where it automatically partitions sdb, but you can just use one disk here and make partitions. Lets use type 8300 for /boot to be sure nothing is confused:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
We'll continue with this partitioning (numbers are in MiB):&lt;br /&gt;
  0 to   4: unused&lt;br /&gt;
  4 to 516: /dev/sda1 512MiB, type 8300&lt;br /&gt;
516 to 520: unused&lt;br /&gt;
520 to -96: /dev/sda2, type bf01&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The -96 means to count from the end of the disk so that 96MiB will remain unused at the end of the disk.&lt;br /&gt;
&lt;br /&gt;
Create a zpool called zfs-root:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool create -m none zfs-root /dev/sda2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A zpool created like this, the normal way, is a kernel-internal block device that contains already a zfs filesystem. There is normally no entry in /dev for this device. However, it can still be referenced as a mountable device similar to how devtmpfs, proc, and sysfs are also kernel-internal mountable block devices. The -m option told zpool not to automatically mount it anywhere, and without -m the default is to always automatically mount to /zfs-root. These kinds of details are explained better elsewhere. For this situation, we do not want it automounted.&lt;br /&gt;
&lt;br /&gt;
Because a zpool itself is a useable zfs fs, it has a full set of zfs &amp;quot;properties&amp;quot; to set options about the filesystem, perhaps similar to tune2fs. The &amp;quot;mountpoint=&amp;lt;some place to mount&amp;gt;&amp;quot; is one such property. We want it set to the special value &amp;quot;none&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs get mountpoint zfs-root&lt;br /&gt;
zfs set mountpoint=none zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On creation, the zpool zfs-pool is &amp;quot;imported&amp;quot; and has a zpool status that can be viewed:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zpool status zfs-root&lt;br /&gt;
&lt;br /&gt;
zpool export zfs-root&lt;br /&gt;
zpool status zfs-root&lt;br /&gt;
# Now there is no status.&lt;br /&gt;
&lt;br /&gt;
zpool import zfs-root&lt;br /&gt;
# Now it is back.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When a zpool is imported, it has it's current configuration cached in a file /etc/zfs/zpool.cache. When a zpool is exported, then it's entries in the cache file are removed and the cache file is deleted if it becomes empty. So long as the zfs kernel modules see this cache file and valid cache data inside it, ZFS considers the described zpools in the cache file to be valid as imported zpools. If the zpool.cache file is present at the time the zfs modules are loaded, then there is no further need to use the import and export commands at system startup and shutdown. With root on a zfs, it is not possible to export the pool that root is on, but this is not a problem. At shutdown, the safe procedure will be to set the zfs-root property readonly=on and sync disks.&lt;br /&gt;
&lt;br /&gt;
To avoid the requirement to import the zfs-root pool at startup, keep a copy of the zpool.cache file to later copy onto the initrd image to read at modules load time to have the pool reactived without need to issue the import command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/zfs/zpool.cache /etc/zfs/zpool.cache-initrd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A zfs fs will not normally allow you to mount over any files. The mountpoint is expected to be an empty directory. Remove any junk files inside the installer's /mnt because zfs won't mount over any files:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rm /mnt/README&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The directory /mnt is where the slackware setup expects you to mount your root for installation.&lt;br /&gt;
&lt;br /&gt;
Controlling whether a zfs fs is to be mounted read-only or read-write is best managed by setting the readonly property while it is not yet mounted:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set readonly=on zfs-root&lt;br /&gt;
zfs set readonly=off zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Slackware expects root to be mounted readonly when /etc/rc.S runs during normal startup, so later this is used to satisfy slackware's expectation to avoid rc.S complaining.&lt;br /&gt;
&lt;br /&gt;
The zfs-root can be mounted and unmounted in two different ways:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=/mnt zfs-root&lt;br /&gt;
zfs set mountpoint=none zfs-root&lt;br /&gt;
# or&lt;br /&gt;
mount zfs-root -t zfs /mnt&lt;br /&gt;
umount /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If it is already mounted and you want to change it to mount somewhere else, it is best to transition it to unmounted first, then mount it in the new place.&lt;br /&gt;
&lt;br /&gt;
The mount options &amp;lt;code&amp;gt;-o ro, -o rw, -o remount,ro, and -o remount,rw &amp;lt;/code&amp;gt; can also be used and will override &amp;lt;code&amp;gt;readonly=on|off&amp;lt;/code&amp;gt; property without altering the property value. This can be confusing until you are familiar with how to the methods of mounting interact.&lt;br /&gt;
&lt;br /&gt;
Now, let's continue some, and mount to /mnt using the current &amp;lt;code&amp;gt;readonly=off&amp;lt;/code&amp;gt; setting (rw mount):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=/mnt zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This method of mounting will show the most detailed mount options in /etc/mtab. They are the mount options that zfs thinks are proper, and they are probably what should be kept in /etc/fstab for zfs-root until we know better.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cat /etc/mtab &amp;gt;&amp;gt; /etc/fstab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now edit /etc/fstab to make sure it looks right, and remove the &amp;quot;rw&amp;quot; mount option, because we want to let it use a default for that, which will come from how we set the readonly= property most of the time. Unmount again:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set mountpoint=none zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mount again, now using all options from /etc/fstab:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It should be mounted at /mnt, and touch /mnt/t should allow you to make the file t. Then rm it: rm /mnt/t&lt;br /&gt;
For installation, we want to make sure it is mounted read-write. After installation, it should mount readonly inside the initrd.&lt;br /&gt;
&lt;br /&gt;
Sometimes there can be problems using the mount command, and then you can try it with the -i option:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 mount -i zfs-root &lt;br /&gt;
 mount -i zfs-root -t zfs /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
but, you should not have to use -i. When using -i makes it work, it performs an &amp;quot;internal-only&amp;quot; mount and does not use any mount.&amp;lt;fstype&amp;gt; helper scripts that might be on the system.&lt;br /&gt;
&lt;br /&gt;
Setup the /boot device:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkfs.ext4 /dev/sda1&lt;br /&gt;
mkdir /mnt/boot&lt;br /&gt;
mount /dev/sda1 /mnt/boot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We have both root and boot mounted where the slackware installer expects them. Unmount the dvd so setup can find it normally:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
umount /dev/sr0&lt;br /&gt;
setup&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the setup, skip straight to TARGET selection for the root device, but the setup doesn't see or understand the zfs-root, so it is not listed. This does not matter because we have mounted it already. Just skip down to a slot that say to continue, and continue on with setup. Because TARGET is skipped, you may not see the ADDITIONAL prompt (or if so, skip it too) where normally you give /dev/sda1 and have it mounted as /boot. This is also okay because we have mounted /mnt/boot already.&lt;br /&gt;
Because we did not give TARGET the root device or say what device /boot is on, the lilo installation will fail, or you can skip it. Otherwise, this installation process it normal.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
umount /dev/sr0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point, it is assumed that the setup has completed installing into /mnt. Congrats! You've installed slackware into a ZFS root!&lt;br /&gt;
&lt;br /&gt;
The next steps are to prepare to use &amp;quot;chroot /mnt&amp;quot; and finish up the configuration on the installed root system and then be able to reboot onto the completed installation. Before doing chroot, copy some files from the setup environment into /mnt.&lt;br /&gt;
&lt;br /&gt;
Copy the current installer /etc/fstab for later use inside the initrd. This fstab is what is proper inside the initrd, except remove option &amp;quot;rw&amp;quot; (if not done already).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/fstab /mnt/etc/fstab.initrd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The fstab.initrd will look like:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 proc /proc proc defaults 0 0&lt;br /&gt;
 zfs-root /mnt zfs defaults,atime,dev,exec,suid,xattr,nomand,zfsutil 0 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the initrd, we want zfs-root to mount to /mnt.&lt;br /&gt;
&lt;br /&gt;
Create /mnt/etc/fstab:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cat /etc/mtab &amp;gt;&amp;gt; /mnt/etc/fstab&lt;br /&gt;
vi /mnt/etc/fstab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using vi started above, edit /mnt/etc/fstab and make it have lines such as:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 zfs-root / zfs defaults,atime,dev,exec,suid,xattr,nomand,zfsutil 0 0&lt;br /&gt;
 /dev/sda1 /boot ext4 defaults 0 2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These two lines in &amp;lt;code&amp;gt;/mnt/etc/fstab&amp;lt;/code&amp;gt; are how the mounts should be looking when root is booted.&lt;br /&gt;
&lt;br /&gt;
Mount some special mounts before chroot:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount -t devtmpfs none /mnt/dev&lt;br /&gt;
mount -t proc none /mnt/proc&lt;br /&gt;
mount -t sysfs none /mnt/sys&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Make sure /boot is mounted:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount /dev/sda1 /mnt/boot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you had mounted a 9p fs share to access spl and zfs packages, then unmount that now:&lt;br /&gt;
umount /packages&lt;br /&gt;
&lt;br /&gt;
Ready, now:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chroot /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point, you should be on the installed system, and now try to configure mkinitrd and lilo. First, switch to use the generic kernel.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /boot&lt;br /&gt;
rm System.map config vmlinuz&lt;br /&gt;
ln -s System.map-gen* System.map&lt;br /&gt;
ln -s config-gen* config&lt;br /&gt;
ln -s vmlinuz-gen* vmlinuz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We install spl and zfs inside the live ramfs install-dvd environment, but not yet have we installed them into the root system:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount /dev/sr0 /mnt/cdrom&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /mnt/cdrom/addon/spl-*.txz&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /mnt/cdrom/addon/zfs-*.txz&lt;br /&gt;
depmod&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If instead, you used a 9p share to access the spl and zfs packages, then repeat that procedure here to install them onto the root system.&lt;br /&gt;
&lt;br /&gt;
Setup lilo: edit /etc/lilo.conf so it is like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  lba32&lt;br /&gt;
  append = &amp;quot; vt.default_utf8=1&amp;quot;&lt;br /&gt;
  boot = /dev/sda&lt;br /&gt;
  message = /boot/boot_message.txt&lt;br /&gt;
  prompt&lt;br /&gt;
  timeout = 1200&lt;br /&gt;
  change-rules&lt;br /&gt;
   reset&lt;br /&gt;
  vga = normal&lt;br /&gt;
  image = /boot/vmlinuz&lt;br /&gt;
   initrd = /boot/initrd.gz&lt;br /&gt;
   root = /dev/sda1&lt;br /&gt;
   label = vmlinuz&lt;br /&gt;
   read-only&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The line, root = /dev/sda1, is not really a true statement but lilo needs a device there that it at least understands. This root = line is a kernel parameter, but since the initrd is what is actually the root, initially, then the root = line is probably useless here. It might even be okay to just delete the root line.&lt;br /&gt;
&lt;br /&gt;
Setup mkinitrd:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/mkinitrd.conf.sample /etc/mkinitrd.conf&lt;br /&gt;
vi /etc/mkinitrd.conf&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Edit it to look like this (other defaults should be ok):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 MODULE_LIST=&amp;quot;sym53c8xx:ext4:8139cp:zfs:9p:9pnet_virtio&amp;quot;&lt;br /&gt;
 ROOTDEV=&amp;quot;zfs-root&amp;quot;&lt;br /&gt;
 ROOTFS=&amp;quot;zfs&amp;quot;&lt;br /&gt;
#Module sym53c8xx is the driver for qemu's if=scsi drive device.&lt;br /&gt;
#Module ext4 for /boot.&lt;br /&gt;
#Module 8139cp for eth0 net device.&lt;br /&gt;
#Module zfs for ZFSonLinux.&lt;br /&gt;
#Modules 9p and 9pnet_virtio for mounting qemu -virtfs mount_tag.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These 9p could be useful from the rescue command line inside the initrd to get needed files that are on the host.&lt;br /&gt;
&lt;br /&gt;
All dependent modules will also be included automatically into /boot/initrd-tree, which is packaged as /boot/initrd.gz. For example, to see the dependent modules of zfs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
modprobe --show-depends zfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All listed modules will also be in the initrd. Now, make a /boot/initrd-tree that we can begin to look at and edit.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkinitrd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create an empty /etc/mtab or else zpool import fails (zfs expects /etc/mtab to exists already, it won't make it).&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
touch /boot/initrd-tree/etc/mtab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Copy in the fstab.initrd that was made earlier while on the installer. This provides all the mount options for a simple &amp;quot;mount zfs-root&amp;quot; onto /mnt.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/fstab.initrd /boot/initrd-tree/etc/fstab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More package installing! This time into an alternate root, the root of the initrd, /boot/initrd-tree. This is how you can put whatever packages you like into your initrd. These installations work independent of your normal installations. You can install, upgrade, and remove packages using an altroot:&lt;br /&gt;
&lt;br /&gt;
If spl and zfs are on your customized dvd:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/addon/spl-*.txz&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/addon/zfs-*.txz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Otherwise, repeat same procedure but you mount your 9p mount_tag and get them installed.&lt;br /&gt;
&lt;br /&gt;
More regular packages from the dvd:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/kmod-*.txz&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/coreutils-*.txz&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/gptfdisk-*.txz&lt;br /&gt;
&lt;br /&gt;
# A bash script is in /boot/initrd-tree/lib/udev/, so we need it or udev rules have problems:&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/bash-*.txz&lt;br /&gt;
# Bash needs this:&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/l/libtermcap-*.txz&lt;br /&gt;
&lt;br /&gt;
# Install net-tools to ensure that /etc/HOSTNAME, /etc/hosts, and potentially, /etc/hostid are handled proper.&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/n/net-tools-*.txz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When ZFS has to import a zpool while the initrd is running (this can be avoided by not exporting and keeping /etc/zfs/zpool.cache inside the initrd), ZFS will refuse to import a pool if it thinks that the pool may be in use by another system. ZFS was designed for network attached storage where multiple hosts might have access to the same disks but ZFS cannot support two hosts importing and using a ZFS pool at the same time. ZFS checks a value called &amp;quot;hostid&amp;quot; to determine this kind of conflict, and it can be a tricky issue with an initrd boot process. The value of hostid is returned by a system call, the gethostid() function or the hostid command. This function will return the hostid from /etc/hostid if that file exists and has a valid id in it, or else if the file doesn't exist it obtains a hostid number based on the hostname and ip address address assigned to hostname found in /etc/hosts or in DNS. If the hostid trying to import a pool is not the same as the hostid that imported it last time, ZFS will not import the pool unless &amp;quot;zpool import -f zfs-root&amp;quot; is used to force the import. This force option is not recommended to use, so it is best to configure your initrd with matching /etc/HOSTNAME and /etc/hosts as on the root installation and ensure what your system looks like on the initrd matches the booted root system.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Edit /boot/initrd-tree/init (this is the main system startup script on the initrd, responsibe for configuring your block devices and mount your root at /mnt and then booting root):&lt;br /&gt;
&lt;br /&gt;
Inside init, right near the top of the file after the PATH= line, add this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/bin/hostname -F /etc/HOSTNAME&lt;br /&gt;
/bin/hostname $( /bin/hostname -s )&lt;br /&gt;
#/sbin/chhostid 13371400&lt;br /&gt;
# you can make your hostid whatever, but this didn't work right with ZFS, so it is commented out&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This sets the name reported by the hostname command (the default is &amp;quot;darkstar&amp;quot;) to be what is contained in /etc/HOSTNAME. The hostname is modified in the next line to be the short name. These lines will help ZFS to properly identify your host when importing pools.&lt;br /&gt;
&lt;br /&gt;
Inside init, right after it runs &amp;quot;mdadm&amp;quot; commands as used for raid setup, we like it to setup ZFS, so add:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/sbin/zpool import zfs-root&lt;br /&gt;
/sbin/zfs set readonly=on zfs-root&lt;br /&gt;
mount zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Inside init, close to the bottom, where it &amp;quot;Switch to real root partition&amp;quot;, comment out 1 line that normally does the mount:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# mount -o ro -t $ROOTFS $ROOTDEV /mnt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
We have already mounted, and we don't want to use any mount options because we should be using a properly set /etc/fstab inside the initrd for zfs-root mount options onto /mnt.&lt;br /&gt;
&lt;br /&gt;
During a normal startup we want a readonly mount.&lt;br /&gt;
&lt;br /&gt;
Note: we are going to setup with using zpool import and export and startup and shutdown. But later, you can experiment having /etc/zfs/zpool.cache stored in the initrd and commenting out zpool import/export lines.&lt;br /&gt;
&lt;br /&gt;
As mentioned, the import command may sometimes fail, and give the message: &amp;quot;pool may be in use from another system&amp;quot;. This is nothing serious in this test situation. When this happens, root will not be mounted to /mnt and the init script will detect this and drop you into a rescue command line where you may manually &amp;quot;import -f&amp;quot; then &amp;quot;mount zfs-root&amp;quot; and then &amp;quot;exit&amp;quot; to continue on to booting the root.&lt;br /&gt;
&lt;br /&gt;
To avoid this problem we copy some files in (assuming you first edit /etc/HOSTNAME to hold the hostname you like to see on your command prompts, and edited /etc/hosts to have hostname on your loopback or other local ip address):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/HOSTNAME /etc/hosts /boot/initrd-tree/etc&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The value reported by the hostid command is what ZFS sees as your hostid. In this setup so far, the value is based on the ip found assigned to your hostname. If your hostname is on the line in /etc/hosts for ip address 192.168.13.37, then your hostid will be hex numbers C0.A8.0D.25 rearranged as A8C0250D (pairs of bytes are swapped). That is ip-based hostid value, a 32bit hexadecimal number. This has to be the same each boot or import will need a -f option to force it. Simply setting the hostid using the system call sethostid() which writes a /etc/hostid file doesn't seem to agree with ZFS and you'd have to force the import, so this setup now assumes that you do not have or have deleted /etc/hostid.&lt;br /&gt;
&lt;br /&gt;
You can sometimes see what has been happening to a zpool by using the command &amp;quot;zpool history -li zfs-root&amp;quot; to see a log of commands.&lt;br /&gt;
&lt;br /&gt;
Once again, you can do away with the import and export commands by trying to have /etc/zfs/zpool.cache inside your initrd. To create zpool.cache, while on the installer or in the rescue shell of the initrd (at lilo &amp;quot;boot: vmlinuz rescue&amp;quot;), import only the pool for the root fs with mountpoint=none and readonly=on properties set and while it is not mounted:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(on installer or initrd rescue shell)&lt;br /&gt;
cp /etc/zfs/zpool.cache /etc/zfs/zpool.cache-initrd&lt;br /&gt;
zfs set readonly=off zfs-root&lt;br /&gt;
mount zfs-pool&lt;br /&gt;
cp /etc/zfs/zpool.cache-initrd /mnt/etc/zfs/&lt;br /&gt;
cp /mnt/etc/zfs/zpool.cache-initrd /mnt/boot/initrd-tree/etc/zfs/zpool.cache&lt;br /&gt;
umount /mnt&lt;br /&gt;
zfs set readonly=on zfs-root&lt;br /&gt;
#mount zfs-root&lt;br /&gt;
#exit (to continue boot process onto rootfs mounted at /mnt)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, doing this zpool.cache approach is not necessary, and some talk suggests this is deprecated or discouraged. Although /etc/hostid setup fails to import without -f option, ip-based (hosts|dns) hostid works on booting and import works without -f option and may be the more proper way to do shutdown and startup rather than using a cache file which could be come invalid and cause a problem that is difficult to understand. The contents and exact function of the cache file are not well understood by many people.&lt;br /&gt;
&lt;br /&gt;
Save /boot/initrd-tree/init and exit.&lt;br /&gt;
&lt;br /&gt;
Now, edit /etc/rc.d/rc.S and rc.6 to understand how to &amp;quot;remount&amp;quot; rw or ro as a readonly property changes&lt;br /&gt;
&lt;br /&gt;
In /etc/rc.d/rc.S:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# comment out the line&lt;br /&gt;
#    /sbin/mount -w -v -n -o remount /&lt;br /&gt;
#add the line&lt;br /&gt;
     /sbin/zfs set readonly=off zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In /etc/rc.d/rc.6&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# comment out the line&lt;br /&gt;
#    /bin/mount -v -n -o remount,ro /&lt;br /&gt;
#add the line&lt;br /&gt;
     /sbin/zfs set readonly=on zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In /etc/rc.d/rc.6, near the bottom just before poweroff|reboot, add the following block of lines:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
########################&lt;br /&gt;
# Try to export zfs-root&lt;br /&gt;
/sbin/zpool export zfs-root&lt;br /&gt;
if [ $? -gt 0 ] ; then&lt;br /&gt;
 echo &amp;quot;ZFS export failed.&amp;quot;&lt;br /&gt;
 echo &amp;quot;Notice: if root fs is busy, then this is normal fail.&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;ZFS export successful.&amp;quot;&lt;br /&gt;
 echo &amp;quot;Warning: successful export is abnormal for root fs.&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
/bin/sleep 5&lt;br /&gt;
########################&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
For ZFS, you cannot run fsck on it. It doesn't support that kind of filesystem checks. The rc.S script will complain a lot in many places about not being about to run fsck on the zfs-root. To disable all attempts of run fsck, we can simple create a file that acts as a flag in /etc/rc.d/rc.S to tell it to skip fsck:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
touch /etc/fastboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This fastboot file is normally a run-once temporary file, and it is deleted near the bottom inside rc.S. Edit rc.S and stop it from deleting /etc/fastboot. We would like it to always skip all fsck. Edit /etc/rc.d/rc.S, and find the &amp;quot;rm&amp;quot; of fastboot, and do not have it removed!&lt;br /&gt;
&lt;br /&gt;
We are getting close, and have finished all editing, so make /boot/initrd.gz and install lilo:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkinitrd -F&lt;br /&gt;
lilo&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We finished! All that's left to do is clean up.&lt;br /&gt;
&lt;br /&gt;
Exit the chroot.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
exit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Try to mount everything:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
umount /mnt/proc&lt;br /&gt;
umount /mnt/sys&lt;br /&gt;
umount /mnt/dev&lt;br /&gt;
umount /mnt/boot&lt;br /&gt;
umount /mnt/mnt/cdrom&lt;br /&gt;
umount /mnt/root/packages&lt;br /&gt;
umount /mnt&lt;br /&gt;
zpool export zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note, that export stops a pool and frees devices, while import binds devices and starts a pool. It is somewhat like mdadm -A -s and mdadm -S -s, while /etc/zfs/zpool.cache might be somewhat like mdadm -E -s &amp;gt; /etc/mdadm.conf.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Remove the DVD or change boot order&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When you reboot, if all is good, you are booting properly onto a slackware installed on a ZFS root! Congrat!&lt;br /&gt;
&lt;br /&gt;
If this seem to go badly, and this might happen if the import fails as explain some before, then you will be on the initrd's rescue command line just before the part in it's init where it wants to mount and switch_root to boot your root. Instead, you typically got commands like this to do:&lt;br /&gt;
&lt;br /&gt;
If you get dumped to rescue because import will not work and requires -f (force), then:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 zpool import -f zfs-root&lt;br /&gt;
 zpool export    zfs-root&lt;br /&gt;
 zpool import    zfs-root&lt;br /&gt;
 mount zfs-root&lt;br /&gt;
 exit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This can happen if hostname, hostid, or uname changes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you get into a jam and need to boot into the initrd and skip zfs import etc, use the lilo prompt (or, boot the install-dvd):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
boot: vmlinuz rescue&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the rescue mode of the initrd, after you have mounted your root as readonly=on to /mnt, then exit to continue.&lt;br /&gt;
&lt;br /&gt;
In other emergency modes, you might need to run the lines at end of init starting from: &amp;lt;code&amp;gt;udevadm info --cleanup-db; udevadm control --exit&amp;lt;/code&amp;gt;&lt;br /&gt;
If you don't run those udevadm commands, two runs of udevd fight each other and it is slow; you have to wait 2 minutes twice for timeouts (4 minutes).&lt;br /&gt;
The last line is run is: &amp;lt;code&amp;gt;exec switch_root /mnt /sbin/init 1&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Warning... this switch_root command is kind of dangerous, so read the manual page about it.&lt;br /&gt;
From what I can tell, everything except the new root &amp;quot;/mnt&amp;quot; is deleted, so you are giving a command that says what NOT to delete!&lt;br /&gt;
Make sure nothing got mounted outside of &amp;quot;/mnt&amp;quot; before you run it.&lt;br /&gt;
&lt;br /&gt;
Also, in rescue or anytime you have finished making changes and are about to reboot in some abnormal mode, first run:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs set readonly=on zfs-root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A bug in unpatched grep 2.13 build 1, found slackware 14.0rc1, causes problems when processing files stored on ZFS but rarely shows problems on other filesystems; the bug does not handle sparse files on zfs and btrfs correctly and results in chaos with slackpkg, compiling kernel modules, and possibly many other things. You must downgrade grep to 2.12 or use the patched grep 2.13 build 2 in slackware 14.0rc2 or later.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Upgrading.&lt;br /&gt;
&lt;br /&gt;
From time to time you will want to upgrade the kernel to the new kernel in slackware64-current or in patches/. This will also necessitate a rebuilt and reinstall or upgrade of spl and zfs. Below is an example of when both kernel and spl/zfs are being upgraded, to give an idea of the process:&lt;br /&gt;
&lt;br /&gt;
Using slackpkg, that is configured to use your local slackware mirror is a good option but you can also configure it to use a remote mirror.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slackpkg upgrade-all&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Assume slackpkg just upgraded your kernel, kernel-modules, and kernel-headers.&lt;br /&gt;
&lt;br /&gt;
Note: the first time you try to run on kernel-generic, setup kernel-huge in lilo as 2nd choice. Huge has all the hard drive controllers builtin, but generic has them all as modules. For example, run &amp;quot;modinfo mptsas&amp;quot; to see module options (maybe you have a LSISAS1068) for your hard drive controller. Add file /etc/modprobe.d/mptsas.conf to set options you want with a line: options mptsas ... Do this for all the device driver modules for your hardware. Do this setup while you are on the huge kernel, then setup to reboot to generic. Include all these modules you need into mkinitrd.conf MODULES_LIST. Check that /boot/initrd-tree/etc/modprobe.d/ has a copy of your customized module conf files because it is on the initrd where the modules will load and use the conf files. mkinitrd probably copies all /etc/modprobe.d/* files into the initrd-tree, but check it. Pay attention to /etc/modprobe.d/README and /lib/modprobe.d/* /lib/modprobe.d/* maybe not copied to initrd-tree but you might want to copy some of it into your initrd-tree yourself to use them.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Check that upgraded kernel-source is symlinked to /usr/src/linux (zfs build looks here). SQL/ZFS modules will install to the kernel version in /lib/modules/&amp;lt;/usr/src/linux kernel version&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /usr/local/src&lt;br /&gt;
tar xvzf ~/spl-*.tar.gz&lt;br /&gt;
tar xvzf ~/zfs-*.tar.gz&lt;br /&gt;
&lt;br /&gt;
###### upgrade spl 1st&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-*&lt;br /&gt;
./configure --prefix=/ --libexecdir=/usr/libexec --libdir=/lib64 --includedir=/usr/include --datarootdir=/usr/share&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=/usr/local/src/install&lt;br /&gt;
cd ../install&lt;br /&gt;
makepkg ../spl-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
upgradepkg spl-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
depmod &amp;lt;new kernel version&amp;gt;     (e.g. depmod 3.2.27, if .27 is new kernel upgrade; you currently run on old, maybe .26)&lt;br /&gt;
# this builds the module dependencies in /lib/modules/&amp;lt;new kernel version&amp;gt;&lt;br /&gt;
###### upgrade zfs 2nd&lt;br /&gt;
mkdir install&lt;br /&gt;
cd zfs-*&lt;br /&gt;
./configure --prefix=/ --libexecdir=/usr/libexec --libdir=/lib64 --includedir=/usr/include --datarootdir=/usr/share&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=/usr/local/src/install&lt;br /&gt;
cd ../install&lt;br /&gt;
makepkg ../zfs-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
upgradepkg zfs-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
depmod 3.2.27&lt;br /&gt;
####### upgrade spl/zfs inside altroot /boot/initrd-tree&lt;br /&gt;
ROOT=/boot/initrd-tree upgradepkg spl-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
ROOT=/boot/initrd-tree upgradepkg zfs-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
# note: ROOT is an environment variable, not a command line option to upgradepkg!&lt;br /&gt;
# note: do not worry about depmod inside initrd-tree, mkinitrd -F actually installs the modules&lt;br /&gt;
# note: this upgrade here is really to just upgrade the command line tools zpool, zfs etc&lt;br /&gt;
####### rebuild /boot/initrd.gz and reinstall lilo&lt;br /&gt;
vi /etc/mkinitrd.conf&lt;br /&gt;
# temporarily set KERNEL_VERSION to new version, but you are still running on old version&lt;br /&gt;
mkinitrd -F&lt;br /&gt;
lilo&lt;br /&gt;
vi /etc/mkinitrd.conf&lt;br /&gt;
# you can set KERNEL_VERSION back to $(uname r) now&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After reboot you can remove any old /lib/modules/&amp;lt;old kernel version&amp;gt; directory.&lt;br /&gt;
&lt;br /&gt;
More about /etc/hostid. If you want to experiment changing your /etc/hostid file and seeing if you can use it and make zpool import work normally, here is a tool that might be helpful:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
################################################&lt;br /&gt;
/* software product name: foobarz-chhostid.c&lt;br /&gt;
 * suggested binary name: chhostid&lt;br /&gt;
 * license              : BSD&lt;br /&gt;
 * license text:&lt;br /&gt;
Copyright (c) 2012, foobarz&lt;br /&gt;
All rights reserved.&lt;br /&gt;
&lt;br /&gt;
Redistribution and use in source and binary forms, with or without&lt;br /&gt;
modification, are permitted provided that the following conditions are met:&lt;br /&gt;
    * Redistributions of source code must retain the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer.&lt;br /&gt;
    * Redistributions in binary form must reproduce the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer in the&lt;br /&gt;
      documentation and/or other materials provided with the distribution.&lt;br /&gt;
    * Neither the name of the &amp;lt;organization&amp;gt; nor the&lt;br /&gt;
      names of its contributors may be used to endorse or promote products&lt;br /&gt;
      derived from this software without specific prior written permission.&lt;br /&gt;
&lt;br /&gt;
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &amp;quot;AS IS&amp;quot; AND&lt;br /&gt;
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED&lt;br /&gt;
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE&lt;br /&gt;
DISCLAIMED. IN NO EVENT SHALL &amp;lt;COPYRIGHT HOLDER&amp;gt; BE LIABLE FOR ANY&lt;br /&gt;
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES&lt;br /&gt;
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;&lt;br /&gt;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND&lt;br /&gt;
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT&lt;br /&gt;
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS&lt;br /&gt;
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#define FOOBARZ_CHHOSTID_VERSION &amp;quot;1.0.5&amp;quot;&lt;br /&gt;
#include &amp;lt;sys/socket.h&amp;gt;&lt;br /&gt;
#include &amp;lt;netinet/in.h&amp;gt;&lt;br /&gt;
#include &amp;lt;arpa/inet.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;endian.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sysexits.h&amp;gt;&lt;br /&gt;
/* note: if include stdlib then sethostid fails even with _BSD_SOURCE defined */&lt;br /&gt;
&lt;br /&gt;
long swapbytes(long abcd) {&lt;br /&gt;
  long badc;&lt;br /&gt;
  unsigned char addr_a;&lt;br /&gt;
  unsigned char addr_b;&lt;br /&gt;
  unsigned char addr_c;&lt;br /&gt;
  unsigned char addr_d;&lt;br /&gt;
  addr_a = (unsigned char) (abcd &amp;gt;&amp;gt; 24);&lt;br /&gt;
  addr_b = (unsigned char) (abcd &amp;gt;&amp;gt; 16);&lt;br /&gt;
  addr_c = (unsigned char) (abcd &amp;gt;&amp;gt;  8);&lt;br /&gt;
  addr_d = (unsigned char) (abcd);&lt;br /&gt;
  return badc = ( (addr_b &amp;lt;&amp;lt; 24) | (addr_a &amp;lt;&amp;lt; 16) | (addr_d &amp;lt;&amp;lt; 8) | addr_c );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[])&lt;br /&gt;
{&lt;br /&gt;
 long newhostid;&lt;br /&gt;
 struct in_addr addr;&lt;br /&gt;
 char* invalidchar;&lt;br /&gt;
&lt;br /&gt;
 /*********** check command line */&lt;br /&gt;
 if(!( ((argc==3) &amp;amp;&amp;amp; ( (strcmp(argv[1],&amp;quot;-h&amp;quot;)==0) ||&lt;br /&gt;
                       (strcmp(argv[1],&amp;quot;-i&amp;quot;)==0) ||&lt;br /&gt;
                       (strcmp(argv[1],&amp;quot;-l&amp;quot;)==0) )) ||&lt;br /&gt;
       ((argc==2) &amp;amp;&amp;amp; ( (strcmp(argv[1],&amp;quot;-s&amp;quot;)==0) ))&lt;br /&gt;
     )&lt;br /&gt;
   ) {&lt;br /&gt;
                 /*01234567890123456789012345678901234567890123456789012345678901234567890123456789*/&lt;br /&gt;
  fprintf(stderr, &amp;quot;foobarz-chhostid, version %s. License: BSD.\n&amp;quot;, FOOBARZ_CHHOSTID_VERSION);&lt;br /&gt;
  fprintf(stderr, &amp;quot;foobarz-chhostid, (c) 2012, foobarz; all rights reserved.\n&amp;quot;);&lt;br /&gt;
  fprintf(stderr, &amp;quot;descr: %s change system hostid (in /etc/hostid).\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -h &amp;lt;new hostid&amp;gt;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        Change system hostid to &amp;lt;new hostid&amp;gt;;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        &amp;lt;new hostid&amp;gt; must be 32bit 8-digit hex number xxxxxxxx, each x in 0-f|F.\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        The ip corresponding to &amp;lt;new hostid&amp;gt; is also listed for reference only.\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -i &amp;lt;dotted ip address&amp;gt;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        Change system hostid to hostid corresponding to &amp;lt;dotted ip address&amp;gt;.\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -l &amp;lt;dotted ip address&amp;gt;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        List hostid corresponding to &amp;lt;dotted ip address&amp;gt;;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        no change to system hostid.\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -s\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        List current system hostid and corresponding ip address;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        no change to system hostid.\n&amp;quot;, argv[0]);&lt;br /&gt;
  return EX_USAGE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -h &amp;lt;hostid&amp;gt; */&lt;br /&gt;
 if( strcmp(argv[1],&amp;quot;-h&amp;quot;) == 0 ) {&lt;br /&gt;
  if(strlen(argv[2]) != 8) { fprintf(stderr, &amp;quot;new hostid must be 8-digit hex number xxxxxxxx, each x in 0-f|F\n&amp;quot;); return EX_USAGE; }&lt;br /&gt;
&lt;br /&gt;
  newhostid = strtol(argv[2],&amp;amp;invalidchar,16);&lt;br /&gt;
  if( newhostid==LONG_MIN ) { perror(&amp;quot;strtol (underflow)&amp;quot;); return EX_USAGE; }&lt;br /&gt;
  if( newhostid==LONG_MAX ) { perror(&amp;quot;strtol (overflow)&amp;quot;); return EX_USAGE; }&lt;br /&gt;
  if(*invalidchar != '\0') { fprintf(stderr, &amp;quot;invalid hex number %c; must be in 0-f|F\n&amp;quot;, *invalidchar); return EX_USAGE; }&lt;br /&gt;
&lt;br /&gt;
  if( sethostid(newhostid) != 0 ) {&lt;br /&gt;
   perror(&amp;quot;sethostid&amp;quot;);&lt;br /&gt;
   if( errno == EPERM ) return EX_NOPERM;&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
  }&lt;br /&gt;
  printf(&amp;quot;System hostid changed.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  /* hostid is a byte-swapped ip like b.a.d.c */&lt;br /&gt;
  /* get ip by swapping to correct order a.b.c.d and save into in_addr struct */&lt;br /&gt;
  addr.s_addr = htonl(swapbytes(newhostid));&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -i or -l, then find hostid for &amp;lt;dotted ip address&amp;gt; */&lt;br /&gt;
 if( (strcmp(argv[1],&amp;quot;-i&amp;quot;) == 0) || (strcmp(argv[1],&amp;quot;-l&amp;quot;) == 0) ) {&lt;br /&gt;
  if( inet_aton(argv[2], &amp;amp;addr) == 0 ) { fprintf(stderr, &amp;quot;inet_aton: invalid dotted ip address: %s\n&amp;quot;, argv[2]); return EX_USAGE; }&lt;br /&gt;
&lt;br /&gt;
  /* hostid is a byte-swapped ip like b.a.d.c */&lt;br /&gt;
  /* get hostid by swapping bytes of ip a.b.c.d */&lt;br /&gt;
  newhostid = swapbytes(ntohl(addr.s_addr));&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -i &amp;lt;dotted ip address&amp;gt; */&lt;br /&gt;
 if( strcmp(argv[1],&amp;quot;-i&amp;quot;) == 0 ) {&lt;br /&gt;
  if( sethostid(newhostid) != 0 ) {&lt;br /&gt;
   perror(&amp;quot;sethostid&amp;quot;);&lt;br /&gt;
   if( errno == EPERM ) return EX_NOPERM;&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
  }&lt;br /&gt;
  printf(&amp;quot;System hostid changed.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -l &amp;lt;dotted ip address&amp;gt; */&lt;br /&gt;
 if(strcmp(argv[1],&amp;quot;-l&amp;quot;) == 0 ) {&lt;br /&gt;
   printf(&amp;quot;Listing hostid for ip. (no changes)\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -s */&lt;br /&gt;
 if(strcmp(argv[1],&amp;quot;-s&amp;quot;) == 0 ) {&lt;br /&gt;
   /* see if /etc/hostid exists and print info */&lt;br /&gt;
   if( access(&amp;quot;/etc/hostid&amp;quot;, F_OK) != 0 ) {&lt;br /&gt;
     printf(&amp;quot;Notice: /etc/hostid does not exist.\n&amp;quot;);&lt;br /&gt;
     perror(&amp;quot;Reason&amp;quot;);&lt;br /&gt;
     printf(&amp;quot;System hostid derived from ip of hostname found in hosts file or dns.\n&amp;quot;);&lt;br /&gt;
   } else {&lt;br /&gt;
     printf(&amp;quot;Notice: /etc/hostid exists.\n&amp;quot;&lt;br /&gt;
            &amp;quot;System hostid is obtained from hostid file.\n&amp;quot;);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
  errno=0;&lt;br /&gt;
  newhostid = gethostid();&lt;br /&gt;
  if(errno!=0) { perror(&amp;quot;gethostid&amp;quot;); return EX_UNAVAILABLE; }&lt;br /&gt;
&lt;br /&gt;
  /* hostid is a byte-swapped ip like b.a.d.c */&lt;br /&gt;
  /* get ip by swapping to correct order a.b.c.d and save into in_addr struct */&lt;br /&gt;
  addr.s_addr = htonl(swapbytes(newhostid));&lt;br /&gt;
&lt;br /&gt;
  printf(&amp;quot;Listing current system hostid. (no changes)\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** print info and return */&lt;br /&gt;
 printf(&amp;quot;ip dot: %s\n&amp;quot;, inet_ntoa(addr) );&lt;br /&gt;
 printf(&amp;quot;ip hex: %.8x\n&amp;quot;, ntohl(addr.s_addr) );&lt;br /&gt;
 printf(&amp;quot;hostid: %.8x\n&amp;quot;, newhostid );&lt;br /&gt;
 return EX_OK;&lt;br /&gt;
}&lt;br /&gt;
################################################&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</description>
			<pubDate>Sat, 18 Aug 2012 18:36:51 GMT</pubDate>
			<dc:creator>Foobarz</dc:creator>
			<comments>https://www.slackwiki.com/Talk:ZFS_root</comments>
		</item>
		<item>
			<title>ZFS root</title>
			<link>https://www.slackwiki.com/index.php?title=ZFS_root&amp;diff=731</link>
			<guid isPermaLink="false">https://www.slackwiki.com/index.php?title=ZFS_root&amp;diff=731</guid>
			<description>&lt;p&gt;Foobarz: installing slackware into a ZFS root&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;If you have heard about the ZFS filesystem and you're curious to try it out, then you can try it on slackware64, thanks to the ZFSonLinux.org project!&lt;br /&gt;
&lt;br /&gt;
In this article, an example is shown of how to install slackware64 14.0 onto a ZFS root filesystem (zfs-root) inside a QEMU virtual machine for testing purposes. It is recommended that you install qemu and learn how to use it to test a ZFS installation before you decide to use it on real hardware. A slackbuild for qemu can be found on slackbuilds.org. If you have a processor that supports Intel VT-x or AMD AMD-V virtualization acceleration (try modprobe kvm-intel or modprobe kvm-amd), then use the slackbuild for qemu-kvm.&lt;br /&gt;
&lt;br /&gt;
This article isn't going to go into any detail on actually using ZFS or what kinds of installation options and settings might be optimal. This article just presents an example of how to get started with ZFS on slackware.&lt;br /&gt;
&lt;br /&gt;
At this time of writing, ZFSonLinux is at &amp;quot;release candidate&amp;quot; (version 0.6.0-rc10) development stage, and many issues can occur. See the ZFSonLinux.org web site and the issues tracker for an idea about the current issues. There is also an irc channel on irc.freenode.net, #zfsonlinux, for discussion of issues and help.&lt;br /&gt;
&lt;br /&gt;
Although not required, it is helpful to keep a local mirror of slackware64 on your system. Having a local mirror makes it easier to upgrade to slackware64-current or to patches/* in a release. To help manage your own local slackware mirror and generate your own CD and DVD slackware installers, see http://alien.slackbook.org/blog/local-slackware-mirror/.&lt;br /&gt;
&lt;br /&gt;
In this article, we use a slackware64-current DVD image file as the qemu cdrom device media for the installation of the slackware guest. This was tested at slackware64-current = slackware64 14.0rc2. You can obtain a slackware DVD image using a torrent, buy the DVD from slackware.com, or generate your own DVD image file using the mirror script. For an actual DVD, you can pass your DVD device (e.g., /dev/sr0) as the qemu cdrom device. For a DVD image file, pass the image file as the qemu cdrom device.&lt;br /&gt;
&lt;br /&gt;
The ZFSonLinux packages are not included in slackware at this time. There are two packages involved: spl and zfs. The first, spl, is &amp;quot;Solaris Porting Layer&amp;quot; and must be installed on the system before zfs can be compiled. The source code tarballs for these are at ZFSonLinux.org. At this time of writing, they are spl-0.6.0-rc10.tar.gz and zfs-0.6.0-rc10.tar.gz.&lt;br /&gt;
&lt;br /&gt;
At this point, it is assumed you have qemu installed, have obtained a slackware64-current/14.0 DVD, and have downloaded spl and zfs tarballs to your host system. The first step now is, if your host is not slackware64-current/14.0 (the same as the guest will be), then you need to create a minimal development slackware64 guest system in qemu for just the purpose of compiling and packaging the spl and zfs slackware packages and transferring a copy of these packages back onto your host system to use later to install onto zfs during the slackware install process.&lt;br /&gt;
&lt;br /&gt;
From this point onward, instructions become a bit terse and mostly limited to examples of the commands you might use to complete tasks. You are encouraged to examine what each command does by reading the command's man pages. For example, the command &amp;quot;man qemu&amp;quot; can show you most of what you need to know about running qemu on the command line.&lt;br /&gt;
&lt;br /&gt;
So, here's an example of how you might build the spl and zfs packages, starting in your home directory:&lt;br /&gt;
&lt;br /&gt;
(on host)&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir qemu&lt;br /&gt;
cd qemu&lt;br /&gt;
mkdir slackdevel&lt;br /&gt;
cd slackdevel&lt;br /&gt;
mkdir packages&lt;br /&gt;
cp ~/spl-*.tar.gz packages&lt;br /&gt;
cp ~/zfs-*.tar.gz packages&lt;br /&gt;
qemu-img create disk1.raw 10G&lt;br /&gt;
ln -s ~/slackware64-current-install-dvd.iso dvd.iso&lt;br /&gt;
qemu-system-x86_64 \&lt;br /&gt;
 -no-quit \&lt;br /&gt;
 -no-shutdown \&lt;br /&gt;
 -boot order=cd,menu=on \&lt;br /&gt;
 -m 2G \&lt;br /&gt;
 -cpu host \&lt;br /&gt;
 -smp sockets=1,cores=4 \&lt;br /&gt;
 -net nic,model=rtl8139 -net user \&lt;br /&gt;
 -cdrom dvd.iso \&lt;br /&gt;
 -drive boot=on,format=raw,media=disk,cache=none,aio=native,if=scsi,bus=0,unit=0,file=disk1.raw \&lt;br /&gt;
 -virtfs local,path=./packages/,security_model=none,mount_tag=hostpackages&lt;br /&gt;
&lt;br /&gt;
When you need to change boot to cd or disk, add or remove &amp;quot;boot=on&amp;quot;, or change &amp;quot;order=dc&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Qemu should boot into the install-dvd, and now perform a very ordinary slackware64 install onto /dev/sda. Install d package set and most others, but package sets x, kde, xfce not really needed.&lt;br /&gt;
&lt;br /&gt;
First note: examples here use tools from the gptfdisk package (gdisk, sgdisk, cgdisk) to partition the disk with GUID partition table (GPT) format. GPT might not be too familiar to everyone, who mostly have only used MBR partitions with fdisk. In the slackware installations this author has tested in qemu, using GPT partitions has caused no problems with lilo or other tools used in slackware. GPT disk labels support creating up to 128 partitions and support disks larger than 2TB (the limit of MBR fdisk). LILO installs into the first 440 bytes on /dev/sda, inside a GPT &amp;quot;protective MBR&amp;quot; that serves to provide compatibility with MBR bootloaders like lilo. LILO uses LBA32 sector addressing and can see all 512-byte sectors side the first 2TB of a disk. So long as the /boot partition is within the first 2TB of a disk, lilo can work on a disk larger than 2TB. Unlike the common default of fdisk to start the first partition at sector 63, which is not aligned with the 4KiB sector size of Advanced Format hard disks, gdisk's default is to start partitions at 2048 sector (1MiB) boundaries which are also 4KiB aligned. Using gdisk GPT works on all disks and is compatible with using Advanced Format hard disks larger than 2TB. More information about GPT disk label format can be found on wikipedia.org. For those that have used grub instead of lilo, grub installation is different with GPT than with MBR, and grub requires a GPT partition of type grub-bios or 0xEF02 &amp;quot;BIOS Boot Partition&amp;quot; of about 8MiB where it can install it's additional bootloader stages because grub cannot embed in sectors 1-62 on GPT where GPT keeps it's partition tables. On MBR, sectors 1-62 were normally reserved space for bootloaders to keep a 2nd stage.&lt;br /&gt;
&lt;br /&gt;
For this purpose of development guest, just create a simple 1-partition system, /dev/sda1, and do a simple slackware install on it. Don't bother with swap or separate /boot unless you want to:&lt;br /&gt;
&lt;br /&gt;
(on install-dvd)&lt;br /&gt;
cgdisk /dev/sda&lt;br /&gt;
setup&lt;br /&gt;
reboot&lt;br /&gt;
&lt;br /&gt;
When this simple development guest boots, login as root, and continue:&lt;br /&gt;
&lt;br /&gt;
(on qemu guest)&lt;br /&gt;
cd ~&lt;br /&gt;
mkdir packages&lt;br /&gt;
mount hostpackages -t 9p -o trans=virtio packages&lt;br /&gt;
echo --prefix=/ --libexecdir=/usr/libexec --libdir=/lib64 --includedir=/usr/include --datarootdir=/usr/share &amp;gt; configure-options&lt;br /&gt;
mkdir src&lt;br /&gt;
cd src&lt;br /&gt;
&lt;br /&gt;
mkdir install&lt;br /&gt;
tar xvzf ~/packages/spl-*.tar.gz&lt;br /&gt;
cd spl-*&lt;br /&gt;
./configure $( cat ~/configure-options )&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../spl-&amp;lt;version&amp;gt;_&amp;lt;kernel_version&amp;gt;-x86_64-&amp;lt;build_id&amp;gt;.txz&lt;br /&gt;
(e.g., makepkg ../spl-0.6.0rc10_3.2.27-x86_64-1root.txz)&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
installpkg spl-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
cp spl-0.6.0rc10_3.2.27-x86_64-1root.txz ~/packages&lt;br /&gt;
&lt;br /&gt;
mkdir install&lt;br /&gt;
tar xvzf ~/packages/zfs-*.tar.gz&lt;br /&gt;
cd zfs-*&lt;br /&gt;
./configure $( cat ~/configure-options )&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=~/src/install&lt;br /&gt;
cd ~/src/install&lt;br /&gt;
makepkg ../zfs-&amp;lt;version&amp;gt;_&amp;lt;kernel_version&amp;gt;-x86_64-&amp;lt;build_id&amp;gt;.txz&lt;br /&gt;
(e.g., makepkg ../zfs-0.6.0rc10_3.2.27-x86_64-1root.txz)&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
installpkg zfs-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
cp zfs-0.6.0rc10_3.2.27-x86_64-1root.txz ~/packages&lt;br /&gt;
&lt;br /&gt;
At this point spl and zfs packages are copied back to the host in the packages directory. Also, spl and zfs are installed in this simple development guest, so one could begin to experiment with zfs pools and datasets but while the root fs is whatever you made it during setup (probably the default, ext4). This development guest isn't really needed anymore, so it can be deleted:&lt;br /&gt;
&lt;br /&gt;
halt&lt;br /&gt;
(exit qemu: ctrl-alt-2 then enter quit at QEMU command prompt)&lt;br /&gt;
&lt;br /&gt;
(on host)&lt;br /&gt;
rm disk1.raw dvd.iso&lt;br /&gt;
mv packages ..&lt;br /&gt;
cd ..&lt;br /&gt;
rmdir slackdevel&lt;br /&gt;
&lt;br /&gt;
Now that we have the spl and zfs packages on the host, it is possible to copy them into your local slackware64 mirror and then generate your own install DVD image that includes them. For example, change to the directory that contains the slackware README files, and create a &amp;quot;addon&amp;quot; directory and copy the spl and zfs slackware packages into there. Then, generate the DVD image using a command such as $( ./mirror-slackware-current.sh -i ) from where you have this script configured to maintain your local mirror. We can also just continue to access them inside the installer using qemu's virtfs option. When you are going to do a real installation onto real hardware, you need to generate and burn your own DVD that includes the packages.&lt;br /&gt;
&lt;br /&gt;
It is time to begin the installation of slackware64 on a ZFS root, assuming either you have regenerated dvd.iso with zfs packages in addon/* or we access the zfs packages while in the installer using qemu's virtfs to the host's packages directory. ZFS supports creating complex data storage configurations such as pools (similar to a volume group) backed by one or more of various kinds of virtual devices (similar to disks and raid arrays) and containing one or more datasets (similar to mounted filesystems, logical volume devices, or snapshots). But here, we keep it simple and will install on just a single disk device. On a real ZFS installation, users will typically want to use the ZFS raidz1 or raidz2 virtual device types for reliability against hard drive failures.&lt;br /&gt;
&lt;br /&gt;
(on host)&lt;br /&gt;
mkdir slackzfs&lt;br /&gt;
mv packages slackzfs/&lt;br /&gt;
cd slackzfs&lt;br /&gt;
qemu-img create disk1.raw 10G&lt;br /&gt;
ln -s ~/slackware64-current-install-dvd.iso dvd.iso&lt;br /&gt;
qemu-system-x86_64 \&lt;br /&gt;
 -no-quit \&lt;br /&gt;
 -no-shutdown \&lt;br /&gt;
 -boot order=cd,menu=on \&lt;br /&gt;
 -m 2G \&lt;br /&gt;
 -cpu host \&lt;br /&gt;
 -smp sockets=1,cores=4 \&lt;br /&gt;
 -net nic,model=rtl8139 -net user \&lt;br /&gt;
 -cdrom dvd.iso \&lt;br /&gt;
 -drive boot=on,format=raw,media=disk,cache=none,aio=native,if=scsi,bus=0,unit=0,file=disk1.raw \&lt;br /&gt;
 -virtfs local,path=./packages/,security_model=none,mount_tag=hostpackages&lt;br /&gt;
&lt;br /&gt;
The install-dvd should boot, and then begin installation steps on the installer command line:&lt;br /&gt;
&lt;br /&gt;
(on install-dvd)&lt;br /&gt;
# mount the install-dvd&lt;br /&gt;
mkdir /dvd&lt;br /&gt;
mount /dev/sr0 /dvd&lt;br /&gt;
&lt;br /&gt;
# install coreutils, which provides the &amp;quot;hostid&amp;quot; command needed to load the spl module&lt;br /&gt;
installpkg /dvd/slackware64/a/coreutils-8.17-x86_64-1.txz&lt;br /&gt;
&lt;br /&gt;
# install kmod package which includes &amp;quot;depmod&amp;quot; command and others&lt;br /&gt;
installpkg /dvd/slackware64/a/kmod-9-x86_64-2.txz&lt;br /&gt;
depmod&lt;br /&gt;
&lt;br /&gt;
# install the full kernel modules so you can load 9p filesystem and use it if you want&lt;br /&gt;
# .. you might keep the zfs modules packages off the dvd and use a plain slack dvd&lt;br /&gt;
installpkg /dvd/slackware64/a/kernel-modules-*.txz&lt;br /&gt;
depmod&lt;br /&gt;
&lt;br /&gt;
# install bash and libtermcap because udev rules in zfs use bash scripts&lt;br /&gt;
installpkg /dvd/slackware64/a/bash-*.txz&lt;br /&gt;
installpkg /dvd/slackware64/l/libtermcap-*.txz&lt;br /&gt;
&lt;br /&gt;
# install spl and zfs that you have copied into the mirror before running the DVD creation&lt;br /&gt;
installpkg /dvd/addon/spl-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /dvd/addon/zfs-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
&lt;br /&gt;
Or:&lt;br /&gt;
mkdir /packages&lt;br /&gt;
find /lib/modules/ | grep 9p&lt;br /&gt;
lsmod&lt;br /&gt;
# check that 9p modules load, mainly 9pnet_virtio&lt;br /&gt;
modprobe 9pnet_virtio&lt;br /&gt;
mount hostpackages -t 9p -o trans=virtio /packages&lt;br /&gt;
installpkg /packages/spl-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /packages/zfs-0.6.0rc10_3.2.27-x86_64-1root.txz&lt;br /&gt;
depmod&lt;br /&gt;
modprobe zfs&lt;br /&gt;
&lt;br /&gt;
Now zfs tools: &amp;quot;zpool&amp;quot; and &amp;quot;zfs&amp;quot; should work in the live installer.&lt;br /&gt;
On the installer, there can be trouble seeing man pages, so install:&lt;br /&gt;
&lt;br /&gt;
installpkg /dvd/slackware64/ap/man-*.txz&lt;br /&gt;
installpkg /dvd/slackware64/ap/groff-*.txz&lt;br /&gt;
installpkg /dvd/slackware64/a/less-*.txz&lt;br /&gt;
export MANPATH=/usr/man:/usr/share/man&lt;br /&gt;
&lt;br /&gt;
The manual pages should be readable:&lt;br /&gt;
&lt;br /&gt;
man zpool&lt;br /&gt;
man zfs&lt;br /&gt;
&lt;br /&gt;
After seeing the man pages, we should be fully ready to continue to setup on ZFS.&lt;br /&gt;
&lt;br /&gt;
(still on install-dvd)&lt;br /&gt;
ls -l /dev/sd*&lt;br /&gt;
&lt;br /&gt;
Make sure the disk devices you expect are there. We'll use sda and make boot (/boot on /dev/sda1) and root (/ on /dev/sda2) partitions.&lt;br /&gt;
&lt;br /&gt;
First, some background info: A ZFS filesystem is not supported by lilo as the filesystem containing /boot, which holds lilo's 2nd stage and the linux kernel files. The on-disk format of a ZFS filesystem is often a complex raid configuration where even if lilo understood ZFS it would likely require /boot to reside in only certain simple ZFS configurations to be plainly readable to lilo. As things are, a linux root installed in a partition with ZFS filesystem needs /boot to be on another partition with a filesystem that lilo understands, such as ext4 fs. In addition, because the spl and zfs modules are not built into the kernel, and the zfs startup requires some configuration to mount the zfs root, an initial ram/root filesystem (initrd) is needed. The initrd is a gzip compressed cpio archive file that contains a small linux root operating system that is decompressed into a ramfs block device at boot up and takes initial control of the system. The initrd contains an init script that configures devices in devtmpfs mounted at /dev. For example, if using mdadm, lvm, luks, losetup, and now zfs, this init script runs all the commands to create or start these devices (one of which is the root device), mounts the root device, and then transfers system control to the init script in the mounted root filesystem. The ramfs-based root environment on the booted install-dvd or booted initrd image (in rescue command line) are small slackware installations that exist only in ram and are temporary, but while inside them you can install, upgrade, and remove slackware packages inside them using the regular package management tools; this allows you access to any kernel modules and programs as needed inside these ramfs root. Packages can be installed, upgraded, or removed permanantly in the initrd image file to manage the programs and modules required during the initrd boot stage. Also from within these ramfs initial root environments, once the root device is mounted, chroot can be used to work on the mounted root system as if it were booted; this allows one to fix problems that are occuring in the root fs init scripts that cause normal booting to fail, or to install a kernel and/or modules etc. Now on to partitioning:&lt;br /&gt;
&lt;br /&gt;
cgdisk /dev/sda&lt;br /&gt;
&lt;br /&gt;
Here, cgdisk looks just like cfdisk, but it makes GPT partitions.&lt;br /&gt;
&lt;br /&gt;
Make a partition for /boot that is about 512MiB of whatever partition type you like (8300 &amp;quot;Linux filesystem&amp;quot; is fine), or make it type bf07 &amp;quot;Solaris Reserved 1&amp;quot; if you want ZFS to maybe see the disk as if it was given as a whole disk to ZFS. Make a second partition using the remaining space with partition type bf01 &amp;quot;Solaris ZFS&amp;quot;. Currently, when ZFSonLinux is given a whole disk device like /dev/sdb to use, it will automatically GPT partition it with a bf01 partition #1 that is the whole disk except a small 8MiB type bf07 partition #9 at the end of the disk (/dev/sdb1 and /dev/sb9). The small 8MiB type bf07 partition #9 is mostly likely reserved for use by bootloaders, like lilo, to have a /boot or other boot-related files kept there. For example, you might have /dev/sda that is totally non-ZFS for booting and /dev/sdb passed to ZFS whole where it automatically partitions sdb, but you can just use one disk here and make partitions. Lets use type 8300 for /boot to be sure nothing is confused:&lt;br /&gt;
&lt;br /&gt;
We'll continue with this partitioning (numbers are in MiB):&lt;br /&gt;
0 to 4: unused&lt;br /&gt;
4 to 516: /dev/sda1 512MiB, type 8300&lt;br /&gt;
516 to 520: unused&lt;br /&gt;
520 to -96: /dev/sda2, type bf01&lt;br /&gt;
The -96 means to count from the end of the disk so that 96MiB will remain unused at the end of the disk.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Create a zpool called zfs-root:&lt;br /&gt;
&lt;br /&gt;
zpool create -m none zfs-root /dev/sda2&lt;br /&gt;
&lt;br /&gt;
A zpool created like this, the normal way, is a kernel-internal block device that contains already a zfs filesystem. There is normally no entry in /dev for this device. However, it can still be referenced as a mountable device similar to how devtmpfs, proc, and sysfs are also kernel-internal mountable block devices. The -m option told zpool not to automatically mount it anywhere, and without -m the default is to always automatically mount to /zfs-root. These kinds of details are explained better elsewhere. For this situation, we do not want it automounted.&lt;br /&gt;
&lt;br /&gt;
Because a zpool itself is a useable zfs fs, it has a full set of zfs &amp;quot;properties&amp;quot; to set options about the filesystem, perhaps similar to tune2fs. The &amp;quot;mountpoint=&amp;lt;some place to mount&amp;gt;&amp;quot; is one such property. We want it set to the special value &amp;quot;none&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
zfs get mountpoint zfs-root&lt;br /&gt;
zfs set mountpoint=none zfs-root&lt;br /&gt;
&lt;br /&gt;
On creation, the zpool zfs-pool is &amp;quot;imported&amp;quot; and has a zpool status that can be viewed:&lt;br /&gt;
&lt;br /&gt;
zpool status zfs-root&lt;br /&gt;
&lt;br /&gt;
zpool export zfs-root&lt;br /&gt;
zpool status zfs-root&lt;br /&gt;
Now there is no status.&lt;br /&gt;
&lt;br /&gt;
zpool import zfs-root&lt;br /&gt;
Now it is back.&lt;br /&gt;
&lt;br /&gt;
When a zpool is imported, it has it's current configuration cached in a file /etc/zfs/zpool.cache. When a zpool is exported, then it's entries in the cache file are removed and the cache file is deleted if it becomes empty. So long as the zfs kernel modules see this cache file and valid cache data inside it, ZFS considers the described zpools in the cache file to be valid as imported zpools. If the zpool.cache file is present at the time the zfs modules are loaded, then there is no further need to use the import and export commands at system startup and shutdown. With root on a zfs, it is not possible to export the pool that root is on, but this is not a problem. At shutdown, the safe procedure will be to set the zfs-root property readonly=on and sync disks.&lt;br /&gt;
&lt;br /&gt;
To avoid the requirement to import the zfs-root pool at startup, keep a copy of the zpool.cache file to later copy onto the initrd image to read at modules load time to have the pool reactived without need to issue the import command:&lt;br /&gt;
&lt;br /&gt;
cp /etc/zfs/zpool.cache /etc/zfs/zpool.cache-initrd&lt;br /&gt;
&lt;br /&gt;
A zfs fs will not normally allow you to mount over any files. The mountpoint is expected to be an empty directory. Remove any junk files inside the installer's /mnt because zfs won't mount over any files:&lt;br /&gt;
&lt;br /&gt;
rm /mnt/README&lt;br /&gt;
&lt;br /&gt;
The directory /mnt is where the slackware setup expects you to mount your root for installation.&lt;br /&gt;
&lt;br /&gt;
Controlling whether a zfs fs is to be mounted read-only or read-write is best managed by setting the readonly property while it is not yet mounted:&lt;br /&gt;
&lt;br /&gt;
zfs set readonly=on zfs-root&lt;br /&gt;
zfs set readonly=off zfs-root&lt;br /&gt;
&lt;br /&gt;
Slackware expects root to be mounted readonly when /etc/rc.S runs during normal startup, so later this is used to satisfy slackware's expectation to avoid rc.S complaining.&lt;br /&gt;
&lt;br /&gt;
The zfs-root can be mounted and unmounted in two different ways:&lt;br /&gt;
&lt;br /&gt;
zfs set mountpoint=/mnt zfs-root&lt;br /&gt;
zfs set mountpoint=none zfs-root&lt;br /&gt;
&lt;br /&gt;
mount zfs-root -t zfs /mnt&lt;br /&gt;
umount /mnt&lt;br /&gt;
&lt;br /&gt;
If it is already mounted and you want to change it to mount somewhere else, it is best to transition it to unmounted first, then mount it in the new place.&lt;br /&gt;
&lt;br /&gt;
The mount options -o ro, -o rw, -o remount,ro, and -o remount,rw can also be used and will override readonly=on|off property without altering the property value. This can be confusing until you are familiar with how to the methods of mounting interact.&lt;br /&gt;
&lt;br /&gt;
Now, let's continue some, and mount to /mnt using the current readonly=off setting (rw mount):&lt;br /&gt;
&lt;br /&gt;
zfs set mountpoint=/mnt zfs-root&lt;br /&gt;
&lt;br /&gt;
This method of mounting will show the most detailed mount options in /etc/mtab. They are the mount options that zfs thinks are proper, and they are probably what should be kept in /etc/fstab for zfs-root until we know better.&lt;br /&gt;
&lt;br /&gt;
cat /etc/mtab &amp;gt;&amp;gt; /etc/fstab&lt;br /&gt;
&lt;br /&gt;
Now edit /etc/fstab to make sure it looks right, and remove the &amp;quot;rw&amp;quot; mount option, because we want to let it use a default for that, which will come from how we set the readonly= property most of the time. Unmount again:&lt;br /&gt;
&lt;br /&gt;
zfs set mountpoint=none zfs-root&lt;br /&gt;
&lt;br /&gt;
Mount again, now using all options from /etc/fstab:&lt;br /&gt;
&lt;br /&gt;
mount zfs-root&lt;br /&gt;
&lt;br /&gt;
It should be mounted at /mnt, and touch /mnt/t should allow you to make the file t. Then rm it: rm /mnt/t&lt;br /&gt;
For installation, we want to make sure it is mounted read-write. After installation, it should mount readonly inside the initrd.&lt;br /&gt;
&lt;br /&gt;
Sometimes there can be problems using the mount command, and then you can try it with the -i option:&lt;br /&gt;
 mount -i zfs-root &lt;br /&gt;
 mount -i zfs-root -t zfs /mnt&lt;br /&gt;
but, you should not have to use -i. When using -i makes it work, it performs an &amp;quot;internal-only&amp;quot; mount and does not use any mount.&amp;lt;fstype&amp;gt; helper scripts that might be on the system.&lt;br /&gt;
&lt;br /&gt;
Setup the /boot device:&lt;br /&gt;
&lt;br /&gt;
mkfs.ext4 /dev/sda1&lt;br /&gt;
mkdir /mnt/boot&lt;br /&gt;
mount /dev/sda1 /mnt/boot&lt;br /&gt;
&lt;br /&gt;
We have both root and boot mounted where the slackware installer expects them. Unmount the dvd so setup can find it normally:&lt;br /&gt;
&lt;br /&gt;
umount /dev/sr0&lt;br /&gt;
setup&lt;br /&gt;
&lt;br /&gt;
In the setup, skip straight to TARGET selection for the root device, but the setup doesn't see or understand the zfs-root, so it is not listed. This does not matter because we have mounted it already. Just skip down to a slot that say to continue, and continue on with setup. Because TARGET is skipped, you may not see the ADDITIONAL prompt (or if so, skip it too) where normally you give /dev/sda1 and have it mounted as /boot. This is also okay because we have mounted /mnt/boot already.&lt;br /&gt;
Because we did not give TARGET the root device or say what device /boot is on, the lilo installation will fail, or you can skip it. Otherwise, this installation process it normal.&lt;br /&gt;
&lt;br /&gt;
umount /dev/sr0&lt;br /&gt;
&lt;br /&gt;
At this point, it is assumed that the setup has completed installing into /mnt. Congrats! You've installed slackware into a ZFS root!&lt;br /&gt;
&lt;br /&gt;
The next steps are to prepare to use &amp;quot;chroot /mnt&amp;quot; and finish up the configuration on the installed root system and then be able to reboot onto the completed installation. Before doing chroot, copy some files from the setup environment into /mnt.&lt;br /&gt;
&lt;br /&gt;
Copy the current installer /etc/fstab for later use inside the initrd. This fstab is what is proper inside the initrd, except remove option &amp;quot;rw&amp;quot; (if not done already).&lt;br /&gt;
&lt;br /&gt;
cp /etc/fstab /mnt/etc/fstab.initrd&lt;br /&gt;
&lt;br /&gt;
The fstab.initrd will look like:&lt;br /&gt;
 proc /proc proc defaults 0 0&lt;br /&gt;
 zfs-root /mnt zfs defaults,atime,dev,exec,suid,xattr,nomand,zfsutil 0 0&lt;br /&gt;
&lt;br /&gt;
In the initrd, we want zfs-root to mount to /mnt.&lt;br /&gt;
&lt;br /&gt;
Create /mnt/etc/fstab:&lt;br /&gt;
&lt;br /&gt;
cat /etc/mtab &amp;gt;&amp;gt; /mnt/etc/fstab&lt;br /&gt;
vi /mnt/etc/fstab&lt;br /&gt;
&lt;br /&gt;
Using vi started above, edit /mnt/etc/fstab and make it have lines such as:&lt;br /&gt;
 zfs-root / zfs defaults,atime,dev,exec,suid,xattr,nomand,zfsutil 0 0&lt;br /&gt;
 /dev/sda1 /boot ext4 defaults 0 2&lt;br /&gt;
&lt;br /&gt;
These two lines in /mnt/etc/fstab are how the mounts should be looking when root is booted.&lt;br /&gt;
&lt;br /&gt;
Mount some special mounts before chroot:&lt;br /&gt;
&lt;br /&gt;
mount -t devtmpfs none /mnt/dev&lt;br /&gt;
mount -t proc none /mnt/proc&lt;br /&gt;
mount -t sysfs none /mnt/sys&lt;br /&gt;
&lt;br /&gt;
Make sure /boot is mounted:&lt;br /&gt;
&lt;br /&gt;
mount /dev/sda1 /mnt/boot&lt;br /&gt;
&lt;br /&gt;
If you had mounted a 9p fs share to access spl and zfs packages, then unmount that now:&lt;br /&gt;
umount /packages&lt;br /&gt;
&lt;br /&gt;
Ready, now:&lt;br /&gt;
&lt;br /&gt;
chroot /mnt&lt;br /&gt;
&lt;br /&gt;
At this point, you should be on the installed system, and now try to configure mkinitrd and lilo. First, switch to use the generic kernel.&lt;br /&gt;
&lt;br /&gt;
cd /boot&lt;br /&gt;
rm System.map config vmlinuz&lt;br /&gt;
ln -s System.map-gen* System.map&lt;br /&gt;
ln -s config-gen* config&lt;br /&gt;
ln -s vmlinuz-gen* vmlinuz&lt;br /&gt;
&lt;br /&gt;
We install spl and zfs inside the live ramfs install-dvd environment, but not yet have we installed them into the root system:&lt;br /&gt;
&lt;br /&gt;
mount /dev/sr0 /mnt/cdrom&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /mnt/cdrom/addon/spl-*.txz&lt;br /&gt;
depmod&lt;br /&gt;
installpkg /mnt/cdrom/addon/zfs-*.txz&lt;br /&gt;
depmod&lt;br /&gt;
&lt;br /&gt;
If instead, you used a 9p share to access the spl and zfs packages, then repeat that procedure here to install them onto the root system.&lt;br /&gt;
&lt;br /&gt;
Setup lilo: edit /etc/lilo.conf so it is like:&lt;br /&gt;
&lt;br /&gt;
  lba32&lt;br /&gt;
  append = &amp;quot; vt.default_utf8=1&amp;quot;&lt;br /&gt;
  boot = /dev/sda&lt;br /&gt;
  message = /boot/boot_message.txt&lt;br /&gt;
  prompt&lt;br /&gt;
  timeout = 1200&lt;br /&gt;
  change-rules&lt;br /&gt;
   reset&lt;br /&gt;
  vga = normal&lt;br /&gt;
  image = /boot/vmlinuz&lt;br /&gt;
   initrd = /boot/initrd.gz&lt;br /&gt;
   root = /dev/sda1&lt;br /&gt;
   label = vmlinuz&lt;br /&gt;
   read-only&lt;br /&gt;
&lt;br /&gt;
The line, root = /dev/sda1, is not really a true statement but lilo needs a device there that it at least understands. This root = line is a kernel parameter, but since the initrd is what is actually the root, initially, then the root = line is probably useless here. It might even be okay to just delete the root line.&lt;br /&gt;
&lt;br /&gt;
Setup mkinitrd:&lt;br /&gt;
&lt;br /&gt;
cp /etc/mkinitrd.conf.sample /etc/mkinitrd.conf&lt;br /&gt;
vi /etc/mkinitrd.conf&lt;br /&gt;
&lt;br /&gt;
Edit it to look like this (other defaults should be ok):&lt;br /&gt;
&lt;br /&gt;
 MODULE_LIST=&amp;quot;sym53c8xx:ext4:8139cp:zfs:9p:9pnet_virtio&amp;quot;&lt;br /&gt;
 ROOTDEV=&amp;quot;zfs-root&amp;quot;&lt;br /&gt;
 ROOTFS=&amp;quot;zfs&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Module sym53c8xx is the driver for qemu's if=scsi drive device.&lt;br /&gt;
Module ext4 for /boot.&lt;br /&gt;
Module 8139cp for eth0 net device.&lt;br /&gt;
Module zfs for ZFSonLinux.&lt;br /&gt;
Modules 9p and 9pnet_virtio for mounting qemu -virtfs mount_tag.&lt;br /&gt;
&lt;br /&gt;
These 9p could be useful from the rescue command line inside the initrd to get needed files that are on the host.&lt;br /&gt;
&lt;br /&gt;
All dependent modules will also be included automatically into /boot/initrd-tree, which is packaged as /boot/initrd.gz. For example, to see the dependent modules of zfs:&lt;br /&gt;
&lt;br /&gt;
modprobe --show-depends zfs&lt;br /&gt;
&lt;br /&gt;
All listed modules will also be in the initrd. Now, make a /boot/initrd-tree that we can begin to look at and edit.&lt;br /&gt;
&lt;br /&gt;
mkinitrd&lt;br /&gt;
&lt;br /&gt;
Create an empty /etc/mtab or else zpool import fails (zfs expects /etc/mtab to exists already, it won't make it).&lt;br /&gt;
&lt;br /&gt;
touch /boot/initrd-tree/etc/mtab&lt;br /&gt;
&lt;br /&gt;
Copy in the fstab.initrd that was made earlier while on the installer. This provides all the mount options for a simple &amp;quot;mount zfs-root&amp;quot; onto /mnt.&lt;br /&gt;
&lt;br /&gt;
cp /etc/fstab.initrd /boot/initrd-tree/etc/fstab&lt;br /&gt;
&lt;br /&gt;
More package installing! This time into an alternate root, the root of the initrd, /boot/initrd-tree. This is how you can put whatever packages you like into your initrd. These installations work independent of your normal installations. You can install, upgrade, and remove packages using an altroot:&lt;br /&gt;
&lt;br /&gt;
If spl and zfs are on your customized dvd:&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/addon/spl-*.txz&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/addon/zfs-*.txz&lt;br /&gt;
Otherwise, repeat same procedure but you mount your 9p mount_tag and get them installed.&lt;br /&gt;
&lt;br /&gt;
More regular packages from the dvd:&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/kmod-*.txz&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/coreutils-*.txz&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/gptfdisk-*.txz&lt;br /&gt;
&lt;br /&gt;
A bash script is in /boot/initrd-tree/lib/udev/, so we need it or udev rules have problems:&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/a/bash-*.txz&lt;br /&gt;
Bash needs this:&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/l/libtermcap-*.txz&lt;br /&gt;
&lt;br /&gt;
Install net-tools to ensure that /etc/HOSTNAME, /etc/hosts, and potentially, /etc/hostid are handled proper.&lt;br /&gt;
installpkg --root /boot/initrd-tree /mnt/cdrom/slackware64/n/net-tools-*.txz&lt;br /&gt;
&lt;br /&gt;
When ZFS has to import a zpool while the initrd is running (this can be avoided by not exporting and keeping /etc/zfs/zpool.cache inside the initrd), ZFS will refuse to import a pool if it thinks that the pool may be in use by another system. ZFS was designed for network attached storage where multiple hosts might have access to the same disks but ZFS cannot support two hosts importing and using a ZFS pool at the same time. ZFS checks a value called &amp;quot;hostid&amp;quot; to determine this kind of conflict, and it can be a tricky issue with an initrd boot process. The value of hostid is returned by a system call, the gethostid() function or the hostid command. This function will return the hostid from /etc/hostid if that file exists and has a valid id in it, or else if the file doesn't exist it obtains a hostid number based on the hostname and ip address address assigned to hostname found in /etc/hosts or in DNS. If the hostid trying to import a pool is not the same as the hostid that imported it last time, ZFS will not import the pool unless &amp;quot;zpool import -f zfs-root&amp;quot; is used to force the import. This force option is not recommended to use, so it is best to configure your initrd with matching /etc/HOSTNAME and /etc/hosts as on the root installation and ensure what your system looks like on the initrd matches the booted root system.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Edit /boot/initrd-tree/init (this is the main system startup script on the initrd, responsibe for configuring your block devices and mount your root at /mnt and then booting root):&lt;br /&gt;
&lt;br /&gt;
Inside init, right near the top of the file after the PATH= line, add this:&lt;br /&gt;
&lt;br /&gt;
/bin/hostname -F /etc/HOSTNAME&lt;br /&gt;
/bin/hostname $( /bin/hostname -s )&lt;br /&gt;
#/sbin/chhostid 13371400&lt;br /&gt;
# you can make your hostid whatever, but this didn't work right with ZFS, so it is commented out&lt;br /&gt;
&lt;br /&gt;
This sets the name reported by the hostname command (the default is &amp;quot;darkstar&amp;quot;) to be what is contained in /etc/HOSTNAME. The hostname is modified in the next line to be the short name. These lines will help ZFS to properly identify your host when importing pools.&lt;br /&gt;
&lt;br /&gt;
Inside init, right after it runs &amp;quot;mdadm&amp;quot; commands as used for raid setup, we like it to setup ZFS, so add:&lt;br /&gt;
&lt;br /&gt;
/sbin/zpool import zfs-root&lt;br /&gt;
/sbin/zfs set readonly=on zfs-root&lt;br /&gt;
mount zfs-root&lt;br /&gt;
&lt;br /&gt;
Inside init, close to the bottom, where it &amp;quot;Switch to real root partition&amp;quot;, comment out 1 line that normally does the mount:&lt;br /&gt;
# mount -o ro -t $ROOTFS $ROOTDEV /mnt&lt;br /&gt;
We have already mounted, and we don't want to use any mount options because we should be using a properly set /etc/fstab inside the initrd for zfs-root mount options onto /mnt.&lt;br /&gt;
&lt;br /&gt;
During a normal startup we want a readonly mount.&lt;br /&gt;
&lt;br /&gt;
Note: we are going to setup with using zpool import and export and startup and shutdown. But later, you can experiment having /etc/zfs/zpool.cache stored in the initrd and commenting out zpool import/export lines.&lt;br /&gt;
&lt;br /&gt;
As mentioned, the import command may sometimes fail, and give the message: &amp;quot;pool may be in use from another system&amp;quot;. This is nothing serious in this test situation. When this happens, root will not be mounted to /mnt and the init script will detect this and drop you into a rescue command line where you may manually &amp;quot;import -f&amp;quot; then &amp;quot;mount zfs-root&amp;quot; and then &amp;quot;exit&amp;quot; to continue on to booting the root.&lt;br /&gt;
&lt;br /&gt;
To avoid this problem we copy some files in (assuming you first edit /etc/HOSTNAME to hold the hostname you like to see on your command prompts, and edited /etc/hosts to have hostname on your loopback or other local ip address):&lt;br /&gt;
&lt;br /&gt;
cp /etc/HOSTNAME /etc/hosts /boot/initrd-tree/etc&lt;br /&gt;
&lt;br /&gt;
The value reported by the hostid command is what ZFS sees as your hostid. In this setup so far, the value is based on the ip found assigned to your hostname. If your hostname is on the line in /etc/hosts for ip address 192.168.13.37, then your hostid will be hex numbers C0.A8.0D.25 rearranged as A8C0250D (pairs of bytes are swapped). That is ip-based hostid value, a 32bit hexadecimal number. This has to be the same each boot or import will need a -f option to force it. Simply setting the hostid using the system call sethostid() which writes a /etc/hostid file doesn't seem to agree with ZFS and you'd have to force the import, so this setup now assumes that you do not have or have deleted /etc/hostid.&lt;br /&gt;
&lt;br /&gt;
You can sometimes see what has been happening to a zpool by using the command &amp;quot;zpool history -li zfs-root&amp;quot; to see a log of commands.&lt;br /&gt;
&lt;br /&gt;
Once again, you can do away with the import and export commands by trying to have /etc/zfs/zpool.cache inside your initrd. To create zpool.cache, while on the installer or in the rescue shell of the initrd (at lilo &amp;quot;boot: vmlinuz rescue&amp;quot;), import only the pool for the root fs with mountpoint=none and readonly=on properties set and while it is not mounted:&lt;br /&gt;
&lt;br /&gt;
(on installer or initrd rescue shell)&lt;br /&gt;
cp /etc/zfs/zpool.cache /etc/zfs/zpool.cache-initrd&lt;br /&gt;
zfs set readonly=off zfs-root&lt;br /&gt;
mount zfs-pool&lt;br /&gt;
cp /etc/zfs/zpool.cache-initrd /mnt/etc/zfs/&lt;br /&gt;
cp /mnt/etc/zfs/zpool.cache-initrd /mnt/boot/initrd-tree/etc/zfs/zpool.cache&lt;br /&gt;
umount /mnt&lt;br /&gt;
zfs set readonly=on zfs-root&lt;br /&gt;
#mount zfs-root&lt;br /&gt;
#exit (to continue boot process onto rootfs mounted at /mnt)&lt;br /&gt;
&lt;br /&gt;
Now, doing this zpool.cache approach is not necessary, and some talk suggests this is deprecated or discouraged. Although /etc/hostid setup fails to import without -f option, ip-based (hosts|dns) hostid works on booting and import works without -f option and may be the more proper way to do shutdown and startup rather than using a cache file which could be come invalid and cause a problem that is difficult to understand. The contents and exact function of the cache file are not well understood by many people.&lt;br /&gt;
&lt;br /&gt;
Save /boot/initrd-tree/init and exit.&lt;br /&gt;
&lt;br /&gt;
Now, edit /etc/rc.d/rc.S and rc.6 to understand how to &amp;quot;remount&amp;quot; rw or ro as a readonly property changes&lt;br /&gt;
&lt;br /&gt;
In /etc/rc.d/rc.S:&lt;br /&gt;
comment out the line&lt;br /&gt;
#    /sbin/mount -w -v -n -o remount /&lt;br /&gt;
add the line&lt;br /&gt;
     /sbin/zfs set readonly=off zfs-root&lt;br /&gt;
&lt;br /&gt;
In /etc/rc.d/rc.6&lt;br /&gt;
comment out the line&lt;br /&gt;
#    /bin/mount -v -n -o remount,ro /&lt;br /&gt;
add the line&lt;br /&gt;
     /sbin/zfs set readonly=on zfs-root&lt;br /&gt;
&lt;br /&gt;
In /etc/rc.d/rc.6, near the bottom just before poweroff|reboot, add the following block of lines:&lt;br /&gt;
&lt;br /&gt;
########################&lt;br /&gt;
# Try to export zfs-root&lt;br /&gt;
/sbin/zpool export zfs-root&lt;br /&gt;
if [ $? -gt 0 ] ; then&lt;br /&gt;
 echo &amp;quot;ZFS export failed.&amp;quot;&lt;br /&gt;
 echo &amp;quot;Notice: if root fs is busy, then this is normal fail.&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;ZFS export successful.&amp;quot;&lt;br /&gt;
 echo &amp;quot;Warning: successful export is abnormal for root fs.&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
/bin/sleep 5&lt;br /&gt;
########################&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
For ZFS, you cannot run fsck on it. It doesn't support that kind of filesystem checks. The rc.S script will complain a lot in many places about not being about to run fsck on the zfs-root. To disable all attempts of run fsck, we can simple create a file that acts as a flag in /etc/rc.d/rc.S to tell it to skip fsck:&lt;br /&gt;
&lt;br /&gt;
touch /etc/fastboot&lt;br /&gt;
&lt;br /&gt;
This fastboot file is normally a run-once temporary file, and it is deleted near the bottom inside rc.S. Edit rc.S and stop it from deleting /etc/fastboot. We would like it to always skip all fsck. Edit /etc/rc.d/rc.S, and find the &amp;quot;rm&amp;quot; of fastboot, and do not have it removed!&lt;br /&gt;
&lt;br /&gt;
We are getting close, and have finished all editing, so make /boot/initrd.gz and install lilo:&lt;br /&gt;
&lt;br /&gt;
mkinitrd -F&lt;br /&gt;
lilo&lt;br /&gt;
&lt;br /&gt;
We finished! All that's left to do is clean up.&lt;br /&gt;
&lt;br /&gt;
Exit the chroot.&lt;br /&gt;
&lt;br /&gt;
exit&lt;br /&gt;
&lt;br /&gt;
Try to mount everything:&lt;br /&gt;
&lt;br /&gt;
umount /mnt/proc&lt;br /&gt;
umount /mnt/sys&lt;br /&gt;
umount /mnt/dev&lt;br /&gt;
umount /mnt/boot&lt;br /&gt;
umount /mnt/mnt/cdrom&lt;br /&gt;
umount /mnt/root/packages&lt;br /&gt;
umount /mnt&lt;br /&gt;
zpool export zfs-root&lt;br /&gt;
&lt;br /&gt;
Note, that export stops a pool and frees devices, while import binds devices and starts a pool. It is somewhat like mdadm -A -s and mdadm -S -s, while /etc/zfs/zpool.cache might be somewhat like mdadm -E -s &amp;gt; /etc/mdadm.conf.&lt;br /&gt;
&lt;br /&gt;
Remove the DVD.&lt;br /&gt;
&lt;br /&gt;
reboot&lt;br /&gt;
&lt;br /&gt;
When you reboot, if all is good, you are booting properly onto a slackware installed on a ZFS root! Congrat!&lt;br /&gt;
&lt;br /&gt;
If this seem to go badly, and this might happen if the import fails as explain some before, then you will be on the initrd's rescue command line just before the part in it's init where it wants to mount and switch_root to boot your root. Instead, you typically got commands like this to do:&lt;br /&gt;
&lt;br /&gt;
If you get dumped to rescue because import will not work and requires -f (force), then:&lt;br /&gt;
 zpool import -f zfs-root&lt;br /&gt;
 zpool export    zfs-root&lt;br /&gt;
 zpool import    zfs-root&lt;br /&gt;
 mount zfs-root&lt;br /&gt;
 exit&lt;br /&gt;
This can happen if hostname, hostid, or uname changes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you get into a jam and need to boot into the initrd and skip zfs import etc, use the lilo prompt (or, boot the install-dvd):&lt;br /&gt;
&lt;br /&gt;
boot: vmlinuz rescue&lt;br /&gt;
&lt;br /&gt;
In the rescue mode of the initrd, after you have mounted your root as readonly=on to /mnt, then exit to continue.&lt;br /&gt;
&lt;br /&gt;
In other emergency modes, you might need to run the lines at end of init starting from: udevadm info --cleanup-db; udevadm control --exit&lt;br /&gt;
If you don't run those udevadm commands, two runs of udevd fight each other and it is slow; you have to wait 2 minutes twice for timeouts (4 minutes).&lt;br /&gt;
The last line is run is: exec switch_root /mnt /sbin/init 1&lt;br /&gt;
&lt;br /&gt;
Warning... this switch_root command is kind of dangerous, so read the manual page about it.&lt;br /&gt;
From what I can tell, everything except the new root &amp;quot;/mnt&amp;quot; is deleted, so you are giving a command that says what NOT to delete!&lt;br /&gt;
Make sure nothing got mounted outside of &amp;quot;/mnt&amp;quot; before you run it.&lt;br /&gt;
&lt;br /&gt;
Also, in rescue or anytime you have finished making changes and are about to reboot in some abnormal mode, first run:&lt;br /&gt;
&lt;br /&gt;
zfs set readonly=on zfs-root&lt;br /&gt;
&lt;br /&gt;
A bug in unpatched grep 2.13 build 1, found slackware 14.0rc1, causes problems when processing files stored on ZFS but rarely shows problems on other filesystems; the bug does not handle sparse files on zfs and btrfs correctly and results in chaos with slackpkg, compiling kernel modules, and possibly many other things. You must downgrade grep to 2.12 or use the patched grep 2.13 build 2 in slackware 14.0rc2 or later.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Upgrading.&lt;br /&gt;
&lt;br /&gt;
From time to time you will want to upgrade the kernel to the new kernel in slackware64-current or in patches/. This will also necessitate a rebuilt and reinstall or upgrade of spl and zfs. Below is an example of when both kernel and spl/zfs are being upgraded, to give an idea of the process:&lt;br /&gt;
&lt;br /&gt;
Using slackpkg, that is configured to use your local slackware mirror is a good option but you can also configure it to use a remote mirror.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
slackpkg upgrade-all&lt;br /&gt;
&lt;br /&gt;
Assume slackpkg just upgraded your kernel, kernel-modules, and kernel-headers.&lt;br /&gt;
&lt;br /&gt;
Note: the first time you try to run on kernel-generic, setup kernel-huge in lilo as 2nd choice. Huge has all the hard drive controllers builtin, but generic has them all as modules. For example, run &amp;quot;modinfo mptsas&amp;quot; to see module options (maybe you have a LSISAS1068) for your hard drive controller. Add file /etc/modprobe.d/mptsas.conf to set options you want with a line: options mptsas ... Do this for all the device driver modules for your hardware. Do this setup while you are on the huge kernel, then setup to reboot to generic. Include all these modules you need into mkinitrd.conf MODULES_LIST. Check that /boot/initrd-tree/etc/modprobe.d/ has a copy of your customized module conf files because it is on the initrd where the modules will load and use the conf files. mkinitrd probably copies all /etc/modprobe.d/* files into the initrd-tree, but check it. Pay attention to /etc/modprobe.d/README and /lib/modprobe.d/* /lib/modprobe.d/* maybe not copied to initrd-tree but you might want to copy some of it into your initrd-tree yourself to use them.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Check that upgraded kernel-source is symlinked to /usr/src/linux (zfs build looks here). SQL/ZFS modules will install to the kernel version in /lib/modules/&amp;lt;/usr/src/linux kernel version&amp;gt;&lt;br /&gt;
&lt;br /&gt;
cd /usr/local/src&lt;br /&gt;
tar xvzf ~/spl-*.tar.gz&lt;br /&gt;
tar xvzf ~/zfs-*.tar.gz&lt;br /&gt;
&lt;br /&gt;
###### upgrade spl 1st&lt;br /&gt;
mkdir install&lt;br /&gt;
cd spl-*&lt;br /&gt;
./configure --prefix=/ --libexecdir=/usr/libexec --libdir=/lib64 --includedir=/usr/include --datarootdir=/usr/share&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=/usr/local/src/install&lt;br /&gt;
cd ../install&lt;br /&gt;
makepkg ../spl-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
upgradepkg spl-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
depmod &amp;lt;new kernel version&amp;gt;     (e.g. depmod 3.2.27, if .27 is new kernel upgrade; you currently run on old, maybe .26)&lt;br /&gt;
# this builds the module dependencies in /lib/modules/&amp;lt;new kernel version&amp;gt;&lt;br /&gt;
###### upgrade zfs 2nd&lt;br /&gt;
mkdir install&lt;br /&gt;
cd zfs-*&lt;br /&gt;
./configure --prefix=/ --libexecdir=/usr/libexec --libdir=/lib64 --includedir=/usr/include --datarootdir=/usr/share&lt;br /&gt;
make&lt;br /&gt;
make install DESTDIR=/usr/local/src/install&lt;br /&gt;
cd ../install&lt;br /&gt;
makepkg ../zfs-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
cd ..&lt;br /&gt;
rm -r install&lt;br /&gt;
upgradepkg zfs-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
depmod 3.2.27&lt;br /&gt;
####### upgrade spl/zfs inside altroot /boot/initrd-tree&lt;br /&gt;
ROOT=/boot/initrd-tree upgradepkg spl-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
ROOT=/boot/initrd-tree upgradepkg zfs-&amp;lt;version&amp;gt;rcX_&amp;lt;kernel version&amp;gt;-x86_64-Xroot.txz&lt;br /&gt;
# note: ROOT is an environment variable, not a command line option to upgradepkg!&lt;br /&gt;
# note: do not worry about depmod inside initrd-tree, mkinitrd -F actually installs the modules&lt;br /&gt;
# note: this upgrade here is really to just upgrade the command line tools zpool, zfs etc&lt;br /&gt;
####### rebuild /boot/initrd.gz and reinstall lilo&lt;br /&gt;
vi /etc/mkinitrd.conf&lt;br /&gt;
# temporarily set KERNEL_VERSION to new version, but you are still running on old version&lt;br /&gt;
mkinitrd -F&lt;br /&gt;
lilo&lt;br /&gt;
vi /etc/mkinitrd.conf&lt;br /&gt;
# you can set KERNEL_VERSION back to $(uname r) now&lt;br /&gt;
reboot&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
After reboot you can remove any old /lib/modules/&amp;lt;old kernel version&amp;gt; directory.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
More about /etc/hostid. If you want to experiment changing your /etc/hostid file and seeing if you can use it and make zpool import work normally, here is a tool that might be helpful:&lt;br /&gt;
&lt;br /&gt;
################################################&lt;br /&gt;
/* software product name: foobarz-chhostid.c&lt;br /&gt;
 * suggested binary name: chhostid&lt;br /&gt;
 * license              : BSD&lt;br /&gt;
 * license text:&lt;br /&gt;
Copyright (c) 2012, foobarz&lt;br /&gt;
All rights reserved.&lt;br /&gt;
&lt;br /&gt;
Redistribution and use in source and binary forms, with or without&lt;br /&gt;
modification, are permitted provided that the following conditions are met:&lt;br /&gt;
    * Redistributions of source code must retain the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer.&lt;br /&gt;
    * Redistributions in binary form must reproduce the above copyright&lt;br /&gt;
      notice, this list of conditions and the following disclaimer in the&lt;br /&gt;
      documentation and/or other materials provided with the distribution.&lt;br /&gt;
    * Neither the name of the &amp;lt;organization&amp;gt; nor the&lt;br /&gt;
      names of its contributors may be used to endorse or promote products&lt;br /&gt;
      derived from this software without specific prior written permission.&lt;br /&gt;
&lt;br /&gt;
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &amp;quot;AS IS&amp;quot; AND&lt;br /&gt;
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED&lt;br /&gt;
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE&lt;br /&gt;
DISCLAIMED. IN NO EVENT SHALL &amp;lt;COPYRIGHT HOLDER&amp;gt; BE LIABLE FOR ANY&lt;br /&gt;
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES&lt;br /&gt;
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;&lt;br /&gt;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND&lt;br /&gt;
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT&lt;br /&gt;
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS&lt;br /&gt;
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#define FOOBARZ_CHHOSTID_VERSION &amp;quot;1.0.5&amp;quot;&lt;br /&gt;
#include &amp;lt;sys/socket.h&amp;gt;&lt;br /&gt;
#include &amp;lt;netinet/in.h&amp;gt;&lt;br /&gt;
#include &amp;lt;arpa/inet.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;endian.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sysexits.h&amp;gt;&lt;br /&gt;
/* note: if include stdlib then sethostid fails even with _BSD_SOURCE defined */&lt;br /&gt;
&lt;br /&gt;
long swapbytes(long abcd) {&lt;br /&gt;
  long badc;&lt;br /&gt;
  unsigned char addr_a;&lt;br /&gt;
  unsigned char addr_b;&lt;br /&gt;
  unsigned char addr_c;&lt;br /&gt;
  unsigned char addr_d;&lt;br /&gt;
  addr_a = (unsigned char) (abcd &amp;gt;&amp;gt; 24);&lt;br /&gt;
  addr_b = (unsigned char) (abcd &amp;gt;&amp;gt; 16);&lt;br /&gt;
  addr_c = (unsigned char) (abcd &amp;gt;&amp;gt;  8);&lt;br /&gt;
  addr_d = (unsigned char) (abcd);&lt;br /&gt;
  return badc = ( (addr_b &amp;lt;&amp;lt; 24) | (addr_a &amp;lt;&amp;lt; 16) | (addr_d &amp;lt;&amp;lt; 8) | addr_c );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[])&lt;br /&gt;
{&lt;br /&gt;
 long newhostid;&lt;br /&gt;
 struct in_addr addr;&lt;br /&gt;
 char* invalidchar;&lt;br /&gt;
&lt;br /&gt;
 /*********** check command line */&lt;br /&gt;
 if(!( ((argc==3) &amp;amp;&amp;amp; ( (strcmp(argv[1],&amp;quot;-h&amp;quot;)==0) ||&lt;br /&gt;
                       (strcmp(argv[1],&amp;quot;-i&amp;quot;)==0) ||&lt;br /&gt;
                       (strcmp(argv[1],&amp;quot;-l&amp;quot;)==0) )) ||&lt;br /&gt;
       ((argc==2) &amp;amp;&amp;amp; ( (strcmp(argv[1],&amp;quot;-s&amp;quot;)==0) ))&lt;br /&gt;
     )&lt;br /&gt;
   ) {&lt;br /&gt;
                 /*01234567890123456789012345678901234567890123456789012345678901234567890123456789*/&lt;br /&gt;
  fprintf(stderr, &amp;quot;foobarz-chhostid, version %s. License: BSD.\n&amp;quot;, FOOBARZ_CHHOSTID_VERSION);&lt;br /&gt;
  fprintf(stderr, &amp;quot;foobarz-chhostid, (c) 2012, foobarz; all rights reserved.\n&amp;quot;);&lt;br /&gt;
  fprintf(stderr, &amp;quot;descr: %s change system hostid (in /etc/hostid).\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -h &amp;lt;new hostid&amp;gt;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        Change system hostid to &amp;lt;new hostid&amp;gt;;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        &amp;lt;new hostid&amp;gt; must be 32bit 8-digit hex number xxxxxxxx, each x in 0-f|F.\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        The ip corresponding to &amp;lt;new hostid&amp;gt; is also listed for reference only.\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -i &amp;lt;dotted ip address&amp;gt;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        Change system hostid to hostid corresponding to &amp;lt;dotted ip address&amp;gt;.\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -l &amp;lt;dotted ip address&amp;gt;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        List hostid corresponding to &amp;lt;dotted ip address&amp;gt;;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        no change to system hostid.\n&amp;quot;, argv[0]);&lt;br /&gt;
  fprintf(stderr, &amp;quot;usage: %s -s\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        List current system hostid and corresponding ip address;\n&amp;quot;&lt;br /&gt;
                  &amp;quot;        no change to system hostid.\n&amp;quot;, argv[0]);&lt;br /&gt;
  return EX_USAGE;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -h &amp;lt;hostid&amp;gt; */&lt;br /&gt;
 if( strcmp(argv[1],&amp;quot;-h&amp;quot;) == 0 ) {&lt;br /&gt;
  if(strlen(argv[2]) != 8) { fprintf(stderr, &amp;quot;new hostid must be 8-digit hex number xxxxxxxx, each x in 0-f|F\n&amp;quot;); return EX_USAGE; }&lt;br /&gt;
&lt;br /&gt;
  newhostid = strtol(argv[2],&amp;amp;invalidchar,16);&lt;br /&gt;
  if( newhostid==LONG_MIN ) { perror(&amp;quot;strtol (underflow)&amp;quot;); return EX_USAGE; }&lt;br /&gt;
  if( newhostid==LONG_MAX ) { perror(&amp;quot;strtol (overflow)&amp;quot;); return EX_USAGE; }&lt;br /&gt;
  if(*invalidchar != '\0') { fprintf(stderr, &amp;quot;invalid hex number %c; must be in 0-f|F\n&amp;quot;, *invalidchar); return EX_USAGE; }&lt;br /&gt;
&lt;br /&gt;
  if( sethostid(newhostid) != 0 ) {&lt;br /&gt;
   perror(&amp;quot;sethostid&amp;quot;);&lt;br /&gt;
   if( errno == EPERM ) return EX_NOPERM;&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
  }&lt;br /&gt;
  printf(&amp;quot;System hostid changed.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  /* hostid is a byte-swapped ip like b.a.d.c */&lt;br /&gt;
  /* get ip by swapping to correct order a.b.c.d and save into in_addr struct */&lt;br /&gt;
  addr.s_addr = htonl(swapbytes(newhostid));&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -i or -l, then find hostid for &amp;lt;dotted ip address&amp;gt; */&lt;br /&gt;
 if( (strcmp(argv[1],&amp;quot;-i&amp;quot;) == 0) || (strcmp(argv[1],&amp;quot;-l&amp;quot;) == 0) ) {&lt;br /&gt;
  if( inet_aton(argv[2], &amp;amp;addr) == 0 ) { fprintf(stderr, &amp;quot;inet_aton: invalid dotted ip address: %s\n&amp;quot;, argv[2]); return EX_USAGE; }&lt;br /&gt;
&lt;br /&gt;
  /* hostid is a byte-swapped ip like b.a.d.c */&lt;br /&gt;
  /* get hostid by swapping bytes of ip a.b.c.d */&lt;br /&gt;
  newhostid = swapbytes(ntohl(addr.s_addr));&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -i &amp;lt;dotted ip address&amp;gt; */&lt;br /&gt;
 if( strcmp(argv[1],&amp;quot;-i&amp;quot;) == 0 ) {&lt;br /&gt;
  if( sethostid(newhostid) != 0 ) {&lt;br /&gt;
   perror(&amp;quot;sethostid&amp;quot;);&lt;br /&gt;
   if( errno == EPERM ) return EX_NOPERM;&lt;br /&gt;
   return EX_UNAVAILABLE;&lt;br /&gt;
  }&lt;br /&gt;
  printf(&amp;quot;System hostid changed.\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -l &amp;lt;dotted ip address&amp;gt; */&lt;br /&gt;
 if(strcmp(argv[1],&amp;quot;-l&amp;quot;) == 0 ) {&lt;br /&gt;
   printf(&amp;quot;Listing hostid for ip. (no changes)\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** -s */&lt;br /&gt;
 if(strcmp(argv[1],&amp;quot;-s&amp;quot;) == 0 ) {&lt;br /&gt;
   /* see if /etc/hostid exists and print info */&lt;br /&gt;
   if( access(&amp;quot;/etc/hostid&amp;quot;, F_OK) != 0 ) {&lt;br /&gt;
     printf(&amp;quot;Notice: /etc/hostid does not exist.\n&amp;quot;);&lt;br /&gt;
     perror(&amp;quot;Reason&amp;quot;);&lt;br /&gt;
     printf(&amp;quot;System hostid derived from ip of hostname found in hosts file or dns.\n&amp;quot;);&lt;br /&gt;
   } else {&lt;br /&gt;
     printf(&amp;quot;Notice: /etc/hostid exists.\n&amp;quot;&lt;br /&gt;
            &amp;quot;System hostid is obtained from hostid file.\n&amp;quot;);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
  errno=0;&lt;br /&gt;
  newhostid = gethostid();&lt;br /&gt;
  if(errno!=0) { perror(&amp;quot;gethostid&amp;quot;); return EX_UNAVAILABLE; }&lt;br /&gt;
&lt;br /&gt;
  /* hostid is a byte-swapped ip like b.a.d.c */&lt;br /&gt;
  /* get ip by swapping to correct order a.b.c.d and save into in_addr struct */&lt;br /&gt;
  addr.s_addr = htonl(swapbytes(newhostid));&lt;br /&gt;
&lt;br /&gt;
  printf(&amp;quot;Listing current system hostid. (no changes)\n&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 /*********** print info and return */&lt;br /&gt;
 printf(&amp;quot;ip dot: %s\n&amp;quot;, inet_ntoa(addr) );&lt;br /&gt;
 printf(&amp;quot;ip hex: %.8x\n&amp;quot;, ntohl(addr.s_addr) );&lt;br /&gt;
 printf(&amp;quot;hostid: %.8x\n&amp;quot;, newhostid );&lt;br /&gt;
 return EX_OK;&lt;br /&gt;
}&lt;br /&gt;
################################################&lt;/div&gt;</description>
			<pubDate>Sat, 18 Aug 2012 09:27:49 GMT</pubDate>
			<dc:creator>Foobarz</dc:creator>
			<comments>https://www.slackwiki.com/Talk:ZFS_root</comments>
		</item>
</channel></rss>