git: a15f787adb44 - main - vfs: add vfs_ref_from_vp

Mateusz Guzik mjg at FreeBSD.org
Sun Feb 21 00:43:16 UTC 2021


The branch main has been updated by mjg:

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

commit a15f787adb4429b83fa911dcb60f69121aaee1ba
Author:     Mateusz Guzik <mjg at FreeBSD.org>
AuthorDate: 2021-02-15 22:08:40 +0000
Commit:     Mateusz Guzik <mjg at FreeBSD.org>
CommitDate: 2021-02-21 00:43:05 +0000

    vfs: add vfs_ref_from_vp
    
    This generalizes what vop_stdgetwritemount used to be doing.
    
    Reviewed by:    kib
    Differential Revision:  https://reviews.freebsd.org/D28695
---
 sys/kern/vfs_default.c | 25 +------------------------
 sys/kern/vfs_mount.c   | 38 ++++++++++++++++++++++++++++++++++++++
 sys/sys/mount.h        |  1 +
 3 files changed, 40 insertions(+), 24 deletions(-)

diff --git a/sys/kern/vfs_default.c b/sys/kern/vfs_default.c
index 3c428d7b7511..4b9b1b43f1ce 100644
--- a/sys/kern/vfs_default.c
+++ b/sys/kern/vfs_default.c
@@ -680,7 +680,6 @@ vop_stdgetwritemount(ap)
 	} */ *ap;
 {
 	struct mount *mp;
-	struct mount_pcpu *mpcpu;
 	struct vnode *vp;
 
 	/*
@@ -693,29 +692,7 @@ vop_stdgetwritemount(ap)
 	 * with releasing it.
 	 */
 	vp = ap->a_vp;
-	mp = vp->v_mount;
-	if (mp == NULL) {
-		*(ap->a_mpp) = NULL;
-		return (0);
-	}
-	if (vfs_op_thread_enter(mp, mpcpu)) {
-		if (mp == vp->v_mount) {
-			vfs_mp_count_add_pcpu(mpcpu, ref, 1);
-			vfs_op_thread_exit(mp, mpcpu);
-		} else {
-			vfs_op_thread_exit(mp, mpcpu);
-			mp = NULL;
-		}
-	} else {
-		MNT_ILOCK(mp);
-		if (mp == vp->v_mount) {
-			MNT_REF(mp);
-			MNT_IUNLOCK(mp);
-		} else {
-			MNT_IUNLOCK(mp);
-			mp = NULL;
-		}
-	}
+	mp = vfs_ref_from_vp(vp);
 	*(ap->a_mpp) = mp;
 	return (0);
 }
diff --git a/sys/kern/vfs_mount.c b/sys/kern/vfs_mount.c
index b3870e46c5e9..e20e1520f677 100644
--- a/sys/kern/vfs_mount.c
+++ b/sys/kern/vfs_mount.c
@@ -449,6 +449,44 @@ sys_nmount(struct thread *td, struct nmount_args *uap)
  * Various utility functions
  */
 
+/*
+ * Get a reference on a mount point from a vnode.
+ *
+ * The vnode is allowed to be passed unlocked and race against dooming. Note in
+ * such case there are no guarantees the referenced mount point will still be
+ * associated with it after the function returns.
+ */
+struct mount *
+vfs_ref_from_vp(struct vnode *vp)
+{
+	struct mount *mp;
+	struct mount_pcpu *mpcpu;
+
+	mp = atomic_load_ptr(&vp->v_mount);
+	if (__predict_false(mp == NULL)) {
+		return (mp);
+	}
+	if (vfs_op_thread_enter(mp, mpcpu)) {
+		if (__predict_true(mp == vp->v_mount)) {
+			vfs_mp_count_add_pcpu(mpcpu, ref, 1);
+			vfs_op_thread_exit(mp, mpcpu);
+		} else {
+			vfs_op_thread_exit(mp, mpcpu);
+			mp = NULL;
+		}
+	} else {
+		MNT_ILOCK(mp);
+		if (mp == vp->v_mount) {
+			MNT_REF(mp);
+			MNT_IUNLOCK(mp);
+		} else {
+			MNT_IUNLOCK(mp);
+			mp = NULL;
+		}
+	}
+	return (mp);
+}
+
 void
 vfs_ref(struct mount *mp)
 {
diff --git a/sys/sys/mount.h b/sys/sys/mount.h
index f965dd72d7ba..9ae5f58e5218 100644
--- a/sys/sys/mount.h
+++ b/sys/sys/mount.h
@@ -997,6 +997,7 @@ void	vfs_mount_error(struct mount *, const char *, ...);
 void	vfs_mountroot(void);			/* mount our root filesystem */
 void	vfs_mountedfrom(struct mount *, const char *from);
 void	vfs_notify_upper(struct vnode *, int);
+struct mount *vfs_ref_from_vp(struct vnode *);
 void	vfs_ref(struct mount *);
 void	vfs_rel(struct mount *);
 struct mount *vfs_mount_alloc(struct vnode *, struct vfsconf *, const char *,


More information about the dev-commits-src-main mailing list