Commit | Line | Data |
---|---|---|
70ad1ba7 JB |
1 | /* -*- mode: c; c-basic-offset: 8; -*- |
2 | * vim: noexpandtab sw=8 ts=8 sts=0: | |
3 | * | |
4 | * blockcheck.c | |
5 | * | |
6 | * Checksum and ECC codes for the OCFS2 userspace library. | |
7 | * | |
8 | * Copyright (C) 2006, 2008 Oracle. All rights reserved. | |
9 | * | |
10 | * This program is free software; you can redistribute it and/or | |
11 | * modify it under the terms of the GNU General Public | |
12 | * License, version 2, as published by the Free Software Foundation. | |
13 | * | |
14 | * This program is distributed in the hope that it will be useful, | |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
17 | * General Public License for more details. | |
18 | */ | |
19 | ||
20 | #include <linux/kernel.h> | |
21 | #include <linux/types.h> | |
22 | #include <linux/crc32.h> | |
23 | #include <linux/buffer_head.h> | |
24 | #include <linux/bitops.h> | |
73be192b JB |
25 | #include <linux/debugfs.h> |
26 | #include <linux/module.h> | |
27 | #include <linux/fs.h> | |
70ad1ba7 JB |
28 | #include <asm/byteorder.h> |
29 | ||
d6b32bbb JB |
30 | #include <cluster/masklog.h> |
31 | ||
70ad1ba7 JB |
32 | #include "ocfs2.h" |
33 | ||
34 | #include "blockcheck.h" | |
35 | ||
36 | ||
70ad1ba7 JB |
37 | /* |
38 | * We use the following conventions: | |
39 | * | |
40 | * d = # data bits | |
41 | * p = # parity bits | |
42 | * c = # total code bits (d + p) | |
43 | */ | |
70ad1ba7 | 44 | |
7bb458a5 | 45 | |
70ad1ba7 JB |
46 | /* |
47 | * Calculate the bit offset in the hamming code buffer based on the bit's | |
48 | * offset in the data buffer. Since the hamming code reserves all | |
49 | * power-of-two bits for parity, the data bit number and the code bit | |
bf48aabb | 50 | * number are offset by all the parity bits beforehand. |
70ad1ba7 JB |
51 | * |
52 | * Recall that bit numbers in hamming code are 1-based. This function | |
53 | * takes the 0-based data bit from the caller. | |
54 | * | |
55 | * An example. Take bit 1 of the data buffer. 1 is a power of two (2^0), | |
56 | * so it's a parity bit. 2 is a power of two (2^1), so it's a parity bit. | |
57 | * 3 is not a power of two. So bit 1 of the data buffer ends up as bit 3 | |
58 | * in the code buffer. | |
58896c4d JB |
59 | * |
60 | * The caller can pass in *p if it wants to keep track of the most recent | |
61 | * number of parity bits added. This allows the function to start the | |
62 | * calculation at the last place. | |
70ad1ba7 | 63 | */ |
58896c4d | 64 | static unsigned int calc_code_bit(unsigned int i, unsigned int *p_cache) |
70ad1ba7 | 65 | { |
58896c4d | 66 | unsigned int b, p = 0; |
70ad1ba7 JB |
67 | |
68 | /* | |
69 | * Data bits are 0-based, but we're talking code bits, which | |
70 | * are 1-based. | |
71 | */ | |
72 | b = i + 1; | |
73 | ||
58896c4d JB |
74 | /* Use the cache if it is there */ |
75 | if (p_cache) | |
76 | p = *p_cache; | |
7bb458a5 JB |
77 | b += p; |
78 | ||
70ad1ba7 JB |
79 | /* |
80 | * For every power of two below our bit number, bump our bit. | |
81 | * | |
58896c4d | 82 | * We compare with (b + 1) because we have to compare with what b |
70ad1ba7 | 83 | * would be _if_ it were bumped up by the parity bit. Capice? |
7bb458a5 | 84 | * |
58896c4d | 85 | * p is set above. |
70ad1ba7 | 86 | */ |
58896c4d | 87 | for (; (1 << p) < (b + 1); p++) |
70ad1ba7 JB |
88 | b++; |
89 | ||
58896c4d JB |
90 | if (p_cache) |
91 | *p_cache = p; | |
92 | ||
70ad1ba7 JB |
93 | return b; |
94 | } | |
95 | ||
96 | /* | |
97 | * This is the low level encoder function. It can be called across | |
98 | * multiple hunks just like the crc32 code. 'd' is the number of bits | |
99 | * _in_this_hunk_. nr is the bit offset of this hunk. So, if you had | |
100 | * two 512B buffers, you would do it like so: | |
101 | * | |
102 | * parity = ocfs2_hamming_encode(0, buf1, 512 * 8, 0); | |
103 | * parity = ocfs2_hamming_encode(parity, buf2, 512 * 8, 512 * 8); | |
104 | * | |
105 | * If you just have one buffer, use ocfs2_hamming_encode_block(). | |
106 | */ | |
107 | u32 ocfs2_hamming_encode(u32 parity, void *data, unsigned int d, unsigned int nr) | |
108 | { | |
58896c4d | 109 | unsigned int i, b, p = 0; |
70ad1ba7 | 110 | |
e798b3f8 | 111 | BUG_ON(!d); |
70ad1ba7 JB |
112 | |
113 | /* | |
114 | * b is the hamming code bit number. Hamming code specifies a | |
115 | * 1-based array, but C uses 0-based. So 'i' is for C, and 'b' is | |
116 | * for the algorithm. | |
117 | * | |
118 | * The i++ in the for loop is so that the start offset passed | |
119 | * to ocfs2_find_next_bit_set() is one greater than the previously | |
120 | * found bit. | |
121 | */ | |
122 | for (i = 0; (i = ocfs2_find_next_bit(data, d, i)) < d; i++) | |
123 | { | |
124 | /* | |
125 | * i is the offset in this hunk, nr + i is the total bit | |
126 | * offset. | |
127 | */ | |
58896c4d | 128 | b = calc_code_bit(nr + i, &p); |
70ad1ba7 | 129 | |
e798b3f8 JB |
130 | /* |
131 | * Data bits in the resultant code are checked by | |
132 | * parity bits that are part of the bit number | |
133 | * representation. Huh? | |
134 | * | |
135 | * <wikipedia href="http://en.wikipedia.org/wiki/Hamming_code"> | |
136 | * In other words, the parity bit at position 2^k | |
137 | * checks bits in positions having bit k set in | |
138 | * their binary representation. Conversely, for | |
139 | * instance, bit 13, i.e. 1101(2), is checked by | |
140 | * bits 1000(2) = 8, 0100(2)=4 and 0001(2) = 1. | |
141 | * </wikipedia> | |
142 | * | |
143 | * Note that 'k' is the _code_ bit number. 'b' in | |
144 | * our loop. | |
145 | */ | |
146 | parity ^= b; | |
70ad1ba7 JB |
147 | } |
148 | ||
149 | /* While the data buffer was treated as little endian, the | |
150 | * return value is in host endian. */ | |
151 | return parity; | |
152 | } | |
153 | ||
154 | u32 ocfs2_hamming_encode_block(void *data, unsigned int blocksize) | |
155 | { | |
156 | return ocfs2_hamming_encode(0, data, blocksize * 8, 0); | |
157 | } | |
158 | ||
159 | /* | |
160 | * Like ocfs2_hamming_encode(), this can handle hunks. nr is the bit | |
161 | * offset of the current hunk. If bit to be fixed is not part of the | |
162 | * current hunk, this does nothing. | |
163 | * | |
164 | * If you only have one hunk, use ocfs2_hamming_fix_block(). | |
165 | */ | |
166 | void ocfs2_hamming_fix(void *data, unsigned int d, unsigned int nr, | |
167 | unsigned int fix) | |
168 | { | |
70ad1ba7 JB |
169 | unsigned int i, b; |
170 | ||
e798b3f8 | 171 | BUG_ON(!d); |
70ad1ba7 JB |
172 | |
173 | /* | |
174 | * If the bit to fix has an hweight of 1, it's a parity bit. One | |
175 | * busted parity bit is its own error. Nothing to do here. | |
176 | */ | |
177 | if (hweight32(fix) == 1) | |
178 | return; | |
179 | ||
180 | /* | |
181 | * nr + d is the bit right past the data hunk we're looking at. | |
182 | * If fix after that, nothing to do | |
183 | */ | |
58896c4d | 184 | if (fix >= calc_code_bit(nr + d, NULL)) |
70ad1ba7 JB |
185 | return; |
186 | ||
187 | /* | |
188 | * nr is the offset in the data hunk we're starting at. Let's | |
189 | * start b at the offset in the code buffer. See hamming_encode() | |
190 | * for a more detailed description of 'b'. | |
191 | */ | |
58896c4d | 192 | b = calc_code_bit(nr, NULL); |
70ad1ba7 JB |
193 | /* If the fix is before this hunk, nothing to do */ |
194 | if (fix < b) | |
195 | return; | |
196 | ||
197 | for (i = 0; i < d; i++, b++) | |
198 | { | |
199 | /* Skip past parity bits */ | |
200 | while (hweight32(b) == 1) | |
201 | b++; | |
202 | ||
203 | /* | |
204 | * i is the offset in this data hunk. | |
205 | * nr + i is the offset in the total data buffer. | |
206 | * b is the offset in the total code buffer. | |
207 | * | |
208 | * Thus, when b == fix, bit i in the current hunk needs | |
209 | * fixing. | |
210 | */ | |
211 | if (b == fix) | |
212 | { | |
213 | if (ocfs2_test_bit(i, data)) | |
214 | ocfs2_clear_bit(i, data); | |
215 | else | |
216 | ocfs2_set_bit(i, data); | |
217 | break; | |
218 | } | |
219 | } | |
220 | } | |
221 | ||
222 | void ocfs2_hamming_fix_block(void *data, unsigned int blocksize, | |
223 | unsigned int fix) | |
224 | { | |
225 | ocfs2_hamming_fix(data, blocksize * 8, 0, fix); | |
226 | } | |
227 | ||
73be192b JB |
228 | |
229 | /* | |
230 | * Debugfs handling. | |
231 | */ | |
232 | ||
233 | #ifdef CONFIG_DEBUG_FS | |
234 | ||
235 | static int blockcheck_u64_get(void *data, u64 *val) | |
236 | { | |
237 | *val = *(u64 *)data; | |
238 | return 0; | |
239 | } | |
240 | DEFINE_SIMPLE_ATTRIBUTE(blockcheck_fops, blockcheck_u64_get, NULL, "%llu\n"); | |
241 | ||
242 | static struct dentry *blockcheck_debugfs_create(const char *name, | |
243 | struct dentry *parent, | |
244 | u64 *value) | |
245 | { | |
246 | return debugfs_create_file(name, S_IFREG | S_IRUSR, parent, value, | |
247 | &blockcheck_fops); | |
248 | } | |
249 | ||
250 | static void ocfs2_blockcheck_debug_remove(struct ocfs2_blockcheck_stats *stats) | |
251 | { | |
252 | if (stats) { | |
253 | debugfs_remove(stats->b_debug_check); | |
254 | stats->b_debug_check = NULL; | |
255 | debugfs_remove(stats->b_debug_failure); | |
256 | stats->b_debug_failure = NULL; | |
257 | debugfs_remove(stats->b_debug_recover); | |
258 | stats->b_debug_recover = NULL; | |
259 | debugfs_remove(stats->b_debug_dir); | |
260 | stats->b_debug_dir = NULL; | |
261 | } | |
262 | } | |
263 | ||
264 | static int ocfs2_blockcheck_debug_install(struct ocfs2_blockcheck_stats *stats, | |
265 | struct dentry *parent) | |
266 | { | |
267 | int rc = -EINVAL; | |
268 | ||
269 | if (!stats) | |
270 | goto out; | |
271 | ||
272 | stats->b_debug_dir = debugfs_create_dir("blockcheck", parent); | |
273 | if (!stats->b_debug_dir) | |
274 | goto out; | |
275 | ||
276 | stats->b_debug_check = | |
277 | blockcheck_debugfs_create("blocks_checked", | |
278 | stats->b_debug_dir, | |
279 | &stats->b_check_count); | |
280 | ||
281 | stats->b_debug_failure = | |
282 | blockcheck_debugfs_create("checksums_failed", | |
283 | stats->b_debug_dir, | |
284 | &stats->b_failure_count); | |
285 | ||
286 | stats->b_debug_recover = | |
287 | blockcheck_debugfs_create("ecc_recoveries", | |
288 | stats->b_debug_dir, | |
289 | &stats->b_recover_count); | |
290 | if (stats->b_debug_check && stats->b_debug_failure && | |
291 | stats->b_debug_recover) | |
292 | rc = 0; | |
293 | ||
294 | out: | |
295 | if (rc) | |
296 | ocfs2_blockcheck_debug_remove(stats); | |
297 | return rc; | |
298 | } | |
299 | #else | |
300 | static inline int ocfs2_blockcheck_debug_install(struct ocfs2_blockcheck_stats *stats, | |
301 | struct dentry *parent) | |
302 | { | |
303 | return 0; | |
304 | } | |
305 | ||
306 | static inline void ocfs2_blockcheck_debug_remove(struct ocfs2_blockcheck_stats *stats) | |
307 | { | |
308 | } | |
309 | #endif /* CONFIG_DEBUG_FS */ | |
310 | ||
311 | /* Always-called wrappers for starting and stopping the debugfs files */ | |
312 | int ocfs2_blockcheck_stats_debugfs_install(struct ocfs2_blockcheck_stats *stats, | |
313 | struct dentry *parent) | |
314 | { | |
315 | return ocfs2_blockcheck_debug_install(stats, parent); | |
316 | } | |
317 | ||
318 | void ocfs2_blockcheck_stats_debugfs_remove(struct ocfs2_blockcheck_stats *stats) | |
319 | { | |
320 | ocfs2_blockcheck_debug_remove(stats); | |
321 | } | |
322 | ||
323 | static void ocfs2_blockcheck_inc_check(struct ocfs2_blockcheck_stats *stats) | |
324 | { | |
325 | u64 new_count; | |
326 | ||
327 | if (!stats) | |
328 | return; | |
329 | ||
330 | spin_lock(&stats->b_lock); | |
331 | stats->b_check_count++; | |
332 | new_count = stats->b_check_count; | |
333 | spin_unlock(&stats->b_lock); | |
334 | ||
335 | if (!new_count) | |
336 | mlog(ML_NOTICE, "Block check count has wrapped\n"); | |
337 | } | |
338 | ||
339 | static void ocfs2_blockcheck_inc_failure(struct ocfs2_blockcheck_stats *stats) | |
340 | { | |
341 | u64 new_count; | |
342 | ||
343 | if (!stats) | |
344 | return; | |
345 | ||
346 | spin_lock(&stats->b_lock); | |
347 | stats->b_failure_count++; | |
348 | new_count = stats->b_failure_count; | |
349 | spin_unlock(&stats->b_lock); | |
350 | ||
351 | if (!new_count) | |
352 | mlog(ML_NOTICE, "Checksum failure count has wrapped\n"); | |
353 | } | |
354 | ||
355 | static void ocfs2_blockcheck_inc_recover(struct ocfs2_blockcheck_stats *stats) | |
356 | { | |
357 | u64 new_count; | |
358 | ||
359 | if (!stats) | |
360 | return; | |
361 | ||
362 | spin_lock(&stats->b_lock); | |
363 | stats->b_recover_count++; | |
364 | new_count = stats->b_recover_count; | |
365 | spin_unlock(&stats->b_lock); | |
366 | ||
367 | if (!new_count) | |
368 | mlog(ML_NOTICE, "ECC recovery count has wrapped\n"); | |
369 | } | |
370 | ||
371 | ||
372 | ||
373 | /* | |
374 | * These are the low-level APIs for using the ocfs2_block_check structure. | |
375 | */ | |
376 | ||
70ad1ba7 JB |
377 | /* |
378 | * This function generates check information for a block. | |
379 | * data is the block to be checked. bc is a pointer to the | |
380 | * ocfs2_block_check structure describing the crc32 and the ecc. | |
381 | * | |
382 | * bc should be a pointer inside data, as the function will | |
383 | * take care of zeroing it before calculating the check information. If | |
384 | * bc does not point inside data, the caller must make sure any inline | |
385 | * ocfs2_block_check structures are zeroed. | |
386 | * | |
387 | * The data buffer must be in on-disk endian (little endian for ocfs2). | |
388 | * bc will be filled with little-endian values and will be ready to go to | |
389 | * disk. | |
390 | */ | |
391 | void ocfs2_block_check_compute(void *data, size_t blocksize, | |
392 | struct ocfs2_block_check *bc) | |
393 | { | |
394 | u32 crc; | |
395 | u32 ecc; | |
396 | ||
397 | memset(bc, 0, sizeof(struct ocfs2_block_check)); | |
398 | ||
399 | crc = crc32_le(~0, data, blocksize); | |
400 | ecc = ocfs2_hamming_encode_block(data, blocksize); | |
401 | ||
402 | /* | |
403 | * No ecc'd ocfs2 structure is larger than 4K, so ecc will be no | |
404 | * larger than 16 bits. | |
405 | */ | |
4be929be | 406 | BUG_ON(ecc > USHRT_MAX); |
70ad1ba7 JB |
407 | |
408 | bc->bc_crc32e = cpu_to_le32(crc); | |
409 | bc->bc_ecc = cpu_to_le16((u16)ecc); | |
410 | } | |
411 | ||
412 | /* | |
413 | * This function validates existing check information. Like _compute, | |
414 | * the function will take care of zeroing bc before calculating check codes. | |
415 | * If bc is not a pointer inside data, the caller must have zeroed any | |
416 | * inline ocfs2_block_check structures. | |
417 | * | |
418 | * Again, the data passed in should be the on-disk endian. | |
419 | */ | |
420 | int ocfs2_block_check_validate(void *data, size_t blocksize, | |
73be192b JB |
421 | struct ocfs2_block_check *bc, |
422 | struct ocfs2_blockcheck_stats *stats) | |
70ad1ba7 JB |
423 | { |
424 | int rc = 0; | |
1db5df98 AV |
425 | u32 bc_crc32e; |
426 | u16 bc_ecc; | |
70ad1ba7 JB |
427 | u32 crc, ecc; |
428 | ||
73be192b JB |
429 | ocfs2_blockcheck_inc_check(stats); |
430 | ||
1db5df98 AV |
431 | bc_crc32e = le32_to_cpu(bc->bc_crc32e); |
432 | bc_ecc = le16_to_cpu(bc->bc_ecc); | |
70ad1ba7 JB |
433 | |
434 | memset(bc, 0, sizeof(struct ocfs2_block_check)); | |
435 | ||
436 | /* Fast path - if the crc32 validates, we're good to go */ | |
437 | crc = crc32_le(~0, data, blocksize); | |
1db5df98 | 438 | if (crc == bc_crc32e) |
70ad1ba7 JB |
439 | goto out; |
440 | ||
73be192b | 441 | ocfs2_blockcheck_inc_failure(stats); |
d6b32bbb | 442 | mlog(ML_ERROR, |
dc696ace | 443 | "CRC32 failed: stored: 0x%x, computed 0x%x. Applying ECC.\n", |
1db5df98 | 444 | (unsigned int)bc_crc32e, (unsigned int)crc); |
d6b32bbb | 445 | |
70ad1ba7 JB |
446 | /* Ok, try ECC fixups */ |
447 | ecc = ocfs2_hamming_encode_block(data, blocksize); | |
1db5df98 | 448 | ocfs2_hamming_fix_block(data, blocksize, ecc ^ bc_ecc); |
70ad1ba7 JB |
449 | |
450 | /* And check the crc32 again */ | |
451 | crc = crc32_le(~0, data, blocksize); | |
1db5df98 | 452 | if (crc == bc_crc32e) { |
73be192b | 453 | ocfs2_blockcheck_inc_recover(stats); |
70ad1ba7 | 454 | goto out; |
73be192b | 455 | } |
70ad1ba7 | 456 | |
dc696ace | 457 | mlog(ML_ERROR, "Fixed CRC32 failed: stored: 0x%x, computed 0x%x\n", |
1db5df98 | 458 | (unsigned int)bc_crc32e, (unsigned int)crc); |
d6b32bbb | 459 | |
70ad1ba7 JB |
460 | rc = -EIO; |
461 | ||
462 | out: | |
1db5df98 AV |
463 | bc->bc_crc32e = cpu_to_le32(bc_crc32e); |
464 | bc->bc_ecc = cpu_to_le16(bc_ecc); | |
70ad1ba7 JB |
465 | |
466 | return rc; | |
467 | } | |
468 | ||
469 | /* | |
470 | * This function generates check information for a list of buffer_heads. | |
471 | * bhs is the blocks to be checked. bc is a pointer to the | |
472 | * ocfs2_block_check structure describing the crc32 and the ecc. | |
473 | * | |
474 | * bc should be a pointer inside data, as the function will | |
475 | * take care of zeroing it before calculating the check information. If | |
476 | * bc does not point inside data, the caller must make sure any inline | |
477 | * ocfs2_block_check structures are zeroed. | |
478 | * | |
479 | * The data buffer must be in on-disk endian (little endian for ocfs2). | |
480 | * bc will be filled with little-endian values and will be ready to go to | |
481 | * disk. | |
482 | */ | |
483 | void ocfs2_block_check_compute_bhs(struct buffer_head **bhs, int nr, | |
484 | struct ocfs2_block_check *bc) | |
485 | { | |
486 | int i; | |
487 | u32 crc, ecc; | |
488 | ||
489 | BUG_ON(nr < 0); | |
490 | ||
491 | if (!nr) | |
492 | return; | |
493 | ||
494 | memset(bc, 0, sizeof(struct ocfs2_block_check)); | |
495 | ||
496 | for (i = 0, crc = ~0, ecc = 0; i < nr; i++) { | |
497 | crc = crc32_le(crc, bhs[i]->b_data, bhs[i]->b_size); | |
498 | /* | |
499 | * The number of bits in a buffer is obviously b_size*8. | |
500 | * The offset of this buffer is b_size*i, so the bit offset | |
501 | * of this buffer is b_size*8*i. | |
502 | */ | |
503 | ecc = (u16)ocfs2_hamming_encode(ecc, bhs[i]->b_data, | |
504 | bhs[i]->b_size * 8, | |
505 | bhs[i]->b_size * 8 * i); | |
506 | } | |
507 | ||
508 | /* | |
509 | * No ecc'd ocfs2 structure is larger than 4K, so ecc will be no | |
510 | * larger than 16 bits. | |
511 | */ | |
4be929be | 512 | BUG_ON(ecc > USHRT_MAX); |
70ad1ba7 JB |
513 | |
514 | bc->bc_crc32e = cpu_to_le32(crc); | |
515 | bc->bc_ecc = cpu_to_le16((u16)ecc); | |
516 | } | |
517 | ||
518 | /* | |
519 | * This function validates existing check information on a list of | |
520 | * buffer_heads. Like _compute_bhs, the function will take care of | |
521 | * zeroing bc before calculating check codes. If bc is not a pointer | |
522 | * inside data, the caller must have zeroed any inline | |
523 | * ocfs2_block_check structures. | |
524 | * | |
525 | * Again, the data passed in should be the on-disk endian. | |
526 | */ | |
527 | int ocfs2_block_check_validate_bhs(struct buffer_head **bhs, int nr, | |
73be192b JB |
528 | struct ocfs2_block_check *bc, |
529 | struct ocfs2_blockcheck_stats *stats) | |
70ad1ba7 JB |
530 | { |
531 | int i, rc = 0; | |
1db5df98 AV |
532 | u32 bc_crc32e; |
533 | u16 bc_ecc; | |
70ad1ba7 JB |
534 | u32 crc, ecc, fix; |
535 | ||
536 | BUG_ON(nr < 0); | |
537 | ||
538 | if (!nr) | |
539 | return 0; | |
540 | ||
73be192b JB |
541 | ocfs2_blockcheck_inc_check(stats); |
542 | ||
1db5df98 AV |
543 | bc_crc32e = le32_to_cpu(bc->bc_crc32e); |
544 | bc_ecc = le16_to_cpu(bc->bc_ecc); | |
70ad1ba7 JB |
545 | |
546 | memset(bc, 0, sizeof(struct ocfs2_block_check)); | |
547 | ||
548 | /* Fast path - if the crc32 validates, we're good to go */ | |
549 | for (i = 0, crc = ~0; i < nr; i++) | |
550 | crc = crc32_le(crc, bhs[i]->b_data, bhs[i]->b_size); | |
1db5df98 | 551 | if (crc == bc_crc32e) |
70ad1ba7 JB |
552 | goto out; |
553 | ||
73be192b | 554 | ocfs2_blockcheck_inc_failure(stats); |
70ad1ba7 JB |
555 | mlog(ML_ERROR, |
556 | "CRC32 failed: stored: %u, computed %u. Applying ECC.\n", | |
1db5df98 | 557 | (unsigned int)bc_crc32e, (unsigned int)crc); |
70ad1ba7 JB |
558 | |
559 | /* Ok, try ECC fixups */ | |
560 | for (i = 0, ecc = 0; i < nr; i++) { | |
561 | /* | |
562 | * The number of bits in a buffer is obviously b_size*8. | |
563 | * The offset of this buffer is b_size*i, so the bit offset | |
564 | * of this buffer is b_size*8*i. | |
565 | */ | |
566 | ecc = (u16)ocfs2_hamming_encode(ecc, bhs[i]->b_data, | |
567 | bhs[i]->b_size * 8, | |
568 | bhs[i]->b_size * 8 * i); | |
569 | } | |
1db5df98 | 570 | fix = ecc ^ bc_ecc; |
70ad1ba7 JB |
571 | for (i = 0; i < nr; i++) { |
572 | /* | |
573 | * Try the fix against each buffer. It will only affect | |
574 | * one of them. | |
575 | */ | |
576 | ocfs2_hamming_fix(bhs[i]->b_data, bhs[i]->b_size * 8, | |
577 | bhs[i]->b_size * 8 * i, fix); | |
578 | } | |
579 | ||
580 | /* And check the crc32 again */ | |
581 | for (i = 0, crc = ~0; i < nr; i++) | |
582 | crc = crc32_le(crc, bhs[i]->b_data, bhs[i]->b_size); | |
1db5df98 | 583 | if (crc == bc_crc32e) { |
73be192b | 584 | ocfs2_blockcheck_inc_recover(stats); |
70ad1ba7 | 585 | goto out; |
73be192b | 586 | } |
70ad1ba7 JB |
587 | |
588 | mlog(ML_ERROR, "Fixed CRC32 failed: stored: %u, computed %u\n", | |
1db5df98 | 589 | (unsigned int)bc_crc32e, (unsigned int)crc); |
70ad1ba7 JB |
590 | |
591 | rc = -EIO; | |
592 | ||
593 | out: | |
1db5df98 AV |
594 | bc->bc_crc32e = cpu_to_le32(bc_crc32e); |
595 | bc->bc_ecc = cpu_to_le16(bc_ecc); | |
70ad1ba7 JB |
596 | |
597 | return rc; | |
598 | } | |
599 | ||
600 | /* | |
601 | * These are the main API. They check the superblock flag before | |
602 | * calling the underlying operations. | |
603 | * | |
604 | * They expect the buffer(s) to be in disk format. | |
605 | */ | |
606 | void ocfs2_compute_meta_ecc(struct super_block *sb, void *data, | |
607 | struct ocfs2_block_check *bc) | |
608 | { | |
609 | if (ocfs2_meta_ecc(OCFS2_SB(sb))) | |
610 | ocfs2_block_check_compute(data, sb->s_blocksize, bc); | |
611 | } | |
612 | ||
613 | int ocfs2_validate_meta_ecc(struct super_block *sb, void *data, | |
614 | struct ocfs2_block_check *bc) | |
615 | { | |
616 | int rc = 0; | |
73be192b | 617 | struct ocfs2_super *osb = OCFS2_SB(sb); |
70ad1ba7 | 618 | |
73be192b JB |
619 | if (ocfs2_meta_ecc(osb)) |
620 | rc = ocfs2_block_check_validate(data, sb->s_blocksize, bc, | |
621 | &osb->osb_ecc_stats); | |
70ad1ba7 JB |
622 | |
623 | return rc; | |
624 | } | |
625 | ||
626 | void ocfs2_compute_meta_ecc_bhs(struct super_block *sb, | |
627 | struct buffer_head **bhs, int nr, | |
628 | struct ocfs2_block_check *bc) | |
629 | { | |
630 | if (ocfs2_meta_ecc(OCFS2_SB(sb))) | |
631 | ocfs2_block_check_compute_bhs(bhs, nr, bc); | |
632 | } | |
633 | ||
634 | int ocfs2_validate_meta_ecc_bhs(struct super_block *sb, | |
635 | struct buffer_head **bhs, int nr, | |
636 | struct ocfs2_block_check *bc) | |
637 | { | |
638 | int rc = 0; | |
73be192b | 639 | struct ocfs2_super *osb = OCFS2_SB(sb); |
70ad1ba7 | 640 | |
73be192b JB |
641 | if (ocfs2_meta_ecc(osb)) |
642 | rc = ocfs2_block_check_validate_bhs(bhs, nr, bc, | |
643 | &osb->osb_ecc_stats); | |
70ad1ba7 JB |
644 | |
645 | return rc; | |
646 | } | |
647 |