[RFC] features: RUNDIR, imgdir, prefix, prefix_mnt and related changes

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



1) $prefix, $prefix_mnt

The prefix itself (and new prefix_mnt option) is used only during /run --move
(pre-pivot, preiously --bind), while internally - dracut files and /run are
kept _separately_ in $imgdir and $rundir.

$prefix is sanitized before use, and its final (adjusted) value is always
relative to /run (not being under /run has little point). If user provided
$prefix doesn't start with /run, or consists only of /run - it's assumed to be
/run relative. Otherwise (2 or more components and beginning with /run) it's
assumed to be absolute.

$prefix_mnt allows us to request tmpfs mount at $newrun/$prefix, before copying
dracut tree.

2) $RUNDIR (inside init only), $imgdir

The crux of changes are these two. Internal split, which previously was based
on $prefix is now based on $imgdir. All /run references from $imgdir point to
/run, which inside init is adjusted to /run -> $RUNDIR. All tmp references
point to just initramfs root's /tmp (as we don't care about the junk after
pivot).

This gives us decoupled runtime tree and dracut image tree. The latter can be
installed if $prefix is set or completely ignored. runtime is always --moved.
Furthermore, $RUNDIR is symlinked from run, so it can be easily kept fully
functional, with trivial symlink adjustment.

Everything in imgdir is symlinked from initramfs's root (similary as it's been
done until now).

All inst*() functions are aware of $imgdir; imgdir, prefix, prefix_mnt and
newroot are exported, and also available in init (after uppercasing, sourced
from simple config file).

Of course, /tmp and /run stuff has to be set differently during installation
phase (e.g. ..../var/run -> ${initdir}/run, etc.) and differenty during
initramfs execution (e.g. ..../var/run -> /run). In dracut script, it's
respectively "initial sewing pass" and "final sewing pass". The latter one also
verifies if all symlinks are valid.

This way of handling $prefix opens path to making it runtime argument (e.g.
rd.prefix).

3) /run ($RUNDIR) move

/run is moved to either $NEWROOT/run or if not possible - to /dev/.run (with
/dev/.initramfs -> .run/initramfs symlink). If $prefix is specified, contents
of $imgdir are copied to the $NEWRUN/$prefix or alternatively (if $prefix_mnt
is set), tmpfs is mounted at $NEWRUN/$prefix and then the $imgdir is copied;
init will refuse overmount, if the directory is already present.

4) udev and /dev/.udev vs /run/udev

There's possibility, that sufficiently new udev will prefer /run during
initramfs stage, while host may still be not run ready. This might lead to
losing certain db entries (e.g. lvm's). If we detect such situation, contents
of /run/udev are moved to /dev/.udev before pivoting.

5) enforcing options of premounted directories

For special directories - /proc, /sys, etc. - as we should assure that the
actual mount options are sane. Though the only realistically pre-mountable
thing is /dev (for now at least).

