diff options
author | mjg <mjg@FreeBSD.org> | 2016-12-31 12:06:27 +0000 |
---|---|---|
committer | mjg <mjg@FreeBSD.org> | 2016-12-31 12:06:27 +0000 |
commit | 1af6bcb527e97aaddea67934bd4fcbd6cb8a1d01 (patch) | |
tree | 6bcdec0ca237f2d33a315bfad1b0af77fdadd516 | |
parent | f83e24b3d82a425ec8bd4bb259f6c75ce6786280 (diff) | |
download | FreeBSD-src-1af6bcb527e97aaddea67934bd4fcbd6cb8a1d01.zip FreeBSD-src-1af6bcb527e97aaddea67934bd4fcbd6cb8a1d01.tar.gz |
MFC r309893,r309929:
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.
==
vfs: use vrefact in getcwd and fchdir
-rw-r--r-- | sys/kern/kern_descrip.c | 46 | ||||
-rw-r--r-- | sys/kern/kern_fork.c | 2 | ||||
-rw-r--r-- | sys/kern/vfs_cache.c | 4 | ||||
-rw-r--r-- | sys/kern/vfs_lookup.c | 8 | ||||
-rw-r--r-- | sys/kern/vfs_subr.c | 22 | ||||
-rw-r--r-- | sys/kern/vfs_syscalls.c | 2 | ||||
-rw-r--r-- | sys/sys/vnode.h | 1 |
7 files changed, 54 insertions, 31 deletions
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index c4edfc9..45e6e97 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -318,11 +318,11 @@ pwd_ensure_dirs(void) FILEDESC_XLOCK(fdp); if (fdp->fd_cdir == NULL) { fdp->fd_cdir = rootvnode; - VREF(rootvnode); + vrefact(rootvnode); } if (fdp->fd_rdir == NULL) { fdp->fd_rdir = rootvnode; - VREF(rootvnode); + vrefact(rootvnode); } FILEDESC_XUNLOCK(fdp); } @@ -1855,13 +1855,13 @@ fdinit(struct filedesc *fdp, bool prepfiles) FILEDESC_SLOCK(fdp); newfdp->fd_cdir = fdp->fd_cdir; if (newfdp->fd_cdir) - VREF(newfdp->fd_cdir); + vrefact(newfdp->fd_cdir); newfdp->fd_rdir = fdp->fd_rdir; if (newfdp->fd_rdir) - VREF(newfdp->fd_rdir); + vrefact(newfdp->fd_rdir); newfdp->fd_jdir = fdp->fd_jdir; if (newfdp->fd_jdir) - VREF(newfdp->fd_jdir); + vrefact(newfdp->fd_jdir); if (!prepfiles) { FILEDESC_SUNLOCK(fdp); @@ -2688,7 +2688,7 @@ _fgetvp(struct thread *td, int fd, int flags, cap_rights_t *needrightsp, error = EINVAL; } else { *vpp = fp->f_vnode; - vref(*vpp); + vrefact(*vpp); } fdrop(fp, td); @@ -2727,7 +2727,7 @@ fgetvp_rights(struct thread *td, int fd, cap_rights_t *needrightsp, return (EINVAL); *vpp = fp->f_vnode; - vref(*vpp); + vrefact(*vpp); filecaps_copy(&fdp->fd_ofiles[fd].fde_caps, havecaps, true); return (0); @@ -3033,10 +3033,10 @@ pwd_chroot(struct thread *td, struct vnode *vp) } } oldvp = fdp->fd_rdir; - VREF(vp); + vrefact(vp); fdp->fd_rdir = vp; if (fdp->fd_jdir == NULL) { - VREF(vp); + vrefact(vp); fdp->fd_jdir = vp; } FILEDESC_XUNLOCK(fdp); @@ -3084,17 +3084,17 @@ mountcheckdirs(struct vnode *olddp, struct vnode *newdp) continue; FILEDESC_XLOCK(fdp); if (fdp->fd_cdir == olddp) { - vref(newdp); + vrefact(newdp); fdp->fd_cdir = newdp; nrele++; } if (fdp->fd_rdir == olddp) { - vref(newdp); + vrefact(newdp); fdp->fd_rdir = newdp; nrele++; } if (fdp->fd_jdir == olddp) { - vref(newdp); + vrefact(newdp); fdp->fd_jdir = newdp; nrele++; } @@ -3103,13 +3103,13 @@ mountcheckdirs(struct vnode *olddp, struct vnode *newdp) } sx_sunlock(&allproc_lock); if (rootvnode == olddp) { - vref(newdp); + vrefact(newdp); rootvnode = newdp; nrele++; } mtx_lock(&prison0.pr_mtx); if (prison0.pr_root == olddp) { - vref(newdp); + vrefact(newdp); prison0.pr_root = newdp; nrele++; } @@ -3118,7 +3118,7 @@ mountcheckdirs(struct vnode *olddp, struct vnode *newdp) TAILQ_FOREACH(pr, &allprison, pr_list) { mtx_lock(&pr->pr_mtx); if (pr->pr_root == olddp) { - vref(newdp); + vrefact(newdp); pr->pr_root = newdp; nrele++; } @@ -3445,17 +3445,17 @@ kern_proc_filedesc_out(struct proc *p, struct sbuf *sb, ssize_t maxlen, /* ktrace vnode */ tracevp = p->p_tracevp; if (tracevp != NULL) - vref(tracevp); + vrefact(tracevp); /* text vnode */ textvp = p->p_textvp; if (textvp != NULL) - vref(textvp); + vrefact(textvp); /* Controlling tty. */ cttyvp = NULL; if (p->p_pgrp != NULL && p->p_pgrp->pg_session != NULL) { cttyvp = p->p_pgrp->pg_session->s_ttyvp; if (cttyvp != NULL) - vref(cttyvp); + vrefact(cttyvp); } fdp = fdhold(p); PROC_UNLOCK(p); @@ -3479,17 +3479,17 @@ kern_proc_filedesc_out(struct proc *p, struct sbuf *sb, ssize_t maxlen, FILEDESC_SLOCK(fdp); /* working directory */ 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); } /* root directory */ 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); } /* jail directory */ 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); } for (i = 0; fdp->fd_refcnt > 0 && i <= fdp->fd_lastfile; i++) { @@ -3579,7 +3579,7 @@ export_vnode_for_osysctl(struct vnode *vp, int type, struct kinfo_file *kif, { int error; - vref(vp); + vrefact(vp); FILEDESC_SUNLOCK(fdp); export_vnode_to_kinfo(vp, type, 0, kif, KERN_FILEDESC_PACK_KINFO); kinfo_to_okinfo(kif, okif); @@ -3706,7 +3706,7 @@ kern_proc_cwd_out(struct proc *p, struct sbuf *sb, ssize_t maxlen) if (fdp->fd_cdir == NULL) error = EINVAL; else { - vref(fdp->fd_cdir); + vrefact(fdp->fd_cdir); error = export_vnode_to_sb(fdp->fd_cdir, KF_FD_TYPE_CWD, FREAD, efbuf); } diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c index b288314..ff1c0a0 100644 --- a/sys/kern/kern_fork.c +++ b/sys/kern/kern_fork.c @@ -549,7 +549,7 @@ do_fork(struct thread *td, struct fork_req *fr, struct proc *p2, struct thread * /* Bump references to the text vnode (for procfs). */ if (p2->p_textvp) - vref(p2->p_textvp); + vrefact(p2->p_textvp); /* * Set up linkage for kernel based threading. diff --git a/sys/kern/vfs_cache.c b/sys/kern/vfs_cache.c index ac46856..efcecaf 100644 --- a/sys/kern/vfs_cache.c +++ b/sys/kern/vfs_cache.c @@ -1122,9 +1122,9 @@ kern___getcwd(struct thread *td, char *buf, enum uio_seg bufseg, u_int buflen, fdp = td->td_proc->p_fd; FILEDESC_SLOCK(fdp); cdir = fdp->fd_cdir; - VREF(cdir); + vrefact(cdir); rdir = fdp->fd_rdir; - VREF(rdir); + vrefact(rdir); FILEDESC_SUNLOCK(fdp); error = vn_fullpath1(td, cdir, rdir, tmpbuf, &bp, buflen); vrele(rdir); diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c index 85c625f..c1ad31e 100644 --- a/sys/kern/vfs_lookup.c +++ b/sys/kern/vfs_lookup.c @@ -200,7 +200,7 @@ namei_handle_root(struct nameidata *ndp, struct vnode **dpp) ndp->ni_pathlen--; } *dpp = ndp->ni_rootdir; - VREF(*dpp); + vrefact(*dpp); return (0); } @@ -321,7 +321,7 @@ namei(struct nameidata *ndp) */ FILEDESC_SLOCK(fdp); ndp->ni_rootdir = fdp->fd_rdir; - VREF(ndp->ni_rootdir); + vrefact(ndp->ni_rootdir); ndp->ni_topdir = fdp->fd_jdir; /* @@ -343,7 +343,7 @@ namei(struct nameidata *ndp) startdir_used = 1; } else if (ndp->ni_dirfd == AT_FDCWD) { dp = fdp->fd_cdir; - VREF(dp); + vrefact(dp); } else { rights = ndp->ni_rightsneeded; cap_rights_set(&rights, CAP_LOOKUP); @@ -910,7 +910,7 @@ good: vput(ndp->ni_dvp); else vrele(ndp->ni_dvp); - vref(vp_crossmp); + vrefact(vp_crossmp); ndp->ni_dvp = vp_crossmp; error = VFS_ROOT(mp, compute_cn_lkflags(mp, cnp->cn_lkflags, cnp->cn_flags), &tdp); diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index cf701c6..9ea3318 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -2576,6 +2576,28 @@ vrefl(struct vnode *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. * diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index 0968486..80b93a1 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -754,7 +754,7 @@ sys_fchdir(td, uap) if (error != 0) return (error); vp = fp->f_vnode; - VREF(vp); + vrefact(vp); fdrop(fp, td); vn_lock(vp, LK_SHARED | LK_RETRY); AUDIT_ARG_VNODE1(vp); diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h index 1f6e384..096806b 100644 --- a/sys/sys/vnode.h +++ b/sys/sys/vnode.h @@ -841,6 +841,7 @@ void vput(struct vnode *vp); void vrele(struct vnode *vp); void vref(struct vnode *vp); void vrefl(struct vnode *vp); +void vrefact(struct vnode *vp); int vrefcnt(struct vnode *vp); void v_addpollinfo(struct vnode *vp); |