Allow using syncfs() in frontend utilities.
authorNathan Bossart <nathan@postgresql.org>
Wed, 6 Sep 2023 23:27:16 +0000 (16:27 -0700)
committerNathan Bossart <nathan@postgresql.org>
Wed, 6 Sep 2023 23:27:16 +0000 (16:27 -0700)
This commit allows specifying a --sync-method in several frontend
utilities that must synchronize many files to disk (initdb,
pg_basebackup, pg_checksums, pg_dump, pg_rewind, and pg_upgrade).
On Linux, users can specify "syncfs" to synchronize the relevant
file systems instead of calling fsync() for every single file.  In
many cases, using syncfs() is much faster.

As with recovery_init_sync_method, this new option comes with some
caveats.  The descriptions of these caveats have been moved to a
new appendix section in the documentation.

Co-authored-by: Justin Pryzby
Reviewed-by: Michael Paquier, Thomas Munro, Robert Haas, Justin Pryzby
Discussion: https://postgr.es/m/20210930004340.GM831%40telsasoft.com

21 files changed:
doc/src/sgml/config.sgml
doc/src/sgml/filelist.sgml
doc/src/sgml/postgres.sgml
doc/src/sgml/ref/initdb.sgml
doc/src/sgml/ref/pg_basebackup.sgml
doc/src/sgml/ref/pg_checksums.sgml
doc/src/sgml/ref/pg_dump.sgml
doc/src/sgml/ref/pg_rewind.sgml
doc/src/sgml/ref/pgupgrade.sgml
doc/src/sgml/syncfs.sgml [new file with mode: 0644]
src/bin/initdb/initdb.c
src/bin/initdb/t/001_initdb.pl
src/bin/pg_basebackup/pg_basebackup.c
src/bin/pg_checksums/pg_checksums.c
src/bin/pg_dump/pg_dump.c
src/bin/pg_rewind/pg_rewind.c
src/bin/pg_upgrade/option.c
src/bin/pg_upgrade/pg_upgrade.c
src/bin/pg_upgrade/pg_upgrade.h
src/fe_utils/option_utils.c
src/include/fe_utils/option_utils.h

index f0a50a5f9ad0dd829e8f4406d0b15549777e2c2f..6bc1b215db99dc53a16403061cccf46cb63549f1 100644 (file)
@@ -10511,15 +10511,9 @@ dynamic_library_path = 'C:\tools\postgresql;H:\my_project\lib;$libdir'
         On Linux, <literal>syncfs</literal> may be used instead, to ask the
         operating system to synchronize the whole file systems that contain the
         data directory, the WAL files and each tablespace (but not any other
-        file systems that may be reachable through symbolic links).  This may
-        be a lot faster than the <literal>fsync</literal> setting, because it
-        doesn't need to open each file one by one.  On the other hand, it may
-        be slower if a file system is shared by other applications that
-        modify a lot of files, since those files will also be written to disk.
-        Furthermore, on versions of Linux before 5.8, I/O errors encountered
-        while writing data to disk may not be reported to
-        <productname>PostgreSQL</productname>, and relevant error messages may
-        appear only in kernel logs.
+        file systems that may be reachable through symbolic links).  See
+        <xref linkend="syncfs"/> for more information about using
+        <function>syncfs()</function>.
        </para>
        <para>
         This parameter can only be set in the
index e3d94a62b3f5a2668e58e1d38c7a43e75cbbc685..4c63a7e76895b5291af18d14b9c3116d7cc63878 100644 (file)
 <!ENTITY acronyms   SYSTEM "acronyms.sgml">
 <!ENTITY glossary   SYSTEM "glossary.sgml">
 <!ENTITY color      SYSTEM "color.sgml">
+<!ENTITY syncfs     SYSTEM "syncfs.sgml">
 
 <!ENTITY features-supported   SYSTEM "features-supported.sgml">
 <!ENTITY features-unsupported SYSTEM "features-unsupported.sgml">
