From 3e8db4616f5d567c98a33554bd6151676f7ea95e Mon Sep 17 00:00:00 2001
From: Bruce Momjian <bruce@momjian.us>
Date: Fri, 25 Jun 2021 16:57:05 -0400
Subject: [PATCH v2 11/12] cfe-11-gist_over_cfe-10-hint squash commit

---
 src/backend/access/gist/README       | 10 ++++++++++
 src/backend/access/gist/gist.c       | 21 +++++++++++++++------
 src/backend/access/gist/gistbuild.c  | 12 +++++++++---
 src/backend/access/gist/gistvacuum.c | 20 ++++++++++++++------
 4 files changed, 48 insertions(+), 15 deletions(-)

diff --git a/src/backend/access/gist/README b/src/backend/access/gist/README
index efb2730e18..c4d908fcb2 100644
--- a/src/backend/access/gist/README
+++ b/src/backend/access/gist/README
@@ -477,6 +477,16 @@ value. The page is not recycled, until that XID is no longer visible to
 anyone. That's much more conservative than necessary, but let's keep it
 simple.
 
+GiST and Encryption
+-------------------
+
+GiST uses LSNs and NSNs for concurrency.  This means that unlogged and
+temporary relations also need LSNs.  GiST has a mechanism to assign LSNs
+to such relations, but sometimes uses fixed LSNs and or calls
+gistGetFakeLSN(), which can cause duplicate LSNs to be used.  Therefore,
+when encryption is enabled and fake LSNs are needed, the GiST code calls
+LSNForEncryption().  See src/backend/crypto/README for more details.
+
 
 Authors:
 	Teodor Sigaev	<teodor@sigaev.ru>
