1 ext4: call out CRC and corruption errors with specific error codes
3 From: "Darrick J. Wong" <darrick.wong@oracle.com>
5 Instead of overloading EIO for CRC errors and corrupt structures,
6 return the same error codes that XFS returns for the same issues.
8 Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
9 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
11 fs/ext4/balloc.c | 2 +
12 fs/ext4/block_validity.c | 2 +
15 fs/ext4/extents.c | 75 +++++++++++++++++++++++-----------------------
16 fs/ext4/ialloc.c | 1 +
17 fs/ext4/indirect.c | 2 +
18 fs/ext4/inode.c | 16 +++++-----
19 fs/ext4/mmp.c | 8 +++--
20 fs/ext4/namei.c | 28 +++++++++--------
21 fs/ext4/super.c | 10 ++++++
22 fs/ext4/symlink.c | 2 +
23 fs/ext4/xattr.c | 28 +++++++++--------
24 fs/jbd2/journal.c | 3 +-
25 fs/jbd2/recovery.c | 8 ++---
26 include/linux/jbd2.h | 3 ++
27 16 files changed, 107 insertions(+), 88 deletions(-)
30 diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
31 index cd6ea29..f831e10 100644
32 --- a/fs/ext4/balloc.c
33 +++ b/fs/ext4/balloc.c
34 @@ -203,7 +203,7 @@ static int ext4_init_block_bitmap(struct super_block *sb,
37 set_bit(EXT4_GROUP_INFO_IBITMAP_CORRUPT_BIT, &grp->bb_state);
41 memset(bh->b_data, 0, sb->s_blocksize);
43 diff --git a/fs/ext4/block_validity.c b/fs/ext4/block_validity.c
44 index 3522340..02ddec6 100644
45 --- a/fs/ext4/block_validity.c
46 +++ b/fs/ext4/block_validity.c
47 @@ -234,7 +234,7 @@ int ext4_check_blockref(const char *function, unsigned int line,
48 es->s_last_error_block = cpu_to_le64(blk);
49 ext4_error_inode(inode, function, line, blk,
52 + return -EFSCORRUPTED;
56 diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
57 index f9e1491..b29cb70 100644
60 @@ -621,14 +621,14 @@ int ext4_check_all_de(struct inode *dir, struct buffer_head *bh, void *buf,
61 while ((char *) de < top) {
62 if (ext4_check_dir_entry(dir, NULL, de, bh,
63 buf, buf_size, offset))
65 + return -EFSCORRUPTED;
66 nlen = EXT4_DIR_REC_LEN(de->name_len);
67 rlen = ext4_rec_len_from_disk(de->rec_len, buf_size);
68 de = (struct ext4_dir_entry_2 *)((char *)de + rlen);
71 if ((char *) de > top)
73 + return -EFSCORRUPTED;
77 diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
78 index 81ce8ae..285b39f 100644
81 @@ -3051,4 +3051,7 @@ extern void ext4_resize_end(struct super_block *sb);
83 #endif /* __KERNEL__ */
85 +#define EFSBADCRC EBADMSG /* Bad CRC detected */
86 +#define EFSCORRUPTED EUCLEAN /* Filesystem is corrupted */
89 diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
90 index 2553aa8..4b6acacc 100644
91 --- a/fs/ext4/extents.c
92 +++ b/fs/ext4/extents.c
93 @@ -442,7 +442,7 @@ static int __ext4_ext_check(const char *function, unsigned int line,
94 int depth, ext4_fsblk_t pblk)
96 const char *error_msg;
98 + int max = 0, err = -EFSCORRUPTED;
100 if (unlikely(eh->eh_magic != EXT4_EXT_MAGIC)) {
101 error_msg = "invalid magic";
102 @@ -473,6 +473,7 @@ static int __ext4_ext_check(const char *function, unsigned int line,
103 if (ext_depth(inode) != depth &&
104 !ext4_extent_block_csum_verify(inode, eh)) {
105 error_msg = "extent tree corrupted";
110 @@ -485,7 +486,7 @@ corrupted:
111 le16_to_cpu(eh->eh_magic),
112 le16_to_cpu(eh->eh_entries), le16_to_cpu(eh->eh_max),
113 max, le16_to_cpu(eh->eh_depth), depth);
118 #define ext4_ext_check(inode, eh, depth, pblk) \
119 @@ -910,7 +911,7 @@ ext4_find_extent(struct inode *inode, ext4_lblk_t block,
121 EXT4_ERROR_INODE(inode,
122 "ppos %d > depth %d", ppos, depth);
124 + ret = -EFSCORRUPTED;
127 path[ppos].p_bh = bh;
128 @@ -959,7 +960,7 @@ static int ext4_ext_insert_index(handle_t *handle, struct inode *inode,
129 EXT4_ERROR_INODE(inode,
130 "logical %d == ei_block %d!",
131 logical, le32_to_cpu(curp->p_idx->ei_block));
133 + return -EFSCORRUPTED;
136 if (unlikely(le16_to_cpu(curp->p_hdr->eh_entries)
137 @@ -968,7 +969,7 @@ static int ext4_ext_insert_index(handle_t *handle, struct inode *inode,
138 "eh_entries %d >= eh_max %d!",
139 le16_to_cpu(curp->p_hdr->eh_entries),
140 le16_to_cpu(curp->p_hdr->eh_max));
142 + return -EFSCORRUPTED;
145 if (logical > le32_to_cpu(curp->p_idx->ei_block)) {
146 @@ -992,7 +993,7 @@ static int ext4_ext_insert_index(handle_t *handle, struct inode *inode,
148 if (unlikely(ix > EXT_MAX_INDEX(curp->p_hdr))) {
149 EXT4_ERROR_INODE(inode, "ix > EXT_MAX_INDEX!");
151 + return -EFSCORRUPTED;
154 ix->ei_block = cpu_to_le32(logical);
155 @@ -1001,7 +1002,7 @@ static int ext4_ext_insert_index(handle_t *handle, struct inode *inode,
157 if (unlikely(ix > EXT_LAST_INDEX(curp->p_hdr))) {
158 EXT4_ERROR_INODE(inode, "ix > EXT_LAST_INDEX!");
160 + return -EFSCORRUPTED;
163 err = ext4_ext_dirty(handle, inode, curp);
164 @@ -1042,7 +1043,7 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode,
165 * border from split point */
166 if (unlikely(path[depth].p_ext > EXT_MAX_EXTENT(path[depth].p_hdr))) {
167 EXT4_ERROR_INODE(inode, "p_ext > EXT_MAX_EXTENT!");
169 + return -EFSCORRUPTED;
171 if (path[depth].p_ext != EXT_MAX_EXTENT(path[depth].p_hdr)) {
172 border = path[depth].p_ext[1].ee_block;
173 @@ -1086,7 +1087,7 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode,
174 newblock = ablocks[--a];
175 if (unlikely(newblock == 0)) {
176 EXT4_ERROR_INODE(inode, "newblock == 0!");
178 + err = -EFSCORRUPTED;
181 bh = sb_getblk_gfp(inode->i_sb, newblock, __GFP_MOVABLE | GFP_NOFS);
182 @@ -1112,7 +1113,7 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode,
183 EXT4_ERROR_INODE(inode, "eh_entries %d != eh_max %d!",
184 path[depth].p_hdr->eh_entries,
185 path[depth].p_hdr->eh_max);
187 + err = -EFSCORRUPTED;
190 /* start copy from next extent */
191 @@ -1151,7 +1152,7 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode,
193 if (unlikely(k < 0)) {
194 EXT4_ERROR_INODE(inode, "k %d < 0!", k);
196 + err = -EFSCORRUPTED;
200 @@ -1191,7 +1192,7 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode,
201 EXT4_ERROR_INODE(inode,
202 "EXT_MAX_INDEX != EXT_LAST_INDEX ee_block %d!",
203 le32_to_cpu(path[i].p_ext->ee_block));
205 + err = -EFSCORRUPTED;
208 /* start copy indexes */
209 @@ -1425,7 +1426,7 @@ static int ext4_ext_search_left(struct inode *inode,
211 if (unlikely(path == NULL)) {
212 EXT4_ERROR_INODE(inode, "path == NULL *logical %d!", *logical);
214 + return -EFSCORRUPTED;
216 depth = path->p_depth;
218 @@ -1444,7 +1445,7 @@ static int ext4_ext_search_left(struct inode *inode,
219 EXT4_ERROR_INODE(inode,
220 "EXT_FIRST_EXTENT != ex *logical %d ee_block %d!",
221 *logical, le32_to_cpu(ex->ee_block));
223 + return -EFSCORRUPTED;
225 while (--depth >= 0) {
226 ix = path[depth].p_idx;
227 @@ -1455,7 +1456,7 @@ static int ext4_ext_search_left(struct inode *inode,
228 EXT_FIRST_INDEX(path[depth].p_hdr) != NULL ?
229 le32_to_cpu(EXT_FIRST_INDEX(path[depth].p_hdr)->ei_block) : 0,
232 + return -EFSCORRUPTED;
236 @@ -1465,7 +1466,7 @@ static int ext4_ext_search_left(struct inode *inode,
237 EXT4_ERROR_INODE(inode,
238 "logical %d < ee_block %d + ee_len %d!",
239 *logical, le32_to_cpu(ex->ee_block), ee_len);
241 + return -EFSCORRUPTED;
244 *logical = le32_to_cpu(ex->ee_block) + ee_len - 1;
245 @@ -1495,7 +1496,7 @@ static int ext4_ext_search_right(struct inode *inode,
247 if (unlikely(path == NULL)) {
248 EXT4_ERROR_INODE(inode, "path == NULL *logical %d!", *logical);
250 + return -EFSCORRUPTED;
252 depth = path->p_depth;
254 @@ -1514,7 +1515,7 @@ static int ext4_ext_search_right(struct inode *inode,
255 EXT4_ERROR_INODE(inode,
256 "first_extent(path[%d].p_hdr) != ex",
259 + return -EFSCORRUPTED;
261 while (--depth >= 0) {
262 ix = path[depth].p_idx;
263 @@ -1522,7 +1523,7 @@ static int ext4_ext_search_right(struct inode *inode,
264 EXT4_ERROR_INODE(inode,
265 "ix != EXT_FIRST_INDEX *logical %d!",
268 + return -EFSCORRUPTED;
272 @@ -1532,7 +1533,7 @@ static int ext4_ext_search_right(struct inode *inode,
273 EXT4_ERROR_INODE(inode,
274 "logical %d < ee_block %d + ee_len %d!",
275 *logical, le32_to_cpu(ex->ee_block), ee_len);
277 + return -EFSCORRUPTED;
280 if (ex != EXT_LAST_EXTENT(path[depth].p_hdr)) {
281 @@ -1670,7 +1671,7 @@ static int ext4_ext_correct_indexes(handle_t *handle, struct inode *inode,
282 if (unlikely(ex == NULL || eh == NULL)) {
283 EXT4_ERROR_INODE(inode,
284 "ex %p == NULL or eh %p == NULL", ex, eh);
286 + return -EFSCORRUPTED;
290 @@ -1938,14 +1939,14 @@ int ext4_ext_insert_extent(handle_t *handle, struct inode *inode,
291 mb_flags |= EXT4_MB_DELALLOC_RESERVED;
292 if (unlikely(ext4_ext_get_actual_len(newext) == 0)) {
293 EXT4_ERROR_INODE(inode, "ext4_ext_get_actual_len(newext) == 0");
295 + return -EFSCORRUPTED;
297 depth = ext_depth(inode);
298 ex = path[depth].p_ext;
299 eh = path[depth].p_hdr;
300 if (unlikely(path[depth].p_hdr == NULL)) {
301 EXT4_ERROR_INODE(inode, "path[%d].p_hdr == NULL", depth);
303 + return -EFSCORRUPTED;
306 /* try to insert block into found extent and return */
307 @@ -2172,7 +2173,7 @@ static int ext4_fill_fiemap_extents(struct inode *inode,
308 if (unlikely(path[depth].p_hdr == NULL)) {
309 up_read(&EXT4_I(inode)->i_data_sem);
310 EXT4_ERROR_INODE(inode, "path[%d].p_hdr == NULL", depth);
312 + err = -EFSCORRUPTED;
315 ex = path[depth].p_ext;
316 @@ -2241,7 +2242,7 @@ static int ext4_fill_fiemap_extents(struct inode *inode,
318 if (unlikely(es.es_len == 0)) {
319 EXT4_ERROR_INODE(inode, "es.es_len == 0");
321 + err = -EFSCORRUPTED;
325 @@ -2264,7 +2265,7 @@ static int ext4_fill_fiemap_extents(struct inode *inode,
326 "next extent == %u, next "
327 "delalloc extent = %u",
330 + err = -EFSCORRUPTED;
334 @@ -2363,7 +2364,7 @@ static int ext4_ext_rm_idx(handle_t *handle, struct inode *inode,
335 leaf = ext4_idx_pblock(path->p_idx);
336 if (unlikely(path->p_hdr->eh_entries == 0)) {
337 EXT4_ERROR_INODE(inode, "path->p_hdr->eh_entries == 0");
339 + return -EFSCORRUPTED;
341 err = ext4_ext_get_access(handle, inode, path);
343 @@ -2612,7 +2613,7 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode,
344 eh = path[depth].p_hdr;
345 if (unlikely(path[depth].p_hdr == NULL)) {
346 EXT4_ERROR_INODE(inode, "path[%d].p_hdr == NULL", depth);
348 + return -EFSCORRUPTED;
350 /* find where to start removing */
351 ex = path[depth].p_ext;
352 @@ -2666,7 +2667,7 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode,
354 start, end, ex_ee_block,
355 ex_ee_block + ex_ee_len - 1);
357 + err = -EFSCORRUPTED;
359 } else if (a != ex_ee_block) {
360 /* remove tail of the extent */
361 @@ -2841,7 +2842,7 @@ again:
362 EXT4_ERROR_INODE(inode,
363 "path[%d].p_hdr == NULL",
366 + err = -EFSCORRUPTED;
370 @@ -2920,7 +2921,7 @@ again:
373 if (ext4_ext_check(inode, path[0].p_hdr, depth, 0)) {
375 + err = -EFSCORRUPTED;
379 @@ -2978,7 +2979,7 @@ again:
380 * Should be a no-op if we did IO above. */
382 if (WARN_ON(i + 1 > depth)) {
384 + err = -EFSCORRUPTED;
387 path[i + 1].p_bh = bh;
388 @@ -3345,7 +3346,7 @@ static int ext4_split_extent(handle_t *handle,
390 EXT4_ERROR_INODE(inode, "unexpected hole at %lu",
391 (unsigned long) map->m_lblk);
393 + return -EFSCORRUPTED;
395 unwritten = ext4_ext_is_unwritten(ex);
397 @@ -3970,7 +3971,7 @@ convert_initialized_extent(handle_t *handle, struct inode *inode,
399 EXT4_ERROR_INODE(inode, "unexpected hole at %lu",
400 (unsigned long) map->m_lblk);
402 + return -EFSCORRUPTED;
406 @@ -4308,7 +4309,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
407 "lblock: %lu, depth: %d pblock %lld",
408 (unsigned long) map->m_lblk, depth,
409 path[depth].p_block);
411 + err = -EFSCORRUPTED;
415 @@ -5271,7 +5272,7 @@ ext4_ext_shift_path_extents(struct ext4_ext_path *path, ext4_lblk_t shift,
416 if (depth == path->p_depth) {
417 ex_start = path[depth].p_ext;
420 + return -EFSCORRUPTED;
422 ex_last = EXT_LAST_EXTENT(path[depth].p_hdr);
424 @@ -5411,7 +5412,7 @@ ext4_ext_shift_extents(struct inode *inode, handle_t *handle,
426 EXT4_ERROR_INODE(inode, "unexpected hole at %lu",
427 (unsigned long) *iterator);
429 + return -EFSCORRUPTED;
431 if (SHIFT == SHIFT_LEFT && *iterator >
432 le32_to_cpu(extent->ee_block)) {
433 diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
434 index 619bfc1..f34b1aa 100644
435 --- a/fs/ext4/ialloc.c
436 +++ b/fs/ext4/ialloc.c
437 @@ -1116,6 +1116,7 @@ struct inode *ext4_orphan_get(struct super_block *sb, unsigned long ino)
438 /* Error cases - e2fsck has already cleaned up for us */
440 ext4_warning(sb, "bad orphan ino %lu! e2fsck was run?", ino);
441 + err = -EFSCORRUPTED;
445 diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c
446 index 2468261..d96ea53 100644
447 --- a/fs/ext4/indirect.c
448 +++ b/fs/ext4/indirect.c
449 @@ -566,7 +566,7 @@ int ext4_ind_map_blocks(handle_t *handle, struct inode *inode,
450 EXT4_FEATURE_RO_COMPAT_BIGALLOC)) {
451 EXT4_ERROR_INODE(inode, "Can't allocate blocks for "
452 "non-extent mapped inodes with bigalloc");
454 + return -EFSCORRUPTED;
457 /* Set up for the direct block allocation */
458 diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
459 index 612fbcf..6facf71 100644
460 --- a/fs/ext4/inode.c
461 +++ b/fs/ext4/inode.c
462 @@ -378,7 +378,7 @@ static int __check_block_validity(struct inode *inode, const char *func,
463 "lblock %lu mapped to illegal pblock "
464 "(length %d)", (unsigned long) map->m_lblk,
467 + return -EFSCORRUPTED;
471 @@ -480,7 +480,7 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
473 /* We can handle the block number less than EXT_MAX_BLOCKS */
474 if (unlikely(map->m_lblk >= EXT_MAX_BLOCKS))
476 + return -EFSCORRUPTED;
478 /* Lookup extent status tree firstly */
479 if (ext4_es_lookup_extent(inode, map->m_lblk, &es)) {
480 @@ -3820,7 +3820,7 @@ static int __ext4_get_inode_loc(struct inode *inode,
483 if (!ext4_valid_inum(sb, inode->i_ino))
485 + return -EFSCORRUPTED;
487 iloc->block_group = (inode->i_ino - 1) / EXT4_INODES_PER_GROUP(sb);
488 gdp = ext4_get_group_desc(sb, iloc->block_group, NULL);
489 @@ -4068,7 +4068,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
490 EXT4_ERROR_INODE(inode, "bad extra_isize (%u != %u)",
491 EXT4_GOOD_OLD_INODE_SIZE + ei->i_extra_isize,
492 EXT4_INODE_SIZE(inode->i_sb));
494 + ret = -EFSCORRUPTED;
498 @@ -4088,7 +4088,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
500 if (!ext4_inode_csum_verify(inode, raw_inode, ei)) {
501 EXT4_ERROR_INODE(inode, "checksum invalid");
507 @@ -4203,7 +4203,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
508 !ext4_data_block_valid(EXT4_SB(sb), ei->i_file_acl, 1)) {
509 EXT4_ERROR_INODE(inode, "bad extended attribute block %llu",
512 + ret = -EFSCORRUPTED;
514 } else if (!ext4_has_inline_data(inode)) {
515 if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) {
516 @@ -4254,7 +4254,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
517 } else if (ino == EXT4_BOOT_LOADER_INO) {
518 make_bad_inode(inode);
521 + ret = -EFSCORRUPTED;
522 EXT4_ERROR_INODE(inode, "bogus i_mode (%o)", inode->i_mode);
525 @@ -4272,7 +4272,7 @@ bad_inode:
526 struct inode *ext4_iget_normal(struct super_block *sb, unsigned long ino)
528 if (ino < EXT4_FIRST_INO(sb) && ino != EXT4_ROOT_INO)
529 - return ERR_PTR(-EIO);
530 + return ERR_PTR(-EFSCORRUPTED);
531 return ext4_iget(sb, ino);
534 diff --git a/fs/ext4/mmp.c b/fs/ext4/mmp.c
535 index 6eb1a61..0a512aa 100644
538 @@ -98,10 +98,12 @@ static int read_mmp_block(struct super_block *sb, struct buffer_head **bh,
541 mmp = (struct mmp_struct *)((*bh)->b_data);
542 - if (le32_to_cpu(mmp->mmp_magic) == EXT4_MMP_MAGIC &&
543 - ext4_mmp_csum_verify(sb, mmp))
544 + if (le32_to_cpu(mmp->mmp_magic) != EXT4_MMP_MAGIC)
545 + ret = -EFSCORRUPTED;
546 + else if (!ext4_mmp_csum_verify(sb, mmp))
553 ext4_warning(sb, "Error %d while reading MMP block %llu",
554 diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
555 index 9f61e76..8fd8e0d 100644
556 --- a/fs/ext4/namei.c
557 +++ b/fs/ext4/namei.c
558 @@ -109,7 +109,7 @@ static struct buffer_head *__ext4_read_dirblock(struct inode *inode,
560 ext4_error_inode(inode, func, line, block,
561 "Directory hole found");
562 - return ERR_PTR(-EIO);
563 + return ERR_PTR(-EFSCORRUPTED);
565 dirent = (struct ext4_dir_entry *) bh->b_data;
566 /* Determine whether or not we have an index block */
567 @@ -124,7 +124,7 @@ static struct buffer_head *__ext4_read_dirblock(struct inode *inode,
568 if (!is_dx_block && type == INDEX) {
569 ext4_error_inode(inode, func, line, block,
570 "directory leaf block found instead of index block");
571 - return ERR_PTR(-EIO);
572 + return ERR_PTR(-EFSCORRUPTED);
574 if (!ext4_has_metadata_csum(inode->i_sb) ||
576 @@ -142,7 +142,7 @@ static struct buffer_head *__ext4_read_dirblock(struct inode *inode,
577 ext4_error_inode(inode, func, line, block,
578 "Directory index failed checksum");
580 - return ERR_PTR(-EIO);
581 + return ERR_PTR(-EFSBADCRC);
585 @@ -152,7 +152,7 @@ static struct buffer_head *__ext4_read_dirblock(struct inode *inode,
586 ext4_error_inode(inode, func, line, block,
587 "Directory block failed checksum");
589 - return ERR_PTR(-EIO);
590 + return ERR_PTR(-EFSBADCRC);
594 @@ -1570,19 +1570,19 @@ static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, unsi
596 if (!ext4_valid_inum(dir->i_sb, ino)) {
597 EXT4_ERROR_INODE(dir, "bad inode number: %u", ino);
598 - return ERR_PTR(-EIO);
599 + return ERR_PTR(-EFSCORRUPTED);
601 if (unlikely(ino == dir->i_ino)) {
602 EXT4_ERROR_INODE(dir, "'%pd' linked to parent dir",
604 - return ERR_PTR(-EIO);
605 + return ERR_PTR(-EFSCORRUPTED);
607 inode = ext4_iget_normal(dir->i_sb, ino);
608 if (inode == ERR_PTR(-ESTALE)) {
609 EXT4_ERROR_INODE(dir,
610 "deleted inode referenced: %u",
612 - return ERR_PTR(-EIO);
613 + return ERR_PTR(-EFSCORRUPTED);
615 if (!IS_ERR(inode) && ext4_encrypted_inode(dir) &&
616 (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
617 @@ -1619,7 +1619,7 @@ struct dentry *ext4_get_parent(struct dentry *child)
618 if (!ext4_valid_inum(d_inode(child)->i_sb, ino)) {
619 EXT4_ERROR_INODE(d_inode(child),
620 "bad parent inode number: %u", ino);
621 - return ERR_PTR(-EIO);
622 + return ERR_PTR(-EFSCORRUPTED);
625 return d_obtain_alias(ext4_iget_normal(d_inode(child)->i_sb, ino));
626 @@ -1807,7 +1807,7 @@ int ext4_find_dest_de(struct inode *dir, struct inode *inode,
627 while ((char *) de <= top) {
628 if (ext4_check_dir_entry(dir, NULL, de, bh,
629 buf, buf_size, offset)) {
631 + res = -EFSCORRUPTED;
634 /* Provide crypto context and crypto buffer to ext4 match */
635 @@ -1967,7 +1967,7 @@ static int make_indexed_dir(handle_t *handle, struct ext4_filename *fname,
636 if ((char *) de >= (((char *) root) + blocksize)) {
637 EXT4_ERROR_INODE(dir, "invalid rec_len for '..'");
640 + return -EFSCORRUPTED;
642 len = ((char *) root) + (blocksize - csum_size) - (char *) de;
644 @@ -2315,7 +2315,7 @@ int ext4_generic_delete_entry(handle_t *handle,
645 while (i < buf_size - csum_size) {
646 if (ext4_check_dir_entry(dir, NULL, de, bh,
647 bh->b_data, bh->b_size, i))
649 + return -EFSCORRUPTED;
652 pde->rec_len = ext4_rec_len_to_disk(
653 @@ -2934,7 +2934,7 @@ static int ext4_rmdir(struct inode *dir, struct dentry *dentry)
655 inode = d_inode(dentry);
658 + retval = -EFSCORRUPTED;
659 if (le32_to_cpu(de->inode) != inode->i_ino)
662 @@ -3008,7 +3008,7 @@ static int ext4_unlink(struct inode *dir, struct dentry *dentry)
664 inode = d_inode(dentry);
667 + retval = -EFSCORRUPTED;
668 if (le32_to_cpu(de->inode) != inode->i_ino)
671 @@ -3310,7 +3310,7 @@ static int ext4_rename_dir_prepare(handle_t *handle, struct ext4_renament *ent)
674 if (le32_to_cpu(ent->parent_de->inode) != ent->dir->i_ino)
676 + return -EFSCORRUPTED;
677 BUFFER_TRACE(ent->dir_bh, "get_write_access");
678 return ext4_journal_get_write_access(handle, ent->dir_bh);
680 diff --git a/fs/ext4/super.c b/fs/ext4/super.c
681 index ec9ccb2..99d5efb 100644
682 --- a/fs/ext4/super.c
683 +++ b/fs/ext4/super.c
684 @@ -495,6 +495,12 @@ const char *ext4_decode_error(struct super_block *sb, int errno,
688 + case -EFSCORRUPTED:
689 + errstr = "Corrupt filesystem";
692 + errstr = "Filesystem failed CRC";
695 errstr = "IO failure";
697 @@ -3559,6 +3565,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
698 ext4_msg(sb, KERN_ERR, "VFS: Found ext4 filesystem with "
699 "invalid superblock checksum. Run e2fsck?");
705 @@ -3986,6 +3993,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
707 if (!ext4_check_descriptors(sb, &first_not_zeroed)) {
708 ext4_msg(sb, KERN_ERR, "group descriptors corrupted!");
709 + ret = -EFSCORRUPTED;
713 @@ -5050,7 +5058,7 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
714 "ext4_remount: Checksum for group %u failed (%u!=%u)",
715 g, le16_to_cpu(ext4_group_desc_csum(sbi, g, gdp)),
716 le16_to_cpu(gdp->bg_checksum));
722 diff --git a/fs/ext4/symlink.c b/fs/ext4/symlink.c
723 index c677f2c..abe2401 100644
724 --- a/fs/ext4/symlink.c
725 +++ b/fs/ext4/symlink.c
726 @@ -57,7 +57,7 @@ static const char *ext4_encrypted_follow_link(struct dentry *dentry, void **cook
727 sizeof(struct ext4_encrypted_symlink_data) - 1) >
729 /* Symlink data on the disk is corrupted */
731 + res = -EFSCORRUPTED;
734 plen = (cstr.len < EXT4_FNAME_CRYPTO_DIGEST_SIZE*2) ?
735 diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
736 index 16e28c0..7649422 100644
737 --- a/fs/ext4/xattr.c
738 +++ b/fs/ext4/xattr.c
739 @@ -195,7 +195,7 @@ ext4_xattr_check_names(struct ext4_xattr_entry *entry, void *end,
740 while (!IS_LAST_ENTRY(e)) {
741 struct ext4_xattr_entry *next = EXT4_XATTR_NEXT(e);
742 if ((void *)next >= end)
744 + return -EFSCORRUPTED;
748 @@ -205,7 +205,7 @@ ext4_xattr_check_names(struct ext4_xattr_entry *entry, void *end,
749 (void *)e + sizeof(__u32) ||
750 value_start + le16_to_cpu(entry->e_value_offs) +
751 le32_to_cpu(entry->e_value_size) > end))
753 + return -EFSCORRUPTED;
754 entry = EXT4_XATTR_NEXT(entry);
757 @@ -222,9 +222,9 @@ ext4_xattr_check_block(struct inode *inode, struct buffer_head *bh)
759 if (BHDR(bh)->h_magic != cpu_to_le32(EXT4_XATTR_MAGIC) ||
760 BHDR(bh)->h_blocks != cpu_to_le32(1))
762 + return -EFSCORRUPTED;
763 if (!ext4_xattr_block_csum_verify(inode, bh->b_blocknr, BHDR(bh)))
766 error = ext4_xattr_check_names(BFIRST(bh), bh->b_data + bh->b_size,
769 @@ -239,7 +239,7 @@ ext4_xattr_check_entry(struct ext4_xattr_entry *entry, size_t size)
771 if (entry->e_value_block != 0 || value_size > size ||
772 le16_to_cpu(entry->e_value_offs) + value_size > size)
774 + return -EFSCORRUPTED;
778 @@ -266,7 +266,7 @@ ext4_xattr_find_entry(struct ext4_xattr_entry **pentry, int name_index,
781 if (!cmp && ext4_xattr_check_entry(entry, size))
783 + return -EFSCORRUPTED;
784 return cmp ? -ENODATA : 0;
787 @@ -297,13 +297,13 @@ ext4_xattr_block_get(struct inode *inode, int name_index, const char *name,
789 EXT4_ERROR_INODE(inode, "bad block %llu",
790 EXT4_I(inode)->i_file_acl);
792 + error = -EFSCORRUPTED;
795 ext4_xattr_cache_insert(ext4_mb_cache, bh);
797 error = ext4_xattr_find_entry(&entry, name_index, name, bh->b_size, 1);
799 + if (error == -EFSCORRUPTED)
803 @@ -445,7 +445,7 @@ ext4_xattr_block_list(struct dentry *dentry, char *buffer, size_t buffer_size)
804 if (ext4_xattr_check_block(inode, bh)) {
805 EXT4_ERROR_INODE(inode, "bad block %llu",
806 EXT4_I(inode)->i_file_acl);
808 + error = -EFSCORRUPTED;
811 ext4_xattr_cache_insert(ext4_mb_cache, bh);
812 @@ -751,7 +751,7 @@ ext4_xattr_block_find(struct inode *inode, struct ext4_xattr_info *i,
813 if (ext4_xattr_check_block(inode, bs->bh)) {
814 EXT4_ERROR_INODE(inode, "bad block %llu",
815 EXT4_I(inode)->i_file_acl);
817 + error = -EFSCORRUPTED;
820 /* Find the named attribute. */
821 @@ -811,7 +811,7 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode,
824 unlock_buffer(bs->bh);
826 + if (error == -EFSCORRUPTED)
829 error = ext4_handle_dirty_xattr_block(handle,
830 @@ -855,7 +855,7 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode,
833 error = ext4_xattr_set_entry(i, s);
835 + if (error == -EFSCORRUPTED)
839 @@ -1314,7 +1314,7 @@ retry:
840 if (ext4_xattr_check_block(inode, bh)) {
841 EXT4_ERROR_INODE(inode, "bad block %llu",
842 EXT4_I(inode)->i_file_acl);
844 + error = -EFSCORRUPTED;
848 @@ -1579,7 +1579,7 @@ ext4_xattr_cmp(struct ext4_xattr_header *header1,
849 memcmp(entry1->e_name, entry2->e_name, entry1->e_name_len))
851 if (entry1->e_value_block != 0 || entry2->e_value_block != 0)
853 + return -EFSCORRUPTED;
854 if (memcmp((char *)header1 + le16_to_cpu(entry1->e_value_offs),
855 (char *)header2 + le16_to_cpu(entry2->e_value_offs),
856 le32_to_cpu(entry1->e_value_size)))
857 diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
858 index 00f7dbd..474c178 100644
859 --- a/fs/jbd2/journal.c
860 +++ b/fs/jbd2/journal.c
861 @@ -1558,6 +1558,7 @@ static int journal_get_superblock(journal_t *journal)
862 /* Check superblock checksum */
863 if (!jbd2_superblock_csum_verify(journal, sb)) {
864 printk(KERN_ERR "JBD2: journal checksum error\n");
869 @@ -1649,7 +1650,7 @@ int jbd2_journal_load(journal_t *journal)
870 printk(KERN_ERR "JBD2: journal transaction %u on %s "
871 "is corrupt.\n", journal->j_failed_commit,
874 + return -EFSCORRUPTED;
877 /* OK, we've finished with the dynamic journal bits:
878 diff --git a/fs/jbd2/recovery.c b/fs/jbd2/recovery.c
879 index a9079d0..5c836d7 100644
880 --- a/fs/jbd2/recovery.c
881 +++ b/fs/jbd2/recovery.c
882 @@ -140,7 +140,7 @@ static int jread(struct buffer_head **bhp, journal_t *journal,
884 if (offset >= journal->j_maxlen) {
885 printk(KERN_ERR "JBD2: corrupted journal superblock\n");
887 + return -EFSCORRUPTED;
890 err = jbd2_journal_bmap(journal, offset, &blocknr);
891 @@ -527,7 +527,7 @@ static int do_one_pass(journal_t *journal,
892 printk(KERN_ERR "JBD2: Invalid checksum "
893 "recovering block %lu in log\n",
900 @@ -602,7 +602,7 @@ static int do_one_pass(journal_t *journal,
901 journal, tag, obh->b_data,
902 be32_to_cpu(tmp->h_sequence))) {
905 + success = -EFSBADCRC;
906 printk(KERN_ERR "JBD2: Invalid "
907 "checksum recovering "
908 "block %llu in log\n",
909 @@ -851,7 +851,7 @@ static int scan_revoke_records(journal_t *journal, struct buffer_head *bh,
910 rcount = be32_to_cpu(header->r_count);
912 if (!jbd2_revoke_block_csum_verify(journal, header))
916 if (jbd2_journal_has_csum_v2or3(journal))
917 csum_size = sizeof(struct jbd2_journal_revoke_tail);
918 diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
919 index 6da6f89..f2a4b07 100644
920 --- a/include/linux/jbd2.h
921 +++ b/include/linux/jbd2.h
922 @@ -1449,4 +1449,7 @@ static inline tid_t jbd2_get_latest_transaction(journal_t *journal)
924 #endif /* __KERNEL__ */
926 +#define EFSBADCRC EBADMSG /* Bad CRC detected */
927 +#define EFSCORRUPTED EUCLEAN /* Filesystem is corrupted */
929 #endif /* _LINUX_JBD2_H */