Skip to content

Commit 877b088

Browse files
committed
Avoid allocations in critical sections.
If a palloc in a critical section fails, it becomes a PANIC.
1 parent c7b3539 commit 877b088

File tree

4 files changed

+49
-57
lines changed

4 files changed

+49
-57
lines changed

src/backend/access/nbtree/nbtinsert.c

Lines changed: 29 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1995,8 +1995,10 @@ _bt_newroot(Relation rel, Buffer lbuf, Buffer rbuf)
19951995
BTPageOpaque lopaque;
19961996
ItemId itemid;
19971997
IndexTuple item;
1998-
Size itemsz;
1999-
IndexTuple new_item;
1998+
IndexTuple left_item;
1999+
Size left_item_sz;
2000+
IndexTuple right_item;
2001+
Size right_item_sz;
20002002
Buffer metabuf;
20012003
Page metapg;
20022004
BTMetaPageData *metad;
@@ -2016,6 +2018,26 @@ _bt_newroot(Relation rel, Buffer lbuf, Buffer rbuf)
20162018
metapg = BufferGetPage(metabuf);
20172019
metad = BTPageGetMeta(metapg);
20182020

2021+
/*
2022+
* Create downlink item for left page (old root). Since this will be the
2023+
* first item in a non-leaf page, it implicitly has minus-infinity key
2024+
* value, so we need not store any actual key in it.
2025+
*/
2026+
left_item_sz = sizeof(IndexTupleData);
2027+
left_item = (IndexTuple) palloc(left_item_sz);
2028+
left_item->t_info = left_item_sz;
2029+
ItemPointerSet(&(left_item->t_tid), lbkno, P_HIKEY);
2030+
2031+
/*
2032+
* Create downlink item for right page. The key for it is obtained from
2033+
* the "high key" position in the left page.
2034+
*/
2035+
itemid = PageGetItemId(lpage, P_HIKEY);
2036+
right_item_sz = ItemIdGetLength(itemid);
2037+
item = (IndexTuple) PageGetItem(lpage, itemid);
2038+
right_item = CopyIndexTuple(item);
2039+
ItemPointerSet(&(right_item->t_tid), rbkno, P_HIKEY);
2040+
20192041
/* NO EREPORT(ERROR) from here till newroot op is logged */
20202042
START_CRIT_SECTION();
20212043

@@ -2033,16 +2055,6 @@ _bt_newroot(Relation rel, Buffer lbuf, Buffer rbuf)
20332055
metad->btm_fastroot = rootblknum;
20342056
metad->btm_fastlevel = rootopaque->btpo.level;
20352057

