[Ocfs2-test-devel] [PATCH 13/13] Ocfs2-test: Add destructive testcase for reflink_test v3.

Tristan Ye tristan.ye at oracle.com
Wed Nov 11 01:59:40 PST 2009


Per sunil's request, we're going to add a destructive testcase for reflink
to expose an expected issue in existing reflink kernel codes: O_DIRECT writes
will not flush the metadata accordingly when being performed on reflinked files
after the completion of write operation, which means a reflinked file may wrongly
points to an old reflinked extent after a unexpectedly crash of machine.

The v3 testcase was also a somewhat quick&dirty one which incorporate sunil's
suggestions, and add checksum verification for data chunk, we also do the verification
for reflinks in this version.

After doing reflinks, we fork procs to perform random writes on a reflinked file,
and each write is going to be logged accordingly via wire to a remote listener server.
then crash the machine somehow, afterwards, the logfile recorded by listener will be
used for verification.

Signed-off-by: Tristan Ye <tristan.ye at oracle.com>
---
 programs/reflink_tests/crc32table.h         |  151 +++++++++
 programs/reflink_tests/reflink_test.c       |  233 +++++++++++++-
 programs/reflink_tests/reflink_test.h       |   41 +++
 programs/reflink_tests/reflink_test_run.sh  |   60 ++++-
 programs/reflink_tests/reflink_test_utils.c |  477 +++++++++++++++++++++++++++
 5 files changed, 955 insertions(+), 7 deletions(-)
 create mode 100644 programs/reflink_tests/crc32table.h

