[Virtio-fs] HOWTO: direct kernel 'root=virtiofs:myfs' boot on 'vanilla' Fedora/RHEL/Centos releases.

Harry G. Coin hgcoin at gmail.com
Sun Oct 11 22:14:13 UTC 2020


To allow direct kernel booting on a non-customized or 'vanilla distro'
Fedora / RHEL /Centos system, some extensions to dracut are required. 
They are below.

Kindly consider editing the following information and replacing the
instructions for the 'direct kernel booting' advice on the virtio-fs web
page.

These steps allow the only 'kernel args' necessary to be in the same
pattern used for other root file systems.  For example,
"root=virtiofs:myfs".

These steps worked for me, feel free to incorporate them as you like.

1) Use other guides/resources to create a fedora file system tree in a
sub-directory on the host.  This was written using Fedora 33 beta.  I
mention a couple options at the end of this email.

2) Use virtio-fs existing guides/resources to set up a virtual machine
with the shared memory and other file system xml for virtiofs, with
virtiofs changes set to point to the above mentioned tree.  Do not start
the virtual machine.

3) Then, on the host:

FIRST:

cd fedora_root_on_host_system
mount --bind /proc proc
mount --bind /sys sys
mount --bind /dev dev
mount --bind /dev/pts dev/pts
mount --bind /run run
chroot .
#(later, after the all work below, exit, then umount run, dev/pts, dev,
sys, proc..)
#Do the following within the chroot
dnf upgrade  
#debug/repeat until that runs without error, so you are confident of a
minimal working setup.
#then these changes:

#A)  Changes to allow user and root logins to succeed.  In the
alternative you can set /etc/selinux/config to permissive.

cat > /root/virtiofs_kernel_boot.te << EOF

module virtiofs_kernel_boot 1.0;

require {
    type unconfined_t;
    type unlabeled_t;
    type kernel_t;
    type rpm_script_t;
    class process transition;
    class file entrypoint;
}

#============= kernel_t ==============
allow kernel_t unconfined_t:process transition;

#============= rpm_script_t ==============
allow rpm_script_t unlabeled_t:file entrypoint;

#============= unconfined_t ==============
allow unconfined_t unlabeled_t:file entrypoint;

EOF

#then
cd /root
checkmodule -M -m -o virtiofs_kernel_boot.mod virtiofs_kernel_boot.te
#then
semodule_package -o virtiofs_kernel_boot.pp -m virtiofs_kernel_boot.mod
#then
semodule -i virtiofs_kernel_boot.pp

#B) Next step, amend dracut (Patterned after 9p examples):

cat > /etc/dracut.conf.d/addvirtiofs.conf  <<EOF
add_dracutmodules+=" virtiofs "
filesystems+=" virtiofs "

EOF

#When the below becomes standard in dracut, the above should

#be the only necessary change per instance. I hope some version of

#the three files below become standard in dracut releases.

cat > /usr/lib/dracut/modules.d/95virtiofs/module-setup.sh  <<EOF

#!/usr/bin/bash

# called by dracut
check() {
   [[ $hostonly ]] || [[ $mount_needs ]] && {
       for fs in "${host_fs_types[@]}"; do
           [[ "$fs" == "virtiofs" ]] && return 0
       done
       return 255
   }

   is_qemu_virtualized && return 0

   return 255
}

# called by dracut
depends() {
   return 0
}

# called by dracut
installkernel() {
   instmods virtiofs
}

# called by dracut
install() {
   inst_hook cmdline 95 "$moddir/parse-virtiofs.sh"
   inst_hook pre-mount 99 "$moddir/mount-virtiofs.sh"
}

EOF

cat > /usr/lib/dracut/modules.d/95virtiofs/parse-virtiofs.sh   <<EOF
#!/usr/bin/sh

if [ "${root%%:*}" = "virtiofs" ] ; then
   modprobe virtiofs

   rootok=1
fi

EOF

cat > /usr/lib/dracut/modules.d/95virtiofs/mount-virtiofs.sh  <<EOF
#!/usr/bin/sh

type getarg >/dev/null 2>&1 || . /lib/dracut-lib.sh

filter_rootopts() {
   rootopts=$1
   # strip ro and rw options
   local OLDIFS="$IFS"
   IFS=,
   set -- $rootopts
   IFS="$OLDIFS"
   local v
   while [ $# -gt 0 ]; do
       case $1 in
           rw|ro);;
           defaults);;
           *)
               v="$v,${1}";;
       esac
       shift
   done
   rootopts=${v#,}
   echo $rootopts
}

