Skip to content

Commit 15baa7d

Browse files
zhangyi089tytso
authored andcommitted
ext4: fix warning when submitting superblock in ext4_commit_super()
We have already check the io_error and uptodate flag before submitting the superblock buffer, and re-set the uptodate flag if it has been failed to write out. But it was lockless and could be raced by another ext4_commit_super(), and finally trigger '!uptodate' WARNING when marking buffer dirty. Fix it by submit buffer directly. Reported-by: Hulk Robot <[email protected]> Signed-off-by: Zhang Yi <[email protected]> Reviewed-by: Jan Kara <[email protected]> Reviewed-by: Ritesh Harjani <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Theodore Ts'o <[email protected]>
1 parent 3103084 commit 15baa7d

File tree

1 file changed

+16
-6
lines changed

1 file changed

+16
-6
lines changed

fs/ext4/super.c

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5898,7 +5898,6 @@ static void ext4_update_super(struct super_block *sb)
58985898
static int ext4_commit_super(struct super_block *sb)
58995899
{
59005900
struct buffer_head *sbh = EXT4_SB(sb)->s_sbh;
5901-
int error = 0;
59025901

59035902
if (!sbh)
59045903
return -EINVAL;
@@ -5907,6 +5906,13 @@ static int ext4_commit_super(struct super_block *sb)
59075906

59085907
ext4_update_super(sb);
59095908

5909+
lock_buffer(sbh);
5910+
/* Buffer got discarded which means block device got invalidated */
5911+
if (!buffer_mapped(sbh)) {
5912+
unlock_buffer(sbh);
5913+
return -EIO;
5914+
}
5915+
59105916
if (buffer_write_io_error(sbh) || !buffer_uptodate(sbh)) {
59115917
/*
59125918
* Oh, dear. A previous attempt to write the
@@ -5921,17 +5927,21 @@ static int ext4_commit_super(struct super_block *sb)
59215927
clear_buffer_write_io_error(sbh);
59225928
set_buffer_uptodate(sbh);
59235929
}
5924-
BUFFER_TRACE(sbh, "marking dirty");
5925-
mark_buffer_dirty(sbh);
5926-
error = __sync_dirty_buffer(sbh,
5927-
REQ_SYNC | (test_opt(sb, BARRIER) ? REQ_FUA : 0));
5930+
get_bh(sbh);
5931+
/* Clear potential dirty bit if it was journalled update */
5932+
clear_buffer_dirty(sbh);
5933+
sbh->b_end_io = end_buffer_write_sync;
5934+
submit_bh(REQ_OP_WRITE,
5935+
REQ_SYNC | (test_opt(sb, BARRIER) ? REQ_FUA : 0), sbh);
5936+
wait_on_buffer(sbh);
59285937
if (buffer_write_io_error(sbh)) {
59295938
ext4_msg(sb, KERN_ERR, "I/O error while writing "
59305939
"superblock");
59315940
clear_buffer_write_io_error(sbh);
59325941
set_buffer_uptodate(sbh);
5942+
return -EIO;
59335943
}
5934-
return error;
5944+
return 0;
59355945
}
59365946

59375947
/*

0 commit comments

Comments
 (0)