initrd.scripts: move rootdev code to 00-rootdev.sh

master
Fabio Erculiani 11 years ago
parent 5a9dc6ae08
commit 9bc5b60794

@ -0,0 +1,257 @@
#!/bin/sh
. /etc/initrd.d/00-common.sh
. /etc/initrd.d/00-splash.sh
. /etc/initrd.d/00-zfs.sh
_fstype_init() {
local fstype="${1}"
if [ "${fstype}" = "btrfs" ]; then
# start BTRFS volume detection, if available
[ -x /sbin/btrfs ] && /sbin/btrfs device scan
elif [ -z "${fstype}" ]; then
warn_msg "Unable to detect the filesystem type (empty variable)"
fi
}
_rootdev_detect() {
local got_good_root=0
while [ "${got_good_root}" != "1" ]; do
case "${REAL_ROOT}" in
LABEL=*|UUID=*)
local root_dev=$(find_real_device "${REAL_ROOT}")
if [ -n "${root_dev}" ]; then
REAL_ROOT="${root_dev}"
good_msg "Detected root: ${REAL_ROOT}"
else
bad_msg "Unable to resolve root: ${REAL_ROOT}"
got_good_root=0
prompt_user "REAL_ROOT" "root block device"
continue
fi
;;
ZFS*)
# zfs_rootdev_init will tweak ${REAL_ROOT}
zfs_rootdev_init
if [ "${?}" = "0" ]; then
got_good_root=1
else
got_good_root=0
prompt_user "REAL_ROOT" "root block device"
continue
fi
;;
esac
if [ -z "${REAL_ROOT}" ]; then
# No REAL_ROOT determined/specified.
# Prompt user for root block device.
prompt_user "REAL_ROOT" "root block device"
got_good_root=0
# Check for a block device or NFS
elif [ -b "${REAL_ROOT}" ] || is_nfs; then
got_good_root=1
else
bad_msg "${REAL_ROOT} is an invalid root device..."
REAL_ROOT=""
got_good_root=0
fi
done
return 0
}
_rootdev_mount() {
local mount_opts=ro
local mount_fstype="${ROOTFSTYPE}"
local fstype=$(get_device_fstype "${REAL_ROOT}")
if is_zfs_fstype "${fstype}"; then
mount_fstype=zfs
mount_opts=$(zfs_get_real_root_mount_flags)
fi
good_msg "Detected fstype: ${fstype}"
good_msg "Using mount fstype: ${mount_fstype}"
_fstype_init "${fstype}"
local mopts="${mount_opts}"
[ -n "${REAL_ROOTFLAGS}" ] && \
mopts="${mopts},${REAL_ROOTFLAGS}"
good_msg "Using mount opts: -o ${mopts}"
mount -t "${mount_fstype}" -o "${mopts}" \
"${REAL_ROOT}" "${NEW_ROOT}" || return 1
return 0
}
_get_mounts_list() {
awk '
/^[[:blank:]]*#/ { next }
{ print $1 }
' ${NEW_ROOT}/etc/initramfs.mounts
}
_get_mount_fstype() {
[ -e "${NEW_ROOT}"/etc/fstab ] || return 1
awk -v fs="$1" '
/^[[:blank:]]*#/ { next }
$2 == fs { print $3 }
' ${NEW_ROOT}/etc/fstab
}
_get_mount_options() {
[ -e "${NEW_ROOT}"/etc/fstab ] || return 1
awk -v fs="$1" '
/^[[:blank:]]*#/ { next }
$2 == fs { print $4 }
' ${NEW_ROOT}/etc/fstab
}
_get_mount_device() {
[ -e "${NEW_ROOT}"/etc/fstab ] || return 1
awk -v fs="$1" '
/^[[:blank:]]*#/ { next }
$2 == fs { print $1 }
' ${NEW_ROOT}/etc/fstab
}
# If the kernel is handed a mount option is does not recognize, it
# WILL fail to mount. util-linux handles auto/noauto, but busybox
# passes it straight to the kernel which then rejects the mount. To
# make like a little easier, busybox mount does not care about
# leading, trailing or duplicate commas.
_strip_mount_options() {
sed -r 's/(,|^)(no)?auto(,|$)/,/g'
}
real_root_init() {
if [ -z "${REAL_ROOT}" ] && [ "${FAKE_ROOT}" != "/dev/ram0" ]; then
REAL_ROOT="${FAKE_ROOT}"
fi
if [ -z "${REAL_INIT}" ] && [ "${FAKE_INIT}" != "/linuxrc" ]; then
REAL_INIT="${FAKE_INIT}"
fi
if [ -z "${REAL_ROOTFLAGS}" ]; then
REAL_ROOTFLAGS="${FAKE_ROOTFLAGS}"
fi
}
# Read /etc/initramfs.mounts from ${NEW_ROOT} and mount the
# listed filesystem mountpoints. For instance, /usr, which is
# required by udev & systemd.
ensure_initramfs_mounts() {
local fslist=
if [ -f "${NEW_ROOT}/etc/initramfs.mounts" ]; then
fslist="$(_get_mounts_list)"
else
fslist="/usr"
fi
local dev= fstype= opts= mnt= cmd=
for fs in ${fslist}; do
mnt="${NEW_ROOT}${fs}"
if mountpoint -q "${mnt}"; then
good_msg "${fs} already mounted, skipping..."
continue
fi
dev=$(_get_mount_device "${fs}")
[ -z "${dev}" ] && continue
# Resolve it like util-linux mount does
[ -L "${dev}" ] && dev=$(readlink "${dev}")
# In this case, it's probably part of the filesystem
# and not a mountpoint
[ -z "${dev}" ] && continue
fstype=$(_get_mount_fstype "${fs}")
if _get_mount_options "${fs}" | fgrep -q bind; then
opts="bind"
dev="${NEW_ROOT}${dev}"
else
# ro must be trailing, and the options will always
# contain at least 'defaults'
opts="$(_get_mount_options ${fs} | _strip_mount_options)"
opts="${opts},ro"
fi
cmd="mount -t ${fstype} -o ${opts} ${dev} ${mnt}"
good_msg "Mounting ${dev} as ${fs}: ${cmd}"
if ! ${cmd}; then
bad_msg "Unable to mount ${dev} for ${fs}"
fi
done
}
rootdev_init() {
good_msg "Initializing root device..."
while true; do
if ! _rootdev_detect; then
bad_msg "Could not mount specified ROOT, try again"
prompt_user "REAL_ROOT" "root block device"
continue
fi
if is_livecd && ! is_nfs; then
# CD already mounted; no further checks necessary
break
fi
if [ "${LOOPTYPE}" = "sgimips" ]; then
# sgimips mounts the livecd root partition directly
# there is no isofs filesystem to worry about
break
fi
good_msg "Mounting ${REAL_ROOT} as root..."
# Try to mount the device as ${NEW_ROOT}
local out=1
if is_nfs; then
find_nfs && out=0
else
_rootdev_mount && out=0
fi
if [ "${out}" != "0" ]; then
bad_msg "Could not mount specified ROOT, try again"
prompt_user "REAL_ROOT" "root block device"
continue
fi
# now that the root filesystem is mounted, before
# checking the validity of ${NEW_ROOT} and ${REAL_INIT},
# ensure that ${NEW_ROOT}/etc/initramfs.mounts entries
# are mounted.
ensure_initramfs_mounts
# NFS does not need further checks here.
is_nfs && break
if [ ! -d "${NEW_ROOT}/dev" ]; then
_msg="The filesystem ${REAL_ROOT},"
_msg="${_msg} mounted at ${NEW_ROOT}"
_msg="${_msg} does not contain /dev"
_msg="${_msg}, init will likely fail..."
bad_msg "${_msg}"
prompt_user "REAL_ROOT" "root block device"
continue
fi
if [ ! -x "${NEW_ROOT}${REAL_INIT}" ]; then
_msg="The filesystem ${REAL_ROOT},"
_msg="${_msg} mounted at ${NEW_ROOT}"
_msg="${_msg} does not contain a valid"
_msg="${_msg} init=${REAL_INIT}"
bad_msg "${_msg}"
prompt_user "REAL_ROOT" "root block device"
continue
fi
break
done
}

