git: 0ef861e6f4dd - main - nullfs: adopt VV_CROSSLOCK

From: Jason A. Harmening <jah_at_FreeBSD.org>
Date: Sun, 11 Dec 2022 03:48:56 UTC
The branch main has been updated by jah:

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

commit 0ef861e6f4dd37047e6fdb1ae18736434c2c957c
Author:     Jason A. Harmening <jah@FreeBSD.org>
AuthorDate: 2022-11-20 18:33:34 +0000
Commit:     Jason A. Harmening <jah@FreeBSD.org>
CommitDate: 2022-12-11 04:02:39 +0000

    nullfs: adopt VV_CROSSLOCK
    
    When the lower filesystem directory hierarchy is the same as the nullfs
    mount point (admittedly not likely to be a useful situation in
    practice), nullfs is subject to the exact deadlock between the busy
    count drain and the covered vnode lock that VV_CROSSLOCK is intended
    to address.
    
    Reviewed by:    kib
    Tested by:      pho
    Differential Revision: https://reviews.freebsd.org/D37458
---
 sys/fs/nullfs/null_vfsops.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/sys/fs/nullfs/null_vfsops.c b/sys/fs/nullfs/null_vfsops.c
index fd119afa7f07..216a8badce56 100644
--- a/sys/fs/nullfs/null_vfsops.c
+++ b/sys/fs/nullfs/null_vfsops.c
@@ -201,6 +201,12 @@ nullfs_mount(struct mount *mp)
 		    &xmp->notify_node);
 	}
 
+	if (lowerrootvp == mp->mnt_vnodecovered) {
+		vn_lock(lowerrootvp, LK_EXCLUSIVE | LK_RETRY | LK_CANRECURSE);
+		lowerrootvp->v_vflag |= VV_CROSSLOCK;
+		VOP_UNLOCK(lowerrootvp);
+	}
+
 	MNT_ILOCK(mp);
 	if ((xmp->nullm_flags & NULLM_CACHE) != 0) {
 		mp->mnt_kern_flag |= lowerrootvp->v_mount->mnt_kern_flag &
@@ -261,6 +267,11 @@ nullfs_unmount(mp, mntflags)
 		vfs_unregister_for_notification(mntdata->nullm_vfs,
 		    &mntdata->notify_node);
 	}
+	if (mntdata->nullm_lowerrootvp == mp->mnt_vnodecovered) {
+		vn_lock(mp->mnt_vnodecovered, LK_EXCLUSIVE | LK_RETRY | LK_CANRECURSE);
+		mp->mnt_vnodecovered->v_vflag &= ~VV_CROSSLOCK;
+		VOP_UNLOCK(mp->mnt_vnodecovered);
+	}
 	vfs_unregister_upper(mntdata->nullm_vfs, &mntdata->upper_node);
 	vrele(mntdata->nullm_lowerrootvp);
 	mp->mnt_data = NULL;