[Ocfs2-tools-devel] [PATCH 1/9] Ocfs2-test: Enhance inline-data.c for regular file(single-node)

Tristan Ye tristan.ye at oracle.com
Thu Sep 4 03:01:27 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.

Most of its original testcase reserved, two main new ones added here is
concurrent r/w and multiple file test.

Specially,most of its basic funcs been abstracted to inline-data-utils.c
for public use with multi-inline-data test.

Signed-off-by: Tristan Ye <tristan.ye at oracle.com>
---
 programs/inline-data/inline-data.c |  989 ++++++++++++++++++++++++------------
 1 files changed, 662 insertions(+), 327 deletions(-)

diff --git a/programs/inline-data/inline-data.c b/programs/inline-data/inline-data.c
index 701796b..d5682e1 100644
--- a/programs/inline-data/inline-data.c
+++ b/programs/inline-data/inline-data.c
@@ -1,4 +1,8 @@
-/*
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * single-inline-data.c
+ *
  * 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.
  *
@@ -18,8 +22,23 @@
  *    3) Extend file past min size
  *    4) Resrve space past min size
  *
+ * [III] Tests for concurrent r/w among multiple processes.
+ *    1) propagate multiple process to perform concurrent rw on one inlined file
+ *    2) Create multiple files among multi-nodes,and perform r/w separately.
+ *
  * XXX: This could easily be turned into an mpi program, where a
  * second node does the verification step.
+ *
+ * Copyright (C) 2008 Oracle.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
  */
 
 #define _XOPEN_SOURCE 600
@@ -37,390 +56,522 @@
 #include <errno.h>
 #include <string.h>
 
-#include "reservations.h"
-
-#define PATTERN_SZ 8192
-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;
+#include <ocfs2/ocfs2.h>
+
+#include <sys/ioctl.h>
+#include <inttypes.h>
+#include <linux/types.h>
+
+#include <sys/wait.h>
+#include <signal.h>
+
+#define PATTERN_SZ			8192
+#define OCFS2_MAX_FILENAME_LEN          255
+
+#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];
+
+ocfs2_filesys *fs;
+struct ocfs2_super_block *ocfs2_sb;
+
+char *pattern;
+unsigned int max_inline_size;
+char *read_buf;
+
+unsigned long page_size;
+unsigned int blocksize = 4096;
+unsigned long clustersize;
+
+unsigned int id_count;
+unsigned long i_size;
+
+char mount_point[OCFS2_MAX_FILENAME_LEN];
+char work_place[OCFS2_MAX_FILENAME_LEN];
+char file_name[OCFS2_MAX_FILENAME_LEN];
+static char dirent[OCFS2_MAX_FILENAME_LEN];
+
+static int iteration = 1;
+static int do_multi_process_test;
+static int do_multi_file_test;
+static unsigned long child_nums = 2;
+static unsigned long file_nums = 2;
+
+pid_t *child_pid_list;
+
+extern unsigned long get_rand(unsigned long min, unsigned long max);
+extern char rand_char(void);
+extern void fill_pattern(int size);
+extern int truncate_pattern(int fd, unsigned int old_size,
+			    unsigned int new_size);
+extern int extend_pattern(int fd, unsigned int old_size, unsigned int new_size);
+extern int try_ioctl(int which, int fd, unsigned int offset,
+		     unsigned int count);
+extern int try_reserve(int fd, unsigned int offset, unsigned int count);
+extern int try_punch_hole(int fd, unsigned int offset, unsigned int count);
+extern int mmap_write_at(int fd, const char *buf, size_t count, off_t offset);
+extern int write_at(int fd, const void *buf, size_t count, off_t offset);
+extern int prep_file_no_fill(unsigned int size, int open_direct);
+extern int prep_file(unsigned int size);
+extern int verify_pattern(int size, char *buf);
+extern int __verify_pattern_fd(int fd, unsigned int size, int direct_read);
+extern int verify_pattern_fd(int fd, unsigned int size);
+extern int verify_pattern_mmap(int fd, unsigned int size);
+extern int open_ocfs2_volume(char *device_name);
+extern int is_file_inlined(char *dirent_name, unsigned long *i_size,
+			   unsigned int *id_count);
+extern int should_inlined_or_not(int is_inlined, int should_inlined,
+				 int test_no);
 
-static unsigned long get_rand(unsigned long min, unsigned long max)
+static void usage(void)
 {
-	if (min == 0 && max == 0)
-		return 0;
-
-	return min + ((rand() % max) - min);
+	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/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 inline char rand_char(void)
+static int parse_opts(int argc, char **argv)
 {
-	return 'A' + (char) get_rand(0, 52);
-}
+	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;
+		}
+	}
 
