fix-relocate-segfault-1.patch
text/x-diff
Filename: fix-relocate-segfault-1.patch
Type: text/x-diff
Part: 0
Message:
Bug in new buffering GiST build code
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: unified
| File | + | − |
|---|---|---|
| src/backend/access/gist/gistbuildbuffers.c | 12 | 8 |
| src/include/access/gist_private.h | 3 | 0 |
diff --git a/src/backend/access/gist/gistbuildbuffers.c b/src/backend/access/gist/gistbuildbuffers.c
index 34a12bc..a40b838 100644
--- a/src/backend/access/gist/gistbuildbuffers.c
+++ b/src/backend/access/gist/gistbuildbuffers.c
@@ -148,8 +148,10 @@ gistGetNodeBuffer(GISTBuildBuffers *gfbb, GISTSTATE *giststate,
int level;
MemoryContext oldcxt = MemoryContextSwitchTo(gfbb->context);
- nodeBuffer->pageBuffer = NULL;
+ /* nodeBuffer->nodeBlocknum is the hash key and was filled in already */
nodeBuffer->blocksCount = 0;
+ nodeBuffer->pageBlocknum = InvalidBlockNumber;
+ nodeBuffer->pageBuffer = NULL;
nodeBuffer->queuedForEmptying = false;
/*
@@ -244,11 +246,15 @@ gistAllocateNewPageBuffer(GISTBuildBuffers *gfbb)
}
/*
- * Add specified block number into loadedBuffers array.
+ * Add specified buffer into loadedBuffers array.
*/
static void
gistAddLoadedBuffer(GISTBuildBuffers *gfbb, GISTNodeBuffer *nodeBuffer)
{
+ /* Never add a temporary buffer to the array */
+ if (nodeBuffer->isTemp)
+ return;
+
/* Enlarge the array if needed */
if (gfbb->loadedBuffersCount >= gfbb->loadedBuffersLen)
{
@@ -591,7 +597,7 @@ gistRelocateBuildBuffersOnSplit(GISTBuildBuffers *gfbb, GISTSTATE *giststate,
i;
GISTENTRY entry[INDEX_MAX_KEYS];
bool isnull[INDEX_MAX_KEYS];
- GISTNodeBuffer nodebuf;
+ GISTNodeBuffer oldBuf;
ListCell *lc;
/* If the splitted page doesn't have buffers, we have nothing to do. */
@@ -619,16 +625,14 @@ gistRelocateBuildBuffersOnSplit(GISTBuildBuffers *gfbb, GISTSTATE *giststate,
* read the tuples straight from the heap instead of the root buffer.
*/
Assert(blocknum != GIST_ROOT_BLKNO);
- memcpy(&nodebuf, nodeBuffer, sizeof(GISTNodeBuffer));
+ memcpy(&oldBuf, nodeBuffer, sizeof(GISTNodeBuffer));
+ oldBuf.isTemp = true;
/* Reset the old buffer, used for the new left page from now on */
nodeBuffer->blocksCount = 0;
nodeBuffer->pageBuffer = NULL;
nodeBuffer->pageBlocknum = InvalidBlockNumber;
- /* Reassign pointer to the saved copy. */
- nodeBuffer = &nodebuf;
-
/*
* Allocate memory for information about relocation buffers.
*/
@@ -675,7 +679,7 @@ gistRelocateBuildBuffersOnSplit(GISTBuildBuffers *gfbb, GISTSTATE *giststate,
* Loop through all index tuples on the buffer on the splitted page,
* moving them to buffers on the new pages.
*/
- while (gistPopItupFromNodeBuffer(gfbb, nodeBuffer, &itup))
+ while (gistPopItupFromNodeBuffer(gfbb, &oldBuf, &itup))
{
float sum_grow,
which_grow[INDEX_MAX_KEYS];
diff --git a/src/include/access/gist_private.h b/src/include/access/gist_private.h
index 0d6b625..481ef5f 100644
--- a/src/include/access/gist_private.h
+++ b/src/include/access/gist_private.h
@@ -326,6 +326,9 @@ typedef struct
/* is this buffer queued for emptying? */
bool queuedForEmptying;
+ /* is this a temporary copy, not in the hash table? */
+ bool isTemp;
+
struct GISTBufferingInsertStack *path;
} GISTNodeBuffer;