index 2e271862fc1800086a64a94b2173ea21142a1628..f629524be07fcd978b2d9eab8b30d6ca4cf14a52 100644 (file)
@@ -294,6 +294,7 @@ break is not needed in a wider output rendering.
   &acronyms;
   &glossary;
   &color;
+  &syncfs;
   &obsolete;
 
  </part>
index 22f1011781fb8ce2ec04ea46a6f66fb22abd89d3..8a09c5c4388322823d1f33d91ce6853535669a7d 100644 (file)
@@ -365,6 +365,28 @@ PostgreSQL documentation
       </listitem>
      </varlistentry>
 
+     <varlistentry id="app-initdb-option-sync-method">
+      <term><option>--sync-method</option></term>
+      <listitem>
+       <para>
+        When set to <literal>fsync</literal>, which is the default,
+        <command>initdb</command> will recursively open and synchronize all
+        files in the data directory.  The search for files will follow symbolic
+        links for the WAL directory and each configured tablespace.
+       </para>
+       <para>
+        On Linux, <literal>syncfs</literal> may be used instead to ask the
+        operating system to synchronize the whole file systems that contain the
+        data directory, the WAL files, and each tablespace.  See
+        <xref linkend="syncfs"/> for more information about using
+        <function>syncfs()</function>.
+       </para>
+       <para>
+        This option has no effect when <option>--no-sync</option> is used.
+       </para>
+      </listitem>
+     </varlistentry>
+
      <varlistentry id="app-initdb-option-sync-only">
       <term><option>-S</option></term>
       <term><option>--sync-only</option></term>
index 79d3e657c32c245f9825c602d2760c0c3f49d9e1..d2b8ddd200c271bf86adb3adaab2f80987ab1987 100644 (file)
@@ -594,6 +594,31 @@ PostgreSQL documentation
       </listitem>
      </varlistentry>
 
+     <varlistentry>
+      <term><option>--sync-method</option></term>
+      <listitem>
+       <para>
+        When set to <literal>fsync</literal>, which is the default,
+        <command>pg_basebackup</command> will recursively open and synchronize
+        all files in the backup directory.  When the plain format is used, the
+        search for files will follow symbolic links for the WAL directory and
+        each configured tablespace.
+       </para>
+       <para>
+        On Linux, <literal>syncfs</literal> may be used instead to ask the
+        operating system to synchronize the whole file system that contains the
+        backup directory.  When the plain format is used,
+        <command>pg_basebackup</command> will also synchronize the file systems
+        that contain the WAL files and each tablespace.  See
+        <xref linkend="syncfs"/> for more information about using
+        <function>syncfs()</function>.
+       </para>
+       <para>
+        This option has no effect when <option>--no-sync</option> is used.
+       </para>
+      </listitem>
+     </varlistentry>
+
      <varlistentry>
       <term><option>-v</option></term>
       <term><option>--verbose</option></term>
index a3d0b0f0a3d64e26792e89dbed52c16642c19774..7b44ba71cf97210b19efd9945d9098a0952f9ae3 100644 (file)
@@ -139,6 +139,28 @@ PostgreSQL documentation
       </listitem>
      </varlistentry>
 
+     <varlistentry>
+      <term><option>--sync-method</option></term>
+      <listitem>
+       <para>
+        When set to <literal>fsync</literal>, which is the default,
+        <command>pg_checksums</command> will recursively open and synchronize
+        all files in the data directory.  The search for files will follow
+        symbolic links for the WAL directory and each configured tablespace.
+       </para>
+       <para>
+        On Linux, <literal>syncfs</literal> may be used instead to ask the
+        operating system to synchronize the whole file systems that contain the
+        data directory, the WAL files, and each tablespace.  See
+        <xref linkend="syncfs"/> for more information about using
+        <function>syncfs()</function>.
+       </para>
+       <para>
+        This option has no effect when <option>--no-sync</option> is used.
+       </para>
+      </listitem>
+     </varlistentry>
+
      <varlistentry>
       <term><option>-v</option></term>
       <term><option>--verbose</option></term>
