Skip to content

Commit

Permalink
ext4: call out CRC and corruption errors with specific error codes
Browse files Browse the repository at this point in the history
Instead of overloading EIO for CRC errors and corrupt structures,
return the same error codes that XFS returns for the same issues.

Signed-off-by: Darrick J. Wong <[email protected]>
Signed-off-by: Theodore Ts'o <[email protected]>
  • Loading branch information
djwong authored and tytso committed Oct 17, 2015
1 parent 8c81bd8 commit 6a797d2
Show file tree
Hide file tree
Showing 16 changed files with 107 additions and 88 deletions.
2 changes: 1 addition & 1 deletion fs/ext4/balloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ static int ext4_init_block_bitmap(struct super_block *sb,
count);
}
set_bit(EXT4_GROUP_INFO_IBITMAP_CORRUPT_BIT, &grp->bb_state);
return -EIO;
return -EFSBADCRC;
}
memset(bh->b_data, 0, sb->s_blocksize);

Expand Down
2 changes: 1 addition & 1 deletion fs/ext4/block_validity.c
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ int ext4_check_blockref(const char *function, unsigned int line,
es->s_last_error_block = cpu_to_le64(blk);
ext4_error_inode(inode, function, line, blk,
"invalid block");
return -EIO;
return -EFSCORRUPTED;
}
}
return 0;
Expand Down
4 changes: 2 additions & 2 deletions fs/ext4/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -621,14 +621,14 @@ int ext4_check_all_de(struct inode *dir, struct buffer_head *bh, void *buf,
while ((char *) de < top) {
if (ext4_check_dir_entry(dir, NULL, de, bh,
buf, buf_size, offset))
return -EIO;
return -EFSCORRUPTED;
nlen = EXT4_DIR_REC_LEN(de->name_len);
rlen = ext4_rec_len_from_disk(de->rec_len, buf_size);
de = (struct ext4_dir_entry_2 *)((char *)de + rlen);
offset += rlen;
}
if ((char *) de > top)
return -EIO;
return -EFSCORRUPTED;

return 0;
}
Expand Down
3 changes: 3 additions & 0 deletions fs/ext4/ext4.h
Original file line number Diff line number Diff line change
Expand Up @@ -3064,4 +3064,7 @@ extern void ext4_resize_end(struct super_block *sb);

#endif /* __KERNEL__ */

#define EFSBADCRC EBADMSG /* Bad CRC detected */
#define EFSCORRUPTED EUCLEAN /* Filesystem is corrupted */

