Author: mjg
Date: Sat Dec 31 12:06:27 2016
New Revision: 310953
URL: https://svnweb.freebsd.org/changeset/base/310953

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

Modified:
  stable/11/sys/kern/kern_descrip.c
  stable/11/sys/kern/kern_fork.c
  stable/11/sys/kern/vfs_cache.c
  stable/11/sys/kern/vfs_lookup.c
  stable/11/sys/kern/vfs_subr.c
  stable/11/sys/kern/vfs_syscalls.c
  stable/11/sys/sys/vnode.h
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/kern/kern_descrip.c
==============================================================================
--- stable/11/sys/kern/kern_descrip.c   Sat Dec 31 12:03:25 2016        
(r310952)
+++ stable/11/sys/kern/kern_descrip.c   Sat Dec 31 12:06:27 2016        
(r310953)
@@ -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 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);
@@ -2688,7 +2688,7 @@ _fgetvp(struct thread *td, int fd, int f
                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,
                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 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);
@@ -3084,17 +3084,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++;
                }
@@ -3103,13 +3103,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++;
        }
@@ -3118,7 +3118,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++;
                }
@@ -3445,17 +3445,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);
@@ -3479,17 +3479,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++) {
@@ -3579,7 +3579,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);
@@ -3706,7 +3706,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: stable/11/sys/kern/kern_fork.c
==============================================================================
--- stable/11/sys/kern/kern_fork.c      Sat Dec 31 12:03:25 2016        
(r310952)
+++ stable/11/sys/kern/kern_fork.c      Sat Dec 31 12:06:27 2016        
(r310953)
@@ -549,7 +549,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: stable/11/sys/kern/vfs_cache.c
==============================================================================
--- stable/11/sys/kern/vfs_cache.c      Sat Dec 31 12:03:25 2016        
(r310952)
+++ stable/11/sys/kern/vfs_cache.c      Sat Dec 31 12:06:27 2016        
(r310953)
@@ -1122,9 +1122,9 @@ kern___getcwd(struct thread *td, char *b
        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);

Modified: stable/11/sys/kern/vfs_lookup.c
==============================================================================
--- stable/11/sys/kern/vfs_lookup.c     Sat Dec 31 12:03:25 2016        
(r310952)
+++ stable/11/sys/kern/vfs_lookup.c     Sat Dec 31 12:06:27 2016        
(r310953)
@@ -200,7 +200,7 @@ namei_handle_root(struct nameidata *ndp,
                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);

Modified: stable/11/sys/kern/vfs_subr.c
==============================================================================
--- stable/11/sys/kern/vfs_subr.c       Sat Dec 31 12:03:25 2016        
(r310952)
+++ stable/11/sys/kern/vfs_subr.c       Sat Dec 31 12:06:27 2016        
(r310953)
@@ -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.
  *

Modified: stable/11/sys/kern/vfs_syscalls.c
==============================================================================
--- stable/11/sys/kern/vfs_syscalls.c   Sat Dec 31 12:03:25 2016        
(r310952)
+++ stable/11/sys/kern/vfs_syscalls.c   Sat Dec 31 12:06:27 2016        
(r310953)
@@ -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);

Modified: stable/11/sys/sys/vnode.h
==============================================================================
--- stable/11/sys/sys/vnode.h   Sat Dec 31 12:03:25 2016        (r310952)
+++ stable/11/sys/sys/vnode.h   Sat Dec 31 12:06:27 2016        (r310953)
@@ -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);
 
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to