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)
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