Author: mjg
Date: Mon Dec 12 15:37:11 2016
New Revision: 309893
URL: https://svnweb.freebsd.org/changeset/base/309893

Log:
  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)

Modified:
  head/sys/kern/kern_descrip.c
  head/sys/kern/kern_fork.c
  head/sys/kern/vfs_lookup.c
  head/sys/kern/vfs_subr.c
  head/sys/sys/vnode.h

Modified: head/sys/kern/kern_descrip.c
==============================================================================
--- head/sys/kern/kern_descrip.c        Mon Dec 12 15:35:57 2016        
(r309892)
+++ head/sys/kern/kern_descrip.c        Mon Dec 12 15:37:11 2016        
(r309893)
@@ -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);
 }
@@ -1860,13 +1860,13 @@ fdinit(struct filedesc *fdp, bool prepfi
        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);
@@ -2769,7 +2769,7 @@ _fgetvp(struct thread *td, int fd, int f
                error = EINVAL;
        } else {
                *vpp = fp->f_vnode;
-               vref(*vpp);
+               vrefact(*vpp);
        }
        fdrop(fp, td);
 
@@ -2807,7 +2807,7 @@ fgetvp_rights(struct thread *td, int fd,
 
        *havecaps = caps;
        *vpp = fp->f_vnode;
-       vref(*vpp);
+       vrefact(*vpp);
 
        return (0);
 out:
@@ -3115,10 +3115,10 @@ pwd_chroot(struct thread *td, struct vno
                }
        }
        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);
@@ -3166,17 +3166,17 @@ mountcheckdirs(struct vnode *olddp, stru
                        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++;
                }
@@ -3185,13 +3185,13 @@ mountcheckdirs(struct vnode *olddp, stru
        }
        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++;
        }
@@ -3200,7 +3200,7 @@ mountcheckdirs(struct vnode *olddp, stru
        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++;
                }
@@ -3527,17 +3527,17 @@ kern_proc_filedesc_out(struct proc *p,  
        /* 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);
@@ -3561,17 +3561,17 @@ kern_proc_filedesc_out(struct proc *p,  
        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++) {
@@ -3661,7 +3661,7 @@ export_vnode_for_osysctl(struct vnode *v
 {
        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);
@@ -3788,7 +3788,7 @@ kern_proc_cwd_out(struct proc *p,  struc
        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);
        }

Modified: head/sys/kern/kern_fork.c
==============================================================================
--- head/sys/kern/kern_fork.c   Mon Dec 12 15:35:57 2016        (r309892)
+++ head/sys/kern/kern_fork.c   Mon Dec 12 15:37:11 2016        (r309893)
@@ -547,7 +547,7 @@ do_fork(struct thread *td, struct fork_r
 
        /* 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.

Modified: head/sys/kern/vfs_lookup.c
==============================================================================
--- head/sys/kern/vfs_lookup.c  Mon Dec 12 15:35:57 2016        (r309892)
+++ head/sys/kern/vfs_lookup.c  Mon Dec 12 15:37:11 2016        (r309893)
@@ -255,7 +255,7 @@ namei_handle_root(struct nameidata *ndp,
                ndp->ni_pathlen--;
        }
        *dpp = ndp->ni_rootdir;
-       VREF(*dpp);
+       vrefact(*dpp);
        return (0);
 }
 
@@ -376,7 +376,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;
 
        /*
@@ -398,7 +398,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);
@@ -956,7 +956,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);

Modified: head/sys/kern/vfs_subr.c
==============================================================================
--- head/sys/kern/vfs_subr.c    Mon Dec 12 15:35:57 2016        (r309892)
+++ head/sys/kern/vfs_subr.c    Mon Dec 12 15:37:11 2016        (r309893)
@@ -2647,6 +2647,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.
  *

Modified: head/sys/sys/vnode.h
==============================================================================
--- head/sys/sys/vnode.h        Mon Dec 12 15:35:57 2016        (r309892)
+++ head/sys/sys/vnode.h        Mon Dec 12 15:37:11 2016        (r309893)
@@ -828,6 +828,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);
 
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to