summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane2022-08-06 15:50:23 +0000
committerTom Lane2022-08-06 15:50:23 +0000
commit811203d4aff505c414e4a9e8c57ea6bb3edfe92e (patch)
tree226e9b4683b84d60b06b0ae60e3c4929b1fe6820
parent6390bc740f902557cad40106708a5d40c6e3389e (diff)
Fix data-corruption hazard in WAL-logged CREATE DATABASE.
RelationCopyStorageUsingBuffer thought it could skip copying empty pages, but of course that does not work at all, because subsequent blocks will be out of place. Also fix it to acquire share lock on the source buffer. It *might* be safe to not do that, but it's not very certain, and I don't think this code deserves any benefit of the doubt. Dilip Kumar, per complaint from me Discussion: https://postgr.es/m/3679800.1659654066@sss.pgh.pa.us
-rw-r--r--src/backend/storage/buffer/bufmgr.c10
1 files changed, 3 insertions, 7 deletions
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index c532ca716d1..8aabf5991b0 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -3742,23 +3742,19 @@ RelationCopyStorageUsingBuffer(Relation src, Relation dst, ForkNumber forkNum,
srcBuf = ReadBufferWithoutRelcache(src->rd_node, forkNum, blkno,
RBM_NORMAL, bstrategy_src,
permanent);
+ LockBuffer(srcBuf, BUFFER_LOCK_SHARE);
srcPage = BufferGetPage(srcBuf);
- if (PageIsNew(srcPage) || PageIsEmpty(srcPage))
- {
- ReleaseBuffer(srcBuf);
- continue;
- }
/* Use P_NEW to extend the destination relation. */
dstBuf = ReadBufferWithoutRelcache(dst->rd_node, forkNum, P_NEW,
RBM_NORMAL, bstrategy_dst,
permanent);
LockBuffer(dstBuf, BUFFER_LOCK_EXCLUSIVE);
+ dstPage = BufferGetPage(dstBuf);
START_CRIT_SECTION();
/* Copy page data from the source to the destination. */
- dstPage = BufferGetPage(dstBuf);
memcpy(dstPage, srcPage, BLCKSZ);
MarkBufferDirty(dstBuf);
@@ -3769,7 +3765,7 @@ RelationCopyStorageUsingBuffer(Relation src, Relation dst, ForkNumber forkNum,
END_CRIT_SECTION();
UnlockReleaseBuffer(dstBuf);
- ReleaseBuffer(srcBuf);
+ UnlockReleaseBuffer(srcBuf);
}
}