From 0cb8398c5c6176b22c1e58d28d163c3c4d7728be Mon Sep 17 00:00:00 2001 From: Paul Guo Date: Mon, 25 Jan 2021 15:23:33 +0800 Subject: [PATCH v3 2/2] Use copy_file_range() for file copying in pg_rewind. --- configure | 2 +- configure.ac | 1 + src/bin/pg_rewind/file_ops.c | 33 +++++++++++++++++++++++++++++++++ src/bin/pg_rewind/file_ops.h | 3 +++ src/bin/pg_rewind/local_source.c | 12 +++++++++--- src/include/pg_config.h.in | 3 +++ src/tools/msvc/Solution.pm | 1 + 7 files changed, 51 insertions(+), 4 deletions(-) diff --git a/configure b/configure index e9b98f442f..91bca24322 100755 --- a/configure +++ b/configure @@ -15456,7 +15456,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 syncfs 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 syncfs 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 3b42d8bdc9..d0c5ebd21b 100644 --- a/configure.ac +++ b/configure.ac @@ -1693,6 +1693,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..ae2ce207aa 100644 --- a/src/bin/pg_rewind/file_ops.c +++ b/src/bin/pg_rewind/file_ops.c @@ -84,6 +84,39 @@ close_target_file(void) dstfd = -1; } +#ifdef HAVE_COPY_FILE_RANGE +void +copy_target_range(int srcfd, off_t begin, size_t size) +{ + ssize_t copylen; + + /* update progress report */ + fetch_done += size; + progress_report(false); + + if (dry_run) + return; + + if (lseek(srcfd, begin, SEEK_SET) == -1) + pg_fatal("could not seek in source file: %m"); + + if (lseek(dstfd, begin, SEEK_SET) == -1) + pg_fatal("could not seek in target file \"%s\": %m", dstpath); + + while (size > 0) + { + copylen = copy_file_range(srcfd, NULL, dstfd, NULL, size, 0); + + if (copylen < 0) + pg_fatal("could not copy file to \"%s\": %m", dstpath); + else if (copylen == 0) + pg_fatal("unexpected EOF while copying to file \"%s\"", dstpath); + + size -= copylen; + } +} +#endif + void write_target_range(char *buf, off_t begin, size_t size) { diff --git a/src/bin/pg_rewind/file_ops.h b/src/bin/pg_rewind/file_ops.h index b6b8b319d5..f441c72ac2 100644 --- a/src/bin/pg_rewind/file_ops.h +++ b/src/bin/pg_rewind/file_ops.h @@ -13,6 +13,9 @@ #include "filemap.h" extern void open_target_file(const char *path, bool trunc); +#ifdef HAVE_COPY_FILE_RANGE +extern void copy_target_range(int srcfd, off_t begin, size_t size); +#endif 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..61d3cbc908 100644 --- a/src/bin/pg_rewind/local_source.c +++ b/src/bin/pg_rewind/local_source.c @@ -73,11 +73,13 @@ local_fetch_file_range(rewind_source *source, const char *path, off_t off, size_t len) { const char *datadir = ((local_source *) source)->datadir; - PGAlignedBlock buf; char srcpath[MAXPGPATH]; int srcfd; off_t begin = off; off_t end = off + len; +#ifndef HAVE_COPY_FILE_RANGE + PGAlignedBlock buf; +#endif snprintf(srcpath, sizeof(srcpath), "%s/%s", datadir, path); @@ -86,11 +88,12 @@ local_fetch_file_range(rewind_source *source, const char *path, off_t off, pg_fatal("could not open source file \"%s\": %m", srcpath); + open_target_file(path, false); + +#ifndef HAVE_COPY_FILE_RANGE if (lseek(srcfd, begin, SEEK_SET) == -1) pg_fatal("could not seek in source file: %m"); - open_target_file(path, false); - while (end - begin > 0) { ssize_t readlen; @@ -111,6 +114,9 @@ local_fetch_file_range(rewind_source *source, const char *path, off_t off, write_target_range(buf.data, begin, readlen); begin += readlen; } +#else + copy_target_range(srcfd, begin, end - begin); +#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 783b8fc1ba..023a84863a 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 diff --git a/src/tools/msvc/Solution.pm b/src/tools/msvc/Solution.pm index 97f012bbb5..6f5a40509b 100644 --- a/src/tools/msvc/Solution.pm +++ b/src/tools/msvc/Solution.pm @@ -235,6 +235,7 @@ sub GenerateFiles HAVE_COMPUTED_GOTO => undef, HAVE_COPYFILE => undef, HAVE_COPYFILE_H => undef, + HAVE_COPY_FILE_RANGE => undef, HAVE_CRTDEFS_H => undef, HAVE_CRYPTO_LOCK => undef, HAVE_DECL_FDATASYNC => 0, -- 2.14.3