Skip to content

Commit df4a056

Browse files
committed
Add more error context to RestoreBlockImage() and consume it
On failure in restoring a block image, no details were provided, while it is possible to see failure with an inconsistent record state, a failure in processing decompression or a failure in decompression because a build does not support this option. RestoreBlockImage() is used in two code paths in the backend code, during recovery and when checking a page consistency after applying masking, and both places are changed to consume the error message produced by the internal routine when it returns a false status. All the error messages are reported under ERRCODE_INTERNAL_ERROR, that gets used also when attempting to access a page compressed by a method not supported by the build attempting the decompression. This is something that can happen in core when doing physical replication with primary and standby using inconsistent build options, for example. This routine is available since 2c03216 and it has never provided any context about the error happening when it failed. This change is justified even more after 57aa5b2, that introduced compression of FPWs in WAL. Reported-by: Justin Prysby Author: Michael Paquier Discussion: https://postgr.es/m/20220905002320.GD31833@telsasoft.com Backpatch-through: 15
1 parent d977ffd commit df4a056

File tree

3 files changed

+23
-7
lines changed

3 files changed

+23
-7
lines changed

src/backend/access/transam/xlogreader.c

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2036,7 +2036,8 @@ XLogRecGetBlockData(XLogReaderState *record, uint8 block_id, Size *len)
20362036
/*
20372037
* Restore a full-page image from a backup block attached to an XLOG record.
20382038
*
2039-
* Returns true if a full-page image is restored.
2039+
* Returns true if a full-page image is restored, and false on failure with
2040+
* an error to be consumed by the caller.
20402041
*/
20412042
bool
20422043
RestoreBlockImage(XLogReaderState *record, uint8 block_id, char *page)
@@ -2047,9 +2048,20 @@ RestoreBlockImage(XLogReaderState *record, uint8 block_id, char *page)
20472048

20482049
if (block_id > record->record->max_block_id ||
20492050
!record->record->blocks[block_id].in_use)
2051+
{
2052+
report_invalid_record(record,
2053+
"could not restore image at %X/%X with invalid block %d specified",
2054+
LSN_FORMAT_ARGS(record->ReadRecPtr),
2055+
block_id);
20502056
return false;
2057+
}
20512058
if (!record->record->blocks[block_id].has_image)
2059+
{
2060+
report_invalid_record(record, "could not restore image at %X/%X with invalid state, block %d",
2061+
LSN_FORMAT_ARGS(record->ReadRecPtr),
2062+
block_id);
20522063
return false;
2064+
}
20532065

20542066
bkpb = &record->record->blocks[block_id];
20552067
ptr = bkpb->bkp_image;
@@ -2072,7 +2084,7 @@ RestoreBlockImage(XLogReaderState *record, uint8 block_id, char *page)
20722084
bkpb->bimg_len, BLCKSZ - bkpb->hole_length) <= 0)
20732085
decomp_success = false;
20742086
#else
2075-
report_invalid_record(record, "image at %X/%X compressed with %s not supported by build, block %d",
2087+
report_invalid_record(record, "could not restore image at %X/%X compressed with %s not supported by build, block %d",
20762088
LSN_FORMAT_ARGS(record->ReadRecPtr),
20772089
"LZ4",
20782090
block_id);
@@ -2089,7 +2101,7 @@ RestoreBlockImage(XLogReaderState *record, uint8 block_id, char *page)
20892101
if (ZSTD_isError(decomp_result))
20902102
decomp_success = false;
20912103
#else
2092-
report_invalid_record(record, "image at %X/%X compressed with %s not supported by build, block %d",
2104+
report_invalid_record(record, "could not restore image at %X/%X compressed with %s not supported by build, block %d",
20932105
LSN_FORMAT_ARGS(record->ReadRecPtr),
20942106
"zstd",
20952107
block_id);
@@ -2098,15 +2110,15 @@ RestoreBlockImage(XLogReaderState *record, uint8 block_id, char *page)
20982110
}
20992111
else
21002112
{
2101-
report_invalid_record(record, "image at %X/%X compressed with unknown method, block %d",
2113+
report_invalid_record(record, "could not restore image at %X/%X compressed with unknown method, block %d",
21022114
LSN_FORMAT_ARGS(record->ReadRecPtr),
21032115
block_id);
21042116
return false;
21052117
}
21062118

21072119
if (!decomp_success)
21082120
{
2109-
report_invalid_record(record, "invalid compressed image at %X/%X, block %d",
2121+
report_invalid_record(record, "could not decompress image at %X/%X, block %d",
21102122
LSN_FORMAT_ARGS(record->ReadRecPtr),
21112123
block_id);
21122124
return false;

src/backend/access/transam/xlogrecovery.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2412,7 +2412,9 @@ verifyBackupPageConsistency(XLogReaderState *record)
24122412
* can be directly applied on it.
24132413
*/
24142414
if (!RestoreBlockImage(record, block_id, primary_image_masked))
2415-
elog(ERROR, "failed to restore block image");
2415+
ereport(ERROR,
2416+
(errcode(ERRCODE_INTERNAL_ERROR),
2417+
errmsg_internal("%s", record->errormsg_buf)));
24162418

24172419
/*
24182420
* If masking function is defined, mask both the primary and replay

src/backend/access/transam/xlogutils.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -393,7 +393,9 @@ XLogReadBufferForRedoExtended(XLogReaderState *record,
393393
prefetch_buffer);
394394
page = BufferGetPage(*buf);
395395
if (!RestoreBlockImage(record, block_id, page))
396-
elog(ERROR, "failed to restore block image");
396+
ereport(ERROR,
397+
(errcode(ERRCODE_INTERNAL_ERROR),
398+
errmsg_internal("%s", record->errormsg_buf)));
397399

398400
/*
399401
* The page may be uninitialized. If so, we can't set the LSN because

0 commit comments

Comments
 (0)