From a28ba23c147def88e552ac5023114ce369b94cde Mon Sep 17 00:00:00 2001
From: Thomas Munro <tmunro@postgresql.org>
Date: Sat, 23 Feb 2019 10:38:05 +1300
Subject: [PATCH] Tolerate ENOSYS failure from sync_file_range().

One unintended consequence of commit 9ccdd7f6 was that Windows WSL
users started getting a panic whenever we tried to initiate data
flushing with sync_file_range(), because WSL does not implement that
system call.  Previously, they got a stream of periodic warnings,
which was also undesirable but at least ignorable.

Prevent the panic by handling ENOSYS specially and skipping promotion
via data_sync_elevel().  As a small added bonus, suppress future
attempts after the first failure so that the earlier problem with
noisy warnings is improved.

Perhaps work could be done in a future release to fall back to our
other write-back hinting mechanisms on such platforms, but this seems
more suitable for back-branches.

Back-patch to all supported versions, like 9ccdd7f6.

Author: Thomas Munro and James Sewell
Tested-by: James Sewell
Reported-by: Bruce Klein
Discussion: https://postgr.es/m/CA+mCpegfOUph2U4ZADtQT16dfbkjjYNJL1bSTWErsazaFjQW9A@mail.gmail.com
---
 src/backend/storage/file/fd.c | 21 ++++++++++++++++++++-
 1 file changed, 20 insertions(+), 1 deletion(-)

diff --git a/src/backend/storage/file/fd.c b/src/backend/storage/file/fd.c
index 213de7698a..d46639d2ed 100644
--- a/src/backend/storage/file/fd.c
+++ b/src/backend/storage/file/fd.c
@@ -420,6 +420,10 @@ pg_flush_data(int fd, off_t offset, off_t nbytes)
 #if defined(HAVE_SYNC_FILE_RANGE)
 	{
 		int			rc;
+		static bool not_implemented_by_kernel = false;
+
+		if (not_implemented_by_kernel)
+			return;
 
 		/*
 		 * sync_file_range(SYNC_FILE_RANGE_WRITE), currently linux specific,
@@ -434,7 +438,22 @@ pg_flush_data(int fd, off_t offset, off_t nbytes)
 							 SYNC_FILE_RANGE_WRITE);
 		if (rc != 0)
 		{
-			ereport(data_sync_elevel(WARNING),
+			int			elevel;
+
+			/*
+			 * For systems that don't have an implementation of
+			 * sync_file_range() such as Windows WSL, generate only one
+			 * warning and then suppress all further attempts by this process.
+			 */
+			if (errno == ENOSYS)
+			{
+				elevel = WARNING;
+				not_implemented_by_kernel = true;
+			}
+			else
+				elevel = data_sync_elevel(WARNING);
+
+			ereport(elevel,
 					(errcode_for_file_access(),
 					 errmsg("could not flush dirty data: %m")));
 		}
-- 
2.20.1

