Skip to content

Commit 1b87e24

Browse files
committed
Change xlog page-header format to include StartUpID. Use the SUI to
detect case that next page in log came from an older run than the prior page. This avoids the necessity to re-zero the log after recovery from a crash, which is good because we need not risk destroying valuable log information. This forces another initdb since yesterday :-(. Need to get that log reset utility done...
1 parent e2f9138 commit 1b87e24

File tree

2 files changed

+63
-16
lines changed

2 files changed

+63
-16
lines changed

src/backend/access/transam/xlog.c

Lines changed: 54 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
/*-------------------------------------------------------------------------
22
*
33
* xlog.c
4+
* PostgreSQL transaction log manager
45
*
56
*
67
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
78
* Portions Copyright (c) 1994, Regents of the University of California
89
*
9-
* $Header: /cvsroot/pgsql/src/backend/access/transam/xlog.c,v 1.56 2001/03/13 01:17:05 tgl Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/access/transam/xlog.c,v 1.57 2001/03/13 20:32:37 tgl Exp $
1011
*
1112
*-------------------------------------------------------------------------
1213
*/
@@ -344,6 +345,7 @@ static char *readBuf = NULL;
344345
static XLogRecPtr ReadRecPtr;
345346
static XLogRecPtr EndRecPtr;
346347
static XLogRecord *nextRecord = NULL;
348+
static StartUpID lastReadSUI;
347349

348350
static bool InRedo = false;
349351

@@ -355,6 +357,7 @@ static int XLogFileOpen(uint32 log, uint32 seg, bool econt);
355357
static void PreallocXlogFiles(XLogRecPtr endptr);
356358
static void MoveOfflineLogs(uint32 log, uint32 seg);
357359
static XLogRecord *ReadRecord(XLogRecPtr *RecPtr, int emode, char *buffer);
360+
static bool ValidXLOGHeader(XLogPageHeader hdr, int emode, bool checkSUI);
358361
static XLogRecord *ReadCheckpointRecord(XLogRecPtr RecPtr,
359362
const char *whichChkpt,
360363
char *buffer);
@@ -891,6 +894,7 @@ AdvanceXLInsertBuffer(void)
891894
MemSet((char*) Insert->currpage, 0, BLCKSZ);
892895
Insert->currpage->xlp_magic = XLOG_PAGE_MAGIC;
893896
/* Insert->currpage->xlp_info = 0; */ /* done by memset */
897+
Insert->currpage->xlp_sui = ThisStartUpID;
894898

895899
return update_needed;
896900
}
@@ -1498,6 +1502,7 @@ ReadRecord(XLogRecPtr *RecPtr, int emode, char *buffer)
14981502
total_len;
14991503
uint32 targetPageOff;
15001504
unsigned i;
1505+
bool nextmode = false;
15011506

