HAMMER 41/Many: Implement CRC checking (WARNING: On-media structures changed)
authorMatthew Dillon <dillon@dragonflybsd.org>
Mon, 5 May 2008 20:34:48 +0000 (20:34 +0000)
committerMatthew Dillon <dillon@dragonflybsd.org>
Mon, 5 May 2008 20:34:48 +0000 (20:34 +0000)
* Generate and check on-media CRC fields.

* Clean up the record modification API

* Add a header signature field for future critical recovery

* Rearrange CRC fields for on-media structures to make them easier to
  deal with.

* Adjust the ioctl API

* When trying to back-out of an operation that errored, free allocated
  data blocks.

16 files changed:
sys/vfs/hammer/hammer.h
sys/vfs/hammer/hammer_blockmap.c
sys/vfs/hammer/hammer_btree.c
sys/vfs/hammer/hammer_btree.h
sys/vfs/hammer/hammer_cursor.c
sys/vfs/hammer/hammer_disk.h
sys/vfs/hammer/hammer_flusher.c
sys/vfs/hammer/hammer_inode.c
sys/vfs/hammer/hammer_ioctl.c
sys/vfs/hammer/hammer_ioctl.h
sys/vfs/hammer/hammer_object.c
sys/vfs/hammer/hammer_ondisk.c
sys/vfs/hammer/hammer_reblock.c
sys/vfs/hammer/hammer_subs.c
sys/vfs/hammer/hammer_undo.c
sys/vfs/hammer/hammer_vnops.c

index b3504ff..5d01fe3 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.60 2008/05/04 09:06:45 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer.h,v 1.61 2008/05/05 20:34:47 dillon Exp $
  */
 /*
  * This header file contains structures used internally by the HAMMERFS
@@ -252,6 +252,7 @@ typedef struct hammer_inode *hammer_inode_t;
 #define HAMMER_INODE_TRUNCATED 0x00010000
 #define HAMMER_INODE_DELETING  0x00020000 /* inode delete request (frontend)*/
 #define HAMMER_INODE_RESIGNAL  0x00040000 /* re-signal on re-flush */
+#define HAMMER_INODE_RESIGNAL  0x00040000 /* re-signal on re-flush */
 
 #define HAMMER_INODE_MODMASK   (HAMMER_INODE_DDIRTY|HAMMER_INODE_RDIRTY| \
                                 HAMMER_INODE_XDIRTY|HAMMER_INODE_BUFS|   \
@@ -724,8 +725,8 @@ void                hammer_rel_buffer(hammer_buffer_t buffer, int flush);
 
 int            hammer_vfs_export(struct mount *mp, int op,
                        const struct export_args *export);
-hammer_node_t  hammer_get_node(hammer_mount_t hmp,
-                       hammer_off_t node_offset, int *errorp);
+hammer_node_t  hammer_get_node(hammer_mount_t hmp, hammer_off_t node_offset,
+                       int isnew, int *errorp);
 void           hammer_ref_node(hammer_node_t node);
 hammer_node_t  hammer_ref_node_safe(struct hammer_mount *hmp,
                        struct hammer_node **cache, int *errorp);
@@ -744,6 +745,7 @@ void *hammer_alloc_record(hammer_transaction_t trans,
                        hammer_off_t *rec_offp, u_int16_t rec_type,
                        struct hammer_buffer **rec_bufferp,
                        int32_t data_len, void **datap,
+                       hammer_off_t *data_offp,
                        struct hammer_buffer **data_bufferp, int *errorp);
 void *hammer_alloc_data(hammer_transaction_t trans, int32_t data_len,
                        hammer_off_t *data_offsetp,
@@ -848,6 +850,14 @@ void hammer_flusher_async(hammer_mount_t hmp);
 
 int hammer_recover(hammer_mount_t hmp, hammer_volume_t rootvol);
 
+void hammer_crc_set_blockmap(hammer_blockmap_t blockmap);
+void hammer_crc_set_volume(hammer_volume_ondisk_t ondisk);
+
+int hammer_crc_test_blockmap(hammer_blockmap_t blockmap);
+int hammer_crc_test_volume(hammer_volume_ondisk_t ondisk);
+int hammer_crc_test_record(hammer_record_ondisk_t ondisk);
+int hammer_crc_test_btree(hammer_node_ondisk_t ondisk);
+
 #endif
 
 static __inline void
@@ -867,30 +877,73 @@ static __inline void
 hammer_modify_node(hammer_transaction_t trans, hammer_node_t node,
                   void *base, int len)
 {
+       hammer_crc_t *crcptr;
+
        KKASSERT((char *)base >= (char *)node->ondisk &&
                 (char *)base + len <=
                    (char *)node->ondisk + sizeof(*node->ondisk));
        hammer_modify_buffer(trans, node->buffer, base, len);
+       crcptr = &node->ondisk->crc;
+       hammer_modify_buffer(trans, node->buffer, crcptr, sizeof(hammer_crc_t));
+       --node->buffer->io.modify_refs; /* only want one ref */
 }
 
 static __inline void
 hammer_modify_node_done(hammer_node_t node)
 {
+       node->ondisk->crc = crc32(&node->ondisk->crc + 1, HAMMER_BTREE_CRCSIZE);
        hammer_modify_buffer_done(node->buffer);
 }
 
+static __inline void
+hammer_modify_record_noundo(hammer_transaction_t trans, hammer_buffer_t buffer,
+                           hammer_record_ondisk_t rec __unused)
+{
+       hammer_modify_buffer(trans, buffer, NULL, 0);
+}
+
+static __inline void
+hammer_modify_record_all(hammer_transaction_t trans, hammer_buffer_t buffer,
+                        hammer_record_ondisk_t rec)
+{
+       KKASSERT((char *)rec >= (char *)buffer->ondisk &&
+                (char *)(rec + 1) <= (char *)buffer->ondisk + HAMMER_BUFSIZE);
+       hammer_modify_buffer(trans, buffer, rec, sizeof(*rec));
+}
+
 static __inline void
 hammer_modify_record(hammer_transaction_t trans, hammer_buffer_t buffer,
-                    void *base, int len)
+                    hammer_record_ondisk_t rec, void *base, int len,
+                    int dodelete)
 {
        KKASSERT((char *)base >= (char *)buffer->ondisk &&
                 (char *)base + len <= (char *)buffer->ondisk + HAMMER_BUFSIZE);
+       KKASSERT((char *)rec >= (char *)buffer->ondisk &&
+                (char *)(rec + 1) <= (char *)buffer->ondisk + HAMMER_BUFSIZE);
+
+       /*
+        * Due to undo overheads it is more efficient to just undo the whole
+        * record.
+        */
+       hammer_modify_buffer(trans, buffer, rec, sizeof(*rec));
+#if 0
        hammer_modify_buffer(trans, buffer, base, len);
+       hammer_modify_buffer(trans, buffer, &rec->base.rec_crc,
+                                    sizeof(rec->base.rec_crc));
+       --node->buffer->io.modify_refs; /* only want one ref */
+       if (dodelete) {
+               hammer_modify_buffer(trans, buffer, &rec->base.signature,
+                                    sizeof(rec->base.signature));
+               --node->buffer->io.modify_refs; /* only want one ref */
+       }
+#endif
 }
 
 static __inline void
-hammer_modify_record_done(hammer_buffer_t buffer)
+hammer_modify_record_done(hammer_buffer_t buffer, hammer_record_ondisk_t rec)
 {
+       rec->base.rec_crc = crc32(&rec->base.rec_crc + 1,
+                                 HAMMER_RECORD_CRCSIZE);
        hammer_modify_buffer_done(buffer);
 }
 
@@ -902,4 +955,7 @@ hammer_modify_record_done(hammer_buffer_t buffer)
        hammer_modify_node(trans, node, &(node)->ondisk->field, \
                             sizeof((node)->ondisk->field))
 
+#define hammer_modify_record_field(trans, buffer, rec, field, dodelete) \
+       hammer_modify_record(trans, buffer, rec, &(rec)->field,         \
+       sizeof((rec)->field), dodelete)
 
