Commit 451d7585 authored by Chris Mason's avatar Chris Mason

Btrfs: add mount -o ssd_spread to spread allocations out

Some SSDs perform best when reusing block numbers often, while
others perform much better when clustering strictly allocates
big chunks of unused space.

The default mount -o ssd will find rough groupings of blocks
where there are a bunch of free blocks that might have some
allocated blocks mixed in.

mount -o ssd_spread will make sure there are no allocated blocks
mixed in.  It should perform better on lower end SSDs.
Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
parent c6044801
...@@ -1100,6 +1100,7 @@ struct btrfs_root { ...@@ -1100,6 +1100,7 @@ struct btrfs_root {
#define BTRFS_MOUNT_COMPRESS (1 << 5) #define BTRFS_MOUNT_COMPRESS (1 << 5)
#define BTRFS_MOUNT_NOTREELOG (1 << 6) #define BTRFS_MOUNT_NOTREELOG (1 << 6)
#define BTRFS_MOUNT_FLUSHONCOMMIT (1 << 7) #define BTRFS_MOUNT_FLUSHONCOMMIT (1 << 7)
#define BTRFS_MOUNT_SSD_SPREAD (1 << 8)
#define btrfs_clear_opt(o, opt) ((o) &= ~BTRFS_MOUNT_##opt) #define btrfs_clear_opt(o, opt) ((o) &= ~BTRFS_MOUNT_##opt)
#define btrfs_set_opt(o, opt) ((o) |= BTRFS_MOUNT_##opt) #define btrfs_set_opt(o, opt) ((o) |= BTRFS_MOUNT_##opt)
......
...@@ -3607,7 +3607,7 @@ static noinline int find_free_extent(struct btrfs_trans_handle *trans, ...@@ -3607,7 +3607,7 @@ static noinline int find_free_extent(struct btrfs_trans_handle *trans,
last_ptr_loop = 0; last_ptr_loop = 0;
/* allocate a cluster in this block group */ /* allocate a cluster in this block group */
ret = btrfs_find_space_cluster(trans, ret = btrfs_find_space_cluster(trans, root,
block_group, last_ptr, block_group, last_ptr,
offset, num_bytes, offset, num_bytes,
empty_cluster + empty_size); empty_cluster + empty_size);
......
...@@ -579,6 +579,7 @@ u64 btrfs_alloc_from_cluster(struct btrfs_block_group_cache *block_group, ...@@ -579,6 +579,7 @@ u64 btrfs_alloc_from_cluster(struct btrfs_block_group_cache *block_group,
* it returns -enospc * it returns -enospc
*/ */
int btrfs_find_space_cluster(struct btrfs_trans_handle *trans, int btrfs_find_space_cluster(struct btrfs_trans_handle *trans,
struct btrfs_root *root,
struct btrfs_block_group_cache *block_group, struct btrfs_block_group_cache *block_group,
struct btrfs_free_cluster *cluster, struct btrfs_free_cluster *cluster,
u64 offset, u64 bytes, u64 empty_size) u64 offset, u64 bytes, u64 empty_size)
...@@ -595,7 +596,9 @@ int btrfs_find_space_cluster(struct btrfs_trans_handle *trans, ...@@ -595,7 +596,9 @@ int btrfs_find_space_cluster(struct btrfs_trans_handle *trans,
int ret; int ret;
/* for metadata, allow allocates with more holes */ /* for metadata, allow allocates with more holes */
if (block_group->flags & BTRFS_BLOCK_GROUP_METADATA) { if (btrfs_test_opt(root, SSD_SPREAD)) {
min_bytes = bytes + empty_size;
} else if (block_group->flags & BTRFS_BLOCK_GROUP_METADATA) {
/* /*
* we want to do larger allocations when we are * we want to do larger allocations when we are
* flushing out the delayed refs, it helps prevent * flushing out the delayed refs, it helps prevent
......
...@@ -31,6 +31,7 @@ void btrfs_dump_free_space(struct btrfs_block_group_cache *block_group, ...@@ -31,6 +31,7 @@ void btrfs_dump_free_space(struct btrfs_block_group_cache *block_group,
u64 bytes); u64 bytes);
u64 btrfs_block_group_free_space(struct btrfs_block_group_cache *block_group); u64 btrfs_block_group_free_space(struct btrfs_block_group_cache *block_group);
int btrfs_find_space_cluster(struct btrfs_trans_handle *trans, int btrfs_find_space_cluster(struct btrfs_trans_handle *trans,
struct btrfs_root *root,
struct btrfs_block_group_cache *block_group, struct btrfs_block_group_cache *block_group,
struct btrfs_free_cluster *cluster, struct btrfs_free_cluster *cluster,
u64 offset, u64 bytes, u64 empty_size); u64 offset, u64 bytes, u64 empty_size);
......
...@@ -66,8 +66,8 @@ static void btrfs_put_super(struct super_block *sb) ...@@ -66,8 +66,8 @@ static void btrfs_put_super(struct super_block *sb)
enum { enum {
Opt_degraded, Opt_subvol, Opt_device, Opt_nodatasum, Opt_nodatacow, Opt_degraded, Opt_subvol, Opt_device, Opt_nodatasum, Opt_nodatacow,
Opt_max_extent, Opt_max_inline, Opt_alloc_start, Opt_nobarrier, Opt_max_extent, Opt_max_inline, Opt_alloc_start, Opt_nobarrier,
Opt_ssd, Opt_nossd, Opt_thread_pool, Opt_noacl, Opt_compress, Opt_ssd, Opt_nossd, Opt_ssd_spread, Opt_thread_pool, Opt_noacl,
Opt_notreelog, Opt_ratio, Opt_flushoncommit, Opt_err, Opt_compress, Opt_notreelog, Opt_ratio, Opt_flushoncommit, Opt_err,
}; };
static match_table_t tokens = { static match_table_t tokens = {
...@@ -83,6 +83,7 @@ static match_table_t tokens = { ...@@ -83,6 +83,7 @@ static match_table_t tokens = {
{Opt_thread_pool, "thread_pool=%d"}, {Opt_thread_pool, "thread_pool=%d"},
{Opt_compress, "compress"}, {Opt_compress, "compress"},
{Opt_ssd, "ssd"}, {Opt_ssd, "ssd"},
{Opt_ssd_spread, "ssd_spread"},
{Opt_nossd, "nossd"}, {Opt_nossd, "nossd"},
{Opt_noacl, "noacl"}, {Opt_noacl, "noacl"},
{Opt_notreelog, "notreelog"}, {Opt_notreelog, "notreelog"},
...@@ -174,9 +175,17 @@ int btrfs_parse_options(struct btrfs_root *root, char *options) ...@@ -174,9 +175,17 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
printk(KERN_INFO "btrfs: use ssd allocation scheme\n"); printk(KERN_INFO "btrfs: use ssd allocation scheme\n");
btrfs_set_opt(info->mount_opt, SSD); btrfs_set_opt(info->mount_opt, SSD);
break; break;
case Opt_ssd_spread:
printk(KERN_INFO "btrfs: use spread ssd "
"allocation scheme\n");
btrfs_set_opt(info->mount_opt, SSD);
btrfs_set_opt(info->mount_opt, SSD_SPREAD);
break;
case Opt_nossd: case Opt_nossd:
printk(KERN_INFO "btrfs: not using ssd allocation scheme\n"); printk(KERN_INFO "btrfs: not using ssd allocation "
"scheme\n");
btrfs_clear_opt(info->mount_opt, SSD); btrfs_clear_opt(info->mount_opt, SSD);
btrfs_clear_opt(info->mount_opt, SSD_SPREAD);
break; break;
case Opt_nobarrier: case Opt_nobarrier:
printk(KERN_INFO "btrfs: turning off barriers\n"); printk(KERN_INFO "btrfs: turning off barriers\n");
...@@ -429,7 +438,9 @@ static int btrfs_show_options(struct seq_file *seq, struct vfsmount *vfs) ...@@ -429,7 +438,9 @@ static int btrfs_show_options(struct seq_file *seq, struct vfsmount *vfs)
seq_printf(seq, ",thread_pool=%d", info->thread_pool_size); seq_printf(seq, ",thread_pool=%d", info->thread_pool_size);
if (btrfs_test_opt(root, COMPRESS)) if (btrfs_test_opt(root, COMPRESS))
seq_puts(seq, ",compress"); seq_puts(seq, ",compress");
if (btrfs_test_opt(root, SSD)) if (btrfs_test_opt(root, SSD_SPREAD))
seq_puts(seq, ",ssd_spread");
else if (btrfs_test_opt(root, SSD))
seq_puts(seq, ",ssd"); seq_puts(seq, ",ssd");
if (btrfs_test_opt(root, NOTREELOG)) if (btrfs_test_opt(root, NOTREELOG))
seq_puts(seq, ",notreelog"); seq_puts(seq, ",notreelog");
......
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