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);
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to