Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 1891a4b

Browse files
committed
Avoid allocations in critical sections.
If a palloc in a critical section fails, it becomes a PANIC.
1 parent d359f71 commit 1891a4b

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
@@ -1845,8 +1845,10 @@ _bt_newroot(Relation rel, Buffer lbuf, Buffer rbuf)
18451845
BTPageOpaque rootopaque;
18461846
ItemId itemid;
18471847
IndexTuple item;
1848-
Size itemsz;
1849-
IndexTuple new_item;
1848+
IndexTuple left_item;
1849+
Size left_item_sz;
1850+
IndexTuple right_item;
1851+
Size right_item_sz;
18501852
Buffer metabuf;
18511853
Page metapg;
18521854
BTMetaPageData *metad;
@@ -1865,6 +1867,26 @@ _bt_newroot(Relation rel, Buffer lbuf, Buffer rbuf)
18651867
metapg = BufferGetPage(metabuf);
18661868
metad = BTPageGetMeta(metapg);
18671869

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

@@ -1882,16 +1904,6 @@ _bt_newroot(Relation rel, Buffer lbuf, Buffer rbuf)
18821904
metad->btm_fastroot = rootblknum;
18831905
metad->btm_fastlevel = rootopaque->btpo.level;
18841906

1885-
/*
1886-
* Create downlink item for left page (old root). Since this will be the
1887-
* first item in a non-leaf page, it implicitly has minus-infinity key
1888-
* value, so we need not store any actual key in it.
1889-
*/
1890-
itemsz = sizeof(IndexTupleData);
1891-
new_item = (IndexTuple) palloc(itemsz);
1892-
new_item->t_info = itemsz;
1893-
ItemPointerSet(&(new_item->t_tid), lbkno, P_HIKEY);
1894-
18951907
/*
18961908
* Insert the left page pointer into the new root page. The root page is
18971909
* the rightmost page on its level so there is no "high key" in it; the
@@ -1900,32 +1912,20 @@ _bt_newroot(Relation rel, Buffer lbuf, Buffer rbuf)
19001912
* Note: we *must* insert the two items in item-number order, for the
19011913
* benefit of _bt_restore_page().
19021914
*/
1903-
if (PageAddItem(rootpage, (Item) new_item, itemsz, P_HIKEY,
1915+
if (PageAddItem(rootpage, (Item) left_item, left_item_sz, P_HIKEY,
19041916
false, false) == InvalidOffsetNumber)
19051917
elog(PANIC, "failed to add leftkey to new root page"
19061918
" while splitting block %u of index \"%s\"",
19071919
BufferGetBlockNumber(lbuf), RelationGetRelationName(rel));
1908-
pfree(new_item);
1909-
1910-
/*
1911-
* Create downlink item for right page. The key for it is obtained from
1912-
* the "high key" position in the left page.
1913-
*/
1914-
itemid = PageGetItemId(lpage, P_HIKEY);
1915-
itemsz = ItemIdGetLength(itemid);
1916-
item = (IndexTuple) PageGetItem(lpage, itemid);
1917-
new_item = CopyIndexTuple(item);
1918-
ItemPointerSet(&(new_item->t_tid), rbkno, P_HIKEY);
19191920

19201921
/*
19211922
* insert the right page pointer into the new root page.
19221923
*/
1923-
if (PageAddItem(rootpage, (Item) new_item, itemsz, P_FIRSTKEY,
1924+
if (PageAddItem(rootpage, (Item) right_item, right_item_sz, P_FIRSTKEY,
19241925
false, false) == InvalidOffsetNumber)
19251926
elog(PANIC, "failed to add rightkey to new root page"
19261927
" while splitting block %u of index \"%s\"",
19271928
BufferGetBlockNumber(lbuf), RelationGetRelationName(rel));
1928-
pfree(new_item);
19291929

19301930
MarkBufferDirty(rootbuf);
19311931
MarkBufferDirty(metabuf);
@@ -1971,6 +1971,9 @@ _bt_newroot(Relation rel, Buffer lbuf, Buffer rbuf)
19711971
/* done with metapage */
19721972
_bt_relbuf(rel, metabuf);
19731973

1974+
pfree(left_item);
1975+
pfree(right_item);
1976+
19741977
return rootbuf;
19751978
}
19761979

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
@@ -739,9 +739,8 @@ XLogInsert(RmgrId rmid, uint8 info, XLogRecData *rdata)
739739

740740
if (rechdr == NULL)
741741
{
742-
rechdr = malloc(SizeOfXLogRecord);
743-
if (rechdr == NULL)
744-
elog(ERROR, "out of memory");
742+
static char rechdrbuf[SizeOfXLogRecord + MAXIMUM_ALIGNOF];
743+
rechdr = (XLogRecord *) MAXALIGN(&rechdrbuf);
745744
MemSet(rechdr, 0, SizeOfXLogRecord);
746745
}
747746

@@ -2248,6 +2247,7 @@ XLogFileInit(XLogSegNo logsegno, bool *use_existent, bool use_lock)
22482247
{
22492248
char path[MAXPGPATH];
22502249
char tmppath[MAXPGPATH];
2250+
char zbuffer_raw[BLCKSZ + MAXIMUM_ALIGNOF];
22512251
char *zbuffer;
22522252
XLogSegNo installed_segno;
22532253
int max_advance;
@@ -2286,16 +2286,6 @@ XLogFileInit(XLogSegNo logsegno, bool *use_existent, bool use_lock)
22862286

22872287
unlink(tmppath);
22882288

2289-
/*
2290-
* Allocate a buffer full of zeros. This is done before opening the file
2291-
* so that we don't leak the file descriptor if palloc fails.
2292-
*
2293-
* Note: palloc zbuffer, instead of just using a local char array, to
2294-
* ensure it is reasonably well-aligned; this may save a few cycles
2295-
* transferring data to the kernel.
2296-
*/
2297-
zbuffer = (char *) palloc0(XLOG_BLCKSZ);
2298-
22992289
/* do not use get_sync_bit() here --- want to fsync only at end of fill */
23002290
fd = BasicOpenFile(tmppath, O_RDWR | O_CREAT | O_EXCL | PG_BINARY,
23012291
S_IRUSR | S_IWUSR);
@@ -2312,7 +2302,12 @@ XLogFileInit(XLogSegNo logsegno, bool *use_existent, bool use_lock)
23122302
* fsync below) that all the indirect blocks are down on disk. Therefore,
23132303
* fdatasync(2) or O_DSYNC will be sufficient to sync future writes to the
23142304
* log file.
2305+
*
2306+
* Note: ensure the buffer is reasonably well-aligned; this may save a few
2307+
* cycles transferring data to the kernel.
23152308
*/
2309+
zbuffer = (char *) MAXALIGN(zbuffer_raw);
2310+
memset(zbuffer, 0, BLCKSZ);
23162311
for (nbytes = 0; nbytes < XLogSegSize; nbytes += XLOG_BLCKSZ)
23172312
{
23182313
errno = 0;
@@ -2335,7 +2330,6 @@ XLogFileInit(XLogSegNo logsegno, bool *use_existent, bool use_lock)
23352330
errmsg("could not write to file \"%s\": %m", tmppath)));
23362331
}
23372332
}
2338-
pfree(zbuffer);
23392333

