HAMMER 25/many: get fsx (filesystem test) working, cleanup pass
authorMatthew Dillon <dillon@dragonflybsd.org>
Fri, 25 Jan 2008 10:36:04 +0000 (10:36 +0000)
committerMatthew Dillon <dillon@dragonflybsd.org>
Fri, 25 Jan 2008 10:36:04 +0000 (10:36 +0000)
* Fix buffer alignment in the write strategy code.  Assert buffer alignment
  in hammer_ip_sync_data().

* Finish implementing file truncation.  There's probably still an edge case
  or two related to B_CACHE on terminal filesystem buffers when expanding
  a file.

* Pass VCHR vnodes through to fsync so the inode data syncs properly.  It
  was previously only syncing on umount or OS flushes.

* Change a bunch of debugging kprintf's to only print if a debug variable is
  set.  Reduce the debugging output considerably.

* Test FSX using both a full historical mount and a nohistory mount.

sys/vfs/hammer/hammer.h
sys/vfs/hammer/hammer_btree.c
sys/vfs/hammer/hammer_io.c
sys/vfs/hammer/hammer_object.c
sys/vfs/hammer/hammer_ondisk.c
sys/vfs/hammer/hammer_spike.c
sys/vfs/hammer/hammer_vfsops.c
sys/vfs/hammer/hammer_vnops.c

index 640c203..b12859e 100644 (file)
@@ -31,7 +31,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
- * $DragonFly: src/sys/vfs/hammer/hammer.h,v 1.29 2008/01/25 05:49:08 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer.h,v 1.30 2008/01/25 10:36:03 dillon Exp $
  */
 /*
  * This header file contains structures used internally by the HAMMERFS
@@ -478,6 +478,7 @@ extern struct hammer_alist_config Clu_master_alist_config;
 extern struct hammer_alist_config Clu_slave_alist_config;
 extern struct bio_ops hammer_bioops;
 
+extern int hammer_debug_general;
 extern int hammer_debug_btree;
 extern int hammer_debug_tid;
 extern int hammer_debug_recover;
index 92404dd..07d5795 100644 (file)
@@ -31,7 +31,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
- * $DragonFly: src/sys/vfs/hammer/hammer_btree.c,v 1.24 2008/01/25 05:49:08 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer_btree.c,v 1.25 2008/01/25 10:36:03 dillon Exp $
  */
 
 /*
@@ -687,11 +687,13 @@ hammer_btree_insert_cluster(hammer_cursor_t cursor, hammer_cluster_t ncluster,
         * flushing it will only clear an existing open flag if the cluster
         * has been validated.
         */
