Re: Buffer locking is special (hints, checksums, AIO writes)
Andres Freund <andres@anarazel.de>
Hi,
On 2026-03-25 17:34:33 -0400, Melanie Plageman wrote:
> On Wed, Mar 11, 2026 at 6:40 PM Andres Freund <andres@anarazel.de> wrote:
> >
> > I pushed this and many of the later patches in the series. Here are updated
> > versions of the remaining changes. The last two previously were one commit
> > with "WIP" in the title. The first one has, I think, not had a lot of review -
> > but it's also not a complicated change.
>
> 0001 looks good except for the comment above PageSetChecksum() that
> says it is only for shared buffers and a stray reference to the
> no-longer-present bufToWrite variable in a comment around line 4490 in
> bufmgr.c
Thanks for catching these.
Updated the PageSetChecksum() comment to
* Set checksum on a page.
*
* If the page is in shared buffers, it needs to be locked in at least
* share-exclusive mode.
...
> 0002
> diff --git a/src/backend/access/nbtree/nbtpage.c
> b/src/backend/access/nbtree/nbtpage.c
> index cc9c45dc40c..ad700e590e8 100644
> --- a/src/backend/access/nbtree/nbtpage.c
> +++ b/src/backend/access/nbtree/nbtpage.c
> @@ -1011,24 +1011,48 @@ _bt_relandgetbuf(Relation rel, Buffer obuf,
> BlockNumber blkno, int access)
> Assert(BlockNumberIsValid(blkno));
> if (BufferIsValid(obuf))
> - _bt_unlockbuf(rel, obuf);
> - buf = ReleaseAndReadBuffer(obuf, rel, blkno);
> - _bt_lockbuf(rel, buf, access);
> + {
> + if (BufferGetBlockNumber(obuf) == blkno)
> + {
> + /* trade in old lock mode for new lock */
> + _bt_unlockbuf(rel, obuf);
> + buf = obuf;
> + }
> + else
> + {
> + /* release lock and pin at once, that's a bit more efficient */
> + _bt_relbuf(rel, obuf);
> + buf = ReadBuffer(rel, blkno);
> + }
> + }
> + else
> + buf = ReadBuffer(rel, blkno);
>
> Not related to this patch, but why do we unlock and relock it when
> obuf has the block we need? Couldn't we pass lock mode and then just
> do nothing if it is the right lockmode?
I think it's very unlikely that it's called at any frequency with the same
buffer and lockmode. What would be the point of calling _bt_relandgetbuf() if
that's the case.
> Setting that aside, I presume we don't need to check the fork and
> relfilelocator (as ReleaseAndReadBuffer() did) because this code knows
> it will be the same?
Yea, it's a single index, so there can't be a different relfilenode.
> 0003
> AFAICT, this does what you claim. I don't really know what else to
> look when reviewing it, if I'm being honest. As such, I diligently fed
> it through AI which suggested you may have lost a
> VALGRIND_MAKE_MEM_NOACCESS(BufHdrGetBlock(buf), BLCKSZ);
> which sounds right to me and like something you should fix.
Good catch Melai.
> Also, I'd say this comment
> + /*
> + * Now okay to allow cancel/die interrupts again, were held when the lock
> + * was acquired.
> + */
>
> needs a "which" after the comma to read smoothly.
Fixed.
Running it through valgrind and then will work on reading through one more
time and pushing them.
Greetings,
Andres Freund
Commits
GET /api/v1/messages/:b64id/commits
the thread's linked commits as JSON, with link sources.
API reference →
-
bufmgr: Fix ordering of checks in PinBuffer()
- c0af4eb4e71e 19 (unreleased) landed
-
Use UnlockReleaseBuffer() in more places
- 8df3c48e466c 19 (unreleased) landed
-
bufmgr: Make UnlockReleaseBuffer() more efficient
- f39cb8c01106 19 (unreleased) landed
-
bufmgr: Don't copy pages while writing out
- 41d3d64e87af 19 (unreleased) landed
-
Fix use of wrong variable in _hash_kill_items()
- f5eb854ab6d6 19 (unreleased) landed
-
Fix bug due to confusion about what IsMVCCSnapshot means
- ce5d489166e5 19 (unreleased) landed
-
bufmgr: Switch to standard order in MarkBufferDirtyHint()
- a766125efd60 19 (unreleased) landed
-
bufmgr: Remove the, now obsolete, BM_JUST_DIRTIED
- b0f4ff3c9266 19 (unreleased) landed
-
Require share-exclusive lock to set hint bits and to flush
- 82467f627bd4 19 (unreleased) landed
-
heapam: Don't mimic MarkBufferDirtyHint() in inplace updates
- f4a4ce52c0d1 19 (unreleased) landed
-
bufmgr: Allow conditionally locking of already locked buffer
- 333f586372aa 19 (unreleased) landed
-
bufmgr: Avoid spurious compiler warning after fcb9c977aa5
- 84705b37273d 19 (unreleased) landed
-
lwlock: Remove ForEachLWLockHeldByMe
- 55fbfb738b00 19 (unreleased) landed
-
lwlock: Remove support for disowned lwlwocks
- d40fd85187d0 19 (unreleased) landed
-
bufmgr: Implement buffer content locks independently of lwlocks
- fcb9c977aa5f 19 (unreleased) landed
-
bufmgr: Change BufferDesc.state to be a 64-bit atomic
- dac328c8a682 19 (unreleased) landed
-
lwlock: Improve local variable name
- 556c92a68972 19 (unreleased) landed
-
lwlock: Invert meaning of LW_FLAG_RELEASE_OK
- 9a385f61666c 19 (unreleased) landed
-
bufmgr: Make definitions related to buffer descriptor easier to modify
- ff219c198789 19 (unreleased) landed
-
heapam: Add batch mode mvcc check and use it in page mode
- 0b96e734c590 19 (unreleased) landed
-
freespace: Don't modify page without any lock
- 45f658dacb9c 19 (unreleased) landed
-
heapam: Move logic to handle HEAP_MOVED into a helper function
- 548de59d93d5 19 (unreleased) landed
-
bufmgr: Optimize & harmonize LockBufHdr(), LWLockWaitListLock()
- 09ae2c8bac8d 19 (unreleased) landed
-
bufmgr: Add one-entry cache for private refcount
- 30df61990c67 19 (unreleased) landed
-
bufmgr: Separate keys for private refcount infrastructure
- edbaaea0a95e 19 (unreleased) landed
-
Add pg_atomic_unlocked_write_u64
- 7902a47c20b1 19 (unreleased) landed
-
Rename BUFFERPIN wait event class to BUFFER
- 6c5c393b7403 19 (unreleased) landed
-
bufmgr: Turn BUFFER_LOCK_* into an enum
- 156680055dc5 19 (unreleased) landed
-
lwlock: Fix, currently harmless, bug in LWLockWakeup()
- 81f773895321 19 (unreleased) landed
- da3971496531 15.16 landed
- 89c8a1b9069f 16.12 landed
- 427e886a79a5 17.8 landed
- 332693e75969 14.21 landed
- 8082b759d9b5 18.2 landed
-
bufmgr: Use atomic sub for unpinning buffers
- 5310fac6e0fc 19 (unreleased) landed
-
bufmgr: Allow some buffer state modifications while holding header lock
- c75ebc657ffc 19 (unreleased) landed
-
bufmgr: Fix valgrind checking for buffers pinned in StrategyGetBuffer()
- c819d1017ddb 19 (unreleased) landed
-
bufmgr: Don't lock buffer header in StrategyGetBuffer()
- 5e8998592879 19 (unreleased) landed
-
bufmgr: fewer calls to BufferDescriptorGetContentLock
- 3baae90013df 19 (unreleased) landed
-
bufmgr: Fix signedness of mask variable in BufferSync()
- 2a2e1b470b9b 19 (unreleased) landed
-
bufmgr: Introduce FlushUnlockedBuffer
- 3c2b97b29ee3 19 (unreleased) landed
-
Improve ReadRecentBuffer() scalability
- 819dc118c0f6 19 (unreleased) landed