From 0e82863c3750e0f8019709c31695a80cb21a37c3 Mon Sep 17 00:00:00 2001
From: Jingtang Zhang <mrdrivingduck@gmail.com>
Date: Wed, 9 Sep 2026 11:38:03 +0800
Subject: [PATCH v2] Use maintenance_io_concurrency for parallel index builds.

Mark parallel index build scans as maintenance work so their heap read
streams use maintenance_io_concurrency instead of
effective_io_concurrency. Apply this to B-tree, BRIN, and GIN parallel
builds while preserving the existing sequential and batching behavior.
---
 src/backend/access/brin/brin.c      | 2 +-
 src/backend/access/gin/gininsert.c  | 2 +-
 src/backend/access/heap/heapam.c    | 7 +++++--
 src/backend/access/nbtree/nbtsort.c | 2 +-
 src/include/access/tableam.h        | 3 +++
 5 files changed, 11 insertions(+), 5 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 5059da8dce7..b6f3f87d768 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -2845,7 +2845,7 @@ _brin_parallel_scan_and_build(BrinBuildState *state,
 
 	scan = table_beginscan_parallel(heap,
 									ParallelTableScanFromBrinShared(brinshared),
-									SO_NONE);
+									SO_MAINTENANCE);
 
 	reltuples = table_index_build_scan(heap, index, indexInfo, true, true,
 									   brinbuildCallbackParallel, state, scan);
diff --git a/src/backend/access/gin/gininsert.c b/src/backend/access/gin/gininsert.c
index 37f689a2cac..07b5ca82167 100644
--- a/src/backend/access/gin/gininsert.c
+++ b/src/backend/access/gin/gininsert.c
@@ -2066,7 +2066,7 @@ _gin_parallel_scan_and_build(GinBuildState *state,
 
 	scan = table_beginscan_parallel(heap,
 									ParallelTableScanFromGinBuildShared(ginshared),
-									SO_NONE);
+									SO_MAINTENANCE);
 
 	reltuples = table_index_build_scan(heap, index, indexInfo, true, progress,
 									   ginBuildCallbackParallel, state, scan);
diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 72d6541734c..1bb5d6afa64 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -1281,6 +1281,10 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 		scan->rs_base.rs_flags & SO_TYPE_TIDRANGESCAN)
 	{
 		ReadStreamBlockNumberCB cb;
+		int			stream_flags = READ_STREAM_SEQUENTIAL | READ_STREAM_USE_BATCHING;
+
+		if (scan->rs_base.rs_flags & SO_MAINTENANCE)
+			stream_flags |= READ_STREAM_MAINTENANCE;
 
 		if (scan->rs_base.rs_parallel)
 			cb = heap_scan_stream_read_next_parallel;
@@ -1294,8 +1298,7 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 		 * - in the parallel case, only spinlocks and atomics are used
 		 * ---
 		 */
-		scan->rs_read_stream = read_stream_begin_relation(READ_STREAM_SEQUENTIAL |
-														  READ_STREAM_USE_BATCHING,
+		scan->rs_read_stream = read_stream_begin_relation(stream_flags,
 														  scan->rs_strategy,
 														  scan->rs_base.rs_rd,
 														  MAIN_FORKNUM,
diff --git a/src/backend/access/nbtree/nbtsort.c b/src/backend/access/nbtree/nbtsort.c
index 756dfa3dcf4..ff5ed01718c 100644
--- a/src/backend/access/nbtree/nbtsort.c
+++ b/src/backend/access/nbtree/nbtsort.c
@@ -1929,7 +1929,7 @@ _bt_parallel_scan_and_sort(BTSpool *btspool, BTSpool *btspool2,
 	indexInfo->ii_Concurrent = btshared->isconcurrent;
 	scan = table_beginscan_parallel(btspool->heap,
 									ParallelTableScanFromBTShared(btshared),
-									SO_NONE);
+									SO_MAINTENANCE);
 	reltuples = table_index_build_scan(btspool->heap, btspool->index, indexInfo,
 									   true, progress, _bt_build_callback,
 									   &buildstate, scan);
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index ff03a2b816f..31f49814433 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -72,6 +72,9 @@ typedef enum ScanOptions
 
 	/* collect scan instrumentation */
 	SO_SCAN_INSTRUMENT = 1 << 11,
+
+	/* use maintenance I/O concurrency */
+	SO_MAINTENANCE = 1 << 12,
 }			ScanOptions;
 
 /*
-- 
2.50.1 (Apple Git-155)

