Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
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)