1
1
/*-------------------------------------------------------------------------
2
2
*
3
3
* xlog.c
4
+ * PostgreSQL transaction log manager
4
5
*
5
6
*
6
7
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
7
8
* Portions Copyright (c) 1994, Regents of the University of California
8
9
*
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 $
10
11
*
11
12
*-------------------------------------------------------------------------
12
13
*/
@@ -344,6 +345,7 @@ static char *readBuf = NULL;
344
345
static XLogRecPtr ReadRecPtr ;
345
346
static XLogRecPtr EndRecPtr ;
346
347
static XLogRecord * nextRecord = NULL ;
348
+ static StartUpID lastReadSUI ;
347
349
348
350
static bool InRedo = false;
349
351
@@ -355,6 +357,7 @@ static int XLogFileOpen(uint32 log, uint32 seg, bool econt);
355
357
static void PreallocXlogFiles (XLogRecPtr endptr );
356
358
static void MoveOfflineLogs (uint32 log , uint32 seg );
357
359
static XLogRecord * ReadRecord (XLogRecPtr * RecPtr , int emode , char * buffer );
360
+ static bool ValidXLOGHeader (XLogPageHeader hdr , int emode , bool checkSUI );
358
361
static XLogRecord * ReadCheckpointRecord (XLogRecPtr RecPtr ,
359
362
const char * whichChkpt ,
360
363
char * buffer );
@@ -891,6 +894,7 @@ AdvanceXLInsertBuffer(void)
891
894
MemSet ((char * ) Insert -> currpage , 0 , BLCKSZ );
892
895
Insert -> currpage -> xlp_magic = XLOG_PAGE_MAGIC ;
893
896
/* Insert->currpage->xlp_info = 0; */ /* done by memset */
897
+ Insert -> currpage -> xlp_sui = ThisStartUpID ;
894
898
895
899
return update_needed ;
896
900
}
@@ -1498,6 +1502,7 @@ ReadRecord(XLogRecPtr *RecPtr, int emode, char *buffer)
1498
1502
total_len ;
1499
1503
uint32 targetPageOff ;
1500
1504
unsigned i ;
1505
+ bool nextmode = false;
1501
1506
1502
1507
if (readBuf == NULL )
1503
1508
{
@@ -1516,6 +1521,7 @@ ReadRecord(XLogRecPtr *RecPtr, int emode, char *buffer)
1516
1521
if (RecPtr == NULL )
1517
1522
{
1518
1523
RecPtr = & tmpRecPtr ;
1524
+ nextmode = true;
1519
1525
/* fast case if next record is on same page */
1520
1526
if (nextRecord != NULL )
1521
1527
{
@@ -1566,13 +1572,8 @@ ReadRecord(XLogRecPtr *RecPtr, int emode, char *buffer)
1566
1572
readId , readSeg , readOff );
1567
1573
goto next_record_is_invalid ;
1568
1574
}
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 ))
1574
1576
goto next_record_is_invalid ;
1575
- }
1576
1577
}
1577
1578
if ((((XLogPageHeader ) readBuf )-> xlp_info & XLP_FIRST_IS_CONTRECORD ) &&
1578
1579
RecPtr -> xrecoff % BLCKSZ == SizeOfXLogPHD )
@@ -1651,13 +1652,8 @@ got_record:;
1651
1652
readId , readSeg , readOff );
1652
1653
goto next_record_is_invalid ;
1653
1654
}
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))
1659
1656
goto next_record_is_invalid ;
1660
- }
1661
1657
if (!(((XLogPageHeader ) readBuf )-> xlp_info & XLP_FIRST_IS_CONTRECORD ))
1662
1658
{
1663
1659
elog (emode , "ReadRecord: there is no ContRecord flag in logfile %u seg %u off %u" ,
@@ -1719,6 +1715,50 @@ next_record_is_invalid:;
1719
1715
return NULL ;
1720
1716
}
1721
1717
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
+
1722
1762
/*
1723
1763
* I/O routines for pg_control
1724
1764
*
@@ -2023,6 +2063,7 @@ BootStrapXLOG(void)
2023
2063
memset (buffer , 0 , BLCKSZ );
2024
2064
page -> xlp_magic = XLOG_PAGE_MAGIC ;
2025
2065
page -> xlp_info = 0 ;
2066
+ page -> xlp_sui = checkPoint .ThisStartUpID ;
2026
2067
record = (XLogRecord * ) ((char * ) page + SizeOfXLogPHD );
2027
2068
record -> xl_prev .xlogid = 0 ;
2028
2069
record -> xl_prev .xrecoff = 0 ;
0 commit comments