0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/kernel.h>
0011 #include <linux/types.h>
0012 #include <linux/crc32.h>
0013 #include <linux/buffer_head.h>
0014 #include <linux/bitops.h>
0015 #include <linux/debugfs.h>
0016 #include <linux/module.h>
0017 #include <linux/fs.h>
0018 #include <asm/byteorder.h>
0019
0020 #include <cluster/masklog.h>
0021
0022 #include "ocfs2.h"
0023
0024 #include "blockcheck.h"
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054 static unsigned int calc_code_bit(unsigned int i, unsigned int *p_cache)
0055 {
0056 unsigned int b, p = 0;
0057
0058
0059
0060
0061
0062 b = i + 1;
0063
0064
0065 if (p_cache)
0066 p = *p_cache;
0067 b += p;
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077 for (; (1 << p) < (b + 1); p++)
0078 b++;
0079
0080 if (p_cache)
0081 *p_cache = p;
0082
0083 return b;
0084 }
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097 u32 ocfs2_hamming_encode(u32 parity, void *data, unsigned int d, unsigned int nr)
0098 {
0099 unsigned int i, b, p = 0;
0100
0101 BUG_ON(!d);
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112 for (i = 0; (i = ocfs2_find_next_bit(data, d, i)) < d; i++)
0113 {
0114
0115
0116
0117
0118 b = calc_code_bit(nr + i, &p);
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136 parity ^= b;
0137 }
0138
0139
0140
0141 return parity;
0142 }
0143
0144 u32 ocfs2_hamming_encode_block(void *data, unsigned int blocksize)
0145 {
0146 return ocfs2_hamming_encode(0, data, blocksize * 8, 0);
0147 }
0148
0149
0150
0151
0152
0153
0154
0155
0156 void ocfs2_hamming_fix(void *data, unsigned int d, unsigned int nr,
0157 unsigned int fix)
0158 {
0159 unsigned int i, b;
0160
0161 BUG_ON(!d);
0162
0163
0164
0165
0166
0167 if (hweight32(fix) == 1)
0168 return;
0169
0170
0171
0172
0173
0174 if (fix >= calc_code_bit(nr + d, NULL))
0175 return;
0176
0177
0178
0179
0180
0181
0182 b = calc_code_bit(nr, NULL);
0183
0184 if (fix < b)
0185 return;
0186
0187 for (i = 0; i < d; i++, b++)
0188 {
0189
0190 while (hweight32(b) == 1)
0191 b++;
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201 if (b == fix)
0202 {
0203 if (ocfs2_test_bit(i, data))
0204 ocfs2_clear_bit(i, data);
0205 else
0206 ocfs2_set_bit(i, data);
0207 break;
0208 }
0209 }
0210 }
0211
0212 void ocfs2_hamming_fix_block(void *data, unsigned int blocksize,
0213 unsigned int fix)
0214 {
0215 ocfs2_hamming_fix(data, blocksize * 8, 0, fix);
0216 }
0217
0218
0219
0220
0221
0222
0223 #ifdef CONFIG_DEBUG_FS
0224
0225 static int blockcheck_u64_get(void *data, u64 *val)
0226 {
0227 *val = *(u64 *)data;
0228 return 0;
0229 }
0230 DEFINE_DEBUGFS_ATTRIBUTE(blockcheck_fops, blockcheck_u64_get, NULL, "%llu\n");
0231
0232 static void ocfs2_blockcheck_debug_remove(struct ocfs2_blockcheck_stats *stats)
0233 {
0234 if (stats) {
0235 debugfs_remove_recursive(stats->b_debug_dir);
0236 stats->b_debug_dir = NULL;
0237 }
0238 }
0239
0240 static void ocfs2_blockcheck_debug_install(struct ocfs2_blockcheck_stats *stats,
0241 struct dentry *parent)
0242 {
0243 struct dentry *dir;
0244
0245 dir = debugfs_create_dir("blockcheck", parent);
0246 stats->b_debug_dir = dir;
0247
0248 debugfs_create_file("blocks_checked", S_IFREG | S_IRUSR, dir,
0249 &stats->b_check_count, &blockcheck_fops);
0250
0251 debugfs_create_file("checksums_failed", S_IFREG | S_IRUSR, dir,
0252 &stats->b_failure_count, &blockcheck_fops);
0253
0254 debugfs_create_file("ecc_recoveries", S_IFREG | S_IRUSR, dir,
0255 &stats->b_recover_count, &blockcheck_fops);
0256
0257 }
0258 #else
0259 static inline void ocfs2_blockcheck_debug_install(struct ocfs2_blockcheck_stats *stats,
0260 struct dentry *parent)
0261 {
0262 }
0263
0264 static inline void ocfs2_blockcheck_debug_remove(struct ocfs2_blockcheck_stats *stats)
0265 {
0266 }
0267 #endif
0268
0269
0270 void ocfs2_blockcheck_stats_debugfs_install(struct ocfs2_blockcheck_stats *stats,
0271 struct dentry *parent)
0272 {
0273 ocfs2_blockcheck_debug_install(stats, parent);
0274 }
0275
0276 void ocfs2_blockcheck_stats_debugfs_remove(struct ocfs2_blockcheck_stats *stats)
0277 {
0278 ocfs2_blockcheck_debug_remove(stats);
0279 }
0280
0281 static void ocfs2_blockcheck_inc_check(struct ocfs2_blockcheck_stats *stats)
0282 {
0283 u64 new_count;
0284
0285 if (!stats)
0286 return;
0287
0288 spin_lock(&stats->b_lock);
0289 stats->b_check_count++;
0290 new_count = stats->b_check_count;
0291 spin_unlock(&stats->b_lock);
0292
0293 if (!new_count)
0294 mlog(ML_NOTICE, "Block check count has wrapped\n");
0295 }
0296
0297 static void ocfs2_blockcheck_inc_failure(struct ocfs2_blockcheck_stats *stats)
0298 {
0299 u64 new_count;
0300
0301 if (!stats)
0302 return;
0303
0304 spin_lock(&stats->b_lock);
0305 stats->b_failure_count++;
0306 new_count = stats->b_failure_count;
0307 spin_unlock(&stats->b_lock);
0308
0309 if (!new_count)
0310 mlog(ML_NOTICE, "Checksum failure count has wrapped\n");
0311 }
0312
0313 static void ocfs2_blockcheck_inc_recover(struct ocfs2_blockcheck_stats *stats)
0314 {
0315 u64 new_count;
0316
0317 if (!stats)
0318 return;
0319
0320 spin_lock(&stats->b_lock);
0321 stats->b_recover_count++;
0322 new_count = stats->b_recover_count;
0323 spin_unlock(&stats->b_lock);
0324
0325 if (!new_count)
0326 mlog(ML_NOTICE, "ECC recovery count has wrapped\n");
0327 }
0328
0329
0330
0331
0332
0333
0334
0335
0336
0337
0338
0339
0340
0341
0342
0343
0344
0345
0346
0347
0348
0349 void ocfs2_block_check_compute(void *data, size_t blocksize,
0350 struct ocfs2_block_check *bc)
0351 {
0352 u32 crc;
0353 u32 ecc;
0354
0355 memset(bc, 0, sizeof(struct ocfs2_block_check));
0356
0357 crc = crc32_le(~0, data, blocksize);
0358 ecc = ocfs2_hamming_encode_block(data, blocksize);
0359
0360
0361
0362
0363
0364 BUG_ON(ecc > USHRT_MAX);
0365
0366 bc->bc_crc32e = cpu_to_le32(crc);
0367 bc->bc_ecc = cpu_to_le16((u16)ecc);
0368 }
0369
0370
0371
0372
0373
0374
0375
0376
0377
0378 int ocfs2_block_check_validate(void *data, size_t blocksize,
0379 struct ocfs2_block_check *bc,
0380 struct ocfs2_blockcheck_stats *stats)
0381 {
0382 int rc = 0;
0383 u32 bc_crc32e;
0384 u16 bc_ecc;
0385 u32 crc, ecc;
0386
0387 ocfs2_blockcheck_inc_check(stats);
0388
0389 bc_crc32e = le32_to_cpu(bc->bc_crc32e);
0390 bc_ecc = le16_to_cpu(bc->bc_ecc);
0391
0392 memset(bc, 0, sizeof(struct ocfs2_block_check));
0393
0394
0395 crc = crc32_le(~0, data, blocksize);
0396 if (crc == bc_crc32e)
0397 goto out;
0398
0399 ocfs2_blockcheck_inc_failure(stats);
0400 mlog(ML_ERROR,
0401 "CRC32 failed: stored: 0x%x, computed 0x%x. Applying ECC.\n",
0402 (unsigned int)bc_crc32e, (unsigned int)crc);
0403
0404
0405 ecc = ocfs2_hamming_encode_block(data, blocksize);
0406 ocfs2_hamming_fix_block(data, blocksize, ecc ^ bc_ecc);
0407
0408
0409 crc = crc32_le(~0, data, blocksize);
0410 if (crc == bc_crc32e) {
0411 ocfs2_blockcheck_inc_recover(stats);
0412 goto out;
0413 }
0414
0415 mlog(ML_ERROR, "Fixed CRC32 failed: stored: 0x%x, computed 0x%x\n",
0416 (unsigned int)bc_crc32e, (unsigned int)crc);
0417
0418 rc = -EIO;
0419
0420 out:
0421 bc->bc_crc32e = cpu_to_le32(bc_crc32e);
0422 bc->bc_ecc = cpu_to_le16(bc_ecc);
0423
0424 return rc;
0425 }
0426
0427
0428
0429
0430
0431
0432
0433
0434
0435
0436
0437
0438
0439
0440
0441 void ocfs2_block_check_compute_bhs(struct buffer_head **bhs, int nr,
0442 struct ocfs2_block_check *bc)
0443 {
0444 int i;
0445 u32 crc, ecc;
0446
0447 BUG_ON(nr < 0);
0448
0449 if (!nr)
0450 return;
0451
0452 memset(bc, 0, sizeof(struct ocfs2_block_check));
0453
0454 for (i = 0, crc = ~0, ecc = 0; i < nr; i++) {
0455 crc = crc32_le(crc, bhs[i]->b_data, bhs[i]->b_size);
0456
0457
0458
0459
0460
0461 ecc = (u16)ocfs2_hamming_encode(ecc, bhs[i]->b_data,
0462 bhs[i]->b_size * 8,
0463 bhs[i]->b_size * 8 * i);
0464 }
0465
0466
0467
0468
0469
0470 BUG_ON(ecc > USHRT_MAX);
0471
0472 bc->bc_crc32e = cpu_to_le32(crc);
0473 bc->bc_ecc = cpu_to_le16((u16)ecc);
0474 }
0475
0476
0477
0478
0479
0480
0481
0482
0483
0484
0485 int ocfs2_block_check_validate_bhs(struct buffer_head **bhs, int nr,
0486 struct ocfs2_block_check *bc,
0487 struct ocfs2_blockcheck_stats *stats)
0488 {
0489 int i, rc = 0;
0490 u32 bc_crc32e;
0491 u16 bc_ecc;
0492 u32 crc, ecc, fix;
0493
0494 BUG_ON(nr < 0);
0495
0496 if (!nr)
0497 return 0;
0498
0499 ocfs2_blockcheck_inc_check(stats);
0500
0501 bc_crc32e = le32_to_cpu(bc->bc_crc32e);
0502 bc_ecc = le16_to_cpu(bc->bc_ecc);
0503
0504 memset(bc, 0, sizeof(struct ocfs2_block_check));
0505
0506
0507 for (i = 0, crc = ~0; i < nr; i++)
0508 crc = crc32_le(crc, bhs[i]->b_data, bhs[i]->b_size);
0509 if (crc == bc_crc32e)
0510 goto out;
0511
0512 ocfs2_blockcheck_inc_failure(stats);
0513 mlog(ML_ERROR,
0514 "CRC32 failed: stored: %u, computed %u. Applying ECC.\n",
0515 (unsigned int)bc_crc32e, (unsigned int)crc);
0516
0517
0518 for (i = 0, ecc = 0; i < nr; i++) {
0519
0520
0521
0522
0523
0524 ecc = (u16)ocfs2_hamming_encode(ecc, bhs[i]->b_data,
0525 bhs[i]->b_size * 8,
0526 bhs[i]->b_size * 8 * i);
0527 }
0528 fix = ecc ^ bc_ecc;
0529 for (i = 0; i < nr; i++) {
0530
0531
0532
0533
0534 ocfs2_hamming_fix(bhs[i]->b_data, bhs[i]->b_size * 8,
0535 bhs[i]->b_size * 8 * i, fix);
0536 }
0537
0538
0539 for (i = 0, crc = ~0; i < nr; i++)
0540 crc = crc32_le(crc, bhs[i]->b_data, bhs[i]->b_size);
0541 if (crc == bc_crc32e) {
0542 ocfs2_blockcheck_inc_recover(stats);
0543 goto out;
0544 }
0545
0546 mlog(ML_ERROR, "Fixed CRC32 failed: stored: %u, computed %u\n",
0547 (unsigned int)bc_crc32e, (unsigned int)crc);
0548
0549 rc = -EIO;
0550
0551 out:
0552 bc->bc_crc32e = cpu_to_le32(bc_crc32e);
0553 bc->bc_ecc = cpu_to_le16(bc_ecc);
0554
0555 return rc;
0556 }
0557
0558
0559
0560
0561
0562
0563
0564 void ocfs2_compute_meta_ecc(struct super_block *sb, void *data,
0565 struct ocfs2_block_check *bc)
0566 {
0567 if (ocfs2_meta_ecc(OCFS2_SB(sb)))
0568 ocfs2_block_check_compute(data, sb->s_blocksize, bc);
0569 }
0570
0571 int ocfs2_validate_meta_ecc(struct super_block *sb, void *data,
0572 struct ocfs2_block_check *bc)
0573 {
0574 int rc = 0;
0575 struct ocfs2_super *osb = OCFS2_SB(sb);
0576
0577 if (ocfs2_meta_ecc(osb))
0578 rc = ocfs2_block_check_validate(data, sb->s_blocksize, bc,
0579 &osb->osb_ecc_stats);
0580
0581 return rc;
0582 }
0583
0584 void ocfs2_compute_meta_ecc_bhs(struct super_block *sb,
0585 struct buffer_head **bhs, int nr,
0586 struct ocfs2_block_check *bc)
0587 {
0588 if (ocfs2_meta_ecc(OCFS2_SB(sb)))
0589 ocfs2_block_check_compute_bhs(bhs, nr, bc);
0590 }
0591
0592 int ocfs2_validate_meta_ecc_bhs(struct super_block *sb,
0593 struct buffer_head **bhs, int nr,
0594 struct ocfs2_block_check *bc)
0595 {
0596 int rc = 0;
0597 struct ocfs2_super *osb = OCFS2_SB(sb);
0598
0599 if (ocfs2_meta_ecc(osb))
0600 rc = ocfs2_block_check_validate_bhs(bhs, nr, bc,
0601 &osb->osb_ecc_stats);
0602
0603 return rc;
0604 }
0605