mirror of
https://git.postgresql.org/git/postgresql.git
synced 2025-01-06 15:24:56 +08:00
Avoid allocations in critical sections.
If a palloc in a critical section fails, it becomes a PANIC.
This commit is contained in:
parent
0de9963b0b
commit
af7004ed6c
@ -1828,8 +1828,10 @@ _bt_newroot(Relation rel, Buffer lbuf, Buffer rbuf)
|
||||
BTPageOpaque rootopaque;
|
||||
ItemId itemid;
|
||||
IndexTuple item;
|
||||
Size itemsz;
|
||||
IndexTuple new_item;
|
||||
IndexTuple left_item;
|
||||
Size left_item_sz;
|
||||
IndexTuple right_item;
|
||||
Size right_item_sz;
|
||||
Buffer metabuf;
|
||||
Page metapg;
|
||||
BTMetaPageData *metad;
|
||||
@ -1848,6 +1850,26 @@ _bt_newroot(Relation rel, Buffer lbuf, Buffer rbuf)
|
||||
metapg = BufferGetPage(metabuf);
|
||||
metad = BTPageGetMeta(metapg);
|
||||
|
||||
/*
|
||||
* Create downlink item for left page (old root). Since this will be the
|
||||
* first item in a non-leaf page, it implicitly has minus-infinity key
|
||||
* value, so we need not store any actual key in it.
|
||||
*/
|
||||
left_item_sz = sizeof(IndexTupleData);
|
||||
left_item = (IndexTuple) palloc(left_item_sz);
|
||||
left_item->t_info = left_item_sz;
|
||||
ItemPointerSet(&(left_item->t_tid), lbkno, P_HIKEY);
|
||||
|
||||
/*
|
||||
* Create downlink item for right page. The key for it is obtained from
|
||||
* the "high key" position in the left page.
|
||||
*/
|
||||
itemid = PageGetItemId(lpage, P_HIKEY);
|
||||
right_item_sz = ItemIdGetLength(itemid);
|
||||
item = (IndexTuple) PageGetItem(lpage, itemid);
|
||||
right_item = CopyIndexTuple(item);
|
||||
ItemPointerSet(&(right_item->t_tid), rbkno, P_HIKEY);
|
||||
|
||||
/* NO EREPORT(ERROR) from here till newroot op is logged */
|
||||
START_CRIT_SECTION();
|
||||
|
||||
@ -1865,16 +1887,6 @@ _bt_newroot(Relation rel, Buffer lbuf, Buffer rbuf)
|
||||
metad->btm_fastroot = rootblknum;
|
||||
metad->btm_fastlevel = rootopaque->btpo.level;
|
||||
|
||||
/*
|
||||
* Create downlink item for left page (old root). Since this will be the
|
||||
* first item in a non-leaf page, it implicitly has minus-infinity key
|
||||
* value, so we need not store any actual key in it.
|
||||
*/
|
||||
itemsz = sizeof(IndexTupleData);
|
||||
new_item = (IndexTuple) palloc(itemsz);
|
||||
new_item->t_info = itemsz;
|
||||
ItemPointerSet(&(new_item->t_tid), lbkno, P_HIKEY);
|
||||
|
||||
/*
|
||||
* Insert the left page pointer into the new root page. The root page is
|
||||
* the rightmost page on its level so there is no "high key" in it; the
|
||||
@ -1883,32 +1895,20 @@ _bt_newroot(Relation rel, Buffer lbuf, Buffer rbuf)
|
||||
* Note: we *must* insert the two items in item-number order, for the
|
||||
* benefit of _bt_restore_page().
|
||||
*/
|
||||
if (PageAddItem(rootpage, (Item) new_item, itemsz, P_HIKEY,
|
||||
if (PageAddItem(rootpage, (Item) left_item, left_item_sz, P_HIKEY,
|
||||
false, false) == InvalidOffsetNumber)
|
||||
elog(PANIC, "failed to add leftkey to new root page"
|
||||
" while splitting block %u of index \"%s\"",
|
||||
BufferGetBlockNumber(lbuf), RelationGetRelationName(rel));
|
||||
pfree(new_item);
|
||||
|
||||
/*
|
||||
* Create downlink item for right page. The key for it is obtained from
|
||||
* the "high key" position in the left page.
|
||||
*/
|
||||
itemid = PageGetItemId(lpage, P_HIKEY);
|
||||
itemsz = ItemIdGetLength(itemid);
|
||||
item = (IndexTuple) PageGetItem(lpage, itemid);
|
||||
new_item = CopyIndexTuple(item);
|
||||
ItemPointerSet(&(new_item->t_tid), rbkno, P_HIKEY);
|
||||
|
||||
/*
|
||||
* insert the right page pointer into the new root page.
|
||||
*/
|
||||
if (PageAddItem(rootpage, (Item) new_item, itemsz, P_FIRSTKEY,
|
||||
if (PageAddItem(rootpage, (Item) right_item, right_item_sz, P_FIRSTKEY,
|
||||
false, false) == InvalidOffsetNumber)
|
||||
elog(PANIC, "failed to add rightkey to new root page"
|
||||
" while splitting block %u of index \"%s\"",
|
||||
BufferGetBlockNumber(lbuf), RelationGetRelationName(rel));
|
||||
pfree(new_item);
|
||||
|
||||
MarkBufferDirty(rootbuf);
|
||||
MarkBufferDirty(metabuf);
|
||||
@ -1956,6 +1956,9 @@ _bt_newroot(Relation rel, Buffer lbuf, Buffer rbuf)
|
||||
/* done with metapage */
|
||||
_bt_relbuf(rel, metabuf);
|
||||
|
||||
pfree(left_item);
|
||||
pfree(right_item);
|
||||
|
||||
return rootbuf;
|
||||
}
|
||||
|
||||
|
@ -2289,6 +2289,7 @@ XLogFileInit(uint32 log, uint32 seg,
|
||||
{
|
||||
char path[MAXPGPATH];
|
||||
char tmppath[MAXPGPATH];
|
||||
char zbuffer_raw[BLCKSZ + MAXIMUM_ALIGNOF];
|
||||
char *zbuffer;
|
||||
uint32 installed_log;
|
||||
uint32 installed_seg;
|
||||
@ -2346,11 +2347,11 @@ XLogFileInit(uint32 log, uint32 seg,
|
||||
* fdatasync(2) or O_DSYNC will be sufficient to sync future writes to the
|
||||
* log file.
|
||||
*
|
||||
* Note: palloc zbuffer, instead of just using a local char array, to
|
||||
* ensure it is reasonably well-aligned; this may save a few cycles
|
||||
* transferring data to the kernel.
|
||||
* Note: ensure the buffer is reasonably well-aligned; this may save a few
|
||||
* cycles transferring data to the kernel.
|
||||
*/
|
||||
zbuffer = (char *) palloc0(XLOG_BLCKSZ);
|
||||
zbuffer = (char *) MAXALIGN(zbuffer_raw);
|
||||
memset(zbuffer, 0, BLCKSZ);
|
||||
for (nbytes = 0; nbytes < XLogSegSize; nbytes += XLOG_BLCKSZ)
|
||||
{
|
||||
errno = 0;
|
||||
@ -2370,7 +2371,6 @@ XLogFileInit(uint32 log, uint32 seg,
|
||||
errmsg("could not write to file \"%s\": %m", tmppath)));
|
||||
}
|
||||
}
|
||||
pfree(zbuffer);
|
||||
|
||||
if (pg_fsync(fd) != 0)
|
||||
ereport(ERROR,
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "postgres.h"
|
||||
|
||||
#include "access/htup.h"
|
||||
#include "access/itup.h"
|
||||
#include "storage/bufpage.h"
|
||||
|
||||
|
||||
@ -363,8 +364,6 @@ PageRepairFragmentation(Page page)
|
||||
Offset pd_lower = ((PageHeader) page)->pd_lower;
|
||||
Offset pd_upper = ((PageHeader) page)->pd_upper;
|
||||
Offset pd_special = ((PageHeader) page)->pd_special;
|
||||
itemIdSort itemidbase,
|
||||
itemidptr;
|
||||
ItemId lp;
|
||||
int nline,
|
||||
nstorage,
|
||||
@ -414,10 +413,11 @@ PageRepairFragmentation(Page page)
|
||||
((PageHeader) page)->pd_upper = pd_special;
|
||||
}
|
||||
else
|
||||
{ /* nstorage != 0 */
|
||||
{
|
||||
/* Need to compact the page the hard way */
|
||||
itemidbase = (itemIdSort) palloc(sizeof(itemIdSortData) * nstorage);
|
||||
itemidptr = itemidbase;
|
||||
itemIdSortData itemidbase[MaxHeapTuplesPerPage];
|
||||
itemIdSort itemidptr = itemidbase;
|
||||
|
||||
totallen = 0;
|
||||
for (i = 0; i < nline; i++)
|
||||
{
|
||||
@ -462,8 +462,6 @@ PageRepairFragmentation(Page page)
|
||||
}
|
||||
|
||||
((PageHeader) page)->pd_upper = upper;
|
||||
|
||||
pfree(itemidbase);
|
||||
}
|
||||
|
||||
/* Set hint bit for PageAddItem */
|
||||
@ -712,8 +710,8 @@ PageIndexMultiDelete(Page page, OffsetNumber *itemnos, int nitems)
|
||||
Offset pd_lower = phdr->pd_lower;
|
||||
Offset pd_upper = phdr->pd_upper;
|
||||
Offset pd_special = phdr->pd_special;
|
||||
itemIdSort itemidbase,
|
||||
itemidptr;
|
||||
itemIdSortData itemidbase[MaxIndexTuplesPerPage];
|
||||
itemIdSort itemidptr;
|
||||
ItemId lp;
|
||||
int nline,
|
||||
nused;
|
||||
@ -725,6 +723,8 @@ PageIndexMultiDelete(Page page, OffsetNumber *itemnos, int nitems)
|
||||
int nextitm;
|
||||
OffsetNumber offnum;
|
||||
|
||||
Assert(nitems < MaxIndexTuplesPerPage);
|
||||
|
||||
/*
|
||||
* If there aren't very many items to delete, then retail
|
||||
* PageIndexTupleDelete is the best way. Delete the items in reverse
|
||||
@ -759,7 +759,6 @@ PageIndexMultiDelete(Page page, OffsetNumber *itemnos, int nitems)
|
||||
* still validity-checking.
|
||||
*/
|
||||
nline = PageGetMaxOffsetNumber(page);
|
||||
itemidbase = (itemIdSort) palloc(sizeof(itemIdSortData) * nline);
|
||||
itemidptr = itemidbase;
|
||||
totallen = 0;
|
||||
nused = 0;
|
||||
@ -825,6 +824,4 @@ PageIndexMultiDelete(Page page, OffsetNumber *itemnos, int nitems)
|
||||
|
||||
phdr->pd_lower = SizeOfPageHeaderData + nused * sizeof(ItemIdData);
|
||||
phdr->pd_upper = upper;
|
||||
|
||||
pfree(itemidbase);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user