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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy