diff options
author | Alvaro Herrera | 2024-04-03 15:49:44 +0000 |
---|---|---|
committer | Alvaro Herrera | 2024-04-03 15:49:44 +0000 |
commit | be2f0731006300876b008fd78a265471984cbcd9 (patch) | |
tree | 3c8162ab58208f61cd6cd199ceacd3b9fefcdea6 | |
parent | bf1e65080629e2b0ac47ffe245576da96eff8420 (diff) |
Fix zeroing of pg_serial page without SLRU bank lock
Bug in commit 53c2a97a9266: we failed to acquire the correct SLRU bank
lock when iterating to zero-out intermediate pages in predicate.c.
Rewrite the code block so that we follow the locking protocol correctly.
Also update an outdated comment in the same file -- SerialSLRULock
exists no more.
Reported-by: Alexander Lakhin <[email protected]>
Reviewed-by: Dilip Kumar <[email protected]>
Discussion: https://postgr.es/m/[email protected]
-rw-r--r-- | src/backend/storage/lmgr/predicate.c | 19 |
1 files changed, 12 insertions, 7 deletions
diff --git a/src/backend/storage/lmgr/predicate.c b/src/backend/storage/lmgr/predicate.c index 3f378c0099b..d5bbfbd4c6f 100644 --- a/src/backend/storage/lmgr/predicate.c +++ b/src/backend/storage/lmgr/predicate.c @@ -137,7 +137,7 @@ * SerialControlLock * - Protects SerialControlData members * - * SerialSLRULock + * SLRU per-bank locks * - Protects SerialSlruCtl * * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group @@ -908,20 +908,25 @@ SerialAdd(TransactionId xid, SerCommitSeqNo minConflictCommitSeqNo) if (isNewPage) serialControl->headPage = targetPage; - LWLockAcquire(lock, LW_EXCLUSIVE); - if (isNewPage) { - /* Initialize intervening pages. */ - while (firstZeroPage != targetPage) + /* Initialize intervening pages; might involve trading locks */ + for (;;) { - (void) SimpleLruZeroPage(SerialSlruCtl, firstZeroPage); + lock = SimpleLruGetBankLock(SerialSlruCtl, firstZeroPage); + LWLockAcquire(lock, LW_EXCLUSIVE); + slotno = SimpleLruZeroPage(SerialSlruCtl, firstZeroPage); + if (firstZeroPage == targetPage) + break; firstZeroPage = SerialNextPage(firstZeroPage); + LWLockRelease(lock); } - slotno = SimpleLruZeroPage(SerialSlruCtl, targetPage); } else + { + LWLockAcquire(lock, LW_EXCLUSIVE); slotno = SimpleLruReadPage(SerialSlruCtl, targetPage, true, xid); + } SerialValue(slotno, xid) = minConflictCommitSeqNo; SerialSlruCtl->shared->page_dirty[slotno] = true; |