From cfca62dd55d7be7e0025e5625f18d3ab9180029c Mon Sep 17 00:00:00 2001
From: Nathan Bossart <bossartn@amazon.com>
Date: Mon, 13 Dec 2021 20:20:12 -0800
Subject: [PATCH v5 7/8] Use syncfs() in CheckPointLogicalRewriteHeap() for
 shutdown and end-of-recovery checkpoints.

This may save quite a bit of time when there are many mapping files
to flush to disk.
---
 src/backend/access/heap/rewriteheap.c | 35 ++++++++++++++++++++++++++-
 src/backend/access/transam/xlog.c     |  2 +-
 src/include/access/rewriteheap.h      |  2 +-
 3 files changed, 36 insertions(+), 3 deletions(-)

diff --git a/src/backend/access/heap/rewriteheap.c b/src/backend/access/heap/rewriteheap.c
index c5a1103687..1a8621c0ef 100644
--- a/src/backend/access/heap/rewriteheap.c
+++ b/src/backend/access/heap/rewriteheap.c
@@ -1193,7 +1193,7 @@ heap_xlog_logical_rewrite(XLogReaderState *r)
  * ---
  */
 void
-CheckPointLogicalRewriteHeap(void)
+CheckPointLogicalRewriteHeap(bool shutdown)
 {
 	XLogRecPtr	cutoff;
 	XLogRecPtr	redo;
@@ -1219,6 +1219,39 @@ CheckPointLogicalRewriteHeap(void)
 	if (ProcGlobal->custodianLatch)
 		SetLatch(ProcGlobal->custodianLatch);
 
+#ifdef HAVE_SYNCFS
+
+	/*
+	 * If we are doing a shutdown or end-of-recovery checkpoint, let's use
+	 * syncfs() to flush the mappings to disk instead of flushing each one
+	 * individually.  This may save us quite a bit of time when there are many
+	 * such files to flush.
+	 */
+	if (shutdown)
+	{
+		int		fd;
+
+		fd = OpenTransientFile("pg_logical/mappings", O_RDONLY);
+		if (fd < 0)
+			ereport(ERROR,
+					(errcode_for_file_access(),
+					 errmsg("could not open file \"pg_logical/mappings\": %m")));
+
+		if (syncfs(fd) < 0)
+			ereport(ERROR,
+					(errcode_for_file_access(),
+					 errmsg("could not synchronize file system for file \"pg_logical/mappings\": %m")));
+
+		if (CloseTransientFile(fd) != 0)
+			ereport(ERROR,
+					(errcode_for_file_access(),
+					 errmsg("could not close file \"pg_logical/mappings\": %m")));
+
+		return;
+	}
+
+#endif							/* HAVE_SYNCFS */
+
 	mappings_dir = AllocateDir("pg_logical/mappings");
 	while ((mapping_de = ReadDir(mappings_dir, "pg_logical/mappings")) != NULL)
 	{
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index c4a80ea82a..6a3613fd98 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -6806,7 +6806,7 @@ CheckPointGuts(XLogRecPtr checkPointRedo, int flags)
 {
 	CheckPointRelationMap();
 	CheckPointReplicationSlots();
-	CheckPointLogicalRewriteHeap();
+	CheckPointLogicalRewriteHeap(flags & (CHECKPOINT_IS_SHUTDOWN | CHECKPOINT_END_OF_RECOVERY));
 	CheckPointReplicationOrigin();
 
 	/* Write out all dirty data in SLRUs and the main buffer pool */
diff --git a/src/include/access/rewriteheap.h b/src/include/access/rewriteheap.h
index f493094557..79cae034e5 100644
--- a/src/include/access/rewriteheap.h
+++ b/src/include/access/rewriteheap.h
@@ -52,7 +52,7 @@ typedef struct LogicalRewriteMappingData
  * ---
  */
 #define LOGICAL_REWRITE_FORMAT "map-%x-%x-%X_%X-%x-%x"
-void		CheckPointLogicalRewriteHeap(void);
+void		CheckPointLogicalRewriteHeap(bool shutdown);
 void		RemoveOldLogicalRewriteMappings(void);
 
 #endif							/* REWRITE_HEAP_H */
-- 
2.25.1