23402334
if (pg_fsync(fd) != 0)
23412335
{

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/memutils.h"
@@ -418,8 +419,6 @@ PageRepairFragmentation(Page page)
418419
Offset pd_lower = ((PageHeader) page)->pd_lower;
419420
Offset pd_upper = ((PageHeader) page)->pd_upper;
420421
Offset pd_special = ((PageHeader) page)->pd_special;
421-
itemIdSort itemidbase,
422-
itemidptr;
423422
ItemId lp;
424423
int nline,
425424
nstorage,
@@ -469,10 +468,11 @@ PageRepairFragmentation(Page page)
469468
((PageHeader) page)->pd_upper = pd_special;
470469
}
471470
else
472-
{ /* nstorage != 0 */
471+
{
473472
/* Need to compact the page the hard way */
474-
itemidbase = (itemIdSort) palloc(sizeof(itemIdSortData) * nstorage);
475-
itemidptr = itemidbase;
473+
itemIdSortData itemidbase[MaxHeapTuplesPerPage];
474+
itemIdSort itemidptr = itemidbase;
475+
476476
totallen = 0;
477477
for (i = 0; i < nline; i++)
478478
{
@@ -517,8 +517,6 @@ PageRepairFragmentation(Page page)
517517
}
518518

519519
((PageHeader) page)->pd_upper = upper;
520-
521-
pfree(itemidbase);
522520
}
523521

524522
/* Set hint bit for PageAddItem */
@@ -767,8 +765,8 @@ PageIndexMultiDelete(Page page, OffsetNumber *itemnos, int nitems)
767765
Offset pd_lower = phdr->pd_lower;
768766
Offset pd_upper = phdr->pd_upper;
769767
Offset pd_special = phdr->pd_special;
770-
itemIdSort itemidbase,
771-
itemidptr;
768+
itemIdSortData itemidbase[MaxIndexTuplesPerPage];
769+
itemIdSort itemidptr;
772770
ItemId lp;
773771
int nline,
774772
nused;
@@ -780,6 +778,8 @@ PageIndexMultiDelete(Page page, OffsetNumber *itemnos, int nitems)
780778
int nextitm;
781779
OffsetNumber offnum;
782780

781+
Assert(nitems < MaxIndexTuplesPerPage);
782+
783783
/*
784784
* If there aren't very many items to delete, then retail
785785
* PageIndexTupleDelete is the best way. Delete the items in reverse
@@ -814,7 +814,6 @@ PageIndexMultiDelete(Page page, OffsetNumber *itemnos, int nitems)
814814
* still validity-checking.
815815
*/
816816
nline = PageGetMaxOffsetNumber(page);
817-
itemidbase = (itemIdSort) palloc(sizeof(itemIdSortData) * nline);
818817
itemidptr = itemidbase;
819818
totallen = 0;
820819
nused = 0;
@@ -880,8 +879,6 @@ PageIndexMultiDelete(Page page, OffsetNumber *itemnos, int nitems)
880879

881880
phdr->pd_lower = SizeOfPageHeaderData + nused * sizeof(ItemIdData);
882881
phdr->pd_upper = upper;
883-
884-
pfree(itemidbase);
885882
}
886883

887884

0 commit comments

Comments
 (0)