amcheck: Remove duplicate XID/MXID bounds checks.

Commit 3b6c1259f9 resulted in the same
xmin and xmax bounds checking being performed in both check_tuple()
and check_tuple_visibility(). Remove the duplication.

While at it, adjust some code comments that were overlooked in that
commit.

Mark Dilger

Discussion: http://postgr.es/m/AC5479E4-6321-473D-AC92-5EC36299FBC2@enterprisedb.com
This commit is contained in:
Robert Haas 2021-04-07 12:11:44 -04:00
parent 3c3b8a4b26
commit 4573f6a9af
1 changed files with 7 additions and 125 deletions

View File

@ -1390,136 +1390,18 @@ check_tuple_attribute(HeapCheckContext *ctx)
static void
check_tuple(HeapCheckContext *ctx)
{
TransactionId xmin;
TransactionId xmax;
bool fatal = false;
uint16 infomask = ctx->tuphdr->t_infomask;
/* If xmin is normal, it should be within valid range */
xmin = HeapTupleHeaderGetXmin(ctx->tuphdr);
switch (get_xid_status(xmin, ctx, NULL))
{
case XID_INVALID:
case XID_BOUNDS_OK:
break;
case XID_IN_FUTURE:
report_corruption(ctx,
psprintf("xmin %u equals or exceeds next valid transaction ID %u:%u",
xmin,
EpochFromFullTransactionId(ctx->next_fxid),
XidFromFullTransactionId(ctx->next_fxid)));
fatal = true;
break;
case XID_PRECEDES_CLUSTERMIN:
report_corruption(ctx,
psprintf("xmin %u precedes oldest valid transaction ID %u:%u",
xmin,
EpochFromFullTransactionId(ctx->oldest_fxid),
XidFromFullTransactionId(ctx->oldest_fxid)));
fatal = true;
break;
case XID_PRECEDES_RELMIN:
report_corruption(ctx,
psprintf("xmin %u precedes relation freeze threshold %u:%u",
xmin,
EpochFromFullTransactionId(ctx->relfrozenfxid),
XidFromFullTransactionId(ctx->relfrozenfxid)));
fatal = true;
break;
}
xmax = HeapTupleHeaderGetRawXmax(ctx->tuphdr);
if (infomask & HEAP_XMAX_IS_MULTI)
{
/* xmax is a multixact, so it should be within valid MXID range */
switch (check_mxid_valid_in_rel(xmax, ctx))
{
case XID_INVALID:
report_corruption(ctx,
pstrdup("multitransaction ID is invalid"));
fatal = true;
break;
case XID_PRECEDES_RELMIN:
report_corruption(ctx,
psprintf("multitransaction ID %u precedes relation minimum multitransaction ID threshold %u",
xmax, ctx->relminmxid));
fatal = true;
break;
case XID_PRECEDES_CLUSTERMIN:
report_corruption(ctx,
psprintf("multitransaction ID %u precedes oldest valid multitransaction ID threshold %u",
xmax, ctx->oldest_mxact));
fatal = true;
break;
case XID_IN_FUTURE:
report_corruption(ctx,
psprintf("multitransaction ID %u equals or exceeds next valid multitransaction ID %u",
xmax,
ctx->next_mxact));
fatal = true;
break;
case XID_BOUNDS_OK:
break;
}
}
else
{
/*
* xmax is not a multixact and is normal, so it should be within the
* valid XID range.
*/
switch (get_xid_status(xmax, ctx, NULL))
{
case XID_INVALID:
case XID_BOUNDS_OK:
break;
case XID_IN_FUTURE:
report_corruption(ctx,
psprintf("xmax %u equals or exceeds next valid transaction ID %u:%u",
xmax,
EpochFromFullTransactionId(ctx->next_fxid),
XidFromFullTransactionId(ctx->next_fxid)));
fatal = true;
break;
case XID_PRECEDES_CLUSTERMIN:
report_corruption(ctx,
psprintf("xmax %u precedes oldest valid transaction ID %u:%u",
xmax,
EpochFromFullTransactionId(ctx->oldest_fxid),
XidFromFullTransactionId(ctx->oldest_fxid)));
fatal = true;
break;
case XID_PRECEDES_RELMIN:
report_corruption(ctx,
psprintf("xmax %u precedes relation freeze threshold %u:%u",
xmax,
EpochFromFullTransactionId(ctx->relfrozenfxid),
XidFromFullTransactionId(ctx->relfrozenfxid)));
fatal = true;
}
}
/*
* Cannot process tuple data if tuple header was corrupt, as the offsets
* within the page cannot be trusted, leaving too much risk of reading
* garbage if we continue.
*
* We also cannot process the tuple if the xmin or xmax were invalid
* relative to relfrozenxid or relminmxid, as clog entries for the xids
* may already be gone.
*/
if (fatal)
return;
/*
* Check various forms of tuple header corruption. If the header is too
* corrupt to continue checking, or if the tuple is not visible to anyone,
* we cannot continue with other checks.
* Check various forms of tuple header corruption, and if the header is too
* corrupt, do not continue with other checks.
*/
if (!check_tuple_header(ctx))
return;
/*
* Check tuple visibility. If the inserting transaction aborted, we
* cannot assume our relation description matches the tuple structure, and
* therefore cannot check it.
*/
if (!check_tuple_visibility(ctx))
return;