318 lines
7.8 KiB
Bash
318 lines
7.8 KiB
Bash
# Local filesystem mounting -*- shell-script -*-
|
|
|
|
local_top()
|
|
{
|
|
if [ "${local_top_used}" != "yes" ]; then
|
|
[ "${quiet?}" != "y" ] && log_begin_msg "Running /scripts/local-top"
|
|
run_scripts /scripts/local-top
|
|
[ "$quiet" != "y" ] && log_end_msg
|
|
fi
|
|
local_top_used=yes
|
|
}
|
|
|
|
local_block()
|
|
{
|
|
[ "${quiet?}" != "y" ] && log_begin_msg "Running /scripts/local-block"
|
|
run_scripts /scripts/local-block "$@"
|
|
[ "$quiet" != "y" ] && log_end_msg
|
|
}
|
|
|
|
local_premount()
|
|
{
|
|
if [ "${local_premount_used}" != "yes" ]; then
|
|
[ "${quiet?}" != "y" ] && log_begin_msg "Running /scripts/local-premount"
|
|
run_scripts /scripts/local-premount
|
|
[ "$quiet" != "y" ] && log_end_msg
|
|
fi
|
|
local_premount_used=yes
|
|
}
|
|
|
|
local_bottom()
|
|
{
|
|
if [ "${local_premount_used}" = "yes" ] || [ "${local_top_used}" = "yes" ]; then
|
|
[ "${quiet?}" != "y" ] && log_begin_msg "Running /scripts/local-bottom"
|
|
run_scripts /scripts/local-bottom
|
|
[ "$quiet" != "y" ] && log_end_msg
|
|
fi
|
|
local_premount_used=no
|
|
local_top_used=no
|
|
}
|
|
|
|
# $1=device ID to mount
|
|
# $2=optionname (for root and etc)
|
|
# $3=panic if device is missing (true or false, default: true)
|
|
# Sets $DEV to the resolved device node
|
|
local_device_setup()
|
|
{
|
|
local dev_id="$1"
|
|
local name="$2"
|
|
local may_panic="${3:-true}"
|
|
local real_dev
|
|
local time_elapsed
|
|
local count
|
|
|
|
# If wait-for-root understands this prefix, then use it to wait for
|
|
# the device rather than settling the whole of udev.
|
|
|
|
# Timeout is max(30, rootdelay) seconds (approximately)
|
|
local slumber=30
|
|
case $DPKG_ARCH in
|
|
powerpc|ppc64|ppc64el)
|
|
slumber=180
|
|
;;
|
|
*)
|
|
slumber=30
|
|
;;
|
|
esac
|
|
if [ "${ROOTDELAY:-0}" -gt $slumber ]; then
|
|
slumber=$ROOTDELAY
|
|
fi
|
|
|
|
case "$dev_id" in
|
|
UUID=*|LABEL=*|PARTUUID=*|/dev/*)
|
|
FSTYPE=$( wait-for-root "$dev_id" "$slumber" )
|
|
;;
|
|
*)
|
|
wait_for_udev 10
|
|
;;
|
|
esac
|
|
|
|
# Load ubi with the correct MTD partition and return since fstype
|
|
# doesn't work with a char device like ubi.
|
|
if [ -n "$UBIMTD" ]; then
|
|
modprobe ubi "mtd=$UBIMTD"
|
|
DEV="${dev_id}"
|
|
return
|
|
fi
|
|
|
|
# Don't wait for a device that doesn't have a corresponding
|
|
# device in /dev and isn't resolvable by blkid (e.g. mtd0)
|
|
if [ "${dev_id#/dev}" = "${dev_id}" ] &&
|
|
[ "${dev_id#*=}" = "${dev_id}" ]; then
|
|
DEV="${dev_id}"
|
|
return
|
|
fi
|
|
|
|
# If the root device hasn't shown up yet, give it a little while
|
|
# to allow for asynchronous device discovery (e.g. USB). We
|
|
# also need to keep invoking the local-block scripts in case
|
|
# there are devices stacked on top of those.
|
|
#
|
|
# in Ubuntu, we should never actually enter this loop as wait-for-root
|
|
# above should have waited until the device appeared.
|
|
if ! real_dev=$(resolve_device "${dev_id}") ||
|
|
! get_fstype "${real_dev}" >/dev/null; then
|
|
log_begin_msg "Waiting for ${name}"
|
|
|
|
while true; do
|
|
sleep 1
|
|
time_elapsed="$(time_elapsed)"
|
|
|
|
local_block "${dev_id}"
|
|
|
|
# If mdadm's local-block script counts the
|
|
# number of times it is run, make sure to
|
|
# run it the expected number of times.
|
|
mdadm_exec=0
|
|
while true; do
|
|
if [ -f /run/count.mdadm.initrd ]; then
|
|
count="$(cat /run/count.mdadm.initrd)"
|
|
elif [ -n "${count}" ]; then
|
|
# mdadm script deleted it; put it back
|
|
count=$((count + 1))
|
|
echo "${count}" >/run/count.mdadm.initrd
|
|
else
|
|
break
|
|
fi
|
|
if [ "${count}" -ge "${time_elapsed}" ]; then
|
|
break;
|
|
fi
|
|
|
|
# Track that mdadm was executed to force
|
|
# cryptroot execution after the loop, see
|
|
# LP #1879980.
|
|
mdadm_exec=1
|
|
/scripts/local-block/mdadm "${dev_id}"
|
|
|
|
# Cryptroot must run here, see LP #1879980.
|
|
# The counter is inc/dec on cryptroot script!
|
|
if [ -f /run/cryptroot.initrd.cnt ]; then
|
|
crypt_cnt=$(cat /run/cryptroot.initrd.cnt)
|
|
if [ "${crypt_cnt}" -gt 0 ]; then
|
|
/scripts/local-block/cryptroot "${dev_id}"
|
|
fi
|
|
fi
|
|
done
|
|
|
|
# Extra cryptroot run after mdadm loop in order to
|
|
# start encrypted volumes on top of RAID arrays.
|
|
if [ -f /run/cryptroot.initrd.cnt ]; then
|
|
crypt_cnt=$(cat /run/cryptroot.initrd.cnt)
|
|
if [ "${crypt_cnt}" -gt 0 ] || [ ${mdadm_exec} -ne 0 ]; then
|
|
/scripts/local-block/cryptroot "${dev_id}"
|
|
fi
|
|
fi
|
|
|
|
if real_dev=$(resolve_device "${dev_id}") &&
|
|
get_fstype "${real_dev}" >/dev/null; then
|
|
wait_for_udev 10
|
|
log_end_msg 0
|
|
break
|
|
fi
|
|
if [ "${time_elapsed}" -ge "${slumber}" ]; then
|
|
log_end_msg 1 || true
|
|
break
|
|
fi
|
|
done
|
|
fi
|
|
|
|
# We've given up, but we'll let the user fix matters if they can
|
|
while ! real_dev=$(resolve_device "${dev_id}") ||
|
|
! get_fstype "${real_dev}" >/dev/null; do
|
|
if ! $may_panic; then
|
|
echo "Gave up waiting for ${name}"
|
|
return 1
|
|
fi
|
|
echo "Gave up waiting for ${name} device. Common problems:"
|
|
echo " - Boot args (cat /proc/cmdline)"
|
|
echo " - Check rootdelay= (did the system wait long enough?)"
|
|
if [ "${name}" = root ]; then
|
|
echo " - Check root= (did the system wait for the right device?)"
|
|
fi
|
|
echo " - Missing modules (cat /proc/modules; ls /dev)"
|
|
panic "ALERT! ${dev_id} does not exist. Dropping to a shell!"
|
|
done
|
|
|
|
DEV="${real_dev}"
|
|
}
|
|
|
|
local_mount_root()
|
|
{
|
|
local_top
|
|
if [ -z "${ROOT}" ]; then
|
|
panic "No root device specified. Boot arguments must include a root= parameter."
|
|
fi
|
|
local_device_setup "${ROOT}" "root file system"
|
|
ROOT="${DEV}"
|
|
|
|
# Get the root filesystem type if not set
|
|
if [ -z "${ROOTFSTYPE}" ] || [ "${ROOTFSTYPE}" = auto ]; then
|
|
FSTYPE=$(get_fstype "${ROOT}")
|
|
else
|
|
FSTYPE=${ROOTFSTYPE}
|
|
fi
|
|
|
|
local_premount
|
|
|
|
if [ "${readonly?}" = "y" ] && \
|
|
[ -z "$LOOP" ]; then
|
|
roflag=-r
|
|
else
|
|
roflag=-w
|
|
fi
|
|
|
|
checkfs "${ROOT}" root "${FSTYPE}"
|
|
|
|
# Mount root
|
|
# shellcheck disable=SC2086
|
|
mount ${roflag} ${FSTYPE:+-t "${FSTYPE}"} ${ROOTFLAGS} "${ROOT}" "${rootmnt?}"
|
|
mountroot_status="$?"
|
|
if [ "$LOOP" ]; then
|
|
if [ "$mountroot_status" != 0 ]; then
|
|
if [ "${FSTYPE}" = ntfs ] || [ "${FSTYPE}" = vfat ]
|
|
then
|
|
panic "
|
|
Could not mount the partition ${ROOT}.
|
|
This could also happen if the file system is not clean because of an operating
|
|
system crash, an interrupted boot process, an improper shutdown, or unplugging
|
|
of a removable device without first unmounting or ejecting it. To fix this,
|
|
simply reboot into Windows, let it fully start, log in, run 'chkdsk /r', then
|
|
gracefully shut down and reboot back into Windows. After this you should be
|
|
able to reboot again and resume the installation.
|
|
(filesystem = ${FSTYPE}, error code = $mountroot_status)
|
|
"
|
|
fi
|
|
fi
|
|
|
|
mkdir -p /host
|
|
mount -o move "$rootmnt" /host
|
|
|
|
while [ ! -e "/host/${LOOP#/}" ]; do
|
|
panic "ALERT! /host/${LOOP#/} does not exist. Dropping to a shell!"
|
|
done
|
|
|
|
# Get the loop filesystem type if not set
|
|
# shellcheck disable=SC2153
|
|
FSTYPE="$LOOPFSTYPE"
|
|
if [ -z "$FSTYPE" ] || [ "$FSTYPE" = "unknown" ]; then
|
|
FSTYPE=$(/sbin/blkid -s TYPE -o value "/host/${LOOP#/}")
|
|
[ -z "$FSTYPE" ] && FSTYPE="unknown"
|
|
fi
|
|
|
|
if [ "$readonly" = y ]; then
|
|
roflag=-r
|
|
else
|
|
roflag=-w
|
|
fi
|
|
|
|
# FIXME This has no error checking
|
|
modprobe loop
|
|
|
|
# FIXME This has no error checking
|
|
# shellcheck disable=SC2086
|
|
mount ${roflag} -o loop -t ${FSTYPE} ${LOOPFLAGS} "/host/${LOOP#/}" "${rootmnt?}"
|
|
|
|
if [ -d "$rootmnt/host" ]; then
|
|
mount -o move /host "$rootmnt/host"
|
|
fi
|
|
fi
|
|
}
|
|
|
|
local_mount_fs()
|
|
{
|
|
read_fstab_entry "$1"
|
|
|
|
local_device_setup "$MNT_FSNAME" "$1 file system"
|
|
MNT_FSNAME="${DEV}"
|
|
|
|
local_premount
|
|
|
|
if [ "${readonly}" = "y" ]; then
|
|
roflag=-r
|
|
else
|
|
roflag=-w
|
|
fi
|
|
|
|
if [ "$MNT_PASS" != 0 ]; then
|
|
checkfs "$MNT_FSNAME" "$MNT_DIR" "${MNT_TYPE}"
|
|
fi
|
|
|
|
# Mount filesystem
|
|
if ! mount ${roflag} -t "${MNT_TYPE}" -o "${MNT_OPTS}" "$MNT_FSNAME" "${rootmnt}${MNT_DIR}"; then
|
|
panic "Failed to mount ${MNT_FSNAME} as $MNT_DIR file system."
|
|
fi
|
|
}
|
|
|
|
mountroot()
|
|
{
|
|
local_mount_root
|
|
}
|
|
|
|
mount_top()
|
|
{
|
|
# Note, also called directly in case it's overridden.
|
|
local_top
|
|
}
|
|
|
|
mount_premount()
|
|
{
|
|
# Note, also called directly in case it's overridden.
|
|
local_premount
|
|
}
|
|
|
|
mount_bottom()
|
|
{
|
|
# Note, also called directly in case it's overridden.
|
|
local_bottom
|
|
}
|