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
This commit is contained in:
parent
5fa12fe0cd
commit
a15f787adb
@ -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);
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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 *,
|
||||
|
Loading…
Reference in New Issue
Block a user