summaryrefslogtreecommitdiffstats
path: root/fs/ext4
diff options
context:
space:
mode:
authorZhangXiaoxu <zhangxiaoxu5@huawei.com>2019-08-22 23:00:32 -0400
committerTheodore Ts'o <tytso@mit.edu>2019-08-22 23:00:32 -0400
commit7963e5ac901251c7a3b36fe7c987623a3f309393 (patch)
tree922d0f204bee33b9dfbfcf63cf1662c401e9e473 /fs/ext4
parente3d550c2c4f2f3dba469bc3c4b83d9332b4e99e1 (diff)
ext4: treat buffers with write errors as containing valid data
I got some errors when I repair an ext4 volume which stacked by an iscsi target: Entry 'test60' in / (2) has deleted/unused inode 73750. Clear? It can be reproduced when the network not good enough. When I debug this I found ext4 will read entry buffer from disk and the buffer is marked with write_io_error. If the buffer is marked with write_io_error, it means it already wroten to journal, and not checked out to disk. IOW, the journal is newer than the data in disk. If this journal record 'delete test60', it means the 'test60' still on the disk metadata. In this case, if we read the buffer from disk successfully and create file continue, the new journal record will overwrite the journal which record 'delete test60', then the entry corruptioned. So, use the buffer rather than read from disk if the buffer is marked with write_io_error. Signed-off-by: Zhang Xiaoxu <zhangxiaoxu5@huawei.com> Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Diffstat (limited to 'fs/ext4')
-rw-r--r--fs/ext4/ext4.h13
-rw-r--r--fs/ext4/inode.c4
2 files changed, 15 insertions, 2 deletions
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 17cc2dc13174..2348be3d66b7 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -3344,6 +3344,19 @@ static inline void ext4_clear_io_unwritten_flag(ext4_io_end_t *io_end)
3344 3344
3345extern const struct iomap_ops ext4_iomap_ops; 3345extern const struct iomap_ops ext4_iomap_ops;
3346 3346
3347static inline int ext4_buffer_uptodate(struct buffer_head *bh)
3348{
3349 /*
3350 * If the buffer has the write error flag, we have failed
3351 * to write out data in the block. In this case, we don't
3352 * have to read the block because we may read the old data
3353 * successfully.
3354 */
3355 if (!buffer_uptodate(bh) && buffer_write_io_error(bh))
3356 set_buffer_uptodate(bh);
3357 return buffer_uptodate(bh);
3358}
3359
3347#endif /* __KERNEL__ */ 3360#endif /* __KERNEL__ */
3348 3361
3349#define EFSBADCRC EBADMSG /* Bad CRC detected */ 3362#define EFSBADCRC EBADMSG /* Bad CRC detected */
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 4b92c7603907..9db896fc6af8 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -1024,7 +1024,7 @@ struct buffer_head *ext4_bread(handle_t *handle, struct inode *inode,
1024 bh = ext4_getblk(handle, inode, block, map_flags); 1024 bh = ext4_getblk(handle, inode, block, map_flags);
1025 if (IS_ERR(bh)) 1025 if (IS_ERR(bh))
1026 return bh; 1026 return bh;
1027 if (!bh || buffer_uptodate(bh)) 1027 if (!bh || ext4_buffer_uptodate(bh))
1028 return bh; 1028 return bh;
1029 ll_rw_block(REQ_OP_READ, REQ_META | REQ_PRIO, 1, &bh); 1029 ll_rw_block(REQ_OP_READ, REQ_META | REQ_PRIO, 1, &bh);
1030 wait_on_buffer(bh); 1030 wait_on_buffer(bh);
@@ -1051,7 +1051,7 @@ int ext4_bread_batch(struct inode *inode, ext4_lblk_t block, int bh_count,
1051 1051
1052 for (i = 0; i < bh_count; i++) 1052 for (i = 0; i < bh_count; i++)
1053 /* Note that NULL bhs[i] is valid because of holes. */ 1053 /* Note that NULL bhs[i] is valid because of holes. */
1054 if (bhs[i] && !buffer_uptodate(bhs[i])) 1054 if (bhs[i] && !ext4_buffer_uptodate(bhs[i]))
1055 ll_rw_block(REQ_OP_READ, REQ_META | REQ_PRIO, 1, 1055 ll_rw_block(REQ_OP_READ, REQ_META | REQ_PRIO, 1,
1056 &bhs[i]); 1056 &bhs[i]);
1057 1057