diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c index a5003c3b922..9073a850e8b 100644 --- a/src/backend/access/transam/xlogutils.c +++ b/src/backend/access/transam/xlogutils.c @@ -368,6 +368,15 @@ XLogReadBufferForRedoExtended(XLogReaderState *record, MarkBufferDirty(*buf); + /* + * At the end of crash recovery the init forks of unlogged relations + * are copied, without going through shared buffers. So we need to + * force the on-disk state of init forks to always be in sync with the + * state in shared buffers. + */ + if (forknum == INIT_FORKNUM) + FlushOneBuffer(*buf); + return BLK_RESTORED; } else diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c index 63188a3932e..b32543b1d56 100644 --- a/src/backend/storage/buffer/bufmgr.c +++ b/src/backend/storage/buffer/bufmgr.c @@ -2988,6 +2988,27 @@ FlushDatabaseBuffers(Oid dbid) } } +/* + * Flush a previously, shared or exclusively, locked and pinned buffer to the + * OS. + */ +void +FlushOneBuffer(Buffer buffer) +{ + BufferDesc *bufHdr; + + /* currently not needed, but no fundamental reason not to support */ + Assert(!BufferIsLocal(buffer)); + + Assert(BufferIsPinned(buffer)); + + bufHdr = GetBufferDescriptor(buffer - 1); + + LWLockHeldByMe(bufHdr->content_lock); + + FlushBuffer(bufHdr, NULL); +} + /* * ReleaseBuffer -- release the pin on a buffer */ diff --git a/src/include/storage/bufmgr.h b/src/include/storage/bufmgr.h index 0f59201bf5b..09b2b1170fa 100644 --- a/src/include/storage/bufmgr.h +++ b/src/include/storage/bufmgr.h @@ -176,6 +176,7 @@ extern void CheckPointBuffers(int flags); extern BlockNumber BufferGetBlockNumber(Buffer buffer); extern BlockNumber RelationGetNumberOfBlocksInFork(Relation relation, ForkNumber forkNum); +extern void FlushOneBuffer(Buffer buffer); extern void FlushRelationBuffers(Relation rel); extern void FlushDatabaseBuffers(Oid dbid); extern void DropRelFileNodeBuffers(RelFileNodeBackend rnode,