Commit 41783ef2 authored by Josef Bacik's avatar Josef Bacik Committed by David Sterba
Browse files

btrfs: move and export can_overcommit



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

Reviewed-by: default avatarNikolay Borisov <nborisov@suse.com>
Signed-off-by: default avatarJosef Bacik <josef@toxicpanda.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent 280c2908
Loading
Loading
Loading
Loading
+7 −75
Original line number Diff line number Diff line
@@ -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,13 +4698,13 @@ 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,
	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,
	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
@@ -5019,7 +4951,7 @@ 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,
	} 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",
@@ -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);
+68 −0
Original line number Diff line number Diff line
@@ -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;
}
+4 −0
Original line number Diff line number Diff line
@@ -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 */