Skip to content

Commit 9acaf1a

Browse files
committed
amcheck: Reword some messages and fix an alignment problem.
We don't need to mention the attribute number in these messages, because there's a dedicated column for that, but we should mention the toast value ID, because that's really useful for any follow-up troubleshooting the user wants to do. This also rewords some of the messages to hopefully read a little better. Also, use VARATT_EXTERNAL_GET_POINTER in case we're accessing a TOAST pointer that isn't aligned on a platform that's fussy about alignment, so that we don't crash while corruption-checking the user's data. Mark Dilger, reviewed by me. Discussion: http://postgr.es/m/7D3B9BF6-50D0-4C30-8506-1C1851C7F96F@enterprisedb.com
1 parent 07e5e66 commit 9acaf1a

File tree

2 files changed

+38
-29
lines changed

2 files changed

+38
-29
lines changed

contrib/amcheck/verify_heapam.c

Lines changed: 36 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1179,15 +1179,17 @@ check_toast_tuple(HeapTuple toasttup, HeapCheckContext *ctx,
11791179
if (isnull)
11801180
{
11811181
report_toast_corruption(ctx, ta,
1182-
pstrdup("toast chunk sequence number is null"));
1182+
psprintf("toast value %u has toast chunk with null sequence number",
1183+
ta->toast_pointer.va_valueid));
11831184
return;
11841185
}
11851186
chunk = DatumGetPointer(fastgetattr(toasttup, 3,
11861187
ctx->toast_rel->rd_att, &isnull));
11871188
if (isnull)
11881189
{
11891190
report_toast_corruption(ctx, ta,
1190-
pstrdup("toast chunk data is null"));
1191+
psprintf("toast value %u chunk %d has null data",
1192+
ta->toast_pointer.va_valueid, chunkno));
11911193
return;
11921194
}
11931195
if (!VARATT_IS_EXTENDED(chunk))
@@ -1205,8 +1207,9 @@ check_toast_tuple(HeapTuple toasttup, HeapCheckContext *ctx,
12051207
uint32 header = ((varattrib_4b *) chunk)->va_4byte.va_header;
12061208

12071209
report_toast_corruption(ctx, ta,
1208-
psprintf("corrupt extended toast chunk has invalid varlena header: %0x (sequence number %d)",
1209-
header, curchunk));
1210+
psprintf("toast value %u chunk %d has invalid varlena header %0x",
1211+
ta->toast_pointer.va_valueid,
1212+
chunkno, header));
12101213
return;
12111214
}
12121215

@@ -1216,15 +1219,17 @@ check_toast_tuple(HeapTuple toasttup, HeapCheckContext *ctx,
12161219
if (curchunk != chunkno)
12171220
{
12181221
report_toast_corruption(ctx, ta,
1219-
psprintf("toast chunk sequence number %u does not match the expected sequence number %u",
1220-
curchunk, chunkno));
1222+
psprintf("toast value %u chunk %d has sequence number %d, but expected sequence number %d",
1223+
ta->toast_pointer.va_valueid,
1224+
chunkno, curchunk, chunkno));
12211225
return;
12221226
}
1223-
if (curchunk > endchunk)
1227+
if (chunkno > endchunk)
12241228
{
12251229
report_toast_corruption(ctx, ta,
1226-
psprintf("toast chunk sequence number %u exceeds the end chunk sequence number %u",
1227-
curchunk, endchunk));
1230+
psprintf("toast value %u chunk %d follows last expected chunk %d",
1231+
ta->toast_pointer.va_valueid,
1232+
chunkno, endchunk));
12281233
return;
12291234
}
12301235

@@ -1233,8 +1238,9 @@ check_toast_tuple(HeapTuple toasttup, HeapCheckContext *ctx,
12331238

12341239
if (chunksize != expected_size)
12351240
report_toast_corruption(ctx, ta,
1236-
psprintf("toast chunk size %u differs from the expected size %u",
1237-
chunksize, expected_size));
1241+
psprintf("toast value %u chunk %d has size %u, but expected size %u",
1242+
ta->toast_pointer.va_valueid,
1243+
chunkno, chunksize, expected_size));
12381244
}
12391245

12401246
/*
@@ -1265,6 +1271,7 @@ check_tuple_attribute(HeapCheckContext *ctx)
12651271
char *tp; /* pointer to the tuple data */
12661272
uint16 infomask;
12671273
Form_pg_attribute thisatt;
1274+
struct varatt_external toast_pointer;
12681275

