From ccac422cf9dd3b2390d1c70cd42eff06d2f53be3 Mon Sep 17 00:00:00 2001 From: James Simmons Date: Tue, 19 May 2020 14:59:40 -0400 Subject: [PATCH] LU-11621 utils: optimize lhsmtool_posix with copy_file_range() 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 Reviewed-on: https://review.whamcloud.com/38651 Reviewed-by: Ben Evans Reviewed-by: Andreas Dilger Tested-by: jenkins Tested-by: Maloo Reviewed-by: Oleg Drokin --- lustre/autoconf/lustre-core.m4 | 11 +++++++++++ lustre/include/lustre/lustreapi.h | 4 ---- lustre/utils/lhsmtool_posix.c | 24 +++++++++++++++++++++++- lustre/utils/liblustreapi.c | 1 + lustre/utils/lstddef.h | 23 +++++++++++++++++++++++ 5 files changed, 58 insertions(+), 5 deletions(-) diff --git a/lustre/autoconf/lustre-core.m4 b/lustre/autoconf/lustre-core.m4 index 4eec916..04de101 100644 --- a/lustre/autoconf/lustre-core.m4 +++ b/lustre/autoconf/lustre-core.m4 @@ -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 diff --git a/lustre/include/lustre/lustreapi.h b/lustre/include/lustre/lustreapi.h index 009a622..c9573db 100644 --- a/lustre/include/lustre/lustreapi.h +++ b/lustre/include/lustre/lustreapi.h @@ -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 diff --git a/lustre/utils/lhsmtool_posix.c b/lustre/utils/lhsmtool_posix.c index 4f933b4..14aa197 100644 --- a/lustre/utils/lhsmtool_posix.c +++ b/lustre/utils/lhsmtool_posix.c @@ -59,6 +59,7 @@ #include #include #include +#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; diff --git a/lustre/utils/liblustreapi.c b/lustre/utils/liblustreapi.c index 1401d92..41dffae 100644 --- a/lustre/utils/liblustreapi.c +++ b/lustre/utils/liblustreapi.c @@ -80,6 +80,7 @@ #include #include #include "lustreapi_internal.h" +#include "lstddef.h" static int llapi_msg_level = LLAPI_MSG_MAX; const char *liblustreapi_cmd; diff --git a/lustre/utils/lstddef.h b/lustre/utils/lstddef.h index c10ab0b..f1a6431 100644 --- a/lustre/utils/lstddef.h +++ b/lustre/utils/lstddef.h @@ -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 */ -- 1.8.3.1