From 6ff2551f405978ca3403187f55089a31fff8bee1 Mon Sep 17 00:00:00 2001 From: Paul Guo Date: Mon, 25 Jan 2021 15:23:33 +0800 Subject: [PATCH 2/2] Use copy_file_range() for file copying in pg_rewind. --- configure | 2 +- configure.ac | 1 + src/bin/pg_rewind/file_ops.c | 8 +++++--- src/bin/pg_rewind/file_ops.h | 2 +- src/bin/pg_rewind/local_source.c | 22 ++++++++++++++++++++++ src/include/pg_config.h.in | 3 +++ 6 files changed, 33 insertions(+), 5 deletions(-) diff --git a/configure b/configure index e202697bbf..64aec3b9af 100755 --- a/configure +++ b/configure @@ -15150,7 +15150,7 @@ fi LIBS_including_readline="$LIBS" LIBS=`echo "$LIBS" | sed -e 's/-ledit//g' -e 's/-lreadline//g'` -for ac_func in backtrace_symbols clock_gettime copyfile fdatasync getifaddrs getpeerucred getrlimit kqueue mbstowcs_l memset_s poll posix_fallocate ppoll pstat pthread_is_threaded_np readlink readv setproctitle setproctitle_fast setsid shm_open strchrnul strsignal symlink sync_file_range uselocale wcstombs_l writev +for ac_func in backtrace_symbols clock_gettime copyfile copy_file_range fdatasync getifaddrs getpeerucred getrlimit kqueue mbstowcs_l memset_s poll posix_fallocate ppoll pstat pthread_is_threaded_np readlink readv setproctitle setproctitle_fast setsid shm_open strchrnul strsignal symlink sync_file_range uselocale wcstombs_l writev do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" diff --git a/configure.ac b/configure.ac index a5ad072ee4..7ff3072410 100644 --- a/configure.ac +++ b/configure.ac @@ -1647,6 +1647,7 @@ AC_CHECK_FUNCS(m4_normalize([ backtrace_symbols clock_gettime copyfile + copy_file_range fdatasync getifaddrs getpeerucred diff --git a/src/bin/pg_rewind/file_ops.c b/src/bin/pg_rewind/file_ops.c index 0dd9c6c95e..9ecac5788b 100644 --- a/src/bin/pg_rewind/file_ops.c +++ b/src/bin/pg_rewind/file_ops.c @@ -43,17 +43,17 @@ static void recurse_dir(const char *datadir, const char *parentpath, * Open a target file for writing. If 'trunc' is true and the file already * exists, it will be truncated. */ -void +int open_target_file(const char *path, bool trunc) { int mode; if (dry_run) - return; + return -1; if (dstfd != -1 && !trunc && strcmp(path, &dstpath[strlen(datadir_target) + 1]) == 0) - return; /* already open */ + return dstfd; /* already open */ close_target_file(); @@ -66,6 +66,8 @@ open_target_file(const char *path, bool trunc) if (dstfd < 0) pg_fatal("could not open target file \"%s\": %m", dstpath); + + return dstfd; } /* diff --git a/src/bin/pg_rewind/file_ops.h b/src/bin/pg_rewind/file_ops.h index b6b8b319d5..d1cde6e705 100644 --- a/src/bin/pg_rewind/file_ops.h +++ b/src/bin/pg_rewind/file_ops.h @@ -12,7 +12,7 @@ #include "filemap.h" -extern void open_target_file(const char *path, bool trunc); +extern int open_target_file(const char *path, bool trunc); extern void write_target_range(char *buf, off_t begin, size_t size); extern void close_target_file(void); extern void remove_target_file(const char *path, bool missing_ok); diff --git a/src/bin/pg_rewind/local_source.c b/src/bin/pg_rewind/local_source.c index 9c3491c3fb..1d17cc8304 100644 --- a/src/bin/pg_rewind/local_source.c +++ b/src/bin/pg_rewind/local_source.c @@ -91,6 +91,27 @@ local_fetch_file_range(rewind_source *source, const char *path, off_t off, open_target_file(path, false); +#ifdef HAVE_COPY_FILE_RANGE + ssize_t readlen; + + if (!dry_run) + { + if (lseek(dstfd, begin, SEEK_SET) == -1) + pg_fatal("could not seek in target file \"%s\": %m", path); + + while (end - begin > 0) + { + readlen = copy_file_range(srcfd, NULL, dstfd, NULL, end - begin, 0); + + if (readlen < 0) + pg_fatal("could not copy file from \"%s\" to \"%s\": %m", srcpath, path); + else if (readlen == 0) + pg_fatal("unexpected EOF while copying file \"%s\" to \"%s\"", srcpath, path); + + begin += readlen; + } + } +#else while (end - begin > 0) { ssize_t readlen; @@ -111,6 +132,7 @@ local_fetch_file_range(rewind_source *source, const char *path, off_t off, write_target_range(buf.data, begin, readlen); begin += readlen; } +#endif if (close(srcfd) != 0) pg_fatal("could not close file \"%s\": %m", srcpath); diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in index f4d9f3b408..8706b9879f 100644 --- a/src/include/pg_config.h.in +++ b/src/include/pg_config.h.in @@ -104,6 +104,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_COPYFILE_H +/* Define to 1 if you have the `copy_file_range' function. */ +#undef HAVE_COPY_FILE_RANGE + /* Define to 1 if you have the header file. */ #undef HAVE_CRTDEFS_H -- 2.14.3