diff options
author | Heikki Linnakangas <heikki.linnakangas@iki.fi> | 2014-04-03 15:09:37 +0300 |
---|---|---|
committer | Heikki Linnakangas <heikki.linnakangas@iki.fi> | 2014-04-03 15:43:50 +0300 |
commit | 04e298b826d452ceb838d9fda884a29f229d484d (patch) | |
tree | 95d544122aff600de78c9e7e716546ea78de925e /src/backend/access/gist/gistxlog.c | |
parent | fc752505a99a4e2c781a070d3d42a25289c22e3c (diff) | |
download | postgresql-04e298b826d452ceb838d9fda884a29f229d484d.tar.gz postgresql-04e298b826d452ceb838d9fda884a29f229d484d.zip |
Avoid palloc in critical section in GiST WAL-logging.
Memory allocation can fail if you run out of memory, and inside a critical
section that will lead to a PANIC. Use conservatively-sized arrays in stack
instead.
There was previously no explicit limit on the number of pages a GiST split
can produce, it was only limited by the number of LWLocks that can be held
simultaneously (100 at the moment). This patch adds an explicit limit of 75
pages. That should be plenty, a typical split shouldn't produce more than
2-3 page halves.
The bug has been there forever, but only backpatch down to 9.1. The code
was changed significantly in 9.1, and it doesn't seem worth the risk or
trouble to adapt this for 9.0 and 8.4.
Diffstat (limited to 'src/backend/access/gist/gistxlog.c')
-rw-r--r-- | src/backend/access/gist/gistxlog.c | 16 |
1 files changed, 8 insertions, 8 deletions
diff --git a/src/backend/access/gist/gistxlog.c b/src/backend/access/gist/gistxlog.c index d6fdc04cf28..7cc64aeb490 100644 --- a/src/backend/access/gist/gistxlog.c +++ b/src/backend/access/gist/gistxlog.c @@ -379,7 +379,7 @@ gistXLogSplit(RelFileNode node, BlockNumber blkno, bool page_is_leaf, BlockNumber origrlink, GistNSN orignsn, Buffer leftchildbuf, bool markfollowright) { - XLogRecData *rdata; + XLogRecData rdata[GIST_MAX_SPLIT_PAGES * 2 + 2]; gistxlogPageSplit xlrec; SplitedPageLayout *ptr; int npage = 0, @@ -388,8 +388,12 @@ gistXLogSplit(RelFileNode node, BlockNumber blkno, bool page_is_leaf, for (ptr = dist; ptr; ptr = ptr->next) npage++; - - rdata = (XLogRecData *) palloc(sizeof(XLogRecData) * (npage * 2 + 2)); + /* + * the caller should've checked this already, but doesn't hurt to check + * again. + */ + if (npage > GIST_MAX_SPLIT_PAGES) + elog(ERROR, "GiST page split into too many halves"); xlrec.node = node; xlrec.origblkno = blkno; @@ -439,7 +443,6 @@ gistXLogSplit(RelFileNode node, BlockNumber blkno, bool page_is_leaf, recptr = XLogInsert(RM_GIST_ID, XLOG_GIST_PAGE_SPLIT, rdata); - pfree(rdata); return recptr; } @@ -462,14 +465,12 @@ gistXLogUpdate(RelFileNode node, Buffer buffer, IndexTuple *itup, int ituplen, Buffer leftchildbuf) { - XLogRecData *rdata; + XLogRecData rdata[MaxIndexTuplesPerPage + 3]; gistxlogPageUpdate xlrec; int cur, i; XLogRecPtr recptr; - rdata = (XLogRecData *) palloc(sizeof(XLogRecData) * (3 + ituplen)); - xlrec.node = node; xlrec.blkno = BufferGetBlockNumber(buffer); xlrec.ntodelete = ntodelete; @@ -516,6 +517,5 @@ gistXLogUpdate(RelFileNode node, Buffer buffer, recptr = XLogInsert(RM_GIST_ID, XLOG_GIST_PAGE_UPDATE, rdata); - pfree(rdata); return recptr; } |