From c774fc30710a7d9af142f75f079759f2275e951e Mon Sep 17 00:00:00 2001
From: Kevin Rocker <me@kevinrocker.com>
Date: Fri, 31 Jul 2026 23:32:17 +0200
Subject: [PATCH v1 1/4] Don't call vacuum_delay_point() while holding a buffer
 lock in GIN.

ginInsertCleanup() called vacuum_delay_point() while still holding a shared
content lock on the current pending-list page.

Every iteration of the loop still passes a vacuum_delay_point() without
a lock: the flush branch unlocks the page before sleeping inside the
ginEntryInsert() loop, and both branches reach a delay after releasing
the buffer and before the next iteration.

This is the same fix commit 2d7f6947293 made in btbulkdelete();
cf. also 8a045f760f6 for the placement rule in GIN's posting-tree vacuum.
---
 src/backend/access/gin/ginfast.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/src/backend/access/gin/ginfast.c b/src/backend/access/gin/ginfast.c
index f50848eb65a..120f0705da0 100644
--- a/src/backend/access/gin/ginfast.c
+++ b/src/backend/access/gin/ginfast.c
@@ -873,6 +873,9 @@ ginInsertCleanup(GinState *ginstate, bool full_clean,
 	 * At the top of this loop, we have pin and lock on the current page of
 	 * the pending list.  However, we'll release that before exiting the loop.
 	 * Note we also have pin but not lock on the metapage.
+	 *
+	 * The vacuum_delay_point() calls below are placed where
+	 * the current page is not locked.
 	 */
 	for (;;)
 	{
@@ -892,8 +895,6 @@ ginInsertCleanup(GinState *ginstate, bool full_clean,
 		 */
 		processPendingPage(&accum, &datums, page, FirstOffsetNumber);
 
-		vacuum_delay_point(false);
-
 		/*
 		 * Is it time to flush memory to disk?	Flush if we are at the end of
 		 * the pending list, or if we have a full row and memory is getting
-- 
2.54.0

