From: Andres Freund <andres@anarazel.de>
Subject: [PATCH v4 2/6] Verify redirect items are still correct after heap_page_prune().
Date: Mon, 22 Nov 2021 09:52:45 -0800
Author: Andres Freund <andres@andres@anarazel.de>
Discussion: https://postgr.es/m/20211122175914.ayk6gg6nvdwuhrzb@alap3.anarazel.de
---
src/backend/access/heap/pruneheap.c | 57 +++++++++++++++++++++++++++++
1 file changed, 57 insertions(+)
inline patch 1: src/backend/access/heap/pruneheap.c (+57/-0 lines) download inline-1.patchdiff --git a/src/backend/access/heap/pruneheap.c b/src/backend/access/heap/pruneheap.cindex baf33c9b988..6557d710262 100644--- a/src/backend/access/heap/pruneheap.c+++ b/src/backend/access/heap/pruneheap.c@@ -89,6 +89,7 @@ static void heap_prune_record_redirect(PruneState *prstate,
OffsetNumber offnum, OffsetNumber rdoffnum);
static void heap_prune_record_dead(PruneState *prstate, OffsetNumber offnum);
static void heap_prune_record_unused(PruneState *prstate, OffsetNumber offnum);
+static void page_verify_redirects(Page page);
/*
@@ -961,6 +962,10 @@ heap_page_prune_execute(Buffer buffer,
* indexes when an entire HOT chain becomes dead. A heap-only tuple
* can never become LP_DEAD; an LP_REDIRECT item or a regular heap
* tuple can.
+ *+ * This check may miss problems, e.g. the target of a redirect could+ * be marked as unused subsequently. The page_verify_redirects() check+ * below will catch such problems.
*/
tolp = PageGetItemId(page, tooff);
Assert(ItemIdHasStorage(tolp) && ItemIdIsNormal(tolp));
@@ -1030,6 +1035,58 @@ heap_page_prune_execute(Buffer buffer,
* whether it has free pointers.
*/
PageRepairFragmentation(page);
++ /*+ * Now that the page has been modified, assert that redirect items still+ * point to valid targets.+ */+ page_verify_redirects(page);+}+++/*+ * If built with assertions, verify that all LP_REDIRECT items point to a+ * valid item.+ *+ * One way that bugs around HOT pruning show is redirect items pointing to+ * removed tuples. It's not trivial to reliably check that making an item+ * unused will not orphan a redirect item during heap_prune_chain() /+ * heap_page_prune_execute(), so we additionally check the whole page after+ * pruning. Without this check such bugs would typically only cause asserts+ * later, potentially well after the corruption has been introduced.+ *+ * Also check comments in heap_page_prune_execute()'s redirection loop.+ */+static void+page_verify_redirects(Page page)+{+#ifdef USE_ASSERT_CHECKING+ OffsetNumber offnum;+ OffsetNumber maxoff;++ maxoff = PageGetMaxOffsetNumber(page);+ for (offnum = FirstOffsetNumber;+ offnum <= maxoff;+ offnum = OffsetNumberNext(offnum))+ {+ ItemId itemid = PageGetItemId(page, offnum);+ OffsetNumber targoff;+ ItemId targitem;+ HeapTupleHeader htup;++ if (!ItemIdIsRedirected(itemid))+ continue;++ targoff = ItemIdGetRedirect(itemid);+ targitem = PageGetItemId(page, targoff);++ Assert(ItemIdIsUsed(targitem));+ Assert(ItemIdIsNormal(targitem));+ Assert(ItemIdHasStorage(targitem));+ htup = (HeapTupleHeader) PageGetItem(page, targitem);+ Assert(HeapTupleHeaderIsHeapOnly(htup));+ }+#endif
}
--
2.34.0
--ychkzf6m3ad4yr7p
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0003-heap-pruning-Only-call-BufferGetBlockNumber-once.patch"
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: pgsql-bugs@postgresql.org
Cc: andres@anarazel.de
Subject: Re: [PATCH v4 2/6] Verify redirect items are still correct after heap_page_prune().
In-Reply-To: <no-message-id-15984@localhost>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by DDX for PostgreSQL; see mirroring instructions
for how to clone and mirror all data and code used for this inbox