aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2022-08-06 11:50:23 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2022-08-06 11:50:34 -0400
commit692df425b6883dd3edcc15bb984415ef349fafb1 (patch)
tree7823db324c91c658f5e1e3486e3cc4cde4f835ba /src
parent922a8fa098404cbd5c6089e78eca4aebd828f847 (diff)
downloadpostgresql-692df425b6883dd3edcc15bb984415ef349fafb1.tar.gz
postgresql-692df425b6883dd3edcc15bb984415ef349fafb1.zip
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
Diffstat (limited to 'src')
-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 6b30138ab32..8ef0436c521 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -3741,23 +3741,19 @@ RelationCopyStorageUsingBuffer(Relation src, Relation dst, ForkNumber forkNum,
srcBuf = ReadBufferWithoutRelcache(src->rd_locator, 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_locator, 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);
@@ -3768,7 +3764,7 @@ RelationCopyStorageUsingBuffer(Relation src, Relation dst, ForkNumber forkNum,
END_CRIT_SECTION();
UnlockReleaseBuffer(dstBuf);
- ReleaseBuffer(srcBuf);
+ UnlockReleaseBuffer(srcBuf);
}
}