index a8769d1..7df1838 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_blockmap.c,v 1.10 2008/05/03 05:28:55 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer_blockmap.c,v 1.11 2008/05/05 20:34:47 dillon Exp $
  */
 
 /*
@@ -124,6 +124,17 @@ again:
        KKASSERT(*errorp == 0);
        KKASSERT(next_offset <= rootmap->alloc_offset);
 
+       /*
+        * Check CRC if not allocating into uninitialized space
+        */
+       if ((next_offset != rootmap->alloc_offset) ||
+           (next_offset & HAMMER_BLOCKMAP_LAYER2_MASK)) {
+               if (layer1->layer1_crc != crc32(layer1,
+                                               HAMMER_LAYER1_CRCSIZE)) {
+                       Debugger("CRC FAILED: LAYER1");
+               }
+       }
+
        /*
         * Allocate layer2 backing store in layer1 if necessary.  next_offset
         * can skip to a bigblock boundary but alloc_offset is at least
@@ -139,6 +150,7 @@ again:
                layer1->phys_offset =
                        hammer_freemap_alloc(trans, next_offset, errorp);
                layer1->blocks_free = HAMMER_BLOCKMAP_RADIX2;
+               layer1->layer1_crc = crc32(layer1, HAMMER_LAYER1_CRCSIZE);
                hammer_modify_buffer_done(buffer1);
                KKASSERT(*errorp == 0);
        }
@@ -173,6 +185,16 @@ again:
        layer2 = hammer_bread(trans->hmp, layer2_offset, errorp, &buffer2);
        KKASSERT(*errorp == 0);
 
+       /*
+        * Check CRC if not allocating into uninitialized space
+        */
+       if (next_offset != rootmap->alloc_offset ||
+           (next_offset & HAMMER_LARGEBLOCK_MASK64)) {
+               if (layer2->entry_crc != crc32(layer2, HAMMER_LAYER2_CRCSIZE)) {
+                       Debugger("CRC FAILED: LAYER2");
+               }
+       }
+
        if ((next_offset & HAMMER_LARGEBLOCK_MASK64) == 0) {
                /*
                 * We are at the beginning of a new bigblock
@@ -188,6 +210,8 @@ again:
                                             layer1, sizeof(*layer1));
                        KKASSERT(layer1->blocks_free);
                        --layer1->blocks_free;
+                       layer1->layer1_crc = crc32(layer1,
+                                                  HAMMER_LAYER1_CRCSIZE);
                        hammer_modify_buffer_done(buffer1);
                        hammer_modify_buffer(trans, buffer2,
                                             layer2, sizeof(*layer2));
@@ -196,6 +220,8 @@ again:
                                hammer_freemap_alloc(trans, next_offset,
                                                     errorp);
                        layer2->bytes_free = HAMMER_LARGEBLOCK_SIZE;
+                       layer2->entry_crc = crc32(layer2,
+                                                 HAMMER_LAYER2_CRCSIZE);
                        hammer_modify_buffer_done(buffer2);
                        KKASSERT(*errorp == 0);
                } else if (layer2->bytes_free != HAMMER_LARGEBLOCK_SIZE) {
@@ -232,6 +258,7 @@ again:
 
        hammer_modify_buffer(trans, buffer2, layer2, sizeof(*layer2));
        layer2->bytes_free -= bytes;
+       layer2->entry_crc = crc32(layer2, HAMMER_LAYER2_CRCSIZE);
        hammer_modify_buffer_done(buffer2);
        KKASSERT(layer2->bytes_free >= 0);
 
@@ -322,6 +349,9 @@ hammer_blockmap_free(hammer_transaction_t trans,
        layer1 = hammer_bread(trans->hmp, layer1_offset, &error, &buffer1);
        KKASSERT(error == 0);
        KKASSERT(layer1->phys_offset);
+       if (layer1->layer1_crc != crc32(layer1, HAMMER_LAYER1_CRCSIZE)) {
+               Debugger("CRC FAILED: LAYER1");
+       }
 
        /*
         * Dive layer 2, each entry represents a large-block.
@@ -329,9 +359,12 @@ hammer_blockmap_free(hammer_transaction_t trans,
        layer2_offset = layer1->phys_offset +
                        HAMMER_BLOCKMAP_LAYER2_OFFSET(bmap_off);
        layer2 = hammer_bread(trans->hmp, layer2_offset, &error, &buffer2);
-
        KKASSERT(error == 0);
        KKASSERT(layer2->u.phys_offset);
+       if (layer2->entry_crc != crc32(layer2, HAMMER_LAYER2_CRCSIZE)) {
+               Debugger("CRC FAILED: LAYER2");
+       }
+
        hammer_modify_buffer(trans, buffer2, layer2, sizeof(*layer2));
        layer2->bytes_free += bytes;
        KKASSERT(layer2->bytes_free <= HAMMER_LARGEBLOCK_SIZE);
@@ -364,6 +397,8 @@ hammer_blockmap_free(hammer_transaction_t trans,
                                layer1->phys_offset = HAMMER_BLOCKMAP_FREE;
                        }
 #endif
+                       layer1->layer1_crc = crc32(layer1,
+                                                  HAMMER_LAYER1_CRCSIZE);
                        hammer_modify_buffer_done(buffer1);
                } else {
                        /*
@@ -381,6 +416,7 @@ hammer_blockmap_free(hammer_transaction_t trans,
 #endif
                }
        }
+       layer2->entry_crc = crc32(layer2, HAMMER_LAYER2_CRCSIZE);
        hammer_modify_buffer_done(buffer2);
 done:
        lockmgr(&trans->hmp->blockmap_lock, LK_RELEASE);
@@ -439,6 +475,9 @@ hammer_blockmap_getfree(hammer_mount_t hmp, hammer_off_t bmap_off,
        layer1 = hammer_bread(hmp, layer1_offset, errorp, &buffer);
        KKASSERT(*errorp == 0);
        KKASSERT(layer1->phys_offset);
+       if (layer1->layer1_crc != crc32(layer1, HAMMER_LAYER1_CRCSIZE)) {
+               Debugger("CRC FAILED: LAYER1");
+       }
 
        /*
         * Dive layer 2, each entry represents a large-block.
@@ -446,9 +485,11 @@ hammer_blockmap_getfree(hammer_mount_t hmp, hammer_off_t bmap_off,
        layer2_offset = layer1->phys_offset +
                        HAMMER_BLOCKMAP_LAYER2_OFFSET(bmap_off);
        layer2 = hammer_bread(hmp, layer2_offset, errorp, &buffer);
-
        KKASSERT(*errorp == 0);
        KKASSERT(layer2->u.phys_offset);
+       if (layer2->entry_crc != crc32(layer2, HAMMER_LAYER2_CRCSIZE)) {
+               Debugger("CRC FAILED: LAYER2");
+       }
 
        bytes = layer2->bytes_free;
 
@@ -510,6 +551,9 @@ hammer_blockmap_lookup(hammer_mount_t hmp, hammer_off_t bmap_off, int *errorp)
        layer1 = hammer_bread(hmp, layer1_offset, errorp, &buffer);
        KKASSERT(*errorp == 0);
        KKASSERT(layer1->phys_offset);
+       if (layer1->layer1_crc != crc32(layer1, HAMMER_LAYER1_CRCSIZE)) {
+               Debugger("CRC FAILED: LAYER1");
+       }
 
        /*
         * Dive layer 2, each entry represents a large-block.
@@ -520,6 +564,9 @@ hammer_blockmap_lookup(hammer_mount_t hmp, hammer_off_t bmap_off, int *errorp)
 
        KKASSERT(*errorp == 0);
        KKASSERT(layer2->u.phys_offset);
+       if (layer2->entry_crc != crc32(layer2, HAMMER_LAYER2_CRCSIZE)) {
+               Debugger("CRC FAILED: LAYER2");
+       }
 
        result_offset = layer2->u.phys_offset +
                        (bmap_off & HAMMER_LARGEBLOCK_MASK64);
index 4918b44..124214d 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.42 2008/05/04 09:06:45 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer_btree.c,v 1.43 2008/05/05 20:34:47 dillon Exp $
  */
 
 /*
@@ -583,6 +583,7 @@ hammer_btree_extract(hammer_cursor_t cursor, int flags)
        hammer_btree_elm_t elm;
        hammer_off_t rec_off;
        hammer_off_t data_off;
+       int32_t data_len;
        int error;
 
        /*
@@ -608,6 +609,7 @@ hammer_btree_extract(hammer_cursor_t cursor, int flags)
        if (elm->leaf.base.btype != HAMMER_BTREE_TYPE_RECORD)
                flags &= ~HAMMER_CURSOR_GET_DATA;
        data_off = elm->leaf.data_offset;
+       data_len = elm->leaf.data_len;
        if (data_off == 0)
                flags &= ~HAMMER_CURSOR_GET_DATA;
        rec_off = elm->leaf.rec_offset;
@@ -621,6 +623,9 @@ hammer_btree_extract(hammer_cursor_t cursor, int flags)
             ((rec_off ^ data_off) & ~HAMMER_BUFMASK64) == 0)) {
                cursor->record = hammer_bread(hmp, rec_off, &error,
                                              &cursor->record_buffer);
+               if (hammer_crc_test_record(cursor->record) == 0) {
+                       Debugger("CRC FAILED: RECORD");
+               }
        } else {
                rec_off = 0;
                error = 0;
@@ -640,6 +645,11 @@ hammer_btree_extract(hammer_cursor_t cursor, int flags)
                                ((char *)cursor->record_buffer->ondisk +
                                ((int32_t)data_off & HAMMER_BUFMASK));
                }
+               KKASSERT(data_len >= 0 && data_len <= HAMMER_BUFSIZE);
+               if (data_len && 
+                   crc32(cursor->data, data_len) != elm->leaf.data_crc) {
+                       Debugger("CRC FAILED: DATA");
+               }
        }
        return(error);
 }
@@ -1908,7 +1918,8 @@ hammer_btree_correct_lhb(hammer_cursor_t cursor, hammer_tid_t tid)
                        kprintf("hammer_btree_correct_lhb-I @%016llx[%d]\n",
                                cursor->node->node_offset, cursor->index);
                        hammer_modify_node(cursor->trans, cursor->node,
-                                          elm, sizeof(*elm));
+                                          &elm->create_tid,
+                                          sizeof(elm->create_tid));
                        elm->create_tid = tid;
                        hammer_modify_node_done(cursor->node);
                } else {
@@ -2085,8 +2096,8 @@ btree_set_parent(hammer_transaction_t trans, hammer_node_t node,
        switch(elm->base.btype) {
        case HAMMER_BTREE_TYPE_INTERNAL:
        case HAMMER_BTREE_TYPE_LEAF:
-               child = hammer_get_node(node->hmp,
-                                       elm->internal.subtree_offset, &error);
+               child = hammer_get_node(node->hmp, elm->internal.subtree_offset,
+                                       0, &error);
                if (error == 0) {
                        hammer_modify_node_field(trans, child, parent);
                        child->ondisk->parent = node->node_offset;
@@ -2134,7 +2145,7 @@ hammer_btree_lock_children(hammer_cursor_t cursor,
                case HAMMER_BTREE_TYPE_LEAF:
                        child = hammer_get_node(node->hmp,
                                                elm->internal.subtree_offset,
-                                               &error);
+                                               0, &error);
                        break;
                default:
                        child = NULL;
index 5dc0e91..f30b6fc 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.h,v 1.12 2008/02/10 09:51:01 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer_btree.h,v 1.13 2008/05/05 20:34:47 dillon Exp $
  */
 
 /*
@@ -132,10 +132,10 @@ struct hammer_btree_internal_elm {
  */
 struct hammer_btree_leaf_elm {
        struct hammer_base_elm base;
-       hammer_off_t rec_offset;
-       hammer_off_t data_offset;
-       int32_t data_len;
-       u_int32_t data_crc;
+       hammer_off_t    rec_offset;
+       hammer_off_t    data_offset;
+       int32_t         data_len;
+       hammer_crc_t    data_crc;
 };
 
 /*
@@ -187,8 +187,8 @@ struct hammer_node_ondisk {
        /*
         * B-Tree node header (64 bytes)
         */
+       hammer_crc_t    crc;            /* MUST BE FIRST FIELD OF STRUCTURE */
        u_int32_t       signature;
-       u_int32_t       crc;
        hammer_off_t    parent;         /* 0 if at root of cluster */
        int32_t         count;
        u_int8_t        type;
@@ -210,5 +210,10 @@ struct hammer_node_ondisk {
        union hammer_btree_elm elms[HAMMER_BTREE_LEAF_ELMS];
 };
 
+#define HAMMER_BTREE_SIGNATURE_GOOD            0xB3A49586
+#define HAMMER_BTREE_SIGNATURE_DESTROYED       0x4A3B2C1D
+#define HAMMER_BTREE_CRCSIZE   \
+       (sizeof(struct hammer_node_ondisk) - sizeof(hammer_crc_t))
+
 typedef struct hammer_node_ondisk *hammer_node_ondisk_t;
 
index 0edcca8..210c6a5 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_cursor.c,v 1.23 2008/05/03 05:28:55 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer_cursor.c,v 1.24 2008/05/05 20:34:47 dillon Exp $
  */
 
 /*
@@ -95,7 +95,8 @@ hammer_init_cursor(hammer_transaction_t trans, hammer_cursor_t cursor,
                if (error)
                        break;
                node = hammer_get_node(trans->hmp,
-                                      volume->ondisk->vol0_btree_root, &error);
+                                      volume->ondisk->vol0_btree_root,
+                                      0, &error);
                hammer_rel_volume(volume, 0);
                if (error)
                        break;
@@ -302,7 +303,7 @@ hammer_load_cursor_parent(hammer_cursor_t cursor)
 
        if (cursor->node->ondisk->parent) {
                node = cursor->node;
-               parent = hammer_get_node(hmp, node->ondisk->parent, &error);
+               parent = hammer_get_node(hmp, node->ondisk->parent, 0, &error);
                if (error)
                        return(error);
                hammer_lock_sh(&parent->lock);
@@ -414,7 +415,7 @@ hammer_cursor_down(hammer_cursor_t cursor)
                cursor->left_bound = &elm[0].internal.base;
                cursor->right_bound = &elm[1].internal.base;
                node = hammer_get_node(cursor->trans->hmp,
-                                      elm->internal.subtree_offset, &error);
+                                      elm->internal.subtree_offset, 0, &error);
                if (error == 0) {
                        KASSERT(elm->base.btype == node->ondisk->type, ("BTYPE MISMATCH %c %c NODE %p\n", elm->base.btype, node->ondisk->type, node));
                        if (node->ondisk->parent != cursor->parent->node_offset)
index 20cc923..6120d69 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_disk.h,v 1.30 2008/04/29 01:10:37 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer_disk.h,v 1.31 2008/05/05 20:34:47 dillon Exp $
  */
 
 #ifndef VFS_HAMMER_DISK_H_
@@ -221,12 +221,15 @@ struct hammer_blockmap {
        hammer_off_t    first_offset;   /* zone-X logical offset (zone 3) */
        hammer_off_t    next_offset;    /* zone-X logical offset */
        hammer_off_t    alloc_offset;   /* zone-X logical offset */
-       hammer_crc_t    entry_crc;
        u_int32_t       reserved01;
+       hammer_crc_t    entry_crc;
 };
 
 typedef struct hammer_blockmap *hammer_blockmap_t;
 
+#define HAMMER_BLOCKMAP_CRCSIZE        \
+       offsetof(struct hammer_blockmap, entry_crc)
+
 /*
  * The blockmap is a 2-layer entity made up of big-blocks.  The first layer
  * contains 262144 32-byte entries (18 bits), the second layer contains
@@ -244,20 +247,27 @@ typedef struct hammer_blockmap *hammer_blockmap_t;
 struct hammer_blockmap_layer1 {
        hammer_off_t    blocks_free;    /* big-blocks free */
        hammer_off_t    phys_offset;    /* UNAVAIL or zone-2 */
-       hammer_crc_t    layer1_crc;     /* crc of this entry */
-       hammer_crc_t    layer2_crc;     /* xor'd crc's of HAMMER_BLOCKSIZE */
        hammer_off_t    reserved01;
+       hammer_crc_t    layer2_crc;     /* xor'd crc's of HAMMER_BLOCKSIZE */
+                                       /* (not yet used) */
+       hammer_crc_t    layer1_crc;     /* MUST BE LAST FIELD OF STRUCTURE*/
 };
 
