Move all files to /run/initramfs
authorHarald Hoyer <harald@redhat.com>
Mon, 11 Apr 2011 15:19:41 +0000 (17:19 +0200)
committerHarald Hoyer <harald@redhat.com>
Tue, 12 Apr 2011 10:08:50 +0000 (12:08 +0200)
Given that we boot into a modern Linux distribution with the "/run" toplevel
directory, we can easily mount move the whole /run directory to the real
root in the end and have the complete initramfs later on in
/run/initramfs. All log files and /run states are still accessible and
to save space /run/initramfs can be removed later on.

Because the kernel does not mount a tmpfs on /run prior to unpacking the
initramfs cpio image, we have to copy ourselves very early to a tmpfs
and mount it on /run.
Due to lazy umount the old initramfs binaries should
be removed in the end by switch_root.

This feature can be turned on with "--prefix".

dracut
dracut.8.xml
modules.d/45ifcfg/write-ifcfg.sh
modules.d/90mdraid/mdmon-pre-udev.sh
modules.d/99base/init

diff --git a/dracut b/dracut
index 92fb40a..544f4b5 100755 (executable)
--- a/dracut
+++ b/dracut
@@ -53,6 +53,9 @@ Creates initial ramdisk images for preloading modules
   --no-kernel           Do not install kernel drivers and firmware files
   --strip               Strip binaries in the initramfs
   --nostrip             Do not strip binaries in the initramfs (default)
+  --prefix              Prefix initramfs files with /run/initramfs/
+  --noprefix            Do not prefix initramfs files with /run/initramfs/ 
+                        (default)
   --mdadmconf           Include local /etc/mdadm.conf
   --nomdadmconf         Do not include local /etc/mdadm.conf
   --lvmconf             Include local /etc/lvm/lvm.conf
@@ -211,6 +214,8 @@ while (($# > 0)); do
         --no-kernel)   kernel_only="no"; no_kernel="yes";;
         --strip)       do_strip_l="yes";;
         --nostrip)     do_strip_l="no";;
+        --prefix)      do_prefix_l="yes";;
+        --noprefix)    do_prefix_l="no";;
         --mdadmconf)   mdadmconf_l="yes";;
         --nomdadmconf) mdadmconf_l="no";;
         --lvmconf)     lvmconf_l="yes";;
@@ -345,6 +350,7 @@ stdloglvl=$((stdloglvl + verbosity_mod_l))
 
 [[ $drivers_dir_l ]] && drivers_dir=$drivers_dir_l
 [[ $do_strip_l ]] && do_strip=$do_strip_l
+[[ $do_prefix_l ]] && do_prefix=$do_prefix_l
 [[ $hostonly_l ]] && hostonly=$hostonly_l
 [[ $use_fstab_l ]] && use_fstab=$use_fstab_l
 [[ $mdadmconf_l ]] && mdadmconf=$mdadmconf_l
@@ -352,6 +358,7 @@ stdloglvl=$((stdloglvl + verbosity_mod_l))
 [[ $dracutbasedir ]] || dracutbasedir=/usr/share/dracut
 [[ $fw_dir ]] || fw_dir="/lib/firmware/updates /lib/firmware"
 [[ $do_strip ]] || do_strip=no
+[[ $do_prefix ]] || do_prefix=no
 [[ $compress_l ]] && compress=$compress_l
 [[ $show_modules_l ]] && show_modules=$show_modules_l
 # eliminate IFS hackery when messing with fw_dir
@@ -463,12 +470,27 @@ export initdir dracutbasedir dracutmodules drivers \
     stdloglvl sysloglvl fileloglvl kmsgloglvl logfile \
     debug
 
+[[ $do_prefix = yes ]] && PREFIX=/run/initramfs
+
+# Create some directory structure first
+[[ $PREFIX ]] && mkdir -m 0755 -p "${initdir}${PREFIX}"
+
+mkdir -m 0755 -p "${initdir}${PREFIX}/lib"
+[[ $PREFIX ]] && ln -sfn "${PREFIX#/}/lib" "$initdir/lib"
+
 if [[ $kernel_only != yes ]]; then
-    # Create some directory structure first
-    for d in bin sbin usr/bin usr/sbin usr/lib etc \
-        proc sys sysroot tmp dev/pts var/run; do 
-        inst_dir "/$d"; 
+    for d in bin etc lib "$libdir" sbin tmp usr var; do 
+        [[ -e "${initdir}${PREFIX}/$d" ]] && continue
+        mkdir -m 0755 -p "${initdir}${PREFIX}/$d"
+        [[ $PREFIX ]] && ln -sfn "${PREFIX#/}/${d#/}" "$initdir/$d"
+    done    
+
+    for d in proc sys sysroot root run run/lock run/initramfs; do 
+        mkdir -m 0755 -p "$initdir/$d"; 
     done
+
+    ln -sfn /run "$initdir/var/run"
+    ln -sfn /run/lock "$initdir/var/lock"
 fi
 
 # check all our modules to see if they should be sourced.