index a3cf0608f5b1475814e750d366d56fe2ab00327a..c1e2220b3cbfbff087f187c4bc987dcffd5424a9 100644 (file)
@@ -1179,6 +1179,27 @@ PostgreSQL documentation
       </listitem>
      </varlistentry>
 
+     <varlistentry>
+      <term><option>--sync-method</option></term>
+      <listitem>
+       <para>
+        When set to <literal>fsync</literal>, which is the default,
+        <command>pg_dump --format=directory</command> will recursively open and
+        synchronize all files in the archive directory.
+       </para>
+       <para>
+        On Linux, <literal>syncfs</literal> may be used instead to ask the
+        operating system to synchronize the whole file system that contains the
+        archive directory.  See <xref linkend="syncfs"/> for more information
+        about using <function>syncfs()</function>.
+       </para>
+       <para>
+        This option has no effect when <option>--no-sync</option> is used or
+        <option>--format</option> is not set to <literal>directory</literal>.
+       </para>
+      </listitem>
+     </varlistentry>
+
      <varlistentry>
       <term><option>--table-and-children=<replaceable class="parameter">pattern</replaceable></option></term>
       <listitem>
index 15cddd086b756b97f6d337622f118ecfeb050aa2..80dff1616820864123b29d47883d48276b68b077 100644 (file)
@@ -284,6 +284,28 @@ PostgreSQL documentation
       </listitem>
      </varlistentry>
 
+     <varlistentry>
+      <term><option>--sync-method</option></term>
+      <listitem>
+       <para>
+        When set to <literal>fsync</literal>, which is the default,
+        <command>pg_rewind</command> will recursively open and synchronize all
+        files in the data directory.  The search for files will follow symbolic
+        links for the WAL directory and each configured tablespace.
+       </para>
+       <para>
+        On Linux, <literal>syncfs</literal> may be used instead to ask the
+        operating system to synchronize the whole file systems that contain the
+        data directory, the WAL files, and each tablespace.  See
+        <xref linkend="syncfs"/> for more information about using
+        <function>syncfs()</function>.
+       </para>
+       <para>
+        This option has no effect when <option>--no-sync</option> is used.
+       </para>
+      </listitem>
+     </varlistentry>
+
      <varlistentry>
       <term><option>-V</option></term>
       <term><option>--version</option></term>
index 7816b4c6859bfa1c9df705f6a32cb538336d8739..bea0d1b93f930ee074dbf3f094e656fdb58e8eca 100644 (file)
@@ -190,6 +190,29 @@ PostgreSQL documentation
       variable <envar>PGSOCKETDIR</envar></para></listitem>
      </varlistentry>
 
+     <varlistentry>
+      <term><option>--sync-method</option></term>
+      <listitem>
+       <para>
+        When set to <literal>fsync</literal>, which is the default,
+        <command>pg_upgrade</command> will recursively open and synchronize all
+        files in the upgraded cluster's data directory.  The search for files
+        will follow symbolic links for the WAL directory and each configured
+        tablespace.
+       </para>
+       <para>
+        On Linux, <literal>syncfs</literal> may be used instead to ask the
+        operating system to synchronize the whole file systems that contain the
+        upgraded cluster's data directory, its WAL files, and each tablespace.
+        See <xref linkend="syncfs"/> for more information about using
+        <function>syncfs()</function>.
+       </para>
+       <para>
+        This option has no effect when <option>--no-sync</option> is used.
+       </para>
+      </listitem>
+     </varlistentry>
+
      <varlistentry>
       <term><option>-U</option> <replaceable>username</replaceable></term>
       <term><option>--username=</option><replaceable>username</replaceable></term>