-static void fill_pattern(int size)
-{
-	int i;
+	if (strcmp(device, "") == 0)
+		return EINVAL;
 
-	/*
-	 * Make sure that anything in the buffer past size is zero'd,
-	 * as a regular file should look.
-	 */
-	memset(pattern, 0, PATTERN_SZ);
+	if (argc - optind != 1)
+		return EINVAL;
+
+	strcpy(mount_point, argv[optind]);
+	if (mount_point[strlen(mount_point) - 1] == '/')
+		 mount_point[strlen(mount_point) - 1] = '\0';
+
+	return 0;
 
-	for(i = 0; i < size; i++)
-		pattern[i] = rand_char();
 }
 
-static int truncate_pattern(int fd, unsigned int old_size,
-			    unsigned int new_size)
+static int setup(int argc, char *argv[])
 {
-	int bytes = old_size - new_size;
 	int ret;
 
-	memset(pattern + new_size, 0, bytes);
+	prog = strrchr(argv[0], '/');
+	if (prog == NULL)
+		prog = argv[0];
+	else
+		prog++;
+
+	if (parse_opts(argc, argv))
+		usage();
+
+	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 = ftruncate(fd, new_size);
-	if (ret == -1) {
-		fprintf(stderr, "ftruncate error %d: \"%s\"\n",
+	ret = posix_memalign((void *)&pattern, blocksize, PATTERN_SZ);
+	if (ret) {
+		fprintf(stderr, "posix_memalign error %d: \"%s\"\n",
 			ret, strerror(ret));
-		return -1;
+		return 1;
 	}
 
-	return 0;
-}
+	ret = posix_memalign((void *)&read_buf, blocksize, PATTERN_SZ);
+	if (ret) {
+		fprintf(stderr, "posix_memalign error %d: \"%s\"\n",
+		ret, strerror(ret));
+		return 1;
+	}
 
-static int extend_pattern(int fd, unsigned int old_size,
-			  unsigned int new_size)
-{
-	int bytes = new_size - old_size;
-	int ret;
+	srand(getpid());
+	page_size = sysconf(_SC_PAGESIZE);
 
-	memset(pattern + old_size, 0, bytes);
+	snprintf(work_place, OCFS2_MAX_FILENAME_LEN, "%s/%s",
+		 mount_point, WORK_PLACE);
+	mkdir(work_place, FILE_MODE);
 
-	ret = ftruncate(fd, new_size);
-	if (ret == -1) {
-		fprintf(stderr, "ftruncate error %d: \"%s\"\n",
-			ret, strerror(ret));
-		return -1;
-	}
+	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);
 
 	return 0;
 }
 
-static int try_ioctl(int which, int fd, unsigned int offset, unsigned int count)
+static int teardown(void)
 {
-	struct ocfs2_space_resv sr;
+	if (child_pid_list)
+		free(child_pid_list);
 
-	memset(&sr, 0, sizeof(sr));
-	sr.l_whence = SEEK_SET;
-	sr.l_start = offset;
-	sr.l_len = count;
+	rmdir(work_place);
 
-	return ioctl(fd, which, &sr);
+	return 0;
 }
 
-static int try_reserve(int fd, unsigned int offset, unsigned int count)
+static void sigchld_handler()
 {
-	int ret;
+	pid_t pid;
+	union wait status;
 
-	ret = try_ioctl(OCFS2_IOC_RESVSP, fd, offset, count);
-	if (ret == -1) {
-		ret = errno;
-		if (ret == ENOTTY)
-			return ret;
-		fprintf(stderr, "IOC_RESVSP error %d: \"%s\"\n",
-			ret, strerror(ret));
-		return -1;
+	while (1) {
+		pid = wait3(&status, WNOHANG, NULL);
+		if (pid <= 0)
+			break;
 	}
-
-	return 0;
 }
 
-static int try_punch_hole(int fd, unsigned int offset, unsigned int count)
+static void kill_all_children()
 {
-	int ret;
+	int i;
+	int process_nums;
 
-	memset(pattern + offset, 0, count);
+	if (do_multi_process_test)
+		process_nums = child_nums;
+	else
+		process_nums = file_nums;
 
-	ret = try_ioctl(OCFS2_IOC_UNRESVSP, fd, offset, count);
-	if (ret == -1) {
-		ret = errno;
-		if (ret == ENOTTY)
-			return ret;
-		fprintf(stderr, "IOC_UNRESVSP error %d: \"%s\"\n",
-			ret, strerror(ret));
-		return -1;
-	}
+	for (i = 0; i < process_nums; i++)
+		kill(child_pid_list[i], SIGTERM);
 
-	return 0;
+	free(child_pid_list);
 }
-
-static int mmap_write_at(int fd, const char *buf, size_t count, off_t offset)
+static void sigint_handler()
 {
-	unsigned int mmap_size = page_size;
-	unsigned int size = count + offset;
-	int i, j, ret;
-	char *region;
+	kill_all_children();
 
-	while (mmap_size < size)
-		mmap_size += page_size;
+	signal(SIGINT, SIG_DFL);
+	kill(getpid(), SIGINT);
 
-	region = mmap(NULL, mmap_size, PROT_WRITE, MAP_SHARED, fd, 0);
-	if (region == MAP_FAILED) {
-		ret = errno;
-		fprintf(stderr, "mmap (write) error %d: \"%s\"\n", ret,
-			strerror(ret));
-		return -1;
-	}
-
-	j = 0;
-	for(i = offset; i < size; i++)
-		region[i] = buf[j++];
+}
 
-	munmap(region, mmap_size);
+static void sigterm_handler()
+{
+	kill_all_children();
 
-	return 0;
+	signal(SIGTERM, SIG_DFL);
+	kill(getpid(), SIGTERM);
 }
 
-static int write_at(int fd, const void *buf, size_t count, off_t offset)
+static int concurrent_rw_test(void)
 {
-	off_t err;
-	int ret;
+	int fd;
+	int i, j, status;
 
-	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;
-	}
+	pid_t pid;
+	int ret, rc;
 
-	ret = write(fd, buf, count);
-	if (ret < 0) {
-		ret = errno;
-		fprintf(stderr, "write error %d: \"%s\"\n", ret, strerror(ret));
-		return -1;
-	}
-	if (ret != count) {
-		fprintf(stderr, "Short write: wanted %d, got %d\n", count, ret);
-		return -1;
-	}
+	int rand_offset;
+	int rand_count;
 
-	return 0;
-}
+	fflush(stderr);
+	fflush(stdout);
 
-static int prep_file_no_fill(unsigned int size, int open_direct)
-{
-	int fd, ret;
-	int flags = O_TRUNC|O_CREAT|O_RDWR;
-	size_t count = size;
+	fd = prep_file(max_inline_size);
+	if (fd < 0)
+		return -1;
 
-	if (open_direct) {
-		flags |= O_DIRECT;
-		count = blocksize;
-	}
+	signal(SIGCHLD, sigchld_handler);
 
-	fd = open(file_name, flags,
-		  S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
-	if (fd == -1) {
-		ret = errno;
-		fprintf(stderr, "open error %d: \"%s\"\n", ret, strerror(ret));
-		return -1;
+	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;
 	}
 
-	ret = write_at(fd, pattern, count, 0);
-	if (ret)
-		return ret;
+	signal(SIGINT, sigint_handler);
+	signal(SIGTERM, sigterm_handler);
 
-	if (count > size) {
-		ret = ftruncate(fd, size);
+	for (j = 0; j < child_nums; j++) {
+		ret =  verify_pattern_fd(fd, max_inline_size);
 		if (ret) {
-			ret = errno;
-			fprintf(stderr, "truncate error %d: \"%s\"\n", ret,
-				strerror(ret));
+			fprintf(stderr, "Father %d pattern verification"
+				" failed!\n", getpid());
 			return -1;
 		}
 	}
 
-	return fd;
-}
-
-static int prep_file(unsigned int size)
-{
-	fill_pattern(size);
-
-	return prep_file_no_fill(size, 0);
-}
-
-static int verify_pattern(int size, char *buf)
-{
-	int i;
-
-	for(i = 0; i < size; i++) {
-		if (buf[i] != pattern[i]) {
-			fprintf(stderr, "Verify failed at byte: %d\n", i);
-			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 __verify_pattern_fd(int fd, unsigned int size, int direct_read)
+static int multi_file_rw_test(int test_num)
 {
-	off_t err;
-	int ret;
-	unsigned int rd_size = size;
-
-	if (direct_read)
-		rd_size = blocksize;
+	int fd;
+	int i, j, status;
 
-	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;
-	}
+	pid_t pid;
+	int ret, rc;
 
-	ret = read(fd, read_buf, rd_size);
-	if (ret < 0) {
-		ret = errno;
-		fprintf(stderr, "read error %d: \"%s\"\n", ret, strerror(ret));
-		return -1;
-	}
-	if (ret != size) {
-		fprintf(stderr, "Short read: wanted %d, got %d\n", size, ret);
-		return -1;
-	}
+	int rand_offset;
+	int rand_count;
 
-	return verify_pattern(size, read_buf);
-}
+	fflush(stderr);
+	fflush(stdout);
 
-static int verify_pattern_fd(int fd, unsigned int size)
-{
-	return __verify_pattern_fd(fd, size, 0);
-}
-
-static int verify_pattern_mmap(int fd, unsigned int size)
-{
-	int ret;
-	unsigned int mmap_size = page_size;
-	void *region;
+	signal(SIGCHLD, sigchld_handler);
 
-	while (mmap_size < size)
-		mmap_size += page_size;
-
-	region = mmap(NULL, mmap_size, PROT_READ, MAP_SHARED, fd, 0);
-	if (region == MAP_FAILED) {
-		ret = errno;
-		fprintf(stderr, "mmap (read) error %d: \"%s\"\n", ret,
-			strerror(ret));
-		return -1;
+	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, OCFS2_MAX_FILENAME_LEN,
+				"inline-data-test-multi-file-%d", getpid());
+			snprintf(file_name, OCFS2_MAX_FILENAME_LEN, "%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;
 	}
 
-	ret = verify_pattern(size, region);
-
-	munmap(region, mmap_size);
+	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 void usage(void)
-{
-	printf("Usage: inline-data [blocksize] [FILE]\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");
-}
-
-static int parse_opts(int argc, char **argv)
+static int test_regular_file(int test_no)
 {
-	if (argc < 3)
-		return 1;
+	int ret, fd, new_size, old_size, init_count, count, j, offset;
+	unsigned int test_num = 1;
+	int hole_gap = 2;
 
-	blocksize = atoi(argv[1]);
-	file_name = argv[2];
-
-	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;
-	}
+	snprintf(dirent, OCFS2_MAX_FILENAME_LEN, "inline-data-test-file-%d",
+		 getpid());
+	snprintf(file_name, OCFS2_MAX_FILENAME_LEN, "%s/%s", work_place,
+		 dirent);
 
-	printf("Blocksize:\t\t%d\nMax Inline Data Size:\t%d\nFilename:\t\t%s\n\n",
-	       blocksize, max_inline_size, file_name);
+	printf("################Test Round %d :%s################\n",
+	       test_no, file_name);
 
-	return 0;
-}
-
-int main(int argc, char **argv)
-{
-	int ret, fd, new_size, old_size, count;
+	printf("Test  %d: Write basic pattern\n", test_num);
+	fd = prep_file(max_inline_size);
+	if (fd < 0)
+		return 1;
 
-	if (parse_opts(argc, argv)) {
-		usage();
-		return EINVAL;
+	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 = posix_memalign((void *)&pattern, blocksize, PATTERN_SZ);
-	if (ret) {
-		fprintf(stderr, "posix_memalign error %d: \"%s\"\n",
-			ret, strerror(ret));
-		return 1;
+	ret = verify_pattern_fd(fd, max_inline_size);
+	if (ret)
+		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;
 	}
 
-	ret = posix_memalign((void *)&read_buf, blocksize, PATTERN_SZ);
-	if (ret) {
-		fprintf(stderr, "posix_memalign error %d: \"%s\"\n",
-			ret, strerror(ret));
-		return 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;
 	}
+	test_num++;
 
-	srand(getpid());
-	page_size = sysconf(_SC_PAGESIZE);
+	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;
 
-	printf("Test  1: Write basic pattern\n");
-	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;
+	}
+	test_num++;
 
-	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;
+	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  3: Reduce size with truncate\n");
-	new_size = max_inline_size - 180;
-	ret = truncate_pattern(fd, max_inline_size, new_size);
+	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);
 	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 +580,43 @@ int main(int argc, char **argv)
 	ret = verify_pattern_fd(fd, new_size);
 	if (ret)
 		return ret;
-
-	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)
+	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: 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 +627,17 @@ int main(int argc, char **argv)
 	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 +648,87 @@ int main(int argc, char **argv)
 	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);
+	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) {
-		if (ret)
-			return ret;
-		ret = verify_pattern_fd(fd, max_inline_size);
+	for (j = 1; j <= max_inline_size; j++) {
+		ret = verify_pattern_mmap(fd, j);
 		if (ret)
 			return ret;
 	}
 
-	printf("Test  10: Punch hole\n");
-	ret = try_punch_hole(fd, 10, 100);
-	if (ret != ENOTTY) {
-		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;
-		ret = verify_pattern_fd(fd, max_inline_size);
-		if (ret)
+	}
+	test_num++;
+
+	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;
+	}
+	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 +741,18 @@ int main(int argc, char **argv)
 	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 +764,42 @@ int main(int argc, char **argv)
 	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 +816,17 @@ int main(int argc, char **argv)
 		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 +842,17 @@ int main(int argc, char **argv)
 	ret = __verify_pattern_fd(fd, max_inline_size, 1);
 	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, 1, test_num);
+		if (ret < 0)
+			return ret;
+	}
+	test_num++;
 
-	printf("Test 16: O_DIRECT write\n");
+	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 +862,65 @@ int main(int argc, char **argv)
 	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++;
 
-	printf("All File I/O Tests Passed\n");
+	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 Files 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);
 
 	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;
+}
-- 
1.5.5




More information about the Ocfs2-tools-devel mailing list