diff options
author | Heikki Linnakangas <heikki.linnakangas@iki.fi> | 2015-07-20 16:02:28 +0300 |
---|---|---|
committer | Heikki Linnakangas <heikki.linnakangas@iki.fi> | 2015-07-20 22:34:18 +0300 |
commit | e015c3e51f76a05cc026c8323c51a373172adaa3 (patch) | |
tree | f911b21b86634480e7b815c53f5e6ce92ef09aa7 /src/backend/access/transam/xlogutils.c | |
parent | 869eb8416255da99fe5ba1f6d98e52a41999d30e (diff) | |
download | postgresql-e015c3e51f76a05cc026c8323c51a373172adaa3.tar.gz postgresql-e015c3e51f76a05cc026c8323c51a373172adaa3.zip |
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.
Diffstat (limited to 'src/backend/access/transam/xlogutils.c')
-rw-r--r-- | src/backend/access/transam/xlogutils.c | 19 |
1 files changed, 13 insertions, 6 deletions
diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c index fa98b8294e8..a5003c3b922 100644 --- a/src/backend/access/transam/xlogutils.c +++ b/src/backend/access/transam/xlogutils.c @@ -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)) { |