#endif /* _EXT4_H */
75 changes: 38 additions & 37 deletions fs/ext4/extents.c
Original file line number Diff line number Diff line change
Expand Up @@ -442,7 +442,7 @@ static int __ext4_ext_check(const char *function, unsigned int line,
int depth, ext4_fsblk_t pblk)
{
const char *error_msg;
int max = 0;
int max = 0, err = -EFSCORRUPTED;

if (unlikely(eh->eh_magic != EXT4_EXT_MAGIC)) {
error_msg = "invalid magic";
Expand Down Expand Up @@ -473,6 +473,7 @@ static int __ext4_ext_check(const char *function, unsigned int line,
if (ext_depth(inode) != depth &&
!ext4_extent_block_csum_verify(inode, eh)) {
error_msg = "extent tree corrupted";
err = -EFSBADCRC;
goto corrupted;
}
return 0;
Expand All @@ -485,7 +486,7 @@ static int __ext4_ext_check(const char *function, unsigned int line,
le16_to_cpu(eh->eh_magic),
le16_to_cpu(eh->eh_entries), le16_to_cpu(eh->eh_max),
max, le16_to_cpu(eh->eh_depth), depth);
return -EIO;
return err;
}

#define ext4_ext_check(inode, eh, depth, pblk) \
Expand Down Expand Up @@ -910,7 +911,7 @@ ext4_find_extent(struct inode *inode, ext4_lblk_t block,
put_bh(bh);
EXT4_ERROR_INODE(inode,
"ppos %d > depth %d", ppos, depth);
ret = -EIO;
ret = -EFSCORRUPTED;
goto err;
}
path[ppos].p_bh = bh;
Expand Down Expand Up @@ -959,7 +960,7 @@ static int ext4_ext_insert_index(handle_t *handle, struct inode *inode,
EXT4_ERROR_INODE(inode,
"logical %d == ei_block %d!",
logical, le32_to_cpu(curp->p_idx->ei_block));
return -EIO;
return -EFSCORRUPTED;
}

if (unlikely(le16_to_cpu(curp->p_hdr->eh_entries)
Expand All @@ -968,7 +969,7 @@ static int ext4_ext_insert_index(handle_t *handle, struct inode *inode,
"eh_entries %d >= eh_max %d!",
le16_to_cpu(curp->p_hdr->eh_entries),
le16_to_cpu(curp->p_hdr->eh_max));
return -EIO;
return -EFSCORRUPTED;
}

if (logical > le32_to_cpu(curp->p_idx->ei_block)) {
Expand All @@ -992,7 +993,7 @@ static int ext4_ext_insert_index(handle_t *handle, struct inode *inode,

if (unlikely(ix > EXT_MAX_INDEX(curp->p_hdr))) {
EXT4_ERROR_INODE(inode, "ix > EXT_MAX_INDEX!");
return -EIO;
return -EFSCORRUPTED;
}

ix->ei_block = cpu_to_le32(logical);
Expand All @@ -1001,7 +1002,7 @@ static int ext4_ext_insert_index(handle_t *handle, struct inode *inode,

if (unlikely(ix > EXT_LAST_INDEX(curp->p_hdr))) {
EXT4_ERROR_INODE(inode, "ix > EXT_LAST_INDEX!");
return -EIO;
return -EFSCORRUPTED;
}

err = ext4_ext_dirty(handle, inode, curp);
Expand Down Expand Up @@ -1042,7 +1043,7 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode,
* border from split point */
if (unlikely(path[depth].p_ext > EXT_MAX_EXTENT(path[depth].p_hdr))) {
EXT4_ERROR_INODE(inode, "p_ext > EXT_MAX_EXTENT!");
return -EIO;
return -EFSCORRUPTED;
}
if (path[depth].p_ext != EXT_MAX_EXTENT(path[depth].p_hdr)) {
border = path[depth].p_ext[1].ee_block;
Expand Down Expand Up @@ -1086,7 +1087,7 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode,
newblock = ablocks[--a];
if (unlikely(newblock == 0)) {
EXT4_ERROR_INODE(inode, "newblock == 0!");
err = -EIO;
err = -EFSCORRUPTED;
goto cleanup;
}
bh = sb_getblk_gfp(inode->i_sb, newblock, __GFP_MOVABLE | GFP_NOFS);
Expand All @@ -1112,7 +1113,7 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode,
EXT4_ERROR_INODE(inode, "eh_entries %d != eh_max %d!",
path[depth].p_hdr->eh_entries,
path[depth].p_hdr->eh_max);
err = -EIO;
err = -EFSCORRUPTED;
goto cleanup;
}
/* start copy from next extent */
Expand Down Expand Up @@ -1151,7 +1152,7 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode,
k = depth - at - 1;
if (unlikely(k < 0)) {
EXT4_ERROR_INODE(inode, "k %d < 0!", k);
err = -EIO;
err = -EFSCORRUPTED;
goto cleanup;
}
if (k)
Expand Down Expand Up @@ -1191,7 +1192,7 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode,
EXT4_ERROR_INODE(inode,
"EXT_MAX_INDEX != EXT_LAST_INDEX ee_block %d!",
le32_to_cpu(path[i].p_ext->ee_block));
err = -EIO;
err = -EFSCORRUPTED;
goto cleanup;
}
/* start copy indexes */
Expand Down Expand Up @@ -1425,7 +1426,7 @@ static int ext4_ext_search_left(struct inode *inode,

if (unlikely(path == NULL)) {
EXT4_ERROR_INODE(inode, "path == NULL *logical %d!", *logical);
return -EIO;
return -EFSCORRUPTED;
}
depth = path->p_depth;
*phys = 0;
Expand All @@ -1444,7 +1445,7 @@ static int ext4_ext_search_left(struct inode *inode,
EXT4_ERROR_INODE(inode,
"EXT_FIRST_EXTENT != ex *logical %d ee_block %d!",
*logical, le32_to_cpu(ex->ee_block));
return -EIO;
return -EFSCORRUPTED;
}
while (--depth >= 0) {
ix = path[depth].p_idx;
Expand All @@ -1455,7 +1456,7 @@ static int ext4_ext_search_left(struct inode *inode,
EXT_FIRST_INDEX(path[depth].p_hdr) != NULL ?
le32_to_cpu(EXT_FIRST_INDEX(path[depth].p_hdr)->ei_block) : 0,
depth);
return -EIO;
return -EFSCORRUPTED;
}
}
return 0;
Expand All @@ -1465,7 +1466,7 @@ static int ext4_ext_search_left(struct inode *inode,
EXT4_ERROR_INODE(inode,
"logical %d < ee_block %d + ee_len %d!",
*logical, le32_to_cpu(ex->ee_block), ee_len);
return -EIO;
return -EFSCORRUPTED;
}

*logical = le32_to_cpu(ex->ee_block) + ee_len - 1;
Expand Down Expand Up @@ -1495,7 +1496,7 @@ static int ext4_ext_search_right(struct inode *inode,

if (unlikely(path == NULL)) {
EXT4_ERROR_INODE(inode, "path == NULL *logical %d!", *logical);
return -EIO;
return -EFSCORRUPTED;
}
depth = path->p_depth;
*phys = 0;
Expand All @@ -1514,15 +1515,15 @@ static int ext4_ext_search_right(struct inode *inode,
EXT4_ERROR_INODE(inode,
"first_extent(path[%d].p_hdr) != ex",
depth);
return -EIO;
return -EFSCORRUPTED;
}
while (--depth >= 0) {
ix = path[depth].p_idx;
if (unlikely(ix != EXT_FIRST_INDEX(path[depth].p_hdr))) {
EXT4_ERROR_INODE(inode,
"ix != EXT_FIRST_INDEX *logical %d!",
*logical);
return -EIO;
return -EFSCORRUPTED;
}
}
goto found_extent;
Expand All @@ -1532,7 +1533,7 @@ static int ext4_ext_search_right(struct inode *inode,
EXT4_ERROR_INODE(inode,
"logical %d < ee_block %d + ee_len %d!",
*logical, le32_to_cpu(ex->ee_block), ee_len);
return -EIO;
return -EFSCORRUPTED;
}

if (ex != EXT_LAST_EXTENT(path[depth].p_hdr)) {
Expand Down Expand Up @@ -1670,7 +1671,7 @@ static int ext4_ext_correct_indexes(handle_t *handle, struct inode *inode,
if (unlikely(ex == NULL || eh == NULL)) {
EXT4_ERROR_INODE(inode,
"ex %p == NULL or eh %p == NULL", ex, eh);
return -EIO;
return -EFSCORRUPTED;
}

if (depth == 0) {
Expand Down Expand Up @@ -1938,14 +1939,14 @@ int ext4_ext_insert_extent(handle_t *handle, struct inode *inode,
mb_flags |= EXT4_MB_DELALLOC_RESERVED;
if (unlikely(ext4_ext_get_actual_len(newext) == 0)) {
EXT4_ERROR_INODE(inode, "ext4_ext_get_actual_len(newext) == 0");
return -EIO;
return -EFSCORRUPTED;
}
depth = ext_depth(inode);
ex = path[depth].p_ext;
eh = path[depth].p_hdr;
if (unlikely(path[depth].p_hdr == NULL)) {
EXT4_ERROR_INODE(inode, "path[%d].p_hdr == NULL", depth);
return -EIO;
return -EFSCORRUPTED;
}

/* try to insert block into found extent and return */
Expand Down Expand Up @@ -2172,7 +2173,7 @@ static int ext4_fill_fiemap_extents(struct inode *inode,
if (unlikely(path[depth].p_hdr == NULL)) {
up_read(&EXT4_I(inode)->i_data_sem);
EXT4_ERROR_INODE(inode, "path[%d].p_hdr == NULL", depth);
err = -EIO;
err = -EFSCORRUPTED;
break;
}
ex = path[depth].p_ext;
Expand Down Expand Up @@ -2241,7 +2242,7 @@ static int ext4_fill_fiemap_extents(struct inode *inode,

if (unlikely(es.es_len == 0)) {
EXT4_ERROR_INODE(inode, "es.es_len == 0");
err = -EIO;
err = -EFSCORRUPTED;
break;
}

Expand All @@ -2264,7 +2265,7 @@ static int ext4_fill_fiemap_extents(struct inode *inode,
"next extent == %u, next "
"delalloc extent = %u",
next, next_del);
err = -EIO;
err = -EFSCORRUPTED;
break;
}
}
Expand Down Expand Up @@ -2363,7 +2364,7 @@ static int ext4_ext_rm_idx(handle_t *handle, struct inode *inode,
leaf = ext4_idx_pblock(path->p_idx);
if (unlikely(path->p_hdr->eh_entries == 0)) {
EXT4_ERROR_INODE(inode, "path->p_hdr->eh_entries == 0");
return -EIO;
return -EFSCORRUPTED;
}
err = ext4_ext_get_access(handle, inode, path);
if (err)
Expand Down Expand Up @@ -2612,7 +2613,7 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode,
eh = path[depth].p_hdr;
if (unlikely(path[depth].p_hdr == NULL)) {
EXT4_ERROR_INODE(inode, "path[%d].p_hdr == NULL", depth);
return -EIO;
return -EFSCORRUPTED;
}
/* find where to start removing */
ex = path[depth].p_ext;
Expand Down Expand Up @@ -2666,7 +2667,7 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode,
"on extent %u:%u",
start, end, ex_ee_block,
ex_ee_block + ex_ee_len - 1);
err = -EIO;
err = -EFSCORRUPTED;
goto out;
} else if (a != ex_ee_block) {
/* remove tail of the extent */
Expand Down Expand Up @@ -2841,7 +2842,7 @@ int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start,
EXT4_ERROR_INODE(inode,
"path[%d].p_hdr == NULL",
depth);
err = -EIO;
err = -EFSCORRUPTED;
}
goto out;
}
Expand Down Expand Up @@ -2920,7 +2921,7 @@ int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start,
i = 0;

if (ext4_ext_check(inode, path[0].p_hdr, depth, 0)) {
err = -EIO;
err = -EFSCORRUPTED;
goto out;
}
}
Expand Down Expand Up @@ -2978,7 +2979,7 @@ int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start,
* Should be a no-op if we did IO above. */
cond_resched();
if (WARN_ON(i + 1 > depth)) {
err = -EIO;
err = -EFSCORRUPTED;
break;
}
path[i + 1].p_bh = bh;
Expand Down Expand Up @@ -3345,7 +3346,7 @@ static int ext4_split_extent(handle_t *handle,
if (!ex) {
EXT4_ERROR_INODE(inode, "unexpected hole at %lu",
(unsigned long) map->m_lblk);
return -EIO;
return -EFSCORRUPTED;
}
unwritten = ext4_ext_is_unwritten(ex);
split_flag1 = 0;
Expand Down Expand Up @@ -3973,7 +3974,7 @@ convert_initialized_extent(handle_t *handle, struct inode *inode,
if (!ex) {
EXT4_ERROR_INODE(inode, "unexpected hole at %lu",
(unsigned long) map->m_lblk);
return -EIO;
return -EFSCORRUPTED;
}
}

Expand Down Expand Up @@ -4311,7 +4312,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
"lblock: %lu, depth: %d pblock %lld",
(unsigned long) map->m_lblk, depth,
path[depth].p_block);
err = -EIO;
err = -EFSCORRUPTED;
goto out2;
}

Expand Down Expand Up @@ -5274,7 +5275,7 @@ ext4_ext_shift_path_extents(struct ext4_ext_path *path, ext4_lblk_t shift,
if (depth == path->p_depth) {
ex_start = path[depth].p_ext;
if (!ex_start)
return -EIO;
return -EFSCORRUPTED;

ex_last = EXT_LAST_EXTENT(path[depth].p_hdr);

Expand Down Expand Up @@ -5414,7 +5415,7 @@ ext4_ext_shift_extents(struct inode *inode, handle_t *handle,
if (!extent) {
EXT4_ERROR_INODE(inode, "unexpected hole at %lu",
(unsigned long) *iterator);
return -EIO;
return -EFSCORRUPTED;
}
if (SHIFT == SHIFT_LEFT && *iterator >
le32_to_cpu(extent->ee_block)) {
Expand Down
1 change: 1 addition & 0 deletions fs/ext4/ialloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1116,6 +1116,7 @@ struct inode *ext4_orphan_get(struct super_block *sb, unsigned long ino)
/* Error cases - e2fsck has already cleaned up for us */
if (ino > max_ino) {
ext4_warning(sb, "bad orphan ino %lu! e2fsck was run?", ino);
err = -EFSCORRUPTED;
goto error;
}

Expand Down
2 changes: 1 addition & 1 deletion fs/ext4/indirect.c
Original file line number Diff line number Diff line change
Expand Up @@ -566,7 +566,7 @@ int ext4_ind_map_blocks(handle_t *handle, struct inode *inode,
EXT4_FEATURE_RO_COMPAT_BIGALLOC)) {
EXT4_ERROR_INODE(inode, "Can't allocate blocks for "
"non-extent mapped inodes with bigalloc");
return -EUCLEAN;
return -EFSCORRUPTED;
}

/* Set up for the direct block allocation */
Expand Down
Loading

0 comments on commit 6a797d2

Please sign in to comment.