[Ocfs2-test-devel] [PATCH 11/12] Ocfs2-test: Move reflink() call to api-compat.

Tristan Ye tristan.ye at oracle.com
Wed Oct 14 01:36:03 PDT 2009


Move reflink()(ioctl based) call to api-compat to make it
compatible for old kernels which have no reflink(2)
implementation(it will be included in mainline soon?)

For new kernels, we'll use reflink(2) system call by default.

Signed-off-by: Tristan Ye <tristan.ye at oracle.com>
---
 Config.make.in                          |    1 +
 Makefile                                |    3 +-
 api-compat/include/reflink.h            |   11 +++++
 configure.in                            |    9 ++++
 programs/reflink_tests/compat_reflink.c |   68 +++++++++++++++++++++++++++++++
 5 files changed, 91 insertions(+), 1 deletions(-)
 create mode 100644 api-compat/include/reflink.h
 create mode 100644 programs/reflink_tests/compat_reflink.c

diff --git a/Config.make.in b/Config.make.in
index a03274e..3fc6146 100644
--- a/Config.make.in
+++ b/Config.make.in
@@ -30,6 +30,7 @@ TESTDIR = $(libdir)/ocfs2-test
 top_builddir = .
 
 EXTRA_CFLAGS += @API_COMPAT_CFLAGS@
+NO_REFLINK  = @NO_REFLINK@
 
 INSTALL = @INSTALL@
 INSTALL_PROGRAM = @INSTALL_PROGRAM@
diff --git a/Makefile b/Makefile
index c412e61..fdbc31c 100644
--- a/Makefile
+++ b/Makefile
@@ -27,7 +27,8 @@ SUBDIRS = programs utilities tests suites
 SUBDIRS += vendor
 
 API_COMPAT_FILES = \
-	api-compat/include/splice.h
+	api-compat/include/splice.h	\
+	api-compat/include/reflink.h
 
 DIST_FILES = \
 	COPYING					\
diff --git a/api-compat/include/reflink.h b/api-compat/include/reflink.h
new file mode 100644
index 0000000..97f4c94
--- /dev/null
+++ b/api-compat/include/reflink.h
@@ -0,0 +1,11 @@
+#ifndef API_REFLINK_H
+#define API_REFLINK_H
+
+#ifdef NO_REFLINK
+
+int reflink(const char *oldpath, const char *newpath, unsigned long preserve);
+
+#endif
+
+#endif
+
diff --git a/configure.in b/configure.in
index b45bdba..9568d3e 100644
--- a/configure.in
+++ b/configure.in
@@ -135,6 +135,15 @@ OCFS2_CHECK_HEADERS([splice() in bits/fcntl.h], bits/fcntl.h,
   , splice_compat_header="splice.h", [splice (int __fdin])
 API_COMPAT_HEADERS="$API_COMPAT_HEADERS $splice_compat_header"
 
+NO_REFLINK=
+OCFS2_CHECK_HEADERS([reflink() in unistd.h], unistd.h, ,
+  NO_REFLINK=yes, [reflink])
+AC_SUBST(NO_REFLINK)
+
+if test "x$NO_REFLINK" = "xyes"; then
+API_COMPAT_HEADERS="$API_COMPAT_HEADERS reflink.h"
+fi
+
 for h in $API_COMPAT_HEADERS; do
   API_COMPAT_CFLAGS="$API_COMPAT_CFLAGS -include \$(TOPDIR)/api-compat/include/$h"
 done
diff --git a/programs/reflink_tests/compat_reflink.c b/programs/reflink_tests/compat_reflink.c
new file mode 100644
index 0000000..0c30bf2
--- /dev/null
+++ b/programs/reflink_tests/compat_reflink.c
@@ -0,0 +1,68 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * compat_reflink.c
+ *
+ * Use ioctl() based reflink call for old kernels which have no
+ * reflink(2) system call implemented.
+ *
+ * Written by tristan.ye at oracle.com
+ *
+ * Copyright (C) 2009 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 _GNU_SOURCE
+#define _XOPEN_SOURCE 500
+#define _LARGEFILE64_SOURCE
+
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+
+#include <ocfs2/ocfs2.h>
+
+extern int open_ro_flags;
+
+int reflink(const char *oldpath, const char *newpath, unsigned long preserve)
+{
+	int fd, ret, o_ret;
+	struct reflink_arguments args;
+
+	args.old_path = (__u64)oldpath;
+	args.new_path = (__u64)newpath;
+	args.preserve = preserve;
+
+	fd = open64(oldpath, open_ro_flags);
+	if (fd < 0) {
+		o_ret = fd;
+		fd = errno;
+		fprintf(stderr, "open file %s failed:%d:%s\n", oldpath, fd,
+			strerror(fd));
+		fd = o_ret;
+		return fd;
+	}
+
+	ret = ioctl(fd, OCFS2_IOC_REFLINK, &args);
+	if (ret) {
+		o_ret = ret;
+		ret = errno;
+		fprintf(stderr, "ioctl failed:%d:%s\n", ret, strerror(ret));
+		close(fd);
+		ret = o_ret;
+		return ret;
+	}
+
+	close(fd);
+
+	return 0;
+}
-- 
1.5.5




More information about the Ocfs2-test-devel mailing list