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

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.edu


Signed-off-by: default avatarTheodore Ts'o <tytso@mit.edu>
parent a562c687
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -506,6 +506,7 @@ int ext4_wait_block_bitmap(struct super_block *sb, ext4_group_t block_group,
		return -EFSCORRUPTED;
	wait_on_buffer(bh);
	if (!buffer_uptodate(bh)) {
		ext4_set_errno(sb, EIO);
		ext4_error(sb, "Cannot read block bitmap - "
			   "block_group = %u, block_bitmap = %llu",
			   block_group, (unsigned long long) bh->b_blocknr);
+29 −1
Original line number Diff line number Diff line
@@ -1343,7 +1343,8 @@ struct ext4_super_block {
	__u8	s_lastcheck_hi;
	__u8	s_first_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_flags;	/* Filename charset encoding flags */
	__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)
		 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
 */
@@ -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,
					     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,
+3 −0
Original line number Diff line number Diff line
@@ -58,6 +58,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");
		return -EROFS;
	}
@@ -249,6 +250,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,
			   "error %d when attempting revoke", err);
	}
@@ -320,6 +322,7 @@ int __ext4_handle_dirty_metadata(const char *where, unsigned int line,
				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,
					"IO error syncing itable block");
+1 −0
Original line number Diff line number Diff line
@@ -492,6 +492,7 @@ 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,
			 "pblk %llu bad header/extent: %s - magic %x, "
			 "entries %u, max %u(%u), depth %u(%u)",
+2 −0
Original line number Diff line number Diff line
@@ -194,6 +194,7 @@ ext4_read_inode_bitmap(struct super_block *sb, ext4_group_t block_group)
	wait_on_buffer(bh);
	if (!buffer_uptodate(bh)) {
		put_bh(bh);
		ext4_set_errno(sb, EIO);
		ext4_error(sb, "Cannot read inode bitmap - "
			   "block_group = %u, inode_bitmap = %llu",
			   block_group, bitmap_blk);
@@ -1223,6 +1224,7 @@ struct inode *ext4_orphan_get(struct super_block *sb, unsigned long ino)
	inode = ext4_iget(sb, ino, EXT4_IGET_NORMAL);
	if (IS_ERR(inode)) {
		err = PTR_ERR(inode);
		ext4_set_errno(sb, -err);
		ext4_error(sb, "couldn't read orphan inode %lu (err %d)",
			   ino, err);
		return inode;
Loading