From 1f4fc659441a805a50b77f4e7810f9a25b5e62ae Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Mon, 8 Aug 2022 14:09:32 +1200
Subject: [PATCH] WIP Fix XLogPageRead() cache invalidation.

When ReadPageInternal() reports an error, including due to failure of
XLogReaderValidatePageHeader(), the reader calls
XLogReaderInvalReaderState() to invalidate the contents of its buffer,
forcing a re-read next time.

This did not work if a header validation error was detected by the
read_page callback itself.  XLogPageRead() calls
XLogValidatePageHeader() directly, and if that failed, there was no
cache invalidation.

Fix, by invalidating the cache directly in report_invalid_record(), so
that XLogValidatePageHeader()'s failure invalidates the cache even with
called directly by xlogrecovery.c.

XXX More research/testing needed

diff --git a/src/backend/access/transam/xlogreader.c b/src/backend/access/transam/xlogreader.c
index 06e91547dd..e6431722e7 100644
--- a/src/backend/access/transam/xlogreader.c
+++ b/src/backend/access/transam/xlogreader.c
@@ -81,6 +81,12 @@ report_invalid_record(XLogReaderState *state, const char *fmt,...)
 	va_end(args);
 
 	state->errormsg_deferred = true;
+
+	/*
+	 * Invalidate the read state. We might read from a different source after
+	 * failure.
+	 */
+	XLogReaderInvalReadState(state);
 }
 
 /*
@@ -1066,11 +1072,6 @@ ReadPageInternal(XLogReaderState *state, XLogRecPtr pageptr, int reqLen)
 	return readLen;
 
 err:
-	if (state->errormsg_buf[0] != '\0')
-	{
-		state->errormsg_deferred = true;
-		XLogReaderInvalReadState(state);
-	}
 	return XLREAD_FAIL;
 }
 
-- 
2.37.1

