summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane2023-11-13 16:44:35 +0000
committerTom Lane2023-11-13 16:44:35 +0000
commit5c62ecf6ec3c912c85a8292a9ad0daa8c0777088 (patch)
tree499e9a8d2673d1e4b01637e1855276595a784388
parentc3fd6a10fc520158e381d0296316be387b5b8da7 (diff)
Don't release index root page pin in ginFindParents().
It's clearly stated in the comments that ginFindParents() must keep the pin on the index's root page that's associated with the topmost GinBtreeStack item. However, the code path for the case that the desired downlink has been pushed down to the next index level ignored this proviso, and would release the pin anyway if we were still examining the root level. That led to an assertion failure or "buffer NNNN is not owned by resource owner" error later, when we try to release the pin again at the end of the insertion. This is quite hard to reproduce, since it can only happen if an index root page split occurs concurrently with our own insertion. Thanks to Jeff Janes for finding a test case that triggers it often enough to allow investigation. This has been there since the beginning of GIN, so back-patch to all supported branches. Discussion: https://postgr.es/m/CAMkU=1yCAKtv86dMrD__Ja-7KzjE=uMeKX8y__cx5W-OEWy2ow@mail.gmail.com
-rw-r--r--src/backend/access/gin/ginbtree.c6
1 files changed, 5 insertions, 1 deletions
diff --git a/src/backend/access/gin/ginbtree.c b/src/backend/access/gin/ginbtree.c
index fc694b40f1..a8e46dfd8c 100644
--- a/src/backend/access/gin/ginbtree.c
+++ b/src/backend/access/gin/ginbtree.c
@@ -272,7 +272,11 @@ ginFindParents(GinBtree btree, GinBtreeStack *stack)
blkno = GinPageGetOpaque(page)->rightlink;
if (blkno == InvalidBlockNumber)
{
- UnlockReleaseBuffer(buffer);
+ /* Link not present in this level */
+ LockBuffer(buffer, GIN_UNLOCK);
+ /* Do not release pin on the root buffer */
+ if (buffer != root->buffer)
+ ReleaseBuffer(buffer);
break;
}
buffer = ginStepRight(buffer, btree->index, GIN_EXCLUSIVE);