diff options
author | Heikki Linnakangas <heikki.linnakangas@iki.fi> | 2019-12-16 13:57:41 +0200 |
---|---|---|
committer | Heikki Linnakangas <heikki.linnakangas@iki.fi> | 2019-12-16 13:58:07 +0200 |
commit | 42d1acd2edc4a02de63c7b3d2a18056d393e373d (patch) | |
tree | 6e4c11781901c9316a47af749fb6ba71c668abd3 /src/backend/access/gist/gist.c | |
parent | e3ac8939324d73c35e2fd0f846001eb02e3a7858 (diff) | |
download | postgresql-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.c | 31 |
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); /* |