-       kprintf("INSERT CLUSTER %d:%d -> %d:%d ",
-               ncluster->ondisk->clu_btree_parent_vol_no,
-               ncluster->ondisk->clu_btree_parent_clu_no,
-               ncluster->volume->vol_no,
-               ncluster->clu_no);
+       if (hammer_debug_general & 0x40) {
+               kprintf("INSERT CLUSTER %d:%d -> %d:%d ",
+                       ncluster->ondisk->clu_btree_parent_vol_no,
+                       ncluster->ondisk->clu_btree_parent_clu_no,
+                       ncluster->volume->vol_no,
+                       ncluster->clu_no);
+       }
 
        ocluster = cursor->node->cluster;
        if (ncluster->ondisk->clu_btree_parent_offset != node_offset ||
@@ -701,9 +703,11 @@ hammer_btree_insert_cluster(hammer_cursor_t cursor, hammer_cluster_t ncluster,
                ncluster->ondisk->clu_btree_parent_offset = node_offset;
                ncluster->ondisk->clu_btree_parent_clu_no = ocluster->clu_no;
                ncluster->ondisk->clu_btree_parent_vol_no = ocluster->volume->vol_no;
-               kprintf("(offset fixup)\n");
+               if (hammer_debug_general & 0x40)
+                       kprintf("(offset fixup)\n");
        } else {
-               kprintf("(offset unchanged)\n");
+               if (hammer_debug_general & 0x40)
+                       kprintf("(offset unchanged)\n");
        }
 
        return(0);
index f8eade3..47b5eaf 100644 (file)
@@ -31,7 +31,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
- * $DragonFly: src/sys/vfs/hammer/hammer_io.c,v 1.18 2008/01/25 05:49:08 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer_io.c,v 1.19 2008/01/25 10:36:03 dillon Exp $
  */
 /*
  * IO Primitives and buffer cache management
@@ -452,9 +452,11 @@ hammer_modify_buffer(hammer_buffer_t buffer)
                                cluster->io.released = 1;
                                cluster->io.running = 1;
                                bawrite(cluster->io.bp);
-                               kprintf("OPEN CLUSTER %d:%d\n",
-                                       cluster->volume->vol_no,
-                                       cluster->clu_no);
+                               if (hammer_debug_general & 0x20) {
+                                       kprintf("OPEN CLUSTER %d:%d\n",
+                                               cluster->volume->vol_no,
+                                               cluster->clu_no);
+                               }
                        }
                        hammer_unlock(&cluster->io.lock);
                }
@@ -554,6 +556,7 @@ hammer_io_complete(struct buf *bp)
         */
        if ((bp->b_flags & B_LOCKED) && iou->io.lock.refs == 0) {
                KKASSERT(iou->io.modified == 0);
+               bp->b_flags &= ~B_LOCKED;
                hammer_io_deallocate(bp);
                /* structure may be dead now */
        }
@@ -660,19 +663,23 @@ hammer_io_checkwrite(struct buf *bp)
        if (iou->io.type == HAMMER_STRUCTURE_CLUSTER && iou->io.modified) {
                hammer_cluster_t cluster = &iou->cluster;
 
-               kprintf("CLOSE CLUSTER %d:%d ",
-                       cluster->volume->vol_no,
-                       cluster->clu_no);
+               if (hammer_debug_general & 0x20) {
+                       kprintf("CLOSE CLUSTER %d:%d ",
+                               cluster->volume->vol_no, cluster->clu_no);
+               }
                if (cluster->ondisk->clu_flags & HAMMER_CLUF_OPEN) {
                        if (cluster->io.validated) {
                                cluster->ondisk->clu_flags &=
                                        ~HAMMER_CLUF_OPEN;
-                               kprintf("(closed)\n");
+                               if (hammer_debug_general & 0x20)
+                                       kprintf("(closed)\n");
                        } else {
-                               kprintf("(leave-open)\n");
+                               if (hammer_debug_general & 0x20)
+                                       kprintf("(leave-open)\n");
                        }
                } else {
-                       kprintf("(header-only)\n");
+                       if (hammer_debug_general & 0x20)
+                               kprintf("(header-only)\n");
                }
        }
 
index 753b554..faaa093 100644 (file)
@@ -31,7 +31,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
- * $DragonFly: src/sys/vfs/hammer/hammer_object.c,v 1.24 2008/01/25 05:49:08 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer_object.c,v 1.25 2008/01/25 10:36:04 dillon Exp $
  */
 
 #include "hammer.h"
@@ -480,6 +480,8 @@ hammer_ip_sync_data(hammer_transaction_t trans, hammer_inode_t ip,
        void *bdata;
        int error;
 
+       KKASSERT((offset & HAMMER_BUFMASK) == 0);
+       KKASSERT((bytes & HAMMER_BUFMASK) == 0);
 retry:
        error = hammer_init_cursor_hmp(&cursor, &ip->cache[0], ip->hmp);
        if (error)
index a0910e6..5536eb0 100644 (file)
@@ -31,7 +31,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
- * $DragonFly: src/sys/vfs/hammer/hammer_ondisk.c,v 1.25 2008/01/25 05:49:08 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer_ondisk.c,v 1.26 2008/01/25 10:36:04 dillon Exp $
  */
 /*
  * Manage HAMMER's on-disk structures.  These routines are primarily
@@ -1057,7 +1057,8 @@ hammer_rel_cluster(hammer_cluster_t cluster, int flush)
        if (cluster->io.lock.refs == 1) {
                if (cluster->flags & HAMMER_CLUSTER_DELETED) {
                        cluster->flags &= ~HAMMER_CLUSTER_DELETED;
-                       kprintf("FREE CLUSTER %d", cluster->clu_no);
+                       if (hammer_debug_general & 0x80)
+                               kprintf("FREE CLUSTER %d\n", cluster->clu_no);
                        if (cluster->ondisk->stat_records) {
                                struct hammer_sync_info info;
 
@@ -1071,7 +1072,6 @@ hammer_rel_cluster(hammer_cluster_t cluster, int flush)
                                hammer_sync_cluster(cluster, &info);
                                Debugger("now debug it");
                        }
-                       kprintf("\n");
 
                        /*
                         * Clean up any statistics we left hanging in the
@@ -1670,7 +1670,6 @@ hammer_alloc_cluster(hammer_mount_t hmp, hammer_cluster_t cluster_hint,
        vol_no = vol_beg;
        do {
                volume = hammer_get_volume(hmp, vol_no, errorp);
-               kprintf("VOLUME %p %d\n", volume, vol_no);
                if (*errorp) {
                        clu_no = HAMMER_ALIST_BLOCK_NONE;
                        break;
@@ -1705,7 +1704,10 @@ hammer_alloc_cluster(hammer_mount_t hmp, hammer_cluster_t cluster_hint,
         * Acquire the cluster.  On success this will force *errorp to 0.
         */
        if (clu_no != HAMMER_ALIST_BLOCK_NONE) {
-               kprintf("ALLOC CLUSTER %d:%d\n", volume->vol_no, clu_no);
+               if (hammer_debug_general & 0x40) {
+                       kprintf("ALLOC CLUSTER %d:%d\n", 
+                               volume->vol_no, clu_no);
+               }
                cluster = hammer_get_cluster(volume, clu_no, errorp,
                                             GET_CLUSTER_NEW);
                volume->clu_iterator = clu_no;
@@ -1783,7 +1785,8 @@ hammer_alloc_btree(hammer_cluster_t cluster, int *errorp)
        if (cluster->io.validated) {
                n = (cluster->ondisk->stat_records * 3 / 
                    HAMMER_BTREE_INT_ELMS / HAMMER_BTREE_NODES) + 1;
-               if (cluster->ondisk->stat_idx_bufs < n) {
+               if (hammer_debug_general &&
+                   cluster->ondisk->stat_idx_bufs < n) {
                        kprintf("hammer_alloc_btree: %d/%d buffers\n",
                                cluster->ondisk->stat_idx_bufs, n);
                }
@@ -1943,7 +1946,6 @@ hammer_alloc_record(hammer_cluster_t cluster, int *errorp,
                alloc_new_buffer(cluster, HAMMER_FSBUF_RECORDS, live,
                                 cluster->ondisk->idx_record, errorp, bufferp);
                elm_no = hammer_alist_alloc_rev(live, 1,HAMMER_ALIST_BLOCK_MAX);
-               kprintf("hammer_alloc_record elm again %08x\n", elm_no);
                if (elm_no == HAMMER_ALIST_BLOCK_NONE) {
                        *errorp = ENOSPC;
                        return(NULL);
@@ -2129,10 +2131,6 @@ alloc_new_buffer(hammer_cluster_t cluster, u_int64_t type, hammer_alist_t live,
         * A-list and update our statistics to reflect the allocation.
         */
        if (buffer) {
-#if 0
-               kprintf("alloc_new_buffer buf_no %d type %016llx nelms %d\n",
-                       buf_no, type, nelements);
-#endif
                hammer_modify_buffer(buffer);  /*XXX*/
                hammer_adjust_stats(cluster, type, 1);
 
@@ -2206,11 +2204,9 @@ hammer_sync_scan2(struct mount *mp, struct vnode *vp, void *data)
             RB_EMPTY(&vp->v_rbdirty_tree))) {
                return(0);
        }
-       if (vp->v_type != VCHR) {
-               error = VOP_FSYNC(vp, info->waitfor);
-               if (error)
-                       info->error = error;
-       }
+       error = VOP_FSYNC(vp, info->waitfor);
+       if (error)
+               info->error = error;
        return(0);
 }
 
@@ -2452,7 +2448,10 @@ buffer_alist_destroy(void *info, int32_t blk, int32_t radix)
        int32_t buf_no;
 
        buf_no = blk / HAMMER_FSBUF_MAXBLKS;
-       kprintf("destroy buffer %d:%d:%d\n", cluster->volume->vol_no, cluster->clu_no, buf_no);
+       if (hammer_debug_general & 0x80) {
+               kprintf("destroy buffer %d:%d:%d\n",
+                       cluster->volume->vol_no, cluster->clu_no, buf_no);
+       }
        return (0);
 }
 
index 2f729b5..a944aa4 100644 (file)
@@ -31,7 +31,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
- * $DragonFly: src/sys/vfs/hammer/Attic/hammer_spike.c,v 1.12 2008/01/25 05:49:08 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/Attic/hammer_spike.c,v 1.13 2008/01/25 10:36:04 dillon Exp $
  */
 
 #include "hammer.h"
@@ -64,7 +64,8 @@ hammer_load_spike(hammer_cursor_t cursor, struct hammer_cursor **spikep)
        }
        hammer_ref_node(spike->node);
        hammer_lock_sh(&spike->node->lock);
-       kprintf("LOAD SPIKE %p\n", spike);
+       if (hammer_debug_general & 0x40)
+               kprintf("LOAD SPIKE %p\n", spike);
 }
 
 /*
@@ -97,7 +98,8 @@ hammer_spike(struct hammer_cursor **spikep)
        int b, e;
        const int esize = sizeof(*elm);
 
-       kprintf("hammer_spike: ENOSPC in cluster, spiking\n");
+       if (hammer_debug_general & 0x40)
+               kprintf("hammer_spike: ENOSPC in cluster, spiking\n");
        /*Debugger("ENOSPC");*/
 
        /*
@@ -372,7 +374,8 @@ success:
        hammer_unlock(&ncluster->io.lock);
        hammer_rel_cluster(ncluster, 0);
 failed3:
-       kprintf("UNLOAD SPIKE %p %d\n", spike, error);
+       if (hammer_debug_general & 0x40)
+               kprintf("UNLOAD SPIKE %p %d\n", spike, error);
        hammer_unlock(&ocluster->io.lock);
 failed4:
        hammer_btree_unlock_children(&locklist);
index 6c15f17..5cd4b2d 100644 (file)
@@ -31,7 +31,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
- * $DragonFly: src/sys/vfs/hammer/hammer_vfsops.c,v 1.15 2008/01/25 05:49:08 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer_vfsops.c,v 1.16 2008/01/25 10:36:04 dillon Exp $
  */
 
 #include <sys/param.h>
@@ -47,6 +47,7 @@
 #include <sys/buf2.h>
 #include "hammer.h"
 
+int hammer_debug_general;
 int hammer_debug_btree;
 int hammer_debug_tid;
 int hammer_debug_recover;      /* -1 will disable, +1 will force */
@@ -62,6 +63,8 @@ int hammer_count_nodes;
 int hammer_count_spikes;
 
 SYSCTL_NODE(_vfs, OID_AUTO, hammer, CTLFLAG_RW, 0, "HAMMER filesystem");
+SYSCTL_INT(_vfs_hammer, OID_AUTO, debug_general, CTLFLAG_RW,
+          &hammer_debug_general, 0, "");
 SYSCTL_INT(_vfs_hammer, OID_AUTO, debug_btree, CTLFLAG_RW,
           &hammer_debug_btree, 0, "");
 SYSCTL_INT(_vfs_hammer, OID_AUTO, debug_tid, CTLFLAG_RW,
index ea47d1c..64891c3 100644 (file)
@@ -31,7 +31,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
- * $DragonFly: src/sys/vfs/hammer/hammer_vnops.c,v 1.23 2008/01/25 05:49:08 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer_vnops.c,v 1.24 2008/01/25 10:36:04 dillon Exp $
  */
 
 #include <sys/param.h>
@@ -284,7 +284,17 @@ hammer_vop_write(struct vop_write_args *ap)
         * Access the data in HAMMER_BUFSIZE blocks via the buffer cache.
         */
        while (uio->uio_resid > 0) {
+               int fixsize = 0;
+
                offset = uio->uio_offset & HAMMER_BUFMASK;
+               n = HAMMER_BUFSIZE - offset;
+               if (n > uio->uio_resid)
+                       n = uio->uio_resid;
+               if (uio->uio_offset + n > ip->ino_rec.ino_size) {
+                       vnode_pager_setsize(ap->a_vp, uio->uio_offset + n);
+                       fixsize = 1;
+               }
+
                if (uio->uio_segflg == UIO_NOCOPY) {
                        /*
                         * Issuing a write with the same data backing the
@@ -293,30 +303,26 @@ hammer_vop_write(struct vop_write_args *ap)
                         *
                         * This case is used by vop_stdputpages().
                         */
-                       bp = getblk(ap->a_vp, uio->uio_offset, HAMMER_BUFSIZE,
-                                   GETBLK_BHEAVY, 0);
+                       bp = getblk(ap->a_vp, uio->uio_offset - offset,
+                                   HAMMER_BUFSIZE, GETBLK_BHEAVY, 0);
                        if ((bp->b_flags & B_CACHE) == 0) {
                                bqrelse(bp);
                                error = bread(ap->a_vp,
                                              uio->uio_offset - offset,
                                              HAMMER_BUFSIZE, &bp);
-                               if (error) {
-                                       brelse(bp);
-                                       break;
-                               }
                        }
                } else if (offset == 0 && uio->uio_resid >= HAMMER_BUFSIZE) {
                        /*
                         * entirely overwrite the buffer
                         */
-                       bp = getblk(ap->a_vp, uio->uio_offset, HAMMER_BUFSIZE,
-                                   GETBLK_BHEAVY, 0);
+                       bp = getblk(ap->a_vp, uio->uio_offset - offset,
+                                   HAMMER_BUFSIZE, GETBLK_BHEAVY, 0);
                } else if (offset == 0 && uio->uio_offset >= ip->ino_rec.ino_size) {
                        /*
                         * XXX
                         */
-                       bp = getblk(ap->a_vp, uio->uio_offset, HAMMER_BUFSIZE,
-                                   GETBLK_BHEAVY, 0);
+                       bp = getblk(ap->a_vp, uio->uio_offset - offset,
+                                   HAMMER_BUFSIZE, GETBLK_BHEAVY, 0);
                        vfs_bio_clrbuf(bp);
                } else {
                        /*
@@ -325,18 +331,22 @@ hammer_vop_write(struct vop_write_args *ap)
                         */
                        error = bread(ap->a_vp, uio->uio_offset - offset,
                                      HAMMER_BUFSIZE, &bp);
-                       if (error) {
-                               brelse(bp);
-                               break;
-                       }
-                       bheavy(bp);
+                       if (error == 0)
+                               bheavy(bp);
                }
-               n = HAMMER_BUFSIZE - offset;
-               if (n > uio->uio_resid)
-                       n = uio->uio_resid;
-               error = uiomove((char *)bp->b_data + offset, n, uio);
+               if (error == 0)
+                       error = uiomove((char *)bp->b_data + offset, n, uio);
+
+               /*
+                * If we screwed up we have to undo any VM size changes we
+                * made.
+                */
                if (error) {
                        brelse(bp);
+                       if (fixsize) {
+                               vtruncbuf(ap->a_vp, ip->ino_rec.ino_size,
+                                         HAMMER_BUFSIZE);
+                       }
                        break;
                }
                /* bp->b_flags |= B_CLUSTEROK; temporarily disabled */
@@ -1233,6 +1243,7 @@ hammer_vop_setattr(struct vop_setattr_args *ap)
        struct hammer_inode *ip;
        int modflags;
        int error;
+       int truncating;
        int64_t aligned_size;
        u_int32_t flags;
        uuid_t uuid;
@@ -1287,20 +1298,48 @@ hammer_vop_setattr(struct vop_setattr_args *ap)
        while (vap->va_size != VNOVAL && ip->ino_rec.ino_size != vap->va_size) {
                switch(ap->a_vp->v_type) {
                case VREG:
+                       if (vap->va_size == ip->ino_rec.ino_size)
+                               break;
                        if (vap->va_size < ip->ino_rec.ino_size) {
                                vtruncbuf(ap->a_vp, vap->va_size,
                                          HAMMER_BUFSIZE);
-                       } else if (vap->va_size > ip->ino_rec.ino_size) {
+                               truncating = 1;
+                       } else {
                                vnode_pager_setsize(ap->a_vp, vap->va_size);
+                               truncating = 0;
                        }
+                       ip->ino_rec.ino_size = vap->va_size;
+                       modflags |= HAMMER_INODE_RDIRTY;
                        aligned_size = (vap->va_size + HAMMER_BUFMASK) &
                                        ~(int64_t)HAMMER_BUFMASK;
-                       error = hammer_ip_delete_range(&trans, ip,
+
+                       if (truncating) {
+                               error = hammer_ip_delete_range(&trans, ip,
                                                    aligned_size,
                                                    0x7FFFFFFFFFFFFFFFLL,
                                                    &spike);
-                       ip->ino_rec.ino_size = vap->va_size;
-                       modflags |= HAMMER_INODE_RDIRTY;
+                       }
+                       /*
+                        * If truncating we have to clean out a portion of
+                        * the last block on-disk.
+                        */
+                       if (truncating && error == 0 &&
+                           vap->va_size < aligned_size) {
+                               struct buf *bp;
+                               int offset;
+
+                               offset = vap->va_size & HAMMER_BUFMASK;
+                               error = bread(ap->a_vp,
+                                             aligned_size - HAMMER_BUFSIZE,
+                                             HAMMER_BUFSIZE, &bp);
+                               if (error == 0) {
+                                       bzero(bp->b_data + offset,
+                                             HAMMER_BUFSIZE - offset);
+                                       bdwrite(bp);
+                               } else {
+                                       brelse(bp);
+                               }
+                       }
                        break;
                case VDATABASE:
                        error = hammer_ip_delete_range(&trans, ip,
@@ -1562,7 +1601,6 @@ hammer_vop_strategy_read(struct vop_strategy_args *ap)
                if (n > 0) {
                        if (n > bp->b_bufsize - boff)
                                n = bp->b_bufsize - boff;
-                       kprintf("zfill %d bytes\n", n);
                        bzero((char *)bp->b_data + boff, n);
                        boff += n;
                        n = 0;