add patch use-EXT_MAX_BLOCKS-in-ext4_es_can_be_merged
[ext4-patch-queue.git] / fix-extent-merging-in-ext4_shift_path_extents
blobdb30bf2bc7203834a724059ae248590f4820895f
1 ext4: fix extent merging in ext4_ext_shift_path_extents()
3 From: Lukas Czerner <lczerner@redhat.com>
5 There is a bug in ext4_ext_shift_path_extents() where if we actually
6 manage to merge a extent we would skip shifting the next extent. This
7 will result in in one extent in the extent tree not being properly
8 shifted.
10 This is causing failure in various xfstests tests using fsx or fsstress
11 with collapse range support. It will also cause file system corruption
12 which looks something like:
14  e2fsck 1.42.9 (4-Feb-2014)
15  Pass 1: Checking inodes, blocks, and sizes
16  Inode 20 has out of order extents
17         (invalid logical block 3, physical block 492938, len 2)
18  Clear? yes
19  ...
21 when running e2fsck.
23 It's also very easily reproducible just by running fsx without any
24 parameters. I can usually hit the problem within a minute.
26 Fix it by increasing ex_start only if we're not merging the extent.
28 Signed-off-by: Lukas Czerner <lczerner@redhat.com>
29 Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
30 Reviewed-by: Namjae Jeon <namjae.jeon@samsung.com>
31 ---
32  fs/ext4/extents.c | 15 ++++++++-------
33  1 file changed, 8 insertions(+), 7 deletions(-)
35 diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
36 index 283e2e8..0503b43 100644
37 --- a/fs/ext4/extents.c
38 +++ b/fs/ext4/extents.c
39 @@ -5263,13 +5263,14 @@ ext4_ext_shift_path_extents(struct ext4_ext_path *path, ext4_lblk_t shift,
41                         while (ex_start <= ex_last) {
42                                 le32_add_cpu(&ex_start->ee_block, -shift);
43 -                               if (ex_start >
44 -                                       EXT_FIRST_EXTENT(path[depth].p_hdr)) {
45 -                                       if (ext4_ext_try_to_merge_right(inode,
46 -                                               path, ex_start - 1))
47 -                                               ex_last--;
48 -                               }
49 -                               ex_start++;
50 +                               /* Try to merge to the left. */
51 +                               if ((ex_start >
52 +                                    EXT_FIRST_EXTENT(path[depth].p_hdr)) &&
53 +                                   ext4_ext_try_to_merge_right(inode,
54 +                                                       path, ex_start - 1))
55 +                                       ex_last--;
56 +                               else
57 +                                       ex_start++;
58                         }
59                         err = ext4_ext_dirty(handle, inode, path + depth);
60                         if (err)