+#define HAMMER_LAYER1_CRCSIZE  \
+       offsetof(struct hammer_blockmap_layer1, layer1_crc)
+
 struct hammer_blockmap_layer2 {
-       hammer_crc_t    entry_crc;
-       u_int32_t       bytes_free;     /* bytes free within this bigblock */
        union {
                hammer_off_t    owner;          /* used by freemap */
                hammer_off_t    phys_offset;    /* used by blockmap */
        } u;
+       u_int32_t       bytes_free;     /* bytes free within this bigblock */
+       hammer_crc_t    entry_crc;
 };
 
+#define HAMMER_LAYER2_CRCSIZE  \
+       offsetof(struct hammer_blockmap_layer2, entry_crc)
+
 #define HAMMER_BLOCKMAP_FREE   0ULL
 #define HAMMER_BLOCKMAP_UNAVAIL        ((hammer_off_t)-1LL)
 
@@ -333,9 +343,11 @@ struct hammer_fifo_head {
        u_int16_t hdr_type;
        u_int32_t hdr_size;     /* aligned size of the whole mess */
        u_int32_t reserved01;   /* (0) reserved for future use */
-       hammer_crc_t hdr_crc;
+       hammer_crc_t hdr_crc;   /* XOR crc up to field w/ crc after field */
 };
 
