From cee5e9f3ed9e190569a99548545801564b087fec Mon Sep 17 00:00:00 2001
From: Michael Paquier <michael@paquier.xyz>
Date: Fri, 22 Mar 2019 09:24:14 +0900
Subject: [PATCH v9 2/2] Add option -N/--no-sync to pg_checksums

This is an option consistent with what pg_dump, pg_rewind and
pg_basebackup provide which is useful for leveraging the I/O effort when
testing things, not to be used in a production environment.

Author: Michael Paquier
Reviewed-by: Fabien Coelho
Discussion: https://postgr.es/m/20181221201616.GD4974@nighthawk.caipicrew.dd-dns.de
---
 doc/src/sgml/ref/pg_checksums.sgml    | 16 ++++++++++++++++
 src/bin/pg_checksums/pg_checksums.c   | 17 +++++++++++++----
 src/bin/pg_checksums/t/002_actions.pl | 10 +++++-----
 3 files changed, 34 insertions(+), 9 deletions(-)

diff --git a/doc/src/sgml/ref/pg_checksums.sgml b/doc/src/sgml/ref/pg_checksums.sgml
index fda85e7ea0..ce761cc662 100644
--- a/doc/src/sgml/ref/pg_checksums.sgml
+++ b/doc/src/sgml/ref/pg_checksums.sgml
@@ -100,6 +100,22 @@ PostgreSQL documentation
       </listitem>
      </varlistentry>
 
+     <varlistentry>
+      <term><option>-N</option></term>
+      <term><option>--no-sync</option></term>
+      <listitem>
+       <para>
+        By default, <command>pg_checksums</command> will wait for all files
+        to be written safely to disk.  This option causes
+        <command>pg_checksums</command> to return without waiting, which is
+        faster, but means that a subsequent operating system crash can leave
+        the updated data folder corrupt.  Generally, this option is useful
+        for testing but should not be used on a production installation.
+        This option has no effect when using <literal>--check</literal>.
+       </para>
+      </listitem>
+     </varlistentry>
+
      <varlistentry>
       <term><option>-v</option></term>
       <term><option>--verbose</option></term>
diff --git a/src/bin/pg_checksums/pg_checksums.c b/src/bin/pg_checksums/pg_checksums.c
index f640fda14b..5265a30d97 100644
--- a/src/bin/pg_checksums/pg_checksums.c
+++ b/src/bin/pg_checksums/pg_checksums.c
@@ -35,6 +35,7 @@ static int64 badblocks = 0;
 static ControlFileData *ControlFile;
 
 static char *only_relfilenode = NULL;
+static bool do_sync = true;
 static bool verbose = false;
 
 typedef enum
@@ -69,6 +70,7 @@ usage(void)
 	printf(_("  -c, --check            check data checksums (default)\n"));
 	printf(_("  -d, --disable          disable data checksums\n"));
 	printf(_("  -e, --enable           enable data checksums\n"));
+	printf(_("  -N, --no-sync          do not wait for changes to be written safely to disk\n"));
 	printf(_("  -v, --verbose          output verbose messages\n"));
 	printf(_("  -r RELFILENODE         check only relation with specified relfilenode\n"));
 	printf(_("  -V, --version          output version information, then exit\n"));
@@ -297,6 +299,7 @@ main(int argc, char *argv[])
 		{"pgdata", required_argument, NULL, 'D'},
 		{"disable", no_argument, NULL, 'd'},
 		{"enable", no_argument, NULL, 'e'},
+		{"no-sync", no_argument, NULL, 'N'},
 		{"verbose", no_argument, NULL, 'v'},
 		{NULL, 0, NULL, 0}
 	};
@@ -324,7 +327,7 @@ main(int argc, char *argv[])
 		}
 	}
 
-	while ((c = getopt_long(argc, argv, "cD:der:v", long_options, &option_index)) != -1)
+	while ((c = getopt_long(argc, argv, "cD:deNr:v", long_options, &option_index)) != -1)
 	{
 		switch (c)
 		{
@@ -337,6 +340,9 @@ main(int argc, char *argv[])
 			case 'e':
 				mode = PG_MODE_ENABLE;
 				break;
+			case 'N':
+				do_sync = false;
+				break;
 			case 'v':
 				verbose = true;
 				break;
@@ -472,11 +478,14 @@ main(int argc, char *argv[])
 		ControlFile->data_checksum_version =
 			(mode == PG_MODE_ENABLE) ? PG_DATA_CHECKSUM_VERSION : 0;
 
-		printf(_("Syncing data directory\n"));
-		fsync_pgdata(DataDir, progname, PG_VERSION_NUM);
+		if (do_sync)
+		{
+			printf(_("Syncing data directory\n"));
+			fsync_pgdata(DataDir, progname, PG_VERSION_NUM);
+		}
 
 		printf(_("Updating control file\n"));
-		update_controlfile(DataDir, progname, ControlFile, true);
+		update_controlfile(DataDir, progname, ControlFile, do_sync);
 
 		if (verbose)
 			printf(_("Data checksum version: %d\n"), ControlFile->data_checksum_version);
diff --git a/src/bin/pg_checksums/t/002_actions.pl b/src/bin/pg_checksums/t/002_actions.pl
index 3ab18a6b89..41575c5245 100644
--- a/src/bin/pg_checksums/t/002_actions.pl
+++ b/src/bin/pg_checksums/t/002_actions.pl
@@ -101,11 +101,11 @@ mkdir "$pgdata/global/pgsql_tmp";
 append_to_file "$pgdata/global/pgsql_tmp/1.1", "foo";
 
 # Enable checksums.
-command_ok(['pg_checksums', '--enable', '-D', $pgdata],
+command_ok(['pg_checksums', '--enable', '--no-sync', '-D', $pgdata],
 	   "checksums successfully enabled in cluster");
 
 # Successive attempt to enable checksums fails.
-command_fails(['pg_checksums', '--enable', '-D', $pgdata],
+command_fails(['pg_checksums', '--enable', '--no-sync', '-D', $pgdata],
 	      "enabling checksums fails if already enabled");
 
 # Control file should know that checksums are enabled.
@@ -113,12 +113,12 @@ command_like(['pg_controldata', $pgdata],
 	     qr/Data page checksum version:.*1/,
 	     'checksums enabled in control file');
 
-# Disable checksums again.
+# Disable checksums again.  Flush result here as that should be cheap.
 command_ok(['pg_checksums', '--disable', '-D', $pgdata],
 	   "checksums successfully disabled in cluster");
 
 # Successive attempt to disable checksums fails.
-command_fails(['pg_checksums', '--disable', '-D', $pgdata],
+command_fails(['pg_checksums', '--disable', '--no-sync', '-D', $pgdata],
 	      "disabling checksums fails if already disabled");
 
 # Control file should know that checksums are disabled.
@@ -127,7 +127,7 @@ command_like(['pg_controldata', $pgdata],
 		 'checksums disabled in control file');
 
 # Enable checksums again for follow-up tests.
-command_ok(['pg_checksums', '--enable', '-D', $pgdata],
+command_ok(['pg_checksums', '--enable', '--no-sync', '-D', $pgdata],
 		   "checksums successfully enabled in cluster");
 
 # Control file should know that checksums are enabled.
-- 
2.20.1

