Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit2b196f0

Browse files
committed
Fix transient clobbering of shared buffers during WAL replay.
RestoreBkpBlocks was in the habit of zeroing and refilling the targetbuffer; which was perfectly safe when the code was written, but is unsafeduring Hot Standby operation. The reason is that we have coding rulesthat allow backends to continue accessing a tuple in a heap relation whileholding only a pin on its buffer. Such a backend could see transientlyzeroed data, if WAL replay had occasion to change other data on the page.This has been shown to be the cause of bug #6425 from Duncan Rance (whodeserves kudos for developing a sufficiently-reproducible test case) aswell as Bridget Frey's re-report of bug #6200. It most likely explains theoriginal report as well, though we don't yet have confirmation of that.To fix, change the code so that only bytes that are supposed to change willchange, even transiently. This actually saves cycles in RestoreBkpBlocks,since it's not writing the same bytes twice.Also fix seq_redo, which has the same disease, though it has to work a bitharder to meet the requirement.So far as I can tell, no other WAL replay routines have this type of bug.In particular, the index-related replay routines, which would certainly bebroken if they had to meet the same standard, are not at risk because wedo not have coding rules that allow access to an index page when notholding a buffer lock on it.Back-patch to 9.0 where Hot Standby was added.
1 parenta286b6f commit2b196f0

File tree

2 files changed

+24
-9
lines changed

2 files changed

+24
-9
lines changed

‎src/backend/access/transam/xlog.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3556,9 +3556,9 @@ RestoreBkpBlocks(XLogRecPtr lsn, XLogRecord *record, bool cleanup)
35563556
}
35573557
else
35583558
{
3559-
/* must zero-fill the hole */
3560-
MemSet((char*)page,0,BLCKSZ);
35613559
memcpy((char*)page,blk,bkpb.hole_offset);
3560+
/* must zero-fill the hole */
3561+
MemSet((char*)page+bkpb.hole_offset,0,bkpb.hole_length);
35623562
memcpy((char*)page+ (bkpb.hole_offset+bkpb.hole_length),
35633563
blk+bkpb.hole_offset,
35643564
BLCKSZ- (bkpb.hole_offset+bkpb.hole_length));

‎src/backend/commands/sequence.c

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1358,6 +1358,7 @@ seq_redo(XLogRecPtr lsn, XLogRecord *record)
13581358
uint8info=record->xl_info& ~XLR_INFO_MASK;
13591359
Bufferbuffer;
13601360
Pagepage;
1361+
Pagelocalpage;
13611362
char*item;
13621363
Sizeitemsz;
13631364
xl_seq_rec*xlrec= (xl_seq_rec*)XLogRecGetData(record);
@@ -1373,23 +1374,37 @@ seq_redo(XLogRecPtr lsn, XLogRecord *record)
13731374
Assert(BufferIsValid(buffer));
13741375
page= (Page)BufferGetPage(buffer);
13751376

1376-
/* Always reinit the page and reinstall the magic number */
1377-
/* See comments in DefineSequence */
1378-
PageInit((Page)page,BufferGetPageSize(buffer),sizeof(sequence_magic));
1379-
sm= (sequence_magic*)PageGetSpecialPointer(page);
1377+
/*
1378+
* We must always reinit the page and reinstall the magic number (see
1379+
* comments in fill_seq_with_data). However, since this WAL record type
1380+
* is also used for updating sequences, it's possible that a hot-standby
1381+
* backend is examining the page concurrently; so we mustn't transiently
1382+
* trash the buffer. The solution is to build the correct new page
1383+
* contents in local workspace and then memcpy into the buffer. Then
1384+
* only bytes that are supposed to change will change, even transiently.
1385+
* We must palloc the local page for alignment reasons.
1386+
*/
1387+
localpage= (Page)palloc(BufferGetPageSize(buffer));
1388+
1389+
PageInit(localpage,BufferGetPageSize(buffer),sizeof(sequence_magic));
1390+
sm= (sequence_magic*)PageGetSpecialPointer(localpage);
13801391
sm->magic=SEQ_MAGIC;
13811392

13821393
item= (char*)xlrec+sizeof(xl_seq_rec);
13831394
itemsz=record->xl_len-sizeof(xl_seq_rec);
13841395
itemsz=MAXALIGN(itemsz);
1385-
if (PageAddItem(page, (Item)item,itemsz,
1396+
if (PageAddItem(localpage, (Item)item,itemsz,
13861397
FirstOffsetNumber, false, false)==InvalidOffsetNumber)
13871398
elog(PANIC,"seq_redo: failed to add item to page");
13881399

1389-
PageSetLSN(page,lsn);
1390-
PageSetTLI(page,ThisTimeLineID);
1400+
PageSetLSN(localpage,lsn);
1401+
PageSetTLI(localpage,ThisTimeLineID);
1402+
1403+
memcpy(page,localpage,BufferGetPageSize(buffer));
13911404
MarkBufferDirty(buffer);
13921405
UnlockReleaseBuffer(buffer);
1406+
1407+
pfree(localpage);
13931408
}
13941409

13951410
void

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp