mirror of
https://github.com/postgres/postgres.git
synced 2025-07-11 10:01:57 +03:00
Fix zeroing of pg_serial page without SLRU bank lock
Bug in commit 53c2a97a92
: 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 <exclusion@gmail.com>
Reviewed-by: Dilip Kumar <dilipbalaut@gmail.com>
Discussion: https://postgr.es/m/2a25eaf4-a3a4-5fd1-6241-9d7c73142085@gmail.com
This commit is contained in:
@ -137,7 +137,7 @@
|
|||||||
* SerialControlLock
|
* SerialControlLock
|
||||||
* - Protects SerialControlData members
|
* - Protects SerialControlData members
|
||||||
*
|
*
|
||||||
* SerialSLRULock
|
* SLRU per-bank locks
|
||||||
* - Protects SerialSlruCtl
|
* - Protects SerialSlruCtl
|
||||||
*
|
*
|
||||||
* Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
|
||||||
@ -908,20 +908,25 @@ SerialAdd(TransactionId xid, SerCommitSeqNo minConflictCommitSeqNo)
|
|||||||
if (isNewPage)
|
if (isNewPage)
|
||||||
serialControl->headPage = targetPage;
|
serialControl->headPage = targetPage;
|
||||||
|
|
||||||
LWLockAcquire(lock, LW_EXCLUSIVE);
|
|
||||||
|
|
||||||
if (isNewPage)
|
if (isNewPage)
|
||||||
{
|
{
|
||||||
/* Initialize intervening pages. */
|
/* Initialize intervening pages; might involve trading locks */
|
||||||
while (firstZeroPage != targetPage)
|
for (;;)
|
||||||
{
|
{
|
||||||
(void) SimpleLruZeroPage(SerialSlruCtl, firstZeroPage);
|
lock = SimpleLruGetBankLock(SerialSlruCtl, firstZeroPage);
|
||||||
|
LWLockAcquire(lock, LW_EXCLUSIVE);
|
||||||
|
slotno = SimpleLruZeroPage(SerialSlruCtl, firstZeroPage);
|
||||||
|
if (firstZeroPage == targetPage)
|
||||||
|
break;
|
||||||
firstZeroPage = SerialNextPage(firstZeroPage);
|
firstZeroPage = SerialNextPage(firstZeroPage);
|
||||||
|
LWLockRelease(lock);
|
||||||
}
|
}
|
||||||
slotno = SimpleLruZeroPage(SerialSlruCtl, targetPage);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
LWLockAcquire(lock, LW_EXCLUSIVE);
|
||||||
slotno = SimpleLruReadPage(SerialSlruCtl, targetPage, true, xid);
|
slotno = SimpleLruReadPage(SerialSlruCtl, targetPage, true, xid);
|
||||||
|
}
|
||||||
|
|
||||||
SerialValue(slotno, xid) = minConflictCommitSeqNo;
|
SerialValue(slotno, xid) = minConflictCommitSeqNo;
|
||||||
SerialSlruCtl->shared->page_dirty[slotno] = true;
|
SerialSlruCtl->shared->page_dirty[slotno] = true;
|
||||||
|
Reference in New Issue
Block a user