From c180f965da2ddc46076cc9d5b05227923bc5cade Mon Sep 17 00:00:00 2001 From: Peter Geoghegan Date: Wed, 14 Oct 2026 14:26:04 -0400 Subject: [PATCH] Fix hash bucket split buffer pin leak. The process by which a hash index inserter finishes an incomplete bucket split involves a walk of the new bucket (the bucket "being populated") to collect the TIDs that the interrupted split already moved. This process keeps a pin on the new bucket's primary page, and then takes conditional cleanup locks on both buckets. When either lock could not be acquired, we gave up, but neglected to release the new bucket's pin. To fix, release the buffer pin on failure. Oversight in commit 6d46f4783, which improved hash index bucket split behavior by switching it from using a heavyweight lock to using these cleanup locks. Author: Peter Geoghegan Reviewed-by: Ayush Tiwari Discussion: https://postgr.es/m/CAH2-Wz=b9sSBv15HsgZAuazjJu8-YRGHOpLjvp+dJgEDaBx0Ng@mail.gmail.com Backpatch-through: 14 --- src/backend/access/hash/hashpage.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/backend/access/hash/hashpage.c b/src/backend/access/hash/hashpage.c index 0c6e79f1bdc..25113959aa1 100644 --- a/src/backend/access/hash/hashpage.c +++ b/src/backend/access/hash/hashpage.c @@ -1439,12 +1439,14 @@ _hash_finish_split(Relation rel, Buffer metabuf, Buffer obuf, Bucket obucket, */ if (!ConditionalLockBufferForCleanup(obuf)) { + _hash_dropbuf(rel, bucket_nbuf); hash_destroy(tidhtab); return; } if (!ConditionalLockBufferForCleanup(bucket_nbuf)) { LockBuffer(obuf, BUFFER_LOCK_UNLOCK); + _hash_dropbuf(rel, bucket_nbuf); hash_destroy(tidhtab); return; }