You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
157 lines
4.6 KiB
157 lines
4.6 KiB
#!/bin/sh |
|
|
|
type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh |
|
. /lib/net-lib.sh |
|
|
|
# TODO: make these things not pollute the calling namespace |
|
|
|
# nfs_to_var NFSROOT [NETIF] |
|
# use NFSROOT to set $nfs, $server, $path, and $options. |
|
# NFSROOT is something like: nfs[4]:<server>:/<path>[:<options>|,<options>] |
|
# NETIF is used to get information from DHCP options, if needed. |
|
nfs_to_var() { |
|
# Unfortunately, there's multiple styles of nfs "URL" in use, so we need |
|
# extra functions to parse them into $nfs, $server, $path, and $options. |
|
# FIXME: local netif=${2:-$netif}? |
|
case "$1" in |
|
nfs://*) rfc2224_nfs_to_var "$1" ;; |
|
nfs:*[*) anaconda_nfsv6_to_var "$1" ;; |
|
nfs:*:*:/*) anaconda_nfs_to_var "$1" ;; |
|
*) nfsroot_to_var "$1" ;; |
|
esac |
|
# if anything's missing, try to fill it in from DHCP options |
|
if [ -z "$server" ] || [ -z "$path" ]; then nfsroot_from_dhcp "$2"; fi |
|
# if there's a "%s" in the path, replace it with the hostname/IP |
|
if strstr "$path" "%s"; then |
|
local node="" |
|
read -r node < /proc/sys/kernel/hostname |
|
[ "$node" = "(none)" ] && node=$(get_ip "$2") |
|
path=${path%%%s*}$node${path#*%s} # replace only the first %s |
|
fi |
|
} |
|
|
|
# root=nfs:[<server-ip>:]<root-dir>[:<nfs-options>] |
|
# root=nfs4:[<server-ip>:]<root-dir>[:<nfs-options>] |
|
nfsroot_to_var() { |
|
# strip nfs[4]: |
|
local arg="$*:" |
|
nfs="${arg%%:*}" |
|
arg="${arg##$nfs:}" |
|
|
|
# check if we have a server |
|
if strstr "$arg" ':/'; then |
|
server="${arg%%:/*}" |
|
arg="/${arg##*:/}" |
|
fi |
|
|
|
path="${arg%%:*}" |
|
|
|
# rest are options |
|
options="${arg##$path}" |
|
# strip leading ":" |
|
options="${options##:}" |
|
# strip ":" |
|
options="${options%%:}" |
|
|
|
# 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 |
|
} |
|
|
|
# RFC2224: nfs://<server>[:<port>]/<path> |
|
rfc2224_nfs_to_var() { |
|
nfs="nfs" |
|
server="${1#nfs://}" |
|
path="/${server#*/}" |
|
server="${server%%/*}" |
|
server="${server%%:}" # anaconda compat (nfs://<server>:/<path>) |
|
local port="${server##*:}" |
|
[ "$port" != "$server" ] && options="port=$port" |
|
} |
|
|
|
# Anaconda-style path with options: nfs:<options>:<server>:/<path> |
|
# (without mount options, anaconda is the same as dracut) |
|
anaconda_nfs_to_var() { |
|
nfs="nfs" |
|
options="${1#nfs:}" |
|
server="${options#*:}" |
|
server="${server%:/*}" |
|
options="${options%%:*}" |
|
path="/${1##*:/}" |
|
} |
|
|
|
# IPv6 nfs path will be treated separately |
|
anaconda_nfsv6_to_var() { |
|
nfs="nfs" |
|
path="$1" |
|
options="${path#*:/}" |
|
path="/${options%%:*}" |
|
server="${1#*nfs:}" |
|
if str_starts "$server" '['; then |
|
server="${server%:/*}" |
|
options="${options#*:*}" |
|
else |
|
server="${server%:/*}" |
|
options="${server%%:*}" |
|
server="${server#*:}" |
|
fi |
|
} |
|
|
|
# nfsroot_from_dhcp NETIF |
|
# fill in missing server/path from DHCP options. |
|
nfsroot_from_dhcp() { |
|
local f |
|
for f in /tmp/net.$1.override /tmp/dhclient.$1.dhcpopts; do |
|
# shellcheck disable=SC1090 |
|
[ -f "$f" ] && . "$f" |
|
done |
|
[ -n "$new_root_path" ] && nfsroot_to_var "$nfs:$new_root_path" |
|
[ -z "$path" ] && [ "$(getarg root=)" = "/dev/nfs" ] && path=/tftpboot/%s |
|
[ -z "$server" ] && server=$srv |
|
[ -z "$server" ] && server=$new_next_server |
|
[ -z "$server" ] && server=$new_dhcp_server_identifier |
|
[ -z "$server" ] && server=${new_root_path%%:*} |
|
} |
|
|
|
# Look through $options, fix "rw"/"ro", move "lock"/"nolock" to $nfslock |
|
munge_nfs_options() { |
|
local f="" flags="" nfsrw="ro" OLDIFS="$IFS" |
|
IFS=, |
|
for f in $options; do |
|
case $f in |
|
ro | rw) nfsrw=$f ;; |
|
lock | nolock) nfslock=$f ;; |
|
*) flags=${flags:+$flags,}$f ;; |
|
esac |
|
done |
|
IFS="$OLDIFS" |
|
|
|
# Override rw/ro if set on cmdline |
|
getarg ro > /dev/null && nfsrw=ro |
|
getarg rw > /dev/null && nfsrw=rw |
|
|
|
options=$nfsrw${flags:+,$flags} |
|
} |
|
|
|
# mount_nfs NFSROOT MNTDIR [NETIF] |
|
mount_nfs() { |
|
local nfsroot="$1" mntdir="$2" netif="$3" |
|
local nfs="" server="" path="" options="" |
|
nfs_to_var "$nfsroot" "$netif" |
|
munge_nfs_options |
|
if [ "$nfs" = "nfs4" ]; then |
|
options=$options${nfslock:+,$nfslock} |
|
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 |
|
options=$options,nolock |
|
fi |
|
mount -t "$nfs" -o"$options" "$server:$path" "$mntdir" |
|
}
|
|
|