On Tue, Jul 20, 2021 at 2:13 AM Tom Lane <t...@sss.pgh.pa.us> wrote:
> Hmm ... we used to have to avoid putting #if constructs in the arguments
> of macros (such as StaticAssertStmt).  Maybe that's not a thing anymore
> with C99, and in any case this whole stanza is fairly platform-specific
> so we may not run into a compiler that complains.  But my hindbrain wants
> to see this done with separate statements, eg
>
> #if defined(O_CLOEXEC)
>     StaticAssertStmt((PG_O_DIRECT & O_CLOEXEC) == 0,
>                      "PG_O_DIRECT collides with O_CLOEXEC");
> #endif

Ok, done.

While I was here again, I couldn't resist trying to extend this to
Solaris, since it looked so easy.  I don't have access, but I tested
on Illumos by undefining O_DIRECT.  Thoughts?
From 3016ede1dfd972badac65954d6e908f77e3c134b Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.mu...@gmail.com>
Date: Mon, 19 Jul 2021 21:47:16 +0000
Subject: [PATCH 1/2] Support direct I/O on Solaris.

Extend the change done for macOS by commit 2dbe8905 to cover Solaris.
Note that this doesn't affect Illumos (it gained O_DIRECT).

Discussion: https://postgr.es/m/CA%2BhUKG%2BADiyyHe0cun2wfT%2BSVnFVqNYPxoO6J9zcZkVO7%2BNGig%40mail.gmail.com
---
 src/backend/storage/file/fd.c         | 19 +++++++++++++++----
 src/bin/pg_test_fsync/pg_test_fsync.c | 27 +++++++++++++++++++++------
 src/include/storage/fd.h              |  9 ++++++---
 3 files changed, 42 insertions(+), 13 deletions(-)

diff --git a/src/backend/storage/file/fd.c b/src/backend/storage/file/fd.c
index 5d5e8ae94e..78ac2caa8f 100644
--- a/src/backend/storage/file/fd.c
+++ b/src/backend/storage/file/fd.c
@@ -1057,11 +1057,13 @@ BasicOpenFilePerm(const char *fileName, int fileFlags, mode_t fileMode)
 	int			fd;
 
 tryAgain:
