aboutsummaryrefslogtreecommitdiff
path: root/src/backend/access/gist/gist.c
diff options
context:
space:
mode:
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>2019-12-16 13:57:41 +0200
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>2019-12-16 13:58:07 +0200
commit42d1acd2edc4a02de63c7b3d2a18056d393e373d (patch)
tree6e4c11781901c9316a47af749fb6ba71c668abd3 /src/backend/access/gist/gist.c
parente3ac8939324d73c35e2fd0f846001eb02e3a7858 (diff)
downloadpostgresql-42d1acd2edc4a02de63c7b3d2a18056d393e373d.tar.gz
postgresql-42d1acd2edc4a02de63c7b3d2a18056d393e373d.zip
Fix yet another crash in page split during GiST index creation.
Commit a7ee7c8513 fixed a bug in GiST page split during index creation, where we failed to re-find the position of a downlink after the page containing it was split. However, that fix was incomplete; the other call to gistinserttuples() in the same function needs to also clear 'downlinkoffnum'. Fixes bug #16134 reported by Alexander Lakhin, for real this time. The previous fix was enough to fix the crash with the reproducer script for bug #16162, but the original script for #16134 was still crashing. Backpatch to v12, like the previous incomplete fix. Discussion: https://www.postgresql.org/message-id/d869f537-abe4-d2ea-0510-38cd053f5152%40gmail.com
Diffstat (limited to 'src/backend/access/gist/gist.c')
-rw-r--r--src/backend/access/gist/gist.c31
1 files changed, 19 insertions, 12 deletions
diff --git a/src/backend/access/gist/gist.c b/src/backend/access/gist/gist.c
index a44112befce..12d8a68c6c1 100644
--- a/src/backend/access/gist/gist.c
+++ b/src/backend/access/gist/gist.c
@@ -1338,10 +1338,9 @@ gistfinishsplit(GISTInsertState *state, GISTInsertStack *stack,
}
LockBuffer(stack->parent->buffer, GIST_EXCLUSIVE);
- gistFindCorrectParent(state->r, stack);
/*
- * insert downlinks for the siblings from right to left, until there are
+ * Insert downlinks for the siblings from right to left, until there are
* only two siblings left.
*/
while (list_length(reversed) > 2)
@@ -1349,17 +1348,17 @@ gistfinishsplit(GISTInsertState *state, GISTInsertStack *stack,
right = (GISTPageSplitInfo *) linitial(reversed);
left = (GISTPageSplitInfo *) lsecond(reversed);
+ gistFindCorrectParent(state->r, stack);
if (gistinserttuples(state, stack->parent, giststate,
&right->downlink, 1,
InvalidOffsetNumber,
left->buf, right->buf, false, false))
{
/*
- * If the parent page was split, need to relocate the original
- * parent pointer.
+ * If the parent page was split, the existing downlink might
+ * have moved.
*/
stack->downlinkoffnum = InvalidOffsetNumber;
- gistFindCorrectParent(state->r, stack);
}
/* gistinserttuples() released the lock on right->buf. */
reversed = list_delete_first(reversed);
@@ -1375,13 +1374,21 @@ gistfinishsplit(GISTInsertState *state, GISTInsertStack *stack,
*/
tuples[0] = left->downlink;
tuples[1] = right->downlink;
- gistinserttuples(state, stack->parent, giststate,
- tuples, 2,
- stack->downlinkoffnum,
- left->buf, right->buf,
- true, /* Unlock parent */
- unlockbuf /* Unlock stack->buffer if caller wants that */
- );
+ gistFindCorrectParent(state->r, stack);
+ if (gistinserttuples(state, stack->parent, giststate,
+ tuples, 2,
+ stack->downlinkoffnum,
+ left->buf, right->buf,
+ true, /* Unlock parent */
+ unlockbuf /* Unlock stack->buffer if caller wants that */
+ ))
+ {
+ /*
+ * If the parent page was split, the downlink might have moved.
+ */
+ stack->downlinkoffnum = InvalidOffsetNumber;
+ }
+
Assert(left->buf == stack->buffer);
/*