From b6603e35147c4bbe3337280222e6243524b0110e Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Sun, 31 Dec 2023 09:47:18 -0500
Subject: [PATCH v2 5/6] VacSkipState saves reference to LVRelState

The streaming read interface can only give pgsr_next callbacks access to
two pieces of private data. As such, move a reference to the LVRelState
into the VacSkipState.

This is a separate commit (as opposed to as part of the commit
introducing VacSkipState) because it is required for using the streaming
read interface but not a natural change on its own. VacSkipState is per
block and the LVRelState is referenced for the whole relation vacuum.
---
 src/backend/access/heap/vacuumlazy.c | 35 +++++++++++++++-------------
 1 file changed, 19 insertions(+), 16 deletions(-)

diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c
index 42da4ac64f8..1b64b9988de 100644
--- a/src/backend/access/heap/vacuumlazy.c
+++ b/src/backend/access/heap/vacuumlazy.c
@@ -250,11 +250,13 @@ typedef struct VacSkipState
 	Buffer		vmbuffer;
 	/* Next unskippable block's visibility status */
 	bool		next_unskippable_allvis;
+	/* reference to whole relation vac state */
+	LVRelState *vacrel;
 } VacSkipState;
 
 /* non-export function prototypes */
 static void lazy_scan_heap(LVRelState *vacrel);
-static BlockNumber lazy_scan_skip(LVRelState *vacrel, VacSkipState *vacskip,
+static BlockNumber lazy_scan_skip(VacSkipState *vacskip,
 								  BlockNumber blkno,
 								  bool *all_visible_according_to_vm);
 static bool lazy_scan_new_or_empty(LVRelState *vacrel, Buffer buf,
@@ -844,7 +846,8 @@ lazy_scan_heap(LVRelState *vacrel)
 	BlockNumber blkno = InvalidBlockNumber;
 	VacSkipState vacskip = {
 		.next_unskippable_block = InvalidBlockNumber,
-		.vmbuffer = InvalidBuffer
+		.vmbuffer = InvalidBuffer,
+		.vacrel = vacrel
 	};
 	VacDeadItems *dead_items = vacrel->dead_items;
 	const int	initprog_index[] = {
@@ -866,7 +869,7 @@ lazy_scan_heap(LVRelState *vacrel)
 		Page		page;
 		LVPagePruneState prunestate;
 
-		blkno = lazy_scan_skip(vacrel, &vacskip, blkno + 1,
+		blkno = lazy_scan_skip(&vacskip, blkno + 1,
 							   &all_visible_according_to_vm);
 
 		if (blkno == InvalidBlockNumber)
@@ -1299,9 +1302,10 @@ lazy_scan_heap(LVRelState *vacrel)
  * lazy_scan_skip() returns the next block for vacuum to process and sets its
  * visibility status in the output parameter, all_visible_according_to_vm.
  *
- * vacrel is an in/out parameter here; vacuum options and information about the
- * relation are read and vacrel->skippedallvis is set to ensure we don't
- * advance relfrozenxid when we have skipped vacuuming all visible blocks.
+ * vacskip->vacrel is an in/out parameter here; vacuum options and information
+ * about the relation are read and vacrel->skippedallvis is set to ensure we
+ * don't advance relfrozenxid when we have skipped vacuuming all visible
+ * blocks.
  *
  * vacskip->vmbuffer will contain the block from the VM containing visibility
  * information for the next unskippable heap block. We may end up needed a
@@ -1318,21 +1322,20 @@ lazy_scan_heap(LVRelState *vacrel)
  * choice to skip such a range is actually made, making everything safe.)
  */
 static BlockNumber
-lazy_scan_skip(LVRelState *vacrel, VacSkipState *vacskip,
-			   BlockNumber next_block,
-			   bool *all_visible_according_to_vm)
+lazy_scan_skip(VacSkipState *vacskip,
+			   BlockNumber next_block, bool *all_visible_according_to_vm)
 {
 	bool		skipsallvis = false;
 
-	if (next_block >= vacrel->rel_pages)
+	if (next_block >= vacskip->vacrel->rel_pages)
 		return InvalidBlockNumber;
 
 	if (vacskip->next_unskippable_block == InvalidBlockNumber ||
 		next_block > vacskip->next_unskippable_block)
 	{
-		while (++vacskip->next_unskippable_block < vacrel->rel_pages)
+		while (++vacskip->next_unskippable_block < vacskip->vacrel->rel_pages)
 		{
-			uint8		mapbits = visibilitymap_get_status(vacrel->rel,
+			uint8		mapbits = visibilitymap_get_status(vacskip->vacrel->rel,
 														   vacskip->next_unskippable_block,
 														   &vacskip->vmbuffer);
 
@@ -1356,11 +1359,11 @@ lazy_scan_skip(LVRelState *vacrel, VacSkipState *vacskip,
 			 * Implement this by always treating the last block as unsafe to
 			 * skip.
 			 */
-			if (vacskip->next_unskippable_block == vacrel->rel_pages - 1)
+			if (vacskip->next_unskippable_block == vacskip->vacrel->rel_pages - 1)
 				break;
 
 			/* DISABLE_PAGE_SKIPPING makes all skipping unsafe */
-			if (!vacrel->skipwithvm)
+			if (!vacskip->vacrel->skipwithvm)
 			{
 				/* Caller shouldn't rely on all_visible_according_to_vm */
 				vacskip->next_unskippable_allvis = false;
@@ -1375,7 +1378,7 @@ lazy_scan_skip(LVRelState *vacrel, VacSkipState *vacskip,
 			 */
 			if ((mapbits & VISIBILITYMAP_ALL_FROZEN) == 0)
 			{
-				if (vacrel->aggressive)
+				if (vacskip->vacrel->aggressive)
 					break;
 
 				/*
@@ -1405,7 +1408,7 @@ lazy_scan_skip(LVRelState *vacrel, VacSkipState *vacskip,
 		{
 			next_block = vacskip->next_unskippable_block;
 			if (skipsallvis)
-				vacrel->skippedallvis = true;
+				vacskip->vacrel->skippedallvis = true;
 		}
 	}
 
-- 
2.37.2