-#ifdef PG_O_DIRECT_USE_F_NOCACHE
+#if defined(PG_O_DIRECT_USE_F_NOCACHE) || \
+	defined(PG_O_DIRECT_USE_DIRECTIO_ON)
 
 	/*
 	 * The value we defined to stand in for O_DIRECT when simulating it with
-	 * F_NOCACHE had better not collide with any of the standard flags.
+	 * an extra system call had better not collide with any of the standard
+	 * flags.
 	 */
 	StaticAssertStmt((PG_O_DIRECT &
 					  (O_APPEND |
@@ -1089,10 +1091,19 @@ tryAgain:
 
 	if (fd >= 0)
 	{
-#ifdef PG_O_DIRECT_USE_F_NOCACHE
+#if defined(PG_O_DIRECT_USE_F_NOCACHE) || \
+	defined(PG_O_DIRECT_USE_DIRECTIO_ON)
 		if (fileFlags & PG_O_DIRECT)
 		{
-			if (fcntl(fd, F_NOCACHE, 1) < 0)
+			int			rc;
+
+#if defined(PG_O_DIRECT_USE_F_NOCACHE)
+			rc = fcntl(fd, F_NOCACHE, 1);
+#endif
+#if defined(PG_O_DIRECT_USE_DIRECTIO_ON)
+			rc = directio(fd, DIRECTIO_ON);
+#endif
+			if (rc < 0)
 			{
 				int			save_errno = errno;
 
diff --git a/src/bin/pg_test_fsync/pg_test_fsync.c b/src/bin/pg_test_fsync/pg_test_fsync.c
index fef31844fa..f5e3868c10 100644
--- a/src/bin/pg_test_fsync/pg_test_fsync.c
+++ b/src/bin/pg_test_fsync/pg_test_fsync.c
@@ -221,6 +221,8 @@ handle_args(int argc, char *argv[])
 	printf(_("O_DIRECT supported on this platform for open_datasync and open_sync.\n"));
 #elif defined(F_NOCACHE)
 	printf(_("F_NOCACHE supported on this platform for open_datasync and open_sync.\n"));
+#elif defined(DIRECTIO_ON)
+	printf(_("DIRECTIO_ON supported on this platform for open_datasync and open_sync.\n"));
 #else
 	printf(_("Direct I/O is not supported on this platform.\n"));
 #endif
@@ -271,14 +273,27 @@ open_direct(const char *path, int flags, mode_t mode)
 
 	fd = open(path, flags, mode);
 
-#if !defined(O_DIRECT) && defined(F_NOCACHE)
-	if (fd >= 0 && fcntl(fd, F_NOCACHE, 1) < 0)
+#if !defined(O_DIRECT) && \
+	(defined(F_NOCACHE) || \
+	 defined(DIRECTIO_ON))
+	if (fd >= 0)
 	{
-		int			save_errno = errno;
+		int			rc;
 
-		close(fd);
-		errno = save_errno;
-		return -1;
+#if defined(F_NOCACHE)
+		rc = fcntl(fd, F_NOCACHE, 1);
+#endif
+#if defined(DIRECTIO_ON)
+		rc = directio(fd, DIRECTIO_ON);
+#endif
+		if (rc < 0)
+		{
+			int			save_errno = errno;
+
+			close(fd);
+			errno = save_errno;
+			return -1;
+		}
 	}
 #endif
 
diff --git a/src/include/storage/fd.h b/src/include/storage/fd.h
index 2d843eb992..b04988f818 100644
--- a/src/include/storage/fd.h
+++ b/src/include/storage/fd.h
@@ -82,15 +82,18 @@ extern int	max_safe_fds;
 /*
  * O_DIRECT is not standard, but almost every Unix has it.  We translate it
  * to the appropriate Windows flag in src/port/open.c.  We simulate it with
- * fcntl(F_NOCACHE) on macOS inside fd.c's open() wrapper.  We use the name
- * PG_O_DIRECT rather than defining O_DIRECT in that case (probably not a good
- * idea on a Unix).
+ * extra calls on macOS and Solaris inside fd.c's open() wrapper.  We use the
+ * name PG_O_DIRECT rather than defining O_DIRECT in that case (probably not a
+ * good idea on a Unix).
  */
 #if defined(O_DIRECT)
 #define		PG_O_DIRECT O_DIRECT
 #elif defined(F_NOCACHE)
 #define		PG_O_DIRECT 0x80000000
 #define		PG_O_DIRECT_USE_F_NOCACHE
+#elif defined(DIRECTIO_ON)
+#define		PG_O_DIRECT 0x80000000
+#define		PG_O_DIRECT_USE_DIRECTIO_ON
 #else
 #define		PG_O_DIRECT 0
 #endif
-- 
2.30.2

From 7c99892354500f046995acddc0789879a50a1096 Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.mu...@gmail.com>
Date: Mon, 19 Jul 2021 22:26:34 +0000
Subject: [PATCH 2/2] XXX Test

---
 src/backend/storage/file/fd.c         | 2 ++
 src/bin/pg_test_fsync/pg_test_fsync.c | 2 ++
 src/include/storage/fd.h              | 2 ++
 3 files changed, 6 insertions(+)

diff --git a/src/backend/storage/file/fd.c b/src/backend/storage/file/fd.c
index 78ac2caa8f..248e2c3cd4 100644
--- a/src/backend/storage/file/fd.c
+++ b/src/backend/storage/file/fd.c
@@ -1098,9 +1098,11 @@ tryAgain:
 			int			rc;
 
 #if defined(PG_O_DIRECT_USE_F_NOCACHE)
+			elog(LOG, "XXX F_NOCACHE"); /* HACK */
 			rc = fcntl(fd, F_NOCACHE, 1);
 #endif
 #if defined(PG_O_DIRECT_USE_DIRECTIO_ON)
+			elog(LOG, "XXX DIRECTIO_ON");	/* HACK */
 			rc = directio(fd, DIRECTIO_ON);
 #endif
 			if (rc < 0)
diff --git a/src/bin/pg_test_fsync/pg_test_fsync.c b/src/bin/pg_test_fsync/pg_test_fsync.c
index f5e3868c10..7396886cec 100644
--- a/src/bin/pg_test_fsync/pg_test_fsync.c
+++ b/src/bin/pg_test_fsync/pg_test_fsync.c
@@ -17,6 +17,8 @@
 #include "common/logging.h"
 #include "getopt_long.h"
 
+#undef O_DIRECT					/* HACK: make Illumos behave like Solaris */
+
 /*
  * put the temp files in the local directory
  * unless the user specifies otherwise
diff --git a/src/include/storage/fd.h b/src/include/storage/fd.h
index b04988f818..2c09639cf1 100644
--- a/src/include/storage/fd.h
+++ b/src/include/storage/fd.h
@@ -79,6 +79,8 @@ extern int	max_safe_fds;
 #define FILE_POSSIBLY_DELETED(err)	((err) == ENOENT || (err) == EACCES)
 #endif
 
+#undef O_DIRECT					/* HACK: make Illumos behave like Solaris */
+
 /*
  * O_DIRECT is not standard, but almost every Unix has it.  We translate it
  * to the appropriate Windows flag in src/port/open.c.  We simulate it with
-- 
2.30.2

Reply via email to