[PATCH 05/17] misc: add a crc32c self test to mkfs and repair

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

 



From: Darrick J. Wong <djwong@xxxxxxxxxx>

Enhance mkfs and xfs_repair to run the crc32c self test when they start
up, and refuse to continue if the self test fails.   We don't want to
format a filesystem if the checksum algorithm produces incorrect
results, and we especially don't want repair to tear a filesystem apart
because it thinks the checksum is wrong.

Signed-off-by: Darrick J. Wong <djwong@xxxxxxxxxx>
---
 io/crc32cselftest.c      |    2 +-
 libfrog/crc32.c          |    2 +-
 libfrog/crc32cselftest.h |   21 ++++++++++++++-------
 man/man8/mkfs.xfs.8      |    4 ++++
 man/man8/xfs_repair.8    |    4 ++++
 mkfs/xfs_mkfs.c          |    8 ++++++++
 repair/init.c            |    5 +++++
 7 files changed, 37 insertions(+), 9 deletions(-)


diff --git a/io/crc32cselftest.c b/io/crc32cselftest.c
index f8f757f6..49eb5b6d 100644
--- a/io/crc32cselftest.c
+++ b/io/crc32cselftest.c
@@ -16,7 +16,7 @@ crc32cselftest_f(
 	int		argc,
 	char		**argv)
 {
-	return crc32c_test() != 0;
+	return crc32c_test(0) != 0;
 }
 
 static const cmdinfo_t	crc32cselftest_cmd = {
diff --git a/libfrog/crc32.c b/libfrog/crc32.c
index 6a273b71..2499615d 100644
--- a/libfrog/crc32.c
+++ b/libfrog/crc32.c
@@ -202,7 +202,7 @@ int main(int argc, char **argv)
 
 	printf("CRC_LE_BITS = %d\n", CRC_LE_BITS);
 
-	errors = crc32c_test();
+	errors = crc32c_test(0);
 
 	return errors != 0;
 }
diff --git a/libfrog/crc32cselftest.h b/libfrog/crc32cselftest.h
index 08284153..447a7f7d 100644
--- a/libfrog/crc32cselftest.h
+++ b/libfrog/crc32cselftest.h
@@ -661,18 +661,22 @@ static struct crc_test {
 	{0xb18a0319, 0x00000026, 0x000007db, 0x9dc0bb48},
 };
 
+/* Don't print anything to stdout. */
+#define CRC32CTEST_QUIET	(1U << 0)
+
 static int
-crc32c_test(void)
+crc32c_test(
+	unsigned int	flags)
 {
-	int i;
-	int errors = 0;
-	int bytes = 0;
-	struct timeval start, stop;
-	uint64_t usec;
+	int		i;
+	int		errors = 0;
+	int		bytes = 0;
+	struct timeval	start, stop;
+	uint64_t	usec;
 
 	/* keep static to prevent cache warming code from
 	 * getting eliminated by the compiler */
-	static uint32_t crc;
+	static uint32_t	crc;
 
 	/* pre-warm the cache */
 	for (i = 0; i < 100; i++) {
@@ -693,6 +697,9 @@ crc32c_test(void)
 	usec = stop.tv_usec - start.tv_usec +
 		1000000 * (stop.tv_sec - start.tv_sec);
 
+	if (flags & CRC32CTEST_QUIET)
+		return errors;
+
 	if (errors)
 		printf("crc32c: %d self tests failed\n", errors);
 	else {
diff --git a/man/man8/mkfs.xfs.8 b/man/man8/mkfs.xfs.8
index a7f70285..880e949b 100644
--- a/man/man8/mkfs.xfs.8
+++ b/man/man8/mkfs.xfs.8
@@ -121,6 +121,10 @@ If the size of the block or sector is not specified, the default sizes
 .PP
 Many feature options allow an optional argument of 0 or 1, to explicitly
 disable or enable the functionality.
+
+The correctness of the crc32c checksum implementation will be tested
+before formatting the filesystem.
+If the test fails, the format will abort.
 .SH OPTIONS
 Options may be specified either on the command line or in a configuration file.
 Not all command line options can be specified in configuration files; only the
diff --git a/man/man8/xfs_repair.8 b/man/man8/xfs_repair.8
index cc6a2be8..6625b47a 100644
--- a/man/man8/xfs_repair.8
+++ b/man/man8/xfs_repair.8
@@ -184,6 +184,10 @@ usual 0. This option cannot be used together with
 .B \-V
 Prints the version number and exits.
 .SS Checks Performed
+The correctness of the crc32c checksum implementation will be tested
+before examining the filesystem.
+If the test fails, the program will abort.
+
 Inconsistencies corrected include the following:
 .IP 1.
 Inode and inode blockmap (addressing) checks:
diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index 057b3b09..3a41e17f 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -10,6 +10,7 @@
 #include "libxcmd.h"
 #include "libfrog/fsgeom.h"
 #include "libfrog/convert.h"
+#include "libfrog/crc32cselftest.h"
 #include "proto.h"
 #include <ini.h>
 
@@ -4044,6 +4045,13 @@ main(
 			exit(0);
 	}
 
+	/* Make sure our checksum algorithm really works. */
+	if (crc32c_test(CRC32CTEST_QUIET) != 0) {
+		fprintf(stderr,
+ _("crc32c self-test failed, will not create a filesystem here.\n"));
+		return 1;
+	}
+
 	/*
 	 * All values have been validated, discard the old device layout.
 	 */
diff --git a/repair/init.c b/repair/init.c
index 55f226e9..3a320b4f 100644
--- a/repair/init.c
+++ b/repair/init.c
@@ -14,6 +14,7 @@
 #include "bmap.h"
 #include "incore.h"
 #include "prefetch.h"
+#include "libfrog/crc32cselftest.h"
 #include <sys/resource.h>
 
 static void
@@ -100,4 +101,8 @@ _("Unmount or use the dangerous (-d) option to repair a read-only mounted filesy
 	ts_create();
 	increase_rlimit();
 	pftrace_init();
+
+	if (crc32c_test(CRC32CTEST_QUIET) != 0)
+		do_error(
+ _("crc32c self-test failed, will not examine filesystem.\n"));
 }




[Index of Archives]     [XFS Filesystem Development (older mail)]     [Linux Filesystem Development]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux RAID]     [Linux SCSI]


  Powered by Linux