1 /* 2 * Copyright (c) 2007-2016 The DragonFly Project. All rights reserved. 3 * 4 * This code is derived from software contributed to The DragonFly Project 5 * by Matthew Dillon <dillon@backplane.com> 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * 3. Neither the name of The DragonFly Project nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific, prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 35 #ifndef VFS_HAMMER_CRC_H_ 36 #define VFS_HAMMER_CRC_H_ 37 38 #include "hammer_disk.h" 39 #include "hammer_ioctl.h" 40 41 #ifndef _KERNEL 42 /* 43 * These are only for userspace. 44 * Userspace can't include sys/sys/systm.h. 45 */ 46 uint32_t crc32(const void *buf, size_t size); 47 uint32_t crc32_ext(const void *buf, size_t size, uint32_t ocrc); 48 #endif 49 50 static __inline hammer_crc_t 51 hammer_crc_get_blockmap(hammer_blockmap_t blockmap) 52 { 53 return(crc32(blockmap, HAMMER_BLOCKMAP_CRCSIZE)); 54 } 55 56 static __inline void 57 hammer_crc_set_blockmap(hammer_blockmap_t blockmap) 58 { 59 blockmap->entry_crc = hammer_crc_get_blockmap(blockmap); 60 } 61 62 static __inline int 63 hammer_crc_test_blockmap(hammer_blockmap_t blockmap) 64 { 65 return(blockmap->entry_crc == hammer_crc_get_blockmap(blockmap)); 66 } 67 68 static __inline hammer_crc_t 69 hammer_crc_get_layer1(hammer_blockmap_layer1_t layer1) 70 { 71 return(crc32(layer1, HAMMER_LAYER1_CRCSIZE)); 72 } 73 74 static __inline void 75 hammer_crc_set_layer1(hammer_blockmap_layer1_t layer1) 76 { 77 layer1->layer1_crc = hammer_crc_get_layer1(layer1); 78 } 79 80 static __inline int 81 hammer_crc_test_layer1(hammer_blockmap_layer1_t layer1) 82 { 83 return(layer1->layer1_crc == hammer_crc_get_layer1(layer1)); 84 } 85 86 static __inline hammer_crc_t 87 hammer_crc_get_layer2(hammer_blockmap_layer2_t layer2) 88 { 89 return(crc32(layer2, HAMMER_LAYER2_CRCSIZE)); 90 } 91 92 static __inline void 93 hammer_crc_set_layer2(hammer_blockmap_layer2_t layer2) 94 { 95 layer2->entry_crc = hammer_crc_get_layer2(layer2); 96 } 97 98 static __inline int 99 hammer_crc_test_layer2(hammer_blockmap_layer2_t layer2) 100 { 101 return(layer2->entry_crc == hammer_crc_get_layer2(layer2)); 102 } 103 104 static __inline hammer_crc_t 105 hammer_crc_get_volume(hammer_volume_ondisk_t ondisk) 106 { 107 return(crc32(ondisk, HAMMER_VOL_CRCSIZE1) ^ 108 crc32(&ondisk->vol_crc + 1, HAMMER_VOL_CRCSIZE2)); 109 } 110 111 static __inline void 112 hammer_crc_set_volume(hammer_volume_ondisk_t ondisk) 113 { 114 ondisk->vol_crc = hammer_crc_get_volume(ondisk); 115 } 116 117 static __inline int 118 hammer_crc_test_volume(hammer_volume_ondisk_t ondisk) 119 { 120 return(ondisk->vol_crc == hammer_crc_get_volume(ondisk)); 121 } 122 123 static __inline hammer_crc_t 124 hammer_crc_get_fifo_head(hammer_fifo_head_t head, int bytes) 125 { 126 return(crc32(head, HAMMER_FIFO_HEAD_CRCOFF) ^ 127 crc32(head + 1, bytes - sizeof(*head))); 128 } 129 130 static __inline void 131 hammer_crc_set_fifo_head(hammer_fifo_head_t head, int bytes) 132 { 133 head->hdr_crc = hammer_crc_get_fifo_head(head, bytes); 134 } 135 136 static __inline int 137 hammer_crc_test_fifo_head(hammer_fifo_head_t head, int bytes) 138 { 139 return(head->hdr_crc == hammer_crc_get_fifo_head(head, bytes)); 140 } 141 142 static __inline hammer_crc_t 143 hammer_crc_get_btree(hammer_node_ondisk_t node) 144 { 145 return(crc32(&node->crc + 1, HAMMER_BTREE_CRCSIZE)); 146 } 147 148 static __inline void 149 hammer_crc_set_btree(hammer_node_ondisk_t node) 150 { 151 node->crc = hammer_crc_get_btree(node); 152 } 153 154 static __inline int 155 hammer_crc_test_btree(hammer_node_ondisk_t node) 156 { 157 return(node->crc == hammer_crc_get_btree(node)); 158 } 159 160 /* 161 * Get the leaf->data_crc field. Deal with any special cases given 162 * a generic B-Tree leaf element and its data. 163 * 164 * NOTE: Inode-data: the atime and mtime fields are not CRCd, 165 * allowing them to be updated in-place. 166 */ 167 static __inline hammer_crc_t 168 hammer_crc_get_leaf(void *data, hammer_btree_leaf_elm_t leaf) 169 { 170 hammer_crc_t crc; 171 172 if (leaf->data_len == 0) 173 return(0); 174 175 switch(leaf->base.rec_type) { 176 case HAMMER_RECTYPE_INODE: 177 if (leaf->data_len != sizeof(struct hammer_inode_data)) 178 return(0); /* This shouldn't happen */ 179 crc = crc32(data, HAMMER_INODE_CRCSIZE); 180 break; 181 default: 182 crc = crc32(data, leaf->data_len); 183 break; 184 } 185 return(crc); 186 } 187 188 static __inline void 189 hammer_crc_set_leaf(void *data, hammer_btree_leaf_elm_t leaf) 190 { 191 #ifdef _KERNEL 192 #ifdef INVARIANTS 193 if (leaf->data_len && leaf->base.rec_type == HAMMER_RECTYPE_INODE) 194 KKASSERT(leaf->data_len == sizeof(struct hammer_inode_data)); 195 #endif 196 #endif 197 leaf->data_crc = hammer_crc_get_leaf(data, leaf); 198 } 199 200 static __inline int 201 hammer_crc_test_leaf(void *data, hammer_btree_leaf_elm_t leaf) 202 { 203 return(leaf->data_crc == hammer_crc_get_leaf(data, leaf)); 204 } 205 206 static __inline hammer_crc_t 207 hammer_crc_get_mrec_head(hammer_ioc_mrecord_head_t head, int bytes) 208 { 209 return(crc32(&head->rec_size, bytes - HAMMER_MREC_CRCOFF)); 210 } 211 212 static __inline void 213 hammer_crc_set_mrec_head(hammer_ioc_mrecord_head_t head, int bytes) 214 { 215 head->rec_crc = hammer_crc_get_mrec_head(head, bytes); 216 } 217 218 static __inline int 219 hammer_crc_test_mrec_head(hammer_ioc_mrecord_head_t head, int bytes) 220 { 221 return(head->rec_crc == hammer_crc_get_mrec_head(head, bytes)); 222 } 223 224 #endif /* !VFS_HAMMER_CRC_H_ */ 225