Created attachment 937 [details] Log of read-only boot of core-image-sato At the moment, booting a target with the root filesystem being read-only causes some problems and this is something we'd like to support. For core-image-minimal the issues are: 1) update-modules needing to be run on the target as a postinstall - this should be able to be run on the host without too much difficulty. 2) populate-volatile.sh which runs as an initscript; the parts of this that write to the rootfs should be able to be done on the host. Attached is a log when running core-image-sato with a read-only rootfs, showing other issues. I'm not sure how many of those we can commit to fixing though.
/etc/init.d/bootmisc.sh:59 # This is as good a place as any for a sanity check # /tmp should be a symlink to /var/tmp to cut down on the number # of mounted ramdisks. if test ! -L /tmp && test -d /var/tmp then rm -rf /tmp ln -sf /var/tmp /tmp fi On read-only / you can't delete /tmp it should be done before image creation
There are also some other initscripts that may write to rootfs. udev-cache, bootmisc.sh, avahi-daemon, rmnologin.sh
A first implementation, please have a look at it. From 2090c4034958af58f9df950cd171c63fe71d4ace Mon Sep 17 00:00:00 2001 From: Chen Qi <Qi.Chen@windriver.com> Date: Mon, 10 Dec 2012 14:30:48 +0800 Subject: [PATCH] Read-only Rootfs Support Signed-off-by: Chen Qi <Qi.Chen@windriver.com> --- .../initscripts-1.0/readonly-rootfs-hook.sh | 151 ++++++++++++++++++++ meta/recipes-core/initscripts/initscripts_1.0.bb | 6 +- 2 files changed, 156 insertions(+), 1 deletions(-) create mode 100755 meta/recipes-core/initscripts/initscripts-1.0/readonly-rootfs-hook.sh diff --git a/meta/recipes-core/initscripts/initscripts-1.0/readonly-rootfs-hook.sh b/meta/recipes-core/initscripts/initscripts-1.0/readonly-rootfs-hook.sh new file mode 100755 index 0000000..d9a3c7a --- /dev/null +++ b/meta/recipes-core/initscripts/initscripts-1.0/readonly-rootfs-hook.sh @@ -0,0 +1,151 @@ +#!/bin/sh +# Short-Description: Hook script to support read-only rootfs + +# This script starts after mountall.sh and before populate-volatile.sh +# This script stops after postintalls on the target having been done + +# helper functions +migrate() { + orig_dir=$1 + volatile_dir=$2 + # migrate $orig_dir to be under $volatile_dir, and make a link to it + # $volatile_dir is supposed to be under /var/volatile + [ -d "$volatile_dir" ] || mkdir -p "$volatile_dir" + [ -d "$orig_dir" ] && cp -r "$orig_dir" "$volatile_dir" + rm -rf "$orig_dir" + ln -sf "$volatile_dir" "$orig_dir" +} + +# functions to help fix the first boot problem +module_id() { + awk 'BEGIN { FS=": " } /Hardware/ { print $2 } ' </proc/cpuinfo +} + +support_irattach() { + if [ ! -f /etc/sysconfig/irda ]; then + case `module_id` in + "HP iPAQ H2200" | "HP iPAQ HX4700" | "HTC Universal") + IRDA=yes + DEVICE=/dev/ttyS2 + DONGLE= + DISCOVERY= + ;; + *) + IRDA=yes + DEVICE=/dev/ttyS1 + DONGLE= + DISCOVERY= + ;; + esac + mkdir -p /etc/sysconfig + echo "IRDA=$IRDA" > /etc/sysconfig/irda + if [ $IRDA = "yes" ]; then + echo "DEVICE=$DEVICE" >> /etc/sysconfig/irda + echo "DONGLE=$DONGLE" >> /etc/sysconfig/irda + echo "DISCOVERY=$DISCOVERY" >> /etc/sysconfig/irda + fi + fi +} + +# Set basic varibles +RO_ROOTFS_INFO_FILE="/etc/.ro_rootfs_info_file" +[ -w /etc ] && ROOTMODE="rw" || ROOTMODE="ro" +FLAG_TMP_RW_ROOTFS="no" +ACTION="$1" +case "$0" in + *stop-readonly-rootfs-hook*) + ACTION="stop" + ;; +esac + +# Actions +case "$ACTION" in + start) + # Certain directories under /var/lib and /var/volatile/ have to be handled properly + # to deal with the following situations correctly. + # last-time this-time + # ro ro -> may need to make some dirs under /var/volatile + # ro rw -> may need to make dirs under /var/lib + # rw rw -> nothing to do (keep the same as before) + # rw ro -> nothing to do (the stop-readonly-rootfs-hook will take care of this situation) + # -- ro -> nothing to do (the stop-readonly-rootfs-hook will take care of this situation) + # -- rw -> nothing to do (keep the same as before) + # We do this for three reasons: + # 1) /var/volatile is a mount point for tmpfs, every time the system reboots, everything's lost + # 2) some application may need to write to /var/lib/xxx at run time, this type of directory should be handled carefully + # 3) we want things to keep the same as before if the rootfs is writable + LASTROOTMODE="" + [ -f "$RO_ROOTFS_INFO_FILE" ] && LASTROOTMODE=$(cat "$RO_ROOTFS_INFO_FILE") + if [ "$LASTROOTMODE" == "ro" ] && [ "$ROOTMODE" == "ro" ]; then + echo "last: readonly; now: readonly; make dirs under /var/volatile/lib" +# mkdir -p /var/volatile/lib/xxx + mkdir -p /var/volatile/lib/dropbear + mkdir -p /var/volatile/lib/nfs + mkdir -p /var/volatile/lib/dbus + elif [ "$LASTROOTMODE" == "ro" ] && [ "$ROOTMODE" == "rw" ]; then + echo "last: readonly; now: readwrite; rm links, and make dirs undr /var/lib" +# [ -L /var/lib/xxx ] && { rm /var/lib/xxx; mkdir /var/lib/xxx; } + [ -L /var/lib/dropbear ] && { rm /var/lib/dropbear; mkdir /var/lib/dropbear; } + [ -L /var/lib/nfs ] && { rm /var/lib/nfs; mkdir /var/lib/nfs; } + [ -L /var/lib/dbus ] && { rm /var/lib/dbus; mkdir /var/lib/dbus; } + fi + if [ -f "$RO_ROOTFS_INFO_FILE" ] && [ "$LASTROOTMODE" == "ro" ]; then + echo $ROOTMODE > "$RO_ROOTFS_INFO_FILE" + exit 0 + fi + if [ "$ROOTMODE" == "ro" ]; then + # boot with read-only rootfs & last time rootmode isn't ro ==> mount it as rw temporarily + # let other daemons and init scripts do their job properly + mount -o remount,rw / + if [ $? != 0 ]; then + echo "Remount rootfs as read-write Failed" + exit 1 + else + echo "Remount rootfs as read-write Succeed" + fi + fi + touch "$RO_ROOTFS_INFO_FILE" + echo $ROOTMODE > "$RO_ROOTFS_INFO_FILE" + ;; + stop) + # If $RO_ROOTFS_INFO_FILE has "ro" in it, but the rootfs is writable now, + # We can assert that the rootfs has been mounted as rw temporarily + if [ $(cat "$RO_ROOTFS_INFO_FILE") == "ro" ] && [ -w /etc ]; then + FLAG_TMP_RW_ROOTFS="yes" + fi + [ "$FLAG_TMP_RW_ROOTFS" == "no" ] && { echo "rootfs is not mounted as rw temporarily"; exit 0; } + # $FLAG_TMP_RW_ROOTFS == "yes" ==> rootfs should be readonly but now it's rw temporarily + # Do all stuff here to support read-only rootfs + # For example, migrate directories from /var/lib/xxx to /var/volatile/lib/xxx. + # These directories are needed to be written to by other applications or daemons at run time. + +# migrate /var/lib/xxx /var/volatile/lib/xxx + migrate /var/lib/dropbear /var/volatile/lib/dropbear + migrate /var/lib/nfs /var/volatile/lib/nfs + migrate /var/lib/dbus /var/volatile/lib/dbus + + # Another problem we need to take into consideration is the first boot problem. + # Some scripts in /etc/init.d may need to write to /etc/xxx at first boot, for example, irattach. + # This kind of operation should be done even if the rootfs is supposed to be read-only after system's set up. + # This is the section to collect all operations of such kind. + support_irattach + + # Remount rootfs as read-only + mount -n -o remount,ro / + if [ $? == 0 ]; then + echo "Remount rootfs as read-only succeed" + exit 0 + else + echo "Remount rootfs as read-only failed" + exit 1 + fi + ;; + *) + Prog=${0##*/} + Prog=${Prog#[SK]??} + echo "Usage: $Prog {start|stop}" >&2 + exit 1 + ;; +esac + +exit 0 \ No newline at end of file diff --git a/meta/recipes-core/initscripts/initscripts_1.0.bb b/meta/recipes-core/initscripts/initscripts_1.0.bb index d25838b..175653e 100644 --- a/meta/recipes-core/initscripts/initscripts_1.0.bb +++ b/meta/recipes-core/initscripts/initscripts_1.0.bb @@ -3,7 +3,7 @@ DESCRIPTION = "Initscripts provide the basic system startup initialization scrip SECTION = "base" LICENSE = "GPLv2" LIC_FILES_CHKSUM = "file://COPYING;md5=751419260aa954499f7abaabaa882bbe" -PR = "r137" +PR = "r138" INHIBIT_DEFAULT_DEPS = "1" @@ -31,6 +31,7 @@ SRC_URI = "file://functions \ file://populate-volatile.sh \ file://volatiles \ file://save-rtc.sh \ + file://readonly-rootfs-hook.sh \ file://GPLv2.patch" SRC_URI_append_arm = " file://alignment.sh" @@ -85,6 +86,7 @@ do_install () { install -m 0755 ${WORKDIR}/sysfs.sh ${D}${sysconfdir}/init.d install -m 0755 ${WORKDIR}/populate-volatile.sh ${D}${sysconfdir}/init.d install -m 0755 ${WORKDIR}/save-rtc.sh ${D}${sysconfdir}/init.d + install -m 0755 ${WORKDIR}/readonly-rootfs-hook.sh ${D}${sysconfdir}/init.d install -m 0644 ${WORKDIR}/volatiles ${D}${sysconfdir}/default/volatiles/00_core if [ "${TARGET_ARCH}" = "arm" ]; then install -m 0755 ${WORKDIR}/alignment.sh ${D}${sysconfdir}/init.d @@ -119,11 +121,13 @@ do_install () { ln -sf ../init.d/checkroot.sh ${D}${sysconfdir}/rcS.d/S10checkroot.sh # ln -sf ../init.d/checkfs.sh ${D}${sysconfdir}/rcS.d/S30checkfs.sh ln -sf ../init.d/mountall.sh ${D}${sysconfdir}/rcS.d/S35mountall.sh + ln -sf ../init.d/readonly-rootfs-hook.sh ${D}${sysconfdir}/rcS.d/S36readonly-rootfs-hook ln -sf ../init.d/hostname.sh ${D}${sysconfdir}/rcS.d/S39hostname.sh ln -sf ../init.d/mountnfs.sh ${D}${sysconfdir}/rcS.d/S45mountnfs.sh ln -sf ../init.d/bootmisc.sh ${D}${sysconfdir}/rcS.d/S55bootmisc.sh # ln -sf ../init.d/urandom ${D}${sysconfdir}/rcS.d/S55urandom # ln -sf ../init.d/finish.sh ${D}${sysconfdir}/rcS.d/S99finish.sh + ln -sf ../init.d/readonly-rootfs-hook.sh ${D}${sysconfdir}/rcS.d/S99stop-readonly-rootfs-hook ln -sf ../init.d/sysfs.sh ${D}${sysconfdir}/rcS.d/S02sysfs.sh # udev will run at S03 if installed ln -sf ../init.d/populate-volatile.sh ${D}${sysconfdir}/rcS.d/S37populate-volatile.sh -- 1.7.5.4
merged into poky/master: d823759b4594143d522eae0b2a2498436a6dcb1e http://git.openembedded.org/?p=openembedded-core.git&a=commit;h=05182ee354a9f773c8ab2f4cd7f1fdf552e7fcda
Verified with commit 410d1e049a1933c44b29416f3ac833ed001f8248, adding read-only-rootfs to EXTRA_IMAGE_FEATURES, build core-image-sato, the root fs is indeed read only.