diff --git a/src/backend/access/transam/xlogreader.c b/src/backend/access/transam/xlogreader.c index f17e80948d..cdcacc7803 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 successfully read. + */ + state->readLen = 0; + /* * Data is not in our buffer. * @@ -1067,11 +1074,8 @@ ReadPageInternal(XLogReaderState *state, XLogRecPtr pageptr, int reqLen) return readLen; err: - if (state->errormsg_buf[0] != '\0') - { - state->errormsg_deferred = true; - XLogReaderInvalReadState(state); - } + XLogReaderInvalReadState(state); + return XLREAD_FAIL; } @@ -1323,6 +1327,16 @@ XLogReaderValidatePageHeader(XLogReaderState *state, XLogRecPtr recptr, return true; } +/* + * Forget about an error produced by XLogReaderValidatePageHeader(). + */ +void +XLogReaderResetError(XLogReaderState *state) +{ + state->errormsg_buf[0] = '\0'; + state->errormsg_deferred = false; +} + /* * Find the first record with an lsn >= RecPtr. * diff --git a/src/backend/access/transam/xlogrecovery.c b/src/backend/access/transam/xlogrecovery.c index 4ad145dd16..ae2af5ae3d 100644 --- a/src/backend/access/transam/xlogrecovery.c +++ b/src/backend/access/transam/xlogrecovery.c @@ -3341,13 +3341,21 @@ retry: (errmsg_internal("%s", xlogreader->errormsg_buf))); /* reset any error XLogReaderValidatePageHeader() might have set */ - xlogreader->errormsg_buf[0] = '\0'; + XLogReaderResetError(xlogreader); goto next_record_is_invalid; } return readLen; next_record_is_invalid: + + /* + * If we're reading ahead, give up fast. Retries and error reporting will + * be handled by a later read when recovery catches up to this point. + */ + if (xlogreader->nonblocking) + return XLREAD_WOULDBLOCK; + lastSourceFailed = true; if (readFile >= 0) diff --git a/src/include/access/xlogreader.h b/src/include/access/xlogreader.h index 87ff00feb7..97b6f00114 100644 --- a/src/include/access/xlogreader.h +++ b/src/include/access/xlogreader.h @@ -373,6 +373,9 @@ extern DecodedXLogRecord *XLogReadAhead(XLogReaderState *state, extern bool XLogReaderValidatePageHeader(XLogReaderState *state, XLogRecPtr recptr, char *phdr); +/* Forget error produced by XLogReaderValidatePageHeader(). */ +extern void XLogReaderResetError(XLogReaderState *state); + /* * Error information from WALRead that both backend and frontend caller can * process. Currently only errors from pread can be reported.