12691276
infomask = ctx->tuphdr->t_infomask;
12701277
thisatt = TupleDescAttr(RelationGetDescr(ctx->rel), ctx->attnum);
@@ -1274,8 +1281,7 @@ check_tuple_attribute(HeapCheckContext *ctx)
12741281
if (ctx->tuphdr->t_hoff + ctx->offset > ctx->lp_len)
12751282
{
12761283
report_corruption(ctx,
1277-
psprintf("attribute %u with length %u starts at offset %u beyond total tuple length %u",
1278-
ctx->attnum,
1284+
psprintf("attribute with length %u starts at offset %u beyond total tuple length %u",
12791285
thisatt->attlen,
12801286
ctx->tuphdr->t_hoff + ctx->offset,
12811287
ctx->lp_len));
@@ -1295,8 +1301,7 @@ check_tuple_attribute(HeapCheckContext *ctx)
12951301
if (ctx->tuphdr->t_hoff + ctx->offset > ctx->lp_len)
12961302
{
12971303
report_corruption(ctx,
1298-
psprintf("attribute %u with length %u ends at offset %u beyond total tuple length %u",
1299-
ctx->attnum,
1304+
psprintf("attribute with length %u ends at offset %u beyond total tuple length %u",
13001305
thisatt->attlen,
13011306
ctx->tuphdr->t_hoff + ctx->offset,
13021307
ctx->lp_len));
@@ -1328,8 +1333,7 @@ check_tuple_attribute(HeapCheckContext *ctx)
13281333
if (va_tag != VARTAG_ONDISK)
13291334
{
13301335
report_corruption(ctx,
1331-
psprintf("toasted attribute %u has unexpected TOAST tag %u",
1332-
ctx->attnum,
1336+
psprintf("toasted attribute has unexpected TOAST tag %u",
13331337
va_tag));
13341338
/* We can't know where the next attribute begins */
13351339
return false;
@@ -1343,8 +1347,7 @@ check_tuple_attribute(HeapCheckContext *ctx)
13431347
if (ctx->tuphdr->t_hoff + ctx->offset > ctx->lp_len)
13441348
{
13451349
report_corruption(ctx,
1346-
psprintf("attribute %u with length %u ends at offset %u beyond total tuple length %u",
1347-
ctx->attnum,
1350+
psprintf("attribute with length %u ends at offset %u beyond total tuple length %u",
13481351
thisatt->attlen,
13491352
ctx->tuphdr->t_hoff + ctx->offset,
13501353
ctx->lp_len));
@@ -1371,21 +1374,26 @@ check_tuple_attribute(HeapCheckContext *ctx)
13711374

13721375
/* It is external, and we're looking at a page on disk */
13731376

1377+
/*
1378+
* Must copy attr into toast_pointer for alignment considerations
1379+
*/
1380+
VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr);
1381+
13741382
/* The tuple header better claim to contain toasted values */
13751383
if (!(infomask & HEAP_HASEXTERNAL))
13761384
{
13771385
report_corruption(ctx,
1378-
psprintf("attribute %u is external but tuple header flag HEAP_HASEXTERNAL not set",
1379-
ctx->attnum));
1386+
psprintf("toast value %u is external but tuple header flag HEAP_HASEXTERNAL not set",
1387+
toast_pointer.va_valueid));
13801388
return true;
13811389
}
13821390

13831391
/* The relation better have a toast table */
13841392
if (!ctx->rel->rd_rel->reltoastrelid)
13851393
{
13861394
report_corruption(ctx,
1387-
psprintf("attribute %u is external but relation has no toast relation",
1388-
ctx->attnum));
1395+
psprintf("toast value %u is external but relation has no toast relation",
1396+
toast_pointer.va_valueid));
13891397
return true;
13901398
}
13911399

@@ -1464,12 +1472,13 @@ check_toasted_attribute(HeapCheckContext *ctx, ToastedAttribute *ta)
14641472

14651473
if (!found_toasttup)
14661474
report_toast_corruption(ctx, ta,
1467-
psprintf("toasted value for attribute %u missing from toast table",
1468-
ta->attnum));
1475+
psprintf("toast value %u not found in toast table",
1476+
ta->toast_pointer.va_valueid));
14691477
else if (chunkno != (endchunk + 1))
14701478
report_toast_corruption(ctx, ta,
1471-
psprintf("final toast chunk number %u differs from expected value %u",
1472-
chunkno, (endchunk + 1)));
1479+
psprintf("toast value %u was expected to end at chunk %u, but ended at chunk %u",
1480+
ta->toast_pointer.va_valueid,
1481+
(endchunk + 1), chunkno));
14731482
}
14741483

14751484
/*

src/bin/pg_amcheck/t/004_verify_heapam.pl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -480,7 +480,7 @@ sub header
480480

481481
$header = header(0, $offnum, 1);
482482
push @expected,
483-
qr/${header}attribute \d+ with length \d+ ends at offset \d+ beyond total tuple length \d+/;
483+
qr/${header}attribute with length \d+ ends at offset \d+ beyond total tuple length \d+/;
484484
}
485485
elsif ($offnum == 13)
486486
{
@@ -489,7 +489,7 @@ sub header
489489

490490
$header = header(0, $offnum, 2);
491491
push @expected,
492-
qr/${header}toasted value for attribute 2 missing from toast table/;
492+
qr/${header}toast value \d+ not found in toast table/;
493493
}
494494
elsif ($offnum == 14)
495495
{

0 commit comments

Comments
 (0)