Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit d9fbb88

Browse files
committed
Use correct LSN for error reporting in pg_walinspect
Usage of ReadNextXLogRecord()'s first_record parameter for error reporting isn't always correct. For instance, in GetWALRecordsInfo() and GetWalStats(), we're reading multiple records, and first_record is always passed as the LSN of the first record which is then used for error reporting for later WAL record read failures. This isn't correct. The correct parameter to use for error reports in case of WAL reading failures is xlogreader->EndRecPtr. This change fixes it. While on it, removed an unnecessary Assert in pg_walinspect code. Reported-by: Robert Haas Author: Bharath Rupireddy Reviewed-by: Robert Haas Discussion: https://www.postgresql.org/message-id/CA%2BTgmoZAOGzPUifrcZRjFZ2vbtcw3mp-mN6UgEoEcQg6bY3OVg%40mail.gmail.com Backpatch-through: 15
1 parent 9288c2e commit d9fbb88

File tree

1 file changed

+23
-30
lines changed

1 file changed

+23
-30
lines changed

contrib/pg_walinspect/pg_walinspect.c

+23-30
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,10 @@ PG_FUNCTION_INFO_V1(pg_get_wal_stats);
3737
PG_FUNCTION_INFO_V1(pg_get_wal_stats_till_end_of_wal);
3838

3939
static bool IsFutureLSN(XLogRecPtr lsn, XLogRecPtr *curr_lsn);
40-
static XLogReaderState *InitXLogReaderState(XLogRecPtr lsn,
41-
XLogRecPtr *first_record);
42-
static XLogRecord *ReadNextXLogRecord(XLogReaderState *xlogreader,
43-
XLogRecPtr first_record);
44-
static void GetWALRecordInfo(XLogReaderState *record, XLogRecPtr lsn,
45-
Datum *values, bool *nulls, uint32 ncols);
40+
static XLogReaderState *InitXLogReaderState(XLogRecPtr lsn);
41+
static XLogRecord *ReadNextXLogRecord(XLogReaderState *xlogreader);
42+
static void GetWALRecordInfo(XLogReaderState *record, Datum *values,
43+
bool *nulls, uint32 ncols);
4644
static XLogRecPtr ValidateInputLSNs(bool till_end_of_wal,
4745
XLogRecPtr start_lsn, XLogRecPtr end_lsn);
4846
static void GetWALRecordsInfo(FunctionCallInfo fcinfo, XLogRecPtr start_lsn,
@@ -86,10 +84,11 @@ IsFutureLSN(XLogRecPtr lsn, XLogRecPtr *curr_lsn)
8684
* Intialize WAL reader and identify first valid LSN.
8785
*/
8886
static XLogReaderState *
89-
InitXLogReaderState(XLogRecPtr lsn, XLogRecPtr *first_record)
87+
InitXLogReaderState(XLogRecPtr lsn)
9088
{
9189
XLogReaderState *xlogreader;
9290
ReadLocalXLogPageNoWaitPrivate *private_data;
91+
XLogRecPtr first_valid_record;
9392

9493
/*
9594
* Reading WAL below the first page of the first segments isn't allowed.
@@ -117,9 +116,9 @@ InitXLogReaderState(XLogRecPtr lsn, XLogRecPtr *first_record)
117116
errdetail("Failed while allocating a WAL reading processor.")));
118117

119118
/* first find a valid recptr to start from */
120-
*first_record = XLogFindNextRecord(xlogreader, lsn);
119+
first_valid_record = XLogFindNextRecord(xlogreader, lsn);
121120

122-
if (XLogRecPtrIsInvalid(*first_record))
121+
if (XLogRecPtrIsInvalid(first_valid_record))
123122
ereport(ERROR,
124123
(errmsg("could not find a valid record after %X/%X",
125124
LSN_FORMAT_ARGS(lsn))));
@@ -140,7 +139,7 @@ InitXLogReaderState(XLogRecPtr lsn, XLogRecPtr *first_record)
140139
* that case we'll return NULL.
141140
*/
142141
static XLogRecord *
143-
ReadNextXLogRecord(XLogReaderState *xlogreader, XLogRecPtr first_record)
142+
ReadNextXLogRecord(XLogReaderState *xlogreader)
144143
{
145144
XLogRecord *record;
146145
char *errormsg;
@@ -162,12 +161,12 @@ ReadNextXLogRecord(XLogReaderState *xlogreader, XLogRecPtr first_record)
162161
ereport(ERROR,
163162
(errcode_for_file_access(),
164163
errmsg("could not read WAL at %X/%X: %s",
165-
LSN_FORMAT_ARGS(first_record), errormsg)));
164+
LSN_FORMAT_ARGS(xlogreader->EndRecPtr), errormsg)));
166165
else
167166
ereport(ERROR,
168167
(errcode_for_file_access(),
169168
errmsg("could not read WAL at %X/%X",
170-
LSN_FORMAT_ARGS(first_record))));
169+
LSN_FORMAT_ARGS(xlogreader->EndRecPtr))));
171170
}
172171

