]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
jbd2: store more accurate errno in superblock when possible
authorWengang Wang <wen.gang.wang@oracle.com>
Fri, 31 Oct 2025 21:05:01 +0000 (14:05 -0700)
committerTheodore Ts'o <tytso@mit.edu>
Wed, 26 Nov 2025 22:05:39 +0000 (17:05 -0500)
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>
fs/ext4/super.c
fs/jbd2/checkpoint.c
fs/jbd2/journal.c
fs/jbd2/transaction.c

index 760c9d7588be80a638297fa45cfb60d3c4180b85..7de15249e826760d4c37bacafee594636f56e4c5 100644 (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;
index 2d0719bf6d87cffe9d6105b1bf90e9c8b2fc9e3e..de89c5bef60749235b43931e350c12b016860fd4 100644 (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 {
index f43474002f50f1c1571adb23db8d242980d01d0d..2fe1786a8f1b8db798ed7276a316d52944887d9f 100644 (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)) {
index 653ee540c4a1b7050ac32d132547ad93a9df4193..dca4b5d8aaaa3e1505b09fab42eb45bb201a8db8 100644 (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;
        }