diff --git a/programs/reflink_tests/crc32table.h b/programs/reflink_tests/crc32table.h
new file mode 100644
index 0000000..ac7e97b
--- /dev/null
+++ b/programs/reflink_tests/crc32table.h
@@ -0,0 +1,151 @@
+/* this file is generated - do not edit */
+
+/*
+ * This file is generated in the kernel sources by lib/gen_crc32table.c.
+ * The following includes and defines are for our usage.
+ */
+#include <inttypes.h>
+#include <byteswap.h>
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+# define tole(x) ((uint32_t)(x))
+# define tobe(x) ((uint32_t)__bswap_constant_32(x))
+#elif __BYTE_ORDER == __BIG_ENDIAN
+# define tole(x) ((uint32_t)__bswap_constant_32(x))
+# define tobe(x) ((uint32_t)(x))
+#else
+# error Invalid byte order __BYTE_ORDER
+#endif
+
+static const uint32_t crc32table_le[] = {
+tole(0x00000000L), tole(0x77073096L), tole(0xee0e612cL), tole(0x990951baL),
+tole(0x076dc419L), tole(0x706af48fL), tole(0xe963a535L), tole(0x9e6495a3L),
+tole(0x0edb8832L), tole(0x79dcb8a4L), tole(0xe0d5e91eL), tole(0x97d2d988L),
+tole(0x09b64c2bL), tole(0x7eb17cbdL), tole(0xe7b82d07L), tole(0x90bf1d91L),
+tole(0x1db71064L), tole(0x6ab020f2L), tole(0xf3b97148L), tole(0x84be41deL),
+tole(0x1adad47dL), tole(0x6ddde4ebL), tole(0xf4d4b551L), tole(0x83d385c7L),
+tole(0x136c9856L), tole(0x646ba8c0L), tole(0xfd62f97aL), tole(0x8a65c9ecL),
+tole(0x14015c4fL), tole(0x63066cd9L), tole(0xfa0f3d63L), tole(0x8d080df5L),
+tole(0x3b6e20c8L), tole(0x4c69105eL), tole(0xd56041e4L), tole(0xa2677172L),
+tole(0x3c03e4d1L), tole(0x4b04d447L), tole(0xd20d85fdL), tole(0xa50ab56bL),
+tole(0x35b5a8faL), tole(0x42b2986cL), tole(0xdbbbc9d6L), tole(0xacbcf940L),
+tole(0x32d86ce3L), tole(0x45df5c75L), tole(0xdcd60dcfL), tole(0xabd13d59L),
+tole(0x26d930acL), tole(0x51de003aL), tole(0xc8d75180L), tole(0xbfd06116L),
+tole(0x21b4f4b5L), tole(0x56b3c423L), tole(0xcfba9599L), tole(0xb8bda50fL),
+tole(0x2802b89eL), tole(0x5f058808L), tole(0xc60cd9b2L), tole(0xb10be924L),
+tole(0x2f6f7c87L), tole(0x58684c11L), tole(0xc1611dabL), tole(0xb6662d3dL),
+tole(0x76dc4190L), tole(0x01db7106L), tole(0x98d220bcL), tole(0xefd5102aL),
+tole(0x71b18589L), tole(0x06b6b51fL), tole(0x9fbfe4a5L), tole(0xe8b8d433L),
+tole(0x7807c9a2L), tole(0x0f00f934L), tole(0x9609a88eL), tole(0xe10e9818L),
+tole(0x7f6a0dbbL), tole(0x086d3d2dL), tole(0x91646c97L), tole(0xe6635c01L),
+tole(0x6b6b51f4L), tole(0x1c6c6162L), tole(0x856530d8L), tole(0xf262004eL),
+tole(0x6c0695edL), tole(0x1b01a57bL), tole(0x8208f4c1L), tole(0xf50fc457L),
+tole(0x65b0d9c6L), tole(0x12b7e950L), tole(0x8bbeb8eaL), tole(0xfcb9887cL),
+tole(0x62dd1ddfL), tole(0x15da2d49L), tole(0x8cd37cf3L), tole(0xfbd44c65L),
+tole(0x4db26158L), tole(0x3ab551ceL), tole(0xa3bc0074L), tole(0xd4bb30e2L),
+tole(0x4adfa541L), tole(0x3dd895d7L), tole(0xa4d1c46dL), tole(0xd3d6f4fbL),
+tole(0x4369e96aL), tole(0x346ed9fcL), tole(0xad678846L), tole(0xda60b8d0L),
+tole(0x44042d73L), tole(0x33031de5L), tole(0xaa0a4c5fL), tole(0xdd0d7cc9L),
+tole(0x5005713cL), tole(0x270241aaL), tole(0xbe0b1010L), tole(0xc90c2086L),
+tole(0x5768b525L), tole(0x206f85b3L), tole(0xb966d409L), tole(0xce61e49fL),
+tole(0x5edef90eL), tole(0x29d9c998L), tole(0xb0d09822L), tole(0xc7d7a8b4L),
+tole(0x59b33d17L), tole(0x2eb40d81L), tole(0xb7bd5c3bL), tole(0xc0ba6cadL),
+tole(0xedb88320L), tole(0x9abfb3b6L), tole(0x03b6e20cL), tole(0x74b1d29aL),
+tole(0xead54739L), tole(0x9dd277afL), tole(0x04db2615L), tole(0x73dc1683L),
+tole(0xe3630b12L), tole(0x94643b84L), tole(0x0d6d6a3eL), tole(0x7a6a5aa8L),
+tole(0xe40ecf0bL), tole(0x9309ff9dL), tole(0x0a00ae27L), tole(0x7d079eb1L),
+tole(0xf00f9344L), tole(0x8708a3d2L), tole(0x1e01f268L), tole(0x6906c2feL),
+tole(0xf762575dL), tole(0x806567cbL), tole(0x196c3671L), tole(0x6e6b06e7L),
+tole(0xfed41b76L), tole(0x89d32be0L), tole(0x10da7a5aL), tole(0x67dd4accL),
+tole(0xf9b9df6fL), tole(0x8ebeeff9L), tole(0x17b7be43L), tole(0x60b08ed5L),
+tole(0xd6d6a3e8L), tole(0xa1d1937eL), tole(0x38d8c2c4L), tole(0x4fdff252L),
+tole(0xd1bb67f1L), tole(0xa6bc5767L), tole(0x3fb506ddL), tole(0x48b2364bL),
+tole(0xd80d2bdaL), tole(0xaf0a1b4cL), tole(0x36034af6L), tole(0x41047a60L),
+tole(0xdf60efc3L), tole(0xa867df55L), tole(0x316e8eefL), tole(0x4669be79L),
+tole(0xcb61b38cL), tole(0xbc66831aL), tole(0x256fd2a0L), tole(0x5268e236L),
+tole(0xcc0c7795L), tole(0xbb0b4703L), tole(0x220216b9L), tole(0x5505262fL),
+tole(0xc5ba3bbeL), tole(0xb2bd0b28L), tole(0x2bb45a92L), tole(0x5cb36a04L),
+tole(0xc2d7ffa7L), tole(0xb5d0cf31L), tole(0x2cd99e8bL), tole(0x5bdeae1dL),
+tole(0x9b64c2b0L), tole(0xec63f226L), tole(0x756aa39cL), tole(0x026d930aL),
+tole(0x9c0906a9L), tole(0xeb0e363fL), tole(0x72076785L), tole(0x05005713L),
+tole(0x95bf4a82L), tole(0xe2b87a14L), tole(0x7bb12baeL), tole(0x0cb61b38L),
+tole(0x92d28e9bL), tole(0xe5d5be0dL), tole(0x7cdcefb7L), tole(0x0bdbdf21L),
+tole(0x86d3d2d4L), tole(0xf1d4e242L), tole(0x68ddb3f8L), tole(0x1fda836eL),
+tole(0x81be16cdL), tole(0xf6b9265bL), tole(0x6fb077e1L), tole(0x18b74777L),
+tole(0x88085ae6L), tole(0xff0f6a70L), tole(0x66063bcaL), tole(0x11010b5cL),
+tole(0x8f659effL), tole(0xf862ae69L), tole(0x616bffd3L), tole(0x166ccf45L),
+tole(0xa00ae278L), tole(0xd70dd2eeL), tole(0x4e048354L), tole(0x3903b3c2L),
+tole(0xa7672661L), tole(0xd06016f7L), tole(0x4969474dL), tole(0x3e6e77dbL),
+tole(0xaed16a4aL), tole(0xd9d65adcL), tole(0x40df0b66L), tole(0x37d83bf0L),
+tole(0xa9bcae53L), tole(0xdebb9ec5L), tole(0x47b2cf7fL), tole(0x30b5ffe9L),
+tole(0xbdbdf21cL), tole(0xcabac28aL), tole(0x53b39330L), tole(0x24b4a3a6L),
+tole(0xbad03605L), tole(0xcdd70693L), tole(0x54de5729L), tole(0x23d967bfL),
+tole(0xb3667a2eL), tole(0xc4614ab8L), tole(0x5d681b02L), tole(0x2a6f2b94L),
+tole(0xb40bbe37L), tole(0xc30c8ea1L), tole(0x5a05df1bL), tole(0x2d02ef8dL)
+};
+
+static const uint32_t crc32table_be[] = {
+tobe(0x00000000L), tobe(0x04c11db7L), tobe(0x09823b6eL), tobe(0x0d4326d9L),
+tobe(0x130476dcL), tobe(0x17c56b6bL), tobe(0x1a864db2L), tobe(0x1e475005L),
+tobe(0x2608edb8L), tobe(0x22c9f00fL), tobe(0x2f8ad6d6L), tobe(0x2b4bcb61L),
+tobe(0x350c9b64L), tobe(0x31cd86d3L), tobe(0x3c8ea00aL), tobe(0x384fbdbdL),
+tobe(0x4c11db70L), tobe(0x48d0c6c7L), tobe(0x4593e01eL), tobe(0x4152fda9L),
+tobe(0x5f15adacL), tobe(0x5bd4b01bL), tobe(0x569796c2L), tobe(0x52568b75L),
+tobe(0x6a1936c8L), tobe(0x6ed82b7fL), tobe(0x639b0da6L), tobe(0x675a1011L),
+tobe(0x791d4014L), tobe(0x7ddc5da3L), tobe(0x709f7b7aL), tobe(0x745e66cdL),
+tobe(0x9823b6e0L), tobe(0x9ce2ab57L), tobe(0x91a18d8eL), tobe(0x95609039L),
+tobe(0x8b27c03cL), tobe(0x8fe6dd8bL), tobe(0x82a5fb52L), tobe(0x8664e6e5L),
+tobe(0xbe2b5b58L), tobe(0xbaea46efL), tobe(0xb7a96036L), tobe(0xb3687d81L),
+tobe(0xad2f2d84L), tobe(0xa9ee3033L), tobe(0xa4ad16eaL), tobe(0xa06c0b5dL),
+tobe(0xd4326d90L), tobe(0xd0f37027L), tobe(0xddb056feL), tobe(0xd9714b49L),
+tobe(0xc7361b4cL), tobe(0xc3f706fbL), tobe(0xceb42022L), tobe(0xca753d95L),
+tobe(0xf23a8028L), tobe(0xf6fb9d9fL), tobe(0xfbb8bb46L), tobe(0xff79a6f1L),
+tobe(0xe13ef6f4L), tobe(0xe5ffeb43L), tobe(0xe8bccd9aL), tobe(0xec7dd02dL),
+tobe(0x34867077L), tobe(0x30476dc0L), tobe(0x3d044b19L), tobe(0x39c556aeL),
+tobe(0x278206abL), tobe(0x23431b1cL), tobe(0x2e003dc5L), tobe(0x2ac12072L),
+tobe(0x128e9dcfL), tobe(0x164f8078L), tobe(0x1b0ca6a1L), tobe(0x1fcdbb16L),
+tobe(0x018aeb13L), tobe(0x054bf6a4L), tobe(0x0808d07dL), tobe(0x0cc9cdcaL),
+tobe(0x7897ab07L), tobe(0x7c56b6b0L), tobe(0x71159069L), tobe(0x75d48ddeL),
+tobe(0x6b93dddbL), tobe(0x6f52c06cL), tobe(0x6211e6b5L), tobe(0x66d0fb02L),
+tobe(0x5e9f46bfL), tobe(0x5a5e5b08L), tobe(0x571d7dd1L), tobe(0x53dc6066L),
+tobe(0x4d9b3063L), tobe(0x495a2dd4L), tobe(0x44190b0dL), tobe(0x40d816baL),
+tobe(0xaca5c697L), tobe(0xa864db20L), tobe(0xa527fdf9L), tobe(0xa1e6e04eL),
+tobe(0xbfa1b04bL), tobe(0xbb60adfcL), tobe(0xb6238b25L), tobe(0xb2e29692L),
+tobe(0x8aad2b2fL), tobe(0x8e6c3698L), tobe(0x832f1041L), tobe(0x87ee0df6L),
+tobe(0x99a95df3L), tobe(0x9d684044L), tobe(0x902b669dL), tobe(0x94ea7b2aL),
+tobe(0xe0b41de7L), tobe(0xe4750050L), tobe(0xe9362689L), tobe(0xedf73b3eL),
+tobe(0xf3b06b3bL), tobe(0xf771768cL), tobe(0xfa325055L), tobe(0xfef34de2L),
+tobe(0xc6bcf05fL), tobe(0xc27dede8L), tobe(0xcf3ecb31L), tobe(0xcbffd686L),
+tobe(0xd5b88683L), tobe(0xd1799b34L), tobe(0xdc3abdedL), tobe(0xd8fba05aL),
+tobe(0x690ce0eeL), tobe(0x6dcdfd59L), tobe(0x608edb80L), tobe(0x644fc637L),
+tobe(0x7a089632L), tobe(0x7ec98b85L), tobe(0x738aad5cL), tobe(0x774bb0ebL),
+tobe(0x4f040d56L), tobe(0x4bc510e1L), tobe(0x46863638L), tobe(0x42472b8fL),
+tobe(0x5c007b8aL), tobe(0x58c1663dL), tobe(0x558240e4L), tobe(0x51435d53L),
+tobe(0x251d3b9eL), tobe(0x21dc2629L), tobe(0x2c9f00f0L), tobe(0x285e1d47L),
+tobe(0x36194d42L), tobe(0x32d850f5L), tobe(0x3f9b762cL), tobe(0x3b5a6b9bL),
+tobe(0x0315d626L), tobe(0x07d4cb91L), tobe(0x0a97ed48L), tobe(0x0e56f0ffL),
+tobe(0x1011a0faL), tobe(0x14d0bd4dL), tobe(0x19939b94L), tobe(0x1d528623L),
+tobe(0xf12f560eL), tobe(0xf5ee4bb9L), tobe(0xf8ad6d60L), tobe(0xfc6c70d7L),
+tobe(0xe22b20d2L), tobe(0xe6ea3d65L), tobe(0xeba91bbcL), tobe(0xef68060bL),
+tobe(0xd727bbb6L), tobe(0xd3e6a601L), tobe(0xdea580d8L), tobe(0xda649d6fL),
+tobe(0xc423cd6aL), tobe(0xc0e2d0ddL), tobe(0xcda1f604L), tobe(0xc960ebb3L),
+tobe(0xbd3e8d7eL), tobe(0xb9ff90c9L), tobe(0xb4bcb610L), tobe(0xb07daba7L),
+tobe(0xae3afba2L), tobe(0xaafbe615L), tobe(0xa7b8c0ccL), tobe(0xa379dd7bL),
+tobe(0x9b3660c6L), tobe(0x9ff77d71L), tobe(0x92b45ba8L), tobe(0x9675461fL),
+tobe(0x8832161aL), tobe(0x8cf30badL), tobe(0x81b02d74L), tobe(0x857130c3L),
+tobe(0x5d8a9099L), tobe(0x594b8d2eL), tobe(0x5408abf7L), tobe(0x50c9b640L),
+tobe(0x4e8ee645L), tobe(0x4a4ffbf2L), tobe(0x470cdd2bL), tobe(0x43cdc09cL),
+tobe(0x7b827d21L), tobe(0x7f436096L), tobe(0x7200464fL), tobe(0x76c15bf8L),
+tobe(0x68860bfdL), tobe(0x6c47164aL), tobe(0x61043093L), tobe(0x65c52d24L),
+tobe(0x119b4be9L), tobe(0x155a565eL), tobe(0x18197087L), tobe(0x1cd86d30L),
+tobe(0x029f3d35L), tobe(0x065e2082L), tobe(0x0b1d065bL), tobe(0x0fdc1becL),
+tobe(0x3793a651L), tobe(0x3352bbe6L), tobe(0x3e119d3fL), tobe(0x3ad08088L),
+tobe(0x2497d08dL), tobe(0x2056cd3aL), tobe(0x2d15ebe3L), tobe(0x29d4f654L),
+tobe(0xc5a92679L), tobe(0xc1683bceL), tobe(0xcc2b1d17L), tobe(0xc8ea00a0L),
+tobe(0xd6ad50a5L), tobe(0xd26c4d12L), tobe(0xdf2f6bcbL), tobe(0xdbee767cL),
+tobe(0xe3a1cbc1L), tobe(0xe760d676L), tobe(0xea23f0afL), tobe(0xeee2ed18L),
+tobe(0xf0a5bd1dL), tobe(0xf464a0aaL), tobe(0xf9278673L), tobe(0xfde69bc4L),
+tobe(0x89b8fd09L), tobe(0x8d79e0beL), tobe(0x803ac667L), tobe(0x84fbdbd0L),
+tobe(0x9abc8bd5L), tobe(0x9e7d9662L), tobe(0x933eb0bbL), tobe(0x97ffad0cL),
+tobe(0xafb010b1L), tobe(0xab710d06L), tobe(0xa6322bdfL), tobe(0xa2f33668L),
+tobe(0xbcb4666dL), tobe(0xb8757bdaL), tobe(0xb5365d03L), tobe(0xb1f740b4L)
+};
diff --git a/programs/reflink_tests/reflink_test.c b/programs/reflink_tests/reflink_test.c
index ea05567..41bd544 100755
--- a/programs/reflink_tests/reflink_test.c
+++ b/programs/reflink_tests/reflink_test.c
@@ -50,8 +50,13 @@ static char ref_path[PATH_MAX];
 static char fh_log_orig[PATH_MAX];
 static char fh_log_dest[PATH_MAX];
 
