From 196198822a4f1c66629fc5ad6a526c3b2fa7657d Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Mon, 5 May 2008 20:34:48 +0000 Subject: [PATCH] HAMMER 41/Many: Implement CRC checking (WARNING: On-media structures changed) * 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. --- sys/vfs/hammer/hammer.h | 66 +++++++++++++++++++++++-- sys/vfs/hammer/hammer_blockmap.c | 53 ++++++++++++++++++-- sys/vfs/hammer/hammer_btree.c | 21 ++++++-- sys/vfs/hammer/hammer_btree.h | 17 ++++--- sys/vfs/hammer/hammer_cursor.c | 9 ++-- sys/vfs/hammer/hammer_disk.h | 45 +++++++++++++---- sys/vfs/hammer/hammer_flusher.c | 10 +++- sys/vfs/hammer/hammer_inode.c | 24 ++++++--- sys/vfs/hammer/hammer_ioctl.c | 84 +++++++++++++++++++------------- sys/vfs/hammer/hammer_ioctl.h | 30 +++++++++--- sys/vfs/hammer/hammer_object.c | 63 ++++++++++++++++++------ sys/vfs/hammer/hammer_ondisk.c | 24 ++++++--- sys/vfs/hammer/hammer_reblock.c | 24 ++++----- sys/vfs/hammer/hammer_subs.c | 53 +++++++++++++++++++- sys/vfs/hammer/hammer_undo.c | 7 ++- sys/vfs/hammer/hammer_vnops.c | 3 +- 16 files changed, 411 insertions(+), 122 deletions(-) diff --git a/sys/vfs/hammer/hammer.h b/sys/vfs/hammer/hammer.h index b3504ff5d2..5d01fe3633 100644 --- a/sys/vfs/hammer/hammer.h +++ b/sys/vfs/hammer/hammer.h @@ -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) diff --git a/sys/vfs/hammer/hammer_blockmap.c b/sys/vfs/hammer/hammer_blockmap.c index a8769d17e0..7df1838750 100644 --- a/sys/vfs/hammer/hammer_blockmap.c +++ b/sys/vfs/hammer/hammer_blockmap.c @@ -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); diff --git a/sys/vfs/hammer/hammer_btree.c b/sys/vfs/hammer/hammer_btree.c index 4918b44e59..124214d542 100644 --- a/sys/vfs/hammer/hammer_btree.c +++ b/sys/vfs/hammer/hammer_btree.c @@ -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; diff --git a/sys/vfs/hammer/hammer_btree.h b/sys/vfs/hammer/hammer_btree.h index 5dc0e91578..f30b6fcb64 100644 --- a/sys/vfs/hammer/hammer_btree.h +++ b/sys/vfs/hammer/hammer_btree.h @@ -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; diff --git a/sys/vfs/hammer/hammer_cursor.c b/sys/vfs/hammer/hammer_cursor.c index 0edcca81e9..210c6a5ebc 100644 --- a/sys/vfs/hammer/hammer_cursor.c +++ b/sys/vfs/hammer/hammer_cursor.c @@ -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) diff --git a/sys/vfs/hammer/hammer_disk.h b/sys/vfs/hammer/hammer_disk.h index 20cc923bfc..6120d694bd 100644 --- a/sys/vfs/hammer/hammer_disk.h +++ b/sys/vfs/hammer/hammer_disk.h @@ -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 * diff --git a/sys/vfs/hammer/hammer_flusher.c b/sys/vfs/hammer/hammer_flusher.c index 6f8a666e86..5bd671cb0b 100644 --- a/sys/vfs/hammer/hammer_flusher.c +++ b/sys/vfs/hammer/hammer_flusher.c @@ -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 diff --git a/sys/vfs/hammer/hammer_inode.c b/sys/vfs/hammer/hammer_inode.c index 986d03bd33..3bb0261b5c 100644 --- a/sys/vfs/hammer/hammer_inode.c +++ b/sys/vfs/hammer/hammer_inode.c @@ -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]); diff --git a/sys/vfs/hammer/hammer_ioctl.c b/sys/vfs/hammer/hammer_ioctl.c index 54ee1f5e2f..595f0fd161 100644 --- a/sys/vfs/hammer/hammer_ioctl.c +++ b/sys/vfs/hammer/hammer_ioctl.c @@ -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; diff --git a/sys/vfs/hammer/hammer_ioctl.h b/sys/vfs/hammer/hammer_ioctl.h index 238e2536e9..2254cc9791 100644 --- a/sys/vfs/hammer/hammer_ioctl.h +++ b/sys/vfs/hammer/hammer_ioctl.h @@ -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 @@ -44,6 +44,19 @@ #include #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) diff --git a/sys/vfs/hammer/hammer_object.c b/sys/vfs/hammer/hammer_object.c index f87672a7e5..c94570da58 100644 --- a/sys/vfs/hammer/hammer_object.c +++ b/sys/vfs/hammer/hammer_object.c @@ -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) { diff --git a/sys/vfs/hammer/hammer_ondisk.c b/sys/vfs/hammer/hammer_ondisk.c index efcbfe5baa..4dccece1e5 100644 --- a/sys/vfs/hammer/hammer_ondisk.c +++ b/sys/vfs/hammer/hammer_ondisk.c @@ -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; diff --git a/sys/vfs/hammer/hammer_reblock.c b/sys/vfs/hammer/hammer_reblock.c index 43a34893ae..69a0a38bfc 100644 --- a/sys/vfs/hammer/hammer_reblock.c +++ b/sys/vfs/hammer/hammer_reblock.c @@ -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)); diff --git a/sys/vfs/hammer/hammer_subs.c b/sys/vfs/hammer/hammer_subs.c index b39f913531..e6918515f5 100644 --- a/sys/vfs/hammer/hammer_subs.c +++ b/sys/vfs/hammer/hammer_subs.c @@ -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); +} + diff --git a/sys/vfs/hammer/hammer_undo.c b/sys/vfs/hammer/hammer_undo.c index b12bd8997d..b3aff4af43 100644 --- a/sys/vfs/hammer/hammer_undo.c +++ b/sys/vfs/hammer/hammer_undo.c @@ -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); diff --git a/sys/vfs/hammer/hammer_vnops.c b/sys/vfs/hammer/hammer_vnops.c index 807ca16889..2cf0ce9ae7 100644 --- a/sys/vfs/hammer/hammer_vnops.c +++ b/sys/vfs/hammer/hammer_vnops.c @@ -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 @@ -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); -- 2.41.0