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

Commit04e298b

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 parentfc75250 commit04e298b

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
@@ -135,7 +135,7 @@ that didn't need to be split.
135135

136136
This differs from the insertion algorithm in the original paper. In the
137137
original paper, you first walk down the tree until you reach a leaf page, and
138-
then you adjust the downlink in the parent, andpropagating the adjustment up,
138+
then you adjust the downlink in the parent, andpropagate the adjustment up,
139139
all the way up to the root in the worst case. But we adjust the downlinks to
140140
cover the new key already when we walk down, so that when we reach the leaf
141141
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
@@ -220,6 +220,7 @@ gistplacetopage(Relation rel, Size freespace, GISTSTATE *giststate,
220220
GistNSNoldnsn=0;
221221
SplitedPageLayoutrootpg;
222222
boolis_rootsplit;
223+
intnpage;
223224

224225
is_rootsplit= (blkno==GIST_ROOT_BLKNO);
225226

@@ -240,6 +241,19 @@ gistplacetopage(Relation rel, Size freespace, GISTSTATE *giststate,
240241
itvec=gistjoinvector(itvec,&tlen,itup,ntup);
241242
dist=gistSplit(rel,page,itvec,tlen,giststate);
242243

244+
/*
245+
* Check that split didn't produce too many pages.
246+
*/
247+
npage=0;
248+
for (ptr=dist;ptr;ptr=ptr->next)
249+
npage++;
250+
/* in a root split, we'll add one more page to the list below */
251+
if (is_rootsplit)
252+
npage++;
253+
if (npage>GIST_MAX_SPLIT_PAGES)
254+
elog(ERROR,"GiST page split into too many halves (%d, maximum %d)",
255+
npage,GIST_MAX_SPLIT_PAGES);
256+
243257
/*
244258
* Set up pages to work with. Allocate new buffers for all but the
245259
* 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
@@ -379,7 +379,7 @@ gistXLogSplit(RelFileNode node, BlockNumber blkno, bool page_is_leaf,
379379
BlockNumberorigrlink,GistNSNorignsn,
380380
Bufferleftchildbuf,boolmarkfollowright)
381381
{
382-
XLogRecData*rdata;
382+
XLogRecDatardata[GIST_MAX_SPLIT_PAGES*2+2];
383383
gistxlogPageSplitxlrec;
384384
SplitedPageLayout*ptr;
385385
intnpage=0,
@@ -388,8 +388,12 @@ gistXLogSplit(RelFileNode node, BlockNumber blkno, bool page_is_leaf,
388388

389389
for (ptr=dist;ptr;ptr=ptr->next)
390390
npage++;
391-
392-
rdata= (XLogRecData*)palloc(sizeof(XLogRecData)* (npage*2+2));
391+
/*
392+
* the caller should've checked this already, but doesn't hurt to check
393+
* again.
394+
*/
395+
if (npage>GIST_MAX_SPLIT_PAGES)
396+
elog(ERROR,"GiST page split into too many halves");
393397

394398
xlrec.node=node;
395399
xlrec.origblkno=blkno;
@@ -439,7 +443,6 @@ gistXLogSplit(RelFileNode node, BlockNumber blkno, bool page_is_leaf,
439443

440444
recptr=XLogInsert(RM_GIST_ID,XLOG_GIST_PAGE_SPLIT,rdata);
441445

442-
pfree(rdata);
443446
returnrecptr;
444447
}
445448

@@ -462,14 +465,12 @@ gistXLogUpdate(RelFileNode node, Buffer buffer,
462465
IndexTuple*itup,intituplen,
463466
Bufferleftchildbuf)
464467
{
465-
XLogRecData*rdata;
468+
XLogRecDatardata[MaxIndexTuplesPerPage+3];
466469
gistxlogPageUpdatexlrec;
467470
intcur,
468471
i;
469472
XLogRecPtrrecptr;
470473

471-
rdata= (XLogRecData*)palloc(sizeof(XLogRecData)* (3+ituplen));
472-
473474
xlrec.node=node;
474475
xlrec.blkno=BufferGetBlockNumber(buffer);
475476
xlrec.ntodelete=ntodelete;
@@ -516,6 +517,5 @@ gistXLogUpdate(RelFileNode node, Buffer buffer,
516517

517518
recptr=XLogInsert(RM_GIST_ID,XLOG_GIST_PAGE_UPDATE,rdata);
518519

519-
pfree(rdata);
520520
returnrecptr;
521521
}

‎src/include/access/gist_private.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,21 @@
2222
#include"utils/rbtree.h"
2323
#include"utils/hsearch.h"
2424

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

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp