Btrfs: change how we calculate the global block rsv
[cascardo/linux.git] / fs / btrfs / extent-tree.c
index 31ded6a..7c644f8 100644 (file)
@@ -4936,7 +4936,7 @@ btrfs_calc_reclaim_metadata_size(struct btrfs_root *root,
 }
 
 static inline int need_do_async_reclaim(struct btrfs_space_info *space_info,
-                                       struct btrfs_fs_info *fs_info, u64 used)
+                                       struct btrfs_root *root, u64 used)
 {
        u64 thresh = div_factor_fine(space_info->total_bytes, 98);
 
@@ -4944,8 +4944,12 @@ static inline int need_do_async_reclaim(struct btrfs_space_info *space_info,
        if ((space_info->bytes_used + space_info->bytes_reserved) >= thresh)
                return 0;
 
-       return (used >= thresh && !btrfs_fs_closing(fs_info) &&
-               !test_bit(BTRFS_FS_STATE_REMOUNTING, &fs_info->fs_state));
+       if (!btrfs_calc_reclaim_metadata_size(root, space_info))
+               return 0;
+
+       return (used >= thresh && !btrfs_fs_closing(root->fs_info) &&
+               !test_bit(BTRFS_FS_STATE_REMOUNTING,
+                         &root->fs_info->fs_state));
 }
 
 static void wake_all_tickets(struct list_head *head)
@@ -5190,7 +5194,7 @@ static int __reserve_metadata_bytes(struct btrfs_root *root,
                 * the async reclaim as we will panic.
                 */
                if (!root->fs_info->log_root_recovering &&
-                   need_do_async_reclaim(space_info, root->fs_info, used) &&
+                   need_do_async_reclaim(space_info, root, used) &&
                    !work_busy(&root->fs_info->async_reclaim_work)) {
                        trace_btrfs_trigger_flush(root->fs_info,
                                                  space_info->flags,
@@ -5611,48 +5615,21 @@ void btrfs_block_rsv_release(struct btrfs_root *root,
                                num_bytes);
 }
 
-/*
- * helper to calculate size of global block reservation.
- * the desired value is sum of space used by extent tree,
- * checksum tree and root tree
- */
-static u64 calc_global_metadata_size(struct btrfs_fs_info *fs_info)
-{
-       struct btrfs_space_info *sinfo;
-       u64 num_bytes;
-       u64 meta_used;
-       u64 data_used;
-       int csum_size = btrfs_super_csum_size(fs_info->super_copy);
-
-       sinfo = __find_space_info(fs_info, BTRFS_BLOCK_GROUP_DATA);
-       spin_lock(&sinfo->lock);
-       data_used = sinfo->bytes_used;
-       spin_unlock(&sinfo->lock);
-
-       sinfo = __find_space_info(fs_info, BTRFS_BLOCK_GROUP_METADATA);
-       spin_lock(&sinfo->lock);
-       if (sinfo->flags & BTRFS_BLOCK_GROUP_DATA)
-               data_used = 0;
-       meta_used = sinfo->bytes_used;
-       spin_unlock(&sinfo->lock);
-
-       num_bytes = (data_used >> fs_info->sb->s_blocksize_bits) *
-                   csum_size * 2;
-       num_bytes += div_u64(data_used + meta_used, 50);
-
-       if (num_bytes * 3 > meta_used)
-               num_bytes = div_u64(meta_used, 3);
-
-       return ALIGN(num_bytes, fs_info->extent_root->nodesize << 10);
-}
-
 static void update_global_block_rsv(struct btrfs_fs_info *fs_info)
 {
        struct btrfs_block_rsv *block_rsv = &fs_info->global_block_rsv;
        struct btrfs_space_info *sinfo = block_rsv->space_info;
        u64 num_bytes;
 
-       num_bytes = calc_global_metadata_size(fs_info);
+       /*
+        * The global block rsv is based on the size of the extent tree, the
+        * checksum tree and the root tree.  If the fs is empty we want to set
+        * it to a minimal amount for safety.
+        */
+       num_bytes = btrfs_root_used(&fs_info->extent_root->root_item) +
+               btrfs_root_used(&fs_info->csum_root->root_item) +
+               btrfs_root_used(&fs_info->tree_root->root_item);
+       num_bytes = max_t(u64, num_bytes, SZ_16M);
 
        spin_lock(&sinfo->lock);
        spin_lock(&block_rsv->lock);
@@ -6331,8 +6308,6 @@ static int pin_down_extent(struct btrfs_root *root,
                                      cache->space_info->flags, num_bytes, 1);
        set_extent_dirty(root->fs_info->pinned_extents, bytenr,
                         bytenr + num_bytes - 1, GFP_NOFS | __GFP_NOFAIL);
-       if (reserved)
-               trace_btrfs_reserved_extent_free(root, bytenr, num_bytes);
        return 0;
 }
 
@@ -8008,12 +7983,10 @@ static int __btrfs_free_reserved_extent(struct btrfs_root *root,
                        ret = btrfs_discard_extent(root, start, len, NULL);
                btrfs_add_free_space(cache, start, len);
                btrfs_update_reserved_bytes(cache, len, RESERVE_FREE, delalloc);
+               trace_btrfs_reserved_extent_free(root, start, len);
        }
 
        btrfs_put_block_group(cache);
-
-       trace_btrfs_reserved_extent_free(root, start, len);
-
        return ret;
 }