diff options
author | Joel Becker <joel.becker@oracle.com> | 2008-10-17 17:55:01 -0400 |
---|---|---|
committer | Mark Fasheh <mfasheh@suse.com> | 2009-01-05 11:40:31 -0500 |
commit | d6b32bbb3eae3fb787f1c33bf9f767ca1ddeb208 (patch) | |
tree | ce38de666096f571f4b1754e898729cf2d9eb435 /fs/ocfs2 | |
parent | 684ef278377725d505aa23259ee673dab9b11851 (diff) |
ocfs2: block read meta ecc.
Add block check calls to the read_block validate functions. This is the
almost all of the read-side checking of metaecc. xattr buckets are not checked
yet. Writes are also unchecked, and so a read-write mount will quickly fail.
Signed-off-by: Joel Becker <joel.becker@oracle.com>
Signed-off-by: Mark Fasheh <mfasheh@suse.com>
Diffstat (limited to 'fs/ocfs2')
-rw-r--r-- | fs/ocfs2/alloc.c | 17 | ||||
-rw-r--r-- | fs/ocfs2/blockcheck.c | 9 | ||||
-rw-r--r-- | fs/ocfs2/inode.c | 18 | ||||
-rw-r--r-- | fs/ocfs2/quota_global.c | 13 | ||||
-rw-r--r-- | fs/ocfs2/suballoc.c | 31 | ||||
-rw-r--r-- | fs/ocfs2/xattr.c | 17 |
6 files changed, 101 insertions, 4 deletions
diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c index 84a7bd4db5da..6b27f74bb346 100644 --- a/fs/ocfs2/alloc.c +++ b/fs/ocfs2/alloc.c | |||
@@ -37,6 +37,7 @@ | |||
37 | 37 | ||
38 | #include "alloc.h" | 38 | #include "alloc.h" |
39 | #include "aops.h" | 39 | #include "aops.h" |
40 | #include "blockcheck.h" | ||
40 | #include "dlmglue.h" | 41 | #include "dlmglue.h" |
41 | #include "extent_map.h" | 42 | #include "extent_map.h" |
42 | #include "inode.h" | 43 | #include "inode.h" |
@@ -682,12 +683,28 @@ struct ocfs2_merge_ctxt { | |||
682 | static int ocfs2_validate_extent_block(struct super_block *sb, | 683 | static int ocfs2_validate_extent_block(struct super_block *sb, |
683 | struct buffer_head *bh) | 684 | struct buffer_head *bh) |
684 | { | 685 | { |
686 | int rc; | ||
685 | struct ocfs2_extent_block *eb = | 687 | struct ocfs2_extent_block *eb = |
686 | (struct ocfs2_extent_block *)bh->b_data; | 688 | (struct ocfs2_extent_block *)bh->b_data; |
687 | 689 | ||
688 | mlog(0, "Validating extent block %llu\n", | 690 | mlog(0, "Validating extent block %llu\n", |
689 | (unsigned long long)bh->b_blocknr); | 691 | (unsigned long long)bh->b_blocknr); |
690 | 692 | ||
693 | BUG_ON(!buffer_uptodate(bh)); | ||
694 | |||
695 | /* | ||
696 | * If the ecc fails, we return the error but otherwise | ||
697 | * leave the filesystem running. We know any error is | ||
698 | * local to this block. | ||
699 | */ | ||
700 | rc = ocfs2_validate_meta_ecc(sb, bh->b_data, &eb->h_check); | ||
701 | if (rc) | ||
702 | return rc; | ||
703 | |||
704 | /* | ||
705 | * Errors after here are fatal. | ||
706 | */ | ||
707 | |||
691 | if (!OCFS2_IS_VALID_EXTENT_BLOCK(eb)) { | 708 | if (!OCFS2_IS_VALID_EXTENT_BLOCK(eb)) { |
692 | ocfs2_error(sb, | 709 | ocfs2_error(sb, |
693 | "Extent block #%llu has bad signature %.*s", | 710 | "Extent block #%llu has bad signature %.*s", |
diff --git a/fs/ocfs2/blockcheck.c b/fs/ocfs2/blockcheck.c index 2bf3d7f61aec..2ce6ae5e4b8c 100644 --- a/fs/ocfs2/blockcheck.c +++ b/fs/ocfs2/blockcheck.c | |||
@@ -24,6 +24,8 @@ | |||
24 | #include <linux/bitops.h> | 24 | #include <linux/bitops.h> |
25 | #include <asm/byteorder.h> | 25 | #include <asm/byteorder.h> |
26 | 26 | ||
27 | #include <cluster/masklog.h> | ||
28 | |||
27 | #include "ocfs2.h" | 29 | #include "ocfs2.h" |
28 | 30 | ||
29 | #include "blockcheck.h" | 31 | #include "blockcheck.h" |
@@ -292,6 +294,10 @@ int ocfs2_block_check_validate(void *data, size_t blocksize, | |||
292 | if (crc == check.bc_crc32e) | 294 | if (crc == check.bc_crc32e) |
293 | goto out; | 295 | goto out; |
294 | 296 | ||
297 | mlog(ML_ERROR, | ||
298 | "CRC32 failed: stored: %u, computed %u. Applying ECC.\n", | ||
299 | (unsigned int)check.bc_crc32e, (unsigned int)crc); | ||
300 | |||
295 | /* Ok, try ECC fixups */ | 301 | /* Ok, try ECC fixups */ |
296 | ecc = ocfs2_hamming_encode_block(data, blocksize); | 302 | ecc = ocfs2_hamming_encode_block(data, blocksize); |
297 | ocfs2_hamming_fix_block(data, blocksize, ecc ^ check.bc_ecc); | 303 | ocfs2_hamming_fix_block(data, blocksize, ecc ^ check.bc_ecc); |
@@ -301,6 +307,9 @@ int ocfs2_block_check_validate(void *data, size_t blocksize, | |||
301 | if (crc == check.bc_crc32e) | 307 | if (crc == check.bc_crc32e) |
302 | goto out; | 308 | goto out; |
303 | 309 | ||
310 | mlog(ML_ERROR, "Fixed CRC32 failed: stored: %u, computed %u\n", | ||
311 | (unsigned int)check.bc_crc32e, (unsigned int)crc); | ||
312 | |||
304 | rc = -EIO; | 313 | rc = -EIO; |
305 | 314 | ||
306 | out: | 315 | out: |
diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c index 288512c9dbc2..9370b652ab94 100644 --- a/fs/ocfs2/inode.c +++ b/fs/ocfs2/inode.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include "ocfs2.h" | 38 | #include "ocfs2.h" |
39 | 39 | ||
40 | #include "alloc.h" | 40 | #include "alloc.h" |
41 | #include "blockcheck.h" | ||
41 | #include "dlmglue.h" | 42 | #include "dlmglue.h" |
42 | #include "extent_map.h" | 43 | #include "extent_map.h" |
43 | #include "file.h" | 44 | #include "file.h" |
@@ -1262,7 +1263,7 @@ void ocfs2_refresh_inode(struct inode *inode, | |||
1262 | int ocfs2_validate_inode_block(struct super_block *sb, | 1263 | int ocfs2_validate_inode_block(struct super_block *sb, |
1263 | struct buffer_head *bh) | 1264 | struct buffer_head *bh) |
1264 | { | 1265 | { |
1265 | int rc = -EINVAL; | 1266 | int rc; |
1266 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)bh->b_data; | 1267 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)bh->b_data; |
1267 | 1268 | ||
1268 | mlog(0, "Validating dinode %llu\n", | 1269 | mlog(0, "Validating dinode %llu\n", |
@@ -1270,6 +1271,21 @@ int ocfs2_validate_inode_block(struct super_block *sb, | |||
1270 | 1271 | ||
1271 | BUG_ON(!buffer_uptodate(bh)); | 1272 | BUG_ON(!buffer_uptodate(bh)); |
1272 | 1273 | ||
1274 | /* | ||
1275 | * If the ecc fails, we return the error but otherwise | ||
1276 | * leave the filesystem running. We know any error is | ||
1277 | * local to this block. | ||
1278 | */ | ||
1279 | rc = ocfs2_validate_meta_ecc(sb, bh->b_data, &di->i_check); | ||
1280 | if (rc) | ||
1281 | goto bail; | ||
1282 | |||
1283 | /* | ||
1284 | * Errors after here are fatal. | ||
1285 | */ | ||
1286 | |||
1287 | rc = -EINVAL; | ||
1288 | |||
1273 | if (!OCFS2_IS_VALID_DINODE(di)) { | 1289 | if (!OCFS2_IS_VALID_DINODE(di)) { |
1274 | ocfs2_error(sb, "Invalid dinode #%llu: signature = %.*s\n", | 1290 | ocfs2_error(sb, "Invalid dinode #%llu: signature = %.*s\n", |
1275 | (unsigned long long)bh->b_blocknr, 7, | 1291 | (unsigned long long)bh->b_blocknr, 7, |
diff --git a/fs/ocfs2/quota_global.c b/fs/ocfs2/quota_global.c index 7dbcfd7f65e6..a0b8b14cca8f 100644 --- a/fs/ocfs2/quota_global.c +++ b/fs/ocfs2/quota_global.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include "ocfs2_fs.h" | 16 | #include "ocfs2_fs.h" |
17 | #include "ocfs2.h" | 17 | #include "ocfs2.h" |
18 | #include "alloc.h" | 18 | #include "alloc.h" |
19 | #include "blockcheck.h" | ||
19 | #include "inode.h" | 20 | #include "inode.h" |
20 | #include "journal.h" | 21 | #include "journal.h" |
21 | #include "file.h" | 22 | #include "file.h" |
@@ -90,12 +91,20 @@ struct qtree_fmt_operations ocfs2_global_ops = { | |||
90 | static int ocfs2_validate_quota_block(struct super_block *sb, | 91 | static int ocfs2_validate_quota_block(struct super_block *sb, |
91 | struct buffer_head *bh) | 92 | struct buffer_head *bh) |
92 | { | 93 | { |
93 | struct ocfs2_disk_dqtrailer *dqt = ocfs2_dq_trailer(sb, bh->b_data); | 94 | struct ocfs2_disk_dqtrailer *dqt = |
95 | ocfs2_block_dqtrailer(sb->s_blocksize, bh->b_data); | ||
94 | 96 | ||
95 | mlog(0, "Validating quota block %llu\n", | 97 | mlog(0, "Validating quota block %llu\n", |
96 | (unsigned long long)bh->b_blocknr); | 98 | (unsigned long long)bh->b_blocknr); |
97 | 99 | ||
98 | return 0; | 100 | BUG_ON(!buffer_uptodate(bh)); |
101 | |||
102 | /* | ||
103 | * If the ecc fails, we return the error but otherwise | ||
104 | * leave the filesystem running. We know any error is | ||
105 | * local to this block. | ||
106 | */ | ||
107 | return ocfs2_validate_meta_ecc(sb, bh->b_data, &dqt->dq_check); | ||
99 | } | 108 | } |
100 | 109 | ||
101 | int ocfs2_read_quota_block(struct inode *inode, u64 v_block, | 110 | int ocfs2_read_quota_block(struct inode *inode, u64 v_block, |
diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c index 226fe21f2608..78755766c329 100644 --- a/fs/ocfs2/suballoc.c +++ b/fs/ocfs2/suballoc.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include "ocfs2.h" | 35 | #include "ocfs2.h" |
36 | 36 | ||
37 | #include "alloc.h" | 37 | #include "alloc.h" |
38 | #include "blockcheck.h" | ||
38 | #include "dlmglue.h" | 39 | #include "dlmglue.h" |
39 | #include "inode.h" | 40 | #include "inode.h" |
40 | #include "journal.h" | 41 | #include "journal.h" |
@@ -250,8 +251,18 @@ int ocfs2_check_group_descriptor(struct super_block *sb, | |||
250 | struct buffer_head *bh) | 251 | struct buffer_head *bh) |
251 | { | 252 | { |
252 | int rc; | 253 | int rc; |
254 | struct ocfs2_group_desc *gd = (struct ocfs2_group_desc *)bh->b_data; | ||
255 | |||
256 | BUG_ON(!buffer_uptodate(bh)); | ||
253 | 257 | ||
254 | rc = ocfs2_validate_gd_self(sb, bh, 1); | 258 | /* |
259 | * If the ecc fails, we return the error but otherwise | ||
260 | * leave the filesystem running. We know any error is | ||
261 | * local to this block. | ||
262 | */ | ||
263 | rc = ocfs2_validate_meta_ecc(sb, bh->b_data, &gd->bg_check); | ||
264 | if (!rc) | ||
265 | rc = ocfs2_validate_gd_self(sb, bh, 1); | ||
255 | if (!rc) | 266 | if (!rc) |
256 | rc = ocfs2_validate_gd_parent(sb, di, bh, 1); | 267 | rc = ocfs2_validate_gd_parent(sb, di, bh, 1); |
257 | 268 | ||
@@ -261,9 +272,27 @@ int ocfs2_check_group_descriptor(struct super_block *sb, | |||
261 | static int ocfs2_validate_group_descriptor(struct super_block *sb, | 272 | static int ocfs2_validate_group_descriptor(struct super_block *sb, |
262 | struct buffer_head *bh) | 273 | struct buffer_head *bh) |
263 | { | 274 | { |
275 | int rc; | ||
276 | struct ocfs2_group_desc *gd = (struct ocfs2_group_desc *)bh->b_data; | ||
277 | |||
264 | mlog(0, "Validating group descriptor %llu\n", | 278 | mlog(0, "Validating group descriptor %llu\n", |
265 | (unsigned long long)bh->b_blocknr); | 279 | (unsigned long long)bh->b_blocknr); |
266 | 280 | ||
281 | BUG_ON(!buffer_uptodate(bh)); | ||
282 | |||
283 | /* | ||
284 | * If the ecc fails, we return the error but otherwise | ||
285 | * leave the filesystem running. We know any error is | ||
286 | * local to this block. | ||
287 | */ | ||
288 | rc = ocfs2_validate_meta_ecc(sb, bh->b_data, &gd->bg_check); | ||
289 | if (rc) | ||
290 | return rc; | ||
291 | |||
292 | /* | ||
293 | * Errors after here are fatal. | ||
294 | */ | ||
295 | |||
267 | return ocfs2_validate_gd_self(sb, bh, 0); | 296 | return ocfs2_validate_gd_self(sb, bh, 0); |
268 | } | 297 | } |
269 | 298 | ||
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c index dfc51c305bb9..bc822d6ba542 100644 --- a/fs/ocfs2/xattr.c +++ b/fs/ocfs2/xattr.c | |||
@@ -42,6 +42,7 @@ | |||
42 | 42 | ||
43 | #include "ocfs2.h" | 43 | #include "ocfs2.h" |
44 | #include "alloc.h" | 44 | #include "alloc.h" |
45 | #include "blockcheck.h" | ||
45 | #include "dlmglue.h" | 46 | #include "dlmglue.h" |
46 | #include "file.h" | 47 | #include "file.h" |
47 | #include "symlink.h" | 48 | #include "symlink.h" |
@@ -322,12 +323,28 @@ static void ocfs2_xattr_bucket_copy_data(struct ocfs2_xattr_bucket *dest, | |||
322 | static int ocfs2_validate_xattr_block(struct super_block *sb, | 323 | static int ocfs2_validate_xattr_block(struct super_block *sb, |
323 | struct buffer_head *bh) | 324 | struct buffer_head *bh) |
324 | { | 325 | { |
326 | int rc; | ||
325 | struct ocfs2_xattr_block *xb = | 327 | struct ocfs2_xattr_block *xb = |
326 | (struct ocfs2_xattr_block *)bh->b_data; | 328 | (struct ocfs2_xattr_block *)bh->b_data; |
327 | 329 | ||
328 | mlog(0, "Validating xattr block %llu\n", | 330 | mlog(0, "Validating xattr block %llu\n", |
329 | (unsigned long long)bh->b_blocknr); | 331 | (unsigned long long)bh->b_blocknr); |
330 | 332 | ||
333 | BUG_ON(!buffer_uptodate(bh)); | ||
334 | |||
335 | /* | ||
336 | * If the ecc fails, we return the error but otherwise | ||
337 | * leave the filesystem running. We know any error is | ||
338 | * local to this block. | ||
339 | */ | ||
340 | rc = ocfs2_validate_meta_ecc(sb, bh->b_data, &xb->xb_check); | ||
341 | if (rc) | ||
342 | return rc; | ||
343 | |||
344 | /* | ||
345 | * Errors after here are fatal | ||
346 | */ | ||
347 | |||
331 | if (!OCFS2_IS_VALID_XATTR_BLOCK(xb)) { | 348 | if (!OCFS2_IS_VALID_XATTR_BLOCK(xb)) { |
332 | ocfs2_error(sb, | 349 | ocfs2_error(sb, |
333 | "Extended attribute block #%llu has bad " | 350 | "Extended attribute block #%llu has bad " |