Skip to content
Snippets Groups Projects
Commit f06ef2be authored by Heikki Linnakangas's avatar Heikki Linnakangas
Browse files

Fix WAL redo of FSM truncation. We can't call smgrtruncate() during WAL

replay, because it tries to XLogInsert().
parent 6ca1b1cd
No related branches found
No related tags found
No related merge requests found
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/storage/freespace/freespace.c,v 1.62 2008/09/30 14:15:58 tgl Exp $ * $PostgreSQL: pgsql/src/backend/storage/freespace/freespace.c,v 1.63 2008/10/01 08:12:14 heikki Exp $
* *
* *
* NOTES: * NOTES:
...@@ -123,6 +123,8 @@ static int fsm_set_and_search(Relation rel, FSMAddress addr, uint16 slot, ...@@ -123,6 +123,8 @@ static int fsm_set_and_search(Relation rel, FSMAddress addr, uint16 slot,
static BlockNumber fsm_search(Relation rel, uint8 min_cat); static BlockNumber fsm_search(Relation rel, uint8 min_cat);
static uint8 fsm_vacuum_page(Relation rel, FSMAddress addr, bool *eof); static uint8 fsm_vacuum_page(Relation rel, FSMAddress addr, bool *eof);
static void fsm_redo_truncate(xl_fsm_truncate *xlrec);
/******** Public API ********/ /******** Public API ********/
...@@ -281,7 +283,7 @@ FreeSpaceMapTruncateRel(Relation rel, BlockNumber nblocks) ...@@ -281,7 +283,7 @@ FreeSpaceMapTruncateRel(Relation rel, BlockNumber nblocks)
* record, but that's not enough to zero out the last remaining FSM page. * record, but that's not enough to zero out the last remaining FSM page.
* (if we didn't need to zero out anything above, we can skip this) * (if we didn't need to zero out anything above, we can skip this)
*/ */
if (!rel->rd_istemp && !InRecovery && first_removed_slot != 0) if (!rel->rd_istemp && first_removed_slot != 0)
{ {
xl_fsm_truncate xlrec; xl_fsm_truncate xlrec;
XLogRecData rdata; XLogRecData rdata;
...@@ -310,8 +312,8 @@ FreeSpaceMapTruncateRel(Relation rel, BlockNumber nblocks) ...@@ -310,8 +312,8 @@ FreeSpaceMapTruncateRel(Relation rel, BlockNumber nblocks)
* Need to invalidate the relcache entry, because rd_fsm_nblocks_cache * Need to invalidate the relcache entry, because rd_fsm_nblocks_cache
* seen by other backends is no longer valid. * seen by other backends is no longer valid.
*/ */
if (!InRecovery) CacheInvalidateRelcache(rel);
CacheInvalidateRelcache(rel);
rel->rd_fsm_nblocks_cache = new_nfsmblocks; rel->rd_fsm_nblocks_cache = new_nfsmblocks;
} }
...@@ -762,6 +764,43 @@ fsm_vacuum_page(Relation rel, FSMAddress addr, bool *eof_p) ...@@ -762,6 +764,43 @@ fsm_vacuum_page(Relation rel, FSMAddress addr, bool *eof_p)
/****** WAL-logging ******/ /****** WAL-logging ******/
static void
fsm_redo_truncate(xl_fsm_truncate *xlrec)
{
FSMAddress first_removed_address;
uint16 first_removed_slot;
BlockNumber fsmblk;
Buffer buf;
/* Get the location in the FSM of the first removed heap block */
first_removed_address = fsm_get_location(xlrec->nheapblocks,
&first_removed_slot);
fsmblk = fsm_logical_to_physical(first_removed_address);
/*
* Zero out the tail of the last remaining FSM page. We rely on the
* replay of the smgr truncation record to remove completely unused
* pages.
*/
buf = XLogReadBufferWithFork(xlrec->node, FSM_FORKNUM, fsmblk, false);
if (BufferIsValid(buf))
{
fsm_truncate_avail(BufferGetPage(buf), first_removed_slot);
MarkBufferDirty(buf);
UnlockReleaseBuffer(buf);
}
else
{
/*
* The page doesn't exist. Because FSM extensions are not WAL-logged,
* it's normal to have a truncation record for a page that doesn't
* exist. Tell xlogutils.c not to PANIC at the end of recovery
* because of the missing page
*/
XLogTruncateRelation(xlrec->node, FSM_FORKNUM, fsmblk);
}
}
void void
fsm_redo(XLogRecPtr lsn, XLogRecord *record) fsm_redo(XLogRecPtr lsn, XLogRecord *record)
{ {
...@@ -770,15 +809,7 @@ fsm_redo(XLogRecPtr lsn, XLogRecord *record) ...@@ -770,15 +809,7 @@ fsm_redo(XLogRecPtr lsn, XLogRecord *record)
switch (info) switch (info)
{ {
case XLOG_FSM_TRUNCATE: case XLOG_FSM_TRUNCATE:
{ fsm_redo_truncate((xl_fsm_truncate *) XLogRecGetData(record));
xl_fsm_truncate *xlrec;
Relation rel;
xlrec = (xl_fsm_truncate *) XLogRecGetData(record);
rel = CreateFakeRelcacheEntry(xlrec->node);
FreeSpaceMapTruncateRel(rel, xlrec->nheapblocks);
FreeFakeRelcacheEntry(rel);
}
break; break;
default: default:
elog(PANIC, "fsm_redo: unknown op code %u", info); elog(PANIC, "fsm_redo: unknown op code %u", info);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment