btrfs: move and export can_overcommit

This is the first piece of moving the space reservation code to
space-info.c

Reviewed-by: Nikolay Borisov <nborisov@suse.com>
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
Josef Bacik 2019-06-18 16:09:20 -04:00 committed by David Sterba
parent 280c290881
commit 41783ef24d
3 changed files with 79 additions and 75 deletions

View File

@ -4147,11 +4147,6 @@ static void force_metadata_allocation(struct btrfs_fs_info *info)
rcu_read_unlock();
}
static inline u64 calc_global_rsv_need_space(struct btrfs_block_rsv *global)
{
return (global->size << 1);
}
static int should_alloc_chunk(struct btrfs_fs_info *fs_info,
struct btrfs_space_info *sinfo, int force)
{
@ -4376,69 +4371,6 @@ out:
return ret;
}
static int can_overcommit(struct btrfs_fs_info *fs_info,
struct btrfs_space_info *space_info, u64 bytes,
enum btrfs_reserve_flush_enum flush,
bool system_chunk)
{
struct btrfs_block_rsv *global_rsv = &fs_info->global_block_rsv;
u64 profile;
u64 space_size;
u64 avail;
u64 used;
int factor;
/* Don't overcommit when in mixed mode. */
if (space_info->flags & BTRFS_BLOCK_GROUP_DATA)
return 0;
if (system_chunk)
profile = btrfs_system_alloc_profile(fs_info);
else
profile = btrfs_metadata_alloc_profile(fs_info);
used = btrfs_space_info_used(space_info, false);
/*
* We only want to allow over committing if we have lots of actual space
* free, but if we don't have enough space to handle the global reserve
* space then we could end up having a real enospc problem when trying
* to allocate a chunk or some other such important allocation.
*/
spin_lock(&global_rsv->lock);
space_size = calc_global_rsv_need_space(global_rsv);
spin_unlock(&global_rsv->lock);
if (used + space_size >= space_info->total_bytes)
return 0;
used += space_info->bytes_may_use;
avail = atomic64_read(&fs_info->free_chunk_space);
/*
* If we have dup, raid1 or raid10 then only half of the free
* space is actually usable. For raid56, the space info used
* doesn't include the parity drive, so we don't have to
* change the math
*/
factor = btrfs_bg_type_to_factor(profile);
avail = div_u64(avail, factor);
/*
* If we aren't flushing all things, let us overcommit up to
* 1/2th of the space. If we can flush, don't let us overcommit
* too much, let it overcommit up to 1/8 of the space.
*/
if (flush == BTRFS_RESERVE_FLUSH_ALL)
avail >>= 3;
else
avail >>= 1;
if (used + bytes < space_info->total_bytes + avail)
return 1;
return 0;
}
static void btrfs_writeback_inodes_sb_nr(struct btrfs_fs_info *fs_info,
unsigned long nr_pages, int nr_items)
{
@ -4766,14 +4698,14 @@ btrfs_calc_reclaim_metadata_size(struct btrfs_fs_info *fs_info,
return to_reclaim;
to_reclaim = min_t(u64, num_online_cpus() * SZ_1M, SZ_16M);
if (can_overcommit(fs_info, space_info, to_reclaim,
BTRFS_RESERVE_FLUSH_ALL, system_chunk))
if (btrfs_can_overcommit(fs_info, space_info, to_reclaim,
BTRFS_RESERVE_FLUSH_ALL, system_chunk))
return 0;
used = btrfs_space_info_used(space_info, true);
if (can_overcommit(fs_info, space_info, SZ_1M,
BTRFS_RESERVE_FLUSH_ALL, system_chunk))
if (btrfs_can_overcommit(fs_info, space_info, SZ_1M,
BTRFS_RESERVE_FLUSH_ALL, system_chunk))
expected = div_factor_fine(space_info->total_bytes, 95);
else
expected = div_factor_fine(space_info->total_bytes, 90);
@ -5019,8 +4951,8 @@ static int __reserve_metadata_bytes(struct btrfs_fs_info *fs_info,
trace_btrfs_space_reservation(fs_info, "space_info",
space_info->flags, orig_bytes, 1);
ret = 0;
} else if (can_overcommit(fs_info, space_info, orig_bytes, flush,
system_chunk)) {
} else if (btrfs_can_overcommit(fs_info, space_info, orig_bytes, flush,
system_chunk)) {
update_bytes_may_use(fs_info, space_info, orig_bytes);
trace_btrfs_space_reservation(fs_info, "space_info",
space_info->flags, orig_bytes, 1);
@ -5331,7 +5263,7 @@ again:
* adding the ticket space would be a double count.
*/
if (check_overcommit &&
!can_overcommit(fs_info, space_info, 0, flush, false))
!btrfs_can_overcommit(fs_info, space_info, 0, flush, false))
break;
if (num_bytes >= ticket->bytes) {
list_del_init(&ticket->list);

View File

@ -172,3 +172,71 @@ struct btrfs_space_info *btrfs_find_space_info(struct btrfs_fs_info *info,
rcu_read_unlock();
return NULL;
}
static inline u64 calc_global_rsv_need_space(struct btrfs_block_rsv *global)
{
return (global->size << 1);
}
int btrfs_can_overcommit(struct btrfs_fs_info *fs_info,
struct btrfs_space_info *space_info, u64 bytes,
enum btrfs_reserve_flush_enum flush,
bool system_chunk)
{
struct btrfs_block_rsv *global_rsv = &fs_info->global_block_rsv;
u64 profile;
u64 space_size;
u64 avail;
u64 used;
int factor;
/* Don't overcommit when in mixed mode. */
if (space_info->flags & BTRFS_BLOCK_GROUP_DATA)
return 0;
if (system_chunk)
profile = btrfs_system_alloc_profile(fs_info);
else
profile = btrfs_metadata_alloc_profile(fs_info);
used = btrfs_space_info_used(space_info, false);
/*
* We only want to allow over committing if we have lots of actual space
* free, but if we don't have enough space to handle the global reserve
* space then we could end up having a real enospc problem when trying
* to allocate a chunk or some other such important allocation.
*/
spin_lock(&global_rsv->lock);
space_size = calc_global_rsv_need_space(global_rsv);
spin_unlock(&global_rsv->lock);
if (used + space_size >= space_info->total_bytes)
return 0;
used += space_info->bytes_may_use;
avail = atomic64_read(&fs_info->free_chunk_space);
/*
* If we have dup, raid1 or raid10 then only half of the free
* space is actually usable. For raid56, the space info used
* doesn't include the parity drive, so we don't have to
* change the math
*/
factor = btrfs_bg_type_to_factor(profile);
avail = div_u64(avail, factor);
/*
* If we aren't flushing all things, let us overcommit up to
* 1/2th of the space. If we can flush, don't let us overcommit
* too much, let it overcommit up to 1/8 of the space.
*/
if (flush == BTRFS_RESERVE_FLUSH_ALL)
avail >>= 3;
else
avail >>= 1;
if (used + bytes < space_info->total_bytes + avail)
return 1;
return 0;
}

View File

@ -91,5 +91,9 @@ struct btrfs_space_info *btrfs_find_space_info(struct btrfs_fs_info *info,
u64 btrfs_space_info_used(struct btrfs_space_info *s_info,
bool may_use_included);
void btrfs_clear_space_info_full(struct btrfs_fs_info *info);
int btrfs_can_overcommit(struct btrfs_fs_info *fs_info,
struct btrfs_space_info *space_info, u64 bytes,
enum btrfs_reserve_flush_enum flush,
bool system_chunk);
#endif /* BTRFS_SPACE_INFO_H */