6) other smaller changes:

 - copying cp -a -t <dst> . after cd <src>, instead of <dst> <src>/* - as this
   also handles .* files (otherwise we would have to tinker with some crude
   globbing and/or dotglob)
 - We don't try to mimic host's directory layout anymore (if some directories
   are symlinked, which is rarely the case either way and serves little
   purpose)
 - removed certain mkdirs, that are guaranteed to be handled by dracut

---
 dracut                           |  115 +++++++++++++++++++------------
 dracut-functions                 |   50 +++++++-------
 modules.d/99base/init            |  137 ++++++++++++++++++++++++--------------
 modules.d/99base/module-setup.sh |   13 ++--
 4 files changed, 189 insertions(+), 126 deletions(-)

diff --git a/dracut b/dracut
index 205f5d1..1d5f2f4 100755
--- a/dracut
+++ b/dracut
@@ -53,7 +53,11 @@ 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 [DIR]        Prefix initramfs files with [DIR]
+  --prefix [DIR]        Prefix initramfs files with [DIR]. If DIR doesn't
+                        start with /run (or if it's the only component), it's
+                        assumed to be relative to /run.
+  --prefix_mnt          Copy initramfs into additional tmpfs mount, instead of
+                        directly into prefix subdirectory.
   --noprefix            Do not prefix initramfs files (default)
   --mdadmconf           Include local /etc/mdadm.conf
   --nomdadmconf         Do not include local /etc/mdadm.conf
@@ -222,6 +226,7 @@ while (($# > 0)); do
         --strip)       do_strip_l="yes";;
         --nostrip)     do_strip_l="no";;
         --noprefix)    prefix_l="/";;
+        --prefix_mnt)  prefix_mnt_l="yes";;
         --mdadmconf)   mdadmconf_l="yes";;
         --nomdadmconf) mdadmconf_l="no";;
         --lvmconf)     lvmconf_l="yes";;
@@ -378,8 +383,6 @@ stdloglvl=$((stdloglvl + verbosity_mod_l))
 
 [[ $drivers_dir_l ]] && drivers_dir=$drivers_dir_l
 [[ $do_strip_l ]] && do_strip=$do_strip_l
-[[ $prefix_l ]] && prefix=$prefix_l
-[[ $prefix = "/" ]] && unset prefix
 [[ $hostonly_l ]] && hostonly=$hostonly_l
 [[ $use_fstab_l ]] && use_fstab=$use_fstab_l
 [[ $mdadmconf_l ]] && mdadmconf=$mdadmconf_l
@@ -390,6 +393,7 @@ stdloglvl=$((stdloglvl + verbosity_mod_l))
 [[ $compress_l ]] && compress=$compress_l
 [[ $show_modules_l ]] && show_modules=$show_modules_l
 [[ $nofscks_l ]] && nofscks="yes"
+[[ $prefix_mnt_l ]] && prefix_mnt="yes"
 # eliminate IFS hackery when messing with fw_dir
 fw_dir=${fw_dir//:/ }
 
@@ -428,6 +432,19 @@ fi
 dracutfunctions=$dracutbasedir/dracut-functions
 export dracutfunctions
 
+# sanitize and handle prefix.
+# If /run is the only component, or if $prefix_l doesn't start with /run, then
+# the path is assumed to be relative to /run, otherwise it's absolute.
+# Final prefix is always set as relative to /run
+if [[ "$prefix_l" =~ [[:alnum:]] ]]; then
+    prefix=$(normalize_path "/$prefix_l")
+    prefix=${prefix#/}
+    prefix=${prefix#run/}
+else
+    unset prefix
+    unset prefix_mnt
+fi
+
 ddebug "Executing $0 $dracut_args"
 
 [[ $do_list = yes ]] && {
@@ -494,6 +511,7 @@ readonly initdir=$(mktemp --tmpdir=/var/tmp/ -d -t initramfs.XXXXXX)
     dfatal "mktemp failed."
     exit 1
 }
+readonly imgdir=/_img newroot=/sysroot
 
 # clean up after ourselves no matter how we die.
 trap 'ret=$?;[[ $keep ]] && echo "Not removing $initdir." >&2 || rm -rf "$initdir";exit $ret;' EXIT
@@ -508,48 +526,30 @@ export initdir dracutbasedir dracutmodules drivers \
     add_drivers mdadmconf lvmconf filesystems \
     use_fstab libdir usrlibdir fscks nofscks \
     stdloglvl sysloglvl fileloglvl kmsgloglvl logfile \
-    debug
-
-# Create some directory structure first
-[[ $prefix ]] && mkdir -m 0755 -p "${initdir}${prefix}"
-
-[[ -h /lib ]] || mkdir -m 0755 -p "${initdir}${prefix}/lib"
-[[ $prefix ]] && ln -sfn "${prefix#/}/lib" "$initdir/lib"
-
-if [[ $prefix ]]; then
-    for d in bin etc lib "$libdir" sbin tmp usr var; do
-        ln -sfn "${prefix#/}/${d#/}" "$initdir/$d"
-    done
-fi
+    debug imgdir prefix prefix_mnt newroot
 
+# initial directory layout + host safe symlinks
 if [[ $kernel_only != yes ]]; then
-    for d in bin etc lib "$libdir" sbin tmp usr var usr/bin usr/sbin; do
-        [[ -e "${initdir}${prefix}/$d" ]] && continue
-        if [ -h "/$d" ]; then
-            inst "/$d" "${prefix}/$d"
-        else
-            mkdir -m 0755 -p "${initdir}${prefix}/$d"
-        fi
-    done
-
-    for d in dev proc sys sysroot root run run/lock run/initramfs; do
-        if [ -h "/$d" ]; then
-            inst "/$d"
-        else
-            mkdir -m 0755 -p "$initdir/$d"
-        fi
+    mkdir -m 0755 -p \
+        "${initdir}${imgdir}"/{bin,etc,lib,${libdir#/},sbin,var,usr/{bin,sbin}} \
+        "${initdir}"/{dev,proc,sys,${newroot#/},root,run/{lock,initramfs},tmp}
+
+    # host safe symlinks (will be adjusted later), needed during inst*() calls
+    ln -sfn "${initdir}"/tmp      "${initdir}${imgdir}"/tmp
+    ln -sfn "${initdir}"/tmp      "${initdir}${imgdir}"/var/tmp
+    ln -sfn "${initdir}"/run      "${initdir}${imgdir}"/run
+    ln -sfn "${initdir}"/run      "${initdir}${imgdir}"/var/run
+    ln -sfn "${initdir}"/run/lock "${initdir}${imgdir}"/var/lock
+    # initial sewing pass
+    for d in bin etc lib "${libdir#/}" sbin var usr; do
+        ln -sfn "${imgdir#/}/$d" "${initdir}/$d"
     done
-
-    ln -sfn /run "$initdir/var/run"
-    ln -sfn /run/lock "$initdir/var/lock"
 else
-    for d in lib "$libdir"; do
-        [[ -e "${initdir}${prefix}/$d" ]] && continue
-        if [ -h "/$d" ]; then
-            inst "/$d" "${prefix}/$d"
-        else
-            mkdir -m 0755 -p "${initdir}${prefix}/$d"
-        fi
+    mkdir -m 0755 -p "${initdir}${imgdir}/"{lib,${libdir#/}}
+
+    # initial sewing pass
+    for d in lib "${libdir#/}"; do
+        ln -sfn "${imgdir#/}/$d" "${initdir}/$d"
     done
 fi
 
@@ -593,18 +593,20 @@ while pop include_src src && pop include_target tgt; do
             inst $src $tgt
         else
             ddebug "Including directory: $src"
-            mkdir -p "${initdir}/${tgt}"
+            mkdir -p "${initdir}${imgdir}/${tgt}"
             # 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/}
+                s=${initdir}${imgdir}/${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"/*
+                    pushd "$i" &>/dev/null
+                    cp -a -t "$s" .
+                    popd &>/dev/null
                 else
                     cp -a -t "$s" "$i"
                 fi
@@ -620,7 +622,6 @@ while pop install_items items; do
 done
 unset item
 
-
 if [[ $kernel_only != yes ]]; then
     # make sure that library links are correct and up to date
     for f in /etc/ld.so.conf /etc/ld.so.conf.d/*; do
@@ -672,6 +673,30 @@ if strstr "$modules_loaded" " fips " && command -v prelink >/dev/null; then
     done
 fi
 
+# final sewing pass
+# remove helper /run & /tmp links, set symlinks to match initramfs's root, link
+# remaining directories (if any)
+if [[ $kernel_only != yes ]]; then
+    rm -f             "${initdir}${imgdir}"/{run,tmp}
+    ln -sfn /tmp      "${initdir}${imgdir}"/var/tmp
+    ln -sfn /run      "${initdir}${imgdir}"/var/run
+    ln -sfn /run/lock "${initdir}${imgdir}"/var/lock
+fi
+for d in "${initdir}${imgdir}"/*; do
+    s="${initdir}/${d##*/}"
+    if [[ -h ${s} ]]; then
+        # verify if everything is fine
+        t=$(readlink -e "${s}")
+        if [[ $t != $d ]]; then
+            dfatal "dracut: symlink mismatch ${d##*/} -/-> ${d#${initdir}/}"
+            exit 1
+        fi
+    else
+        ln -sfn "${imgdir#/}/${d##*/}" "${s}"
+    fi
+done
+
+# create the image
 if ! ( cd "$initdir"; find . |cpio -R 0:0 -H newc -o --quiet| \
     $compress > "$outfile"; ); then
     dfatal "dracut: creation of $outfile failed"
