1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-30 11:03:19 +03:00

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
This commit is contained in:
Heikki Linnakangas
2019-12-16 13:57:41 +02:00
parent e3ac893932
commit 42d1acd2ed

View File

@ -1338,10 +1338,9 @@ gistfinishsplit(GISTInsertState *state, GISTInsertStack *stack,
} }
LockBuffer(stack->parent->buffer, GIST_EXCLUSIVE); 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. * only two siblings left.
*/ */
while (list_length(reversed) > 2) while (list_length(reversed) > 2)
@ -1349,17 +1348,17 @@ gistfinishsplit(GISTInsertState *state, GISTInsertStack *stack,
right = (GISTPageSplitInfo *) linitial(reversed); right = (GISTPageSplitInfo *) linitial(reversed);
left = (GISTPageSplitInfo *) lsecond(reversed); left = (GISTPageSplitInfo *) lsecond(reversed);
gistFindCorrectParent(state->r, stack);
if (gistinserttuples(state, stack->parent, giststate, if (gistinserttuples(state, stack->parent, giststate,
&right->downlink, 1, &right->downlink, 1,
InvalidOffsetNumber, InvalidOffsetNumber,
left->buf, right->buf, false, false)) left->buf, right->buf, false, false))
{ {
/* /*
* If the parent page was split, need to relocate the original * If the parent page was split, the existing downlink might
* parent pointer. * have moved.
*/ */
stack->downlinkoffnum = InvalidOffsetNumber; stack->downlinkoffnum = InvalidOffsetNumber;
gistFindCorrectParent(state->r, stack);
} }
/* gistinserttuples() released the lock on right->buf. */ /* gistinserttuples() released the lock on right->buf. */
reversed = list_delete_first(reversed); reversed = list_delete_first(reversed);
@ -1375,13 +1374,21 @@ gistfinishsplit(GISTInsertState *state, GISTInsertStack *stack,
*/ */
tuples[0] = left->downlink; tuples[0] = left->downlink;
tuples[1] = right->downlink; tuples[1] = right->downlink;
gistinserttuples(state, stack->parent, giststate, gistFindCorrectParent(state->r, stack);
tuples, 2, if (gistinserttuples(state, stack->parent, giststate,
stack->downlinkoffnum, tuples, 2,
left->buf, right->buf, stack->downlinkoffnum,
true, /* Unlock parent */ left->buf, right->buf,
unlockbuf /* Unlock stack->buffer if caller wants that */ 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); Assert(left->buf == stack->buffer);
/* /*