OSDN Git Service

Btrfs: fix race between readahead and device replace/removal
[sagit-ice-cold/kernel_xiaomi_msm8998.git] / fs / btrfs / free-space-cache.c
index 85a1f86..6c01612 100644 (file)
@@ -891,7 +891,7 @@ out:
                spin_unlock(&block_group->lock);
                ret = 0;
 
-               btrfs_warn(fs_info, "failed to load free space cache for block group %llu, rebuild it now",
+               btrfs_warn(fs_info, "failed to load free space cache for block group %llu, rebuilding it now",
                        block_group->key.objectid);
        }
 
@@ -1258,7 +1258,7 @@ static int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode,
        /* Lock all pages first so we can lock the extent safely. */
        ret = io_ctl_prepare_pages(io_ctl, inode, 0);
        if (ret)
-               goto out;
+               goto out_unlock;
 
        lock_extent_bits(&BTRFS_I(inode)->io_tree, 0, i_size_read(inode) - 1,
                         0, &cached_state);
@@ -1351,6 +1351,7 @@ out_nospc_locked:
 out_nospc:
        cleanup_write_cache_enospc(inode, io_ctl, &cached_state, &bitmap_list);
 
+out_unlock:
        if (block_group && (block_group->flags & BTRFS_BLOCK_GROUP_DATA))
                up_write(&block_group->data_rwsem);
 
@@ -1698,6 +1699,8 @@ static inline void __bitmap_clear_bits(struct btrfs_free_space_ctl *ctl,
        bitmap_clear(info->bitmap, start, count);
 
        info->bytes -= bytes;
+       if (info->max_extent_size > ctl->unit)
+               info->max_extent_size = 0;
 }
 
 static void bitmap_clear_bits(struct btrfs_free_space_ctl *ctl,
@@ -1781,6 +1784,13 @@ static int search_bitmap(struct btrfs_free_space_ctl *ctl,
        return -1;
 }
 
+static inline u64 get_max_extent_size(struct btrfs_free_space *entry)
+{
+       if (entry->bitmap)
+               return entry->max_extent_size;
+       return entry->bytes;
+}
+
 /* Cache the size of the max extent in bytes */
 static struct btrfs_free_space *
 find_free_space(struct btrfs_free_space_ctl *ctl, u64 *offset, u64 *bytes,
@@ -1802,8 +1812,8 @@ find_free_space(struct btrfs_free_space_ctl *ctl, u64 *offset, u64 *bytes,
        for (node = &entry->offset_index; node; node = rb_next(node)) {
                entry = rb_entry(node, struct btrfs_free_space, offset_index);
                if (entry->bytes < *bytes) {
-                       if (entry->bytes > *max_extent_size)
-                               *max_extent_size = entry->bytes;
+                       *max_extent_size = max(get_max_extent_size(entry),
+                                              *max_extent_size);
                        continue;
                }
 
@@ -1821,8 +1831,8 @@ find_free_space(struct btrfs_free_space_ctl *ctl, u64 *offset, u64 *bytes,
                }
 
                if (entry->bytes < *bytes + align_off) {
-                       if (entry->bytes > *max_extent_size)
-                               *max_extent_size = entry->bytes;
+                       *max_extent_size = max(get_max_extent_size(entry),
+                                              *max_extent_size);
                        continue;
                }
 
@@ -1834,8 +1844,10 @@ find_free_space(struct btrfs_free_space_ctl *ctl, u64 *offset, u64 *bytes,
                                *offset = tmp;
                                *bytes = size;
                                return entry;
-                       } else if (size > *max_extent_size) {
-                               *max_extent_size = size;
+                       } else {
+                               *max_extent_size =
+                                       max(get_max_extent_size(entry),
+                                           *max_extent_size);
                        }
                        continue;
                }
@@ -2457,6 +2469,7 @@ void btrfs_dump_free_space(struct btrfs_block_group_cache *block_group,
        struct rb_node *n;
        int count = 0;
 
+       spin_lock(&ctl->tree_lock);
        for (n = rb_first(&ctl->free_space_offset); n; n = rb_next(n)) {
                info = rb_entry(n, struct btrfs_free_space, offset_index);
                if (info->bytes >= bytes && !block_group->ro)
@@ -2466,6 +2479,7 @@ void btrfs_dump_free_space(struct btrfs_block_group_cache *block_group,
                           info->offset, info->bytes,
                       (info->bitmap) ? "yes" : "no");
        }
+       spin_unlock(&ctl->tree_lock);
        btrfs_info(block_group->fs_info, "block group has cluster?: %s",
               list_empty(&block_group->cluster_list) ? "no" : "yes");
        btrfs_info(block_group->fs_info,
@@ -2693,8 +2707,8 @@ static u64 btrfs_alloc_from_bitmap(struct btrfs_block_group_cache *block_group,
 
        err = search_bitmap(ctl, entry, &search_start, &search_bytes, true);
        if (err) {
-               if (search_bytes > *max_extent_size)
-                       *max_extent_size = search_bytes;
+               *max_extent_size = max(get_max_extent_size(entry),
+                                      *max_extent_size);
                return 0;
        }
 
@@ -2731,8 +2745,9 @@ u64 btrfs_alloc_from_cluster(struct btrfs_block_group_cache *block_group,
 
        entry = rb_entry(node, struct btrfs_free_space, offset_index);
        while (1) {
-               if (entry->bytes < bytes && entry->bytes > *max_extent_size)
-                       *max_extent_size = entry->bytes;
+               if (entry->bytes < bytes)
+                       *max_extent_size = max(get_max_extent_size(entry),
+                                              *max_extent_size);
 
                if (entry->bytes < bytes ||
                    (!entry->bitmap && entry->offset < min_start)) {
@@ -2972,7 +2987,7 @@ setup_cluster_bitmap(struct btrfs_block_group_cache *block_group,
                     u64 cont1_bytes, u64 min_bytes)
 {
        struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl;
-       struct btrfs_free_space *entry;
+       struct btrfs_free_space *entry = NULL;
        int ret = -ENOSPC;
        u64 bitmap_offset = offset_to_bitmap(ctl, offset);
 
@@ -2983,8 +2998,10 @@ setup_cluster_bitmap(struct btrfs_block_group_cache *block_group,
         * The bitmap that covers offset won't be in the list unless offset
         * is just its start offset.
         */
-       entry = list_first_entry(bitmaps, struct btrfs_free_space, list);
-       if (entry->offset != bitmap_offset) {
+       if (!list_empty(bitmaps))
+               entry = list_first_entry(bitmaps, struct btrfs_free_space, list);
+
+       if (!entry || entry->offset != bitmap_offset) {
                entry = tree_search_offset(ctl, bitmap_offset, 1, 0);
                if (entry && list_empty(&entry->list))
                        list_add(&entry->list, bitmaps);