# We should go last, and default the root if needed
if [ -z "$root" -a -z "$netroot" ]; then
+ rootok=1
+ root=dhcp
netroot=dhcp
fi
if [ "$root" = "dhcp" -a -z "$netroot" ]; then
rootok=1
netroot=dhcp
- unset root
fi
-# Cleanup any coversions from root->netroot if they are the same
-if [ "$netroot" = "$root" ]; then
- unset root
+if [ "$netroot" = "dhcp" -a -z "$root" ]; then
+ rootok=1
+ root=dhcp
+fi
+
+if [ -n "$NEEDDHCP" ] ; then
+ rootok=1
+ root=dhcp
+ #Don't overwrite netroot here, as it might contain something useful
fi
netif=$1
-[ -e /tmp/dhclient.$netif.dhcpopts ] && . /tmp/dhclient.$netif.dhcpopts
+# Figure out the handler for root=dhcp by recalling all netroot cmdline
+# handlers
+if [ "$netroot" = "dhcp" ] ; then
+ # Unset root so we can check later
+ unset root
-# Now, let the installed network root handlers figure this out
-#
-source_all netroot
+ # Load dhcp options
+ [ -e /tmp/dhclient.$netif.dhcpopts ] && . /tmp/dhclient.$netif.dhcpopts
-# If we didn't get a handler set, then we're done
-#
-if [ -z "$handler" ]; then
- # XXX informative error message?
- exit 0
+ # Set netroot to new_root_path, so cmdline parsers don't call
+ netroot=$new_root_path
+
+ for f in ./cmdline/90*.sh; do
+ [ -f "$f" ] && . "$f";
+ done
+else
+ rootok="1"
fi
+# Check: do we really know how to handle (net)root?
+[ -z "$root" ] && die "No or empty root= argument"
+[ -z "$rootok" ] && die "Don't know how to handle 'root=$root'"
+
+handler=${netroot%%:*}
+handler=${handler%%4}
+handler="/sbin/${handler}root"
+if [ -z "$netroot" ] || [ ! -e "$handler" ] ; then
+ die "No handler for netroot type '$netroot'"
+fi
+
+# Source netroot hooks before we start the handler
+source_all netroot
+
# Run the handler; don't store the root, it may change from device to device
# XXX other variables to export?
if $handler $netif $netroot $NEWROOT; then
inst hostname
inst iscsi-iname
inst_hook cmdline 90 "$moddir/parse-iscsiroot.sh"
-inst_hook netroot 90 "$moddir/iscsi-netroot.sh"
inst "$moddir/iscsiroot" "/sbin/iscsiroot"
instmods iscsi_tcp crc32c
+++ /dev/null
-if [ "$root" = "dhcp" ]; then
- if [ -n "$new_root_path" -a -z "${new_root_path%%iscsi:*}" ]; then
- root="$new_root_path"
- fi
-fi
-
-if [ -z "${root%iscsi:*}" ]; then
- handler=/sbin/iscsiroot
-fi
-
-if getarg iscsiroot >/dev/null; then
- handler=/sbin/iscsiroot
-fi
PATH=$PATH:/sbin:/usr/sbin
-# XXX needs error handling like ifup/dhclient-script
-
if getarg rdnetdebug; then
exec > /tmp/iscsiroot.$1.$$.out
exec 2>> /tmp/iscsiroot.$1.$$.out
[ -f ${conf} ] && . ${conf}
done
-modprobe iscsi_tcp
+# If it's not iscsi we don't continue
+[ "${root%%:*}" = "iscsi" ] || exit 1
+
+# XXX modprobe crc32c should go in the cmdline parser, but I haven't yet
+# figured out a way how to check whether this is built-in or not
modprobe crc32c
if getarg iscsi_firmware ; then
-# XXX actually we could, if we move to root=XXX and netroot=XXX, then
-# you could do root=LABEL=/ iscsiroot=XXX, or netroot=iscsi:XXX
-#
+#!/bin/sh
#
# Preferred format:
-# root=iscsi:[<servername>]:[<protocol>]:[<port>]:[<LUN>]:<targetname>
+# root=iscsi:[<servername>]:[<protocol>]:[<port>]:[<LUN>]:<targetname>
+# [root=*] netroot=iscsi:[<servername>]:[<protocol>]:[<port>]:[<LUN>]:<targetname>
#
# Legacy formats:
-# iscsiroot=[<servername>]:[<protocol>]:[<port>]:[<LUN>]:<targetname>
-# root=dhcp iscsiroot=[<servername>]:[<protocol>]:[<port>]:[<LUN>]:<targetname>
-# root=iscsi iscsiroot=[<servername>]:[<protocol>]:[<port>]:[<LUN>]:<targetname>
-# root=??? iscsi_initiator= iscsi_target_name= iscsi_target_ip= iscsi_target_port= iscsi_target_group= iscsi_username= iscsi_password= iscsi_in_username= iscsi_in_password=
-# root=??? iscsi_firmware
-
-case "$root" in
- iscsi|dhcp|'')
- if getarg iscsiroot= > /dev/null; then
- root=iscsi:$(getarg iscsiroot=)
- fi
- ;;
-esac
-
-if [ "${root%%:*}" = "iscsi" ]; then
- # XXX validate options here?
- # XXX generate udev rules?
- rootok=1
- netroot=iscsi
+# [net]root=[iscsi] iscsiroot=[<servername>]:[<protocol>]:[<port>]:[<LUN>]:<targetname>
+# [net]root=[iscsi] iscsi_firmware
+#
+# root= takes precedence over netroot= if root=iscsi[...]
+#
+
+# Don't continue if root is ok
+[ -n "$rootok" ] && return
+
+# This script is sourced, so root should be set. But let's be paranoid
+[ -z "$root" ] && root=$(getarg root=)
+[ -z "$netroot" ] && netroot=$(getarg netroot=)
+[ -z "$iscsiroot" ] && iscsiroot=$(getarg iscsiroot=)
+[ -z "$iscsi_firmware" ] && getarg iscsi_firmware && iscsi_firmware="1"
+
+[ -n "$iscsiroot" ] && [ -n "$iscsi_firmware" ] && die "Mixing iscsiroot and iscsi_firmware is dangerous"
+
+# Root takes precedence over netroot
+if [ "${root%%:*}" = "iscsi" ] ; then
+ if [ -n "$netroot" ] ; then
+ echo "Warning: root takes precedence over netroot. Ignoring netroot"
+
+ fi
+ netroot=$root
+fi
+
+# If it's not empty or iscsi we don't continue
+[ -z "$netroot" ] || [ "${netroot%%:*}" = "iscsi" ] || return
+
+if [ -n "$iscsiroot" ] ; then
+ [ -z "$netroot" ] && netroot=$root
+
+ # @deprecated
+ echo "Warning: Argument isciroot is deprecated and might be removed in a future"
+ echo "release. See http://apps.sourceforge.net/trac/dracut/wiki/commandline for"
+ echo "more information."
+
+ # Accept iscsiroot argument?
+ [ -z "$netroot" ] || [ "$netroot" = "iscsi" ] || \
+ die "Argument iscsiroot only accepted for empty root= or [net]root=iscsi"
+
+ # Override root with iscsiroot content?
+ [ -z "$netroot" ] || [ "$netroot" = "iscsi" ] && netroot=iscsi:$iscsiroot
+fi
+
+# iscsi_firmware does not need argument checking
+if [ -n "$iscsi_firmware" ] ; then
+ netroot=${netroot:-iscsi}
fi
-if getarg iscsiroot; then
- netroot=iscsi
+# If it's not iscsi we don't continue
+[ "${netroot%%:*}" = "iscsi" ] || return
+
+# Check required arguments. there's only one, but it's at the end
+if [ -z "$iscsi_firmware" ] ; then
+ case "${netroot##iscsi:*:*:*:*:}" in
+ $netroot|'') die "Argument targetname for iscsiroot is missing";;
+ esac
fi
+
+# ISCSI actually supported?
+[ -e /sys/devices/virtual/iscsi_transport ] || modprobe iscsi_tcp || die "iscsiroot requested but kernel/initrd does not support iscsi"
+
+# Done, all good!
+rootok=1
+
+# Shut up init error check
+[ -z "$root" ] && root="iscsi"
inst nbd-client
inst_hook cmdline 90 "$moddir/parse-nbdroot.sh"
-inst_hook netroot 90 "$moddir/nbd-netroot.sh"
inst "$moddir/nbdroot" "/sbin/nbdroot"
instmods nbd
+++ /dev/null
-if [ "$netroot" = "dhcp" ]; then
- if [ -n "$new_root_path" -a -z "${new_root_path%%nbd:*}" ]; then
- netroot="$new_root_path"
- fi
-fi
-
-if [ -z "${netroot%nbd:*}" ]; then
- handler=/sbin/nbdroot
-fi
PATH=$PATH:/sbin:/usr/sbin
-# XXX needs error handling like ifup/dhclient-script
-
if getarg rdnetdebug; then
exec > /tmp/nbdroot.$1.$$.out
exec 2>> /tmp/nbdroot.$1.$$.out
# Huh? Empty $3?
[ -z "$3" ] && exit 1
-# root is in the form root=nbd:server:port:fstype:fsopts:nbdopts
+# root is in the form root=nbd:srv:port[:fstype[:rootflags[:nbdopts]]]
netif="$1"
root="$2"
NEWROOT="$3"
+# If it's not nbd we don't continue
+[ "${root%%:*}" = "nbd" ] || return
+
root=${root#nbd:}
nbdserver=${root%%:*}; root=${root#*:}
nbdport=${root%%:*}; root=${root#*:}
getarg rw && nbdrw=rw
fsopts=${fsopts+$fsopts,}${nbdrw}
-incol2 /proc/devices nbd || modprobe nbd || exit 1
-
# XXX better way to wait for the device to be made?
i=0
while [ ! -b /dev/nbd0 ]; do
-# It'd be nice if this could share rules with 99-block.sh, but since
-# the kernel side adds nbd{1..16} when the module is loaded -- before
-# they are associated with a server -- we cannot use the udev add rule
-# to find it
-#
-# XXX actually we could, if we move to root=XXX and netroot=XXX, then
-# you could do root=LABEL=/ nbdroot=XXX, or netroot=nbd:XXX
-#
-# However, we need to be 90-nbd.sh to catch root=/dev/nbd*
+#!/bin/sh
#
# Preferred format:
# root=nbd:srv:port[:fstype[:rootflags[:nbdopts]]]
+# [root=*] netroot=nbd:srv:port[:fstype[:rootflags[:nbdopts]]]
#
-# nbdopts is a comma seperated list of options to give to nbd-client
+# Legacy formats:
+# [net]root=[nbd] nbdroot=srv,port
+# [net]root=[nbd] nbdroot=srv:port[:fstype[:rootflags[:nbdopts]]]
#
+# nbdopts is a comma seperated list of options to give to nbd-client
#
-# Legacy formats:
-# nbdroot=srv,port
-# nbdroot=srv:port[:fstype[:rootflags[:nbdopts]]]
-# root=dhcp nbdroot=srv:port[:fstype[:rootflags[:nbdopts]]]
-# root=nbd nbdroot=srv:port[:fstype[:rootflags[:nbdopts]]]
+# root= takes precedence over netroot= if root=nbd[...]
#
-case "$root" in
- nbd|dhcp|'')
- if getarg nbdroot= > /dev/null; then
- root=nbd:$(getarg nbdroot=)
- fi
- ;;
-esac
-
-# Convert the Debian style to our syntax, but avoid matches on fs arguments
-case "$root" in
- nbd:*,*)
- if check_occurances "$root" ',' 1 && check_occurances "$root" ':' 1;
- then
- root=${root%,*}:${root#*,}
- fi
- ;;
-esac
-
-if [ -z "$netroot" -a -n "$root" -a -z "${root%%nbd:*}" ]; then
- netroot="$root"
- unset root
+# Sadly there's no easy way to split ':' separated lines into variables
+netroot_to_var() {
+ local v=${1}:
+ set --
+ while [ -n "$v" ]; do
+ set -- "$@" "${v%%:*}"
+ v=${v#*:}
+ done
+
+ unset server port
+ server=$2; port=$3;
+}
+
+# Don't continue if root is ok
+[ -n "$rootok" ] && return
+
+# This script is sourced, so root should be set. But let's be paranoid
+[ -z "$root" ] && root=$(getarg root=)
+[ -z "$netroot" ] && netroot=$(getarg netroot=)
+[ -z "$nbdroot" ] && nbdroot=$(getarg nbdroot=)
+
+# Root takes precedence over netroot
+if [ "${root%%:*}" = "nbd" ] ; then
+ if [ -n "$netroot" ] ; then
+ warn "root takes precedence over netroot. Ignoring netroot"
+
+ fi
+ netroot=$root
fi
-if [ "${netroot%%:*}" = "nbd" ]; then
- # XXX validate options here?
- # XXX generate udev rules?
- rootok=1
+# If it's not empty or nbd we don't continue
+[ -z "$netroot" ] || [ "${netroot%%:*}" = "nbd" ] || return
+
+if [ -n "$nbdroot" ] ; then
+ [ -z "$netroot" ] && netroot=$root
+
+ # Debian legacy style contains no ':' Converting is easy
+ [ "$nbdroot" = "${nbdroot##*:}" ] && nbdroot=${nbdroot%,*}:${nbdroot#*,}
+
+ # @deprecated
+ warn "Argument nbdroot is deprecated and might be removed in a future release. See http://apps.sourceforge.net/trac/dracut/wiki/commandline for more information."
+
+ # Accept nbdroot argument?
+ [ -z "$netroot" ] || [ "$netroot" = "nbd" ] || \
+ die "Argument nbdroot only accepted for empty root= or [net]root=nbd"
+
+ # Override netroot with nbdroot content?
+ [ -z "$netroot" ] || [ "$netroot" = "nbd" ] && netroot=nbd:$nbdroot
fi
+
+# If it's not nbd we don't continue
+[ "${netroot%%:*}" = "nbd" ] || return
+
+# Check required arguments
+netroot_to_var $netroot
+[ -z "$server" ] && die "Argument server for nbdroot is missing"
+[ -z "$port" ] && die "Argument port for nbdroot is missing"
+
+# NBD actually supported?
+incol2 /proc/devices nbd || modprobe nbd || die "nbdroot requested but kernel/initrd does not support nbd"
+
+# Done, all good!
+rootok=1
+
+# Shut up init error check
+[ -z "$root" ] && root="nbd"
instmods nfs sunrpc ipv6
inst_hook cmdline 90 "$moddir/parse-nfsroot.sh"
-inst_hook netroot 90 "$moddir/nfs-netroot.sh"
inst_hook pre-pivot 70 "$moddir/nfsroot-cleanup.sh"
inst "$moddir/nfsroot" "/sbin/nfsroot"
mkdir -p "$initdir/var/lib/nfs/rpc_pipefs"
+++ /dev/null
-# If we're auto-detecting our root type from DHCP, see if this looks like
-# an NFS root option. As the variety of root-path formats is large, validate
-# that the number of colons match what we expect, and our glob didn't
-# inadvertently match a different handler's.
-#
-if [ "$netroot" = "dhcp" -o "$netroot" = "nfs" -o "$netroot" = "nfs4" ]; then
- nfsver=nfs
- if [ "$netroot" = "nfs4" ]; then
- nfsver=nfs4
- fi
- case "$new_root_path" in
- nfs:*|nfs4:*) netroot="$new_root_path" ;;
- *:/*:*)
- if check_occurances "$new_root_path" ':' 2; then
- netroot="$nfsver:$new_root_path"
- fi ;;
- *:/*,*)
- if check_occurances "$new_root_path" ':' 1; then
- netroot="$nfsver:$new_root_path"
- fi ;;
- *:/*)
- if check_occurances "$new_root_path" ':' 1; then
- netroot="$nfsver:$new_root_path:"
- fi ;;
- /*:*)
- if check_occurances "$new_root_path" ':' 1; then
- netroot="$nfsver::$new_root_path"
- fi ;;
- /*,*)
- if check_occurances "$new_root_path" ':' 0; then
- netroot="$nfsver::$new_root_path"
- fi ;;
- /*)
- if check_occurances "$new_root_path" ':' 0; then
- netroot="$nfsver::$new_root_path:"
- fi ;;
- '') netroot="$nfsver:::" ;;
- esac
-fi
-
-if [ -z "${netroot%%nfs:*}" -o -z "${netroot%%nfs4:*}" ]; then
- # Fill in missing information from DHCP
- nfsver=${netroot%%:*}; netroot=${netroot#*:}
- nfsserver=${netroot%%:*}; netroot=${netroot#*:}
- nfspath=${netroot%%:*}
- nfsflags=${netroot#*:}
-
- # XXX where does dhclient stash the next-server option? Do we care?
- if [ -z "$nfsserver" -o "$nfsserver" = "$nfspath" ]; then
- nfsserver=$new_dhcp_server_identifier
- fi
-
- # Handle alternate syntax of path,options
- if [ "$nfsflags" = "$nfspath" -a "${netroot#*,}" != "$netroot" ]; then
- nfspath=${netroot%%,*}
- nfsflags=${netroot#*,}
- fi
-
- # Catch the case when no additional flags are set
- if [ "$nfspath" = "$nfsflags" ]; then
- unset nfsflags
- fi
-
- # XXX validate we have all the required info?
- netroot="$nfsver:$nfsserver:$nfspath:$nfsflags"
- handler=/sbin/nfsroot
-fi
#!/bin/sh
+# Copy from parse-nfsroot.sh
+root_to_var() {
+ local v=${1}:
+ set --
+ while [ -n "$v" ]; do
+ set -- "$@" "${v%%:*}"
+ v=${v#*:}
+ done
+
+ unset nfs server path options
+
+ # Ugly: Can't -z test $path after the case, since it might be allowed
+ # to be empty for root=nfs
+ nfs=$1
+ case $# in
+ 0|1);;
+ 2) path=$2;;
+ 3)
+ # This is ultra ugly. But we can't decide in which position path
+ # sits without checking if the string starts with '/'
+ case $2 in
+ /*) path=$2; options=$3;;
+ *) server=$2; path=$3;;
+ esac
+ ;;
+ *) server=$2; path=$3; options=$4;
+ esac
+
+ # Does it really start with '/'?
+ [ -n "${path%%/*}" ] && path="error";
+
+ #Fix kernel legacy style separating path and options with ','
+ if [ "$path" != "${path#*,}" ] ; then
+ options=${path#*,}
+ path=${path%%,*}
+ fi
+}
+
. /lib/dracut-lib
PATH=$PATH:/sbin:/usr/sbin
-# XXX needs error handling like ifup/dhclient-script
-
if getarg rdnetdebug ; then
exec > /tmp/nfsroot.$1.$$.out
exec 2>> /tmp/nfsroot.$1.$$.out
# Huh? Empty $3?
[ -z "$3" ] && exit 1
-# root is in the form root=nfs[4]:server:path:[options]
+# root is in the form root=nfs[4]:[server:]path[:options], either from
+# cmdline or dhcp root-path
netif="$1"
root="$2"
NEWROOT="$3"
-nfsver=${root%%:*}; root=${root#*:}
-nfsserver=${root%%:*}; root=${root#*:}
-nfspath=${root%%:*}
-flags=${root#*:}
+# If it's not nfs we don't continue
+case "${root%%:*}" in
+ nfs|nfs4);;
+ *) return;;
+esac
+
+# Ugly: root=nfs[4] requires dhcp root-path
+if [ "$root" = "nfs" ] || [ "$root" = "nfs4" ] ; then
+ # No need to check if the file exists. ip cmdline parser takes care of this
+ . /tmp/dhclient.$netif.dhcpopts
+ [ -z "$new_root_path" ] && die "Required dhcp option root-path not available"
+ root=$root:$new_root_path
+fi
+
+root_to_var $root
+
+#Load other data that might provide info
+[ -f /tmp/net.$netif.override ] && . /tmp/net.$netif.override
+[ -f /tmp/dhclient.$netif.dhcpopts ] && . /tmp/dhclient.$netif.dhcpopts
+
+#Empty path means try dhcp root-path, this is ok here since parse-nfsroot.sh
+#already takes care of nfs:... formatted root-path
+[ -z "$path" ] && root_to_var $nfs:$new_root_path
+
+#Empty path defaults to "/tftpboot/%s"
+[ -z "$path" ] && path="/tftpboot/%s"
+
+if [ -z "$server" ] ; then
+ # XXX new_dhcp_next_server is unconfirmed this is an assumption
+ for var in $srv $new_dhcp_server_identifier $new_dhcp_next_server $new_root_path '' ; do
+ [ -n "$var" ] && server=$var && break;
+ done
+
+ # XXX This blindly assumes that if new_root_path has to used that
+ # XXX it really can be used as server
+ server=${server%%:*}
+fi
-[ -z "$nfspath" ] && nfspath=/tftpboot/%s
+[ -z "$server" ] && die "Required parameter 'server' is missing"
# Kernel replaces first %s with host name, and falls back to the ip address
# if it isn't set. Only the first %s is substituted.
-#
-if [ "${nfspath#*%s}" != "$nfspath" ]; then
+if [ "${path#*%s}" != "$path" ]; then
ip=$(ip -o -f inet addr show $netif)
ip=${ip%%/*}
ip=${ip##* }
read node < /proc/sys/kernel/hostname
[ "$node" = "(none)" ] && node=$ip
- nfspath=${nfspath%%%s*}$node${nfspath#*%s}
+ path=${path%%%s*}$node${path#*%s}
fi
-# Look through the flags and see if any are overridden by the command line
-# Append a , so we know we terminate
-flags=${flags},
-while [ -n "$flags" ]; do
- f=${flags%%,*}
- flags=${flags#*,}
- if [ -z "$f" ]; then
- break
- fi
- if [ "$f" = "ro" -o "$f" = "rw" ]; then
- nfsrw=$f
- continue
- fi
- if [ "$f" = "lock" -o "$f" = "nolock" ]; then
- nfslock=$f
- continue
- fi
- nfsflags=${nfsflags+$nfsflags,}$f
+# Look through the options and remove rw/locking options
+OLDIFS=$IFS
+IFS=,
+for f in $options ; do
+ [ "$f" = "ro" -o "$f" = "rw" ] && nfsrw=$f && continue
+ [ "$f" = "lock" -o "$f" = "nolock" ] && nfslock=$f && continue
+ flags=${flags:+$flags,}$f
done
+IFS=$OLDIFS
+options=$flags
# Override rw/ro if set on cmdline
getarg ro && nfsrw=ro
getarg rw && nfsrw=rw
-nfsflags=${nfsflags+$nfsflags,}${nfsrw}
-# Load the modules so the filesystem type is there
-incol2 /proc/filesystems nfs || modprobe nfs || exit 1
-incol2 /proc/filesystems nfs4 || modprobe nfs || exit 1
+# Default to ro if unset
+[ -z "$nfsrw" ] && nfsrw=ro
+
+options=${options:+$options,}$nfsrw
# Start rpcbind or rpcbind
# FIXME occasionally saw 'rpcbind: fork failed: No such device' -- why?
[ -x /sbin/portmap ] && [ -z "$(pidof portmap)" ] && portmap
[ -x /sbin/rpcbind ] && [ -z "$(pidof rpcbind)" ] && rpcbind
-if [ "$nfsver" = "nfs4" ]; then
+if [ "$nfs" = "nfs4" ]; then
# Start rpc.statd as mount won't let us use locks on a NFSv4
# filesystem without talking to it. NFSv4 does locks internally,
# rpc.lockd isn't needed
# XXX really needed? Do we need non-root users before we start it in
# XXX the real root image?
- if [ -z "$(pidof rpc.idmapd)" ]; then
- rpc.idmapd
- fi
+ [ -z "$(pidof rpc.idmapd)" ] && rpc.idmapd
# XXX Should we loop here?
- exec mount -t nfs4 -o${nfsflags}${nfslock+,$nfslock} \
- $nfsserver:$nfspath $NEWROOT
+ exec mount -t nfs4 -o$options${nfslock+,$nfslock} \
+ $server:$path $NEWROOT
fi
# NFSv{2,3} doesn't support using locks as it requires a helper to transfer
# the rpcbind state to the new root
-[ -z "$nfslock" -o "$nfslock" = "lock" ] &&
- echo "Warning: Locks unsupported on NFSv{2,3}, using nolock" 1>&2
+[ "$nfslock" = "lock" ] && \
+ warn "Locks unsupported on NFSv{2,3}, using nolock" 1>&2
# XXX Should we loop here?
-exec mount -t nfs -onolock,$nfsflags $nfsserver:$nfspath $NEWROOT
+exec mount -t nfs -o$options${options:+,}nolock $server:$path $NEWROOT
-# We're 90-nfs.sh to catch root=/dev/nfs
+#!/bin/sh
#
# Preferred format:
# root=nfs[4]:[server:]path[:options]
-# netroot=nfs[4]:[server:]path[:options]
+# [root=*] netroot=nfs[4]:[server:]path[:options]
+#
+# Legacy formats:
+# [net]root=[[/dev/]nfs[4]] nfsroot=[server:]path[,options]
+# [net]root=[[/dev/]nfs[4]] nfsroot=[server:]path[:options]
+#
+# If the 'nfsroot' parameter is not given on the command line or is empty,
+# the dhcp root-path is used as [server:]path[:options] or the default
+# "/tftpboot/%s" will be used.
#
# If server is unspecified it will be pulled from one of the following
# sources, in order:
# static ip= option on kernel command line
# DHCP next-server option
# DHCP server-id option
+# DHCP root-path option
#
-# Legacy formats:
-# root=nfs[4]
-# root=/dev/nfs[4] nfsroot=[server:]path[,options]
+# NFSv4 is only used if explicitly requested; default is NFSv2 or NFSv3
+# depending on kernel configuration
#
-# Plain "root=nfs" interprets DHCP root-path option as [ip:]path[:options]
-#
-# NFSv4 is only used if explicitly listed; default is NFSv3
+# root= takes precedence over netroot= if root=nfs[...]
#
-case "$root" in
- nfs|dhcp|'')
- if getarg nfsroot= > /dev/null; then
- root=nfs:$(getarg nfsroot=)
- fi
- ;;
- nfs4)
- if getarg nfsroot= > /dev/null; then
- root=nfs4:$(getarg nfsroot=)
- fi
- ;;
- /dev/nfs|/dev/nfs4)
- if getarg nfsroot= > /dev/null; then
- root=${root#/dev/}:$(getarg nfsroot=)
- else
- root=${root#/dev/}
- fi
- ;;
+# Sadly there's no easy way to split ':' separated lines into variables
+netroot_to_var() {
+ local v=${1}:
+ set --
+ while [ -n "$v" ]; do
+ set -- "$@" "${v%%:*}"
+ v=${v#*:}
+ done
+
+ unset nfs server path options
+
+ nfs=$1
+ # Ugly: Can't -z test #path after the case, since it might be allowed
+ # to be empty for root=nfs
+ case $# in
+ 0|1);;
+ 2) path=${2:-error};;
+ 3)
+ # This is ultra ugly. But we can't decide in which position path
+ # sits without checking if the string starts with '/'
+ case $2 in
+ /*) path=$2; options=$3;;
+ *) server=$2; path=${3:-error};;
+ esac
+ ;;
+ *) server=$2; path=${3:-error}; options=$4;
+ esac
+
+ # Does it really start with '/'?
+ [ -n "${path%%/*}" ] && path="error";
+
+ #Fix kernel legacy style separating path and options with ','
+ if [ "$path" != "${path#*,}" ] ; then
+ options=${path#*,}
+ path=${path%%,*}
+ fi
+}
+
+#Don't continue if root is ok
+[ -n "$rootok" ] && return
+
+# This script is sourced, so root should be set. But let's be paranoid
+[ -z "$root" ] && root=$(getarg root=)
+[ -z "$netroot" ] && netroot=$(getarg netroot=)
+[ -z "$nfsroot" ] && nfsroot=$(getarg nfsroot=)
+
+# Root takes precedence over netroot
+case "${root%%:*}" in
+ nfs|nfs4|/dev/nfs|/dev/nfs4)
+ if [ -n "$netroot" ] ; then
+ warn "root takes precedence over netroot. Ignoring netroot"
+
+ fi
+ netroot=$root
+ ;;
+esac
+
+# If it's not empty or nfs we don't continue
+case "${netroot%%:*}" in
+ ''|nfs|nfs4|/dev/nfs|/dev/nfs4);;
+ *) return;;
esac
-if [ -z "$netroot" -a -n "$root" -a -z "${root%%nfs*}" ]; then
- netroot="$root"
- unset root
+if [ -n "$nfsroot" ] ; then
+ [ -z "$netroot" ] && netroot=$root
+
+ # @deprecated
+ warn "Argument nfsroot is deprecated and might be removed in a future release. See http://apps.sourceforge.net/trac/dracut/wiki/commandline for more information."
+
+ case "$netroot" in
+ ''|nfs|nfs4|/dev/nfs|/dev/nfs4) netroot=${netroot:-nfs}:$nfsroot;;
+ *) die "Argument nfsroot only accepted for empty root= or root=[/dev/]nfs[4]"
+ esac
fi
-case "$netroot" in
- nfs|nfs4|nfs:*|nfs4:*)
- rootok=1
- if [ -n "$root" -a "$netroot" != "$root" ]; then
- echo "WARNING: root= and netroot= do not match, ignoring root="
- fi
- unset root
- ;;
+# If it's not nfs we don't continue
+case "${netroot%%:*}" in
+ nfs|nfs4|/dev/nfs|/dev/nfs4);;
+ *) return;;
esac
+
+# Check required arguments
+netroot_to_var $netroot
+[ "$path" = "error" ] && die "Argument nfsroot must contain a valid path!"
+
+# Set fstype, might help somewhere
+fstype=${nfs#/dev/}
+
+# NFS actually supported? Some more uglyness here: nfs3 or nfs4 might not
+# be in the module...
+if ! incol2 /proc/filesystems $fstype ; then
+ modprobe nfs
+ incol2 /proc/filesystems $fstype || die "nfsroot type $fstype requested but kernel/initrd does not support nfs"
+fi
+
+# Rewrite root so we don't have to parse this uglyness later on again
+netroot="$fstype:$server:$path:$options"
+
+# If we don't have a server, we need dhcp
+if [ -z "$server" ] ; then
+ NEEDDHCP="1"
+fi;
+
+# Done, all good!
+rootok=1
+
+# Shut up init error check or make sure that block parser wont get
+# confused by having /dev/nfs[4]
+root="$fstype"
fi
$testdir/run-qemu -hda client.img -m 512M -nographic \
- -net nic,macaddr=$mac,model=e1000 \
- -net socket,mcast=230.0.0.1:1234 \
- -kernel /boot/vmlinuz-$KVERSION \
- -append "$cmdline $DEBUGFAIL ro quiet console=ttyS0,115200n81" \
- -initrd initramfs.testing
+ -net nic,macaddr=$mac,model=e1000 \
+ -net socket,mcast=230.0.0.1:1234 \
+ -kernel /boot/vmlinuz-$KVERSION \
+ -append "$cmdline $DEBUGFAIL ro quiet console=ttyS0,115200n81" \
+ -initrd initramfs.testing
if [[ $? -ne 0 ]] || ! grep -m 1 -q nfs-OK client.img; then
echo "CLIENT TEST END: $test_name [FAILED - BAD EXIT]"
# NFSv3: last octect starts at 0x00 and works up
# NFSv4: last octect starts at 0x80 and works up
+ # This test must fail: dhcp root-path must have proto:...
client_test "NFSv3 netroot=dhcp DHCP path only" 52:54:00:12:34:00 \
- "netroot=dhcp" 192.168.50.1 -wsize=4096 || return 1
+ "netroot=dhcp" 192.168.50.1 -wsize=4096 && return 1
+ # This test must fail: dhcp root-path must have proto:...
client_test "NFSv3 root=dhcp DHCP path only" 52:54:00:12:34:00 \
- "root=dhcp" 192.168.50.1 -wsize=4096 || return 1
+ "root=dhcp" 192.168.50.1 -wsize=4096 && return 1
client_test "NFSv3 root=nfs DHCP path only" 52:54:00:12:34:00 \
- "root=nfs" 192.168.50.1 -wsize=4096 || return 1
+ "root=nfs" 192.168.50.1 -wsize=4096 || return 1
client_test "NFSv3 root=/dev/nfs DHCP path only" 52:54:00:12:34:00 \
- "root=/dev/nfs" 192.168.50.1 -wsize=4096 || return 1
+ "root=/dev/nfs" 192.168.50.1 -wsize=4096 || return 1
+ # This test must fail: dhcp root-path must have proto:...
client_test "NFSv3 netroot=dhcp DHCP IP:path" 52:54:00:12:34:01 \
- "netroot=dhcp" 192.168.50.2 -wsize=4096 || return 1
+ "netroot=dhcp" 192.168.50.2 -wsize=4096 && return 1
+ # This test must fail: dhcp root-path must have proto:...
client_test "NFSv3 root=dhcp DHCP IP:path" 52:54:00:12:34:01 \
- "root=dhcp" 192.168.50.2 -wsize=4096 || return 1
+ "root=dhcp" 192.168.50.2 -wsize=4096 && return 1
client_test "NFSv3 root=nfs DHCP IP:path" 52:54:00:12:34:01 \
- "root=nfs" 192.168.50.2 -wsize=4096 || return 1
+ "root=nfs" 192.168.50.2 -wsize=4096 || return 1
client_test "NFSv3 root=/dev/nfs DHCP IP:path" 52:54:00:12:34:01 \
- "root=/dev/nfs" 192.168.50.2 -wsize=4096 || return 1
+ "root=/dev/nfs" 192.168.50.2 -wsize=4096 || return 1
client_test "NFSv3 root=dhcp DHCP proto:IP:path" 52:54:00:12:34:02 \
- "root=dhcp" 192.168.50.3 -wsize=4096 || return 1
+ "root=dhcp" 192.168.50.3 -wsize=4096 || return 1
client_test "NFSv3 netroot=dhcp DHCP proto:IP:path:options" \
- 52:54:00:12:34:03 "netroot=dhcp" 192.168.50.3 wsize=4096 || return 1
+ 52:54:00:12:34:03 "netroot=dhcp" 192.168.50.3 wsize=4096 || return 1
client_test "NFSv3 root=dhcp DHCP proto:IP:path:options" 52:54:00:12:34:03 \
- "root=dhcp" 192.168.50.3 wsize=4096 || return 1
+ "root=dhcp" 192.168.50.3 wsize=4096 || return 1
client_test "NFSv3 netroot=nfs:..." 52:54:00:12:34:04 \
- "netroot=nfs:192.168.50.1:/nfs/client" 192.168.50.1 \
- -wsize=4096 || return 1
+ "netroot=nfs:192.168.50.1:/nfs/client" 192.168.50.1 \
+ -wsize=4096 || return 1
client_test "NFSv3 root=nfs:..." 52:54:00:12:34:04 \
- "root=nfs:192.168.50.1:/nfs/client" 192.168.50.1 -wsize=4096 || return 1
+ "root=nfs:192.168.50.1:/nfs/client" 192.168.50.1 -wsize=4096 || return 1
client_test "NFSv3 nfsroot=/nfs/client" 52:54:00:12:34:04 \
"nfsroot=/nfs/client" 192.168.50.1 -wsize=4096 || return 1
client_test "NFSv3 nfsroot=192.168.50.2:/nfs/client" 52:54:00:12:34:04 \
"nfsroot=192.168.50.2:/nfs/client" 192.168.50.2 -wsize=4096 || return 1
+ # This test must fail: root=dhcp must ignore other arguments
client_test "NFSv3 root=dhcp nfsroot=/nfs/client" 52:54:00:12:34:04 \
- "root=dhcp nfsroot=/nfs/client" 192.168.50.1 -wsize=4096 || return 1
+ "root=dhcp nfsroot=/nfs/client" 192.168.50.1 -wsize=4096 && return 1
client_test "NFSv3 root=nfs nfsroot=/nfs/client" 52:54:00:12:34:04 \
"root=nfs nfsroot=/nfs/client" 192.168.50.1 -wsize=4096 || return 1
52:54:00:12:34:04 "root=nfs nfsroot=/nfs/client,wsize=4096" \
192.168.50.1 wsize=4096 || return 1
- client_test "NFSv3 root=nfs DHCP path,options" \
- 52:54:00:12:34:05 "root=dhcp" 192.168.50.1 wsize=4096 || return 1
+ # This test must fail: dhcp root-path must have proto:...
+ client_test "NFSv3 root=dhcp DHCP path,options" \
+ 52:54:00:12:34:05 "root=dhcp" 192.168.50.1 wsize=4096 && return 1
+ # This test must fail: dhcp root-path must have proto:...
client_test "NFSv3 root=dhcp DHCP IP:path,options" \
- 52:54:00:12:34:06 "root=dhcp" 192.168.50.2 wsize=4096 || return 1
+ 52:54:00:12:34:06 "root=dhcp" 192.168.50.2 wsize=4096 && return 1
client_test "NFSv3 root=dhcp DHCP proto:IP:path,options" \
52:54:00:12:34:07 "root=dhcp" 192.168.50.3 wsize=4096 || return 1
# switch_root
client_test "NFSv4 netroot=nfs4 DHCP path only" 52:54:00:12:34:80 \
- "netroot=nfs4" 192.168.50.1 -wsize=4096 || return 1
-
+ "netroot=nfs4" 192.168.50.1 -wsize=4096 || return 1
+
client_test "NFSv4 root=nfs4 DHCP path only" 52:54:00:12:34:80 \
- "root=nfs4" 192.168.50.1 -wsize=4096 || return 1
+ "root=nfs4" 192.168.50.1 -wsize=4096 || return 1
client_test "NFSv4 root=/dev/nfs4 DHCP path only" 52:54:00:12:34:80 \
- "root=/dev/nfs4" 192.168.50.1 -wsize=4096 || return 1
+ "root=/dev/nfs4" 192.168.50.1 -wsize=4096 || return 1
client_test "NFSv4 netroot=nfs4 DHCP IP:path" 52:54:00:12:34:81 \
- "netroot=nfs4" 192.168.50.2 -wsize=4096 || return 1
+ "netroot=nfs4" 192.168.50.2 -wsize=4096 || return 1
client_test "NFSv4 root=nfs4 DHCP IP:path" 52:54:00:12:34:81 \
- "root=nfs4" 192.168.50.2 -wsize=4096 || return 1
+ "root=nfs4" 192.168.50.2 -wsize=4096 || return 1
client_test "NFSv4 root=/dev/nfs4 DHCP IP:path" 52:54:00:12:34:81 \
- "root=/dev/nfs4" 192.168.50.2 -wsize=4096 || return 1
+ "root=/dev/nfs4" 192.168.50.2 -wsize=4096 || return 1
client_test "NFSv4 netroot=dhcp DHCP proto:IP:path" 52:54:00:12:34:82 \
- "netroot=dhcp" 192.168.50.3 -wsize=4096 || return 1
+ "netroot=dhcp" 192.168.50.3 -wsize=4096 || return 1
client_test "NFSv4 root=dhcp DHCP proto:IP:path" 52:54:00:12:34:82 \
- "root=dhcp" 192.168.50.3 -wsize=4096 || return 1
+ "root=dhcp" 192.168.50.3 -wsize=4096 || return 1
client_test "NFSv4 netroot=dhcp DHCP proto:IP:path:options" \
- 52:54:00:12:34:83 "netroot=dhcp" 192.168.50.3 wsize=4096 || return 1
+ 52:54:00:12:34:83 "netroot=dhcp" 192.168.50.3 wsize=4096 || return 1
client_test "NFSv4 root=dhcp DHCP proto:IP:path:options" 52:54:00:12:34:83 \
- "root=dhcp" 192.168.50.3 wsize=4096 || return 1
+ "root=dhcp" 192.168.50.3 wsize=4096 || return 1
client_test "NFSv4 netroot=nfs4:..." 52:54:00:12:34:84 \
"netroot=nfs4:192.168.50.1:/client" 192.168.50.1 \
# The default is ext3,errors=continue so use that to determine
# if our options were parsed and used
- client_test "NBD root=nbd:IP:port" 52:54:00:12:34:00 \
- "root=nbd:192.168.50.1:2000" || return 1
+ client_test "NBD root=nbd:IP:port" 52:54:00:12:34:00 \
+ "root=nbd:192.168.50.1:2000" || return 1
- client_test "NBD root=nbd:IP:port:fstype" 52:54:00:12:34:00 \
- "root=nbd:192.168.50.1:2000:ext2" ext2 || return 1
+ client_test "NBD root=nbd:IP:port:fstype" 52:54:00:12:34:00 \
+ "root=nbd:192.168.50.1:2000:ext2" ext2 || return 1
- client_test "NBD root=nbd:IP:port::fsopts" 52:54:00:12:34:00 \
- "root=nbd:192.168.50.1:2000::errors=panic" \
- ext3 errors=panic || return 1
+ client_test "NBD root=nbd:IP:port::fsopts" 52:54:00:12:34:00 \
+ "root=nbd:192.168.50.1:2000::errors=panic" \
+ ext3 errors=panic || return 1
- client_test "NBD root=nbd:IP:port:fstype:fsopts" 52:54:00:12:34:00 \
- "root=nbd:192.168.50.1:2000:ext2:errors=panic" \
- ext2 errors=panic || return 1
+ client_test "NBD root=nbd:IP:port:fstype:fsopts" 52:54:00:12:34:00 \
+ "root=nbd:192.168.50.1:2000:ext2:errors=panic" \
+ ext2 errors=panic || return 1
- # There doesn't seem to be a good way to validate the NBD options, so
- # just check that we don't screw up the other options
+ # There doesn't seem to be a good way to validate the NBD options, so
+ # just check that we don't screw up the other options
- client_test "NBD root=nbd:IP:port:::NBD opts" 52:54:00:12:34:00 \
- "root=nbd:192.168.50.1:2000:::bs=2048" || return 1
+ client_test "NBD root=nbd:IP:port:::NBD opts" 52:54:00:12:34:00 \
+ "root=nbd:192.168.50.1:2000:::bs=2048" || return 1
- client_test "NBD root=nbd:IP:port:fstype::NBD opts" 52:54:00:12:34:00 \
- "root=nbd:192.168.50.1:2000:ext2::bs=2048" ext2 || return 1
+ client_test "NBD root=nbd:IP:port:fstype::NBD opts" 52:54:00:12:34:00 \
+ "root=nbd:192.168.50.1:2000:ext2::bs=2048" ext2 || return 1
- client_test "NBD root=nbd:IP:port:fstype:fsopts:NBD opts" \
- 52:54:00:12:34:00 \
- "root=nbd:192.168.50.1:2000:ext2:errors=panic:bs=2048" \
- ext2 errors=panic || return 1
+ client_test "NBD root=nbd:IP:port:fstype:fsopts:NBD opts" \
+ 52:54:00:12:34:00 \
+ "root=nbd:192.168.50.1:2000:ext2:errors=panic:bs=2048" \
+ ext2 errors=panic || return 1
- # Check legacy parsing
+ # Check legacy parsing
- client_test "NBD root=nbd nbdroot=srv:port" 52:54:00:12:34:00 \
- "root=nbd nbdroot=192.168.50.1:2000" || return 1
+ client_test "NBD root=nbd nbdroot=srv:port" 52:54:00:12:34:00 \
+ "root=nbd nbdroot=192.168.50.1:2000" || return 1
- client_test "NBD root=dhcp nbdroot=srv:port" 52:54:00:12:34:00 \
- "root=dhcp nbdroot=192.168.50.1:2000" || return 1
+ # This test must fail: root=dhcp ignores nbdroot
+ client_test "NBD root=dhcp nbdroot=srv:port" 52:54:00:12:34:00 \
+ "root=dhcp nbdroot=192.168.50.1:2000" && return 1
- client_test "NBD root=nbd nbdroot=srv,port" 52:54:00:12:34:00 \
- "root=nbd nbdroot=192.168.50.1,2000" || return 1
+ client_test "NBD root=nbd nbdroot=srv,port" 52:54:00:12:34:00 \
+ "root=nbd nbdroot=192.168.50.1,2000" || return 1
- client_test "NBD root=dhcp nbdroot=srv,port" 52:54:00:12:34:00 \
- "root=dhcp nbdroot=192.168.50.1,2000" || return 1
+ # This test must fail: root=dhcp ignores nbdroot
+ client_test "NBD root=dhcp nbdroot=srv,port" 52:54:00:12:34:00 \
+ "root=dhcp nbdroot=192.168.50.1,2000" && return 1
# DHCP root-path parsing