git: fb16013129a1 - stable/13 - vfs: add vfs_ref_from_vp
Mateusz Guzik
mjg at FreeBSD.org
Sat Apr 10 06:02:08 UTC 2021
The branch stable/13 has been updated by mjg:
URL: https://cgit.FreeBSD.org/src/commit/?id=fb16013129a10a10be46197a82b814e479ed0905
commit fb16013129a10a10be46197a82b814e479ed0905
Author: Mateusz Guzik <mjg at FreeBSD.org>
AuthorDate: 2021-02-15 22:08:40 +0000
Commit: Mateusz Guzik <mjg at FreeBSD.org>
CommitDate: 2021-04-10 05:57:55 +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
(cherry picked from commit a15f787adb4429b83fa911dcb60f69121aaee1ba)
---
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 59000728efcc..7dc6b795eefd 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 98d50161bed5..e6a74bf1fb60 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-branches
mailing list