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

+6-9
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

+4
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

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