@ -13,264 +13,13 @@
. /etc/initrd.d/00-crypt.sh
. /etc/initrd.d/00-suspend.sh
. /etc/initrd.d/00-iscsi.sh
. /etc/initrd.d/00-rootdev.sh
real_root_init() {
if [ -z "${REAL_ROOT}" ] && [ "${FAKE_ROOT}" != "/dev/ram0" ]; then
REAL_ROOT="${FAKE_ROOT}"
fi
if [ -z "${REAL_INIT}" ] && [ "${FAKE_INIT}" != "/linuxrc" ]; then
REAL_INIT="${FAKE_INIT}"
fi
if [ -z "${REAL_ROOTFLAGS}" ]; then
REAL_ROOTFLAGS="${FAKE_ROOTFLAGS}"
fi
}
getdvhoff() {
echo $(( $(hexdump -n 4 -s $((316 + 12 * $2)) -e '"%i"' $1) * 512))
}
get_mounts_list() {
awk '
/^[[:blank:]]*#/ { next }
{ print $1 }
' ${NEW_ROOT}/etc/initramfs.mounts
}
get_mount_fstype() {
[ -e "${NEW_ROOT}"/etc/fstab ] || return 1
awk -v fs="$1" '
/^[[:blank:]]*#/ { next }
$2 == fs { print $3 }
' ${NEW_ROOT}/etc/fstab
}
get_mount_options() {
[ -e "${NEW_ROOT}"/etc/fstab ] || return 1
awk -v fs="$1" '
/^[[:blank:]]*#/ { next }
$2 == fs { print $4 }
' ${NEW_ROOT}/etc/fstab
}
get_mount_device() {
[ -e "${NEW_ROOT}"/etc/fstab ] || return 1
awk -v fs="$1" '
/^[[:blank:]]*#/ { next }
$2 == fs { print $1 }
' ${NEW_ROOT}/etc/fstab
}
# If the kernel is handed a mount option is does not recognize, it
# WILL fail to mount. util-linux handles auto/noauto, but busybox
# passes it straight to the kernel which then rejects the mount. To
# make like a little easier, busybox mount does not care about
# leading, trailing or duplicate commas.
strip_mount_options() {
sed -r 's/(,|^)(no)?auto(,|$)/,/g'
}
# Read /etc/initramfs.mounts from ${NEW_ROOT} and mount the
# listed filesystem mountpoints. For instance, /usr, which is
# required by udev & systemd.
ensure_initramfs_mounts() {
local fslist=
if [ -f "${NEW_ROOT}/etc/initramfs.mounts" ]; then
fslist="$(get_mounts_list)"
else
fslist="/usr"
fi
local dev= fstype= opts= mnt= cmd=
for fs in ${fslist}; do
mnt="${NEW_ROOT}${fs}"
if mountpoint -q "${mnt}"; then
good_msg "${fs} already mounted, skipping..."
continue
fi
dev=$(get_mount_device "${fs}")
[ -z "${dev}" ] && continue
# Resolve it like util-linux mount does
[ -L "${dev}" ] && dev=$(readlink "${dev}")
# In this case, it's probably part of the filesystem
# and not a mountpoint
[ -z "${dev}" ] && continue
fstype=$(get_mount_fstype "${fs}")
if get_mount_options "${fs}" | fgrep -q bind; then
opts="bind"
dev="${NEW_ROOT}${dev}"
else
# ro must be trailing, and the options will always
# contain at least 'defaults'
opts="$(get_mount_options ${fs} | strip_mount_options)"
opts="${opts},ro"
fi
cmd="mount -t ${fstype} -o ${opts} ${dev} ${mnt}"
good_msg "Mounting ${dev} as ${fs}: ${cmd}"
if ! ${cmd}; then
bad_msg "Unable to mount ${dev} for ${fs}"
fi
done
}
fstype_init() {
local fstype="${1}"
if [ "${fstype}" = "btrfs" ]; then
# start BTRFS volume detection, if available
[ -x /sbin/btrfs ] && /sbin/btrfs device scan
elif [ -z "${fstype}" ]; then
warn_msg "Unable to detect the filesystem type (empty variable)"
fi
}
_rootdev_detect() {
local got_good_root=0
while [ "${got_good_root}" != "1" ]; do
case "${REAL_ROOT}" in
LABEL=*|UUID=*)
local root_dev=$(find_real_device "${REAL_ROOT}")
if [ -n "${root_dev}" ]; then
REAL_ROOT="${root_dev}"
good_msg "Detected root: ${REAL_ROOT}"
else
bad_msg "Unable to resolve root: ${REAL_ROOT}"
got_good_root=0
prompt_user "REAL_ROOT" "root block device"
continue
fi
;;
ZFS*)
# zfs_rootdev_init will tweak ${REAL_ROOT}
zfs_rootdev_init
if [ "${?}" = "0" ]; then
got_good_root=1
else
got_good_root=0
prompt_user "REAL_ROOT" "root block device"
continue
fi
;;
esac
if [ -z "${REAL_ROOT}" ]; then
# No REAL_ROOT determined/specified.
# Prompt user for root block device.
prompt_user "REAL_ROOT" "root block device"
got_good_root=0
# Check for a block device or NFS
elif [ -b "${REAL_ROOT}" ] || is_nfs; then
got_good_root=1
else
bad_msg "${REAL_ROOT} is an invalid root device..."
REAL_ROOT=""
got_good_root=0
fi
done
return 0
}
_rootdev_mount() {
local mount_opts=ro
local mount_fstype="${ROOTFSTYPE}"
local fstype=$(get_device_fstype "${REAL_ROOT}")
if is_zfs_fstype "${fstype}"; then
mount_fstype=zfs
mount_opts=$(zfs_get_real_root_mount_flags)
fi
good_msg "Detected fstype: ${fstype}"
good_msg "Using mount fstype: ${mount_fstype}"
fstype_init "${fstype}"
local mopts="${mount_opts}"
[ -n "${REAL_ROOTFLAGS}" ] && \
mopts="${mopts},${REAL_ROOTFLAGS}"
good_msg "Using mount opts: -o ${mopts}"
mount -t "${mount_fstype}" -o "${mopts}" \
"${REAL_ROOT}" "${NEW_ROOT}" || return 1
return 0
}
rootdev_init() {
good_msg "Initializing root device..."
while true; do
if ! _rootdev_detect; then
bad_msg "Could not mount specified ROOT, try again"
prompt_user "REAL_ROOT" "root block device"
continue
fi
if is_livecd && ! is_nfs; then
# CD already mounted; no further checks necessary
break
fi
if [ "${LOOPTYPE}" = "sgimips" ]; then
# sgimips mounts the livecd root partition directly
# there is no isofs filesystem to worry about
break
fi
good_msg "Mounting ${REAL_ROOT} as root..."
# Try to mount the device as ${NEW_ROOT}
local out=1
if is_nfs; then
find_nfs && out=0
else
_rootdev_mount && out=0
fi
if [ "${out}" != "0" ]; then
bad_msg "Could not mount specified ROOT, try again"
prompt_user "REAL_ROOT" "root block device"
continue
fi
# now that the root filesystem is mounted, before
# checking the validity of ${NEW_ROOT} and ${REAL_INIT},
# ensure that ${NEW_ROOT}/etc/initramfs.mounts entries
# are mounted.
ensure_initramfs_mounts
# NFS does not need further checks here.
is_nfs && break
if [ ! -d "${NEW_ROOT}/dev" ]; then
_msg="The filesystem ${REAL_ROOT},"
_msg="${_msg} mounted at ${NEW_ROOT}"
_msg="${_msg} does not contain /dev"
_msg="${_msg}, init will likely fail..."
bad_msg "${_msg}"
prompt_user "REAL_ROOT" "root block device"
continue
fi
if [ ! -x "${NEW_ROOT}${REAL_INIT}" ]; then
_msg="The filesystem ${REAL_ROOT},"
_msg="${_msg} mounted at ${NEW_ROOT}"
_msg="${_msg} does not contain a valid"
_msg="${_msg} init=${REAL_INIT}"
bad_msg "${_msg}"
prompt_user "REAL_ROOT" "root block device"
continue
fi
break
done
}
# If devtmpfs is mounted, try move it to the new root
# If that fails, try to unmount all possible mounts of devtmpfs as
# stuff breaks otherwise

Loading…
Cancel
Save