DF-3253 / fix.diff
--- a/sys/vfs/hpfs/hpfs_hash.c 2026-09-09 14:23:15.467586441 +0000 +++ b/sys/vfs/hpfs/hpfs_hash.c 2026-09-09 14:23:15.483586242 +0000 @@ -129,6 +129,20 @@ } /* + * DF-3253: hpfs_vget publishes nodes into the hash before + * validating them (bread + FN_MAGIC) and its error paths + * vx_put() without unhashing. Never hand out a node that + * is still marked H_INVAL -- its h_fn is either not yet + * initialized (bread failed) or was already rejected. + * The retry is bounded because failed creators now unhash + * the node (hpfs_vfsops.c DF-3253 fix). + */ + if (hp->h_flag & H_INVAL) { + vput(vp); + goto loop; + } + + /* * Or if the vget fails (due to a race) */ lwkt_reltoken(&hpfs_hphash_token); --- a/sys/vfs/hpfs/hpfs_vfsops.c 2026-09-09 14:21:27.496928348 +0000 +++ b/sys/vfs/hpfs/hpfs_vfsops.c 2026-09-09 14:23:15.495586092 +0000 @@ -529,6 +529,7 @@ error = bread(hpmp->hpm_devvp, dbtodoff(ino), FNODESIZE, &bp); if (error) { kprintf("hpfs_vget: can't read ino %"PRId64"\n",ino); + hpfs_hphashrem(hp); /* DF-3253: don't leave H_INVAL hashed */ vx_put(vp); return (error); } @@ -537,6 +538,7 @@ if (hp->h_fn.fn_magic != FN_MAGIC) { kprintf("hpfs_vget: MAGIC DOESN'T MATCH\n"); + hpfs_hphashrem(hp); /* DF-3253: don't leave H_INVAL hashed */ vx_put(vp); return (EINVAL); } |