@@ -509,9 +531,23 @@ while pop include_src src && pop include_target tgt; do
         if [[ -f $src ]]; then
             inst $src $tgt
         else
-            ddebug "Including directory: $src"
+            ddebug "Including directory: $src"            
             mkdir -p "${initdir}/${tgt}"
-            cp -a -t "${initdir}/${tgt}" "$src"/*
+            # check for preexisting symlinks, so we can cope with the
+            # symlinks to $PREFIX
+            for i in "$src"/*; do
+                [[ -e "$i" || -h "$i" ]] || continue
+                s=${initdir}/${tgt}/${i#$src/}
+                if [[ -d "$i" ]]; then
+                    if ! [[ -e "$s" ]]; then
+                        mkdir -m 0755 -p "$s"
+                        chmod --reference="$i" "$s"
+                    fi
+                    cp -a -t "$s" "$i"/*
+                else
+                    cp -a -t "$s" "$i"
+                fi                
+            done
         fi
     fi
 done
index f915b7d..4663d70 100644 (file)
@@ -236,6 +236,22 @@ include in the generic initramfs. This parameter can be specified multiple times
         </varlistentry>
         <varlistentry>
           <term>
+            <option>--prefix</option>
+          </term>
+          <listitem>
+            <para>prefix initramfs files with /run/initramfs/</para>
+          </listitem>
+        </varlistentry>
+        <varlistentry>
+          <term>
+            <option>--noprefix</option>
+          </term>
+          <listitem>
+            <para>do not prefix initramfs files with /run/initramfs/ (default)</para>
+          </listitem>
+        </varlistentry>
+        <varlistentry>
+          <term>
             <option>-h</option>
           </term>
           <term>
index fb88318..f495e24 100755 (executable)
@@ -134,9 +134,11 @@ for netif in $IFACES ; do
 done
 
 # Pass network opts
-mkdir -m 0755 -p /run/initramfs
+[ -d /run/initramfs ] || mkdir -m 0755 -p /run/initramfs
 cp /tmp/net.* /run/initramfs/ >/dev/null 2>&1
-mkdir -m 0755 -p /run/initramfs/state/etc/sysconfig/network-scripts/
+for i in /run/initramfs/state /run/initramfs/state/etc/ /run/initramfs/state/etc/sysconfig /run/initramfs/state/etc/sysconfig/network-scripts; do
+    [ -d $i ] || mkdir -m 0755 -p $i
+done
 cp /tmp/net.$netif.resolv.conf /run/initramfs/state/etc/ >/dev/null 2>&1
 echo "files /etc/sysconfig/network-scripts" > /run/initramfs/rwtab
-cp -a /tmp/ifcfg/* /run/initramfs/state/etc/sysconfig/network-scripts/ >/dev/null 2>&1
+cp -a -t /run/initramfs/state/etc/sysconfig/network-scripts/ /tmp/ifcfg/* >/dev/null 2>&1
index e38163b..676e69b 100755 (executable)
@@ -2,5 +2,5 @@
 # -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
 # ex: ts=8 sw=4 sts=4 et filetype=sh
 # save state dir for mdmon/mdadm for the real root
-mkdir -m 0755 /run/mdadm
+[ -d /run/mdadm ] || mkdir -m 0755 /run/mdadm
 # backward compat link
index f0445e7..3569f0b 100755 (executable)
@@ -98,9 +98,12 @@ else
     unset _tmp
 fi
 
-if [ ! -c /dev/ptmx ]; then
+ismounted sys || \
+    mount -t sysfs -o nosuid,noexec,nodev /sys /sys >/dev/null 2>&1
+
+if ! ismounted /dev; then
     # try to mount devtmpfs
-    if ! mount -t devtmpfs -o mode=0755,nosuid udev /dev >/dev/null 2>&1; then
+    if ! mount -t devtmpfs -o mode=0755,nosuid,noexec,nosuid udev /dev >/dev/null 2>&1; then
         # if it failed fall back to normal tmpfs
         mount -t tmpfs -o mode=0755,nosuid udev /dev >/dev/null 2>&1 
         # Make some basic devices first, let udev handle the rest
@@ -112,17 +115,28 @@ if [ ! -c /dev/ptmx ]; then
 fi
 
 # prepare the /dev directory
-ln -s /proc/self/fd /dev/fd >/dev/null 2>&1
-ln -s /proc/self/fd/0 /dev/stdin >/dev/null 2>&1
-ln -s /proc/self/fd/1 /dev/stdout >/dev/null 2>&1
-ln -s /proc/self/fd/2 /dev/stderr >/dev/null 2>&1
-mkdir -m 0755 /dev/shm /dev/pts /run 
-mount -t devpts -o gid=5,mode=620,noexec,nosuid devpts /dev/pts >/dev/null 2>&1
-mount -t tmpfs -o mode=1777,nosuid,nodev  tmpfs /dev/shm >/dev/null 2>&1
-# create /run which will obsolete /var/run
-mount -t tmpfs -o mode=0755,nodev,noexec,nosuid tmpfs /run >/dev/null 2>&1
-
-mkdir -m 0755 /run/initramfs
+[ ! -h /dev/fd ] && ln -s /proc/self/fd /dev/fd >/dev/null 2>&1
+[ ! -h /dev/stdin ] && ln -s /proc/self/fd/0 /dev/stdin >/dev/null 2>&1
+[ ! -h /dev/stdout ] && ln -s /proc/self/fd/1 /dev/stdout >/dev/null 2>&1
+[ ! -h /dev/stderr ] && ln -s /proc/self/fd/2 /dev/stderr >/dev/null 2>&1
+
+if ! ismounted /dev/pts; then
+    mkdir -m 0755 /dev/pts
+    mount -t devpts -o gid=5,mode=620,noexec,nosuid devpts /dev/pts >/dev/null 2>&1
+fi
+
+if ! ismounted /dev/shm; then
+    mkdir -m 0755 /dev/shm
+    mount -t tmpfs -o mode=1777,nosuid,nodev  tmpfs /dev/shm >/dev/null 2>&1
+fi
+
+if ! ismounted /run; then
+    mkdir -m 0755 /newrun
+    mount -t tmpfs -o mode=0755,nosuid,nodev tmpfs /newrun >/dev/null 2>&1
+    cp -a -t /newrun /run/*
+    mount --move /newrun /run
+    rm -fr /newrun
+fi
 
 UDEVVERSION=$(udevadm --version)
 if [ $UDEVVERSION -gt 166 ]; then
@@ -133,15 +147,6 @@ else
     export UDEVRULESD=/dev/.udev/rules.d
 fi
 
-[ -e /var/run ] &&  mv /var/run /var/run.bak
-[ -e /var/lock ] &&  mv /var/lock /var/lock.bak
-ln -fs /run /var/run
-mkdir -m 0755 /run/lock
-ln -fs /run/lock /var/lock
-# copy over any possible directory structure
-cp -ar /var/run.bak/* /run/ 2>/dev/null
-cp -ar /var/lock.bak/* /run/lock/ 2>/dev/null
-
 if [ "$RD_DEBUG" = "yes" ]; then
     mkfifo /run/initramfs/loginit.pipe
     loginit $DRACUT_QUIET </run/initramfs/loginit.pipe >/dev/console 2>&1 &
@@ -374,31 +379,44 @@ else
         esac
     done
 fi
+[ "$RD_DEBUG" = "yes" ] && set -x
+if [ -d "$NEWROOT"/run ]; then
+    NEWRUN="${NEWROOT}/run"
+    mount --bind /run "$NEWRUN"
+    NEWINITRAMFSROOT="$NEWRUN/initramfs"
 
-info "Switching root"
+    if [ "$NEWINITRAMFSROOT/lib" -ef "/lib" ]; then
+        for d in bin etc lib lib64 sbin tmp usr var; do 
+            [ -h /$d ] && ln -fsn $NEWINITRAMFSROOT/$d /$d
+        done
+    fi
+else
+    NEWRUN=/dev/.initramfs
+    mkdir -m 0755 "$NEWRUN"
+    mount --bind /run/initramfs "$NEWRUN"
+fi
 
 wait_for_loginit
+info "Switching root"
+umount -l /run
 
-if [ -d "$NEWROOT"/run ]; then
-    mount --move /run "$NEWROOT"/run
-else
-    if [ -e /run/initramfs ]; then
-        cp -axr /run/initramfs /dev/.initramfs >/dev/null 2>&1
-        if [ -e /run/initramfs/live ]; then
-            mkdir -m 0755 /dev/.initramfs/live
-            mount --move /run/initramfs/live /dev/.initramfs/live
-        fi
-    fi
-    umount -l /run
-fi
+unset PS4
 
-export PATH="$OLD_PATH"
+CAPSH=$(command -v capsh)
+SWITCH_ROOT=$(command -v switch_root)
+PATH=$OLDPATH
+export PATH
 
 if [ -f /etc/capsdrop ]; then
     . /etc/capsdrop
     info "Calling $INIT with capabilities $CAPS_INIT_DROP dropped."
     unset RD_DEBUG
-    exec /usr/sbin/capsh --drop="$CAPS_INIT_DROP" -- -c "exec /sbin/switch_root \"$NEWROOT\" \"$INIT\" $initargs" || {
+    exec $CAPSH --drop="$CAPS_INIT_DROP" -- \
+        -c "exec switch_root \"$NEWROOT\" \"$INIT\" $initargs" || \
+    {
        warn "Command:"
        warn capsh --drop=$CAPS_INIT_DROP -- -c exec switch_root "$NEWROOT" "$INIT" $initargs
        warn "failed."
@@ -406,7 +424,7 @@ if [ -f /etc/capsdrop ]; then
     }
 else
     unset RD_DEBUG
-    exec /sbin/switch_root "$NEWROOT" "$INIT" $initargs || {
+    exec $SWITCH_ROOT "$NEWROOT" "$INIT" $initargs || {
        warn "Something went very badly wrong in the initramfs.  Please "
        warn "file a bug against dracut."
        emergency_shell