--- a/sys/vfs/hammer2/hammer2.h 2026-06-29 12:51:19.000000000 +0000 +++ b/sys/vfs/hammer2/hammer2.h 2026-08-29 01:18:27.847135212 +0000 @@ -1254,6 +1254,7 @@ */ #define HAMMER2_PMPF_SPMP 0x00000001 #define HAMMER2_PMPF_EMERG 0x00000002 /* Emergency delete mode */ +#define HAMMER2_PMPF_ROOTFAILED 0x00000004 /* root quorum unreachable */ #define HAMMER2_DIRTYCHAIN_WAITING 0x80000000 #define HAMMER2_DIRTYCHAIN_MASK 0x7FFFFFFF --- a/sys/vfs/hammer2/hammer2_vfsops.c 2026-06-29 12:51:19.000000000 +0000 +++ b/sys/vfs/hammer2/hammer2_vfsops.c 2026-08-29 01:18:27.871134910 +0000 @@ -112,6 +112,10 @@ SYSCTL_INT(_vfs_hammer2, OID_AUTO, supported_version, CTLFLAG_RD, &hammer2_supported_version, 0, ""); +static int hammer2_root_timeout = 60; /* secs; 0 = forever (legacy) */ +SYSCTL_INT(_vfs_hammer2, OID_AUTO, root_timeout, CTLFLAG_RW, + &hammer2_root_timeout, 0, + "max seconds VFS_ROOT waits for cluster quorum (0 = forever)"); SYSCTL_INT(_vfs_hammer2, OID_AUTO, aux_flags, CTLFLAG_RW, &hammer2_aux_flags, 0, ""); SYSCTL_INT(_vfs_hammer2, OID_AUTO, debug, CTLFLAG_RW, @@ -1951,6 +1955,7 @@ hammer2_pfs_t *pmp; struct vnode *vp; int error; + int loops; pmp = MPTOPMP(mp); if (pmp->iroot == NULL) { @@ -1960,7 +1965,19 @@ return EINVAL; } + /* + * DF-2630: A quorum failure is permanent for this pmp (e.g. + * pfs_nmasters ingested from a forged/corrupt PFS inode exceeds + * the number of attached chains). Fail immediately instead of + * re-waiting the full timeout on every lookup crossing the mount. + */ + if (pmp->flags & HAMMER2_PMPF_ROOTFAILED) { + *vpp = NULL; + return EIO; + } + error = 0; + loops = 0; hammer2_inode_lock(pmp->iroot, HAMMER2_RESOLVE_SHARED); while (pmp->inode_tid == 0) { @@ -2008,6 +2025,18 @@ hammer2_inode_lock(pmp->iroot, HAMMER2_RESOLVE_SHARED); if (error == EINTR) break; + if (hammer2_root_timeout && ++loops >= hammer2_root_timeout) { + kprintf("hammer2 (%s): root quorum cannot be reached " + "(nmasters=%d nchains=%d), failing VFS_ROOT " + "after %ds\n", + mp->mnt_stat.f_mntfromname, + pmp->pfs_nmasters, + pmp->iroot->cluster.nchains, + hammer2_root_timeout); + atomic_set_int(&pmp->flags, HAMMER2_PMPF_ROOTFAILED); + error = EIO; + break; + } } if (error) {