VFS messaging/interfacing work stage 7h/99: More firming up of stage 7.
authorMatthew Dillon <dillon@dragonflybsd.org>
Thu, 7 Oct 2004 20:18:33 +0000 (20:18 +0000)
committerMatthew Dillon <dillon@dragonflybsd.org>
Thu, 7 Oct 2004 20:18:33 +0000 (20:18 +0000)
Fix a vnode leak due to a missed change when the cache_lookup() semantics
were modified.  Hold the parent namecache record in naccess() when checking
for write perms on a directory.

Reported-by: walt <wa1ter@myrealbox.com>
sys/kern/vfs_cache.c
sys/kern/vfs_nlookup.c

index f797698..2496bf6 100644 (file)
@@ -67,7 +67,7 @@
  *
  *     @(#)vfs_cache.c 8.5 (Berkeley) 3/22/95
  * $FreeBSD: src/sys/kern/vfs_cache.c,v 1.42.2.6 2001/10/05 20:07:03 dillon Exp $
- * $DragonFly: src/sys/kern/vfs_cache.c,v 1.36 2004/10/07 10:03:02 dillon Exp $
+ * $DragonFly: src/sys/kern/vfs_cache.c,v 1.37 2004/10/07 20:18:33 dillon Exp $
  */
 
 #include <sys/param.h>
@@ -1611,6 +1611,9 @@ vfs_cache_lookup(struct vop_lookup_args *ap)
 
        error = cache_lookup(dvp, vpp, cnp);
 
+       /*
+        * failure if error == 0, do a physical lookup
+        */
        if (!error) 
                return (VOP_CACHEDLOOKUP(dvp, vpp, cnp));
 
@@ -1621,18 +1624,20 @@ vfs_cache_lookup(struct vop_lookup_args *ap)
        vpid = vp->v_id;
        cnp->cn_flags &= ~CNP_PDIRUNLOCK;
        if (dvp == vp) {   /* lookup on "." */
-               vref(vp);
+               /* already ref'd from cache_lookup() */
                error = 0;
        } else if (flags & CNP_ISDOTDOT) {
                VOP_UNLOCK(dvp, NULL, 0, td);
                cnp->cn_flags |= CNP_PDIRUNLOCK;
                error = vget(vp, NULL, LK_EXCLUSIVE, td);
+               vrele(vp);
                if (!error && lockparent && (flags & CNP_ISLASTCN)) {
                        if ((error = vn_lock(dvp, NULL, LK_EXCLUSIVE, td)) == 0)
                                cnp->cn_flags &= ~CNP_PDIRUNLOCK;
                }
        } else {
                error = vget(vp, NULL, LK_EXCLUSIVE, td);
+               vrele(vp);
                if (!lockparent || error || !(flags & CNP_ISLASTCN)) {
                        VOP_UNLOCK(dvp, NULL, 0, td);
                        cnp->cn_flags |= CNP_PDIRUNLOCK;
index 39e14c0..3cedaeb 100644 (file)
@@ -31,7 +31,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
- * $DragonFly: src/sys/kern/vfs_nlookup.c,v 1.5 2004/10/07 10:03:02 dillon Exp $
+ * $DragonFly: src/sys/kern/vfs_nlookup.c,v 1.6 2004/10/07 20:18:33 dillon Exp $
  */
 /*
  * nlookup() is the 'new' namei interface.  Rather then return directory and
@@ -580,6 +580,7 @@ fail:
 int
 naccess(struct namecache *ncp, int vmode, struct ucred *cred)
 {
+    struct namecache *par;
     struct vnode *vp;
     struct vattr va;
     int error;
@@ -594,11 +595,13 @@ naccess(struct namecache *ncp, int vmode, struct ucred *cred)
        if (((vmode & VCREATE) && ncp->nc_vp == NULL) ||
            ((vmode & VDELETE) && ncp->nc_vp != NULL)
        ) {
-           if (ncp->nc_parent == NULL) {
+           if ((par = ncp->nc_parent) == NULL) {
                if (error != EAGAIN)
                        error = EROFS;
            } else {
-               error = naccess(ncp->nc_parent, VWRITE, cred);
+               cache_hold(par);
+               error = naccess(par, VWRITE, cred);
+               cache_drop(par);
            }
        }
        if ((vmode & VEXCL) && ncp->nc_vp != NULL)