Skip to content

Commit f8d2cdc

Browse files
amcheck: Skip unlogged relations during recovery.
contrib/amcheck failed to consider the possibility that unlogged relations will not have any main relation fork files when running in hot standby mode. This led to low-level "can't happen" errors that complain about the absence of a relfilenode file. To fix, simply skip verification of unlogged index relations during recovery. In passing, add a direct check for the presence of a main fork just before verification proper begins, so that we cleanly verify the presence of the main relation fork file. Author: Andrey Borodin, Peter Geoghegan Reported-By: Andrey Borodin Diagnosed-By: Andrey Borodin Discussion: https://postgr.es/m/DA9B33AC-53CB-4643-96D4-7A0BBC037FA1@yandex-team.ru Backpatch: 10-, where amcheck was introduced.
1 parent 333a186 commit f8d2cdc

File tree

1 file changed

+36
-2
lines changed

1 file changed

+36
-2
lines changed

contrib/amcheck/verify_nbtree.c

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "commands/tablecmds.h"
2626
#include "miscadmin.h"
2727
#include "storage/lmgr.h"
28+
#include "storage/smgr.h"
2829
#include "utils/memutils.h"
2930
#include "utils/snapmgr.h"
3031

@@ -94,6 +95,7 @@ PG_FUNCTION_INFO_V1(bt_index_parent_check);
9495

9596
static void bt_index_check_internal(Oid indrelid, bool parentcheck);
9697
static inline void btree_index_checkable(Relation rel);
98+
static inline bool btree_index_mainfork_expected(Relation rel);
9799
static void bt_check_every_level(Relation rel, bool readonly);
98100
static BtreeLevel bt_check_level_from_leftmost(BtreeCheckState *state,
99101
BtreeLevel level);
@@ -204,8 +206,18 @@ bt_index_check_internal(Oid indrelid, bool parentcheck)
204206
/* Relation suitable for checking as B-Tree? */
205207
btree_index_checkable(indrel);
206208

207-
/* Check index */
208-
bt_check_every_level(indrel, parentcheck);
209+
if (btree_index_mainfork_expected(indrel))
210+
{
211+
RelationOpenSmgr(indrel);
212+
if (!smgrexists(indrel->rd_smgr, MAIN_FORKNUM))
213+
ereport(ERROR,
214+
(errcode(ERRCODE_INDEX_CORRUPTED),
215+
errmsg("index \"%s\" lacks a main relation fork",
216+
RelationGetRelationName(indrel))));
217+
218+
/* Check index */
219+
bt_check_every_level(indrel, parentcheck);
220+
}
209221

210222
/*
211223
* Release locks early. That's ok here because nothing in the called
@@ -251,6 +263,28 @@ btree_index_checkable(Relation rel)
251263
errdetail("Index is not valid")));
252264
}
253265

266+
/*
267+
* Check if B-Tree index relation should have a file for its main relation
268+
* fork. Verification uses this to skip unlogged indexes when in hot standby
269+
* mode, where there is simply nothing to verify.
270+
*
271+
* NB: Caller should call btree_index_checkable() before calling here.
272+
*/
273+
static inline bool
274+
btree_index_mainfork_expected(Relation rel)
275+
{
276+
if (rel->rd_rel->relpersistence != RELPERSISTENCE_UNLOGGED ||
277+
!RecoveryInProgress())
278+
return true;
279+
280+
ereport(NOTICE,
281+
(errcode(ERRCODE_READ_ONLY_SQL_TRANSACTION),
282+
errmsg("cannot verify unlogged index \"%s\" during recovery, skipping",
283+
RelationGetRelationName(rel))));
284+
285+
return false;
286+
}
287+
254288
/*
255289
* Main entry point for B-Tree SQL-callable functions. Walks the B-Tree in
256290
* logical order, verifying invariants as it goes.

0 commit comments

Comments
 (0)