xref: /dragonfly/sys/vfs/hammer/hammer_crc.h (revision 9348a738)
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