+static char dest_log_path[PATH_MAX];
+
+static char lsnr_addr[HOSTNAME_LEN];
+
 static int iteration = 1;
 static int testno = 1;
+static unsigned long port = 9999;
 
 static unsigned long ref_counts = 10;
 static unsigned long ref_trees = 10;
@@ -103,7 +108,7 @@ static void usage(void)
 	printf("Usage: reflink_tests [-i iteration] <-n ref_counts> "
 	       "<-p refcount_tree_pairs> <-l file_size> <-d disk> "
 	       "<-w workplace> -f -b [-c conc_procs] -m -s -r [-x xattr_nums]"
-	       " [-h holes_num] [-o holes_filling_log] -O -I\n\n"
+	       " [-h holes_num] [-o holes_filling_log] -O -D <child_nums> -I\n\n"
 	       "-f enable basic feature test.\n"
 	       "-b enable boundary test.\n"
 	       "-c enable concurrent tests with conc_procs processes.\n"
@@ -111,12 +116,16 @@ static void usage(void)
 	       "-r enable random test.\n"
 	       "-s enable stress test.\n"
 	       "-O enable O_DIRECT test.\n"
+	       "-D enable destructive test.\n"
+	       "-v enable verification for destructive test.\n"
 	       "-I enable inline-data test.\n"
 	       "-x enable combination test with xattr.\n"
 	       "-h enable holes punching and filling tests.\n"
 	       "-o specify logfile for holes filling tests,it takes effect"
 	       " when -h enabled.\n"
 	       "-p specify number of refcount trees in fs.\n"
+	       "-a specify listener's ip addr for destructive test.\n"
+	       "-P specify listener's listening port for destructive test.\n"
 	       "iteration specify the running times.\n"
 	       "ref_counts specify the reflinks number for one shared inode.\n"
 	       "refcount_tree_pairs specify the refcount tree numbers in fs.\n"
@@ -133,7 +142,7 @@ static int parse_opts(int argc, char **argv)
 	while (1) {
 		c = getopt(argc, argv,
 			   "i:d:w:IOfFbBsSrRmMW:n:N:"
-			   "l:L:c:C:p:P:x:X:h:H:o:");
+			   "l:L:c:C:p:x:X:h:H:o:v:a:P:D:");
 		if (c == -1)
 			break;
 
@@ -146,7 +155,6 @@ static int parse_opts(int argc, char **argv)
 			ref_counts = atol(optarg);
 			break;
 		case 'p':
-		case 'P':
 			ref_trees = atol(optarg);
 			break;
 		case 'l':
@@ -159,6 +167,10 @@ static int parse_opts(int argc, char **argv)
 		case 'O':
 			test_flags |= ODCT_TEST;
 			break;
+		case 'D':
+			test_flags |= DSCV_TEST;
+			child_nums = atol(optarg);
+			break;
 		case 'I':
 			test_flags |= INLN_TEST;
 			xattr_nums = 100;
@@ -170,6 +182,13 @@ static int parse_opts(int argc, char **argv)
 		case 'o':
 			strcpy(fh_log_orig, optarg);
 			break;
+		case 'v':
+			strcpy(dest_log_path, optarg);
+			test_flags |= VERI_TEST;
+			break;
+		case 'a':
+			strcpy(lsnr_addr, optarg);
+			break;
 		case 'f':
 		case 'F':
 			test_flags |= BASC_TEST;
@@ -204,6 +223,8 @@ static int parse_opts(int argc, char **argv)
 		case 'H':
 			test_flags |= HOLE_TEST;
 			hole_nums = atol(optarg);
+		case 'P':
+			port = atol(optarg);
 		default:
 			break;
 		}
