btrfs: don't use ctl->free_space for max_extent_size
authorJosef Bacik <jbacik@fb.com>
Thu, 11 Oct 2018 19:54:09 +0000 (15:54 -0400)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 13 Nov 2018 19:08:59 +0000 (11:08 -0800)
commit fb5c39d7a887108087de6ff93d3f326b01b4ef41 upstream.

max_extent_size is supposed to be the largest contiguous range for the
space info, and ctl->free_space is the total free space in the block
group.  We need to keep track of these separately and _only_ use the
max_free_space if we don't have a max_extent_size, as that means our
original request was too large to search any of the block groups for and
therefore wouldn't have a max_extent_size set.

CC: stable@vger.kernel.org # 4.14+
Reviewed-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: Josef Bacik <jbacik@fb.com>
Signed-off-by: David Sterba <dsterba@suse.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
fs/btrfs/extent-tree.c

index 5fa6a78..a43554b 100644 (file)
@@ -7230,6 +7230,7 @@ static noinline int find_free_extent(struct btrfs_fs_info *fs_info,
        struct btrfs_block_group_cache *block_group = NULL;
        u64 search_start = 0;
        u64 max_extent_size = 0;
+       u64 max_free_space = 0;
        u64 empty_cluster = 0;
        struct btrfs_space_info *space_info;
        int loop = 0;
@@ -7525,8 +7526,8 @@ unclustered_alloc:
                        spin_lock(&ctl->tree_lock);
                        if (ctl->free_space <
                            num_bytes + empty_cluster + empty_size) {
-                               if (ctl->free_space > max_extent_size)
-                                       max_extent_size = ctl->free_space;
+                               max_free_space = max(max_free_space,
+                                                    ctl->free_space);
                                spin_unlock(&ctl->tree_lock);
                                goto loop;
                        }
@@ -7693,6 +7694,8 @@ loop:
        }
 out:
        if (ret == -ENOSPC) {
+               if (!max_extent_size)
+                       max_extent_size = max_free_space;
                spin_lock(&space_info->lock);
                space_info->max_extent_size = max_extent_size;
                spin_unlock(&space_info->lock);