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:
Родитель
280c290881
Коммит
41783ef24d
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
Загрузка…
Ссылка в новой задаче