@@ -215,6 +236,10 @@ static int parse_opts(int argc, char **argv)
 	if (strcmp(device, "") == 0)
 		return EINVAL;
 
+	if (test_flags & DSCV_TEST)
+		if (strcmp(lsnr_addr, "") == 0)
+			return EINVAL;
+
 	return 0;
 }
 
@@ -890,7 +915,7 @@ static int concurrent_test()
 
 	signal(SIGCHLD, sigchld_handler);
 
-	 for (i = 0; i < child_nums; i++) {
+	for (i = 0; i < child_nums; i++) {
 
 		pid = fork();
 
@@ -1768,6 +1793,200 @@ static int holes_fill_test(void)
 	return 0;
 }
 
+static int destructive_test(void)
+{
+	int o_flags_rw, o_flags_ro, sockfd, i, j, status;
+	int ret, o_ret, fd, rc, sub_testno = 1;
+	char log_rec[1024], dest[PATH_MAX];
+
+	struct dest_write_unit dwu;
+
+	unsigned long align_slice = CHUNK_SIZE;
+	unsigned long align_filesz = align_slice;
+	unsigned long chunk_no = 0;
+
+	pid_t pid;
+
+	while (align_filesz < file_size)
+		align_filesz += CHUNK_SIZE;
+
+	chunk_no = file_size / CHUNK_SIZE;
+
+	printf("Test %d: Destructive reflink test.\n", testno);
+
+	o_flags_rw = open_rw_flags;
+	o_flags_ro = open_ro_flags;
+
+	open_rw_flags |= O_DIRECT;
+	open_ro_flags |= O_DIRECT;
+
+	snprintf(orig_path, PATH_MAX, "%s/original_destructive_refile",
+		 workplace);
+
+	printf("  *SubTest %d: Prepare original file in %ld chunks.\n",
+	       sub_testno++, chunk_no);
+
+	ret = prep_orig_file_in_chunks(orig_path, chunk_no);
+	should_exit(ret);
+
+	printf("  *SubTest %d: Do reflinks to reflink the extents.\n",
+	       sub_testno++);
+
+	ret = do_reflinks(orig_path, orig_path, ref_counts, 0);
+	should_exit(ret);
+
+	sync();
+
+	/*flush out the father's i/o buffer*/
+	fflush(stderr);
+	fflush(stdout);
+
+	signal(SIGCHLD, sigchld_handler);
+
+	printf("  *SubTest %d: Init socket for msg sending\n", sub_testno++);
+
+	sockfd = init_sock(lsnr_addr, port);
+
+	printf("  *SubTest %d: Fork %lu children to write in chunks.\n",
+	       sub_testno++, child_nums);
+
+	fd  = open64(orig_path, open_rw_flags);
+	if (fd < 0) {
+		o_ret = fd;
+		fd = errno;
+		fprintf(stderr, "open file %s failed:%d:%s\n", orig_path, fd,
+			strerror(fd));
+		fd = o_ret;
+		return fd;
+	}
+
+	for (i = 0; i < child_nums; i++) {
+
+		pid = fork();
+
+		if (pid < 0) {
+			fprintf(stderr, "Fork process error!\n");
+			return pid;
+		}
+
+		/* child to do CoW*/
+		if (pid == 0) {
+
+			srand(getpid());
+
+			for (j = 0; j < chunk_no; j++) {
+
+				memset(log_rec, 0, sizeof(log_rec));
+				prep_rand_dest_write_unit(&dwu, get_rand(0,
+							  chunk_no - 1));
+				snprintf(log_rec, sizeof(log_rec), "%lu\t%llu"
+					 "\t%d\t%c\n", dwu.d_chunk_no,
+					 dwu.d_timestamp, dwu.d_checksum,
+					 dwu.d_char);
+
+				ret = do_write_chunk(fd, &dwu);
+				if (ret)
+					return -1;
+				write(sockfd, log_rec, strlen(log_rec) + 1);
+
+				if (get_rand(0, 1)) {
+					snprintf(dest, PATH_MAX,
+						 "%s_target_%d_%d",
+						 orig_path, getpid(), j);
+					ret = reflink(orig_path, dest, 1);
+					should_exit(ret);
+					memset(log_rec, 0, sizeof(log_rec));
+					snprintf(log_rec, sizeof(log_rec),
+						 "Reflink:\t%s\t->\t%s\n",
+						 orig_path, dest);
+					write(sockfd, log_rec,
+					      strlen(log_rec) + 1);
+
+				}
+
+				/*
+				 * Are you ready to crash the machine?
+				*/
+
+				if ((j > 1) && (j < chunk_no - 1)) {
+					if (get_rand(1, chunk_no) == chunk_no / 2)
+						system("echo b>/proc/sysrq-trigger");
+				} else if (j == chunk_no - 1)
+						system("echo b>/proc/sysrq-trigger");
+
+				usleep(10000);
+			}
+
+			if (!fd)
+				close(fd);
+
+			if (!sockfd)
+				close(sockfd);
+
+			exit(0);
+		}
+
+		if (pid > 0)
+			child_pid_list[i] = pid;
+	}
+
+	signal(SIGINT, sigint_handler);
+	signal(SIGTERM, sigterm_handler);
+
+	/*father wait all children to leave*/
+	for (i = 0; i < child_nums; i++) {
+		ret = waitpid(child_pid_list[i], &status, 0);
+		rc = WEXITSTATUS(status);
+		if (rc) {
+			fprintf(stderr, "Child %d exits abnormally with "
+				"RC=%d\n", child_pid_list[i], rc);
+		}
+	}
+
+	open_rw_flags = o_flags_rw;
+	open_ro_flags = o_flags_ro;
+
+	/*
+	ret = do_unlinks(orig_path, ref_counts);
+	should_exit(ret);
+
+	ret = do_unlink(orig_path);
+	should_exit(ret);
+	*/
+
+	if (fd)
+		close(fd);
+
+	if (sockfd)
+		close(sockfd);
+
+	return 0;
+}
+
+static int verification_dest(void)
+{
+
+	unsigned long align_slice = CHUNK_SIZE;
+	unsigned long align_filesz = align_slice;
+	unsigned long chunk_no = 0;
+	int ret;
+
+	while (align_filesz < file_size)
+		align_filesz += CHUNK_SIZE;
+
+	chunk_no = file_size / CHUNK_SIZE;
+
+	printf("Test %d: Verification for destructive test.\n", testno);
+
+	snprintf(orig_path, PATH_MAX, "%s/original_destructive_refile",
+		 workplace);
+
+	ret = verify_dest_files(dest_log_path, orig_path, chunk_no);
+	should_exit(ret);
+
+	return ret;
+}
+
 static int directio_test(void)
 {
 
@@ -2005,6 +2224,12 @@ static void run_test(void)
 		if (test_flags & INLN_TEST)
 			inline_test();
 
+		if (test_flags & DSCV_TEST)
+			destructive_test();
+
+		if (test_flags & VERI_TEST)
+			verification_dest();
+
 	}
 }
 
