btrfs: only keep track of data extents for async discard
authorDennis Zhou <dennis@kernel.org>
Thu, 2 Jan 2020 21:26:40 +0000 (16:26 -0500)
committerDavid Sterba <dsterba@suse.com>
Mon, 20 Jan 2020 15:41:00 +0000 (16:41 +0100)
As mentioned earlier, discarding data can be done either by issuing an
explicit discard or implicitly by reusing the LBA. Metadata block_groups
see much more frequent reuse due to well it being metadata. So instead
of explicitly discarding metadata block_groups, just leave them be and
let the latter implicit discarding be done for them.

For mixed block_groups, block_groups which contain both metadata and
data, we let them be as higher fragmentation is expected.

Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Dennis Zhou <dennis@kernel.org>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/block-group.h
fs/btrfs/discard.c

index a8d2edcd8760b7207d4e1224a4f6565602954181..5cf1ea33f284e32679e468e5f92478470d62c688 100644 (file)
@@ -182,6 +182,17 @@ static inline u64 btrfs_block_group_end(struct btrfs_block_group *block_group)
        return (block_group->start + block_group->length);
 }
 
+static inline bool btrfs_is_block_group_data_only(
+                                       struct btrfs_block_group *block_group)
+{
+       /*
+        * In mixed mode the fragmentation is expected to be high, lowering the
+        * efficiency, so only proper data block groups are considered.
+        */
+       return (block_group->flags & BTRFS_BLOCK_GROUP_DATA) &&
+              !(block_group->flags & BTRFS_BLOCK_GROUP_METADATA);
+}
+
 #ifdef CONFIG_BTRFS_DEBUG
 static inline int btrfs_should_fragment_free_space(
                struct btrfs_block_group *block_group)
index 0299981d0c62b88306e0c6ede6b7cba16fabfb2a..5af42e0317b7d95dbd6f5777f3beab84668ac3bc 100644 (file)
@@ -57,6 +57,9 @@ static void __add_to_discard_list(struct btrfs_discard_ctl *discard_ctl,
 static void add_to_discard_list(struct btrfs_discard_ctl *discard_ctl,
                                struct btrfs_block_group *block_group)
 {
+       if (!btrfs_is_block_group_data_only(block_group))
+               return;
+
        spin_lock(&discard_ctl->lock);
        __add_to_discard_list(discard_ctl, block_group);
        spin_unlock(&discard_ctl->lock);
@@ -169,7 +172,10 @@ again:
        if (block_group && now > block_group->discard_eligible_time) {
                if (block_group->discard_index == BTRFS_DISCARD_INDEX_UNUSED &&
                    block_group->used != 0) {
-                       __add_to_discard_list(discard_ctl, block_group);
+                       if (btrfs_is_block_group_data_only(block_group))
+                               __add_to_discard_list(discard_ctl, block_group);
+                       else
+                               list_del_init(&block_group->discard_list);
                        goto again;
                }
                if (block_group->discard_state == BTRFS_DISCARD_RESET_CURSOR) {
@@ -507,7 +513,9 @@ void btrfs_discard_update_discardable(struct btrfs_block_group *block_group,
        s32 extents_delta;
        s64 bytes_delta;
 
-       if (!block_group || !btrfs_test_opt(block_group->fs_info, DISCARD_ASYNC))
+       if (!block_group ||
+           !btrfs_test_opt(block_group->fs_info, DISCARD_ASYNC) ||
+           !btrfs_is_block_group_data_only(block_group))
                return;
 
        discard_ctl = &block_group->fs_info->discard_ctl;