@@ -3,10 +3,15 @@
#ifndef BTRFS_DISCARD_H
#define BTRFS_DISCARD_H
+#include <linux/sizes.h>
+
struct btrfs_fs_info;
struct btrfs_discard_ctl;
struct btrfs_block_group;
+/* Discard size limits. */
+#define BTRFS_ASYNC_DISCARD_MAX_SIZE (SZ_64M)
+
/* List operations. */
void btrfs_add_to_discard_list(struct btrfs_discard_ctl *discard_ctl,
struct btrfs_block_group *block_group);
@@ -3442,19 +3442,40 @@ static int trim_no_bitmap(struct btrfs_block_group *block_group,
if (entry->offset >= end)
goto out_unlock;
- extent_start = entry->offset;
- extent_bytes = entry->bytes;
- extent_trim_state = entry->trim_state;
- start = max(start, extent_start);
- bytes = min(extent_start + extent_bytes, end) - start;
- if (bytes < minlen) {
- spin_unlock(&ctl->tree_lock);
- mutex_unlock(&ctl->cache_writeout_mutex);
- goto next;
- }
+ if (async) {
+ start = extent_start = entry->offset;
+ bytes = extent_bytes = entry->bytes;
+ extent_trim_state = entry->trim_state;
+ 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 = 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 {
+ extent_start = entry->offset;
+ extent_bytes = entry->bytes;
+ extent_trim_state = entry->trim_state;
+ start = max(start, extent_start);
+ bytes = min(extent_start + extent_bytes, end) - start;
+ if (bytes < minlen) {
+ spin_unlock(&ctl->tree_lock);
+ mutex_unlock(&ctl->cache_writeout_mutex);
+ goto next;
+ }
- unlink_free_space(ctl, entry);
- kmem_cache_free(btrfs_free_space_cachep, entry);
+ unlink_free_space(ctl, entry);
+ kmem_cache_free(btrfs_free_space_cachep, entry);
+ }
spin_unlock(&ctl->tree_lock);
trim_entry.start = extent_start;
@@ -3619,6 +3640,9 @@ 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;
+
bitmap_clear_bits(ctl, entry, start, bytes);
if (entry->bytes == 0)
free_bitmap(ctl, entry);