Jump to content

How To Mount A Linux Filesystem Readonly

+ 1
  lm317t's Photo
Posted Nov 13 2009 12:22 PM

-*- shell-script -*-
#
################################################################
# File:
# /scripts/local
#
# Root, or / in these notes is the initrd's (busybox) root,
# not your system's root!
#
# You need the aufs module for this to work. To do this install
# aufs on your base install, add aufs to: /etc/initramfs-tools/modules
# Now using your target kernel run:
# mkinitramfs -o initrd.img <kernel-name>
#
# make a directory, copy an initrd from boot to it then cd to it and:
#
# mv initrd.img initrd.img.gz
# gunzip initrd.img.gz
#
# make sure aufs exists somewhere in /lib/modules/<uname -r>/
# After modifying local script, etc do the following in the initrd's
# root folder where /bin and /lib etc is to create a new initrd:
#
# find ./ -print | cpio -H newc -o > ../newinitrd.img
#
# Now tell grub to use this initrd for a RO root filesystem
#
# Note fstab gets hosed, if you need an fstab, make sure this
# script reflects that. I use an fstab for the default initrd for RW
# and none for RO, but you can make this script use a different one for
# RO if you want.
#
#
#######################
# My changes are shown below between the ### lines
#######################
#
#
################################################################
# Parameter: device node to check
# Echos fstype to stdout
# Return value: indicates if an fs could be recognized
get_fstype ()
{
local FS FSTYPE FSSIZE RET
FS="${1}"

# vol_id has a more complete list of file systems,
# but fstype is more robust
eval $(fstype "${FS}" 2> /dev/null)
if [ "$FSTYPE" = "unknown" ] && [ -x /lib/udev/vol_id ]; then
FSTYPE=$(/lib/udev/vol_id -t "${FS}" 2> /dev/null)
fi
RET=$?

if [ -z "${FSTYPE}" ]; then
FSTYPE="unknown"
fi

echo "${FSTYPE}"
return ${RET}
}

# Parameter: Where to mount the filesystem
mountroot ()
{
[ "$quiet" != "y" ] && log_begin_msg "Running /scripts/local-top"
run_scripts /scripts/local-top
[ "$quiet" != "y" ] && log_end_msg

wait_for_udev 10

# If the root device hasn't shown up yet, give it a little while
# to deal with removable devices
if [ ! -e "${ROOT}" ] || ! $(get_fstype "${ROOT}" >/dev/null); then
log_begin_msg "Waiting for root file system"

# Default delay is 180s
if [ -z "${ROOTDELAY}" ]; then
slumber=180
else
slumber=${ROOTDELAY}
fi
if [ -x /sbin/usplash_write ]; then
/sbin/usplash_write "TIMEOUT ${slumber}" || true
fi

slumber=$(( ${slumber} * 10 ))
while [ ! -e "${ROOT}" ] \
|| ! $(get_fstype "${ROOT}" >/dev/null); do
/bin/sleep 0.1
slumber=$(( ${slumber} - 1 ))
[ ${slumber} -gt 0 ] || break
done

if [ ${slumber} -gt 0 ]; then
log_end_msg 0
else
log_end_msg 1 || true
fi
if [ -x /sbin/usplash_write ]; then
/sbin/usplash_write "TIMEOUT 15" || true
fi
fi

# We've given up, but we'll let the user fix matters if they can
while [ ! -e "${ROOT}" ]; do
# give hint about renamed root
case "${ROOT}" in
/dev/hd*)
suffix="${ROOT#/dev/hd}"
major="${suffix%[[:digit:]]}"
major="${major%[[:digit:]]}"
if [ -d "/sys/block/sd${major}" ]; then
echo "WARNING bootdevice may be renamed. Try root=/dev/sd${suffix}"
fi
;;
/dev/sd*)
suffix="${ROOT#/dev/sd}"
major="${suffix%[[:digit:]]}"
major="${major%[[:digit:]]}"
if [ -d "/sys/block/hd${major}" ]; then
echo "WARNING bootdevice may be renamed. Try root=/dev/hd${suffix}"
fi
;;
esac
echo "Gave up waiting for root device. Common problems:"
echo " - Boot args (cat /proc/cmdline)"
echo " - Check rootdelay= (did the system wait long enough?)"
echo " - Check root= (did the system wait for the right device?)"
echo " - Missing modules (cat /proc/modules; ls /dev)"
panic "alert! ${ROOT} does not exist. Dropping to a shell!"
done

# Get the root filesystem type if not set
if [ -z "${ROOTFSTYPE}" ]; then
FSTYPE=$(get_fstype "${ROOT}")
else
FSTYPE=${ROOTFSTYPE}
fi

[ "$quiet" != "y" ] && log_begin_msg "Running /scripts/local-premount"
run_scripts /scripts/local-premount
[ "$quiet" != "y" ] && log_end_msg

if [ "${readonly}" = "y" ]; then
roflag=-r
else
roflag=-w
fi

# FIXME This has no error checking

modprobe ${FSTYPE}
##########################################################################
###### Mod'd by Brian Phelps aka Electronjunkie ##########################

mkdir /root/.tmpfs
mkdir /root/.rootfs

mount -r -t ext2 /dev/sda1 /root/.rootfs

modprobe aufs
modprobe loop
mount -t tmpfs -o size=20M tmpfs /root/.tmpfs

mount -t aufs -o br:/root/.tmpfs=rw:/root/.rootfs=ro none /root/
mv /root/etc/fstab /root/etc/fstab.defunct

#########################################################################

# FIXME This has no error checking
# Mount root

[ "$quiet" != "y" ] && log_begin_msg "Running /scripts/local-bottom"
run_scripts /scripts/local-bottom
[ "$quiet" != "y" ] && log_end_msg
}

Tags:
0 Subscribe


1 Reply

+ 5
  KBenson's Photo
Posted Nov 29 2009 10:43 PM

Well, for completeness sake and since knowing and understanding the underlying utilities that linux uses in it's many shell scripts is useful, I'll provide a simplistic low-level alternative.

The mount command. It mounts a file system found on a device. For example, if you have an ext3 file system on /dev/sdb3 (the third partition of scsi/sata disk "b") that you want to mount on /media/otherdisk, the complete command would be:

$ mount -t ext3 /dev/sdb3 /media/otherdisk

Often you can leave out the filesystem type (the "-t ext3" above). If the relationship is defined in /etc/fstab, you can even leave out the source device, as it can be inferred from that file:

$ mount /demia/otherdisk

Now, to mound a disk readonly, you want to specify some options to the mount command, using "-o". Readonly is "ro", so we can mount the disk in the example above readonly like so:

$ mount -t ext3 -o ro /dev/sdb3 /media/otherdisk

Multiple options can be supplied with commas between them, and no spaces.

Here's a neat trick to mount a filesystem readonly without unmounting it:

$ mount -o remount,ro /media/otherdisk

We didn't need to define any of the other information, as the system already has it mounted and can infer anything left out (such as the type, source address, etc.)

P.S. mount options are also used to set a number of other possibly desirable settings for a filesystem, such as ports and block sizes for NFS, ACL support, etc.