diff --git a/programs/reflink_tests/reflink_test.h b/programs/reflink_tests/reflink_test.h
index 3f7b263..6b12e84 100755
--- a/programs/reflink_tests/reflink_test.h
+++ b/programs/reflink_tests/reflink_test.h
@@ -33,6 +33,7 @@
 #include <sys/ioctl.h>
 #include <inttypes.h>
 #include <linux/types.h>
+#include <sys/time.h>
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -40,7 +41,14 @@
 #include <assert.h>
 #include <getopt.h>
 
+#include <sys/socket.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
 #include <ocfs2/ocfs2.h>
+#include <ocfs2/byteorder.h>
+#include "crc32table.h"
 
 #define OCFS2_MAX_FILENAME_LEN	255
 #define FILE_RW_FLAGS		(O_CREAT|O_RDWR)
@@ -66,6 +74,8 @@
 #define HOLE_TEST		0x00000200
 #define ODCT_TEST		0x00000400
 #define INLN_TEST		0x00000800
+#define DSCV_TEST		0x00001000
+#define VERI_TEST		0x00002000
 
 #define MPI_RET_SUCCESS		0
 #define MPI_RET_FAILED		1
@@ -74,12 +84,27 @@
 #define RAND_CHAR_START 'A'
 #define MAGIC_HOLE_CHAR (RAND_CHAR_START - 1)
 
+#define CHUNK_SIZE	(1024*8)
+#define HOSTNAME_LEN	256
+
 struct write_unit {
 	char w_char;
 	unsigned long w_offset;
 	unsigned int  w_len;
 };
 
+struct dest_write_unit{
+	unsigned long d_chunk_no;
+	unsigned long long d_timestamp;
+	uint32_t d_checksum;
+	char d_char;
+};
+
+struct dest_logs {
+	char filename[PATH_MAX];
+	unsigned long index;
+};
+
 char rand_char(void);
 unsigned long get_rand(unsigned long min, unsigned long max);
 int get_rand_buf(char *buf, unsigned long size);
@@ -97,6 +122,7 @@ int mmap_write_at_file(char *pathname, const void *buf, size_t count,
 int fill_pattern(unsigned long size);
 int prep_orig_file(char *file_name, unsigned long size, int once);
 int prep_orig_file_dio(char *file_name, unsigned long size);
+int prep_orig_file_in_chunks(char *file_name, unsigned long chunks);
 int verify_pattern(char *buf, unsigned long offset, unsigned long size);
 int verify_orig_file(char *orig);
 
@@ -124,4 +150,19 @@ void prep_rand_write_unit(struct write_unit *wu);
 int do_write(int fd, struct write_unit *wu);
 int do_write_file(char *fname, struct write_unit *wu);
 
+unsigned long long get_time_microseconds(void);
+void prep_rand_dest_write_unit(struct dest_write_unit *dwu,
+			       unsigned long chunk_no);
+int fill_chunk_pattern(char *pattern, struct dest_write_unit *dwu);
+int dump_pattern(char *pattern, struct dest_write_unit *dwu);
+int verify_chunk_pattern(char *pattern, struct dest_write_unit *dwu);
+int do_write_chunk(int fd, struct dest_write_unit *dwu);
+/*
+int do_write_chunk_file(char *fname, struct dest_write_unit *du);
+*/
+int init_sock(char *serv, int port);
+long get_verify_logs_num(char *log);
+int verify_dest_file(char *log, struct dest_logs d_log, unsigned long chunk_no);
+int verify_dest_files(char *log, char *orig, unsigned long chunk_no);
+uint32_t crc32_checksum(uint32_t crc, char *p, size_t len);
 #endif
diff --git a/programs/reflink_tests/reflink_test_run.sh b/programs/reflink_tests/reflink_test_run.sh
index 0c2420f..097a97a 100755
--- a/programs/reflink_tests/reflink_test_run.sh
+++ b/programs/reflink_tests/reflink_test_run.sh
@@ -66,6 +66,13 @@ WORK_PLACE=
 
 MOUNT_OPTS=
 
+DSCV_TEST=
+LISTENER_ADDR=
+LISTENER_PORT=
+
+VERI_TEST=
+VERI_LOG=
+
 REFLINK_TEST_BIN="${BINDIR}/reflink_test"
 FILL_HOLES_BIN="${BINDIR}/fill_holes"
 VERIFY_HOLES_BIN="${BINDIR}/verify_holes"
@@ -85,11 +92,13 @@ set -o pipefail
 ################################################################################
 function f_usage()
 {
-        echo "usage: `basename ${0}` [-W] [-o logdir] <-d device>\
- <mountpoint path>"
+        echo "usage: `basename ${0}` [-D <-a remote_listener_addr> <-p port>] \
+[-v verify_log] [-W] [-o logdir] <-d device> <mountpoint path>"
         echo "       -o output directory for the logs"
         echo "       -d block device name used for ocfs2 volume"
         echo "       -W enable data=writeback mode"
+	echo "       -D enable destructive test,it will crash the testing node,\
+be cautious, you need to specify listener addr and port then"
         echo "       <mountpoint path> specify the testing mounting point."
         exit 1;
 
@@ -102,11 +111,15 @@ function f_getoptions()
                 exit 1
          fi
 
-         while getopts "o:Whd:" options; do
+         while getopts "o:WDhd:a:p:v:" options; do
                 case $options in
                 o ) LOG_DIR="$OPTARG";;
                 d ) DEVICE="$OPTARG";;
 		W ) MOUNT_OPTS="data=writeback";;
