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