Skip to content

Commit 54d3adb

Browse files
committed
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/[email protected] Fixes: 878520a ("ext4: save the error code which triggered...") Signed-off-by: Theodore Ts'o <[email protected]>
1 parent df41460 commit 54d3adb

File tree

15 files changed

+199
-215
lines changed

15 files changed

+199
-215
lines changed

fs/ext4/balloc.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -516,10 +516,9 @@ int ext4_wait_block_bitmap(struct super_block *sb, ext4_group_t block_group,
516516
wait_on_buffer(bh);
517517
ext4_simulate_fail_bh(sb, bh, EXT4_SIM_BBITMAP_EIO);
518518
if (!buffer_uptodate(bh)) {
519-
ext4_set_errno(sb, EIO);
520-
ext4_error(sb, "Cannot read block bitmap - "
521-
"block_group = %u, block_bitmap = %llu",
522-
block_group, (unsigned long long) bh->b_blocknr);
519+
ext4_error_err(sb, EIO, "Cannot read block bitmap - "
520+
"block_group = %u, block_bitmap = %llu",
521+
block_group, (unsigned long long) bh->b_blocknr);
523522
ext4_mark_group_bitmap_corrupted(sb, block_group,
524523
EXT4_GROUP_INFO_BBITMAP_CORRUPT);
525524
return -EIO;

fs/ext4/block_validity.c

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -166,10 +166,8 @@ static int ext4_data_block_valid_rcu(struct ext4_sb_info *sbi,
166166

167167
if ((start_blk <= le32_to_cpu(sbi->s_es->s_first_data_block)) ||
168168
(start_blk + count < start_blk) ||
169-
(start_blk + count > ext4_blocks_count(sbi->s_es))) {
170-
sbi->s_es->s_last_error_block = cpu_to_le64(start_blk);
169+
(start_blk + count > ext4_blocks_count(sbi->s_es)))
171170
return 0;
172-
}
173171

174172
if (system_blks == NULL)
175173
return 1;
@@ -181,10 +179,8 @@ static int ext4_data_block_valid_rcu(struct ext4_sb_info *sbi,
181179
n = n->rb_left;
182180
else if (start_blk >= (entry->start_blk + entry->count))
183181
n = n->rb_right;
184-
else {
185-
sbi->s_es->s_last_error_block = cpu_to_le64(start_blk);
182+
else
186183
return 0;
187-
}
188184
}
189185
return 1;
190186
}
@@ -220,10 +216,12 @@ static int ext4_protect_reserved_inode(struct super_block *sb,
220216
} else {
221217
if (!ext4_data_block_valid_rcu(sbi, system_blks,
222218
map.m_pblk, n)) {
223-
ext4_error(sb, "blocks %llu-%llu from inode %u "
224-
"overlap system zone", map.m_pblk,
225-
map.m_pblk + map.m_len - 1, ino);
226219
err = -EFSCORRUPTED;
220+
__ext4_error(sb, __func__, __LINE__, -err,
221+
map.m_pblk, "blocks %llu-%llu "
222+
"from inode %u overlap system zone",
223+
map.m_pblk,
224+
map.m_pblk + map.m_len - 1, ino);
227225
break;
228226
}
229227
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,
365363
int ext4_check_blockref(const char *function, unsigned int line,
366364
struct inode *inode, __le32 *p, unsigned int max)
367365
{
368-
struct ext4_super_block *es = EXT4_SB(inode->i_sb)->s_es;
369366
__le32 *bref = p;
370367
unsigned int blk;
371368

@@ -379,7 +376,6 @@ int ext4_check_blockref(const char *function, unsigned int line,
379376
if (blk &&
380377
unlikely(!ext4_data_block_valid(EXT4_SB(inode->i_sb),
381378
blk, 1))) {
382-
es->s_last_error_block = cpu_to_le64(blk);
383379
ext4_error_inode(inode, function, line, blk,
384380
"invalid block");
385381
return -EFSCORRUPTED;

fs/ext4/ext4.h

Lines changed: 36 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2770,21 +2770,20 @@ extern const char *ext4_decode_error(struct super_block *sb, int errno,
27702770
extern void ext4_mark_group_bitmap_corrupted(struct super_block *sb,
27712771
ext4_group_t block_group,
27722772
unsigned int flags);
2773-
extern void ext4_set_errno(struct super_block *sb, int err);
27742773

2775-
extern __printf(4, 5)
2776-
void __ext4_error(struct super_block *, const char *, unsigned int,
2774+
extern __printf(6, 7)
2775+
void __ext4_error(struct super_block *, const char *, unsigned int, int, __u64,
27772776
const char *, ...);
2778-
extern __printf(5, 6)
2779-
void __ext4_error_inode(struct inode *, const char *, unsigned int, ext4_fsblk_t,
2780-
const char *, ...);
2777+
extern __printf(6, 7)
2778+
void __ext4_error_inode(struct inode *, const char *, unsigned int,
2779+
ext4_fsblk_t, int, const char *, ...);
27812780
extern __printf(5, 6)
27822781
void __ext4_error_file(struct file *, const char *, unsigned int, ext4_fsblk_t,
27832782
const char *, ...);
27842783
extern void __ext4_std_error(struct super_block *, const char *,
27852784
unsigned int, int);
2786-
extern __printf(4, 5)
2787-
void __ext4_abort(struct super_block *, const char *, unsigned int,
2785+
extern __printf(5, 6)
2786+
void __ext4_abort(struct super_block *, const char *, unsigned int, int,
27882787
const char *, ...);
27892788
extern __printf(4, 5)
27902789
void __ext4_warning(struct super_block *, const char *, unsigned int,
@@ -2805,22 +2804,31 @@ void __ext4_grp_locked_error(const char *, unsigned int,
28052804
#define EXT4_ERROR_INODE(inode, fmt, a...) \
28062805
ext4_error_inode((inode), __func__, __LINE__, 0, (fmt), ## a)
28072806

2808-
#define EXT4_ERROR_INODE_BLOCK(inode, block, fmt, a...) \
2809-
ext4_error_inode((inode), __func__, __LINE__, (block), (fmt), ## a)
2807+
#define EXT4_ERROR_INODE_ERR(inode, err, fmt, a...) \
2808+
__ext4_error_inode((inode), __func__, __LINE__, 0, (err), (fmt), ## a)
2809+
2810+
#define ext4_error_inode_block(inode, block, err, fmt, a...) \
2811+
__ext4_error_inode((inode), __func__, __LINE__, (block), (err), \
2812+
(fmt), ## a)
28102813

28112814
#define EXT4_ERROR_FILE(file, block, fmt, a...) \
28122815
ext4_error_file((file), __func__, __LINE__, (block), (fmt), ## a)
28132816

28142817
#ifdef CONFIG_PRINTK
28152818

28162819
#define ext4_error_inode(inode, func, line, block, fmt, ...) \
2817-
__ext4_error_inode(inode, func, line, block, fmt, ##__VA_ARGS__)
2820+
__ext4_error_inode(inode, func, line, block, 0, fmt, ##__VA_ARGS__)
2821+
#define ext4_error_inode_err(inode, func, line, block, err, fmt, ...) \
2822+
__ext4_error_inode((inode), (func), (line), (block), \
2823+
(err), (fmt), ##__VA_ARGS__)
28182824
#define ext4_error_file(file, func, line, block, fmt, ...) \
28192825
__ext4_error_file(file, func, line, block, fmt, ##__VA_ARGS__)
28202826
#define ext4_error(sb, fmt, ...) \
2821-
__ext4_error(sb, __func__, __LINE__, fmt, ##__VA_ARGS__)
2822-
#define ext4_abort(sb, fmt, ...) \
2823-
__ext4_abort(sb, __func__, __LINE__, fmt, ##__VA_ARGS__)
2827+
__ext4_error((sb), __func__, __LINE__, 0, 0, (fmt), ##__VA_ARGS__)
2828+
#define ext4_error_err(sb, err, fmt, ...) \
2829+
__ext4_error((sb), __func__, __LINE__, (err), 0, (fmt), ##__VA_ARGS__)
2830+
#define ext4_abort(sb, err, fmt, ...) \
2831+
__ext4_abort((sb), __func__, __LINE__, (err), (fmt), ##__VA_ARGS__)
28242832
#define ext4_warning(sb, fmt, ...) \
28252833
__ext4_warning(sb, __func__, __LINE__, fmt, ##__VA_ARGS__)
28262834
#define ext4_warning_inode(inode, fmt, ...) \
@@ -2838,7 +2846,12 @@ void __ext4_grp_locked_error(const char *, unsigned int,
28382846
#define ext4_error_inode(inode, func, line, block, fmt, ...) \
28392847
do { \
28402848
no_printk(fmt, ##__VA_ARGS__); \
2841-
__ext4_error_inode(inode, "", 0, block, " "); \
2849+
__ext4_error_inode(inode, "", 0, block, 0, " "); \
2850+
} while (0)
2851+
#define ext4_error_inode_err(inode, func, line, block, err, fmt, ...) \
2852+
do { \
2853+
no_printk(fmt, ##__VA_ARGS__); \
2854+
__ext4_error_inode(inode, "", 0, block, err, " "); \
28422855
} while (0)
28432856
#define ext4_error_file(file, func, line, block, fmt, ...) \
28442857
do { \
@@ -2848,12 +2861,17 @@ do { \
28482861
#define ext4_error(sb, fmt, ...) \
28492862
do { \
28502863
no_printk(fmt, ##__VA_ARGS__); \
2851-
__ext4_error(sb, "", 0, " "); \
2864+
__ext4_error(sb, "", 0, 0, 0, " "); \
2865+
} while (0)
2866+
#define ext4_error_err(sb, err, fmt, ...) \
2867+
do { \
2868+
no_printk(fmt, ##__VA_ARGS__); \
2869+
__ext4_error(sb, "", 0, err, 0, " "); \
28522870
} while (0)
2853-
#define ext4_abort(sb, fmt, ...) \
2871+
#define ext4_abort(sb, err, fmt, ...) \
28542872
do { \
28552873
no_printk(fmt, ##__VA_ARGS__); \
2856-
__ext4_abort(sb, "", 0, " "); \
2874+
__ext4_abort(sb, "", 0, err, " "); \
28572875
} while (0)
28582876
#define ext4_warning(sb, fmt, ...) \
28592877
do { \

fs/ext4/ext4_jbd2.c

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,7 @@ static int ext4_journal_check_start(struct super_block *sb)
8080
* take the FS itself readonly cleanly.
8181
*/
8282
if (journal && is_journal_aborted(journal)) {
83-
ext4_set_errno(sb, -journal->j_errno);
84-
ext4_abort(sb, "Detected aborted journal");
83+
ext4_abort(sb, -journal->j_errno, "Detected aborted journal");
8584
return -EROFS;
8685
}
8786
return 0;
@@ -272,8 +271,7 @@ int __ext4_forget(const char *where, unsigned int line, handle_t *handle,
272271
if (err) {
273272
ext4_journal_abort_handle(where, line, __func__,
274273
bh, handle, err);
275-
ext4_set_errno(inode->i_sb, -err);
276-
__ext4_abort(inode->i_sb, where, line,
274+
__ext4_abort(inode->i_sb, where, line, -err,
277275
"error %d when attempting revoke", err);
278276
}
279277
BUFFER_TRACE(bh, "exit");
@@ -343,11 +341,8 @@ int __ext4_handle_dirty_metadata(const char *where, unsigned int line,
343341
struct ext4_super_block *es;
344342

345343
es = EXT4_SB(inode->i_sb)->s_es;
346-
es->s_last_error_block =
347-
cpu_to_le64(bh->b_blocknr);
348-
ext4_set_errno(inode->i_sb, EIO);
349-
ext4_error_inode(inode, where, line,
350-
bh->b_blocknr,
344+
ext4_error_inode_err(inode, where, line,
345+
bh->b_blocknr, EIO,
351346
"IO error syncing itable block");
352347
err = -EIO;
353348
}

fs/ext4/extents.c

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -349,8 +349,8 @@ static int ext4_valid_extent_idx(struct inode *inode,
349349
}
350350

351351
static int ext4_valid_extent_entries(struct inode *inode,
352-
struct ext4_extent_header *eh,
353-
int depth)
352+
struct ext4_extent_header *eh,
353+
ext4_fsblk_t *pblk, int depth)
354354
{
355355
unsigned short entries;
356356
if (eh->eh_entries == 0)
@@ -361,8 +361,6 @@ static int ext4_valid_extent_entries(struct inode *inode,
361361
if (depth == 0) {
362362
/* leaf entries */
363363
struct ext4_extent *ext = EXT_FIRST_EXTENT(eh);
364-
struct ext4_super_block *es = EXT4_SB(inode->i_sb)->s_es;
365-
ext4_fsblk_t pblock = 0;
366364
ext4_lblk_t lblock = 0;
367365
ext4_lblk_t prev = 0;
368366
int len = 0;
@@ -374,8 +372,7 @@ static int ext4_valid_extent_entries(struct inode *inode,
374372
lblock = le32_to_cpu(ext->ee_block);
375373
len = ext4_ext_get_actual_len(ext);
376374
if ((lblock <= prev) && prev) {
377-
pblock = ext4_ext_pblock(ext);
378-
es->s_last_error_block = cpu_to_le64(pblock);
375+
*pblk = ext4_ext_pblock(ext);
379376
return 0;
380377
}
381378
ext++;
@@ -422,7 +419,7 @@ static int __ext4_ext_check(const char *function, unsigned int line,
422419
error_msg = "invalid eh_entries";
423420
goto corrupted;
424421
}
425-
if (!ext4_valid_extent_entries(inode, eh, depth)) {
422+
if (!ext4_valid_extent_entries(inode, eh, &pblk, depth)) {
426423
error_msg = "invalid extent entries";
427424
goto corrupted;
428425
}
@@ -440,14 +437,14 @@ static int __ext4_ext_check(const char *function, unsigned int line,
440437
return 0;
441438

442439
corrupted:
443-
ext4_set_errno(inode->i_sb, -err);
444-
ext4_error_inode(inode, function, line, 0,
445-
"pblk %llu bad header/extent: %s - magic %x, "
446-
"entries %u, max %u(%u), depth %u(%u)",
447-
(unsigned long long) pblk, error_msg,
448-
le16_to_cpu(eh->eh_magic),
449-
le16_to_cpu(eh->eh_entries), le16_to_cpu(eh->eh_max),
450-
max, le16_to_cpu(eh->eh_depth), depth);
440+
ext4_error_inode_err(inode, function, line, 0, -err,
441+
"pblk %llu bad header/extent: %s - magic %x, "
442+
"entries %u, max %u(%u), depth %u(%u)",
443+
(unsigned long long) pblk, error_msg,
444+
le16_to_cpu(eh->eh_magic),
445+
le16_to_cpu(eh->eh_entries),
446+
le16_to_cpu(eh->eh_max),
447+
max, le16_to_cpu(eh->eh_depth), depth);
451448
return err;
452449
}
453450

fs/ext4/ialloc.c

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -196,10 +196,9 @@ ext4_read_inode_bitmap(struct super_block *sb, ext4_group_t block_group)
196196
ext4_simulate_fail_bh(sb, bh, EXT4_SIM_IBITMAP_EIO);
197197
if (!buffer_uptodate(bh)) {
198198
put_bh(bh);
199-
ext4_set_errno(sb, EIO);
200-
ext4_error(sb, "Cannot read inode bitmap - "
201-
"block_group = %u, inode_bitmap = %llu",
202-
block_group, bitmap_blk);
199+
ext4_error_err(sb, EIO, "Cannot read inode bitmap - "
200+
"block_group = %u, inode_bitmap = %llu",
201+
block_group, bitmap_blk);
203202
ext4_mark_group_bitmap_corrupted(sb, block_group,
204203
EXT4_GROUP_INFO_IBITMAP_CORRUPT);
205204
return ERR_PTR(-EIO);
@@ -1244,9 +1243,9 @@ struct inode *ext4_orphan_get(struct super_block *sb, unsigned long ino)
12441243
inode = ext4_iget(sb, ino, EXT4_IGET_NORMAL);
12451244
if (IS_ERR(inode)) {
12461245
err = PTR_ERR(inode);
1247-
ext4_set_errno(sb, -err);
1248-
ext4_error(sb, "couldn't read orphan inode %lu (err %d)",
1249-
ino, err);
1246+
ext4_error_err(sb, -err,
1247+
"couldn't read orphan inode %lu (err %d)",
1248+
ino, err);
12501249
return inode;
12511250
}
12521251

fs/ext4/indirect.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1019,7 +1019,7 @@ static void ext4_free_branches(handle_t *handle, struct inode *inode,
10191019
* (should be rare).
10201020
*/
10211021
if (!bh) {
1022-
EXT4_ERROR_INODE_BLOCK(inode, nr,
1022+
ext4_error_inode_block(inode, nr, EIO,
10231023
"Read failure");
10241024
continue;
10251025
}

fs/ext4/inline.c

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -98,10 +98,9 @@ int ext4_get_max_inline_size(struct inode *inode)
9898

9999
error = ext4_get_inode_loc(inode, &iloc);
100100
if (error) {
101-
ext4_set_errno(inode->i_sb, -error);
102-
ext4_error_inode(inode, __func__, __LINE__, 0,
103-
"can't get inode location %lu",
104-
inode->i_ino);
101+
ext4_error_inode_err(inode, __func__, __LINE__, 0, -error,
102+
"can't get inode location %lu",
103+
inode->i_ino);
105104
return 0;
106105
}
107106

@@ -1762,9 +1761,9 @@ bool empty_inline_dir(struct inode *dir, int *has_inline_data)
17621761

17631762
err = ext4_get_inode_loc(dir, &iloc);
17641763
if (err) {
1765-
ext4_set_errno(dir->i_sb, -err);
1766-
EXT4_ERROR_INODE(dir, "error %d getting inode %lu block",
1767-
err, dir->i_ino);
1764+
EXT4_ERROR_INODE_ERR(dir, -err,
1765+
"error %d getting inode %lu block",
1766+
err, dir->i_ino);
17681767
return true;
17691768
}
17701769

0 commit comments

Comments
 (0)