Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit05a5623

Browse files
committed
Avoid palloc in critical section in GiST WAL-logging.
Memory allocation can fail if you run out of memory, and inside a criticalsection that will lead to a PANIC. Use conservatively-sized arrays in stackinstead.There was previously no explicit limit on the number of pages a GiST splitcan produce, it was only limited by the number of LWLocks that can be heldsimultaneously (100 at the moment). This patch adds an explicit limit of 75pages. That should be plenty, a typical split shouldn't produce more than2-3 page halves.The bug has been there forever, but only backpatch down to 9.1. The codewas changed significantly in 9.1, and it doesn't seem worth the risk ortrouble to adapt this for 9.0 and 8.4.
1 parentb7a4243 commit05a5623

File tree

4 files changed

+38
-9
lines changed

4 files changed

+38
-9
lines changed

‎src/backend/access/gist/README

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ that didn't need to be split.
128128

129129
This differs from the insertion algorithm in the original paper. In the
130130
original paper, you first walk down the tree until you reach a leaf page, and
131-
then you adjust the downlink in the parent, andpropagating the adjustment up,
131+
then you adjust the downlink in the parent, andpropagate the adjustment up,
132132
all the way up to the root in the worst case. But we adjust the downlinks to
133133
cover the new key already when we walk down, so that when we reach the leaf
134134
page, we don't need to update the parents anymore, except to insert the

‎src/backend/access/gist/gist.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,7 @@ gistplacetopage(GISTInsertState *state, GISTSTATE *giststate,
356356
SplitedPageLayoutrootpg;
357357
BlockNumberblkno=BufferGetBlockNumber(buffer);
358358
boolis_rootsplit;
359+
intnpage;
359360

360361
is_rootsplit= (blkno==GIST_ROOT_BLKNO);
361362

@@ -376,6 +377,19 @@ gistplacetopage(GISTInsertState *state, GISTSTATE *giststate,
376377
itvec=gistjoinvector(itvec,&tlen,itup,ntup);
377378
dist=gistSplit(state->r,page,itvec,tlen,giststate);
378379

380+
/*
381+
* Check that split didn't produce too many pages.
382+
*/
383+
npage=0;
384+
for (ptr=dist;ptr;ptr=ptr->next)
385+
npage++;
386+
/* in a root split, we'll add one more page to the list below */
387+
if (is_rootsplit)
388+
npage++;
389+
if (npage>GIST_MAX_SPLIT_PAGES)
390+
elog(ERROR,"GiST page split into too many halves (%d, maximum %d)",
391+
npage,GIST_MAX_SPLIT_PAGES);
392+
379393
/*
380394
* Set up pages to work with. Allocate new buffers for all but the
381395
* leftmost page. The original page becomes the new leftmost page, and

‎src/backend/access/gist/gistxlog.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -434,7 +434,7 @@ gistXLogSplit(RelFileNode node, BlockNumber blkno, bool page_is_leaf,
434434
BlockNumberorigrlink,GistNSNorignsn,
435435
Bufferleftchildbuf)
436436
{
437-
XLogRecData*rdata;
437+
XLogRecDatardata[GIST_MAX_SPLIT_PAGES*2+2];
438438
gistxlogPageSplitxlrec;
439439
SplitedPageLayout*ptr;
440440
intnpage=0,
@@ -443,8 +443,12 @@ gistXLogSplit(RelFileNode node, BlockNumber blkno, bool page_is_leaf,
443443

444444
for (ptr=dist;ptr;ptr=ptr->next)
445445
npage++;
446-
447-
rdata= (XLogRecData*)palloc(sizeof(XLogRecData)* (npage*2+2));
446+
/*
447+
* the caller should've checked this already, but doesn't hurt to check
448+
* again.
449+
*/
450+
if (npage>GIST_MAX_SPLIT_PAGES)
451+
elog(ERROR,"GiST page split into too many halves");
448452

449453
xlrec.node=node;
450454
xlrec.origblkno=blkno;
@@ -493,7 +497,6 @@ gistXLogSplit(RelFileNode node, BlockNumber blkno, bool page_is_leaf,
493497

494498
recptr=XLogInsert(RM_GIST_ID,XLOG_GIST_PAGE_SPLIT,rdata);
495499

496-
pfree(rdata);
497500
returnrecptr;
498501
}
499502

@@ -516,14 +519,12 @@ gistXLogUpdate(RelFileNode node, Buffer buffer,
516519
IndexTuple*itup,intituplen,
517520
Bufferleftchildbuf)
518521
{
519-
XLogRecData*rdata;
522+
XLogRecDatardata[MaxIndexTuplesPerPage+3];
520523
gistxlogPageUpdatexlrec;
521524
intcur,
522525
i;
523526
XLogRecPtrrecptr;
524527

525-
rdata= (XLogRecData*)palloc(sizeof(XLogRecData)* (3+ituplen));
526-
527528
xlrec.node=node;
528529
xlrec.blkno=BufferGetBlockNumber(buffer);
529530
xlrec.ntodelete=ntodelete;
@@ -570,6 +571,5 @@ gistXLogUpdate(RelFileNode node, Buffer buffer,
570571

571572
recptr=XLogInsert(RM_GIST_ID,XLOG_GIST_PAGE_UPDATE,rdata);
572573

573-
pfree(rdata);
574574
returnrecptr;
575575
}

‎src/include/access/gist_private.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,21 @@
1919
#include"storage/bufmgr.h"
2020
#include"utils/rbtree.h"
2121

22+
/*
23+
* Maximum number of "halves" a page can be split into in one operation.
24+
* Typically a split produces 2 halves, but can be more if keys have very
25+
* different lengths, or when inserting multiple keys in one operation (as
26+
* when inserting downlinks to an internal node). There is no theoretical
27+
* limit on this, but in practice if you get more than a handful page halves
28+
* in one split, there's something wrong with the opclass implementation.
29+
* GIST_MAX_SPLIT_PAGES is an arbitrary limit on that, used to size some
30+
* local arrays used during split. Note that there is also a limit on the
31+
* number of buffers that can be held locked at a time, MAX_SIMUL_LWLOCKS,
32+
* so if you raise this higher than that limit, you'll just get a different
33+
* error.
34+
*/
35+
#defineGIST_MAX_SPLIT_PAGES75
36+
2237
/* Buffer lock modes */
2338
#defineGIST_SHAREBUFFER_LOCK_SHARE
2439
#defineGIST_EXCLUSIVEBUFFER_LOCK_EXCLUSIVE

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp