From cf44ee614d4c44a95fa3279ffceb626bc29a46d1 Mon Sep 17 00:00:00 2001 From: Peipei Yin Date: Wed, 12 Aug 2026 09:52:31 -0700 Subject: [PATCH v2] Use smgrzeroextend() in a few more places. Previously, the bulk write path (smgr_bulk_flush()), the database copy (RelationCopyStorageUsingBuffer()) and the segment padding in SMGR (_mdfd_getseg()) each kept a zero-filled buffer of their own and passed it to smgrextend(), or mdextend() inside SMGR, one block per call. The bulk write path did that in a loop, to fill the gap left by a write that was not sequential. This commit changes them to use smgrzeroextend() (added by commit 4d330a61bb19), which is meant for exactly this and can extend several blocks in one call. The bulk write path now fills a whole gap at once. Note that the database copy and the segment padding still zero-extend only the last block as they did before. Zero-extending the whole range instead would regress CREATE DATABASE, both in bytes written and in execution time, where extension falls back to writing zeros, and would reserve whole segments that the copy overwrites moments later where it can preallocate. Author: Peipei Yin Reviewed-by: Bharath Rupireddy Reviewed-by: shihao zhong Discussion: https://postgr.es/m/CADkZ2Ka8Ky4bEPJu_BA5zZT-6K_bf58uT_zXWMDz-iC4Tqu9cA@mail.gmail.com --- src/backend/storage/buffer/bufmgr.c | 6 ++---- src/backend/storage/smgr/bulk_write.c | 16 +++++++--------- src/backend/storage/smgr/md.c | 10 +++------- 3 files changed, 12 insertions(+), 20 deletions(-) diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c index 5c82865a084..2f466344876 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, + nblocks - 1, 1, 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 780c88c0630..0687c800d80 100644 --- a/src/backend/storage/smgr/md.c +++ b/src/backend/storage/smgr/md.c @@ -1823,13 +1823,9 @@ _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 * ((BlockNumber) RELSEG_SIZE) - 1, + 1, skipFsync); } flags = O_CREAT; } -- 2.47.3