A VM object is now required for vnode-based buffer cache ops. This
authorMatthew Dillon <dillon@dragonflybsd.org>
Wed, 29 Mar 2006 20:46:07 +0000 (20:46 +0000)
committerMatthew Dillon <dillon@dragonflybsd.org>
Wed, 29 Mar 2006 20:46:07 +0000 (20:46 +0000)
is usually handled by VOP_OPEN but there are a few cases where UFS issues
buffer cache ops on vnodes that have not been opened, such as when creating
a new directory or softlink.

sys/kern/vfs_subr.c
sys/vfs/ufs/ufs_vnops.c

index b42fdfa..86d53dd 100644 (file)
@@ -37,7 +37,7 @@
  *
  *     @(#)vfs_subr.c  8.31 (Berkeley) 5/26/95
  * $FreeBSD: src/sys/kern/vfs_subr.c,v 1.249.2.30 2003/04/04 20:35:57 tegge Exp $
- * $DragonFly: src/sys/kern/vfs_subr.c,v 1.72 2006/03/29 18:44:50 dillon Exp $
+ * $DragonFly: src/sys/kern/vfs_subr.c,v 1.73 2006/03/29 20:46:05 dillon Exp $
  */
 
 /*
@@ -1335,6 +1335,8 @@ retry:
                        if ((error = VOP_GETATTR(vp, &vat, td)) != 0)
                                goto retn;
                        object = vnode_pager_alloc(vp, vat.va_size, 0, 0);
+               } else if (vp->v_type == VLNK) {
+                       object = vnode_pager_alloc(vp, MAXPATHLEN, 0, 0);
                } else if (vp->v_rdev && dev_is_good(vp->v_rdev)) {
                        /*
                         * XXX v_rdev uses NULL/non-NULL instead of NODEV
index 4aadfad..5cb72a9 100644 (file)
@@ -37,7 +37,7 @@
  *
  *     @(#)ufs_vnops.c 8.27 (Berkeley) 5/27/95
  * $FreeBSD: src/sys/ufs/ufs/ufs_vnops.c,v 1.131.2.8 2003/01/02 17:26:19 bde Exp $
- * $DragonFly: src/sys/vfs/ufs/ufs_vnops.c,v 1.36 2006/03/29 18:45:04 dillon Exp $
+ * $DragonFly: src/sys/vfs/ufs/ufs_vnops.c,v 1.37 2006/03/29 20:46:07 dillon Exp $
  */
 
 #include "opt_quota.h"
@@ -1419,19 +1419,24 @@ ufs_mkdir(struct vop_old_mkdir_args *ap)
        if (error)
                goto bad;
 
+       /*
+        * The vnode must have a VM object in order to issue buffer cache
+        * ops on it.
+        */
+       vinitvmio(tvp);
+
        /*
         * Initialize directory with "." and ".." from static template.
         */
-       if (dvp->v_mount->mnt_maxsymlinklen > 0
-       )
+       if (dvp->v_mount->mnt_maxsymlinklen > 0)
                dtp = &mastertemplate;
        else
                dtp = (struct dirtemplate *)&omastertemplate;
        dirtemplate = *dtp;
        dirtemplate.dot_ino = ip->i_number;
        dirtemplate.dotdot_ino = dp->i_number;
-       if ((error = VOP_BALLOC(tvp, (off_t)0, DIRBLKSIZ, cnp->cn_cred,
-           B_CLRBUF, &bp)) != 0)
+       error = VOP_BALLOC(tvp, 0LL, DIRBLKSIZ, cnp->cn_cred, B_CLRBUF, &bp);
+       if (error)
                goto bad;
        ip->i_size = DIRBLKSIZ;
        ip->i_flag |= IN_CHANGE | IN_UPDATE;
@@ -1610,7 +1615,7 @@ ufs_symlink(struct vop_old_symlink_args *ap)
        int len, error;
 
        error = ufs_makeinode(IFLNK | ap->a_vap->va_mode, ap->a_dvp,
-           vpp, ap->a_cnp);
+                             vpp, ap->a_cnp);
        if (error)
                return (error);
        VN_KNOTE(ap->a_dvp, NOTE_WRITE);
@@ -1621,10 +1626,17 @@ ufs_symlink(struct vop_old_symlink_args *ap)
                bcopy(ap->a_target, (char *)ip->i_shortlink, len);
                ip->i_size = len;
                ip->i_flag |= IN_CHANGE | IN_UPDATE;
-       } else
+       } else {
+               /*
+                * Make sure we have a VM object in order to use
+                * the buffer cache.
+                */
+               if (vp->v_object == NULL)
+                       vinitvmio(vp);
                error = vn_rdwr(UIO_WRITE, vp, ap->a_target, len, (off_t)0,
-                   UIO_SYSSPACE, IO_NODELOCKED, ap->a_cnp->cn_cred,
-                   (int *)0, NULL);
+                               UIO_SYSSPACE, IO_NODELOCKED, 
+                               ap->a_cnp->cn_cred, NULL, NULL);
+       }
        if (error)
                vput(vp);
        return (error);
@@ -1757,6 +1769,13 @@ ufs_readlink(struct vop_readlink_args *ap)
                uiomove((char *)ip->i_shortlink, isize, ap->a_uio);
                return (0);
        }
+
+       /*
+        * Perform the equivalent of an OPEN on vp so we can issue a
+        * VOP_READ.
+        */
+       if (vp->v_object == NULL)
+               vinitvmio(vp);
        return (VOP_READ(vp, ap->a_uio, 0, ap->a_cred));
 }