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 u32 bc_crc32e;
426 u16 bc_ecc;
427 u32 crc, ecc;
428
429 ocfs2_blockcheck_inc_check(stats);
430
431 bc_crc32e = le32_to_cpu(bc->bc_crc32e);
432 bc_ecc = le16_to_cpu(bc->bc_ecc);
433
434 memset(bc, 0, sizeof(struct ocfs2_block_check));
435
436
437 crc = crc32_le(~0, data, blocksize);
438 if (crc == bc_crc32e)
439 goto out;
440
441 ocfs2_blockcheck_inc_failure(stats);
442 mlog(ML_ERROR,
443 "CRC32 failed: stored: 0x%x, computed 0x%x. Applying ECC.\n",
444 (unsigned int)bc_crc32e, (unsigned int)crc);
445
446
447 ecc = ocfs2_hamming_encode_block(data, blocksize);
448 ocfs2_hamming_fix_block(data, blocksize, ecc ^ bc_ecc);
449
450
451 crc = crc32_le(~0, data, blocksize);
452 if (crc == bc_crc32e) {
453 ocfs2_blockcheck_inc_recover(stats);
454 goto out;
455 }
456
457 mlog(ML_ERROR, "Fixed CRC32 failed: stored: 0x%x, computed 0x%x\n",
458 (unsigned int)bc_crc32e, (unsigned int)crc);
459
460 rc = -EIO;
461
462out:
463 bc->bc_crc32e = cpu_to_le32(bc_crc32e);
464 bc->bc_ecc = cpu_to_le16(bc_ecc);
465
466 return rc;
467}
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483void 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
500
501
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
510
511
512 BUG_ON(ecc > USHRT_MAX);
513
514 bc->bc_crc32e = cpu_to_le32(crc);
515 bc->bc_ecc = cpu_to_le16((u16)ecc);
516}
517
518
519
520
521
522
523
524
525
526
527int ocfs2_block_check_validate_bhs(struct buffer_head **bhs, int nr,
528 struct ocfs2_block_check *bc,
529 struct ocfs2_blockcheck_stats *stats)
530{
531 int i, rc = 0;
532 u32 bc_crc32e;
533 u16 bc_ecc;
534 u32 crc, ecc, fix;
535
536 BUG_ON(nr < 0);
537
538 if (!nr)
539 return 0;
540
541 ocfs2_blockcheck_inc_check(stats);
542
543 bc_crc32e = le32_to_cpu(bc->bc_crc32e);
544 bc_ecc = le16_to_cpu(bc->bc_ecc);
545
546 memset(bc, 0, sizeof(struct ocfs2_block_check));
547
548
549 for (i = 0, crc = ~0; i < nr; i++)
550 crc = crc32_le(crc, bhs[i]->b_data, bhs[i]->b_size);
551 if (crc == bc_crc32e)
552 goto out;
553
554 ocfs2_blockcheck_inc_failure(stats);
555 mlog(ML_ERROR,
556 "CRC32 failed: stored: %u, computed %u. Applying ECC.\n",
557 (unsigned int)bc_crc32e, (unsigned int)crc);
558
559
560 for (i = 0, ecc = 0; i < nr; i++) {
561
562
563
564
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 }
570 fix = ecc ^ bc_ecc;
571 for (i = 0; i < nr; i++) {
572
573
574
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
581 for (i = 0, crc = ~0; i < nr; i++)
582 crc = crc32_le(crc, bhs[i]->b_data, bhs[i]->b_size);
583 if (crc == bc_crc32e) {
584 ocfs2_blockcheck_inc_recover(stats);
585 goto out;
586 }
587
588 mlog(ML_ERROR, "Fixed CRC32 failed: stored: %u, computed %u\n",
589 (unsigned int)bc_crc32e, (unsigned int)crc);
590
591 rc = -EIO;
592
593out:
594 bc->bc_crc32e = cpu_to_le32(bc_crc32e);
595 bc->bc_ecc = cpu_to_le16(bc_ecc);
596
597 return rc;
598}
599
600
601
602
603
604
605
606void 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
613int ocfs2_validate_meta_ecc(struct super_block *sb, void *data,
614 struct ocfs2_block_check *bc)
615{
616 int rc = 0;
617 struct ocfs2_super *osb = OCFS2_SB(sb);
618
619 if (ocfs2_meta_ecc(osb))
620 rc = ocfs2_block_check_validate(data, sb->s_blocksize, bc,
621 &osb->osb_ecc_stats);
622
623 return rc;
624}
625
626void 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
634int 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;
639 struct ocfs2_super *osb = OCFS2_SB(sb);
640
641 if (ocfs2_meta_ecc(osb))
642 rc = ocfs2_block_check_validate_bhs(bhs, nr, bc,
643 &osb->osb_ecc_stats);
644
645 return rc;
646}
647
648