diff --git a/doc/src/sgml/syncfs.sgml b/doc/src/sgml/syncfs.sgml
new file mode 100644 (file)
index 0000000..00457d2
--- /dev/null
@@ -0,0 +1,36 @@
+<!-- doc/src/sgml/syncfs.sgml -->
+
+<appendix id="syncfs">
+ <title><function>syncfs()</function> Caveats</title>
+
+ <indexterm zone="syncfs">
+  <primary>syncfs</primary>
+ </indexterm>
+
+ <para>
+  On Linux <function>syncfs()</function> may be specified for some
+  configuration parameters (e.g.,
+  <xref linkend="guc-recovery-init-sync-method"/>), server applications (e.g.,
+  <application>pg_upgrade</application>), and client applications (e.g.,
+  <application>pg_basebackup</application>) that involve synchronizing many
+  files to disk.  <function>syncfs()</function> is advantageous in many cases,
+  but there are some trade-offs to keep in mind.
+ </para>
+
+ <para>
+  Since <function>syncfs()</function> instructs the operating system to
+  synchronize a whole file system, it typically requires many fewer system
+  calls than using <function>fsync()</function> to synchronize each file one by
+  one.  Therefore, using <function>syncfs()</function> may be a lot faster than
+  using <function>fsync()</function>.  However, it may be slower if a file
+  system is shared by other applications that modify a lot of files, since
+  those files will also be written to disk.
+ </para>
+
+ <para>
+  Furthermore, on versions of Linux before 5.8, I/O errors encountered while
+  writing data to disk may not be reported to the calling program, and relevant
+  error messages may appear only in kernel logs.
+ </para>
+
+</appendix>
index 51198e666554b3a18777e714fa293b45b8309e6d..bddb30d766cb2170a70d3a807e9568a20122bd48 100644 (file)
@@ -2467,6 +2467,7 @@ usage(const char *progname)
    printf(_("  -N, --no-sync             do not wait for changes to be written safely to disk\n"));
    printf(_("      --no-instructions     do not print instructions for next steps\n"));
    printf(_("  -s, --show                show internal settings\n"));
+   printf(_("      --sync-method=METHOD  set method for syncing files to disk\n"));
    printf(_("  -S, --sync-only           only sync database files to disk, then exit\n"));
    printf(_("\nOther options:\n"));
    printf(_("  -V, --version             output version information, then exit\n"));
@@ -3107,6 +3108,7 @@ main(int argc, char *argv[])
        {"locale-provider", required_argument, NULL, 15},
        {"icu-locale", required_argument, NULL, 16},
        {"icu-rules", required_argument, NULL, 17},
+       {"sync-method", required_argument, NULL, 18},
        {NULL, 0, NULL, 0}
    };
 
@@ -3287,6 +3289,10 @@ main(int argc, char *argv[])
            case 17:
                icu_rules = pg_strdup(optarg);
                break;
+           case 18:
+               if (!parse_sync_method(optarg, &sync_method))
+                   exit(1);
+               break;
            default:
                /* getopt_long already emitted a complaint */
                pg_log_error_hint("Try \"%s --help\" for more information.", progname);
index 2d7469d2fc339a3b045be69a1012e3e74ed038da..45f96cd8bbf04991d54555c6a80c7d6e1bfe1f7c 100644 (file)
@@ -16,6 +16,7 @@ use Test::More;
 my $tempdir = PostgreSQL::Test::Utils::tempdir;
 my $xlogdir = "$tempdir/pgxlog";
 my $datadir = "$tempdir/data";
+my $supports_syncfs = check_pg_config("#define HAVE_SYNCFS 1");
 
 program_help_ok('initdb');
 program_version_ok('initdb');