+		D ) DSCV_TEST="1";;
+		a ) LISTENER_ADDR="$OPTARG";;
+		p ) LISTENER_PORT="$OPTARG";;
+		v ) VERI_LOG="$OPTARG";;
                 h ) f_usage;;
                 * ) f_usage;;
                 esac
@@ -136,6 +149,22 @@ function f_check()
                 fi
         fi
 
+	if [ -n "${DSCV_TEST}" ];then
+		if [ -z "${LISTENER_ADDR}" -o -z "${LISTENER_PORT}" ];then
+			echo "You need to specify listener address and port in destructive test."
+			exit 1
+		fi
+	fi
+
+	if [ -n "${VERI_LOG}" ];then
+		if [ ! -f "${VERI_LOG}" ];then
+			echo "Please specify a legal verify log file."
+			exit 1
+		else
+			VERI_TEST="1"
+		fi
+	fi
+
         LOG_DIR=${LOG_DIR:-$DEFAULT_LOG}
 	${MKDIR_BIN} -p ${LOG_DIR} || exit 1
 
@@ -381,6 +410,31 @@ ${DEVICE} "refcount,xattr" ${JOURNALSIZE} ${BLOCKS}
 	WORK_PLACE=${MOUNT_POINT}/${WORK_PLACE_DIRENT}
 	${MKDIR_BIN} -p ${WORK_PLACE}
 
+	if [ -n "${VERI_TEST}" ];then
+	((TEST_NO++))
+	f_LogRunMsg ${RUN_LOG_FILE} "[${TEST_NO}] Verify Test After Desctruction :"
+	f_LogMsg ${LOG_FILE} "[${TEST_NO}] Verify Test After Desctruction, CMD:${SUDO} \
+${REFLINK_TEST_BIN} -i 1 -n 10 -p 10 -l 1638400 -d ${DEVICE} -w ${WORK_PLACE} -v ${VERI_LOG} "
+	${SUDO} ${REFLINK_TEST_BIN} -i 1 -n 10 -p 10 -l 1638400 -d ${DEVICE} -w \
+${WORK_PLACE} -v ${VERI_LOG} >>${LOG_FILE} 2>&1
+        RET=$?
+        f_echo_status ${RET} | tee -a ${RUN_LOG_FILE}
+	exit ${RET}
+	fi
+
+	if [ -n "${DSCV_TEST}" ];then
+	((TEST_NO++))
+	f_LogRunMsg ${RUN_LOG_FILE} "[${TEST_NO}] Destructive Test For DirectIO:"
+	f_LogMsg ${LOG_FILE} "[${TEST_NO}] Destructive Test For DirectIO, CMD:${SUDO} \
+${REFLINK_TEST_BIN} -i 1 -n 10 -p 10 -l 1638400 -d ${DEVICE} -w ${WORK_PLACE} \
+-D 10 -a ${LISTENER_ADDR} -P ${LISTENER_PORT} "
+	${SUDO} ${REFLINK_TEST_BIN} -i 1 -n 10 -p 10 -l 1638400 -d ${DEVICE} -w \
+${WORK_PLACE} -D 10 -a ${LISTENER_ADDR} -p ${LISTENER_ADDR} >>${LOG_FILE} 2>&1
+        RET=$?
+        f_echo_status ${RET} | tee -a ${RUN_LOG_FILE}
+	exit ${RET}
+	fi
+
 	((TEST_NO++))
 	f_LogRunMsg ${RUN_LOG_FILE} "[${TEST_NO}] Basic Fucntional Test:"
 	f_LogMsg ${LOG_FILE} "[${TEST_NO}] Basic Fucntional Test, CMD:${SUDO} \
diff --git a/programs/reflink_tests/reflink_test_utils.c b/programs/reflink_tests/reflink_test_utils.c
index b39ae5f..a816255 100755
--- a/programs/reflink_tests/reflink_test_utils.c
+++ b/programs/reflink_tests/reflink_test_utils.c
@@ -41,6 +41,55 @@ extern struct ocfs2_super_block *ocfs2_sb;
 extern char *prog;
 
 static char buf_dio[DIRECTIO_SLICE] __attribute__ ((aligned(DIRECTIO_SLICE)));
+static char chunk_pattern[CHUNK_SIZE] __attribute__ ((aligned(DIRECTIO_SLICE)));
+
+uint32_t crc32_checksum(uint32_t crc, char *p, size_t len)
+{
+	const uint32_t      *b = (uint32_t *)p;
+	const uint32_t      *tab = crc32table_le;
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+# define DO_CRC(x) crc = tab[(crc ^ (x)) & 255] ^ (crc >> 8)
+#else
+# define DO_CRC(x) crc = tab[((crc >> 24) ^ (x)) & 255] ^ (crc << 8)
+#endif
+
+	crc = cpu_to_le32(crc);
+	/* Align it */
+	if (((long)b)&3 && len) {
+		do {
+			uint8_t *p = (uint8_t *)b;
+			DO_CRC(*p++);
+			b = (void *)p;
+		} while ((--len) && ((long)b)&3);
+	}
+	if (len >= 4) {
+		/* load data 32 bits wide, xor data 32 bits wide. */
+		size_t save_len = len & 3;
+		len = len >> 2;
+		--b; /* use pre increment below(*++b) for speed */
+		do {
+			crc ^= *++b;
+			DO_CRC(0);
+			DO_CRC(0);
+			DO_CRC(0);
+			DO_CRC(0);
+		} while (--len);
+		b++; /* point to next byte(s) */
+		len = save_len;
+	}
+	/* And the last few bytes */
+	if (len) {
+		do {
+			uint8_t *p = (uint8_t *)b;
+			DO_CRC(*p++);
+			b = (void *)p;
+		} while (--len);
+	}
+
+	return le32_to_cpu(crc);
+#undef DO_CRC
+}
 
 unsigned long get_rand(unsigned long min, unsigned long max)
 {
@@ -464,6 +513,139 @@ int prep_orig_file_dio(char *file_name, unsigned long size)
 	return 0;
 }
 
