Fix a number of core kernel issues related to HAMMER operation.
[games.git] / sys / kern / vfs_subr.c
index fd23da6..30249bf 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.106 2007/07/31 01:14:50 dillon Exp $
+ * $DragonFly: src/sys/kern/vfs_subr.c,v 1.114 2008/05/18 05:54:25 dillon Exp $
  */
 
 /*
@@ -128,7 +128,7 @@ SYSCTL_INT(_kern, KERN_MAXVNODES, maxvnodes, CTLFLAG_RW,
 static void    vfs_free_addrlist (struct netexport *nep);
 static int     vfs_free_netcred (struct radix_node *rn, void *w);
 static int     vfs_hang_addrlist (struct mount *mp, struct netexport *nep,
-                                      struct export_args *argp);
+                                      const struct export_args *argp);
 
 extern int dev_ref_debug;
 
@@ -256,6 +256,7 @@ vattr_null(struct vattr *vap)
        vap->va_gen = VNOVAL;
        vap->va_vaflags = 0;
        vap->va_fsmid = VNOVAL;
+       /* va_*_uuid fields are only valid if related flags are set */
 }
 
 /*
@@ -392,6 +393,9 @@ vinvalbuf_bp(struct buf *bp, void *data)
         * check for it.  Note that vfs_bio_awrite expects
         * buffers to reside on a queue, while bwrite() and
         * brelse() do not.
+        *
+        * NOTE:  NO B_LOCKED CHECK.  Also no buf_checkwrite()
+        * check.  This code will write out the buffer, period.
         */
        if (((bp->b_flags & (B_DELWRI | B_INVAL)) == B_DELWRI) &&
            (info->flags & V_SAVE)) {
@@ -793,6 +797,15 @@ vfsync_bp(struct buf *bp, void *data)
                return(0);
        }
 
+       /*
+        * Ask bioops if it is ok to sync 
+        */
+       if (LIST_FIRST(&bp->b_dep) != NULL && buf_checkwrite(bp)) {
+               bremfree(bp);
+               brelse(bp);
+               return(0);
+       }
+
        if (info->synchronous) {
                /*
                 * Synchronous flushing.  An error may be returned.
@@ -1108,7 +1121,7 @@ vclean_vxlocked(struct vnode *vp, int flags)
        }
 
        /*
-        * If the vnode has not be deactivated, deactivated it.  Deactivation
+        * If the vnode has not been deactivated, deactivated it.  Deactivation
         * can create new buffers and VM pages so we have to call vinvalbuf()
         * again to make sure they all get flushed.
         *
@@ -1135,7 +1148,6 @@ vclean_vxlocked(struct vnode *vp, int flags)
        }
        KKASSERT((vp->v_flag & VOBJBUF) == 0);
 
-
        /*
         * Reclaim the vnode.
         */
@@ -1148,6 +1160,16 @@ vclean_vxlocked(struct vnode *vp, int flags)
        vp->v_ops = &dead_vnode_vops_p;
        vn_pollgone(vp);
        vp->v_tag = VT_NON;
+
+       /*
+        * If we are destroying an active vnode, reactivate it now that
+        * we have reassociated it with deadfs.  This prevents the system
+        * from crashing on the vnode due to it being unexpectedly marked
+        * as inactive or reclaimed.
+        */
+       if (active && (flags & DOCLOSE)) {
+               vp->v_flag &= ~(VINACTIVE|VRECLAIMED);
+       }
 }
 
 /*
@@ -1208,17 +1230,38 @@ vop_stdrevoke(struct vop_revoke_args *ap)
  * This is called when the object underlying a vnode is being destroyed,
  * such as in a remove().  Try to recycle the vnode immediately if the
  * only active reference is our reference.
+ *
+ * Directory vnodes in the namecache with children cannot be immediately
+ * recycled because numerous VOP_N*() ops require them to be stable.
  */
 int
 vrecycle(struct vnode *vp)
 {
        if (vp->v_sysref.refcnt <= 1) {
+               if (cache_inval_vp_nonblock(vp))
+                       return(0);
                vgone_vxlocked(vp);
                return (1);
        }
        return (0);
 }
 
+/*
+ * Return the maximum I/O size allowed for strategy calls on VP.
+ *
+ * If vp is VCHR or VBLK we dive the device, otherwise we use
+ * the vp's mount info.
+ */
+int
+vmaxiosize(struct vnode *vp)
+{
+       if (vp->v_type == VBLK || vp->v_type == VCHR) {
+               return(vp->v_rdev->si_iosize_max);
+       } else {
+               return(vp->v_mount->mnt_iosize_max);
+       }
+}
+
 /*
  * Eliminate all activity associated with a vnode in preparation for reuse.
  *
@@ -1577,7 +1620,7 @@ vfs_umountall_callback(struct mount *mp, void *data)
  */
 static int
 vfs_hang_addrlist(struct mount *mp, struct netexport *nep,
-               struct export_args *argp)
+               const struct export_args *argp)
 {
        struct netcred *np;
        struct radix_node_head *rnh;
@@ -1604,8 +1647,7 @@ vfs_hang_addrlist(struct mount *mp, struct netexport *nep,
                return (EINVAL);
 
        i = sizeof(struct netcred) + argp->ex_addrlen + argp->ex_masklen;
-       np = (struct netcred *) kmalloc(i, M_NETADDR, M_WAITOK);
-       bzero((caddr_t) np, i);
+       np = (struct netcred *) kmalloc(i, M_NETADDR, M_WAITOK | M_ZERO);
        saddr = (struct sockaddr *) (np + 1);
        if ((error = copyin(argp->ex_addr, (caddr_t) saddr, argp->ex_addrlen)))
                goto out;
@@ -1681,7 +1723,8 @@ vfs_free_addrlist(struct netexport *nep)
 }
 
 int
-vfs_export(struct mount *mp, struct netexport *nep, struct export_args *argp)
+vfs_export(struct mount *mp, struct netexport *nep,
+          const struct export_args *argp)
 {
        int error;
 
@@ -1713,7 +1756,7 @@ vfs_export(struct mount *mp, struct netexport *nep, struct export_args *argp)
  */
 int
 vfs_setpublicfs(struct mount *mp, struct netexport *nep,
-               struct export_args *argp)
+               const struct export_args *argp)
 {
        int error;
        struct vnode *rvp;