Differences between revisions 1 and 2
Revision 1 as of 2012-12-27 23:05:36
Size: 17965
Editor: RogerLeigh
Comment: Initial description
Revision 2 as of 2012-12-28 11:36:11
Size: 17287
Editor: RogerLeigh
Comment: Remove /etc mounting
Deletions are marked like this. Additions are marked like this.
Line 28: Line 28:
=== Mounting /etc in the initramfs ===

One use case identified in previous discussion was the need to support encrypted filesystems at boot. It's common to keep /usr separate and just encrypt the rootfs for performance reasons. However, the real need is for /etc to be encrypted. With a separate /usr mount no longer making sense, it would therefore be useful to be able to mount /etc encrypted directly in the initramfs, leaving the rootfs and /usr unencrypted.
Line 47: Line 43:

== Additional changes ==

 1. Update initramfs to mount /etc
 1. Update util-linux to skip /etc with the -R option
 1. Update initscripts to fsck /etc in checkroot and remount r/o when shutting down

Mount /usr in the initramfs

Introduction

Traditionally, /usr has been mounted in mountall, as for any filesystem in /etc/fstab other than the root filesystem (or special filesystems like /proc and /dev). This has several implications:

  • Programs, libraries and data under /usr are not available in the early stages of booting
  • Programs in /bin and /sbin can not assume /usr is available
  • init scripts need to cope with /usr being unavailable in early boot
  • This causes particular problems with shared libraries, PAM modules, NSS module dependencies, etc. as well as locale availability.

If /usr could be guaranteed to be available by mounting it in the initramfs, these problems can also be overcome. This permits all shared libraries, PAM modules, NSS modules etc. to function at once. It also allows locales to be used at once as well. Additionally, it is possible to use C++ (libstdc++ is under /usr), and interpreters such as perl and python, etc. In short, it makes a large number of things possible which were previously not possible, and this will both allow greater flexibility in what can run in the early stages of booting, as well as removing a large number of special cases and hairy logic which existed solely to cope with /usr not being available.

Initial implementation

The change to the initramfs is fairly simple. Once the root filesystem is mounted, the /etc/fstab on the root filesystem can be read, and then if it contains an entry for /usr, we mount it.

The -R option of /sbin/fsck, used to check all filesystems except the root filesystem needs updating so that it will also ignore /usr, or else at boot the checkfs script will try to fsck a mounted /usr.

The initscripts themselves need updating to treat /usr like the root filesystem

  • Remount r/o
  • Check
  • Remount r/w
  • Remount r/o at shutdown and don't umount

Caveats

