From c5edef91b479ddcd99be5fe500f7a10ec1b2ae8d Mon Sep 17 00:00:00 2001
From: reshke <reshke@double.cloud>
Date: Tue, 17 Feb 2026 09:53:27 +0000
Subject: [PATCH v1] Release and unpin buffers after leaving CRIT section in
 GIN.

This patches cleanup a few places in GIN code that
used to release and/or unpin buffers before leaving CRIT
section but not after. The latter is suggested by transam/README.
---
 src/backend/access/gin/gindatapage.c |  4 ++--
 src/backend/access/gin/ginfast.c     | 12 ++++++------
 src/backend/access/gin/gininsert.c   |  3 ++-
 src/backend/access/gin/ginutil.c     |  4 ++--
 src/backend/access/gin/ginvacuum.c   |  6 +++---
 5 files changed, 15 insertions(+), 14 deletions(-)

diff --git a/src/backend/access/gin/gindatapage.c b/src/backend/access/gin/gindatapage.c
index 436e54f2066..c5d7db28077 100644
--- a/src/backend/access/gin/gindatapage.c
+++ b/src/backend/access/gin/gindatapage.c
@@ -1854,10 +1854,10 @@ createPostingTree(Relation index, ItemPointerData *items, uint32 nitems,
 		PageSetLSN(page, recptr);
 	}
 
-	UnlockReleaseBuffer(buffer);
-
 	END_CRIT_SECTION();
 
+	UnlockReleaseBuffer(buffer);
+
 	/* During index build, count the newly-added data page */
 	if (buildStats)
 		buildStats->nDataPages++;
diff --git a/src/backend/access/gin/ginfast.c b/src/backend/access/gin/ginfast.c
index 7a6b177977b..f50848eb65a 100644
--- a/src/backend/access/gin/ginfast.c
+++ b/src/backend/access/gin/ginfast.c
@@ -134,10 +134,10 @@ writeListPage(Relation index, Buffer buffer,
 	/* get free space before releasing buffer */
 	freesize = PageGetExactFreeSpace(page);
 
-	UnlockReleaseBuffer(buffer);
-
 	END_CRIT_SECTION();
 
+	UnlockReleaseBuffer(buffer);
+
 	return freesize;
 }
 
@@ -459,10 +459,10 @@ ginHeapTupleFastInsert(GinState *ginstate, GinTupleCollector *collector)
 	if (metadata->nPendingPages * GIN_PAGE_FREESIZE > cleanupSize * (Size) 1024)
 		needCleanup = true;
 
-	UnlockReleaseBuffer(metabuffer);
-
 	END_CRIT_SECTION();
 
+	UnlockReleaseBuffer(metabuffer);
+
 	/*
 	 * Since it could contend with concurrent cleanup process we cleanup
 	 * pending list not forcibly.
@@ -659,11 +659,11 @@ shiftList(Relation index, Buffer metabuffer, BlockNumber newHead,
 			}
 		}
 
+		END_CRIT_SECTION();
+
 		for (i = 0; i < data.ndeleted; i++)
 			UnlockReleaseBuffer(buffers[i]);
 
-		END_CRIT_SECTION();
-
 		for (i = 0; fill_fsm && i < data.ndeleted; i++)
 			RecordFreeIndexPage(index, freespace[i]);
 
diff --git a/src/backend/access/gin/gininsert.c b/src/backend/access/gin/gininsert.c
index 0d63fb4ba27..c972848b29e 100644
--- a/src/backend/access/gin/gininsert.c
+++ b/src/backend/access/gin/gininsert.c
@@ -652,9 +652,10 @@ ginbuild(Relation heap, Relation index, IndexInfo *indexInfo)
 	MarkBufferDirty(RootBuffer);
 
 
+	END_CRIT_SECTION();
+
 	UnlockReleaseBuffer(MetaBuffer);
 	UnlockReleaseBuffer(RootBuffer);
-	END_CRIT_SECTION();
 
 	/* count the root as first entry page */
 	buildstate.buildStats.nEntryPages++;
diff --git a/src/backend/access/gin/ginutil.c b/src/backend/access/gin/ginutil.c
index d205093e21d..ff927279cc3 100644
--- a/src/backend/access/gin/ginutil.c
+++ b/src/backend/access/gin/ginutil.c
@@ -663,9 +663,9 @@ ginUpdateStats(Relation index, const GinStatsData *stats, bool is_build)
 		PageSetLSN(metapage, recptr);
 	}
 
-	UnlockReleaseBuffer(metabuffer);
-
 	END_CRIT_SECTION();
+
+	UnlockReleaseBuffer(metabuffer);
 }
 
 /*
diff --git a/src/backend/access/gin/ginvacuum.c b/src/backend/access/gin/ginvacuum.c
index 11a6674a10b..c9f143f6c31 100644
--- a/src/backend/access/gin/ginvacuum.c
+++ b/src/backend/access/gin/ginvacuum.c
@@ -224,12 +224,12 @@ ginDeletePage(GinVacuumState *gvs, BlockNumber deleteBlkno, BlockNumber leftBlkn
 		PageSetLSN(BufferGetPage(lBuffer), recptr);
 	}
 
+	END_CRIT_SECTION();
+
 	ReleaseBuffer(pBuffer);
 	ReleaseBuffer(lBuffer);
 	ReleaseBuffer(dBuffer);
 
-	END_CRIT_SECTION();
-
 	gvs->result->pages_newly_deleted++;
 	gvs->result->pages_deleted++;
 }
@@ -654,8 +654,8 @@ ginbulkdelete(IndexVacuumInfo *info, IndexBulkDeleteResult *stats,
 			PageRestoreTempPage(resPage, page);
 			MarkBufferDirty(buffer);
 			xlogVacuumPage(gvs.index, buffer);
-			UnlockReleaseBuffer(buffer);
 			END_CRIT_SECTION();
+			UnlockReleaseBuffer(buffer);
 		}
 		else
 		{
-- 
2.43.0

