From b90f7fbe9958ea785a1302395bb1a201a00f3bc5 Mon Sep 17 00:00:00 2001 From: Andres Freund Date: Thu, 29 Jan 2026 12:22:02 -0500 Subject: [PATCH v1] bufmgr: Allow conditionally locking of already locked buffer Discussion: https://postgr.es/m/90bd2cbb-49ce-4092-9f61-5ac2ab782c94@gmail.com --- src/backend/storage/buffer/bufmgr.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c index 6f935648ae9..f5602f4e7e1 100644 --- a/src/backend/storage/buffer/bufmgr.c +++ b/src/backend/storage/buffer/bufmgr.c @@ -5895,6 +5895,13 @@ BufferLockUnlock(Buffer buffer, BufferDesc *buf_hdr) /* * Acquire the content lock for the buffer, but only if we don't have to wait. + * + * It is allowed to try to conditionally acquire a lock on a buffer that this + * backend has already locked, but the lock acquisition will always fail, even + * if the new lock acquisition does not conflict with an already held lock + * (e.g. two share locks). This is because we don't track per-backend + * ownership of multiple lock levels. That is ok for the current uses of + * BufferLockConditional(). */ static bool BufferLockConditional(Buffer buffer, BufferDesc *buf_hdr, BufferLockMode mode) @@ -5902,11 +5909,16 @@ BufferLockConditional(Buffer buffer, BufferDesc *buf_hdr, BufferLockMode mode) PrivateRefCountEntry *entry = GetPrivateRefCountEntry(buffer, true); bool mustwait; - /* - * We better not already hold a lock on the buffer. - */ Assert(entry->data.lockmode == BUFFER_LOCK_UNLOCK); + /* + * As described above, if we're trying to lock a buffer this backend + * already has locked, return false, independent of the existing and + * desired lock level. + */ + if (entry->data.lockmode != BUFFER_LOCK_UNLOCK) + return false; + /* * Lock out cancel/die interrupts until we exit the code section protected * by the content lock. This ensures that interrupts will not interfere -- 2.48.1.76.g4e746b1a31.dirty