2036-
/*
2037-
* Create downlink item for left page (old root). Since this will be the
2038-
* first item in a non-leaf page, it implicitly has minus-infinity key
2039-
* value, so we need not store any actual key in it.
2040-
*/
2041-
itemsz = sizeof(IndexTupleData);
2042-
new_item = (IndexTuple) palloc(itemsz);
2043-
new_item->t_info = itemsz;
2044-
ItemPointerSet(&(new_item->t_tid), lbkno, P_HIKEY);
2045-
20462058
/*
20472059
* Insert the left page pointer into the new root page. The root page is
20482060
* the rightmost page on its level so there is no "high key" in it; the
@@ -2051,32 +2063,20 @@ _bt_newroot(Relation rel, Buffer lbuf, Buffer rbuf)
20512063
* Note: we *must* insert the two items in item-number order, for the
20522064
* benefit of _bt_restore_page().
20532065
*/
2054-
if (PageAddItem(rootpage, (Item) new_item, itemsz, P_HIKEY,
2066+
if (PageAddItem(rootpage, (Item) left_item, left_item_sz, P_HIKEY,
20552067
false, false) == InvalidOffsetNumber)
20562068
elog(PANIC, "failed to add leftkey to new root page"
20572069
" while splitting block %u of index \"%s\"",
20582070
BufferGetBlockNumber(lbuf), RelationGetRelationName(rel));
2059-
pfree(new_item);
2060-
2061-
/*
2062-
* Create downlink item for right page. The key for it is obtained from
2063-
* the "high key" position in the left page.
2064-
*/
2065-
itemid = PageGetItemId(lpage, P_HIKEY);
2066-
itemsz = ItemIdGetLength(itemid);
2067-
item = (IndexTuple) PageGetItem(lpage, itemid);
2068-
new_item = CopyIndexTuple(item);
2069-
ItemPointerSet(&(new_item->t_tid), rbkno, P_HIKEY);
20702071

20712072
/*
20722073
* insert the right page pointer into the new root page.
20732074
*/
2074-
if (PageAddItem(rootpage, (Item) new_item, itemsz, P_FIRSTKEY,
2075+
if (PageAddItem(rootpage, (Item) right_item, right_item_sz, P_FIRSTKEY,
20752076
false, false) == InvalidOffsetNumber)
20762077
elog(PANIC, "failed to add rightkey to new root page"
20772078
" while splitting block %u of index \"%s\"",
20782079
BufferGetBlockNumber(lbuf), RelationGetRelationName(rel));
2079-
pfree(new_item);
20802080

20812081
/* Clear the incomplete-split flag in the left child */
20822082
Assert(P_INCOMPLETE_SPLIT(lopaque));
@@ -2129,6 +2129,9 @@ _bt_newroot(Relation rel, Buffer lbuf, Buffer rbuf)
21292129
/* done with metapage */
21302130
_bt_relbuf(rel, metabuf);
21312131

2132+
pfree(left_item);
2133+
pfree(right_item);
2134+
21322135
return rootbuf;
21332136
}
21342137

src/backend/access/spgist/spgdoinsert.c

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

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

180178
/*

src/backend/access/transam/xlog.c

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -859,9 +859,8 @@ XLogInsert(RmgrId rmid, uint8 info, XLogRecData *rdata)
859859

860860
if (rechdr == NULL)
861861
{
862-
rechdr = malloc(SizeOfXLogRecord);
863-
if (rechdr == NULL)
864-
elog(ERROR, "out of memory");
862+
static char rechdrbuf[SizeOfXLogRecord + MAXIMUM_ALIGNOF];
863+
rechdr = (XLogRecord *) MAXALIGN(&rechdrbuf);
865864
MemSet(rechdr, 0, SizeOfXLogRecord);
866865
}
867866

@@ -3080,6 +3079,7 @@ XLogFileInit(XLogSegNo logsegno, bool *use_existent, bool use_lock)
30803079
{
30813080
char path[MAXPGPATH];
30823081
char tmppath[MAXPGPATH];
3082+
char zbuffer_raw[BLCKSZ + MAXIMUM_ALIGNOF];
30833083
char *zbuffer;
30843084
XLogSegNo installed_segno;
30853085
int max_advance;
@@ -3118,16 +3118,6 @@ XLogFileInit(XLogSegNo logsegno, bool *use_existent, bool use_lock)
31183118

31193119
unlink(tmppath);
31203120

3121-
/*
3122-
* Allocate a buffer full of zeros. This is done before opening the file
3123-
* so that we don't leak the file descriptor if palloc fails.
3124-
*
3125-
* Note: palloc zbuffer, instead of just using a local char array, to
3126-
* ensure it is reasonably well-aligned; this may save a few cycles
3127-
* transferring data to the kernel.
3128-
*/
3129-
zbuffer = (char *) palloc0(XLOG_BLCKSZ);
3130-
31313121
/* do not use get_sync_bit() here --- want to fsync only at end of fill */
31323122
fd = BasicOpenFile(tmppath, O_RDWR | O_CREAT | O_EXCL | PG_BINARY,
31333123
S_IRUSR | S_IWUSR);
@@ -3144,7 +3134,12 @@ XLogFileInit(XLogSegNo logsegno, bool *use_existent, bool use_lock)
31443134
* fsync below) that all the indirect blocks are down on disk. Therefore,
31453135
* fdatasync(2) or O_DSYNC will be sufficient to sync future writes to the
31463136
* log file.
3137+
*
3138+
* Note: ensure the buffer is reasonably well-aligned; this may save a few
3139+
* cycles transferring data to the kernel.
31473140
*/
3141+
zbuffer = (char *) MAXALIGN(zbuffer_raw);
3142+
memset(zbuffer, 0, BLCKSZ);
31483143
for (nbytes = 0; nbytes < XLogSegSize; nbytes += XLOG_BLCKSZ)
31493144
{
31503145
errno = 0;
@@ -3167,7 +3162,6 @@ XLogFileInit(XLogSegNo logsegno, bool *use_existent, bool use_lock)
31673162
errmsg("could not write to file \"%s\": %m", tmppath)));
31683163
}
31693164
}
3170-
pfree(zbuffer);
31713165

