]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
btrfs: make max async discard size tunable
authorDennis Zhou <dennis@kernel.org>
Thu, 2 Jan 2020 21:26:38 +0000 (16:26 -0500)
committerDavid Sterba <dsterba@suse.com>
Mon, 20 Jan 2020 15:40:59 +0000 (16:40 +0100)
Expose max_discard_size as a tunable via sysfs and switch the current
fixed maximum to the default value.

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/ctree.h
fs/btrfs/discard.c
fs/btrfs/discard.h
fs/btrfs/free-space-cache.c
fs/btrfs/sysfs.c

index f58b1cfeeca683fb03ca1f47aa5b87575330cd72..fa6c95fdf5c6841a5411f382b462d218316bc61f 100644 (file)
@@ -469,6 +469,7 @@ struct btrfs_discard_ctl {
        u64 prev_discard;
        atomic_t discardable_extents;
        atomic64_t discardable_bytes;
+       u64 max_discard_size;
        unsigned long delay;
        u32 iops_limit;
        u32 kbps_limit;
index 565931f9a9aa897a51abaede60148aec3b6c1ee9..5fdd82c356a406c91e6103f724a1204d911f3ded 100644 (file)
@@ -527,6 +527,7 @@ void btrfs_discard_init(struct btrfs_fs_info *fs_info)
        discard_ctl->prev_discard = 0;
        atomic_set(&discard_ctl->discardable_extents, 0);
        atomic64_set(&discard_ctl->discardable_bytes, 0);
+       discard_ctl->max_discard_size = BTRFS_ASYNC_DISCARD_DEFAULT_MAX_SIZE;
        discard_ctl->delay = BTRFS_DISCARD_MAX_DELAY_MSEC;
        discard_ctl->iops_limit = BTRFS_DISCARD_MAX_IOPS;
        discard_ctl->kbps_limit = 0;
index 562c60fab77a90d6b141eaf87027a019705d48ad..f9445ee5dcc329966d2c66094d4e768a91bae2cc 100644 (file)
@@ -10,7 +10,7 @@ struct btrfs_discard_ctl;
 struct btrfs_block_group;
 
 /* Discard size limits */
-#define BTRFS_ASYNC_DISCARD_MAX_SIZE   (SZ_64M)
+#define BTRFS_ASYNC_DISCARD_DEFAULT_MAX_SIZE           (SZ_64M)
 
 /* Work operations */
 void btrfs_discard_cancel_work(struct btrfs_discard_ctl *discard_ctl,
index 438043aab6fb7f068eb4f11fd62bdef6d8a7251c..db90bea30a8d085768a7619970fd91b7badfe24f 100644 (file)
@@ -3428,6 +3428,8 @@ static int trim_no_bitmap(struct btrfs_block_group *block_group,
                          u64 *total_trimmed, u64 start, u64 end, u64 minlen,
                          bool async)
 {
+       struct btrfs_discard_ctl *discard_ctl =
+                                       &block_group->fs_info->discard_ctl;
        struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl;
        struct btrfs_free_space *entry;
        struct rb_node *node;
@@ -3436,6 +3438,7 @@ static int trim_no_bitmap(struct btrfs_block_group *block_group,
        u64 extent_bytes;
        enum btrfs_trim_state extent_trim_state;
        u64 bytes;
+       const u64 max_discard_size = READ_ONCE(discard_ctl->max_discard_size);
 
        while (start < end) {
                struct btrfs_trim_range trim_entry;
@@ -3475,11 +3478,11 @@ static int trim_no_bitmap(struct btrfs_block_group *block_group,
                                goto next;
                        }
                        unlink_free_space(ctl, entry);
-                       if (bytes > BTRFS_ASYNC_DISCARD_MAX_SIZE) {
-                               bytes = BTRFS_ASYNC_DISCARD_MAX_SIZE;
-                               extent_bytes = BTRFS_ASYNC_DISCARD_MAX_SIZE;
-                               entry->offset += BTRFS_ASYNC_DISCARD_MAX_SIZE;
-                               entry->bytes -= BTRFS_ASYNC_DISCARD_MAX_SIZE;
+                       if (max_discard_size && bytes > max_discard_size) {
+                               bytes = max_discard_size;
+                               extent_bytes = max_discard_size;
+                               entry->offset += max_discard_size;
+                               entry->bytes -= max_discard_size;
                                link_free_space(ctl, entry);
                        } else {
                                kmem_cache_free(btrfs_free_space_cachep, entry);
@@ -3584,12 +3587,15 @@ static int trim_bitmaps(struct btrfs_block_group *block_group,
                        u64 *total_trimmed, u64 start, u64 end, u64 minlen,
                        bool async)
 {
+       struct btrfs_discard_ctl *discard_ctl =
+                                       &block_group->fs_info->discard_ctl;
        struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl;
        struct btrfs_free_space *entry;
        int ret = 0;
        int ret2;
        u64 bytes;
        u64 offset = offset_to_bitmap(ctl, start);
+       const u64 max_discard_size = READ_ONCE(discard_ctl->max_discard_size);
 
        while (offset < end) {
                bool next_bitmap = false;
@@ -3659,8 +3665,8 @@ static int trim_bitmaps(struct btrfs_block_group *block_group,
                        goto next;
                }
 
-               if (async && bytes > BTRFS_ASYNC_DISCARD_MAX_SIZE)
-                       bytes = BTRFS_ASYNC_DISCARD_MAX_SIZE;
+               if (async && max_discard_size && bytes > max_discard_size)
+                       bytes = max_discard_size;
 
                bitmap_clear_bits(ctl, entry, start, bytes);
                if (entry->bytes == 0)
index 0168bc12875ef4eaf35efe0ffbe56b755efc8d9a..eac0155bf8c7765a2a66848e7674d86cca0cefb6 100644 (file)
@@ -426,11 +426,42 @@ static ssize_t btrfs_discard_kbps_limit_store(struct kobject *kobj,
 BTRFS_ATTR_RW(discard, kbps_limit, btrfs_discard_kbps_limit_show,
              btrfs_discard_kbps_limit_store);
 
+static ssize_t btrfs_discard_max_discard_size_show(struct kobject *kobj,
+                                                  struct kobj_attribute *a,
+                                                  char *buf)
+{
+       struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj);
+
+       return snprintf(buf, PAGE_SIZE, "%llu\n",
+                       READ_ONCE(fs_info->discard_ctl.max_discard_size));
+}
+
+static ssize_t btrfs_discard_max_discard_size_store(struct kobject *kobj,
+                                                   struct kobj_attribute *a,
+                                                   const char *buf, size_t len)
+{
+       struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj);
+       struct btrfs_discard_ctl *discard_ctl = &fs_info->discard_ctl;
+       u64 max_discard_size;
+       int ret;
+
+       ret = kstrtou64(buf, 10, &max_discard_size);
+       if (ret)
+               return -EINVAL;
+
+       WRITE_ONCE(discard_ctl->max_discard_size, max_discard_size);
+
+       return len;
+}
+BTRFS_ATTR_RW(discard, max_discard_size, btrfs_discard_max_discard_size_show,
+             btrfs_discard_max_discard_size_store);
+
 static const struct attribute *discard_debug_attrs[] = {
        BTRFS_ATTR_PTR(discard, discardable_bytes),
        BTRFS_ATTR_PTR(discard, discardable_extents),
        BTRFS_ATTR_PTR(discard, iops_limit),
        BTRFS_ATTR_PTR(discard, kbps_limit),
+       BTRFS_ATTR_PTR(discard, max_discard_size),
        NULL,
 };