Commit 54d3adbc authored by Theodore Ts'o's avatar Theodore Ts'o
Browse files

ext4: save all error info in save_error_info() and drop ext4_set_errno()

Using a separate function, ext4_set_errno() to set the errno is
problematic because it doesn't do the right thing once
s_last_error_errorcode is non-zero.  It's also less racy to set all of
the error information all at once.  (Also, as a bonus, it shrinks code
size slightly.)

Link: https://lore.kernel.org/r/20200329020404.686965-1-tytso@mit.edu


Fixes: 878520ac ("ext4: save the error code which triggered...")
Signed-off-by: default avatarTheodore Ts'o <tytso@mit.edu>
parent df41460a
Loading
Loading
Loading
Loading
+3 −4
Original line number Diff line number Diff line
@@ -516,8 +516,7 @@ int ext4_wait_block_bitmap(struct super_block *sb, ext4_group_t block_group,
	wait_on_buffer(bh);
	ext4_simulate_fail_bh(sb, bh, EXT4_SIM_BBITMAP_EIO);
	if (!buffer_uptodate(bh)) {
		ext4_set_errno(sb, EIO);
		ext4_error(sb, "Cannot read block bitmap - "
		ext4_error_err(sb, EIO, "Cannot read block bitmap - "
			       "block_group = %u, block_bitmap = %llu",
			       block_group, (unsigned long long) bh->b_blocknr);
		ext4_mark_group_bitmap_corrupted(sb, block_group,
+7 −11
Original line number Diff line number Diff line
@@ -166,10 +166,8 @@ static int ext4_data_block_valid_rcu(struct ext4_sb_info *sbi,

	if ((start_blk <= le32_to_cpu(sbi->s_es->s_first_data_block)) ||
	    (start_blk + count < start_blk) ||
	    (start_blk + count > ext4_blocks_count(sbi->s_es))) {
		sbi->s_es->s_last_error_block = cpu_to_le64(start_blk);
	    (start_blk + count > ext4_blocks_count(sbi->s_es)))
		return 0;
	}

	if (system_blks == NULL)
		return 1;
@@ -181,11 +179,9 @@ static int ext4_data_block_valid_rcu(struct ext4_sb_info *sbi,
			n = n->rb_left;
		else if (start_blk >= (entry->start_blk + entry->count))
			n = n->rb_right;
		else {
			sbi->s_es->s_last_error_block = cpu_to_le64(start_blk);
		else
			return 0;
	}
	}
	return 1;
}

@@ -220,10 +216,12 @@ static int ext4_protect_reserved_inode(struct super_block *sb,
		} else {
			if (!ext4_data_block_valid_rcu(sbi, system_blks,
						map.m_pblk, n)) {
				ext4_error(sb, "blocks %llu-%llu from inode %u "
					   "overlap system zone", map.m_pblk,
					   map.m_pblk + map.m_len - 1, ino);
				err = -EFSCORRUPTED;
				__ext4_error(sb, __func__, __LINE__, -err,
					     map.m_pblk, "blocks %llu-%llu "
					     "from inode %u overlap system zone",
					     map.m_pblk,
					     map.m_pblk + map.m_len - 1, ino);
				break;
			}
			err = add_system_zone(system_blks, map.m_pblk, n);
@@ -365,7 +363,6 @@ int ext4_data_block_valid(struct ext4_sb_info *sbi, ext4_fsblk_t start_blk,
int ext4_check_blockref(const char *function, unsigned int line,
			struct inode *inode, __le32 *p, unsigned int max)
{
	struct ext4_super_block *es = EXT4_SB(inode->i_sb)->s_es;
	__le32 *bref = p;
	unsigned int blk;

@@ -379,7 +376,6 @@ int ext4_check_blockref(const char *function, unsigned int line,
		if (blk &&
		    unlikely(!ext4_data_block_valid(EXT4_SB(inode->i_sb),
						    blk, 1))) {
			es->s_last_error_block = cpu_to_le64(blk);
			ext4_error_inode(inode, function, line, blk,
					 "invalid block");
			return -EFSCORRUPTED;
+36 −18
Original line number Diff line number Diff line
@@ -2770,21 +2770,20 @@ extern const char *ext4_decode_error(struct super_block *sb, int errno,
extern void ext4_mark_group_bitmap_corrupted(struct super_block *sb,
					     ext4_group_t block_group,
					     unsigned int flags);
extern void ext4_set_errno(struct super_block *sb, int err);

extern __printf(4, 5)
void __ext4_error(struct super_block *, const char *, unsigned int,
		  const char *, ...);
extern __printf(5, 6)
void __ext4_error_inode(struct inode *, const char *, unsigned int, ext4_fsblk_t,
extern __printf(6, 7)
void __ext4_error(struct super_block *, const char *, unsigned int, int, __u64,
		  const char *, ...);
extern __printf(6, 7)
void __ext4_error_inode(struct inode *, const char *, unsigned int,
			ext4_fsblk_t, int, const char *, ...);
extern __printf(5, 6)
void __ext4_error_file(struct file *, const char *, unsigned int, ext4_fsblk_t,
		     const char *, ...);
extern void __ext4_std_error(struct super_block *, const char *,
			     unsigned int, int);
extern __printf(4, 5)
void __ext4_abort(struct super_block *, const char *, unsigned int,
extern __printf(5, 6)
void __ext4_abort(struct super_block *, const char *, unsigned int, int,
		  const char *, ...);
extern __printf(4, 5)
void __ext4_warning(struct super_block *, const char *, unsigned int,
@@ -2805,8 +2804,12 @@ void __ext4_grp_locked_error(const char *, unsigned int,
#define EXT4_ERROR_INODE(inode, fmt, a...) \
	ext4_error_inode((inode), __func__, __LINE__, 0, (fmt), ## a)

#define EXT4_ERROR_INODE_BLOCK(inode, block, fmt, a...)			\
	ext4_error_inode((inode), __func__, __LINE__, (block), (fmt), ## a)
#define EXT4_ERROR_INODE_ERR(inode, err, fmt, a...)			\
	__ext4_error_inode((inode), __func__, __LINE__, 0, (err), (fmt), ## a)

#define ext4_error_inode_block(inode, block, err, fmt, a...)		\
	__ext4_error_inode((inode), __func__, __LINE__, (block), (err),	\
			   (fmt), ## a)

#define EXT4_ERROR_FILE(file, block, fmt, a...)				\
	ext4_error_file((file), __func__, __LINE__, (block), (fmt), ## a)
@@ -2814,13 +2817,18 @@ void __ext4_grp_locked_error(const char *, unsigned int,
#ifdef CONFIG_PRINTK

#define ext4_error_inode(inode, func, line, block, fmt, ...)		\
	__ext4_error_inode(inode, func, line, block, fmt, ##__VA_ARGS__)
	__ext4_error_inode(inode, func, line, block, 0, fmt, ##__VA_ARGS__)
#define ext4_error_inode_err(inode, func, line, block, err, fmt, ...)	\
	__ext4_error_inode((inode), (func), (line), (block), 		\
			   (err), (fmt), ##__VA_ARGS__)
#define ext4_error_file(file, func, line, block, fmt, ...)		\
	__ext4_error_file(file, func, line, block, fmt, ##__VA_ARGS__)
#define ext4_error(sb, fmt, ...)					\
	__ext4_error(sb, __func__, __LINE__, fmt, ##__VA_ARGS__)
#define ext4_abort(sb, fmt, ...)					\
	__ext4_abort(sb, __func__, __LINE__, fmt, ##__VA_ARGS__)
	__ext4_error((sb), __func__, __LINE__, 0, 0, (fmt), ##__VA_ARGS__)
#define ext4_error_err(sb, err, fmt, ...)				\
	__ext4_error((sb), __func__, __LINE__, (err), 0, (fmt), ##__VA_ARGS__)
#define ext4_abort(sb, err, fmt, ...)					\
	__ext4_abort((sb), __func__, __LINE__, (err), (fmt), ##__VA_ARGS__)
#define ext4_warning(sb, fmt, ...)					\
	__ext4_warning(sb, __func__, __LINE__, fmt, ##__VA_ARGS__)
#define ext4_warning_inode(inode, fmt, ...)				\
@@ -2838,7 +2846,12 @@ void __ext4_grp_locked_error(const char *, unsigned int,
#define ext4_error_inode(inode, func, line, block, fmt, ...)		\
do {									\
	no_printk(fmt, ##__VA_ARGS__);					\
	__ext4_error_inode(inode, "", 0, block, " ");			\
	__ext4_error_inode(inode, "", 0, block, 0, " ");		\
} while (0)
#define ext4_error_inode_err(inode, func, line, block, err, fmt, ...)	\
do {									\
	no_printk(fmt, ##__VA_ARGS__);					\
	__ext4_error_inode(inode, "", 0, block, err, " ");		\
} while (0)
#define ext4_error_file(file, func, line, block, fmt, ...)		\
do {									\
@@ -2848,12 +2861,17 @@ do { \
#define ext4_error(sb, fmt, ...)					\
do {									\
	no_printk(fmt, ##__VA_ARGS__);					\
	__ext4_error(sb, "", 0, " ");					\
	__ext4_error(sb, "", 0, 0, 0, " ");				\
} while (0)
#define ext4_error_err(sb, err, fmt, ...)				\
do {									\
	no_printk(fmt, ##__VA_ARGS__);					\
	__ext4_error(sb, "", 0, err, 0, " ");				\
} while (0)
#define ext4_abort(sb, fmt, ...)					\
#define ext4_abort(sb, err, fmt, ...)					\
do {									\
	no_printk(fmt, ##__VA_ARGS__);					\
	__ext4_abort(sb, "", 0, " ");					\
	__ext4_abort(sb, "", 0, err, " ");				\
} while (0)
#define ext4_warning(sb, fmt, ...)					\
do {									\
+4 −9
Original line number Diff line number Diff line
@@ -80,8 +80,7 @@ static int ext4_journal_check_start(struct super_block *sb)
	 * take the FS itself readonly cleanly.
	 */
	if (journal && is_journal_aborted(journal)) {
		ext4_set_errno(sb, -journal->j_errno);
		ext4_abort(sb, "Detected aborted journal");
		ext4_abort(sb, -journal->j_errno, "Detected aborted journal");
		return -EROFS;
	}
	return 0;
@@ -272,8 +271,7 @@ int __ext4_forget(const char *where, unsigned int line, handle_t *handle,
	if (err) {
		ext4_journal_abort_handle(where, line, __func__,
					  bh, handle, err);
		ext4_set_errno(inode->i_sb, -err);
		__ext4_abort(inode->i_sb, where, line,
		__ext4_abort(inode->i_sb, where, line, -err,
			   "error %d when attempting revoke", err);
	}
	BUFFER_TRACE(bh, "exit");
@@ -343,11 +341,8 @@ int __ext4_handle_dirty_metadata(const char *where, unsigned int line,
				struct ext4_super_block *es;

				es = EXT4_SB(inode->i_sb)->s_es;
				es->s_last_error_block =
					cpu_to_le64(bh->b_blocknr);
				ext4_set_errno(inode->i_sb, EIO);
				ext4_error_inode(inode, where, line,
						 bh->b_blocknr,
				ext4_error_inode_err(inode, where, line,
						     bh->b_blocknr, EIO,
					"IO error syncing itable block");
				err = -EIO;
			}
+12 −15
Original line number Diff line number Diff line
@@ -350,7 +350,7 @@ static int ext4_valid_extent_idx(struct inode *inode,

static int ext4_valid_extent_entries(struct inode *inode,
				     struct ext4_extent_header *eh,
				int depth)
				     ext4_fsblk_t *pblk, int depth)
{
	unsigned short entries;
	if (eh->eh_entries == 0)
@@ -361,8 +361,6 @@ static int ext4_valid_extent_entries(struct inode *inode,
	if (depth == 0) {
		/* leaf entries */
		struct ext4_extent *ext = EXT_FIRST_EXTENT(eh);
		struct ext4_super_block *es = EXT4_SB(inode->i_sb)->s_es;
		ext4_fsblk_t pblock = 0;
		ext4_lblk_t lblock = 0;
		ext4_lblk_t prev = 0;
		int len = 0;
@@ -374,8 +372,7 @@ static int ext4_valid_extent_entries(struct inode *inode,
			lblock = le32_to_cpu(ext->ee_block);
			len = ext4_ext_get_actual_len(ext);
			if ((lblock <= prev) && prev) {
				pblock = ext4_ext_pblock(ext);
				es->s_last_error_block = cpu_to_le64(pblock);
				*pblk = ext4_ext_pblock(ext);
				return 0;
			}
			ext++;
@@ -422,7 +419,7 @@ static int __ext4_ext_check(const char *function, unsigned int line,
		error_msg = "invalid eh_entries";
		goto corrupted;
	}
	if (!ext4_valid_extent_entries(inode, eh, depth)) {
	if (!ext4_valid_extent_entries(inode, eh, &pblk, depth)) {
		error_msg = "invalid extent entries";
		goto corrupted;
	}
@@ -440,13 +437,13 @@ static int __ext4_ext_check(const char *function, unsigned int line,
	return 0;

corrupted:
	ext4_set_errno(inode->i_sb, -err);
	ext4_error_inode(inode, function, line, 0,
	ext4_error_inode_err(inode, function, line, 0, -err,
			     "pblk %llu bad header/extent: %s - magic %x, "
			     "entries %u, max %u(%u), depth %u(%u)",
			     (unsigned long long) pblk, error_msg,
			     le16_to_cpu(eh->eh_magic),
			 le16_to_cpu(eh->eh_entries), le16_to_cpu(eh->eh_max),
			     le16_to_cpu(eh->eh_entries),
			     le16_to_cpu(eh->eh_max),
			     max, le16_to_cpu(eh->eh_depth), depth);
	return err;
}
Loading