+int fill_chunk_pattern(char *pattern, struct dest_write_unit *dwu)
+{
+	unsigned long mem_offset = 0;
+	uint32_t checksum = 0;
+
+	memset(pattern, 0, CHUNK_SIZE);
+	mem_offset = 0;
+
+	memmove(pattern , &dwu->d_chunk_no, sizeof(unsigned long));
+	mem_offset += sizeof(unsigned long);
+	memmove(pattern + mem_offset, &dwu->d_timestamp,
+		sizeof(unsigned long long));
+	mem_offset += sizeof(unsigned long long);
+	/*
+	memmove(pattern + mem_offset, &checksum, sizeof(unsigned long));
+	*/
+	mem_offset += sizeof(uint32_t);
+
+	memset(pattern + mem_offset, dwu->d_char, CHUNK_SIZE - mem_offset * 2);
+
+	checksum = crc32_checksum(~0, pattern + mem_offset,
+				  (size_t)CHUNK_SIZE - mem_offset * 2);
+
+	mem_offset = CHUNK_SIZE - mem_offset;
+
+	memmove(pattern + mem_offset, &checksum, sizeof(uint32_t));
+	mem_offset += sizeof(uint32_t);
+	memmove(pattern + mem_offset, &dwu->d_timestamp,
+		sizeof(unsigned long long));
+	mem_offset += sizeof(unsigned long long);
+	memmove(pattern + mem_offset, &dwu->d_chunk_no, sizeof(unsigned long));
+
+	mem_offset = sizeof(unsigned long) + sizeof(unsigned long long);
+	memmove(pattern + mem_offset, &checksum, sizeof(uint32_t));
+
+	dwu->d_checksum = checksum;
+
+	return 0;
+}
+
+int dump_pattern(char *pattern, struct dest_write_unit *dwu)
+{
+	unsigned long mem_offset = 0;
+
+	memset(dwu, 0, sizeof(struct dest_write_unit));
+
+	memmove(&dwu->d_chunk_no, pattern, sizeof(unsigned long));
+	mem_offset += sizeof(unsigned long);
+	memmove(&dwu->d_timestamp, pattern + mem_offset,
+		sizeof(unsigned long long));
+	mem_offset += sizeof(unsigned long long);
+	memmove(&dwu->d_checksum, pattern + mem_offset, sizeof(uint32_t));
+	mem_offset += sizeof(uint32_t);
+
+	memmove(&dwu->d_char, pattern + mem_offset, 1);
+	mem_offset = CHUNK_SIZE - mem_offset;
+
+	memmove(&dwu->d_checksum, pattern + mem_offset, sizeof(uint32_t));
+	mem_offset += sizeof(uint32_t);
+	memmove(&dwu->d_timestamp, pattern + mem_offset,
+		sizeof(unsigned long long));
+	mem_offset += sizeof(unsigned long long);
+	memmove(&dwu->d_chunk_no, pattern + mem_offset, sizeof(unsigned long));
+
+	return 0;
+}
+
+int verify_chunk_pattern(char *pattern, struct dest_write_unit *dwu)
+{
+	char tmp_pattern[CHUNK_SIZE];
+
+	fill_chunk_pattern(tmp_pattern, dwu);
+
+	return !memcmp(pattern, tmp_pattern, CHUNK_SIZE);
+}
+
+int prep_orig_file_in_chunks(char *file_name, unsigned long chunks)
+{
+
+	int fd, ret, o_ret, flags;
+	unsigned long offset = 0;
+	unsigned long size = CHUNK_SIZE * chunks, chunk_no = 0;
+	struct dest_write_unit dwu;
+
+	if ((CHUNK_SIZE % DIRECTIO_SLICE) != 0) {
+
+		fprintf(stderr, "File size in destructive tests is expected to "
+			"be %d aligned, your chunk size %d is not allowed.\n",
+			DIRECTIO_SLICE, CHUNK_SIZE);
+		return -1;
+	}
+
+	flags = FILE_RW_FLAGS;
+
+	fd = open64(file_name, flags, FILE_MODE);
+
+	if (fd < 0) {
+		o_ret = fd;
+		fd = errno;
+		fprintf(stderr, "create file %s failed:%d:%s\n", file_name, fd,
+			strerror(fd));
+		fd = o_ret;
+		return fd;
+	}
+
+	/*
+	 * Original file for desctrutive tests, it consists of chunks.
+	 * Each chunks consists of following parts:
+	 * chunkno + timestamp + checksum + random chars
+	 * + checksum + timestamp + chunkno
+	 *
+	*/
+
+	while (offset < size) {
+
+		memset(&dwu, 0, sizeof(struct dest_write_unit));
+		dwu.d_chunk_no = chunk_no;
+		fill_chunk_pattern(chunk_pattern, &dwu);
+
+		ret = write_at(fd, chunk_pattern, CHUNK_SIZE, offset);
+		if (ret < 0)
+			return ret;
+
+		chunk_no++;
+		offset += CHUNK_SIZE;
+	}
+
+	fsync(fd);
+	close(fd);
+
+	return 0;
+}
+
 int verify_reflink_pair(const char *src, const char *dest)
 {
 	int fds, fdd, ret, o_ret;
@@ -1279,3 +1461,298 @@ int do_write_file(char *fname, struct write_unit *wu)
 
 	return ret;
 }
