Received: from malur.postgresql.org ([2a02:16a8:dc51::56]) by arkaria.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA384:256) (Exim 4.89) (envelope-from ) id 1g5dYE-0006Cv-GB for pgsql-hackers@arkaria.postgresql.org; Thu, 27 Sep 2018 21:10:23 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.89) (envelope-from ) id 1g5dYC-0004qv-W7 for pgsql-hackers@arkaria.postgresql.org; Thu, 27 Sep 2018 21:10:20 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA384:256) (Exim 4.89) (envelope-from ) id 1g5dYB-0004qF-ST for pgsql-hackers@lists.postgresql.org; Thu, 27 Sep 2018 21:10:20 +0000 Received: from out1-smtp.messagingengine.com ([66.111.4.25]) by magus.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA384:256) (Exim 4.89) (envelope-from ) id 1g5dY6-0008Rt-7e for pgsql-hackers@postgresql.org; Thu, 27 Sep 2018 21:10:19 +0000 Received: from compute7.internal (compute7.nyi.internal [10.202.2.47]) by mailout.nyi.internal (Postfix) with ESMTP id 46AF420E73; Thu, 27 Sep 2018 17:10:12 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute7.internal (MEProxy); Thu, 27 Sep 2018 17:10:12 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to:x-me-sender :x-me-sender:x-sasl-enc; s=fm3; bh=mWgSCQmh4z7lCX3TMqpjK5y6bl0Rc jcVx1KH1kamY1I=; b=tEx+3C0PlAVqyjyj2Hc/vCZaseq2eAF2ReQ39gAJal0s2 CNc4coBZgu2UVdSoLX53MZcfSoxVvKTPHsSKSf1XO7tcYCQs+VI1WQLz96YLkRAz e888L7pm3cvSR2i+QBz5lF2u09Q5RWtbUsaKOao9jSRwEX5H4Fi6zzdGvnGy23tT 90JvqIZTfUOmO8B3i5dYbOAtJNxf+g0mBTpoADQxV8783tnFxrTlwfpp8/JjRwrA e2OmgctGZ4m2KcKKpLF3CzMBJnwwWWfjq4fP9RtOM7rQaQVW2PraJqSwnWol9ZTx +vAmXA9F6d5H9xTstcYV6ypucgRIqxz8ESLojS5ug== X-ME-Proxy: X-ME-Sender: Received: from april.pezone.net (p5df2a2d9.dip0.t-ipconnect.de [93.242.162.217]) by mail.messagingengine.com (Postfix) with ESMTPA id 97600102A0; Thu, 27 Sep 2018 17:10:10 -0400 (EDT) Subject: Re: file cloning in pg_upgrade and CREATE DATABASE To: Michael Paquier References: <20180319070636.GA4633@paquier.xyz> <20180319071415.GB4633@paquier.xyz> <20180320025849.GB4963@paquier.xyz> <678999c6-0967-d22a-e7d1-2a3aff83a77b@2ndquadrant.com> <20180323171650.GI1302@momjian.us> <4a62b089-ee93-50ee-f3f7-43c67b4c8ea4@2ndquadrant.com> <0241eae2-2f31-3667-200d-ae0e2293f692@2ndquadrant.com> <20180717065833.GG3388@paquier.xyz> <067fed44-db29-1334-3411-84b41959681a@2ndquadrant.com> <20180926064408.GL1659@paquier.xyz> Cc: pgsql-hackers , Bruce Momjian From: Peter Eisentraut Openpgp: preference=signencrypt Autocrypt: addr=peter.eisentraut@2ndquadrant.com; prefer-encrypt=mutual; keydata= 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 3jI= Organization: 2ndQuadrant Message-ID: Date: Thu, 27 Sep 2018 23:10:08 +0200 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:52.0) Gecko/20100101 Thunderbird/52.9.1 MIME-Version: 1.0 In-Reply-To: <20180926064408.GL1659@paquier.xyz> Content-Type: multipart/mixed; boundary="------------59B7766A964E29E66AF4A3FB" Content-Language: en-US List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Precedence: bulk This is a multi-part message in MIME format. --------------59B7766A964E29E66AF4A3FB Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 7bit On 26/09/2018 08:44, Michael Paquier wrote: > On Sat, Sep 01, 2018 at 07:28:37AM +0200, Peter Eisentraut wrote: >> rebased patch, no functionality changes > > Could you rebase once again? I am going through the patch and wanted to > test pg_upgrade on Linux with XFS, but it does not apply anymore. attached -- Peter Eisentraut http://www.2ndQuadrant.com/ PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services --------------59B7766A964E29E66AF4A3FB Content-Type: text/plain; charset=UTF-8; x-mac-type="0"; x-mac-creator="0"; name="v5-0001-pg_upgrade-Allow-use-of-file-cloning.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename*0="v5-0001-pg_upgrade-Allow-use-of-file-cloning.patch" From 9a58fc2589e50d69b4b158ea5e8f3898483290d0 Mon Sep 17 00:00:00 2001 From: Peter Eisentraut Date: Thu, 27 Sep 2018 22:42:33 +0200 Subject: [PATCH v5] pg_upgrade: Allow use of file cloning For file copying in pg_upgrade, allow using special file cloning calls if available. This makes the copying faster and more space efficient. This achieves speed similar to --link mode without the associated drawbacks. Add an option --reflink to select whether file cloning is turned on, off, or automatic. Automatic is the default. On Linux, file cloning is supported on Btrfs and XFS (if formatted with reflink support). On macOS, file cloning is supported on APFS. --- configure | 2 +- configure.in | 2 +- doc/src/sgml/ref/pgupgrade.sgml | 33 +++++++++ src/bin/pg_upgrade/check.c | 2 + src/bin/pg_upgrade/file.c | 123 +++++++++++++++++++++++++++++++ src/bin/pg_upgrade/option.c | 14 ++++ src/bin/pg_upgrade/pg_upgrade.h | 15 ++++ src/bin/pg_upgrade/relfilenode.c | 31 +++++++- src/include/pg_config.h.in | 3 + 9 files changed, 220 insertions(+), 5 deletions(-) diff --git a/configure b/configure index 6414ec1ea6..ae6f1a2e17 100755 --- a/configure +++ b/configure @@ -15100,7 +15100,7 @@ fi LIBS_including_readline="$LIBS" LIBS=`echo "$LIBS" | sed -e 's/-ledit//g' -e 's/-lreadline//g'` -for ac_func in cbrt clock_gettime fdatasync getifaddrs getpeerucred getrlimit mbstowcs_l memmove poll posix_fallocate ppoll pstat pthread_is_threaded_np readlink setproctitle setproctitle_fast setsid shm_open symlink sync_file_range utime utimes wcstombs_l +for ac_func in cbrt clock_gettime copyfile fdatasync getifaddrs getpeerucred getrlimit mbstowcs_l memmove poll posix_fallocate ppoll pstat pthread_is_threaded_np readlink setproctitle setproctitle_fast setsid shm_open symlink sync_file_range utime utimes wcstombs_l 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.in b/configure.in index 158d5a1ac8..265faf1b99 100644 --- a/configure.in +++ b/configure.in @@ -1571,7 +1571,7 @@ PGAC_FUNC_WCSTOMBS_L LIBS_including_readline="$LIBS" LIBS=`echo "$LIBS" | sed -e 's/-ledit//g' -e 's/-lreadline//g'` -AC_CHECK_FUNCS([cbrt clock_gettime fdatasync getifaddrs getpeerucred getrlimit mbstowcs_l memmove poll posix_fallocate ppoll pstat pthread_is_threaded_np readlink setproctitle setproctitle_fast setsid shm_open symlink sync_file_range utime utimes wcstombs_l]) +AC_CHECK_FUNCS([cbrt clock_gettime copyfile fdatasync getifaddrs getpeerucred getrlimit mbstowcs_l memmove poll posix_fallocate ppoll pstat pthread_is_threaded_np readlink setproctitle setproctitle_fast setsid shm_open symlink sync_file_range utime utimes wcstombs_l]) AC_REPLACE_FUNCS(fseeko) case $host_os in diff --git a/doc/src/sgml/ref/pgupgrade.sgml b/doc/src/sgml/ref/pgupgrade.sgml index d51146d641..d994218c44 100644 --- a/doc/src/sgml/ref/pgupgrade.sgml +++ b/doc/src/sgml/ref/pgupgrade.sgml @@ -182,6 +182,39 @@ Options display version information, then exit + + ={always|auto|never} + + + Determines whether pg_upgrade, when in copy + mode, should use efficient file cloning (also known as + reflinks) on some operating systems and file systems. + This can result in near-instantaneous copying of the data files, + giving the speed advantages of + / while leaving the old + cluster untouched. + + + + The setting always requires the use of reflinks. If + they are not supported, the pg_upgrade run + will abort. Use this in production to limit the upgrade run time. + The setting auto uses reflinks when available, + otherwise it falls back to a normal copy. This is the default. The + setting never prevents use of reflinks and always + uses a normal copy. This can be useful to ensure that the upgraded + cluster has its disk space fully allocated and not shared with the old + cluster. + + + + At present, reflinks are supported on Linux (kernel 4.5 or later) with + Btrfs and XFS (on file systems created with reflink support, which is + not the default for XFS at this writing), and on macOS with APFS. + + + + diff --git a/src/bin/pg_upgrade/check.c b/src/bin/pg_upgrade/check.c index 5a78d603dc..eb1f18180a 100644 --- a/src/bin/pg_upgrade/check.c +++ b/src/bin/pg_upgrade/check.c @@ -151,6 +151,8 @@ check_new_cluster(void) if (user_opts.transfer_mode == TRANSFER_MODE_LINK) check_hard_link(); + else if (user_opts.transfer_mode == TRANSFER_MODE_COPY && user_opts.reflink_mode != REFLINK_NEVER) + check_reflink(); check_is_install_user(&new_cluster); diff --git a/src/bin/pg_upgrade/file.c b/src/bin/pg_upgrade/file.c index c27cc93dc2..2e864cd6bb 100644 --- a/src/bin/pg_upgrade/file.c +++ b/src/bin/pg_upgrade/file.c @@ -18,6 +18,13 @@ #include #include +#ifdef HAVE_COPYFILE +#include +#endif +#ifdef __linux__ +#include +#include +#endif #ifdef WIN32 @@ -93,6 +100,68 @@ copyFile(const char *src, const char *dst, #endif /* WIN32 */ } +/* + * cloneFile() + * + * Clones/reflinks a relation file from src to dst. + * + * schemaName/relName are relation's SQL name (used for error messages only). + * + * If unsupported_ok is true, then if the cloning fails because the OS or file + * system don't support it, don't error, instead return false. Otherwise, + * true is returned. Based on this, the caller can then try to call + * copyFile() instead, for example. + */ +bool +cloneFile(const char *src, const char *dst, + const char *schemaName, const char *relName, + bool unsupported_ok) +{ +#if defined(HAVE_COPYFILE) && defined(COPYFILE_CLONE_FORCE) + if (copyfile(src, dst, NULL, COPYFILE_CLONE_FORCE) < 0) + { + if (unsupported_ok && errno == ENOTSUP) + return false; + else + pg_fatal("error while cloning relation \"%s.%s\" (\"%s\" to \"%s\"): %s\n", + schemaName, relName, src, dst, strerror(errno)); + } + return true; +#elif defined(__linux__) && defined(FICLONE) + int src_fd; + int dest_fd; + + if ((src_fd = open(src, O_RDONLY | PG_BINARY, 0)) < 0) + pg_fatal("error while cloning relation \"%s.%s\": could not open file \"%s\": %s\n", + schemaName, relName, src, strerror(errno)); + + if ((dest_fd = open(dst, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, + pg_file_create_mode)) < 0) + pg_fatal("error while cloning relation \"%s.%s\": could not create file \"%s\": %s\n", + schemaName, relName, dst, strerror(errno)); + + if (ioctl(dest_fd, FICLONE, src_fd) < 0) + { + unlink(dst); + if (unsupported_ok && errno == EOPNOTSUPP) + { + close(src_fd); + close(dest_fd); + return false; + } + else + pg_fatal("error while cloning relation \"%s.%s\" (\"%s\" to \"%s\"): %s\n", + schemaName, relName, src, dst, strerror(errno)); + } + + close(src_fd); + close(dest_fd); + return true; +#else + return false; +#endif +} + /* * linkFile() @@ -270,6 +339,60 @@ rewriteVisibilityMap(const char *fromfile, const char *tofile, close(src_fd); } +void +check_reflink(void) +{ + char existing_file[MAXPGPATH]; + char new_link_file[MAXPGPATH]; + + snprintf(existing_file, sizeof(existing_file), "%s/PG_VERSION", old_cluster.pgdata); + snprintf(new_link_file, sizeof(new_link_file), "%s/PG_VERSION.reflinktest", new_cluster.pgdata); + unlink(new_link_file); /* might fail */ + +#if defined(HAVE_COPYFILE) && defined(COPYFILE_CLONE_FORCE) + if (copyfile(existing_file, new_link_file, NULL, COPYFILE_CLONE_FORCE) < 0) + { + if (user_opts.reflink_mode == REFLINK_ALWAYS) + pg_fatal("could not clone file between old and new data directories: %s\n", + strerror(errno)); + else if (user_opts.check) + pg_log(PG_REPORT, "could not clone file between old and new data directories: %s\n", + strerror(errno)); + } +#elif defined(__linux__) && defined(FICLONE) + { + int src_fd; + int dest_fd; + + if ((src_fd = open(existing_file, O_RDONLY | PG_BINARY, 0)) < 0) + pg_fatal("could not open file \"%s\": %s\n", + existing_file, strerror(errno)); + + if ((dest_fd = open(new_link_file, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, + pg_file_create_mode)) < 0) + pg_fatal("could not create file \"%s\": %s\n", + new_link_file, strerror(errno)); + + if (ioctl(dest_fd, FICLONE, src_fd) < 0) + { + if (user_opts.reflink_mode == REFLINK_ALWAYS) + pg_fatal("could not clone file between old and new data directories: %s\n", + strerror(errno)); + else if (user_opts.check) + pg_log(PG_REPORT, "could not clone file between old and new data directories: %s\n", + strerror(errno)); + } + + close(src_fd); + close(dest_fd); + } +#else + pg_fatal("file cloning not supported on this platform\n"); +#endif + + unlink(new_link_file); +} + void check_hard_link(void) { diff --git a/src/bin/pg_upgrade/option.c b/src/bin/pg_upgrade/option.c index 9dbc9225a6..d52a1bcee3 100644 --- a/src/bin/pg_upgrade/option.c +++ b/src/bin/pg_upgrade/option.c @@ -53,6 +53,9 @@ parseCommandLine(int argc, char *argv[]) {"retain", no_argument, NULL, 'r'}, {"jobs", required_argument, NULL, 'j'}, {"verbose", no_argument, NULL, 'v'}, + + {"reflink", required_argument, NULL, 1}, + {NULL, 0, NULL, 0} }; int option; /* Command line option */ @@ -203,6 +206,17 @@ parseCommandLine(int argc, char *argv[]) log_opts.verbose = true; break; + case 1: + if (strcmp(optarg, "always") == 0) + user_opts.reflink_mode = REFLINK_ALWAYS; + else if (strcmp(optarg, "auto") == 0) + user_opts.reflink_mode = REFLINK_AUTO; + else if (strcmp(optarg, "never") == 0) + user_opts.reflink_mode = REFLINK_NEVER; + else + pg_fatal("invalid reflink mode: %s\n", optarg); + break; + default: pg_fatal("Try \"%s --help\" for more information.\n", os_info.progname); diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h index f83a3eeb67..16eb34e14c 100644 --- a/src/bin/pg_upgrade/pg_upgrade.h +++ b/src/bin/pg_upgrade/pg_upgrade.h @@ -238,6 +238,16 @@ typedef enum TRANSFER_MODE_LINK } transferMode; +/* + * Enumeration to denote reflink modes + */ +typedef enum +{ + REFLINK_NEVER, + REFLINK_AUTO, + REFLINK_ALWAYS +} reflinkMode; + /* * Enumeration to denote pg_log modes */ @@ -297,6 +307,7 @@ typedef struct bool check; /* true -> ask user for permission to make * changes */ transferMode transfer_mode; /* copy files or link them? */ + reflinkMode reflink_mode; int jobs; } UserOpts; @@ -374,10 +385,14 @@ bool pid_lock_file_exists(const char *datadir); void copyFile(const char *src, const char *dst, const char *schemaName, const char *relName); +bool cloneFile(const char *src, const char *dst, + const char *schemaName, const char *relName, + bool unsupported_ok); void linkFile(const char *src, const char *dst, const char *schemaName, const char *relName); void rewriteVisibilityMap(const char *fromfile, const char *tofile, const char *schemaName, const char *relName); +void check_reflink(void); void check_hard_link(void); /* fopen_priv() is no longer different from fopen() */ diff --git a/src/bin/pg_upgrade/relfilenode.c b/src/bin/pg_upgrade/relfilenode.c index ed604f26ca..fc00cfdfae 100644 --- a/src/bin/pg_upgrade/relfilenode.c +++ b/src/bin/pg_upgrade/relfilenode.c @@ -252,9 +252,34 @@ transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_fro } else if (user_opts.transfer_mode == TRANSFER_MODE_COPY) { - pg_log(PG_VERBOSE, "copying \"%s\" to \"%s\"\n", - old_file, new_file); - copyFile(old_file, new_file, map->nspname, map->relname); + if (user_opts.reflink_mode == REFLINK_ALWAYS) + { + pg_log(PG_VERBOSE, "cloning \"%s\" to \"%s\"\n", + old_file, new_file); + cloneFile(old_file, new_file, map->nspname, map->relname, false); + } + else if (user_opts.reflink_mode == REFLINK_AUTO) + { + static bool cloning_ok = true; + + pg_log(PG_VERBOSE, "copying \"%s\" to \"%s\"\n", + old_file, new_file); + if (cloning_ok && + !cloneFile(old_file, new_file, map->nspname, map->relname, true)) + { + pg_log(PG_VERBOSE, "cloning not supported, switching to copying\n"); + cloning_ok = false; + copyFile(old_file, new_file, map->nspname, map->relname); + } + else + copyFile(old_file, new_file, map->nspname, map->relname); + } + else + { + pg_log(PG_VERBOSE, "copying \"%s\" to \"%s\"\n", + old_file, new_file); + copyFile(old_file, new_file, map->nspname, map->relname); + } } else { diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in index 90dda8ea05..2c57e31dcd 100644 --- a/src/include/pg_config.h.in +++ b/src/include/pg_config.h.in @@ -114,6 +114,9 @@ /* Define to 1 if your compiler handles computed gotos. */ #undef HAVE_COMPUTED_GOTO +/* Define to 1 if you have the `copyfile' function. */ +#undef HAVE_COPYFILE + /* Define to 1 if you have the header file. */ #undef HAVE_CRTDEFS_H base-commit: 27e082b0c6e564facfbf54b56090fdcc4bf44cca -- 2.19.0 --------------59B7766A964E29E66AF4A3FB--