mount_root() {
   local _ret

   rootfs="virtiofs"
   rflags="rw"

   modprobe virtiofs

   mount -t ${rootfs} -o "$rflags",ro "${root#virtiofs:}" "$NEWROOT"

   rootopts=
   if getargbool 1 rd.fstab -n rd_NO_FSTAB \
       && ! getarg rootflags \
       && [ -f "$NEWROOT/etc/fstab" ] \
       && ! [ -L "$NEWROOT/etc/fstab" ]; then
       # if $NEWROOT/etc/fstab contains special mount options for
       # the root filesystem,
       # remount it with the proper options
       rootopts="defaults"
       while read dev mp fs opts rest || [ -n "$dev" ]; do
           # skip comments
           [ "${dev%%#*}" != "$dev" ] && continue

           if [ "$mp" = "/" ]; then
               rootopts=$opts
               break
           fi
       done < "$NEWROOT/etc/fstab"

       rootopts=$(filter_rootopts $rootopts)
   fi

   # we want rootflags (rflags) to take precedence so prepend rootopts to
   # them; rflags is guaranteed to not be empty
   rflags="${rootopts:+${rootopts},}${rflags}"

   umount "$NEWROOT"

   info "Remounting ${root#virtiofs:} with -o ${rflags}"
   mount -t ${rootfs} -o "$rflags" "${root#virtiofs:}" "$NEWROOT" 2>&1 |
vinfo

   [ -f "$NEWROOT"/forcefsck ] && rm -f -- "$NEWROOT"/forcefsck 2>/dev/null
   [ -f "$NEWROOT"/.autofsck ] && rm -f -- "$NEWROOT"/.autofsck 2>/dev/null
}

if [ -n "$root" -a -z "${root%%virtiofs:*}" ]; then
   mount_root
fi
:
EOF


#Look in /boot in the image, find the file like
vmlinuz-5.8.14-300.fc33.x86_64
#Let X be everything after vmlinuz- so in this case 5.8.14-300.fc33.x86_64
#Give the command
#dracut --force --kver X
#or in this case
dracut --force --kver 5.8.14-300.fc33.x86_64

#That should complete without error.
exit
#Don't forget to unmount dev dev/pts proc sys run

In your libvirt setup, Enable 'direct kernel boot'.
On my host, the vm root image is in /vmsystems/fedora_generic,
So change the following to fit your case.

Change the kernel path to the then current variation on:

/vmsystems/fedora_generic/boot/vmlinuz-5.8.14-300.fc33.x86_64

Change the Initrd path to the then current variation on:

/vmsystems/fedora_generic/boot/initramfs-5.8.14-300.fc33.x86_64.img

Change the kernel args to be only, or at least to include:

root=virtiofs:myfs

Where 'myfs' matches the 'target dir' setting in the libvirt xml:
<filesystem type="mount" accessmode="passthrough">
  <driver type="virtiofs" queue="1024"/>
...
  <target dir="myfs"/>
...

And.... That's it.

You should be able to boot a standard fedora/rhel/centos distro that
uses yum/dnf/dracut  directly from the underlying file system.  My
Fedora 33 beta boots reliably with exactly the setup above using a
direct kernel boot.    The underlying file system on the host is
btrfs.... and this setup is a complete rocket compared to a .qcow2 or
raw underlying image.  I think the reason for the speed is all the guest
VM's rely on just and only the host file system to manage the block
devices underneath, so you get all the benefits of the caching, the seek
optimizations, etc.   And it's 'really nice' to be able to sync or shut
down the vm, take a snapshot on the host (which is 'free' in terms of
extra space used) then be able to roll back, etc.

To get the initial file system tree I did a default 'iso' install to a
vm, then mounted the qcow2 file on the host, mounted the partitions in a
tree in tmp, then did an rsync -a to the host systems 'fedora_generic'
tree.  There are variations on

dnf -y --releasever=33 --installroot=/vmsystems/fedora_generic install
fedora-release systemd passwd rootfiles sudo dracut dracut-network
nfs-utils vim-minimal dnf
detailed at
https://fedoramagazine.org/how-to-build-a-netboot-server-part-1/ for a
more 'hands on' methods

In the 'would be nice' category:   I wish in the guest filesystem tree
there was a link named 'vmlinuz' and 'initrd.img' that pointed to the
latest installed kernel, so I wouldn't have to update where the host
looks for the boot info in the guest.

In the 'questions I have' department, I'd like the virtio-fs folks to
determine what the default flags should be for the generic kernel,
specifically whether there is a test for whether dax is available and to
use it by default if it is, etc.

Perhaps others might suggest tweaking the above files then asking dracut
maintainers to include the /usr/lib/dracut... items as standard .

Best to all

Harry Coin

Bettendorf, Iowa









More information about the Virtio-fs mailing list