vfs: add vrefact, to be used when the vnode has to be already active
This allows blind increment of relevant counters which under contention is cheaper than inc-not-zero loops at least on amd64. Use it in some of the places which are guaranteed to see already active vnodes. Reviewed by: kib (previous version)
This commit is contained in:
parent
f24a1f7d0d
commit
f03b37f3e8
@ -318,11 +318,11 @@ pwd_ensure_dirs(void)
|
|||||||
FILEDESC_XLOCK(fdp);
|
FILEDESC_XLOCK(fdp);
|
||||||
if (fdp->fd_cdir == NULL) {
|
if (fdp->fd_cdir == NULL) {
|
||||||
fdp->fd_cdir = rootvnode;
|
fdp->fd_cdir = rootvnode;
|
||||||
VREF(rootvnode);
|
vrefact(rootvnode);
|
||||||
}
|
}
|
||||||
if (fdp->fd_rdir == NULL) {
|
if (fdp->fd_rdir == NULL) {
|
||||||
fdp->fd_rdir = rootvnode;
|
fdp->fd_rdir = rootvnode;
|
||||||
VREF(rootvnode);
|
vrefact(rootvnode);
|
||||||
}
|
}
|
||||||
FILEDESC_XUNLOCK(fdp);
|
FILEDESC_XUNLOCK(fdp);
|
||||||
}
|
}
|
||||||
@ -1860,13 +1860,13 @@ fdinit(struct filedesc *fdp, bool prepfiles)
|
|||||||
FILEDESC_SLOCK(fdp);
|
FILEDESC_SLOCK(fdp);
|
||||||
newfdp->fd_cdir = fdp->fd_cdir;
|
newfdp->fd_cdir = fdp->fd_cdir;
|
||||||
if (newfdp->fd_cdir)
|
if (newfdp->fd_cdir)
|
||||||
VREF(newfdp->fd_cdir);
|
vrefact(newfdp->fd_cdir);
|
||||||
newfdp->fd_rdir = fdp->fd_rdir;
|
newfdp->fd_rdir = fdp->fd_rdir;
|
||||||
if (newfdp->fd_rdir)
|
if (newfdp->fd_rdir)
|
||||||
VREF(newfdp->fd_rdir);
|
vrefact(newfdp->fd_rdir);
|
||||||
newfdp->fd_jdir = fdp->fd_jdir;
|
newfdp->fd_jdir = fdp->fd_jdir;
|
||||||
if (newfdp->fd_jdir)
|
if (newfdp->fd_jdir)
|
||||||
VREF(newfdp->fd_jdir);
|
vrefact(newfdp->fd_jdir);
|
||||||
|
|
||||||
if (!prepfiles) {
|
if (!prepfiles) {
|
||||||
FILEDESC_SUNLOCK(fdp);
|
FILEDESC_SUNLOCK(fdp);
|
||||||
@ -2769,7 +2769,7 @@ _fgetvp(struct thread *td, int fd, int flags, cap_rights_t *needrightsp,
|
|||||||
error = EINVAL;
|
error = EINVAL;
|
||||||
} else {
|
} else {
|
||||||
*vpp = fp->f_vnode;
|
*vpp = fp->f_vnode;
|
||||||
vref(*vpp);
|
vrefact(*vpp);
|
||||||
}
|
}
|
||||||
fdrop(fp, td);
|
fdrop(fp, td);
|
||||||
|
|
||||||
@ -2807,7 +2807,7 @@ fgetvp_rights(struct thread *td, int fd, cap_rights_t *needrightsp,
|
|||||||
|
|
||||||
*havecaps = caps;
|
*havecaps = caps;
|
||||||
*vpp = fp->f_vnode;
|
*vpp = fp->f_vnode;
|
||||||
vref(*vpp);
|
vrefact(*vpp);
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
out:
|
out:
|
||||||
@ -3115,10 +3115,10 @@ pwd_chroot(struct thread *td, struct vnode *vp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
oldvp = fdp->fd_rdir;
|
oldvp = fdp->fd_rdir;
|
||||||
VREF(vp);
|
vrefact(vp);
|
||||||
fdp->fd_rdir = vp;
|
fdp->fd_rdir = vp;
|
||||||
if (fdp->fd_jdir == NULL) {
|
if (fdp->fd_jdir == NULL) {
|
||||||
VREF(vp);
|
vrefact(vp);
|
||||||
fdp->fd_jdir = vp;
|
fdp->fd_jdir = vp;
|
||||||
}
|
}
|
||||||
FILEDESC_XUNLOCK(fdp);
|
FILEDESC_XUNLOCK(fdp);
|
||||||
@ -3166,17 +3166,17 @@ mountcheckdirs(struct vnode *olddp, struct vnode *newdp)
|
|||||||
continue;
|
continue;
|
||||||
FILEDESC_XLOCK(fdp);
|
FILEDESC_XLOCK(fdp);
|
||||||
if (fdp->fd_cdir == olddp) {
|
if (fdp->fd_cdir == olddp) {
|
||||||
vref(newdp);
|
vrefact(newdp);
|
||||||
fdp->fd_cdir = newdp;
|
fdp->fd_cdir = newdp;
|
||||||
nrele++;
|
nrele++;
|
||||||
}
|
}
|
||||||
if (fdp->fd_rdir == olddp) {
|
if (fdp->fd_rdir == olddp) {
|
||||||
vref(newdp);
|
vrefact(newdp);
|
||||||
fdp->fd_rdir = newdp;
|
fdp->fd_rdir = newdp;
|
||||||
nrele++;
|
nrele++;
|
||||||
}
|
}
|
||||||
if (fdp->fd_jdir == olddp) {
|
if (fdp->fd_jdir == olddp) {
|
||||||
vref(newdp);
|
vrefact(newdp);
|
||||||
fdp->fd_jdir = newdp;
|
fdp->fd_jdir = newdp;
|
||||||
nrele++;
|
nrele++;
|
||||||
}
|
}
|
||||||
@ -3185,13 +3185,13 @@ mountcheckdirs(struct vnode *olddp, struct vnode *newdp)
|
|||||||
}
|
}
|
||||||
sx_sunlock(&allproc_lock);
|
sx_sunlock(&allproc_lock);
|
||||||
if (rootvnode == olddp) {
|
if (rootvnode == olddp) {
|
||||||
vref(newdp);
|
vrefact(newdp);
|
||||||
rootvnode = newdp;
|
rootvnode = newdp;
|
||||||
nrele++;
|
nrele++;
|
||||||
}
|
}
|
||||||
mtx_lock(&prison0.pr_mtx);
|
mtx_lock(&prison0.pr_mtx);
|
||||||
if (prison0.pr_root == olddp) {
|
if (prison0.pr_root == olddp) {
|
||||||
vref(newdp);
|
vrefact(newdp);
|
||||||
prison0.pr_root = newdp;
|
prison0.pr_root = newdp;
|
||||||
nrele++;
|
nrele++;
|
||||||
}
|
}
|
||||||
@ -3200,7 +3200,7 @@ mountcheckdirs(struct vnode *olddp, struct vnode *newdp)
|
|||||||
TAILQ_FOREACH(pr, &allprison, pr_list) {
|
TAILQ_FOREACH(pr, &allprison, pr_list) {
|
||||||
mtx_lock(&pr->pr_mtx);
|
mtx_lock(&pr->pr_mtx);
|
||||||
if (pr->pr_root == olddp) {
|
if (pr->pr_root == olddp) {
|
||||||
vref(newdp);
|
vrefact(newdp);
|
||||||
pr->pr_root = newdp;
|
pr->pr_root = newdp;
|
||||||
nrele++;
|
nrele++;
|
||||||
}
|
}
|
||||||
@ -3527,17 +3527,17 @@ kern_proc_filedesc_out(struct proc *p, struct sbuf *sb, ssize_t maxlen,
|
|||||||
/* ktrace vnode */
|
/* ktrace vnode */
|
||||||
tracevp = p->p_tracevp;
|
tracevp = p->p_tracevp;
|
||||||
if (tracevp != NULL)
|
if (tracevp != NULL)
|
||||||
vref(tracevp);
|
vrefact(tracevp);
|
||||||
/* text vnode */
|
/* text vnode */
|
||||||
textvp = p->p_textvp;
|
textvp = p->p_textvp;
|
||||||
if (textvp != NULL)
|
if (textvp != NULL)
|
||||||
vref(textvp);
|
vrefact(textvp);
|
||||||
/* Controlling tty. */
|
/* Controlling tty. */
|
||||||
cttyvp = NULL;
|
cttyvp = NULL;
|
||||||
if (p->p_pgrp != NULL && p->p_pgrp->pg_session != NULL) {
|
if (p->p_pgrp != NULL && p->p_pgrp->pg_session != NULL) {
|
||||||
cttyvp = p->p_pgrp->pg_session->s_ttyvp;
|
cttyvp = p->p_pgrp->pg_session->s_ttyvp;
|
||||||
if (cttyvp != NULL)
|
if (cttyvp != NULL)
|
||||||
vref(cttyvp);
|
vrefact(cttyvp);
|
||||||
}
|
}
|
||||||
fdp = fdhold(p);
|
fdp = fdhold(p);
|
||||||
PROC_UNLOCK(p);
|
PROC_UNLOCK(p);
|
||||||
@ -3561,17 +3561,17 @@ kern_proc_filedesc_out(struct proc *p, struct sbuf *sb, ssize_t maxlen,
|
|||||||
FILEDESC_SLOCK(fdp);
|
FILEDESC_SLOCK(fdp);
|
||||||
/* working directory */
|
/* working directory */
|
||||||
if (fdp->fd_cdir != NULL) {
|
if (fdp->fd_cdir != NULL) {
|
||||||
vref(fdp->fd_cdir);
|
vrefact(fdp->fd_cdir);
|
||||||
export_vnode_to_sb(fdp->fd_cdir, KF_FD_TYPE_CWD, FREAD, efbuf);
|
export_vnode_to_sb(fdp->fd_cdir, KF_FD_TYPE_CWD, FREAD, efbuf);
|
||||||
}
|
}
|
||||||
/* root directory */
|
/* root directory */
|
||||||
if (fdp->fd_rdir != NULL) {
|
if (fdp->fd_rdir != NULL) {
|
||||||
vref(fdp->fd_rdir);
|
vrefact(fdp->fd_rdir);
|
||||||
export_vnode_to_sb(fdp->fd_rdir, KF_FD_TYPE_ROOT, FREAD, efbuf);
|
export_vnode_to_sb(fdp->fd_rdir, KF_FD_TYPE_ROOT, FREAD, efbuf);
|
||||||
}
|
}
|
||||||
/* jail directory */
|
/* jail directory */
|
||||||
if (fdp->fd_jdir != NULL) {
|
if (fdp->fd_jdir != NULL) {
|
||||||
vref(fdp->fd_jdir);
|
vrefact(fdp->fd_jdir);
|
||||||
export_vnode_to_sb(fdp->fd_jdir, KF_FD_TYPE_JAIL, FREAD, efbuf);
|
export_vnode_to_sb(fdp->fd_jdir, KF_FD_TYPE_JAIL, FREAD, efbuf);
|
||||||
}
|
}
|
||||||
for (i = 0; fdp->fd_refcnt > 0 && i <= fdp->fd_lastfile; i++) {
|
for (i = 0; fdp->fd_refcnt > 0 && i <= fdp->fd_lastfile; i++) {
|
||||||
@ -3661,7 +3661,7 @@ export_vnode_for_osysctl(struct vnode *vp, int type, struct kinfo_file *kif,
|
|||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
vref(vp);
|
vrefact(vp);
|
||||||
FILEDESC_SUNLOCK(fdp);
|
FILEDESC_SUNLOCK(fdp);
|
||||||
export_vnode_to_kinfo(vp, type, 0, kif, KERN_FILEDESC_PACK_KINFO);
|
export_vnode_to_kinfo(vp, type, 0, kif, KERN_FILEDESC_PACK_KINFO);
|
||||||
kinfo_to_okinfo(kif, okif);
|
kinfo_to_okinfo(kif, okif);
|
||||||
@ -3788,7 +3788,7 @@ kern_proc_cwd_out(struct proc *p, struct sbuf *sb, ssize_t maxlen)
|
|||||||
if (fdp->fd_cdir == NULL)
|
if (fdp->fd_cdir == NULL)
|
||||||
error = EINVAL;
|
error = EINVAL;
|
||||||
else {
|
else {
|
||||||
vref(fdp->fd_cdir);
|
vrefact(fdp->fd_cdir);
|
||||||
error = export_vnode_to_sb(fdp->fd_cdir, KF_FD_TYPE_CWD,
|
error = export_vnode_to_sb(fdp->fd_cdir, KF_FD_TYPE_CWD,
|
||||||
FREAD, efbuf);
|
FREAD, efbuf);
|
||||||
}
|
}
|
||||||
|
@ -547,7 +547,7 @@ do_fork(struct thread *td, struct fork_req *fr, struct proc *p2, struct thread *
|
|||||||
|
|
||||||
/* Bump references to the text vnode (for procfs). */
|
/* Bump references to the text vnode (for procfs). */
|
||||||
if (p2->p_textvp)
|
if (p2->p_textvp)
|
||||||
vref(p2->p_textvp);
|
vrefact(p2->p_textvp);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set up linkage for kernel based threading.
|
* Set up linkage for kernel based threading.
|
||||||
|
@ -255,7 +255,7 @@ namei_handle_root(struct nameidata *ndp, struct vnode **dpp)
|
|||||||
ndp->ni_pathlen--;
|
ndp->ni_pathlen--;
|
||||||
}
|
}
|
||||||
*dpp = ndp->ni_rootdir;
|
*dpp = ndp->ni_rootdir;
|
||||||
VREF(*dpp);
|
vrefact(*dpp);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -376,7 +376,7 @@ namei(struct nameidata *ndp)
|
|||||||
*/
|
*/
|
||||||
FILEDESC_SLOCK(fdp);
|
FILEDESC_SLOCK(fdp);
|
||||||
ndp->ni_rootdir = fdp->fd_rdir;
|
ndp->ni_rootdir = fdp->fd_rdir;
|
||||||
VREF(ndp->ni_rootdir);
|
vrefact(ndp->ni_rootdir);
|
||||||
ndp->ni_topdir = fdp->fd_jdir;
|
ndp->ni_topdir = fdp->fd_jdir;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -398,7 +398,7 @@ namei(struct nameidata *ndp)
|
|||||||
startdir_used = 1;
|
startdir_used = 1;
|
||||||
} else if (ndp->ni_dirfd == AT_FDCWD) {
|
} else if (ndp->ni_dirfd == AT_FDCWD) {
|
||||||
dp = fdp->fd_cdir;
|
dp = fdp->fd_cdir;
|
||||||
VREF(dp);
|
vrefact(dp);
|
||||||
} else {
|
} else {
|
||||||
rights = ndp->ni_rightsneeded;
|
rights = ndp->ni_rightsneeded;
|
||||||
cap_rights_set(&rights, CAP_LOOKUP);
|
cap_rights_set(&rights, CAP_LOOKUP);
|
||||||
@ -956,7 +956,7 @@ lookup(struct nameidata *ndp)
|
|||||||
vput(ndp->ni_dvp);
|
vput(ndp->ni_dvp);
|
||||||
else
|
else
|
||||||
vrele(ndp->ni_dvp);
|
vrele(ndp->ni_dvp);
|
||||||
vref(vp_crossmp);
|
vrefact(vp_crossmp);
|
||||||
ndp->ni_dvp = vp_crossmp;
|
ndp->ni_dvp = vp_crossmp;
|
||||||
error = VFS_ROOT(mp, compute_cn_lkflags(mp, cnp->cn_lkflags,
|
error = VFS_ROOT(mp, compute_cn_lkflags(mp, cnp->cn_lkflags,
|
||||||
cnp->cn_flags), &tdp);
|
cnp->cn_flags), &tdp);
|
||||||
|
@ -2647,6 +2647,28 @@ vrefl(struct vnode *vp)
|
|||||||
v_incr_usecount_locked(vp);
|
v_incr_usecount_locked(vp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
vrefact(struct vnode *vp)
|
||||||
|
{
|
||||||
|
|
||||||
|
CTR2(KTR_VFS, "%s: vp %p", __func__, vp);
|
||||||
|
if (__predict_false(vp->v_type == VCHR)) {
|
||||||
|
VNASSERT(vp->v_holdcnt > 0 && vp->v_usecount > 0, vp,
|
||||||
|
("%s: wrong ref counts", __func__));
|
||||||
|
vref(vp);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#ifdef INVARIANTS
|
||||||
|
int old = atomic_fetchadd_int(&vp->v_holdcnt, 1);
|
||||||
|
VNASSERT(old > 0, vp, ("%s: wrong hold count", __func__));
|
||||||
|
old = atomic_fetchadd_int(&vp->v_usecount, 1);
|
||||||
|
VNASSERT(old > 0, vp, ("%s: wrong use count", __func__));
|
||||||
|
#else
|
||||||
|
refcount_acquire(&vp->v_holdcnt);
|
||||||
|
refcount_acquire(&vp->v_usecount);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return reference count of a vnode.
|
* Return reference count of a vnode.
|
||||||
*
|
*
|
||||||
|
@ -828,6 +828,7 @@ void vput(struct vnode *vp);
|
|||||||
void vrele(struct vnode *vp);
|
void vrele(struct vnode *vp);
|
||||||
void vref(struct vnode *vp);
|
void vref(struct vnode *vp);
|
||||||
void vrefl(struct vnode *vp);
|
void vrefl(struct vnode *vp);
|
||||||
|
void vrefact(struct vnode *vp);
|
||||||
int vrefcnt(struct vnode *vp);
|
int vrefcnt(struct vnode *vp);
|
||||||
void v_addpollinfo(struct vnode *vp);
|
void v_addpollinfo(struct vnode *vp);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user