mirror of
https://github.com/postgres/postgres.git
synced 2025-08-18 12:22:09 +03:00
Fix pageinspect failures on hash indexes.
Make every page in a hash index which isn't all-zeroes have a valid special space, so that tools like pageinspect don't error out. Also, make pageinspect cope with all-zeroes pages, because _hash_alloc_buckets can leave behind large numbers of those until they're consumed by splits. Ashutosh Sharma and Robert Haas, reviewed by Amit Kapila. Original trouble report from Jeff Janes. Discussion: http://postgr.es/m/CAMkU=1y6NjKmqbJ8wLMhr=F74WzcMALYWcVFhEpm7i=mV=XsOg@mail.gmail.com
This commit is contained in:
@@ -697,11 +697,20 @@ hash_xlog_squeeze_page(XLogReaderState *record)
|
||||
if (XLogReadBufferForRedo(record, 2, &ovflbuf) == BLK_NEEDS_REDO)
|
||||
{
|
||||
Page ovflpage;
|
||||
HashPageOpaque ovflopaque;
|
||||
|
||||
ovflpage = BufferGetPage(ovflbuf);
|
||||
|
||||
_hash_pageinit(ovflpage, BufferGetPageSize(ovflbuf));
|
||||
|
||||
ovflopaque = (HashPageOpaque) PageGetSpecialPointer(ovflpage);
|
||||
|
||||
ovflopaque->hasho_prevblkno = InvalidBlockNumber;
|
||||
ovflopaque->hasho_nextblkno = InvalidBlockNumber;
|
||||
ovflopaque->hasho_bucket = -1;
|
||||
ovflopaque->hasho_flag = LH_UNUSED_PAGE;
|
||||
ovflopaque->hasho_page_id = HASHO_PAGE_ID;
|
||||
|
||||
PageSetLSN(ovflpage, lsn);
|
||||
MarkBufferDirty(ovflbuf);
|
||||
}
|
||||
|
@@ -590,11 +590,22 @@ _hash_freeovflpage(Relation rel, Buffer bucketbuf, Buffer ovflbuf,
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the freed overflow page. Just zeroing the page won't work,
|
||||
* because WAL replay routines expect pages to be initialized. See
|
||||
* explanation of RBM_NORMAL mode atop XLogReadBufferExtended.
|
||||
* Reinitialize the freed overflow page. Just zeroing the page won't
|
||||
* work, because WAL replay routines expect pages to be initialized. See
|
||||
* explanation of RBM_NORMAL mode atop XLogReadBufferExtended. We are
|
||||
* careful to make the special space valid here so that tools like
|
||||
* pageinspect won't get confused.
|
||||
*/
|
||||
_hash_pageinit(ovflpage, BufferGetPageSize(ovflbuf));
|
||||
|
||||
ovflopaque = (HashPageOpaque) PageGetSpecialPointer(ovflpage);
|
||||
|
||||
ovflopaque->hasho_prevblkno = InvalidBlockNumber;
|
||||
ovflopaque->hasho_nextblkno = InvalidBlockNumber;
|
||||
ovflopaque->hasho_bucket = -1;
|
||||
ovflopaque->hasho_flag = LH_UNUSED_PAGE;
|
||||
ovflopaque->hasho_page_id = HASHO_PAGE_ID;
|
||||
|
||||
MarkBufferDirty(ovflbuf);
|
||||
|
||||
if (BufferIsValid(prevbuf))
|
||||
|
@@ -993,6 +993,7 @@ _hash_alloc_buckets(Relation rel, BlockNumber firstblock, uint32 nblocks)
|
||||
BlockNumber lastblock;
|
||||
char zerobuf[BLCKSZ];
|
||||
Page page;
|
||||
HashPageOpaque ovflopaque;
|
||||
|
||||
lastblock = firstblock + nblocks - 1;
|
||||
|
||||
@@ -1007,10 +1008,19 @@ _hash_alloc_buckets(Relation rel, BlockNumber firstblock, uint32 nblocks)
|
||||
|
||||
/*
|
||||
* Initialize the page. Just zeroing the page won't work; see
|
||||
* _hash_freeovflpage for similar usage.
|
||||
* _hash_freeovflpage for similar usage. We take care to make the
|
||||
* special space valid for the benefit of tools such as pageinspect.
|
||||
*/
|
||||
_hash_pageinit(page, BLCKSZ);
|
||||
|
||||
ovflopaque = (HashPageOpaque) PageGetSpecialPointer(page);
|
||||
|
||||
ovflopaque->hasho_prevblkno = InvalidBlockNumber;
|
||||
ovflopaque->hasho_nextblkno = InvalidBlockNumber;
|
||||
ovflopaque->hasho_bucket = -1;
|
||||
ovflopaque->hasho_flag = LH_UNUSED_PAGE;
|
||||
ovflopaque->hasho_page_id = HASHO_PAGE_ID;
|
||||
|
||||
if (RelationNeedsWAL(rel))
|
||||
log_newpage(&rel->rd_node,
|
||||
MAIN_FORKNUM,
|
||||
|
Reference in New Issue
Block a user