Commit 6a797d27 authored by Darrick J. Wong's avatar Darrick J. Wong Committed by Theodore Ts'o

ext4: call out CRC and corruption errors with specific error codes

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: default avatarDarrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: default avatarTheodore Ts'o <tytso@mit.edu>
parent 8c81bd8f
...@@ -203,7 +203,7 @@ static int ext4_init_block_bitmap(struct super_block *sb, ...@@ -203,7 +203,7 @@ static int ext4_init_block_bitmap(struct super_block *sb,
count); count);
} }
set_bit(EXT4_GROUP_INFO_IBITMAP_CORRUPT_BIT, &grp->bb_state); set_bit(EXT4_GROUP_INFO_IBITMAP_CORRUPT_BIT, &grp->bb_state);
return -EIO; return -EFSBADCRC;
} }
memset(bh->b_data, 0, sb->s_blocksize); memset(bh->b_data, 0, sb->s_blocksize);
......
...@@ -234,7 +234,7 @@ int ext4_check_blockref(const char *function, unsigned int line, ...@@ -234,7 +234,7 @@ int ext4_check_blockref(const char *function, unsigned int line,
es->s_last_error_block = cpu_to_le64(blk); es->s_last_error_block = cpu_to_le64(blk);
ext4_error_inode(inode, function, line, blk, ext4_error_inode(inode, function, line, blk,
"invalid block"); "invalid block");
return -EIO; return -EFSCORRUPTED;
} }
} }
return 0; return 0;
......
...@@ -621,14 +621,14 @@ int ext4_check_all_de(struct inode *dir, struct buffer_head *bh, void *buf, ...@@ -621,14 +621,14 @@ int ext4_check_all_de(struct inode *dir, struct buffer_head *bh, void *buf,
while ((char *) de < top) { while ((char *) de < top) {
if (ext4_check_dir_entry(dir, NULL, de, bh, if (ext4_check_dir_entry(dir, NULL, de, bh,
buf, buf_size, offset)) buf, buf_size, offset))
return -EIO; return -EFSCORRUPTED;
nlen = EXT4_DIR_REC_LEN(de->name_len); nlen = EXT4_DIR_REC_LEN(de->name_len);
rlen = ext4_rec_len_from_disk(de->rec_len, buf_size); rlen = ext4_rec_len_from_disk(de->rec_len, buf_size);
de = (struct ext4_dir_entry_2 *)((char *)de + rlen); de = (struct ext4_dir_entry_2 *)((char *)de + rlen);
offset += rlen; offset += rlen;
} }
if ((char *) de > top) if ((char *) de > top)
return -EIO; return -EFSCORRUPTED;
return 0; return 0;
} }
......
...@@ -3064,4 +3064,7 @@ extern void ext4_resize_end(struct super_block *sb); ...@@ -3064,4 +3064,7 @@ extern void ext4_resize_end(struct super_block *sb);
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
#define EFSBADCRC EBADMSG /* Bad CRC detected */
#define EFSCORRUPTED EUCLEAN /* Filesystem is corrupted */
#endif /* _EXT4_H */ #endif /* _EXT4_H */
This diff is collapsed.
...@@ -1116,6 +1116,7 @@ struct inode *ext4_orphan_get(struct super_block *sb, unsigned long ino) ...@@ -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 */ /* Error cases - e2fsck has already cleaned up for us */
if (ino > max_ino) { if (ino > max_ino) {
ext4_warning(sb, "bad orphan ino %lu! e2fsck was run?", ino); ext4_warning(sb, "bad orphan ino %lu! e2fsck was run?", ino);
err = -EFSCORRUPTED;
goto error; goto error;
} }
......
...@@ -566,7 +566,7 @@ int ext4_ind_map_blocks(handle_t *handle, struct inode *inode, ...@@ -566,7 +566,7 @@ int ext4_ind_map_blocks(handle_t *handle, struct inode *inode,
EXT4_FEATURE_RO_COMPAT_BIGALLOC)) { EXT4_FEATURE_RO_COMPAT_BIGALLOC)) {
EXT4_ERROR_INODE(inode, "Can't allocate blocks for " EXT4_ERROR_INODE(inode, "Can't allocate blocks for "
"non-extent mapped inodes with bigalloc"); "non-extent mapped inodes with bigalloc");
return -EUCLEAN; return -EFSCORRUPTED;
} }
/* Set up for the direct block allocation */ /* Set up for the direct block allocation */
......
...@@ -378,7 +378,7 @@ static int __check_block_validity(struct inode *inode, const char *func, ...@@ -378,7 +378,7 @@ static int __check_block_validity(struct inode *inode, const char *func,
"lblock %lu mapped to illegal pblock " "lblock %lu mapped to illegal pblock "
"(length %d)", (unsigned long) map->m_lblk, "(length %d)", (unsigned long) map->m_lblk,
map->m_len); map->m_len);
return -EIO; return -EFSCORRUPTED;
} }
return 0; return 0;
} }
...@@ -480,7 +480,7 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode, ...@@ -480,7 +480,7 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
/* We can handle the block number less than EXT_MAX_BLOCKS */ /* We can handle the block number less than EXT_MAX_BLOCKS */
if (unlikely(map->m_lblk >= EXT_MAX_BLOCKS)) if (unlikely(map->m_lblk >= EXT_MAX_BLOCKS))
return -EIO; return -EFSCORRUPTED;
/* Lookup extent status tree firstly */ /* Lookup extent status tree firstly */
if (ext4_es_lookup_extent(inode, map->m_lblk, &es)) { if (ext4_es_lookup_extent(inode, map->m_lblk, &es)) {
...@@ -3863,7 +3863,7 @@ static int __ext4_get_inode_loc(struct inode *inode, ...@@ -3863,7 +3863,7 @@ static int __ext4_get_inode_loc(struct inode *inode,
iloc->bh = NULL; iloc->bh = NULL;
if (!ext4_valid_inum(sb, inode->i_ino)) if (!ext4_valid_inum(sb, inode->i_ino))
return -EIO; return -EFSCORRUPTED;
iloc->block_group = (inode->i_ino - 1) / EXT4_INODES_PER_GROUP(sb); iloc->block_group = (inode->i_ino - 1) / EXT4_INODES_PER_GROUP(sb);
gdp = ext4_get_group_desc(sb, iloc->block_group, NULL); gdp = ext4_get_group_desc(sb, iloc->block_group, NULL);
...@@ -4111,7 +4111,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) ...@@ -4111,7 +4111,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
EXT4_ERROR_INODE(inode, "bad extra_isize (%u != %u)", EXT4_ERROR_INODE(inode, "bad extra_isize (%u != %u)",
EXT4_GOOD_OLD_INODE_SIZE + ei->i_extra_isize, EXT4_GOOD_OLD_INODE_SIZE + ei->i_extra_isize,
EXT4_INODE_SIZE(inode->i_sb)); EXT4_INODE_SIZE(inode->i_sb));
ret = -EIO; ret = -EFSCORRUPTED;
goto bad_inode; goto bad_inode;
} }
} else } else
...@@ -4131,7 +4131,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) ...@@ -4131,7 +4131,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
if (!ext4_inode_csum_verify(inode, raw_inode, ei)) { if (!ext4_inode_csum_verify(inode, raw_inode, ei)) {
EXT4_ERROR_INODE(inode, "checksum invalid"); EXT4_ERROR_INODE(inode, "checksum invalid");
ret = -EIO; ret = -EFSBADCRC;
goto bad_inode; goto bad_inode;
} }
...@@ -4246,7 +4246,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) ...@@ -4246,7 +4246,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
!ext4_data_block_valid(EXT4_SB(sb), ei->i_file_acl, 1)) { !ext4_data_block_valid(EXT4_SB(sb), ei->i_file_acl, 1)) {
EXT4_ERROR_INODE(inode, "bad extended attribute block %llu", EXT4_ERROR_INODE(inode, "bad extended attribute block %llu",
ei->i_file_acl); ei->i_file_acl);
ret = -EIO; ret = -EFSCORRUPTED;
goto bad_inode; goto bad_inode;
} else if (!ext4_has_inline_data(inode)) { } else if (!ext4_has_inline_data(inode)) {
if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) { if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) {
...@@ -4297,7 +4297,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) ...@@ -4297,7 +4297,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
} else if (ino == EXT4_BOOT_LOADER_INO) { } else if (ino == EXT4_BOOT_LOADER_INO) {
make_bad_inode(inode); make_bad_inode(inode);
} else { } else {
ret = -EIO; ret = -EFSCORRUPTED;
EXT4_ERROR_INODE(inode, "bogus i_mode (%o)", inode->i_mode); EXT4_ERROR_INODE(inode, "bogus i_mode (%o)", inode->i_mode);
goto bad_inode; goto bad_inode;
} }
...@@ -4315,7 +4315,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) ...@@ -4315,7 +4315,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
struct inode *ext4_iget_normal(struct super_block *sb, unsigned long ino) struct inode *ext4_iget_normal(struct super_block *sb, unsigned long ino)
{ {
if (ino < EXT4_FIRST_INO(sb) && ino != EXT4_ROOT_INO) if (ino < EXT4_FIRST_INO(sb) && ino != EXT4_ROOT_INO)
return ERR_PTR(-EIO); return ERR_PTR(-EFSCORRUPTED);
return ext4_iget(sb, ino); return ext4_iget(sb, ino);
} }
......
...@@ -98,10 +98,12 @@ static int read_mmp_block(struct super_block *sb, struct buffer_head **bh, ...@@ -98,10 +98,12 @@ static int read_mmp_block(struct super_block *sb, struct buffer_head **bh,
} }
mmp = (struct mmp_struct *)((*bh)->b_data); mmp = (struct mmp_struct *)((*bh)->b_data);
if (le32_to_cpu(mmp->mmp_magic) == EXT4_MMP_MAGIC && if (le32_to_cpu(mmp->mmp_magic) != EXT4_MMP_MAGIC)
ext4_mmp_csum_verify(sb, mmp)) ret = -EFSCORRUPTED;
else if (!ext4_mmp_csum_verify(sb, mmp))
ret = -EFSBADCRC;
else
return 0; return 0;
ret = -EINVAL;
warn_exit: warn_exit:
ext4_warning(sb, "Error %d while reading MMP block %llu", ext4_warning(sb, "Error %d while reading MMP block %llu",
......
...@@ -109,7 +109,7 @@ static struct buffer_head *__ext4_read_dirblock(struct inode *inode, ...@@ -109,7 +109,7 @@ static struct buffer_head *__ext4_read_dirblock(struct inode *inode,
if (!bh) { if (!bh) {
ext4_error_inode(inode, func, line, block, ext4_error_inode(inode, func, line, block,
"Directory hole found"); "Directory hole found");
return ERR_PTR(-EIO); return ERR_PTR(-EFSCORRUPTED);
} }
dirent = (struct ext4_dir_entry *) bh->b_data; dirent = (struct ext4_dir_entry *) bh->b_data;
/* Determine whether or not we have an index block */ /* Determine whether or not we have an index block */
...@@ -124,7 +124,7 @@ static struct buffer_head *__ext4_read_dirblock(struct inode *inode, ...@@ -124,7 +124,7 @@ static struct buffer_head *__ext4_read_dirblock(struct inode *inode,
if (!is_dx_block && type == INDEX) { if (!is_dx_block && type == INDEX) {
ext4_error_inode(inode, func, line, block, ext4_error_inode(inode, func, line, block,
"directory leaf block found instead of index block"); "directory leaf block found instead of index block");
return ERR_PTR(-EIO); return ERR_PTR(-EFSCORRUPTED);
} }
if (!ext4_has_metadata_csum(inode->i_sb) || if (!ext4_has_metadata_csum(inode->i_sb) ||
buffer_verified(bh)) buffer_verified(bh))
...@@ -142,7 +142,7 @@ static struct buffer_head *__ext4_read_dirblock(struct inode *inode, ...@@ -142,7 +142,7 @@ static struct buffer_head *__ext4_read_dirblock(struct inode *inode,
ext4_error_inode(inode, func, line, block, ext4_error_inode(inode, func, line, block,
"Directory index failed checksum"); "Directory index failed checksum");
brelse(bh); brelse(bh);
return ERR_PTR(-EIO); return ERR_PTR(-EFSBADCRC);
} }
} }
if (!is_dx_block) { if (!is_dx_block) {
...@@ -152,7 +152,7 @@ static struct buffer_head *__ext4_read_dirblock(struct inode *inode, ...@@ -152,7 +152,7 @@ static struct buffer_head *__ext4_read_dirblock(struct inode *inode,
ext4_error_inode(inode, func, line, block, ext4_error_inode(inode, func, line, block,
"Directory block failed checksum"); "Directory block failed checksum");
brelse(bh); brelse(bh);
return ERR_PTR(-EIO); return ERR_PTR(-EFSBADCRC);
} }
} }
return bh; return bh;
...@@ -1570,19 +1570,19 @@ static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, unsi ...@@ -1570,19 +1570,19 @@ static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, unsi
brelse(bh); brelse(bh);
if (!ext4_valid_inum(dir->i_sb, ino)) { if (!ext4_valid_inum(dir->i_sb, ino)) {
EXT4_ERROR_INODE(dir, "bad inode number: %u", ino); EXT4_ERROR_INODE(dir, "bad inode number: %u", ino);
return ERR_PTR(-EIO); return ERR_PTR(-EFSCORRUPTED);
} }
if (unlikely(ino == dir->i_ino)) { if (unlikely(ino == dir->i_ino)) {
EXT4_ERROR_INODE(dir, "'%pd' linked to parent dir", EXT4_ERROR_INODE(dir, "'%pd' linked to parent dir",
dentry); dentry);
return ERR_PTR(-EIO); return ERR_PTR(-EFSCORRUPTED);
} }
inode = ext4_iget_normal(dir->i_sb, ino); inode = ext4_iget_normal(dir->i_sb, ino);
if (inode == ERR_PTR(-ESTALE)) { if (inode == ERR_PTR(-ESTALE)) {
EXT4_ERROR_INODE(dir, EXT4_ERROR_INODE(dir,
"deleted inode referenced: %u", "deleted inode referenced: %u",
ino); ino);
return ERR_PTR(-EIO); return ERR_PTR(-EFSCORRUPTED);
} }
if (!IS_ERR(inode) && ext4_encrypted_inode(dir) && if (!IS_ERR(inode) && ext4_encrypted_inode(dir) &&
(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
...@@ -1619,7 +1619,7 @@ struct dentry *ext4_get_parent(struct dentry *child) ...@@ -1619,7 +1619,7 @@ struct dentry *ext4_get_parent(struct dentry *child)
if (!ext4_valid_inum(d_inode(child)->i_sb, ino)) { if (!ext4_valid_inum(d_inode(child)->i_sb, ino)) {
EXT4_ERROR_INODE(d_inode(child), EXT4_ERROR_INODE(d_inode(child),
"bad parent inode number: %u", ino); "bad parent inode number: %u", ino);
return ERR_PTR(-EIO); return ERR_PTR(-EFSCORRUPTED);
} }
return d_obtain_alias(ext4_iget_normal(d_inode(child)->i_sb, ino)); return d_obtain_alias(ext4_iget_normal(d_inode(child)->i_sb, ino));
...@@ -1807,7 +1807,7 @@ int ext4_find_dest_de(struct inode *dir, struct inode *inode, ...@@ -1807,7 +1807,7 @@ int ext4_find_dest_de(struct inode *dir, struct inode *inode,
while ((char *) de <= top) { while ((char *) de <= top) {
if (ext4_check_dir_entry(dir, NULL, de, bh, if (ext4_check_dir_entry(dir, NULL, de, bh,
buf, buf_size, offset)) { buf, buf_size, offset)) {
res = -EIO; res = -EFSCORRUPTED;
goto return_result; goto return_result;
} }
/* Provide crypto context and crypto buffer to ext4 match */ /* Provide crypto context and crypto buffer to ext4 match */
...@@ -1967,7 +1967,7 @@ static int make_indexed_dir(handle_t *handle, struct ext4_filename *fname, ...@@ -1967,7 +1967,7 @@ static int make_indexed_dir(handle_t *handle, struct ext4_filename *fname,
if ((char *) de >= (((char *) root) + blocksize)) { if ((char *) de >= (((char *) root) + blocksize)) {
EXT4_ERROR_INODE(dir, "invalid rec_len for '..'"); EXT4_ERROR_INODE(dir, "invalid rec_len for '..'");
brelse(bh); brelse(bh);
return -EIO; return -EFSCORRUPTED;
} }
len = ((char *) root) + (blocksize - csum_size) - (char *) de; len = ((char *) root) + (blocksize - csum_size) - (char *) de;
...@@ -2315,7 +2315,7 @@ int ext4_generic_delete_entry(handle_t *handle, ...@@ -2315,7 +2315,7 @@ int ext4_generic_delete_entry(handle_t *handle,
while (i < buf_size - csum_size) { while (i < buf_size - csum_size) {
if (ext4_check_dir_entry(dir, NULL, de, bh, if (ext4_check_dir_entry(dir, NULL, de, bh,
bh->b_data, bh->b_size, i)) bh->b_data, bh->b_size, i))
return -EIO; return -EFSCORRUPTED;
if (de == de_del) { if (de == de_del) {
if (pde) if (pde)
pde->rec_len = ext4_rec_len_to_disk( pde->rec_len = ext4_rec_len_to_disk(
...@@ -2934,7 +2934,7 @@ static int ext4_rmdir(struct inode *dir, struct dentry *dentry) ...@@ -2934,7 +2934,7 @@ static int ext4_rmdir(struct inode *dir, struct dentry *dentry)
inode = d_inode(dentry); inode = d_inode(dentry);
retval = -EIO; retval = -EFSCORRUPTED;
if (le32_to_cpu(de->inode) != inode->i_ino) if (le32_to_cpu(de->inode) != inode->i_ino)
goto end_rmdir; goto end_rmdir;
...@@ -3008,7 +3008,7 @@ static int ext4_unlink(struct inode *dir, struct dentry *dentry) ...@@ -3008,7 +3008,7 @@ static int ext4_unlink(struct inode *dir, struct dentry *dentry)
inode = d_inode(dentry); inode = d_inode(dentry);
retval = -EIO; retval = -EFSCORRUPTED;
if (le32_to_cpu(de->inode) != inode->i_ino) if (le32_to_cpu(de->inode) != inode->i_ino)
goto end_unlink; goto end_unlink;
...@@ -3310,7 +3310,7 @@ static int ext4_rename_dir_prepare(handle_t *handle, struct ext4_renament *ent) ...@@ -3310,7 +3310,7 @@ static int ext4_rename_dir_prepare(handle_t *handle, struct ext4_renament *ent)
if (!ent->dir_bh) if (!ent->dir_bh)
return retval; return retval;
if (le32_to_cpu(ent->parent_de->inode) != ent->dir->i_ino) if (le32_to_cpu(ent->parent_de->inode) != ent->dir->i_ino)
return -EIO; return -EFSCORRUPTED;
BUFFER_TRACE(ent->dir_bh, "get_write_access"); BUFFER_TRACE(ent->dir_bh, "get_write_access");
return ext4_journal_get_write_access(handle, ent->dir_bh); return ext4_journal_get_write_access(handle, ent->dir_bh);
} }
......
...@@ -490,6 +490,12 @@ const char *ext4_decode_error(struct super_block *sb, int errno, ...@@ -490,6 +490,12 @@ const char *ext4_decode_error(struct super_block *sb, int errno,
char *errstr = NULL; char *errstr = NULL;
switch (errno) { switch (errno) {
case -EFSCORRUPTED:
errstr = "Corrupt filesystem";
break;
case -EFSBADCRC:
errstr = "Filesystem failed CRC";
break;
case -EIO: case -EIO:
errstr = "IO failure"; errstr = "IO failure";
break; break;
...@@ -3192,6 +3198,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) ...@@ -3192,6 +3198,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
ext4_msg(sb, KERN_ERR, "VFS: Found ext4 filesystem with " ext4_msg(sb, KERN_ERR, "VFS: Found ext4 filesystem with "
"invalid superblock checksum. Run e2fsck?"); "invalid superblock checksum. Run e2fsck?");
silent = 1; silent = 1;
ret = -EFSBADCRC;
goto cantfind_ext4; goto cantfind_ext4;
} }
...@@ -3612,6 +3619,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) ...@@ -3612,6 +3619,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
} }
if (!ext4_check_descriptors(sb, &first_not_zeroed)) { if (!ext4_check_descriptors(sb, &first_not_zeroed)) {
ext4_msg(sb, KERN_ERR, "group descriptors corrupted!"); ext4_msg(sb, KERN_ERR, "group descriptors corrupted!");
ret = -EFSCORRUPTED;
goto failed_mount2; goto failed_mount2;
} }
...@@ -4664,7 +4672,7 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data) ...@@ -4664,7 +4672,7 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
"ext4_remount: Checksum for group %u failed (%u!=%u)", "ext4_remount: Checksum for group %u failed (%u!=%u)",
g, le16_to_cpu(ext4_group_desc_csum(sbi, g, gdp)), g, le16_to_cpu(ext4_group_desc_csum(sbi, g, gdp)),
le16_to_cpu(gdp->bg_checksum)); le16_to_cpu(gdp->bg_checksum));
err = -EINVAL; err = -EFSBADCRC;
goto restore_opts; goto restore_opts;
} }
} }
......
...@@ -57,7 +57,7 @@ static const char *ext4_encrypted_follow_link(struct dentry *dentry, void **cook ...@@ -57,7 +57,7 @@ static const char *ext4_encrypted_follow_link(struct dentry *dentry, void **cook
sizeof(struct ext4_encrypted_symlink_data) - 1) > sizeof(struct ext4_encrypted_symlink_data) - 1) >
max_size) { max_size) {
/* Symlink data on the disk is corrupted */ /* Symlink data on the disk is corrupted */
res = -EIO; res = -EFSCORRUPTED;
goto errout; goto errout;
} }
plen = (cstr.len < EXT4_FNAME_CRYPTO_DIGEST_SIZE*2) ? plen = (cstr.len < EXT4_FNAME_CRYPTO_DIGEST_SIZE*2) ?
......
...@@ -195,7 +195,7 @@ ext4_xattr_check_names(struct ext4_xattr_entry *entry, void *end, ...@@ -195,7 +195,7 @@ ext4_xattr_check_names(struct ext4_xattr_entry *entry, void *end,
while (!IS_LAST_ENTRY(e)) { while (!IS_LAST_ENTRY(e)) {
struct ext4_xattr_entry *next = EXT4_XATTR_NEXT(e); struct ext4_xattr_entry *next = EXT4_XATTR_NEXT(e);
if ((void *)next >= end) if ((void *)next >= end)
return -EIO; return -EFSCORRUPTED;
e = next; e = next;
} }
...@@ -205,7 +205,7 @@ ext4_xattr_check_names(struct ext4_xattr_entry *entry, void *end, ...@@ -205,7 +205,7 @@ ext4_xattr_check_names(struct ext4_xattr_entry *entry, void *end,
(void *)e + sizeof(__u32) || (void *)e + sizeof(__u32) ||
value_start + le16_to_cpu(entry->e_value_offs) + value_start + le16_to_cpu(entry->e_value_offs) +
le32_to_cpu(entry->e_value_size) > end)) le32_to_cpu(entry->e_value_size) > end))
return -EIO; return -EFSCORRUPTED;
entry = EXT4_XATTR_NEXT(entry); entry = EXT4_XATTR_NEXT(entry);
} }
...@@ -222,9 +222,9 @@ ext4_xattr_check_block(struct inode *inode, struct buffer_head *bh) ...@@ -222,9 +222,9 @@ ext4_xattr_check_block(struct inode *inode, struct buffer_head *bh)
if (BHDR(bh)->h_magic != cpu_to_le32(EXT4_XATTR_MAGIC) || if (BHDR(bh)->h_magic != cpu_to_le32(EXT4_XATTR_MAGIC) ||
BHDR(bh)->h_blocks != cpu_to_le32(1)) BHDR(bh)->h_blocks != cpu_to_le32(1))
return -EIO; return -EFSCORRUPTED;
if (!ext4_xattr_block_csum_verify(inode, bh->b_blocknr, BHDR(bh))) if (!ext4_xattr_block_csum_verify(inode, bh->b_blocknr, BHDR(bh)))
return -EIO; return -EFSBADCRC;
error = ext4_xattr_check_names(BFIRST(bh), bh->b_data + bh->b_size, error = ext4_xattr_check_names(BFIRST(bh), bh->b_data + bh->b_size,
bh->b_data); bh->b_data);
if (!error) if (!error)
...@@ -239,7 +239,7 @@ ext4_xattr_check_entry(struct ext4_xattr_entry *entry, size_t size) ...@@ -239,7 +239,7 @@ ext4_xattr_check_entry(struct ext4_xattr_entry *entry, size_t size)
if (entry->e_value_block != 0 || value_size > size || if (entry->e_value_block != 0 || value_size > size ||
le16_to_cpu(entry->e_value_offs) + value_size > size) le16_to_cpu(entry->e_value_offs) + value_size > size)
return -EIO; return -EFSCORRUPTED;
return 0; return 0;
} }
...@@ -266,7 +266,7 @@ ext4_xattr_find_entry(struct ext4_xattr_entry **pentry, int name_index, ...@@ -266,7 +266,7 @@ ext4_xattr_find_entry(struct ext4_xattr_entry **pentry, int name_index,
} }
*pentry = entry; *pentry = entry;
if (!cmp && ext4_xattr_check_entry(entry, size)) if (!cmp && ext4_xattr_check_entry(entry, size))
return -EIO; return -EFSCORRUPTED;
return cmp ? -ENODATA : 0; return cmp ? -ENODATA : 0;
} }
...@@ -297,13 +297,13 @@ ext4_xattr_block_get(struct inode *inode, int name_index, const char *name, ...@@ -297,13 +297,13 @@ ext4_xattr_block_get(struct inode *inode, int name_index, const char *name,
bad_block: bad_block:
EXT4_ERROR_INODE(inode, "bad block %llu", EXT4_ERROR_INODE(inode, "bad block %llu",
EXT4_I(inode)->i_file_acl); EXT4_I(inode)->i_file_acl);
error = -EIO; error = -EFSCORRUPTED;
goto cleanup; goto cleanup;
} }
ext4_xattr_cache_insert(ext4_mb_cache, bh); ext4_xattr_cache_insert(ext4_mb_cache, bh);
entry = BFIRST(bh); entry = BFIRST(bh);
error = ext4_xattr_find_entry(&entry, name_index, name, bh->b_size, 1); error = ext4_xattr_find_entry(&entry, name_index, name, bh->b_size, 1);
if (error == -EIO) if (error == -EFSCORRUPTED)
goto bad_block; goto bad_block;
if (error) if (error)
goto cleanup; goto cleanup;
...@@ -445,7 +445,7 @@ ext4_xattr_block_list(struct dentry *dentry, char *buffer, size_t buffer_size) ...@@ -445,7 +445,7 @@ ext4_xattr_block_list(struct dentry *dentry, char *buffer, size_t buffer_size)
if (ext4_xattr_check_block(inode, bh)) { if (ext4_xattr_check_block(inode, bh)) {
EXT4_ERROR_INODE(inode, "bad block %llu", EXT4_ERROR_INODE(inode, "bad block %llu",
EXT4_I(inode)->i_file_acl); EXT4_I(inode)->i_file_acl);
error = -EIO; error = -EFSCORRUPTED;
goto cleanup; goto cleanup;
} }
ext4_xattr_cache_insert(ext4_mb_cache, bh); ext4_xattr_cache_insert(ext4_mb_cache, bh);
...@@ -751,7 +751,7 @@ ext4_xattr_block_find(struct inode *inode, struct ext4_xattr_info *i, ...@@ -751,7 +751,7 @@ ext4_xattr_block_find(struct inode *inode, struct ext4_xattr_info *i,
if (ext4_xattr_check_block(inode, bs->bh)) { if (ext4_xattr_check_block(inode, bs->bh)) {
EXT4_ERROR_INODE(inode, "bad block %llu", EXT4_ERROR_INODE(inode, "bad block %llu",
EXT4_I(inode)->i_file_acl); EXT4_I(inode)->i_file_acl);
error = -EIO; error = -EFSCORRUPTED;
goto cleanup; goto cleanup;
} }
/* Find the named attribute. */ /* Find the named attribute. */
...@@ -811,7 +811,7 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode, ...@@ -811,7 +811,7 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode,
bs->bh); bs->bh);
} }
unlock_buffer(bs->bh); unlock_buffer(bs->bh);
if (error == -EIO) if (error == -EFSCORRUPTED)
goto bad_block; goto bad_block;
if (!error) if (!error)
error = ext4_handle_dirty_xattr_block(handle, error = ext4_handle_dirty_xattr_block(handle,
...@@ -855,7 +855,7 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode, ...@@ -855,7 +855,7 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode,
} }
error = ext4_xattr_set_entry(i, s); error = ext4_xattr_set_entry(i, s);
if (error == -EIO) if (error == -EFSCORRUPTED)
goto bad_block; goto bad_block;
if (error) if (error)
goto cleanup; goto cleanup;
...@@ -1314,7 +1314,7 @@ int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize, ...@@ -1314,7 +1314,7 @@ int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize,
if (ext4_xattr_check_block(inode, bh)) { if (ext4_xattr_check_block(inode, bh)) {
EXT4_ERROR_INODE(inode, "bad block %llu", EXT4_ERROR_INODE(inode, "bad block %llu",
EXT4_I(inode)->i_file_acl); EXT4_I(inode)->i_file_acl);
error = -EIO; error = -EFSCORRUPTED;
goto cleanup; goto cleanup;
} }
base = BHDR(bh); base = BHDR(bh);
...@@ -1579,7 +1579,7 @@ ext4_xattr_cmp(struct ext4_xattr_header *header1, ...@@ -1579,7 +1579,7 @@ ext4_xattr_cmp(struct ext4_xattr_header *header1,
memcmp(entry1->e_name, entry2->e_name, entry1->e_name_len)) memcmp(entry1->e_name, entry2->e_name, entry1->e_name_len))
return 1; return 1;
if (entry1->e_value_block != 0 || entry2->e_value_block != 0) if (entry1->e_value_block != 0 || entry2->e_value_block != 0)
return -EIO; return -EFSCORRUPTED;
if (memcmp((char *)header1 + le16_to_cpu(entry1->e_value_offs), if (memcmp((char *)header1 + le16_to_cpu(entry1->e_value_offs),
(char *)header2 + le16_to_cpu(entry2->e_value_offs), (char *)header2 + le16_to_cpu(entry2->e_value_offs),
le32_to_cpu(entry1->e_value_size))) le32_to_cpu(entry1->e_value_size)))
......
...@@ -1558,6 +1558,7 @@ static int journal_get_superblock(journal_t *journal) ...@@ -1558,6 +1558,7 @@ static int journal_get_superblock(journal_t *journal)
/* Check superblock checksum */ /* Check superblock checksum */
if (!jbd2_superblock_csum_verify(journal, sb)) { if (!jbd2_superblock_csum_verify(journal, sb)) {
printk(KERN_ERR "JBD2: journal checksum error\n"); printk(KERN_ERR "JBD2: journal checksum error\n");
err = -EFSBADCRC;
goto out; goto out;
} }
...@@ -1649,7 +1650,7 @@ int jbd2_journal_load(journal_t *journal) ...@@ -1649,7 +1650,7 @@ int jbd2_journal_load(journal_t *journal)
printk(KERN_ERR "JBD2: journal transaction %u on %s " printk(KERN_ERR "JBD2: journal transaction %u on %s "
"is corrupt.\n", journal->j_failed_commit, "is corrupt.\n", journal->j_failed_commit,
journal->j_devname); journal->j_devname);
return -EIO; return -EFSCORRUPTED;
} }
/* OK, we've finished with the dynamic journal bits: /* OK, we've finished with the dynamic journal bits:
......
...@@ -140,7 +140,7 @@ static int jread(struct buffer_head **bhp, journal_t *journal, ...@@ -140,7 +140,7 @@ static int jread(struct buffer_head **bhp, journal_t *journal,
if (offset >= journal->j_maxlen) { if (offset >= journal->j_maxlen) {
printk(KERN_ERR "JBD2: corrupted journal superblock\n"); printk(KERN_ERR "JBD2: corrupted journal superblock\n");
return -EIO; return -EFSCORRUPTED;
} }
err = jbd2_journal_bmap(journal, offset, &blocknr); err = jbd2_journal_bmap(journal, offset, &blocknr);
...@@ -527,7 +527,7 @@ static int do_one_pass(journal_t *journal, ...@@ -527,7 +527,7 @@ static int do_one_pass(journal_t *journal,
printk(KERN_ERR "JBD2: Invalid checksum " printk(KERN_ERR "JBD2: Invalid checksum "
"recovering block %lu in log\n", "recovering block %lu in log\n",
next_log_block); next_log_block);
err = -EIO; err = -EFSBADCRC;
brelse(bh); brelse(bh);
goto failed; goto failed;
} }
...@@ -602,7 +602,7 @@ static int do_one_pass(journal_t *journal, ...@@ -602,7 +602,7 @@ static int do_one_pass(journal_t *journal,
journal, tag, obh->b_data, journal, tag, obh->b_data,
be32_to_cpu(tmp->h_sequence))) { be32_to_cpu(tmp->h_sequence))) {
brelse(obh); brelse(obh);
success = -EIO; success = -EFSBADCRC;
printk(KERN_ERR "JBD2: Invalid " printk(KERN_ERR "JBD2: Invalid "
"checksum recovering " "checksum recovering "
"block %llu in log\n", "block %llu in log\n",
...@@ -851,7 +851,7 @@ static int scan_revoke_records(journal_t *journal, struct buffer_head *bh, ...@@ -851,7 +851,7 @@ static int scan_revoke_records(journal_t *journal, struct buffer_head *bh,
rcount = be32_to_cpu(header->r_count); rcount = be32_to_cpu(header->r_count);
if (!jbd2_revoke_block_csum_verify(journal, header)) if (!jbd2_revoke_block_csum_verify(journal, header))
return -EINVAL; return -EFSBADCRC;
if (jbd2_journal_has_csum_v2or3(journal)) if (jbd2_journal_has_csum_v2or3(journal))
csum_size = sizeof(struct jbd2_journal_revoke_tail); csum_size = sizeof(struct jbd2_journal_revoke_tail);
......
...@@ -1449,4 +1449,7 @@ static inline tid_t jbd2_get_latest_transaction(journal_t *journal) ...@@ -1449,4 +1449,7 @@ static inline tid_t jbd2_get_latest_transaction(journal_t *journal)
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
#define EFSBADCRC EBADMSG /* Bad CRC detected */
#define EFSCORRUPTED EUCLEAN /* Filesystem is corrupted */
#endif /* _LINUX_JBD2_H */ #endif /* _LINUX_JBD2_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment