Skip to content

Commit a45c70a

Browse files
committed
Fix double-XLogBeginInsert call in GIN page splits.
If data checksums or wal_log_hints is on, and a GIN page is split, the code to find a new, empty, block was called after having already called XLogBeginInsert(). That causes an assertion failure or PANIC, if finding the new block involves updating a FSM page that had not been modified since last checkpoint, because that update is WAL-logged, which calls XLogBeginInsert again. Nested XLogBeginInsert calls are not supported. To fix, rearrange GIN code so that XLogBeginInsert is called later, after finding the victim buffers. Reported by Jeff Janes.
1 parent b36805f commit a45c70a

File tree

3 files changed

+11
-9
lines changed

3 files changed

+11
-9
lines changed

src/backend/access/gin/ginbtree.c

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -358,20 +358,15 @@ ginPlaceToPage(GinBtree btree, GinBtreeStack *stack,
358358
* placeToPage can register some data to the WAL record.
359359
*
360360
* If placeToPage returns INSERTED, placeToPage has already called
361-
* START_CRIT_SECTION(), and we're responsible for calling
362-
* END_CRIT_SECTION. When it returns INSERTED, it is also responsible for
363-
* registering any data required to replay the operation with
364-
* XLogRegisterData(0, ...). It may only add data to block index 0; the
365-
* main data of the WAL record is reserved for this function.
361+
* START_CRIT_SECTION() and XLogBeginInsert(), and registered any data
362+
* required to replay the operation, in block index 0. We're responsible
363+
* for filling in the main data portion of the WAL record, calling
364+
* XLogInsert(), and END_CRIT_SECTION.
366365
*
367366
* If placeToPage returns SPLIT, we're wholly responsible for WAL logging.
368367
* Splits happen infrequently, so we just make a full-page image of all
369368
* the pages involved.
370369
*/
371-
372-
if (RelationNeedsWAL(btree->index))
373-
XLogBeginInsert();
374-
375370
rc = btree->placeToPage(btree, stack->buffer, stack,
376371
insertdata, updateblkno,
377372
&newlpage, &newrpage);
@@ -558,6 +553,8 @@ ginPlaceToPage(GinBtree btree, GinBtreeStack *stack,
558553
{
559554
XLogRecPtr recptr;
560555

556+
XLogBeginInsert();
557+
561558
/*
562559
* We just take full page images of all the split pages. Splits
563560
* are uncommon enough that it's not worth complicating the code

src/backend/access/gin/gindatapage.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -600,7 +600,10 @@ dataPlaceToPageLeaf(GinBtree btree, Buffer buf, GinBtreeStack *stack,
600600
*/
601601
MemoryContextSwitchTo(oldCxt);
602602
if (RelationNeedsWAL(btree->index))
603+
{
604+
XLogBeginInsert();
603605
registerLeafRecompressWALData(buf, leaf);
606+
}
604607
START_CRIT_SECTION();
605608
dataPlaceToPageLeafRecompress(buf, leaf);
606609

@@ -1120,6 +1123,7 @@ dataPlaceToPageInternal(GinBtree btree, Buffer buf, GinBtreeStack *stack,
11201123
data.offset = off;
11211124
data.newitem = *pitem;
11221125

1126+
XLogBeginInsert();
11231127
XLogRegisterBuffer(0, buf, REGBUF_STANDARD);
11241128
XLogRegisterBufData(0, (char *) &data,
11251129
sizeof(ginxlogInsertDataInternal));

src/backend/access/gin/ginentrypage.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -557,6 +557,7 @@ entryPlaceToPage(GinBtree btree, Buffer buf, GinBtreeStack *stack,
557557
data.isDelete = insertData->isDelete;
558558
data.offset = off;
559559

560+
XLogBeginInsert();
560561
XLogRegisterBuffer(0, buf, REGBUF_STANDARD);
561562
XLogRegisterBufData(0, (char *) &data,
562563
offsetof(ginxlogInsertEntry, tuple));

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