[Ocfs2-tools-devel] [Ocfs2-test-devel] [PATCH 2/6] New set of inline-data testing tools:Add single-node testing binary for regular file
tristan.ye
tristan.ye at oracle.com
Sat Aug 30 03:18:46 PDT 2008
Have sent this patch out before,now just have some other minor
modifications,
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.
Signed-off-by: Tristan Ye <tristan.ye at oracle.com>
---
Index: ocfs2-test/programs/inline-data/single-inline-data.c
===================================================================
--- ocfs2-test/programs/inline-data/single-inline-data.c (revision 0)
+++ ocfs2-test/programs/inline-data/single-inline-data.c (revision 0)
@@ -0,0 +1,1264 @@
+/*
+ * 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.
+ *
+ * [I] Tests of inline-data code. All tests read back the pattern
+ * written to verify data integrity.
+ * 1) Write a pattern, read it back.
+ * 2) Shrink file by some bytes
+ * 3) Extend file again
+ * 4) Mmap file and read pattern
+ * 5) Reserve space inside of region
+ * 6) Punch hole in the middle
+ *
+ * [II] Tests intended to force data out of inode. Before each test,
+ * we'll have to truncate to zero and re-write file.
+ * 1) Seek past EOF, write pattern.
+ * 2) Mmap and do a write inside of i_size
+ * 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 multiple processes,and perform r/w
separately.
+ *
+ * XXX: This could easily be turned into an mpi program, where a
+ * second node does the verification step.
+ */
+
+#define _XOPEN_SOURCE 600
+#define _GNU_SOURCE
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/vfs.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <limits.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+
+#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 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 "single-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 = 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 + 1));
+}
+
+static inline char rand_char(void)
+{
+ return 'A' + (char) get_rand(0, 25);
+}
+
+static void fill_pattern(int size)
+{
+ int i;
+
+ /*
+ * Make sure that anything in the buffer past size is zero'd,
+ * as a regular file should look.
+ */
+ memset(pattern, 0, PATTERN_SZ);
+
+ for(i = 0; i < size; i++)
+ pattern[i] = rand_char();
+}
+
+static int truncate_pattern(int fd, unsigned int old_size,
+ unsigned int new_size)
+{
+ int bytes = old_size - new_size;
+ int ret;
+
+ memset(pattern + new_size, 0, bytes);
+
+ ret = ftruncate(fd, new_size);
+ if (ret == -1) {
+ fprintf(stderr, "ftruncate error %d: \"%s\"\n",
+ ret, strerror(ret));
+ return -1;
+ }
+
+ 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) {
+ fprintf(stderr, "ftruncate error %d: \"%s\"\n",
+ ret, strerror(ret));
+ return -1;
+ }
+
+ ret = write_at(fd, pattern + old_size, bytes, old_size);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static int try_ioctl(int which, int fd, unsigned int offset, unsigned
int count)
+{
+ struct ocfs2_space_resv sr;
+
+ memset(&sr, 0, sizeof(sr));
+ sr.l_whence = SEEK_SET;
+ sr.l_start = offset;
+ sr.l_len = count;
+
+ return ioctl(fd, which, &sr);
+}
+
+static int try_reserve(int fd, unsigned int offset, unsigned int count)
+{
+ int ret;
+
+ 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;
+ }
+
+ return 0;
+}
+
+static int try_punch_hole(int fd, unsigned int offset, unsigned int
count)
+{
+ int ret;
+
+ memset(pattern + offset, 0, count);
+
+ 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;
+ }
+
+ return 0;
+}
+
+static int mmap_write_at(int fd, const char *buf, size_t count, off_t
offset)
+{
+ unsigned int mmap_size = page_size;
+ unsigned int size = count + offset;
+ int i, j, ret;
+ char *region;
+
+ while (mmap_size < size)
+ mmap_size += page_size;
+
+ 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);
+
+ return 0;
+}
+
+static int write_at(int fd, const void *buf, size_t count, off_t
offset)
+{
+ int ret;
+
+ ret = pwrite(fd, buf, count, offset);
+ 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;
+ }
+
+ return 0;
+}
+
+static int prep_file_no_fill(unsigned int size, int open_direct)
+{
+ int fd, ret;
+ int flags = FILE_BUFFERED_RW_FLAGS;
+ size_t count = size;
+
+ if (open_direct) {
+ flags |= O_DIRECT;
+ count = blocksize;
+ }
+
+ fd = open(file_name, flags, FILE_MODE);
+ if (fd == -1) {
+ ret = errno;
+ fprintf(stderr, "open error %d: \"%s\"\n", ret, strerror(ret));
+ return -1;
+ }
+
+ ret = write_at(fd, pattern, count, 0);
+ if (ret)
+ return ret;
+
+ if (count > size) {
+ ret = ftruncate(fd, size);
+ if (ret) {
+ ret = errno;
+ fprintf(stderr, "truncate error %d: \"%s\"\n", ret,
+ strerror(ret));
+ 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;
+ }
+ }
+ return 0;
+}
+
+static int __verify_pattern_fd(int fd, unsigned int size, int
direct_read)
+{
+ int ret;
+ unsigned int rd_size = size;
+
+ if (direct_read)
+ rd_size = blocksize;
+
+ ret = pread(fd, read_buf, rd_size, 0);
+ 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;
+ }
+
+ return verify_pattern(size, read_buf);
+}
+
+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;
+
+ 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;
+ }
+
+ ret = verify_pattern(size, region);
+
+ munmap(region, mmap_size);
+
+ return 0;
+}
+
+static void usage(void)
+{
+ 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 int parse_opts(int argc, char **argv)
+{
+ 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;
+
+ 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;
+
+}
+
+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;
+}
+
+static int is_file_inlined(char *dirent_name, unsigned long *i_size,
+ unsigned int *id_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);
+
+ 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();
+
+ 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",
+ ret, strerror(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;
+ }
+
+ 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);
+
+ 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 = 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)
+ 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 = 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);
+ if (ret)
+ return ret;
+ old_size = new_size;
+ new_size = 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 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 %d: Fsync\n", test_num);
+ close(fd);
+ fd = prep_file(max_inline_size);
+ if (fd < 0)
+ return fd;
+ ret = fsync(fd);
+ 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: Fdatasync\n", test_num);
+ close(fd);
+ fd = prep_file(max_inline_size);
+ if (fd < 0)
+ return fd;
+ ret = fdatasync(fd);
+ 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: Mmap reads\n", test_num);
+ close(fd);
+ fd = prep_file(max_inline_size);
+ if (fd < 0)
+ return fd;
+ for (j = 1; j <= max_inline_size; j++) {
+ ret = verify_pattern_mmap(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 %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 %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);
+ if (fd < 0)
+ return 1;
+ count = PATTERN_SZ - max_inline_size;
+ ret = write_at(fd, &pattern[max_inline_size], count, max_inline_size);
+ if (ret)
+ return ret;
+ 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 %d: Force expansion to extents via mmap write\n",
test_num);
+ close(fd);
+ fd = prep_file(max_inline_size);
+ if (fd < 0)
+ return 1;
+ fill_pattern(max_inline_size);
+ ret = mmap_write_at(fd, pattern, max_inline_size, 0);
+ 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 , 0, test_num);
+ if (ret < 0)
+ return ret;
+ }
+ test_num++;
+
+ 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;
+ 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 %d: Force expansion to extents via large reservation\n",
test_num);
+ close(fd);
+ fd = prep_file(max_inline_size);
+ if (fd < 0)
+ return 1;
+ new_size = PATTERN_SZ;
+ ret = try_reserve(fd, 0, new_size);
+ if (ret != ENOTTY) {
+ if (ret)
+ return ret;
+ ret = extend_pattern(fd, max_inline_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, 0, test_num);
+ if (ret < 0)
+ return ret;
+ }
+ test_num++;
+
+ printf("Test %d: O_DIRECT read\n", test_num);
+ close(fd);
+ fd = prep_file(max_inline_size);
+ if (fd < 0)
+ return 1;
+ close(fd);
+ fd = open(file_name, O_RDWR|O_DIRECT);
+ if (fd < 0) {
+ ret = errno;
+ fprintf(stderr, "open (direct) error %d: \"%s\"\n", ret,
+ strerror(ret));
+ return -1;
+ }
+ 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 %d: O_DIRECT write\n", test_num);
+ close(fd);
+ fill_pattern(max_inline_size);
+ fd = prep_file_no_fill(max_inline_size, 1);
+ if (fd < 0)
+ return 1;
+ ret = __verify_pattern_fd(fd, max_inline_size, 1);
+ 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;
+}
Property changes on:
ocfs2-test/programs/inline-data/single-inline-data.c
___________________________________________________________________
Name: svn:executable
+ *
More information about the Ocfs2-tools-devel
mailing list