Skip to content

Commit 7d1e0e8

Browse files
committed
Avoid allocations in critical sections.
If a palloc in a critical section fails, it becomes a PANIC.
1 parent 6c1cfba commit 7d1e0e8

File tree

4 files changed

+46
-48
lines changed

4 files changed

+46
-48
lines changed

src/backend/access/nbtree/nbtinsert.c

Lines changed: 29 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1839,8 +1839,10 @@ _bt_newroot(Relation rel, Buffer lbuf, Buffer rbuf)
18391839
BTPageOpaque rootopaque;
18401840
ItemId itemid;
18411841
IndexTuple item;
1842-
Size itemsz;
1843-
IndexTuple new_item;
1842+
IndexTuple left_item;
1843+
Size left_item_sz;
1844+
IndexTuple right_item;
1845+
Size right_item_sz;
18441846
Buffer metabuf;
18451847
Page metapg;
18461848
BTMetaPageData *metad;
@@ -1859,6 +1861,26 @@ _bt_newroot(Relation rel, Buffer lbuf, Buffer rbuf)
18591861
metapg = BufferGetPage(metabuf);
18601862
metad = BTPageGetMeta(metapg);
18611863

1864+
/*
1865+
* Create downlink item for left page (old root). Since this will be the
1866+
* first item in a non-leaf page, it implicitly has minus-infinity key
1867+
* value, so we need not store any actual key in it.
1868+
*/
1869+
left_item_sz = sizeof(IndexTupleData);
1870+
left_item = (IndexTuple) palloc(left_item_sz);
1871+
left_item->t_info = left_item_sz;
1872+
ItemPointerSet(&(left_item->t_tid), lbkno, P_HIKEY);
1873+
1874+
/*
1875+
* Create downlink item for right page. The key for it is obtained from
1876+
* the "high key" position in the left page.
1877+
*/
1878+
itemid = PageGetItemId(lpage, P_HIKEY);
1879+
right_item_sz = ItemIdGetLength(itemid);
1880+
item = (IndexTuple) PageGetItem(lpage, itemid);
1881+
right_item = CopyIndexTuple(item);
1882+
ItemPointerSet(&(right_item->t_tid), rbkno, P_HIKEY);
1883+
18621884
/* NO EREPORT(ERROR) from here till newroot op is logged */
18631885
START_CRIT_SECTION();
18641886

@@ -1876,16 +1898,6 @@ _bt_newroot(Relation rel, Buffer lbuf, Buffer rbuf)
18761898
metad->btm_fastroot = rootblknum;
18771899
metad->btm_fastlevel = rootopaque->btpo.level;
18781900

