1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-05 07:21:24 +03:00

Sanity-check that a page zeroed by redo routine is marked with WILL_INIT.

There was already a sanity-check in the other direction: if a page was
marked with WILL_INIT, it had to be initialized by the redo routine. It's
not strictly necessary for correctness that a page is marked with WILL_INIT
if it's going to be initialized at redo, but it's a missed optimization if
nothing else.

Fix a few instances of this issue in SP-GiST, where a block in WAL record
was not marked with WILL_INIT, but was in fact always initialized at redo.
We were creating a full-page image of the page unnecessarily in those
cases.

Backpatch to 9.5, where the new WILL_INIT flag was added.
This commit is contained in:
Heikki Linnakangas
2015-07-20 16:02:28 +03:00
parent e52b690cf5
commit eb11de8ff5
2 changed files with 38 additions and 12 deletions

View File

@ -328,6 +328,8 @@ XLogReadBufferForRedoExtended(XLogReaderState *record,
ForkNumber forknum;
BlockNumber blkno;
Page page;
bool zeromode;
bool willinit;
if (!XLogRecGetBlockTag(record, block_id, &rnode, &forknum, &blkno))
{
@ -335,6 +337,17 @@ XLogReadBufferForRedoExtended(XLogReaderState *record,
elog(PANIC, "failed to locate backup block with ID %d", block_id);
}
/*
* Make sure that if the block is marked with WILL_INIT, the caller is
* going to initialize it. And vice versa.
*/
zeromode = (mode == RBM_ZERO_AND_LOCK || mode == RBM_ZERO_AND_CLEANUP_LOCK);
willinit = (record->blocks[block_id].flags & BKPBLOCK_WILL_INIT) != 0;
if (willinit && !zeromode)
elog(PANIC, "block with WILL_INIT flag in WAL record must be zeroed by redo routine");
if (!willinit && zeromode)
elog(PANIC, "block to be initialized in redo routine must be marked with WILL_INIT flag in the WAL record");
/* If it's a full-page image, restore it. */
if (XLogRecHasBlockImage(record, block_id))
{
@ -359,12 +372,6 @@ XLogReadBufferForRedoExtended(XLogReaderState *record,
}
else
{
if ((record->blocks[block_id].flags & BKPBLOCK_WILL_INIT) != 0 &&
mode != RBM_ZERO_AND_LOCK && mode != RBM_ZERO_AND_CLEANUP_LOCK)
{
elog(PANIC, "block with WILL_INIT flag in WAL record must be zeroed by redo routine");
}
*buf = XLogReadBufferExtended(rnode, forknum, blkno, mode);
if (BufferIsValid(*buf))
{