1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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>
25#include <linux/debugfs.h>
26#include <linux/module.h>
27#include <linux/fs.h>
28#include <asm/byteorder.h>
29
30#include <cluster/masklog.h>
31
32#include "ocfs2.h"
33
34#include "blockcheck.h"
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64static unsigned int calc_code_bit(unsigned int i, unsigned int *p_cache)
65{
66 unsigned int b, p = 0;
67
68
69
70
71
72 b = i + 1;
73
74
75 if (p_cache)
76 p = *p_cache;
77 b += p;
78
79
80
81
82
83
84
85
86
87 for (; (1 << p) < (b + 1); p++)
88 b++;
89
90 if (p_cache)
91 *p_cache = p;
92
93 return b;
94}
95
96
97
98
99
100
101
102
103
104
105
106
107u32 ocfs2_hamming_encode(u32 parity, void *data, unsigned int d, unsigned int nr)
108{
109 unsigned int i, b, p = 0;
110
111 BUG_ON(!d);
112
113
114
115
116
117
118
119
120
121
122 for (i = 0; (i = ocfs2_find_next_bit(data, d, i)) < d; i++)
123 {
124
125
126
127
128 b = calc_code_bit(nr + i, &p);
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146 parity ^= b;
147 }
148
149
150
151 return parity;
152}
153
154u32 ocfs2_hamming_encode_block(void *data, unsigned int blocksize)
155{
156 return ocfs2_hamming_encode(0, data, blocksize * 8, 0);
157}
158
159
160
161
162
163
164
165
166void ocfs2_hamming_fix(void *data, unsigned int d, unsigned int nr,
167 unsigned int fix)
168{
169 unsigned int i, b;
170
171 BUG_ON(!d);
172
173
174
175
176
177 if (hweight32(fix) == 1)
178 return;
179
180
181
182
183
184 if (fix >= calc_code_bit(nr + d, NULL))
185 return;
186
187
188
189
190
191
192 b = calc_code_bit(nr, NULL);
193
194 if (fix < b)
195 return;
196
197 for (i = 0; i < d; i++, b++)
198 {
199
200 while (hweight32(b) == 1)
201 b++;
202
203
204
205
206
207
208
209
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
222void 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
228
229
230
231
232
233#ifdef CONFIG_DEBUG_FS
234
235static int blockcheck_u64_get(void *data, u64 *val)
236{
237 *val = *(u64 *)data;
238 return 0;
239}
240DEFINE_SIMPLE_ATTRIBUTE(blockcheck_fops, blockcheck_u64_get, NULL, "%llu\n");
241
242static 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
250static 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
264static 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
294out:
295 if (rc)
296 ocfs2_blockcheck_debug_remove(stats);
297 return rc;
298}
299#else
300static inline int ocfs2_blockcheck_debug_install(struct ocfs2_blockcheck_stats *stats,
301 struct dentry *parent)
302{
303 return 0;
304}
305
306static inline void ocfs2_blockcheck_debug_remove(struct ocfs2_blockcheck_stats *stats)
307{
308}
309#endif
310
311
312int 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
318void ocfs2_blockcheck_stats_debugfs_remove(struct ocfs2_blockcheck_stats *stats)
319{
320 ocfs2_blockcheck_debug_remove(stats);
321}
322
323static 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
339static 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
355static 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
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391void 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
404
405
406 BUG_ON(ecc > USHRT_MAX);
407
408 bc->bc_crc32e = cpu_to_le32(crc);
409 bc->bc_ecc = cpu_to_le16((u16)ecc);
410}
411
412
413
414
415
416
417
418
419
420int ocfs2_block_check_validate(void *data, size_t blocksize,
421 struct ocfs2_block_check *bc,
422 struct ocfs2_blockcheck_stats *stats)
423{
424 int rc = 0;
425 struct ocfs2_block_check check;
426 u32 crc, ecc;
427
428 ocfs2_blockcheck_inc_check(stats);
429
430 check.bc_crc32e = le32_to_cpu(bc->bc_crc32e);
431 check.bc_ecc = le16_to_cpu(bc->bc_ecc);
432
433 memset(bc, 0, sizeof(struct ocfs2_block_check));
434
435
436 crc = crc32_le(~0, data, blocksize);
437 if (crc == check.bc_crc32e)
438 goto out;
439
440 ocfs2_blockcheck_inc_failure(stats);
441 mlog(ML_ERROR,
442 "CRC32 failed: stored: 0x%x, computed 0x%x. Applying ECC.\n",
443 (unsigned int)check.bc_crc32e, (unsigned int)crc);
444
445
446 ecc = ocfs2_hamming_encode_block(data, blocksize);
447 ocfs2_hamming_fix_block(data, blocksize, ecc ^ check.bc_ecc);
448
449
450 crc = crc32_le(~0, data, blocksize);
451 if (crc == check.bc_crc32e) {
452 ocfs2_blockcheck_inc_recover(stats);
453 goto out;
454 }
455
456 mlog(ML_ERROR, "Fixed CRC32 failed: stored: 0x%x, computed 0x%x\n",
457 (unsigned int)check.bc_crc32e, (unsigned int)crc);
458
459 rc = -EIO;
460
461out:
462 bc->bc_crc32e = cpu_to_le32(check.bc_crc32e);
463 bc->bc_ecc = cpu_to_le16(check.bc_ecc);
464
465 return rc;
466}
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482void ocfs2_block_check_compute_bhs(struct buffer_head **bhs, int nr,
483 struct ocfs2_block_check *bc)
484{
485 int i;
486 u32 crc, ecc;
487
488 BUG_ON(nr < 0);
489
490 if (!nr)
491 return;
492
493 memset(bc, 0, sizeof(struct ocfs2_block_check));
494
495 for (i = 0, crc = ~0, ecc = 0; i < nr; i++) {
496 crc = crc32_le(crc, bhs[i]->b_data, bhs[i]->b_size);
497
498
499
500
501
502 ecc = (u16)ocfs2_hamming_encode(ecc, bhs[i]->b_data,
503 bhs[i]->b_size * 8,
504 bhs[i]->b_size * 8 * i);
505 }
506
507
508
509
510
511 BUG_ON(ecc > USHRT_MAX);
512
513 bc->bc_crc32e = cpu_to_le32(crc);
514 bc->bc_ecc = cpu_to_le16((u16)ecc);
515}
516
517
518
519
520
521
522
523
524
525
526int ocfs2_block_check_validate_bhs(struct buffer_head **bhs, int nr,
527 struct ocfs2_block_check *bc,
528 struct ocfs2_blockcheck_stats *stats)
529{
530 int i, rc = 0;
531 struct ocfs2_block_check check;
532 u32 crc, ecc, fix;
533
534 BUG_ON(nr < 0);
535
536 if (!nr)
537 return 0;
538
539 ocfs2_blockcheck_inc_check(stats);
540
541 check.bc_crc32e = le32_to_cpu(bc->bc_crc32e);
542 check.bc_ecc = le16_to_cpu(bc->bc_ecc);
543
544 memset(bc, 0, sizeof(struct ocfs2_block_check));
545
546
547 for (i = 0, crc = ~0; i < nr; i++)
548 crc = crc32_le(crc, bhs[i]->b_data, bhs[i]->b_size);
549 if (crc == check.bc_crc32e)
550 goto out;
551
552 ocfs2_blockcheck_inc_failure(stats);
553 mlog(ML_ERROR,
554 "CRC32 failed: stored: %u, computed %u. Applying ECC.\n",
555 (unsigned int)check.bc_crc32e, (unsigned int)crc);
556
557
558 for (i = 0, ecc = 0; i < nr; i++) {
559
560
561
562
563
564 ecc = (u16)ocfs2_hamming_encode(ecc, bhs[i]->b_data,
565 bhs[i]->b_size * 8,
566 bhs[i]->b_size * 8 * i);
567 }
568 fix = ecc ^ check.bc_ecc;
569 for (i = 0; i < nr; i++) {
570
571
572
573
574 ocfs2_hamming_fix(bhs[i]->b_data, bhs[i]->b_size * 8,
575 bhs[i]->b_size * 8 * i, fix);
576 }
577
578
579 for (i = 0, crc = ~0; i < nr; i++)
580 crc = crc32_le(crc, bhs[i]->b_data, bhs[i]->b_size);
581 if (crc == check.bc_crc32e) {
582 ocfs2_blockcheck_inc_recover(stats);
583 goto out;
584 }
585
586 mlog(ML_ERROR, "Fixed CRC32 failed: stored: %u, computed %u\n",
587 (unsigned int)check.bc_crc32e, (unsigned int)crc);
588
589 rc = -EIO;
590
591out:
592 bc->bc_crc32e = cpu_to_le32(check.bc_crc32e);
593 bc->bc_ecc = cpu_to_le16(check.bc_ecc);
594
595 return rc;
596}
597
598
599
600
601
602
603
604void ocfs2_compute_meta_ecc(struct super_block *sb, void *data,
605 struct ocfs2_block_check *bc)
606{
607 if (ocfs2_meta_ecc(OCFS2_SB(sb)))
608 ocfs2_block_check_compute(data, sb->s_blocksize, bc);
609}
610
611int ocfs2_validate_meta_ecc(struct super_block *sb, void *data,
612 struct ocfs2_block_check *bc)
613{
614 int rc = 0;
615 struct ocfs2_super *osb = OCFS2_SB(sb);
616
617 if (ocfs2_meta_ecc(osb))
618 rc = ocfs2_block_check_validate(data, sb->s_blocksize, bc,
619 &osb->osb_ecc_stats);
620
621 return rc;
622}
623
624void ocfs2_compute_meta_ecc_bhs(struct super_block *sb,
625 struct buffer_head **bhs, int nr,
626 struct ocfs2_block_check *bc)
627{
628 if (ocfs2_meta_ecc(OCFS2_SB(sb)))
629 ocfs2_block_check_compute_bhs(bhs, nr, bc);
630}
631
632int ocfs2_validate_meta_ecc_bhs(struct super_block *sb,
633 struct buffer_head **bhs, int nr,
634 struct ocfs2_block_check *bc)
635{
636 int rc = 0;
637 struct ocfs2_super *osb = OCFS2_SB(sb);
638
639 if (ocfs2_meta_ecc(osb))
640 rc = ocfs2_block_check_validate_bhs(bhs, nr, bc,
641 &osb->osb_ecc_stats);
642
643 return rc;
644}
645
646