From 28440393ed4e58d69f719729e5f0af85bd2997b5 Mon Sep 17 00:00:00 2001
From: Takashi Menjo <takashi.menjou.vg@hco.ntt.co.jp>
Date: Tue, 1 Jun 2021 19:29:22 +0900
Subject: [PATCH v4 9/9] Preallocate and initialize more WAL if
 wal_pmem_map=true

---
 src/backend/access/transam/xlog.c | 30 ++++++++++++++++++++++++------
 src/backend/utils/misc/guc.c      |  2 +-
 2 files changed, 25 insertions(+), 7 deletions(-)

diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 9753b7b24f..cee88de0b7 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2016,7 +2016,9 @@ GetXLogBuffer(XLogRecPtr ptr)
 	if (wal_pmem_map)
 	{
 		openLogSegNo = PmemXLogEnsurePrevMapped(endptr);
-		cachedPos = PmemXLogGetBufferPages() + idx * (Size) XLOG_BLCKSZ;
+		cachedPos = PmemXLogGetBufferPages() +
+					(Size) XLogSegmentOffset(endptr - XLOG_BLCKSZ,
+											 wal_segment_size);
 	}
 	else
 		cachedPos = XLogCtl->pages + idx * (Size) XLOG_BLCKSZ;
@@ -2256,7 +2258,9 @@ AdvanceXLInsertBuffer(XLogRecPtr upto, bool opportunistic)
 		if (wal_pmem_map)
 		{
 			openLogSegNo = PmemXLogEnsurePrevMapped(NewPageEndPtr);
-			NewPage = (XLogPageHeader) (PmemXLogGetBufferPages() + nextidx * (Size) XLOG_BLCKSZ);
+			NewPage = (XLogPageHeader)
+				(PmemXLogGetBufferPages() +
+				 (Size) XLogSegmentOffset(NewPageBeginPtr, wal_segment_size));
 		}
 		else
 			NewPage = (XLogPageHeader) (XLogCtl->pages + nextidx * (Size) XLOG_BLCKSZ);
@@ -5210,15 +5214,25 @@ XLOGShmemSize(void)
 	/*
 	 * If we use WAL segment files as WAL buffers, we don't use the given
 	 * value of wal_buffers. Instead, we set it to the value based on the
-	 * segment size and the page size. This should be done before calculating
+	 * min_wal_size and the page size. This should be done before calculating
 	 * the size of xlblocks array.
+	 *
+	 * TODO Do not allow changing min_wal_size by SIGHUP if wal_pmem_map=true.
+	 *
+	 * TODO Move validations to check_hook functions.
 	 */
 	if (wal_pmem_map)
 	{
 		int			npages;
 		char		buf[32];
 
-		npages = wal_segment_size / XLOG_BLCKSZ;
+		if (min_wal_size_mb % (wal_segment_size / (1024 * 1024)) != 0)
+			elog(PANIC, "min_wal_size should be multiple of wal_segment_size when wal_pmem_map=true");
+
+		if (min_wal_size_mb / (XLOG_BLCKSZ / 1024) > INT_MAX / 1024)
+			elog(PANIC, "too many wal buffer pages");
+
+		npages = min_wal_size_mb / (XLOG_BLCKSZ / 1024) * 1024;
 		snprintf(buf, sizeof(buf), "%d", (int) npages);
 		SetConfigOption("wal_buffers", buf, PGC_POSTMASTER, PGC_S_OVERRIDE);
 	}
@@ -8117,7 +8131,8 @@ StartupXLOG(void)
 			 * Note that "len" indicates the size of the valid part.
 			 */
 			openLogSegNo = PmemXLogEnsurePrevMapped(EndOfLog);
-			page = PmemXLogGetBufferPages() + firstIdx * (Size) XLOG_BLCKSZ;
+			page = PmemXLogGetBufferPages() +
+				   (Size) XLogSegmentOffset(pageBeginPtr, wal_segment_size);
 			len = EndOfLog % XLOG_BLCKSZ;
 			memset(page + len, 0, XLOG_BLCKSZ - len);
 
@@ -8157,7 +8172,10 @@ StartupXLOG(void)
 	/*
 	 * Preallocate additional log files, if wanted.
 	 */
-	PreallocXlogFiles(EndOfLog);
+	if (wal_pmem_map)
+		AdvanceXLInsertBuffer(InvalidXLogRecPtr, true);
+	else
+		PreallocXlogFiles(EndOfLog);
 
 	/*
 	 * Okay, we're officially UP.
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 05c9d260d8..7799981a34 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -2862,7 +2862,7 @@ static struct config_int ConfigureNamesInt[] =
 			GUC_UNIT_XBLOCKS
 		},
 		&XLOGbuffers,
-		-1, -1, (INT_MAX / XLOG_BLCKSZ),
+		-1, -1, INT_MAX,
 		check_wal_buffers, NULL, NULL
 	},
 
-- 
2.25.1

