kernel - Incidental mplock removal - NTP support
[dragonfly.git] / sys / vfs / hammer / hammer_crc.h
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_ */