Source-Changes-HG archive

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

[src/netbsd-2-0]: src/etc/rc.d Pull up revisions 1.1-1.10 (requested by dbj i...



details:   https://anonhg.NetBSD.org/src/rev/faaaea16c2c9
branches:  netbsd-2-0
changeset: 560551:faaaea16c2c9
user:      jdc <jdc%NetBSD.org@localhost>
date:      Tue Apr 27 17:54:49 2004 +0000

description:
Pull up revisions 1.1-1.10 (requested by dbj in ticket #185)

Fix problems related to superblock upgrade issues which may be
experienced by -current users from 2003.

diffstat:

 etc/rc.d/fixsb |  205 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 205 insertions(+), 0 deletions(-)

diffs (209 lines):

diff -r 4777a86ef4f7 -r faaaea16c2c9 etc/rc.d/fixsb
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/etc/rc.d/fixsb    Tue Apr 27 17:54:49 2004 +0000
@@ -0,0 +1,205 @@
+#!/bin/sh
+#
+# $NetBSD: fixsb,v 1.10.2.2 2004/04/27 17:54:49 jdc Exp $
+#
+
+# PROVIDE: fixsb
+# REQUIRE: localswap
+# BEFORE: fsck
+
+. /etc/rc.subr
+
+name="fixsb"
+rcvar=$name
+start_cmd="fsck_start"
+stop_cmd=":"
+
+# This rc.d script attempts to correct problems with ffs1 filesystems
+# which may have been introduced by booting a netbsd-current kernel
+# from between April of 2003 and January 2004. For more information
+# see <http://mail-index.NetBSD.org/current-users/2004/01/11/0022.html>
+# This script was developed as a response to NetBSD pr install/25138
+# Additional prs regarding the original issue include:
+#  bin/17910 kern/21283 kern/21404 port-macppc/23925 port-macppc/23926
+#
+
+fstab=/etc/fstab
+#verbose=1
+
+verbose()
+{
+       if [ -n "${verbose}" ]; then
+               echo "$@" 1>&2
+       fi
+}
+
+# This reads a field from the ffs superblock
+# at the specified offset and length in bytes
+# from the start of the superblock
+readsbfield()
+{
+       # The first dd command reads in the superblock using block aligned i/o
+       # sothat it works on a raw character device.  The second dd extracts
+       # the exact field from the superblock that we wish to read.
+       (dd if="$1" bs=8192 count=1 skip=1 | 
+        dd bs=1 skip="$2" count="$3" | cat -v) 2> /dev/null
+}
+
+# This shell function extracts the `ffs superblock' of the file
+# provided as its argument and tests for the following condition:
+# ((fs_magic == FS_UFS1_MAGIC) || fs_magic == FS_UFS1_MAGIC_SWAPPED) &&
+# (fs_sbsize == fs_maxbsize) && !(fs_old_flags & FS_FLAGS_UPDATED)
+#
+# return status is based on status of last filesystem checked:
+#   0 for botched superblock
+#   1 for filesystem does not appear to be ffs1 filesystem
+#   3 for ok fslevel 3 filesystem
+#   4 for ok fslevel 4 filesystem
+#
+# dbj%NetBSD.org@localhost 2004-04-12T18:15:06-0400
+check_part()
+{
+       verbose -n "Checking $1 ... "
+
+       # The following are 'cat -v' representations of the ffs1 magic number:
+       fsmagicn="^@^A^YT"  # 0x00011954 FS_UFS1_MAGIC
+       fsmagics="T^Y^A^@"  # 0x54190100 FS_UFS1_MAGIC_SWAPPED
+
+       # First we extract the superblock magic number field.
+       # We use cat -v to avoid having binary data in shell strings.
+       magic="$(readsbfield "$1" 1372 4)"
+
+       # Then we check if the magic number is valid (swapped or unswapped):
+       if [ "${magic}" != "${fsmagicn}" -a "${magic}" != "${fsmagics}" ]; then
+               verbose "does not appear to be an ffs1 filesystem."
+               return 1
+       fi
+
+       # Then we read fs_old_flags fields from disk
+       # And check the value of its high bit.
+       oldflags="$(readsbfield "$1" 211 1)"
+
+       case "${oldflags}" in
+       # Since the shell variable is the cat -v output, the
+       # high bit is indicated in the variable with the prefix M-
+       M-*)
+               verbose "file system looks ok at fslevel 4."
+               return 4
+               ;;
+       esac
+
+       # Then we read fs_bsize, fs_maxbsize fields from the disk:
+       bsize="$(readsbfield "$1" 48 4)"
+       maxbsize="$(readsbfield "$1" 860 4)"
+
+       # Compare the fs_bsize with fs_maxbsize to see if they are the same
+       if [ "${bsize}" != "${maxbsize}" ]; then
+               verbose "file system looks ok at fslevel 3."
+               return 3
+       fi
+
+       verbose "file system has botched superblock upgrade."
+       return 0
+}
+
+# This extracts raw ufs partitions to be fsck'ed from the file ${fstab}
+parse_fstab()
+{
+       for l in 1 2; do
+               cat "${fstab}" 2> /dev/null | 
+               while read d m t o b f err; do
+                       case "$d" in
+                       \#*)
+                               continue
+                               ;;
+                       /dev/*)
+                               d="/dev/r${d#/dev/}"
+                               ;;
+                       esac
+                       case "$t" in
+                       ffs|ufs)
+                               if [ "$f" = "$l" ]; then
+                                       echo "$d"
+                               fi
+                               ;;
+                       esac
+               done
+       done
+}
+
+stop_boot()
+{
+       # Terminate the process (which may include the parent /etc/rc)
+       # if booting directly to multiuser mode.
+       if [ "$autoboot" = "yes" ]; then
+               kill -TERM $$
+       fi
+       exit 1
+}
+
+do_fsck()
+{
+       # During fsck ignore SIGQUIT
+
+       fsck_ffs "$@"
+       case $? in
+       0)
+               ;;
+       2)
+               stop_boot
+               ;;
+       4)
+               echo "Rebooting..."
+               reboot
+               echo "Reboot failed; help!"
+               stop_boot
+               ;;
+       8)
+               echo "Automatic file system check failed; help!"
+               stop_boot
+               ;;
+       12)
+               echo "Boot interrupted."
+               stop_boot
+               ;;
+       130)
+               stop_boot
+               ;;
+       *)
+               echo "Unknown error; help!"
+               stop_boot
+               ;;
+       esac
+}
+
+fsck_start()
+{
+       if [ -e /fastboot ]; then
+               echo "Fast boot: skipping disk checks."
+       else
+               # During fsck ignore SIGQUIT
+               trap : 3
+               okfs=true
+
+               echo -n "Checking for botched superblock upgrades:"
+               for p in $(parse_fstab); do
+                       if check_part "$p"; then
+                               if $okfs; then
+                                       echo
+                                       okfs=false
+                               fi
+                               echo "Repairing partition $p"
+                               do_fsck -p -b 16 -c 4 "$p"
+                               do_fsck -p -c 3 "$p"
+                       fi
+               done
+               if $okfs; then
+                       echo " done."
+               else
+                       echo "Superblock(s) updated successfully."
+               fi
+       fi
+}
+
+load_rc_config $name
+run_rc_command "$1"



Home | Main Index | Thread Index | Old Index