[Ocfs2-test-devel] [PATCH 1/1] Ocfs2-test: Add destructive testcase for reflink_test v2.
Tristan Ye
tristan.ye at oracle.com
Tue Nov 3 03:14:56 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 v2 testcase was also a somewhat quick&dirty one which incorporate sunil's
suggestions, and add checksum verification for data chunk.
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/Makefile | 2 +-
programs/reflink_tests/crc32table.h | 150 +++++++++++
programs/reflink_tests/reflink_test.c | 225 ++++++++++++++++-
programs/reflink_tests/reflink_test.h | 34 +++
programs/reflink_tests/reflink_test_utils.c | 359 +++++++++++++++++++++++++++
5 files changed, 765 insertions(+), 5 deletions(-)
create mode 100644 programs/reflink_tests/crc32table.h
diff --git a/programs/reflink_tests/Makefile b/programs/reflink_tests/Makefile
index d2f2110..c73b647 100755
--- a/programs/reflink_tests/Makefile
+++ b/programs/reflink_tests/Makefile
@@ -4,7 +4,7 @@ include $(TOPDIR)/Preamble.make
TESTS = reflink_tests
-CFLAGS = -O2 -Wall -g $(OCFS2_CFLAGS)
+CFLAGS = -O2 -Wall -g $(OCFS2_CFLAGS) -ggdb
CFLAGS += $(EXTRA_CFLAGS)
diff --git a/programs/reflink_tests/crc32table.h b/programs/reflink_tests/crc32table.h
new file mode 100644
index 0000000..67eae31
--- /dev/null
+++ b/programs/reflink_tests/crc32table.h
@@ -0,0 +1,150 @@
+/* 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 9370925..3e6a7e9 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,192 @@ 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[100], 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);
+
+ /*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 children to write in chunks.\n",
+ sub_testno++);
+
+ 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%c\n", dwu.d_chunk_no,
+ dwu.d_timestamp, 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, 100);
+ snprintf(log_rec, 100, "Reflinking:\t%s->%s\n",orig_path, dest);
+ write(sockfd, log_rec, 100);
+
+ }
+ */
+
+ /*
+ * 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(50000);
+ }
+
+ 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;
+
+ 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);
+
+ verify_dest_files(dest_log_path, orig_path, chunk_no);
+
+ return 0;
+}
+
static int directio_test(void)
{
@@ -2005,6 +2216,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..de682c5 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,22 @@
#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;
+};
+
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 +117,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 +145,17 @@ 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);
+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_utils.c b/programs/reflink_tests/reflink_test_utils.c
index 1401566..2dd67db 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,137 @@ 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;
+ }
+
+ close(fd);
+ return 0;
+}
+
int verify_reflink_pair(const char *src, const char *dest)
{
int fds, fdd, ret, o_ret;
@@ -1279,3 +1459,182 @@ 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)
+{
+ dwu->d_char = rand_char();
+ dwu->d_chunk_no = chunk_no;
+ dwu->d_timestamp = get_time_microseconds();
+}
+
+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 do_write_chunk_file(char *fname, struct dest_write_unit *du)
+{
+ int fd, ret, o_ret, flags = open_rw_flags;
+
+ if (test_flags & DSCV_TEST)
+ flags |= O_DIRECT;
+
+ fd = open64(fname, flags);
+
+ if (fd < 0) {
+ o_ret = fd;
+ fd = errno;
+ fprintf(stderr, "open file %s failed:%d:%s\n", fname, fd,
+ strerror(fd));
+ fd = o_ret;
+ return fd;
+ }
+
+ ret = do_write_chunk(fd, du);
+
+ close(fd);
+
+ return ret;
+}
+*/
+
+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;
+}
+
+int verify_dest_files(char *log, char *orig, unsigned long chunk_no)
+{
+ FILE *logfile;
+ struct dest_write_unit *dwus, dwu;
+ unsigned long i, t_bytes = sizeof(struct dest_write_unit) * chunk_no;
+ int fd = 0, ret = 0, o_ret;
+ char dest[PATH_MAX];
+
+ 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, "%lu\t%llu\t%c\n", &dwu.d_chunk_no,
+ &dwu.d_timestamp, &dwu.d_char);
+
+ if (ret != 3) {
+ fprintf(stderr, "input failure from dest log, ret "
+ "%d, %d %s\n", ret, errno, strerror(errno));
+ ret = -EINVAL;
+ goto bail;
+ }
+
+ if (dwu.d_timestamp >= dwus[dwu.d_chunk_no].d_timestamp) {
+
+ /*
+ printf("#%lu \tchunk record updated, from [%llu](%c) to [%llu](%c)\n",
+ dwu.d_chunk_no, dwus[dwu.d_chunk_no].d_timestamp, dwus[dwu.d_chunk_no].d_char,
+ dwu.d_timestamp, dwu.d_char);
+ */
+ memmove(&dwus[dwu.d_chunk_no], &dwu,
+ sizeof(struct dest_write_unit));
+ }
+
+ }
+
+ fd = open64(orig, open_ro_flags, FILE_MODE);
+ if (fd < 0) {
+ ret = fd;
+ fd = errno;
+ fprintf(stderr, "open file %s failed:%d:%s\n",
+ orig, fd, strerror(fd));
+ goto bail;
+ }
+
+ 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;
+ }
+
+ if (!verify_chunk_pattern(chunk_pattern, &dwus[i])) {
+
+ dump_pattern(chunk_pattern, &dwu);
+ fprintf(stderr, "Inconsistent chunk record found!\n"
+ "Expected:\tchunkno(%ld)\ttimestmp(%llu)\t"
+ "chksum(%d)\tchar(%c)\nFound :\tchunkno"
+ "(%ld)\ttimestmp(%llu)\tchksum(%d)\tchar(%c)\n",
+ 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;
+
+ }
+ }
+
+bail:
+ if (dwus)
+ free(dwus);
+
+ if (logfile)
+ fclose(logfile);
+
+ if (fd)
+ close(fd);
+
+ return ret;
+}
--
1.5.5
More information about the Ocfs2-test-devel
mailing list