Whamcloud - gitweb
LU-11621 utils: optimize lhsmtool_posix with copy_file_range() 51/38651/5
authorJames Simmons <jsimmons@infradead.org>
Tue, 19 May 2020 18:59:40 +0000 (14:59 -0400)
committerOleg Drokin <green@whamcloud.com>
Wed, 27 May 2020 05:05:39 +0000 (05:05 +0000)
Newer kernels and glibc offer copy_file_range() which avoids
a context switch needed with read() + write() for file data
copying. In the future Lustre can look to optimize this copy
on the server backend. Update lhsmtool_posix to use this new
functionality.

Change-Id: If63d57b89902f3d5c9ddde66901f3f55d15080f5
Signed-off-by: James Simmons <jsimmons@infradead.org>
Reviewed-on: https://review.whamcloud.com/38651
Reviewed-by: Ben Evans <beevans@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/autoconf/lustre-core.m4
lustre/include/lustre/lustreapi.h
lustre/utils/lhsmtool_posix.c
lustre/utils/liblustreapi.c
lustre/utils/lstddef.h

index 4eec916..04de101 100644 (file)
@@ -56,6 +56,16 @@ AC_CHECK_FUNCS([name_to_handle_at],
 ]) # LC_GLIBC_SUPPORT_FHANDLES
 
 #
+# LC_GLIBC_SUPPORT_COPY_FILE_RANGE
+#
+AC_DEFUN([LC_GLIBC_SUPPORT_COPY_FILE_RANGE], [
+AC_CHECK_FUNCS([copy_file_range],
+       [AC_DEFINE(HAVE_COPY_FILE_RANGE, 1,
+               [copy_file_range() is supported])],
+       [AC_MSG_WARN([copy_file_range() is not supported])])
+]) # LC_GLIBC_SUPPORT_COPY_FILE_RANGE
+
+#
 # LC_STACK_SIZE
 #
 # Ensure the stack size is at least 8k in Lustre server (all kernels)
@@ -2239,6 +2249,7 @@ AC_DEFUN([LC_PROG_LINUX], [
        LC_CONFIG_GSS
 
        LC_GLIBC_SUPPORT_FHANDLES
+       LC_GLIBC_SUPPORT_COPY_FILE_RANGE
        LC_OPENSSL_SSK
        LC_OPENSSL_GETSEPOL
 
index 009a622..c9573db 100644 (file)
@@ -54,10 +54,6 @@ extern "C" {
 #define LL_MAXQUOTAS 3
 #endif
 
-#ifndef ARRAY_SIZE
-#define ARRAY_SIZE(a) ((sizeof(a)) / (sizeof((a)[0])))
-#endif
-
 #define lustre_fid struct lu_fid
 
 /* Currently external applications can access this but in the
index 4f933b4..14aa197 100644 (file)
@@ -59,6 +59,7 @@
 #include <libcfs/util/string.h>
 #include <linux/lustre/lustre_fid.h>
 #include <lustre/lustreapi.h>
+#include "lstddef.h"
 
 /* Progress reporting period */
 #define REPORT_INTERVAL_DEFAULT 30
@@ -656,6 +657,27 @@ static int ct_copy_data(struct hsm_copyaction_private *hcp, const char *src,
                int     chunk = (length - write_total > opt.o_chunk_size) ?
                                 opt.o_chunk_size : length - write_total;
 
+               /* Try the accelerated copy path first. Once LU-10180 lands
+                * we should deal with holes.
+                */
+               wsize = copy_file_range(src_fd, NULL, dst_fd, NULL,
+                                       chunk, 0);
+               if (wsize != -1)
+                       goto fini_fastcopy;
+               rc = -errno;
+               /* Before Linux kernel 5.3 copy_file_range only supported
+                * file copies between filesystems of the same type. In
+                * that case copy_file_range() will return -EXDEV.
+                */
+               if (rc != -EXDEV && rc != -ENOSYS) {
+                       CT_ERROR(rc, "copy_file_range failed for '%s' to '%s'",
+                                src, dst);
+                       break;
+               }
+
+               /* copy_file_range is not avalible or failed
+                * so use what works.
+                */
                rsize = pread(src_fd, buf, chunk, offset);
                if (rsize == 0)
                        /* EOF */
@@ -673,7 +695,7 @@ static int ct_copy_data(struct hsm_copyaction_private *hcp, const char *src,
                        CT_ERROR(rc, "cannot write to '%s'", dst);
                        break;
                }
-
+fini_fastcopy:
                write_total += wsize;
                offset += wsize;
 
index 1401d92..41dffae 100644 (file)
@@ -80,6 +80,7 @@
 #include <linux/lustre/lustre_ostid.h>
 #include <linux/lustre/lustre_ioctl.h>
 #include "lustreapi_internal.h"
+#include "lstddef.h"
 
 static int llapi_msg_level = LLAPI_MSG_MAX;
 const char *liblustreapi_cmd;
index c10ab0b..f1a6431 100644 (file)
@@ -292,4 +292,27 @@ static inline __u32 reciprocal_scale(__u32 val, __u32 ep_ro)
        (type *)((char *)__mptr - offsetof(type, member));      \
 })
 
+#ifndef HAVE_COPY_FILE_RANGE
+
+#ifndef __NR_copy_file_range
+
+#if defined(_ASM_X86_UNISTD_64_H)
+#define __NR_copy_file_range 326
+#elif defined(_ASM_X86_UNISTD_32_H)
+#define __NR_copy_file_range 285
+#else
+#define __NR_copy_file_range 285
+#endif
+
+#endif
+
+static inline loff_t copy_file_range(int fd_in, loff_t *off_in, int fd_out,
+                                    loff_t *off_out, size_t len,
+                                    unsigned int flags)
+{
+       return syscall(__NR_copy_file_range, fd_in, off_in, fd_out,
+                      off_out, len, flags);
+}
+#endif /* !HAVE_COPY_FILE_RANGE */
+
 #endif /* !_LSTDDEF_H */