jbd2: store more accurate errno in superblock when possible

When jbd2_journal_abort() is called, the provided error code is stored
in the journal superblock. Some existing calls hard-code -EIO even when
the actual failure is not I/O related.

This patch updates those calls to pass more accurate error codes,
allowing the superblock to record the true cause of failure. This helps
improve diagnostics and debugging clarity when analyzing journal aborts.

Signed-off-by: Wengang Wang <wen.gang.wang@oracle.com>
Reviewed-by: Zhang Yi <yi.zhang@huawei.com>
Message-ID: <20251031210501.7337-1-wen.gang.wang@oracle.com>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
pull/1354/merge
Wengang Wang 2025-10-31 14:05:01 -07:00 committed by Theodore Ts'o
parent 986835bf4d
commit 80d05f640a
4 changed files with 15 additions and 11 deletions

View File

@ -698,7 +698,7 @@ static void ext4_handle_error(struct super_block *sb, bool force_ro, int error,
WARN_ON_ONCE(1);
if (!continue_fs && !ext4_emergency_ro(sb) && journal)
jbd2_journal_abort(journal, -EIO);
jbd2_journal_abort(journal, -error);
if (!bdev_read_only(sb->s_bdev)) {
save_error_info(sb, error, ino, block, func, line);
@ -5843,7 +5843,7 @@ static int ext4_journal_bmap(journal_t *journal, sector_t *block)
ext4_msg(journal->j_inode->i_sb, KERN_CRIT,
"journal bmap failed: block %llu ret %d\n",
*block, ret);
jbd2_journal_abort(journal, ret ? ret : -EIO);
jbd2_journal_abort(journal, ret ? ret : -EFSCORRUPTED);
return ret;
}
*block = map.m_pblk;

View File

@ -113,7 +113,7 @@ __releases(&journal->j_state_lock)
"journal space in %s\n", __func__,
journal->j_devname);
WARN_ON(1);
jbd2_journal_abort(journal, -EIO);
jbd2_journal_abort(journal, -ENOSPC);
}
write_lock(&journal->j_state_lock);
} else {

View File

@ -937,8 +937,8 @@ int jbd2_journal_bmap(journal_t *journal, unsigned long blocknr,
printk(KERN_ALERT "%s: journal block not found "
"at offset %lu on %s\n",
__func__, blocknr, journal->j_devname);
jbd2_journal_abort(journal, ret ? ret : -EFSCORRUPTED);
err = -EIO;
jbd2_journal_abort(journal, err);
} else {
*retp = block;
}
@ -1859,8 +1859,9 @@ int jbd2_journal_update_sb_log_tail(journal_t *journal, tid_t tail_tid,
if (is_journal_aborted(journal))
return -EIO;
if (jbd2_check_fs_dev_write_error(journal)) {
jbd2_journal_abort(journal, -EIO);
ret = jbd2_check_fs_dev_write_error(journal);
if (ret) {
jbd2_journal_abort(journal, ret);
return -EIO;
}
@ -2157,9 +2158,11 @@ int jbd2_journal_destroy(journal_t *journal)
* failed to write back to the original location, otherwise the
* filesystem may become inconsistent.
*/
if (!is_journal_aborted(journal) &&
jbd2_check_fs_dev_write_error(journal))
jbd2_journal_abort(journal, -EIO);
if (!is_journal_aborted(journal)) {
int ret = jbd2_check_fs_dev_write_error(journal);
if (ret)
jbd2_journal_abort(journal, ret);
}
if (journal->j_sb_buffer) {
if (!is_journal_aborted(journal)) {

View File

@ -1219,7 +1219,8 @@ int jbd2_journal_get_write_access(handle_t *handle, struct buffer_head *bh)
return -EROFS;
journal = handle->h_transaction->t_journal;
if (jbd2_check_fs_dev_write_error(journal)) {
rc = jbd2_check_fs_dev_write_error(journal);
if (rc) {
/*
* If the fs dev has writeback errors, it may have failed
* to async write out metadata buffers in the background.
@ -1227,7 +1228,7 @@ int jbd2_journal_get_write_access(handle_t *handle, struct buffer_head *bh)
* it out again, which may lead to on-disk filesystem
* inconsistency. Aborting journal can avoid it happen.
*/
jbd2_journal_abort(journal, -EIO);
jbd2_journal_abort(journal, rc);
return -EIO;
}