31723166
if (pg_fsync(fd) != 0)
31733167
{

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_details.h"
18+
#include "access/itup.h"
1819
#include "access/xlog.h"
1920
#include "storage/checksum.h"
2021
#include "utils/memdebug.h"
@@ -433,8 +434,6 @@ PageRepairFragmentation(Page page)
433434
Offset pd_lower = ((PageHeader) page)->pd_lower;
434435
Offset pd_upper = ((PageHeader) page)->pd_upper;
435436
Offset pd_special = ((PageHeader) page)->pd_special;
436-
itemIdSort itemidbase,
437-
itemidptr;
438437
ItemId lp;
439438
int nline,
440439
nstorage,
@@ -484,10 +483,11 @@ PageRepairFragmentation(Page page)
484483
((PageHeader) page)->pd_upper = pd_special;
485484
}
486485
else
487-
{ /* nstorage != 0 */
486+
{
488487
/* Need to compact the page the hard way */
489-
itemidbase = (itemIdSort) palloc(sizeof(itemIdSortData) * nstorage);
490-
itemidptr = itemidbase;
488+
itemIdSortData itemidbase[MaxHeapTuplesPerPage];
489+
itemIdSort itemidptr = itemidbase;
490+
491491
totallen = 0;
492492
for (i = 0; i < nline; i++)
493493
{
@@ -532,8 +532,6 @@ PageRepairFragmentation(Page page)
532532
}
533533

534534
((PageHeader) page)->pd_upper = upper;
535-
536-
pfree(itemidbase);
537535
}
538536

539537
/* Set hint bit for PageAddItem */
@@ -782,8 +780,8 @@ PageIndexMultiDelete(Page page, OffsetNumber *itemnos, int nitems)
782780
Offset pd_lower = phdr->pd_lower;
783781
Offset pd_upper = phdr->pd_upper;
784782
Offset pd_special = phdr->pd_special;
785-
itemIdSort itemidbase,
786-
itemidptr;
783+
itemIdSortData itemidbase[MaxIndexTuplesPerPage];
784+
itemIdSort itemidptr;
787785
ItemId lp;
788786
int nline,
789787
nused;
@@ -795,6 +793,8 @@ PageIndexMultiDelete(Page page, OffsetNumber *itemnos, int nitems)
795793
int nextitm;
796794
OffsetNumber offnum;
797795

796+
Assert(nitems < MaxIndexTuplesPerPage);
797+
798798
/*
799799
* If there aren't very many items to delete, then retail
800800
* PageIndexTupleDelete is the best way. Delete the items in reverse
@@ -829,7 +829,6 @@ PageIndexMultiDelete(Page page, OffsetNumber *itemnos, int nitems)
829829
* still validity-checking.
830830
*/
831831
nline = PageGetMaxOffsetNumber(page);
832-
itemidbase = (itemIdSort) palloc(sizeof(itemIdSortData) * nline);
833832
itemidptr = itemidbase;
834833
totallen = 0;
835834
nused = 0;
@@ -895,8 +894,6 @@ PageIndexMultiDelete(Page page, OffsetNumber *itemnos, int nitems)
895894

896895
phdr->pd_lower = SizeOfPageHeaderData + nused * sizeof(ItemIdData);
897896
phdr->pd_upper = upper;
898-
899-
pfree(itemidbase);
900897
}
901898

902899

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