@@ -82,6 +83,17 @@ command_fails([ 'pg_checksums', '-D', $datadir ],
 command_ok([ 'initdb', '-S', $datadir ], 'sync only');
 command_fails([ 'initdb', $datadir ], 'existing data directory');
 
+if ($supports_syncfs)
+{
+   command_ok([ 'initdb', '-S', $datadir, '--sync-method', 'syncfs' ],
+       'sync method syncfs');
+}
+else
+{
+   command_fails([ 'initdb', '-S', $datadir, '--sync-method', 'syncfs' ],
+       'sync method syncfs');
+}
+
 # Check group access on PGDATA
 SKIP:
 {
index e9033af5c031fab6166d5d0d992ae8af19b50480..74f5332e95652a3a720db8699ce2e0c4bfda7107 100644 (file)
@@ -425,6 +425,8 @@ usage(void)
    printf(_("      --no-slot          prevent creation of temporary replication slot\n"));
    printf(_("      --no-verify-checksums\n"
             "                         do not verify checksums\n"));
+   printf(_("      --sync-method=METHOD\n"
+            "                         set method for syncing files to disk\n"));
    printf(_("  -?, --help             show this help, then exit\n"));
    printf(_("\nConnection options:\n"));
    printf(_("  -d, --dbname=CONNSTR   connection string\n"));
@@ -2282,6 +2284,7 @@ main(int argc, char **argv)
        {"no-manifest", no_argument, NULL, 5},
        {"manifest-force-encode", no_argument, NULL, 6},
        {"manifest-checksums", required_argument, NULL, 7},
+       {"sync-method", required_argument, NULL, 8},
        {NULL, 0, NULL, 0}
    };
    int         c;
@@ -2453,6 +2456,10 @@ main(int argc, char **argv)
            case 7:
                manifest_checksums = pg_strdup(optarg);
                break;
+           case 8:
+               if (!parse_sync_method(optarg, &sync_method))
+                   exit(1);
+               break;
            default:
                /* getopt_long already emitted a complaint */
                pg_log_error_hint("Try \"%s --help\" for more information.", progname);
index 836ee65405904b7673f48b50e243470cc990c41b..e009ba5e0bc9509ace3e696b227d0d729d28fc2f 100644 (file)
@@ -78,6 +78,7 @@ usage(void)
    printf(_("  -f, --filenode=FILENODE  check only relation with specified filenode\n"));
    printf(_("  -N, --no-sync            do not wait for changes to be written safely to disk\n"));
    printf(_("  -P, --progress           show progress information\n"));
+   printf(_("      --sync-method=METHOD set method for syncing files to disk\n"));
    printf(_("  -v, --verbose            output verbose messages\n"));
    printf(_("  -V, --version            output version information, then exit\n"));
    printf(_("  -?, --help               show this help, then exit\n"));
@@ -436,6 +437,7 @@ main(int argc, char *argv[])
        {"no-sync", no_argument, NULL, 'N'},
        {"progress", no_argument, NULL, 'P'},
        {"verbose", no_argument, NULL, 'v'},
+       {"sync-method", required_argument, NULL, 1},
        {NULL, 0, NULL, 0}
    };
 
@@ -494,6 +496,10 @@ main(int argc, char *argv[])
            case 'v':
                verbose = true;
                break;
+           case 1:
+               if (!parse_sync_method(optarg, &sync_method))
+                   exit(1);
+               break;
            default:
                /* getopt_long already emitted a complaint */
                pg_log_error_hint("Try \"%s --help\" for more information.", progname);
index 280662bc3321dc29e54e7c6b7032597683c9c907..f7b61766921370cc212f776ce1de5036da4bbad7 100644 (file)
@@ -432,6 +432,7 @@ main(int argc, char **argv)
        {"table-and-children", required_argument, NULL, 12},
        {"exclude-table-and-children", required_argument, NULL, 13},
        {"exclude-table-data-and-children", required_argument, NULL, 14},
+       {"sync-method", required_argument, NULL, 15},
 
        {NULL, 0, NULL, 0}
    };
@@ -658,6 +659,11 @@ main(int argc, char **argv)
                                          optarg);
                break;
 
