From ffe8c7c677197ef8062a71309b14a1847841118c Mon Sep 17 00:00:00 2001
From: Heikki Linnakangas <heikki.linnakangas@iki.fi>
Date: Mon, 3 May 2010 11:17:52 +0000
Subject: [PATCH] Need to hold ControlFileLock while updating control file.
 Update minRecoveryPoint in control file when replaying a parameter change
 record, to ensure that we don't allow hot standby on WAL generated without
 wal_level='hot_standby' after a standby restart.

---
 src/backend/access/transam/xlog.c | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 99e53b76321..a39d455a7f0 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.408 2010/05/02 02:10:33 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.409 2010/05/03 11:17:52 heikki Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -7920,11 +7920,28 @@ xlog_redo(XLogRecPtr lsn, XLogRecord *record)
 		/* Update our copy of the parameters in pg_control */
 		memcpy(&xlrec, XLogRecGetData(record), sizeof(xl_parameter_change));
 
+		LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
 		ControlFile->MaxConnections = xlrec.MaxConnections;
 		ControlFile->max_prepared_xacts = xlrec.max_prepared_xacts;
 		ControlFile->max_locks_per_xact = xlrec.max_locks_per_xact;
 		ControlFile->wal_level = xlrec.wal_level;
+		/*
+		 * Update minRecoveryPoint to ensure that if recovery is aborted,
+		 * we recover back up to this point before allowing hot standby
+		 * again. This is particularly important if wal_level was set to
+		 * 'archive' before, and is now 'hot_standby', to ensure you don't
+		 * run queries against the WAL preceding the wal_level change.
+		 * Same applies to decreasing max_* settings.
+		 */
+		minRecoveryPoint = ControlFile->minRecoveryPoint;
+		if ((minRecoveryPoint.xlogid != 0 || minRecoveryPoint.xrecoff != 0)
+			&& XLByteLT(minRecoveryPoint, lsn))
+		{
+			ControlFile->minRecoveryPoint = lsn;
+		}
+
 		UpdateControlFile();
+		LWLockRelease(ControlFileLock);
 
 		/* Check to see if any changes to max_connections give problems */
 		CheckRequiredParameterValues();
-- 
GitLab