svn commit: r328013 - head/sbin/fsck_ffs

Mark Johnston markj at FreeBSD.org
Fri Mar 9 22:09:45 UTC 2018


On Mon, Jan 15, 2018 at 07:25:11PM +0000, David Bright wrote:
> Author: dab
> Date: Mon Jan 15 19:25:11 2018
> New Revision: 328013
> URL: https://svnweb.freebsd.org/changeset/base/328013
> 
> Log:
>   Exit fsck_ffs with non-zero status when file system is not repaired.
>   
>   When the fsck_ffs program cannot fully repair a file system, it will
>   output the message PLEASE RERUN FSCK. However, it does not exit with a
>   non-zero status in this case (contradicting the man page claim that it
>   "exits with 0 on success, and >0 if an error occurs."  The fsck
>   rc-script (when running "fsck -y") tests the status from fsck (which
>   passes along the exit status from fsck_ffs) and issues a "stop_boot"
>   if the status fails. However, this is not effective since fsck_ffs can
>   return zero even on (some) errors. Effectively, it is left to a later
>   step in the boot process when the file systems are mounted to detect
>   the still-unclean file system and stop the boot.
>   
>   This change modifies fsck_ffs so that when it cannot fully repair the
>   file system and issues the PLEASE RERUN FSCK message it also exits
>   with a non-zero status.
>   
>   While here, the fsck_ffs man page has also been updated to document
>   the failing exit status codes used by fsck_ffs. Previously, only exit
>   status 7 was documented. Some of these exit statuses are tested for in
>   the fsck rc-script, so they are clearly depended upon and deserve
>   documentation.

etc/rc.d/fsck doesn't know how to interpret the new exit code and now
just drops to a single-user shell when it is encountered. This is
happening to me semi-regularly when my test systems crash, especially
when I test kernel panic handling. :)

Is there any reason etc/rc.d/fsck shouldn't automatically retry (up to
some configurable number of retries) when the new error code is seen?
The patch below seems to do the trick for me:

diff --git a/etc/defaults/rc.conf b/etc/defaults/rc.conf
index 584e842bba2c..63d2fcc0be8d 100644
--- a/etc/defaults/rc.conf
+++ b/etc/defaults/rc.conf
@@ -95,6 +95,7 @@ root_rw_mount="YES"	# Set to NO to inhibit remounting root read-write.
 root_hold_delay="30"	# Time to wait for root mount hold release.
 fsck_y_enable="NO"	# Set to YES to do fsck -y if the initial preen fails.
 fsck_y_flags="-T ffs:-R -T ufs:-R"	# Additional flags for fsck -y
+fsck_retries="3"        # Number of times to retry fsck before giving up.
 background_fsck="YES"	# Attempt to run fsck in the background where possible.
 background_fsck_delay="60" # Time to wait (seconds) before starting the fsck.
 growfs_enable="NO"	# Set to YES to attempt to grow the root filesystem on boot
diff --git a/etc/rc.d/fsck b/etc/rc.d/fsck
index bd3122a20110..708d92228e3d 100755
--- a/etc/rc.d/fsck
+++ b/etc/rc.d/fsck
@@ -14,8 +14,82 @@ desc="Run file system checks"
 start_cmd="fsck_start"
 stop_cmd=":"
 
+_fsck_run()
+{
+	local err
+
+	if checkyesno background_fsck; then
+		fsck -F -p
+	else
+		fsck -p
+	fi
+
+	err=$?
+	if [ ${err} -eq 3 ]; then
+		echo "Warning! Some of the devices might not be" \
+		    "available; retrying"
+		root_hold_wait
+		check_startmsgs && echo "Restarting file system checks:"
+		if checkyesno background_fsck; then
+			fsck -F -p
+		else
+			fsck -p
+		fi
+		err=$?
+	fi
+
+	case ${err} in
+	0)
+		;;
+	2)
+		stop_boot
+		;;
+	4)
+		echo "Rebooting..."
+		reboot
+		echo "Reboot failed; help!"
+		stop_boot
+		;;
+	8)
+		if checkyesno fsck_y_enable; then
+			echo "File system preen failed, trying fsck -y ${fsck_y_flags}"
+			fsck -y ${fsck_y_flags}
+			case $? in
+			0)
+				;;
+			*)
+			echo "Automatic file system check failed; help!"
+				stop_boot
+				;;
+			esac
+		else
+			echo "Automatic file system check failed; help!"
+			stop_boot
+		fi
+		;;
+	12)
+		echo "Boot interrupted."
+		stop_boot
+		;;
+	16)
+		echo "File system check retry requested."
+		;;
+	130)
+		stop_boot
+		;;
+	*)
+		echo "Unknown error ${err}; help!"
+		stop_boot
+		;;
+	esac
+
+	return $err
+}
+
 fsck_start()
 {
+	local err tries
+
 	if [ "$autoboot" = no ]; then
 		echo "Fast boot: skipping disk checks."
 	elif [ ! -r /etc/fstab ]; then
@@ -25,67 +99,13 @@ fsck_start()
 		trap : 3
 
 		check_startmsgs && echo "Starting file system checks:"
-		if checkyesno background_fsck; then
-			fsck -F -p
-		else
-			fsck -p
-		fi
-
-		err=$?
-		if [ ${err} -eq 3 ]; then
-			echo "Warning! Some of the devices might not be" \
-			    "available; retrying"
-			root_hold_wait
-			check_startmsgs && echo "Restarting file system checks:"
-			if checkyesno background_fsck; then
-				fsck -F -p
-			else
-				fsck -p
-			fi
+		tries=$fsck_retries
+		while [ $tries -gt 0 ]; do
+			_fsck_run
 			err=$?
-		fi
-
-		case ${err} in
-		0)
-			;;
-		2)
-			stop_boot
-			;;
-		4)
-			echo "Rebooting..."
-			reboot
-			echo "Reboot failed; help!"
-			stop_boot
-			;;
-		8)
-			if checkyesno fsck_y_enable; then
-				echo "File system preen failed, trying fsck -y ${fsck_y_flags}"
-				fsck -y ${fsck_y_flags}
-				case $? in
-				0)
-					;;
-				*)
-				echo "Automatic file system check failed; help!"
-					stop_boot
-					;;
-				esac
-			else
-				echo "Automatic file system check failed; help!"
-				stop_boot
-			fi
-			;;
-		12)
-			echo "Boot interrupted."
-			stop_boot
-			;;
-		130)
-			stop_boot
-			;;
-		*)
-			echo "Unknown error ${err}; help!"
-			stop_boot
-			;;
-		esac
+			[ $err -eq 16 ] || break
+			tries=$(($tries - 1))
+		done
 	fi
 }
 
diff --git a/share/man/man5/rc.conf.5 b/share/man/man5/rc.conf.5
index c27a2134e6bc..c9a16ca9f65c 100644
--- a/share/man/man5/rc.conf.5
+++ b/share/man/man5/rc.conf.5
@@ -24,7 +24,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd February 15, 2018
+.Dd March 9, 2018
 .Dt RC.CONF 5
 .Os
 .Sh NAME
@@ -2053,6 +2053,11 @@ will be run with the
 .Fl y
 flag if the initial preen
 of the file systems fails.
+.It Va fsck_retries
+.Pq Vt int
+Maximum number of times to re-run
+.Xr fsck 8
+if its exit status indicates that a re-run is required.
 .It Va background_fsck
 .Pq Vt bool
 If set to


More information about the svn-src-all mailing list