diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c index cb4289bba29..eb8eada27d6 100644 --- a/src/backend/access/heap/heapam.c +++ b/src/backend/access/heap/heapam.c @@ -4941,6 +4941,16 @@ heap_xlog_newpage(XLogRecPtr lsn, XLogRecord *record) } MarkBufferDirty(buffer); + + /* + * 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 (xlrec->forknum == INIT_FORKNUM) + FlushOneBuffer(buffer); + UnlockReleaseBuffer(buffer); } diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c index f9b881ff690..81b9b297724 100644 --- a/src/backend/storage/buffer/bufmgr.c +++ b/src/backend/storage/buffer/bufmgr.c @@ -2396,6 +2396,27 @@ FlushDatabaseBuffers(Oid dbid) } } +/* + * Flush a previously, shared or exclusively, locked and pinned buffer to the + * OS. + */ +void +FlushOneBuffer(Buffer buffer) +{ + volatile BufferDesc *bufHdr; + + /* currently not needed, but no fundamental reason not to support */ + Assert(!BufferIsLocal(buffer)); + + Assert(BufferIsPinned(buffer)); + + bufHdr = &BufferDescriptors[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 4e2bd8866a9..f5bbe965640 100644 --- a/src/include/storage/bufmgr.h +++ b/src/include/storage/bufmgr.h @@ -191,6 +191,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,