From 45824b79b53ee3257d037d3ac9801d8eda3c35d6 Mon Sep 17 00:00:00 2001 From: Melanie Plageman Date: Wed, 23 Sep 2026 11:59:53 -0400 Subject: [PATCH v3 1/3] Read visibility map pages with RBM_ZERO_ON_ERROR in VM clear redo ed62d26caca started registering VM blocks when clearing the VM which is required for protection against torn pages as well as for correct incremental backups. However, it read the VM pages in recovery with RBM_NORMAL which errors out when it encounters a corrupt page. This is usually desirable, however, we still retain code paths that modify the VM in recovery without the block having been registered. A crash while modifying the VM page could lead to a corrupt page and no FPI to recover it. As long as we can trivially produce corrupt pages during recovery through our own redo mechanism, we shouldn't error out when reading a corrupt VM page. Make clearing the VM read the page with RBM_ZERO_ON_ERROR. This is consistent with the VM's other redo paths which set the VM bit (heap_xlog_prune_freeze() and heap_xlog_multi_insert()). Backpatch-through: 17 --- Notes: This is v2-0002 from https://postgr.es/m/CAAKRu_bApoksLDb-HX0GYciU3uLWqA1JagntaV8GP0%3D%2BidehHw%40mail.gmail.com The changed lines and the commit message are the same. Only the context differs, so that it applies to master without v2-0001. It fixes the standby PANIC that Jacky Nguyen reported in https://postgr.es/m/CAL4mQLAp562c1rCgg2Dqx6TBSdOk6vOvaLFjwFG9E6k4uwvJJw@mail.gmail.com src/backend/access/heap/heapam_xlog.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/backend/access/heap/heapam_xlog.c b/src/backend/access/heap/heapam_xlog.c index 5fa1de09cfb..b82f388b4be 100644 --- a/src/backend/access/heap/heapam_xlog.c +++ b/src/backend/access/heap/heapam_xlog.c @@ -53,8 +53,9 @@ heap_xlog_vm_clear(XLogReaderState *record, * read it. These will either apply an FPI or indicate that we should * clear the requested bits ourselves. */ - if (XLogReadBufferForRedo(record, wal_vm_block_id, - &vmbuffer) == BLK_NEEDS_REDO) + if (XLogReadBufferForRedoExtended(record, wal_vm_block_id, + RBM_ZERO_ON_ERROR, false, + &vmbuffer) == BLK_NEEDS_REDO) { if (visibilitymap_clear(target_locator, heap_blkno, vmbuffer, flags)) PageSetLSN(BufferGetPage(vmbuffer), lsn); @@ -812,8 +813,9 @@ heap_xlog_update(XLogReaderState *record, bool hot_update) Assert(xlrec->flags & XLH_UPDATE_NEW_ALL_VISIBLE_CLEARED); - if (XLogReadBufferForRedo(record, HEAP_UPDATE_BLKREF_VM_NEW, - &vmbuffer_new) == BLK_NEEDS_REDO) + if (XLogReadBufferForRedoExtended(record, HEAP_UPDATE_BLKREF_VM_NEW, + RBM_ZERO_ON_ERROR, false, + &vmbuffer_new) == BLK_NEEDS_REDO) { /* * If both the old and new heap pages were all-visible and their @@ -850,8 +852,9 @@ heap_xlog_update(XLogReaderState *record, bool hot_update) Assert(xlrec->flags & XLH_UPDATE_OLD_ALL_VISIBLE_CLEARED); - if (XLogReadBufferForRedo(record, HEAP_UPDATE_BLKREF_VM_OLD, - &vmbuffer_old) == BLK_NEEDS_REDO) + if (XLogReadBufferForRedoExtended(record, HEAP_UPDATE_BLKREF_VM_OLD, + RBM_ZERO_ON_ERROR, false, + &vmbuffer_old) == BLK_NEEDS_REDO) { if (visibilitymap_clear(rlocator, oldblk, vmbuffer_old, VISIBILITYMAP_VALID_BITS)) -- 2.37.1 (Apple Git-137.1)