ext4: do not polute the extents cache while shifting extents
authorRoman Pen <roman.penyaev@profitbricks.com>
Mon, 9 Jan 2017 02:00:35 +0000 (21:00 -0500)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 12 Mar 2017 05:37:27 +0000 (06:37 +0100)
commit 03e916fa8b5577d85471452a3d0c5738aa658dae upstream.

Inside ext4_ext_shift_extents() function ext4_find_extent() is called
without EXT4_EX_NOCACHE flag, which should prevent cache population.

This leads to oudated offsets in the extents tree and wrong blocks
afterwards.

Patch fixes the problem providing EXT4_EX_NOCACHE flag for each
ext4_find_extents() call inside ext4_ext_shift_extents function.

Fixes: 331573febb6a2
Signed-off-by: Roman Pen <roman.penyaev@profitbricks.com>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Cc: Namjae Jeon <namjae.jeon@samsung.com>
Cc: Andreas Dilger <adilger.kernel@dilger.ca>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
fs/ext4/extents.c

index ffc9fe0e7b79b3d5e14e6785055a6cbd6baa349b..8a456f9b8a4485d540423ececc5eb3f0252712dc 100644 (file)
@@ -5362,7 +5362,8 @@ ext4_ext_shift_extents(struct inode *inode, handle_t *handle,
        ext4_lblk_t stop, *iterator, ex_start, ex_end;
 
        /* Let path point to the last extent */
-       path = ext4_find_extent(inode, EXT_MAX_BLOCKS - 1, NULL, 0);
+       path = ext4_find_extent(inode, EXT_MAX_BLOCKS - 1, NULL,
+                               EXT4_EX_NOCACHE);
        if (IS_ERR(path))
                return PTR_ERR(path);
 
@@ -5378,7 +5379,8 @@ ext4_ext_shift_extents(struct inode *inode, handle_t *handle,
         * sure the hole is big enough to accommodate the shift.
        */
        if (SHIFT == SHIFT_LEFT) {
-               path = ext4_find_extent(inode, start - 1, &path, 0);
+               path = ext4_find_extent(inode, start - 1, &path,
+                                       EXT4_EX_NOCACHE);
                if (IS_ERR(path))
                        return PTR_ERR(path);
                depth = path->p_depth;
@@ -5416,7 +5418,8 @@ ext4_ext_shift_extents(struct inode *inode, handle_t *handle,
         * becomes NULL to indicate the end of the loop.
         */
        while (iterator && start <= stop) {
-               path = ext4_find_extent(inode, *iterator, &path, 0);
+               path = ext4_find_extent(inode, *iterator, &path,
+                                       EXT4_EX_NOCACHE);
                if (IS_ERR(path))
                        return PTR_ERR(path);
                depth = path->p_depth;