diff --git a/dracut-functions b/dracut-functions
index 1ef5269..3b971c7 100755
--- a/dracut-functions
+++ b/dracut-functions
@@ -269,13 +269,13 @@ check_vol_slaves() {
 
 # Install a directory, keeping symlinks as on the original system.
 # Example: if /lib points to /lib64 on the host, "inst_dir /lib/file"
-# will create ${initdir}/lib64, ${initdir}/lib64/file,
-# and a symlink ${initdir}/lib -> lib64.
+# will create ${initdir}${imgdir}/lib64, ${initdir}${imgdir}/lib64/file,
+# and a symlink ${initdir}${imgdir}/lib -> lib64.
 inst_dir() {
-    [[ -e ${initdir}"$1" ]] && return 0  # already there
+    [[ -e ${initdir}${imgdir}"$1" ]] && return 0  # already there
 
     local _dir="$1" _part="${1%/*}" _file
-    while [[ "$_part" != "${_part%/*}" ]] && ! [[ -e "${initdir}${_part}" ]]; do
+    while [[ "$_part" != "${_part%/*}" ]] && ! [[ -e "${initdir}${imgdir}${_part}" ]]; do
         _dir="$_part $_dir"
         _part=${_part%/*}
     done
@@ -290,12 +290,12 @@ inst_dir() {
             inst_dir "$target"
             inst_symlink "$_file"
         else
-            [[ -h ${initdir}$_file ]] && _file=$(readlink "${initdir}$_file")
+            [[ -h ${initdir}${imgdir}$_file ]] && _file=$(readlink "${initdir}${imgdir}$_file")
             # create directory
-            mkdir -m 0755 -p "${initdir}$_file" || return 1
+            mkdir -m 0755 -p "${initdir}${imgdir}$_file" || return 1
             if [[ -d "$_file" ]]; then
-                chmod --reference="$_file" "${initdir}$_file"
-                chmod u+w "${initdir}$_file"
+                chmod --reference="$_file" "${initdir}${imgdir}$_file"
+                chmod u+w "${initdir}${imgdir}$_file"
             fi
         fi
     done
@@ -303,15 +303,15 @@ inst_dir() {
 
 # $1 = file to copy to ramdisk
 # $2 (optional) Name for the file on the ramdisk
-# Location of the image dir is assumed to be $initdir
+# Location of the image dir is assumed to be ${initdir}${imgdir}
 # We never overwrite the target if it exists.
 inst_simple() {
     [[ -f $1 ]] || return 1
 
     local _src=$1 target="${2:-$1}"
-    if ! [[ -d ${initdir}$target ]]; then
-        [[ -e ${initdir}$target ]] && return 0
-        [[ -h ${initdir}$target ]] && return 0
+    if ! [[ -d ${initdir}${imgdir}$target ]]; then
+        [[ -e ${initdir}${imgdir}$target ]] && return 0
+        [[ -h ${initdir}${imgdir}$target ]] && return 0
         inst_dir "${target%/*}"
     fi
     # install checksum files also
@@ -319,7 +319,7 @@ inst_simple() {
         inst "${_src%/*}/.${_src##*/}.hmac" "${target%/*}/.${target##*/}.hmac"
     fi
     ddebug "Installing $_src"
-    cp --sparse=always -pfL "$_src" "${initdir}$target" 
+    cp --sparse=always -pfL "$_src" "${initdir}${imgdir}$target"
 }
 
 # find symlinks linked to given library file
@@ -352,7 +352,7 @@ rev_lib_symlinks() {
 # is referenced.
 inst_library() {
     local _src=$1 _dest=${2:-$1} _lib _reallib _symlink
-    [[ -e $initdir$_dest ]] && return 0
+    [[ -e ${initdir}${imgdir}$_dest ]] && return 0
     if [[ -L $_src ]]; then
         # install checksum files also
         if [[ -e "${_src%/*}/.${_src##*/}.hmac" ]]; then
@@ -361,14 +361,14 @@ inst_library() {
         _reallib=$(readlink -f "$_src")
         inst_simple "$_reallib" "$_reallib"
         inst_dir "${_dest%/*}"
-        ln -sfn $(convert_abs_rel "${_dest}" "${_reallib}") "${initdir}${_dest}"
+        ln -sfn $(convert_abs_rel "${_dest}" "${_reallib}") "${initdir}${imgdir}${_dest}"
     else
         inst_simple "$_src" "$_dest"
     fi
 
     # Create additional symlinks.  See rev_symlinks description.
     for _symlink in $(rev_lib_symlinks $_src) $(rev_lib_symlinks $_reallib); do
-        [[ ! -e $initdir$_symlink ]] && {
+        [[ ! -e ${initdir}${imgdir}$_symlink ]] && {
             ddebug "Creating extra symlink: $_symlink"
             inst_symlink $_symlink
         }
@@ -396,7 +396,7 @@ inst_binary() {
     _bin=$(find_binary "$1") || return 1
     _target=${2:-$_bin}
     inst_symlink $_bin $_target && return 0
-    [[ -e $initdir$_target ]] && return 0
+    [[ -e ${initdir}${imgdir}$_target ]] && return 0
 
     # If the binary being installed is also a library, add it to the loop.
     _so_regex='([^ ]*/lib[^/]*/[^ ]*\.so[^ ]*)'
@@ -414,7 +414,7 @@ inst_binary() {
         fi
         [[ $_line =~ $_so_regex ]] || continue
         _file=${BASH_REMATCH[1]}
-        [[ -e ${initdir}$_file ]] && continue
+        [[ -e ${initdir}${imgdir}$_file ]] && continue
 
         # See if we are loading an optimized version of a shared lib.
         if [[ $_file =~ $_lib_regex ]]; then
@@ -451,7 +451,7 @@ inst_script() {
 
 # same as above, but specialized for symlinks
 inst_symlink() {
-    local _src=$1 _target=$initdir${2:-$1} _realsrc
+    local _src=$1 _target=${initdir}${imgdir}${2:-$1} _realsrc
     [[ -L $1 ]] || return 1
     [[ -L $_target ]] && return 0
     _realsrc=$(readlink -f "$_src")
@@ -459,7 +459,7 @@ inst_symlink() {
     if [[ -d $_realsrc ]]; then
         inst_dir "$_realsrc"
     else
-        inst "$_realsrc" && mkdir -m 0755 -p "${_target%/*}" 
+        inst "$_realsrc" && mkdir -m 0755 -p "${_target%/*}"
     fi
     if [[ -e "${_src}" ]]; then
         ln -sfn $(convert_abs_rel "${_src}" "${_realsrc}") "$_target"
@@ -604,9 +604,9 @@ inst_decompress() {
             _realsrc="$(readlink -f ${_src})" # symlink target with extension
             _dst="${_src%.*}" # symlink without extension
             _realdst="${_realsrc%.*}" # symlink target without extension
-            mksubdirs "${initdir}/${_src}"
+            mksubdirs "${initdir}${imgdir}/${_src}"
             # Create symlink without extension to target without extension.
-            ln -sfn "${_realdst}" "${initdir}/${_dst}"
+            ln -sfn "${_realdst}" "${initdir}${imgdir}/${_dst}"
         fi
 
         # If the source is symlink we operate on its target.
@@ -614,7 +614,7 @@ inst_decompress() {
         inst ${_src}
         # Decompress with chosen tool.  We assume that tool changes name e.g.
         # from 'name.gz' to 'name'.
-        ${_cmd} "${initdir}${_src}"
+        ${_cmd} "${initdir}${imgdir}${_src}"
     done
 }
 
@@ -787,7 +787,7 @@ check_module_dir() {
 # $1 = full path to kernel module to install
 install_kmod_with_fw() {
     # no need to go further if the module is already installed
-    [[ -e "${initdir}/lib/modules/$kernel/${1##*/lib/modules/$kernel/}" ]] \
+    [[ -e "${initdir}${imgdir}/lib/modules/$kernel/${1##*/lib/modules/$kernel/}" ]] \
         && return 0
     inst_simple "$1" "/lib/modules/$kernel/${1##*/lib/modules/$kernel/}" \
         || return $?
@@ -915,7 +915,7 @@ instmods() {
 
                 # if we are already installed, skip this module and go on
                 # to the next one.
-                [[ -f $initdir/$1 ]] && return
+                [[ -f ${initdir}${imgdir}/$1 ]] && return
 
                 # If we are building a host-specific initramfs and this
                 # module is not already loaded, move on to the next one.
diff --git a/modules.d/99base/init b/modules.d/99base/init
index 06d61a8..0970a48 100755
--- a/modules.d/99base/init
+++ b/modules.d/99base/init
@@ -66,25 +66,31 @@ emergency_shell()
     fi
 }
 
-NEWROOT="/sysroot"
-[ -d $NEWROOT ] || mkdir -p -m 0755 $NEWROOT
-
 trap "emergency_shell Signal caught!" 0
 OLDPATH=$PATH
 PATH=/usr/sbin:/usr/bin:/sbin:/bin
 export PATH
 
 RD_DEBUG=""
+. /etc/dracut-init.conf
 . /lib/dracut-lib.sh
 
 [ -c /dev/null ] || mknod -m 0666 /dev/null c 1 3
 
-# mount some important things
-[ ! -d /proc/self ] && \
-    mount -t proc -o nosuid,noexec,nodev proc /proc >/dev/null 2>&1
+# mount some important things; if something is already mounted,
+# we sanitize mount options by remounting
+# note: although -t would be ignored during remount, we play
+# it safe and make sure -t is not specified in such case
+# note: at this point, only /dev can be premounted by kernel, so
+# maybe just skip those checks altogether ?
+
+_opt="-o nosuid,noexec,nodev"; _fs="-t proc"
+[ -d /proc/self ] && { _opt="$_opt,remount"; unset _fs; }
+mount $_fs $_opt proc /proc >/dev/null 2>&1
 
-[ ! -d /sys/kernel ] && \
-    mount -t sysfs -o nosuid,noexec,nodev sysfs /sys >/dev/null 2>&1
+_opt="-o nosuid,noexec,nodev"; _fs="-t sysfs"
+[ -d /sys/kernel ] && { _opt="$_opt,remount"; unset _fs; }
+mount $_fs $_opt sysfs /sys >/dev/null 2>&1
 
 if [ -x /lib/systemd/systemd-timestamp ]; then
     RD_TIMESTAMP=$(/lib/systemd/systemd-timestamp)
@@ -101,44 +107,50 @@ if [ "$RD_DEBUG" = "yes" ]; then
     [ -n "$a" ] && [ $a -ge 8 ] && unset DRACUT_QUIET
 fi
 
-if ! ismounted /dev; then
-    # try to mount devtmpfs
-    if ! mount -t devtmpfs -o mode=0755,nosuid devtmpfs /dev >/dev/null 2>&1; then
-        # if it failed fall back to normal tmpfs
-        mount -t tmpfs -o mode=0755,nosuid tmpfs /dev >/dev/null 2>&1
-        # Make some basic devices first, let udev handle the rest
-        mknod -m 0666 /dev/null c 1 3
-        mknod -m 0666 /dev/ptmx c 5 2
-        mknod -m 0600 /dev/console c 5 1
-        mknod -m 0660 /dev/kmsg c 1 11
-    fi
+_opt="-o mode=0755,nosuid,exec"; _fs="-t devtmpfs"
+ismounted /dev && { _opt="$_opt,remount"; unset _fs; }
+if ! mount $_fs $_opt devtmpfs /dev >/dev/null 2>&1; then
+    # if it failed (remount can't fail - no need to redo $_opt), fall back to
+    # normal tmpfs
+    mount -t tmpfs $_opt tmpfs /dev >/dev/null 2>&1
+    # Make some basic devices first, let udev handle the rest
+    mknod -m 0666 /dev/null c 1 3
+    mknod -m 0666 /dev/ptmx c 5 2
+    mknod -m 0600 /dev/console c 5 1
+    mknod -m 0660 /dev/kmsg c 1 11
 fi
 
-# prepare the /dev directory
+# prepare the /dev directory (note: newer udevd takes care of it automatically)
 [ ! -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
-
-[ -d /run/initramfs ] || mkdir -p -m 0755 /run/initramfs
+_opt="-o gid=5,mode=620,noexec,nosuid"; _fs="-t devpts"
+ismounted /dev/pts && { _opt="$_opt,remount"; unset _fs; } || mkdir -m 0755 /dev/pts
+mount $_fs $_opt devpts /dev/pts >/dev/null 2>&1
+
+_opt="-o mode=1777,nosuid,nodev"; _fs="-t tmpfs"
+ismounted /dev/shm && { _opt="$_opt,remount"; unset _fs; } || mkdir -m 0755 /dev/shm
+mount $_fs $_opt tmpfs /dev/shm >/dev/null 2>&1
+
+# Prepare proper tmpfs mount for /run:
+# - /run is just a symlink to real staging area. This allows us to be
+#   independent from any mount place, with trivial symlink manipulation
+# - checking if /run is premounted, is pretty crazy in initramfs ...
+
+_opt="-o mode=0755,nosuid,nodev,exec"; _fs="-t tmpfs"
+RUNDIR=/_run
+ismounted /run && { _opt="$_opt,remount"; unset _fs; }
+mkdir -m 0755 -p $RUNDIR
+# move + remount or mount
+[ -z "$_fs" ] && mount --move /run $RUNDIR
+mount $_fs $_opt tmpfs $RUNDIR >/dev/null 2>&1
+# copy if mount
+[ -z "$_fs" ] || { cd /run; cp -a -t $RUNDIR .; cd /; }
+# set symlink
+rm -rf /run
+ln -sfn ${RUNDIR#/} /run
 
 UDEVVERSION=$(udevadm --version)
 if [ $UDEVVERSION -gt 166 ]; then
@@ -410,20 +422,43 @@ else
 fi
 [ "$RD_DEBUG" = "yes" ] && set -x
 
-if [ -d "$NEWROOT"/run ]; then
-    NEWRUN="${NEWROOT}/run"
-    mount --bind /run "$NEWRUN"
-    NEWINITRAMFSROOT="$NEWRUN/initramfs"
+# /run move, udev adjustment (if applicable), prefix handling
+if [ -d "$NEWROOT/run" ]; then
+    NEWRUN="$NEWROOT/run"
+else
+    NEWRUN=/dev/.run
+    mkdir -p -m 0755 "$NEWRUN"
+    [ -n "$PREFIX" ] && ln -sfn .run/initramfs /dev/.initramfs
+    # if initramfs's udev uses /run by default, but the host is
+    # still /run-less, we should copy udev's data to legacy
+    # /dev/.udev, so the necessary info is available for the host
+    # (e.g. lvm db entries)
+    if [ -d /run/udev/data -o -d /run/udev/db ]; then
+        mkdir -p -m 0755 /dev/.udev
+        cd /run/udev
+        cp -a -t /dev/.udev .
+        cd /
+        rm -rf /run/udev
+    fi
+fi
 
-    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
+mount --move "$RUNDIR" "$NEWRUN"
+ln -sfn "${NEWRUN#/}" /run
+
+if [ -n "$PREFIX" ]; then
+    if [ -d "$NEWRUN/$PREFIX" ]; then
+        [ -n "$PREFIX_MNT" ] &&
+            warn "'$NEWRUN/$PREFIX' already exists, dracut files will be copied directly to this directory"
+        unset PREFIX_MNT
+    else
+        mkdir -p -m 0755 "$NEWRUN/$PREFIX"
     fi
-else
-    NEWRUN=/dev/.initramfs
-    mkdir -m 0755 "$NEWRUN"
-    mount --bind /run/initramfs "$NEWRUN"
+    if [ -n "$PREFIX_MNT" ]; then
+        mount -t tmpfs -o mode=0755,nosuid,nodev,exec tmpfs "$NEWRUN/$PREFIX"
+    fi
+    cd "$IMGDIR"
+    cp -a -t "$NEWRUN/$PREFIX" .
+    cd /
 fi
 
 wait_for_loginit
diff --git a/modules.d/99base/module-setup.sh b/modules.d/99base/module-setup.sh
index f6dc920..2a9b643 100755
--- a/modules.d/99base/module-setup.sh
+++ b/modules.d/99base/module-setup.sh
@@ -12,7 +12,7 @@ depends() {
 }
 
 install() {
-    local _d
+    local _d _x
     dracut_install mount mknod mkdir modprobe pidof sleep chroot \
         sed ls flock cp mv dmesg rm ln rmmod mkfifo umount readlink
     dracut_install -o less
@@ -25,7 +25,6 @@ install() {
     inst "$moddir/initqueue" "/sbin/initqueue"
     inst "$moddir/loginit" "/sbin/loginit"
 
-    [ -e "${initdir}/lib" ] || mkdir -m 0755 -p ${initdir}/lib
     mkdir -m 0755 -p ${initdir}/lib/dracut
     mkdir -m 0755 -p ${initdir}/lib/dracut/hooks
     for _d in $hookdirs emergency \
@@ -33,13 +32,17 @@ install() {
         mkdir -m 0755 -p ${initdir}/lib/dracut/hooks/$_d
     done
 
-    mkdir -p ${initdir}/tmp
-
     dracut_install switch_root || dfatal "Failed to install switch_root"
 
     inst "$moddir/dracut-lib.sh" "/lib/dracut-lib.sh"
     inst_hook cmdline 10 "$moddir/parse-root-opts.sh"
-    mkdir -p "${initdir}/var"
+
     [ -x /lib/systemd/systemd-timestamp ] && inst /lib/systemd/systemd-timestamp
+
+    # export certain settings to init
+    for _d in newroot imgdir prefix prefix_mnt; do
+        _x=$(echo $_d | tr "a-z" "A-Z")
+        [ -n "$_d" ] && echo "${_x}=${!_d}" >>${initdir}/etc/dracut-init.conf
+    done
 }
 
-- 
1.7.5.3

--
To unsubscribe from this list: send the line "unsubscribe initramfs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Kernel]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux SCSI]

  Powered by Linux