+#define HAMMER_FIFO_HEAD_CRCOFF        offsetof(struct hammer_fifo_head, hdr_crc)
+
 struct hammer_fifo_tail {
        u_int16_t tail_signature;
        u_int16_t tail_type;
@@ -443,7 +455,7 @@ struct hammer_volume_ondisk {
        int32_t vol_count;      /* number of volumes making up FS */
 
        u_int32_t vol_version;  /* version control information */
-       u_int32_t vol_reserved01;
+       hammer_crc_t vol_crc;   /* header crc */
        u_int32_t vol_flags;    /* volume flags */
        u_int32_t vol_rootvol;  /* which volume is the root volume? */
 
@@ -488,6 +500,12 @@ typedef struct hammer_volume_ondisk *hammer_volume_ondisk_t;
 #define HAMMER_VOLF_VALID              0x0001  /* valid entry */
 #define HAMMER_VOLF_OPEN               0x0002  /* volume is open */
 
+#define HAMMER_VOL_CRCSIZE1    \
+       offsetof(struct hammer_volume_ondisk, vol_crc)
+#define HAMMER_VOL_CRCSIZE2    \
+       (sizeof(struct hammer_volume_ondisk) - HAMMER_VOL_CRCSIZE1 -    \
+        sizeof(hammer_crc_t))
+
 /*
  * All HAMMER records have a common 64-byte base and a 32 byte extension,
  * plus a possible data reference.  The data reference can be in-band or
@@ -497,14 +515,19 @@ typedef struct hammer_volume_ondisk *hammer_volume_ondisk_t;
 #define HAMMER_RECORD_SIZE             (64+32)
 
 struct hammer_base_record {
-       u_int32_t       signature;      /* record signature */
+       hammer_crc_t    rec_crc;        /* record crc (full 64-4 bytes) */
+                                       /* MUST BE FIRST FIELD OF STRUCTURE */
        hammer_crc_t    data_crc;       /* data crc */
+                                       /* MUST BE SECOND FIELD OF STRUCTURE */
        struct hammer_base_elm base;    /* 40 byte base element */
        hammer_off_t    data_off;       /* in-band or out-of-band */
        int32_t         data_len;       /* size of data in bytes */
-       u_int32_t       reserved02;
+       u_int32_t       signature;      /* record signature */
 };
 
+#define HAMMER_RECORD_SIGNATURE_GOOD           0xA7B6C5D4
+#define HAMMER_RECORD_SIGNATURE_DESTROYED      0xF8071625
+
 /*
  * Record types are fairly straightforward.  The B-Tree includes the record
  * type in its index sort.
@@ -648,6 +671,8 @@ union hammer_record_ondisk {
 
 typedef union hammer_record_ondisk *hammer_record_ondisk_t;
 
+#define HAMMER_RECORD_CRCSIZE  (HAMMER_RECORD_SIZE - sizeof(hammer_crc_t))
+
 /*
  * HAMMER UNIX Attribute data
  *
index 6f8a666..5bd671c 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_flusher.c,v 1.12 2008/05/04 09:06:45 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer_flusher.c,v 1.13 2008/05/05 20:34:47 dillon Exp $
  */
 /*
  * HAMMER dependancy flusher thread
@@ -247,6 +247,7 @@ hammer_flusher_finalize(hammer_transaction_t trans)
        const int bmsize = sizeof(root_volume->ondisk->vol0_blockmap);
        hammer_io_t io;
        int count;
+       int i;
 
        hammer_lock_ex(&hmp->sync_lock);
        rootmap = &hmp->blockmap[HAMMER_ZONE_UNDO_INDEX];
@@ -266,6 +267,8 @@ hammer_flusher_finalize(hammer_transaction_t trans)
                hammer_modify_volume(trans, root_volume,
                            &root_volume->ondisk->vol0_blockmap,
                            bmsize);
+               for (i = 0; i < HAMMER_MAX_ZONES; ++i)
+                       hammer_crc_set_blockmap(&hmp->blockmap[i]);
                bcopy(hmp->blockmap, root_volume->ondisk->vol0_blockmap,
                      bmsize);
                hammer_modify_volume_done(root_volume);
@@ -328,6 +331,7 @@ hammer_flusher_finalize(hammer_transaction_t trans)
                hammer_modify_volume(NULL, root_volume, NULL, 0);
                rootmap->first_offset = hmp->flusher_undo_start;
                root_volume->ondisk->vol0_blockmap[HAMMER_ZONE_UNDO_INDEX].first_offset = rootmap->first_offset;
+               hammer_crc_set_blockmap(&root_volume->ondisk->vol0_blockmap[HAMMER_ZONE_UNDO_INDEX]);
                hammer_modify_volume_done(root_volume);
        }
        trans->hmp->flusher_undo_start = rootmap->next_offset;
@@ -339,8 +343,10 @@ hammer_flusher_finalize(hammer_transaction_t trans)
         * we just have to hope that the undo range has been updated.  It
         * should be done in one I/O but XXX this won't be perfect.
         */
-       if (root_volume->io.modified)
+       if (root_volume->io.modified) {
+               hammer_crc_set_volume(root_volume->ondisk);
                hammer_io_flush(&root_volume->io);
+       }
 
        /*
         * Wait for I/O to complete
index 986d03b..3bb0261 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_inode.c,v 1.51 2008/05/04 19:57:42 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer_inode.c,v 1.52 2008/05/05 20:34:47 dillon Exp $
  */
 
 #include "hammer.h"
@@ -281,9 +281,16 @@ retry:
                }
                ip->flags |= HAMMER_INODE_ONDISK;
        } else {
-               kprintf("hammer_get_inode: failed ip %p obj_id %016llx cursor %p error %d\n",
-                       ip, ip->obj_id, &cursor, *errorp);
-               /*Debugger("x");*/
+               /*
+                * Do not panic on read-only accesses which fail, particularly
+                * historical accesses where the snapshot might not have
+                * complete connectivity.
+                */
+               if ((flags & HAMMER_INODE_RO) == 0) {
+                       kprintf("hammer_get_inode: failed ip %p obj_id %016llx cursor %p error %d\n",
+                               ip, ip->obj_id, &cursor, *errorp);
+                               Debugger("x");
+               }
                --hammer_count_inodes;
                kfree(ip, M_HAMMER);
                ip = NULL;
@@ -465,6 +472,7 @@ retry:
                record->rec.inode = ip->sync_ino_rec;
                record->rec.inode.base.base.create_tid = trans->tid;
                record->rec.inode.base.data_len = sizeof(ip->sync_ino_data);
+               record->rec.base.signature = HAMMER_RECORD_SIGNATURE_GOOD;
                record->data = (void *)&ip->sync_ino_data;
                record->flags |= HAMMER_RECF_INTERLOCK_BE;
                for (;;) {
@@ -573,11 +581,13 @@ retry:
                         * updates.
                         */
                        rec = &cursor->record->inode;
-                       hammer_modify_buffer(trans, cursor->record_buffer,
-                                            NULL, 0);
+                       hammer_modify_record_noundo(trans,
+                                                   cursor->record_buffer,
+                                                   cursor->record);
                        rec->ino_atime = ip->sync_ino_rec.ino_atime;
                        rec->ino_mtime = ip->sync_ino_rec.ino_mtime;
-                       hammer_modify_buffer_done(cursor->record_buffer);
+                       hammer_modify_record_done(cursor->record_buffer,
+                                                 cursor->record);
                        ip->sync_flags &= ~HAMMER_INODE_ITIMES;
                        /* XXX recalculate crc */
                        hammer_cache_node(cursor->node, &ip->cache[0]);
index 54ee1f5..595f0fd 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_ioctl.c,v 1.11 2008/05/03 05:28:55 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer_ioctl.c,v 1.12 2008/05/05 20:34:47 dillon Exp $
  */
 
 #include "hammer.h"
@@ -103,7 +103,7 @@ hammer_ioc_prune(hammer_transaction_t trans, hammer_inode_t ip,
                return(EINVAL);
        if (prune->beg_obj_id >= prune->end_obj_id)
                return(EINVAL);
-       if ((prune->flags & HAMMER_IOC_PRUNE_ALL) && prune->nelms)
+       if ((prune->head.flags & HAMMER_IOC_PRUNE_ALL) && prune->nelms)
                return(EINVAL);
 
 retry:
@@ -119,8 +119,8 @@ retry:
        cursor.key_beg.rec_type = HAMMER_MIN_RECTYPE;
        cursor.key_beg.obj_type = 0;
 
-       cursor.key_end.obj_id = prune->cur_obj_id;
-       cursor.key_end.key = prune->cur_key;
+       cursor.key_end.obj_id = prune->end_obj_id;
+       cursor.key_end.key = HAMMER_MAX_KEY;
        cursor.key_end.create_tid = HAMMER_MAX_TID - 1;
        cursor.key_end.delete_tid = 0;
        cursor.key_end.rec_type = HAMMER_MAX_RECTYPE;
@@ -129,6 +129,9 @@ retry:
        cursor.flags |= HAMMER_CURSOR_END_INCLUSIVE;
        cursor.flags |= HAMMER_CURSOR_BACKEND;
 
+       prune->cur_obj_id = cursor.key_end.obj_id;
+       prune->cur_key = cursor.key_end.key;
+
        error = hammer_btree_last(&cursor);
        while (error == 0) {
                elm = &cursor.node->ondisk->elms[cursor.index];
@@ -201,6 +204,10 @@ retry:
        hammer_done_cursor(&cursor);
        if (error == EDEADLK)
                goto retry;
+       if (error == EINTR) {
+               prune->head.flags |= HAMMER_IOC_HEAD_INTR;
+               error = 0;
+       }
        return(error);
 }
 
@@ -221,7 +228,7 @@ check_prune(struct hammer_ioc_prune *prune, hammer_btree_elm_t elm,
         * If pruning everything remove all records with a non-zero
         * delete_tid.
         */
-       if (prune->flags & HAMMER_IOC_PRUNE_ALL) {
+       if (prune->head.flags & HAMMER_IOC_PRUNE_ALL) {
                if (elm->base.delete_tid != 0)
                        return(0);
                return(-1);
@@ -323,14 +330,17 @@ realign_prune(struct hammer_ioc_prune *prune,
                                error = hammer_cursor_upgrade(cursor);
                        }
                        if (error == 0) {
-                               hammer_modify_buffer(cursor->trans,
-                                                    cursor->record_buffer,
-                                                    NULL, 0);
+                               hammer_modify_record_field(cursor->trans,
+                                           cursor->record_buffer,
+                                           cursor->record,
+                                           base.base.create_tid, 0);
                                cursor->record->base.base.create_tid = tid;
-                               hammer_modify_buffer_done(cursor->record_buffer);
+                               hammer_modify_record_done(
+                                           cursor->record_buffer,
+                                           cursor->record);
                                hammer_modify_node(cursor->trans, cursor->node,
-                                                  &elm->leaf.base.create_tid,
-                                                  sizeof(elm->leaf.base.create_tid));
+                                           &elm->leaf.base.create_tid,
+                                           sizeof(elm->leaf.base.create_tid));
                                elm->leaf.base.create_tid = tid;
                                hammer_modify_node_done(cursor->node);
                        }
@@ -351,16 +361,20 @@ realign_prune(struct hammer_ioc_prune *prune,
                                                     HAMMER_CURSOR_GET_RECORD);
                        if (error == 0) {
                                hammer_modify_node(cursor->trans, cursor->node,
-                                                  &elm->leaf.base.delete_tid,
-                                                  sizeof(elm->leaf.base.delete_tid));
+                                           &elm->leaf.base.delete_tid,
+                                           sizeof(elm->leaf.base.delete_tid));
                                elm->leaf.base.delete_tid =
-                                               elm->leaf.base.delete_tid -
-                                               delta + mod;
+                                           elm->leaf.base.delete_tid -
+                                           delta + mod;
                                hammer_modify_node_done(cursor->node);
-                               hammer_modify_buffer(cursor->trans, cursor->record_buffer, &cursor->record->base.base.delete_tid, sizeof(hammer_tid_t));
+                               hammer_modify_record_field(cursor->trans,
+                                           cursor->record_buffer,
+                                           cursor->record,
+                                           base.base.delete_tid, 0);
                                cursor->record->base.base.delete_tid =
-                                               elm->leaf.base.delete_tid;
-                               hammer_modify_buffer_done(cursor->record_buffer);
+                                           elm->leaf.base.delete_tid;
+                               hammer_modify_record_done(cursor->record_buffer,
+                                           cursor->record);
                        }
                }
        }
@@ -388,7 +402,7 @@ hammer_ioc_gethistory(hammer_transaction_t trans, hammer_inode_t ip,
         */
        if (hist->beg_tid > hist->end_tid)
                return(EINVAL);
-       if (hist->flags & HAMMER_IOC_HISTORY_ATKEY) {
+       if (hist->head.flags & HAMMER_IOC_HISTORY_ATKEY) {
                if (hist->key > hist->nxt_key)
                        return(EINVAL);
        }
@@ -396,12 +410,12 @@ hammer_ioc_gethistory(hammer_transaction_t trans, hammer_inode_t ip,
        hist->obj_id = ip->obj_id;
        hist->count = 0;
        hist->nxt_tid = hist->end_tid;
-       hist->flags &= ~HAMMER_IOC_HISTORY_NEXT_TID;
-       hist->flags &= ~HAMMER_IOC_HISTORY_NEXT_KEY;
-       hist->flags &= ~HAMMER_IOC_HISTORY_EOF;
-       hist->flags &= ~HAMMER_IOC_HISTORY_UNSYNCED;
+       hist->head.flags &= ~HAMMER_IOC_HISTORY_NEXT_TID;
+       hist->head.flags &= ~HAMMER_IOC_HISTORY_NEXT_KEY;
+       hist->head.flags &= ~HAMMER_IOC_HISTORY_EOF;
+       hist->head.flags &= ~HAMMER_IOC_HISTORY_UNSYNCED;
        if ((ip->flags & HAMMER_INODE_MODMASK) & ~HAMMER_INODE_ITIMES)
-               hist->flags |= HAMMER_IOC_HISTORY_UNSYNCED;
+               hist->head.flags |= HAMMER_IOC_HISTORY_UNSYNCED;
 
        /*
         * Setup the cursor.  We can't handle undeletable records
@@ -428,7 +442,7 @@ hammer_ioc_gethistory(hammer_transaction_t trans, hammer_inode_t ip,
 
        cursor.flags |= HAMMER_CURSOR_END_EXCLUSIVE;
 
-       if (hist->flags & HAMMER_IOC_HISTORY_ATKEY) {
+       if (hist->head.flags & HAMMER_IOC_HISTORY_ATKEY) {
                /*
                 * key-range within the file.  For a regular file the
                 * on-disk key represents BASE+LEN, not BASE, so the
@@ -469,15 +483,15 @@ hammer_ioc_gethistory(hammer_transaction_t trans, hammer_inode_t ip,
                elm = &cursor.node->ondisk->elms[cursor.index];
 
                add_history(ip, hist, elm);
-               if (hist->flags & (HAMMER_IOC_HISTORY_NEXT_TID |
-                                 HAMMER_IOC_HISTORY_NEXT_KEY |
-                                 HAMMER_IOC_HISTORY_EOF)) {
+               if (hist->head.flags & (HAMMER_IOC_HISTORY_NEXT_TID |
+                                       HAMMER_IOC_HISTORY_NEXT_KEY |
+                                       HAMMER_IOC_HISTORY_EOF)) {
                        break;
                }
                error = hammer_btree_iterate(&cursor);
        }
        if (error == ENOENT) {
-               hist->flags |= HAMMER_IOC_HISTORY_EOF;
+               hist->head.flags |= HAMMER_IOC_HISTORY_EOF;
                error = 0;
        }
        hammer_done_cursor(&cursor);
@@ -495,7 +509,7 @@ add_history(hammer_inode_t ip, struct hammer_ioc_history *hist,
 {
        if (elm->base.btype != HAMMER_BTREE_TYPE_RECORD)
                return;
-       if ((hist->flags & HAMMER_IOC_HISTORY_ATKEY) &&
+       if ((hist->head.flags & HAMMER_IOC_HISTORY_ATKEY) &&
            ip->ino_rec.base.base.obj_type == HAMMER_OBJTYPE_REGFILE) {
                /*
                 * Adjust nxt_key
@@ -513,7 +527,7 @@ add_history(hammer_inode_t ip, struct hammer_ioc_history *hist,
                 */
                if (elm->leaf.base.key >= MAXPHYS &&
                    elm->leaf.base.key - MAXPHYS > hist->key) {
-                       hist->flags |= HAMMER_IOC_HISTORY_NEXT_KEY;
+                       hist->head.flags |= HAMMER_IOC_HISTORY_NEXT_KEY;
                }
 
                /*
@@ -522,7 +536,7 @@ add_history(hammer_inode_t ip, struct hammer_ioc_history *hist,
                if (elm->leaf.base.key - elm->leaf.data_len > hist->key)
                        return;
 
-       } else if (hist->flags & HAMMER_IOC_HISTORY_ATKEY) {
+       } else if (hist->head.flags & HAMMER_IOC_HISTORY_ATKEY) {
                /*
                 * Adjust nxt_key
                 */
@@ -535,7 +549,7 @@ add_history(hammer_inode_t ip, struct hammer_ioc_history *hist,
                 * Record is beyond the requested key.
                 */
                if (elm->leaf.base.key > hist->key)
-                       hist->flags |= HAMMER_IOC_HISTORY_NEXT_KEY;
+                       hist->head.flags |= HAMMER_IOC_HISTORY_NEXT_KEY;
        }
 
        /*
@@ -547,7 +561,7 @@ add_history(hammer_inode_t ip, struct hammer_ioc_history *hist,
            elm->leaf.base.create_tid < hist->end_tid) {
                if (hist->count == HAMMER_MAX_HISTORY_ELMS) {
                        hist->nxt_tid = elm->leaf.base.create_tid;
-                       hist->flags |= HAMMER_IOC_HISTORY_NEXT_TID;
+                       hist->head.flags |= HAMMER_IOC_HISTORY_NEXT_TID;
                        return;
                }
                hist->tid_ary[hist->count++] = elm->leaf.base.create_tid;
@@ -567,7 +581,7 @@ add_history(hammer_inode_t ip, struct hammer_ioc_history *hist,
            elm->leaf.base.delete_tid < hist->end_tid) {
                if (hist->count == HAMMER_MAX_HISTORY_ELMS) {
                        hist->nxt_tid = elm->leaf.base.delete_tid;
-                       hist->flags |= HAMMER_IOC_HISTORY_NEXT_TID;
+                       hist->head.flags |= HAMMER_IOC_HISTORY_NEXT_TID;
                        return;
                }
                hist->tid_ary[hist->count++] = elm->leaf.base.delete_tid;
index 238e253..2254cc9 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_ioctl.h,v 1.5 2008/03/20 06:08:40 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer_ioctl.h,v 1.6 2008/05/05 20:34:47 dillon Exp $
  */
 /*
  * HAMMER ioctl's.  This file can be #included from userland
 #include <sys/ioccom.h>
 #include "hammer_disk.h"
 
+/*
+ * Common HAMMER ioctl header
+ *
+ * Global flags are stored in the upper 16 bits
+ */
+struct hammer_ioc_head {
+       int32_t         flags;
+       int32_t         reserved01;
+       int32_t         reserved02[4];
+};
+
+#define HAMMER_IOC_HEAD_INTR   0x00010000
+
 /*
  * HAMMERIOC_PRUNE
  *
@@ -59,11 +72,12 @@ struct hammer_ioc_prune_elm {
 #define HAMMER_MAX_PRUNE_ELMS  64
 
 struct hammer_ioc_prune {
+       struct hammer_ioc_head head;
        int             nelms;
-       int             flags;
+       int             reserved01;
        int64_t         beg_obj_id;
-       int64_t         cur_obj_id;     /* initialize to end_obj_id */
-       int64_t         cur_key;        /* initialize to HAMMER_MAX_KEY */
+       int64_t         cur_obj_id;
+       int64_t         cur_key;
        int64_t         end_obj_id;      /* (range-exclusive) */
        int64_t         stat_scanrecords;/* number of records scanned */
        int64_t         stat_rawrecords; /* number of raw records pruned */
@@ -105,6 +119,7 @@ struct hammer_ioc_prune {
 #define HAMMER_MAX_HISTORY_ELMS        64
 
 struct hammer_ioc_history {
+       struct hammer_ioc_head head;
        int64_t         obj_id;
        hammer_tid_t    beg_tid;
        hammer_tid_t    nxt_tid;
@@ -112,7 +127,7 @@ struct hammer_ioc_history {
        int64_t         key;
        int64_t         nxt_key;
        int             count;
-       int             flags;
+       int             reserve01;
        hammer_tid_t    tid_ary[HAMMER_MAX_HISTORY_ELMS];
 };
 
@@ -126,6 +141,7 @@ struct hammer_ioc_history {
  * Reblock request
  */
 struct hammer_ioc_reblock {
+       struct hammer_ioc_head head;
        int64_t         beg_obj_id;
        int64_t         cur_obj_id;             /* Stopped at (interrupt) */
        int64_t         end_obj_id;
@@ -142,8 +158,8 @@ struct hammer_ioc_reblock {
        int64_t         data_moves;             /* Data segments moved */
        int64_t         data_byte_moves;        /* Data bytes moved */
 
-       int             flags;
-       int             unused03;
+       int32_t         unused02;
+       int32_t         unused03;
 };
 
 #define HAMMERIOC_PRUNE                _IOWR('h',1,struct hammer_ioc_prune)
index f87672a..c94570d 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.54 2008/05/04 19:57:42 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer_object.c,v 1.55 2008/05/05 20:34:48 dillon Exp $
  */
 
 #include "hammer.h"
@@ -485,6 +485,7 @@ hammer_ip_add_directory(struct hammer_transaction *trans,
                ++trans->hmp->namekey_iterator;
 
        record->type = HAMMER_MEM_RECORD_ADD;
+       record->rec.entry.base.signature = HAMMER_RECORD_SIGNATURE_GOOD;
        record->rec.entry.base.base.obj_id = dip->obj_id;
        record->rec.entry.base.base.key =
                hammer_directory_namekey(ncp->nc_name, bytes);
@@ -565,6 +566,7 @@ hammer_ip_del_directory(struct hammer_transaction *trans,
                 */
                record = hammer_alloc_mem_record(dip);
                record->type = HAMMER_MEM_RECORD_DEL;
+               record->rec.entry.base.signature = HAMMER_RECORD_SIGNATURE_GOOD;
                record->rec.entry.base.base = cursor->record->base.base;
                hammer_modify_inode(trans, ip, HAMMER_INODE_RDIRTY);
 
@@ -660,7 +662,7 @@ hammer_ip_sync_data(hammer_cursor_t cursor, hammer_inode_t ip,
        hammer_transaction_t trans = cursor->trans;
        hammer_record_ondisk_t rec;
        union hammer_btree_elm elm;
-       hammer_off_t rec_offset;
+       hammer_off_t rec_offset, data_offset;
        void *bdata;
        int error;
 
@@ -703,7 +705,7 @@ retry:
        rec = hammer_alloc_record(trans, &rec_offset, HAMMER_RECTYPE_DATA,
                                  &cursor->record_buffer,
                                  bytes, &bdata,
-                                 &cursor->data_buffer, &error);
+                                 &data_offset, &cursor->data_buffer, &error);
        if (rec == NULL)
                goto done;
        if (hammer_debug_general & 0x1000)
@@ -724,6 +726,9 @@ retry:
        rec->base.base.delete_tid = 0;
        rec->base.base.rec_type = HAMMER_RECTYPE_DATA;
        rec->base.data_crc = crc32(data, bytes);
+       rec->base.signature = HAMMER_RECORD_SIGNATURE_GOOD;
+       rec->base.rec_crc = crc32(&rec->base.data_crc,
+                                 HAMMER_RECORD_CRCSIZE);
        hammer_modify_buffer_done(cursor->record_buffer);
        KKASSERT(rec->base.data_len == bytes);
 
@@ -748,7 +753,12 @@ retry:
        if (error == 0)
                goto done;
 
+       hammer_modify_buffer(trans, cursor->record_buffer, NULL, 0);
+       rec->base.signature = HAMMER_RECORD_SIGNATURE_DESTROYED;
+       hammer_modify_buffer_done(cursor->record_buffer);
+
        hammer_blockmap_free(trans, rec_offset, HAMMER_RECORD_SIZE);
+       hammer_blockmap_free(trans, data_offset, bytes);
 done:
        if (error == EDEADLK) {
                hammer_done_cursor(cursor);
@@ -799,11 +809,13 @@ hammer_ip_sync_record_cursor(hammer_cursor_t cursor, hammer_record_t record)
        hammer_record_ondisk_t rec;
        union hammer_btree_elm elm;
        hammer_off_t rec_offset;
+       hammer_off_t data_offset;
        void *bdata;
        int error;
 
        KKASSERT(record->flush_state == HAMMER_FST_FLUSH);
        KKASSERT(record->flags & HAMMER_RECF_INTERLOCK_BE);
+       KKASSERT(record->rec.base.signature == HAMMER_RECORD_SIGNATURE_GOOD);
 
        hammer_normalize_cursor(cursor);
        cursor->key_beg = record->rec.base.base;
@@ -870,7 +882,7 @@ hammer_ip_sync_record_cursor(hammer_cursor_t cursor, hammer_record_t record)
                                          record->rec.base.base.rec_type,
                                          &cursor->record_buffer,
                                          0, &bdata,
-                                         NULL, &error);
+                                         NULL, NULL, &error);
                if (hammer_debug_general & 0x1000)
                        kprintf("NULL RECORD DATA\n");
        } else if (record->flags & HAMMER_RECF_INBAND) {
@@ -878,7 +890,7 @@ hammer_ip_sync_record_cursor(hammer_cursor_t cursor, hammer_record_t record)
                                          record->rec.base.base.rec_type,
                                          &cursor->record_buffer,
                                          record->rec.base.data_len, &bdata,
-                                         NULL, &error);
+                                         NULL, NULL, &error);
                if (hammer_debug_general & 0x1000)
                        kprintf("INBAND RECORD DATA %016llx DATA %016llx LEN=%d\n", rec_offset, rec->base.data_off, record->rec.base.data_len);
        } else {
@@ -886,6 +898,7 @@ hammer_ip_sync_record_cursor(hammer_cursor_t cursor, hammer_record_t record)
                                          record->rec.base.base.rec_type,
                                          &cursor->record_buffer,
                                          record->rec.base.data_len, &bdata,
+                                         &data_offset,
                                          &cursor->data_buffer, &error);
                if (hammer_debug_general & 0x1000)
                        kprintf("OOB RECORD DATA REC %016llx DATA %016llx LEN=%d\n", rec_offset, rec->base.data_off, record->rec.base.data_len);
@@ -918,6 +931,9 @@ hammer_ip_sync_record_cursor(hammer_cursor_t cursor, hammer_record_t record)
        } else {
                rec->base.data_len = record->rec.base.data_len;
        }
+       rec->base.signature = HAMMER_RECORD_SIGNATURE_GOOD;
+       rec->base.rec_crc = crc32(&rec->base.data_crc,
+                                 HAMMER_RECORD_CRCSIZE);
        hammer_modify_buffer_done(cursor->record_buffer);
 
        elm.leaf.base = record->rec.base.base;
@@ -954,8 +970,14 @@ hammer_ip_sync_record_cursor(hammer_cursor_t cursor, hammer_record_t record)
                        record->flags |= HAMMER_RECF_DELETED_BE;
                }
        } else {
+               hammer_modify_buffer(trans, cursor->record_buffer, NULL, 0);
+               rec->base.signature = HAMMER_RECORD_SIGNATURE_DESTROYED;
+               hammer_modify_buffer_done(cursor->record_buffer);
                hammer_blockmap_free(trans, rec_offset, HAMMER_RECORD_SIZE);
-               /* XXX free data buffer? */
+               if (record->data && (record->flags & HAMMER_RECF_INBAND) == 0) {
+                       hammer_blockmap_free(trans, data_offset,
+                                            record->rec.base.data_len);
+               }
        }
 
 done:
@@ -982,6 +1004,8 @@ hammer_mem_add(struct hammer_transaction *trans, hammer_record_t record)
        int bytes;
        int reclen;
                
+       KKASSERT(record->rec.base.signature == HAMMER_RECORD_SIGNATURE_GOOD);
+
        /*
         * Make a private copy of record->data
         */
@@ -1617,7 +1641,15 @@ hammer_ip_delete_record(hammer_cursor_t cursor, hammer_tid_t tid)
        elm = NULL;
        hmp = cursor->node->hmp;
 
-       dodelete = 0;
+       /*
+        * If we were mounted with the nohistory option, we physically
+        * delete the record.
+        */
+       if (hmp->hflags & HMNT_NOHISTORY)
+               dodelete = 1;
+       else
+               dodelete = 0;
+
        if (error == 0) {
                error = hammer_cursor_upgrade(cursor);
                if (error == 0) {
@@ -1634,19 +1666,18 @@ hammer_ip_delete_record(hammer_cursor_t cursor, hammer_tid_t tid)
                         * this could result in a duplicate record.
                         */
                        KKASSERT(elm->leaf.base.delete_tid != elm->leaf.base.create_tid);
-                       hammer_modify_buffer(cursor->trans, cursor->record_buffer, &cursor->record->base.base.delete_tid, sizeof(hammer_tid_t));
+
+                       hammer_modify_record_field(cursor->trans, cursor->record_buffer, cursor->record, base.base.delete_tid, dodelete);
                        cursor->record->base.base.delete_tid = tid;
-                       hammer_modify_buffer_done(cursor->record_buffer);
+                       if (dodelete) {
+                               cursor->record->base.signature =
+                                           HAMMER_RECORD_SIGNATURE_DESTROYED;
+                       }
+                       hammer_modify_record_done(cursor->record_buffer,
+                                                 cursor->record);
                }
        }
 
-       /*
-        * If we were mounted with the nohistory option, we physically
-        * delete the record.
-        */
-       if (hmp->hflags & HMNT_NOHISTORY)
-               dodelete = 1;
-
        if (error == 0 && dodelete) {
                error = hammer_delete_at_cursor(cursor, NULL);
                if (error) {
index efcbfe5..4dccece 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.40 2008/04/27 00:45:37 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer_ondisk.c,v 1.41 2008/05/05 20:34:48 dillon Exp $
  */
 /*
  * Manage HAMMER's on-disk structures.  These routines are primarily
@@ -48,7 +48,7 @@
 static void hammer_free_volume(hammer_volume_t volume);
 static int hammer_load_volume(hammer_volume_t volume);
 static int hammer_load_buffer(hammer_buffer_t buffer, int isnew);
-static int hammer_load_node(hammer_node_t node);
+static int hammer_load_node(hammer_node_t node, int isnew);
 
 /*
  * Red-Black tree support for various structures
@@ -861,7 +861,8 @@ hammer_bnew(hammer_mount_t hmp, hammer_off_t buf_offset, int *errorp,
  * additional references, if necessary.
  */
 hammer_node_t
-hammer_get_node(hammer_mount_t hmp, hammer_off_t node_offset, int *errorp)
+hammer_get_node(hammer_mount_t hmp, hammer_off_t node_offset,
+               int isnew, int *errorp)
 {
        hammer_node_t node;
 
@@ -887,7 +888,7 @@ again:
        if (node->ondisk)
                *errorp = 0;
        else
-               *errorp = hammer_load_node(node);
+               *errorp = hammer_load_node(node, isnew);
        if (*errorp) {
                hammer_rel_node(node);
                node = NULL;
@@ -909,7 +910,7 @@ hammer_ref_node(hammer_node_t node)
  * Load a node's on-disk data reference.
  */
 static int
-hammer_load_node(hammer_node_t node)
+hammer_load_node(hammer_node_t node, int isnew)
 {
        hammer_buffer_t buffer;
        int error;
@@ -949,6 +950,10 @@ hammer_load_node(hammer_node_t node)
                if (error == 0) {
                        node->ondisk = (void *)((char *)buffer->ondisk +
                               (node->node_offset & HAMMER_BUFMASK));
+                       if (isnew == 0 &&
+                           hammer_crc_test_btree(node->ondisk) == 0) {
+                               Debugger("CRC FAILED: B-TREE NODE");
+                       }
                }
        }
        --node->loading;
@@ -971,7 +976,7 @@ hammer_ref_node_safe(struct hammer_mount *hmp, struct hammer_node **cache,
                if (node->ondisk)
                        *errorp = 0;
                else
-                       *errorp = hammer_load_node(node);
+                       *errorp = hammer_load_node(node, 0);
                if (*errorp) {
                        hammer_rel_node(node);
                        node = NULL;
@@ -1179,7 +1184,7 @@ hammer_alloc_btree(hammer_transaction_t trans, int *errorp)
                                            sizeof(struct hammer_node_ondisk),
                                            errorp);
        if (*errorp == 0) {
-               node = hammer_get_node(trans->hmp, node_offset, errorp);
+               node = hammer_get_node(trans->hmp, node_offset, 1, errorp);
                hammer_modify_node_noundo(trans, node);
                bzero(node->ondisk, sizeof(*node->ondisk));
                hammer_modify_node_done(node);
@@ -1205,6 +1210,7 @@ hammer_alloc_record(hammer_transaction_t trans,
                    hammer_off_t *rec_offp, u_int16_t rec_type, 
                    struct hammer_buffer **rec_bufferp,
                    int32_t data_len, void **datap,
+                   hammer_off_t *data_offp,
                    struct hammer_buffer **data_bufferp, int *errorp)
 {
        hammer_record_ondisk_t rec;
@@ -1222,6 +1228,8 @@ hammer_alloc_record(hammer_transaction_t trans,
                                           HAMMER_RECORD_SIZE, errorp);
        if (*errorp)
                return(NULL);
+       if (data_offp)
+               *data_offp = 0;
 
        /*
         * Allocate data
@@ -1250,10 +1258,12 @@ hammer_alloc_record(hammer_transaction_t trans,
                        data_offset = hammer_blockmap_alloc(trans,
                                                HAMMER_ZONE_SMALL_DATA_INDEX,
                                                data_len, errorp);
+                       *data_offp = data_offset;
                } else {
                        data_offset = hammer_blockmap_alloc(trans,
                                                HAMMER_ZONE_LARGE_DATA_INDEX,
                                                data_len, errorp);
+                       *data_offp = data_offset;
                }
        } else {
                data_offset = 0;
index 43a3489..69a0a38 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_reblock.c,v 1.10 2008/05/03 20:21:20 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer_reblock.c,v 1.11 2008/05/05 20:34:48 dillon Exp $
  */
 /*
  * HAMMER reblocker - This code frees up fragmented physical space
@@ -122,6 +122,10 @@ retry:
        hammer_done_cursor(&cursor);
        if (error == EDEADLK)
                goto retry;
+       if (error == EINTR) {
+               reblock->head.flags |= HAMMER_IOC_HEAD_INTR;
+               error = 0;
+       }
        return(error);
 }
 
@@ -260,11 +264,10 @@ hammer_reblock_data(struct hammer_ioc_reblock *reblock,
        hammer_blockmap_free(cursor->trans,
                             elm->leaf.data_offset, elm->leaf.data_len);
 
-       hammer_modify_record(cursor->trans, cursor->record_buffer,
-                            &cursor->record->base.data_off,
-                            sizeof(hammer_off_t));
+       hammer_modify_record_field(cursor->trans, cursor->record_buffer,
+                                  cursor->record, base.data_off, 0);
        cursor->record->base.data_off = ndata_offset;
-       hammer_modify_record_done(cursor->record_buffer);
+       hammer_modify_record_done(cursor->record_buffer, cursor->record);
 
        hammer_modify_node(cursor->trans, cursor->node,
                           &elm->leaf.data_offset, sizeof(hammer_off_t));
@@ -300,7 +303,7 @@ hammer_reblock_record(struct hammer_ioc_reblock *reblock,
 
        nrec = hammer_alloc_record(cursor->trans, &nrec_offset,
                                   elm->leaf.base.rec_type, &rec_buffer,
-                                  0, NULL, NULL, &error);
+                                  0, NULL, NULL, NULL, &error);
        if (error)
                goto done;
 
@@ -321,12 +324,11 @@ hammer_reblock_record(struct hammer_ioc_reblock *reblock,
                ndata_offset = 0;
                inline_data = 0;
        }
-
-       hammer_modify_record(cursor->trans, cursor->record_buffer,
-                            &orec->base.base.rec_type,
-                            sizeof(orec->base.base.rec_type));
+       hammer_modify_record_field(cursor->trans, cursor->record_buffer,
+                                  orec, base.base.rec_type, 1);
        orec->base.base.rec_type |= HAMMER_RECTYPE_MOVED;
-       hammer_modify_record_done(cursor->record_buffer);
+       orec->base.signature = HAMMER_RECORD_SIGNATURE_DESTROYED;
+       hammer_modify_record_done(cursor->record_buffer, orec);
 
        hammer_blockmap_free(cursor->trans,
                             elm->leaf.rec_offset, sizeof(*nrec));
index b39f913..e691851 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_subs.c,v 1.16 2008/04/24 21:20:33 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer_subs.c,v 1.17 2008/05/05 20:34:48 dillon Exp $
  */
 /*
  * HAMMER structural locking
@@ -354,3 +354,54 @@ hammer_str_to_tid(const char *str)
        return(tid);
 }
 
+void
+hammer_crc_set_blockmap(hammer_blockmap_t blockmap)
+{
+       blockmap->entry_crc = crc32(blockmap, HAMMER_BLOCKMAP_CRCSIZE);
+}
+
+void
+hammer_crc_set_volume(hammer_volume_ondisk_t ondisk)
+{
+       ondisk->vol_crc = crc32(ondisk, HAMMER_VOL_CRCSIZE1) ^
+                         crc32(&ondisk->vol_crc + 1, HAMMER_VOL_CRCSIZE2);
+}
+
+int
+hammer_crc_test_blockmap(hammer_blockmap_t blockmap)
+{
+       hammer_crc_t crc;
+
+       crc = crc32(blockmap, HAMMER_BLOCKMAP_CRCSIZE);
+       return (blockmap->entry_crc == crc);
+}
+
+int
+hammer_crc_test_volume(hammer_volume_ondisk_t ondisk)
+{
+       hammer_crc_t crc;
+
+       crc = crc32(ondisk, HAMMER_VOL_CRCSIZE1) ^
+             crc32(&ondisk->vol_crc + 1, HAMMER_VOL_CRCSIZE2);
+       return (ondisk->vol_crc == crc);
+}
+
+int
+hammer_crc_test_record(hammer_record_ondisk_t ondisk)
+{
+       hammer_crc_t crc;
+
+       crc = crc32(&ondisk->base.rec_crc + 1, HAMMER_RECORD_CRCSIZE);
+       return (ondisk->base.rec_crc == crc &&
+               ondisk->base.signature == HAMMER_RECORD_SIGNATURE_GOOD);
+}
+
+int
+hammer_crc_test_btree(hammer_node_ondisk_t ondisk)
+{
+       hammer_crc_t crc;
+
+       crc = crc32(&ondisk->crc + 1, HAMMER_BTREE_CRCSIZE);
+       return (ondisk->crc == crc);
+}
+
index b12bd89..b3aff4a 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_undo.c,v 1.12 2008/05/04 19:57:42 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer_undo.c,v 1.13 2008/05/05 20:34:48 dillon Exp $
  */
 
 /*
@@ -160,6 +160,7 @@ again:
                undo->head.hdr_signature = HAMMER_HEAD_SIGNATURE;
                undo->head.hdr_type = HAMMER_HEAD_TYPE_PAD;
                undo->head.hdr_size = bytes;
+               /* NO CRC */
                undomap->next_offset += bytes;
                hammer_modify_buffer_done(buffer);
                goto again;
@@ -184,7 +185,9 @@ again:
        tail->tail_type = HAMMER_HEAD_TYPE_UNDO;
        tail->tail_size = bytes;
 
-       undo->head.hdr_crc = crc32(undo, bytes);
+       KKASSERT(bytes >= sizeof(undo->head));
+       undo->head.hdr_crc = crc32(undo, HAMMER_FIFO_HEAD_CRCOFF) ^
+                            crc32(&undo->head + 1, bytes - sizeof(undo->head));
        undomap->next_offset += bytes;
 
        hammer_modify_buffer_done(buffer);
index 807ca16..2cf0ce9 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.47 2008/05/04 09:06:45 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer_vnops.c,v 1.48 2008/05/05 20:34:48 dillon Exp $
  */
 
 #include <sys/param.h>
@@ -1543,6 +1543,7 @@ hammer_vop_nsymlink(struct vop_nsymlink_args *ap)
                record->rec.base.base.key = HAMMER_FIXKEY_SYMLINK;
                record->rec.base.base.rec_type = HAMMER_RECTYPE_FIX;
                record->rec.base.data_len = bytes;
+               record->rec.base.signature = HAMMER_RECORD_SIGNATURE_GOOD;
                record->data = (void *)ap->a_target;
                /* will be reallocated by routine below */
                error = hammer_ip_add_record(&trans, record);