1
0
mirror of https://github.com/postgres/postgres.git synced 2026-10-23 13:29:09 +03:00

Add VM corruption check to verify_heapam()

Detect heap pages whose PD_ALL_VISIBLE flag is clear while either
visibility map bit is set. This inconsistent state can cause incorrect
index-only scan results and is not currently reported by verify_heapam().

This also helps users who have access to amcheck but not pg_visibility
to diagnose corruption.

Author: Melanie Plageman <melanieplageman@gmail.com>
Reviewed-by: Andres Freund <andres@anarazel.de>
Discussion: https://postgr.es/m/66mqpfyti3qhfttcsv6r2lbvqqd32rrmpn6i47ovrsnvguts46@gou54xc5jld3
This commit is contained in:
Melanie Plageman
2026-09-23 18:20:49 -04:00
parent bd2aebd7a7
commit 5d84c76021

View File

@@ -482,6 +482,7 @@ verify_heapam(PG_FUNCTION_ARGS)
while ((ctx.buffer = read_stream_next_buffer(stream, NULL)) != InvalidBuffer)
{
uint8 vmbits;
OffsetNumber maxoff;
OffsetNumber predecessor[MaxOffsetNumber];
OffsetNumber successor[MaxOffsetNumber];
@@ -500,6 +501,23 @@ verify_heapam(PG_FUNCTION_ARGS)
ctx.blkno = BufferGetBlockNumber(ctx.buffer);
ctx.page = BufferGetPage(ctx.buffer);
/*
* It is corruption if PD_ALL_VISIBLE is clear while either VM bit is
* set. Missing VM pages are treated as having no bits set. VM pages
* that fail page verification are read with RBM_ZERO_ON_ERROR, so
* those failures are not reported as corruption rows here.
*/
vmbits = visibilitymap_get_status(ctx.rel, ctx.blkno, &vmbuffer);
if (!PageIsAllVisible(ctx.page) &&
(vmbits & VISIBILITYMAP_VALID_BITS) != 0)
{
ctx.offnum = InvalidOffsetNumber;
ctx.attnum = -1;
report_corruption(&ctx,
psprintf("page is not marked all-visible in page header but visibility map bit is set"));
}
/* Perform tuple checks */
maxoff = PageGetMaxOffsetNumber(ctx.page);
for (ctx.offnum = FirstOffsetNumber; ctx.offnum <= maxoff;