+
+unsigned long long get_time_microseconds(void)
+{
+	unsigned long long curtime_ms = 0;
+	struct timeval curtime;
+
+	gettimeofday(&curtime, NULL);
+
+	curtime_ms = (unsigned long long)curtime.tv_sec * 1000000 +
+					 curtime.tv_usec;
+
+	return curtime_ms;
+}
+
+void prep_rand_dest_write_unit(struct dest_write_unit *dwu,
+			       unsigned long chunk_no)
+{
+	char tmp_pattern[CHUNK_SIZE];
+
+	dwu->d_char = rand_char();
+	dwu->d_chunk_no = chunk_no;
+	dwu->d_timestamp = get_time_microseconds();
+
+	fill_chunk_pattern(tmp_pattern, dwu);
+}
+
+int do_write_chunk(int fd, struct dest_write_unit *dwu)
+{
+	int ret;
+	size_t count = CHUNK_SIZE;
+	off_t offset = CHUNK_SIZE * dwu->d_chunk_no;
+
+	fill_chunk_pattern(chunk_pattern, dwu);
+
+	ret = write_at(fd, chunk_pattern, count, offset);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+int init_sock(char *serv, int port)
+{
+	int sockfd;
+	struct sockaddr_in servaddr;
+
+	sockfd = socket(AF_INET, SOCK_STREAM, 0);
+	bzero(&servaddr, sizeof(struct sockaddr_in));
+	servaddr.sin_family = AF_INET;
+	servaddr.sin_port = htons(port);
+	inet_pton(AF_INET, serv, &servaddr.sin_addr);
+
+	connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
+
+	return sockfd;
+}
+
+long get_verify_logs_num(char *log)
+{
+	FILE *logfile;
+	long num_logs = 1;
+	int ret;
+	char arg1[100], arg2[100], arg3[100], arg4[100];
+
+	logfile = fopen(log, "r");
+	if (!logfile) {
+		fprintf(stderr, "Error %d opening dest log: %s\n", errno,
+			strerror(errno));
+		num_logs = -1;
+		goto bail;
+	}
+
+	while (!feof(logfile)) {
+
+		ret = fscanf(logfile, "%s\t%s\t%s\t%s\n", arg1, arg2,
+			     arg3, arg4);
+		if (ret != 4) {
+			fprintf(stderr, "input failure from dest log, ret "
+				"%d, %d %s\n", ret, errno, strerror(errno));
+			num_logs = -1;
+			goto bail;
+		}
+
+		if (strcmp(arg1, "Reflink:"))
+			continue;
+		else
+			num_logs++;
+	}
+
+bail:
+	if (logfile)
+		fclose(logfile);
+
+	return num_logs;
+}
+
+int verify_dest_file(char *log, struct dest_logs d_log, unsigned long chunk_no)
+{
+	FILE *logfile;
+	struct dest_write_unit *dwus, dwu;
+	unsigned long i, t_bytes = sizeof(struct dest_write_unit) * chunk_no;
+	unsigned long record_index = 0;
+	int fd = 0, ret = 0, o_ret;
+	char arg1[100], arg2[100], arg3[100], arg4[100];
+
+	memset(&dwu, 0, sizeof(struct dest_write_unit));
+
+	dwus = (struct dest_write_unit *)malloc(t_bytes);
+	memset(dwus, 0, t_bytes);
+
+	for (i = 0; i < chunk_no; i++)
+		dwus[i].d_chunk_no = i;
+
+	logfile = fopen(log, "r");
+	if (!logfile) {
+		fprintf(stderr, "Error %d opening dest log: %s\n", errno,
+			strerror(errno));
+		ret = -EINVAL;
+		goto bail;
+	}
+
+	while (!feof(logfile)) {
+
+		ret = fscanf(logfile, "%s\t%s\t%s\t%s\n", arg1, arg2,
+			     arg3, arg4);
+		if (ret != 4) {
+			fprintf(stderr, "input failure from dest log, ret "
+				"%d, %d %s\n", ret, errno, strerror(errno));
+			ret = -EINVAL;
+			goto bail;
+		}
+
+		if (!strcmp(arg1, "Reflink:"))
+			continue;
+		else {
+			dwu.d_chunk_no = atol(arg1);
+			dwu.d_timestamp = atoll(arg2);
+			dwu.d_checksum = atoi(arg3);
+			dwu.d_char = arg4[0];
+
+			record_index++;
+		}
+
+		if (dwu.d_timestamp >= dwus[dwu.d_chunk_no].d_timestamp) {
+
+			memmove(&dwus[dwu.d_chunk_no], &dwu,
+				sizeof(struct dest_write_unit));
+		}
+
+		if (record_index == d_log.index)
+			break;
+
+	}
+
+	fd = open64(d_log.filename, open_ro_flags, FILE_MODE);
+	if (fd < 0) {
+		ret = fd;
+		fd = errno;
+		fprintf(stderr, "open file %s failed:%d:%s\n",
+			d_log.filename, fd, strerror(fd));
+		goto bail;
+	}
+
+	fprintf(stdout, "Verify file %s :", d_log.filename);
+
+	for (i = 0; i < chunk_no; i++) {
+
+		ret = pread(fd, chunk_pattern, CHUNK_SIZE, CHUNK_SIZE * i);
+		if (ret < 0) {
+			o_ret = ret;
+			ret = errno;
+			fprintf(stderr, "read failed:%d:%s\n", ret,
+				strerror(ret));
+			ret = o_ret;
+			goto bail;
+		}
+
+		/*
+		dump_pattern(chunk_pattern, &dwu);
+		fprintf(stdout, "#%lu\t%llu\t%d\t%c\n", dwus[i].d_chunk_no,
+			dwus[i].d_timestamp, dwus[i].d_checksum,
+			dwus[i].d_char);
+		*/
+
+		/*
+		dump_pattern(chunk_pattern, &dwu);
+		fprintf(stdout, "#%lu\t%llu\t%d\t%c\n", dwu.d_chunk_no,
+			dwu.d_timestamp, dwu.d_checksum, dwu.d_char);
+		*/
+
+		if (!verify_chunk_pattern(chunk_pattern, &dwus[i])) {
+
+			dump_pattern(chunk_pattern, &dwu);
+			fprintf(stderr, "Inconsistent chunk found in file %s!\n"
+				"Expected:\tchunkno(%ld)\ttimestmp(%llu)\t"
+				"chksum(%d)\tchar(%c)\nFound   :\tchunkno"
+				"(%ld)\ttimestmp(%llu)\tchksum(%d)\tchar(%c)\n",
+				d_log.filename,
+				dwus[i].d_chunk_no, dwus[i].d_timestamp,
+				dwus[i].d_checksum, dwus[i].d_char,
+				dwu.d_chunk_no, dwu.d_timestamp,
+				dwu.d_checksum, dwu.d_char);
+			ret = -1;
+			goto bail;
+
+		}
+	}
+
+	fprintf(stdout, "Pass\n");
+
+bail:
+	if (dwus)
+		free(dwus);
+
+	if (logfile)
+		fclose(logfile);
+
+	if (fd)
+		close(fd);
+
+	return ret;
+}
+
+int verify_dest_files(char *log, char *orig, unsigned long chunk_no)
+{
+	unsigned long record_index = 0, log_index = 0, i;
+	long log_nums;
+	int ret = 0;
+
+	struct dest_logs *logs = NULL;
+	FILE *logfile = NULL;
+	char arg1[100], arg2[100], arg3[100], arg4[100];
+
+	log_nums = get_verify_logs_num(log);
+	if (log_nums < 0) {
+		ret = log_nums;
+		goto bail;
+	}
+
+	logs = (struct dest_logs *)malloc(sizeof(struct dest_logs) * log_nums);
+
+	strncpy(logs[0].filename, orig, PATH_MAX);
+
+	logfile = fopen(log, "r");
+	if (!logfile) {
+		fprintf(stderr, "Error %d opening dest log: %s\n", errno,
+			strerror(errno));
+		ret = -EINVAL;
+		goto bail;
+	}
+
+	while (!feof(logfile)) {
+
+		ret = fscanf(logfile, "%s\t%s\t%s\t%s\n", arg1, arg2,
+			     arg3, arg4);
+		if (ret != 4) {
+			fprintf(stderr, "input failure from dest log, ret "
+				"%d, %d %s\n", ret, errno, strerror(errno));
+			ret = -EINVAL;
+			goto bail;
+		}
+
+		if (strcmp(arg1, "Reflink:")) {
+			record_index++;
+			continue;
+		} else {
+			log_index++;
+			strncpy(logs[log_index].filename, arg4, PATH_MAX);
+			logs[log_index].index = record_index;
+			/*
+			printf(" #%lu log: %s, index = %lu\n",log_index, arg4, record_index);
+			*/
+		}
+	}
+
+	logs[0].index = record_index;
+
+	for (i = 0; i < log_nums; i++) {
+		ret = verify_dest_file(log, logs[i], chunk_no);
+		if (ret < 0) {
+			ret = -1;
+			goto bail;
+		}
+	}
+
+bail:
+	if (logfile)
+		fclose(logfile);
+
+	if (logs)
+
+		free(logs);
+
+	return ret;
+}
-- 
1.5.5




More information about the Ocfs2-test-devel mailing list