From 9f547088e54fcf279c74fbd03e4afaeffec69ea3 Mon Sep 17 00:00:00 2001 From: Thomas Munro Date: Mon, 29 Aug 2022 19:56:27 +1200 Subject: [PATCH 1/3] Fix cache invalidation in rare recovery_prefetch case. Since commit 0668719801 we've had an extra page validation and retry loop inside XLogPageRead() to handle a rare special case. The new recovery prefetch code from commit 5dc0418f could lead to a PANIC in this case, because the WAL page cached internally by xlogreader.c was not invalidated when it should have been. Make tracking of the cached page's status more robust by invalidating it just before we attempt any read. Because it is only marked valid when a read succeeds, now we don't have to worry about invalidation in error code paths. The removed line that was setting errormsg_deferred was redundant because it's already set by report_invalid_record(). Back-patch to 15. Reported-by: Noah Misch Reviewed-by: Discussion: https://postgr.es/m/20220807003627.GA4168930%40rfd.leadboat.com --- src/backend/access/transam/xlogreader.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/backend/access/transam/xlogreader.c b/src/backend/access/transam/xlogreader.c index f17e80948d..e883ade607 100644 --- a/src/backend/access/transam/xlogreader.c +++ b/src/backend/access/transam/xlogreader.c @@ -987,6 +987,13 @@ ReadPageInternal(XLogReaderState *state, XLogRecPtr pageptr, int reqLen) targetPageOff == state->segoff && reqLen <= state->readLen) return state->readLen; + /* + * Invalidate contents of internal buffer before read attempt. Just set + * the length to 0, rather than a full XLogReaderInvalReadState(), so we + * don't forget the segment we last read. + */ + state->readLen = 0; + /* * Data is not in our buffer. * @@ -1067,11 +1074,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.30.2