173172
return record;
@@ -177,8 +176,8 @@ ReadNextXLogRecord(XLogReaderState *xlogreader, XLogRecPtr first_record)
177176
* Get a single WAL record info.
178177
*/
179178
static void
180-
GetWALRecordInfo(XLogReaderState *record, XLogRecPtr lsn,
181-
Datum *values, bool *nulls, uint32 ncols)
179+
GetWALRecordInfo(XLogReaderState *record, Datum *values,
180+
bool *nulls, uint32 ncols)
182181
{
183182
const char *id;
184183
RmgrData desc;
@@ -203,7 +202,7 @@ GetWALRecordInfo(XLogReaderState *record, XLogRecPtr lsn,
203202

204203
main_data_len = XLogRecGetDataLen(record);
205204

206-
values[i++] = LSNGetDatum(lsn);
205+
values[i++] = LSNGetDatum(record->ReadRecPtr);
207206
values[i++] = LSNGetDatum(record->EndRecPtr);
208207
values[i++] = LSNGetDatum(XLogRecGetPrev(record));
209208
values[i++] = TransactionIdGetDatum(XLogRecGetXid(record));
@@ -233,7 +232,6 @@ pg_get_wal_record_info(PG_FUNCTION_ARGS)
233232
bool nulls[PG_GET_WAL_RECORD_INFO_COLS] = {0};
234233
XLogRecPtr lsn;
235234
XLogRecPtr curr_lsn;
236-
XLogRecPtr first_record;
237235
XLogReaderState *xlogreader;
238236
TupleDesc tupdesc;
239237
HeapTuple tuple;
@@ -258,16 +256,15 @@ pg_get_wal_record_info(PG_FUNCTION_ARGS)
258256
if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
259257
elog(ERROR, "return type must be a row type");
260258

261-
xlogreader = InitXLogReaderState(lsn, &first_record);
259+
xlogreader = InitXLogReaderState(lsn);
262260

263-
if (!ReadNextXLogRecord(xlogreader, first_record))
261+
if (!ReadNextXLogRecord(xlogreader))
264262
ereport(ERROR,
265263
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
266264
errmsg("could not read WAL at %X/%X",
267-
LSN_FORMAT_ARGS(first_record))));
265+
LSN_FORMAT_ARGS(xlogreader->EndRecPtr))));
268266

269-
GetWALRecordInfo(xlogreader, first_record, values, nulls,
270-
PG_GET_WAL_RECORD_INFO_COLS);
267+
GetWALRecordInfo(xlogreader, values, nulls, PG_GET_WAL_RECORD_INFO_COLS);
271268

272269
pfree(xlogreader->private_data);
273270
XLogReaderFree(xlogreader);
@@ -328,22 +325,19 @@ GetWALRecordsInfo(FunctionCallInfo fcinfo, XLogRecPtr start_lsn,
328325
XLogRecPtr end_lsn)
329326
{
330327
#define PG_GET_WAL_RECORDS_INFO_COLS 11
331-
XLogRecPtr first_record;
332328
XLogReaderState *xlogreader;
333329
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
334330
Datum values[PG_GET_WAL_RECORDS_INFO_COLS] = {0};
335331
bool nulls[PG_GET_WAL_RECORDS_INFO_COLS] = {0};
336332

337333
SetSingleFuncCall(fcinfo, 0);
338334

339-
xlogreader = InitXLogReaderState(start_lsn, &first_record);
340-
341-
Assert(xlogreader);
335+
xlogreader = InitXLogReaderState(start_lsn);
342336

343-
while (ReadNextXLogRecord(xlogreader, first_record) &&
337+
while (ReadNextXLogRecord(xlogreader) &&
344338
xlogreader->EndRecPtr <= end_lsn)
345339
{
346-
GetWALRecordInfo(xlogreader, xlogreader->currRecPtr, values, nulls,
340+
GetWALRecordInfo(xlogreader, values, nulls,
347341
PG_GET_WAL_RECORDS_INFO_COLS);
348342

349343
tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
@@ -548,7 +542,6 @@ GetWalStats(FunctionCallInfo fcinfo, XLogRecPtr start_lsn,
548542
XLogRecPtr end_lsn, bool stats_per_record)
549543
{
550544
#define PG_GET_WAL_STATS_COLS 9
551-
XLogRecPtr first_record;
552545
XLogReaderState *xlogreader;
553546
XLogStats stats = {0};
554547
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
@@ -557,9 +550,9 @@ GetWalStats(FunctionCallInfo fcinfo, XLogRecPtr start_lsn,
557550

558551
SetSingleFuncCall(fcinfo, 0);
559552

560-
xlogreader = InitXLogReaderState(start_lsn, &first_record);
553+
xlogreader = InitXLogReaderState(start_lsn);
561554

562-
while (ReadNextXLogRecord(xlogreader, first_record) &&
555+
while (ReadNextXLogRecord(xlogreader) &&
563556
xlogreader->EndRecPtr <= end_lsn)
564557
{
565558
XLogRecStoreStats(&stats, xlogreader);

0 commit comments

Comments
 (0)