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