Do not panic in case of corrupted UFS/FFS directory.

Historically the system panic'ed when it encountered a corrupt
directory. This change recovers well enough to continue operations.
This change is made in response to a similar change made in the ext2
filesystem as described in the cited Differential Revision.

MFC after:    2 weeks
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D38503
This commit is contained in:
Kirk McKusick 2023-03-18 15:36:54 -07:00
parent bad8f86843
commit 069767091e
2 changed files with 8 additions and 14 deletions

View file

@ -548,9 +548,8 @@ ufs_lookup_ino(struct vnode *vdp, struct vnode **vpp, struct componentname *cnp,
*/
if (i_offset + DIRSIZ(OFSFMT(vdp), ep) > dp->i_size) {
ufs_dirbad(dp, i_offset, "i_size too small");
dp->i_size = i_offset + DIRSIZ(OFSFMT(vdp), ep);
DIP_SET(dp, i_size, dp->i_size);
UFS_INODE_SET_FLAG(dp, IN_SIZEMOD | IN_CHANGE | IN_UPDATE);
brelse(bp);
return (EIO);
}
brelse(bp);
@ -758,17 +757,10 @@ ufs_lookup_ino(struct vnode *vdp, struct vnode **vpp, struct componentname *cnp,
void
ufs_dirbad(struct inode *ip, doff_t offset, char *how)
{
struct mount *mp;
mp = ITOV(ip)->v_mount;
if ((mp->mnt_flag & MNT_RDONLY) == 0)
panic("ufs_dirbad: %s: bad dir ino %ju at offset %ld: %s",
mp->mnt_stat.f_mntonname, (uintmax_t)ip->i_number,
(long)offset, how);
else
(void)printf("%s: bad dir ino %ju at offset %ld: %s\n",
mp->mnt_stat.f_mntonname, (uintmax_t)ip->i_number,
(long)offset, how);
(void)printf("%s: bad dir ino %ju at offset %ld: %s\n",
ITOV(ip)->v_mount->mnt_stat.f_mntonname, (uintmax_t)ip->i_number,
(long)offset, how);
}
/*

View file

@ -1730,7 +1730,9 @@ ufs_rename(
/* Journal must account for each new link. */
softdep_setup_dotdot_link(tdp, fip);
SET_I_OFFSET(fip, mastertemplate.dot_reclen);
ufs_dirrewrite(fip, fdp, newparent, DT_DIR, 0);
if (ufs_dirrewrite(fip, fdp, newparent, DT_DIR, 0) != 0)
ufs_dirbad(fip, mastertemplate.dot_reclen,
"rename: missing ".." entry");
cache_purge(fdvp);
}
error = ufs_dirremove(fdvp, fip, fcnp->cn_flags, 0);