1
2
3
4
5
6
7
8
9
10
11
12#include <linux/kernel.h>
13#include <linux/types.h>
14#include <linux/crc32.h>
15#include <linux/buffer_head.h>
16#include <linux/bitops.h>
17#include <linux/debugfs.h>
18#include <linux/module.h>
19#include <linux/fs.h>
20#include <asm/byteorder.h>
21
22#include <cluster/masklog.h>
23
24#include "ocfs2.h"
25
26#include "blockcheck.h"
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56static unsigned int calc_code_bit(unsigned int i, unsigned int *p_cache)
57{
58 unsigned int b, p = 0;
59
60
61
62
63
64 b = i + 1;
65
66
67 if (p_cache)
68 p = *p_cache;
69 b += p;
70
71
72
73
74
75
76
77
78
79 for (; (1 << p) < (b + 1); p++)
80 b++;
81
82 if (p_cache)
83 *p_cache = p;
84
85 return b;
86}
87
88
89
90
91
92
93
94
95
96
97
98
99u32 ocfs2_hamming_encode(u32 parity, void *data, unsigned int d, unsigned int nr)
100{
101 unsigned int i, b, p = 0;
102
103 BUG_ON(!d);
104
105
106
107
108
109
110
111
112
113
114 for (i = 0; (i = ocfs2_find_next_bit(data, d, i)) < d; i++)
115 {
116
117
118
119
120 b = calc_code_bit(nr + i, &p);
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138 parity ^= b;
139 }
140
141
142
143 return parity;
144}
145
146u32 ocfs2_hamming_encode_block(void *data, unsigned int blocksize)
147{
148 return ocfs2_hamming_encode(0, data, blocksize * 8, 0);
149}
150
151
152
153
154
155
156
157
158void ocfs2_hamming_fix(void *data, unsigned int d, unsigned int nr,
159 unsigned int fix)
160{
161 unsigned int i, b;
162
163 BUG_ON(!d);
164
165
166
167
168
169 if (hweight32(fix) == 1)
170 return;
171
172
173
174
175
176 if (fix >= calc_code_bit(nr + d, NULL))
177 return;
178
179
180
181
182
183
184 b = calc_code_bit(nr, NULL);
185
186 if (fix < b)
187 return;
188
189 for (i = 0; i < d; i++, b++)
190 {
191
192 while (hweight32(b) == 1)
193 b++;
194
195
196
197
198
199
200
201
202
203 if (b == fix)
204 {
205 if (ocfs2_test_bit(i, data))
206 ocfs2_clear_bit(i, data);
207 else
208 ocfs2_set_bit(i, data);
209 break;
210 }
211 }
212}
213
214void ocfs2_hamming_fix_block(void *data, unsigned int blocksize,
215 unsigned int fix)
216{
217 ocfs2_hamming_fix(data, blocksize * 8, 0, fix);
218}
219
220
221
222
223
224
225#ifdef CONFIG_DEBUG_FS
226
227static int blockcheck_u64_get(void *data, u64 *val)
228{
229 *val = *(u64 *)data;
230 return 0;
231}
232DEFINE_SIMPLE_ATTRIBUTE(blockcheck_fops, blockcheck_u64_get, NULL, "%llu\n");
233
234static void ocfs2_blockcheck_debug_remove(struct ocfs2_blockcheck_stats *stats)
235{
236 if (stats) {
237 debugfs_remove_recursive(stats->b_debug_dir);
238 stats->b_debug_dir = NULL;
239 }
240}
241
242static void ocfs2_blockcheck_debug_install(struct ocfs2_blockcheck_stats *stats,
243 struct dentry *parent)
244{
245 struct dentry *dir;
246
247 dir = debugfs_create_dir("blockcheck", parent);
248 stats->b_debug_dir = dir;
249
250 debugfs_create_file("blocks_checked", S_IFREG | S_IRUSR, dir,
251 &stats->b_check_count, &blockcheck_fops);
252
253 debugfs_create_file("checksums_failed", S_IFREG | S_IRUSR, dir,
254 &stats->b_failure_count, &blockcheck_fops);
255
256 debugfs_create_file("ecc_recoveries", S_IFREG | S_IRUSR, dir,
257 &stats->b_recover_count, &blockcheck_fops);
258
259}
260#else
261static inline void ocfs2_blockcheck_debug_install(struct ocfs2_blockcheck_stats *stats,
262 struct dentry *parent)
263{
264}
265
266static inline void ocfs2_blockcheck_debug_remove(struct ocfs2_blockcheck_stats *stats)
267{
268}
269#endif
270
271
272void ocfs2_blockcheck_stats_debugfs_install(struct ocfs2_blockcheck_stats *stats,
273 struct dentry *parent)
274{
275 ocfs2_blockcheck_debug_install(stats, parent);
276}
277
278void ocfs2_blockcheck_stats_debugfs_remove(struct ocfs2_blockcheck_stats *stats)
279{
280 ocfs2_blockcheck_debug_remove(stats);
281}
282
283static void ocfs2_blockcheck_inc_check(struct ocfs2_blockcheck_stats *stats)
284{
285 u64 new_count;
286
287 if (!stats)
288 return;
289
290 spin_lock(&stats->b_lock);
291 stats->b_check_count++;
292 new_count = stats->b_check_count;
293 spin_unlock(&stats->b_lock);
294
295 if (!new_count)
296 mlog(ML_NOTICE, "Block check count has wrapped\n");
297}
298
299static void ocfs2_blockcheck_inc_failure(struct ocfs2_blockcheck_stats *stats)
300{
301 u64 new_count;
302
303 if (!stats)
304 return;
305
306 spin_lock(&stats->b_lock);
307 stats->b_failure_count++;
308 new_count = stats->b_failure_count;
309 spin_unlock(&stats->b_lock);
310
311 if (!new_count)
312 mlog(ML_NOTICE, "Checksum failure count has wrapped\n");
313}
314
315static void ocfs2_blockcheck_inc_recover(struct ocfs2_blockcheck_stats *stats)
316{
317 u64 new_count;
318
319 if (!stats)
320 return;
321
322 spin_lock(&stats->b_lock);
323 stats->b_recover_count++;
324 new_count = stats->b_recover_count;
325 spin_unlock(&stats->b_lock);
326
327 if (!new_count)
328 mlog(ML_NOTICE, "ECC recovery count has wrapped\n");
329}
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351void ocfs2_block_check_compute(void *data, size_t blocksize,
352 struct ocfs2_block_check *bc)
353{
354 u32 crc;
355 u32 ecc;
356
357 memset(bc, 0, sizeof(struct ocfs2_block_check));
358
359 crc = crc32_le(~0, data, blocksize);
360 ecc = ocfs2_hamming_encode_block(data, blocksize);
361
362
363
364
365
366 BUG_ON(ecc > USHRT_MAX);
367
368 bc->bc_crc32e = cpu_to_le32(crc);
369 bc->bc_ecc = cpu_to_le16((u16)ecc);
370}
371
372
373
374
375
376
377
378
379
380int ocfs2_block_check_validate(void *data, size_t blocksize,
381 struct ocfs2_block_check *bc,
382 struct ocfs2_blockcheck_stats *stats)
383{
384 int rc = 0;
385 u32 bc_crc32e;
386 u16 bc_ecc;
387 u32 crc, ecc;
388
389 ocfs2_blockcheck_inc_check(stats);
390
391 bc_crc32e = le32_to_cpu(bc->bc_crc32e);
392 bc_ecc = le16_to_cpu(bc->bc_ecc);
393
394 memset(bc, 0, sizeof(struct ocfs2_block_check));
395
396
397 crc = crc32_le(~0, data, blocksize);
398 if (crc == bc_crc32e)
399 goto out;
400
401 ocfs2_blockcheck_inc_failure(stats);
402 mlog(ML_ERROR,
403 "CRC32 failed: stored: 0x%x, computed 0x%x. Applying ECC.\n",
404 (unsigned int)bc_crc32e, (unsigned int)crc);
405
406
407 ecc = ocfs2_hamming_encode_block(data, blocksize);
408 ocfs2_hamming_fix_block(data, blocksize, ecc ^ bc_ecc);
409
410
411 crc = crc32_le(~0, data, blocksize);
412 if (crc == bc_crc32e) {
413 ocfs2_blockcheck_inc_recover(stats);
414 goto out;
415 }
416
417 mlog(ML_ERROR, "Fixed CRC32 failed: stored: 0x%x, computed 0x%x\n",
418 (unsigned int)bc_crc32e, (unsigned int)crc);
419
420 rc = -EIO;
421
422out:
423 bc->bc_crc32e = cpu_to_le32(bc_crc32e);
424 bc->bc_ecc = cpu_to_le16(bc_ecc);
425
426 return rc;
427}
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443void ocfs2_block_check_compute_bhs(struct buffer_head **bhs, int nr,
444 struct ocfs2_block_check *bc)
445{
446 int i;
447 u32 crc, ecc;
448
449 BUG_ON(nr < 0);
450
451 if (!nr)
452 return;
453
454 memset(bc, 0, sizeof(struct ocfs2_block_check));
455
456 for (i = 0, crc = ~0, ecc = 0; i < nr; i++) {
457 crc = crc32_le(crc, bhs[i]->b_data, bhs[i]->b_size);
458
459
460
461
462
463 ecc = (u16)ocfs2_hamming_encode(ecc, bhs[i]->b_data,
464 bhs[i]->b_size * 8,
465 bhs[i]->b_size * 8 * i);
466 }
467
468
469
470
471
472 BUG_ON(ecc > USHRT_MAX);
473
474 bc->bc_crc32e = cpu_to_le32(crc);
475 bc->bc_ecc = cpu_to_le16((u16)ecc);
476}
477
478
479
480
481
482
483
484
485
486
487int ocfs2_block_check_validate_bhs(struct buffer_head **bhs, int nr,
488 struct ocfs2_block_check *bc,
489 struct ocfs2_blockcheck_stats *stats)
490{
491 int i, rc = 0;
492 u32 bc_crc32e;
493 u16 bc_ecc;
494 u32 crc, ecc, fix;
495
496 BUG_ON(nr < 0);
497
498 if (!nr)
499 return 0;
500
501 ocfs2_blockcheck_inc_check(stats);
502
503 bc_crc32e = le32_to_cpu(bc->bc_crc32e);
504 bc_ecc = le16_to_cpu(bc->bc_ecc);
505
506 memset(bc, 0, sizeof(struct ocfs2_block_check));
507
508
509 for (i = 0, crc = ~0; i < nr; i++)
510 crc = crc32_le(crc, bhs[i]->b_data, bhs[i]->b_size);
511 if (crc == bc_crc32e)
512 goto out;
513
514 ocfs2_blockcheck_inc_failure(stats);
515 mlog(ML_ERROR,
516 "CRC32 failed: stored: %u, computed %u. Applying ECC.\n",
517 (unsigned int)bc_crc32e, (unsigned int)crc);
518
519
520 for (i = 0, ecc = 0; i < nr; i++) {
521
522
523
524
525
526 ecc = (u16)ocfs2_hamming_encode(ecc, bhs[i]->b_data,
527 bhs[i]->b_size * 8,
528 bhs[i]->b_size * 8 * i);
529 }
530 fix = ecc ^ bc_ecc;
531 for (i = 0; i < nr; i++) {
532
533
534
535
536 ocfs2_hamming_fix(bhs[i]->b_data, bhs[i]->b_size * 8,
537 bhs[i]->b_size * 8 * i, fix);
538 }
539
540
541 for (i = 0, crc = ~0; i < nr; i++)
542 crc = crc32_le(crc, bhs[i]->b_data, bhs[i]->b_size);
543 if (crc == bc_crc32e) {
544 ocfs2_blockcheck_inc_recover(stats);
545 goto out;
546 }
547
548 mlog(ML_ERROR, "Fixed CRC32 failed: stored: %u, computed %u\n",
549 (unsigned int)bc_crc32e, (unsigned int)crc);
550
551 rc = -EIO;
552
553out:
554 bc->bc_crc32e = cpu_to_le32(bc_crc32e);
555 bc->bc_ecc = cpu_to_le16(bc_ecc);
556
557 return rc;
558}
559
560
561
562
563
564
565
566void ocfs2_compute_meta_ecc(struct super_block *sb, void *data,
567 struct ocfs2_block_check *bc)
568{
569 if (ocfs2_meta_ecc(OCFS2_SB(sb)))
570 ocfs2_block_check_compute(data, sb->s_blocksize, bc);
571}
572
573int ocfs2_validate_meta_ecc(struct super_block *sb, void *data,
574 struct ocfs2_block_check *bc)
575{
576 int rc = 0;
577 struct ocfs2_super *osb = OCFS2_SB(sb);
578
579 if (ocfs2_meta_ecc(osb))
580 rc = ocfs2_block_check_validate(data, sb->s_blocksize, bc,
581 &osb->osb_ecc_stats);
582
583 return rc;
584}
585
586void ocfs2_compute_meta_ecc_bhs(struct super_block *sb,
587 struct buffer_head **bhs, int nr,
588 struct ocfs2_block_check *bc)
589{
590 if (ocfs2_meta_ecc(OCFS2_SB(sb)))
591 ocfs2_block_check_compute_bhs(bhs, nr, bc);
592}
593
594int ocfs2_validate_meta_ecc_bhs(struct super_block *sb,
595 struct buffer_head **bhs, int nr,
596 struct ocfs2_block_check *bc)
597{
598 int rc = 0;
599 struct ocfs2_super *osb = OCFS2_SB(sb);
600
601 if (ocfs2_meta_ecc(osb))
602 rc = ocfs2_block_check_validate_bhs(bhs, nr, bc,
603 &osb->osb_ecc_stats);
604
605 return rc;
606}
607
608