|
|
|
#!/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.sh
|
|
|
|
|
|
|
|
PATH=$PATH:/sbin:/usr/sbin
|
|
|
|
|
|
|
|
# Huh? Empty $1?
|
|
|
|
[ -z "$1" ] && exit 1
|
|
|
|
|
|
|
|
# Huh? Empty $2?
|
|
|
|
[ -z "$2" ] && exit 1
|
|
|
|
|
|
|
|
# Huh? Empty $3?
|
|
|
|
[ -z "$3" ] && exit 1
|
|
|
|
|
|
|
|
# root is in the form root=nfs[4]:[server:]path[:options], either from
|
|
|
|
# cmdline or dhcp root-path
|
|
|
|
netif="$1"
|
|
|
|
root="$2"
|
|
|
|
NEWROOT="$3"
|
|
|
|
|
|
|
|
# Continue if nfs prefix
|
|
|
|
case "${root%%:*}" in
|
|
|
|
nfs|nfs4);;
|
|
|
|
*) return;;
|
|
|
|
esac
|
|
|
|
|
|
|
|
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" only in nfsroot.txt legacy mode
|
|
|
|
[ -z "$path" ] && [ "$(getarg root=)" = "/dev/nfs" ] && 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 "$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 [ "${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
|
|
|
|
path=${path%%%s*}$node${path#*%s}
|
|
|
|
fi
|
|
|
|
|
|
|
|
# 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
|
|
|
|
|
|
|
|
# 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 [ "$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
|
|
|
|
[ -z "$(pidof rpc.statd)" ] && rpc.statd
|
|
|
|
|
|
|
|
# XXX really needed? Do we need non-root users before we start it in
|
|
|
|
# XXX the real root image?
|
|
|
|
if nfsdomain=$(getarg rd_NFS_DOMAIN); then
|
|
|
|
[ -z "$(pidof rpc.idmapd)" ] && rpc.idmapd -d $nfsdomain
|
|
|
|
else
|
|
|
|
[ -z "$(pidof rpc.idmapd)" ] && rpc.idmapd
|
|
|
|
fi
|
|
|
|
|
|
|
|
# XXX Should we loop here?
|
|
|
|
mount -t nfs4 -o$options${nfslock+,$nfslock} \
|
|
|
|
$server:$path $NEWROOT \
|
|
|
|
&& { [ -e /dev/root ] || >/dev/root ; }
|
|
|
|
else
|
|
|
|
# NFSv{2,3} doesn't support using locks as it requires a helper to transfer
|
|
|
|
# the rpcbind state to the new root
|
|
|
|
[ "$nfslock" = "lock" ] && \
|
|
|
|
warn "Locks unsupported on NFSv{2,3}, using nolock" 1>&2
|
|
|
|
|
|
|
|
# XXX Should we loop here?
|
|
|
|
{ mount -t nfs -o$options${options:+,}nolock,nfsvers=3 $server:$path $NEWROOT || \
|
|
|
|
mount -t nfs -o$options${options:+,}nolock,nfsvers=2 $server:$path $NEWROOT ; } \
|
|
|
|
&& { [ -e /dev/root ] || >/dev/root ; }
|
|
|
|
fi
|
|
|
|
|
|
|
|
# inject new exit_if_exists
|
|
|
|
echo 'settle_exit_if_exists="--exit-if-exists=/dev/root"; rm "$job"' > /initqueue/nfs.sh
|
|
|
|
# force udevsettle to break
|
|
|
|
> /initqueue/work
|
|
|
|
|
|
|
|
|