Commit 878520ac authored by Theodore Ts'o's avatar Theodore Ts'o

ext4: save the error code which triggered an ext4_error() in the superblock

This allows the cause of an ext4_error() report to be categorized
based on whether it was triggered due to an I/O error, or an memory
allocation error, or other possible causes.  Most errors are caused by
a detected file system inconsistency, so the default code stored in
the superblock will be EXT4_ERR_EFSCORRUPTED.

Link: https://lore.kernel.org/r/20191204032335.7683-1-tytso@mit.eduSigned-off-by: default avatarTheodore Ts'o <tytso@mit.edu>
parent a562c687
...@@ -506,6 +506,7 @@ int ext4_wait_block_bitmap(struct super_block *sb, ext4_group_t block_group, ...@@ -506,6 +506,7 @@ int ext4_wait_block_bitmap(struct super_block *sb, ext4_group_t block_group,
return -EFSCORRUPTED; return -EFSCORRUPTED;
wait_on_buffer(bh); wait_on_buffer(bh);
if (!buffer_uptodate(bh)) { if (!buffer_uptodate(bh)) {
ext4_set_errno(sb, EIO);
ext4_error(sb, "Cannot read block bitmap - " ext4_error(sb, "Cannot read block bitmap - "
"block_group = %u, block_bitmap = %llu", "block_group = %u, block_bitmap = %llu",
block_group, (unsigned long long) bh->b_blocknr); block_group, (unsigned long long) bh->b_blocknr);
......
...@@ -1343,7 +1343,8 @@ struct ext4_super_block { ...@@ -1343,7 +1343,8 @@ struct ext4_super_block {
__u8 s_lastcheck_hi; __u8 s_lastcheck_hi;
__u8 s_first_error_time_hi; __u8 s_first_error_time_hi;
__u8 s_last_error_time_hi; __u8 s_last_error_time_hi;
__u8 s_pad[2]; __u8 s_first_error_errcode;
__u8 s_last_error_errcode;
__le16 s_encoding; /* Filename charset encoding */ __le16 s_encoding; /* Filename charset encoding */
__le16 s_encoding_flags; /* Filename charset encoding flags */ __le16 s_encoding_flags; /* Filename charset encoding flags */
__le32 s_reserved[95]; /* Padding to the end of the block */ __le32 s_reserved[95]; /* Padding to the end of the block */
...@@ -1574,6 +1575,32 @@ static inline int ext4_valid_inum(struct super_block *sb, unsigned long ino) ...@@ -1574,6 +1575,32 @@ static inline int ext4_valid_inum(struct super_block *sb, unsigned long ino)
ino <= le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count)); ino <= le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count));
} }
/*
* Error number codes for s_{first,last}_error_errno
*
* Linux errno numbers are architecture specific, so we need to translate
* them into something which is architecture independent. We don't define
* codes for all errno's; just the ones which are most likely to be the cause
* of an ext4_error() call.
*/
#define EXT4_ERR_UNKNOWN 1
#define EXT4_ERR_EIO 2
#define EXT4_ERR_ENOMEM 3
#define EXT4_ERR_EFSBADCRC 4
#define EXT4_ERR_EFSCORRUPTED 5
#define EXT4_ERR_ENOSPC 6
#define EXT4_ERR_ENOKEY 7
#define EXT4_ERR_EROFS 8
#define EXT4_ERR_EFBIG 9
#define EXT4_ERR_EEXIST 10
#define EXT4_ERR_ERANGE 11
#define EXT4_ERR_EOVERFLOW 12
#define EXT4_ERR_EBUSY 13
#define EXT4_ERR_ENOTDIR 14
#define EXT4_ERR_ENOTEMPTY 15
#define EXT4_ERR_ESHUTDOWN 16
#define EXT4_ERR_EFAULT 17
/* /*
* Inode dynamic state flags * Inode dynamic state flags
*/ */
...@@ -2688,6 +2715,7 @@ extern const char *ext4_decode_error(struct super_block *sb, int errno, ...@@ -2688,6 +2715,7 @@ extern const char *ext4_decode_error(struct super_block *sb, int errno,
extern void ext4_mark_group_bitmap_corrupted(struct super_block *sb, extern void ext4_mark_group_bitmap_corrupted(struct super_block *sb,
ext4_group_t block_group, ext4_group_t block_group,
unsigned int flags); unsigned int flags);
extern void ext4_set_errno(struct super_block *sb, int err);
extern __printf(4, 5) extern __printf(4, 5)
void __ext4_error(struct super_block *, const char *, unsigned int, void __ext4_error(struct super_block *, const char *, unsigned int,
......
...@@ -58,6 +58,7 @@ static int ext4_journal_check_start(struct super_block *sb) ...@@ -58,6 +58,7 @@ static int ext4_journal_check_start(struct super_block *sb)
* take the FS itself readonly cleanly. * take the FS itself readonly cleanly.
*/ */
if (journal && is_journal_aborted(journal)) { if (journal && is_journal_aborted(journal)) {
ext4_set_errno(sb, -journal->j_errno);
ext4_abort(sb, "Detected aborted journal"); ext4_abort(sb, "Detected aborted journal");
return -EROFS; return -EROFS;
} }
...@@ -249,6 +250,7 @@ int __ext4_forget(const char *where, unsigned int line, handle_t *handle, ...@@ -249,6 +250,7 @@ int __ext4_forget(const char *where, unsigned int line, handle_t *handle,
if (err) { if (err) {
ext4_journal_abort_handle(where, line, __func__, ext4_journal_abort_handle(where, line, __func__,
bh, handle, err); bh, handle, err);
ext4_set_errno(inode->i_sb, -err);
__ext4_abort(inode->i_sb, where, line, __ext4_abort(inode->i_sb, where, line,
"error %d when attempting revoke", err); "error %d when attempting revoke", err);
} }
...@@ -320,6 +322,7 @@ int __ext4_handle_dirty_metadata(const char *where, unsigned int line, ...@@ -320,6 +322,7 @@ int __ext4_handle_dirty_metadata(const char *where, unsigned int line,
es = EXT4_SB(inode->i_sb)->s_es; es = EXT4_SB(inode->i_sb)->s_es;
es->s_last_error_block = es->s_last_error_block =
cpu_to_le64(bh->b_blocknr); cpu_to_le64(bh->b_blocknr);
ext4_set_errno(inode->i_sb, EIO);
ext4_error_inode(inode, where, line, ext4_error_inode(inode, where, line,
bh->b_blocknr, bh->b_blocknr,
"IO error syncing itable block"); "IO error syncing itable block");
......
...@@ -492,6 +492,7 @@ static int __ext4_ext_check(const char *function, unsigned int line, ...@@ -492,6 +492,7 @@ static int __ext4_ext_check(const char *function, unsigned int line,
return 0; return 0;
corrupted: corrupted:
ext4_set_errno(inode->i_sb, -err);
ext4_error_inode(inode, function, line, 0, ext4_error_inode(inode, function, line, 0,
"pblk %llu bad header/extent: %s - magic %x, " "pblk %llu bad header/extent: %s - magic %x, "
"entries %u, max %u(%u), depth %u(%u)", "entries %u, max %u(%u), depth %u(%u)",
......
...@@ -194,6 +194,7 @@ ext4_read_inode_bitmap(struct super_block *sb, ext4_group_t block_group) ...@@ -194,6 +194,7 @@ ext4_read_inode_bitmap(struct super_block *sb, ext4_group_t block_group)
wait_on_buffer(bh); wait_on_buffer(bh);
if (!buffer_uptodate(bh)) { if (!buffer_uptodate(bh)) {
put_bh(bh); put_bh(bh);
ext4_set_errno(sb, EIO);
ext4_error(sb, "Cannot read inode bitmap - " ext4_error(sb, "Cannot read inode bitmap - "
"block_group = %u, inode_bitmap = %llu", "block_group = %u, inode_bitmap = %llu",
block_group, bitmap_blk); block_group, bitmap_blk);
...@@ -1223,6 +1224,7 @@ struct inode *ext4_orphan_get(struct super_block *sb, unsigned long ino) ...@@ -1223,6 +1224,7 @@ struct inode *ext4_orphan_get(struct super_block *sb, unsigned long ino)
inode = ext4_iget(sb, ino, EXT4_IGET_NORMAL); inode = ext4_iget(sb, ino, EXT4_IGET_NORMAL);
if (IS_ERR(inode)) { if (IS_ERR(inode)) {
err = PTR_ERR(inode); err = PTR_ERR(inode);
ext4_set_errno(sb, -err);
ext4_error(sb, "couldn't read orphan inode %lu (err %d)", ext4_error(sb, "couldn't read orphan inode %lu (err %d)",
ino, err); ino, err);
return inode; return inode;
......
...@@ -98,6 +98,7 @@ int ext4_get_max_inline_size(struct inode *inode) ...@@ -98,6 +98,7 @@ int ext4_get_max_inline_size(struct inode *inode)
error = ext4_get_inode_loc(inode, &iloc); error = ext4_get_inode_loc(inode, &iloc);
if (error) { if (error) {
ext4_set_errno(inode->i_sb, -error);
ext4_error_inode(inode, __func__, __LINE__, 0, ext4_error_inode(inode, __func__, __LINE__, 0,
"can't get inode location %lu", "can't get inode location %lu",
inode->i_ino); inode->i_ino);
...@@ -1761,6 +1762,7 @@ bool empty_inline_dir(struct inode *dir, int *has_inline_data) ...@@ -1761,6 +1762,7 @@ bool empty_inline_dir(struct inode *dir, int *has_inline_data)
err = ext4_get_inode_loc(dir, &iloc); err = ext4_get_inode_loc(dir, &iloc);
if (err) { if (err) {
ext4_set_errno(dir->i_sb, -err);
EXT4_ERROR_INODE(dir, "error %d getting inode %lu block", EXT4_ERROR_INODE(dir, "error %d getting inode %lu block",
err, dir->i_ino); err, dir->i_ino);
return true; return true;
......
...@@ -271,6 +271,7 @@ void ext4_evict_inode(struct inode *inode) ...@@ -271,6 +271,7 @@ void ext4_evict_inode(struct inode *inode)
if (inode->i_blocks) { if (inode->i_blocks) {
err = ext4_truncate(inode); err = ext4_truncate(inode);
if (err) { if (err) {
ext4_set_errno(inode->i_sb, -err);
ext4_error(inode->i_sb, ext4_error(inode->i_sb,
"couldn't truncate inode %lu (err %d)", "couldn't truncate inode %lu (err %d)",
inode->i_ino, err); inode->i_ino, err);
...@@ -2478,10 +2479,12 @@ static int mpage_map_and_submit_extent(handle_t *handle, ...@@ -2478,10 +2479,12 @@ static int mpage_map_and_submit_extent(handle_t *handle,
EXT4_I(inode)->i_disksize = disksize; EXT4_I(inode)->i_disksize = disksize;
up_write(&EXT4_I(inode)->i_data_sem); up_write(&EXT4_I(inode)->i_data_sem);
err2 = ext4_mark_inode_dirty(handle, inode); err2 = ext4_mark_inode_dirty(handle, inode);
if (err2) if (err2) {
ext4_set_errno(inode->i_sb, -err2);
ext4_error(inode->i_sb, ext4_error(inode->i_sb,
"Failed to mark inode %lu dirty", "Failed to mark inode %lu dirty",
inode->i_ino); inode->i_ino);
}
if (!err) if (!err)
err = err2; err = err2;
} }
...@@ -4338,6 +4341,7 @@ static int __ext4_get_inode_loc(struct inode *inode, ...@@ -4338,6 +4341,7 @@ static int __ext4_get_inode_loc(struct inode *inode,
blk_finish_plug(&plug); blk_finish_plug(&plug);
wait_on_buffer(bh); wait_on_buffer(bh);
if (!buffer_uptodate(bh)) { if (!buffer_uptodate(bh)) {
ext4_set_errno(inode->i_sb, EIO);
EXT4_ERROR_INODE_BLOCK(inode, block, EXT4_ERROR_INODE_BLOCK(inode, block,
"unable to read itable block"); "unable to read itable block");
brelse(bh); brelse(bh);
...@@ -4552,6 +4556,7 @@ struct inode *__ext4_iget(struct super_block *sb, unsigned long ino, ...@@ -4552,6 +4556,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_set_errno(inode->i_sb, EFSBADCRC);
ext4_error_inode(inode, function, line, 0, ext4_error_inode(inode, function, line, 0,
"iget: checksum invalid"); "iget: checksum invalid");
ret = -EFSBADCRC; ret = -EFSBADCRC;
...@@ -5090,6 +5095,7 @@ int ext4_write_inode(struct inode *inode, struct writeback_control *wbc) ...@@ -5090,6 +5095,7 @@ int ext4_write_inode(struct inode *inode, struct writeback_control *wbc)
if (wbc->sync_mode == WB_SYNC_ALL && !wbc->for_sync) if (wbc->sync_mode == WB_SYNC_ALL && !wbc->for_sync)
sync_dirty_buffer(iloc.bh); sync_dirty_buffer(iloc.bh);
if (buffer_req(iloc.bh) && !buffer_uptodate(iloc.bh)) { if (buffer_req(iloc.bh) && !buffer_uptodate(iloc.bh)) {
ext4_set_errno(inode->i_sb, EIO);
EXT4_ERROR_INODE_BLOCK(inode, iloc.bh->b_blocknr, EXT4_ERROR_INODE_BLOCK(inode, iloc.bh->b_blocknr,
"IO error syncing inode"); "IO error syncing inode");
err = -EIO; err = -EIO;
......
...@@ -3895,6 +3895,7 @@ ext4_mb_discard_group_preallocations(struct super_block *sb, ...@@ -3895,6 +3895,7 @@ ext4_mb_discard_group_preallocations(struct super_block *sb,
bitmap_bh = ext4_read_block_bitmap(sb, group); bitmap_bh = ext4_read_block_bitmap(sb, group);
if (IS_ERR(bitmap_bh)) { if (IS_ERR(bitmap_bh)) {
err = PTR_ERR(bitmap_bh); err = PTR_ERR(bitmap_bh);
ext4_set_errno(sb, -err);
ext4_error(sb, "Error %d reading block bitmap for %u", ext4_error(sb, "Error %d reading block bitmap for %u",
err, group); err, group);
return 0; return 0;
...@@ -4063,6 +4064,7 @@ void ext4_discard_preallocations(struct inode *inode) ...@@ -4063,6 +4064,7 @@ void ext4_discard_preallocations(struct inode *inode)
err = ext4_mb_load_buddy_gfp(sb, group, &e4b, err = ext4_mb_load_buddy_gfp(sb, group, &e4b,
GFP_NOFS|__GFP_NOFAIL); GFP_NOFS|__GFP_NOFAIL);
if (err) { if (err) {
ext4_set_errno(sb, -err);
ext4_error(sb, "Error %d loading buddy information for %u", ext4_error(sb, "Error %d loading buddy information for %u",
err, group); err, group);
continue; continue;
...@@ -4071,6 +4073,7 @@ void ext4_discard_preallocations(struct inode *inode) ...@@ -4071,6 +4073,7 @@ void ext4_discard_preallocations(struct inode *inode)
bitmap_bh = ext4_read_block_bitmap(sb, group); bitmap_bh = ext4_read_block_bitmap(sb, group);
if (IS_ERR(bitmap_bh)) { if (IS_ERR(bitmap_bh)) {
err = PTR_ERR(bitmap_bh); err = PTR_ERR(bitmap_bh);
ext4_set_errno(sb, -err);
ext4_error(sb, "Error %d reading block bitmap for %u", ext4_error(sb, "Error %d reading block bitmap for %u",
err, group); err, group);
ext4_mb_unload_buddy(&e4b); ext4_mb_unload_buddy(&e4b);
...@@ -4325,6 +4328,7 @@ ext4_mb_discard_lg_preallocations(struct super_block *sb, ...@@ -4325,6 +4328,7 @@ ext4_mb_discard_lg_preallocations(struct super_block *sb,
err = ext4_mb_load_buddy_gfp(sb, group, &e4b, err = ext4_mb_load_buddy_gfp(sb, group, &e4b,
GFP_NOFS|__GFP_NOFAIL); GFP_NOFS|__GFP_NOFAIL);
if (err) { if (err) {
ext4_set_errno(sb, -err);
ext4_error(sb, "Error %d loading buddy information for %u", ext4_error(sb, "Error %d loading buddy information for %u",
err, group); err, group);
continue; continue;
......
...@@ -173,8 +173,10 @@ static int kmmpd(void *data) ...@@ -173,8 +173,10 @@ static int kmmpd(void *data)
* (s_mmp_update_interval * 60) seconds. * (s_mmp_update_interval * 60) seconds.
*/ */
if (retval) { if (retval) {
if ((failed_writes % 60) == 0) if ((failed_writes % 60) == 0) {
ext4_set_errno(sb, -retval);
ext4_error(sb, "Error writing to MMP block"); ext4_error(sb, "Error writing to MMP block");
}
failed_writes++; failed_writes++;
} }
...@@ -205,6 +207,7 @@ static int kmmpd(void *data) ...@@ -205,6 +207,7 @@ static int kmmpd(void *data)
retval = read_mmp_block(sb, &bh_check, mmp_block); retval = read_mmp_block(sb, &bh_check, mmp_block);
if (retval) { if (retval) {
ext4_set_errno(sb, -retval);
ext4_error(sb, "error reading MMP data: %d", ext4_error(sb, "error reading MMP data: %d",
retval); retval);
goto exit_thread; goto exit_thread;
...@@ -218,6 +221,7 @@ static int kmmpd(void *data) ...@@ -218,6 +221,7 @@ static int kmmpd(void *data)
"Error while updating MMP info. " "Error while updating MMP info. "
"The filesystem seems to have been" "The filesystem seems to have been"
" multiply mounted."); " multiply mounted.");
ext4_set_errno(sb, EBUSY);
ext4_error(sb, "abort"); ext4_error(sb, "abort");
put_bh(bh_check); put_bh(bh_check);
retval = -EBUSY; retval = -EBUSY;
......
...@@ -156,6 +156,7 @@ static struct buffer_head *__ext4_read_dirblock(struct inode *inode, ...@@ -156,6 +156,7 @@ static struct buffer_head *__ext4_read_dirblock(struct inode *inode,
if (ext4_dx_csum_verify(inode, dirent)) if (ext4_dx_csum_verify(inode, dirent))
set_buffer_verified(bh); set_buffer_verified(bh);
else { else {
ext4_set_errno(inode->i_sb, EFSBADCRC);
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);
...@@ -166,6 +167,7 @@ static struct buffer_head *__ext4_read_dirblock(struct inode *inode, ...@@ -166,6 +167,7 @@ static struct buffer_head *__ext4_read_dirblock(struct inode *inode,
if (ext4_dirblock_csum_verify(inode, bh)) if (ext4_dirblock_csum_verify(inode, bh))
set_buffer_verified(bh); set_buffer_verified(bh);
else { else {
ext4_set_errno(inode->i_sb, EFSBADCRC);
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);
...@@ -1527,6 +1529,7 @@ static struct buffer_head *__ext4_find_entry(struct inode *dir, ...@@ -1527,6 +1529,7 @@ static struct buffer_head *__ext4_find_entry(struct inode *dir,
goto next; goto next;
wait_on_buffer(bh); wait_on_buffer(bh);
if (!buffer_uptodate(bh)) { if (!buffer_uptodate(bh)) {
ext4_set_errno(sb, EIO);
EXT4_ERROR_INODE(dir, "reading directory lblock %lu", EXT4_ERROR_INODE(dir, "reading directory lblock %lu",
(unsigned long) block); (unsigned long) block);
brelse(bh); brelse(bh);
...@@ -1537,6 +1540,7 @@ static struct buffer_head *__ext4_find_entry(struct inode *dir, ...@@ -1537,6 +1540,7 @@ static struct buffer_head *__ext4_find_entry(struct inode *dir,
!is_dx_internal_node(dir, block, !is_dx_internal_node(dir, block,
(struct ext4_dir_entry *)bh->b_data) && (struct ext4_dir_entry *)bh->b_data) &&
!ext4_dirblock_csum_verify(dir, bh)) { !ext4_dirblock_csum_verify(dir, bh)) {
ext4_set_errno(sb, EFSBADCRC);
EXT4_ERROR_INODE(dir, "checksumming directory " EXT4_ERROR_INODE(dir, "checksumming directory "
"block %lu", (unsigned long)block); "block %lu", (unsigned long)block);
brelse(bh); brelse(bh);
......
...@@ -367,6 +367,8 @@ static void __save_error_info(struct super_block *sb, const char *func, ...@@ -367,6 +367,8 @@ static void __save_error_info(struct super_block *sb, const char *func,
ext4_update_tstamp(es, s_last_error_time); ext4_update_tstamp(es, s_last_error_time);
strncpy(es->s_last_error_func, func, sizeof(es->s_last_error_func)); strncpy(es->s_last_error_func, func, sizeof(es->s_last_error_func));
es->s_last_error_line = cpu_to_le32(line); es->s_last_error_line = cpu_to_le32(line);
if (es->s_last_error_errcode == 0)
es->s_last_error_errcode = EXT4_ERR_EFSCORRUPTED;
if (!es->s_first_error_time) { if (!es->s_first_error_time) {
es->s_first_error_time = es->s_last_error_time; es->s_first_error_time = es->s_last_error_time;
es->s_first_error_time_hi = es->s_last_error_time_hi; es->s_first_error_time_hi = es->s_last_error_time_hi;
...@@ -375,6 +377,7 @@ static void __save_error_info(struct super_block *sb, const char *func, ...@@ -375,6 +377,7 @@ static void __save_error_info(struct super_block *sb, const char *func,
es->s_first_error_line = cpu_to_le32(line); es->s_first_error_line = cpu_to_le32(line);
es->s_first_error_ino = es->s_last_error_ino; es->s_first_error_ino = es->s_last_error_ino;
es->s_first_error_block = es->s_last_error_block; es->s_first_error_block = es->s_last_error_block;
es->s_first_error_errcode = es->s_last_error_errcode;
} }
/* /*
* Start the daily error reporting function if it hasn't been * Start the daily error reporting function if it hasn't been
...@@ -631,6 +634,66 @@ const char *ext4_decode_error(struct super_block *sb, int errno, ...@@ -631,6 +634,66 @@ const char *ext4_decode_error(struct super_block *sb, int errno,
return errstr; return errstr;
} }
void ext4_set_errno(struct super_block *sb, int err)
{
if (err < 0)
err = -err;
switch (err) {
case EIO:
err = EXT4_ERR_EIO;
break;
case ENOMEM:
err = EXT4_ERR_ENOMEM;
break;
case EFSBADCRC:
err = EXT4_ERR_EFSBADCRC;
break;
case EFSCORRUPTED:
err = EXT4_ERR_EFSCORRUPTED;
break;
case ENOSPC:
err = EXT4_ERR_ENOSPC;
break;
case ENOKEY:
err = EXT4_ERR_ENOKEY;
break;
case EROFS:
err = EXT4_ERR_EROFS;
break;
case EFBIG:
err = EXT4_ERR_EFBIG;
break;
case EEXIST:
err = EXT4_ERR_EEXIST;
break;
case ERANGE:
err = EXT4_ERR_ERANGE;
break;
case EOVERFLOW:
err = EXT4_ERR_EOVERFLOW;
break;
case EBUSY:
err = EXT4_ERR_EBUSY;
break;
case ENOTDIR:
err = EXT4_ERR_ENOTDIR;
break;
case ENOTEMPTY:
err = EXT4_ERR_ENOTEMPTY;
break;
case ESHUTDOWN:
err = EXT4_ERR_ESHUTDOWN;
break;
case EFAULT:
err = EXT4_ERR_EFAULT;
break;
default:
err = EXT4_ERR_UNKNOWN;
}
EXT4_SB(sb)->s_es->s_last_error_errcode = err;
}
/* __ext4_std_error decodes expected errors from journaling functions /* __ext4_std_error decodes expected errors from journaling functions
* automatically and invokes the appropriate error response. */ * automatically and invokes the appropriate error response. */
...@@ -655,6 +718,7 @@ void __ext4_std_error(struct super_block *sb, const char *function, ...@@ -655,6 +718,7 @@ void __ext4_std_error(struct super_block *sb, const char *function,
sb->s_id, function, line, errstr); sb->s_id, function, line, errstr);
} }
ext4_set_errno(sb, -errno);
save_error_info(sb, function, line); save_error_info(sb, function, line);
ext4_handle_error(sb); ext4_handle_error(sb);
} }
...@@ -982,8 +1046,10 @@ static void ext4_put_super(struct super_block *sb) ...@@ -982,8 +1046,10 @@ static void ext4_put_super(struct super_block *sb)
aborted = is_journal_aborted(sbi->s_journal); aborted = is_journal_aborted(sbi->s_journal);
err = jbd2_journal_destroy(sbi->s_journal); err = jbd2_journal_destroy(sbi->s_journal);
sbi->s_journal = NULL; sbi->s_journal = NULL;
if ((err < 0) && !aborted) if ((err < 0) && !aborted) {
ext4_set_errno(sb, -err);
ext4_abort(sb, "Couldn't clean up the journal"); ext4_abort(sb, "Couldn't clean up the journal");
}
} }
ext4_unregister_sysfs(sb); ext4_unregister_sysfs(sb);
......
...@@ -2879,9 +2879,11 @@ int ext4_xattr_delete_inode(handle_t *handle, struct inode *inode, ...@@ -2879,9 +2879,11 @@ int ext4_xattr_delete_inode(handle_t *handle, struct inode *inode,
bh = ext4_sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl, REQ_PRIO); bh = ext4_sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl, REQ_PRIO);
if (IS_ERR(bh)) { if (IS_ERR(bh)) {
error = PTR_ERR(bh); error = PTR_ERR(bh);
if (error == -EIO) if (error == -EIO) {
ext4_set_errno(inode->i_sb, EIO);
EXT4_ERROR_INODE(inode, "block %llu read error", EXT4_ERROR_INODE(inode, "block %llu read error",
EXT4_I(inode)->i_file_acl); EXT4_I(inode)->i_file_acl);
}
bh = NULL; bh = NULL;
goto cleanup; goto cleanup;
} }
......
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