svn commit: r229703 - in stable/9: . sys/cddl/contrib/opensolaris/uts/common/fs/zfs sys/fs/devfs sys/fs/nullfs sys/fs/pseudofs sys/kern

Konstantin Belousov kib at FreeBSD.org
Fri Jan 6 15:07:29 UTC 2012


Author: kib
Date: Fri Jan  6 15:07:28 2012
New Revision: 229703
URL: http://svn.freebsd.org/changeset/base/229703

Log:
  MFC r227697:
  Change the interface for VOP_VPTOCNP(), now the dvp must be
  referenced. Convert all in-tree implementations of VOP_VPTOCNP().
  This fixes VOP_VPTOCNP bypass for nullfs.
  
  Approved by:	re (bz)

Modified:
  stable/9/UPDATING
  stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c
  stable/9/sys/fs/devfs/devfs_vnops.c
  stable/9/sys/fs/nullfs/null_vnops.c
  stable/9/sys/fs/pseudofs/pseudofs_vnops.c
  stable/9/sys/kern/vfs_cache.c
  stable/9/sys/kern/vfs_default.c
Directory Properties:
  stable/9/sys/   (props changed)
  stable/9/sys/cddl/contrib/opensolaris/   (props changed)

Modified: stable/9/UPDATING
==============================================================================
--- stable/9/UPDATING	Fri Jan  6 15:01:05 2012	(r229702)
+++ stable/9/UPDATING	Fri Jan  6 15:07:28 2012	(r229703)
@@ -10,6 +10,11 @@ Items affecting the ports and packages s
 /usr/ports/UPDATING.  Please read that file before running portupgrade.
 
 20120106:
+	The interface of the VOP_VPTOCNP(9) changed, now the returned
+	vnode shall be referenced, previously it was required to be
+	only held.  All in-tree filesystems are converted.
+
+20120106:
 	9.0-RELEASE.
 
 20111101:

Modified: stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c
==============================================================================
--- stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c	Fri Jan  6 15:01:05 2012	(r229702)
+++ stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c	Fri Jan  6 15:07:28 2012	(r229703)
@@ -1594,7 +1594,7 @@ zfsctl_snapshot_vptocnp(struct vop_vptoc
 		*ap->a_buflen -= len;
 		bcopy(sep->se_name, ap->a_buf + *ap->a_buflen, len);
 		mutex_exit(&sdp->sd_lock);
-		vhold(dvp);
+		vref(dvp);
 		*ap->a_vpp = dvp;
 	}
 	VN_RELE(dvp);

Modified: stable/9/sys/fs/devfs/devfs_vnops.c
==============================================================================
--- stable/9/sys/fs/devfs/devfs_vnops.c	Fri Jan  6 15:01:05 2012	(r229702)
+++ stable/9/sys/fs/devfs/devfs_vnops.c	Fri Jan  6 15:07:28 2012	(r229703)
@@ -261,7 +261,7 @@ devfs_vptocnp(struct vop_vptocnp_args *a
 	} else if (vp->v_type == VDIR) {
 		if (dd == dmp->dm_rootdir) {
 			*dvp = vp;
-			vhold(*dvp);
+			vref(*dvp);
 			goto finished;
 		}
 		i -= dd->de_dirent->d_namlen;
@@ -289,6 +289,8 @@ devfs_vptocnp(struct vop_vptocnp_args *a
 		mtx_unlock(&devfs_de_interlock);
 		vholdl(*dvp);
 		VI_UNLOCK(*dvp);
+		vref(*dvp);
+		vdrop(*dvp);
 	} else {
 		mtx_unlock(&devfs_de_interlock);
 		error = ENOENT;

Modified: stable/9/sys/fs/nullfs/null_vnops.c
==============================================================================
--- stable/9/sys/fs/nullfs/null_vnops.c	Fri Jan  6 15:01:05 2012	(r229702)
+++ stable/9/sys/fs/nullfs/null_vnops.c	Fri Jan  6 15:07:28 2012	(r229703)
@@ -784,6 +784,7 @@ null_vptocnp(struct vop_vptocnp_args *ap
 	vhold(lvp);
 	VOP_UNLOCK(vp, 0); /* vp is held by vn_vptocnp_locked that called us */
 	ldvp = lvp;
+	vref(lvp);
 	error = vn_vptocnp(&ldvp, cred, ap->a_buf, ap->a_buflen);
 	vdrop(lvp);
 	if (error != 0) {
@@ -797,19 +798,17 @@ null_vptocnp(struct vop_vptocnp_args *ap
 	 */
 	error = vn_lock(ldvp, LK_EXCLUSIVE);
 	if (error != 0) {
+		vrele(ldvp);
 		vn_lock(vp, locked | LK_RETRY);
-		vdrop(ldvp);
 		return (ENOENT);
 	}
 	vref(ldvp);
-	vdrop(ldvp);
 	error = null_nodeget(vp->v_mount, ldvp, dvp);
 	if (error == 0) {
 #ifdef DIAGNOSTIC
 		NULLVPTOLOWERVP(*dvp);
 #endif
-		vhold(*dvp);
-		vput(*dvp);
+		VOP_UNLOCK(*dvp, 0); /* keep reference on *dvp */
 	} else
 		vput(ldvp);
 

Modified: stable/9/sys/fs/pseudofs/pseudofs_vnops.c
==============================================================================
--- stable/9/sys/fs/pseudofs/pseudofs_vnops.c	Fri Jan  6 15:01:05 2012	(r229702)
+++ stable/9/sys/fs/pseudofs/pseudofs_vnops.c	Fri Jan  6 15:07:28 2012	(r229703)
@@ -410,8 +410,7 @@ pfs_vptocnp(struct vop_vptocnp_args *ap)
 	}
 
 	*buflen = i;
-	vhold(*dvp);
-	vput(*dvp);
+	VOP_UNLOCK(*dvp, 0);
 	vn_lock(vp, locked | LK_RETRY);
 	vfs_unbusy(mp);
 

Modified: stable/9/sys/kern/vfs_cache.c
==============================================================================
--- stable/9/sys/kern/vfs_cache.c	Fri Jan  6 15:01:05 2012	(r229702)
+++ stable/9/sys/kern/vfs_cache.c	Fri Jan  6 15:07:28 2012	(r229703)
@@ -1067,16 +1067,8 @@ vn_vptocnp(struct vnode **vp, struct ucr
 
 	CACHE_RLOCK();
 	error = vn_vptocnp_locked(vp, cred, buf, buflen);
-	if (error == 0) {
-		/*
-		 * vn_vptocnp_locked() dropped hold acquired by
-		 * VOP_VPTOCNP immediately after locking the
-		 * cache. Since we are going to drop the cache rlock,
-		 * re-hold the result.
-		 */
-		vhold(*vp);
+	if (error == 0)
 		CACHE_RUNLOCK();
-	}
 	return (error);
 }
 
@@ -1095,6 +1087,9 @@ vn_vptocnp_locked(struct vnode **vp, str
 	if (ncp != NULL) {
 		if (*buflen < ncp->nc_nlen) {
 			CACHE_RUNLOCK();
+			vfslocked = VFS_LOCK_GIANT((*vp)->v_mount);
+			vrele(*vp);
+			VFS_UNLOCK_GIANT(vfslocked);
 			numfullpathfail4++;
 			error = ENOMEM;
 			SDT_PROBE(vfs, namecache, fullpath, return, error,
@@ -1105,18 +1100,23 @@ vn_vptocnp_locked(struct vnode **vp, str
 		memcpy(buf + *buflen, ncp->nc_name, ncp->nc_nlen);
 		SDT_PROBE(vfs, namecache, fullpath, hit, ncp->nc_dvp,
 		    ncp->nc_name, vp, 0, 0);
+		dvp = *vp;
 		*vp = ncp->nc_dvp;
+		vref(*vp);
+		CACHE_RUNLOCK();
+		vfslocked = VFS_LOCK_GIANT(dvp->v_mount);
+		vrele(dvp);
+		VFS_UNLOCK_GIANT(vfslocked);
+		CACHE_RLOCK();
 		return (0);
 	}
 	SDT_PROBE(vfs, namecache, fullpath, miss, vp, 0, 0, 0, 0);
 
-	vhold(*vp);
 	CACHE_RUNLOCK();
 	vfslocked = VFS_LOCK_GIANT((*vp)->v_mount);
 	vn_lock(*vp, LK_SHARED | LK_RETRY);
 	error = VOP_VPTOCNP(*vp, &dvp, cred, buf, buflen);
-	VOP_UNLOCK(*vp, 0);
-	vdrop(*vp);
+	vput(*vp);
 	VFS_UNLOCK_GIANT(vfslocked);
 	if (error) {
 		numfullpathfail2++;
@@ -1127,16 +1127,20 @@ vn_vptocnp_locked(struct vnode **vp, str
 
 	*vp = dvp;
 	CACHE_RLOCK();
-	if ((*vp)->v_iflag & VI_DOOMED) {
+	if (dvp->v_iflag & VI_DOOMED) {
 		/* forced unmount */
 		CACHE_RUNLOCK();
-		vdrop(*vp);
+		vfslocked = VFS_LOCK_GIANT(dvp->v_mount);
+		vrele(dvp);
+		VFS_UNLOCK_GIANT(vfslocked);
 		error = ENOENT;
 		SDT_PROBE(vfs, namecache, fullpath, return, error, vp,
 		    NULL, 0, 0);
 		return (error);
 	}
-	vdrop(*vp);
+	/*
+	 * *vp has its use count incremented still.
+	 */
 
 	return (0);
 }
@@ -1148,10 +1152,11 @@ static int
 vn_fullpath1(struct thread *td, struct vnode *vp, struct vnode *rdir,
     char *buf, char **retbuf, u_int buflen)
 {
-	int error, slash_prefixed;
+	int error, slash_prefixed, vfslocked;
 #ifdef KDTRACE_HOOKS
 	struct vnode *startvp = vp;
 #endif
+	struct vnode *vp1;
 
 	buflen--;
 	buf[buflen] = '\0';
@@ -1160,6 +1165,7 @@ vn_fullpath1(struct thread *td, struct v
 
 	SDT_PROBE(vfs, namecache, fullpath, entry, vp, 0, 0, 0, 0);
 	numfullpathcalls++;
+	vref(vp);
 	CACHE_RLOCK();
 	if (vp->v_type != VDIR) {
 		error = vn_vptocnp_locked(&vp, td->td_ucred, buf, &buflen);
@@ -1167,6 +1173,9 @@ vn_fullpath1(struct thread *td, struct v
 			return (error);
 		if (buflen == 0) {
 			CACHE_RUNLOCK();
+			vfslocked = VFS_LOCK_GIANT(vp->v_mount);
+			vrele(vp);
+			VFS_UNLOCK_GIANT(vfslocked);
 			return (ENOMEM);
 		}
 		buf[--buflen] = '/';
@@ -1176,16 +1185,29 @@ vn_fullpath1(struct thread *td, struct v
 		if (vp->v_vflag & VV_ROOT) {
 			if (vp->v_iflag & VI_DOOMED) {	/* forced unmount */
 				CACHE_RUNLOCK();
+				vfslocked = VFS_LOCK_GIANT(vp->v_mount);
+				vrele(vp);
+				VFS_UNLOCK_GIANT(vfslocked);
 				error = ENOENT;
 				SDT_PROBE(vfs, namecache, fullpath, return,
 				    error, vp, NULL, 0, 0);
 				break;
 			}
-			vp = vp->v_mount->mnt_vnodecovered;
+			vp1 = vp->v_mount->mnt_vnodecovered;
+			vref(vp1);
+			CACHE_RUNLOCK();
+			vfslocked = VFS_LOCK_GIANT(vp->v_mount);
+			vrele(vp);
+			VFS_UNLOCK_GIANT(vfslocked);
+			vp = vp1;
+			CACHE_RLOCK();
 			continue;
 		}
 		if (vp->v_type != VDIR) {
 			CACHE_RUNLOCK();
+			vfslocked = VFS_LOCK_GIANT(vp->v_mount);
+			vrele(vp);
+			VFS_UNLOCK_GIANT(vfslocked);
 			numfullpathfail1++;
 			error = ENOTDIR;
 			SDT_PROBE(vfs, namecache, fullpath, return,
@@ -1197,6 +1219,9 @@ vn_fullpath1(struct thread *td, struct v
 			break;
 		if (buflen == 0) {
 			CACHE_RUNLOCK();
+			vfslocked = VFS_LOCK_GIANT(vp->v_mount);
+			vrele(vp);
+			VFS_UNLOCK_GIANT(vfslocked);
 			error = ENOMEM;
 			SDT_PROBE(vfs, namecache, fullpath, return, error,
 			    startvp, NULL, 0, 0);
@@ -1210,6 +1235,9 @@ vn_fullpath1(struct thread *td, struct v
 	if (!slash_prefixed) {
 		if (buflen == 0) {
 			CACHE_RUNLOCK();
+			vfslocked = VFS_LOCK_GIANT(vp->v_mount);
+			vrele(vp);
+			VFS_UNLOCK_GIANT(vfslocked);
 			numfullpathfail4++;
 			SDT_PROBE(vfs, namecache, fullpath, return, ENOMEM,
 			    startvp, NULL, 0, 0);
@@ -1219,6 +1247,9 @@ vn_fullpath1(struct thread *td, struct v
 	}
 	numfullpathfound++;
 	CACHE_RUNLOCK();
+	vfslocked = VFS_LOCK_GIANT(vp->v_mount);
+	vrele(vp);
+	VFS_UNLOCK_GIANT(vfslocked);
 
 	SDT_PROBE(vfs, namecache, fullpath, return, 0, startvp, buf + buflen,
 	    0, 0);

Modified: stable/9/sys/kern/vfs_default.c
==============================================================================
--- stable/9/sys/kern/vfs_default.c	Fri Jan  6 15:01:05 2012	(r229702)
+++ stable/9/sys/kern/vfs_default.c	Fri Jan  6 15:07:28 2012	(r229703)
@@ -843,7 +843,7 @@ out:
 	free(dirbuf, M_TEMP);
 	if (!error) {
 		*buflen = i;
-		vhold(*dvp);
+		vref(*dvp);
 	}
 	if (covered) {
 		vput(*dvp);


More information about the svn-src-stable-9 mailing list