Commit 4aa9ad52 authored by Dennis Zhou's avatar Dennis Zhou Committed by David Sterba

btrfs: limit max discard size for async discard

Throttle the maximum size of a discard so that we can provide an upper
bound for the rate of async discard. While the block layer is able to
split discards into the appropriate sized discards, we want to be able
to account more accurately the rate at which we are consuming NCQ slots
as well as limit the upper bound of work for a discard.
Reviewed-by: default avatarJosef Bacik <josef@toxicpanda.com>
Signed-off-by: default avatarDennis Zhou <dennis@kernel.org>
Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent e93591bb
...@@ -3,10 +3,15 @@ ...@@ -3,10 +3,15 @@
#ifndef BTRFS_DISCARD_H #ifndef BTRFS_DISCARD_H
#define BTRFS_DISCARD_H #define BTRFS_DISCARD_H
#include <linux/sizes.h>
struct btrfs_fs_info; struct btrfs_fs_info;
struct btrfs_discard_ctl; struct btrfs_discard_ctl;
struct btrfs_block_group; struct btrfs_block_group;
/* Discard size limits */
#define BTRFS_ASYNC_DISCARD_MAX_SIZE (SZ_64M)
/* Work operations */ /* Work operations */
void btrfs_discard_cancel_work(struct btrfs_discard_ctl *discard_ctl, void btrfs_discard_cancel_work(struct btrfs_discard_ctl *discard_ctl,
struct btrfs_block_group *block_group); struct btrfs_block_group *block_group);
......
...@@ -3466,6 +3466,25 @@ static int trim_no_bitmap(struct btrfs_block_group *block_group, ...@@ -3466,6 +3466,25 @@ static int trim_no_bitmap(struct btrfs_block_group *block_group,
extent_start = entry->offset; extent_start = entry->offset;
extent_bytes = entry->bytes; extent_bytes = entry->bytes;
extent_trim_state = entry->trim_state; extent_trim_state = entry->trim_state;
if (async) {
start = entry->offset;
bytes = entry->bytes;
if (bytes < minlen) {
spin_unlock(&ctl->tree_lock);
mutex_unlock(&ctl->cache_writeout_mutex);
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;
link_free_space(ctl, entry);
} else {
kmem_cache_free(btrfs_free_space_cachep, entry);
}
} else {
start = max(start, extent_start); start = max(start, extent_start);
bytes = min(extent_start + extent_bytes, end) - start; bytes = min(extent_start + extent_bytes, end) - start;
if (bytes < minlen) { if (bytes < minlen) {
...@@ -3476,6 +3495,7 @@ static int trim_no_bitmap(struct btrfs_block_group *block_group, ...@@ -3476,6 +3495,7 @@ static int trim_no_bitmap(struct btrfs_block_group *block_group,
unlink_free_space(ctl, entry); unlink_free_space(ctl, entry);
kmem_cache_free(btrfs_free_space_cachep, entry); kmem_cache_free(btrfs_free_space_cachep, entry);
}
spin_unlock(&ctl->tree_lock); spin_unlock(&ctl->tree_lock);
trim_entry.start = extent_start; trim_entry.start = extent_start;
...@@ -3639,6 +3659,9 @@ static int trim_bitmaps(struct btrfs_block_group *block_group, ...@@ -3639,6 +3659,9 @@ static int trim_bitmaps(struct btrfs_block_group *block_group,
goto next; goto next;
} }
if (async && bytes > BTRFS_ASYNC_DISCARD_MAX_SIZE)
bytes = BTRFS_ASYNC_DISCARD_MAX_SIZE;
bitmap_clear_bits(ctl, entry, start, bytes); bitmap_clear_bits(ctl, entry, start, bytes);
if (entry->bytes == 0) if (entry->bytes == 0)
free_bitmap(ctl, entry); free_bitmap(ctl, entry);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment