git: a179e72489f8 - main - ufs: report a mismatched ".." in ufs_dirrewrite()

From: Maxim Sobolev <sobomax_at_FreeBSD.org>
Date: Wed, 30 Sep 2026 05:13:15 UTC
The branch main has been updated by sobomax:

URL: https://cgit.FreeBSD.org/src/commit/?id=a179e72489f8601f37b9039c86d3f224c73b3d51

commit a179e72489f8601f37b9039c86d3f224c73b3d51
Author:     Maxim Sobolev <sobomax@FreeBSD.org>
AuthorDate: 2026-09-30 05:11:10 +0000
Commit:     Maxim Sobolev <sobomax@FreeBSD.org>
CommitDate: 2026-09-30 05:11:42 +0000

    ufs: report a mismatched ".." in ufs_dirrewrite()
    
    When ufs_rename() moves a directory to a new parent and ufs_dirrewrite()
    fails to rewrite its ".." entry, it reports "bad dir ... rename: missing
    .. entry" whatever the error.  ufs_dirrewrite() never finds a missing
    "..", though: it fails with EIDRM when the ".." entry names another inode
    than the expected one, and otherwise only when the directory block cannot
    be read or written.  The latter happens for every directory rename in
    flight when the device goes away under a forcibly unmounted file system,
    and the log then fills with reports of directories that are intact on
    disk.
    
    Report the EIDRM case with ufs_dirbad() in ufs_dirrewrite() itself, so
    that all of its callers get the same diagnostic, and drop the report
    from ufs_rename().  Errors from the lower layers are not reported, as
    usual for an I/O initiator.
    
    Reviewed by:    kib
    MFC after:      2 weeks
    Differential Revision:  https://reviews.freebsd.org/D60137
---
 sys/ufs/ufs/ufs_lookup.c | 2 ++
 sys/ufs/ufs/ufs_vnops.c  | 4 +---
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/sys/ufs/ufs/ufs_lookup.c b/sys/ufs/ufs/ufs_lookup.c
index 419ec3de8572..216014a72d35 100644
--- a/sys/ufs/ufs/ufs_lookup.c
+++ b/sys/ufs/ufs/ufs_lookup.c
@@ -1246,6 +1246,8 @@ ufs_dirrewrite(struct inode *dp, struct inode *oip, ino_t newinum, int newtype,
 	error = UFS_BLKATOFF(vdp, (off_t)I_OFFSET(dp), (char **)&ep, &bp);
 	if (error == 0 && ep->d_namlen == 2 && ep->d_name[1] == '.' &&
 	    ep->d_name[0] == '.' && ep->d_ino != oip->i_number) {
+		ufs_dirbad(dp, I_OFFSET(dp),
+		    "rewrite: .. entry does not name the expected inode");
 		brelse(bp);
 		error = EIDRM;
 	}
diff --git a/sys/ufs/ufs/ufs_vnops.c b/sys/ufs/ufs/ufs_vnops.c
index 3c79c8814085..aecb784ec46a 100644
--- a/sys/ufs/ufs/ufs_vnops.c
+++ b/sys/ufs/ufs/ufs_vnops.c
@@ -1749,9 +1749,7 @@ relock:
 			/* Journal must account for each new link. */
 			softdep_setup_dotdot_link(tdp, fip);
 		SET_I_OFFSET(fip, mastertemplate.dot_reclen);
-		if (ufs_dirrewrite(fip, fdp, newparent, DT_DIR, 0) != 0)
-			ufs_dirbad(fip, mastertemplate.dot_reclen,
-			    "rename: missing .. entry");
+		(void)ufs_dirrewrite(fip, fdp, newparent, DT_DIR, 0);
 		cache_purge(fdvp);
 	}
 	error = ufs_dirremove(fdvp, fip, fcnp->cn_flags, false);