Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 12 Dec 2016 15:37:11 +0000 (UTC)
From:      Mateusz Guzik <mjg@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r309893 - in head/sys: kern sys
Message-ID:  <201612121537.uBCFbBBk093046@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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);
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201612121537.uBCFbBBk093046>