add patch fix-potential-use-after-free-after-remounting-with-noblock_validity
[ext4-patch-queue.git] / treat-buffers-with-write-errors-as-contining-valid-data
blobe334a543d059e7ad5c77ac7a9a9001ef005c425d
1 ext4: treat buffers with write errors as containing valid data
3 From: ZhangXiaoxu <zhangxiaoxu5@huawei.com>
5 I got some errors when I repair an ext4 volume which stacked by an
6 iscsi target:
7     Entry 'test60' in / (2) has deleted/unused inode 73750.  Clear?
8 It can be reproduced when the network not good enough.
10 When I debug this I found ext4 will read entry buffer from disk and
11 the buffer is marked with write_io_error.
13 If the buffer is marked with write_io_error, it means it already
14 wroten to journal, and not checked out to disk. IOW, the journal
15 is newer than the data in disk.
16 If this journal record 'delete test60', it means the 'test60' still
17 on the disk metadata.
19 In this case, if we read the buffer from disk successfully and create
20 file continue, the new journal record will overwrite the journal
21 which record 'delete test60', then the entry corruptioned.
23 So, use the buffer rather than read from disk if the buffer is marked
24 with write_io_error.
26 Signed-off-by: Zhang Xiaoxu <zhangxiaoxu5@huawei.com>
27 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
28 ---
29  fs/ext4/ext4.h  | 13 +++++++++++++
30  fs/ext4/inode.c |  4 ++--
31  2 files changed, 15 insertions(+), 2 deletions(-)
33 diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
34 index 1cb6785..5ebb36d 100644
35 --- a/fs/ext4/ext4.h
36 +++ b/fs/ext4/ext4.h
37 @@ -3301,6 +3301,19 @@ static inline void ext4_clear_io_unwritten_flag(ext4_io_end_t *io_end)
39  extern const struct iomap_ops ext4_iomap_ops;
41 +static inline int ext4_buffer_uptodate(struct buffer_head *bh)
43 +       /*
44 +        * If the buffer has the write error flag, we have failed
45 +        * to write out data in the block.  In this  case, we don't
46 +        * have to read the block because we may read the old data
47 +        * successfully.
48 +        */
49 +       if (!buffer_uptodate(bh) && buffer_write_io_error(bh))
50 +               set_buffer_uptodate(bh);
51 +       return buffer_uptodate(bh);
54  #endif /* __KERNEL__ */
56  #define EFSBADCRC      EBADMSG         /* Bad CRC detected */
57 diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
58 index 82298c6..3546388 100644
59 --- a/fs/ext4/inode.c
60 +++ b/fs/ext4/inode.c
61 @@ -1018,7 +1018,7 @@ struct buffer_head *ext4_bread(handle_t *handle, struct inode *inode,
62         bh = ext4_getblk(handle, inode, block, map_flags);
63         if (IS_ERR(bh))
64                 return bh;
65 -       if (!bh || buffer_uptodate(bh))
66 +       if (!bh || ext4_buffer_uptodate(bh))
67                 return bh;
68         ll_rw_block(REQ_OP_READ, REQ_META | REQ_PRIO, 1, &bh);
69         wait_on_buffer(bh);
70 @@ -1045,7 +1045,7 @@ int ext4_bread_batch(struct inode *inode, ext4_lblk_t block, int bh_count,
72         for (i = 0; i < bh_count; i++)
73                 /* Note that NULL bhs[i] is valid because of holes. */
74 -               if (bhs[i] && !buffer_uptodate(bhs[i]))
75 +               if (bhs[i] && !ext4_buffer_uptodate(bhs[i]))
76                         ll_rw_block(REQ_OP_READ, REQ_META | REQ_PRIO, 1,
77                                     &bhs[i]);
79 -- 
80 2.7.4