[Ocfs2-tools-devel] [Ocfs2-test-devel] [PATCH 1/2] Enhancement for inline-data test:Add new testcases and make it workload-configurable for inline-data

tristan.ye tristan.ye at oracle.com
Mon Aug 25 22:15:04 PDT 2008


This patch mainly aims at ehancing the existing inline-data testing
tool(ocfs2-test/programs/inline-data/inline-data.c) by introducing my
newly added testcases and make it more flexbile to tune workload as to
perform different testing requirements ,such as stress test.

Following items have been enhanced or added:

1.Set a fixed workplace for inline-data test under a ocfs2 volume,where
all inline-nodes and inline-dirs tested here.

2.Add arguments for testing binary,the mandatory ones are device and
mount point,such as ./inline-data -d /dev/sdc5 /storage,rest ones are
[-i <iteration>][-c <concurrent_process_num>] [-m
<multi_file_num>].which all have default values.specailly,we calculate
the  max_inline_size by ourselves which should be specified in original
version.

3.Add inline-file judgement mechanism by introducing the ocfs2lib(that's
why we need device name)to verify if files/dirs still inlined or
extented after test.

4.For regular testing,add workload to perform a more random test.

5.Add concurrent r/w testcase,multiple proccess perform random r/w on
one file,the process_nums can be tuned for stress test.

6.Add multiple files r/w testcase,multiple process perform random r/w on
different files separately,the file_nums can be tuned for stress test.

7.iterations can be used for stress test.

8.for other minor modifications,please turn to patch for review.

Signed-off-by: Tristan Ye <tristan.ye at oracle.com>
---

Index: ocfs2-test/programs/inline-data/inline-data.c
===================================================================
--- ocfs2-test/programs/inline-data/inline-data.c	(revision 192)
+++ ocfs2-test/programs/inline-data/inline-data.c	(working copy)
@@ -1,4 +1,6 @@
 /*
+
+#define WORK_PLACE	"inline-data-test"
  * Verify I/O to/from files small enough to hold inline data. Includes
  * some tests intended to force an inode out to an extent list.
  *
@@ -37,28 +39,64 @@
 #include <errno.h>
 #include <string.h>
 
-#include "reservations.h"
+#include <ocfs2/ocfs2.h>
 
-#define PATTERN_SZ 8192
+#include <sys/ioctl.h>
+#include <inttypes.h>
+#include <linux/types.h>
+
+#include <sys/wait.h>
+#include <signal.h>
+
+#define PATTERN_SZ	8192
+
+#define FILE_BUFFERED_RW_FLAGS  (O_CREAT|O_RDWR|O_TRUNC)
+#define FILE_MODE               (S_IRUSR|S_IWUSR|S_IXUSR|S_IROTH|\
+                                S_IWOTH|S_IXOTH|S_IRGRP|S_IWGRP|
S_IXGRP)
+
+#define WORK_PLACE	"inline-data-test"
+
+static char *prog;
+static char device[100];
+
+static ocfs2_filesys *fs = NULL;
+static struct ocfs2_super_block *ocfs2_sb = NULL;
+
 static char *pattern = NULL;
 static unsigned int max_inline_size;
 static char *read_buf = NULL;
 
 static unsigned long page_size;
-static unsigned int blocksize;
-static char *file_name;
+static unsigned int blocksize = 4096;
+static unsigned long clustersize;
 
+unsigned int id_count;
+unsigned long i_size;
+
+static char mount_point[255];
+static char work_place[255];
+static char dirent[255];
+static char file_name[255];
+
+static int iteration = 1;
+static int do_multi_process_test = 0;
+static int do_multi_file_test = 0;
+static unsigned long child_nums = 2;
+static unsigned long file_nums = 2;
+
+pid_t *child_pid_list = NULL;
+
 static unsigned long get_rand(unsigned long min, unsigned long max)
 {
 	if (min == 0 && max == 0)
 		return 0;
 
-	return min + ((rand() % max) - min);
+	return min + (rand() % (max - min + 1));
 }
 
 static inline char rand_char(void)
 {
-	return 'A' + (char) get_rand(0, 52);
+	return 'A' + (char) get_rand(0, 25);
 }
 
 static void fill_pattern(int size)
@@ -93,13 +131,19 @@
 	return 0;
 }
 
+static int write_at(int fd, const void *buf, size_t count, off_t
offset);
+
 static int extend_pattern(int fd, unsigned int old_size,
 			  unsigned int new_size)
 {
 	int bytes = new_size - old_size;
 	int ret;
+	int i;
 
 	memset(pattern + old_size, 0, bytes);
+	/*fill extended area with reandom chars*/
+	for (i = 0; i < bytes; i++)
+		pattern[old_size + i] = rand_char();
 
 	ret = ftruncate(fd, new_size);
 	if (ret == -1) {
@@ -108,6 +152,10 @@
 		return -1;
 	}
 
