[Ocfs2-test-devel] [PATCH 2/4] Ocfs2-test: Add generic file operation funcs for libocfs2test.

Tristan Ye tristan.ye at oracle.com
Tue Mar 24 05:24:06 PDT 2009


Provide generic utility fuctions on file operations for ocfs2-tests.

Signed-off-by: Tristan Ye <tristan.ye at oracle.com>
---
 programs/libocfs2test/file_ops.c |  345 ++++++++++++++++++++++++++++++++++++++
 programs/libocfs2test/file_ops.h |   88 ++++++++++
 2 files changed, 433 insertions(+), 0 deletions(-)
 create mode 100644 programs/libocfs2test/file_ops.c
 create mode 100644 programs/libocfs2test/file_ops.h

diff --git a/programs/libocfs2test/file_ops.c b/programs/libocfs2test/file_ops.c
new file mode 100644
index 0000000..c979b5c
--- /dev/null
+++ b/programs/libocfs2test/file_ops.c
@@ -0,0 +1,345 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * file_ops.c
+ *
+ * Provide generic utility fuctions on file operations for ocfs2-tests
+ *
+ * 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 "file_ops.h"
+
+extern unsigned long get_rand(unsigned long min, unsigned long max)
+{
+	if (min == 0 && max == 0)
+		return 0;
+
+	return min + (rand() % (max - min + 1));
+}
+
+extern char rand_char(void)
+{
+	return 'A' + (char) get_rand(0, 25);
+}
+
+extern int read_at(int fd, void *buf, size_t count, off_t offset)
+{
+	int ret;
+
+	ret = pread(fd, buf, count, offset);
+
+	if (ret < 0) {
+		ret = errno;
+		fprintf(stderr, "read error %d: \"%s\"\n", ret, strerror(ret));
+		return -1;
+	}
+
+	if (ret != count) {
+		fprintf(stderr, "Short read: wanted %ld, got %d\n", count, ret);
+		return -1;
+	}
+
+        return 0;
+}
+
+extern int read_at_file(char *pathname, void *buf, size_t count, off_t offset)
+{
+	int fd, ret;
+
+	fd  = open64(pathname, FILE_RO_FLAGS);
+	if (fd < 0) {
+		fd = errno;
+		fprintf(stderr, "open file %s failed:%d:%s\n", pathname, fd,
+			strerror(fd));
+		return fd;
+	}
+
+        ret = read_at(fd, buf, count, offset);
+
+	if (ret < 0)
+		return ret;
+
+	close(fd);
+
+	return 0;
+}
+
+extern int mmap_read_at(int fd, char *buf, size_t count, off_t offset,
+			size_t page_size)
+{
+	int i, j, 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;
+	}
+
+        j = 0;
+
+	for (i = offset; i < size; i++) {
+		buf[j] = region[i];
+		j++;
+	}
+
+	munmap(region, mmap_size);
+
+	return 0;
+}
+
+extern int mmap_read_at_file(char *pathname, void *buf, size_t count,
+			     off_t offset, size_t page_size)
+{
+	int fd, ret;
+
+	fd  = open64(pathname, FILE_RO_FLAGS);
+
+        if (fd < 0) {
+                fd = errno;
+                fprintf(stderr, "open file %s failed:%d:%s\n", pathname, fd,
+                        strerror(fd));
+                return fd;
+        }
+
+        ret = mmap_read_at(fd, buf, count, offset, page_size);
+
+	if (ret < 0)
+		return ret;
+
+        close(fd);
+
+        return ret;
+}
+
+extern 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 %ld, got %d\n", count, ret);
+		return -1;
+	}
+
+        return 0;
+}
+
+extern int write_at_file(char *pathname, const void *buf, size_t count,
+                         off_t offset)
+{
+	int fd, ret;
+
+        fd  = open64(pathname, FILE_RW_FLAGS);
+
+        if (fd < 0) {
+		fd = errno;
+		fprintf(stderr, "open file %s failed:%d:%s\n", pathname, fd,
+			strerror(fd));
+		return fd;
+	}
+
+	ret = write_at(fd, buf, count, offset);
+
+	if (ret < 0)
+		return ret;
+
+        close(fd);
+
+        return 0;
+}
+
+extern int mmap_write_at(int fd, const char *buf, size_t count, off_t offset,
+			 size_t page_size)
+{
+	int i, j, 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;
+	}
+
+	j = 0;
+
+	for (i = offset; i < size; i++)
+		region[i] = buf[j++];
+
+	munmap(region, mmap_size);
+
+	return 0;
+}
+
+extern int mmap_write_at_file(char *pathname, const void *buf, size_t count,
+			      off_t offset, size_t page_size)
+{
+	int fd, ret;
+
+	fd  = open64(pathname, FILE_RW_FLAGS);
+
+	if (fd < 0) {
+		fd = errno;
+		fprintf(stderr, "open file %s failed:%d:%s\n", pathname, fd,
+			strerror(fd));
+		return fd;
+	}
+
+	ret = mmap_write_at(fd, buf, count, offset, page_size);
+
+	if (ret < 0)
+		return ret;
+
+	close(fd);
+
+	return 0;
+}
+
+extern int reflink(const char *oldpath, const char *newpath)
+{
+	int fd, ret;
+	struct reflink_arguments args;
+
+	args.old_path = (__u64)oldpath;
+	args.new_path = (__u64)newpath;
+
+	fd = open64(oldpath, FILE_RO_FLAGS);
+
+	if (fd < 0) {
+		fd = errno;
+		fprintf(stderr, "open file %s failed:%d:%s\n", oldpath, fd,
+			strerror(fd));
+		return fd;
+	}
+
+	ret = ioctl(fd, OCFS2_IOC_REFLINK, &args);
+
+	if (ret) {
+		ret = errno;
+		fprintf(stderr, "ioctl failed:%d:%s\n", ret, strerror(ret));
+		return ret;
+	}
+
+	close(fd);
+
+	return 0;
+}
+
+extern int do_write(int fd, struct write_unit *wu, int write_method, size_t page_size)
+{
+        int ret;
+        char buf[MAX_WRITE_SIZE];
+
+        memset(buf, wu->w_char, wu->w_len);
+
+        if (write_method == 1)
+
+		ret = mmap_write_at(fd, buf, wu->w_len, wu->w_offset, page_size);
+	else
+		ret = write_at(fd, buf, wu->w_len, wu->w_offset);
+
+	return ret;
+}
+
+extern int do_write_file(char *fname, struct write_unit *wu, int write_method,
+			 size_t page_size)
+{
+        int fd, ret;
+
+        fd  = open64(fname, FILE_RW_FLAGS);
+        if (fd < 0) {
+                fd = errno;
+                fprintf(stderr, "open file %s failed:%d:%s\n", fname, fd,
+                        strerror(fd));
+                return fd;
+        }
+
+        ret = do_write(fd, wu, write_method, page_size);
+
+        close(fd);
+
+        return ret;
+}
+
+extern int get_bs_cs(char * device_name, unsigned int *bs, unsigned long *cs,
+		     unsigned long *max_inline_sz)
+{
+	int ret;
+	int open_flags = OCFS2_FLAG_HEARTBEAT_DEV_OK | OCFS2_FLAG_RO;
+
+	ocfs2_filesys *fs;
+	struct ocfs2_super_block *ocfs2_sb;
+
+	ret = ocfs2_open(device_name, open_flags, 0, 0, &fs);
+
+        if (ret < 0) {
+                com_err("CurrentTest", ret,
+                        "while opening file system.");
+                return ret;
+        }
+
+	ocfs2_sb = OCFS2_RAW_SB(fs->fs_super);
+
+	*bs = 1 << ocfs2_sb->s_blocksize_bits;
+	*cs = 1 << ocfs2_sb->s_clustersize_bits;
+	*max_inline_sz = ocfs2_max_inline_data(*bs);
+
+	ocfs2_close(fs);
+
+	return 0;
+}
+
+extern int punch_hole(int fd, struct write_unit *wu)
+{
+	int ret;
+	struct ocfs2_space_resv sr;
+
+	memset(&sr, 0, sizeof(sr));
+	sr.l_whence = 0;
+	sr.l_start = wu->w_offset;
+	sr.l_len = wu->w_len;
+
+	ret = ioctl(fd, OCFS2_IOC_UNRESVSP64, &sr);
+	if (ret == -1) {
+		fprintf(stderr, "ioctl error %d: \"%s\"\n",
+			errno, strerror(errno));
+		return -1;
+	}
+
+	return 0;
+}
+
diff --git a/programs/libocfs2test/file_ops.h b/programs/libocfs2test/file_ops.h
new file mode 100644
index 0000000..dfe5b92
--- /dev/null
+++ b/programs/libocfs2test/file_ops.h
@@ -0,0 +1,88 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * file_ops.h
+ *
+ * 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.
+ */
+
+#ifndef FILE_OPS_H
+#define FILE_OPS_H
+
+#define _GNU_SOURCE
+#define _XOPEN_SOURCE 500
+#define _LARGEFILE64_SOURCE
+#include <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <signal.h>
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+#include <inttypes.h>
+#include <linux/types.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <getopt.h>
+
+#include <ocfs2/ocfs2.h>
+
+#define OCFS2_MAX_FILENAME_LEN  255
+#define MAX_WRITE_SIZE		32768
+#define RAND_CHAR_START		'A'
+#define MAGIC_HOLE_CHAR		(RAND_CHAR_START - 1)
+
+#define FILE_RW_FLAGS           (O_CREAT|O_RDWR)
+#define FILE_RO_FLAGS           (O_RDONLY)
+#define FILE_AP_FLAGS		(O_CREAT|O_RDWR|O_APPEND)
+
+#define FILE_MODE               (S_IRUSR|S_IWUSR|S_IXUSR|S_IROTH|\
+                                 S_IWOTH|S_IXOTH|S_IRGRP|S_IWGRP|S_IXGRP)
+
+struct write_unit {
+	char w_char;
+	unsigned long w_offset;
+	unsigned int  w_len;
+};
+
+unsigned long get_rand(unsigned long min, unsigned long max);
+char rand_char(void);
+
+int read_at(int fd, void *buf, size_t count, off_t offset);
+int read_at_file(char *pathname, void *buf, size_t count, off_t offset);
+int mmap_read_at(int fd, char *buf, size_t count, off_t offset,
+		 size_t page_size);
+int mmap_read_at_file(char *pathname, void *buf, size_t count, off_t offset,
+		      size_t page_size);
+int write_at(int fd, const void *buf, size_t count, off_t offset);
+int write_at_file(char *pathname, const void *buf, size_t count, off_t offset);
+int mmap_write_at(int fd, const char *buf, size_t count, off_t offset,
+		  size_t page_size);
+int mmap_write_at_file(char *pathname, const void *buf, size_t count,
+		       off_t offset, size_t page_size);
+
+int reflink(const char *oldpath, const char *newpath);
+
+int do_write(int fd, struct write_unit *wu, int write_method, size_t page_size);
+int do_write_file(char *fname, struct write_unit *wu, int write_method,
+		  size_t page_size);
+
+int get_bs_cs(char * device_name, unsigned int *bs, unsigned long *cs,
+	      unsigned long *max_inline_sz);
+
+int punch_hole(int fd, struct write_unit *wu);
+#endif
-- 
1.5.5




More information about the Ocfs2-test-devel mailing list