diff --git a/src/backend/access/gist/gist.c b/src/backend/access/gist/gist.c
index 30069f139c..74e7e485e6 100644
--- a/src/backend/access/gist/gist.c
+++ b/src/backend/access/gist/gist.c
@@ -501,13 +501,16 @@ gistplacetopage(Relation rel, Size freespace, GISTSTATE *giststate,
 		 * we don't need to be able to detect concurrent splits yet.)
 		 */
 		if (is_build)
-			recptr = GistBuildLSN;
+			recptr = !FileEncryptionEnabled ? GistBuildLSN :
+						LSNForEncryption(RelationIsPermanent(rel));
 		else
 		{
 			if (RelationNeedsWAL(rel))
 				recptr = gistXLogSplit(is_leaf,
 									   dist, oldrlink, oldnsn, leftchildbuf,
 									   markfollowright);
+			else if (FileEncryptionEnabled)
+				recptr = LSNForEncryption(RelationIsPermanent(rel));
 			else
 				recptr = gistGetFakeLSN(rel);
 		}
@@ -568,7 +571,8 @@ gistplacetopage(Relation rel, Size freespace, GISTSTATE *giststate,
 			MarkBufferDirty(leftchildbuf);
 
 		if (is_build)
-			recptr = GistBuildLSN;
+			recptr = !FileEncryptionEnabled ? GistBuildLSN :
+						LSNForEncryption(RelationIsPermanent(rel));
 		else
 		{
 			if (RelationNeedsWAL(rel))
@@ -586,6 +590,8 @@ gistplacetopage(Relation rel, Size freespace, GISTSTATE *giststate,
 										deloffs, ndeloffs, itup, ntup,
 										leftchildbuf);
 			}
+			else if (FileEncryptionEnabled)
+				recptr = LSNForEncryption(RelationIsPermanent(rel));
 			else
 				recptr = gistGetFakeLSN(rel);
 		}
@@ -1665,6 +1671,8 @@ gistprunepage(Relation rel, Page page, Buffer buffer, Relation heapRel)
 
 	if (ndeletable > 0)
 	{
+		XLogRecPtr	recptr;
+
 		TransactionId latestRemovedXid = InvalidTransactionId;
 
 		if (XLogStandbyInfoActive() && RelationNeedsWAL(rel))
@@ -1690,16 +1698,17 @@ gistprunepage(Relation rel, Page page, Buffer buffer, Relation heapRel)
 		/* XLOG stuff */
 		if (RelationNeedsWAL(rel))
 		{
-			XLogRecPtr	recptr;
-
 			recptr = gistXLogDelete(buffer,
 									deletable, ndeletable,
 									latestRemovedXid);
 
-			PageSetLSN(page, recptr);
 		}
+		else if (FileEncryptionEnabled)
+			recptr = LSNForEncryption(RelationIsPermanent(rel));
 		else
-			PageSetLSN(page, gistGetFakeLSN(rel));
+			recptr = gistGetFakeLSN(rel);
+
+		PageSetLSN(page, recptr);
 
 		END_CRIT_SECTION();
 	}
diff --git a/src/backend/access/gist/gistbuild.c b/src/backend/access/gist/gistbuild.c
index fb0f466708..bf5162b410 100644
--- a/src/backend/access/gist/gistbuild.c
+++ b/src/backend/access/gist/gistbuild.c
@@ -48,6 +48,8 @@
 #include "utils/rel.h"
 #include "utils/tuplesort.h"
 
+extern XLogRecPtr LSNForEncryption(bool use_wal_lsn);
+
 /* Step of index tuples for check whether to switch to buffering build mode */
 #define BUFFERING_MODE_SWITCH_CHECK_STEP 256
 
@@ -307,7 +309,8 @@ gistbuild(Relation heap, Relation index, IndexInfo *indexInfo)
 		GISTInitBuffer(buffer, F_LEAF);
 
 		MarkBufferDirty(buffer);
-		PageSetLSN(page, GistBuildLSN);
+		PageSetLSN(page, !FileEncryptionEnabled ? GistBuildLSN :
+				   LSNForEncryption(RelationIsPermanent(index)));
 
 		UnlockReleaseBuffer(buffer);
 
@@ -458,7 +461,9 @@ gist_indexsortbuild(GISTBuildState *state)
 	gist_indexsortbuild_flush_ready_pages(state);
 
 	/* Write out the root */
-	PageSetLSN(levelstate->pages[0], GistBuildLSN);
+	RelationGetSmgr(state->indexrel);
+	PageSetLSN(levelstate->pages[0], !FileEncryptionEnabled ? GistBuildLSN :
+			   LSNForEncryption(RelationIsPermanent(state->indexrel)));
 	PageSetChecksumInplace(levelstate->pages[0], GIST_ROOT_BLKNO);
 	smgrwrite(RelationGetSmgr(state->indexrel), MAIN_FORKNUM, GIST_ROOT_BLKNO,
 			  levelstate->pages[0], true);
@@ -655,7 +660,8 @@ gist_indexsortbuild_flush_ready_pages(GISTBuildState *state)
 		if (blkno != state->pages_written)
 			elog(ERROR, "unexpected block number to flush GiST sorting build");
 
-		PageSetLSN(page, GistBuildLSN);
+		PageSetLSN(page, !FileEncryptionEnabled ? GistBuildLSN :
+				   LSNForEncryption(RelationIsPermanent(state->indexrel)));
 		PageSetChecksumInplace(page, blkno);
 		smgrextend(RelationGetSmgr(state->indexrel), MAIN_FORKNUM, blkno, page,
 				   true);
diff --git a/src/backend/access/gist/gistvacuum.c b/src/backend/access/gist/gistvacuum.c
index 0aa6e58a62..35265ae0e7 100644
--- a/src/backend/access/gist/gistvacuum.c
+++ b/src/backend/access/gist/gistvacuum.c
@@ -24,6 +24,8 @@
 #include "storage/lmgr.h"
 #include "utils/memutils.h"
 
+extern XLogRecPtr LSNForEncryption(bool use_wal_lsn);
+
 /* Working state needed by gistbulkdelete */
 typedef struct
 {
@@ -180,6 +182,8 @@ gistvacuumscan(IndexVacuumInfo *info, IndexBulkDeleteResult *stats,
 	vstate.callback_state = callback_state;
 	if (RelationNeedsWAL(rel))
 		vstate.startNSN = GetInsertRecPtr();
+	else if (FileEncryptionEnabled)
+		vstate.startNSN = LSNForEncryption(RelationIsPermanent(rel));
 	else
 		vstate.startNSN = gistGetFakeLSN(rel);
 
@@ -359,6 +363,8 @@ restart:
 		 */
 		if (ntodelete > 0)
 		{
+			XLogRecPtr	recptr;
+
 			START_CRIT_SECTION();
 
 			MarkBufferDirty(buffer);
@@ -367,16 +373,15 @@ restart:
 			GistMarkTuplesDeleted(page);
 
 			if (RelationNeedsWAL(rel))
-			{
-				XLogRecPtr	recptr;
-
 				recptr = gistXLogUpdate(buffer,
 										todelete, ntodelete,
 										NULL, 0, InvalidBuffer);
-				PageSetLSN(page, recptr);
-			}
+			else if (FileEncryptionEnabled)
+				recptr = LSNForEncryption(RelationIsPermanent(rel));
 			else
-				PageSetLSN(page, gistGetFakeLSN(rel));
+				recptr = gistGetFakeLSN(rel);
+
+			PageSetLSN(page, recptr);
 
 			END_CRIT_SECTION();
 
@@ -663,8 +668,11 @@ gistdeletepage(IndexVacuumInfo *info, IndexBulkDeleteResult *stats,
 
 	if (RelationNeedsWAL(info->index))
 		recptr = gistXLogPageDelete(leafBuffer, txid, parentBuffer, downlink);
+	else if (FileEncryptionEnabled)
+		recptr = LSNForEncryption(RelationIsPermanent(info->index));
 	else
 		recptr = gistGetFakeLSN(info->index);
+
 	PageSetLSN(parentPage, recptr);
 	PageSetLSN(leafPage, recptr);
 
-- 
2.31.1