+	ret = write_at(fd, pattern + old_size, bytes, old_size);
+	if (ret < 0)
+		return ret;
+	
 	return 0;
 }
 
@@ -188,17 +236,9 @@
 
 static int write_at(int fd, const void *buf, size_t count, off_t
offset)
 {
-	off_t err;
 	int ret;
 
-	err = lseek(fd, offset, SEEK_SET);
-	if (err == ((off_t)-1)) {
-		ret = errno;
-		fprintf(stderr, "seek error %d: \"%s\"\n", ret, strerror(ret));
-		return -1;
-	}
-
-	ret = write(fd, buf, count);
+	ret = pwrite(fd, buf, count, offset);
 	if (ret < 0) {
 		ret = errno;
 		fprintf(stderr, "write error %d: \"%s\"\n", ret, strerror(ret));
@@ -215,7 +255,7 @@
 static int prep_file_no_fill(unsigned int size, int open_direct)
 {
 	int fd, ret;
-	int flags = O_TRUNC|O_CREAT|O_RDWR;
+	int flags = FILE_BUFFERED_RW_FLAGS;
 	size_t count = size;
 
 	if (open_direct) {
@@ -223,8 +263,7 @@
 		count = blocksize;
 	}
 
-	fd = open(file_name, flags,
-		  S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
+	fd = open(file_name, flags, FILE_MODE);
 	if (fd == -1) {
 		ret = errno;
 		fprintf(stderr, "open error %d: \"%s\"\n", ret, strerror(ret));
@@ -270,21 +309,13 @@
 
 static int __verify_pattern_fd(int fd, unsigned int size, int
direct_read)
 {
-	off_t err;
 	int ret;
 	unsigned int rd_size = size;
 
 	if (direct_read)
 		rd_size = blocksize;
 
-	err = lseek(fd, 0, SEEK_SET);
-	if (err == ((off_t)-1)) {
-		ret = errno;
-		fprintf(stderr, "seek error %d: \"%s\"\n", ret, strerror(ret));
-		return -1;
-	}
-
-	ret = read(fd, read_buf, rd_size);
+	ret = pread(fd, read_buf, rd_size, 0);
 	if (ret < 0) {
 		ret = errno;
 		fprintf(stderr, "read error %d: \"%s\"\n", ret, strerror(ret));
@@ -329,55 +360,166 @@
 
 static void usage(void)
 {
-	printf("Usage: inline-data [blocksize] [FILE]\n"
+	printf("Usage: inline-data [-i <iteration>]"
+	       "[-c <concurrent_process_num>] [-m <multi_file_num>] "
+	       "<-d <device>> <mount_point>\n"
 	       "Run a series of tests intended to verify I/O to and from\n"
-	       "files with inline data.\n\n"
-	       "blocksize is the blocksize of the underlying file system and
\n"
-	       "must be specified.\n"
-	       "FILE is the name of a file which will be used for
testing.\n");
+	       "files/dirs with inline data.\n\n"
+	       "iteration specify the running times.\n"
+	       "concurrent_process_num specify the number of concurrent "
+	       "multi_file_num specify the number of multiple files"
+	       "processes to perform inline-data write/read.\n"
+	       "device and mount_point are mandatory.\n");
+	exit(1);
 }
 
 static int parse_opts(int argc, char **argv)
 {
-	if (argc < 3)
-		return 1;
+	int c;
+	while (1) {
+		c = getopt(argc, argv, "D:d:I:i:C:c:M:m:");
+		if (c == -1)
+			break;
+		switch (c) {
+		case 'i':
+		case 'I':
+			iteration = atol(optarg);
+			break;
+		case 'd':
+		case 'D':
+			strcpy(device, optarg);
+			break;
+		case 'c':
+		case 'C':
+			do_multi_process_test = 1;
+			child_nums = atol(optarg);
+			break;
+		case 'm':
+		case 'M':
+			do_multi_file_test = 1;
+			file_nums = atol(optarg);
+			break;
+		default:
+			break;
+		}
+	}
+	
+	if (strcmp(device, "") == 0)
+		return EINVAL;
 
-	blocksize = atoi(argv[1]);
-	file_name = argv[2];
+	if (argc - optind != 1)
+                return EINVAL;
 
-	switch (blocksize) {
-	case 4096:
-		max_inline_size = 3896;
-		break;
-	case 2048:
-		max_inline_size = 1848;
-		break;
-	case 1024:
-		max_inline_size = 824;
-		break;
-	case 512:
-		max_inline_size = 312;
-		break;
-	default:
-		fprintf(stderr, "Invalid blocksize, %u\n", blocksize);
-		return 1;
-	}
+	strcpy(mount_point, argv[optind]);
+	if (mount_point[strlen(mount_point) - 1] == '/')
+		 mount_point[strlen(mount_point) - 1] = '\0';
 
-	printf("Blocksize:\t\t%d\nMax Inline Data Size:\t%d\nFilename:\t\t%s\n
\n",
-	       blocksize, max_inline_size, file_name);
+	return 0;
 
+}
+
+static int open_ocfs2_volume(char *device_name)
+{
+	int open_flags = OCFS2_FLAG_HEARTBEAT_DEV_OK | OCFS2_FLAG_RO;
+	int ret; 
+	ret = ocfs2_open(device_name, open_flags, 0, 0, &fs);
+	if (ret < 0) {
+		fprintf(stderr,"Not a ocfs2 volume!\n");
+		return ret;
+        }
+
+	ocfs2_sb = OCFS2_RAW_SB(fs->fs_super);
+	if (!(ocfs2_sb->s_feature_incompat &
OCFS2_FEATURE_INCOMPAT_INLINE_DATA)) {
+		fprintf(stderr,"Inline-data not supported"
+			" on this ocfs2 volume\n");
+		return -1;
+        }
+
+	blocksize = 1 << ocfs2_sb->s_blocksize_bits;
+	clustersize = 1 << ocfs2_sb->s_clustersize_bits;
+	max_inline_size = ocfs2_max_inline_data(blocksize);
+
 	return 0;
 }
 
-int main(int argc, char **argv)
+static int is_file_inlined(char *dirent_name, unsigned long *i_size,
+                           unsigned int *id_count)
 {
-	int ret, fd, new_size, old_size, count;
+        int ret;
+        uint64_t workplace_blk_no = 1;
+        uint64_t testfile_blk_no = 1;
+        char *buf = NULL;
+        struct ocfs2_dinode *di;
+        struct ocfs2_super_block *sb = OCFS2_RAW_SB(fs->fs_super);
 
-	if (parse_opts(argc, argv)) {
+	sync();
+
+        ocfs2_malloc_block(fs->fs_io, &buf);
+
+        /*lookup worksplace inode*/
+        ret = ocfs2_lookup(fs, sb->s_root_blkno, WORK_PLACE,
+                           strlen(WORK_PLACE), NULL,
&workplace_blk_no);
+        if ( ret < 0 ) {
+                fprintf(stderr, "failed to lookup work_place(%s)'s"
+                        " inode blkno\n", work_place);
+                goto bail;
+        }
+
+        /*lookup file inode,then read*/
+        ret = ocfs2_lookup(fs, workplace_blk_no, dirent_name,
strlen(dirent_name),
+                           NULL, &testfile_blk_no);
+        if ( ret < 0 ) {
+
+                fprintf(stderr, "failed to lookup file(%s/%s)'s"
+                        " inode blkno\n", work_place, dirent_name);
+                goto bail;
+        }
+
+	ret = ocfs2_read_inode(fs, testfile_blk_no, buf);
+	if ( ret < 0 ) {
+		fprintf(stderr, "failed to read file(%s/%s/%s)'s"
+			" inode.\n", mount_point, WORK_PLACE, dirent_name);
+		goto bail;
+	}
+
+	di = (struct ocfs2_dinode *)buf;
+        *i_size = di->i_size;
+        *id_count = ((di->id2).i_data).id_count;
+
+        if (di->i_dyn_features & OCFS2_INLINE_DATA_FL) 
+		ret = 1;
+        else
+		ret = 0;
+bail:
+	if (buf)
+        	ocfs2_free(&buf);
+        return ret;
+}
+
+static int setup(int argc, char *argv[])
+{
+	int ret;
+
+	prog = strrchr(argv[0], '/');
+	if (prog == NULL)
+		prog = argv[0];
+	else
+		prog++;
+
+	if (parse_opts(argc, argv))
 		usage();
-		return EINVAL;
+
+	ret = open_ocfs2_volume(device);
+	if (ret < 0) {
+		fprintf(stderr,"Open_ocfs2_volume failed!\n");
+		return ret;
 	}
 
+	if (do_multi_process_test)
+		child_pid_list = (pid_t *)malloc(sizeof(pid_t) * child_nums);
+	if (do_multi_file_test)
+		child_pid_list = (pid_t *)malloc(sizeof(pid_t) * file_nums);
+
 	ret = posix_memalign((void *)&pattern, blocksize, PATTERN_SZ);
 	if (ret) {
 		fprintf(stderr, "posix_memalign error %d: \"%s\"\n",
@@ -388,39 +530,387 @@
 	ret = posix_memalign((void *)&read_buf, blocksize, PATTERN_SZ);
 	if (ret) {
 		fprintf(stderr, "posix_memalign error %d: \"%s\"\n",
-			ret, strerror(ret));
+		ret, strerror(ret));
 		return 1;
 	}
 
 	srand(getpid());
 	page_size = sysconf(_SC_PAGESIZE);
+	
+	snprintf(work_place, 255, "%s/%s",mount_point,WORK_PLACE);
+	mkdir(work_place, FILE_MODE);
+	
+	printf("BlockSize:\t\t%d\nMax Inline Data Size:\t%d\n"
+	       "ClusterSize:\t\t%d\nPageSize:\t\t%d\nWorkingPlace:\t\t%s\n\n",
+               blocksize, max_inline_size, clustersize, page_size,
work_place);
 
-	printf("Test  1: Write basic pattern\n");
+	return 0;
+}
+
+static int teardown(void)
+{
+	if (child_pid_list)
+		free(child_pid_list);
+
+	return 0;
+}
+
+static void sigchld_handler()
+{
+	pid_t pid;
+	union wait status;
+
+	while (1) {
+		pid = wait3(&status, WNOHANG, NULL);
+		if (pid <= 0)
+			break;
+	}
+}
+
+static void sigint_handler()
+{
+	/*Kill all children when father interrupted*/
+	int i;
+	int process_nums;
+
+	if (do_multi_process_test)
+		process_nums = child_nums;
+	else
+		process_nums = file_nums;
+
+	for (i = 0; i < process_nums; i++)
+                kill(child_pid_list[i], SIGTERM);
+	
+	free(child_pid_list);
+	signal(SIGINT, SIG_DFL);
+	kill(getpid(), SIGINT);
+
+}
+
+static void sigterm_handler()
+{
+	/*Kill all children when father terminated*/
+        int i;
+        int process_nums;
+
+	if (do_multi_process_test)
+		process_nums = child_nums;
+	else
+		process_nums = file_nums;
+
+        for (i = 0; i < process_nums; i++)
+                kill(child_pid_list[i], SIGTERM);
+
+	free(child_pid_list);
+	signal(SIGTERM, SIG_DFL);
+	kill(getpid(), SIGTERM);
+}
+
+static int concurrent_rw_test(void)
+{
+	int fd;
+	int i, j, status;
+
+	pid_t pid;
+	int ret, rc;
+	
+	int rand_offset;
+	int rand_count;
+	
+	fflush(stderr);
+	fflush(stdout);
+
 	fd = prep_file(max_inline_size);
 	if (fd < 0)
+		return -1;
+
+	signal(SIGCHLD, sigchld_handler);
+
+	for (i = 0; i < child_nums; i++) {
+		pid = fork();
+		if (pid < 0) {
+			fprintf(stderr, "Fork process error!\n");
+			return -1;
+		}
+		/*Children perform random write/read*/
+		if (pid == 0) {
+			for (j = 0; j < child_nums; j++) {	
+				rand_offset = get_rand(0, max_inline_size - 1);
+				rand_count = get_rand(1, max_inline_size -
+						      rand_offset);
+				ret = write_at(fd, pattern + rand_offset,
+					       rand_count, rand_offset);
+				if (ret) {
+					fprintf(stderr, "Child %d random "
+						"write error!\n", getpid());
+					exit(1);
+				}
+
+				ret = verify_pattern_fd(fd, max_inline_size);
+        			if (ret) {
+					fprintf(stderr, "Child %d pattern "
+						"verification failed!\n",
+						getpid()); 
+					exit(1);
+				}
+			}
+			sleep(1);
+			exit(0);
+		}
+		/*Father attempt to control the children*/
+		if (pid > 0)
+			child_pid_list[i] = pid;
+	}
+	
+        signal(SIGINT, sigint_handler);
+        signal(SIGTERM, sigterm_handler);
+	
+	for(j = 0; j < child_nums; j++) {
+		ret =  verify_pattern_fd(fd, max_inline_size);
+		if (ret) {
+			fprintf(stderr, "Father %d pattern verification"
+				" failed!\n", getpid());
+			return -1;
+			
+		}
+	}
+
+        /*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);
+			return rc;
+		}
+	}
+
+	close(fd);
+        return 0;
+}
+
+static int should_inlined_or_not(int is_inlined, int should_inlined,
int test_no);
+
+static int multi_file_rw_test(int test_num)
+{
+	int fd;
+	int i, j, status;
+
+	pid_t pid;
+	int ret, rc;
+
+	int rand_offset;
+	int rand_count;
+
+	fflush(stderr);
+	fflush(stdout);
+
+	signal(SIGCHLD, sigchld_handler);
+	
+	for (j = 0; j < file_nums; j++) {
+		pid = fork();
+		if (pid < 0) {
+			fprintf(stderr,"Fork process failed!\n");
+			return pid;
+		}
+		if (pid == 0) {
+			snprintf(dirent, 255, "inline-data-test-multi-file-%d",
+				 getpid());
+			snprintf(file_name, 255, "%s/%s", work_place, dirent);
+			fd = prep_file(max_inline_size);
+			if (fd < 0)
+				exit(1);
+
+			for (i = 0; i < file_nums; i++) {
+				rand_offset = get_rand(0, max_inline_size -1);
+				rand_count = get_rand(1, max_inline_size - 
+						      rand_offset);
+				ret = write_at(fd, pattern + rand_offset, 
+					       rand_count, rand_offset);
+				if (ret) {
+					fprintf(stderr, "Child %d random "
+						"write error on %s !\n",
+						getpid(), file_name);
+					exit(1);
+                                }
+				ret = verify_pattern_fd(fd, max_inline_size);
+				if (ret) {
+					fprintf(stderr, "Child %d pattern "
+						"verification failed on %s!\n",
+						getpid(), file_name);
+					exit(1);
+                                }
+				fsync(fd);
+				sleep(1);
+				ret = is_file_inlined(dirent, &i_size, &id_count);
+				if (ret < 0)
+					return ret;
+				else {
+					ret = should_inlined_or_not(ret, 1, test_num);
+					if (ret < 0)
+                        			return ret;
+				}
+
+			}
+			close(fd);
+			exit(0);
+		}
+		if (pid > 0)
+			child_pid_list[j] = pid;
+	}
+	
+	signal(SIGINT, sigint_handler);
+	signal(SIGTERM, sigterm_handler);
+
+        /*father wait all children to leave*/
+	for (i = 0; i < file_nums; i++) {
+		ret = waitpid(child_pid_list[i], &status,0);
+		rc = WEXITSTATUS(status);
+		if (rc) {
+			fprintf(stderr, "Child %d exists abnormally with "
+				"RC=%d\n", child_pid_list[i], rc);
+			return rc;
+		}
+	}
+
+        return 0;
+}
+
+static int should_inlined_or_not(int is_inlined, int should_inlined,
int test_no)
+{
+	/* is_inlined represent if the ret is inlined or not
+	   while should_inlined represnt if we expect it inlined or not
+	*/
+	if (should_inlined) {
+		if (!is_inlined) {
+			fprintf(stderr, "After Test #%d, file %s should be "
+				"inlined here!\n", test_no, file_name);
+			fprintf(stderr, "File(%s): i_size = %d,id_count = %d\n",
+				file_name, i_size, id_count);
+			return -1;
+		}
+
+	} else {
+		if (is_inlined) {
+			fprintf(stderr, "After Test #%d, file %s should be "
+				"extented here!\n", test_no, file_name);
+			fprintf(stderr, "File(%s): i_size = %d,id_count = %d\n",
+				file_name, i_size, id_count);
+			return -1;
+			
+		}
+	}
+	
+	return 0;
+}
+
+static int test_regular_file(int test_no)
+{
+	int ret, fd, new_size, old_size, init_count, count, j, offset;
+	unsigned int test_num = 1;
+	int hole_gap = 2;
+	
+	snprintf(dirent, 255, "inline-data-test-file-%d", getpid());
+	snprintf(file_name, 255, "%s/%s", work_place, dirent);
+
+	printf("################Test Round %d :%s################\n",
+	       test_no, file_name);
+	
+	
+	printf("Test  %d: Write basic pattern\n", test_num);
+	fd = prep_file(max_inline_size);
+	if (fd < 0)
 		return 1;
-	ret = verify_pattern_fd(fd, max_inline_size);
-	if (ret)
+
+	ret = is_file_inlined(dirent, &i_size, &id_count);
+	if (ret < 0)
 		return ret;
+	else {
+		ret = should_inlined_or_not(ret, 1, test_num);
+		if (ret < 0)
+			return ret;
+	}
 
-	printf("Test  2: Rewrite portion of basic pattern\n");
-	ret = write_at(fd, pattern + 10, 100, 10);
-	if (ret)
-		return 1;
 	ret = verify_pattern_fd(fd, max_inline_size);
 	if (ret)
-		return 1;
+		return ret;
+	test_num++;
+	
+	printf("Test  %d: Rewrite portion of basic pattern\n", test_num);
+	for (j = 0; j < max_inline_size; j++) {
+		count = get_rand(1, max_inline_size - j);
+		ret = write_at(fd, pattern + j, count, j);
+		if (ret)
+			return 1;
+		ret = verify_pattern_fd(fd, max_inline_size);
+		if (ret)
+			return 1;
+	}
 
-	printf("Test  3: Reduce size with truncate\n");
-	new_size = max_inline_size - 180;
-	ret = truncate_pattern(fd, max_inline_size, new_size);
+	ret = is_file_inlined(dirent, &i_size, &id_count);
+	if (ret < 0)
+		return ret;
+	else {
+		ret = should_inlined_or_not(ret, 1, test_num);
+		if (ret < 0)
+			return ret;
+	}
+	test_num++;
+
+	printf("Test  %d: Reduce size with truncate\n", test_num);
+	new_size = max_inline_size;
+	for (j = 0; j < max_inline_size; j++) {
+		old_size = new_size;
+		new_size = max_inline_size - j;
+		ret = truncate_pattern(fd, old_size, new_size);
+		if (ret)
+			return ret;
+		ret = verify_pattern_fd(fd, new_size);
+		if (ret)
+			return ret;
+
+	}
+	ret = is_file_inlined(dirent, &i_size, &id_count);
+	if (ret < 0)
+		return ret;
+	else {
+		ret = should_inlined_or_not(ret, 1, test_num);
+		if (ret < 0)
+			return ret;
+	}
+	test_num++;
+
+	printf("Test  %d: Extend file\n", test_num);
+	for (j = 2; j <= max_inline_size; j++) {
+		old_size = new_size;
+		new_size = j;
+		ret = extend_pattern(fd, old_size, new_size);
+		if (ret)
+			return ret;
+		ret = verify_pattern_fd(fd, new_size);
+		if (ret)
+			return ret;
+	}
+	ret = is_file_inlined(dirent, &i_size, &id_count);
+	if (ret < 0)
+		return ret;
+	else {
+		ret = should_inlined_or_not(ret, 1, test_num);
+		if (ret < 0)
+			return ret;
+	}
+	test_num++;
+
+	printf("Test  %d: Extreme truncate and extend\n", test_num);
+	old_size = new_size;
+	new_size = 0;
+	ret = truncate_pattern(fd, old_size, new_size);
 	if (ret)
 		return ret;
-	ret = verify_pattern_fd(fd, new_size);
+	ret =verify_pattern_fd(fd, new_size);
 	if (ret)
 		return ret;
-
-	printf("Test  4: Extend file\n");
 	old_size = new_size;
 	new_size = max_inline_size;
 	ret = extend_pattern(fd, old_size, new_size);
@@ -429,21 +919,43 @@
 	ret = verify_pattern_fd(fd, new_size);
 	if (ret)
 		return ret;
+	ret = is_file_inlined(dirent, &i_size, &id_count);
+	if (ret < 0)
+		return ret;
+	else {
+		ret = should_inlined_or_not(ret, 1, test_num);
+		if (ret < 0)
+			return ret;
+	}
+	test_num++;
 
-	printf("Test  5: Double write, both extending\n");
-	close(fd);
-	fill_pattern(200);
-	fd = prep_file_no_fill(100, 0);
-	if (fd < 0)
-		return 1;
-	ret = write_at(fd, pattern + 50, 150, 50);
-	if (ret)
-		return 1;
-	ret = verify_pattern_fd(fd, 200);
-	if (ret)
+	printf("Test  %d: Double write, both extending\n", test_num);
+	for (j = 1; j <= max_inline_size; j++){
+		close(fd);
+		fill_pattern(j);
+		init_count = get_rand(1, j);
+		fd = prep_file_no_fill(init_count, 0);
+		if (fd < 0)
+			return 1;
+		offset = get_rand(1, init_count);
+		ret = write_at(fd, pattern + offset, j - offset, offset);
+		if (ret)
+			return ret;
+		ret = verify_pattern_fd(fd, j);
+		if (ret)
+			return ret;
+	}
+	ret = is_file_inlined(dirent, &i_size, &id_count);
+	if (ret < 0)
 		return ret;
+	else {
+		ret = should_inlined_or_not(ret, 1, test_num);
+		if (ret < 0)
+			return ret;
+	}
+	test_num++;
 
-	printf("Test  6: Fsync\n");
+	printf("Test  %d: Fsync\n", test_num);
 	close(fd);
 	fd = prep_file(max_inline_size);
 	if (fd < 0)
@@ -454,8 +966,17 @@
 	ret = verify_pattern_fd(fd, max_inline_size);
 	if (ret)
 		return ret;
+	ret = is_file_inlined(dirent, &i_size, &id_count);
+	if (ret < 0)
+		return ret;
+	else {
+		ret = should_inlined_or_not(ret, 1, test_num);
+		if (ret < 0)
+			return ret;
+	}
+	test_num++;
 
-	printf("Test  7: Fdatasync\n");
+	printf("Test  %d: Fdatasync\n", test_num);
 	close(fd);
 	fd = prep_file(max_inline_size);
 	if (fd < 0)
@@ -466,37 +987,86 @@
 	ret = verify_pattern_fd(fd, max_inline_size);
 	if (ret)
 		return ret;
+	ret = is_file_inlined(dirent, &i_size, &id_count);
+	if (ret < 0)
+		return ret;
+	else {
+		ret = should_inlined_or_not(ret, 1, test_num);
+		if (ret < 0)
+			return ret;
+	}
+	test_num++;
 
-	printf("Test  8: Mmap reads\n");
+	printf("Test  %d: Mmap reads\n", test_num);
 	close(fd);
         fd = prep_file(max_inline_size);
 	if (fd < 0)
 		return fd;
-	ret = verify_pattern_mmap(fd, max_inline_size);
-	if (ret)
-		return ret;
-
-	printf("Test  9: Reserve space\n");
-	ret = try_reserve(fd, 0, max_inline_size);
-	if (ret != ENOTTY) {
+	for (j = 1; j <= max_inline_size; j++) {
+		ret = verify_pattern_mmap(fd, j);
 		if (ret)
 			return ret;
-		ret = verify_pattern_fd(fd, max_inline_size);
-		if (ret)
+	}
+
+	ret = is_file_inlined(dirent, &i_size, &id_count);
+	if (ret < 0)
+		return ret;
+	else {
+		ret = should_inlined_or_not(ret, 1, test_num);
+		if (ret < 0)
 			return ret;
 	}
+	test_num++;
 
-	printf("Test  10: Punch hole\n");
-	ret = try_punch_hole(fd, 10, 100);
-	if (ret != ENOTTY) {
-		if (ret)
+	printf("Test  %d: Reserve space\n", test_num);
+	for (j = 0; j < max_inline_size; j++) {
+		offset = j;
+		count = get_rand(1, max_inline_size - j);
+		ret = try_reserve(fd, offset, count);
+		if (ret != ENOTTY) {
+			if (ret)
+				return ret;
+			ret = verify_pattern_fd(fd, max_inline_size);
+			if (ret)
+				return ret;
+		}
+	}
+	ret = is_file_inlined(dirent, &i_size, &id_count);
+	if (ret < 0)
+		return ret;
+	else {
+		ret = should_inlined_or_not(ret, 1, test_num);
+		if (ret < 0)
 			return ret;
-		ret = verify_pattern_fd(fd, max_inline_size);
-		if (ret)
+	}
+	test_num++;
+
+	printf("Test  %d: Punch hole\n", test_num);
+	offset = 0;
+	hole_gap = 10;
+	while (offset < max_inline_size)  {
+		count = get_rand(1, max_inline_size - offset);
+		ret = try_punch_hole(fd, offset, count);
+		if (ret != ENOTTY) {
+			if (ret)
+				return ret;
+			ret = verify_pattern_fd(fd, max_inline_size);
+			if (ret)
+				return ret;
+		}
+		offset = offset + count + hole_gap;
+	}
+	ret = is_file_inlined(dirent ,&i_size, &id_count);
+	if (ret < 0)
+		return ret;
+	else {
+		ret = should_inlined_or_not(ret, 1, test_num);
+		if (ret < 0)
 			return ret;
 	}
+	test_num++;
 
-	printf("Test  11: Force expansion to extents via large write\n");
+	printf("Test  %d: Force expansion to extents via large write\n",
test_num);
 	close(fd);
 	fill_pattern(PATTERN_SZ);
 	fd = prep_file_no_fill(max_inline_size, 0);
@@ -509,8 +1079,17 @@
 	ret = verify_pattern_fd(fd, PATTERN_SZ);
 	if (ret)
 		return ret;
+	ret = is_file_inlined(dirent, &i_size, &id_count);
+	if (ret < 0)
+		return ret;
+	else {
+		ret = should_inlined_or_not(ret, 0, test_num);
+		if (ret < 0)
+			return ret;
+	}
+	test_num++;
 
-	printf("Test 12: Force expansion to extents via mmap write\n");
+	printf("Test  %d: Force expansion to extents via mmap write\n",
test_num);
 	close(fd);
 	fd = prep_file(max_inline_size);
 	if (fd < 0)
@@ -522,22 +1101,40 @@
 	ret = verify_pattern_fd(fd, max_inline_size);
 	if (ret)
 		return ret;
+	ret = is_file_inlined(dirent, &i_size, &id_count);
+	if (ret < 0)
+		return ret;
+	else {
+		ret = should_inlined_or_not(ret , 0, test_num);
+		if (ret < 0)
+			return ret;
+	}
+	test_num++;
 
-	printf("Test 13: Force expansion to extents via large extend\n");
+	printf("Test  %d: Force expansion to extents via large extend\n",
test_num);
 	close(fd);
 	fd = prep_file(max_inline_size);
 	if (fd < 0)
 		return fd;
 	old_size = max_inline_size;
-	new_size = 2*max_inline_size;
+	new_size = 2 * max_inline_size;
 	ret = extend_pattern(fd, old_size, new_size);
 	if (ret)
 		return ret;
 	ret = verify_pattern_fd(fd, new_size);
 	if (ret)
 		return 1;
+	ret = is_file_inlined(dirent, &i_size, &id_count);
+	if (ret < 0)
+		return ret;
+	else {
+		ret = should_inlined_or_not(ret, 0, test_num);
+		if (ret < 0)
+			return ret;
+	}
+	test_num++;
 
-	printf("Test 14: Force expansion to extents via large reservation\n");
+	printf("Test  %d: Force expansion to extents via large reservation\n",
test_num);
 	close(fd);
 	fd = prep_file(max_inline_size);
 	if (fd < 0)
@@ -554,8 +1151,17 @@
 		if (ret)
 			return ret;
 	}
+	ret = is_file_inlined(dirent, &i_size, &id_count);
+	if (ret < 0)
+		return ret;
+	else {
+		ret = should_inlined_or_not(ret, 0, test_num);
+		if (ret < 0)
+			return ret;
+	}
+	test_num++;
 
-	printf("Test 15: O_DIRECT read\n");
+	printf("Test  %d: O_DIRECT read\n", test_num);
 	close(fd);
 	fd = prep_file(max_inline_size);
 	if (fd < 0)
@@ -571,8 +1177,17 @@
 	ret = __verify_pattern_fd(fd, max_inline_size, 1);
 	if (ret)
 		return 1;
-
-	printf("Test 16: O_DIRECT write\n");
+	ret = is_file_inlined(dirent, &i_size, &id_count);
+	if (ret < 0)
+		return ret;
+	else {
+		ret = should_inlined_or_not(ret, 1, test_num);
+		if (ret < 0)
+			return ret;
+	}
+	test_num++;
+	
+	printf("Test  %d: O_DIRECT write\n", test_num);
 	close(fd);
 	fill_pattern(max_inline_size);
 	fd = prep_file_no_fill(max_inline_size, 1);
@@ -582,10 +1197,66 @@
 	if (ret)
 		return 1;
 	close(fd);
+	ret = is_file_inlined(dirent, &i_size, &id_count);
+	if (ret < 0)
+		return ret;
+	else {
+		ret = should_inlined_or_not(ret, 0, test_num);
+		if (ret < 0)
+			return ret;
+	}
+	test_num++;
+	
+	if (do_multi_process_test) {
+		printf("Test  %d: Concurrent Write/Read\n", test_num);
+		close(fd);
+		ret = concurrent_rw_test();
+		if (ret < 0)
+			return ret;
+	
+		ret = is_file_inlined(dirent, &i_size, &id_count);
+		if (ret < 0)
+			return ret;
+		else {
+			ret = should_inlined_or_not(ret, 1, test_num);
+			if (ret < 0)
+				return ret;
+		}
+		test_num++;
+	}
 
+	if (do_multi_file_test) {
+		printf("Test  %d: Multiple File Write/Read\n", test_num);
+		ret = multi_file_rw_test(test_num);
+		if (ret < 0)
+			return ret;
+		test_num++;
+	}
+
+bail:
 	printf("All File I/O Tests Passed\n");
-
 	unlink(file_name);
+	rmdir(work_place);
 
 	return ret;
 }
+int main(int argc, char **argv)
+{
+	int ret;
+	int i;
+
+	ret = setup(argc,argv);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < iteration; i++) {
+		ret = test_regular_file(i);
+		if (ret)
+			return ret;
+	}
+	ret = teardown();
+	if (ret)
+		return ret;
+
+	return 0;
+}




More information about the Ocfs2-tools-devel mailing list