提交 eca58bf9 编写于 作者: J Jan Kara 提交者: Cheng Jian

ext4: make ext4_abort() use __ext4_error()

mainline inclusion
from mainline-v5.11-rc1
commit 014c9caa
category: bugfix
bugzilla: 46758
CVE: NA

-----------------------------------------------

The only difference between __ext4_abort() and __ext4_error() is that
the former one ignores errors=continue mount option. Unify the code to
reduce duplication.
Signed-off-by: NJan Kara <jack@suse.cz>
Reviewed-by: NAndreas Dilger <adilger@dilger.ca>
Link: https://lore.kernel.org/r/20201127113405.26867-5-jack@suse.czSigned-off-by: NTheodore Ts'o <tytso@mit.edu>

conflicts:
fs/ext4/super.c
Signed-off-by: NYe Bin <yebin10@huawei.com>
Reviewed-by: Nzhangyi (F) <yi.zhang@huawei.com>
Signed-off-by: NYang Yingliang <yangyingliang@huawei.com>
Signed-off-by: NCheng Jian <cj.chengjian@huawei.com>
上级 76ef095d
...@@ -2653,9 +2653,9 @@ extern void ext4_mark_group_bitmap_corrupted(struct super_block *sb, ...@@ -2653,9 +2653,9 @@ 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 __printf(6, 7) extern __printf(7, 8)
void __ext4_error(struct super_block *, const char *, unsigned int, int, __u64, void __ext4_error(struct super_block *, const char *, unsigned int, bool,
const char *, ...); int, __u64, const char *, ...);
extern __printf(6, 7) extern __printf(6, 7)
void __ext4_error_inode(struct inode *, const char *, unsigned int, void __ext4_error_inode(struct inode *, const char *, unsigned int,
ext4_fsblk_t, int, const char *, ...); ext4_fsblk_t, int, const char *, ...);
...@@ -2664,9 +2664,6 @@ void __ext4_error_file(struct file *, const char *, unsigned int, ext4_fsblk_t, ...@@ -2664,9 +2664,6 @@ void __ext4_error_file(struct file *, const char *, unsigned int, ext4_fsblk_t,
const char *, ...); const char *, ...);
extern void __ext4_std_error(struct super_block *, const char *, extern void __ext4_std_error(struct super_block *, const char *,
unsigned int, int); unsigned int, int);
extern __printf(5, 6)
void __ext4_abort(struct super_block *, const char *, unsigned int, int,
const char *, ...);
extern __printf(4, 5) extern __printf(4, 5)
void __ext4_warning(struct super_block *, const char *, unsigned int, void __ext4_warning(struct super_block *, const char *, unsigned int,
const char *, ...); const char *, ...);
...@@ -2696,6 +2693,9 @@ void __ext4_grp_locked_error(const char *, unsigned int, ...@@ -2696,6 +2693,9 @@ void __ext4_grp_locked_error(const char *, unsigned int,
#define EXT4_ERROR_FILE(file, block, fmt, a...) \ #define EXT4_ERROR_FILE(file, block, fmt, a...) \
ext4_error_file((file), __func__, __LINE__, (block), (fmt), ## a) ext4_error_file((file), __func__, __LINE__, (block), (fmt), ## a)
#define ext4_abort(sb, err, fmt, a...) \
__ext4_error((sb), __func__, __LINE__, true, (err), 0, (fmt), ## a)
#ifdef CONFIG_PRINTK #ifdef CONFIG_PRINTK
#define ext4_error_inode(inode, func, line, block, fmt, ...) \ #define ext4_error_inode(inode, func, line, block, fmt, ...) \
...@@ -2706,11 +2706,11 @@ void __ext4_grp_locked_error(const char *, unsigned int, ...@@ -2706,11 +2706,11 @@ void __ext4_grp_locked_error(const char *, unsigned int,
#define ext4_error_file(file, func, line, block, fmt, ...) \ #define ext4_error_file(file, func, line, block, fmt, ...) \
__ext4_error_file(file, func, line, block, fmt, ##__VA_ARGS__) __ext4_error_file(file, func, line, block, fmt, ##__VA_ARGS__)
#define ext4_error(sb, fmt, ...) \ #define ext4_error(sb, fmt, ...) \
__ext4_error((sb), __func__, __LINE__, 0, 0, (fmt), ##__VA_ARGS__) __ext4_error((sb), __func__, __LINE__, false, 0, 0, (fmt), \
##__VA_ARGS__)
#define ext4_error_err(sb, err, fmt, ...) \ #define ext4_error_err(sb, err, fmt, ...) \
__ext4_error((sb), __func__, __LINE__, (err), 0, (fmt), ##__VA_ARGS__) __ext4_error((sb), __func__, __LINE__, false, (err), 0, (fmt), \
#define ext4_abort(sb, err, fmt, ...) \ ##__VA_ARGS__)
__ext4_abort((sb), __func__, __LINE__, (err), (fmt), ##__VA_ARGS__)
#define ext4_warning(sb, fmt, ...) \ #define ext4_warning(sb, fmt, ...) \
__ext4_warning(sb, __func__, __LINE__, fmt, ##__VA_ARGS__) __ext4_warning(sb, __func__, __LINE__, fmt, ##__VA_ARGS__)
#define ext4_warning_inode(inode, fmt, ...) \ #define ext4_warning_inode(inode, fmt, ...) \
...@@ -2743,17 +2743,12 @@ do { \ ...@@ -2743,17 +2743,12 @@ do { \
#define ext4_error(sb, fmt, ...) \ #define ext4_error(sb, fmt, ...) \
do { \ do { \
no_printk(fmt, ##__VA_ARGS__); \ no_printk(fmt, ##__VA_ARGS__); \
__ext4_error(sb, "", 0, 0, 0, " "); \ __ext4_error(sb, "", 0, false, 0, 0, " "); \
} while (0) } while (0)
#define ext4_error_err(sb, err, fmt, ...) \ #define ext4_error_err(sb, err, fmt, ...) \
do { \ do { \
no_printk(fmt, ##__VA_ARGS__); \ no_printk(fmt, ##__VA_ARGS__); \
__ext4_error(sb, "", 0, err, 0, " "); \ __ext4_error(sb, "", 0, false, err, 0, " "); \
} while (0)
#define ext4_abort(sb, err, fmt, ...) \
do { \
no_printk(fmt, ##__VA_ARGS__); \
__ext4_abort(sb, "", 0, err, " "); \
} while (0) } while (0)
#define ext4_warning(sb, fmt, ...) \ #define ext4_warning(sb, fmt, ...) \
do { \ do { \
......
...@@ -273,8 +273,8 @@ int __ext4_forget(const char *where, unsigned int line, handle_t *handle, ...@@ -273,8 +273,8 @@ 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_abort(inode->i_sb, where, line, -err, __ext4_error(inode->i_sb, where, line, true, -err, 0,
"error %d when attempting revoke", err); "error %d when attempting revoke", err);
} }
BUFFER_TRACE(bh, "exit"); BUFFER_TRACE(bh, "exit");
return err; return err;
......
...@@ -4879,7 +4879,7 @@ struct inode *__ext4_iget(struct super_block *sb, unsigned long ino, ...@@ -4879,7 +4879,7 @@ struct inode *__ext4_iget(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))) {
if (flags & EXT4_IGET_HANDLE) if (flags & EXT4_IGET_HANDLE)
return ERR_PTR(-ESTALE); return ERR_PTR(-ESTALE);
__ext4_error(sb, function, line, EFSCORRUPTED, 0, __ext4_error(sb, function, line, false, EFSCORRUPTED, 0,
"inode #%lu: comm %s: iget: illegal inode #", "inode #%lu: comm %s: iget: illegal inode #",
ino, current->comm); ino, current->comm);
return ERR_PTR(-EFSCORRUPTED); return ERR_PTR(-EFSCORRUPTED);
......
...@@ -560,9 +560,15 @@ static void ext4_netlink_send_info(struct super_block *sb, int ext4_errno) ...@@ -560,9 +560,15 @@ static void ext4_netlink_send_info(struct super_block *sb, int ext4_errno)
* We'll just use the jbd2_journal_abort() error code to record an error in * We'll just use the jbd2_journal_abort() error code to record an error in
* the journal instead. On recovery, the journal will complain about * the journal instead. On recovery, the journal will complain about
* that error until we've noted it down and cleared it. * that error until we've noted it down and cleared it.
*
* If force_ro is set, we unconditionally force the filesystem into an
* ABORT|READONLY state, unless the error response on the fs has been set to
* panic in which case we take the easy way out and panic immediately. This is
* used to deal with unrecoverable failures such as journal IO errors or ENOMEM
* at a critical moment in log management.
*/ */
static void ext4_handle_error(struct super_block *sb) static void ext4_handle_error(struct super_block *sb, bool force_ro)
{ {
journal_t *journal = EXT4_SB(sb)->s_journal; journal_t *journal = EXT4_SB(sb)->s_journal;
...@@ -572,7 +578,7 @@ static void ext4_handle_error(struct super_block *sb) ...@@ -572,7 +578,7 @@ static void ext4_handle_error(struct super_block *sb)
if (sb_rdonly(sb)) if (sb_rdonly(sb))
return; return;
if (test_opt(sb, ERRORS_CONT)) if (!force_ro && test_opt(sb, ERRORS_CONT))
goto out; goto out;
EXT4_SB(sb)->s_mount_flags |= EXT4_MF_FS_ABORTED; EXT4_SB(sb)->s_mount_flags |= EXT4_MF_FS_ABORTED;
...@@ -583,19 +589,18 @@ static void ext4_handle_error(struct super_block *sb) ...@@ -583,19 +589,18 @@ static void ext4_handle_error(struct super_block *sb)
* could panic during 'reboot -f' as the underlying device got already * could panic during 'reboot -f' as the underlying device got already
* disabled. * disabled.
*/ */
if (test_opt(sb, ERRORS_RO) || system_going_down()) { if (test_opt(sb, ERRORS_PANIC) && !system_going_down()) {
ext4_msg(sb, KERN_CRIT, "Remounting filesystem read-only");
/*
* Make sure updated value of ->s_mount_flags will be visible
* before ->s_flags update
*/
smp_wmb();
sb->s_flags |= SB_RDONLY;
} else if (test_opt(sb, ERRORS_PANIC)) {
panic("EXT4-fs (device %s): panic forced after error\n", panic("EXT4-fs (device %s): panic forced after error\n",
sb->s_id); sb->s_id);
} }
ext4_msg(sb, KERN_CRIT, "Remounting filesystem read-only");
/*
* Make sure updated value of ->s_mount_flags will be visible before
* ->s_flags update
*/
smp_wmb();
sb->s_flags |= SB_RDONLY;
out: out:
ext4_netlink_send_info(sb, 1); ext4_netlink_send_info(sb, 1);
} }
...@@ -605,7 +610,7 @@ static void ext4_handle_error(struct super_block *sb) ...@@ -605,7 +610,7 @@ static void ext4_handle_error(struct super_block *sb)
"EXT4-fs error") "EXT4-fs error")
void __ext4_error(struct super_block *sb, const char *function, void __ext4_error(struct super_block *sb, const char *function,
unsigned int line, int error, __u64 block, unsigned int line, bool force_ro, int error, __u64 block,
const char *fmt, ...) const char *fmt, ...)
{ {
struct va_format vaf; struct va_format vaf;
...@@ -625,7 +630,7 @@ void __ext4_error(struct super_block *sb, const char *function, ...@@ -625,7 +630,7 @@ void __ext4_error(struct super_block *sb, const char *function,
va_end(args); va_end(args);
} }
save_error_info(sb, error, 0, block, function, line); save_error_info(sb, error, 0, block, function, line);
ext4_handle_error(sb); ext4_handle_error(sb, force_ro);
} }
void __ext4_error_inode(struct inode *inode, const char *function, void __ext4_error_inode(struct inode *inode, const char *function,
...@@ -657,7 +662,7 @@ void __ext4_error_inode(struct inode *inode, const char *function, ...@@ -657,7 +662,7 @@ void __ext4_error_inode(struct inode *inode, const char *function,
} }
save_error_info(inode->i_sb, error, inode->i_ino, block, save_error_info(inode->i_sb, error, inode->i_ino, block,
function, line); function, line);
ext4_handle_error(inode->i_sb); ext4_handle_error(inode->i_sb, false);
} }
void __ext4_error_file(struct file *file, const char *function, void __ext4_error_file(struct file *file, const char *function,
...@@ -698,7 +703,7 @@ void __ext4_error_file(struct file *file, const char *function, ...@@ -698,7 +703,7 @@ void __ext4_error_file(struct file *file, const char *function,
} }
save_error_info(inode->i_sb, EFSCORRUPTED, inode->i_ino, block, save_error_info(inode->i_sb, EFSCORRUPTED, inode->i_ino, block,
function, line); function, line);
ext4_handle_error(inode->i_sb); ext4_handle_error(inode->i_sb, false);
} }
const char *ext4_decode_error(struct super_block *sb, int errno, const char *ext4_decode_error(struct super_block *sb, int errno,
...@@ -766,52 +771,7 @@ void __ext4_std_error(struct super_block *sb, const char *function, ...@@ -766,52 +771,7 @@ void __ext4_std_error(struct super_block *sb, const char *function,
} }
save_error_info(sb, -errno, 0, 0, function, line); save_error_info(sb, -errno, 0, 0, function, line);
ext4_handle_error(sb); ext4_handle_error(sb, false);
}
/*
* ext4_abort is a much stronger failure handler than ext4_error. The
* abort function may be used to deal with unrecoverable failures such
* as journal IO errors or ENOMEM at a critical moment in log management.
*
* We unconditionally force the filesystem into an ABORT|READONLY state,
* unless the error response on the fs has been set to panic in which
* case we take the easy way out and panic immediately.
*/
void __ext4_abort(struct super_block *sb, const char *function,
unsigned int line, int error, const char *fmt, ...)
{
struct va_format vaf;
va_list args;
if (unlikely(ext4_forced_shutdown(EXT4_SB(sb))))
return;
save_error_info(sb, error, 0, 0, function, line);
va_start(args, fmt);
vaf.fmt = fmt;
vaf.va = &args;
printk(KERN_CRIT "EXT4-fs error (device %s): %s:%d: %pV\n",
sb->s_id, function, line, &vaf);
va_end(args);
if (sb_rdonly(sb) == 0) {
EXT4_SB(sb)->s_mount_flags |= EXT4_MF_FS_ABORTED;
if (EXT4_SB(sb)->s_journal)
jbd2_journal_abort(EXT4_SB(sb)->s_journal, -EIO);
ext4_msg(sb, KERN_CRIT, "Remounting filesystem read-only");
/*
* Make sure updated value of ->s_mount_flags will be visible
* before ->s_flags update
*/
smp_wmb();
sb->s_flags |= SB_RDONLY;
ext4_netlink_send_info(sb, 2);
}
if (test_opt(sb, ERRORS_PANIC) && !system_going_down())
panic("EXT4-fs panic from previous error\n");
} }
void __ext4_msg(struct super_block *sb, void __ext4_msg(struct super_block *sb,
...@@ -910,7 +870,7 @@ __acquires(bitlock) ...@@ -910,7 +870,7 @@ __acquires(bitlock)
ext4_unlock_group(sb, grp); ext4_unlock_group(sb, grp);
ext4_commit_super(sb, 1); ext4_commit_super(sb, 1);
ext4_handle_error(sb); ext4_handle_error(sb, false);
/* /*
* We only get here in the ERRORS_RO case; relocking the group * We only get here in the ERRORS_RO case; relocking the group
* may be dangerous, but nothing bad will happen since the * may be dangerous, but nothing bad will happen since the
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册