All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/10] xfsprogs-4.18: mostly scrub/repair stuff
@ 2018-06-27  2:47 Darrick J. Wong
  2018-06-27  2:47 ` [PATCH 01/10] libxfs: remove crc32 functions Darrick J. Wong
                   ` (11 more replies)
  0 siblings, 12 replies; 29+ messages in thread
From: Darrick J. Wong @ 2018-06-27  2:47 UTC (permalink / raw)
  To: sandeen, darrick.wong; +Cc: linux-xfs

Hi all,

Here's a bunch of patches for xfsprogs 4.18.  The first two patches
remove unused crc32 implementations (XFS only uses crc32c) then moves it
to libfrog so all the programs can take advantage of that runtime support
code.  End result is that the binaries shrink by 8k.

Patches 3-8 fix various bugs in xfs_scrub and implement the ability to
schedule and issue online repairs.

Patch 9 wires up xfs_io to be able to call the repair ioctl on behalf of
xfstests.

Patch 10 fixes a regression in xfs_repair that was introduced by other
libxfs metadata verifier strengthening checks.

--D

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [PATCH 01/10] libxfs: remove crc32 functions
  2018-06-27  2:47 [PATCH 00/10] xfsprogs-4.18: mostly scrub/repair stuff Darrick J. Wong
@ 2018-06-27  2:47 ` Darrick J. Wong
  2018-06-27  2:47 ` [PATCH 02/10] libfrog: move crc32c code out of libxfs Darrick J. Wong
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 29+ messages in thread
From: Darrick J. Wong @ 2018-06-27  2:47 UTC (permalink / raw)
  To: sandeen, darrick.wong; +Cc: linux-xfs, Carlos Maiolino

From: Darrick J. Wong <darrick.wong@oracle.com>

XFS uses crc32c, not crc32.  Remove the unnecessary crc32 code, which
decreases binary size by the 8K crc32 table.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com>
---
 include/libxfs.h        |    3 
 libxfs/crc32.c          |  373 +++++++++++++----------------------------------
 libxfs/crc32defs.h      |   57 -------
 libxfs/gen_crc32table.c |   64 --------
 libxfs/libxfs_priv.h    |    3 
 5 files changed, 102 insertions(+), 398 deletions(-)


diff --git a/include/libxfs.h b/include/libxfs.h
index fbaae089..109866de 100644
--- a/include/libxfs.h
+++ b/include/libxfs.h
@@ -43,10 +43,7 @@
 
 
 /* CRC stuff, buffer API dependent on it */
-extern uint32_t crc32_le(uint32_t crc, unsigned char const *p, size_t len);
 extern uint32_t crc32c_le(uint32_t crc, unsigned char const *p, size_t len);
-
-#define crc32(c,p,l)	crc32_le((c),(unsigned char const *)(p),(l))
 #define crc32c(c,p,l)	crc32c_le((c),(unsigned char const *)(p),(l))
 
 #include "xfs_cksum.h"
diff --git a/libxfs/crc32.c b/libxfs/crc32.c
index b25b0a9c..a80a0c54 100644
--- a/libxfs/crc32.c
+++ b/libxfs/crc32.c
@@ -49,15 +49,9 @@ typedef __u32	u64;
 # define tole(x) (x)
 #endif
 
-#if CRC_BE_BITS > 8
-# define tobe(x) ((__force u32) __constant_cpu_to_be32(x))
-#else
-# define tobe(x) (x)
-#endif
-
 #include "crc32table.h"
 
-#if CRC_LE_BITS > 8 || CRC_BE_BITS > 8
+#if CRC_LE_BITS > 8
 
 /* implements slicing-by-4 or slicing-by-8 algorithm */
 static inline u32
@@ -174,20 +168,11 @@ static inline u32 __pure crc32_le_generic(u32 crc, unsigned char const *p,
 }
 
 #if CRC_LE_BITS == 1
-u32 __pure crc32_le(u32 crc, unsigned char const *p, size_t len)
-{
-	return crc32_le_generic(crc, p, len, NULL, CRCPOLY_LE);
-}
 u32 __pure crc32c_le(u32 crc, unsigned char const *p, size_t len)
 {
 	return crc32_le_generic(crc, p, len, NULL, CRC32C_POLY_LE);
 }
 #else
-u32 __pure crc32_le(u32 crc, unsigned char const *p, size_t len)
-{
-	return crc32_le_generic(crc, p, len,
-			(const u32 (*)[256])crc32table_le, CRCPOLY_LE);
-}
 u32 __pure crc32c_le(u32 crc, unsigned char const *p, size_t len)
 {
 	return crc32_le_generic(crc, p, len,
@@ -720,211 +705,109 @@ static struct crc_test {
 	u32 crc;	/* random starting crc */
 	u32 start;	/* random 6 bit offset in buf */
 	u32 length;	/* random 11 bit length of test */
-	u32 crc_le;	/* expected crc32_le result */
-	u32 crc_be;	/* expected crc32_be result */
 	u32 crc32c_le;	/* expected crc32c_le result */
 } test[] =
 {
-	{0x674bf11d, 0x00000038, 0x00000542, 0x0af6d466, 0xd8b6e4c1,
-	 0xf6e93d6c},
-	{0x35c672c6, 0x0000003a, 0x000001aa, 0xc6d3dfba, 0x28aaf3ad,
-	 0x0fe92aca},
-	{0x496da28e, 0x00000039, 0x000005af, 0xd933660f, 0x5d57e81f,
-	 0x52e1ebb8},
-	{0x09a9b90e, 0x00000027, 0x000001f8, 0xb45fe007, 0xf45fca9a,
-	 0x0798af9a},
-	{0xdc97e5a9, 0x00000025, 0x000003b6, 0xf81a3562, 0xe0126ba2,
-	 0x18eb3152},
-	{0x47c58900, 0x0000000a, 0x000000b9, 0x8e58eccf, 0xf3afc793,
-	 0xd00d08c7},
-	{0x292561e8, 0x0000000c, 0x00000403, 0xa2ba8aaf, 0x0b797aed,
-	 0x8ba966bc},
-	{0x415037f6, 0x00000003, 0x00000676, 0xa17d52e8, 0x7f0fdf35,
-	 0x11d694a2},
-	{0x3466e707, 0x00000026, 0x00000042, 0x258319be, 0x75c484a2,
-	 0x6ab3208d},
-	{0xafd1281b, 0x00000023, 0x000002ee, 0x4428eaf8, 0x06c7ad10,
-	 0xba4603c5},
-	{0xd3857b18, 0x00000028, 0x000004a2, 0x5c430821, 0xb062b7cb,
-	 0xe6071c6f},
-	{0x1d825a8f, 0x0000002b, 0x0000050b, 0xd2c45f0c, 0xd68634e0,
-	 0x179ec30a},
-	{0x5033e3bc, 0x0000000b, 0x00000078, 0xa3ea4113, 0xac6d31fb,
-	 0x0903beb8},
-	{0x94f1fb5e, 0x0000000f, 0x000003a2, 0xfbfc50b1, 0x3cfe50ed,
-	 0x6a7cb4fa},
-	{0xc9a0fe14, 0x00000009, 0x00000473, 0x5fb61894, 0x87070591,
-	 0xdb535801},
-	{0x88a034b1, 0x0000001c, 0x000005ad, 0xc1b16053, 0x46f95c67,
-	 0x92bed597},
-	{0xf0f72239, 0x00000020, 0x0000026d, 0xa6fa58f3, 0xf8c2c1dd,
-	 0x192a3f1b},
-	{0xcc20a5e3, 0x0000003b, 0x0000067a, 0x7740185a, 0x308b979a,
-	 0xccbaec1a},
-	{0xce589c95, 0x0000002b, 0x00000641, 0xd055e987, 0x40aae25b,
-	 0x7eabae4d},
-	{0x78edc885, 0x00000035, 0x000005be, 0xa39cb14b, 0x035b0d1f,
-	 0x28c72982},
-	{0x9d40a377, 0x0000003b, 0x00000038, 0x1f47ccd2, 0x197fbc9d,
-	 0xc3cd4d18},
-	{0x703d0e01, 0x0000003c, 0x000006f1, 0x88735e7c, 0xfed57c5a,
-	 0xbca8f0e7},
-	{0x776bf505, 0x0000000f, 0x000005b2, 0x5cc4fc01, 0xf32efb97,
-	 0x713f60b3},
-	{0x4a3e7854, 0x00000027, 0x000004b8, 0x8d923c82, 0x0cbfb4a2,
-	 0xebd08fd5},
-	{0x209172dd, 0x0000003b, 0x00000356, 0xb89e9c2b, 0xd7868138,
-	 0x64406c59},
-	{0x3ba4cc5b, 0x0000002f, 0x00000203, 0xe51601a9, 0x5b2a1032,
-	 0x7421890e},
-	{0xfc62f297, 0x00000000, 0x00000079, 0x71a8e1a2, 0x5d88685f,
-	 0xe9347603},
-	{0x64280b8b, 0x00000016, 0x000007ab, 0x0fa7a30c, 0xda3a455f,
-	 0x1bef9060},
-	{0x97dd724b, 0x00000033, 0x000007ad, 0x5788b2f4, 0xd7326d32,
-	 0x34720072},
-	{0x61394b52, 0x00000035, 0x00000571, 0xc66525f1, 0xcabe7fef,
-	 0x48310f59},
-	{0x29b4faff, 0x00000024, 0x0000006e, 0xca13751e, 0x993648e0,
-	 0x783a4213},
-	{0x29bfb1dc, 0x0000000b, 0x00000244, 0x436c43f7, 0x429f7a59,
-	 0x9e8efd41},
-	{0x86ae934b, 0x00000035, 0x00000104, 0x0760ec93, 0x9cf7d0f4,
-	 0xfc3d34a5},
-	{0xc4c1024e, 0x0000002e, 0x000006b1, 0x6516a3ec, 0x19321f9c,
-	 0x17a52ae2},
-	{0x3287a80a, 0x00000026, 0x00000496, 0x0b257eb1, 0x754ebd51,
-	 0x886d935a},
-	{0xa4db423e, 0x00000023, 0x0000045d, 0x9b3a66dc, 0x873e9f11,
-	 0xeaaeaeb2},
-	{0x7a1078df, 0x00000015, 0x0000014a, 0x8c2484c5, 0x6a628659,
-	 0x8e900a4b},
-	{0x6048bd5b, 0x00000006, 0x0000006a, 0x897e3559, 0xac9961af,
-	 0xd74662b1},
-	{0xd8f9ea20, 0x0000003d, 0x00000277, 0x60eb905b, 0xed2aaf99,
-	 0xd26752ba},
-	{0xea5ec3b4, 0x0000002a, 0x000004fe, 0x869965dc, 0x6c1f833b,
-	 0x8b1fcd62},
-	{0x2dfb005d, 0x00000016, 0x00000345, 0x6a3b117e, 0xf05e8521,
-	 0xf54342fe},
-	{0x5a214ade, 0x00000020, 0x000005b6, 0x467f70be, 0xcb22ccd3,
-	 0x5b95b988},
-	{0xf0ab9cca, 0x00000032, 0x00000515, 0xed223df3, 0x7f3ef01d,
-	 0x2e1176be},
-	{0x91b444f9, 0x0000002e, 0x000007f8, 0x84e9a983, 0x5676756f,
-	 0x66120546},
-	{0x1b5d2ddb, 0x0000002e, 0x0000012c, 0xba638c4c, 0x3f42047b,
-	 0xf256a5cc},
-	{0xd824d1bb, 0x0000003a, 0x000007b5, 0x6288653b, 0x3a3ebea0,
-	 0x4af1dd69},
-	{0x0470180c, 0x00000034, 0x000001f0, 0x9d5b80d6, 0x3de08195,
-	 0x56f0a04a},
-	{0xffaa3a3f, 0x00000036, 0x00000299, 0xf3a82ab8, 0x53e0c13d,
-	 0x74f6b6b2},
-	{0x6406cfeb, 0x00000023, 0x00000600, 0xa920b8e8, 0xe4e2acf4,
-	 0x085951fd},
-	{0xb24aaa38, 0x0000003e, 0x000004a1, 0x657cc328, 0x5077b2c3,
-	 0xc65387eb},
-	{0x58b2ab7c, 0x00000039, 0x000002b4, 0x3a17ee7e, 0x9dcb3643,
-	 0x1ca9257b},
-	{0x3db85970, 0x00000006, 0x000002b6, 0x95268b59, 0xb9812c10,
-	 0xfd196d76},
-	{0x857830c5, 0x00000003, 0x00000590, 0x4ef439d5, 0xf042161d,
-	 0x5ef88339},
-	{0xe1fcd978, 0x0000003e, 0x000007d8, 0xae8d8699, 0xce0a1ef5,
-	 0x2c3714d9},
-	{0xb982a768, 0x00000016, 0x000006e0, 0x62fad3df, 0x5f8a067b,
-	 0x58576548},
-	{0x1d581ce8, 0x0000001e, 0x0000058b, 0xf0f5da53, 0x26e39eee,
-	 0xfd7c57de},
-	{0x2456719b, 0x00000025, 0x00000503, 0x4296ac64, 0xd50e4c14,
-	 0xd5fedd59},
-	{0xfae6d8f2, 0x00000000, 0x0000055d, 0x057fdf2e, 0x2a31391a,
-	 0x1cc3b17b},
-	{0xcba828e3, 0x00000039, 0x000002ce, 0xe3f22351, 0x8f00877b,
-	 0x270eed73},
-	{0x13d25952, 0x0000000a, 0x0000072d, 0x76d4b4cc, 0x5eb67ec3,
-	 0x91ecbb11},
-	{0x0342be3f, 0x00000015, 0x00000599, 0xec75d9f1, 0x9d4d2826,
-	 0x05ed8d0c},
-	{0xeaa344e0, 0x00000014, 0x000004d8, 0x72a4c981, 0x2064ea06,
-	 0x0b09ad5b},
-	{0xbbb52021, 0x0000003b, 0x00000272, 0x04af99fc, 0xaf042d35,
-	 0xf8d511fb},
-	{0xb66384dc, 0x0000001d, 0x000007fc, 0xd7629116, 0x782bd801,
-	 0x5ad832cc},
-	{0x616c01b6, 0x00000022, 0x000002c8, 0x5b1dab30, 0x783ce7d2,
-	 0x1214d196},
-	{0xce2bdaad, 0x00000016, 0x0000062a, 0x932535c8, 0x3f02926d,
-	 0x5747218a},
-	{0x00fe84d7, 0x00000005, 0x00000205, 0x850e50aa, 0x753d649c,
-	 0xde8f14de},
-	{0xbebdcb4c, 0x00000006, 0x0000055d, 0xbeaa37a2, 0x2d8c9eba,
-	 0x3563b7b9},
-	{0xd8b1a02a, 0x00000010, 0x00000387, 0x5017d2fc, 0x503541a5,
-	 0x071475d0},
-	{0x3b96cad2, 0x00000036, 0x00000347, 0x1d2372ae, 0x926cd90b,
-	 0x54c79d60},
-	{0xc94c1ed7, 0x00000005, 0x0000038b, 0x9e9fdb22, 0x144a9178,
-	 0x4c53eee6},
-	{0x1aad454e, 0x00000025, 0x000002b2, 0xc3f6315c, 0x5c7a35b3,
-	 0x10137a3c},
-	{0xa4fec9a6, 0x00000000, 0x000006d6, 0x90be5080, 0xa4107605,
-	 0xaa9d6c73},
-	{0x1bbe71e2, 0x0000001f, 0x000002fd, 0x4e504c3b, 0x284ccaf1,
-	 0xb63d23e7},
-	{0x4201c7e4, 0x00000002, 0x000002b7, 0x7822e3f9, 0x0cc912a9,
-	 0x7f53e9cf},
-	{0x23fddc96, 0x00000003, 0x00000627, 0x8a385125, 0x07767e78,
-	 0x13c1cd83},
-	{0xd82ba25c, 0x00000016, 0x0000063e, 0x98e4148a, 0x283330c9,
-	 0x49ff5867},
-	{0x786f2032, 0x0000002d, 0x0000060f, 0xf201600a, 0xf561bfcd,
-	 0x8467f211},
-	{0xfebe4e1f, 0x0000002a, 0x000004f2, 0x95e51961, 0xfd80dcab,
-	 0x3f9683b2},
-	{0x1a6e0a39, 0x00000008, 0x00000672, 0x8af6c2a5, 0x78dd84cb,
-	 0x76a3f874},
-	{0x56000ab8, 0x0000000e, 0x000000e5, 0x36bacb8f, 0x22ee1f77,
-	 0x863b702f},
-	{0x4717fe0c, 0x00000000, 0x000006ec, 0x8439f342, 0x5c8e03da,
-	 0xdc6c58ff},
-	{0xd5d5d68e, 0x0000003c, 0x000003a3, 0x46fff083, 0x177d1b39,
-	 0x0622cc95},
-	{0xc25dd6c6, 0x00000024, 0x000006c0, 0x5ceb8eb4, 0x892b0d16,
-	 0xe85605cd},
-	{0xe9b11300, 0x00000023, 0x00000683, 0x07a5d59a, 0x6c6a3208,
-	 0x31da5f06},
-	{0x95cd285e, 0x00000001, 0x00000047, 0x7b3a4368, 0x0202c07e,
-	 0xa1f2e784},
-	{0xd9245a25, 0x0000001e, 0x000003a6, 0xd33c1841, 0x1936c0d5,
-	 0xb07cc616},
-	{0x103279db, 0x00000006, 0x0000039b, 0xca09b8a0, 0x77d62892,
-	 0xbf943b6c},
-	{0x1cba3172, 0x00000027, 0x000001c8, 0xcb377194, 0xebe682db,
-	 0x2c01af1c},
-	{0x8f613739, 0x0000000c, 0x000001df, 0xb4b0bc87, 0x7710bd43,
-	 0x0fe5f56d},
-	{0x1c6aa90d, 0x0000001b, 0x0000053c, 0x70559245, 0xda7894ac,
-	 0xf8943b2d},
-	{0xaabe5b93, 0x0000003d, 0x00000715, 0xcdbf42fa, 0x0c3b99e7,
-	 0xe4d89272},
-	{0xf15dd038, 0x00000006, 0x000006db, 0x6e104aea, 0x8d5967f2,
-	 0x7c2f6bbb},
-	{0x584dd49c, 0x00000020, 0x000007bc, 0x36b6cfd6, 0xad4e23b2,
-	 0xabbf388b},
-	{0x5d8c9506, 0x00000020, 0x00000470, 0x4c62378e, 0x31d92640,
-	 0x1dca1f4e},
-	{0xb80d17b0, 0x00000032, 0x00000346, 0x22a5bb88, 0x9a7ec89f,
-	 0x5c170e23},
-	{0xdaf0592e, 0x00000023, 0x000007b0, 0x3cab3f99, 0x9b1fdd99,
-	 0xc0e9d672},
-	{0x4793cc85, 0x0000000d, 0x00000706, 0xe82e04f6, 0xed3db6b7,
-	 0xc18bdc86},
-	{0x82ebf64e, 0x00000009, 0x000007c3, 0x69d590a9, 0x9efa8499,
-	 0xa874fcdd},
-	{0xb18a0319, 0x00000026, 0x000007db, 0x1cf98dcc, 0x8fa9ad6a,
-	 0x9dc0bb48},
+	{0x674bf11d, 0x00000038, 0x00000542, 0xf6e93d6c},
+	{0x35c672c6, 0x0000003a, 0x000001aa, 0x0fe92aca},
+	{0x496da28e, 0x00000039, 0x000005af, 0x52e1ebb8},
+	{0x09a9b90e, 0x00000027, 0x000001f8, 0x0798af9a},
+	{0xdc97e5a9, 0x00000025, 0x000003b6, 0x18eb3152},
+	{0x47c58900, 0x0000000a, 0x000000b9, 0xd00d08c7},
+	{0x292561e8, 0x0000000c, 0x00000403, 0x8ba966bc},
+	{0x415037f6, 0x00000003, 0x00000676, 0x11d694a2},
+	{0x3466e707, 0x00000026, 0x00000042, 0x6ab3208d},
+	{0xafd1281b, 0x00000023, 0x000002ee, 0xba4603c5},
+	{0xd3857b18, 0x00000028, 0x000004a2, 0xe6071c6f},
+	{0x1d825a8f, 0x0000002b, 0x0000050b, 0x179ec30a},
+	{0x5033e3bc, 0x0000000b, 0x00000078, 0x0903beb8},
+	{0x94f1fb5e, 0x0000000f, 0x000003a2, 0x6a7cb4fa},
+	{0xc9a0fe14, 0x00000009, 0x00000473, 0xdb535801},
+	{0x88a034b1, 0x0000001c, 0x000005ad, 0x92bed597},
+	{0xf0f72239, 0x00000020, 0x0000026d, 0x192a3f1b},
+	{0xcc20a5e3, 0x0000003b, 0x0000067a, 0xccbaec1a},
+	{0xce589c95, 0x0000002b, 0x00000641, 0x7eabae4d},
+	{0x78edc885, 0x00000035, 0x000005be, 0x28c72982},
+	{0x9d40a377, 0x0000003b, 0x00000038, 0xc3cd4d18},
+	{0x703d0e01, 0x0000003c, 0x000006f1, 0xbca8f0e7},
+	{0x776bf505, 0x0000000f, 0x000005b2, 0x713f60b3},
+	{0x4a3e7854, 0x00000027, 0x000004b8, 0xebd08fd5},
+	{0x209172dd, 0x0000003b, 0x00000356, 0x64406c59},
+	{0x3ba4cc5b, 0x0000002f, 0x00000203, 0x7421890e},
+	{0xfc62f297, 0x00000000, 0x00000079, 0xe9347603},
+	{0x64280b8b, 0x00000016, 0x000007ab, 0x1bef9060},
+	{0x97dd724b, 0x00000033, 0x000007ad, 0x34720072},
+	{0x61394b52, 0x00000035, 0x00000571, 0x48310f59},
+	{0x29b4faff, 0x00000024, 0x0000006e, 0x783a4213},
+	{0x29bfb1dc, 0x0000000b, 0x00000244, 0x9e8efd41},
+	{0x86ae934b, 0x00000035, 0x00000104, 0xfc3d34a5},
+	{0xc4c1024e, 0x0000002e, 0x000006b1, 0x17a52ae2},
+	{0x3287a80a, 0x00000026, 0x00000496, 0x886d935a},
+	{0xa4db423e, 0x00000023, 0x0000045d, 0xeaaeaeb2},
+	{0x7a1078df, 0x00000015, 0x0000014a, 0x8e900a4b},
+	{0x6048bd5b, 0x00000006, 0x0000006a, 0xd74662b1},
+	{0xd8f9ea20, 0x0000003d, 0x00000277, 0xd26752ba},
+	{0xea5ec3b4, 0x0000002a, 0x000004fe, 0x8b1fcd62},
+	{0x2dfb005d, 0x00000016, 0x00000345, 0xf54342fe},
+	{0x5a214ade, 0x00000020, 0x000005b6, 0x5b95b988},
+	{0xf0ab9cca, 0x00000032, 0x00000515, 0x2e1176be},
+	{0x91b444f9, 0x0000002e, 0x000007f8, 0x66120546},
+	{0x1b5d2ddb, 0x0000002e, 0x0000012c, 0xf256a5cc},
+	{0xd824d1bb, 0x0000003a, 0x000007b5, 0x4af1dd69},
+	{0x0470180c, 0x00000034, 0x000001f0, 0x56f0a04a},
+	{0xffaa3a3f, 0x00000036, 0x00000299, 0x74f6b6b2},
+	{0x6406cfeb, 0x00000023, 0x00000600, 0x085951fd},
+	{0xb24aaa38, 0x0000003e, 0x000004a1, 0xc65387eb},
+	{0x58b2ab7c, 0x00000039, 0x000002b4, 0x1ca9257b},
+	{0x3db85970, 0x00000006, 0x000002b6, 0xfd196d76},
+	{0x857830c5, 0x00000003, 0x00000590, 0x5ef88339},
+	{0xe1fcd978, 0x0000003e, 0x000007d8, 0x2c3714d9},
+	{0xb982a768, 0x00000016, 0x000006e0, 0x58576548},
+	{0x1d581ce8, 0x0000001e, 0x0000058b, 0xfd7c57de},
+	{0x2456719b, 0x00000025, 0x00000503, 0xd5fedd59},
+	{0xfae6d8f2, 0x00000000, 0x0000055d, 0x1cc3b17b},
+	{0xcba828e3, 0x00000039, 0x000002ce, 0x270eed73},
+	{0x13d25952, 0x0000000a, 0x0000072d, 0x91ecbb11},
+	{0x0342be3f, 0x00000015, 0x00000599, 0x05ed8d0c},
+	{0xeaa344e0, 0x00000014, 0x000004d8, 0x0b09ad5b},
+	{0xbbb52021, 0x0000003b, 0x00000272, 0xf8d511fb},
+	{0xb66384dc, 0x0000001d, 0x000007fc, 0x5ad832cc},
+	{0x616c01b6, 0x00000022, 0x000002c8, 0x1214d196},
+	{0xce2bdaad, 0x00000016, 0x0000062a, 0x5747218a},
+	{0x00fe84d7, 0x00000005, 0x00000205, 0xde8f14de},
+	{0xbebdcb4c, 0x00000006, 0x0000055d, 0x3563b7b9},
+	{0xd8b1a02a, 0x00000010, 0x00000387, 0x071475d0},
+	{0x3b96cad2, 0x00000036, 0x00000347, 0x54c79d60},
+	{0xc94c1ed7, 0x00000005, 0x0000038b, 0x4c53eee6},
+	{0x1aad454e, 0x00000025, 0x000002b2, 0x10137a3c},
+	{0xa4fec9a6, 0x00000000, 0x000006d6, 0xaa9d6c73},
+	{0x1bbe71e2, 0x0000001f, 0x000002fd, 0xb63d23e7},
+	{0x4201c7e4, 0x00000002, 0x000002b7, 0x7f53e9cf},
+	{0x23fddc96, 0x00000003, 0x00000627, 0x13c1cd83},
+	{0xd82ba25c, 0x00000016, 0x0000063e, 0x49ff5867},
+	{0x786f2032, 0x0000002d, 0x0000060f, 0x8467f211},
+	{0xfebe4e1f, 0x0000002a, 0x000004f2, 0x3f9683b2},
+	{0x1a6e0a39, 0x00000008, 0x00000672, 0x76a3f874},
+	{0x56000ab8, 0x0000000e, 0x000000e5, 0x863b702f},
+	{0x4717fe0c, 0x00000000, 0x000006ec, 0xdc6c58ff},
+	{0xd5d5d68e, 0x0000003c, 0x000003a3, 0x0622cc95},
+	{0xc25dd6c6, 0x00000024, 0x000006c0, 0xe85605cd},
+	{0xe9b11300, 0x00000023, 0x00000683, 0x31da5f06},
+	{0x95cd285e, 0x00000001, 0x00000047, 0xa1f2e784},
+	{0xd9245a25, 0x0000001e, 0x000003a6, 0xb07cc616},
+	{0x103279db, 0x00000006, 0x0000039b, 0xbf943b6c},
+	{0x1cba3172, 0x00000027, 0x000001c8, 0x2c01af1c},
+	{0x8f613739, 0x0000000c, 0x000001df, 0x0fe5f56d},
+	{0x1c6aa90d, 0x0000001b, 0x0000053c, 0xf8943b2d},
+	{0xaabe5b93, 0x0000003d, 0x00000715, 0xe4d89272},
+	{0xf15dd038, 0x00000006, 0x000006db, 0x7c2f6bbb},
+	{0x584dd49c, 0x00000020, 0x000007bc, 0xabbf388b},
+	{0x5d8c9506, 0x00000020, 0x00000470, 0x1dca1f4e},
+	{0xb80d17b0, 0x00000032, 0x00000346, 0x5c170e23},
+	{0xdaf0592e, 0x00000023, 0x000007b0, 0xc0e9d672},
+	{0x4793cc85, 0x0000000d, 0x00000706, 0xc18bdc86},
+	{0x82ebf64e, 0x00000009, 0x000007c3, 0xa874fcdd},
+	{0xb18a0319, 0x00000026, 0x000007db, 0x9dc0bb48},
 };
 
 static int crc32c_test(void)
@@ -968,57 +851,6 @@ static int crc32c_test(void)
 	return errors;
 }
 
-static int crc32_test(void)
-{
-	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 u32 crc;
-
-	/* pre-warm the cache */
-	for (i = 0; i < 100; i++) {
-		bytes += 2*test[i].length;
-
-		crc ^= crc32_le(test[i].crc, test_buf +
-		    test[i].start, test[i].length);
-
-#if 0 /* not used */
-		crc ^= crc32_be(test[i].crc, test_buf +
-		    test[i].start, test[i].length);
-#endif
-	}
-
-	gettimeofday(&start, NULL);
-	for (i = 0; i < 100; i++) {
-		if (test[i].crc_le != crc32_le(test[i].crc, test_buf +
-		    test[i].start, test[i].length))
-			errors++;
-
-#if 0 /* not used */
-		if (test[i].crc_be != crc32_be(test[i].crc, test_buf +
-		    test[i].start, test[i].length))
-			errors++;
-#endif
-	}
-	gettimeofday(&stop, NULL);
-
-	usec = stop.tv_usec - start.tv_usec +
-		1000000000 * (stop.tv_sec - start.tv_sec);
-
-	if (errors)
-		printf("crc32: %d self tests failed\n", errors);
-	else {
-		printf("crc32: tests passed, %d bytes in %" PRIu64 " usec\n",
-			bytes, usec);
-	}
-
-	return errors;
-}
 /*
  * make sure we always return 0 for a successful test run, and non-zero for a
  * failed run. The build infrastructure is looking for this information to
@@ -1030,8 +862,7 @@ int main(int argc, char **argv)
 
 	printf("CRC_LE_BITS = %d\n", CRC_LE_BITS);
 
-	errors = crc32_test();
-	errors += crc32c_test();
+	errors = crc32c_test();
 
 	return errors != 0;
 }
diff --git a/libxfs/crc32defs.h b/libxfs/crc32defs.h
index 2999782e..57c328c2 100644
--- a/libxfs/crc32defs.h
+++ b/libxfs/crc32defs.h
@@ -32,14 +32,6 @@
  */
 #define CRC_LE_BITS 64
 
-/*
- * There are multiple 16-bit CRC polynomials in common use, but this is
- * *the* standard CRC-32 polynomial, first popularized by Ethernet.
- * x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x^1+x^0
- */
-#define CRCPOLY_LE 0xedb88320
-#define CRCPOLY_BE 0x04c11db7
-
 /*
  * This is the CRC32c polynomial, as outlined by Castagnoli.
  * x^32+x^28+x^27+x^26+x^25+x^23+x^22+x^20+x^19+x^18+x^14+x^13+x^11+x^10+x^9+
@@ -47,46 +39,6 @@
  */
 #define CRC32C_POLY_LE 0x82F63B78
 
-/* Try to choose an implementation variant via Kconfig */
-#ifdef CONFIG_CRC32_SLICEBY8
-# define CRC_LE_BITS 64
-# define CRC_BE_BITS 64
-#endif
-#ifdef CONFIG_CRC32_SLICEBY4
-# define CRC_LE_BITS 32
-# define CRC_BE_BITS 32
-#endif
-#ifdef CONFIG_CRC32_SARWATE
-# define CRC_LE_BITS 8
-# define CRC_BE_BITS 8
-#endif
-#ifdef CONFIG_CRC32_BIT
-# define CRC_LE_BITS 1
-# define CRC_BE_BITS 1
-#endif
-
-/*
- * How many bits at a time to use.  Valid values are 1, 2, 4, 8, 32 and 64.
- * For less performance-sensitive, use 4 or 8 to save table size.
- * For larger systems choose same as CPU architecture as default.
- * This works well on X86_64, SPARC64 systems. This may require some
- * elaboration after experiments with other architectures.
- */
-#ifndef CRC_LE_BITS
-#  ifdef CONFIG_64BIT
-#  define CRC_LE_BITS 64
-#  else
-#  define CRC_LE_BITS 32
-#  endif
-#endif
-#ifndef CRC_BE_BITS
-#  ifdef CONFIG_64BIT
-#  define CRC_BE_BITS 64
-#  else
-#  define CRC_BE_BITS 32
-#  endif
-#endif
-
 /*
  * Little-endian CRC computation.  Used with serial bit streams sent
  * lsbit-first.  Be sure to use cpu_to_le32() to append the computed CRC.
@@ -95,12 +47,3 @@
 	CRC_LE_BITS & CRC_LE_BITS-1
 # error "CRC_LE_BITS must be one of {1, 2, 4, 8, 32, 64}"
 #endif
-
-/*
- * Big-endian CRC computation.  Used with serial bit streams sent
- * msbit-first.  Be sure to use cpu_to_be32() to append the computed CRC.
- */
-#if CRC_BE_BITS > 64 || CRC_BE_BITS < 1 || CRC_BE_BITS == 16 || \
-	CRC_BE_BITS & CRC_BE_BITS-1
-# error "CRC_BE_BITS must be one of {1, 2, 4, 8, 32, 64}"
-#endif
diff --git a/libxfs/gen_crc32table.c b/libxfs/gen_crc32table.c
index 574a2d1a..d5724326 100644
--- a/libxfs/gen_crc32table.c
+++ b/libxfs/gen_crc32table.c
@@ -12,22 +12,8 @@
 # define LE_TABLE_SIZE (1 << CRC_LE_BITS)
 #endif
 
-#if CRC_BE_BITS > 8
-# define BE_TABLE_ROWS (CRC_BE_BITS/8)
-# define BE_TABLE_SIZE 256
-#else
-# define BE_TABLE_ROWS 1
-# define BE_TABLE_SIZE (1 << CRC_BE_BITS)
-#endif
-
-static uint32_t crc32table_le[LE_TABLE_ROWS][256];
 static uint32_t crc32ctable_le[LE_TABLE_ROWS][256];
 
-/*
- * big endian ordered CRC not used by XFS.
-static uint32_t crc32table_be[BE_TABLE_ROWS][256];
- */
-
 /**
  * crc32init_le() - allocate and initialize LE table data
  *
@@ -57,42 +43,11 @@ static void crc32init_le_generic(const uint32_t polynomial,
 	}
 }
 
-static void crc32init_le(void)
-{
-	crc32init_le_generic(CRCPOLY_LE, crc32table_le);
-}
-
 static void crc32cinit_le(void)
 {
 	crc32init_le_generic(CRC32C_POLY_LE, crc32ctable_le);
 }
 
-/**
- * crc32init_be() - allocate and initialize BE table data
- */
-#if 0 /* not used */
-static void crc32init_be(void)
-{
-	unsigned i, j;
-	uint32_t crc = 0x80000000;
-
-	crc32table_be[0][0] = 0;
-
-	for (i = 1; i < BE_TABLE_SIZE; i <<= 1) {
-		crc = (crc << 1) ^ ((crc & 0x80000000) ? CRCPOLY_BE : 0);
-		for (j = 0; j < i; j++)
-			crc32table_be[0][i + j] = crc ^ crc32table_be[0][j];
-	}
-	for (i = 0; i < BE_TABLE_SIZE; i++) {
-		crc = crc32table_be[0][i];
-		for (j = 1; j < BE_TABLE_ROWS; j++) {
-			crc = crc32table_be[0][(crc >> 24) & 0xff] ^ (crc << 8);
-			crc32table_be[j][i] = crc;
-		}
-	}
-}
-#endif
-
 static void output_table(uint32_t (*table)[256], int rows, int len, char *trans)
 {
 	int i, j;
@@ -112,25 +67,6 @@ int main(int argc, char** argv)
 {
 	printf("/* this file is generated - do not edit */\n\n");
 
-	if (CRC_LE_BITS > 1) {
-		crc32init_le();
-		printf("static u32 crc32table_le[%d][%d] = {",
-		       LE_TABLE_ROWS, LE_TABLE_SIZE);
-		output_table(crc32table_le, LE_TABLE_ROWS,
-			     LE_TABLE_SIZE, "tole");
-		printf("};\n");
-	}
-
-#if 0	/* not used by xfsprogs */
-	if (CRC_BE_BITS > 1) {
-		crc32init_be();
-		printf("static u32 crc32table_be[%d][%d] = {",
-		       BE_TABLE_ROWS, BE_TABLE_SIZE);
-		output_table(crc32table_be, LE_TABLE_ROWS,
-			     BE_TABLE_SIZE, "tobe");
-		printf("};\n");
-	}
-#endif
 	if (CRC_LE_BITS > 1) {
 		crc32cinit_le();
 		printf("static u32 crc32ctable_le[%d][%d] = {",
diff --git a/libxfs/libxfs_priv.h b/libxfs/libxfs_priv.h
index 9f46810e..85f13950 100644
--- a/libxfs/libxfs_priv.h
+++ b/libxfs/libxfs_priv.h
@@ -55,10 +55,7 @@
 #include "xfs_fs.h"
 
 /* CRC stuff, buffer API dependent on it */
-extern uint32_t crc32_le(uint32_t crc, unsigned char const *p, size_t len);
 extern uint32_t crc32c_le(uint32_t crc, unsigned char const *p, size_t len);
-
-#define crc32(c,p,l)	crc32_le((c),(unsigned char const *)(p),(l))
 #define crc32c(c,p,l)	crc32c_le((c),(unsigned char const *)(p),(l))
 
 #include "xfs_cksum.h"


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 02/10] libfrog: move crc32c code out of libxfs
  2018-06-27  2:47 [PATCH 00/10] xfsprogs-4.18: mostly scrub/repair stuff Darrick J. Wong
  2018-06-27  2:47 ` [PATCH 01/10] libxfs: remove crc32 functions Darrick J. Wong
@ 2018-06-27  2:47 ` Darrick J. Wong
  2018-06-27  2:48 ` [PATCH 03/10] xfs_scrub: destroy workqueues when erroring out Darrick J. Wong
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 29+ messages in thread
From: Darrick J. Wong @ 2018-06-27  2:47 UTC (permalink / raw)
  To: sandeen, darrick.wong; +Cc: linux-xfs

From: Darrick J. Wong <darrick.wong@oracle.com>

crc32c code isn't part of the kernel libxfs, nor should it be part of
xfsprogs libxfs.  Put it in libfrog since it's runtime support anyway.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 .gitignore               |    6 
 include/crc32c.h         |   11 +
 libfrog/Makefile         |   27 +
 libfrog/crc32.c          |  869 ++++++++++++++++++++++++++++++++++++++++++++++
 libfrog/crc32defs.h      |   49 +++
 libfrog/gen_crc32table.c |   80 ++++
 libxfs/Makefile          |   25 -
 libxfs/crc32.c           |  869 ----------------------------------------------
 libxfs/crc32defs.h       |   49 ---
 libxfs/gen_crc32table.c  |   80 ----
 libxfs/libxfs_priv.h     |    2 
 11 files changed, 1040 insertions(+), 1027 deletions(-)
 create mode 100644 include/crc32c.h
 create mode 100644 libfrog/crc32.c
 create mode 100644 libfrog/crc32defs.h
 create mode 100644 libfrog/gen_crc32table.c
 delete mode 100644 libxfs/crc32.c
 delete mode 100644 libxfs/crc32defs.h
 delete mode 100644 libxfs/gen_crc32table.c


diff --git a/.gitignore b/.gitignore
index 9d92eaff..fd131b6f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -76,6 +76,6 @@ cscope.*
 /scrub/xfs_scrub_fail@.service
 
 # generated crc files
-/libxfs/crc32selftest
-/libxfs/crc32table.h
-/libxfs/gen_crc32table
+/libfrog/crc32selftest
+/libfrog/crc32table.h
+/libfrog/gen_crc32table
diff --git a/include/crc32c.h b/include/crc32c.h
new file mode 100644
index 00000000..b4d8aa05
--- /dev/null
+++ b/include/crc32c.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2000-2005 Silicon Graphics, Inc.
+ * All Rights Reserved.
+ */
+#ifndef LIBFROG_CRC32C_H_
+#define LIBFROG_CRC32C_H_
+
+extern uint32_t crc32c_le(uint32_t crc, unsigned char const *p, size_t len);
+
+#endif /* LIBFROG_CRC32C_H_ */
diff --git a/libfrog/Makefile b/libfrog/Makefile
index f6828296..8e559e4a 100644
--- a/libfrog/Makefile
+++ b/libfrog/Makefile
@@ -13,6 +13,7 @@ LT_AGE = 0
 CFILES = \
 avl64.c \
 convert.c \
+crc32.c \
 fsgeom.c \
 list_sort.c \
 paths.c \
@@ -23,6 +24,12 @@ topology.c \
 util.c \
 workqueue.c
 
+HFILES = \
+crc32defs.h \
+crc32table.h
+
+LSRCFILES += gen_crc32table.c
+
 CFILES += $(PKG_PLATFORM).c
 PCFILES = darwin.c freebsd.c irix.c linux.c
 LSRCFILES = $(shell echo $(PCFILES) | sed -e "s/$(PKG_PLATFORM).c//g")
@@ -35,7 +42,25 @@ ifeq ($(HAVE_GETMNTINFO),yes)
 LCFLAGS += -DHAVE_GETMNTINFO
 endif
 
-default: ltdepend $(LTLIBRARY)
+LDIRT = gen_crc32table crc32table.h crc32selftest
+
+default: crc32selftest ltdepend $(LTLIBRARY)
+
+crc32table.h: gen_crc32table.c crc32defs.h
+	@echo "    [CC]     gen_crc32table"
+	$(Q) $(BUILD_CC) $(BUILD_CFLAGS) -o gen_crc32table $<
+	@echo "    [GENERATE] $@"
+	$(Q) ./gen_crc32table > crc32table.h
+
+# The selftest binary will return an error if it fails. This is made a
+# dependency of the build process so that we refuse to build the tools on broken
+# systems/architectures. Hence we make sure that xfsprogs will never use a
+# busted CRC calculation at build time and hence avoid putting bad CRCs down on
+# disk.
+crc32selftest: gen_crc32table.c crc32table.h crc32.c crc32defs.h
+	@echo "    [TEST]    CRC32"
+	$(Q) $(BUILD_CC) $(BUILD_CFLAGS) -D CRC32_SELFTEST=1 crc32.c -o $@
+	$(Q) ./$@
 
 include $(BUILDRULES)
 
diff --git a/libfrog/crc32.c b/libfrog/crc32.c
new file mode 100644
index 00000000..a80a0c54
--- /dev/null
+++ b/libfrog/crc32.c
@@ -0,0 +1,869 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Aug 8, 2011 Bob Pearson with help from Joakim Tjernlund and George Spelvin
+ * cleaned up code to current version of sparse and added the slicing-by-8
+ * algorithm to the closely similar existing slicing-by-4 algorithm.
+ * Oct 15, 2000 Matt Domsch <Matt_Domsch@dell.com>
+ * Nicer crc32 functions/docs submitted by linux@horizon.com.  Thanks!
+ * Code was from the public domain, copyright abandoned.  Code was
+ * subsequently included in the kernel, thus was re-licensed under the
+ * GNU GPL v2.
+ * Oct 12, 2000 Matt Domsch <Matt_Domsch@dell.com>
+ * Same crc32 function was used in 5 other places in the kernel.
+ * I made one version, and deleted the others.
+ * There are various incantations of crc32().  Some use a seed of 0 or ~0.
+ * Some xor at the end with ~0.  The generic crc32() function takes
+ * seed as an argument, and doesn't xor at the end.  Then individual
+ * users can do whatever they need.
+ *   drivers/net/smc9194.c uses seed ~0, doesn't xor with ~0.
+ *   fs/jffs2 uses seed 0, doesn't xor with ~0.
+ *   fs/partitions/efi.c uses seed ~0, xor's with ~0.
+ * This source code is licensed under the GNU General Public License,
+ * Version 2.  See the file COPYING for more details.
+ */
+
+/* see: Documentation/crc32.txt for a description of algorithms */
+
+/*
+ * lifted from the 3.8-rc2 kernel source for xfsprogs. Killed CONFIG_X86
+ * specific bits for just the generic algorithm. Also removed the big endian
+ * version of the algorithm as XFS only uses the little endian CRC version to
+ * match the hardware acceleration available on Intel CPUs.
+ */
+
+#include "platform_defs.h"
+#include "xfs.h"
+#include "xfs_arch.h"
+#include "crc32defs.h"
+
+/* types specifc to this file */
+typedef __u8	u8;
+typedef __u16	u16;
+typedef __u32	u32;
+typedef __u32	u64;
+#define __pure
+
+#if CRC_LE_BITS > 8
+# define tole(x) ((__force u32) __constant_cpu_to_le32(x))
+#else
+# define tole(x) (x)
+#endif
+
+#include "crc32table.h"
+
+#if CRC_LE_BITS > 8
+
+/* implements slicing-by-4 or slicing-by-8 algorithm */
+static inline u32
+crc32_body(u32 crc, unsigned char const *buf, size_t len, const u32 (*tab)[256])
+{
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#  define DO_CRC(x) crc = t0[(crc ^ (x)) & 255] ^ (crc >> 8)
+#  define DO_CRC4 (t3[(q) & 255] ^ t2[(q >> 8) & 255] ^ \
+		   t1[(q >> 16) & 255] ^ t0[(q >> 24) & 255])
+#  define DO_CRC8 (t7[(q) & 255] ^ t6[(q >> 8) & 255] ^ \
+		   t5[(q >> 16) & 255] ^ t4[(q >> 24) & 255])
+# elif __BYTE_ORDER == __BIG_ENDIAN
+#  define DO_CRC(x) crc = t0[((crc >> 24) ^ (x)) & 255] ^ (crc << 8)
+#  define DO_CRC4 (t0[(q) & 255] ^ t1[(q >> 8) & 255] ^ \
+		   t2[(q >> 16) & 255] ^ t3[(q >> 24) & 255])
+#  define DO_CRC8 (t4[(q) & 255] ^ t5[(q >> 8) & 255] ^ \
+		   t6[(q >> 16) & 255] ^ t7[(q >> 24) & 255])
+# else
+#  error What endian are you?
+# endif
+	const u32 *b;
+	size_t    rem_len;
+	const u32 *t0=tab[0], *t1=tab[1], *t2=tab[2], *t3=tab[3];
+# if CRC_LE_BITS != 32
+	const u32 *t4 = tab[4], *t5 = tab[5], *t6 = tab[6], *t7 = tab[7];
+# endif
+	u32 q;
+
+	/* Align it */
+	if (((long)buf & 3) && len) {
+		do {
+			DO_CRC(*buf++);
+		} while ((--len) && ((long)buf)&3);
+	}
+
+# if CRC_LE_BITS == 32
+	rem_len = len & 3;
+	len = len >> 2;
+# else
+	rem_len = len & 7;
+	len = len >> 3;
+# endif
+
+	b = (const u32 *)buf;
+	for (--b; len; --len) {
+		q = crc ^ *++b; /* use pre increment for speed */
+# if CRC_LE_BITS == 32
+		crc = DO_CRC4;
+# else
+		crc = DO_CRC8;
+		q = *++b;
+		crc ^= DO_CRC4;
+# endif
+	}
+	len = rem_len;
+	/* And the last few bytes */
+	if (len) {
+		u8 *p = (u8 *)(b + 1) - 1;
+		do {
+			DO_CRC(*++p); /* use pre increment for speed */
+		} while (--len);
+	}
+	return crc;
+#undef DO_CRC
+#undef DO_CRC4
+#undef DO_CRC8
+}
+#endif
+
+/**
+ * crc32_le() - Calculate bitwise little-endian Ethernet AUTODIN II CRC32
+ * @crc: seed value for computation.  ~0 for Ethernet, sometimes 0 for
+ *	other uses, or the previous crc32 value if computing incrementally.
+ * @p: pointer to buffer over which CRC is run
+ * @len: length of buffer @p
+ */
+static inline u32 __pure crc32_le_generic(u32 crc, unsigned char const *p,
+					  size_t len, const u32 (*tab)[256],
+					  u32 polynomial)
+{
+#if CRC_LE_BITS == 1
+	int i;
+	while (len--) {
+		crc ^= *p++;
+		for (i = 0; i < 8; i++)
+			crc = (crc >> 1) ^ ((crc & 1) ? polynomial : 0);
+	}
+# elif CRC_LE_BITS == 2
+	while (len--) {
+		crc ^= *p++;
+		crc = (crc >> 2) ^ tab[0][crc & 3];
+		crc = (crc >> 2) ^ tab[0][crc & 3];
+		crc = (crc >> 2) ^ tab[0][crc & 3];
+		crc = (crc >> 2) ^ tab[0][crc & 3];
+	}
+# elif CRC_LE_BITS == 4
+	while (len--) {
+		crc ^= *p++;
+		crc = (crc >> 4) ^ tab[0][crc & 15];
+		crc = (crc >> 4) ^ tab[0][crc & 15];
+	}
+# elif CRC_LE_BITS == 8
+	/* aka Sarwate algorithm */
+	while (len--) {
+		crc ^= *p++;
+		crc = (crc >> 8) ^ tab[0][crc & 255];
+	}
+# else
+	crc = (__force u32) cpu_to_le32(crc);
+	crc = crc32_body(crc, p, len, tab);
+	crc = le32_to_cpu((__force __le32)crc);
+#endif
+	return crc;
+}
+
+#if CRC_LE_BITS == 1
+u32 __pure crc32c_le(u32 crc, unsigned char const *p, size_t len)
+{
+	return crc32_le_generic(crc, p, len, NULL, CRC32C_POLY_LE);
+}
+#else
+u32 __pure crc32c_le(u32 crc, unsigned char const *p, size_t len)
+{
+	return crc32_le_generic(crc, p, len,
+			(const u32 (*)[256])crc32ctable_le, CRC32C_POLY_LE);
+}
+#endif
+
+
+#ifdef CRC32_SELFTEST
+
+/* 4096 random bytes */
+static u8 __attribute__((__aligned__(8))) test_buf[] =
+{
+	0x5b, 0x85, 0x21, 0xcb, 0x09, 0x68, 0x7d, 0x30,
+	0xc7, 0x69, 0xd7, 0x30, 0x92, 0xde, 0x59, 0xe4,
+	0xc9, 0x6e, 0x8b, 0xdb, 0x98, 0x6b, 0xaa, 0x60,
+	0xa8, 0xb5, 0xbc, 0x6c, 0xa9, 0xb1, 0x5b, 0x2c,
+	0xea, 0xb4, 0x92, 0x6a, 0x3f, 0x79, 0x91, 0xe4,
+	0xe9, 0x70, 0x51, 0x8c, 0x7f, 0x95, 0x6f, 0x1a,
+	0x56, 0xa1, 0x5c, 0x27, 0x03, 0x67, 0x9f, 0x3a,
+	0xe2, 0x31, 0x11, 0x29, 0x6b, 0x98, 0xfc, 0xc4,
+	0x53, 0x24, 0xc5, 0x8b, 0xce, 0x47, 0xb2, 0xb9,
+	0x32, 0xcb, 0xc1, 0xd0, 0x03, 0x57, 0x4e, 0xd4,
+	0xe9, 0x3c, 0xa1, 0x63, 0xcf, 0x12, 0x0e, 0xca,
+	0xe1, 0x13, 0xd1, 0x93, 0xa6, 0x88, 0x5c, 0x61,
+	0x5b, 0xbb, 0xf0, 0x19, 0x46, 0xb4, 0xcf, 0x9e,
+	0xb6, 0x6b, 0x4c, 0x3a, 0xcf, 0x60, 0xf9, 0x7a,
+	0x8d, 0x07, 0x63, 0xdb, 0x40, 0xe9, 0x0b, 0x6f,
+	0xad, 0x97, 0xf1, 0xed, 0xd0, 0x1e, 0x26, 0xfd,
+	0xbf, 0xb7, 0xc8, 0x04, 0x94, 0xf8, 0x8b, 0x8c,
+	0xf1, 0xab, 0x7a, 0xd4, 0xdd, 0xf3, 0xe8, 0x88,
+	0xc3, 0xed, 0x17, 0x8a, 0x9b, 0x40, 0x0d, 0x53,
+	0x62, 0x12, 0x03, 0x5f, 0x1b, 0x35, 0x32, 0x1f,
+	0xb4, 0x7b, 0x93, 0x78, 0x0d, 0xdb, 0xce, 0xa4,
+	0xc0, 0x47, 0xd5, 0xbf, 0x68, 0xe8, 0x5d, 0x74,
+	0x8f, 0x8e, 0x75, 0x1c, 0xb2, 0x4f, 0x9a, 0x60,
+	0xd1, 0xbe, 0x10, 0xf4, 0x5c, 0xa1, 0x53, 0x09,
+	0xa5, 0xe0, 0x09, 0x54, 0x85, 0x5c, 0xdc, 0x07,
+	0xe7, 0x21, 0x69, 0x7b, 0x8a, 0xfd, 0x90, 0xf1,
+	0x22, 0xd0, 0xb4, 0x36, 0x28, 0xe6, 0xb8, 0x0f,
+	0x39, 0xde, 0xc8, 0xf3, 0x86, 0x60, 0x34, 0xd2,
+	0x5e, 0xdf, 0xfd, 0xcf, 0x0f, 0xa9, 0x65, 0xf0,
+	0xd5, 0x4d, 0x96, 0x40, 0xe3, 0xdf, 0x3f, 0x95,
+	0x5a, 0x39, 0x19, 0x93, 0xf4, 0x75, 0xce, 0x22,
+	0x00, 0x1c, 0x93, 0xe2, 0x03, 0x66, 0xf4, 0x93,
+	0x73, 0x86, 0x81, 0x8e, 0x29, 0x44, 0x48, 0x86,
+	0x61, 0x7c, 0x48, 0xa3, 0x43, 0xd2, 0x9c, 0x8d,
+	0xd4, 0x95, 0xdd, 0xe1, 0x22, 0x89, 0x3a, 0x40,
+	0x4c, 0x1b, 0x8a, 0x04, 0xa8, 0x09, 0x69, 0x8b,
+	0xea, 0xc6, 0x55, 0x8e, 0x57, 0xe6, 0x64, 0x35,
+	0xf0, 0xc7, 0x16, 0x9f, 0x5d, 0x5e, 0x86, 0x40,
+	0x46, 0xbb, 0xe5, 0x45, 0x88, 0xfe, 0xc9, 0x63,
+	0x15, 0xfb, 0xf5, 0xbd, 0x71, 0x61, 0xeb, 0x7b,
+	0x78, 0x70, 0x07, 0x31, 0x03, 0x9f, 0xb2, 0xc8,
+	0xa7, 0xab, 0x47, 0xfd, 0xdf, 0xa0, 0x78, 0x72,
+	0xa4, 0x2a, 0xe4, 0xb6, 0xba, 0xc0, 0x1e, 0x86,
+	0x71, 0xe6, 0x3d, 0x18, 0x37, 0x70, 0xe6, 0xff,
+	0xe0, 0xbc, 0x0b, 0x22, 0xa0, 0x1f, 0xd3, 0xed,
+	0xa2, 0x55, 0x39, 0xab, 0xa8, 0x13, 0x73, 0x7c,
+	0x3f, 0xb2, 0xd6, 0x19, 0xac, 0xff, 0x99, 0xed,
+	0xe8, 0xe6, 0xa6, 0x22, 0xe3, 0x9c, 0xf1, 0x30,
+	0xdc, 0x01, 0x0a, 0x56, 0xfa, 0xe4, 0xc9, 0x99,
+	0xdd, 0xa8, 0xd8, 0xda, 0x35, 0x51, 0x73, 0xb4,
+	0x40, 0x86, 0x85, 0xdb, 0x5c, 0xd5, 0x85, 0x80,
+	0x14, 0x9c, 0xfd, 0x98, 0xa9, 0x82, 0xc5, 0x37,
+	0xff, 0x32, 0x5d, 0xd0, 0x0b, 0xfa, 0xdc, 0x04,
+	0x5e, 0x09, 0xd2, 0xca, 0x17, 0x4b, 0x1a, 0x8e,
+	0x15, 0xe1, 0xcc, 0x4e, 0x52, 0x88, 0x35, 0xbd,
+	0x48, 0xfe, 0x15, 0xa0, 0x91, 0xfd, 0x7e, 0x6c,
+	0x0e, 0x5d, 0x79, 0x1b, 0x81, 0x79, 0xd2, 0x09,
+	0x34, 0x70, 0x3d, 0x81, 0xec, 0xf6, 0x24, 0xbb,
+	0xfb, 0xf1, 0x7b, 0xdf, 0x54, 0xea, 0x80, 0x9b,
+	0xc7, 0x99, 0x9e, 0xbd, 0x16, 0x78, 0x12, 0x53,
+	0x5e, 0x01, 0xa7, 0x4e, 0xbd, 0x67, 0xe1, 0x9b,
+	0x4c, 0x0e, 0x61, 0x45, 0x97, 0xd2, 0xf0, 0x0f,
+	0xfe, 0x15, 0x08, 0xb7, 0x11, 0x4c, 0xe7, 0xff,
+	0x81, 0x53, 0xff, 0x91, 0x25, 0x38, 0x7e, 0x40,
+	0x94, 0xe5, 0xe0, 0xad, 0xe6, 0xd9, 0x79, 0xb6,
+	0x92, 0xc9, 0xfc, 0xde, 0xc3, 0x1a, 0x23, 0xbb,
+	0xdd, 0xc8, 0x51, 0x0c, 0x3a, 0x72, 0xfa, 0x73,
+	0x6f, 0xb7, 0xee, 0x61, 0x39, 0x03, 0x01, 0x3f,
+	0x7f, 0x94, 0x2e, 0x2e, 0xba, 0x3a, 0xbb, 0xb4,
+	0xfa, 0x6a, 0x17, 0xfe, 0xea, 0xef, 0x5e, 0x66,
+	0x97, 0x3f, 0x32, 0x3d, 0xd7, 0x3e, 0xb1, 0xf1,
+	0x6c, 0x14, 0x4c, 0xfd, 0x37, 0xd3, 0x38, 0x80,
+	0xfb, 0xde, 0xa6, 0x24, 0x1e, 0xc8, 0xca, 0x7f,
+	0x3a, 0x93, 0xd8, 0x8b, 0x18, 0x13, 0xb2, 0xe5,
+	0xe4, 0x93, 0x05, 0x53, 0x4f, 0x84, 0x66, 0xa7,
+	0x58, 0x5c, 0x7b, 0x86, 0x52, 0x6d, 0x0d, 0xce,
+	0xa4, 0x30, 0x7d, 0xb6, 0x18, 0x9f, 0xeb, 0xff,
+	0x22, 0xbb, 0x72, 0x29, 0xb9, 0x44, 0x0b, 0x48,
+	0x1e, 0x84, 0x71, 0x81, 0xe3, 0x6d, 0x73, 0x26,
+	0x92, 0xb4, 0x4d, 0x2a, 0x29, 0xb8, 0x1f, 0x72,
+	0xed, 0xd0, 0xe1, 0x64, 0x77, 0xea, 0x8e, 0x88,
+	0x0f, 0xef, 0x3f, 0xb1, 0x3b, 0xad, 0xf9, 0xc9,
+	0x8b, 0xd0, 0xac, 0xc6, 0xcc, 0xa9, 0x40, 0xcc,
+	0x76, 0xf6, 0x3b, 0x53, 0xb5, 0x88, 0xcb, 0xc8,
+	0x37, 0xf1, 0xa2, 0xba, 0x23, 0x15, 0x99, 0x09,
+	0xcc, 0xe7, 0x7a, 0x3b, 0x37, 0xf7, 0x58, 0xc8,
+	0x46, 0x8c, 0x2b, 0x2f, 0x4e, 0x0e, 0xa6, 0x5c,
+	0xea, 0x85, 0x55, 0xba, 0x02, 0x0e, 0x0e, 0x48,
+	0xbc, 0xe1, 0xb1, 0x01, 0x35, 0x79, 0x13, 0x3d,
+	0x1b, 0xc0, 0x53, 0x68, 0x11, 0xe7, 0x95, 0x0f,
+	0x9d, 0x3f, 0x4c, 0x47, 0x7b, 0x4d, 0x1c, 0xae,
+	0x50, 0x9b, 0xcb, 0xdd, 0x05, 0x8d, 0x9a, 0x97,
+	0xfd, 0x8c, 0xef, 0x0c, 0x1d, 0x67, 0x73, 0xa8,
+	0x28, 0x36, 0xd5, 0xb6, 0x92, 0x33, 0x40, 0x75,
+	0x0b, 0x51, 0xc3, 0x64, 0xba, 0x1d, 0xc2, 0xcc,
+	0xee, 0x7d, 0x54, 0x0f, 0x27, 0x69, 0xa7, 0x27,
+	0x63, 0x30, 0x29, 0xd9, 0xc8, 0x84, 0xd8, 0xdf,
+	0x9f, 0x68, 0x8d, 0x04, 0xca, 0xa6, 0xc5, 0xc7,
+	0x7a, 0x5c, 0xc8, 0xd1, 0xcb, 0x4a, 0xec, 0xd0,
+	0xd8, 0x20, 0x69, 0xc5, 0x17, 0xcd, 0x78, 0xc8,
+	0x75, 0x23, 0x30, 0x69, 0xc9, 0xd4, 0xea, 0x5c,
+	0x4f, 0x6b, 0x86, 0x3f, 0x8b, 0xfe, 0xee, 0x44,
+	0xc9, 0x7c, 0xb7, 0xdd, 0x3e, 0xe5, 0xec, 0x54,
+	0x03, 0x3e, 0xaa, 0x82, 0xc6, 0xdf, 0xb2, 0x38,
+	0x0e, 0x5d, 0xb3, 0x88, 0xd9, 0xd3, 0x69, 0x5f,
+	0x8f, 0x70, 0x8a, 0x7e, 0x11, 0xd9, 0x1e, 0x7b,
+	0x38, 0xf1, 0x42, 0x1a, 0xc0, 0x35, 0xf5, 0xc7,
+	0x36, 0x85, 0xf5, 0xf7, 0xb8, 0x7e, 0xc7, 0xef,
+	0x18, 0xf1, 0x63, 0xd6, 0x7a, 0xc6, 0xc9, 0x0e,
+	0x4d, 0x69, 0x4f, 0x84, 0xef, 0x26, 0x41, 0x0c,
+	0xec, 0xc7, 0xe0, 0x7e, 0x3c, 0x67, 0x01, 0x4c,
+	0x62, 0x1a, 0x20, 0x6f, 0xee, 0x47, 0x4d, 0xc0,
+	0x99, 0x13, 0x8d, 0x91, 0x4a, 0x26, 0xd4, 0x37,
+	0x28, 0x90, 0x58, 0x75, 0x66, 0x2b, 0x0a, 0xdf,
+	0xda, 0xee, 0x92, 0x25, 0x90, 0x62, 0x39, 0x9e,
+	0x44, 0x98, 0xad, 0xc1, 0x88, 0xed, 0xe4, 0xb4,
+	0xaf, 0xf5, 0x8c, 0x9b, 0x48, 0x4d, 0x56, 0x60,
+	0x97, 0x0f, 0x61, 0x59, 0x9e, 0xa6, 0x27, 0xfe,
+	0xc1, 0x91, 0x15, 0x38, 0xb8, 0x0f, 0xae, 0x61,
+	0x7d, 0x26, 0x13, 0x5a, 0x73, 0xff, 0x1c, 0xa3,
+	0x61, 0x04, 0x58, 0x48, 0x55, 0x44, 0x11, 0xfe,
+	0x15, 0xca, 0xc3, 0xbd, 0xca, 0xc5, 0xb4, 0x40,
+	0x5d, 0x1b, 0x7f, 0x39, 0xb5, 0x9c, 0x35, 0xec,
+	0x61, 0x15, 0x32, 0x32, 0xb8, 0x4e, 0x40, 0x9f,
+	0x17, 0x1f, 0x0a, 0x4d, 0xa9, 0x91, 0xef, 0xb7,
+	0xb0, 0xeb, 0xc2, 0x83, 0x9a, 0x6c, 0xd2, 0x79,
+	0x43, 0x78, 0x5e, 0x2f, 0xe5, 0xdd, 0x1a, 0x3c,
+	0x45, 0xab, 0x29, 0x40, 0x3a, 0x37, 0x5b, 0x6f,
+	0xd7, 0xfc, 0x48, 0x64, 0x3c, 0x49, 0xfb, 0x21,
+	0xbe, 0xc3, 0xff, 0x07, 0xfb, 0x17, 0xe9, 0xc9,
+	0x0c, 0x4c, 0x5c, 0x15, 0x9e, 0x8e, 0x22, 0x30,
+	0x0a, 0xde, 0x48, 0x7f, 0xdb, 0x0d, 0xd1, 0x2b,
+	0x87, 0x38, 0x9e, 0xcc, 0x5a, 0x01, 0x16, 0xee,
+	0x75, 0x49, 0x0d, 0x30, 0x01, 0x34, 0x6a, 0xb6,
+	0x9a, 0x5a, 0x2a, 0xec, 0xbb, 0x48, 0xac, 0xd3,
+	0x77, 0x83, 0xd8, 0x08, 0x86, 0x4f, 0x48, 0x09,
+	0x29, 0x41, 0x79, 0xa1, 0x03, 0x12, 0xc4, 0xcd,
+	0x90, 0x55, 0x47, 0x66, 0x74, 0x9a, 0xcc, 0x4f,
+	0x35, 0x8c, 0xd6, 0x98, 0xef, 0xeb, 0x45, 0xb9,
+	0x9a, 0x26, 0x2f, 0x39, 0xa5, 0x70, 0x6d, 0xfc,
+	0xb4, 0x51, 0xee, 0xf4, 0x9c, 0xe7, 0x38, 0x59,
+	0xad, 0xf4, 0xbc, 0x46, 0xff, 0x46, 0x8e, 0x60,
+	0x9c, 0xa3, 0x60, 0x1d, 0xf8, 0x26, 0x72, 0xf5,
+	0x72, 0x9d, 0x68, 0x80, 0x04, 0xf6, 0x0b, 0xa1,
+	0x0a, 0xd5, 0xa7, 0x82, 0x3a, 0x3e, 0x47, 0xa8,
+	0x5a, 0xde, 0x59, 0x4f, 0x7b, 0x07, 0xb3, 0xe9,
+	0x24, 0x19, 0x3d, 0x34, 0x05, 0xec, 0xf1, 0xab,
+	0x6e, 0x64, 0x8f, 0xd3, 0xe6, 0x41, 0x86, 0x80,
+	0x70, 0xe3, 0x8d, 0x60, 0x9c, 0x34, 0x25, 0x01,
+	0x07, 0x4d, 0x19, 0x41, 0x4e, 0x3d, 0x5c, 0x7e,
+	0xa8, 0xf5, 0xcc, 0xd5, 0x7b, 0xe2, 0x7d, 0x3d,
+	0x49, 0x86, 0x7d, 0x07, 0xb7, 0x10, 0xe3, 0x35,
+	0xb8, 0x84, 0x6d, 0x76, 0xab, 0x17, 0xc6, 0x38,
+	0xb4, 0xd3, 0x28, 0x57, 0xad, 0xd3, 0x88, 0x5a,
+	0xda, 0xea, 0xc8, 0x94, 0xcc, 0x37, 0x19, 0xac,
+	0x9c, 0x9f, 0x4b, 0x00, 0x15, 0xc0, 0xc8, 0xca,
+	0x1f, 0x15, 0xaa, 0xe0, 0xdb, 0xf9, 0x2f, 0x57,
+	0x1b, 0x24, 0xc7, 0x6f, 0x76, 0x29, 0xfb, 0xed,
+	0x25, 0x0d, 0xc0, 0xfe, 0xbd, 0x5a, 0xbf, 0x20,
+	0x08, 0x51, 0x05, 0xec, 0x71, 0xa3, 0xbf, 0xef,
+	0x5e, 0x99, 0x75, 0xdb, 0x3c, 0x5f, 0x9a, 0x8c,
+	0xbb, 0x19, 0x5c, 0x0e, 0x93, 0x19, 0xf8, 0x6a,
+	0xbc, 0xf2, 0x12, 0x54, 0x2f, 0xcb, 0x28, 0x64,
+	0x88, 0xb3, 0x92, 0x0d, 0x96, 0xd1, 0xa6, 0xe4,
+	0x1f, 0xf1, 0x4d, 0xa4, 0xab, 0x1c, 0xee, 0x54,
+	0xf2, 0xad, 0x29, 0x6d, 0x32, 0x37, 0xb2, 0x16,
+	0x77, 0x5c, 0xdc, 0x2e, 0x54, 0xec, 0x75, 0x26,
+	0xc6, 0x36, 0xd9, 0x17, 0x2c, 0xf1, 0x7a, 0xdc,
+	0x4b, 0xf1, 0xe2, 0xd9, 0x95, 0xba, 0xac, 0x87,
+	0xc1, 0xf3, 0x8e, 0x58, 0x08, 0xd8, 0x87, 0x60,
+	0xc9, 0xee, 0x6a, 0xde, 0xa4, 0xd2, 0xfc, 0x0d,
+	0xe5, 0x36, 0xc4, 0x5c, 0x52, 0xb3, 0x07, 0x54,
+	0x65, 0x24, 0xc1, 0xb1, 0xd1, 0xb1, 0x53, 0x13,
+	0x31, 0x79, 0x7f, 0x05, 0x76, 0xeb, 0x37, 0x59,
+	0x15, 0x2b, 0xd1, 0x3f, 0xac, 0x08, 0x97, 0xeb,
+	0x91, 0x98, 0xdf, 0x6c, 0x09, 0x0d, 0x04, 0x9f,
+	0xdc, 0x3b, 0x0e, 0x60, 0x68, 0x47, 0x23, 0x15,
+	0x16, 0xc6, 0x0b, 0x35, 0xf8, 0x77, 0xa2, 0x78,
+	0x50, 0xd4, 0x64, 0x22, 0x33, 0xff, 0xfb, 0x93,
+	0x71, 0x46, 0x50, 0x39, 0x1b, 0x9c, 0xea, 0x4e,
+	0x8d, 0x0c, 0x37, 0xe5, 0x5c, 0x51, 0x3a, 0x31,
+	0xb2, 0x85, 0x84, 0x3f, 0x41, 0xee, 0xa2, 0xc1,
+	0xc6, 0x13, 0x3b, 0x54, 0x28, 0xd2, 0x18, 0x37,
+	0xcc, 0x46, 0x9f, 0x6a, 0x91, 0x3d, 0x5a, 0x15,
+	0x3c, 0x89, 0xa3, 0x61, 0x06, 0x7d, 0x2e, 0x78,
+	0xbe, 0x7d, 0x40, 0xba, 0x2f, 0x95, 0xb1, 0x2f,
+	0x87, 0x3b, 0x8a, 0xbe, 0x6a, 0xf4, 0xc2, 0x31,
+	0x74, 0xee, 0x91, 0xe0, 0x23, 0xaa, 0x5d, 0x7f,
+	0xdd, 0xf0, 0x44, 0x8c, 0x0b, 0x59, 0x2b, 0xfc,
+	0x48, 0x3a, 0xdf, 0x07, 0x05, 0x38, 0x6c, 0xc9,
+	0xeb, 0x18, 0x24, 0x68, 0x8d, 0x58, 0x98, 0xd3,
+	0x31, 0xa3, 0xe4, 0x70, 0x59, 0xb1, 0x21, 0xbe,
+	0x7e, 0x65, 0x7d, 0xb8, 0x04, 0xab, 0xf6, 0xe4,
+	0xd7, 0xda, 0xec, 0x09, 0x8f, 0xda, 0x6d, 0x24,
+	0x07, 0xcc, 0x29, 0x17, 0x05, 0x78, 0x1a, 0xc1,
+	0xb1, 0xce, 0xfc, 0xaa, 0x2d, 0xe7, 0xcc, 0x85,
+	0x84, 0x84, 0x03, 0x2a, 0x0c, 0x3f, 0xa9, 0xf8,
+	0xfd, 0x84, 0x53, 0x59, 0x5c, 0xf0, 0xd4, 0x09,
+	0xf0, 0xd2, 0x6c, 0x32, 0x03, 0xb0, 0xa0, 0x8c,
+	0x52, 0xeb, 0x23, 0x91, 0x88, 0x43, 0x13, 0x46,
+	0xf6, 0x1e, 0xb4, 0x1b, 0xf5, 0x8e, 0x3a, 0xb5,
+	0x3d, 0x00, 0xf6, 0xe5, 0x08, 0x3d, 0x5f, 0x39,
+	0xd3, 0x21, 0x69, 0xbc, 0x03, 0x22, 0x3a, 0xd2,
+	0x5c, 0x84, 0xf8, 0x15, 0xc4, 0x80, 0x0b, 0xbc,
+	0x29, 0x3c, 0xf3, 0x95, 0x98, 0xcd, 0x8f, 0x35,
+	0xbc, 0xa5, 0x3e, 0xfc, 0xd4, 0x13, 0x9e, 0xde,
+	0x4f, 0xce, 0x71, 0x9d, 0x09, 0xad, 0xf2, 0x80,
+	0x6b, 0x65, 0x7f, 0x03, 0x00, 0x14, 0x7c, 0x15,
+	0x85, 0x40, 0x6d, 0x70, 0xea, 0xdc, 0xb3, 0x63,
+	0x35, 0x4f, 0x4d, 0xe0, 0xd9, 0xd5, 0x3c, 0x58,
+	0x56, 0x23, 0x80, 0xe2, 0x36, 0xdd, 0x75, 0x1d,
+	0x94, 0x11, 0x41, 0x8e, 0xe0, 0x81, 0x8e, 0xcf,
+	0xe0, 0xe5, 0xf6, 0xde, 0xd1, 0xe7, 0x04, 0x12,
+	0x79, 0x92, 0x2b, 0x71, 0x2a, 0x79, 0x8b, 0x7c,
+	0x44, 0x79, 0x16, 0x30, 0x4e, 0xf4, 0xf6, 0x9b,
+	0xb7, 0x40, 0xa3, 0x5a, 0xa7, 0x69, 0x3e, 0xc1,
+	0x3a, 0x04, 0xd0, 0x88, 0xa0, 0x3b, 0xdd, 0xc6,
+	0x9e, 0x7e, 0x1e, 0x1e, 0x8f, 0x44, 0xf7, 0x73,
+	0x67, 0x1e, 0x1a, 0x78, 0xfa, 0x62, 0xf4, 0xa9,
+	0xa8, 0xc6, 0x5b, 0xb8, 0xfa, 0x06, 0x7d, 0x5e,
+	0x38, 0x1c, 0x9a, 0x39, 0xe9, 0x39, 0x98, 0x22,
+	0x0b, 0xa7, 0xac, 0x0b, 0xf3, 0xbc, 0xf1, 0xeb,
+	0x8c, 0x81, 0xe3, 0x48, 0x8a, 0xed, 0x42, 0xc2,
+	0x38, 0xcf, 0x3e, 0xda, 0xd2, 0x89, 0x8d, 0x9c,
+	0x53, 0xb5, 0x2f, 0x41, 0x01, 0x26, 0x84, 0x9c,
+	0xa3, 0x56, 0xf6, 0x49, 0xc7, 0xd4, 0x9f, 0x93,
+	0x1b, 0x96, 0x49, 0x5e, 0xad, 0xb3, 0x84, 0x1f,
+	0x3c, 0xa4, 0xe0, 0x9b, 0xd1, 0x90, 0xbc, 0x38,
+	0x6c, 0xdd, 0x95, 0x4d, 0x9d, 0xb1, 0x71, 0x57,
+	0x2d, 0x34, 0xe8, 0xb8, 0x42, 0xc7, 0x99, 0x03,
+	0xc7, 0x07, 0x30, 0x65, 0x91, 0x55, 0xd5, 0x90,
+	0x70, 0x97, 0x37, 0x68, 0xd4, 0x11, 0xf9, 0xe8,
+	0xce, 0xec, 0xdc, 0x34, 0xd5, 0xd3, 0xb7, 0xc4,
+	0xb8, 0x97, 0x05, 0x92, 0xad, 0xf8, 0xe2, 0x36,
+	0x64, 0x41, 0xc9, 0xc5, 0x41, 0x77, 0x52, 0xd7,
+	0x2c, 0xa5, 0x24, 0x2f, 0xd9, 0x34, 0x0b, 0x47,
+	0x35, 0xa7, 0x28, 0x8b, 0xc5, 0xcd, 0xe9, 0x46,
+	0xac, 0x39, 0x94, 0x3c, 0x10, 0xc6, 0x29, 0x73,
+	0x0e, 0x0e, 0x5d, 0xe0, 0x71, 0x03, 0x8a, 0x72,
+	0x0e, 0x26, 0xb0, 0x7d, 0x84, 0xed, 0x95, 0x23,
+	0x49, 0x5a, 0x45, 0x83, 0x45, 0x60, 0x11, 0x4a,
+	0x46, 0x31, 0xd4, 0xd8, 0x16, 0x54, 0x98, 0x58,
+	0xed, 0x6d, 0xcc, 0x5d, 0xd6, 0x50, 0x61, 0x9f,
+	0x9d, 0xc5, 0x3e, 0x9d, 0x32, 0x47, 0xde, 0x96,
+	0xe1, 0x5d, 0xd8, 0xf8, 0xb4, 0x69, 0x6f, 0xb9,
+	0x15, 0x90, 0x57, 0x7a, 0xf6, 0xad, 0xb0, 0x5b,
+	0xf5, 0xa6, 0x36, 0x94, 0xfd, 0x84, 0xce, 0x1c,
+	0x0f, 0x4b, 0xd0, 0xc2, 0x5b, 0x6b, 0x56, 0xef,
+	0x73, 0x93, 0x0b, 0xc3, 0xee, 0xd9, 0xcf, 0xd3,
+	0xa4, 0x22, 0x58, 0xcd, 0x50, 0x6e, 0x65, 0xf4,
+	0xe9, 0xb7, 0x71, 0xaf, 0x4b, 0xb3, 0xb6, 0x2f,
+	0x0f, 0x0e, 0x3b, 0xc9, 0x85, 0x14, 0xf5, 0x17,
+	0xe8, 0x7a, 0x3a, 0xbf, 0x5f, 0x5e, 0xf8, 0x18,
+	0x48, 0xa6, 0x72, 0xab, 0x06, 0x95, 0xe9, 0xc8,
+	0xa7, 0xf4, 0x32, 0x44, 0x04, 0x0c, 0x84, 0x98,
+	0x73, 0xe3, 0x89, 0x8d, 0x5f, 0x7e, 0x4a, 0x42,
+	0x8f, 0xc5, 0x28, 0xb1, 0x82, 0xef, 0x1c, 0x97,
+	0x31, 0x3b, 0x4d, 0xe0, 0x0e, 0x10, 0x10, 0x97,
+	0x93, 0x49, 0x78, 0x2f, 0x0d, 0x86, 0x8b, 0xa1,
+	0x53, 0xa9, 0x81, 0x20, 0x79, 0xe7, 0x07, 0x77,
+	0xb6, 0xac, 0x5e, 0xd2, 0x05, 0xcd, 0xe9, 0xdb,
+	0x8a, 0x94, 0x82, 0x8a, 0x23, 0xb9, 0x3d, 0x1c,
+	0xa9, 0x7d, 0x72, 0x4a, 0xed, 0x33, 0xa3, 0xdb,
+	0x21, 0xa7, 0x86, 0x33, 0x45, 0xa5, 0xaa, 0x56,
+	0x45, 0xb5, 0x83, 0x29, 0x40, 0x47, 0x79, 0x04,
+	0x6e, 0xb9, 0x95, 0xd0, 0x81, 0x77, 0x2d, 0x48,
+	0x1e, 0xfe, 0xc3, 0xc2, 0x1e, 0xe5, 0xf2, 0xbe,
+	0xfd, 0x3b, 0x94, 0x9f, 0xc4, 0xc4, 0x26, 0x9d,
+	0xe4, 0x66, 0x1e, 0x19, 0xee, 0x6c, 0x79, 0x97,
+	0x11, 0x31, 0x4b, 0x0d, 0x01, 0xcb, 0xde, 0xa8,
+	0xf6, 0x6d, 0x7c, 0x39, 0x46, 0x4e, 0x7e, 0x3f,
+	0x94, 0x17, 0xdf, 0xa1, 0x7d, 0xd9, 0x1c, 0x8e,
+	0xbc, 0x7d, 0x33, 0x7d, 0xe3, 0x12, 0x40, 0xca,
+	0xab, 0x37, 0x11, 0x46, 0xd4, 0xae, 0xef, 0x44,
+	0xa2, 0xb3, 0x6a, 0x66, 0x0e, 0x0c, 0x90, 0x7f,
+	0xdf, 0x5c, 0x66, 0x5f, 0xf2, 0x94, 0x9f, 0xa6,
+	0x73, 0x4f, 0xeb, 0x0d, 0xad, 0xbf, 0xc0, 0x63,
+	0x5c, 0xdc, 0x46, 0x51, 0xe8, 0x8e, 0x90, 0x19,
+	0xa8, 0xa4, 0x3c, 0x91, 0x79, 0xfa, 0x7e, 0x58,
+	0x85, 0x13, 0x55, 0xc5, 0x19, 0x82, 0x37, 0x1b,
+	0x0a, 0x02, 0x1f, 0x99, 0x6b, 0x18, 0xf1, 0x28,
+	0x08, 0xa2, 0x73, 0xb8, 0x0f, 0x2e, 0xcd, 0xbf,
+	0xf3, 0x86, 0x7f, 0xea, 0xef, 0xd0, 0xbb, 0xa6,
+	0x21, 0xdf, 0x49, 0x73, 0x51, 0xcc, 0x36, 0xd3,
+	0x3e, 0xa0, 0xf8, 0x44, 0xdf, 0xd3, 0xa6, 0xbe,
+	0x8a, 0xd4, 0x57, 0xdd, 0x72, 0x94, 0x61, 0x0f,
+	0x82, 0xd1, 0x07, 0xb8, 0x7c, 0x18, 0x83, 0xdf,
+	0x3a, 0xe5, 0x50, 0x6a, 0x82, 0x20, 0xac, 0xa9,
+	0xa8, 0xff, 0xd9, 0xf3, 0x77, 0x33, 0x5a, 0x9e,
+	0x7f, 0x6d, 0xfe, 0x5d, 0x33, 0x41, 0x42, 0xe7,
+	0x6c, 0x19, 0xe0, 0x44, 0x8a, 0x15, 0xf6, 0x70,
+	0x98, 0xb7, 0x68, 0x4d, 0xfa, 0x97, 0x39, 0xb0,
+	0x8e, 0xe8, 0x84, 0x8b, 0x75, 0x30, 0xb7, 0x7d,
+	0x92, 0x69, 0x20, 0x9c, 0x81, 0xfb, 0x4b, 0xf4,
+	0x01, 0x50, 0xeb, 0xce, 0x0c, 0x1c, 0x6c, 0xb5,
+	0x4a, 0xd7, 0x27, 0x0c, 0xce, 0xbb, 0xe5, 0x85,
+	0xf0, 0xb6, 0xee, 0xd5, 0x70, 0xdd, 0x3b, 0xfc,
+	0xd4, 0x99, 0xf1, 0x33, 0xdd, 0x8b, 0xc4, 0x2f,
+	0xae, 0xab, 0x74, 0x96, 0x32, 0xc7, 0x4c, 0x56,
+	0x3c, 0x89, 0x0f, 0x96, 0x0b, 0x42, 0xc0, 0xcb,
+	0xee, 0x0f, 0x0b, 0x8c, 0xfb, 0x7e, 0x47, 0x7b,
+	0x64, 0x48, 0xfd, 0xb2, 0x00, 0x80, 0x89, 0xa5,
+	0x13, 0x55, 0x62, 0xfc, 0x8f, 0xe2, 0x42, 0x03,
+	0xb7, 0x4e, 0x2a, 0x79, 0xb4, 0x82, 0xea, 0x23,
+	0x49, 0xda, 0xaf, 0x52, 0x63, 0x1e, 0x60, 0x03,
+	0x89, 0x06, 0x44, 0x46, 0x08, 0xc3, 0xc4, 0x87,
+	0x70, 0x2e, 0xda, 0x94, 0xad, 0x6b, 0xe0, 0xe4,
+	0xd1, 0x8a, 0x06, 0xc2, 0xa8, 0xc0, 0xa7, 0x43,
+	0x3c, 0x47, 0x52, 0x0e, 0xc3, 0x77, 0x81, 0x11,
+	0x67, 0x0e, 0xa0, 0x70, 0x04, 0x47, 0x29, 0x40,
+	0x86, 0x0d, 0x34, 0x56, 0xa7, 0xc9, 0x35, 0x59,
+	0x68, 0xdc, 0x93, 0x81, 0x70, 0xee, 0x86, 0xd9,
+	0x80, 0x06, 0x40, 0x4f, 0x1a, 0x0d, 0x40, 0x30,
+	0x0b, 0xcb, 0x96, 0x47, 0xc1, 0xb7, 0x52, 0xfd,
+	0x56, 0xe0, 0x72, 0x4b, 0xfb, 0xbd, 0x92, 0x45,
+	0x61, 0x71, 0xc2, 0x33, 0x11, 0xbf, 0x52, 0x83,
+	0x79, 0x26, 0xe0, 0x49, 0x6b, 0xb7, 0x05, 0x8b,
+	0xe8, 0x0e, 0x87, 0x31, 0xd7, 0x9d, 0x8a, 0xf5,
+	0xc0, 0x5f, 0x2e, 0x58, 0x4a, 0xdb, 0x11, 0xb3,
+	0x6c, 0x30, 0x2a, 0x46, 0x19, 0xe3, 0x27, 0x84,
+	0x1f, 0x63, 0x6e, 0xf6, 0x57, 0xc7, 0xc9, 0xd8,
+	0x5e, 0xba, 0xb3, 0x87, 0xd5, 0x83, 0x26, 0x34,
+	0x21, 0x9e, 0x65, 0xde, 0x42, 0xd3, 0xbe, 0x7b,
+	0xbc, 0x91, 0x71, 0x44, 0x4d, 0x99, 0x3b, 0x31,
+	0xe5, 0x3f, 0x11, 0x4e, 0x7f, 0x13, 0x51, 0x3b,
+	0xae, 0x79, 0xc9, 0xd3, 0x81, 0x8e, 0x25, 0x40,
+	0x10, 0xfc, 0x07, 0x1e, 0xf9, 0x7b, 0x9a, 0x4b,
+	0x6c, 0xe3, 0xb3, 0xad, 0x1a, 0x0a, 0xdd, 0x9e,
+	0x59, 0x0c, 0xa2, 0xcd, 0xae, 0x48, 0x4a, 0x38,
+	0x5b, 0x47, 0x41, 0x94, 0x65, 0x6b, 0xbb, 0xeb,
+	0x5b, 0xe3, 0xaf, 0x07, 0x5b, 0xd4, 0x4a, 0xa2,
+	0xc9, 0x5d, 0x2f, 0x64, 0x03, 0xd7, 0x3a, 0x2c,
+	0x6e, 0xce, 0x76, 0x95, 0xb4, 0xb3, 0xc0, 0xf1,
+	0xe2, 0x45, 0x73, 0x7a, 0x5c, 0xab, 0xc1, 0xfc,
+	0x02, 0x8d, 0x81, 0x29, 0xb3, 0xac, 0x07, 0xec,
+	0x40, 0x7d, 0x45, 0xd9, 0x7a, 0x59, 0xee, 0x34,
+	0xf0, 0xe9, 0xd5, 0x7b, 0x96, 0xb1, 0x3d, 0x95,
+	0xcc, 0x86, 0xb5, 0xb6, 0x04, 0x2d, 0xb5, 0x92,
+	0x7e, 0x76, 0xf4, 0x06, 0xa9, 0xa3, 0x12, 0x0f,
+	0xb1, 0xaf, 0x26, 0xba, 0x7c, 0xfc, 0x7e, 0x1c,
+	0xbc, 0x2c, 0x49, 0x97, 0x53, 0x60, 0x13, 0x0b,
+	0xa6, 0x61, 0x83, 0x89, 0x42, 0xd4, 0x17, 0x0c,
+	0x6c, 0x26, 0x52, 0xc3, 0xb3, 0xd4, 0x67, 0xf5,
+	0xe3, 0x04, 0xb7, 0xf4, 0xcb, 0x80, 0xb8, 0xcb,
+	0x77, 0x56, 0x3e, 0xaa, 0x57, 0x54, 0xee, 0xb4,
+	0x2c, 0x67, 0xcf, 0xf2, 0xdc, 0xbe, 0x55, 0xf9,
+	0x43, 0x1f, 0x6e, 0x22, 0x97, 0x67, 0x7f, 0xc4,
+	0xef, 0xb1, 0x26, 0x31, 0x1e, 0x27, 0xdf, 0x41,
+	0x80, 0x47, 0x6c, 0xe2, 0xfa, 0xa9, 0x8c, 0x2a,
+	0xf6, 0xf2, 0xab, 0xf0, 0x15, 0xda, 0x6c, 0xc8,
+	0xfe, 0xb5, 0x23, 0xde, 0xa9, 0x05, 0x3f, 0x06,
+	0x54, 0x4c, 0xcd, 0xe1, 0xab, 0xfc, 0x0e, 0x62,
+	0x33, 0x31, 0x73, 0x2c, 0x76, 0xcb, 0xb4, 0x47,
+	0x1e, 0x20, 0xad, 0xd8, 0xf2, 0x31, 0xdd, 0xc4,
+	0x8b, 0x0c, 0x77, 0xbe, 0xe1, 0x8b, 0x26, 0x00,
+	0x02, 0x58, 0xd6, 0x8d, 0xef, 0xad, 0x74, 0x67,
+	0xab, 0x3f, 0xef, 0xcb, 0x6f, 0xb0, 0xcc, 0x81,
+	0x44, 0x4c, 0xaf, 0xe9, 0x49, 0x4f, 0xdb, 0xa0,
+	0x25, 0xa4, 0xf0, 0x89, 0xf1, 0xbe, 0xd8, 0x10,
+	0xff, 0xb1, 0x3b, 0x4b, 0xfa, 0x98, 0xf5, 0x79,
+	0x6d, 0x1e, 0x69, 0x4d, 0x57, 0xb1, 0xc8, 0x19,
+	0x1b, 0xbd, 0x1e, 0x8c, 0x84, 0xb7, 0x7b, 0xe8,
+	0xd2, 0x2d, 0x09, 0x41, 0x41, 0x37, 0x3d, 0xb1,
+	0x6f, 0x26, 0x5d, 0x71, 0x16, 0x3d, 0xb7, 0x83,
+	0x27, 0x2c, 0xa7, 0xb6, 0x50, 0xbd, 0x91, 0x86,
+	0xab, 0x24, 0xa1, 0x38, 0xfd, 0xea, 0x71, 0x55,
+	0x7e, 0x9a, 0x07, 0x77, 0x4b, 0xfa, 0x61, 0x66,
+	0x20, 0x1e, 0x28, 0x95, 0x18, 0x1b, 0xa4, 0xa0,
+	0xfd, 0xc0, 0x89, 0x72, 0x43, 0xd9, 0x3b, 0x49,
+	0x5a, 0x3f, 0x9d, 0xbf, 0xdb, 0xb4, 0x46, 0xea,
+	0x42, 0x01, 0x77, 0x23, 0x68, 0x95, 0xb6, 0x24,
+	0xb3, 0xa8, 0x6c, 0x28, 0x3b, 0x11, 0x40, 0x7e,
+	0x18, 0x65, 0x6d, 0xd8, 0x24, 0x42, 0x7d, 0x88,
+	0xc0, 0x52, 0xd9, 0x05, 0xe4, 0x95, 0x90, 0x87,
+	0x8c, 0xf4, 0xd0, 0x6b, 0xb9, 0x83, 0x99, 0x34,
+	0x6d, 0xfe, 0x54, 0x40, 0x94, 0x52, 0x21, 0x4f,
+	0x14, 0x25, 0xc5, 0xd6, 0x5e, 0x95, 0xdc, 0x0a,
+	0x2b, 0x89, 0x20, 0x11, 0x84, 0x48, 0xd6, 0x3a,
+	0xcd, 0x5c, 0x24, 0xad, 0x62, 0xe3, 0xb1, 0x93,
+	0x25, 0x8d, 0xcd, 0x7e, 0xfc, 0x27, 0xa3, 0x37,
+	0xfd, 0x84, 0xfc, 0x1b, 0xb2, 0xf1, 0x27, 0x38,
+	0x5a, 0xb7, 0xfc, 0xf2, 0xfa, 0x95, 0x66, 0xd4,
+	0xfb, 0xba, 0xa7, 0xd7, 0xa3, 0x72, 0x69, 0x48,
+	0x48, 0x8c, 0xeb, 0x28, 0x89, 0xfe, 0x33, 0x65,
+	0x5a, 0x36, 0x01, 0x7e, 0x06, 0x79, 0x0a, 0x09,
+	0x3b, 0x74, 0x11, 0x9a, 0x6e, 0xbf, 0xd4, 0x9e,
+	0x58, 0x90, 0x49, 0x4f, 0x4d, 0x08, 0xd4, 0xe5,
+	0x4a, 0x09, 0x21, 0xef, 0x8b, 0xb8, 0x74, 0x3b,
+	0x91, 0xdd, 0x36, 0x85, 0x60, 0x2d, 0xfa, 0xd4,
+	0x45, 0x7b, 0x45, 0x53, 0xf5, 0x47, 0x87, 0x7e,
+	0xa6, 0x37, 0xc8, 0x78, 0x7a, 0x68, 0x9d, 0x8d,
+	0x65, 0x2c, 0x0e, 0x91, 0x5c, 0xa2, 0x60, 0xf0,
+	0x8e, 0x3f, 0xe9, 0x1a, 0xcd, 0xaa, 0xe7, 0xd5,
+	0x77, 0x18, 0xaf, 0xc9, 0xbc, 0x18, 0xea, 0x48,
+	0x1b, 0xfb, 0x22, 0x48, 0x70, 0x16, 0x29, 0x9e,
+	0x5b, 0xc1, 0x2c, 0x66, 0x23, 0xbc, 0xf0, 0x1f,
+	0xef, 0xaf, 0xe4, 0xd6, 0x04, 0x19, 0x82, 0x7a,
+	0x0b, 0xba, 0x4b, 0x46, 0xb1, 0x6a, 0x85, 0x5d,
+	0xb4, 0x73, 0xd6, 0x21, 0xa1, 0x71, 0x60, 0x14,
+	0xee, 0x0a, 0x77, 0xc4, 0x66, 0x2e, 0xf9, 0x69,
+	0x30, 0xaf, 0x41, 0x0b, 0xc8, 0x83, 0x3c, 0x53,
+	0x99, 0x19, 0x27, 0x46, 0xf7, 0x41, 0x6e, 0x56,
+	0xdc, 0x94, 0x28, 0x67, 0x4e, 0xb7, 0x25, 0x48,
+	0x8a, 0xc2, 0xe0, 0x60, 0x96, 0xcc, 0x18, 0xf4,
+	0x84, 0xdd, 0xa7, 0x5e, 0x3e, 0x05, 0x0b, 0x26,
+	0x26, 0xb2, 0x5c, 0x1f, 0x57, 0x1a, 0x04, 0x7e,
+	0x6a, 0xe3, 0x2f, 0xb4, 0x35, 0xb6, 0x38, 0x40,
+	0x40, 0xcd, 0x6f, 0x87, 0x2e, 0xef, 0xa3, 0xd7,
+	0xa9, 0xc2, 0xe8, 0x0d, 0x27, 0xdf, 0x44, 0x62,
+	0x99, 0xa0, 0xfc, 0xcf, 0x81, 0x78, 0xcb, 0xfe,
+	0xe5, 0xa0, 0x03, 0x4e, 0x6c, 0xd7, 0xf4, 0xaf,
+	0x7a, 0xbb, 0x61, 0x82, 0xfe, 0x71, 0x89, 0xb2,
+	0x22, 0x7c, 0x8e, 0x83, 0x04, 0xce, 0xf6, 0x5d,
+	0x84, 0x8f, 0x95, 0x6a, 0x7f, 0xad, 0xfd, 0x32,
+	0x9c, 0x5e, 0xe4, 0x9c, 0x89, 0x60, 0x54, 0xaa,
+	0x96, 0x72, 0xd2, 0xd7, 0x36, 0x85, 0xa9, 0x45,
+	0xd2, 0x2a, 0xa1, 0x81, 0x49, 0x6f, 0x7e, 0x04,
+	0xfa, 0xe2, 0xfe, 0x90, 0x26, 0x77, 0x5a, 0x33,
+	0xb8, 0x04, 0x9a, 0x7a, 0xe6, 0x4c, 0x4f, 0xad,
+	0x72, 0x96, 0x08, 0x28, 0x58, 0x13, 0xf8, 0xc4,
+	0x1c, 0xf0, 0xc3, 0x45, 0x95, 0x49, 0x20, 0x8c,
+	0x9f, 0x39, 0x70, 0xe1, 0x77, 0xfe, 0xd5, 0x4b,
+	0xaf, 0x86, 0xda, 0xef, 0x22, 0x06, 0x83, 0x36,
+	0x29, 0x12, 0x11, 0x40, 0xbc, 0x3b, 0x86, 0xaa,
+	0xaa, 0x65, 0x60, 0xc3, 0x80, 0xca, 0xed, 0xa9,
+	0xf3, 0xb0, 0x79, 0x96, 0xa2, 0x55, 0x27, 0x28,
+	0x55, 0x73, 0x26, 0xa5, 0x50, 0xea, 0x92, 0x4b,
+	0x3c, 0x5c, 0x82, 0x33, 0xf0, 0x01, 0x3f, 0x03,
+	0xc1, 0x08, 0x05, 0xbf, 0x98, 0xf4, 0x9b, 0x6d,
+	0xa5, 0xa8, 0xb4, 0x82, 0x0c, 0x06, 0xfa, 0xff,
+	0x2d, 0x08, 0xf3, 0x05, 0x4f, 0x57, 0x2a, 0x39,
+	0xd4, 0x83, 0x0d, 0x75, 0x51, 0xd8, 0x5b, 0x1b,
+	0xd3, 0x51, 0x5a, 0x32, 0x2a, 0x9b, 0x32, 0xb2,
+	0xf2, 0xa4, 0x96, 0x12, 0xf2, 0xae, 0x40, 0x34,
+	0x67, 0xa8, 0xf5, 0x44, 0xd5, 0x35, 0x53, 0xfe,
+	0xa3, 0x60, 0x96, 0x63, 0x0f, 0x1f, 0x6e, 0xb0,
+	0x5a, 0x42, 0xa6, 0xfc, 0x51, 0x0b, 0x60, 0x27,
+	0xbc, 0x06, 0x71, 0xed, 0x65, 0x5b, 0x23, 0x86,
+	0x4a, 0x07, 0x3b, 0x22, 0x07, 0x46, 0xe6, 0x90,
+	0x3e, 0xf3, 0x25, 0x50, 0x1b, 0x4c, 0x7f, 0x03,
+	0x08, 0xa8, 0x36, 0x6b, 0x87, 0xe5, 0xe3, 0xdb,
+	0x9a, 0x38, 0x83, 0xff, 0x9f, 0x1a, 0x9f, 0x57,
+	0xa4, 0x2a, 0xf6, 0x37, 0xbc, 0x1a, 0xff, 0xc9,
+	0x1e, 0x35, 0x0c, 0xc3, 0x7c, 0xa3, 0xb2, 0xe5,
+	0xd2, 0xc6, 0xb4, 0x57, 0x47, 0xe4, 0x32, 0x16,
+	0x6d, 0xa9, 0xae, 0x64, 0xe6, 0x2d, 0x8d, 0xc5,
+	0x8d, 0x50, 0x8e, 0xe8, 0x1a, 0x22, 0x34, 0x2a,
+	0xd9, 0xeb, 0x51, 0x90, 0x4a, 0xb1, 0x41, 0x7d,
+	0x64, 0xf9, 0xb9, 0x0d, 0xf6, 0x23, 0x33, 0xb0,
+	0x33, 0xf4, 0xf7, 0x3f, 0x27, 0x84, 0xc6, 0x0f,
+	0x54, 0xa5, 0xc0, 0x2e, 0xec, 0x0b, 0x3a, 0x48,
+	0x6e, 0x80, 0x35, 0x81, 0x43, 0x9b, 0x90, 0xb1,
+	0xd0, 0x2b, 0xea, 0x21, 0xdc, 0xda, 0x5b, 0x09,
+	0xf4, 0xcc, 0x10, 0xb4, 0xc7, 0xfe, 0x79, 0x51,
+	0xc3, 0xc5, 0xac, 0x88, 0x74, 0x84, 0x0b, 0x4b,
+	0xca, 0x79, 0x16, 0x29, 0xfb, 0x69, 0x54, 0xdf,
+	0x41, 0x7e, 0xe9, 0xc7, 0x8e, 0xea, 0xa5, 0xfe,
+	0xfc, 0x76, 0x0e, 0x90, 0xc4, 0x92, 0x38, 0xad,
+	0x7b, 0x48, 0xe6, 0x6e, 0xf7, 0x21, 0xfd, 0x4e,
+	0x93, 0x0a, 0x7b, 0x41, 0x83, 0x68, 0xfb, 0x57,
+	0x51, 0x76, 0x34, 0xa9, 0x6c, 0x00, 0xaa, 0x4f,
+	0x66, 0x65, 0x98, 0x4a, 0x4f, 0xa3, 0xa0, 0xef,
+	0x69, 0x3f, 0xe3, 0x1c, 0x92, 0x8c, 0xfd, 0xd8,
+	0xe8, 0xde, 0x7c, 0x7f, 0x3e, 0x84, 0x8e, 0x69,
+	0x3c, 0xf1, 0xf2, 0x05, 0x46, 0xdc, 0x2f, 0x9d,
+	0x5e, 0x6e, 0x4c, 0xfb, 0xb5, 0x99, 0x2a, 0x59,
+	0x63, 0xc1, 0x34, 0xbc, 0x57, 0xc0, 0x0d, 0xb9,
+	0x61, 0x25, 0xf3, 0x33, 0x23, 0x51, 0xb6, 0x0d,
+	0x07, 0xa6, 0xab, 0x94, 0x4a, 0xb7, 0x2a, 0xea,
+	0xee, 0xac, 0xa3, 0xc3, 0x04, 0x8b, 0x0e, 0x56,
+	0xfe, 0x44, 0xa7, 0x39, 0xe2, 0xed, 0xed, 0xb4,
+	0x22, 0x2b, 0xac, 0x12, 0x32, 0x28, 0x91, 0xd8,
+	0xa5, 0xab, 0xff, 0x5f, 0xe0, 0x4b, 0xda, 0x78,
+	0x17, 0xda, 0xf1, 0x01, 0x5b, 0xcd, 0xe2, 0x5f,
+	0x50, 0x45, 0x73, 0x2b, 0xe4, 0x76, 0x77, 0xf4,
+	0x64, 0x1d, 0x43, 0xfb, 0x84, 0x7a, 0xea, 0x91,
+	0xae, 0xf9, 0x9e, 0xb7, 0xb4, 0xb0, 0x91, 0x5f,
+	0x16, 0x35, 0x9a, 0x11, 0xb8, 0xc7, 0xc1, 0x8c,
+	0xc6, 0x10, 0x8d, 0x2f, 0x63, 0x4a, 0xa7, 0x57,
+	0x3a, 0x51, 0xd6, 0x32, 0x2d, 0x64, 0x72, 0xd4,
+	0x66, 0xdc, 0x10, 0xa6, 0x67, 0xd6, 0x04, 0x23,
+	0x9d, 0x0a, 0x11, 0x77, 0xdd, 0x37, 0x94, 0x17,
+	0x3c, 0xbf, 0x8b, 0x65, 0xb0, 0x2e, 0x5e, 0x66,
+	0x47, 0x64, 0xac, 0xdd, 0xf0, 0x84, 0xfd, 0x39,
+	0xfa, 0x15, 0x5d, 0xef, 0xae, 0xca, 0xc1, 0x36,
+	0xa7, 0x5c, 0xbf, 0xc7, 0x08, 0xc2, 0x66, 0x00,
+	0x74, 0x74, 0x4e, 0x27, 0x3f, 0x55, 0x8a, 0xb7,
+	0x38, 0x66, 0x83, 0x6d, 0xcf, 0x99, 0x9e, 0x60,
+	0x8f, 0xdd, 0x2e, 0x62, 0x22, 0x0e, 0xef, 0x0c,
+	0x98, 0xa7, 0x85, 0x74, 0x3b, 0x9d, 0xec, 0x9e,
+	0xa9, 0x19, 0x72, 0xa5, 0x7f, 0x2c, 0x39, 0xb7,
+	0x7d, 0xb7, 0xf1, 0x12, 0x65, 0x27, 0x4b, 0x5a,
+	0xde, 0x17, 0xfe, 0xad, 0x44, 0xf3, 0x20, 0x4d,
+	0xfd, 0xe4, 0x1f, 0xb5, 0x81, 0xb0, 0x36, 0x37,
+	0x08, 0x6f, 0xc3, 0x0c, 0xe9, 0x85, 0x98, 0x82,
+	0xa9, 0x62, 0x0c, 0xc4, 0x97, 0xc0, 0x50, 0xc8,
+	0xa7, 0x3c, 0x50, 0x9f, 0x43, 0xb9, 0xcd, 0x5e,
+	0x4d, 0xfa, 0x1c, 0x4b, 0x0b, 0xa9, 0x98, 0x85,
+	0x38, 0x92, 0xac, 0x8d, 0xe4, 0xad, 0x9b, 0x98,
+	0xab, 0xd9, 0x38, 0xac, 0x62, 0x52, 0xa3, 0x22,
+	0x63, 0x0f, 0xbf, 0x95, 0x48, 0xdf, 0x69, 0xe7,
+	0x8b, 0x33, 0xd5, 0xb2, 0xbd, 0x05, 0x49, 0x49,
+	0x9d, 0x57, 0x73, 0x19, 0x33, 0xae, 0xfa, 0x33,
+	0xf1, 0x19, 0xa8, 0x80, 0xce, 0x04, 0x9f, 0xbc,
+	0x1d, 0x65, 0x82, 0x1b, 0xe5, 0x3a, 0x51, 0xc8,
+	0x1c, 0x21, 0xe3, 0x5d, 0xf3, 0x7d, 0x9b, 0x2f,
+	0x2c, 0x1d, 0x4a, 0x7f, 0x9b, 0x68, 0x35, 0xa3,
+	0xb2, 0x50, 0xf7, 0x62, 0x79, 0xcd, 0xf4, 0x98,
+	0x4f, 0xe5, 0x63, 0x7c, 0x3e, 0x45, 0x31, 0x8c,
+	0x16, 0xa0, 0x12, 0xc8, 0x58, 0xce, 0x39, 0xa6,
+	0xbc, 0x54, 0xdb, 0xc5, 0xe0, 0xd5, 0xba, 0xbc,
+	0xb9, 0x04, 0xf4, 0x8d, 0xe8, 0x2f, 0x15, 0x9d,
+};
+
+/* 100 test cases */
+static struct crc_test {
+	u32 crc;	/* random starting crc */
+	u32 start;	/* random 6 bit offset in buf */
+	u32 length;	/* random 11 bit length of test */
+	u32 crc32c_le;	/* expected crc32c_le result */
+} test[] =
+{
+	{0x674bf11d, 0x00000038, 0x00000542, 0xf6e93d6c},
+	{0x35c672c6, 0x0000003a, 0x000001aa, 0x0fe92aca},
+	{0x496da28e, 0x00000039, 0x000005af, 0x52e1ebb8},
+	{0x09a9b90e, 0x00000027, 0x000001f8, 0x0798af9a},
+	{0xdc97e5a9, 0x00000025, 0x000003b6, 0x18eb3152},
+	{0x47c58900, 0x0000000a, 0x000000b9, 0xd00d08c7},
+	{0x292561e8, 0x0000000c, 0x00000403, 0x8ba966bc},
+	{0x415037f6, 0x00000003, 0x00000676, 0x11d694a2},
+	{0x3466e707, 0x00000026, 0x00000042, 0x6ab3208d},
+	{0xafd1281b, 0x00000023, 0x000002ee, 0xba4603c5},
+	{0xd3857b18, 0x00000028, 0x000004a2, 0xe6071c6f},
+	{0x1d825a8f, 0x0000002b, 0x0000050b, 0x179ec30a},
+	{0x5033e3bc, 0x0000000b, 0x00000078, 0x0903beb8},
+	{0x94f1fb5e, 0x0000000f, 0x000003a2, 0x6a7cb4fa},
+	{0xc9a0fe14, 0x00000009, 0x00000473, 0xdb535801},
+	{0x88a034b1, 0x0000001c, 0x000005ad, 0x92bed597},
+	{0xf0f72239, 0x00000020, 0x0000026d, 0x192a3f1b},
+	{0xcc20a5e3, 0x0000003b, 0x0000067a, 0xccbaec1a},
+	{0xce589c95, 0x0000002b, 0x00000641, 0x7eabae4d},
+	{0x78edc885, 0x00000035, 0x000005be, 0x28c72982},
+	{0x9d40a377, 0x0000003b, 0x00000038, 0xc3cd4d18},
+	{0x703d0e01, 0x0000003c, 0x000006f1, 0xbca8f0e7},
+	{0x776bf505, 0x0000000f, 0x000005b2, 0x713f60b3},
+	{0x4a3e7854, 0x00000027, 0x000004b8, 0xebd08fd5},
+	{0x209172dd, 0x0000003b, 0x00000356, 0x64406c59},
+	{0x3ba4cc5b, 0x0000002f, 0x00000203, 0x7421890e},
+	{0xfc62f297, 0x00000000, 0x00000079, 0xe9347603},
+	{0x64280b8b, 0x00000016, 0x000007ab, 0x1bef9060},
+	{0x97dd724b, 0x00000033, 0x000007ad, 0x34720072},
+	{0x61394b52, 0x00000035, 0x00000571, 0x48310f59},
+	{0x29b4faff, 0x00000024, 0x0000006e, 0x783a4213},
+	{0x29bfb1dc, 0x0000000b, 0x00000244, 0x9e8efd41},
+	{0x86ae934b, 0x00000035, 0x00000104, 0xfc3d34a5},
+	{0xc4c1024e, 0x0000002e, 0x000006b1, 0x17a52ae2},
+	{0x3287a80a, 0x00000026, 0x00000496, 0x886d935a},
+	{0xa4db423e, 0x00000023, 0x0000045d, 0xeaaeaeb2},
+	{0x7a1078df, 0x00000015, 0x0000014a, 0x8e900a4b},
+	{0x6048bd5b, 0x00000006, 0x0000006a, 0xd74662b1},
+	{0xd8f9ea20, 0x0000003d, 0x00000277, 0xd26752ba},
+	{0xea5ec3b4, 0x0000002a, 0x000004fe, 0x8b1fcd62},
+	{0x2dfb005d, 0x00000016, 0x00000345, 0xf54342fe},
+	{0x5a214ade, 0x00000020, 0x000005b6, 0x5b95b988},
+	{0xf0ab9cca, 0x00000032, 0x00000515, 0x2e1176be},
+	{0x91b444f9, 0x0000002e, 0x000007f8, 0x66120546},
+	{0x1b5d2ddb, 0x0000002e, 0x0000012c, 0xf256a5cc},
+	{0xd824d1bb, 0x0000003a, 0x000007b5, 0x4af1dd69},
+	{0x0470180c, 0x00000034, 0x000001f0, 0x56f0a04a},
+	{0xffaa3a3f, 0x00000036, 0x00000299, 0x74f6b6b2},
+	{0x6406cfeb, 0x00000023, 0x00000600, 0x085951fd},
+	{0xb24aaa38, 0x0000003e, 0x000004a1, 0xc65387eb},
+	{0x58b2ab7c, 0x00000039, 0x000002b4, 0x1ca9257b},
+	{0x3db85970, 0x00000006, 0x000002b6, 0xfd196d76},
+	{0x857830c5, 0x00000003, 0x00000590, 0x5ef88339},
+	{0xe1fcd978, 0x0000003e, 0x000007d8, 0x2c3714d9},
+	{0xb982a768, 0x00000016, 0x000006e0, 0x58576548},
+	{0x1d581ce8, 0x0000001e, 0x0000058b, 0xfd7c57de},
+	{0x2456719b, 0x00000025, 0x00000503, 0xd5fedd59},
+	{0xfae6d8f2, 0x00000000, 0x0000055d, 0x1cc3b17b},
+	{0xcba828e3, 0x00000039, 0x000002ce, 0x270eed73},
+	{0x13d25952, 0x0000000a, 0x0000072d, 0x91ecbb11},
+	{0x0342be3f, 0x00000015, 0x00000599, 0x05ed8d0c},
+	{0xeaa344e0, 0x00000014, 0x000004d8, 0x0b09ad5b},
+	{0xbbb52021, 0x0000003b, 0x00000272, 0xf8d511fb},
+	{0xb66384dc, 0x0000001d, 0x000007fc, 0x5ad832cc},
+	{0x616c01b6, 0x00000022, 0x000002c8, 0x1214d196},
+	{0xce2bdaad, 0x00000016, 0x0000062a, 0x5747218a},
+	{0x00fe84d7, 0x00000005, 0x00000205, 0xde8f14de},
+	{0xbebdcb4c, 0x00000006, 0x0000055d, 0x3563b7b9},
+	{0xd8b1a02a, 0x00000010, 0x00000387, 0x071475d0},
+	{0x3b96cad2, 0x00000036, 0x00000347, 0x54c79d60},
+	{0xc94c1ed7, 0x00000005, 0x0000038b, 0x4c53eee6},
+	{0x1aad454e, 0x00000025, 0x000002b2, 0x10137a3c},
+	{0xa4fec9a6, 0x00000000, 0x000006d6, 0xaa9d6c73},
+	{0x1bbe71e2, 0x0000001f, 0x000002fd, 0xb63d23e7},
+	{0x4201c7e4, 0x00000002, 0x000002b7, 0x7f53e9cf},
+	{0x23fddc96, 0x00000003, 0x00000627, 0x13c1cd83},
+	{0xd82ba25c, 0x00000016, 0x0000063e, 0x49ff5867},
+	{0x786f2032, 0x0000002d, 0x0000060f, 0x8467f211},
+	{0xfebe4e1f, 0x0000002a, 0x000004f2, 0x3f9683b2},
+	{0x1a6e0a39, 0x00000008, 0x00000672, 0x76a3f874},
+	{0x56000ab8, 0x0000000e, 0x000000e5, 0x863b702f},
+	{0x4717fe0c, 0x00000000, 0x000006ec, 0xdc6c58ff},
+	{0xd5d5d68e, 0x0000003c, 0x000003a3, 0x0622cc95},
+	{0xc25dd6c6, 0x00000024, 0x000006c0, 0xe85605cd},
+	{0xe9b11300, 0x00000023, 0x00000683, 0x31da5f06},
+	{0x95cd285e, 0x00000001, 0x00000047, 0xa1f2e784},
+	{0xd9245a25, 0x0000001e, 0x000003a6, 0xb07cc616},
+	{0x103279db, 0x00000006, 0x0000039b, 0xbf943b6c},
+	{0x1cba3172, 0x00000027, 0x000001c8, 0x2c01af1c},
+	{0x8f613739, 0x0000000c, 0x000001df, 0x0fe5f56d},
+	{0x1c6aa90d, 0x0000001b, 0x0000053c, 0xf8943b2d},
+	{0xaabe5b93, 0x0000003d, 0x00000715, 0xe4d89272},
+	{0xf15dd038, 0x00000006, 0x000006db, 0x7c2f6bbb},
+	{0x584dd49c, 0x00000020, 0x000007bc, 0xabbf388b},
+	{0x5d8c9506, 0x00000020, 0x00000470, 0x1dca1f4e},
+	{0xb80d17b0, 0x00000032, 0x00000346, 0x5c170e23},
+	{0xdaf0592e, 0x00000023, 0x000007b0, 0xc0e9d672},
+	{0x4793cc85, 0x0000000d, 0x00000706, 0xc18bdc86},
+	{0x82ebf64e, 0x00000009, 0x000007c3, 0xa874fcdd},
+	{0xb18a0319, 0x00000026, 0x000007db, 0x9dc0bb48},
+};
+
+static int crc32c_test(void)
+{
+	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 u32 crc;
+
+	/* pre-warm the cache */
+	for (i = 0; i < 100; i++) {
+		bytes += 2*test[i].length;
+
+		crc ^= crc32c_le(test[i].crc, test_buf +
+		    test[i].start, test[i].length);
+	}
+
+	gettimeofday(&start, NULL);
+	for (i = 0; i < 100; i++) {
+		if (test[i].crc32c_le != crc32c_le(test[i].crc, test_buf +
+		    test[i].start, test[i].length))
+			errors++;
+	}
+	gettimeofday(&stop, NULL);
+
+	usec = stop.tv_usec - start.tv_usec +
+		1000000 * (stop.tv_sec - start.tv_sec);
+
+	if (errors)
+		printf("crc32c: %d self tests failed\n", errors);
+	else {
+		printf("crc32c: tests passed, %d bytes in %" PRIu64 " usec\n",
+			bytes, usec);
+	}
+
+	return errors;
+}
+
+/*
+ * make sure we always return 0 for a successful test run, and non-zero for a
+ * failed run. The build infrastructure is looking for this information to
+ * determine whether to allow the build to proceed.
+ */
+int main(int argc, char **argv)
+{
+	int errors;
+
+	printf("CRC_LE_BITS = %d\n", CRC_LE_BITS);
+
+	errors = crc32c_test();
+
+	return errors != 0;
+}
+#endif /* CRC32_SELFTEST */
diff --git a/libfrog/crc32defs.h b/libfrog/crc32defs.h
new file mode 100644
index 00000000..57c328c2
--- /dev/null
+++ b/libfrog/crc32defs.h
@@ -0,0 +1,49 @@
+/*
+ * Use slice-by-8, which is the fastest variant.
+ *
+ * Calculate checksum 8 bytes at a time with a clever slicing algorithm.
+ * This is the fastest algorithm, but comes with a 8KiB lookup table.
+ * Most modern processors have enough cache to hold this table without
+ * thrashing the cache.
+ *
+ * The Linux kernel uses this as the default implementation "unless you
+ * have a good reason not to".  The reason why Kconfig urges you to pick
+ * SLICEBY8 is because people challenged the assertion that we should
+ * always use slice by 8, so Darrick wrote a crc microbenchmark utility
+ * and ran it on as many machines as he could get his hands on to show
+ * that sb8 was the fastest.
+ *
+ * Every 64-bit machine (and most of the 32-bit ones too) saw the best
+ * results with sb8.  Any machine with more than 4K of cache saw better
+ * results.  The spreadsheet still exists today[1]; note that
+ * 'crc32-kern-le' corresponds to the slice by 4 algorithm which is the
+ * default unless CRC_LE_BITS is defined explicitly.
+ *
+ * FWIW, there are a handful of board defconfigs in the kernel that
+ * don't pick sliceby8.  These are all embedded 32-bit mips/ppc systems
+ * with very small cache sizes which experience cache thrashing with the
+ * slice by 8 algorithm, and therefore chose to pick defaults that are
+ * saner for their particular board configuration.  For nearly all of
+ * XFS' perceived userbase (which we assume are 32 and 64-bit machines
+ * with sufficiently large CPU cache and largeish storage devices) slice
+ * by 8 is the right choice.
+ *
+ * [1] https://goo.gl/0LSzsG ("crc32c_bench")
+ */
+#define CRC_LE_BITS 64
+
+/*
+ * This is the CRC32c polynomial, as outlined by Castagnoli.
+ * x^32+x^28+x^27+x^26+x^25+x^23+x^22+x^20+x^19+x^18+x^14+x^13+x^11+x^10+x^9+
+ * x^8+x^6+x^0
+ */
+#define CRC32C_POLY_LE 0x82F63B78
+
+/*
+ * Little-endian CRC computation.  Used with serial bit streams sent
+ * lsbit-first.  Be sure to use cpu_to_le32() to append the computed CRC.
+ */
+#if CRC_LE_BITS > 64 || CRC_LE_BITS < 1 || CRC_LE_BITS == 16 || \
+	CRC_LE_BITS & CRC_LE_BITS-1
+# error "CRC_LE_BITS must be one of {1, 2, 4, 8, 32, 64}"
+#endif
diff --git a/libfrog/gen_crc32table.c b/libfrog/gen_crc32table.c
new file mode 100644
index 00000000..d5724326
--- /dev/null
+++ b/libfrog/gen_crc32table.c
@@ -0,0 +1,80 @@
+#include <stdio.h>
+#include "crc32defs.h"
+#include <inttypes.h>
+
+#define ENTRIES_PER_LINE 4
+
+#if CRC_LE_BITS > 8
+# define LE_TABLE_ROWS (CRC_LE_BITS/8)
+# define LE_TABLE_SIZE 256
+#else
+# define LE_TABLE_ROWS 1
+# define LE_TABLE_SIZE (1 << CRC_LE_BITS)
+#endif
+
+static uint32_t crc32ctable_le[LE_TABLE_ROWS][256];
+
+/**
+ * crc32init_le() - allocate and initialize LE table data
+ *
+ * crc is the crc of the byte i; other entries are filled in based on the
+ * fact that crctable[i^j] = crctable[i] ^ crctable[j].
+ *
+ */
+static void crc32init_le_generic(const uint32_t polynomial,
+				 uint32_t (*tab)[256])
+{
+	unsigned i, j;
+	uint32_t crc = 1;
+
+	tab[0][0] = 0;
+
+	for (i = LE_TABLE_SIZE >> 1; i; i >>= 1) {
+		crc = (crc >> 1) ^ ((crc & 1) ? polynomial : 0);
+		for (j = 0; j < LE_TABLE_SIZE; j += 2 * i)
+			tab[0][i + j] = crc ^ tab[0][j];
+	}
+	for (i = 0; i < LE_TABLE_SIZE; i++) {
+		crc = tab[0][i];
+		for (j = 1; j < LE_TABLE_ROWS; j++) {
+			crc = tab[0][crc & 0xff] ^ (crc >> 8);
+			tab[j][i] = crc;
+		}
+	}
+}
+
+static void crc32cinit_le(void)
+{
+	crc32init_le_generic(CRC32C_POLY_LE, crc32ctable_le);
+}
+
+static void output_table(uint32_t (*table)[256], int rows, int len, char *trans)
+{
+	int i, j;
+
+	for (j = 0 ; j < rows; j++) {
+		printf("{");
+		for (i = 0; i < len - 1; i++) {
+			if (i % ENTRIES_PER_LINE == 0)
+				printf("\n");
+			printf("%s(0x%8.8xL), ", trans, table[j][i]);
+		}
+		printf("%s(0x%8.8xL)},\n", trans, table[j][len - 1]);
+	}
+}
+
+int main(int argc, char** argv)
+{
+	printf("/* this file is generated - do not edit */\n\n");
+
+	if (CRC_LE_BITS > 1) {
+		crc32cinit_le();
+		printf("static u32 crc32ctable_le[%d][%d] = {",
+		       LE_TABLE_ROWS, LE_TABLE_SIZE);
+		output_table(crc32ctable_le, LE_TABLE_ROWS,
+			     LE_TABLE_SIZE, "tole");
+		printf("};\n");
+	}
+
+	return 0;
+}
diff --git a/libxfs/Makefile b/libxfs/Makefile
index 42ce0f8a..3cbfc9ff 100644
--- a/libxfs/Makefile
+++ b/libxfs/Makefile
@@ -48,13 +48,10 @@ HFILES = \
 	libxfs_io.h \
 	libxfs_api_defs.h \
 	init.h \
-	crc32defs.h \
-	crc32table.h \
 	libxfs_priv.h \
 	xfs_dir2_priv.h
 
 CFILES = cache.c \
-	crc32.c \
 	defer_item.c \
 	init.c \
 	kmem.c \
@@ -99,8 +96,6 @@ CFILES = cache.c \
 	xfs_trans_resv.c \
 	xfs_types.c
 
-LSRCFILES += gen_crc32table.c
-
 #
 # Tracing flags:
 # -DIO_DEBUG		reads and writes of buffers
@@ -117,25 +112,7 @@ LTLIBS = $(LIBPTHREAD) $(LIBRT)
 # don't try linking xfs_repair with a debug libxfs.
 DEBUG = -DNDEBUG
 
-LDIRT = gen_crc32table crc32table.h crc32selftest
-
-default: crc32selftest ltdepend $(LTLIBRARY)
-
-crc32table.h: gen_crc32table.c crc32defs.h
-	@echo "    [CC]     gen_crc32table"
-	$(Q) $(BUILD_CC) $(BUILD_CFLAGS) -o gen_crc32table $<
-	@echo "    [GENERATE] $@"
-	$(Q) ./gen_crc32table > crc32table.h
-
-# The selftest binary will return an error if it fails. This is made a
-# dependency of the build process so that we refuse to build the tools on broken
-# systems/architectures. Hence we make sure that xfsprogs will never use a
-# busted CRC calculation at build time and hence avoid putting bad CRCs down on
-# disk.
-crc32selftest: gen_crc32table.c crc32table.h crc32.c crc32defs.h
-	@echo "    [TEST]    CRC32"
-	$(Q) $(BUILD_CC) $(BUILD_CFLAGS) -D CRC32_SELFTEST=1 crc32.c -o $@
-	$(Q) ./$@
+default: ltdepend $(LTLIBRARY)
 
 # set up include/xfs header directory
 include $(BUILDRULES)
diff --git a/libxfs/crc32.c b/libxfs/crc32.c
deleted file mode 100644
index a80a0c54..00000000
--- a/libxfs/crc32.c
+++ /dev/null
@@ -1,869 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Aug 8, 2011 Bob Pearson with help from Joakim Tjernlund and George Spelvin
- * cleaned up code to current version of sparse and added the slicing-by-8
- * algorithm to the closely similar existing slicing-by-4 algorithm.
- * Oct 15, 2000 Matt Domsch <Matt_Domsch@dell.com>
- * Nicer crc32 functions/docs submitted by linux@horizon.com.  Thanks!
- * Code was from the public domain, copyright abandoned.  Code was
- * subsequently included in the kernel, thus was re-licensed under the
- * GNU GPL v2.
- * Oct 12, 2000 Matt Domsch <Matt_Domsch@dell.com>
- * Same crc32 function was used in 5 other places in the kernel.
- * I made one version, and deleted the others.
- * There are various incantations of crc32().  Some use a seed of 0 or ~0.
- * Some xor at the end with ~0.  The generic crc32() function takes
- * seed as an argument, and doesn't xor at the end.  Then individual
- * users can do whatever they need.
- *   drivers/net/smc9194.c uses seed ~0, doesn't xor with ~0.
- *   fs/jffs2 uses seed 0, doesn't xor with ~0.
- *   fs/partitions/efi.c uses seed ~0, xor's with ~0.
- * This source code is licensed under the GNU General Public License,
- * Version 2.  See the file COPYING for more details.
- */
-
-/* see: Documentation/crc32.txt for a description of algorithms */
-
-/*
- * lifted from the 3.8-rc2 kernel source for xfsprogs. Killed CONFIG_X86
- * specific bits for just the generic algorithm. Also removed the big endian
- * version of the algorithm as XFS only uses the little endian CRC version to
- * match the hardware acceleration available on Intel CPUs.
- */
-
-#include "platform_defs.h"
-#include "xfs.h"
-#include "xfs_arch.h"
-#include "crc32defs.h"
-
-/* types specifc to this file */
-typedef __u8	u8;
-typedef __u16	u16;
-typedef __u32	u32;
-typedef __u32	u64;
-#define __pure
-
-#if CRC_LE_BITS > 8
-# define tole(x) ((__force u32) __constant_cpu_to_le32(x))
-#else
-# define tole(x) (x)
-#endif
-
-#include "crc32table.h"
-
-#if CRC_LE_BITS > 8
-
-/* implements slicing-by-4 or slicing-by-8 algorithm */
-static inline u32
-crc32_body(u32 crc, unsigned char const *buf, size_t len, const u32 (*tab)[256])
-{
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-#  define DO_CRC(x) crc = t0[(crc ^ (x)) & 255] ^ (crc >> 8)
-#  define DO_CRC4 (t3[(q) & 255] ^ t2[(q >> 8) & 255] ^ \
-		   t1[(q >> 16) & 255] ^ t0[(q >> 24) & 255])
-#  define DO_CRC8 (t7[(q) & 255] ^ t6[(q >> 8) & 255] ^ \
-		   t5[(q >> 16) & 255] ^ t4[(q >> 24) & 255])
-# elif __BYTE_ORDER == __BIG_ENDIAN
-#  define DO_CRC(x) crc = t0[((crc >> 24) ^ (x)) & 255] ^ (crc << 8)
-#  define DO_CRC4 (t0[(q) & 255] ^ t1[(q >> 8) & 255] ^ \
-		   t2[(q >> 16) & 255] ^ t3[(q >> 24) & 255])
-#  define DO_CRC8 (t4[(q) & 255] ^ t5[(q >> 8) & 255] ^ \
-		   t6[(q >> 16) & 255] ^ t7[(q >> 24) & 255])
-# else
-#  error What endian are you?
-# endif
-	const u32 *b;
-	size_t    rem_len;
-	const u32 *t0=tab[0], *t1=tab[1], *t2=tab[2], *t3=tab[3];
-# if CRC_LE_BITS != 32
-	const u32 *t4 = tab[4], *t5 = tab[5], *t6 = tab[6], *t7 = tab[7];
-# endif
-	u32 q;
-
-	/* Align it */
-	if (((long)buf & 3) && len) {
-		do {
-			DO_CRC(*buf++);
-		} while ((--len) && ((long)buf)&3);
-	}
-
-# if CRC_LE_BITS == 32
-	rem_len = len & 3;
-	len = len >> 2;
-# else
-	rem_len = len & 7;
-	len = len >> 3;
-# endif
-
-	b = (const u32 *)buf;
-	for (--b; len; --len) {
-		q = crc ^ *++b; /* use pre increment for speed */
-# if CRC_LE_BITS == 32
-		crc = DO_CRC4;
-# else
-		crc = DO_CRC8;
-		q = *++b;
-		crc ^= DO_CRC4;
-# endif
-	}
-	len = rem_len;
-	/* And the last few bytes */
-	if (len) {
-		u8 *p = (u8 *)(b + 1) - 1;
-		do {
-			DO_CRC(*++p); /* use pre increment for speed */
-		} while (--len);
-	}
-	return crc;
-#undef DO_CRC
-#undef DO_CRC4
-#undef DO_CRC8
-}
-#endif
-
-/**
- * crc32_le() - Calculate bitwise little-endian Ethernet AUTODIN II CRC32
- * @crc: seed value for computation.  ~0 for Ethernet, sometimes 0 for
- *	other uses, or the previous crc32 value if computing incrementally.
- * @p: pointer to buffer over which CRC is run
- * @len: length of buffer @p
- */
-static inline u32 __pure crc32_le_generic(u32 crc, unsigned char const *p,
-					  size_t len, const u32 (*tab)[256],
-					  u32 polynomial)
-{
-#if CRC_LE_BITS == 1
-	int i;
-	while (len--) {
-		crc ^= *p++;
-		for (i = 0; i < 8; i++)
-			crc = (crc >> 1) ^ ((crc & 1) ? polynomial : 0);
-	}
-# elif CRC_LE_BITS == 2
-	while (len--) {
-		crc ^= *p++;
-		crc = (crc >> 2) ^ tab[0][crc & 3];
-		crc = (crc >> 2) ^ tab[0][crc & 3];
-		crc = (crc >> 2) ^ tab[0][crc & 3];
-		crc = (crc >> 2) ^ tab[0][crc & 3];
-	}
-# elif CRC_LE_BITS == 4
-	while (len--) {
-		crc ^= *p++;
-		crc = (crc >> 4) ^ tab[0][crc & 15];
-		crc = (crc >> 4) ^ tab[0][crc & 15];
-	}
-# elif CRC_LE_BITS == 8
-	/* aka Sarwate algorithm */
-	while (len--) {
-		crc ^= *p++;
-		crc = (crc >> 8) ^ tab[0][crc & 255];
-	}
-# else
-	crc = (__force u32) cpu_to_le32(crc);
-	crc = crc32_body(crc, p, len, tab);
-	crc = le32_to_cpu((__force __le32)crc);
-#endif
-	return crc;
-}
-
-#if CRC_LE_BITS == 1
-u32 __pure crc32c_le(u32 crc, unsigned char const *p, size_t len)
-{
-	return crc32_le_generic(crc, p, len, NULL, CRC32C_POLY_LE);
-}
-#else
-u32 __pure crc32c_le(u32 crc, unsigned char const *p, size_t len)
-{
-	return crc32_le_generic(crc, p, len,
-			(const u32 (*)[256])crc32ctable_le, CRC32C_POLY_LE);
-}
-#endif
-
-
-#ifdef CRC32_SELFTEST
-
-/* 4096 random bytes */
-static u8 __attribute__((__aligned__(8))) test_buf[] =
-{
-	0x5b, 0x85, 0x21, 0xcb, 0x09, 0x68, 0x7d, 0x30,
-	0xc7, 0x69, 0xd7, 0x30, 0x92, 0xde, 0x59, 0xe4,
-	0xc9, 0x6e, 0x8b, 0xdb, 0x98, 0x6b, 0xaa, 0x60,
-	0xa8, 0xb5, 0xbc, 0x6c, 0xa9, 0xb1, 0x5b, 0x2c,
-	0xea, 0xb4, 0x92, 0x6a, 0x3f, 0x79, 0x91, 0xe4,
-	0xe9, 0x70, 0x51, 0x8c, 0x7f, 0x95, 0x6f, 0x1a,
-	0x56, 0xa1, 0x5c, 0x27, 0x03, 0x67, 0x9f, 0x3a,
-	0xe2, 0x31, 0x11, 0x29, 0x6b, 0x98, 0xfc, 0xc4,
-	0x53, 0x24, 0xc5, 0x8b, 0xce, 0x47, 0xb2, 0xb9,
-	0x32, 0xcb, 0xc1, 0xd0, 0x03, 0x57, 0x4e, 0xd4,
-	0xe9, 0x3c, 0xa1, 0x63, 0xcf, 0x12, 0x0e, 0xca,
-	0xe1, 0x13, 0xd1, 0x93, 0xa6, 0x88, 0x5c, 0x61,
-	0x5b, 0xbb, 0xf0, 0x19, 0x46, 0xb4, 0xcf, 0x9e,
-	0xb6, 0x6b, 0x4c, 0x3a, 0xcf, 0x60, 0xf9, 0x7a,
-	0x8d, 0x07, 0x63, 0xdb, 0x40, 0xe9, 0x0b, 0x6f,
-	0xad, 0x97, 0xf1, 0xed, 0xd0, 0x1e, 0x26, 0xfd,
-	0xbf, 0xb7, 0xc8, 0x04, 0x94, 0xf8, 0x8b, 0x8c,
-	0xf1, 0xab, 0x7a, 0xd4, 0xdd, 0xf3, 0xe8, 0x88,
-	0xc3, 0xed, 0x17, 0x8a, 0x9b, 0x40, 0x0d, 0x53,
-	0x62, 0x12, 0x03, 0x5f, 0x1b, 0x35, 0x32, 0x1f,
-	0xb4, 0x7b, 0x93, 0x78, 0x0d, 0xdb, 0xce, 0xa4,
-	0xc0, 0x47, 0xd5, 0xbf, 0x68, 0xe8, 0x5d, 0x74,
-	0x8f, 0x8e, 0x75, 0x1c, 0xb2, 0x4f, 0x9a, 0x60,
-	0xd1, 0xbe, 0x10, 0xf4, 0x5c, 0xa1, 0x53, 0x09,
-	0xa5, 0xe0, 0x09, 0x54, 0x85, 0x5c, 0xdc, 0x07,
-	0xe7, 0x21, 0x69, 0x7b, 0x8a, 0xfd, 0x90, 0xf1,
-	0x22, 0xd0, 0xb4, 0x36, 0x28, 0xe6, 0xb8, 0x0f,
-	0x39, 0xde, 0xc8, 0xf3, 0x86, 0x60, 0x34, 0xd2,
-	0x5e, 0xdf, 0xfd, 0xcf, 0x0f, 0xa9, 0x65, 0xf0,
-	0xd5, 0x4d, 0x96, 0x40, 0xe3, 0xdf, 0x3f, 0x95,
-	0x5a, 0x39, 0x19, 0x93, 0xf4, 0x75, 0xce, 0x22,
-	0x00, 0x1c, 0x93, 0xe2, 0x03, 0x66, 0xf4, 0x93,
-	0x73, 0x86, 0x81, 0x8e, 0x29, 0x44, 0x48, 0x86,
-	0x61, 0x7c, 0x48, 0xa3, 0x43, 0xd2, 0x9c, 0x8d,
-	0xd4, 0x95, 0xdd, 0xe1, 0x22, 0x89, 0x3a, 0x40,
-	0x4c, 0x1b, 0x8a, 0x04, 0xa8, 0x09, 0x69, 0x8b,
-	0xea, 0xc6, 0x55, 0x8e, 0x57, 0xe6, 0x64, 0x35,
-	0xf0, 0xc7, 0x16, 0x9f, 0x5d, 0x5e, 0x86, 0x40,
-	0x46, 0xbb, 0xe5, 0x45, 0x88, 0xfe, 0xc9, 0x63,
-	0x15, 0xfb, 0xf5, 0xbd, 0x71, 0x61, 0xeb, 0x7b,
-	0x78, 0x70, 0x07, 0x31, 0x03, 0x9f, 0xb2, 0xc8,
-	0xa7, 0xab, 0x47, 0xfd, 0xdf, 0xa0, 0x78, 0x72,
-	0xa4, 0x2a, 0xe4, 0xb6, 0xba, 0xc0, 0x1e, 0x86,
-	0x71, 0xe6, 0x3d, 0x18, 0x37, 0x70, 0xe6, 0xff,
-	0xe0, 0xbc, 0x0b, 0x22, 0xa0, 0x1f, 0xd3, 0xed,
-	0xa2, 0x55, 0x39, 0xab, 0xa8, 0x13, 0x73, 0x7c,
-	0x3f, 0xb2, 0xd6, 0x19, 0xac, 0xff, 0x99, 0xed,
-	0xe8, 0xe6, 0xa6, 0x22, 0xe3, 0x9c, 0xf1, 0x30,
-	0xdc, 0x01, 0x0a, 0x56, 0xfa, 0xe4, 0xc9, 0x99,
-	0xdd, 0xa8, 0xd8, 0xda, 0x35, 0x51, 0x73, 0xb4,
-	0x40, 0x86, 0x85, 0xdb, 0x5c, 0xd5, 0x85, 0x80,
-	0x14, 0x9c, 0xfd, 0x98, 0xa9, 0x82, 0xc5, 0x37,
-	0xff, 0x32, 0x5d, 0xd0, 0x0b, 0xfa, 0xdc, 0x04,
-	0x5e, 0x09, 0xd2, 0xca, 0x17, 0x4b, 0x1a, 0x8e,
-	0x15, 0xe1, 0xcc, 0x4e, 0x52, 0x88, 0x35, 0xbd,
-	0x48, 0xfe, 0x15, 0xa0, 0x91, 0xfd, 0x7e, 0x6c,
-	0x0e, 0x5d, 0x79, 0x1b, 0x81, 0x79, 0xd2, 0x09,
-	0x34, 0x70, 0x3d, 0x81, 0xec, 0xf6, 0x24, 0xbb,
-	0xfb, 0xf1, 0x7b, 0xdf, 0x54, 0xea, 0x80, 0x9b,
-	0xc7, 0x99, 0x9e, 0xbd, 0x16, 0x78, 0x12, 0x53,
-	0x5e, 0x01, 0xa7, 0x4e, 0xbd, 0x67, 0xe1, 0x9b,
-	0x4c, 0x0e, 0x61, 0x45, 0x97, 0xd2, 0xf0, 0x0f,
-	0xfe, 0x15, 0x08, 0xb7, 0x11, 0x4c, 0xe7, 0xff,
-	0x81, 0x53, 0xff, 0x91, 0x25, 0x38, 0x7e, 0x40,
-	0x94, 0xe5, 0xe0, 0xad, 0xe6, 0xd9, 0x79, 0xb6,
-	0x92, 0xc9, 0xfc, 0xde, 0xc3, 0x1a, 0x23, 0xbb,
-	0xdd, 0xc8, 0x51, 0x0c, 0x3a, 0x72, 0xfa, 0x73,
-	0x6f, 0xb7, 0xee, 0x61, 0x39, 0x03, 0x01, 0x3f,
-	0x7f, 0x94, 0x2e, 0x2e, 0xba, 0x3a, 0xbb, 0xb4,
-	0xfa, 0x6a, 0x17, 0xfe, 0xea, 0xef, 0x5e, 0x66,
-	0x97, 0x3f, 0x32, 0x3d, 0xd7, 0x3e, 0xb1, 0xf1,
-	0x6c, 0x14, 0x4c, 0xfd, 0x37, 0xd3, 0x38, 0x80,
-	0xfb, 0xde, 0xa6, 0x24, 0x1e, 0xc8, 0xca, 0x7f,
-	0x3a, 0x93, 0xd8, 0x8b, 0x18, 0x13, 0xb2, 0xe5,
-	0xe4, 0x93, 0x05, 0x53, 0x4f, 0x84, 0x66, 0xa7,
-	0x58, 0x5c, 0x7b, 0x86, 0x52, 0x6d, 0x0d, 0xce,
-	0xa4, 0x30, 0x7d, 0xb6, 0x18, 0x9f, 0xeb, 0xff,
-	0x22, 0xbb, 0x72, 0x29, 0xb9, 0x44, 0x0b, 0x48,
-	0x1e, 0x84, 0x71, 0x81, 0xe3, 0x6d, 0x73, 0x26,
-	0x92, 0xb4, 0x4d, 0x2a, 0x29, 0xb8, 0x1f, 0x72,
-	0xed, 0xd0, 0xe1, 0x64, 0x77, 0xea, 0x8e, 0x88,
-	0x0f, 0xef, 0x3f, 0xb1, 0x3b, 0xad, 0xf9, 0xc9,
-	0x8b, 0xd0, 0xac, 0xc6, 0xcc, 0xa9, 0x40, 0xcc,
-	0x76, 0xf6, 0x3b, 0x53, 0xb5, 0x88, 0xcb, 0xc8,
-	0x37, 0xf1, 0xa2, 0xba, 0x23, 0x15, 0x99, 0x09,
-	0xcc, 0xe7, 0x7a, 0x3b, 0x37, 0xf7, 0x58, 0xc8,
-	0x46, 0x8c, 0x2b, 0x2f, 0x4e, 0x0e, 0xa6, 0x5c,
-	0xea, 0x85, 0x55, 0xba, 0x02, 0x0e, 0x0e, 0x48,
-	0xbc, 0xe1, 0xb1, 0x01, 0x35, 0x79, 0x13, 0x3d,
-	0x1b, 0xc0, 0x53, 0x68, 0x11, 0xe7, 0x95, 0x0f,
-	0x9d, 0x3f, 0x4c, 0x47, 0x7b, 0x4d, 0x1c, 0xae,
-	0x50, 0x9b, 0xcb, 0xdd, 0x05, 0x8d, 0x9a, 0x97,
-	0xfd, 0x8c, 0xef, 0x0c, 0x1d, 0x67, 0x73, 0xa8,
-	0x28, 0x36, 0xd5, 0xb6, 0x92, 0x33, 0x40, 0x75,
-	0x0b, 0x51, 0xc3, 0x64, 0xba, 0x1d, 0xc2, 0xcc,
-	0xee, 0x7d, 0x54, 0x0f, 0x27, 0x69, 0xa7, 0x27,
-	0x63, 0x30, 0x29, 0xd9, 0xc8, 0x84, 0xd8, 0xdf,
-	0x9f, 0x68, 0x8d, 0x04, 0xca, 0xa6, 0xc5, 0xc7,
-	0x7a, 0x5c, 0xc8, 0xd1, 0xcb, 0x4a, 0xec, 0xd0,
-	0xd8, 0x20, 0x69, 0xc5, 0x17, 0xcd, 0x78, 0xc8,
-	0x75, 0x23, 0x30, 0x69, 0xc9, 0xd4, 0xea, 0x5c,
-	0x4f, 0x6b, 0x86, 0x3f, 0x8b, 0xfe, 0xee, 0x44,
-	0xc9, 0x7c, 0xb7, 0xdd, 0x3e, 0xe5, 0xec, 0x54,
-	0x03, 0x3e, 0xaa, 0x82, 0xc6, 0xdf, 0xb2, 0x38,
-	0x0e, 0x5d, 0xb3, 0x88, 0xd9, 0xd3, 0x69, 0x5f,
-	0x8f, 0x70, 0x8a, 0x7e, 0x11, 0xd9, 0x1e, 0x7b,
-	0x38, 0xf1, 0x42, 0x1a, 0xc0, 0x35, 0xf5, 0xc7,
-	0x36, 0x85, 0xf5, 0xf7, 0xb8, 0x7e, 0xc7, 0xef,
-	0x18, 0xf1, 0x63, 0xd6, 0x7a, 0xc6, 0xc9, 0x0e,
-	0x4d, 0x69, 0x4f, 0x84, 0xef, 0x26, 0x41, 0x0c,
-	0xec, 0xc7, 0xe0, 0x7e, 0x3c, 0x67, 0x01, 0x4c,
-	0x62, 0x1a, 0x20, 0x6f, 0xee, 0x47, 0x4d, 0xc0,
-	0x99, 0x13, 0x8d, 0x91, 0x4a, 0x26, 0xd4, 0x37,
-	0x28, 0x90, 0x58, 0x75, 0x66, 0x2b, 0x0a, 0xdf,
-	0xda, 0xee, 0x92, 0x25, 0x90, 0x62, 0x39, 0x9e,
-	0x44, 0x98, 0xad, 0xc1, 0x88, 0xed, 0xe4, 0xb4,
-	0xaf, 0xf5, 0x8c, 0x9b, 0x48, 0x4d, 0x56, 0x60,
-	0x97, 0x0f, 0x61, 0x59, 0x9e, 0xa6, 0x27, 0xfe,
-	0xc1, 0x91, 0x15, 0x38, 0xb8, 0x0f, 0xae, 0x61,
-	0x7d, 0x26, 0x13, 0x5a, 0x73, 0xff, 0x1c, 0xa3,
-	0x61, 0x04, 0x58, 0x48, 0x55, 0x44, 0x11, 0xfe,
-	0x15, 0xca, 0xc3, 0xbd, 0xca, 0xc5, 0xb4, 0x40,
-	0x5d, 0x1b, 0x7f, 0x39, 0xb5, 0x9c, 0x35, 0xec,
-	0x61, 0x15, 0x32, 0x32, 0xb8, 0x4e, 0x40, 0x9f,
-	0x17, 0x1f, 0x0a, 0x4d, 0xa9, 0x91, 0xef, 0xb7,
-	0xb0, 0xeb, 0xc2, 0x83, 0x9a, 0x6c, 0xd2, 0x79,
-	0x43, 0x78, 0x5e, 0x2f, 0xe5, 0xdd, 0x1a, 0x3c,
-	0x45, 0xab, 0x29, 0x40, 0x3a, 0x37, 0x5b, 0x6f,
-	0xd7, 0xfc, 0x48, 0x64, 0x3c, 0x49, 0xfb, 0x21,
-	0xbe, 0xc3, 0xff, 0x07, 0xfb, 0x17, 0xe9, 0xc9,
-	0x0c, 0x4c, 0x5c, 0x15, 0x9e, 0x8e, 0x22, 0x30,
-	0x0a, 0xde, 0x48, 0x7f, 0xdb, 0x0d, 0xd1, 0x2b,
-	0x87, 0x38, 0x9e, 0xcc, 0x5a, 0x01, 0x16, 0xee,
-	0x75, 0x49, 0x0d, 0x30, 0x01, 0x34, 0x6a, 0xb6,
-	0x9a, 0x5a, 0x2a, 0xec, 0xbb, 0x48, 0xac, 0xd3,
-	0x77, 0x83, 0xd8, 0x08, 0x86, 0x4f, 0x48, 0x09,
-	0x29, 0x41, 0x79, 0xa1, 0x03, 0x12, 0xc4, 0xcd,
-	0x90, 0x55, 0x47, 0x66, 0x74, 0x9a, 0xcc, 0x4f,
-	0x35, 0x8c, 0xd6, 0x98, 0xef, 0xeb, 0x45, 0xb9,
-	0x9a, 0x26, 0x2f, 0x39, 0xa5, 0x70, 0x6d, 0xfc,
-	0xb4, 0x51, 0xee, 0xf4, 0x9c, 0xe7, 0x38, 0x59,
-	0xad, 0xf4, 0xbc, 0x46, 0xff, 0x46, 0x8e, 0x60,
-	0x9c, 0xa3, 0x60, 0x1d, 0xf8, 0x26, 0x72, 0xf5,
-	0x72, 0x9d, 0x68, 0x80, 0x04, 0xf6, 0x0b, 0xa1,
-	0x0a, 0xd5, 0xa7, 0x82, 0x3a, 0x3e, 0x47, 0xa8,
-	0x5a, 0xde, 0x59, 0x4f, 0x7b, 0x07, 0xb3, 0xe9,
-	0x24, 0x19, 0x3d, 0x34, 0x05, 0xec, 0xf1, 0xab,
-	0x6e, 0x64, 0x8f, 0xd3, 0xe6, 0x41, 0x86, 0x80,
-	0x70, 0xe3, 0x8d, 0x60, 0x9c, 0x34, 0x25, 0x01,
-	0x07, 0x4d, 0x19, 0x41, 0x4e, 0x3d, 0x5c, 0x7e,
-	0xa8, 0xf5, 0xcc, 0xd5, 0x7b, 0xe2, 0x7d, 0x3d,
-	0x49, 0x86, 0x7d, 0x07, 0xb7, 0x10, 0xe3, 0x35,
-	0xb8, 0x84, 0x6d, 0x76, 0xab, 0x17, 0xc6, 0x38,
-	0xb4, 0xd3, 0x28, 0x57, 0xad, 0xd3, 0x88, 0x5a,
-	0xda, 0xea, 0xc8, 0x94, 0xcc, 0x37, 0x19, 0xac,
-	0x9c, 0x9f, 0x4b, 0x00, 0x15, 0xc0, 0xc8, 0xca,
-	0x1f, 0x15, 0xaa, 0xe0, 0xdb, 0xf9, 0x2f, 0x57,
-	0x1b, 0x24, 0xc7, 0x6f, 0x76, 0x29, 0xfb, 0xed,
-	0x25, 0x0d, 0xc0, 0xfe, 0xbd, 0x5a, 0xbf, 0x20,
-	0x08, 0x51, 0x05, 0xec, 0x71, 0xa3, 0xbf, 0xef,
-	0x5e, 0x99, 0x75, 0xdb, 0x3c, 0x5f, 0x9a, 0x8c,
-	0xbb, 0x19, 0x5c, 0x0e, 0x93, 0x19, 0xf8, 0x6a,
-	0xbc, 0xf2, 0x12, 0x54, 0x2f, 0xcb, 0x28, 0x64,
-	0x88, 0xb3, 0x92, 0x0d, 0x96, 0xd1, 0xa6, 0xe4,
-	0x1f, 0xf1, 0x4d, 0xa4, 0xab, 0x1c, 0xee, 0x54,
-	0xf2, 0xad, 0x29, 0x6d, 0x32, 0x37, 0xb2, 0x16,
-	0x77, 0x5c, 0xdc, 0x2e, 0x54, 0xec, 0x75, 0x26,
-	0xc6, 0x36, 0xd9, 0x17, 0x2c, 0xf1, 0x7a, 0xdc,
-	0x4b, 0xf1, 0xe2, 0xd9, 0x95, 0xba, 0xac, 0x87,
-	0xc1, 0xf3, 0x8e, 0x58, 0x08, 0xd8, 0x87, 0x60,
-	0xc9, 0xee, 0x6a, 0xde, 0xa4, 0xd2, 0xfc, 0x0d,
-	0xe5, 0x36, 0xc4, 0x5c, 0x52, 0xb3, 0x07, 0x54,
-	0x65, 0x24, 0xc1, 0xb1, 0xd1, 0xb1, 0x53, 0x13,
-	0x31, 0x79, 0x7f, 0x05, 0x76, 0xeb, 0x37, 0x59,
-	0x15, 0x2b, 0xd1, 0x3f, 0xac, 0x08, 0x97, 0xeb,
-	0x91, 0x98, 0xdf, 0x6c, 0x09, 0x0d, 0x04, 0x9f,
-	0xdc, 0x3b, 0x0e, 0x60, 0x68, 0x47, 0x23, 0x15,
-	0x16, 0xc6, 0x0b, 0x35, 0xf8, 0x77, 0xa2, 0x78,
-	0x50, 0xd4, 0x64, 0x22, 0x33, 0xff, 0xfb, 0x93,
-	0x71, 0x46, 0x50, 0x39, 0x1b, 0x9c, 0xea, 0x4e,
-	0x8d, 0x0c, 0x37, 0xe5, 0x5c, 0x51, 0x3a, 0x31,
-	0xb2, 0x85, 0x84, 0x3f, 0x41, 0xee, 0xa2, 0xc1,
-	0xc6, 0x13, 0x3b, 0x54, 0x28, 0xd2, 0x18, 0x37,
-	0xcc, 0x46, 0x9f, 0x6a, 0x91, 0x3d, 0x5a, 0x15,
-	0x3c, 0x89, 0xa3, 0x61, 0x06, 0x7d, 0x2e, 0x78,
-	0xbe, 0x7d, 0x40, 0xba, 0x2f, 0x95, 0xb1, 0x2f,
-	0x87, 0x3b, 0x8a, 0xbe, 0x6a, 0xf4, 0xc2, 0x31,
-	0x74, 0xee, 0x91, 0xe0, 0x23, 0xaa, 0x5d, 0x7f,
-	0xdd, 0xf0, 0x44, 0x8c, 0x0b, 0x59, 0x2b, 0xfc,
-	0x48, 0x3a, 0xdf, 0x07, 0x05, 0x38, 0x6c, 0xc9,
-	0xeb, 0x18, 0x24, 0x68, 0x8d, 0x58, 0x98, 0xd3,
-	0x31, 0xa3, 0xe4, 0x70, 0x59, 0xb1, 0x21, 0xbe,
-	0x7e, 0x65, 0x7d, 0xb8, 0x04, 0xab, 0xf6, 0xe4,
-	0xd7, 0xda, 0xec, 0x09, 0x8f, 0xda, 0x6d, 0x24,
-	0x07, 0xcc, 0x29, 0x17, 0x05, 0x78, 0x1a, 0xc1,
-	0xb1, 0xce, 0xfc, 0xaa, 0x2d, 0xe7, 0xcc, 0x85,
-	0x84, 0x84, 0x03, 0x2a, 0x0c, 0x3f, 0xa9, 0xf8,
-	0xfd, 0x84, 0x53, 0x59, 0x5c, 0xf0, 0xd4, 0x09,
-	0xf0, 0xd2, 0x6c, 0x32, 0x03, 0xb0, 0xa0, 0x8c,
-	0x52, 0xeb, 0x23, 0x91, 0x88, 0x43, 0x13, 0x46,
-	0xf6, 0x1e, 0xb4, 0x1b, 0xf5, 0x8e, 0x3a, 0xb5,
-	0x3d, 0x00, 0xf6, 0xe5, 0x08, 0x3d, 0x5f, 0x39,
-	0xd3, 0x21, 0x69, 0xbc, 0x03, 0x22, 0x3a, 0xd2,
-	0x5c, 0x84, 0xf8, 0x15, 0xc4, 0x80, 0x0b, 0xbc,
-	0x29, 0x3c, 0xf3, 0x95, 0x98, 0xcd, 0x8f, 0x35,
-	0xbc, 0xa5, 0x3e, 0xfc, 0xd4, 0x13, 0x9e, 0xde,
-	0x4f, 0xce, 0x71, 0x9d, 0x09, 0xad, 0xf2, 0x80,
-	0x6b, 0x65, 0x7f, 0x03, 0x00, 0x14, 0x7c, 0x15,
-	0x85, 0x40, 0x6d, 0x70, 0xea, 0xdc, 0xb3, 0x63,
-	0x35, 0x4f, 0x4d, 0xe0, 0xd9, 0xd5, 0x3c, 0x58,
-	0x56, 0x23, 0x80, 0xe2, 0x36, 0xdd, 0x75, 0x1d,
-	0x94, 0x11, 0x41, 0x8e, 0xe0, 0x81, 0x8e, 0xcf,
-	0xe0, 0xe5, 0xf6, 0xde, 0xd1, 0xe7, 0x04, 0x12,
-	0x79, 0x92, 0x2b, 0x71, 0x2a, 0x79, 0x8b, 0x7c,
-	0x44, 0x79, 0x16, 0x30, 0x4e, 0xf4, 0xf6, 0x9b,
-	0xb7, 0x40, 0xa3, 0x5a, 0xa7, 0x69, 0x3e, 0xc1,
-	0x3a, 0x04, 0xd0, 0x88, 0xa0, 0x3b, 0xdd, 0xc6,
-	0x9e, 0x7e, 0x1e, 0x1e, 0x8f, 0x44, 0xf7, 0x73,
-	0x67, 0x1e, 0x1a, 0x78, 0xfa, 0x62, 0xf4, 0xa9,
-	0xa8, 0xc6, 0x5b, 0xb8, 0xfa, 0x06, 0x7d, 0x5e,
-	0x38, 0x1c, 0x9a, 0x39, 0xe9, 0x39, 0x98, 0x22,
-	0x0b, 0xa7, 0xac, 0x0b, 0xf3, 0xbc, 0xf1, 0xeb,
-	0x8c, 0x81, 0xe3, 0x48, 0x8a, 0xed, 0x42, 0xc2,
-	0x38, 0xcf, 0x3e, 0xda, 0xd2, 0x89, 0x8d, 0x9c,
-	0x53, 0xb5, 0x2f, 0x41, 0x01, 0x26, 0x84, 0x9c,
-	0xa3, 0x56, 0xf6, 0x49, 0xc7, 0xd4, 0x9f, 0x93,
-	0x1b, 0x96, 0x49, 0x5e, 0xad, 0xb3, 0x84, 0x1f,
-	0x3c, 0xa4, 0xe0, 0x9b, 0xd1, 0x90, 0xbc, 0x38,
-	0x6c, 0xdd, 0x95, 0x4d, 0x9d, 0xb1, 0x71, 0x57,
-	0x2d, 0x34, 0xe8, 0xb8, 0x42, 0xc7, 0x99, 0x03,
-	0xc7, 0x07, 0x30, 0x65, 0x91, 0x55, 0xd5, 0x90,
-	0x70, 0x97, 0x37, 0x68, 0xd4, 0x11, 0xf9, 0xe8,
-	0xce, 0xec, 0xdc, 0x34, 0xd5, 0xd3, 0xb7, 0xc4,
-	0xb8, 0x97, 0x05, 0x92, 0xad, 0xf8, 0xe2, 0x36,
-	0x64, 0x41, 0xc9, 0xc5, 0x41, 0x77, 0x52, 0xd7,
-	0x2c, 0xa5, 0x24, 0x2f, 0xd9, 0x34, 0x0b, 0x47,
-	0x35, 0xa7, 0x28, 0x8b, 0xc5, 0xcd, 0xe9, 0x46,
-	0xac, 0x39, 0x94, 0x3c, 0x10, 0xc6, 0x29, 0x73,
-	0x0e, 0x0e, 0x5d, 0xe0, 0x71, 0x03, 0x8a, 0x72,
-	0x0e, 0x26, 0xb0, 0x7d, 0x84, 0xed, 0x95, 0x23,
-	0x49, 0x5a, 0x45, 0x83, 0x45, 0x60, 0x11, 0x4a,
-	0x46, 0x31, 0xd4, 0xd8, 0x16, 0x54, 0x98, 0x58,
-	0xed, 0x6d, 0xcc, 0x5d, 0xd6, 0x50, 0x61, 0x9f,
-	0x9d, 0xc5, 0x3e, 0x9d, 0x32, 0x47, 0xde, 0x96,
-	0xe1, 0x5d, 0xd8, 0xf8, 0xb4, 0x69, 0x6f, 0xb9,
-	0x15, 0x90, 0x57, 0x7a, 0xf6, 0xad, 0xb0, 0x5b,
-	0xf5, 0xa6, 0x36, 0x94, 0xfd, 0x84, 0xce, 0x1c,
-	0x0f, 0x4b, 0xd0, 0xc2, 0x5b, 0x6b, 0x56, 0xef,
-	0x73, 0x93, 0x0b, 0xc3, 0xee, 0xd9, 0xcf, 0xd3,
-	0xa4, 0x22, 0x58, 0xcd, 0x50, 0x6e, 0x65, 0xf4,
-	0xe9, 0xb7, 0x71, 0xaf, 0x4b, 0xb3, 0xb6, 0x2f,
-	0x0f, 0x0e, 0x3b, 0xc9, 0x85, 0x14, 0xf5, 0x17,
-	0xe8, 0x7a, 0x3a, 0xbf, 0x5f, 0x5e, 0xf8, 0x18,
-	0x48, 0xa6, 0x72, 0xab, 0x06, 0x95, 0xe9, 0xc8,
-	0xa7, 0xf4, 0x32, 0x44, 0x04, 0x0c, 0x84, 0x98,
-	0x73, 0xe3, 0x89, 0x8d, 0x5f, 0x7e, 0x4a, 0x42,
-	0x8f, 0xc5, 0x28, 0xb1, 0x82, 0xef, 0x1c, 0x97,
-	0x31, 0x3b, 0x4d, 0xe0, 0x0e, 0x10, 0x10, 0x97,
-	0x93, 0x49, 0x78, 0x2f, 0x0d, 0x86, 0x8b, 0xa1,
-	0x53, 0xa9, 0x81, 0x20, 0x79, 0xe7, 0x07, 0x77,
-	0xb6, 0xac, 0x5e, 0xd2, 0x05, 0xcd, 0xe9, 0xdb,
-	0x8a, 0x94, 0x82, 0x8a, 0x23, 0xb9, 0x3d, 0x1c,
-	0xa9, 0x7d, 0x72, 0x4a, 0xed, 0x33, 0xa3, 0xdb,
-	0x21, 0xa7, 0x86, 0x33, 0x45, 0xa5, 0xaa, 0x56,
-	0x45, 0xb5, 0x83, 0x29, 0x40, 0x47, 0x79, 0x04,
-	0x6e, 0xb9, 0x95, 0xd0, 0x81, 0x77, 0x2d, 0x48,
-	0x1e, 0xfe, 0xc3, 0xc2, 0x1e, 0xe5, 0xf2, 0xbe,
-	0xfd, 0x3b, 0x94, 0x9f, 0xc4, 0xc4, 0x26, 0x9d,
-	0xe4, 0x66, 0x1e, 0x19, 0xee, 0x6c, 0x79, 0x97,
-	0x11, 0x31, 0x4b, 0x0d, 0x01, 0xcb, 0xde, 0xa8,
-	0xf6, 0x6d, 0x7c, 0x39, 0x46, 0x4e, 0x7e, 0x3f,
-	0x94, 0x17, 0xdf, 0xa1, 0x7d, 0xd9, 0x1c, 0x8e,
-	0xbc, 0x7d, 0x33, 0x7d, 0xe3, 0x12, 0x40, 0xca,
-	0xab, 0x37, 0x11, 0x46, 0xd4, 0xae, 0xef, 0x44,
-	0xa2, 0xb3, 0x6a, 0x66, 0x0e, 0x0c, 0x90, 0x7f,
-	0xdf, 0x5c, 0x66, 0x5f, 0xf2, 0x94, 0x9f, 0xa6,
-	0x73, 0x4f, 0xeb, 0x0d, 0xad, 0xbf, 0xc0, 0x63,
-	0x5c, 0xdc, 0x46, 0x51, 0xe8, 0x8e, 0x90, 0x19,
-	0xa8, 0xa4, 0x3c, 0x91, 0x79, 0xfa, 0x7e, 0x58,
-	0x85, 0x13, 0x55, 0xc5, 0x19, 0x82, 0x37, 0x1b,
-	0x0a, 0x02, 0x1f, 0x99, 0x6b, 0x18, 0xf1, 0x28,
-	0x08, 0xa2, 0x73, 0xb8, 0x0f, 0x2e, 0xcd, 0xbf,
-	0xf3, 0x86, 0x7f, 0xea, 0xef, 0xd0, 0xbb, 0xa6,
-	0x21, 0xdf, 0x49, 0x73, 0x51, 0xcc, 0x36, 0xd3,
-	0x3e, 0xa0, 0xf8, 0x44, 0xdf, 0xd3, 0xa6, 0xbe,
-	0x8a, 0xd4, 0x57, 0xdd, 0x72, 0x94, 0x61, 0x0f,
-	0x82, 0xd1, 0x07, 0xb8, 0x7c, 0x18, 0x83, 0xdf,
-	0x3a, 0xe5, 0x50, 0x6a, 0x82, 0x20, 0xac, 0xa9,
-	0xa8, 0xff, 0xd9, 0xf3, 0x77, 0x33, 0x5a, 0x9e,
-	0x7f, 0x6d, 0xfe, 0x5d, 0x33, 0x41, 0x42, 0xe7,
-	0x6c, 0x19, 0xe0, 0x44, 0x8a, 0x15, 0xf6, 0x70,
-	0x98, 0xb7, 0x68, 0x4d, 0xfa, 0x97, 0x39, 0xb0,
-	0x8e, 0xe8, 0x84, 0x8b, 0x75, 0x30, 0xb7, 0x7d,
-	0x92, 0x69, 0x20, 0x9c, 0x81, 0xfb, 0x4b, 0xf4,
-	0x01, 0x50, 0xeb, 0xce, 0x0c, 0x1c, 0x6c, 0xb5,
-	0x4a, 0xd7, 0x27, 0x0c, 0xce, 0xbb, 0xe5, 0x85,
-	0xf0, 0xb6, 0xee, 0xd5, 0x70, 0xdd, 0x3b, 0xfc,
-	0xd4, 0x99, 0xf1, 0x33, 0xdd, 0x8b, 0xc4, 0x2f,
-	0xae, 0xab, 0x74, 0x96, 0x32, 0xc7, 0x4c, 0x56,
-	0x3c, 0x89, 0x0f, 0x96, 0x0b, 0x42, 0xc0, 0xcb,
-	0xee, 0x0f, 0x0b, 0x8c, 0xfb, 0x7e, 0x47, 0x7b,
-	0x64, 0x48, 0xfd, 0xb2, 0x00, 0x80, 0x89, 0xa5,
-	0x13, 0x55, 0x62, 0xfc, 0x8f, 0xe2, 0x42, 0x03,
-	0xb7, 0x4e, 0x2a, 0x79, 0xb4, 0x82, 0xea, 0x23,
-	0x49, 0xda, 0xaf, 0x52, 0x63, 0x1e, 0x60, 0x03,
-	0x89, 0x06, 0x44, 0x46, 0x08, 0xc3, 0xc4, 0x87,
-	0x70, 0x2e, 0xda, 0x94, 0xad, 0x6b, 0xe0, 0xe4,
-	0xd1, 0x8a, 0x06, 0xc2, 0xa8, 0xc0, 0xa7, 0x43,
-	0x3c, 0x47, 0x52, 0x0e, 0xc3, 0x77, 0x81, 0x11,
-	0x67, 0x0e, 0xa0, 0x70, 0x04, 0x47, 0x29, 0x40,
-	0x86, 0x0d, 0x34, 0x56, 0xa7, 0xc9, 0x35, 0x59,
-	0x68, 0xdc, 0x93, 0x81, 0x70, 0xee, 0x86, 0xd9,
-	0x80, 0x06, 0x40, 0x4f, 0x1a, 0x0d, 0x40, 0x30,
-	0x0b, 0xcb, 0x96, 0x47, 0xc1, 0xb7, 0x52, 0xfd,
-	0x56, 0xe0, 0x72, 0x4b, 0xfb, 0xbd, 0x92, 0x45,
-	0x61, 0x71, 0xc2, 0x33, 0x11, 0xbf, 0x52, 0x83,
-	0x79, 0x26, 0xe0, 0x49, 0x6b, 0xb7, 0x05, 0x8b,
-	0xe8, 0x0e, 0x87, 0x31, 0xd7, 0x9d, 0x8a, 0xf5,
-	0xc0, 0x5f, 0x2e, 0x58, 0x4a, 0xdb, 0x11, 0xb3,
-	0x6c, 0x30, 0x2a, 0x46, 0x19, 0xe3, 0x27, 0x84,
-	0x1f, 0x63, 0x6e, 0xf6, 0x57, 0xc7, 0xc9, 0xd8,
-	0x5e, 0xba, 0xb3, 0x87, 0xd5, 0x83, 0x26, 0x34,
-	0x21, 0x9e, 0x65, 0xde, 0x42, 0xd3, 0xbe, 0x7b,
-	0xbc, 0x91, 0x71, 0x44, 0x4d, 0x99, 0x3b, 0x31,
-	0xe5, 0x3f, 0x11, 0x4e, 0x7f, 0x13, 0x51, 0x3b,
-	0xae, 0x79, 0xc9, 0xd3, 0x81, 0x8e, 0x25, 0x40,
-	0x10, 0xfc, 0x07, 0x1e, 0xf9, 0x7b, 0x9a, 0x4b,
-	0x6c, 0xe3, 0xb3, 0xad, 0x1a, 0x0a, 0xdd, 0x9e,
-	0x59, 0x0c, 0xa2, 0xcd, 0xae, 0x48, 0x4a, 0x38,
-	0x5b, 0x47, 0x41, 0x94, 0x65, 0x6b, 0xbb, 0xeb,
-	0x5b, 0xe3, 0xaf, 0x07, 0x5b, 0xd4, 0x4a, 0xa2,
-	0xc9, 0x5d, 0x2f, 0x64, 0x03, 0xd7, 0x3a, 0x2c,
-	0x6e, 0xce, 0x76, 0x95, 0xb4, 0xb3, 0xc0, 0xf1,
-	0xe2, 0x45, 0x73, 0x7a, 0x5c, 0xab, 0xc1, 0xfc,
-	0x02, 0x8d, 0x81, 0x29, 0xb3, 0xac, 0x07, 0xec,
-	0x40, 0x7d, 0x45, 0xd9, 0x7a, 0x59, 0xee, 0x34,
-	0xf0, 0xe9, 0xd5, 0x7b, 0x96, 0xb1, 0x3d, 0x95,
-	0xcc, 0x86, 0xb5, 0xb6, 0x04, 0x2d, 0xb5, 0x92,
-	0x7e, 0x76, 0xf4, 0x06, 0xa9, 0xa3, 0x12, 0x0f,
-	0xb1, 0xaf, 0x26, 0xba, 0x7c, 0xfc, 0x7e, 0x1c,
-	0xbc, 0x2c, 0x49, 0x97, 0x53, 0x60, 0x13, 0x0b,
-	0xa6, 0x61, 0x83, 0x89, 0x42, 0xd4, 0x17, 0x0c,
-	0x6c, 0x26, 0x52, 0xc3, 0xb3, 0xd4, 0x67, 0xf5,
-	0xe3, 0x04, 0xb7, 0xf4, 0xcb, 0x80, 0xb8, 0xcb,
-	0x77, 0x56, 0x3e, 0xaa, 0x57, 0x54, 0xee, 0xb4,
-	0x2c, 0x67, 0xcf, 0xf2, 0xdc, 0xbe, 0x55, 0xf9,
-	0x43, 0x1f, 0x6e, 0x22, 0x97, 0x67, 0x7f, 0xc4,
-	0xef, 0xb1, 0x26, 0x31, 0x1e, 0x27, 0xdf, 0x41,
-	0x80, 0x47, 0x6c, 0xe2, 0xfa, 0xa9, 0x8c, 0x2a,
-	0xf6, 0xf2, 0xab, 0xf0, 0x15, 0xda, 0x6c, 0xc8,
-	0xfe, 0xb5, 0x23, 0xde, 0xa9, 0x05, 0x3f, 0x06,
-	0x54, 0x4c, 0xcd, 0xe1, 0xab, 0xfc, 0x0e, 0x62,
-	0x33, 0x31, 0x73, 0x2c, 0x76, 0xcb, 0xb4, 0x47,
-	0x1e, 0x20, 0xad, 0xd8, 0xf2, 0x31, 0xdd, 0xc4,
-	0x8b, 0x0c, 0x77, 0xbe, 0xe1, 0x8b, 0x26, 0x00,
-	0x02, 0x58, 0xd6, 0x8d, 0xef, 0xad, 0x74, 0x67,
-	0xab, 0x3f, 0xef, 0xcb, 0x6f, 0xb0, 0xcc, 0x81,
-	0x44, 0x4c, 0xaf, 0xe9, 0x49, 0x4f, 0xdb, 0xa0,
-	0x25, 0xa4, 0xf0, 0x89, 0xf1, 0xbe, 0xd8, 0x10,
-	0xff, 0xb1, 0x3b, 0x4b, 0xfa, 0x98, 0xf5, 0x79,
-	0x6d, 0x1e, 0x69, 0x4d, 0x57, 0xb1, 0xc8, 0x19,
-	0x1b, 0xbd, 0x1e, 0x8c, 0x84, 0xb7, 0x7b, 0xe8,
-	0xd2, 0x2d, 0x09, 0x41, 0x41, 0x37, 0x3d, 0xb1,
-	0x6f, 0x26, 0x5d, 0x71, 0x16, 0x3d, 0xb7, 0x83,
-	0x27, 0x2c, 0xa7, 0xb6, 0x50, 0xbd, 0x91, 0x86,
-	0xab, 0x24, 0xa1, 0x38, 0xfd, 0xea, 0x71, 0x55,
-	0x7e, 0x9a, 0x07, 0x77, 0x4b, 0xfa, 0x61, 0x66,
-	0x20, 0x1e, 0x28, 0x95, 0x18, 0x1b, 0xa4, 0xa0,
-	0xfd, 0xc0, 0x89, 0x72, 0x43, 0xd9, 0x3b, 0x49,
-	0x5a, 0x3f, 0x9d, 0xbf, 0xdb, 0xb4, 0x46, 0xea,
-	0x42, 0x01, 0x77, 0x23, 0x68, 0x95, 0xb6, 0x24,
-	0xb3, 0xa8, 0x6c, 0x28, 0x3b, 0x11, 0x40, 0x7e,
-	0x18, 0x65, 0x6d, 0xd8, 0x24, 0x42, 0x7d, 0x88,
-	0xc0, 0x52, 0xd9, 0x05, 0xe4, 0x95, 0x90, 0x87,
-	0x8c, 0xf4, 0xd0, 0x6b, 0xb9, 0x83, 0x99, 0x34,
-	0x6d, 0xfe, 0x54, 0x40, 0x94, 0x52, 0x21, 0x4f,
-	0x14, 0x25, 0xc5, 0xd6, 0x5e, 0x95, 0xdc, 0x0a,
-	0x2b, 0x89, 0x20, 0x11, 0x84, 0x48, 0xd6, 0x3a,
-	0xcd, 0x5c, 0x24, 0xad, 0x62, 0xe3, 0xb1, 0x93,
-	0x25, 0x8d, 0xcd, 0x7e, 0xfc, 0x27, 0xa3, 0x37,
-	0xfd, 0x84, 0xfc, 0x1b, 0xb2, 0xf1, 0x27, 0x38,
-	0x5a, 0xb7, 0xfc, 0xf2, 0xfa, 0x95, 0x66, 0xd4,
-	0xfb, 0xba, 0xa7, 0xd7, 0xa3, 0x72, 0x69, 0x48,
-	0x48, 0x8c, 0xeb, 0x28, 0x89, 0xfe, 0x33, 0x65,
-	0x5a, 0x36, 0x01, 0x7e, 0x06, 0x79, 0x0a, 0x09,
-	0x3b, 0x74, 0x11, 0x9a, 0x6e, 0xbf, 0xd4, 0x9e,
-	0x58, 0x90, 0x49, 0x4f, 0x4d, 0x08, 0xd4, 0xe5,
-	0x4a, 0x09, 0x21, 0xef, 0x8b, 0xb8, 0x74, 0x3b,
-	0x91, 0xdd, 0x36, 0x85, 0x60, 0x2d, 0xfa, 0xd4,
-	0x45, 0x7b, 0x45, 0x53, 0xf5, 0x47, 0x87, 0x7e,
-	0xa6, 0x37, 0xc8, 0x78, 0x7a, 0x68, 0x9d, 0x8d,
-	0x65, 0x2c, 0x0e, 0x91, 0x5c, 0xa2, 0x60, 0xf0,
-	0x8e, 0x3f, 0xe9, 0x1a, 0xcd, 0xaa, 0xe7, 0xd5,
-	0x77, 0x18, 0xaf, 0xc9, 0xbc, 0x18, 0xea, 0x48,
-	0x1b, 0xfb, 0x22, 0x48, 0x70, 0x16, 0x29, 0x9e,
-	0x5b, 0xc1, 0x2c, 0x66, 0x23, 0xbc, 0xf0, 0x1f,
-	0xef, 0xaf, 0xe4, 0xd6, 0x04, 0x19, 0x82, 0x7a,
-	0x0b, 0xba, 0x4b, 0x46, 0xb1, 0x6a, 0x85, 0x5d,
-	0xb4, 0x73, 0xd6, 0x21, 0xa1, 0x71, 0x60, 0x14,
-	0xee, 0x0a, 0x77, 0xc4, 0x66, 0x2e, 0xf9, 0x69,
-	0x30, 0xaf, 0x41, 0x0b, 0xc8, 0x83, 0x3c, 0x53,
-	0x99, 0x19, 0x27, 0x46, 0xf7, 0x41, 0x6e, 0x56,
-	0xdc, 0x94, 0x28, 0x67, 0x4e, 0xb7, 0x25, 0x48,
-	0x8a, 0xc2, 0xe0, 0x60, 0x96, 0xcc, 0x18, 0xf4,
-	0x84, 0xdd, 0xa7, 0x5e, 0x3e, 0x05, 0x0b, 0x26,
-	0x26, 0xb2, 0x5c, 0x1f, 0x57, 0x1a, 0x04, 0x7e,
-	0x6a, 0xe3, 0x2f, 0xb4, 0x35, 0xb6, 0x38, 0x40,
-	0x40, 0xcd, 0x6f, 0x87, 0x2e, 0xef, 0xa3, 0xd7,
-	0xa9, 0xc2, 0xe8, 0x0d, 0x27, 0xdf, 0x44, 0x62,
-	0x99, 0xa0, 0xfc, 0xcf, 0x81, 0x78, 0xcb, 0xfe,
-	0xe5, 0xa0, 0x03, 0x4e, 0x6c, 0xd7, 0xf4, 0xaf,
-	0x7a, 0xbb, 0x61, 0x82, 0xfe, 0x71, 0x89, 0xb2,
-	0x22, 0x7c, 0x8e, 0x83, 0x04, 0xce, 0xf6, 0x5d,
-	0x84, 0x8f, 0x95, 0x6a, 0x7f, 0xad, 0xfd, 0x32,
-	0x9c, 0x5e, 0xe4, 0x9c, 0x89, 0x60, 0x54, 0xaa,
-	0x96, 0x72, 0xd2, 0xd7, 0x36, 0x85, 0xa9, 0x45,
-	0xd2, 0x2a, 0xa1, 0x81, 0x49, 0x6f, 0x7e, 0x04,
-	0xfa, 0xe2, 0xfe, 0x90, 0x26, 0x77, 0x5a, 0x33,
-	0xb8, 0x04, 0x9a, 0x7a, 0xe6, 0x4c, 0x4f, 0xad,
-	0x72, 0x96, 0x08, 0x28, 0x58, 0x13, 0xf8, 0xc4,
-	0x1c, 0xf0, 0xc3, 0x45, 0x95, 0x49, 0x20, 0x8c,
-	0x9f, 0x39, 0x70, 0xe1, 0x77, 0xfe, 0xd5, 0x4b,
-	0xaf, 0x86, 0xda, 0xef, 0x22, 0x06, 0x83, 0x36,
-	0x29, 0x12, 0x11, 0x40, 0xbc, 0x3b, 0x86, 0xaa,
-	0xaa, 0x65, 0x60, 0xc3, 0x80, 0xca, 0xed, 0xa9,
-	0xf3, 0xb0, 0x79, 0x96, 0xa2, 0x55, 0x27, 0x28,
-	0x55, 0x73, 0x26, 0xa5, 0x50, 0xea, 0x92, 0x4b,
-	0x3c, 0x5c, 0x82, 0x33, 0xf0, 0x01, 0x3f, 0x03,
-	0xc1, 0x08, 0x05, 0xbf, 0x98, 0xf4, 0x9b, 0x6d,
-	0xa5, 0xa8, 0xb4, 0x82, 0x0c, 0x06, 0xfa, 0xff,
-	0x2d, 0x08, 0xf3, 0x05, 0x4f, 0x57, 0x2a, 0x39,
-	0xd4, 0x83, 0x0d, 0x75, 0x51, 0xd8, 0x5b, 0x1b,
-	0xd3, 0x51, 0x5a, 0x32, 0x2a, 0x9b, 0x32, 0xb2,
-	0xf2, 0xa4, 0x96, 0x12, 0xf2, 0xae, 0x40, 0x34,
-	0x67, 0xa8, 0xf5, 0x44, 0xd5, 0x35, 0x53, 0xfe,
-	0xa3, 0x60, 0x96, 0x63, 0x0f, 0x1f, 0x6e, 0xb0,
-	0x5a, 0x42, 0xa6, 0xfc, 0x51, 0x0b, 0x60, 0x27,
-	0xbc, 0x06, 0x71, 0xed, 0x65, 0x5b, 0x23, 0x86,
-	0x4a, 0x07, 0x3b, 0x22, 0x07, 0x46, 0xe6, 0x90,
-	0x3e, 0xf3, 0x25, 0x50, 0x1b, 0x4c, 0x7f, 0x03,
-	0x08, 0xa8, 0x36, 0x6b, 0x87, 0xe5, 0xe3, 0xdb,
-	0x9a, 0x38, 0x83, 0xff, 0x9f, 0x1a, 0x9f, 0x57,
-	0xa4, 0x2a, 0xf6, 0x37, 0xbc, 0x1a, 0xff, 0xc9,
-	0x1e, 0x35, 0x0c, 0xc3, 0x7c, 0xa3, 0xb2, 0xe5,
-	0xd2, 0xc6, 0xb4, 0x57, 0x47, 0xe4, 0x32, 0x16,
-	0x6d, 0xa9, 0xae, 0x64, 0xe6, 0x2d, 0x8d, 0xc5,
-	0x8d, 0x50, 0x8e, 0xe8, 0x1a, 0x22, 0x34, 0x2a,
-	0xd9, 0xeb, 0x51, 0x90, 0x4a, 0xb1, 0x41, 0x7d,
-	0x64, 0xf9, 0xb9, 0x0d, 0xf6, 0x23, 0x33, 0xb0,
-	0x33, 0xf4, 0xf7, 0x3f, 0x27, 0x84, 0xc6, 0x0f,
-	0x54, 0xa5, 0xc0, 0x2e, 0xec, 0x0b, 0x3a, 0x48,
-	0x6e, 0x80, 0x35, 0x81, 0x43, 0x9b, 0x90, 0xb1,
-	0xd0, 0x2b, 0xea, 0x21, 0xdc, 0xda, 0x5b, 0x09,
-	0xf4, 0xcc, 0x10, 0xb4, 0xc7, 0xfe, 0x79, 0x51,
-	0xc3, 0xc5, 0xac, 0x88, 0x74, 0x84, 0x0b, 0x4b,
-	0xca, 0x79, 0x16, 0x29, 0xfb, 0x69, 0x54, 0xdf,
-	0x41, 0x7e, 0xe9, 0xc7, 0x8e, 0xea, 0xa5, 0xfe,
-	0xfc, 0x76, 0x0e, 0x90, 0xc4, 0x92, 0x38, 0xad,
-	0x7b, 0x48, 0xe6, 0x6e, 0xf7, 0x21, 0xfd, 0x4e,
-	0x93, 0x0a, 0x7b, 0x41, 0x83, 0x68, 0xfb, 0x57,
-	0x51, 0x76, 0x34, 0xa9, 0x6c, 0x00, 0xaa, 0x4f,
-	0x66, 0x65, 0x98, 0x4a, 0x4f, 0xa3, 0xa0, 0xef,
-	0x69, 0x3f, 0xe3, 0x1c, 0x92, 0x8c, 0xfd, 0xd8,
-	0xe8, 0xde, 0x7c, 0x7f, 0x3e, 0x84, 0x8e, 0x69,
-	0x3c, 0xf1, 0xf2, 0x05, 0x46, 0xdc, 0x2f, 0x9d,
-	0x5e, 0x6e, 0x4c, 0xfb, 0xb5, 0x99, 0x2a, 0x59,
-	0x63, 0xc1, 0x34, 0xbc, 0x57, 0xc0, 0x0d, 0xb9,
-	0x61, 0x25, 0xf3, 0x33, 0x23, 0x51, 0xb6, 0x0d,
-	0x07, 0xa6, 0xab, 0x94, 0x4a, 0xb7, 0x2a, 0xea,
-	0xee, 0xac, 0xa3, 0xc3, 0x04, 0x8b, 0x0e, 0x56,
-	0xfe, 0x44, 0xa7, 0x39, 0xe2, 0xed, 0xed, 0xb4,
-	0x22, 0x2b, 0xac, 0x12, 0x32, 0x28, 0x91, 0xd8,
-	0xa5, 0xab, 0xff, 0x5f, 0xe0, 0x4b, 0xda, 0x78,
-	0x17, 0xda, 0xf1, 0x01, 0x5b, 0xcd, 0xe2, 0x5f,
-	0x50, 0x45, 0x73, 0x2b, 0xe4, 0x76, 0x77, 0xf4,
-	0x64, 0x1d, 0x43, 0xfb, 0x84, 0x7a, 0xea, 0x91,
-	0xae, 0xf9, 0x9e, 0xb7, 0xb4, 0xb0, 0x91, 0x5f,
-	0x16, 0x35, 0x9a, 0x11, 0xb8, 0xc7, 0xc1, 0x8c,
-	0xc6, 0x10, 0x8d, 0x2f, 0x63, 0x4a, 0xa7, 0x57,
-	0x3a, 0x51, 0xd6, 0x32, 0x2d, 0x64, 0x72, 0xd4,
-	0x66, 0xdc, 0x10, 0xa6, 0x67, 0xd6, 0x04, 0x23,
-	0x9d, 0x0a, 0x11, 0x77, 0xdd, 0x37, 0x94, 0x17,
-	0x3c, 0xbf, 0x8b, 0x65, 0xb0, 0x2e, 0x5e, 0x66,
-	0x47, 0x64, 0xac, 0xdd, 0xf0, 0x84, 0xfd, 0x39,
-	0xfa, 0x15, 0x5d, 0xef, 0xae, 0xca, 0xc1, 0x36,
-	0xa7, 0x5c, 0xbf, 0xc7, 0x08, 0xc2, 0x66, 0x00,
-	0x74, 0x74, 0x4e, 0x27, 0x3f, 0x55, 0x8a, 0xb7,
-	0x38, 0x66, 0x83, 0x6d, 0xcf, 0x99, 0x9e, 0x60,
-	0x8f, 0xdd, 0x2e, 0x62, 0x22, 0x0e, 0xef, 0x0c,
-	0x98, 0xa7, 0x85, 0x74, 0x3b, 0x9d, 0xec, 0x9e,
-	0xa9, 0x19, 0x72, 0xa5, 0x7f, 0x2c, 0x39, 0xb7,
-	0x7d, 0xb7, 0xf1, 0x12, 0x65, 0x27, 0x4b, 0x5a,
-	0xde, 0x17, 0xfe, 0xad, 0x44, 0xf3, 0x20, 0x4d,
-	0xfd, 0xe4, 0x1f, 0xb5, 0x81, 0xb0, 0x36, 0x37,
-	0x08, 0x6f, 0xc3, 0x0c, 0xe9, 0x85, 0x98, 0x82,
-	0xa9, 0x62, 0x0c, 0xc4, 0x97, 0xc0, 0x50, 0xc8,
-	0xa7, 0x3c, 0x50, 0x9f, 0x43, 0xb9, 0xcd, 0x5e,
-	0x4d, 0xfa, 0x1c, 0x4b, 0x0b, 0xa9, 0x98, 0x85,
-	0x38, 0x92, 0xac, 0x8d, 0xe4, 0xad, 0x9b, 0x98,
-	0xab, 0xd9, 0x38, 0xac, 0x62, 0x52, 0xa3, 0x22,
-	0x63, 0x0f, 0xbf, 0x95, 0x48, 0xdf, 0x69, 0xe7,
-	0x8b, 0x33, 0xd5, 0xb2, 0xbd, 0x05, 0x49, 0x49,
-	0x9d, 0x57, 0x73, 0x19, 0x33, 0xae, 0xfa, 0x33,
-	0xf1, 0x19, 0xa8, 0x80, 0xce, 0x04, 0x9f, 0xbc,
-	0x1d, 0x65, 0x82, 0x1b, 0xe5, 0x3a, 0x51, 0xc8,
-	0x1c, 0x21, 0xe3, 0x5d, 0xf3, 0x7d, 0x9b, 0x2f,
-	0x2c, 0x1d, 0x4a, 0x7f, 0x9b, 0x68, 0x35, 0xa3,
-	0xb2, 0x50, 0xf7, 0x62, 0x79, 0xcd, 0xf4, 0x98,
-	0x4f, 0xe5, 0x63, 0x7c, 0x3e, 0x45, 0x31, 0x8c,
-	0x16, 0xa0, 0x12, 0xc8, 0x58, 0xce, 0x39, 0xa6,
-	0xbc, 0x54, 0xdb, 0xc5, 0xe0, 0xd5, 0xba, 0xbc,
-	0xb9, 0x04, 0xf4, 0x8d, 0xe8, 0x2f, 0x15, 0x9d,
-};
-
-/* 100 test cases */
-static struct crc_test {
-	u32 crc;	/* random starting crc */
-	u32 start;	/* random 6 bit offset in buf */
-	u32 length;	/* random 11 bit length of test */
-	u32 crc32c_le;	/* expected crc32c_le result */
-} test[] =
-{
-	{0x674bf11d, 0x00000038, 0x00000542, 0xf6e93d6c},
-	{0x35c672c6, 0x0000003a, 0x000001aa, 0x0fe92aca},
-	{0x496da28e, 0x00000039, 0x000005af, 0x52e1ebb8},
-	{0x09a9b90e, 0x00000027, 0x000001f8, 0x0798af9a},
-	{0xdc97e5a9, 0x00000025, 0x000003b6, 0x18eb3152},
-	{0x47c58900, 0x0000000a, 0x000000b9, 0xd00d08c7},
-	{0x292561e8, 0x0000000c, 0x00000403, 0x8ba966bc},
-	{0x415037f6, 0x00000003, 0x00000676, 0x11d694a2},
-	{0x3466e707, 0x00000026, 0x00000042, 0x6ab3208d},
-	{0xafd1281b, 0x00000023, 0x000002ee, 0xba4603c5},
-	{0xd3857b18, 0x00000028, 0x000004a2, 0xe6071c6f},
-	{0x1d825a8f, 0x0000002b, 0x0000050b, 0x179ec30a},
-	{0x5033e3bc, 0x0000000b, 0x00000078, 0x0903beb8},
-	{0x94f1fb5e, 0x0000000f, 0x000003a2, 0x6a7cb4fa},
-	{0xc9a0fe14, 0x00000009, 0x00000473, 0xdb535801},
-	{0x88a034b1, 0x0000001c, 0x000005ad, 0x92bed597},
-	{0xf0f72239, 0x00000020, 0x0000026d, 0x192a3f1b},
-	{0xcc20a5e3, 0x0000003b, 0x0000067a, 0xccbaec1a},
-	{0xce589c95, 0x0000002b, 0x00000641, 0x7eabae4d},
-	{0x78edc885, 0x00000035, 0x000005be, 0x28c72982},
-	{0x9d40a377, 0x0000003b, 0x00000038, 0xc3cd4d18},
-	{0x703d0e01, 0x0000003c, 0x000006f1, 0xbca8f0e7},
-	{0x776bf505, 0x0000000f, 0x000005b2, 0x713f60b3},
-	{0x4a3e7854, 0x00000027, 0x000004b8, 0xebd08fd5},
-	{0x209172dd, 0x0000003b, 0x00000356, 0x64406c59},
-	{0x3ba4cc5b, 0x0000002f, 0x00000203, 0x7421890e},
-	{0xfc62f297, 0x00000000, 0x00000079, 0xe9347603},
-	{0x64280b8b, 0x00000016, 0x000007ab, 0x1bef9060},
-	{0x97dd724b, 0x00000033, 0x000007ad, 0x34720072},
-	{0x61394b52, 0x00000035, 0x00000571, 0x48310f59},
-	{0x29b4faff, 0x00000024, 0x0000006e, 0x783a4213},
-	{0x29bfb1dc, 0x0000000b, 0x00000244, 0x9e8efd41},
-	{0x86ae934b, 0x00000035, 0x00000104, 0xfc3d34a5},
-	{0xc4c1024e, 0x0000002e, 0x000006b1, 0x17a52ae2},
-	{0x3287a80a, 0x00000026, 0x00000496, 0x886d935a},
-	{0xa4db423e, 0x00000023, 0x0000045d, 0xeaaeaeb2},
-	{0x7a1078df, 0x00000015, 0x0000014a, 0x8e900a4b},
-	{0x6048bd5b, 0x00000006, 0x0000006a, 0xd74662b1},
-	{0xd8f9ea20, 0x0000003d, 0x00000277, 0xd26752ba},
-	{0xea5ec3b4, 0x0000002a, 0x000004fe, 0x8b1fcd62},
-	{0x2dfb005d, 0x00000016, 0x00000345, 0xf54342fe},
-	{0x5a214ade, 0x00000020, 0x000005b6, 0x5b95b988},
-	{0xf0ab9cca, 0x00000032, 0x00000515, 0x2e1176be},
-	{0x91b444f9, 0x0000002e, 0x000007f8, 0x66120546},
-	{0x1b5d2ddb, 0x0000002e, 0x0000012c, 0xf256a5cc},
-	{0xd824d1bb, 0x0000003a, 0x000007b5, 0x4af1dd69},
-	{0x0470180c, 0x00000034, 0x000001f0, 0x56f0a04a},
-	{0xffaa3a3f, 0x00000036, 0x00000299, 0x74f6b6b2},
-	{0x6406cfeb, 0x00000023, 0x00000600, 0x085951fd},
-	{0xb24aaa38, 0x0000003e, 0x000004a1, 0xc65387eb},
-	{0x58b2ab7c, 0x00000039, 0x000002b4, 0x1ca9257b},
-	{0x3db85970, 0x00000006, 0x000002b6, 0xfd196d76},
-	{0x857830c5, 0x00000003, 0x00000590, 0x5ef88339},
-	{0xe1fcd978, 0x0000003e, 0x000007d8, 0x2c3714d9},
-	{0xb982a768, 0x00000016, 0x000006e0, 0x58576548},
-	{0x1d581ce8, 0x0000001e, 0x0000058b, 0xfd7c57de},
-	{0x2456719b, 0x00000025, 0x00000503, 0xd5fedd59},
-	{0xfae6d8f2, 0x00000000, 0x0000055d, 0x1cc3b17b},
-	{0xcba828e3, 0x00000039, 0x000002ce, 0x270eed73},
-	{0x13d25952, 0x0000000a, 0x0000072d, 0x91ecbb11},
-	{0x0342be3f, 0x00000015, 0x00000599, 0x05ed8d0c},
-	{0xeaa344e0, 0x00000014, 0x000004d8, 0x0b09ad5b},
-	{0xbbb52021, 0x0000003b, 0x00000272, 0xf8d511fb},
-	{0xb66384dc, 0x0000001d, 0x000007fc, 0x5ad832cc},
-	{0x616c01b6, 0x00000022, 0x000002c8, 0x1214d196},
-	{0xce2bdaad, 0x00000016, 0x0000062a, 0x5747218a},
-	{0x00fe84d7, 0x00000005, 0x00000205, 0xde8f14de},
-	{0xbebdcb4c, 0x00000006, 0x0000055d, 0x3563b7b9},
-	{0xd8b1a02a, 0x00000010, 0x00000387, 0x071475d0},
-	{0x3b96cad2, 0x00000036, 0x00000347, 0x54c79d60},
-	{0xc94c1ed7, 0x00000005, 0x0000038b, 0x4c53eee6},
-	{0x1aad454e, 0x00000025, 0x000002b2, 0x10137a3c},
-	{0xa4fec9a6, 0x00000000, 0x000006d6, 0xaa9d6c73},
-	{0x1bbe71e2, 0x0000001f, 0x000002fd, 0xb63d23e7},
-	{0x4201c7e4, 0x00000002, 0x000002b7, 0x7f53e9cf},
-	{0x23fddc96, 0x00000003, 0x00000627, 0x13c1cd83},
-	{0xd82ba25c, 0x00000016, 0x0000063e, 0x49ff5867},
-	{0x786f2032, 0x0000002d, 0x0000060f, 0x8467f211},
-	{0xfebe4e1f, 0x0000002a, 0x000004f2, 0x3f9683b2},
-	{0x1a6e0a39, 0x00000008, 0x00000672, 0x76a3f874},
-	{0x56000ab8, 0x0000000e, 0x000000e5, 0x863b702f},
-	{0x4717fe0c, 0x00000000, 0x000006ec, 0xdc6c58ff},
-	{0xd5d5d68e, 0x0000003c, 0x000003a3, 0x0622cc95},
-	{0xc25dd6c6, 0x00000024, 0x000006c0, 0xe85605cd},
-	{0xe9b11300, 0x00000023, 0x00000683, 0x31da5f06},
-	{0x95cd285e, 0x00000001, 0x00000047, 0xa1f2e784},
-	{0xd9245a25, 0x0000001e, 0x000003a6, 0xb07cc616},
-	{0x103279db, 0x00000006, 0x0000039b, 0xbf943b6c},
-	{0x1cba3172, 0x00000027, 0x000001c8, 0x2c01af1c},
-	{0x8f613739, 0x0000000c, 0x000001df, 0x0fe5f56d},
-	{0x1c6aa90d, 0x0000001b, 0x0000053c, 0xf8943b2d},
-	{0xaabe5b93, 0x0000003d, 0x00000715, 0xe4d89272},
-	{0xf15dd038, 0x00000006, 0x000006db, 0x7c2f6bbb},
-	{0x584dd49c, 0x00000020, 0x000007bc, 0xabbf388b},
-	{0x5d8c9506, 0x00000020, 0x00000470, 0x1dca1f4e},
-	{0xb80d17b0, 0x00000032, 0x00000346, 0x5c170e23},
-	{0xdaf0592e, 0x00000023, 0x000007b0, 0xc0e9d672},
-	{0x4793cc85, 0x0000000d, 0x00000706, 0xc18bdc86},
-	{0x82ebf64e, 0x00000009, 0x000007c3, 0xa874fcdd},
-	{0xb18a0319, 0x00000026, 0x000007db, 0x9dc0bb48},
-};
-
-static int crc32c_test(void)
-{
-	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 u32 crc;
-
-	/* pre-warm the cache */
-	for (i = 0; i < 100; i++) {
-		bytes += 2*test[i].length;
-
-		crc ^= crc32c_le(test[i].crc, test_buf +
-		    test[i].start, test[i].length);
-	}
-
-	gettimeofday(&start, NULL);
-	for (i = 0; i < 100; i++) {
-		if (test[i].crc32c_le != crc32c_le(test[i].crc, test_buf +
-		    test[i].start, test[i].length))
-			errors++;
-	}
-	gettimeofday(&stop, NULL);
-
-	usec = stop.tv_usec - start.tv_usec +
-		1000000 * (stop.tv_sec - start.tv_sec);
-
-	if (errors)
-		printf("crc32c: %d self tests failed\n", errors);
-	else {
-		printf("crc32c: tests passed, %d bytes in %" PRIu64 " usec\n",
-			bytes, usec);
-	}
-
-	return errors;
-}
-
-/*
- * make sure we always return 0 for a successful test run, and non-zero for a
- * failed run. The build infrastructure is looking for this information to
- * determine whether to allow the build to proceed.
- */
-int main(int argc, char **argv)
-{
-	int errors;
-
-	printf("CRC_LE_BITS = %d\n", CRC_LE_BITS);
-
-	errors = crc32c_test();
-
-	return errors != 0;
-}
-#endif /* CRC32_SELFTEST */
diff --git a/libxfs/crc32defs.h b/libxfs/crc32defs.h
deleted file mode 100644
index 57c328c2..00000000
--- a/libxfs/crc32defs.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Use slice-by-8, which is the fastest variant.
- *
- * Calculate checksum 8 bytes at a time with a clever slicing algorithm.
- * This is the fastest algorithm, but comes with a 8KiB lookup table.
- * Most modern processors have enough cache to hold this table without
- * thrashing the cache.
- *
- * The Linux kernel uses this as the default implementation "unless you
- * have a good reason not to".  The reason why Kconfig urges you to pick
- * SLICEBY8 is because people challenged the assertion that we should
- * always use slice by 8, so Darrick wrote a crc microbenchmark utility
- * and ran it on as many machines as he could get his hands on to show
- * that sb8 was the fastest.
- *
- * Every 64-bit machine (and most of the 32-bit ones too) saw the best
- * results with sb8.  Any machine with more than 4K of cache saw better
- * results.  The spreadsheet still exists today[1]; note that
- * 'crc32-kern-le' corresponds to the slice by 4 algorithm which is the
- * default unless CRC_LE_BITS is defined explicitly.
- *
- * FWIW, there are a handful of board defconfigs in the kernel that
- * don't pick sliceby8.  These are all embedded 32-bit mips/ppc systems
- * with very small cache sizes which experience cache thrashing with the
- * slice by 8 algorithm, and therefore chose to pick defaults that are
- * saner for their particular board configuration.  For nearly all of
- * XFS' perceived userbase (which we assume are 32 and 64-bit machines
- * with sufficiently large CPU cache and largeish storage devices) slice
- * by 8 is the right choice.
- *
- * [1] https://goo.gl/0LSzsG ("crc32c_bench")
- */
-#define CRC_LE_BITS 64
-
-/*
- * This is the CRC32c polynomial, as outlined by Castagnoli.
- * x^32+x^28+x^27+x^26+x^25+x^23+x^22+x^20+x^19+x^18+x^14+x^13+x^11+x^10+x^9+
- * x^8+x^6+x^0
- */
-#define CRC32C_POLY_LE 0x82F63B78
-
-/*
- * Little-endian CRC computation.  Used with serial bit streams sent
- * lsbit-first.  Be sure to use cpu_to_le32() to append the computed CRC.
- */
-#if CRC_LE_BITS > 64 || CRC_LE_BITS < 1 || CRC_LE_BITS == 16 || \
-	CRC_LE_BITS & CRC_LE_BITS-1
-# error "CRC_LE_BITS must be one of {1, 2, 4, 8, 32, 64}"
-#endif
diff --git a/libxfs/gen_crc32table.c b/libxfs/gen_crc32table.c
deleted file mode 100644
index d5724326..00000000
--- a/libxfs/gen_crc32table.c
+++ /dev/null
@@ -1,80 +0,0 @@
-#include <stdio.h>
-#include "crc32defs.h"
-#include <inttypes.h>
-
-#define ENTRIES_PER_LINE 4
-
-#if CRC_LE_BITS > 8
-# define LE_TABLE_ROWS (CRC_LE_BITS/8)
-# define LE_TABLE_SIZE 256
-#else
-# define LE_TABLE_ROWS 1
-# define LE_TABLE_SIZE (1 << CRC_LE_BITS)
-#endif
-
-static uint32_t crc32ctable_le[LE_TABLE_ROWS][256];
-
-/**
- * crc32init_le() - allocate and initialize LE table data
- *
- * crc is the crc of the byte i; other entries are filled in based on the
- * fact that crctable[i^j] = crctable[i] ^ crctable[j].
- *
- */
-static void crc32init_le_generic(const uint32_t polynomial,
-				 uint32_t (*tab)[256])
-{
-	unsigned i, j;
-	uint32_t crc = 1;
-
-	tab[0][0] = 0;
-
-	for (i = LE_TABLE_SIZE >> 1; i; i >>= 1) {
-		crc = (crc >> 1) ^ ((crc & 1) ? polynomial : 0);
-		for (j = 0; j < LE_TABLE_SIZE; j += 2 * i)
-			tab[0][i + j] = crc ^ tab[0][j];
-	}
-	for (i = 0; i < LE_TABLE_SIZE; i++) {
-		crc = tab[0][i];
-		for (j = 1; j < LE_TABLE_ROWS; j++) {
-			crc = tab[0][crc & 0xff] ^ (crc >> 8);
-			tab[j][i] = crc;
-		}
-	}
-}
-
-static void crc32cinit_le(void)
-{
-	crc32init_le_generic(CRC32C_POLY_LE, crc32ctable_le);
-}
-
-static void output_table(uint32_t (*table)[256], int rows, int len, char *trans)
-{
-	int i, j;
-
-	for (j = 0 ; j < rows; j++) {
-		printf("{");
-		for (i = 0; i < len - 1; i++) {
-			if (i % ENTRIES_PER_LINE == 0)
-				printf("\n");
-			printf("%s(0x%8.8xL), ", trans, table[j][i]);
-		}
-		printf("%s(0x%8.8xL)},\n", trans, table[j][len - 1]);
-	}
-}
-
-int main(int argc, char** argv)
-{
-	printf("/* this file is generated - do not edit */\n\n");
-
-	if (CRC_LE_BITS > 1) {
-		crc32cinit_le();
-		printf("static u32 crc32ctable_le[%d][%d] = {",
-		       LE_TABLE_ROWS, LE_TABLE_SIZE);
-		output_table(crc32ctable_le, LE_TABLE_ROWS,
-			     LE_TABLE_SIZE, "tole");
-		printf("};\n");
-	}
-
-	return 0;
-}
diff --git a/libxfs/libxfs_priv.h b/libxfs/libxfs_priv.h
index 85f13950..bc205cb7 100644
--- a/libxfs/libxfs_priv.h
+++ b/libxfs/libxfs_priv.h
@@ -53,9 +53,9 @@
 #include "xfs_arch.h"
 
 #include "xfs_fs.h"
+#include "crc32c.h"
 
 /* CRC stuff, buffer API dependent on it */
-extern uint32_t crc32c_le(uint32_t crc, unsigned char const *p, size_t len);
 #define crc32c(c,p,l)	crc32c_le((c),(unsigned char const *)(p),(l))
 
 #include "xfs_cksum.h"


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 03/10] xfs_scrub: destroy workqueues when erroring out
  2018-06-27  2:47 [PATCH 00/10] xfsprogs-4.18: mostly scrub/repair stuff Darrick J. Wong
  2018-06-27  2:47 ` [PATCH 01/10] libxfs: remove crc32 functions Darrick J. Wong
  2018-06-27  2:47 ` [PATCH 02/10] libfrog: move crc32c code out of libxfs Darrick J. Wong
@ 2018-06-27  2:48 ` Darrick J. Wong
  2018-07-26  0:29   ` Eric Sandeen
  2018-06-27  2:48 ` [PATCH 04/10] xfs_scrub: schedule and manage optimizations/repairs to the filesystem Darrick J. Wong
                   ` (8 subsequent siblings)
  11 siblings, 1 reply; 29+ messages in thread
From: Darrick J. Wong @ 2018-06-27  2:48 UTC (permalink / raw)
  To: sandeen, darrick.wong; +Cc: linux-xfs

From: Darrick J. Wong <darrick.wong@oracle.com>

Fix a couple of code paths that forgot to tear down a workqueue when
erroring out, because if we don't the wq threads keep running even after
we've freed the wq memory.

Found by fuzzing core.nlinkv2=0 in xfs/377, but only because the fs will
shut down when it hits an error destroying the incore (corrupt) inode
after the scrub.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 scrub/phase2.c |    2 +-
 scrub/vfs.c    |    4 +++-
 2 files changed, 4 insertions(+), 2 deletions(-)


diff --git a/scrub/phase2.c b/scrub/phase2.c
index ad736bf5..7078e38d 100644
--- a/scrub/phase2.c
+++ b/scrub/phase2.c
@@ -102,7 +102,7 @@ xfs_scan_metadata(
 	 */
 	moveon = xfs_scrub_primary_super(ctx);
 	if (!moveon)
-		return moveon;
+		goto out;
 
 	for (agno = 0; moveon && agno < ctx->geo.agcount; agno++) {
 		ret = workqueue_add(&wq, xfs_scan_ag_metadata, agno, &moveon);
diff --git a/scrub/vfs.c b/scrub/vfs.c
index 77df2874..12a6a860 100644
--- a/scrub/vfs.c
+++ b/scrub/vfs.c
@@ -210,7 +210,7 @@ scan_fs_tree(
 	if (ret) {
 		str_info(ctx, ctx->mntpoint,
 _("Could not queue directory scan work."));
-		goto out_free;
+		goto out_wq;
 	}
 
 	pthread_mutex_lock(&sft.lock);
@@ -220,6 +220,8 @@ _("Could not queue directory scan work."));
 	workqueue_destroy(&wq);
 
 	return sft.moveon;
+out_wq:
+	workqueue_destroy(&wq);
 out_free:
 	free(sftd->path);
 	free(sftd);


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 04/10] xfs_scrub: schedule and manage optimizations/repairs to the filesystem
  2018-06-27  2:47 [PATCH 00/10] xfsprogs-4.18: mostly scrub/repair stuff Darrick J. Wong
                   ` (2 preceding siblings ...)
  2018-06-27  2:48 ` [PATCH 03/10] xfs_scrub: destroy workqueues when erroring out Darrick J. Wong
@ 2018-06-27  2:48 ` Darrick J. Wong
  2018-07-26  1:06   ` Eric Sandeen
  2018-06-27  2:48 ` [PATCH 05/10] xfs_scrub: allow developers to force repairs Darrick J. Wong
                   ` (7 subsequent siblings)
  11 siblings, 1 reply; 29+ messages in thread
From: Darrick J. Wong @ 2018-06-27  2:48 UTC (permalink / raw)
  To: sandeen, darrick.wong; +Cc: linux-xfs

From: Darrick J. Wong <darrick.wong@oracle.com>

Teach xfs_scrub to remember scrub requests that failed (or indicated
that optimization is a possibility) as action items.  Depending on the
circumstances, certain items are acted upon immediately (e.g. metadata
that needs to be healthy in order to finish the scan, or files that are
already open) or deferred until later.  Expand the repair phase to
deal with the deferred actions.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 man/man8/xfs_scrub.8 |   38 ++++++-
 scrub/Makefile       |    2 
 scrub/phase1.c       |    7 +
 scrub/phase2.c       |   59 ++++++++++
 scrub/phase3.c       |   42 +++++--
 scrub/phase4.c       |   76 +++++++++++++
 scrub/repair.c       |  286 ++++++++++++++++++++++++++++++++++++++++++++++++++
 scrub/repair.h       |   42 +++++++
 scrub/scrub.c        |  130 ++++++++++++++++-------
 scrub/scrub.h        |   42 +++++--
 scrub/xfs_scrub.c    |   44 +++++++-
 scrub/xfs_scrub.h    |    1 
 12 files changed, 690 insertions(+), 79 deletions(-)
 create mode 100644 scrub/repair.c
 create mode 100644 scrub/repair.h


diff --git a/man/man8/xfs_scrub.8 b/man/man8/xfs_scrub.8
index 680ef72b..18948a4e 100644
--- a/man/man8/xfs_scrub.8
+++ b/man/man8/xfs_scrub.8
@@ -1,6 +1,6 @@
 .TH xfs_scrub 8
 .SH NAME
-xfs_scrub \- check the contents of a mounted XFS filesystem
+xfs_scrub \- check and repair the contents of a mounted XFS filesystem
 .SH SYNOPSIS
 .B xfs_scrub
 [
@@ -108,10 +108,40 @@ Optimizations supported by this program include, but are not limited to:
 Instructing the underlying storage to discard unused extents via the
 .B TRIM
 ioctl.
+.IP \[bu]
+Updating secondary superblocks to match the primary superblock.
+.IP \[bu]
+Turning off shared block write checks for files that no longer share blocks.
 .SH REPAIRS
-This program currently does not support making any repairs.
-Corruptions can only be fixed by unmounting the filesystem and running
-.BR xfs_repair (8).
+Repairs are performed by calling into the kernel.
+This limits the scope of repair activities to rebuilding primary data
+structures from secondary data structures, or secondary structures from
+primary structures.
+The existence of secondary data structures may require features that can
+only be turned on from
+.BR mkfs.xfs (8).
+If errors cannot be repaired, the filesystem must be
+unmounted and
+.BR xfs_repair (8)
+run.
+Repairs supported by the kernel include, but are not limited to:
+.IP \[bu] 2
+Reconstructing extent allocation data.
+.IP \[bu]
+Rebuilding free space information.
+.IP \[bu]
+Rebuilding inode indexes.
+.IP \[bu]
+Fixing minor corruptions of inode records.
+.IP \[bu]
+Recalculating reference count information.
+.IP \[bu]
+Reconstructing reverse mapping data from primary extent allocation data.
+.IP \[bu]
+Scheduling a quotacheck for the next mount.
+.PP
+If corrupt metadata is successfully repaired, this program will log that
+a repair has succeeded instead of a corruption report.
 .SH EXIT CODE
 The exit code returned by
 .B xfs_scrub
diff --git a/scrub/Makefile b/scrub/Makefile
index 482e8a7b..f5a2c38b 100644
--- a/scrub/Makefile
+++ b/scrub/Makefile
@@ -40,6 +40,7 @@ fscounters.h \
 inodes.h \
 progress.h \
 read_verify.h \
+repair.h \
 scrub.h \
 spacemap.h \
 unicrash.h \
@@ -63,6 +64,7 @@ phase6.c \
 phase7.c \
 progress.c \
 read_verify.c \
+repair.c \
 scrub.c \
 spacemap.c \
 vfs.c \
diff --git a/scrub/phase1.c b/scrub/phase1.c
index 87847259..abf8f316 100644
--- a/scrub/phase1.c
+++ b/scrub/phase1.c
@@ -39,6 +39,7 @@
 #include "common.h"
 #include "disk.h"
 #include "scrub.h"
+#include "repair.h"
 
 /* Phase 1: Find filesystem geometry (and clean up after) */
 
@@ -62,6 +63,7 @@ xfs_cleanup_fs(
 {
 	int			error;
 
+	xfs_action_lists_free(&ctx->action_lists);
 	if (ctx->fshandle)
 		free_handle(ctx->fshandle, ctx->fshandle_len);
 	if (ctx->rtdev)
@@ -152,6 +154,11 @@ _("Does not appear to be an XFS filesystem!"));
 		return false;
 	}
 
+	if (!xfs_action_lists_alloc(ctx->geo.agcount, &ctx->action_lists)) {
+		str_error(ctx, ctx->mntpoint, _("Not enough memory."));
+		return false;
+	}
+
 	ctx->agblklog = log2_roundup(ctx->geo.agblocks);
 	ctx->blocklog = highbit32(ctx->geo.blocksize);
 	ctx->inodelog = highbit32(ctx->geo.inodesize);
diff --git a/scrub/phase2.c b/scrub/phase2.c
index 7078e38d..c0c949e0 100644
--- a/scrub/phase2.c
+++ b/scrub/phase2.c
@@ -27,6 +27,7 @@
 #include "xfs_scrub.h"
 #include "common.h"
 #include "scrub.h"
+#include "repair.h"
 
 /* Phase 2: Check internal metadata. */
 
@@ -39,24 +40,65 @@ xfs_scan_ag_metadata(
 {
 	struct scrub_ctx		*ctx = (struct scrub_ctx *)wq->wq_ctx;
 	bool				*pmoveon = arg;
+	struct xfs_action_list		alist;
+	struct xfs_action_list		immediate_alist;
+	unsigned long long		broken_primaries;
+	unsigned long long		broken_secondaries;
 	bool				moveon;
 	char				descr[DESCR_BUFSZ];
 
+	xfs_action_list_init(&alist);
+	xfs_action_list_init(&immediate_alist);
 	snprintf(descr, DESCR_BUFSZ, _("AG %u"), agno);
 
 	/*
 	 * First we scrub and fix the AG headers, because we need
 	 * them to work well enough to check the AG btrees.
 	 */
-	moveon = xfs_scrub_ag_headers(ctx, agno);
+	moveon = xfs_scrub_ag_headers(ctx, agno, &alist);
+	if (!moveon)
+		goto err;
+
+	/* Repair header damage. */
+	moveon = xfs_action_list_process_or_defer(ctx, agno, &alist);
 	if (!moveon)
 		goto err;
 
 	/* Now scrub the AG btrees. */
-	moveon = xfs_scrub_ag_metadata(ctx, agno);
+	moveon = xfs_scrub_ag_metadata(ctx, agno, &alist);
+	if (!moveon)
+		goto err;
+
+	/*
+	 * Figure out if we need to perform early fixing.  The only
+	 * reason we need to do this is if the inobt is broken, which
+	 * prevents phase 3 (inode scan) from running.  We can rebuild
+	 * the inobt from rmapbt data, but if the rmapbt is broken even
+	 * at this early phase then we are sunk.
+	 */
+	broken_secondaries = 0;
+	broken_primaries = 0;
+	xfs_action_list_find_mustfix(&alist, &immediate_alist,
+			&broken_primaries, &broken_secondaries);
+	if (broken_secondaries && !debug_tweak_on("XFS_SCRUB_FORCE_REPAIR")) {
+		if (broken_primaries)
+			str_info(ctx, descr,
+_("Corrupt primary and secondary block mapping metadata."));
+		else
+			str_info(ctx, descr,
+_("Corrupt secondary block mapping metadata."));
+		str_info(ctx, descr,
+_("Filesystem might not be repairable."));
+	}
+
+	/* Repair (inode) btree damage. */
+	moveon = xfs_action_list_process_or_defer(ctx, agno, &immediate_alist);
 	if (!moveon)
 		goto err;
 
+	/* Everything else gets fixed during phase 4. */
+	xfs_action_list_defer(ctx, agno, &alist);
+
 	return;
 err:
 	*pmoveon = false;
@@ -71,11 +113,15 @@ xfs_scan_fs_metadata(
 {
 	struct scrub_ctx		*ctx = (struct scrub_ctx *)wq->wq_ctx;
 	bool				*pmoveon = arg;
+	struct xfs_action_list		alist;
 	bool				moveon;
 
-	moveon = xfs_scrub_fs_metadata(ctx);
+	xfs_action_list_init(&alist);
+	moveon = xfs_scrub_fs_metadata(ctx, &alist);
 	if (!moveon)
 		*pmoveon = false;
+
+	xfs_action_list_defer(ctx, agno, &alist);
 }
 
 /* Scan all filesystem metadata. */
@@ -83,6 +129,7 @@ bool
 xfs_scan_metadata(
 	struct scrub_ctx	*ctx)
 {
+	struct xfs_action_list	alist;
 	struct workqueue	wq;
 	xfs_agnumber_t		agno;
 	bool			moveon = true;
@@ -100,7 +147,11 @@ xfs_scan_metadata(
 	 * upgrades (followed by a full scrub), do that before we launch
 	 * anything else.
 	 */
-	moveon = xfs_scrub_primary_super(ctx);
+	xfs_action_list_init(&alist);
+	moveon = xfs_scrub_primary_super(ctx, &alist);
+	if (!moveon)
+		goto out;
+	moveon = xfs_action_list_process_or_defer(ctx, 0, &alist);
 	if (!moveon)
 		goto out;
 
diff --git a/scrub/phase3.c b/scrub/phase3.c
index cbaa80ba..a9470de4 100644
--- a/scrub/phase3.c
+++ b/scrub/phase3.c
@@ -30,6 +30,7 @@
 #include "inodes.h"
 #include "progress.h"
 #include "scrub.h"
+#include "repair.h"
 
 /* Phase 3: Scan all inodes. */
 
@@ -42,10 +43,11 @@ static bool
 xfs_scrub_fd(
 	struct scrub_ctx	*ctx,
 	bool			(*fn)(struct scrub_ctx *, uint64_t,
-				      uint32_t, int),
-	struct xfs_bstat	*bs)
+				      uint32_t, int, struct xfs_action_list *),
+	struct xfs_bstat	*bs,
+	struct xfs_action_list	*alist)
 {
-	return fn(ctx, bs->bs_ino, bs->bs_gen, ctx->mnt_fd);
+	return fn(ctx, bs->bs_ino, bs->bs_gen, ctx->mnt_fd, alist);
 }
 
 struct scrub_inode_ctx {
@@ -80,12 +82,16 @@ xfs_scrub_inode(
 	struct xfs_bstat	*bstat,
 	void			*arg)
 {
+	struct xfs_action_list	alist;
 	struct scrub_inode_ctx	*ictx = arg;
 	struct ptcounter	*icount = ictx->icount;
+	xfs_agnumber_t		agno;
 	bool			moveon = true;
 	int			fd = -1;
 	int			error;
 
+	xfs_action_list_init(&alist);
+	agno = bstat->bs_ino / (1ULL << (ctx->inopblog + ctx->agblklog));
 	background_sleep();
 
 	/* Try to open the inode to pin it. */
@@ -97,45 +103,59 @@ xfs_scrub_inode(
 	}
 
 	/* Scrub the inode. */
-	moveon = xfs_scrub_fd(ctx, xfs_scrub_inode_fields, bstat);
+	moveon = xfs_scrub_fd(ctx, xfs_scrub_inode_fields, bstat, &alist);
+	if (!moveon)
+		goto out;
+
+	moveon = xfs_action_list_process_or_defer(ctx, agno, &alist);
 	if (!moveon)
 		goto out;
 
 	/* Scrub all block mappings. */
-	moveon = xfs_scrub_fd(ctx, xfs_scrub_data_fork, bstat);
+	moveon = xfs_scrub_fd(ctx, xfs_scrub_data_fork, bstat, &alist);
 	if (!moveon)
 		goto out;
-	moveon = xfs_scrub_fd(ctx, xfs_scrub_attr_fork, bstat);
+	moveon = xfs_scrub_fd(ctx, xfs_scrub_attr_fork, bstat, &alist);
 	if (!moveon)
 		goto out;
-	moveon = xfs_scrub_fd(ctx, xfs_scrub_cow_fork, bstat);
+	moveon = xfs_scrub_fd(ctx, xfs_scrub_cow_fork, bstat, &alist);
+	if (!moveon)
+		goto out;
+
+	moveon = xfs_action_list_process_or_defer(ctx, agno, &alist);
 	if (!moveon)
 		goto out;
 
 	if (S_ISLNK(bstat->bs_mode)) {
 		/* Check symlink contents. */
 		moveon = xfs_scrub_symlink(ctx, bstat->bs_ino,
-				bstat->bs_gen, ctx->mnt_fd);
+				bstat->bs_gen, ctx->mnt_fd, &alist);
 	} else if (S_ISDIR(bstat->bs_mode)) {
 		/* Check the directory entries. */
-		moveon = xfs_scrub_fd(ctx, xfs_scrub_dir, bstat);
+		moveon = xfs_scrub_fd(ctx, xfs_scrub_dir, bstat, &alist);
 	}
 	if (!moveon)
 		goto out;
 
 	/* Check all the extended attributes. */
-	moveon = xfs_scrub_fd(ctx, xfs_scrub_attr, bstat);
+	moveon = xfs_scrub_fd(ctx, xfs_scrub_attr, bstat, &alist);
 	if (!moveon)
 		goto out;
 
 	/* Check parent pointers. */
-	moveon = xfs_scrub_fd(ctx, xfs_scrub_parent, bstat);
+	moveon = xfs_scrub_fd(ctx, xfs_scrub_parent, bstat, &alist);
+	if (!moveon)
+		goto out;
+
+	/* Try to repair the file while it's open. */
+	moveon = xfs_action_list_process_or_defer(ctx, agno, &alist);
 	if (!moveon)
 		goto out;
 
 out:
 	ptcounter_add(icount, 1);
 	progress_add(1);
+	xfs_action_list_defer(ctx, agno, &alist);
 	if (fd >= 0) {
 		error = close(fd);
 		if (error)
diff --git a/scrub/phase4.c b/scrub/phase4.c
index 8573036a..01a073bc 100644
--- a/scrub/phase4.c
+++ b/scrub/phase4.c
@@ -29,16 +29,82 @@
 #include "common.h"
 #include "progress.h"
 #include "scrub.h"
+#include "repair.h"
 #include "vfs.h"
 
 /* Phase 4: Repair filesystem. */
 
+/* Fix all the problems in our per-AG list. */
+static void
+xfs_repair_ag(
+	struct workqueue		*wq,
+	xfs_agnumber_t			agno,
+	void				*priv)
+{
+	struct scrub_ctx		*ctx = (struct scrub_ctx *)wq->wq_ctx;
+	bool				*pmoveon = priv;
+	struct xfs_action_list		*alist;
+	size_t				unfixed;
+	size_t				new_unfixed;
+	unsigned int			flags = 0;
+	bool				moveon;
+
+	alist = &ctx->action_lists[agno];
+	unfixed = xfs_action_list_length(alist);
+
+	/* Repair anything broken until we fail to make progress. */
+	do {
+		moveon = xfs_action_list_process(ctx, ctx->mnt_fd, alist, flags);
+		if (!moveon) {
+			*pmoveon = false;
+			return;
+		}
+		new_unfixed = xfs_action_list_length(alist);
+		if (new_unfixed == unfixed)
+			break;
+		unfixed = new_unfixed;
+	} while (unfixed > 0 && *pmoveon);
+
+	if (!*pmoveon)
+		return;
+
+	/* Try once more, but this time complain if we can't fix things. */
+	flags |= ALP_NOFIX_COMPLAIN;
+	moveon = xfs_action_list_process(ctx, ctx->mnt_fd, alist, flags);
+	if (!moveon)
+		*pmoveon = false;
+}
+
 /* Process all the action items. */
 static bool
 xfs_process_action_items(
 	struct scrub_ctx		*ctx)
 {
+	struct workqueue		wq;
+	xfs_agnumber_t			agno;
 	bool				moveon = true;
+	int				ret;
+
+	ret = workqueue_create(&wq, (struct xfs_mount *)ctx,
+			scrub_nproc_workqueue(ctx));
+	if (ret) {
+		str_error(ctx, ctx->mntpoint, _("Could not create workqueue."));
+		return false;
+	}
+	for (agno = 0; agno < ctx->geo.agcount; agno++) {
+		if (xfs_action_list_length(&ctx->action_lists[agno]) > 0) {
+			ret = workqueue_add(&wq, xfs_repair_ag, agno, &moveon);
+			if (ret) {
+				moveon = false;
+				str_error(ctx, ctx->mntpoint,
+_("Could not queue repair work."));
+				break;
+			}
+		}
+		if (!moveon)
+			break;
+	}
+	workqueue_destroy(&wq);
 
 	pthread_mutex_lock(&ctx->lock);
 	if (moveon && ctx->errors_found == 0 && want_fstrim) {
@@ -66,8 +132,14 @@ xfs_estimate_repair_work(
 	unsigned int		*nr_threads,
 	int			*rshift)
 {
-	*items = 1;
-	*nr_threads = 1;
+	xfs_agnumber_t		agno;
+	size_t			need_fixing = 0;
+
+	for (agno = 0; agno < ctx->geo.agcount; agno++)
+		need_fixing += xfs_action_list_length(&ctx->action_lists[agno]);
+	need_fixing++;
+	*items = need_fixing;
+	*nr_threads = scrub_nproc(ctx) + 1;
 	*rshift = 0;
 	return true;
 }
diff --git a/scrub/repair.c b/scrub/repair.c
new file mode 100644
index 00000000..4ed3c09a
--- /dev/null
+++ b/scrub/repair.c
@@ -0,0 +1,286 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Oracle.  All Rights Reserved.
+ * Author: Darrick J. Wong <darrick.wong@oracle.com>
+ */
+#include "xfs.h"
+#include <stdint.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/statvfs.h>
+#include "list.h"
+#include "path.h"
+#include "xfs_scrub.h"
+#include "common.h"
+#include "scrub.h"
+#include "progress.h"
+#include "repair.h"
+
+/*
+ * Prioritize action items in order of how long we can wait.
+ * 0 = do it now, 10000 = do it later.
+ *
+ * To minimize the amount of repair work, we want to prioritize metadata
+ * objects by perceived corruptness.  If CORRUPT is set, the fields are
+ * just plain bad; try fixing that first.  Otherwise if XCORRUPT is set,
+ * the fields could be bad, but the xref data could also be bad; we'll
+ * try fixing that next.  Finally, if XFAIL is set, some other metadata
+ * structure failed validation during xref, so we'll recheck this
+ * metadata last since it was probably fine.
+ *
+ * For metadata that lie in the critical path of checking other metadata
+ * (superblock, AG{F,I,FL}, inobt) we scrub and fix those things before
+ * we even get to handling their dependencies, so things should progress
+ * in order.
+ */
+
+/* Sort action items in severity order. */
+static int
+PRIO(
+	struct action_item	*aitem,
+	int			order)
+{
+	if (aitem->flags & XFS_SCRUB_OFLAG_CORRUPT)
+		return order;
+	else if (aitem->flags & XFS_SCRUB_OFLAG_XCORRUPT)
+		return 100 + order;
+	else if (aitem->flags & XFS_SCRUB_OFLAG_XFAIL)
+		return 200 + order;
+	else if (aitem->flags & XFS_SCRUB_OFLAG_PREEN)
+		return 300 + order;
+	abort();
+}
+
+/* Sort the repair items in dependency order. */
+static int
+xfs_action_item_priority(
+	struct action_item	*aitem)
+{
+	switch (aitem->type) {
+	case XFS_SCRUB_TYPE_SB:
+	case XFS_SCRUB_TYPE_AGF:
+	case XFS_SCRUB_TYPE_AGFL:
+	case XFS_SCRUB_TYPE_AGI:
+	case XFS_SCRUB_TYPE_BNOBT:
+	case XFS_SCRUB_TYPE_CNTBT:
+	case XFS_SCRUB_TYPE_INOBT:
+	case XFS_SCRUB_TYPE_FINOBT:
+	case XFS_SCRUB_TYPE_REFCNTBT:
+	case XFS_SCRUB_TYPE_RMAPBT:
+	case XFS_SCRUB_TYPE_INODE:
+	case XFS_SCRUB_TYPE_BMBTD:
+	case XFS_SCRUB_TYPE_BMBTA:
+	case XFS_SCRUB_TYPE_BMBTC:
+		return PRIO(aitem, aitem->type - 1);
+	case XFS_SCRUB_TYPE_DIR:
+	case XFS_SCRUB_TYPE_XATTR:
+	case XFS_SCRUB_TYPE_SYMLINK:
+	case XFS_SCRUB_TYPE_PARENT:
+		return PRIO(aitem, XFS_SCRUB_TYPE_DIR);
+	case XFS_SCRUB_TYPE_RTBITMAP:
+	case XFS_SCRUB_TYPE_RTSUM:
+		return PRIO(aitem, XFS_SCRUB_TYPE_RTBITMAP);
+	case XFS_SCRUB_TYPE_UQUOTA:
+	case XFS_SCRUB_TYPE_GQUOTA:
+	case XFS_SCRUB_TYPE_PQUOTA:
+		return PRIO(aitem, XFS_SCRUB_TYPE_UQUOTA);
+	}
+	abort();
+}
+
+/* Make sure that btrees get repaired before headers. */
+static int
+xfs_action_item_compare(
+	void				*priv,
+	struct list_head		*a,
+	struct list_head		*b)
+{
+	struct action_item		*ra;
+	struct action_item		*rb;
+
+	ra = container_of(a, struct action_item, list);
+	rb = container_of(b, struct action_item, list);
+
+	return xfs_action_item_priority(ra) - xfs_action_item_priority(rb);
+}
+
+/*
+ * Figure out which AG metadata must be fixed before we can move on
+ * to the inode scan.
+ */
+void
+xfs_action_list_find_mustfix(
+	struct xfs_action_list		*alist,
+	struct xfs_action_list		*immediate_alist,
+	unsigned long long		*broken_primaries,
+	unsigned long long		*broken_secondaries)
+{
+	struct action_item		*n;
+	struct action_item		*aitem;
+
+	list_for_each_entry_safe(aitem, n, &alist->list, list) {
+		if (!(aitem->flags & XFS_SCRUB_OFLAG_CORRUPT))
+			continue;
+		switch (aitem->type) {
+		case XFS_SCRUB_TYPE_RMAPBT:
+			(*broken_secondaries)++;
+			break;
+		case XFS_SCRUB_TYPE_FINOBT:
+		case XFS_SCRUB_TYPE_INOBT:
+			alist->nr--;
+			list_move_tail(&aitem->list, &immediate_alist->list);
+			immediate_alist->nr++;
+			/* fall through */
+		case XFS_SCRUB_TYPE_BNOBT:
+		case XFS_SCRUB_TYPE_CNTBT:
+		case XFS_SCRUB_TYPE_REFCNTBT:
+			(*broken_primaries)++;
+			break;
+		default:
+			abort();
+			break;
+		}
+	}
+}
+
+/* Allocate a certain number of repair lists for the scrub context. */
+bool
+xfs_action_lists_alloc(
+	size_t				nr,
+	struct xfs_action_list		**listsp)
+{
+	struct xfs_action_list		*lists;
+	xfs_agnumber_t			agno;
+
+	lists = calloc(nr, sizeof(struct xfs_action_list));
+	if (!lists)
+		return false;
+
+	for (agno = 0; agno < nr; agno++)
+		xfs_action_list_init(&lists[agno]);
+	*listsp = lists;
+
+	return true;
+}
+
+/* Free the repair lists. */
+void
+xfs_action_lists_free(
+	struct xfs_action_list		**listsp)
+{
+	free(*listsp);
+	*listsp = NULL;
+}
+
+/* Initialize repair list */
+void
+xfs_action_list_init(
+	struct xfs_action_list		*alist)
+{
+	INIT_LIST_HEAD(&alist->list);
+	alist->nr = 0;
+	alist->sorted = false;
+}
+
+/* Number of repairs in this list. */
+size_t
+xfs_action_list_length(
+	struct xfs_action_list		*alist)
+{
+	return alist->nr;
+};
+
+/* Add to the list of repairs. */
+void
+xfs_action_list_add(
+	struct xfs_action_list		*alist,
+	struct action_item		*aitem)
+{
+	list_add_tail(&aitem->list, &alist->list);
+	alist->nr++;
+	alist->sorted = false;
+}
+
+/* Splice two repair lists. */
+void
+xfs_action_list_splice(
+	struct xfs_action_list		*dest,
+	struct xfs_action_list		*src)
+{
+	if (src->nr == 0)
+		return;
+
+	list_splice_tail_init(&src->list, &dest->list);
+	dest->nr += src->nr;
+	src->nr = 0;
+	dest->sorted = false;
+}
+
+/* Repair everything on this list. */
+bool
+xfs_action_list_process(
+	struct scrub_ctx		*ctx,
+	int				fd,
+	struct xfs_action_list		*alist,
+	unsigned int			repair_flags)
+{
+	struct action_item		*aitem;
+	struct action_item		*n;
+	enum check_outcome		fix;
+
+	if (!alist->sorted) {
+		list_sort(NULL, &alist->list, xfs_action_item_compare);
+		alist->sorted = true;
+	}
+
+	list_for_each_entry_safe(aitem, n, &alist->list, list) {
+		fix = xfs_repair_metadata(ctx, fd, aitem, repair_flags);
+		switch (fix) {
+		case CHECK_DONE:
+			if (!(repair_flags & ALP_NOPROGRESS))
+				progress_add(1);
+			alist->nr--;
+			list_del(&aitem->list);
+			free(aitem);
+			continue;
+		case CHECK_ABORT:
+			return false;
+		case CHECK_RETRY:
+			continue;
+		case CHECK_REPAIR:
+			abort();
+		}
+	}
+
+	return !xfs_scrub_excessive_errors(ctx);
+}
+
+/* Defer all the repairs until phase 4. */
+void
+xfs_action_list_defer(
+	struct scrub_ctx		*ctx,
+	xfs_agnumber_t			agno,
+	struct xfs_action_list		*alist)
+{
+	ASSERT(agno < ctx->geo.agcount);
+
+	xfs_action_list_splice(&ctx->action_lists[agno], alist);
+}
+
+/* Run actions now and defer unfinished items for later. */
+bool
+xfs_action_list_process_or_defer(
+	struct scrub_ctx		*ctx,
+	xfs_agnumber_t			agno,
+	struct xfs_action_list		*alist)
+{
+	bool				moveon;
+
+	moveon = xfs_action_list_process(ctx, ctx->mnt_fd, alist,
+			ALP_REPAIR_ONLY | ALP_NOPROGRESS);
+	if (!moveon)
+		return moveon;
+
+	xfs_action_list_defer(ctx, agno, alist);
+	return true;
+}
diff --git a/scrub/repair.h b/scrub/repair.h
new file mode 100644
index 00000000..4be950e7
--- /dev/null
+++ b/scrub/repair.h
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2018 Oracle.  All Rights Reserved.
+ * Author: Darrick J. Wong <darrick.wong@oracle.com>
+ */
+#ifndef XFS_SCRUB_REPAIR_H_
+#define XFS_SCRUB_REPAIR_H_
+
+struct xfs_action_list {
+	struct list_head	list;
+	size_t			nr;
+	bool			sorted;
+};
+
+bool xfs_action_lists_alloc(size_t nr, struct xfs_action_list **listsp);
+void xfs_action_lists_free(struct xfs_action_list **listsp);
+
+void xfs_action_list_init(struct xfs_action_list *alist);
+size_t xfs_action_list_length(struct xfs_action_list *alist);
+void xfs_action_list_add(struct xfs_action_list *dest,
+		struct action_item *item);
+void xfs_action_list_splice(struct xfs_action_list *dest,
+		struct xfs_action_list *src);
+
+void xfs_action_list_find_mustfix(struct xfs_action_list *actions,
+		struct xfs_action_list *immediate_alist,
+		unsigned long long *broken_primaries,
+		unsigned long long *broken_secondaries);
+
+/* Passed through to xfs_repair_metadata() */
+#define ALP_REPAIR_ONLY		(XRM_REPAIR_ONLY)
+#define ALP_NOFIX_COMPLAIN	(XRM_NOFIX_COMPLAIN)
+#define ALP_NOPROGRESS		(1U << 31)
+
+bool xfs_action_list_process(struct scrub_ctx *ctx, int fd,
+		struct xfs_action_list *alist, unsigned int repair_flags);
+void xfs_action_list_defer(struct scrub_ctx *ctx, xfs_agnumber_t agno,
+		struct xfs_action_list *alist);
+bool xfs_action_list_process_or_defer(struct scrub_ctx *ctx, xfs_agnumber_t agno,
+		struct xfs_action_list *alist);
+
+#endif /* XFS_SCRUB_REPAIR_H_ */
diff --git a/scrub/scrub.c b/scrub/scrub.c
index a361d8e0..af665c83 100644
--- a/scrub/scrub.c
+++ b/scrub/scrub.c
@@ -31,6 +31,7 @@
 #include "progress.h"
 #include "scrub.h"
 #include "xfs_errortag.h"
+#include "repair.h"
 
 /* Online scrub and repair wrappers. */
 
@@ -317,12 +318,48 @@ _("Optimizations of %s are possible."), scrubbers[i].name);
 	}
 }
 
+/* Save a scrub context for later repairs. */
+bool
+xfs_scrub_save_repair(
+	struct scrub_ctx		*ctx,
+	struct xfs_action_list		*alist,
+	struct xfs_scrub_metadata	*meta)
+{
+	struct action_item		*aitem;
+
+	/* Schedule this item for later repairs. */
+	aitem = malloc(sizeof(struct action_item));
+	if (!aitem) {
+		str_errno(ctx, _("repair list"));
+		return false;
+	}
+	memset(aitem, 0, sizeof(*aitem));
+	aitem->type = meta->sm_type;
+	aitem->flags = meta->sm_flags;
+	switch (scrubbers[meta->sm_type].type) {
+	case ST_AGHEADER:
+	case ST_PERAG:
+		aitem->agno = meta->sm_agno;
+		break;
+	case ST_INODE:
+		aitem->ino = meta->sm_ino;
+		aitem->gen = meta->sm_gen;
+		break;
+	default:
+		break;
+	}
+
+	xfs_action_list_add(alist, aitem);
+	return true;
+}
+
 /* Scrub metadata, saving corruption reports for later. */
 static bool
 xfs_scrub_metadata(
 	struct scrub_ctx		*ctx,
 	enum scrub_type			scrub_type,
-	xfs_agnumber_t			agno)
+	xfs_agnumber_t			agno,
+	struct xfs_action_list		*alist)
 {
 	struct xfs_scrub_metadata	meta = {0};
 	const struct scrub_descr	*sc;
@@ -346,6 +383,8 @@ xfs_scrub_metadata(
 		case CHECK_ABORT:
 			return false;
 		case CHECK_REPAIR:
+			if (!xfs_scrub_save_repair(ctx, alist, &meta))
+				return false;
 			/* fall through */
 		case CHECK_DONE:
 			continue;
@@ -365,7 +404,8 @@ xfs_scrub_metadata(
  */
 bool
 xfs_scrub_primary_super(
-	struct scrub_ctx		*ctx)
+	struct scrub_ctx		*ctx,
+	struct xfs_action_list		*alist)
 {
 	struct xfs_scrub_metadata	meta = {
 		.sm_type = XFS_SCRUB_TYPE_SB,
@@ -378,6 +418,8 @@ xfs_scrub_primary_super(
 	case CHECK_ABORT:
 		return false;
 	case CHECK_REPAIR:
+		if (!xfs_scrub_save_repair(ctx, alist, &meta))
+			return false;
 		/* fall through */
 	case CHECK_DONE:
 		return true;
@@ -393,26 +435,29 @@ xfs_scrub_primary_super(
 bool
 xfs_scrub_ag_headers(
 	struct scrub_ctx		*ctx,
-	xfs_agnumber_t			agno)
+	xfs_agnumber_t			agno,
+	struct xfs_action_list		*alist)
 {
-	return xfs_scrub_metadata(ctx, ST_AGHEADER, agno);
+	return xfs_scrub_metadata(ctx, ST_AGHEADER, agno, alist);
 }
 
 /* Scrub each AG's metadata btrees. */
 bool
 xfs_scrub_ag_metadata(
 	struct scrub_ctx		*ctx,
-	xfs_agnumber_t			agno)
+	xfs_agnumber_t			agno,
+	struct xfs_action_list		*alist)
 {
-	return xfs_scrub_metadata(ctx, ST_PERAG, agno);
+	return xfs_scrub_metadata(ctx, ST_PERAG, agno, alist);
 }
 
 /* Scrub whole-FS metadata btrees. */
 bool
 xfs_scrub_fs_metadata(
-	struct scrub_ctx		*ctx)
+	struct scrub_ctx		*ctx,
+	struct xfs_action_list		*alist)
 {
-	return xfs_scrub_metadata(ctx, ST_FS, 0);
+	return xfs_scrub_metadata(ctx, ST_FS, 0, alist);
 }
 
 /* How many items do we have to check? */
@@ -448,7 +493,8 @@ __xfs_scrub_file(
 	uint64_t			ino,
 	uint32_t			gen,
 	int				fd,
-	unsigned int			type)
+	unsigned int			type,
+	struct xfs_action_list		*alist)
 {
 	struct xfs_scrub_metadata	meta = {0};
 	enum check_outcome		fix;
@@ -467,7 +513,7 @@ __xfs_scrub_file(
 	if (fix == CHECK_DONE)
 		return true;
 
-	return true;
+	return xfs_scrub_save_repair(ctx, alist, &meta);
 }
 
 bool
@@ -475,9 +521,10 @@ xfs_scrub_inode_fields(
 	struct scrub_ctx	*ctx,
 	uint64_t		ino,
 	uint32_t		gen,
-	int			fd)
+	int			fd,
+	struct xfs_action_list	*alist)
 {
-	return __xfs_scrub_file(ctx, ino, gen, fd, XFS_SCRUB_TYPE_INODE);
+	return __xfs_scrub_file(ctx, ino, gen, fd, XFS_SCRUB_TYPE_INODE, alist);
 }
 
 bool
@@ -485,9 +532,10 @@ xfs_scrub_data_fork(
 	struct scrub_ctx	*ctx,
 	uint64_t		ino,
 	uint32_t		gen,
-	int			fd)
+	int			fd,
+	struct xfs_action_list	*alist)
 {
-	return __xfs_scrub_file(ctx, ino, gen, fd, XFS_SCRUB_TYPE_BMBTD);
+	return __xfs_scrub_file(ctx, ino, gen, fd, XFS_SCRUB_TYPE_BMBTD, alist);
 }
 
 bool
@@ -495,9 +543,10 @@ xfs_scrub_attr_fork(
 	struct scrub_ctx	*ctx,
 	uint64_t		ino,
 	uint32_t		gen,
-	int			fd)
+	int			fd,
+	struct xfs_action_list	*alist)
 {
-	return __xfs_scrub_file(ctx, ino, gen, fd, XFS_SCRUB_TYPE_BMBTA);
+	return __xfs_scrub_file(ctx, ino, gen, fd, XFS_SCRUB_TYPE_BMBTA, alist);
 }
 
 bool
@@ -505,9 +554,10 @@ xfs_scrub_cow_fork(
 	struct scrub_ctx	*ctx,
 	uint64_t		ino,
 	uint32_t		gen,
-	int			fd)
+	int			fd,
+	struct xfs_action_list	*alist)
 {
-	return __xfs_scrub_file(ctx, ino, gen, fd, XFS_SCRUB_TYPE_BMBTC);
+	return __xfs_scrub_file(ctx, ino, gen, fd, XFS_SCRUB_TYPE_BMBTC, alist);
 }
 
 bool
@@ -515,9 +565,10 @@ xfs_scrub_dir(
 	struct scrub_ctx	*ctx,
 	uint64_t		ino,
 	uint32_t		gen,
-	int			fd)
+	int			fd,
+	struct xfs_action_list	*alist)
 {
-	return __xfs_scrub_file(ctx, ino, gen, fd, XFS_SCRUB_TYPE_DIR);
+	return __xfs_scrub_file(ctx, ino, gen, fd, XFS_SCRUB_TYPE_DIR, alist);
 }
 
 bool
@@ -525,9 +576,10 @@ xfs_scrub_attr(
 	struct scrub_ctx	*ctx,
 	uint64_t		ino,
 	uint32_t		gen,
-	int			fd)
+	int			fd,
+	struct xfs_action_list	*alist)
 {
-	return __xfs_scrub_file(ctx, ino, gen, fd, XFS_SCRUB_TYPE_XATTR);
+	return __xfs_scrub_file(ctx, ino, gen, fd, XFS_SCRUB_TYPE_XATTR, alist);
 }
 
 bool
@@ -535,9 +587,10 @@ xfs_scrub_symlink(
 	struct scrub_ctx	*ctx,
 	uint64_t		ino,
 	uint32_t		gen,
-	int			fd)
+	int			fd,
+	struct xfs_action_list	*alist)
 {
-	return __xfs_scrub_file(ctx, ino, gen, fd, XFS_SCRUB_TYPE_SYMLINK);
+	return __xfs_scrub_file(ctx, ino, gen, fd, XFS_SCRUB_TYPE_SYMLINK, alist);
 }
 
 bool
@@ -545,9 +598,10 @@ xfs_scrub_parent(
 	struct scrub_ctx	*ctx,
 	uint64_t		ino,
 	uint32_t		gen,
-	int			fd)
+	int			fd,
+	struct xfs_action_list	*alist)
 {
-	return __xfs_scrub_file(ctx, ino, gen, fd, XFS_SCRUB_TYPE_PARENT);
+	return __xfs_scrub_file(ctx, ino, gen, fd, XFS_SCRUB_TYPE_PARENT, alist);
 }
 
 /* Test the availability of a kernel scrub command. */
@@ -663,7 +717,7 @@ enum check_outcome
 xfs_repair_metadata(
 	struct scrub_ctx		*ctx,
 	int				fd,
-	struct repair_item		*ri,
+	struct action_item		*aitem,
 	unsigned int			repair_flags)
 {
 	char				buf[DESCR_BUFSZ];
@@ -671,28 +725,24 @@ xfs_repair_metadata(
 	struct xfs_scrub_metadata	oldm;
 	int				error;
 
-	assert(ri->type < XFS_SCRUB_TYPE_NR);
+	assert(aitem->type < XFS_SCRUB_TYPE_NR);
 	assert(!debug_tweak_on("XFS_SCRUB_NO_KERNEL"));
-	meta.sm_type = ri->type;
-	meta.sm_flags = ri->flags | XFS_SCRUB_IFLAG_REPAIR;
-	switch (scrubbers[ri->type].type) {
+	meta.sm_type = aitem->type;
+	meta.sm_flags = aitem->flags | XFS_SCRUB_IFLAG_REPAIR;
+	switch (scrubbers[aitem->type].type) {
 	case ST_AGHEADER:
 	case ST_PERAG:
-		meta.sm_agno = ri->agno;
+		meta.sm_agno = aitem->agno;
 		break;
 	case ST_INODE:
-		meta.sm_ino = ri->ino;
-		meta.sm_gen = ri->gen;
+		meta.sm_ino = aitem->ino;
+		meta.sm_gen = aitem->gen;
 		break;
 	default:
 		break;
 	}
 
-	/*
-	 * If this is a preen operation but we're only repairing
-	 * critical items, defer the preening until later.
-	 */
-	if (!needs_repair(&meta) && (repair_flags & XRM_REPAIR_ONLY))
+	if (!is_corrupt(&meta) && (repair_flags & XRM_REPAIR_ONLY))
 		return CHECK_RETRY;
 
 	memcpy(&oldm, &meta, sizeof(oldm));
@@ -764,7 +814,7 @@ _("Read-only filesystem; cannot make changes."));
 		xfs_scrub_warn_incomplete_scrub(ctx, buf, &meta);
 	if (needs_repair(&meta)) {
 		/* Still broken, try again or fix offline. */
-		if (repair_flags & XRM_NOFIX_COMPLAIN)
+		if ((repair_flags & XRM_NOFIX_COMPLAIN) || debug)
 			str_error(ctx, buf,
 _("Repair unsuccessful; offline repair required."));
 	} else {
diff --git a/scrub/scrub.h b/scrub/scrub.h
index 1c44fbac..fdcbd40d 100644
--- a/scrub/scrub.h
+++ b/scrub/scrub.h
@@ -28,11 +28,19 @@ enum check_outcome {
 	CHECK_RETRY,	/* repair failed, try again later */
 };
 
+struct action_item;
+
 void xfs_scrub_report_preen_triggers(struct scrub_ctx *ctx);
-bool xfs_scrub_primary_super(struct scrub_ctx *ctx);
-bool xfs_scrub_ag_headers(struct scrub_ctx *ctx, xfs_agnumber_t agno);
-bool xfs_scrub_ag_metadata(struct scrub_ctx *ctx, xfs_agnumber_t agno);
-bool xfs_scrub_fs_metadata(struct scrub_ctx *ctx);
+bool xfs_scrub_primary_super(struct scrub_ctx *ctx,
+		struct xfs_action_list *alist);
+bool xfs_scrub_ag_headers(struct scrub_ctx *ctx, xfs_agnumber_t agno,
+		struct xfs_action_list *alist);
+bool xfs_scrub_ag_metadata(struct scrub_ctx *ctx, xfs_agnumber_t agno,
+		struct xfs_action_list *alist);
+bool xfs_scrub_fs_metadata(struct scrub_ctx *ctx,
+		struct xfs_action_list *alist);
+enum check_outcome xfs_repair_metadata(struct scrub_ctx *ctx, int fd,
+		struct action_item *aitem, unsigned int flags);
 
 bool xfs_can_scrub_fs_metadata(struct scrub_ctx *ctx);
 bool xfs_can_scrub_inode(struct scrub_ctx *ctx);
@@ -44,24 +52,24 @@ bool xfs_can_scrub_parent(struct scrub_ctx *ctx);
 bool xfs_can_repair(struct scrub_ctx *ctx);
 
 bool xfs_scrub_inode_fields(struct scrub_ctx *ctx, uint64_t ino, uint32_t gen,
-		int fd);
+		int fd, struct xfs_action_list *alist);
 bool xfs_scrub_data_fork(struct scrub_ctx *ctx, uint64_t ino, uint32_t gen,
-		int fd);
+		int fd, struct xfs_action_list *alist);
 bool xfs_scrub_attr_fork(struct scrub_ctx *ctx, uint64_t ino, uint32_t gen,
-		int fd);
+		int fd, struct xfs_action_list *alist);
 bool xfs_scrub_cow_fork(struct scrub_ctx *ctx, uint64_t ino, uint32_t gen,
-		int fd);
+		int fd, struct xfs_action_list *alist);
 bool xfs_scrub_dir(struct scrub_ctx *ctx, uint64_t ino, uint32_t gen,
-		int fd);
+		int fd, struct xfs_action_list *alist);
 bool xfs_scrub_attr(struct scrub_ctx *ctx, uint64_t ino, uint32_t gen,
-		int fd);
+		int fd, struct xfs_action_list *alist);
 bool xfs_scrub_symlink(struct scrub_ctx *ctx, uint64_t ino, uint32_t gen,
-		int fd);
+		int fd, struct xfs_action_list *alist);
 bool xfs_scrub_parent(struct scrub_ctx *ctx, uint64_t ino, uint32_t gen,
-		int fd);
+		int fd, struct xfs_action_list *alist);
 
 /* Repair parameters are the scrub inputs and retry count. */
-struct repair_item {
+struct action_item {
 	struct list_head	list;
 	__u64			ino;
 	__u32			type;
@@ -70,13 +78,17 @@ struct repair_item {
 	__u32			agno;
 };
 
-/* Only perform repairs; leave optimization-only actions for later. */
+/*
+ * Only ask the kernel to repair this object if the kernel directly told us it
+ * was corrupt.  Objects that are only flagged as having cross-referencing
+ * errors or flagged as eligible for optimization are left for later.
+ */
 #define XRM_REPAIR_ONLY		(1U << 0)
 
 /* Complain if still broken even after fix. */
 #define XRM_NOFIX_COMPLAIN	(1U << 1)
 
 enum check_outcome xfs_repair_metadata(struct scrub_ctx *ctx, int fd,
-		struct repair_item *ri, unsigned int repair_flags);
+		struct action_item *aitem, unsigned int repair_flags);
 
 #endif /* XFS_SCRUB_SCRUB_H_ */
diff --git a/scrub/xfs_scrub.c b/scrub/xfs_scrub.c
index 8f54f92a..a62615cf 100644
--- a/scrub/xfs_scrub.c
+++ b/scrub/xfs_scrub.c
@@ -86,6 +86,15 @@
  * the previous two phases are retried here; if there are uncorrectable
  * errors, xfs_scrub stops here.
  *
+ * To perform the actual repairs (or optimizations), we iterate all the
+ * items on the per-AG action item list and ask the kernel to repair
+ * them.  Items which are successfully repaired are removed from the
+ * list.  If an item is not acted upon successfully (or the kernel asks us
+ * to try again), we retry the actions until there is nothing left to
+ * fix or we fail to make forward progress.  In that event, the
+ * unfinished items are recorded as errors.  If there are no errors at
+ * this point, we call FSTRIM on the filesystem.
+ *
  * The next phase is the "check directory tree" phase.  In this phase,
  * every directory is opened (via file handle) to confirm that each
  * directory is connected to the root.  Directory entries are checked
@@ -491,6 +500,27 @@ _("Scrub aborted after phase %d."),
 	return moveon;
 }
 
+static void
+report_modifications(
+	struct scrub_ctx	*ctx)
+{
+	if (ctx->repairs == 0 && ctx->preens == 0)
+		return;
+
+	if (ctx->repairs && ctx->preens)
+		fprintf(stdout,
+_("%s: repairs made: %llu; optimizations made: %llu.\n"),
+				ctx->mntpoint, ctx->repairs, ctx->preens);
+	else if (ctx->preens == 0)
+		fprintf(stdout,
+_("%s: repairs made: %llu.\n"),
+				ctx->mntpoint, ctx->repairs);
+	else if (ctx->repairs == 0)
+		fprintf(stdout,
+_("%s: optimizations made: %llu.\n"),
+				ctx->mntpoint, ctx->preens);
+}
+
 static void
 report_outcome(
 	struct scrub_ctx	*ctx)
@@ -525,9 +555,16 @@ report_outcome(
 	 * setting up the scrub and we actually saw corruptions.  Warnings
 	 * are not corruptions.
 	 */
-	if (ctx->scrub_setup_succeeded && total_errors > 0)
-		fprintf(stderr, _("%s: Unmount and run xfs_repair.\n"),
-				ctx->mntpoint);
+	if (ctx->scrub_setup_succeeded && total_errors > 0) {
+		char		*msg;
+
+		if (ctx->mode == SCRUB_MODE_DRY_RUN)
+			msg = _("%s: Re-run xfs_scrub without -n.\n");
+		else
+			msg = _("%s: Unmount and run xfs_repair.\n");
+
+		fprintf(stderr, msg, ctx->mntpoint);
+	}
 }
 
 int
@@ -728,6 +765,7 @@ main(
 		ctx.runtime_errors++;
 
 out:
+	report_modifications(&ctx);
 	report_outcome(&ctx);
 
 	if (ctx.errors_found) {
diff --git a/scrub/xfs_scrub.h b/scrub/xfs_scrub.h
index c9dbe8e0..8b758191 100644
--- a/scrub/xfs_scrub.h
+++ b/scrub/xfs_scrub.h
@@ -86,6 +86,7 @@ struct scrub_ctx {
 
 	/* Mutable scrub state; use lock. */
 	pthread_mutex_t		lock;
+	struct xfs_action_list	*action_lists;
 	unsigned long long	max_errors;
 	unsigned long long	runtime_errors;
 	unsigned long long	errors_found;


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 05/10] xfs_scrub: allow developers to force repairs
  2018-06-27  2:47 [PATCH 00/10] xfsprogs-4.18: mostly scrub/repair stuff Darrick J. Wong
                   ` (3 preceding siblings ...)
  2018-06-27  2:48 ` [PATCH 04/10] xfs_scrub: schedule and manage optimizations/repairs to the filesystem Darrick J. Wong
@ 2018-06-27  2:48 ` Darrick J. Wong
  2018-07-26  1:07   ` Eric Sandeen
  2018-06-27  2:48 ` [PATCH 06/10] xfs_scrub: don't error out if an optimize-only repair isn't supported Darrick J. Wong
                   ` (6 subsequent siblings)
  11 siblings, 1 reply; 29+ messages in thread
From: Darrick J. Wong @ 2018-06-27  2:48 UTC (permalink / raw)
  To: sandeen, darrick.wong; +Cc: linux-xfs

From: Darrick J. Wong <darrick.wong@oracle.com>

Now that we have an error injection knob in the kernel to simulate
corruptions, enable it in xfs_scrub so that developers can test all
the repair capabilities.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 scrub/scrub.c |    8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)


diff --git a/scrub/scrub.c b/scrub/scrub.c
index af665c83..c893f2c9 100644
--- a/scrub/scrub.c
+++ b/scrub/scrub.c
@@ -612,14 +612,18 @@ __xfs_scrub_test(
 	bool				repair)
 {
 	struct xfs_scrub_metadata	meta = {0};
+	struct xfs_error_injection	inject;
 	static bool			injected;
 	int				error;
 
 	if (debug_tweak_on("XFS_SCRUB_NO_KERNEL"))
 		return false;
 	if (debug_tweak_on("XFS_SCRUB_FORCE_REPAIR") && !injected) {
-		str_info(ctx, "XFS_SCRUB_FORCE_REPAIR", "Not supported.");
-		return false;
+		inject.fd = ctx->mnt_fd;
+		inject.errtag = XFS_ERRTAG_FORCE_SCRUB_REPAIR;
+		error = ioctl(ctx->mnt_fd, XFS_IOC_ERROR_INJECTION, &inject);
+		if (error == 0)
+			injected = true;
 	}
 
 	meta.sm_type = type;


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 06/10] xfs_scrub: don't error out if an optimize-only repair isn't supported
  2018-06-27  2:47 [PATCH 00/10] xfsprogs-4.18: mostly scrub/repair stuff Darrick J. Wong
                   ` (4 preceding siblings ...)
  2018-06-27  2:48 ` [PATCH 05/10] xfs_scrub: allow developers to force repairs Darrick J. Wong
@ 2018-06-27  2:48 ` Darrick J. Wong
  2018-07-26  1:09   ` Eric Sandeen
  2018-06-27  2:48 ` [PATCH 07/10] xfs_scrub: rename NOFIX_COMPLAIN to be less confusing Darrick J. Wong
                   ` (5 subsequent siblings)
  11 siblings, 1 reply; 29+ messages in thread
From: Darrick J. Wong @ 2018-06-27  2:48 UTC (permalink / raw)
  To: sandeen, darrick.wong; +Cc: linux-xfs

From: Darrick J. Wong <darrick.wong@oracle.com>

If the kernel told us a metadata object could be optimized, we ask it to
do the optimization and it spits back that it doesn't support
optimizing, don't record this as an error since the fs is still
consistent.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 scrub/scrub.c |    7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)


diff --git a/scrub/scrub.c b/scrub/scrub.c
index c893f2c9..fe4e880f 100644
--- a/scrub/scrub.c
+++ b/scrub/scrub.c
@@ -782,10 +782,11 @@ _("Filesystem is shut down, aborting."));
 		case ENOTTY:
 		case EOPNOTSUPP:
 			/*
-			 * If we forced repairs, don't complain if kernel
-			 * doesn't know how to fix.
+			 * If we forced repairs or this is a preen, don't
+			 * error out if the kernel doesn't know how to fix.
 			 */
-			if (debug_tweak_on("XFS_SCRUB_FORCE_REPAIR"))
+			if (is_unoptimized(&oldm) ||
+			    debug_tweak_on("XFS_SCRUB_FORCE_REPAIR"))
 				return CHECK_DONE;
 			/* fall through */
 		case EINVAL:


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 07/10] xfs_scrub: rename NOFIX_COMPLAIN to be less confusing
  2018-06-27  2:47 [PATCH 00/10] xfsprogs-4.18: mostly scrub/repair stuff Darrick J. Wong
                   ` (5 preceding siblings ...)
  2018-06-27  2:48 ` [PATCH 06/10] xfs_scrub: don't error out if an optimize-only repair isn't supported Darrick J. Wong
@ 2018-06-27  2:48 ` Darrick J. Wong
  2018-07-26  1:10   ` Eric Sandeen
  2018-06-27  2:48 ` [PATCH 08/10] xfs_scrub: only retry non-permanent repair failures Darrick J. Wong
                   ` (4 subsequent siblings)
  11 siblings, 1 reply; 29+ messages in thread
From: Darrick J. Wong @ 2018-06-27  2:48 UTC (permalink / raw)
  To: sandeen, darrick.wong; +Cc: linux-xfs

From: Darrick J. Wong <darrick.wong@oracle.com>

Rename NOFIX_COMPLAIN to COMPLAIN_IF_UNFIXED so that the symbolic name
is less confusing as to what the flag is supposed to mean.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 scrub/phase4.c |    2 +-
 scrub/repair.h |    2 +-
 scrub/scrub.c  |    6 +++---
 scrub/scrub.h  |    2 +-
 4 files changed, 6 insertions(+), 6 deletions(-)


diff --git a/scrub/phase4.c b/scrub/phase4.c
index 01a073bc..7ae6b7cf 100644
--- a/scrub/phase4.c
+++ b/scrub/phase4.c
@@ -69,7 +69,7 @@ xfs_repair_ag(
 		return;
 
 	/* Try once more, but this time complain if we can't fix things. */
-	flags |= ALP_NOFIX_COMPLAIN;
+	flags |= ALP_COMPLAIN_IF_UNFIXED;
 	moveon = xfs_action_list_process(ctx, ctx->mnt_fd, alist, flags);
 	if (!moveon)
 		*pmoveon = false;
diff --git a/scrub/repair.h b/scrub/repair.h
index 4be950e7..c8693ccf 100644
--- a/scrub/repair.h
+++ b/scrub/repair.h
@@ -29,7 +29,7 @@ void xfs_action_list_find_mustfix(struct xfs_action_list *actions,
 
 /* Passed through to xfs_repair_metadata() */
 #define ALP_REPAIR_ONLY		(XRM_REPAIR_ONLY)
-#define ALP_NOFIX_COMPLAIN	(XRM_NOFIX_COMPLAIN)
+#define ALP_COMPLAIN_IF_UNFIXED	(XRM_COMPLAIN_IF_UNFIXED)
 #define ALP_NOPROGRESS		(1U << 31)
 
 bool xfs_action_list_process(struct scrub_ctx *ctx, int fd,
diff --git a/scrub/scrub.c b/scrub/scrub.c
index fe4e880f..2ac146a9 100644
--- a/scrub/scrub.c
+++ b/scrub/scrub.c
@@ -762,7 +762,7 @@ xfs_repair_metadata(
 	 * If the caller doesn't want us to complain, tell the caller to
 	 * requeue the repair for later and don't say a thing.
 	 */
-	if (!(repair_flags & XRM_NOFIX_COMPLAIN) &&
+	if (!(repair_flags & XRM_COMPLAIN_IF_UNFIXED) &&
 	    (error || needs_repair(&meta)))
 		return CHECK_RETRY;
 	if (error) {
@@ -815,11 +815,11 @@ _("Read-only filesystem; cannot make changes."));
 			return CHECK_DONE;
 		}
 	}
-	if (repair_flags & XRM_NOFIX_COMPLAIN)
+	if (repair_flags & XRM_COMPLAIN_IF_UNFIXED)
 		xfs_scrub_warn_incomplete_scrub(ctx, buf, &meta);
 	if (needs_repair(&meta)) {
 		/* Still broken, try again or fix offline. */
-		if ((repair_flags & XRM_NOFIX_COMPLAIN) || debug)
+		if ((repair_flags & XRM_COMPLAIN_IF_UNFIXED) || debug)
 			str_error(ctx, buf,
 _("Repair unsuccessful; offline repair required."));
 	} else {
diff --git a/scrub/scrub.h b/scrub/scrub.h
index fdcbd40d..701a01ae 100644
--- a/scrub/scrub.h
+++ b/scrub/scrub.h
@@ -86,7 +86,7 @@ struct action_item {
 #define XRM_REPAIR_ONLY		(1U << 0)
 
 /* Complain if still broken even after fix. */
-#define XRM_NOFIX_COMPLAIN	(1U << 1)
+#define XRM_COMPLAIN_IF_UNFIXED	(1U << 1)
 
 enum check_outcome xfs_repair_metadata(struct scrub_ctx *ctx, int fd,
 		struct action_item *aitem, unsigned int repair_flags);


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 08/10] xfs_scrub: only retry non-permanent repair failures
  2018-06-27  2:47 [PATCH 00/10] xfsprogs-4.18: mostly scrub/repair stuff Darrick J. Wong
                   ` (6 preceding siblings ...)
  2018-06-27  2:48 ` [PATCH 07/10] xfs_scrub: rename NOFIX_COMPLAIN to be less confusing Darrick J. Wong
@ 2018-06-27  2:48 ` Darrick J. Wong
  2018-07-26  1:16   ` Eric Sandeen
  2018-06-27  2:48 ` [PATCH 09/10] xfs_io: wire up repair ioctl stuff Darrick J. Wong
                   ` (3 subsequent siblings)
  11 siblings, 1 reply; 29+ messages in thread
From: Darrick J. Wong @ 2018-06-27  2:48 UTC (permalink / raw)
  To: sandeen, darrick.wong; +Cc: linux-xfs

From: Darrick J. Wong <darrick.wong@oracle.com>

If a repair fails, we want to retry the repair if the error was a
transient one, such as ENOMEM.  For "permanent" ones (shutdown fs,
repair not supported by kernel, readonly fs) there's no point to
retrying them so just error out immediately.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 scrub/scrub.c |   37 ++++++++++++++++++++++++++-----------
 1 file changed, 26 insertions(+), 11 deletions(-)


diff --git a/scrub/scrub.c b/scrub/scrub.c
index 2ac146a9..b20c1cbe 100644
--- a/scrub/scrub.c
+++ b/scrub/scrub.c
@@ -758,13 +758,6 @@ xfs_repair_metadata(
 		str_info(ctx, buf, _("Attempting optimization."));
 
 	error = ioctl(fd, XFS_IOC_SCRUB_METADATA, &meta);
-	/*
-	 * If the caller doesn't want us to complain, tell the caller to
-	 * requeue the repair for later and don't say a thing.
-	 */
-	if (!(repair_flags & XRM_COMPLAIN_IF_UNFIXED) &&
-	    (error || needs_repair(&meta)))
-		return CHECK_RETRY;
 	if (error) {
 		switch (errno) {
 		case EDEADLOCK:
@@ -781,6 +774,16 @@ _("Filesystem is shut down, aborting."));
 			return CHECK_ABORT;
 		case ENOTTY:
 		case EOPNOTSUPP:
+			/*
+			 * If we're in no-complain mode, requeue the check for
+			 * later.  It's possible that an error in another
+			 * component caused us to flag an error in this
+			 * component.  Even if the kernel didn't think it
+			 * could fix this, it's at least worth trying the scan
+			 * again to see if another repair fixed it.
+			 */
+			if (!(repair_flags & XRM_COMPLAIN_IF_UNFIXED))
+				return CHECK_RETRY;
 			/*
 			 * If we forced repairs or this is a preen, don't
 			 * error out if the kernel doesn't know how to fix.
@@ -810,7 +813,14 @@ _("Read-only filesystem; cannot make changes."));
 				return CHECK_DONE;
 			/* fall through */
 		default:
-			/* Operational error. */
+			/*
+			 * Operational error.  If the caller doesn't want us
+			 * to complain about repair failures, tell the caller
+			 * to requeue the repair for later and don't say a
+			 * thing.  Otherwise, print error and bail out.
+			 */
+			if (!(repair_flags & XRM_COMPLAIN_IF_UNFIXED))
+				return CHECK_RETRY;
 			str_errno(ctx, buf);
 			return CHECK_DONE;
 		}
@@ -818,9 +828,14 @@ _("Read-only filesystem; cannot make changes."));
 	if (repair_flags & XRM_COMPLAIN_IF_UNFIXED)
 		xfs_scrub_warn_incomplete_scrub(ctx, buf, &meta);
 	if (needs_repair(&meta)) {
-		/* Still broken, try again or fix offline. */
-		if ((repair_flags & XRM_COMPLAIN_IF_UNFIXED) || debug)
-			str_error(ctx, buf,
+		/*
+		 * Still broken; if we've been told not to complain then we
+		 * just requeue this and try again later.  Otherwise we
+		 * log the error loudly and don't try again.
+		 */
+		if (!(repair_flags & XRM_COMPLAIN_IF_UNFIXED))
+			return CHECK_RETRY;
+		str_error(ctx, buf,
 _("Repair unsuccessful; offline repair required."));
 	} else {
 		/* Clean metadata, no corruption remains. */


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 09/10] xfs_io: wire up repair ioctl stuff
  2018-06-27  2:47 [PATCH 00/10] xfsprogs-4.18: mostly scrub/repair stuff Darrick J. Wong
                   ` (7 preceding siblings ...)
  2018-06-27  2:48 ` [PATCH 08/10] xfs_scrub: only retry non-permanent repair failures Darrick J. Wong
@ 2018-06-27  2:48 ` Darrick J. Wong
  2018-07-26  1:23   ` Eric Sandeen
  2018-06-27  2:48 ` [PATCH 10/10] xfs_repair: use libxfs extsize/cowextsize validation helpers Darrick J. Wong
                   ` (2 subsequent siblings)
  11 siblings, 1 reply; 29+ messages in thread
From: Darrick J. Wong @ 2018-06-27  2:48 UTC (permalink / raw)
  To: sandeen, darrick.wong; +Cc: linux-xfs

From: Darrick J. Wong <darrick.wong@oracle.com>

Wire up the repair ioctl (which is really the scrub ioctl with special
flags) and the force-repair error injection point.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 io/init.c         |    1 +
 io/io.h           |    1 +
 io/scrub.c        |   97 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 man/man8/xfs_io.8 |    8 ++++
 4 files changed, 107 insertions(+)


diff --git a/io/init.c b/io/init.c
index 3f637e5a..a65f81d6 100644
--- a/io/init.c
+++ b/io/init.c
@@ -85,6 +85,7 @@ init_commands(void)
 	quit_init();
 	readdir_init();
 	reflink_init();
+	repair_init();
 	resblks_init();
 	scrub_init();
 	seek_init();
diff --git a/io/io.h b/io/io.h
index fa0cdff7..ab217789 100644
--- a/io/io.h
+++ b/io/io.h
@@ -198,3 +198,4 @@ extern void		log_writes_init(void);
 #endif
 
 extern void		scrub_init(void);
+extern void		repair_init(void);
diff --git a/io/scrub.c b/io/scrub.c
index 75a8ff15..c2c08e6b 100644
--- a/io/scrub.c
+++ b/io/scrub.c
@@ -26,6 +26,7 @@
 #include "io.h"
 
 static struct cmdinfo scrub_cmd;
+static struct cmdinfo repair_cmd;
 
 /* Type info and names for the scrub types. */
 enum scrub_type {
@@ -249,3 +250,99 @@ scrub_init(void)
 
 	add_command(&scrub_cmd);
 }
+
+static void
+repair_help(void)
+{
+	const struct scrub_descr	*d;
+	int				i;
+
+	printf(_(
+"\n"
+" Repairs a piece of XFS filesystem metadata.  The first argument is the type\n"
+" of metadata to examine.  Allocation group metadata types take one AG number\n"
+" as the second parameter.  Inode metadata types act on the currently open file\n"
+" or (optionally) take an inode number and generation number to act upon as\n"
+" the second and third parameters.\n"
+"\n"
+" Example:\n"
+" 'repair inobt 3' - repairs the inode btree in AG 3.\n"
+" 'repair bmapbtd 128 13525' - repairs the extent map of inode 128 gen 13525.\n"
+"\n"
+" Known metadata repairs types are:"));
+	for (i = 0, d = scrubbers; i < XFS_SCRUB_TYPE_NR; i++, d++)
+		printf(" %s", d->name);
+	printf("\n");
+}
+
+static void
+repair_ioctl(
+	int				fd,
+	int				type,
+	uint64_t			control,
+	uint32_t			control2)
+{
+	struct xfs_scrub_metadata	meta;
+	const struct scrub_descr	*sc;
+	int				error;
+
+	sc = &scrubbers[type];
+	memset(&meta, 0, sizeof(meta));
+	meta.sm_type = type;
+	switch (sc->type) {
+	case ST_PERAG:
+		meta.sm_agno = control;
+		break;
+	case ST_INODE:
+		meta.sm_ino = control;
+		meta.sm_gen = control2;
+		break;
+	case ST_NONE:
+	case ST_FS:
+		/* no control parameters */
+		break;
+	}
+	meta.sm_flags = XFS_SCRUB_IFLAG_REPAIR;
+
+	error = ioctl(fd, XFS_IOC_SCRUB_METADATA, &meta);
+	if (error)
+		perror("scrub");
+	if (meta.sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
+		printf(_("Corruption remains.\n"));
+	if (meta.sm_flags & XFS_SCRUB_OFLAG_PREEN)
+		printf(_("Optimization possible.\n"));
+	if (meta.sm_flags & XFS_SCRUB_OFLAG_XFAIL)
+		printf(_("Cross-referencing failed.\n"));
+	if (meta.sm_flags & XFS_SCRUB_OFLAG_XCORRUPT)
+		printf(_("Corruption still detected during cross-referencing.\n"));
+	if (meta.sm_flags & XFS_SCRUB_OFLAG_INCOMPLETE)
+		printf(_("Repair was not complete.\n"));
+	if (meta.sm_flags & XFS_SCRUB_OFLAG_NO_REPAIR_NEEDED)
+		printf(_("Metadata did not need repair or optimization.\n"));
+}
+
+static int
+repair_f(
+	int				argc,
+	char				**argv)
+{
+	return parse_args(argc, argv, &repair_cmd, repair_ioctl);
+}
+
+void
+repair_init(void)
+{
+	if (!expert)
+		return;
+	repair_cmd.name = "repair";
+	repair_cmd.altname = "fix";
+	repair_cmd.cfunc = repair_f;
+	repair_cmd.argmin = 1;
+	repair_cmd.argmax = -1;
+	repair_cmd.flags = CMD_NOMAP_OK;
+	repair_cmd.args = _("type [agno|ino gen]");
+	repair_cmd.oneline = _("repairs filesystem metadata");
+	repair_cmd.help = repair_help;
+
+	add_command(&repair_cmd);
+}
diff --git a/man/man8/xfs_io.8 b/man/man8/xfs_io.8
index dd91589b..60f7a21c 100644
--- a/man/man8/xfs_io.8
+++ b/man/man8/xfs_io.8
@@ -1167,6 +1167,14 @@ inode number and generation number are specified.
 .RE
 .PD
 .TP
+.BI "repair " type " [ " agnumber " | " "ino" " " "gen" " ]"
+Repair internal XFS filesystem metadata.  The
+.BI type
+parameter specifies which type of metadata to repair.
+For AG metadata, one AG number must be specified.
+For file metadata, the repair is applied to the open file unless the
+inode number and generation number are specified.
+.TP
 .BI "log_writes \-d " device " \-m "  mark
 Create a mark named
 .I mark


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 10/10] xfs_repair: use libxfs extsize/cowextsize validation helpers
  2018-06-27  2:47 [PATCH 00/10] xfsprogs-4.18: mostly scrub/repair stuff Darrick J. Wong
                   ` (8 preceding siblings ...)
  2018-06-27  2:48 ` [PATCH 09/10] xfs_io: wire up repair ioctl stuff Darrick J. Wong
@ 2018-06-27  2:48 ` Darrick J. Wong
  2018-06-27  3:25   ` Eric Sandeen
  2018-06-28 17:29 ` [PATCH 11/10] xfs_repair: clear extent size hints when clearing inode core Darrick J. Wong
  2018-06-28 17:30 ` [PATCH 12/10] xfs_repair: use libxfs extsize/cowextsize validation helpers Darrick J. Wong
  11 siblings, 1 reply; 29+ messages in thread
From: Darrick J. Wong @ 2018-06-27  2:48 UTC (permalink / raw)
  To: sandeen, darrick.wong; +Cc: linux-xfs

From: Darrick J. Wong <darrick.wong@oracle.com>

Now that we've ported the extent size hint verifiers to libxfs, call
them from xfs_repair instead of open-coding the checks.  Tweak the
repair message slightly to reflect the fact that we zero the field and
clear the inode flag if the hint is garbage or is inconsistent with the
inode flags.  Also clear the extent size hints when we're zapping the
inode core since we clear the associated flags.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 libxfs/libxfs_api_defs.h |    2 +
 repair/dinode.c          |   85 +++++++++++++++++++---------------------------
 2 files changed, 38 insertions(+), 49 deletions(-)


diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h
index e5cf1554..fe8336ab 100644
--- a/libxfs/libxfs_api_defs.h
+++ b/libxfs/libxfs_api_defs.h
@@ -98,6 +98,8 @@
 #define xfs_dinode_calc_crc		libxfs_dinode_calc_crc
 #define xfs_idata_realloc		libxfs_idata_realloc
 #define xfs_idestroy_fork		libxfs_idestroy_fork
+#define xfs_inode_validate_extsize	libxfs_inode_validate_extsize
+#define xfs_inode_validate_cowextsize	libxfs_inode_validate_cowextsize
 
 #define xfs_rmap_ag_owner		libxfs_rmap_ag_owner
 #define xfs_rmap_alloc			libxfs_rmap_alloc
diff --git a/repair/dinode.c b/repair/dinode.c
index f9b2bac0..14c055bd 100644
--- a/repair/dinode.c
+++ b/repair/dinode.c
@@ -194,6 +194,11 @@ clear_dinode_core(struct xfs_mount *mp, xfs_dinode_t *dinoc, xfs_ino_t ino_num)
 		dinoc->di_anextents = 0;
 	}
 
+	if (be32_to_cpu(dinoc->di_extsize) != 0)  {
+		__dirty_no_modify_ret(dirty);
+		dinoc->di_extsize = 0;
+	}
+
 	if (dinoc->di_version > 1 &&
 			be32_to_cpu(dinoc->di_nlink) != 0)  {
 		__dirty_no_modify_ret(dirty);
@@ -237,6 +242,11 @@ clear_dinode_core(struct xfs_mount *mp, xfs_dinode_t *dinoc, xfs_ino_t ino_num)
 		dinoc->di_changecount = 0;
 	}
 
+	if (be32_to_cpu(dinoc->di_cowextsize) != 0)  {
+		__dirty_no_modify_ret(dirty);
+		dinoc->di_cowextsize = 0;
+	}
+
 	return dirty;
 }
 
@@ -2843,24 +2853,21 @@ _("bad (negative) size %" PRId64 " on inode %" PRIu64 "\n"),
 	 * only regular files with REALTIME or EXTSIZE flags set can have
 	 * extsize set, or directories with EXTSZINHERIT.
 	 */
-	if (be32_to_cpu(dino->di_extsize) != 0) {
-		if ((type == XR_INO_RTDATA) ||
-		    (type == XR_INO_DIR && (be16_to_cpu(dino->di_flags) &
-					XFS_DIFLAG_EXTSZINHERIT)) ||
-		    (type == XR_INO_DATA && (be16_to_cpu(dino->di_flags) &
-				 XFS_DIFLAG_EXTSIZE)))  {
-			/* s'okay */ ;
-		} else {
-			do_warn(
-_("bad non-zero extent size %u for non-realtime/extsize inode %" PRIu64 ", "),
-					be32_to_cpu(dino->di_extsize), lino);
-			if (!no_modify)  {
-				do_warn(_("resetting to zero\n"));
-				dino->di_extsize = 0;
-				*dirty = 1;
-			} else
-				do_warn(_("would reset to zero\n"));
-		}
+	if (libxfs_inode_validate_extsize(mp,
+			be32_to_cpu(dino->di_extsize),
+			be16_to_cpu(dino->di_mode),
+			be16_to_cpu(dino->di_flags)) != NULL) {
+		do_warn(
+_("Bad extent size %u for non-realtime/extsize inode %" PRIu64 ", "),
+				be32_to_cpu(dino->di_extsize), lino);
+		if (!no_modify)  {
+			do_warn(_("resetting to zero\n"));
+			dino->di_extsize = 0;
+			dino->di_flags &= ~cpu_to_be16(XFS_DIFLAG_EXTSIZE |
+						       XFS_DIFLAG_EXTSZINHERIT);
+			*dirty = 1;
+		} else
+			do_warn(_("would reset to zero\n"));
 	}
 
 	/*
@@ -2868,41 +2875,21 @@ _("bad non-zero extent size %u for non-realtime/extsize inode %" PRIu64 ", "),
 	 * set can have extsize set.
 	 */
 	if (dino->di_version >= 3 &&
-	    be32_to_cpu(dino->di_cowextsize) != 0) {
-		if ((type == XR_INO_DIR || type == XR_INO_DATA) &&
-		    (be64_to_cpu(dino->di_flags2) &
-					XFS_DIFLAG2_COWEXTSIZE)) {
-			/* s'okay */ ;
-		} else {
-			do_warn(
-_("Cannot have non-zero CoW extent size %u on non-cowextsize inode %" PRIu64 ", "),
-					be32_to_cpu(dino->di_cowextsize), lino);
-			if (!no_modify)  {
-				do_warn(_("resetting to zero\n"));
-				dino->di_flags2 &= ~cpu_to_be64(XFS_DIFLAG2_COWEXTSIZE);
-				dino->di_cowextsize = 0;
-				*dirty = 1;
-			} else
-				do_warn(_("would reset to zero\n"));
-		}
-	}
-
-	/*
-	 * Can't have the COWEXTSIZE flag set with no hint.
-	 */
-	if (dino->di_version >= 3 &&
-	    be32_to_cpu(dino->di_cowextsize) == 0 &&
-	    (be64_to_cpu(dino->di_flags2) & XFS_DIFLAG2_COWEXTSIZE)) {
+	    libxfs_inode_validate_cowextsize(mp,
+			be32_to_cpu(dino->di_cowextsize),
+			be16_to_cpu(dino->di_mode),
+			be16_to_cpu(dino->di_flags),
+			be64_to_cpu(dino->di_flags2)) != NULL) {
 		do_warn(
-_("Cannot have CoW extent size of zero on cowextsize inode %" PRIu64 ", "),
-				lino);
+_("Bad CoW extent size %u on non-cowextsize inode %" PRIu64 ", "),
+				be32_to_cpu(dino->di_cowextsize), lino);
 		if (!no_modify)  {
-			do_warn(_("clearing cowextsize flag\n"));
+			do_warn(_("resetting to zero\n"));
 			dino->di_flags2 &= ~cpu_to_be64(XFS_DIFLAG2_COWEXTSIZE);
+			dino->di_cowextsize = 0;
 			*dirty = 1;
-		} else {
-			do_warn(_("would clear cowextsize flag\n"));
-		}
+		} else
+			do_warn(_("would reset to zero\n"));
 	}
 
 	/* nsec fields cannot be larger than 1 billion */


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* Re: [PATCH 10/10] xfs_repair: use libxfs extsize/cowextsize validation helpers
  2018-06-27  2:48 ` [PATCH 10/10] xfs_repair: use libxfs extsize/cowextsize validation helpers Darrick J. Wong
@ 2018-06-27  3:25   ` Eric Sandeen
  2018-06-28 17:28     ` Darrick J. Wong
  0 siblings, 1 reply; 29+ messages in thread
From: Eric Sandeen @ 2018-06-27  3:25 UTC (permalink / raw)
  To: Darrick J. Wong, sandeen; +Cc: linux-xfs

On 6/26/18 9:48 PM, Darrick J. Wong wrote:
> From: Darrick J. Wong <darrick.wong@oracle.com>
> 
> Now that we've ported the extent size hint verifiers to libxfs, call

*almost* ;)

> them from xfs_repair instead of open-coding the checks.

*nod*

> Tweak the
> repair message slightly to reflect the fact that we zero the field and
> clear the inode flag if the hint is garbage or is inconsistent with the
> inode flags.  Also clear the extent size hints when we're zapping the
> inode core since we clear the associated flags.

So for that last clause, the fix to clear_dinode_core, I wonder if it should
be a separate patch, possibly even merged before the libxfs changes.

I guess I can't prove that it's an existing bug prior to adding the extent
size hints to the verifier, but it seems weird for clear_dinode_core to
/not/ clear the extent size hint, doesn't it?

The only advantage is we could avoid any regression point for xfs/033
(which is how I found this) if we fixed up clear_dinode_core, then
added the extent size hint validation to the verifier, and then taught
xfs_repair to use the new extent size hint validation function.

Does that seem worth it?

The patch all looks fine, just wondering if we should structure/sequence
the changes more nicely.

-Eric

> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
> ---
>  libxfs/libxfs_api_defs.h |    2 +
>  repair/dinode.c          |   85 +++++++++++++++++++---------------------------
>  2 files changed, 38 insertions(+), 49 deletions(-)
> 
> 
> diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h
> index e5cf1554..fe8336ab 100644
> --- a/libxfs/libxfs_api_defs.h
> +++ b/libxfs/libxfs_api_defs.h
> @@ -98,6 +98,8 @@
>  #define xfs_dinode_calc_crc		libxfs_dinode_calc_crc
>  #define xfs_idata_realloc		libxfs_idata_realloc
>  #define xfs_idestroy_fork		libxfs_idestroy_fork
> +#define xfs_inode_validate_extsize	libxfs_inode_validate_extsize
> +#define xfs_inode_validate_cowextsize	libxfs_inode_validate_cowextsize
>  
>  #define xfs_rmap_ag_owner		libxfs_rmap_ag_owner
>  #define xfs_rmap_alloc			libxfs_rmap_alloc
> diff --git a/repair/dinode.c b/repair/dinode.c
> index f9b2bac0..14c055bd 100644
> --- a/repair/dinode.c
> +++ b/repair/dinode.c
> @@ -194,6 +194,11 @@ clear_dinode_core(struct xfs_mount *mp, xfs_dinode_t *dinoc, xfs_ino_t ino_num)
>  		dinoc->di_anextents = 0;
>  	}
>  
> +	if (be32_to_cpu(dinoc->di_extsize) != 0)  {
> +		__dirty_no_modify_ret(dirty);
> +		dinoc->di_extsize = 0;
> +	}
> +
>  	if (dinoc->di_version > 1 &&
>  			be32_to_cpu(dinoc->di_nlink) != 0)  {
>  		__dirty_no_modify_ret(dirty);
> @@ -237,6 +242,11 @@ clear_dinode_core(struct xfs_mount *mp, xfs_dinode_t *dinoc, xfs_ino_t ino_num)
>  		dinoc->di_changecount = 0;
>  	}
>  
> +	if (be32_to_cpu(dinoc->di_cowextsize) != 0)  {
> +		__dirty_no_modify_ret(dirty);
> +		dinoc->di_cowextsize = 0;
> +	}
> +
>  	return dirty;
>  }
>  
> @@ -2843,24 +2853,21 @@ _("bad (negative) size %" PRId64 " on inode %" PRIu64 "\n"),
>  	 * only regular files with REALTIME or EXTSIZE flags set can have
>  	 * extsize set, or directories with EXTSZINHERIT.
>  	 */
> -	if (be32_to_cpu(dino->di_extsize) != 0) {
> -		if ((type == XR_INO_RTDATA) ||
> -		    (type == XR_INO_DIR && (be16_to_cpu(dino->di_flags) &
> -					XFS_DIFLAG_EXTSZINHERIT)) ||
> -		    (type == XR_INO_DATA && (be16_to_cpu(dino->di_flags) &
> -				 XFS_DIFLAG_EXTSIZE)))  {
> -			/* s'okay */ ;
> -		} else {
> -			do_warn(
> -_("bad non-zero extent size %u for non-realtime/extsize inode %" PRIu64 ", "),
> -					be32_to_cpu(dino->di_extsize), lino);
> -			if (!no_modify)  {
> -				do_warn(_("resetting to zero\n"));
> -				dino->di_extsize = 0;
> -				*dirty = 1;
> -			} else
> -				do_warn(_("would reset to zero\n"));
> -		}
> +	if (libxfs_inode_validate_extsize(mp,
> +			be32_to_cpu(dino->di_extsize),
> +			be16_to_cpu(dino->di_mode),
> +			be16_to_cpu(dino->di_flags)) != NULL) {
> +		do_warn(
> +_("Bad extent size %u for non-realtime/extsize inode %" PRIu64 ", "),
> +				be32_to_cpu(dino->di_extsize), lino);
> +		if (!no_modify)  {
> +			do_warn(_("resetting to zero\n"));
> +			dino->di_extsize = 0;
> +			dino->di_flags &= ~cpu_to_be16(XFS_DIFLAG_EXTSIZE |
> +						       XFS_DIFLAG_EXTSZINHERIT);
> +			*dirty = 1;
> +		} else
> +			do_warn(_("would reset to zero\n"));
>  	}
>  
>  	/*
> @@ -2868,41 +2875,21 @@ _("bad non-zero extent size %u for non-realtime/extsize inode %" PRIu64 ", "),
>  	 * set can have extsize set.
>  	 */
>  	if (dino->di_version >= 3 &&
> -	    be32_to_cpu(dino->di_cowextsize) != 0) {
> -		if ((type == XR_INO_DIR || type == XR_INO_DATA) &&
> -		    (be64_to_cpu(dino->di_flags2) &
> -					XFS_DIFLAG2_COWEXTSIZE)) {
> -			/* s'okay */ ;
> -		} else {
> -			do_warn(
> -_("Cannot have non-zero CoW extent size %u on non-cowextsize inode %" PRIu64 ", "),
> -					be32_to_cpu(dino->di_cowextsize), lino);
> -			if (!no_modify)  {
> -				do_warn(_("resetting to zero\n"));
> -				dino->di_flags2 &= ~cpu_to_be64(XFS_DIFLAG2_COWEXTSIZE);
> -				dino->di_cowextsize = 0;
> -				*dirty = 1;
> -			} else
> -				do_warn(_("would reset to zero\n"));
> -		}
> -	}
> -
> -	/*
> -	 * Can't have the COWEXTSIZE flag set with no hint.
> -	 */
> -	if (dino->di_version >= 3 &&
> -	    be32_to_cpu(dino->di_cowextsize) == 0 &&
> -	    (be64_to_cpu(dino->di_flags2) & XFS_DIFLAG2_COWEXTSIZE)) {
> +	    libxfs_inode_validate_cowextsize(mp,
> +			be32_to_cpu(dino->di_cowextsize),
> +			be16_to_cpu(dino->di_mode),
> +			be16_to_cpu(dino->di_flags),
> +			be64_to_cpu(dino->di_flags2)) != NULL) {
>  		do_warn(
> -_("Cannot have CoW extent size of zero on cowextsize inode %" PRIu64 ", "),
> -				lino);
> +_("Bad CoW extent size %u on non-cowextsize inode %" PRIu64 ", "),
> +				be32_to_cpu(dino->di_cowextsize), lino);
>  		if (!no_modify)  {
> -			do_warn(_("clearing cowextsize flag\n"));
> +			do_warn(_("resetting to zero\n"));
>  			dino->di_flags2 &= ~cpu_to_be64(XFS_DIFLAG2_COWEXTSIZE);
> +			dino->di_cowextsize = 0;
>  			*dirty = 1;
> -		} else {
> -			do_warn(_("would clear cowextsize flag\n"));
> -		}
> +		} else
> +			do_warn(_("would reset to zero\n"));
>  	}
>  
>  	/* nsec fields cannot be larger than 1 billion */
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH 10/10] xfs_repair: use libxfs extsize/cowextsize validation helpers
  2018-06-27  3:25   ` Eric Sandeen
@ 2018-06-28 17:28     ` Darrick J. Wong
  0 siblings, 0 replies; 29+ messages in thread
From: Darrick J. Wong @ 2018-06-28 17:28 UTC (permalink / raw)
  To: Eric Sandeen; +Cc: sandeen, linux-xfs

On Tue, Jun 26, 2018 at 10:25:54PM -0500, Eric Sandeen wrote:
> On 6/26/18 9:48 PM, Darrick J. Wong wrote:
> > From: Darrick J. Wong <darrick.wong@oracle.com>
> > 
> > Now that we've ported the extent size hint verifiers to libxfs, call
> 
> *almost* ;)
> 
> > them from xfs_repair instead of open-coding the checks.
> 
> *nod*
> 
> > Tweak the
> > repair message slightly to reflect the fact that we zero the field and
> > clear the inode flag if the hint is garbage or is inconsistent with the
> > inode flags.  Also clear the extent size hints when we're zapping the
> > inode core since we clear the associated flags.
> 
> So for that last clause, the fix to clear_dinode_core, I wonder if it should
> be a separate patch, possibly even merged before the libxfs changes.
> 
> I guess I can't prove that it's an existing bug prior to adding the extent
> size hints to the verifier, but it seems weird for clear_dinode_core to
> /not/ clear the extent size hint, doesn't it?
> 
> The only advantage is we could avoid any regression point for xfs/033
> (which is how I found this) if we fixed up clear_dinode_core, then
> added the extent size hint validation to the verifier, and then taught
> xfs_repair to use the new extent size hint validation function.
> 
> Does that seem worth it?
> 
> The patch all looks fine, just wondering if we should structure/sequence
> the changes more nicely.

Yes, we should.  I split this into two patches in my stgit tree and ...
forgot to move the hunk.

--D

> -Eric
> 
> > Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
> > ---
> >  libxfs/libxfs_api_defs.h |    2 +
> >  repair/dinode.c          |   85 +++++++++++++++++++---------------------------
> >  2 files changed, 38 insertions(+), 49 deletions(-)
> > 
> > 
> > diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h
> > index e5cf1554..fe8336ab 100644
> > --- a/libxfs/libxfs_api_defs.h
> > +++ b/libxfs/libxfs_api_defs.h
> > @@ -98,6 +98,8 @@
> >  #define xfs_dinode_calc_crc		libxfs_dinode_calc_crc
> >  #define xfs_idata_realloc		libxfs_idata_realloc
> >  #define xfs_idestroy_fork		libxfs_idestroy_fork
> > +#define xfs_inode_validate_extsize	libxfs_inode_validate_extsize
> > +#define xfs_inode_validate_cowextsize	libxfs_inode_validate_cowextsize
> >  
> >  #define xfs_rmap_ag_owner		libxfs_rmap_ag_owner
> >  #define xfs_rmap_alloc			libxfs_rmap_alloc
> > diff --git a/repair/dinode.c b/repair/dinode.c
> > index f9b2bac0..14c055bd 100644
> > --- a/repair/dinode.c
> > +++ b/repair/dinode.c
> > @@ -194,6 +194,11 @@ clear_dinode_core(struct xfs_mount *mp, xfs_dinode_t *dinoc, xfs_ino_t ino_num)
> >  		dinoc->di_anextents = 0;
> >  	}
> >  
> > +	if (be32_to_cpu(dinoc->di_extsize) != 0)  {
> > +		__dirty_no_modify_ret(dirty);
> > +		dinoc->di_extsize = 0;
> > +	}
> > +
> >  	if (dinoc->di_version > 1 &&
> >  			be32_to_cpu(dinoc->di_nlink) != 0)  {
> >  		__dirty_no_modify_ret(dirty);
> > @@ -237,6 +242,11 @@ clear_dinode_core(struct xfs_mount *mp, xfs_dinode_t *dinoc, xfs_ino_t ino_num)
> >  		dinoc->di_changecount = 0;
> >  	}
> >  
> > +	if (be32_to_cpu(dinoc->di_cowextsize) != 0)  {
> > +		__dirty_no_modify_ret(dirty);
> > +		dinoc->di_cowextsize = 0;
> > +	}
> > +
> >  	return dirty;
> >  }
> >  
> > @@ -2843,24 +2853,21 @@ _("bad (negative) size %" PRId64 " on inode %" PRIu64 "\n"),
> >  	 * only regular files with REALTIME or EXTSIZE flags set can have
> >  	 * extsize set, or directories with EXTSZINHERIT.
> >  	 */
> > -	if (be32_to_cpu(dino->di_extsize) != 0) {
> > -		if ((type == XR_INO_RTDATA) ||
> > -		    (type == XR_INO_DIR && (be16_to_cpu(dino->di_flags) &
> > -					XFS_DIFLAG_EXTSZINHERIT)) ||
> > -		    (type == XR_INO_DATA && (be16_to_cpu(dino->di_flags) &
> > -				 XFS_DIFLAG_EXTSIZE)))  {
> > -			/* s'okay */ ;
> > -		} else {
> > -			do_warn(
> > -_("bad non-zero extent size %u for non-realtime/extsize inode %" PRIu64 ", "),
> > -					be32_to_cpu(dino->di_extsize), lino);
> > -			if (!no_modify)  {
> > -				do_warn(_("resetting to zero\n"));
> > -				dino->di_extsize = 0;
> > -				*dirty = 1;
> > -			} else
> > -				do_warn(_("would reset to zero\n"));
> > -		}
> > +	if (libxfs_inode_validate_extsize(mp,
> > +			be32_to_cpu(dino->di_extsize),
> > +			be16_to_cpu(dino->di_mode),
> > +			be16_to_cpu(dino->di_flags)) != NULL) {
> > +		do_warn(
> > +_("Bad extent size %u for non-realtime/extsize inode %" PRIu64 ", "),
> > +				be32_to_cpu(dino->di_extsize), lino);
> > +		if (!no_modify)  {
> > +			do_warn(_("resetting to zero\n"));
> > +			dino->di_extsize = 0;
> > +			dino->di_flags &= ~cpu_to_be16(XFS_DIFLAG_EXTSIZE |
> > +						       XFS_DIFLAG_EXTSZINHERIT);
> > +			*dirty = 1;
> > +		} else
> > +			do_warn(_("would reset to zero\n"));
> >  	}
> >  
> >  	/*
> > @@ -2868,41 +2875,21 @@ _("bad non-zero extent size %u for non-realtime/extsize inode %" PRIu64 ", "),
> >  	 * set can have extsize set.
> >  	 */
> >  	if (dino->di_version >= 3 &&
> > -	    be32_to_cpu(dino->di_cowextsize) != 0) {
> > -		if ((type == XR_INO_DIR || type == XR_INO_DATA) &&
> > -		    (be64_to_cpu(dino->di_flags2) &
> > -					XFS_DIFLAG2_COWEXTSIZE)) {
> > -			/* s'okay */ ;
> > -		} else {
> > -			do_warn(
> > -_("Cannot have non-zero CoW extent size %u on non-cowextsize inode %" PRIu64 ", "),
> > -					be32_to_cpu(dino->di_cowextsize), lino);
> > -			if (!no_modify)  {
> > -				do_warn(_("resetting to zero\n"));
> > -				dino->di_flags2 &= ~cpu_to_be64(XFS_DIFLAG2_COWEXTSIZE);
> > -				dino->di_cowextsize = 0;
> > -				*dirty = 1;
> > -			} else
> > -				do_warn(_("would reset to zero\n"));
> > -		}
> > -	}
> > -
> > -	/*
> > -	 * Can't have the COWEXTSIZE flag set with no hint.
> > -	 */
> > -	if (dino->di_version >= 3 &&
> > -	    be32_to_cpu(dino->di_cowextsize) == 0 &&
> > -	    (be64_to_cpu(dino->di_flags2) & XFS_DIFLAG2_COWEXTSIZE)) {
> > +	    libxfs_inode_validate_cowextsize(mp,
> > +			be32_to_cpu(dino->di_cowextsize),
> > +			be16_to_cpu(dino->di_mode),
> > +			be16_to_cpu(dino->di_flags),
> > +			be64_to_cpu(dino->di_flags2)) != NULL) {
> >  		do_warn(
> > -_("Cannot have CoW extent size of zero on cowextsize inode %" PRIu64 ", "),
> > -				lino);
> > +_("Bad CoW extent size %u on non-cowextsize inode %" PRIu64 ", "),
> > +				be32_to_cpu(dino->di_cowextsize), lino);
> >  		if (!no_modify)  {
> > -			do_warn(_("clearing cowextsize flag\n"));
> > +			do_warn(_("resetting to zero\n"));
> >  			dino->di_flags2 &= ~cpu_to_be64(XFS_DIFLAG2_COWEXTSIZE);
> > +			dino->di_cowextsize = 0;
> >  			*dirty = 1;
> > -		} else {
> > -			do_warn(_("would clear cowextsize flag\n"));
> > -		}
> > +		} else
> > +			do_warn(_("would reset to zero\n"));
> >  	}
> >  
> >  	/* nsec fields cannot be larger than 1 billion */
> > 
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> > 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [PATCH 11/10] xfs_repair: clear extent size hints when clearing inode core
  2018-06-27  2:47 [PATCH 00/10] xfsprogs-4.18: mostly scrub/repair stuff Darrick J. Wong
                   ` (9 preceding siblings ...)
  2018-06-27  2:48 ` [PATCH 10/10] xfs_repair: use libxfs extsize/cowextsize validation helpers Darrick J. Wong
@ 2018-06-28 17:29 ` Darrick J. Wong
  2018-06-28 19:24   ` Eric Sandeen
  2018-06-28 17:30 ` [PATCH 12/10] xfs_repair: use libxfs extsize/cowextsize validation helpers Darrick J. Wong
  11 siblings, 1 reply; 29+ messages in thread
From: Darrick J. Wong @ 2018-06-28 17:29 UTC (permalink / raw)
  To: sandeen; +Cc: linux-xfs

From: Darrick J. Wong <darrick.wong@oracle.com>

In kernel 4.18 we become more strict about what can be in the extent
size hint fields, even for freed inodes.  Therefore, if repair decides
to clear out an inode core, zero the hint fields and clear the flags so
that the kernel won't trip over the cleared inode if and when it tries
to read the chunk.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 repair/dinode.c |   10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/repair/dinode.c b/repair/dinode.c
index f9b2bac0..4118db7c 100644
--- a/repair/dinode.c
+++ b/repair/dinode.c
@@ -194,6 +194,11 @@ clear_dinode_core(struct xfs_mount *mp, xfs_dinode_t *dinoc, xfs_ino_t ino_num)
 		dinoc->di_anextents = 0;
 	}
 
+	if (be32_to_cpu(dinoc->di_extsize) != 0)  {
+		__dirty_no_modify_ret(dirty);
+		dinoc->di_extsize = 0;
+	}
+
 	if (dinoc->di_version > 1 &&
 			be32_to_cpu(dinoc->di_nlink) != 0)  {
 		__dirty_no_modify_ret(dirty);
@@ -237,6 +242,11 @@ clear_dinode_core(struct xfs_mount *mp, xfs_dinode_t *dinoc, xfs_ino_t ino_num)
 		dinoc->di_changecount = 0;
 	}
 
+	if (be32_to_cpu(dinoc->di_cowextsize) != 0)  {
+		__dirty_no_modify_ret(dirty);
+		dinoc->di_cowextsize = 0;
+	}
+
 	return dirty;
 }
 

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 12/10] xfs_repair: use libxfs extsize/cowextsize validation helpers
  2018-06-27  2:47 [PATCH 00/10] xfsprogs-4.18: mostly scrub/repair stuff Darrick J. Wong
                   ` (10 preceding siblings ...)
  2018-06-28 17:29 ` [PATCH 11/10] xfs_repair: clear extent size hints when clearing inode core Darrick J. Wong
@ 2018-06-28 17:30 ` Darrick J. Wong
  2018-07-26  1:44   ` Eric Sandeen
  2018-07-26 20:38   ` [PATCH v2 " Darrick J. Wong
  11 siblings, 2 replies; 29+ messages in thread
From: Darrick J. Wong @ 2018-06-28 17:30 UTC (permalink / raw)
  To: sandeen; +Cc: linux-xfs

From: Darrick J. Wong <darrick.wong@oracle.com>

Now that we've ported the extent size hint verifiers to libxfs, call
them from xfs_repair instead of open-coding the checks.  Tweak the
repair message slightly to reflect the fact that we zero the field and
clear the inode flag if the hint is garbage or is inconsistent with the
inode flags.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 libxfs/libxfs_api_defs.h |    2 +
 repair/dinode.c          |   75 ++++++++++++++++------------------------------
 2 files changed, 28 insertions(+), 49 deletions(-)

diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h
index e5cf1554..fe8336ab 100644
--- a/libxfs/libxfs_api_defs.h
+++ b/libxfs/libxfs_api_defs.h
@@ -98,6 +98,8 @@
 #define xfs_dinode_calc_crc		libxfs_dinode_calc_crc
 #define xfs_idata_realloc		libxfs_idata_realloc
 #define xfs_idestroy_fork		libxfs_idestroy_fork
+#define xfs_inode_validate_extsize	libxfs_inode_validate_extsize
+#define xfs_inode_validate_cowextsize	libxfs_inode_validate_cowextsize
 
 #define xfs_rmap_ag_owner		libxfs_rmap_ag_owner
 #define xfs_rmap_alloc			libxfs_rmap_alloc
diff --git a/repair/dinode.c b/repair/dinode.c
index 4118db7c..14c055bd 100644
--- a/repair/dinode.c
+++ b/repair/dinode.c
@@ -2853,24 +2853,21 @@ _("bad (negative) size %" PRId64 " on inode %" PRIu64 "\n"),
 	 * only regular files with REALTIME or EXTSIZE flags set can have
 	 * extsize set, or directories with EXTSZINHERIT.
 	 */
-	if (be32_to_cpu(dino->di_extsize) != 0) {
-		if ((type == XR_INO_RTDATA) ||
-		    (type == XR_INO_DIR && (be16_to_cpu(dino->di_flags) &
-					XFS_DIFLAG_EXTSZINHERIT)) ||
-		    (type == XR_INO_DATA && (be16_to_cpu(dino->di_flags) &
-				 XFS_DIFLAG_EXTSIZE)))  {
-			/* s'okay */ ;
-		} else {
-			do_warn(
-_("bad non-zero extent size %u for non-realtime/extsize inode %" PRIu64 ", "),
-					be32_to_cpu(dino->di_extsize), lino);
-			if (!no_modify)  {
-				do_warn(_("resetting to zero\n"));
-				dino->di_extsize = 0;
-				*dirty = 1;
-			} else
-				do_warn(_("would reset to zero\n"));
-		}
+	if (libxfs_inode_validate_extsize(mp,
+			be32_to_cpu(dino->di_extsize),
+			be16_to_cpu(dino->di_mode),
+			be16_to_cpu(dino->di_flags)) != NULL) {
+		do_warn(
+_("Bad extent size %u for non-realtime/extsize inode %" PRIu64 ", "),
+				be32_to_cpu(dino->di_extsize), lino);
+		if (!no_modify)  {
+			do_warn(_("resetting to zero\n"));
+			dino->di_extsize = 0;
+			dino->di_flags &= ~cpu_to_be16(XFS_DIFLAG_EXTSIZE |
+						       XFS_DIFLAG_EXTSZINHERIT);
+			*dirty = 1;
+		} else
+			do_warn(_("would reset to zero\n"));
 	}
 
 	/*
@@ -2878,41 +2875,21 @@ _("bad non-zero extent size %u for non-realtime/extsize inode %" PRIu64 ", "),
 	 * set can have extsize set.
 	 */
 	if (dino->di_version >= 3 &&
-	    be32_to_cpu(dino->di_cowextsize) != 0) {
-		if ((type == XR_INO_DIR || type == XR_INO_DATA) &&
-		    (be64_to_cpu(dino->di_flags2) &
-					XFS_DIFLAG2_COWEXTSIZE)) {
-			/* s'okay */ ;
-		} else {
-			do_warn(
-_("Cannot have non-zero CoW extent size %u on non-cowextsize inode %" PRIu64 ", "),
-					be32_to_cpu(dino->di_cowextsize), lino);
-			if (!no_modify)  {
-				do_warn(_("resetting to zero\n"));
-				dino->di_flags2 &= ~cpu_to_be64(XFS_DIFLAG2_COWEXTSIZE);
-				dino->di_cowextsize = 0;
-				*dirty = 1;
-			} else
-				do_warn(_("would reset to zero\n"));
-		}
-	}
-
-	/*
-	 * Can't have the COWEXTSIZE flag set with no hint.
-	 */
-	if (dino->di_version >= 3 &&
-	    be32_to_cpu(dino->di_cowextsize) == 0 &&
-	    (be64_to_cpu(dino->di_flags2) & XFS_DIFLAG2_COWEXTSIZE)) {
+	    libxfs_inode_validate_cowextsize(mp,
+			be32_to_cpu(dino->di_cowextsize),
+			be16_to_cpu(dino->di_mode),
+			be16_to_cpu(dino->di_flags),
+			be64_to_cpu(dino->di_flags2)) != NULL) {
 		do_warn(
-_("Cannot have CoW extent size of zero on cowextsize inode %" PRIu64 ", "),
-				lino);
+_("Bad CoW extent size %u on non-cowextsize inode %" PRIu64 ", "),
+				be32_to_cpu(dino->di_cowextsize), lino);
 		if (!no_modify)  {
-			do_warn(_("clearing cowextsize flag\n"));
+			do_warn(_("resetting to zero\n"));
 			dino->di_flags2 &= ~cpu_to_be64(XFS_DIFLAG2_COWEXTSIZE);
+			dino->di_cowextsize = 0;
 			*dirty = 1;
-		} else {
-			do_warn(_("would clear cowextsize flag\n"));
-		}
+		} else
+			do_warn(_("would reset to zero\n"));
 	}
 
 	/* nsec fields cannot be larger than 1 billion */

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* Re: [PATCH 11/10] xfs_repair: clear extent size hints when clearing inode core
  2018-06-28 17:29 ` [PATCH 11/10] xfs_repair: clear extent size hints when clearing inode core Darrick J. Wong
@ 2018-06-28 19:24   ` Eric Sandeen
  0 siblings, 0 replies; 29+ messages in thread
From: Eric Sandeen @ 2018-06-28 19:24 UTC (permalink / raw)
  To: Darrick J. Wong, sandeen; +Cc: linux-xfs

On 6/28/18 12:29 PM, Darrick J. Wong wrote:
> From: Darrick J. Wong <darrick.wong@oracle.com>
> 
> In kernel 4.18 we become more strict about what can be in the extent
> size hint fields, even for freed inodes.  Therefore, if repair decides
> to clear out an inode core, zero the hint fields and clear the flags so
> that the kernel won't trip over the cleared inode if and when it tries
> to read the chunk.
> 
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>

Looks good, I'll merge this before the libxfs sync.  Thanks!

Reviewed-by: Eric Sandeen <sandeen@redhat.com>

> ---
>  repair/dinode.c |   10 ++++++++++
>  1 file changed, 10 insertions(+)
> 
> diff --git a/repair/dinode.c b/repair/dinode.c
> index f9b2bac0..4118db7c 100644
> --- a/repair/dinode.c
> +++ b/repair/dinode.c
> @@ -194,6 +194,11 @@ clear_dinode_core(struct xfs_mount *mp, xfs_dinode_t *dinoc, xfs_ino_t ino_num)
>  		dinoc->di_anextents = 0;
>  	}
>  
> +	if (be32_to_cpu(dinoc->di_extsize) != 0)  {
> +		__dirty_no_modify_ret(dirty);
> +		dinoc->di_extsize = 0;
> +	}
> +
>  	if (dinoc->di_version > 1 &&
>  			be32_to_cpu(dinoc->di_nlink) != 0)  {
>  		__dirty_no_modify_ret(dirty);
> @@ -237,6 +242,11 @@ clear_dinode_core(struct xfs_mount *mp, xfs_dinode_t *dinoc, xfs_ino_t ino_num)
>  		dinoc->di_changecount = 0;
>  	}
>  
> +	if (be32_to_cpu(dinoc->di_cowextsize) != 0)  {
> +		__dirty_no_modify_ret(dirty);
> +		dinoc->di_cowextsize = 0;
> +	}
> +
>  	return dirty;
>  }
>  
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH 03/10] xfs_scrub: destroy workqueues when erroring out
  2018-06-27  2:48 ` [PATCH 03/10] xfs_scrub: destroy workqueues when erroring out Darrick J. Wong
@ 2018-07-26  0:29   ` Eric Sandeen
  0 siblings, 0 replies; 29+ messages in thread
From: Eric Sandeen @ 2018-07-26  0:29 UTC (permalink / raw)
  To: Darrick J. Wong, sandeen; +Cc: linux-xfs

On 6/26/18 7:48 PM, Darrick J. Wong wrote:
> From: Darrick J. Wong <darrick.wong@oracle.com>
> 
> Fix a couple of code paths that forgot to tear down a workqueue when
> erroring out, because if we don't the wq threads keep running even after
> we've freed the wq memory.
> 
> Found by fuzzing core.nlinkv2=0 in xfs/377, but only because the fs will
> shut down when it hits an error destroying the incore (corrupt) inode
> after the scrub.
> 
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>

Reviewed-by: Eric Sandeen <sandeen@redhat.com>

> ---
>  scrub/phase2.c |    2 +-
>  scrub/vfs.c    |    4 +++-
>  2 files changed, 4 insertions(+), 2 deletions(-)
> 
> 
> diff --git a/scrub/phase2.c b/scrub/phase2.c
> index ad736bf5..7078e38d 100644
> --- a/scrub/phase2.c
> +++ b/scrub/phase2.c
> @@ -102,7 +102,7 @@ xfs_scan_metadata(
>  	 */
>  	moveon = xfs_scrub_primary_super(ctx);
>  	if (!moveon)
> -		return moveon;
> +		goto out;
>  
>  	for (agno = 0; moveon && agno < ctx->geo.agcount; agno++) {
>  		ret = workqueue_add(&wq, xfs_scan_ag_metadata, agno, &moveon);
> diff --git a/scrub/vfs.c b/scrub/vfs.c
> index 77df2874..12a6a860 100644
> --- a/scrub/vfs.c
> +++ b/scrub/vfs.c
> @@ -210,7 +210,7 @@ scan_fs_tree(
>  	if (ret) {
>  		str_info(ctx, ctx->mntpoint,
>  _("Could not queue directory scan work."));
> -		goto out_free;
> +		goto out_wq;
>  	}
>  
>  	pthread_mutex_lock(&sft.lock);
> @@ -220,6 +220,8 @@ _("Could not queue directory scan work."));
>  	workqueue_destroy(&wq);
>  
>  	return sft.moveon;
> +out_wq:
> +	workqueue_destroy(&wq);
>  out_free:
>  	free(sftd->path);
>  	free(sftd);
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH 04/10] xfs_scrub: schedule and manage optimizations/repairs to the filesystem
  2018-06-27  2:48 ` [PATCH 04/10] xfs_scrub: schedule and manage optimizations/repairs to the filesystem Darrick J. Wong
@ 2018-07-26  1:06   ` Eric Sandeen
  2018-07-26  1:17     ` Darrick J. Wong
  0 siblings, 1 reply; 29+ messages in thread
From: Eric Sandeen @ 2018-07-26  1:06 UTC (permalink / raw)
  To: Darrick J. Wong, sandeen; +Cc: linux-xfs

On 6/26/18 7:48 PM, Darrick J. Wong wrote:
> From: Darrick J. Wong <darrick.wong@oracle.com>
> 
> Teach xfs_scrub to remember scrub requests that failed (or indicated
> that optimization is a possibility) as action items.  Depending on the
> circumstances, certain items are acted upon immediately (e.g. metadata
> that needs to be healthy in order to finish the scan, or files that are
> already open) or deferred until later.  Expand the repair phase to
> deal with the deferred actions.
> 
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
> ---
>  man/man8/xfs_scrub.8 |   38 ++++++-
>  scrub/Makefile       |    2 
>  scrub/phase1.c       |    7 +
>  scrub/phase2.c       |   59 ++++++++++
>  scrub/phase3.c       |   42 +++++--
>  scrub/phase4.c       |   76 +++++++++++++
>  scrub/repair.c       |  286 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  scrub/repair.h       |   42 +++++++
>  scrub/scrub.c        |  130 ++++++++++++++++-------
>  scrub/scrub.h        |   42 +++++--
>  scrub/xfs_scrub.c    |   44 +++++++-
>  scrub/xfs_scrub.h    |    1 
>  12 files changed, 690 insertions(+), 79 deletions(-)
>  create mode 100644 scrub/repair.c
>  create mode 100644 scrub/repair.h
> 
> 
> diff --git a/man/man8/xfs_scrub.8 b/man/man8/xfs_scrub.8
> index 680ef72b..18948a4e 100644
> --- a/man/man8/xfs_scrub.8
> +++ b/man/man8/xfs_scrub.8
> @@ -1,6 +1,6 @@
>  .TH xfs_scrub 8
>  .SH NAME
> -xfs_scrub \- check the contents of a mounted XFS filesystem
> +xfs_scrub \- check and repair the contents of a mounted XFS filesystem
>  .SH SYNOPSIS
>  .B xfs_scrub
>  [
> @@ -108,10 +108,40 @@ Optimizations supported by this program include, but are not limited to:
>  Instructing the underlying storage to discard unused extents via the
>  .B TRIM
>  ioctl.
> +.IP \[bu]
> +Updating secondary superblocks to match the primary superblock.
> +.IP \[bu]
> +Turning off shared block write checks for files that no longer share blocks.
>  .SH REPAIRS
> -This program currently does not support making any repairs.
> -Corruptions can only be fixed by unmounting the filesystem and running
> -.BR xfs_repair (8).
> +Repairs are performed by calling into the kernel.
> +This limits the scope of repair activities to rebuilding primary data
> +structures from secondary data structures, or secondary structures from
> +primary structures.
> +The existence of secondary data structures may require features that can
> +only be turned on from
> +.BR mkfs.xfs (8).
> +If errors cannot be repaired, the filesystem must be
> +unmounted and
> +.BR xfs_repair (8)
> +run.
> +Repairs supported by the kernel include, but are not limited to:
> +.IP \[bu] 2
> +Reconstructing extent allocation data.
> +.IP \[bu]
> +Rebuilding free space information.
> +.IP \[bu]
> +Rebuilding inode indexes.
> +.IP \[bu]
> +Fixing minor corruptions of inode records.
> +.IP \[bu]
> +Recalculating reference count information.
> +.IP \[bu]
> +Reconstructing reverse mapping data from primary extent allocation data.
> +.IP \[bu]
> +Scheduling a quotacheck for the next mount.
> +.PP
> +If corrupt metadata is successfully repaired, this program will log that
> +a repair has succeeded instead of a corruption report.

for 4.18 I think we should only list what's possible, right?
But, um, what is currently possible in 4.18?

Maybe I'll just add a "may include ..." and a "depending on the capabilities
of the running kernel" to give us some wiggle room.

As for the rest, um, seems ok AFAICT (which isn't that far).  Minor nit:

...

>  static void
>  report_outcome(
>  	struct scrub_ctx	*ctx)
> @@ -525,9 +555,16 @@ report_outcome(
>  	 * setting up the scrub and we actually saw corruptions.  Warnings
>  	 * are not corruptions.
>  	 */
> -	if (ctx->scrub_setup_succeeded && total_errors > 0)
> -		fprintf(stderr, _("%s: Unmount and run xfs_repair.\n"),
> -				ctx->mntpoint);
> +	if (ctx->scrub_setup_succeeded && total_errors > 0) {
> +		char		*msg;
> +
> +		if (ctx->mode == SCRUB_MODE_DRY_RUN)
> +			msg = _("%s: Re-run xfs_scrub without -n.\n");

"... to repair?"

Is it possible that we found something that can't actually be repaired
online, and so they'll get:

# xfs_scrub -n
"Re-run xfs_scrub without -n"
# xfs_scrub
"Unmount and run xfs_repair."
#

Maybe that's ok ... there's no way to keep track of which found problems
are repairable by the running kernel, is there?

-Eric

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH 05/10] xfs_scrub: allow developers to force repairs
  2018-06-27  2:48 ` [PATCH 05/10] xfs_scrub: allow developers to force repairs Darrick J. Wong
@ 2018-07-26  1:07   ` Eric Sandeen
  0 siblings, 0 replies; 29+ messages in thread
From: Eric Sandeen @ 2018-07-26  1:07 UTC (permalink / raw)
  To: Darrick J. Wong, sandeen; +Cc: linux-xfs

On 6/26/18 7:48 PM, Darrick J. Wong wrote:
> From: Darrick J. Wong <darrick.wong@oracle.com>
> 
> Now that we have an error injection knob in the kernel to simulate
> corruptions, enable it in xfs_scrub so that developers can test all
> the repair capabilities.
> 
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>

Reviewed-by: Eric Sandeen <sandeen@redhat.com>

> ---
>  scrub/scrub.c |    8 ++++++--
>  1 file changed, 6 insertions(+), 2 deletions(-)
> 
> 
> diff --git a/scrub/scrub.c b/scrub/scrub.c
> index af665c83..c893f2c9 100644
> --- a/scrub/scrub.c
> +++ b/scrub/scrub.c
> @@ -612,14 +612,18 @@ __xfs_scrub_test(
>  	bool				repair)
>  {
>  	struct xfs_scrub_metadata	meta = {0};
> +	struct xfs_error_injection	inject;
>  	static bool			injected;
>  	int				error;
>  
>  	if (debug_tweak_on("XFS_SCRUB_NO_KERNEL"))
>  		return false;
>  	if (debug_tweak_on("XFS_SCRUB_FORCE_REPAIR") && !injected) {
> -		str_info(ctx, "XFS_SCRUB_FORCE_REPAIR", "Not supported.");
> -		return false;
> +		inject.fd = ctx->mnt_fd;
> +		inject.errtag = XFS_ERRTAG_FORCE_SCRUB_REPAIR;
> +		error = ioctl(ctx->mnt_fd, XFS_IOC_ERROR_INJECTION, &inject);
> +		if (error == 0)
> +			injected = true;
>  	}
>  
>  	meta.sm_type = type;
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH 06/10] xfs_scrub: don't error out if an optimize-only repair isn't supported
  2018-06-27  2:48 ` [PATCH 06/10] xfs_scrub: don't error out if an optimize-only repair isn't supported Darrick J. Wong
@ 2018-07-26  1:09   ` Eric Sandeen
  0 siblings, 0 replies; 29+ messages in thread
From: Eric Sandeen @ 2018-07-26  1:09 UTC (permalink / raw)
  To: Darrick J. Wong, sandeen; +Cc: linux-xfs

On 6/26/18 7:48 PM, Darrick J. Wong wrote:
> From: Darrick J. Wong <darrick.wong@oracle.com>
> 
> If the kernel told us a metadata object could be optimized, we ask it to
> do the optimization and it spits back that it doesn't support
> optimizing, don't record this as an error since the fs is still
> consistent.
> 
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>

Reviewed-by: Eric Sandeen <sandeen@redhat.com>

> ---
>  scrub/scrub.c |    7 ++++---
>  1 file changed, 4 insertions(+), 3 deletions(-)
> 
> 
> diff --git a/scrub/scrub.c b/scrub/scrub.c
> index c893f2c9..fe4e880f 100644
> --- a/scrub/scrub.c
> +++ b/scrub/scrub.c
> @@ -782,10 +782,11 @@ _("Filesystem is shut down, aborting."));
>  		case ENOTTY:
>  		case EOPNOTSUPP:
>  			/*
> -			 * If we forced repairs, don't complain if kernel
> -			 * doesn't know how to fix.
> +			 * If we forced repairs or this is a preen, don't
> +			 * error out if the kernel doesn't know how to fix.
>  			 */
> -			if (debug_tweak_on("XFS_SCRUB_FORCE_REPAIR"))
> +			if (is_unoptimized(&oldm) ||
> +			    debug_tweak_on("XFS_SCRUB_FORCE_REPAIR"))
>  				return CHECK_DONE;
>  			/* fall through */
>  		case EINVAL:
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH 07/10] xfs_scrub: rename NOFIX_COMPLAIN to be less confusing
  2018-06-27  2:48 ` [PATCH 07/10] xfs_scrub: rename NOFIX_COMPLAIN to be less confusing Darrick J. Wong
@ 2018-07-26  1:10   ` Eric Sandeen
  0 siblings, 0 replies; 29+ messages in thread
From: Eric Sandeen @ 2018-07-26  1:10 UTC (permalink / raw)
  To: Darrick J. Wong, sandeen; +Cc: linux-xfs



On 6/26/18 7:48 PM, Darrick J. Wong wrote:
> From: Darrick J. Wong <darrick.wong@oracle.com>
> 
> Rename NOFIX_COMPLAIN to COMPLAIN_IF_UNFIXED so that the symbolic name
> is less confusing as to what the flag is supposed to mean.
> 
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>

Yay for clarity ;)

Reviewed-by: Eric Sandeen <sandeen@redhat.com>



^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH 08/10] xfs_scrub: only retry non-permanent repair failures
  2018-06-27  2:48 ` [PATCH 08/10] xfs_scrub: only retry non-permanent repair failures Darrick J. Wong
@ 2018-07-26  1:16   ` Eric Sandeen
  2018-07-26  1:19     ` Darrick J. Wong
  0 siblings, 1 reply; 29+ messages in thread
From: Eric Sandeen @ 2018-07-26  1:16 UTC (permalink / raw)
  To: Darrick J. Wong, sandeen; +Cc: linux-xfs

On 6/26/18 7:48 PM, Darrick J. Wong wrote:
> From: Darrick J. Wong <darrick.wong@oracle.com>
> 
> If a repair fails, we want to retry the repair if the error was a
> transient one, such as ENOMEM.  For "permanent" ones (shutdown fs,
> repair not supported by kernel, readonly fs) there's no point to
> retrying them so just error out immediately.
> 
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>

Is there something that stops infinite retries?
(I need to get this all applied for context I guess)

But anyway,
Reviewed-by: Eric Sandeen <sandeen@redhat.com>


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH 04/10] xfs_scrub: schedule and manage optimizations/repairs to the filesystem
  2018-07-26  1:06   ` Eric Sandeen
@ 2018-07-26  1:17     ` Darrick J. Wong
  0 siblings, 0 replies; 29+ messages in thread
From: Darrick J. Wong @ 2018-07-26  1:17 UTC (permalink / raw)
  To: Eric Sandeen; +Cc: sandeen, linux-xfs

On Wed, Jul 25, 2018 at 06:06:00PM -0700, Eric Sandeen wrote:
> On 6/26/18 7:48 PM, Darrick J. Wong wrote:
> > From: Darrick J. Wong <darrick.wong@oracle.com>
> > 
> > Teach xfs_scrub to remember scrub requests that failed (or indicated
> > that optimization is a possibility) as action items.  Depending on the
> > circumstances, certain items are acted upon immediately (e.g. metadata
> > that needs to be healthy in order to finish the scan, or files that are
> > already open) or deferred until later.  Expand the repair phase to
> > deal with the deferred actions.
> > 
> > Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
> > ---
> >  man/man8/xfs_scrub.8 |   38 ++++++-
> >  scrub/Makefile       |    2 
> >  scrub/phase1.c       |    7 +
> >  scrub/phase2.c       |   59 ++++++++++
> >  scrub/phase3.c       |   42 +++++--
> >  scrub/phase4.c       |   76 +++++++++++++
> >  scrub/repair.c       |  286 ++++++++++++++++++++++++++++++++++++++++++++++++++
> >  scrub/repair.h       |   42 +++++++
> >  scrub/scrub.c        |  130 ++++++++++++++++-------
> >  scrub/scrub.h        |   42 +++++--
> >  scrub/xfs_scrub.c    |   44 +++++++-
> >  scrub/xfs_scrub.h    |    1 
> >  12 files changed, 690 insertions(+), 79 deletions(-)
> >  create mode 100644 scrub/repair.c
> >  create mode 100644 scrub/repair.h
> > 
> > 
> > diff --git a/man/man8/xfs_scrub.8 b/man/man8/xfs_scrub.8
> > index 680ef72b..18948a4e 100644
> > --- a/man/man8/xfs_scrub.8
> > +++ b/man/man8/xfs_scrub.8
> > @@ -1,6 +1,6 @@
> >  .TH xfs_scrub 8
> >  .SH NAME
> > -xfs_scrub \- check the contents of a mounted XFS filesystem
> > +xfs_scrub \- check and repair the contents of a mounted XFS filesystem
> >  .SH SYNOPSIS
> >  .B xfs_scrub
> >  [
> > @@ -108,10 +108,40 @@ Optimizations supported by this program include, but are not limited to:
> >  Instructing the underlying storage to discard unused extents via the
> >  .B TRIM
> >  ioctl.
> > +.IP \[bu]
> > +Updating secondary superblocks to match the primary superblock.
> > +.IP \[bu]
> > +Turning off shared block write checks for files that no longer share blocks.
> >  .SH REPAIRS
> > -This program currently does not support making any repairs.
> > -Corruptions can only be fixed by unmounting the filesystem and running
> > -.BR xfs_repair (8).
> > +Repairs are performed by calling into the kernel.
> > +This limits the scope of repair activities to rebuilding primary data
> > +structures from secondary data structures, or secondary structures from
> > +primary structures.
> > +The existence of secondary data structures may require features that can
> > +only be turned on from
> > +.BR mkfs.xfs (8).
> > +If errors cannot be repaired, the filesystem must be
> > +unmounted and
> > +.BR xfs_repair (8)
> > +run.
> > +Repairs supported by the kernel include, but are not limited to:
> > +.IP \[bu] 2
> > +Reconstructing extent allocation data.
> > +.IP \[bu]
> > +Rebuilding free space information.
> > +.IP \[bu]
> > +Rebuilding inode indexes.
> > +.IP \[bu]
> > +Fixing minor corruptions of inode records.
> > +.IP \[bu]
> > +Recalculating reference count information.
> > +.IP \[bu]
> > +Reconstructing reverse mapping data from primary extent allocation data.
> > +.IP \[bu]
> > +Scheduling a quotacheck for the next mount.
> > +.PP
> > +If corrupt metadata is successfully repaired, this program will log that
> > +a repair has succeeded instead of a corruption report.
> 
> for 4.18 I think we should only list what's possible, right?
> But, um, what is currently possible in 4.18?

Secondary superblocks only.

> Maybe I'll just add a "may include ..." and a "depending on the capabilities
> of the running kernel" to give us some wiggle room.

/me shrugs, happy to resubmit that list w/ just the secondary supers and
then to send more patches with each release as/if I get things
reviewed.

> As for the rest, um, seems ok AFAICT (which isn't that far).  Minor nit:
> 
> ...
> 
> >  static void
> >  report_outcome(
> >  	struct scrub_ctx	*ctx)
> > @@ -525,9 +555,16 @@ report_outcome(
> >  	 * setting up the scrub and we actually saw corruptions.  Warnings
> >  	 * are not corruptions.
> >  	 */
> > -	if (ctx->scrub_setup_succeeded && total_errors > 0)
> > -		fprintf(stderr, _("%s: Unmount and run xfs_repair.\n"),
> > -				ctx->mntpoint);
> > +	if (ctx->scrub_setup_succeeded && total_errors > 0) {
> > +		char		*msg;
> > +
> > +		if (ctx->mode == SCRUB_MODE_DRY_RUN)
> > +			msg = _("%s: Re-run xfs_scrub without -n.\n");
> 
> "... to repair?"

Yes.

> Is it possible that we found something that can't actually be repaired
> online, and so they'll get:
> 
> # xfs_scrub -n
> "Re-run xfs_scrub without -n"
> # xfs_scrub
> "Unmount and run xfs_repair."

Right.  First scrub found something and told you how to fix it, but then
you tried that and it couldn't fix it so it told you about ye olde
repair tool.

> 
> Maybe that's ok ... there's no way to keep track of which found problems
> are repairable by the running kernel, is there?

Not really, I'm afraid.  Either the kernel has a function to repair
things or it doesn't, and there's no good way to track at a finer
grained level than that.

--D

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

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH 08/10] xfs_scrub: only retry non-permanent repair failures
  2018-07-26  1:16   ` Eric Sandeen
@ 2018-07-26  1:19     ` Darrick J. Wong
  0 siblings, 0 replies; 29+ messages in thread
From: Darrick J. Wong @ 2018-07-26  1:19 UTC (permalink / raw)
  To: Eric Sandeen; +Cc: sandeen, linux-xfs

On Wed, Jul 25, 2018 at 06:16:15PM -0700, Eric Sandeen wrote:
> On 6/26/18 7:48 PM, Darrick J. Wong wrote:
> > From: Darrick J. Wong <darrick.wong@oracle.com>
> > 
> > If a repair fails, we want to retry the repair if the error was a
> > transient one, such as ENOMEM.  For "permanent" ones (shutdown fs,
> > repair not supported by kernel, readonly fs) there's no point to
> > retrying them so just error out immediately.
> > 
> > Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
> 
> Is there something that stops infinite retries?
> (I need to get this all applied for context I guess)

If scrub notices the set of unrepaired things stops shrinking it'll try
them all again single-threaded and complain about anything that didn't
get fixed.

--D

> But anyway,
> Reviewed-by: Eric Sandeen <sandeen@redhat.com>
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH 09/10] xfs_io: wire up repair ioctl stuff
  2018-06-27  2:48 ` [PATCH 09/10] xfs_io: wire up repair ioctl stuff Darrick J. Wong
@ 2018-07-26  1:23   ` Eric Sandeen
  0 siblings, 0 replies; 29+ messages in thread
From: Eric Sandeen @ 2018-07-26  1:23 UTC (permalink / raw)
  To: Darrick J. Wong, sandeen; +Cc: linux-xfs

On 6/26/18 7:48 PM, Darrick J. Wong wrote:
> From: Darrick J. Wong <darrick.wong@oracle.com>
> 
> Wire up the repair ioctl (which is really the scrub ioctl with special
> flags) and the force-repair error injection point.


> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>

Reviewed-by: Eric Sandeen <sandeen@redhat.com>

> ---
>  io/init.c         |    1 +
>  io/io.h           |    1 +
>  io/scrub.c        |   97 +++++++++++++++++++++++++++++++++++++++++++++++++++++
>  man/man8/xfs_io.8 |    8 ++++
>  4 files changed, 107 insertions(+)
> 
> 
> diff --git a/io/init.c b/io/init.c
> index 3f637e5a..a65f81d6 100644
> --- a/io/init.c
> +++ b/io/init.c
> @@ -85,6 +85,7 @@ init_commands(void)
>  	quit_init();
>  	readdir_init();
>  	reflink_init();
> +	repair_init();
>  	resblks_init();
>  	scrub_init();
>  	seek_init();
> diff --git a/io/io.h b/io/io.h
> index fa0cdff7..ab217789 100644
> --- a/io/io.h
> +++ b/io/io.h
> @@ -198,3 +198,4 @@ extern void		log_writes_init(void);
>  #endif
>  
>  extern void		scrub_init(void);
> +extern void		repair_init(void);
> diff --git a/io/scrub.c b/io/scrub.c
> index 75a8ff15..c2c08e6b 100644
> --- a/io/scrub.c
> +++ b/io/scrub.c
> @@ -26,6 +26,7 @@
>  #include "io.h"
>  
>  static struct cmdinfo scrub_cmd;
> +static struct cmdinfo repair_cmd;
>  
>  /* Type info and names for the scrub types. */
>  enum scrub_type {
> @@ -249,3 +250,99 @@ scrub_init(void)
>  
>  	add_command(&scrub_cmd);
>  }
> +
> +static void
> +repair_help(void)
> +{
> +	const struct scrub_descr	*d;
> +	int				i;
> +
> +	printf(_(
> +"\n"
> +" Repairs a piece of XFS filesystem metadata.  The first argument is the type\n"
> +" of metadata to examine.  Allocation group metadata types take one AG number\n"
> +" as the second parameter.  Inode metadata types act on the currently open file\n"
> +" or (optionally) take an inode number and generation number to act upon as\n"
> +" the second and third parameters.\n"
> +"\n"
> +" Example:\n"
> +" 'repair inobt 3' - repairs the inode btree in AG 3.\n"
> +" 'repair bmapbtd 128 13525' - repairs the extent map of inode 128 gen 13525.\n"
> +"\n"
> +" Known metadata repairs types are:"));
> +	for (i = 0, d = scrubbers; i < XFS_SCRUB_TYPE_NR; i++, d++)
> +		printf(" %s", d->name);
> +	printf("\n");
> +}
> +
> +static void
> +repair_ioctl(
> +	int				fd,
> +	int				type,
> +	uint64_t			control,
> +	uint32_t			control2)
> +{
> +	struct xfs_scrub_metadata	meta;
> +	const struct scrub_descr	*sc;
> +	int				error;
> +
> +	sc = &scrubbers[type];
> +	memset(&meta, 0, sizeof(meta));
> +	meta.sm_type = type;
> +	switch (sc->type) {
> +	case ST_PERAG:
> +		meta.sm_agno = control;
> +		break;
> +	case ST_INODE:
> +		meta.sm_ino = control;
> +		meta.sm_gen = control2;
> +		break;
> +	case ST_NONE:
> +	case ST_FS:
> +		/* no control parameters */
> +		break;
> +	}
> +	meta.sm_flags = XFS_SCRUB_IFLAG_REPAIR;
> +
> +	error = ioctl(fd, XFS_IOC_SCRUB_METADATA, &meta);
> +	if (error)
> +		perror("scrub");
> +	if (meta.sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
> +		printf(_("Corruption remains.\n"));
> +	if (meta.sm_flags & XFS_SCRUB_OFLAG_PREEN)
> +		printf(_("Optimization possible.\n"));
> +	if (meta.sm_flags & XFS_SCRUB_OFLAG_XFAIL)
> +		printf(_("Cross-referencing failed.\n"));
> +	if (meta.sm_flags & XFS_SCRUB_OFLAG_XCORRUPT)
> +		printf(_("Corruption still detected during cross-referencing.\n"));
> +	if (meta.sm_flags & XFS_SCRUB_OFLAG_INCOMPLETE)
> +		printf(_("Repair was not complete.\n"));
> +	if (meta.sm_flags & XFS_SCRUB_OFLAG_NO_REPAIR_NEEDED)
> +		printf(_("Metadata did not need repair or optimization.\n"));
> +}
> +
> +static int
> +repair_f(
> +	int				argc,
> +	char				**argv)
> +{
> +	return parse_args(argc, argv, &repair_cmd, repair_ioctl);
> +}
> +
> +void
> +repair_init(void)
> +{
> +	if (!expert)
> +		return;
> +	repair_cmd.name = "repair";
> +	repair_cmd.altname = "fix";
> +	repair_cmd.cfunc = repair_f;
> +	repair_cmd.argmin = 1;
> +	repair_cmd.argmax = -1;
> +	repair_cmd.flags = CMD_NOMAP_OK;
> +	repair_cmd.args = _("type [agno|ino gen]");
> +	repair_cmd.oneline = _("repairs filesystem metadata");
> +	repair_cmd.help = repair_help;
> +
> +	add_command(&repair_cmd);
> +}
> diff --git a/man/man8/xfs_io.8 b/man/man8/xfs_io.8
> index dd91589b..60f7a21c 100644
> --- a/man/man8/xfs_io.8
> +++ b/man/man8/xfs_io.8
> @@ -1167,6 +1167,14 @@ inode number and generation number are specified.
>  .RE
>  .PD
>  .TP
> +.BI "repair " type " [ " agnumber " | " "ino" " " "gen" " ]"
> +Repair internal XFS filesystem metadata.  The
> +.BI type
> +parameter specifies which type of metadata to repair.
> +For AG metadata, one AG number must be specified.
> +For file metadata, the repair is applied to the open file unless the
> +inode number and generation number are specified.
> +.TP
>  .BI "log_writes \-d " device " \-m "  mark
>  Create a mark named
>  .I mark
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH 12/10] xfs_repair: use libxfs extsize/cowextsize validation helpers
  2018-06-28 17:30 ` [PATCH 12/10] xfs_repair: use libxfs extsize/cowextsize validation helpers Darrick J. Wong
@ 2018-07-26  1:44   ` Eric Sandeen
  2018-07-26  1:48     ` Eric Sandeen
  2018-07-26 20:38   ` [PATCH v2 " Darrick J. Wong
  1 sibling, 1 reply; 29+ messages in thread
From: Eric Sandeen @ 2018-07-26  1:44 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: linux-xfs

On 6/28/18 10:30 AM, Darrick J. Wong wrote:
> From: Darrick J. Wong <darrick.wong@oracle.com>
> 
> Now that we've ported the extent size hint verifiers to libxfs, call
> them from xfs_repair instead of open-coding the checks.  Tweak the
> repair message slightly to reflect the fact that we zero the field and
> clear the inode flag if the hint is garbage or is inconsistent with the
> inode flags.
> 
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
> ---
>  libxfs/libxfs_api_defs.h |    2 +
>  repair/dinode.c          |   75 ++++++++++++++++------------------------------
>  2 files changed, 28 insertions(+), 49 deletions(-)
> 
> diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h
> index e5cf1554..fe8336ab 100644
> --- a/libxfs/libxfs_api_defs.h
> +++ b/libxfs/libxfs_api_defs.h
> @@ -98,6 +98,8 @@
>  #define xfs_dinode_calc_crc		libxfs_dinode_calc_crc
>  #define xfs_idata_realloc		libxfs_idata_realloc
>  #define xfs_idestroy_fork		libxfs_idestroy_fork
> +#define xfs_inode_validate_extsize	libxfs_inode_validate_extsize
> +#define xfs_inode_validate_cowextsize	libxfs_inode_validate_cowextsize

oh hey, I stepped on this with my later patches didn't I, sorry. I'll sort it out.

>  
>  #define xfs_rmap_ag_owner		libxfs_rmap_ag_owner
>  #define xfs_rmap_alloc			libxfs_rmap_alloc
> diff --git a/repair/dinode.c b/repair/dinode.c
> index 4118db7c..14c055bd 100644
> --- a/repair/dinode.c
> +++ b/repair/dinode.c
> @@ -2853,24 +2853,21 @@ _("bad (negative) size %" PRId64 " on inode %" PRIu64 "\n"),
>  	 * only regular files with REALTIME or EXTSIZE flags set can have
>  	 * extsize set, or directories with EXTSZINHERIT.
>  	 */
> -	if (be32_to_cpu(dino->di_extsize) != 0) {
> -		if ((type == XR_INO_RTDATA) ||
> -		    (type == XR_INO_DIR && (be16_to_cpu(dino->di_flags) &
> -					XFS_DIFLAG_EXTSZINHERIT)) ||
> -		    (type == XR_INO_DATA && (be16_to_cpu(dino->di_flags) &
> -				 XFS_DIFLAG_EXTSIZE)))  {
> -			/* s'okay */ ;
> -		} else {
> -			do_warn(
> -_("bad non-zero extent size %u for non-realtime/extsize inode %" PRIu64 ", "),
> -					be32_to_cpu(dino->di_extsize), lino);
> -			if (!no_modify)  {
> -				do_warn(_("resetting to zero\n"));
> -				dino->di_extsize = 0;
> -				*dirty = 1;
> -			} else
> -				do_warn(_("would reset to zero\n"));
> -		}
> +	if (libxfs_inode_validate_extsize(mp,
> +			be32_to_cpu(dino->di_extsize),
> +			be16_to_cpu(dino->di_mode),
> +			be16_to_cpu(dino->di_flags)) != NULL) {
> +		do_warn(
> +_("Bad extent size %u for non-realtime/extsize inode %" PRIu64 ", "),
> +				be32_to_cpu(dino->di_extsize), lino);

Failure doesn't mean it's "non-realtime/extsize" right?  It could
in fact be flagged as extsize but with a bad value?

> +		if (!no_modify)  {
> +			do_warn(_("resetting to zero\n"));
> +			dino->di_extsize = 0;
> +			dino->di_flags &= ~cpu_to_be16(XFS_DIFLAG_EXTSIZE |
> +						       XFS_DIFLAG_EXTSZINHERIT);
> +			*dirty = 1;
> +		} else
> +			do_warn(_("would reset to zero\n"));
...

> -_("Cannot have CoW extent size of zero on cowextsize inode %" PRIu64 ", "),
> -				lino);
> +_("Bad CoW extent size %u on non-cowextsize inode %" PRIu64 ", "),
> +				be32_to_cpu(dino->di_cowextsize), lino);

Ditto ...

The test could also fail for a cowextsize inode if the size is not
legit, right?  I'm not sure why this says "non-cowextsize inode."

So maybe just:

+_("Bad extent size %u for inode %" PRIu64 ", "),
+_("Bad CoW extent size %u on inode %" PRIu64 ", "),

? Unless you really want to keep track of "is it flagged?" and print a
different message based on flagged-or-not?

-Eric

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH 12/10] xfs_repair: use libxfs extsize/cowextsize validation helpers
  2018-07-26  1:44   ` Eric Sandeen
@ 2018-07-26  1:48     ` Eric Sandeen
  0 siblings, 0 replies; 29+ messages in thread
From: Eric Sandeen @ 2018-07-26  1:48 UTC (permalink / raw)
  To: Eric Sandeen, Darrick J. Wong; +Cc: linux-xfs

On 7/25/18 6:44 PM, Eric Sandeen wrote:
> On 6/28/18 10:30 AM, Darrick J. Wong wrote:
...

> So maybe just:
> 
> +_("Bad extent size %u for inode %" PRIu64 ", "),
> +_("Bad CoW extent size %u on inode %" PRIu64 ", "),

Uh, may as well fix for-vs-on, too :)


^ permalink raw reply	[flat|nested] 29+ messages in thread

* [PATCH v2 12/10] xfs_repair: use libxfs extsize/cowextsize validation helpers
  2018-06-28 17:30 ` [PATCH 12/10] xfs_repair: use libxfs extsize/cowextsize validation helpers Darrick J. Wong
  2018-07-26  1:44   ` Eric Sandeen
@ 2018-07-26 20:38   ` Darrick J. Wong
  2018-07-27 22:44     ` Eric Sandeen
  1 sibling, 1 reply; 29+ messages in thread
From: Darrick J. Wong @ 2018-07-26 20:38 UTC (permalink / raw)
  To: sandeen; +Cc: linux-xfs

From: Darrick J. Wong <darrick.wong@oracle.com>

Now that we've ported the extent size hint verifiers to libxfs, call
them from xfs_repair instead of open-coding the checks.  Tweak the
repair message slightly to reflect the fact that we zero the field and
clear the inode flag if the hint is garbage or is inconsistent with the
inode flags.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
v2: fix error message to reflect what actually happened
---
 libxfs/libxfs_api_defs.h |    2 +
 repair/dinode.c          |   75 ++++++++++++++++------------------------------
 2 files changed, 28 insertions(+), 49 deletions(-)

diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h
index e5cf1554..fe8336ab 100644
--- a/libxfs/libxfs_api_defs.h
+++ b/libxfs/libxfs_api_defs.h
@@ -98,6 +98,8 @@
 #define xfs_dinode_calc_crc		libxfs_dinode_calc_crc
 #define xfs_idata_realloc		libxfs_idata_realloc
 #define xfs_idestroy_fork		libxfs_idestroy_fork
+#define xfs_inode_validate_extsize	libxfs_inode_validate_extsize
+#define xfs_inode_validate_cowextsize	libxfs_inode_validate_cowextsize
 
 #define xfs_rmap_ag_owner		libxfs_rmap_ag_owner
 #define xfs_rmap_alloc			libxfs_rmap_alloc
diff --git a/repair/dinode.c b/repair/dinode.c
index fb65ee22..cf1a0ad8 100644
--- a/repair/dinode.c
+++ b/repair/dinode.c
@@ -2841,24 +2841,21 @@ _("bad (negative) size %" PRId64 " on inode %" PRIu64 "\n"),
 	 * only regular files with REALTIME or EXTSIZE flags set can have
 	 * extsize set, or directories with EXTSZINHERIT.
 	 */
-	if (be32_to_cpu(dino->di_extsize) != 0) {
-		if ((type == XR_INO_RTDATA) ||
-		    (type == XR_INO_DIR && (be16_to_cpu(dino->di_flags) &
-					XFS_DIFLAG_EXTSZINHERIT)) ||
-		    (type == XR_INO_DATA && (be16_to_cpu(dino->di_flags) &
-				 XFS_DIFLAG_EXTSIZE)))  {
-			/* s'okay */ ;
-		} else {
-			do_warn(
-_("bad non-zero extent size %u for non-realtime/extsize inode %" PRIu64 ", "),
-					be32_to_cpu(dino->di_extsize), lino);
-			if (!no_modify)  {
-				do_warn(_("resetting to zero\n"));
-				dino->di_extsize = 0;
-				*dirty = 1;
-			} else
-				do_warn(_("would reset to zero\n"));
-		}
+	if (libxfs_inode_validate_extsize(mp,
+			be32_to_cpu(dino->di_extsize),
+			be16_to_cpu(dino->di_mode),
+			be16_to_cpu(dino->di_flags)) != NULL) {
+		do_warn(
+_("Bad extent size %u on inode %" PRIu64 ", "),
+				be32_to_cpu(dino->di_extsize), lino);
+		if (!no_modify)  {
+			do_warn(_("resetting to zero\n"));
+			dino->di_extsize = 0;
+			dino->di_flags &= ~cpu_to_be16(XFS_DIFLAG_EXTSIZE |
+						       XFS_DIFLAG_EXTSZINHERIT);
+			*dirty = 1;
+		} else
+			do_warn(_("would reset to zero\n"));
 	}
 
 	/*
@@ -2866,41 +2863,21 @@ _("bad non-zero extent size %u for non-realtime/extsize inode %" PRIu64 ", "),
 	 * set can have extsize set.
 	 */
 	if (dino->di_version >= 3 &&
-	    be32_to_cpu(dino->di_cowextsize) != 0) {
-		if ((type == XR_INO_DIR || type == XR_INO_DATA) &&
-		    (be64_to_cpu(dino->di_flags2) &
-					XFS_DIFLAG2_COWEXTSIZE)) {
-			/* s'okay */ ;
-		} else {
-			do_warn(
-_("Cannot have non-zero CoW extent size %u on non-cowextsize inode %" PRIu64 ", "),
-					be32_to_cpu(dino->di_cowextsize), lino);
-			if (!no_modify)  {
-				do_warn(_("resetting to zero\n"));
-				dino->di_flags2 &= ~cpu_to_be64(XFS_DIFLAG2_COWEXTSIZE);
-				dino->di_cowextsize = 0;
-				*dirty = 1;
-			} else
-				do_warn(_("would reset to zero\n"));
-		}
-	}
-
-	/*
-	 * Can't have the COWEXTSIZE flag set with no hint.
-	 */
-	if (dino->di_version >= 3 &&
-	    be32_to_cpu(dino->di_cowextsize) == 0 &&
-	    (be64_to_cpu(dino->di_flags2) & XFS_DIFLAG2_COWEXTSIZE)) {
+	    libxfs_inode_validate_cowextsize(mp,
+			be32_to_cpu(dino->di_cowextsize),
+			be16_to_cpu(dino->di_mode),
+			be16_to_cpu(dino->di_flags),
+			be64_to_cpu(dino->di_flags2)) != NULL) {
 		do_warn(
-_("Cannot have CoW extent size of zero on cowextsize inode %" PRIu64 ", "),
-				lino);
+_("Bad CoW extent size %u on inode %" PRIu64 ", "),
+				be32_to_cpu(dino->di_cowextsize), lino);
 		if (!no_modify)  {
-			do_warn(_("clearing cowextsize flag\n"));
+			do_warn(_("resetting to zero\n"));
 			dino->di_flags2 &= ~cpu_to_be64(XFS_DIFLAG2_COWEXTSIZE);
+			dino->di_cowextsize = 0;
 			*dirty = 1;
-		} else {
-			do_warn(_("would clear cowextsize flag\n"));
-		}
+		} else
+			do_warn(_("would reset to zero\n"));
 	}
 
 	/* nsec fields cannot be larger than 1 billion */

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* Re: [PATCH v2 12/10] xfs_repair: use libxfs extsize/cowextsize validation helpers
  2018-07-26 20:38   ` [PATCH v2 " Darrick J. Wong
@ 2018-07-27 22:44     ` Eric Sandeen
  0 siblings, 0 replies; 29+ messages in thread
From: Eric Sandeen @ 2018-07-27 22:44 UTC (permalink / raw)
  To: Darrick J. Wong, sandeen; +Cc: linux-xfs

On 7/26/18 1:38 PM, Darrick J. Wong wrote:
> From: Darrick J. Wong <darrick.wong@oracle.com>
> 
> Now that we've ported the extent size hint verifiers to libxfs, call
> them from xfs_repair instead of open-coding the checks.  Tweak the
> repair message slightly to reflect the fact that we zero the field and
> clear the inode flag if the hint is garbage or is inconsistent with the
> inode flags.
> 
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
> ---
> v2: fix error message to reflect what actually happened

Much better, thx.

Reviewed-by: Eric Sandeen <sandeen@redhat.com>

> ---
>  libxfs/libxfs_api_defs.h |    2 +
>  repair/dinode.c          |   75 ++++++++++++++++------------------------------
>  2 files changed, 28 insertions(+), 49 deletions(-)
> 
> diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h
> index e5cf1554..fe8336ab 100644
> --- a/libxfs/libxfs_api_defs.h
> +++ b/libxfs/libxfs_api_defs.h
> @@ -98,6 +98,8 @@
>  #define xfs_dinode_calc_crc		libxfs_dinode_calc_crc
>  #define xfs_idata_realloc		libxfs_idata_realloc
>  #define xfs_idestroy_fork		libxfs_idestroy_fork
> +#define xfs_inode_validate_extsize	libxfs_inode_validate_extsize
> +#define xfs_inode_validate_cowextsize	libxfs_inode_validate_cowextsize
>  
>  #define xfs_rmap_ag_owner		libxfs_rmap_ag_owner
>  #define xfs_rmap_alloc			libxfs_rmap_alloc
> diff --git a/repair/dinode.c b/repair/dinode.c
> index fb65ee22..cf1a0ad8 100644
> --- a/repair/dinode.c
> +++ b/repair/dinode.c
> @@ -2841,24 +2841,21 @@ _("bad (negative) size %" PRId64 " on inode %" PRIu64 "\n"),
>  	 * only regular files with REALTIME or EXTSIZE flags set can have
>  	 * extsize set, or directories with EXTSZINHERIT.
>  	 */
> -	if (be32_to_cpu(dino->di_extsize) != 0) {
> -		if ((type == XR_INO_RTDATA) ||
> -		    (type == XR_INO_DIR && (be16_to_cpu(dino->di_flags) &
> -					XFS_DIFLAG_EXTSZINHERIT)) ||
> -		    (type == XR_INO_DATA && (be16_to_cpu(dino->di_flags) &
> -				 XFS_DIFLAG_EXTSIZE)))  {
> -			/* s'okay */ ;
> -		} else {
> -			do_warn(
> -_("bad non-zero extent size %u for non-realtime/extsize inode %" PRIu64 ", "),
> -					be32_to_cpu(dino->di_extsize), lino);
> -			if (!no_modify)  {
> -				do_warn(_("resetting to zero\n"));
> -				dino->di_extsize = 0;
> -				*dirty = 1;
> -			} else
> -				do_warn(_("would reset to zero\n"));
> -		}
> +	if (libxfs_inode_validate_extsize(mp,
> +			be32_to_cpu(dino->di_extsize),
> +			be16_to_cpu(dino->di_mode),
> +			be16_to_cpu(dino->di_flags)) != NULL) {
> +		do_warn(
> +_("Bad extent size %u on inode %" PRIu64 ", "),
> +				be32_to_cpu(dino->di_extsize), lino);
> +		if (!no_modify)  {
> +			do_warn(_("resetting to zero\n"));
> +			dino->di_extsize = 0;
> +			dino->di_flags &= ~cpu_to_be16(XFS_DIFLAG_EXTSIZE |
> +						       XFS_DIFLAG_EXTSZINHERIT);
> +			*dirty = 1;
> +		} else
> +			do_warn(_("would reset to zero\n"));
>  	}
>  
>  	/*
> @@ -2866,41 +2863,21 @@ _("bad non-zero extent size %u for non-realtime/extsize inode %" PRIu64 ", "),
>  	 * set can have extsize set.
>  	 */
>  	if (dino->di_version >= 3 &&
> -	    be32_to_cpu(dino->di_cowextsize) != 0) {
> -		if ((type == XR_INO_DIR || type == XR_INO_DATA) &&
> -		    (be64_to_cpu(dino->di_flags2) &
> -					XFS_DIFLAG2_COWEXTSIZE)) {
> -			/* s'okay */ ;
> -		} else {
> -			do_warn(
> -_("Cannot have non-zero CoW extent size %u on non-cowextsize inode %" PRIu64 ", "),
> -					be32_to_cpu(dino->di_cowextsize), lino);
> -			if (!no_modify)  {
> -				do_warn(_("resetting to zero\n"));
> -				dino->di_flags2 &= ~cpu_to_be64(XFS_DIFLAG2_COWEXTSIZE);
> -				dino->di_cowextsize = 0;
> -				*dirty = 1;
> -			} else
> -				do_warn(_("would reset to zero\n"));
> -		}
> -	}
> -
> -	/*
> -	 * Can't have the COWEXTSIZE flag set with no hint.
> -	 */
> -	if (dino->di_version >= 3 &&
> -	    be32_to_cpu(dino->di_cowextsize) == 0 &&
> -	    (be64_to_cpu(dino->di_flags2) & XFS_DIFLAG2_COWEXTSIZE)) {
> +	    libxfs_inode_validate_cowextsize(mp,
> +			be32_to_cpu(dino->di_cowextsize),
> +			be16_to_cpu(dino->di_mode),
> +			be16_to_cpu(dino->di_flags),
> +			be64_to_cpu(dino->di_flags2)) != NULL) {
>  		do_warn(
> -_("Cannot have CoW extent size of zero on cowextsize inode %" PRIu64 ", "),
> -				lino);
> +_("Bad CoW extent size %u on inode %" PRIu64 ", "),
> +				be32_to_cpu(dino->di_cowextsize), lino);
>  		if (!no_modify)  {
> -			do_warn(_("clearing cowextsize flag\n"));
> +			do_warn(_("resetting to zero\n"));
>  			dino->di_flags2 &= ~cpu_to_be64(XFS_DIFLAG2_COWEXTSIZE);
> +			dino->di_cowextsize = 0;
>  			*dirty = 1;
> -		} else {
> -			do_warn(_("would clear cowextsize flag\n"));
> -		}
> +		} else
> +			do_warn(_("would reset to zero\n"));
>  	}
>  
>  	/* nsec fields cannot be larger than 1 billion */
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

^ permalink raw reply	[flat|nested] 29+ messages in thread

end of thread, other threads:[~2018-07-28  0:08 UTC | newest]

Thread overview: 29+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-06-27  2:47 [PATCH 00/10] xfsprogs-4.18: mostly scrub/repair stuff Darrick J. Wong
2018-06-27  2:47 ` [PATCH 01/10] libxfs: remove crc32 functions Darrick J. Wong
2018-06-27  2:47 ` [PATCH 02/10] libfrog: move crc32c code out of libxfs Darrick J. Wong
2018-06-27  2:48 ` [PATCH 03/10] xfs_scrub: destroy workqueues when erroring out Darrick J. Wong
2018-07-26  0:29   ` Eric Sandeen
2018-06-27  2:48 ` [PATCH 04/10] xfs_scrub: schedule and manage optimizations/repairs to the filesystem Darrick J. Wong
2018-07-26  1:06   ` Eric Sandeen
2018-07-26  1:17     ` Darrick J. Wong
2018-06-27  2:48 ` [PATCH 05/10] xfs_scrub: allow developers to force repairs Darrick J. Wong
2018-07-26  1:07   ` Eric Sandeen
2018-06-27  2:48 ` [PATCH 06/10] xfs_scrub: don't error out if an optimize-only repair isn't supported Darrick J. Wong
2018-07-26  1:09   ` Eric Sandeen
2018-06-27  2:48 ` [PATCH 07/10] xfs_scrub: rename NOFIX_COMPLAIN to be less confusing Darrick J. Wong
2018-07-26  1:10   ` Eric Sandeen
2018-06-27  2:48 ` [PATCH 08/10] xfs_scrub: only retry non-permanent repair failures Darrick J. Wong
2018-07-26  1:16   ` Eric Sandeen
2018-07-26  1:19     ` Darrick J. Wong
2018-06-27  2:48 ` [PATCH 09/10] xfs_io: wire up repair ioctl stuff Darrick J. Wong
2018-07-26  1:23   ` Eric Sandeen
2018-06-27  2:48 ` [PATCH 10/10] xfs_repair: use libxfs extsize/cowextsize validation helpers Darrick J. Wong
2018-06-27  3:25   ` Eric Sandeen
2018-06-28 17:28     ` Darrick J. Wong
2018-06-28 17:29 ` [PATCH 11/10] xfs_repair: clear extent size hints when clearing inode core Darrick J. Wong
2018-06-28 19:24   ` Eric Sandeen
2018-06-28 17:30 ` [PATCH 12/10] xfs_repair: use libxfs extsize/cowextsize validation helpers Darrick J. Wong
2018-07-26  1:44   ` Eric Sandeen
2018-07-26  1:48     ` Eric Sandeen
2018-07-26 20:38   ` [PATCH v2 " Darrick J. Wong
2018-07-27 22:44     ` Eric Sandeen

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.