git: 069767091e54 - main - Do not panic in case of corrupted UFS/FFS directory.
Date: Sat, 18 Mar 2023 22:38:24 UTC
The branch main has been updated by mckusick: URL: https://cgit.FreeBSD.org/src/commit/?id=069767091e54a2537ae509dcdf3005fb0f50ab84 commit 069767091e54a2537ae509dcdf3005fb0f50ab84 Author: Kirk McKusick <mckusick@FreeBSD.org> AuthorDate: 2023-03-18 22:36:54 +0000 Commit: Kirk McKusick <mckusick@FreeBSD.org> CommitDate: 2023-03-18 22:37:58 +0000 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 --- sys/ufs/ufs/ufs_lookup.c | 18 +++++------------- sys/ufs/ufs/ufs_vnops.c | 4 +++- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/sys/ufs/ufs/ufs_lookup.c b/sys/ufs/ufs/ufs_lookup.c index 4c390f4c42ef..cabd04a50bfd 100644 --- a/sys/ufs/ufs/ufs_lookup.c +++ b/sys/ufs/ufs/ufs_lookup.c @@ -548,9 +548,8 @@ found: */ 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 @@ found: 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); } /* diff --git a/sys/ufs/ufs/ufs_vnops.c b/sys/ufs/ufs/ufs_vnops.c index ae6d963920f3..54046c285fd7 100644 --- a/sys/ufs/ufs/ufs_vnops.c +++ b/sys/ufs/ufs/ufs_vnops.c @@ -1730,7 +1730,9 @@ relock: /* 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);