From 21e8623cc5d63e79feb74f85ed53c0028c506611 Mon Sep 17 00:00:00 2001
From: Robert Haas <rhaas@postgresql.org>
Date: Thu, 18 Nov 2021 14:00:43 -0500
Subject: [PATCH 2/2] fix the bug

---
 src/backend/access/transam/xlog.c | 25 ++++++++++++++++---------
 1 file changed, 16 insertions(+), 9 deletions(-)

diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 1616448368..c4b822d98e 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -924,7 +924,8 @@ static int	XLogPageRead(XLogReaderState *xlogreader, XLogRecPtr targetPagePtr,
 						 int reqLen, XLogRecPtr targetRecPtr, char *readBuf);
 static bool WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
 										bool fetching_ckpt, XLogRecPtr tliRecPtr,
-										TimeLineID replayTLI);
+										TimeLineID replayTLI,
+										XLogRecPtr replayLSN);
 static void XLogShutdownWalRcv(void);
 static int	emode_for_corrupt_record(int emode, XLogRecPtr RecPtr);
 static void XLogFileClose(void);
@@ -946,7 +947,8 @@ static bool PerformRecoveryXLogAction(void);
 static XLogRecord *ReadCheckpointRecord(XLogReaderState *xlogreader,
 										XLogRecPtr RecPtr, int whichChkpt, bool report,
 										TimeLineID replayTLI);
-static bool rescanLatestTimeLine(TimeLineID replayTLI);
+static bool rescanLatestTimeLine(TimeLineID replayTLI,
+								 XLogRecPtr replayLSN);
 static void InitControlFile(uint64 sysidentifier);
 static void WriteControlFile(void);
 static void ReadControlFile(void);
@@ -4620,7 +4622,7 @@ ReadRecord(XLogReaderState *xlogreader, int emode,
  * one and returns 'true'.
  */
 static bool
-rescanLatestTimeLine(TimeLineID replayTLI)
+rescanLatestTimeLine(TimeLineID replayTLI, XLogRecPtr replayLSN)
 {
 	List	   *newExpectedTLEs;
 	bool		found;
@@ -4671,13 +4673,13 @@ rescanLatestTimeLine(TimeLineID replayTLI)
 	 * next timeline was forked off from it *after* the current recovery
 	 * location.
 	 */
-	if (currentTle->end < EndRecPtr)
+	if (currentTle->end < replayLSN)
 	{
 		ereport(LOG,
 				(errmsg("new timeline %u forked off current database system timeline %u before current recovery point %X/%X",
 						newtarget,
 						replayTLI,
-						LSN_FORMAT_ARGS(EndRecPtr))));
+						LSN_FORMAT_ARGS(replayLSN))));
 		return false;
 	}
 
@@ -12471,7 +12473,8 @@ retry:
 										 private->randAccess,
 										 private->fetching_ckpt,
 										 targetRecPtr,
-										 private->replayTLI))
+										 private->replayTLI,
+										 xlogreader->EndRecPtr))
 		{
 			if (readFile >= 0)
 				close(readFile);
@@ -12624,6 +12627,10 @@ next_record_is_invalid:
  * 'tliRecPtr' is the position of the WAL record we're interested in. It is
  * used to decide which timeline to stream the requested WAL from.
  *
+ * 'replayLSN' is the current replay LSN, so that if we scan for new
+ * timelines, we can reject a switch to a timeline that branched off before
+ * this point.
+ *
  * If the record is not immediately available, the function returns false
  * if we're not in standby mode. In standby mode, waits for it to become
  * available.
@@ -12636,7 +12643,7 @@ next_record_is_invalid:
 static bool
 WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
 							bool fetching_ckpt, XLogRecPtr tliRecPtr,
-							TimeLineID replayTLI)
+							TimeLineID replayTLI, XLogRecPtr replayLSN)
 {
 	static TimestampTz last_fail_time = 0;
 	TimestampTz now;
@@ -12759,7 +12766,7 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
 					 */
 					if (recoveryTargetTimeLineGoal == RECOVERY_TARGET_TIMELINE_LATEST)
 					{
-						if (rescanLatestTimeLine(replayTLI))
+						if (rescanLatestTimeLine(replayTLI, replayLSN))
 						{
 							currentSource = XLOG_FROM_ARCHIVE;
 							break;
@@ -12886,7 +12893,7 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
 						 */
 						if (recoveryTargetTimeLineGoal ==
 							RECOVERY_TARGET_TIMELINE_LATEST)
-							rescanLatestTimeLine(replayTLI);
+							rescanLatestTimeLine(replayTLI, replayLSN);
 
 						startWalReceiver = true;
 					}
-- 
2.24.3 (Apple Git-128)

