Commit 4573f6a9 authored by Robert Haas's avatar Robert Haas

amcheck: Remove duplicate XID/MXID bounds checks.

Commit 3b6c1259 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
parent 3c3b8a4b
...@@ -1390,136 +1390,18 @@ check_tuple_attribute(HeapCheckContext *ctx) ...@@ -1390,136 +1390,18 @@ check_tuple_attribute(HeapCheckContext *ctx)
static void static void
check_tuple(HeapCheckContext *ctx) 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 * Check various forms of tuple header corruption, and if the header is too
* valid XID range. * corrupt, do not continue with other checks.
*/ */
switch (get_xid_status(xmax, ctx, NULL)) if (!check_tuple_header(ctx))
{
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; return;
/* /*
* Check various forms of tuple header corruption. If the header is too * Check tuple visibility. If the inserting transaction aborted, we
* corrupt to continue checking, or if the tuple is not visible to anyone, * cannot assume our relation description matches the tuple structure, and
* we cannot continue with other checks. * therefore cannot check it.
*/ */
if (!check_tuple_header(ctx))
return;
if (!check_tuple_visibility(ctx)) if (!check_tuple_visibility(ctx))
return; return;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment