#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)
+
/* Work operations */
void btrfs_discard_cancel_work(struct btrfs_discard_ctl *discard_ctl,
struct btrfs_block_group *block_group);
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 = 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);
+ 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;
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);