The main caveat is that if you use a separately mounted /usr, you must use an initramfs to mount it. While not using an initramfs will continue to be supported, this will only work if you have /usr on the root filesystem (i.e. it's a single mount). This is because mounting /usr in the traditional way will cause startup to fail since it's mounted too late (this will only happen once init scripts start relying on /usr to be available immediately).

initramfs

No initramfs

root only

Supported

Supported

root and /usr

Supported

Broken

The initramfs will support / and /usr mounts on local/local and nfs/nfs. However, it it not yet clear if this will extend to local/nfs and/or nfs/local.

Required changes

  1. Update initramfs to mount /usr
  2. Update util-linux to skip /usr with the -R option
  3. Update initscripts to fsck /usr in checkroot and remount r/o when shutting down

Patches

initramfs-tools

   1 commit afe1bf2fcbb6e8ef56b99a224b44533811cc6c5a
   2 Author: Roger Leigh <rleigh@debian.org>
   3 Date:   Tue Dec 25 13:25:48 2012 +0000
   4 
   5     Mount /usr in the initramfs
   6 
   7 diff --git a/init b/init
   8 index cb832ff..7a0fc0f 100755
   9 --- a/init
  10 +++ b/init
  11 @@ -217,12 +217,18 @@ run_scripts /scripts/init-premount
  12  
  13  maybe_break mount
  14  log_begin_msg "Mounting root file system"
  15 -. /scripts/${BOOT}
  16 +. /scripts/local
  17 +. /scripts/nfs
  18  parse_numeric ${ROOT}
  19  maybe_break mountroot
  20  mountroot
  21  log_end_msg
  22  
  23 +if read_fstab_entry /usr; then
  24 +    log_begin_msg "Mounting /usr file system"
  25 +    domount unknown /usr
  26 +fi
  27 +
  28  maybe_break bottom
  29  [ "$quiet" != "y" ] && log_begin_msg "Running /scripts/init-bottom"
  30  run_scripts /scripts/init-bottom
  31 diff --git a/scripts/functions b/scripts/functions
  32 index 6e74ade..79506e7 100644
  33 --- a/scripts/functions
  34 +++ b/scripts/functions
  35 @@ -423,3 +423,55 @@ wait_for_udev()
  36         command -v udevadm >/dev/null 2>&1 || return 0
  37         udevadm settle ${1:+--timeout=$1}
  38  }
  39 +
  40 +# Find a specific fstab entry
  41 +# $1=mountpoint
  42 +# $2=fstype (optional)
  43 +# returns 0 on success, 1 on failure (not found or no fstab)
  44 +read_fstab_entry () {
  45 +       # Not found by default.
  46 +       found=1
  47 +
  48 +       for file in ${rootmnt}/etc/fstab; do
  49 +               if [ -f "$file" ]; then
  50 +                       while read MNT_FSNAME MNT_DIR MNT_TYPE MNT_OPTS MNT_FREQ MNT_PASS MNT_JUNK; do
  51 +                               case "$MNT_FSNAME" in
  52 +                                 ""|\#*)
  53 +                                       continue;
  54 +                                       ;;
  55 +                               esac
  56 +                               if [ "$MNT_DIR" = "$1" ]; then
  57 +                                       if [ -n "$2" ]; then
  58 +                                               [ "$MNT_TYPE" = "$2" ] || continue;
  59 +                                       fi
  60 +                                       found=0
  61 +                                       break 2
  62 +                               fi
  63 +                       done < "$file"
  64 +               fi
  65 +       done
  66 +
  67 +       return $found
  68 +}
  69 +
  70 +# Mount a file system.  We parse the information from the fstab.
  71 +# $1=type local|nfs|unknown $2=mountpoint mount location
  72 +domount()
  73 +{
  74 +       read_fstab_entry "$2"
  75 +       mount "-t${MNT_TYPE}" "-o${MNT_OPTS}" "$MNT_FSNAME" "${rootmnt}${MNT_DIR}"
  76 +}
  77 +
  78 +# Mount the root file system.  This is delegated to the
  79 +# mount(local|nfs)root functions.
  80 +# $1=type local|nfs|unknown
  81 +mountroot()
  82 +{
  83 +       case $boot in
  84 +               nfs) : ;;
  85 +               *) boot=local ;;
  86 +       esac
  87 +
  88 +       echo "Mounting ${boot} root filesystem"
  89 +       mount${boot}root
  90 +}
  91 \ No newline at end of file
  92 diff --git a/scripts/local b/scripts/local
  93 index 521e69a..f6f023f 100644
  94 --- a/scripts/local
  95 +++ b/scripts/local
  96 @@ -74,7 +74,7 @@ pre_mountroot()
  97         done
  98  }
  99  
 100 -mountroot()
 101 +mountlocalroot()
 102  {
 103         pre_mountroot
 104  
 105 diff --git a/scripts/nfs b/scripts/nfs
 106 index 6fa0c43..a0764a3 100644
 107 --- a/scripts/nfs
 108 +++ b/scripts/nfs
 109 @@ -49,7 +49,7 @@ do_nfsmount()
 110  }
 111  
 112  # NFS root mounting
 113 -mountroot()
 114 +mountnfsroot()
 115  {
 116         [ "$quiet" != "y" ] && log_begin_msg "Running /scripts/nfs-top"
 117         run_scripts /scripts/nfs-top

Mount /etc (work in progress):

   1 diff --git a/init b/init
   2 index 7a0fc0f..d3ee2b9 100755
   3 --- a/init
   4 +++ b/init
   5 @@ -40,10 +40,18 @@ export ROOT=
   6  export ROOTDELAY=
   7  export ROOTFLAGS=
   8  export ROOTFSTYPE=
   9 +export ETC=
  10 +export ETCDELAY=
  11 +export ETCFLAGS=
  12 +export ETCFSTYPE=
  13  export IP=
  14  export BOOT=
  15  export BOOTIF=
  16  export UBIMTD=
  17 +export localtopused=no
  18 +export localpremountused=no
  19 +export nfstopused=no
  20 +export nfspremountused=no
  21  export break=
  22  export init=/sbin/init
  23  export quiet=n
  24 @@ -119,6 +127,57 @@ for x in $(cat /proc/cmdline); do
  25                         ;;
  26                 esac
  27                 ;;
  28 +       etc=*)
  29 +               ETC=${x#etc=}
  30 +               case $ETC in
  31 +               LABEL=*)
  32 +                       ETC="${ETC#LABEL=}"
  33 +
  34 +                       # support any / in LABEL= path (escape to \x2f)
  35 +                       case "${ETC}" in
  36 +                       */*)
  37 +                       if command -v sed >/dev/null 2>&1; then
  38 +                               ETC="$(echo ${ETC} | sed 's,/,\\x2f,g')"
  39 +                       else
  40 +                               if [ "${ETC}" != "${ETC#/}" ]; then
  41 +                                       ETC="\x2f${ETC#/}"
  42 +                               fi
  43 +                               if [ "${ETC}" != "${ETC%/}" ]; then
  44 +                                       ETC="${ETC%/}\x2f"
  45 +                               fi
  46 +                               IFS='/'
  47 +                               newetc=
  48 +                               for s in $ETC; do
  49 +                                       newetc="${newetc:+${newetc}\\x2f}${s}"
  50 +                               done
  51 +                               unset IFS
  52 +                               ETC="${newetc}"
  53 +                       fi
  54 +                       esac
  55 +                       ETC="/dev/disk/by-label/${ETC}"
  56 +                       ;;
  57 +               UUID=*)
  58 +                       ETC="/dev/disk/by-uuid/${ETC#UUID=}"
  59 +                       ;;
  60 +               /dev/nfs)
  61 +                       [ -z "${BOOT}" ] && BOOT=nfs
  62 +                       ;;
  63 +               esac
  64 +               ;;
  65 +       etcflags=*)
  66 +               ETCFLAGS="-o ${x#etcflags=}"
  67 +               ;;
  68 +       etcfstype=*)
  69 +               ETCFSTYPE="${x#etcfstype=}"
  70 +               ;;
  71 +       etcdelay=*)
  72 +               ETCDELAY="${x#etcdelay=}"
  73 +               case ${ETCDELAY} in
  74 +               *[![:digit:].]*)
  75 +                       ETCDELAY=
  76 +                       ;;
  77 +               esac
  78 +               ;;
  79         nfsroot=*)
  80                 NFSROOT="${x#nfsroot=}"
  81                 ;;
  82 @@ -224,9 +283,23 @@ maybe_break mountroot
  83  mountroot
  84  log_end_msg
  85  
  86 +if [ -n "${ETC}" ]; then
  87 +       log_begin_msg "Mounting /usr file system"
  88 +       mountetc
  89 +       log_end_msg
  90 +fi
  91 +
  92  if read_fstab_entry /usr; then
  93 -    log_begin_msg "Mounting /usr file system"
  94 -    domount unknown /usr
  95 +       log_begin_msg "Mounting /usr file system"
  96 +       domount unknown /usr
  97 +       log_end_msg
  98 +fi
  99 +
 100 +if [ "${localtopused}" = "yes" ] || [ "${localpremountused}" = "yes" ]; then
 101 +       mountlocalend
 102 +fi
 103 +if [ "${nfstopused}" = "yes" ] || [ "${nfspremountused}" = "yes" ]; then
 104 +       mountnfsend
 105  fi
 106  
 107  maybe_break bottom
 108 @@ -308,10 +381,18 @@ unset ROOTFLAGS
 109  unset ROOTFSTYPE
 110  unset ROOTDELAY
 111  unset ROOT
 112 +unset ETCFLAGS
 113 +unset ETCFSTYPE
 114 +unset ETCDELAY
 115 +unset ETC
 116  unset IP
 117  unset BOOT
 118  unset BOOTIF
 119  unset UBIMTD
 120 +unset localtopused
 121 +unset localpremountused
 122 +unset nfstopused
 123 +unset nfspremountused
 124  unset blacklist
 125  unset break
 126  unset noresume
 127 diff --git a/initramfs-tools.8 b/initramfs-tools.8
 128 index bc6a030..5728146 100644
 129 --- a/initramfs-tools.8
 130 +++ b/initramfs-tools.8
 131 @@ -42,6 +42,24 @@ The default is 180 seconds.
 132  set the file system mount option string.
 133  
 134  .TP
 135 +\fB\fI etc= "<path to blockdevice>"
 136 +the device node to mount as the etc file system.
 137 +The recommended usage is to specify the UUID as followed "etc=UUID=xxx".
 138 +
 139 +.TP
 140 +\fB\fI etcfstype
 141 +set the etc file system type.
 142 +
 143 +.TP
 144 +\fB\fI etcdelay
 145 +set delay in seconds. Determines how long mountetc waits for etc to appear.
 146 +The default is 180 seconds.
 147 +
 148 +.TP
 149 +\fB\fI etcflags
 150 +set the file system mount option string.
 151 +
 152 +.TP
 153  \fB\fI nfsroot
 154  can be either "auto" to try to get the relevant information from DHCP or a
 155  string of the form NFSSERVER:NFSPATH or NFSSERVER:NFSPATH:NFSOPTS.
 156 diff --git a/scripts/functions b/scripts/functions
 157 index 79506e7..3c4f7af 100644
 158 --- a/scripts/functions
 159 +++ b/scripts/functions
 160 @@ -472,6 +472,18 @@ mountroot()
 161                 *) boot=local ;;
 162         esac
 163  
 164 -       echo "Mounting ${boot} root filesystem"
 165         mount${boot}root
 166 +}
 167 +
 168 +# Mount the etc file system.  This is delegated to the
 169 +# mountlocaletc function; not currently supported by nfs.
 170 +# $1=type local|nfs|unknown
 171 +mountetc()
 172 +{
 173 +       case $boot in
 174 +               nfs) return ;;
 175 +               *) boot=local ;;
 176 +       esac
 177 +
 178 +       mount${boot}etc
 179  }
 180 \ No newline at end of file
 181 diff --git a/scripts/local b/scripts/local
 182 index f6f023f..2df27ab 100644
 183 --- a/scripts/local
 184 +++ b/scripts/local
 185 @@ -1,11 +1,9 @@
 186  # Local filesystem mounting                    -*- shell-script -*-
 187  
 188 -pre_mountroot()
 189 +# $1=device to mount
 190 +# $2=optionname (for root and etc)
 191 +pre_localmount()
 192  {
 193 -       [ "$quiet" != "y" ] && log_begin_msg "Running /scripts/local-top"
 194 -       run_scripts /scripts/local-top
 195 -       [ "$quiet" != "y" ] && log_end_msg
 196 -
 197         wait_for_udev 10
 198  
 199         # Load ubi with the correct MTD partition and return since fstype
 200 @@ -17,21 +15,21 @@ pre_mountroot()
 201  
 202         # Don't wait for a root device that doesn't have a corresponding
 203         # device in /dev (ie, mtd0)
 204 -       if [ "${ROOT#/dev}" = "${ROOT}" ]; then
 205 +       if [ "${ROOT#/dev}" = "$1" ]; then
 206                 return
 207         fi
 208  
 209         # If the root device hasn't shown up yet, give it a little while
 210         # to deal with removable devices
 211 -       if [ ! -e "${ROOT}" ] || ! $(get_fstype "${ROOT}" >/dev/null); then
 212 +       if [ ! -e "$1" ] || ! $(get_fstype "$1" >/dev/null); then
 213                 log_begin_msg "Waiting for root file system"
 214  
 215                 # Default delay is 30s
 216                 slumber=${ROOTDELAY:-30}
 217  
 218                 slumber=$(( ${slumber} * 10 ))
 219 -               while [ ! -e "${ROOT}" ] \
 220 -               || ! $(get_fstype "${ROOT}" >/dev/null); do
 221 +               while [ ! -e "$1" ] \
 222 +               || ! $(get_fstype "$1" >/dev/null); do
 223                         /bin/sleep 0.1
 224                         slumber=$(( ${slumber} - 1 ))
 225                         [ ${slumber} -gt 0 ] || break
 226 @@ -45,15 +43,15 @@ pre_mountroot()
 227         fi
 228  
 229         # We've given up, but we'll let the user fix matters if they can
 230 -       while [ ! -e "${ROOT}" ]; do
 231 +       while [ ! -e "$1" ]; do
 232                 # give hint about renamed root
 233 -               case "${ROOT}" in
 234 +               case "$1" in
 235                 /dev/hd*)
 236                         suffix="${ROOT#/dev/hd}"
 237                         major="${suffix%[[:digit:]]}"
 238                         major="${major%[[:digit:]]}"
 239                         if [ -d "/sys/block/sd${major}" ]; then
 240 -                               echo "WARNING bootdevice may be renamed. Try root=/dev/sd${suffix}"
 241 +                               echo "WARNING bootdevice may be renamed. Try $2=/dev/sd${suffix}"
 242                         fi
 243                         ;;
 244                 /dev/sd*)
 245 @@ -61,22 +59,43 @@ pre_mountroot()
 246                         major="${suffix%[[:digit:]]}"
 247                         major="${major%[[:digit:]]}"
 248                         if [ -d "/sys/block/hd${major}" ]; then
 249 -                               echo "WARNING bootdevice may be renamed. Try root=/dev/hd${suffix}"
 250 +                               echo "WARNING bootdevice may be renamed. Try $2=/dev/hd${suffix}"
 251                         fi
 252                         ;;
 253                 esac
 254 -               echo "Gave up waiting for root device.  Common problems:"
 255 +               echo "Gave up waiting for $2 device.  Common problems:"
 256                 echo " - Boot args (cat /proc/cmdline)"
 257                 echo "   - Check rootdelay= (did the system wait long enough?)"
 258 -               echo "   - Check root= (did the system wait for the right device?)"
 259 +               echo "   - Check $2= (did the system wait for the right device?)"
 260                 echo " - Missing modules (cat /proc/modules; ls /dev)"
 261 -               panic "ALERT!  ${ROOT} does not exist.  Dropping to a shell!"
 262 +               panic "ALERT!  $1 does not exist.  Dropping to a shell!"
 263         done
 264  }
 265  
 266 +mountlocaltop()
 267 +{
 268 +       if [ "${localtopused}" != "yes" ]; then
 269 +               [ "$quiet" != "y" ] && log_begin_msg "Running /scripts/local-top"
 270 +               run_scripts /scripts/local-top
 271 +               [ "$quiet" != "y" ] && log_end_msg
 272 +       fi
 273 +       localtopused=yes
 274 +}
 275 +
 276 +mountlocalpremount()
 277 +{
 278 +       if [ "${localpremountused}" != "yes" ]; then
 279 +               [ "$quiet" != "y" ] && log_begin_msg "Running /scripts/local-premount"
 280 +               run_scripts /scripts/local-premount
 281 +               [ "$quiet" != "y" ] && log_end_msg
 282 +       fi
 283 +       localpremountused=yes
 284 +}
 285 +
 286  mountlocalroot()
 287  {
 288 -       pre_mountroot
 289 +       mountlocaltop
 290 +       pre_localmount "${ROOT}" root
 291  
 292         # Get the root filesystem type if not set
 293         if [ -z "${ROOTFSTYPE}" ]; then
 294 @@ -85,9 +104,7 @@ mountlocalroot()
 295                 FSTYPE=${ROOTFSTYPE}
 296         fi
 297  
 298 -       [ "$quiet" != "y" ] && log_begin_msg "Running /scripts/local-premount"
 299 -       run_scripts /scripts/local-premount
 300 -       [ "$quiet" != "y" ] && log_end_msg
 301 +       mountlocalpremount
 302  
 303         if [ "${readonly}" = "y" ]; then
 304                 roflag=-r
 305 @@ -105,7 +122,41 @@ mountlocalroot()
 306         else
 307                 mount ${roflag} ${ROOTFLAGS} ${ROOT} ${rootmnt}
 308         fi
 309 +}
 310 +
 311 +mountlocaletc()
 312 +{
 313 +       pre_localmount "${ETC}" etc
 314 +
 315 +       # Get the etc filesystem type if not set
 316 +       if [ -z "${ETCFSTYPE}" ]; then
 317 +               FSTYPE=$(get_fstype "${ETC}")
 318 +       else
 319 +               FSTYPE=${ETCFSTYPE}
 320 +       fi
 321  
 322 +       mountlocalstart
 323 +
 324 +       if [ "${readonly}" = "y" ]; then
 325 +               roflag=-r
 326 +       else
 327 +               roflag=-w
 328 +       fi
 329 +
 330 +       # FIXME This has no error checking
 331 +       modprobe ${FSTYPE}
 332 +
 333 +       # FIXME This has no error checking
 334 +       # Mount etc
 335 +       if [ "${FSTYPE}" != "unknown" ]; then
 336 +               mount ${roflag} -t ${FSTYPE} ${ETCFLAGS} ${ETC} ${rootmnt}/etc
 337 +       else
 338 +               mount ${roflag} ${ETCFLAGS} ${ETC} ${rootmnt}/etc
 339 +       fi
 340 +}
 341 +
 342 +mountlocalend()
 343 +{
 344         [ "$quiet" != "y" ] && log_begin_msg "Running /scripts/local-bottom"
 345         run_scripts /scripts/local-bottom
 346         [ "$quiet" != "y" ] && log_end_msg
 347 diff --git a/scripts/nfs b/scripts/nfs
 348 index a0764a3..d93f5fb 100644
 349 --- a/scripts/nfs
 350 +++ b/scripts/nfs
 351 @@ -35,9 +35,7 @@ do_nfsmount()
 352                 NFSOPTS="-o retrans=10"
 353         fi
 354  
 355 -       [ "$quiet" != "y" ] && log_begin_msg "Running /scripts/nfs-premount"
 356 -       run_scripts /scripts/nfs-premount
 357 -       [ "$quiet" != "y" ] && log_end_msg
 358 +       mountnfspremount
 359  
 360         if [ ${readonly} = y ]; then
 361                 roflag="-o ro"
 362 @@ -48,12 +46,31 @@ do_nfsmount()
 363         nfsmount -o nolock ${roflag} ${NFSOPTS} ${NFSROOT} ${rootmnt}
 364  }
 365  
 366 +mountnfstop()
 367 +{
 368 +       if [ "${nfstopused}" != "yes" ]; then
 369 +               [ "$quiet" != "y" ] && log_begin_msg "Running /scripts/nfs-top"
 370 +               run_scripts /scripts/nfs-top
 371 +               [ "$quiet" != "y" ] && log_end_msg
 372 +       fi
 373 +       nfstopused=yes
 374 +}
 375 +
 376 +mountnfspremount()
 377 +{
 378 +       if [ "${nfspremountused}" != "yes" ]; then
 379 +               [ "$quiet" != "y" ] && log_begin_msg "Running /scripts/nfs-premount"
 380 +               run_scripts /scripts/nfs-premount
 381 +               [ "$quiet" != "y" ] && log_end_msg
 382 +       fi
 383 +       nfspremountused=yes
 384 +}
 385 +
 386 +
 387  # NFS root mounting
 388  mountnfsroot()
 389  {
 390 -       [ "$quiet" != "y" ] && log_begin_msg "Running /scripts/nfs-top"
 391 -       run_scripts /scripts/nfs-top
 392 -       [ "$quiet" != "y" ] && log_end_msg
 393 +       mountnfstop
 394  
 395         modprobe nfs
 396         # For DHCP
 397 @@ -73,7 +90,10 @@ mountnfsroot()
 398                 retry_nr=$(( ${retry_nr} + 1 ))
 399                 [ "$quiet" != "y" ] && log_end_msg
 400         done
 401 +}
 402  
 403 +mountnfsend()
 404 +{
 405         [ "$quiet" != "y" ] && log_begin_msg "Running /scripts/nfs-bottom"
 406         run_scripts /scripts/nfs-bottom
 407         [ "$quiet" != "y" ] && log_end_msg

util-linux

   1 --- util-linux-2.20.1.original/fsck/fsck.8      2012-12-25 15:14:40.000000000 +0000
   2 +++ util-linux-2.20.1/fsck/fsck.8       2012-12-27 22:19:18.000000000 +0000
   3 @@ -273,8 +273,8 @@
   4  .B \-R
   5  When checking all filesystems with the
   6  .B \-A
   7 -flag, skip the root filesystem.  (This is useful in case the root
   8 -filesystem has already been mounted read-write.)
   9 +flag, skip the root, /etc and /usr filesystems.  (This is useful in case the root,
  10 +/etc and/or /usr filesystems have already been mounted read-write.)
  11  .TP
  12  .B \-T
  13  Don't show the title on startup.
  14 --- util-linux-2.20.1.original/fsck/fsck.c      2012-12-25 15:14:40.000000000 +0000
  15 +++ util-linux-2.20.1/fsck/fsck.c       2012-12-27 22:18:20.000000000 +0000
  16 @@ -1132,11 +1132,11 @@
  17         }
  18         /*
  19          * This is for the bone-headed user who enters the root
  20 -        * filesystem twice.  Skip root will skep all root entries.
  21 +        * filesystem twice.  Skip root will skep all root, /etc and /usr entries.
  22          */
  23         if (skip_root)
  24                 for (fs = filesys_info; fs; fs = fs->next)
  25 -                       if (!strcmp(fs->mountpt, "/"))
  26 +                       if (!strcmp(fs->mountpt, "/") || !strcmp(fs->mountpt, "/etc") || !strcmp(fs->mountpt, "/usr"))
  27                                 fs->flags |= FLAG_DONE;
  28  
  29         while (not_done_yet) {

initscripts (sysvinit)

TODO