summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYe Bin <yebin10@huawei.com>2022-03-21 22:44:38 +0800
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2022-04-27 13:53:56 +0200
commita46b3d8498646913209693de52e3ad61da04c64a (patch)
tree2708e0de41c4870902e117fccb875a60a5506c8d
parentf6038d43b25bba1cd50d2a77e207f6550aee9954 (diff)
downloadlinux-stable-a46b3d8498646913209693de52e3ad61da04c64a.tar.gz
linux-stable-a46b3d8498646913209693de52e3ad61da04c64a.tar.bz2
linux-stable-a46b3d8498646913209693de52e3ad61da04c64a.zip
ext4: fix symlink file size not match to file content
commit a2b0b205d125f27cddfb4f7280e39affdaf46686 upstream. We got issue as follows: [home]# fsck.ext4 -fn ram0yb e2fsck 1.45.6 (20-Mar-2020) Pass 1: Checking inodes, blocks, and sizes Pass 2: Checking directory structure Symlink /p3/d14/d1a/l3d (inode #3494) is invalid. Clear? no Entry 'l3d' in /p3/d14/d1a (3383) has an incorrect filetype (was 7, should be 0). Fix? no As the symlink file size does not match the file content. If the writeback of the symlink data block failed, ext4_finish_bio() handles the end of IO. However this function fails to mark the buffer with BH_write_io_error and so when unmount does journal checkpoint it cannot detect the writeback error and will cleanup the journal. Thus we've lost the correct data in the journal area. To solve this issue, mark the buffer as BH_write_io_error in ext4_finish_bio(). Cc: stable@kernel.org Signed-off-by: Ye Bin <yebin10@huawei.com> Reviewed-by: Jan Kara <jack@suse.cz> Link: https://lore.kernel.org/r/20220321144438.201685-1-yebin10@huawei.com Signed-off-by: Theodore Ts'o <tytso@mit.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--fs/ext4/page-io.c4
1 files changed, 3 insertions, 1 deletions
diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c
index defd2e10dfd1..4569075a7da0 100644
--- a/fs/ext4/page-io.c
+++ b/fs/ext4/page-io.c
@@ -137,8 +137,10 @@ static void ext4_finish_bio(struct bio *bio)
continue;
}
clear_buffer_async_write(bh);
- if (bio->bi_status)
+ if (bio->bi_status) {
+ set_buffer_write_io_error(bh);
buffer_io_error(bh);
+ }
} while ((bh = bh->b_this_page) != head);
spin_unlock_irqrestore(&head->b_uptodate_lock, flags);
if (!under_io) {