+           case 15:
+               if (!parse_sync_method(optarg, &sync_method))
+                   exit_nicely(1);
+               break;
+
            default:
                /* getopt_long already emitted a complaint */
                pg_log_error_hint("Try \"%s --help\" for more information.", progname);
@@ -1069,6 +1075,7 @@ help(const char *progname)
             "                               compress as specified\n"));
    printf(_("  --lock-wait-timeout=TIMEOUT  fail after waiting TIMEOUT for a table lock\n"));
    printf(_("  --no-sync                    do not wait for changes to be written safely to disk\n"));
+   printf(_("  --sync-method=METHOD         set method for syncing files to disk\n"));
    printf(_("  -?, --help                   show this help, then exit\n"));
 
    printf(_("\nOptions controlling the output content:\n"));
index bdfacf32632c780bb6bf085585654f1182195574..bfd44a284e224080e41e50b942d2adb134cedd88 100644 (file)
@@ -22,6 +22,7 @@
 #include "common/file_perm.h"
 #include "common/restricted_token.h"
 #include "common/string.h"
+#include "fe_utils/option_utils.h"
 #include "fe_utils/recovery_gen.h"
 #include "fe_utils/string_utils.h"
 #include "file_ops.h"
@@ -108,6 +109,7 @@ usage(const char *progname)
             "                                 file when running target cluster\n"));
    printf(_("      --debug                    write a lot of debug messages\n"));
    printf(_("      --no-ensure-shutdown       do not automatically fix unclean shutdown\n"));
+   printf(_("      --sync-method=METHOD       set method for syncing files to disk\n"));
    printf(_("  -V, --version                  output version information, then exit\n"));
    printf(_("  -?, --help                     show this help, then exit\n"));
    printf(_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
@@ -132,6 +134,7 @@ main(int argc, char **argv)
        {"no-sync", no_argument, NULL, 'N'},
        {"progress", no_argument, NULL, 'P'},
        {"debug", no_argument, NULL, 3},
+       {"sync-method", required_argument, NULL, 6},
        {NULL, 0, NULL, 0}
    };
    int         option_index;
@@ -219,6 +222,11 @@ main(int argc, char **argv)
                config_file = pg_strdup(optarg);
                break;
 
+           case 6:
+               if (!parse_sync_method(optarg, &sync_method))
+                   exit(1);
+               break;
+
            default:
                /* getopt_long already emitted a complaint */
                pg_log_error_hint("Try \"%s --help\" for more information.", progname);
index 640361009e30a5f4c9b7593ef8d93a53c2e395bf..b9d900d0db46096a9477a0156893f14cc1433f7f 100644 (file)
@@ -14,6 +14,7 @@
 #endif
 
 #include "common/string.h"
+#include "fe_utils/option_utils.h"
 #include "getopt_long.h"
 #include "pg_upgrade.h"
 #include "utils/pidfile.h"
@@ -57,12 +58,14 @@ parseCommandLine(int argc, char *argv[])
        {"verbose", no_argument, NULL, 'v'},
        {"clone", no_argument, NULL, 1},
        {"copy", no_argument, NULL, 2},
+       {"sync-method", required_argument, NULL, 3},
 
        {NULL, 0, NULL, 0}
    };
    int         option;         /* Command line option */
    int         optindex = 0;   /* used by getopt_long */
    int         os_user_effective_id;
+   DataDirSyncMethod unused;
 
    user_opts.do_sync = true;
    user_opts.transfer_mode = TRANSFER_MODE_COPY;
@@ -199,6 +202,12 @@ parseCommandLine(int argc, char *argv[])
                user_opts.transfer_mode = TRANSFER_MODE_COPY;
                break;
 
+           case 3:
+               if (!parse_sync_method(optarg, &unused))
+                   exit(1);
+               user_opts.sync_method = pg_strdup(optarg);
+               break;
+
            default:
                fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
                        os_info.progname);
