From 7ec86c54dc032c1e66da53e8d5fda8b53255cc2d Mon Sep 17 00:00:00 2001
From: Peipei Yin <yinpeipei0426@gmail.com>
Date: Wed, 12 Aug 2026 09:52:31 -0700
Subject: [PATCH] Use smgrzeroextend() for zero-filled relation extension

Replace memset()+smgrextend() patterns that extended relations with
all-zero pages. smgrzeroextend() can extend multiple blocks in one call
and uses mdzeroextend() underneath, which may use posix_fallocate() or
FileZero() instead of relying on sparse-file hole semantics.

Update RelationCopyStorageUsingBuffer() to zero-extend the destination
fork before copying, smgr_bulk_flush() to fill non-sequential write
gaps in one call, and segment padding in _mdfd_getseg() to use
mdzeroextend() when opening a new segment leaves the previous one
short of RELSEG_SIZE.
---
 src/backend/storage/buffer/bufmgr.c   |  6 ++----
 src/backend/storage/smgr/bulk_write.c | 16 +++++++---------
 src/backend/storage/smgr/md.c         | 11 ++++-------
 3 files changed, 13 insertions(+), 20 deletions(-)

diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index 169829eb020..729b65fcac5 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -5379,7 +5379,6 @@ RelationCopyStorageUsingBuffer(RelFileLocator srclocator,
 	bool		use_wal;
 	BlockNumber nblocks;
 	BlockNumber blkno;
-	PGIOAlignedBlock buf;
 	BufferAccessStrategy bstrategy_src;
 	BufferAccessStrategy bstrategy_dst;
 	BlockRangeReadStreamPrivate p;
@@ -5405,9 +5404,8 @@ RelationCopyStorageUsingBuffer(RelFileLocator srclocator,
 	 * Bulk extend the destination relation of the same size as the source
 	 * relation before starting to copy block by block.
 	 */
-	memset(buf.data, 0, BLCKSZ);
-	smgrextend(smgropen(dstlocator, INVALID_PROC_NUMBER), forkNum, nblocks - 1,
-			   buf.data, true);
+	smgrzeroextend(smgropen(dstlocator, INVALID_PROC_NUMBER), forkNum, 0,
+				   nblocks, true);
 
 	/* This is a bulk operation, so use buffer access strategies. */
 	bstrategy_src = GetAccessStrategy(BAS_BULKREAD);
diff --git a/src/backend/storage/smgr/bulk_write.c b/src/backend/storage/smgr/bulk_write.c
index f3c24082a69..a7f27fb41d3 100644
--- a/src/backend/storage/smgr/bulk_write.c
+++ b/src/backend/storage/smgr/bulk_write.c
@@ -46,8 +46,6 @@
 
 #define MAX_PENDING_WRITES XLR_MAX_BLOCK_ID
 
-static const PGIOAlignedBlock zero_buffer = {0};	/* worth BLCKSZ */
-
 typedef struct PendingWrite
 {
 	BulkWriteBuffer buf;
@@ -290,14 +288,14 @@ smgr_bulk_flush(BulkWriteState *bulkstate)
 			 * space will read as zeroes anyway), but it should help to avoid
 			 * fragmentation.  The dummy pages aren't WAL-logged though.
 			 */
-			while (blkno > bulkstate->relsize)
+			if (blkno > bulkstate->relsize)
 			{
-				/* don't set checksum for all-zero page */
-				smgrextend(bulkstate->smgr, bulkstate->forknum,
-						   bulkstate->relsize,
-						   &zero_buffer,
-						   true);
-				bulkstate->relsize++;
+				/* don't set checksum for all-zero pages */
+				smgrzeroextend(bulkstate->smgr, bulkstate->forknum,
+							   bulkstate->relsize,
+							   blkno - bulkstate->relsize,
+							   true);
+				bulkstate->relsize = blkno;
 			}
 
 			smgrextend(bulkstate->smgr, bulkstate->forknum, blkno, page, true);
diff --git a/src/backend/storage/smgr/md.c b/src/backend/storage/smgr/md.c
index 9f96d9cbbfc..216c5a6846e 100644
--- a/src/backend/storage/smgr/md.c
+++ b/src/backend/storage/smgr/md.c
@@ -1825,13 +1825,10 @@ _mdfd_getseg(SMgrRelation reln, ForkNumber forknum, BlockNumber blkno,
 			 */
 			if (nblocks < ((BlockNumber) RELSEG_SIZE))
 			{
-				char	   *zerobuf = palloc_aligned(BLCKSZ, PG_IO_ALIGN_SIZE,
-													 MCXT_ALLOC_ZERO);
-
-				mdextend(reln, forknum,
-						 nextsegno * ((BlockNumber) RELSEG_SIZE) - 1,
-						 zerobuf, skipFsync);
-				pfree(zerobuf);
+				mdzeroextend(reln, forknum,
+							 (nextsegno - 1) * ((BlockNumber) RELSEG_SIZE) + nblocks,
+							 RELSEG_SIZE - nblocks,
+							 skipFsync);
 			}
 			flags = O_CREAT;
 		}
-- 
2.50.1 (Apple Git-155)

