[Ocfs2-test-devel] [PATCH 04/12] Ocfs2-test: Add utility funcs for both single-node and multi-nodes tests.

Tristan Ye tristan.ye at oracle.com
Wed Oct 14 01:35:56 PDT 2009


All common funcs shared by single-node and multi-nodes testing binaries
gathered here.

Signed-off-by: Tristan Ye <tristan.ye at oracle.com>
---
 programs/reflink_tests/reflink_test_utils.c | 1281 +++++++++++++++++++++++++++
 1 files changed, 1281 insertions(+), 0 deletions(-)
 create mode 100755 programs/reflink_tests/reflink_test_utils.c

diff --git a/programs/reflink_tests/reflink_test_utils.c b/programs/reflink_tests/reflink_test_utils.c
new file mode 100755
index 0000000..5fa05aa
--- /dev/null
+++ b/programs/reflink_tests/reflink_test_utils.c
@@ -0,0 +1,1281 @@
+ /* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * reflink_test_utils.c
+ *
+ * Provide generic utility fuctions for both single and multiple
+ * nodes refcount test on ocfs2.
+ *
+ * Written by tristan.ye at oracle.com
+ *
+ * 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.
+ */
+
+#include "reflink_test.h"
+
+extern char *orig_pattern;
+extern int test_flags;
+
+extern unsigned long page_size;
+extern unsigned long file_size;
+
+extern unsigned int blocksize;
+extern unsigned long clustersize;
+extern unsigned int max_inline_size;
+
+extern int open_rw_flags;
+extern int open_ro_flags;
+
+extern ocfs2_filesys *fs;
+extern struct ocfs2_super_block *ocfs2_sb;
+
+extern char *prog;
+
+static char buf_dio[DIRECTIO_SLICE] __attribute__ ((aligned(DIRECTIO_SLICE)));
+
+unsigned long get_rand(unsigned long min, unsigned long max)
+{
+	if (min == 0 && max == 0)
+		return 0;
+
+	return min + (rand() % (max - min + 1));
+}
+
+char rand_char(void)
+{
+	return 'A' + (char) get_rand(0, 25);
+}
+
+int read_at(int fd, void *buf, size_t count, off_t offset)
+{
+	int ret;
+	size_t bytes_read;
+
+	ret = pread(fd, buf, count, offset);
+	if (ret < 0) {
+		ret = errno;
+		fprintf(stderr, "read error %d: \"%s\"\n", ret, strerror(ret));
+		return -1;
+	}
+
+	bytes_read = ret;
+	while (bytes_read < count) {
+
+		ret = pread(fd, buf + bytes_read, count - bytes_read, offset +
+			    bytes_read);
+		if (ret < 0) {
+			ret = errno;
+			fprintf(stderr, "read error %d: \"%s\"\n", ret,
+				strerror(ret));
+			return -1;
+		}
+
+		bytes_read += ret;
+	}
+
+	return 0;
+}
+
+int read_at_file(char *pathname, void *buf, size_t count, off_t offset)
+{
+	int fd, ret, o_ret;
+
+	fd  = open64(pathname, open_ro_flags);
+	if (fd < 0) {
+		o_ret = fd;
+		fd = errno;
+		fprintf(stderr, "open file %s failed:%d:%s\n", pathname, fd,
+			strerror(fd));
+		fd = o_ret;
+		return fd;
+	}
+
+	ret = read_at(fd, buf, count, offset);
+
+	close(fd);
+
+	return ret;
+}
+
+
+int mmap_read_at(int fd, char *buf, size_t count, off_t offset)
+{
+	int ret;
+	unsigned long mmap_size = page_size;
+	unsigned long size = offset + count;
+	char *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;
+	}
+
+	memcpy(buf, region + offset, count);
+
+	munmap(region, mmap_size);
+
+	return 0;
+}
+
+int mmap_read_at_file(char *pathname, void *buf, size_t count,
+		      off_t offset)
+{
+	int fd, ret, o_ret;
+
+	fd  = open64(pathname, open_ro_flags);
+	if (fd < 0) {
+		o_ret = fd;
+		fd = errno;
+		fprintf(stderr, "open file %s failed:%d:%s\n", pathname, fd,
+			strerror(fd));
+		fd = o_ret;
+		return fd;
+	}
+
+	ret = mmap_read_at(fd, buf, count, offset);
+
+	close(fd);
+
+	return ret;
+}
+
+int write_at(int fd, const void *buf, size_t count, off_t offset)
+{
+	int ret;
+	size_t bytes_write;
+
+	ret = pwrite(fd, buf, count, offset);
+
+	if (ret < 0) {
+		ret = errno;
+		fprintf(stderr, "write error %d: \"%s\"\n", ret, strerror(ret));
+		return -1;
+	}
+
+	bytes_write = ret;
+	while (bytes_write < count) {
+
+		ret = pwrite(fd, buf + bytes_write, count - bytes_write,
+			     offset + bytes_write);
+
+		if (ret < 0) {
+			ret = errno;
+			fprintf(stderr, "write error %d: \"%s\"\n", ret,
+				strerror(ret));
+			return -1;
+		}
+
+		bytes_write += ret;
+	}
+
+	return 0;
+}
+
+int write_at_file(char *pathname, const void *buf, size_t count,
+			 off_t offset)
+{
+	int fd, ret, o_ret;
+
+	fd  = open64(pathname, open_rw_flags);
+	if (fd < 0) {
+		o_ret = fd;
+		fd = errno;
+		fprintf(stderr, "open file %s failed:%d:%s\n", pathname, fd,
+			strerror(fd));
+		fd = o_ret;
+		return fd;
+	}
+
+	ret = write_at(fd, buf, count, offset);
+
+	close(fd);
+
+	return ret;
+}
+
+int mmap_write_at(int fd, const char *buf, size_t count, off_t offset)
+{
+	int ret;
+	unsigned long mmap_size = page_size;
+	unsigned long size = offset + count;
+	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;
+	}
+
+	memcpy(region + offset, buf, count);
+
+	munmap(region, mmap_size);
+
+	return 0;
+}
+
+int mmap_write_at_file(char *pathname, const void *buf, size_t count,
+		       off_t offset)
+{
+	int fd, ret, o_ret;
+
+	fd  = open64(pathname, open_rw_flags);
+	if (fd < 0) {
+		o_ret = fd;
+		fd = errno;
+		fprintf(stderr, "open file %s failed:%d:%s\n", pathname, fd,
+			strerror(fd));
+		fd = o_ret;
+		return fd;
+	}
+
+	ret = mmap_write_at(fd, buf, count, offset);
+
+	close(fd);
+
+	return ret;
+}
+
+
+int get_rand_buf(char *buf, unsigned long size)
+{
+	unsigned long i;
+
+	for (i = 0; i < size; i++)
+		buf[i] = rand_char();
+
+	return 0;
+}
+
+int fill_pattern(unsigned long size)
+{
+	memset(orig_pattern, 0, PATTERN_SIZE);
+	get_rand_buf(orig_pattern, size);
+
+	return 0;
+}
+
+int prep_orig_file(char *file_name, unsigned long size, int once)
+{
+	int fd, fdt, ret, o_ret;
+	unsigned long offset = 0, write_size = 0;
+	char tmp_path[PATH_MAX];
+
+	fd = open64(file_name, open_rw_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;
+	}
+
+	/*
+	 * HUGEFILE large than PATTERN_SIZE will not use pattern to verify
+	*/
+
+	if (size > PATTERN_SIZE) {
+
+		fill_pattern(PATTERN_SIZE);
+
+		if (once) {
+			while (offset < size) {
+				if ((offset + PATTERN_SIZE) > size)
+					write_size = size - offset;
+				else
+					write_size = PATTERN_SIZE;
+
+				ret = write_at(fd, orig_pattern, write_size,
+					       offset);
+				if (ret < 0)
+					return ret;
+
+				offset += write_size;
+			}
+
+		} else {
+
+			snprintf(tmp_path, PATH_MAX, "%s-tmp-file", file_name);
+			fdt = open64(tmp_path, open_rw_flags, FILE_MODE);
+
+			unlink(tmp_path);
+
+			while (offset < size) {
+
+				if ((offset + M_SIZE) > size)
+					write_size = size - offset;
+				else
+					write_size = M_SIZE;
+
+				ret = write_at(fd, orig_pattern +
+					       offset % PATTERN_SIZE,
+					       write_size,
+					       offset);
+				if (ret < 0)
+					return ret;
+
+				ret = write_at(fdt, orig_pattern +
+					       offset % PATTERN_SIZE,
+					       write_size,
+					       offset);
+				if (ret < 0)
+					return ret;
+
+				offset += write_size;
+			}
+
+			close(fdt);
+		}
+
+		close(fd);
+		return 0;
+	}
+
+	/*
+	* file within PATTERN_SIZE should use pattern to verify
+	*/
+
+	fill_pattern(size);
+
+	if (once) {
+		ret = write_at(fd, orig_pattern, size, 0);
+		if (ret < 0)
+			return ret;
+
+		close(fd);
+		return 0;
+	}
+
+	/*
+	* otherwise we need a tmp file to make extents incontiguous by
+	* writing data by turns
+	*/
+
+	snprintf(tmp_path, PATH_MAX, "%s-tmp-file", file_name);
+	fdt = open64(tmp_path, open_rw_flags, FILE_MODE);
+	if (fdt < 0) {
+		o_ret = fdt;
+		fdt = errno;
+		fprintf(stderr, "create file %s failed:%d:%s\n", tmp_path, fdt,
+			strerror(fdt));
+		fdt = o_ret;
+		return fdt;
+	}
+
+	unlink(tmp_path);
+
+	while (offset < size) {
+		if (test_flags & RAND_TEST)
+			write_size = (size >= HUNK_SIZE * 2) ?
+				      get_rand(1, HUNK_SIZE * 2) :
+				      get_rand(1, size);
+		else
+			write_size = HUNK_SIZE;
+
+		if (offset + write_size > size)
+			write_size = size - offset;
+
+		ret = write_at(fd, orig_pattern + offset, write_size, offset);
+		if (ret < 0)
+			return ret;
+
+		ret = write_at(fdt, orig_pattern + offset, write_size, offset);
+		if (ret < 0)
+			return ret;
+
+		offset += write_size;
+	}
+
+	close(fdt);
+	close(fd);
+
+	return 0;
+}
+
+int prep_orig_file_dio(char *file_name, unsigned long size)
+{
+	int fd, ret, o_ret, flags;
+	unsigned long offset = 0, write_size = DIRECTIO_SLICE;
+
+
+	if ((size % DIRECTIO_SLICE) != 0) {
+
+		fprintf(stderr, "File size in directio tests is expected to "
+			"be %d aligned, your size %ld is not allowed.\n",
+			DIRECTIO_SLICE, size);
+		return -1;
+	}
+
+	flags = FILE_RW_FLAGS | O_DIRECT;
+
+	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;
+	}
+
+
+	while (offset < size) {
+
+		if (offset + write_size > size)
+			write_size = size - offset;
+
+		memset(buf_dio, rand_char(), DIRECTIO_SLICE);
+
+		ret = pwrite(fd, buf_dio, write_size, offset);
+		if (ret < 0) {
+			o_ret = ret;
+			ret = errno;
+			fprintf(stderr, "write failed:%d:%s\n", ret,
+				strerror(ret));
+			return ret;
+		}
+
+		offset += write_size;
+
+	}
+
+	close(fd);
+	return 0;
+}
+
+int verify_reflink_pair(const char *src, const char *dest)
+{
+	int fds, fdd, ret, o_ret;
+	char bufs[HUNK_SIZE], bufd[HUNK_SIZE];
+	unsigned long reads, readd;
+
+	fds = open64(src, open_ro_flags);
+	if (fds < 0) {
+		o_ret = fds;
+		fds = errno;
+		fprintf(stderr, "open file %s failed:%d:%s\n", src, fds,
+			strerror(fds));
+		fds = o_ret;
+		return fds;
+	}
+
+	fdd = open64(dest, open_ro_flags);
+	if (fdd < 0) {
+		o_ret = fdd;
+		fdd = errno;
+		fprintf(stderr, "open file %s failed:%d:%s\n", src, fdd,
+			strerror(fdd));
+		fdd = o_ret;
+		return fdd;
+	}
+
+	while ((reads = read(fds, bufs, HUNK_SIZE)) &&
+	       (readd = read(fdd, bufd, HUNK_SIZE))) {
+
+		if (reads != readd) {
+			fprintf(stderr, "data readed are not in the "
+				"same size\n");
+			return 1;
+		}
+
+		ret = memcmp(bufs, bufd, reads);
+		if (ret) {
+			fprintf(stderr, "data readed are different\n");
+			return ret;
+		}
+	}
+
+	close(fds);
+	close(fdd);
+
+	return 0;
+}
+
+int verify_pattern(char *buf, unsigned long offset, unsigned long size)
+{
+	unsigned long i;
+
+	char *start = orig_pattern + offset;
+
+	for (i = 0; i < size; i++) {
+		if (buf[i] != start[i]) {
+			fprintf(stderr, "original file verify failed at byte: "
+				"%ld\n", i);
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
+
+int verify_orig_file(char *orig)
+{
+	int ret, fd, o_ret;
+	unsigned long readed, offset = 0;
+	unsigned long verify_size = 0;
+	char buf[HUNK_SIZE];
+
+	unsigned int mmap_size = page_size;
+	void *region;
+
+	fd = open64(orig, open_ro_flags);
+	if (fd < 0) {
+		o_ret = fd;
+		fd = errno;
+		fprintf(stderr, "open file %s failed:%d:%s\n", orig, fd,
+			strerror(fd));
+		fd = o_ret;
+		return fd;
+	}
+
+	if (file_size > PATTERN_SIZE)
+		verify_size = PATTERN_SIZE;
+	else
+		verify_size = file_size;
+
+	/*
+	* use mmap read to verify original file
+	*/
+	if (test_flags & MMAP_TEST) {
+
+		while (mmap_size < verify_size)
+			mmap_size += page_size;
+
+		region = mmap(NULL, mmap_size, PROT_READ, MAP_SHARED, fd, 0);
+		if (region == MAP_FAILED) {
+			o_ret = ret;
+			ret = errno;
+			fprintf(stderr, "mmap (read) error %d: \"%s\"\n", ret,
+				strerror(ret));
+			ret = o_ret;
+			return ret;
+		}
+
+		ret = verify_pattern(region, 0, verify_size);
+		if (ret) {
+			fprintf(stderr, "Verify orig file by mmap failed\n");
+			return ret;
+		}
+
+		munmap(region, mmap_size);
+		return 0;
+
+	}
+
+	while ((readed = read(fd, buf, HUNK_SIZE)) > 0) {
+		ret = verify_pattern(buf, offset, readed);
+		if (ret) {
+			fprintf(stderr, "Verify original file failed\n");
+			return ret;
+		}
+
+		offset += readed;
+		if (offset >= PATTERN_SIZE)
+			break;
+	}
+
+	close(fd);
+
+	return 0;
+}
+
+int do_reflinks(const char *src, const char *dest_prefix,
+		       unsigned long iter, int manner)
+{
+	int ret;
+	unsigned long i, j = 0;
+	char from[PATH_MAX], to[PATH_MAX];
+
+	for (i = 0; i < iter; i++) {
+
+		snprintf(to, PATH_MAX, "%sr%ld", dest_prefix, i);
+		if (i == 0) {
+			strcpy(from, src);
+		} else {
+			if (manner == 0)
+				j = 0;
+			if (manner == 1)
+				j = i - 1;
+			if (manner > 1)
+				j = get_rand(0, i - 1);
+
+			if (j == 0)
+				strcpy(from, src);
+			else
+				snprintf(from, PATH_MAX, "%sr%ld",
+					 dest_prefix, j);
+		}
+
+		ret = reflink(from, to, 1);
+		if (ret) {
+			fprintf(stderr, "do_reflinks failed\n");
+			return ret;
+		}
+
+	}
+
+	return 0;
+}
+
+int do_reflinks_at_random(const char *src, const char *dest_prefix,
+				 unsigned long iter)
+{
+	int ret, o_ret, fd, method;
+	unsigned long i = 0;
+	char dest[PATH_MAX], buf[2 * HUNK_SIZE], *ptr;
+
+	unsigned long write_size = 0, append_size = 0, truncate_size = 0;
+	unsigned long read_size = 0, offset = 0;
+	unsigned long tmp_file_size = file_size;
+
+	fd = open64(src, open_rw_flags | O_APPEND);
+
+	if (fd < 0) {
+		o_ret = fd;
+		fd = errno;
+		fprintf(stderr, "open file %s failed:%d:%s\n",
+			src, fd, strerror(fd));
+		fd = o_ret;
+		return fd;
+	}
+
+	if (test_flags & ODCT_TEST)
+		ptr = buf_dio;
+	else
+		ptr = buf;
+
+	while (i < iter) {
+
+		method = get_rand(1, 4);
+
+		if (method == 1) {
+			if (test_flags & ODCT_TEST)
+				write_size = DIRECTIO_SLICE;
+			else
+				write_size = get_rand(1, 2 * HUNK_SIZE);
+
+			get_rand_buf(ptr, write_size);
+
+			if (test_flags & ODCT_TEST)
+				offset = get_rand(0, file_size /
+						  DIRECTIO_SLICE) *
+						  DIRECTIO_SLICE;
+			else
+				offset = get_rand(0, file_size - 1);
+
+			ret = write_at(fd, ptr, write_size, offset);
+			if (ret < 0) {
+				fprintf(stderr, "do_reflinks_at_random failed"
+					" at write_at\n");
+				return ret;
+			}
+		}
+
+		if (method == 2) {
+			if (test_flags & ODCT_TEST)
+				append_size = DIRECTIO_SLICE;
+			else
+				append_size = get_rand(1, 2 * HUNK_SIZE);
+			get_rand_buf(ptr, append_size);
+			ret = write(fd, ptr, append_size);
+			if (ret < 0) {
+				o_ret = ret;
+				ret = errno;
+				fprintf(stderr, "do_reflinks_at_random failed "
+					"at appending on file %s:%d:%s.\n",
+					src, ret, strerror(ret));
+				ret = o_ret;
+				return ret;
+			}
+
+			tmp_file_size += append_size;
+		}
+		if (method == 3) {
+			if (test_flags & ODCT_TEST)
+				truncate_size = get_rand(1, file_size /
+							 DIRECTIO_SLICE) *
+							 DIRECTIO_SLICE;
+			else
+				truncate_size = get_rand(1, file_size);
+			ret = ftruncate(fd, truncate_size);
+			if (ret < 0) {
+				o_ret = ret;
+				ret = errno;
+				fprintf(stderr, "do_reflinks_at_random failed "
+					"at truncating on file %s:%d:%s.\n",
+					src, ret, strerror(ret));
+				ret = o_ret;
+				return ret;
+			}
+
+			tmp_file_size = truncate_size;
+		}
+		if (method == 4) {
+
+			if (test_flags & ODCT_TEST)
+				read_size = DIRECTIO_SLICE;
+			else
+				read_size = get_rand(1, 2 * HUNK_SIZE);
+
+			if (test_flags & ODCT_TEST)
+				offset = get_rand(0, tmp_file_size /
+						  DIRECTIO_SLICE) *
+						  DIRECTIO_SLICE;
+			else
+				offset = get_rand(0, tmp_file_size);
+
+			if ((offset + read_size) > tmp_file_size)
+				read_size = tmp_file_size - offset;
+
+			if (test_flags & ODCT_TEST)
+
+				read_size = read_size / DIRECTIO_SLICE *
+					    DIRECTIO_SLICE;
+
+			ret = read_at(fd, ptr, read_size, offset);
+			if (ret < 0) {
+				o_ret = ret;
+				ret = errno;
+				fprintf(stderr, "do_reflinks_at_random failed "
+					"at reading on file %s:%d:%s.\n",
+					src, ret, strerror(ret));
+				ret = o_ret;
+				return ret;
+			}
+		}
+
+		snprintf(dest, PATH_MAX, "%sr%ld", dest_prefix, i);
+		ret = reflink(src, dest, 1);
+		if (ret) {
+			fprintf(stderr, "do_reflinks_at_random failed at "
+				"reflink(%ld) after method(%d) operation.\n",
+				i, method);
+			return ret;
+		}
+
+		i++;
+	}
+
+	close(fd);
+
+	return 0;
+}
+
+int do_reads_on_reflinks(char *ref_pfx, unsigned long iter,
+				unsigned long size, unsigned long interval)
+{
+	int ret, fd, o_ret;
+	unsigned long i, read_size, offset = 0;
+	char ref_path[PATH_MAX];
+	char buf[HUNK_SIZE * 2], *ptr;
+
+	if (test_flags & ODCT_TEST)
+		ptr = buf_dio;
+	else
+		ptr = buf;
+
+	for (i = 0; i < iter; i++) {
+		if ((i % 3) == 0)
+			continue;
+
+		snprintf(ref_path, PATH_MAX, "%sr%ld", ref_pfx, i);
+		fd = open64(ref_path, open_ro_flags);
+		if (fd < 0) {
+			o_ret = fd;
+			fd = errno;
+			fprintf(stderr, "open file %s failed:%d:%s\n",
+				ref_path, fd, strerror(fd));
+			fd = o_ret;
+			return fd;
+		}
+
+		offset = 0;
+
+		while (offset < size) {
+			if (test_flags & RAND_TEST)
+				read_size = ((i % 2) == 0) ?
+					     get_rand(1, HUNK_SIZE) :
+					     get_rand(HUNK_SIZE, HUNK_SIZE * 2);
+			else if (test_flags & ODCT_TEST)
+				read_size = DIRECTIO_SLICE;
+			else
+				read_size = HUNK_SIZE;
+
+			memset(ptr, 0, read_size);
+
+			if (test_flags & MMAP_TEST) {
+
+				/*
+				if ((offset + read_size) > size)
+					break;
+				*/
+
+				if ((offset + read_size) > size)
+					read_size = size - offset;
+
+				ret = mmap_read_at(fd, ptr, read_size, offset);
+				if (ret) {
+					fprintf(stderr, "mmap_read_at fail\n");
+					return ret;
+				}
+
+			} else {
+
+				/*
+				if ((offset + read_size) > size)
+					break;
+				*/
+
+				if ((offset + read_size) > size)
+					read_size = size - offset;
+
+				ret = read_at(fd, ptr, read_size, offset);
+				if (ret) {
+
+					fprintf(stderr, "read_at failed\n");
+					return ret;
+				}
+			}
+
+			if (test_flags & RAND_TEST)
+				offset = offset + read_size +
+					 get_rand(0, interval);
+			else
+				offset = offset + read_size + interval;
+		}
+
+		close(fd);
+	}
+
+	return 0;
+}
+
+int do_cows_on_write(char *ref_pfx, unsigned long iter,
+			    unsigned long size, unsigned long interval)
+{
+	int ret, fd, o_ret;
+	unsigned long i, write_size, offset = 0;
+	char ref_path[PATH_MAX];
+	char buf[HUNK_SIZE * 2], *ptr;
+
+	if (test_flags & ODCT_TEST)
+		ptr = buf_dio;
+	else
+		ptr = buf;
+
+	for (i = 0; i < iter; i++) {
+		/*
+		 * leave 1/3 reflinks still shared the same extents
+		*/
+		if ((i % 3) == 0)
+			continue;
+
+		snprintf(ref_path, PATH_MAX, "%sr%ld", ref_pfx, i);
+		fd = open64(ref_path, open_rw_flags);
+		if (fd < 0) {
+			o_ret = fd;
+			fd = errno;
+			fprintf(stderr, "open file %s failed:%d:%s\n",
+				ref_path, fd, strerror(fd));
+			fd = o_ret;
+			return fd;
+		}
+
+		offset = 0;
+
+		while (offset < size) {
+			if (test_flags & RAND_TEST)
+				write_size = ((i % 2) == 0) ?
+					     get_rand(1, HUNK_SIZE) :
+					     get_rand(HUNK_SIZE, HUNK_SIZE * 2);
+			else if (test_flags & ODCT_TEST)
+				write_size = DIRECTIO_SLICE;
+			else
+				write_size = HUNK_SIZE;
+
+			get_rand_buf(ptr, write_size);
+
+			if (test_flags & MMAP_TEST) {
+
+				/*
+				if ((offset + write_size) > size)
+					break;
+				*/
+
+				if ((offset + write_size) > size)
+					write_size = size - offset;
+
+				ret = mmap_write_at(fd, ptr, write_size,
+						    offset);
+				if (ret) {
+
+					fprintf(stderr, "mmap_write_at fail\n");
+					return ret;
+				}
+
+			} else {
+
+				/*
+				if ((offset + write_size) > size)
+					break;
+				*/
+
+				if ((offset + write_size) > size)
+					write_size = size - offset;
+
+				ret = write_at(fd, ptr, write_size, offset);
+				if (ret) {
+
+					fprintf(stderr, "write_at failed\n");
+					return ret;
+				}
+			}
+
+			if (test_flags & RAND_TEST)
+				offset = offset + write_size +
+					 get_rand(0, interval);
+			else
+				offset = offset + write_size + interval;
+		}
+
+		close(fd);
+	}
+
+	return 0;
+}
+
+int do_cows_on_ftruncate(char *ref_pfx, unsigned long iter,
+				unsigned long size)
+{
+	int ret, fd, o_ret;
+	unsigned long i, truncate_size;
+	char ref_path[PATH_MAX];
+
+	for (i = 0; i < iter; i++) {
+		snprintf(ref_path, PATH_MAX, "%sr%ld", ref_pfx, i);
+		fd = open64(ref_path, open_rw_flags);
+		if (fd < 0) {
+			fd = errno;
+			fprintf(stderr, "create file %s failed:%d:%s\n",
+				ref_path, fd, strerror(fd));
+			return fd;
+		}
+
+		if (test_flags & RAND_TEST)
+			truncate_size = get_rand(0, size);
+		else if (test_flags & ODCT_TEST)
+			truncate_size = ((size / DIRECTIO_SLICE) / iter) * i *
+					DIRECTIO_SLICE;
+		else
+			truncate_size = (size / iter) * i;
+
+		ret = ftruncate(fd, truncate_size);
+		if (ret) {
+			o_ret = ret;
+			ret = errno;
+			fprintf(stderr, "truncate file %s failed:%d:%s\n",
+				ref_path, ret, strerror(ret));
+			ret = o_ret;
+			return ret;
+		}
+
+		close(fd);
+	}
+
+	return 0;
+}
+
+int do_appends(char *ref_pfx, unsigned long iter)
+{
+	int ret, fd, o_ret;
+	unsigned long i, append_size;
+	char ref_path[PATH_MAX];
+	char buf[HUNK_SIZE], *ptr;
+
+	if (test_flags & ODCT_TEST)
+		ptr = buf_dio;
+	else
+		ptr = buf;
+
+	for (i = 0; i < iter; i++) {
+		snprintf(ref_path, PATH_MAX, "%sr%ld", ref_pfx, i);
+		fd = open64(ref_path, open_rw_flags | O_APPEND);
+		if (fd < 0) {
+			o_ret = fd;
+			fd = errno;
+			fprintf(stderr, "create file %s failed:%d:%s\n",
+				ref_path, fd, strerror(fd));
+			fd = o_ret;
+			return fd;
+		}
+
+		if (test_flags & RAND_TEST)
+			append_size = get_rand(1, HUNK_SIZE);
+		else if (test_flags & ODCT_TEST)
+			append_size = DIRECTIO_SLICE;
+		else
+			append_size = HUNK_SIZE;
+
+		get_rand_buf(ptr, append_size);
+
+		ret = write(fd, ptr, append_size);
+		if (ret < 0) {
+			o_ret = ret;
+			ret = errno;
+			fprintf(stderr, "append file %s failed:%d:%s\n",
+				ref_path, ret, strerror(ret));
+			ret = o_ret;
+			return ret;
+		}
+
+		close(fd);
+	}
+
+	return 0;
+}
+
+int do_unlink(char *path)
+{
+	int ret, o_ret;
+
+	ret = unlink(path);
+	if (ret < 0) {
+		o_ret = ret;
+		ret = errno;
+		fprintf(stderr, "unlink file %s failed:%d:%s\n",
+			path, ret, strerror(ret));
+		ret = o_ret;
+		return ret;
+	}
+
+	return 0;
+}
+
+int do_unlinks(char *ref_pfx, unsigned long iter)
+{
+	int ret, o_ret;
+
+	unsigned long i;
+	char ref_path[PATH_MAX];
+
+	for (i = 0; i < iter; i++) {
+		snprintf(ref_path, PATH_MAX, "%sr%ld", ref_pfx, i);
+		ret = unlink(ref_path);
+		if (ret < 0) {
+			o_ret = ret;
+			ret = errno;
+			fprintf(stderr, "unlink file %s failed:%d:%s\n",
+				ref_path, ret, strerror(ret));
+			ret = o_ret;
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+int open_ocfs2_volume(char *device_name)
+{
+	int open_flags = OCFS2_FLAG_HEARTBEAT_DEV_OK | OCFS2_FLAG_RO;
+	int ret;
+	uint64_t superblock = 0, block_size = 0;
+
+	ret = ocfs2_open(device_name, open_flags, superblock, block_size,
+			 &fs);
+	if (ret < 0) {
+		com_err(prog, ret,
+			"while opening file system for reflink_test.");
+		return ret;
+	}
+
+	ocfs2_sb = OCFS2_RAW_SB(fs->fs_super);
+	if (!(ocfs2_sb->s_feature_incompat &
+	      OCFS2_FEATURE_INCOMPAT_REFCOUNT_TREE)) {
+		fprintf(stderr, "refcount is 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);
+
+	ocfs2_close(fs);
+
+	return 0;
+}
+
+/*
+ * Following funcs borrowed from fill_verify_holes
+ * to test holes punching and filling in reflinks
+ *
+*/
+
+int prep_file_with_hole(char *name, unsigned long size)
+{
+	int ret, fd;
+	char trailer[1];
+
+	fd = open64(name, open_rw_flags | O_TRUNC | O_APPEND, FILE_MODE);
+
+	if (fd < 0) {
+		fprintf(stderr, "open error %d: \"%s\"\n", errno,
+			strerror(errno));
+		return -1;
+	}
+
+	ret = ftruncate(fd, size - 1);
+	if (ret < 0) {
+
+		close(fd);
+		fprintf(stderr, "ftruncate error %d: \"%s\"\n", errno,
+			strerror(errno));
+		return -1;
+	}
+
+	memset(trailer, 0, 1);
+
+	ret = write(fd, trailer, 1);
+
+	if (ret < 0) {
+
+		close(fd);
+		fprintf(stderr, "write error %d: \"%s\"\n", errno,
+			strerror(errno));
+		return -1;
+	}
+
+	close(fd);
+
+	return 0;
+
+}
+
+FILE *open_logfile(char *logname)
+{
+	FILE *logfile;
+
+	if (!logname)
+		logfile = stdout;
+	else
+		logfile = fopen(logname, "wa");
+
+	if (!logfile) {
+		fprintf(stderr, "Error %d creating logfile: %s\n", errno,
+			strerror(errno));
+		return NULL;
+	}
+
+	return logfile;
+}
+
+int log_write(FILE *logfile, struct write_unit *wu)
+{
+	int fd;
+
+	fprintf(logfile, "%c\t%lu\t%u\n", wu->w_char, wu->w_offset, wu->w_len);
+
+	fflush(logfile);
+
+	fd = fileno(logfile);
+
+	fsync(fd);
+
+	return 0;
+}
+
+void prep_rand_write_unit(struct write_unit *wu)
+{
+again:
+	wu->w_char = RAND_CHAR_START + (char) get_rand(0, 52);
+	wu->w_offset = get_rand(0, file_size - 1);
+	wu->w_len = (unsigned int) get_rand(1, MAX_WRITE_SIZE);
+
+	if (wu->w_offset + wu->w_len > file_size)
+		wu->w_len = file_size - wu->w_offset;
+
+	/* sometimes the random number might work out like this */
+	if (wu->w_len == 0)
+		goto again;
+
+	assert(wu->w_char >= RAND_CHAR_START && wu->w_char <= 'z');
+	assert(wu->w_len <= MAX_WRITE_SIZE);
+	assert(wu->w_len > 0);
+}
+
+int do_write(int fd, struct write_unit *wu)
+{
+	int ret;
+	char buf[MAX_WRITE_SIZE];
+	void *mapped;
+
+	if (test_flags & MMAP_TEST) {
+
+		mapped = mmap(0, file_size, PROT_WRITE, MAP_SHARED, fd, 0);
+		if (mapped == MAP_FAILED) {
+
+			fprintf(stderr, "mmap error %d: \"%s\"\n", errno,
+				strerror(errno));
+			return -1;
+		}
+
+		memset(mapped + wu->w_offset, wu->w_char, wu->w_len);
+
+		munmap(mapped, file_size);
+
+		return 0;
+	}
+
+	memset(buf, wu->w_char, wu->w_len);
+	ret = pwrite(fd, buf, wu->w_len, wu->w_offset);
+	if (ret == -1) {
+		fprintf(stderr, "write error %d: \"%s\"\n", errno,
+			strerror(errno));
+		return -1;
+	}
+
+	return 0;
+}
+
+int do_write_file(char *fname, struct write_unit *wu)
+{
+	int fd, ret, o_ret;
+
+	fd  = open64(fname, open_rw_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(fd, wu);
+
+	close(fd);
+
+	return ret;
+}
-- 
1.5.5




More information about the Ocfs2-test-devel mailing list