1879-
/*
1880-
* Create downlink item for left page (old root). Since this will be the
1881-
* first item in a non-leaf page, it implicitly has minus-infinity key
1882-
* value, so we need not store any actual key in it.
1883-
*/
1884-
itemsz = sizeof(IndexTupleData);
1885-
new_item = (IndexTuple) palloc(itemsz);
1886-
new_item->t_info = itemsz;
1887-
ItemPointerSet(&(new_item->t_tid), lbkno, P_HIKEY);
1888-
18891901
/*
18901902
* Insert the left page pointer into the new root page. The root page is
18911903
* the rightmost page on its level so there is no "high key" in it; the
@@ -1894,32 +1906,20 @@ _bt_newroot(Relation rel, Buffer lbuf, Buffer rbuf)
18941906
* Note: we *must* insert the two items in item-number order, for the
18951907
* benefit of _bt_restore_page().
18961908
*/
1897-
if (PageAddItem(rootpage, (Item) new_item, itemsz, P_HIKEY,
1909+
if (PageAddItem(rootpage, (Item) left_item, left_item_sz, P_HIKEY,
18981910
false, false) == InvalidOffsetNumber)
18991911
elog(PANIC, "failed to add leftkey to new root page"
19001912
" while splitting block %u of index \"%s\"",
19011913
BufferGetBlockNumber(lbuf), RelationGetRelationName(rel));
1902-
pfree(new_item);
1903-
1904-
/*
1905-
* Create downlink item for right page. The key for it is obtained from
1906-
* the "high key" position in the left page.
1907-
*/
1908-
itemid = PageGetItemId(lpage, P_HIKEY);
1909-
itemsz = ItemIdGetLength(itemid);
1910-
item = (IndexTuple) PageGetItem(lpage, itemid);
1911-
new_item = CopyIndexTuple(item);
1912-
ItemPointerSet(&(new_item->t_tid), rbkno, P_HIKEY);
19131914

19141915
/*
19151916
* insert the right page pointer into the new root page.
19161917
*/
1917-
if (PageAddItem(rootpage, (Item) new_item, itemsz, P_FIRSTKEY,
1918+
if (PageAddItem(rootpage, (Item) right_item, right_item_sz, P_FIRSTKEY,
19181919
false, false) == InvalidOffsetNumber)
19191920
elog(PANIC, "failed to add rightkey to new root page"
19201921
" while splitting block %u of index \"%s\"",
19211922
BufferGetBlockNumber(lbuf), RelationGetRelationName(rel));
1922-
pfree(new_item);
19231923

19241924
MarkBufferDirty(rootbuf);
19251925
MarkBufferDirty(metabuf);
@@ -1967,6 +1967,9 @@ _bt_newroot(Relation rel, Buffer lbuf, Buffer rbuf)
19671967
/* done with metapage */
19681968
_bt_relbuf(rel, metabuf);
19691969

1970+
pfree(left_item);
1971+
pfree(right_item);
1972+
19701973
return rootbuf;
19711974
}
19721975

src/backend/access/spgist/spgdoinsert.c

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,8 @@ cmpOffsetNumbers(const void *a, const void *b)
121121
*
122122
* NB: this is used during WAL replay, so beware of trying to make it too
123123
* smart. In particular, it shouldn't use "state" except for calling
124-
* spgFormDeadTuple().
124+
* spgFormDeadTuple(). This is also used in a critical section, so no
125+
* pallocs either!
125126
*/
126127
void
127128
spgPageIndexMultiDelete(SpGistState *state, Page page,
@@ -130,7 +131,7 @@ spgPageIndexMultiDelete(SpGistState *state, Page page,
130131
BlockNumber blkno, OffsetNumber offnum)
131132
{
132133
OffsetNumber firstItem;
133-
OffsetNumber *sortednos;
134+
OffsetNumber sortednos[MaxIndexTuplesPerPage];
134135
SpGistDeadTuple tuple = NULL;
135136
int i;
136137

@@ -144,7 +145,6 @@ spgPageIndexMultiDelete(SpGistState *state, Page page,
144145
* replacement tuples.) However, we must not scribble on the caller's
145146
* array, so we have to make a copy.
146147
*/
147-
sortednos = (OffsetNumber *) palloc(sizeof(OffsetNumber) * nitems);
148148
memcpy(sortednos, itemnos, sizeof(OffsetNumber) * nitems);
149149
if (nitems > 1)
150150
qsort(sortednos, nitems, sizeof(OffsetNumber), cmpOffsetNumbers);
@@ -172,8 +172,6 @@ spgPageIndexMultiDelete(SpGistState *state, Page page,
172172
else if (tupstate == SPGIST_PLACEHOLDER)
173173
SpGistPageGetOpaque(page)->nPlaceholder++;
174174
}
175-
176-
pfree(sortednos);
177175
}
178176

179177
/*

src/backend/access/transam/xlog.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2449,6 +2449,7 @@ XLogFileInit(uint32 log, uint32 seg,
24492449
{
24502450
char path[MAXPGPATH];
24512451
char tmppath[MAXPGPATH];
2452+
char zbuffer_raw[BLCKSZ + MAXIMUM_ALIGNOF];
24522453
char *zbuffer;
24532454
uint32 installed_log;
24542455
uint32 installed_seg;
@@ -2506,11 +2507,11 @@ XLogFileInit(uint32 log, uint32 seg,
25062507
* fdatasync(2) or O_DSYNC will be sufficient to sync future writes to the
25072508
* log file.
25082509
*
2509-
* Note: palloc zbuffer, instead of just using a local char array, to
2510-
* ensure it is reasonably well-aligned; this may save a few cycles
2511-
* transferring data to the kernel.
2510+
* Note: ensure the buffer is reasonably well-aligned; this may save a few
2511+
* cycles transferring data to the kernel.
25122512
*/
2513-
zbuffer = (char *) palloc0(XLOG_BLCKSZ);
2513+
zbuffer = (char *) MAXALIGN(zbuffer_raw);
2514+
memset(zbuffer, 0, BLCKSZ);
25142515
for (nbytes = 0; nbytes < XLogSegSize; nbytes += XLOG_BLCKSZ)
25152516
{
25162517
errno = 0;
@@ -2530,7 +2531,6 @@ XLogFileInit(uint32 log, uint32 seg,
25302531
errmsg("could not write to file \"%s\": %m", tmppath)));
25312532
}
25322533
}
2533-
pfree(zbuffer);
25342534

25352535
if (pg_fsync(fd) != 0)
25362536
ereport(ERROR,

src/backend/storage/page/bufpage.c

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "postgres.h"
1616

1717
#include "access/htup.h"
18+
#include "access/itup.h"
1819

1920

2021
/* ----------------------------------------------------------------
@@ -362,8 +363,6 @@ PageRepairFragmentation(Page page)
362363
Offset pd_lower = ((PageHeader) page)->pd_lower;
363364
Offset pd_upper = ((PageHeader) page)->pd_upper;
364365
Offset pd_special = ((PageHeader) page)->pd_special;
365-
itemIdSort itemidbase,
366-
itemidptr;
367366
ItemId lp;
368367
int nline,
369368
nstorage,
@@ -413,10 +412,11 @@ PageRepairFragmentation(Page page)
413412
((PageHeader) page)->pd_upper = pd_special;
414413
}
415414
else
416-
{ /* nstorage != 0 */
415+
{
417416
/* Need to compact the page the hard way */
418-
itemidbase = (itemIdSort) palloc(sizeof(itemIdSortData) * nstorage);
419-
itemidptr = itemidbase;
417+
itemIdSortData itemidbase[MaxHeapTuplesPerPage];
418+
itemIdSort itemidptr = itemidbase;
419+
420420
totallen = 0;
421421
for (i = 0; i < nline; i++)
422422
{
@@ -461,8 +461,6 @@ PageRepairFragmentation(Page page)
461461
}
462462

463463
((PageHeader) page)->pd_upper = upper;
464-
465-
pfree(itemidbase);
466464
}
467465

468466
/* Set hint bit for PageAddItem */
@@ -711,8 +709,8 @@ PageIndexMultiDelete(Page page, OffsetNumber *itemnos, int nitems)
711709
Offset pd_lower = phdr->pd_lower;
712710
Offset pd_upper = phdr->pd_upper;
713711
Offset pd_special = phdr->pd_special;
714-
itemIdSort itemidbase,
715-
itemidptr;
712+
itemIdSortData itemidbase[MaxIndexTuplesPerPage];
713+
itemIdSort itemidptr;
716714
ItemId lp;
717715
int nline,
718716
nused;
@@ -724,6 +722,8 @@ PageIndexMultiDelete(Page page, OffsetNumber *itemnos, int nitems)
724722
int nextitm;
725723
OffsetNumber offnum;
726724

725+
Assert(nitems < MaxIndexTuplesPerPage);
726+
727727
/*
728728
* If there aren't very many items to delete, then retail
729729
* PageIndexTupleDelete is the best way. Delete the items in reverse
@@ -758,7 +758,6 @@ PageIndexMultiDelete(Page page, OffsetNumber *itemnos, int nitems)
758758
* still validity-checking.
759759
*/
760760
nline = PageGetMaxOffsetNumber(page);
761-
itemidbase = (itemIdSort) palloc(sizeof(itemIdSortData) * nline);
762761
itemidptr = itemidbase;
763762
totallen = 0;
764763
nused = 0;
@@ -824,6 +823,4 @@ PageIndexMultiDelete(Page page, OffsetNumber *itemnos, int nitems)
824823

825824
phdr->pd_lower = SizeOfPageHeaderData + nused * sizeof(ItemIdData);
826825
phdr->pd_upper = upper;
827-
828-
pfree(itemidbase);
829826
}

0 commit comments

Comments
 (0)