diff --git a/contrib/bloom/blinsert.c b/contrib/bloom/blinsert.c index b42b9e6c41f..b90145148d4 100644 --- a/contrib/bloom/blinsert.c +++ b/contrib/bloom/blinsert.c @@ -129,7 +129,7 @@ blbuild(Relation heap, Relation index, IndexInfo *indexInfo) RelationGetRelationName(index)); /* Initialize the meta page */ - BloomInitMetapage(index); + BloomInitMetapage(index, MAIN_FORKNUM); /* Initialize the bloom build state */ memset(&buildstate, 0, sizeof(buildstate)); @@ -163,31 +163,8 @@ blbuild(Relation heap, Relation index, IndexInfo *indexInfo) void blbuildempty(Relation index) { - Page metapage; - - /* Construct metapage. */ - metapage = (Page) palloc_aligned(BLCKSZ, PG_IO_ALIGN_SIZE, 0); - BloomFillMetapage(index, metapage); - - /* - * Write the page and log it. It might seem that an immediate sync would - * be sufficient to guarantee that the file exists on disk, but recovery - * itself might remove it while replaying, for example, an - * XLOG_DBASE_CREATE* or XLOG_TBLSPC_CREATE record. Therefore, we need - * this even when wal_level=minimal. - */ - PageSetChecksumInplace(metapage, BLOOM_METAPAGE_BLKNO); - smgrwrite(RelationGetSmgr(index), INIT_FORKNUM, BLOOM_METAPAGE_BLKNO, - metapage, true); - log_newpage(&(RelationGetSmgr(index))->smgr_rlocator.locator, INIT_FORKNUM, - BLOOM_METAPAGE_BLKNO, metapage, true); - - /* - * An immediate sync is required even if we xlog'd the page, because the - * write did not go through shared_buffers and therefore a concurrent - * checkpoint may have moved the redo pointer past our xlog record. - */ - smgrimmedsync(RelationGetSmgr(index), INIT_FORKNUM); + /* Initialize the meta page */ + BloomInitMetapage(index, INIT_FORKNUM); } /* diff --git a/contrib/bloom/bloom.h b/contrib/bloom/bloom.h index efdf9415d15..330811ec608 100644 --- a/contrib/bloom/bloom.h +++ b/contrib/bloom/bloom.h @@ -177,7 +177,7 @@ typedef BloomScanOpaqueData *BloomScanOpaque; /* blutils.c */ extern void initBloomState(BloomState *state, Relation index); extern void BloomFillMetapage(Relation index, Page metaPage); -extern void BloomInitMetapage(Relation index); +extern void BloomInitMetapage(Relation index, ForkNumber forknum); extern void BloomInitPage(Page page, uint16 flags); extern Buffer BloomNewBuffer(Relation index); extern void signValue(BloomState *state, BloomSignatureWord *sign, Datum value, int attno); diff --git a/contrib/bloom/blutils.c b/contrib/bloom/blutils.c index a017d58bbe4..f23fbb1d9e0 100644 --- a/contrib/bloom/blutils.c +++ b/contrib/bloom/blutils.c @@ -443,7 +443,7 @@ BloomFillMetapage(Relation index, Page metaPage) * Initialize metapage for bloom index. */ void -BloomInitMetapage(Relation index) +BloomInitMetapage(Relation index, ForkNumber forknum) { Buffer metaBuffer; Page metaPage; @@ -451,9 +451,11 @@ BloomInitMetapage(Relation index) /* * Make a new page; since it is first page it should be associated with - * block number 0 (BLOOM_METAPAGE_BLKNO). + * block number 0 (BLOOM_METAPAGE_BLKNO). No need to hold the extension + * lock because there cannot be concurrent inserters yet. */ - metaBuffer = BloomNewBuffer(index); + metaBuffer = ReadBufferExtended(index, forknum, P_NEW, RBM_NORMAL, NULL); + LockBuffer(metaBuffer, BUFFER_LOCK_EXCLUSIVE); Assert(BufferGetBlockNumber(metaBuffer) == BLOOM_METAPAGE_BLKNO); /* Initialize contents of meta page */ diff --git a/src/backend/access/nbtree/nbtree.c b/src/backend/access/nbtree/nbtree.c index 4553aaee531..ad07b80f758 100644 --- a/src/backend/access/nbtree/nbtree.c +++ b/src/backend/access/nbtree/nbtree.c @@ -151,31 +151,32 @@ bthandler(PG_FUNCTION_ARGS) void btbuildempty(Relation index) { + Buffer metabuf; Page metapage; - /* Construct metapage. */ - metapage = (Page) palloc_aligned(BLCKSZ, PG_IO_ALIGN_SIZE, 0); + /* + * Initalize the metapage. + * + * Regular index build bypasses the buffer manager and uses smgr functions + * directly, with an smgrimmedsync() call at the end. That makes sense + * when the index is large, but for an empty index, it's better to use the + * buffer cache to avoid the smgrimmedsync(). + */ + metabuf = ReadBufferExtended(index, INIT_FORKNUM, P_NEW, RBM_NORMAL, NULL); + Assert(BufferGetBlockNumber(metabuf) == BTREE_METAPAGE); + _bt_lockbuf(index, metabuf, BT_WRITE); + + START_CRIT_SECTION(); + + metapage = BufferGetPage(metabuf); _bt_initmetapage(metapage, P_NONE, 0, _bt_allequalimage(index, false)); + MarkBufferDirty(metabuf); + log_newpage_buffer(metabuf, true); - /* - * Write the page and log it. It might seem that an immediate sync would - * be sufficient to guarantee that the file exists on disk, but recovery - * itself might remove it while replaying, for example, an - * XLOG_DBASE_CREATE* or XLOG_TBLSPC_CREATE record. Therefore, we need - * this even when wal_level=minimal. - */ - PageSetChecksumInplace(metapage, BTREE_METAPAGE); - smgrwrite(RelationGetSmgr(index), INIT_FORKNUM, BTREE_METAPAGE, - metapage, true); - log_newpage(&RelationGetSmgr(index)->smgr_rlocator.locator, INIT_FORKNUM, - BTREE_METAPAGE, metapage, true); + END_CRIT_SECTION(); - /* - * An immediate sync is required even if we xlog'd the page, because the - * write did not go through shared_buffers and therefore a concurrent - * checkpoint may have moved the redo pointer past our xlog record. - */ - smgrimmedsync(RelationGetSmgr(index), INIT_FORKNUM); + _bt_unlockbuf(index, metabuf); + ReleaseBuffer(metabuf); } /* diff --git a/src/backend/access/spgist/spginsert.c b/src/backend/access/spgist/spginsert.c index 72d2e1551cd..4443f1918df 100644 --- a/src/backend/access/spgist/spginsert.c +++ b/src/backend/access/spgist/spginsert.c @@ -155,49 +155,42 @@ spgbuild(Relation heap, Relation index, IndexInfo *indexInfo) void spgbuildempty(Relation index) { - Page page; - - /* Construct metapage. */ - page = (Page) palloc_aligned(BLCKSZ, PG_IO_ALIGN_SIZE, 0); - SpGistInitMetapage(page); + Buffer metabuffer, + rootbuffer, + nullbuffer; /* - * Write the page and log it unconditionally. This is important - * particularly for indexes created on tablespaces and databases whose - * creation happened after the last redo pointer as recovery removes any - * of their existing content when the corresponding create records are - * replayed. + * Initialize the meta page and root pages */ - PageSetChecksumInplace(page, SPGIST_METAPAGE_BLKNO); - smgrwrite(RelationGetSmgr(index), INIT_FORKNUM, SPGIST_METAPAGE_BLKNO, - page, true); - log_newpage(&(RelationGetSmgr(index))->smgr_rlocator.locator, INIT_FORKNUM, - SPGIST_METAPAGE_BLKNO, page, true); + metabuffer = ReadBufferExtended(index, INIT_FORKNUM, P_NEW, RBM_NORMAL, NULL); + LockBuffer(metabuffer, BUFFER_LOCK_EXCLUSIVE); + rootbuffer = ReadBufferExtended(index, INIT_FORKNUM, P_NEW, RBM_NORMAL, NULL); + LockBuffer(rootbuffer, BUFFER_LOCK_EXCLUSIVE); + nullbuffer = ReadBufferExtended(index, INIT_FORKNUM, P_NEW, RBM_NORMAL, NULL); + LockBuffer(nullbuffer, BUFFER_LOCK_EXCLUSIVE); - /* Likewise for the root page. */ - SpGistInitPage(page, SPGIST_LEAF); + Assert(BufferGetBlockNumber(metabuffer) == SPGIST_METAPAGE_BLKNO); + Assert(BufferGetBlockNumber(rootbuffer) == SPGIST_ROOT_BLKNO); + Assert(BufferGetBlockNumber(nullbuffer) == SPGIST_NULL_BLKNO); - PageSetChecksumInplace(page, SPGIST_ROOT_BLKNO); - smgrwrite(RelationGetSmgr(index), INIT_FORKNUM, SPGIST_ROOT_BLKNO, - page, true); - log_newpage(&(RelationGetSmgr(index))->smgr_rlocator.locator, INIT_FORKNUM, - SPGIST_ROOT_BLKNO, page, true); + START_CRIT_SECTION(); - /* Likewise for the null-tuples root page. */ - SpGistInitPage(page, SPGIST_LEAF | SPGIST_NULLS); + SpGistInitMetapage(BufferGetPage(metabuffer)); + MarkBufferDirty(metabuffer); + SpGistInitBuffer(rootbuffer, SPGIST_LEAF); + MarkBufferDirty(rootbuffer); + SpGistInitBuffer(nullbuffer, SPGIST_LEAF | SPGIST_NULLS); + MarkBufferDirty(nullbuffer); - PageSetChecksumInplace(page, SPGIST_NULL_BLKNO); - smgrwrite(RelationGetSmgr(index), INIT_FORKNUM, SPGIST_NULL_BLKNO, - page, true); - log_newpage(&(RelationGetSmgr(index))->smgr_rlocator.locator, INIT_FORKNUM, - SPGIST_NULL_BLKNO, page, true); + log_newpage_buffer(metabuffer, true); + log_newpage_buffer(rootbuffer, true); + log_newpage_buffer(nullbuffer, true); - /* - * An immediate sync is required even if we xlog'd the pages, because the - * writes did not go through shared buffers and therefore a concurrent - * checkpoint may have moved the redo pointer past our xlog record. - */ - smgrimmedsync(RelationGetSmgr(index), INIT_FORKNUM); + END_CRIT_SECTION(); + + UnlockReleaseBuffer(metabuffer); + UnlockReleaseBuffer(rootbuffer); + UnlockReleaseBuffer(nullbuffer); } /*