@@ -209,6 +218,9 @@ parseCommandLine(int argc, char *argv[])
    if (optind < argc)
        pg_fatal("too many command-line arguments (first is \"%s\")", argv[optind]);
 
+   if (!user_opts.sync_method)
+       user_opts.sync_method = pg_strdup("fsync");
+
    if (log_opts.verbose)
        pg_log(PG_REPORT, "Running in verbose mode");
 
@@ -289,6 +301,7 @@ usage(void)
    printf(_("  -V, --version                 display version information, then exit\n"));
    printf(_("  --clone                       clone instead of copying files to new cluster\n"));
    printf(_("  --copy                        copy files to new cluster (default)\n"));
+   printf(_("  --sync-method=METHOD          set method for syncing files to disk\n"));
    printf(_("  -?, --help                    show this help, then exit\n"));
    printf(_("\n"
             "Before running pg_upgrade you must:\n"
index 4562dafcff561ca615e781775a1df090896ff8ef..96bfb67167f736b3b2ceef0f31e9da50a9b83328 100644 (file)
@@ -192,8 +192,10 @@ main(int argc, char **argv)
    {
        prep_status("Sync data directory to disk");
        exec_prog(UTILITY_LOG_FILE, NULL, true, true,
-                 "\"%s/initdb\" --sync-only \"%s\"", new_cluster.bindir,
-                 new_cluster.pgdata);
+                 "\"%s/initdb\" --sync-only \"%s\" --sync-method %s",
+                 new_cluster.bindir,
+                 new_cluster.pgdata,
+                 user_opts.sync_method);
        check_ok();
    }
 
index 7afa96716ec781cdedea77b2f4eb2600496991ac..842f3b6cd377ec163850ded0b1da1334ae553b22 100644 (file)
@@ -304,6 +304,7 @@ typedef struct
    transferMode transfer_mode; /* copy files or link them? */
    int         jobs;           /* number of processes/threads to use */
    char       *socketdir;      /* directory to use for Unix sockets */
+   char       *sync_method;
 } UserOpts;
 
 typedef struct
index 763c991015ba72da6bde721379fe2e7bedeac8f7..d2a3adeb4ba13784f4beb294d64be32e1b18b721 100644 (file)
@@ -82,3 +82,30 @@ option_parse_int(const char *optarg, const char *optname,
        *result = val;
    return true;
 }
+
+/*
+ * Provide strictly harmonized handling of the --sync-method option.
+ */
+bool
+parse_sync_method(const char *optarg, DataDirSyncMethod *sync_method)
+{
+   if (strcmp(optarg, "fsync") == 0)
+       *sync_method = DATA_DIR_SYNC_METHOD_FSYNC;
+   else if (strcmp(optarg, "syncfs") == 0)
+   {
+#ifdef HAVE_SYNCFS
+       *sync_method = DATA_DIR_SYNC_METHOD_SYNCFS;
+#else
+       pg_log_error("this build does not support sync method \"%s\"",
+                    "syncfs");
+       return false;
+#endif
+   }
+   else
+   {
+       pg_log_error("unrecognized sync method: %s", optarg);
+       return false;
+   }
+
+   return true;
+}
index b7b0654cee7a6030a67769a1cdcffe788bc3c7c9..6f3a965916a93fbc43f6c28a714b1b56326f06ce 100644 (file)
@@ -14,6 +14,8 @@
 
 #include "postgres_fe.h"
 
+#include "common/file_utils.h"
+
 typedef void (*help_handler) (const char *progname);
 
 extern void handle_help_version_opts(int argc, char *argv[],
@@ -22,5 +24,7 @@ extern void handle_help_version_opts(int argc, char *argv[],
 extern bool option_parse_int(const char *optarg, const char *optname,
                             int min_range, int max_range,
                             int *result);
+extern bool parse_sync_method(const char *optarg,
+                             DataDirSyncMethod *sync_method);
 
 #endif                         /* OPTION_UTILS_H */