15021507
if (readBuf == NULL)
15031508
{
@@ -1516,6 +1521,7 @@ ReadRecord(XLogRecPtr *RecPtr, int emode, char *buffer)
15161521
if (RecPtr == NULL)
15171522
{
15181523
RecPtr = &tmpRecPtr;
1524+
nextmode = true;
15191525
/* fast case if next record is on same page */
15201526
if (nextRecord != NULL)
15211527
{
@@ -1566,13 +1572,8 @@ ReadRecord(XLogRecPtr *RecPtr, int emode, char *buffer)
15661572
readId, readSeg, readOff);
15671573
goto next_record_is_invalid;
15681574
}
1569-
if (((XLogPageHeader) readBuf)->xlp_magic != XLOG_PAGE_MAGIC)
1570-
{
1571-
elog(emode, "ReadRecord: invalid magic number %u in logfile %u seg %u off %u",
1572-
((XLogPageHeader) readBuf)->xlp_magic,
1573-
readId, readSeg, readOff);
1575+
if (!ValidXLOGHeader((XLogPageHeader) readBuf, emode, nextmode))
15741576
goto next_record_is_invalid;
1575-
}
15761577
}
15771578
if ((((XLogPageHeader) readBuf)->xlp_info & XLP_FIRST_IS_CONTRECORD) &&
15781579
RecPtr->xrecoff % BLCKSZ == SizeOfXLogPHD)
@@ -1651,13 +1652,8 @@ got_record:;
16511652
readId, readSeg, readOff);
16521653
goto next_record_is_invalid;
16531654
}
1654-
if (((XLogPageHeader) readBuf)->xlp_magic != XLOG_PAGE_MAGIC)
1655-
{
1656-
elog(emode, "ReadRecord: invalid magic number %u in logfile %u seg %u off %u",
1657-
((XLogPageHeader) readBuf)->xlp_magic,
1658-
readId, readSeg, readOff);
1655+
if (!ValidXLOGHeader((XLogPageHeader) readBuf, emode, true))
16591656
goto next_record_is_invalid;
1660-
}
16611657
if (!(((XLogPageHeader) readBuf)->xlp_info & XLP_FIRST_IS_CONTRECORD))
16621658
{
16631659
elog(emode, "ReadRecord: there is no ContRecord flag in logfile %u seg %u off %u",
@@ -1719,6 +1715,50 @@ next_record_is_invalid:;
17191715
return NULL;
17201716
}
17211717

1718+
/*
1719+
* Check whether the xlog header of a page just read in looks valid.
1720+
*
1721+
* This is just a convenience subroutine to avoid duplicated code in
1722+
* ReadRecord. It's not intended for use from anywhere else.
1723+
*/
1724+
static bool
1725+
ValidXLOGHeader(XLogPageHeader hdr, int emode, bool checkSUI)
1726+
{
1727+
if (hdr->xlp_magic != XLOG_PAGE_MAGIC)
1728+
{
1729+
elog(emode, "ReadRecord: invalid magic number %04X in logfile %u seg %u off %u",
1730+
hdr->xlp_magic, readId, readSeg, readOff);
1731+
return false;
1732+
}
1733+
if ((hdr->xlp_info & ~XLP_ALL_FLAGS) != 0)
1734+
{
1735+
elog(emode, "ReadRecord: invalid info bits %04X in logfile %u seg %u off %u",
1736+
hdr->xlp_info, readId, readSeg, readOff);
1737+
return false;
1738+
}
1739+
/*
1740+
* We disbelieve a SUI less than the previous page's SUI, or more
1741+
* than a few counts greater. In theory as many as 512 shutdown
1742+
* checkpoint records could appear on a 32K-sized xlog page, so
1743+
* that's the most differential there could legitimately be.
1744+
*
1745+
* Note this check can only be applied when we are reading the next page
1746+
* in sequence, so ReadRecord passes a flag indicating whether to check.
1747+
*/
1748+
if (checkSUI)
1749+
{
1750+
if (hdr->xlp_sui < lastReadSUI ||
1751+
hdr->xlp_sui > lastReadSUI + 512)
1752+
{
1753+
elog(emode, "ReadRecord: out-of-sequence SUI %u (after %u) in logfile %u seg %u off %u",
1754+
hdr->xlp_sui, lastReadSUI, readId, readSeg, readOff);
1755+
return false;
1756+
}
1757+
}
1758+
lastReadSUI = hdr->xlp_sui;
1759+
return true;
1760+
}
1761+
17221762
/*
17231763
* I/O routines for pg_control
17241764
*
@@ -2023,6 +2063,7 @@ BootStrapXLOG(void)
20232063
memset(buffer, 0, BLCKSZ);
20242064
page->xlp_magic = XLOG_PAGE_MAGIC;
20252065
page->xlp_info = 0;
2066+
page->xlp_sui = checkPoint.ThisStartUpID;
20262067
record = (XLogRecord *) ((char *) page + SizeOfXLogPHD);
20272068
record->xl_prev.xlogid = 0;
20282069
record->xl_prev.xrecoff = 0;

src/include/access/xlog.h

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
77
* Portions Copyright (c) 1994, Regents of the University of California
88
*
9-
* $Id: xlog.h,v 1.19 2001/03/13 01:17:06 tgl Exp $
9+
* $Id: xlog.h,v 1.20 2001/03/13 20:32:37 tgl Exp $
1010
*/
1111
#ifndef XLOG_H
1212
#define XLOG_H
@@ -26,6 +26,9 @@
2626
* really:
2727
*
2828
* SizeOfXLogRecord + xl_len + n_backup_blocks * (sizeof(BkpBlock) + BLCKSZ)
29+
*
30+
* rounded up to a MAXALIGN boundary (so that all xlog records start on
31+
* MAXALIGN boundaries).
2932
*/
3033
typedef struct XLogRecord
3134
{
@@ -105,12 +108,13 @@ typedef struct XLogContRecord
105108
/*
106109
* Each page of XLOG file has a header like this:
107110
*/
108-
#define XLOG_PAGE_MAGIC 0x17345169 /* can be used as WAL version indicator */
111+
#define XLOG_PAGE_MAGIC 0xD058 /* can be used as WAL version indicator */
109112

110113
typedef struct XLogPageHeaderData
111114
{
112-
uint32 xlp_magic; /* magic value for correctness checks */
115+
uint16 xlp_magic; /* magic value for correctness checks */
113116
uint16 xlp_info; /* flag bits, see below */
117+
StartUpID xlp_sui; /* StartUpID of first record on page */
114118
} XLogPageHeaderData;
115119

116120
#define SizeOfXLogPHD MAXALIGN(sizeof(XLogPageHeaderData))
@@ -119,6 +123,8 @@ typedef XLogPageHeaderData *XLogPageHeader;
119123

120124
/* When record crosses page boundary, set this flag in new page's header */
121125
#define XLP_FIRST_IS_CONTRECORD 0x0001
126+
/* All defined flag bits in xlp_info (used for validity checking of header) */
127+
#define XLP_ALL_FLAGS 0x0001
122128

123129
/*
124130
* We break each logical log file (xlogid value) into 16Mb segments.

0 commit comments

Comments
 (0)