diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c index 88a60aa12af..559970fe67b 100644 --- a/src/backend/access/heap/heapam.c +++ b/src/backend/access/heap/heapam.c @@ -7175,6 +7175,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 0b03f609f52..a70eed23771 100644 --- a/src/backend/storage/buffer/bufmgr.c +++ b/src/backend/storage/buffer/bufmgr.c @@ -2549,6 +2549,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 44a5f642ee1..e28451263ec 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,