162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci
362306a36Sopenharmony_ci#ifndef BTRFS_BLOCK_RSV_H
462306a36Sopenharmony_ci#define BTRFS_BLOCK_RSV_H
562306a36Sopenharmony_ci
662306a36Sopenharmony_cistruct btrfs_trans_handle;
762306a36Sopenharmony_cistruct btrfs_root;
862306a36Sopenharmony_cienum btrfs_reserve_flush_enum;
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci/*
1162306a36Sopenharmony_ci * Types of block reserves
1262306a36Sopenharmony_ci */
1362306a36Sopenharmony_cienum btrfs_rsv_type {
1462306a36Sopenharmony_ci	BTRFS_BLOCK_RSV_GLOBAL,
1562306a36Sopenharmony_ci	BTRFS_BLOCK_RSV_DELALLOC,
1662306a36Sopenharmony_ci	BTRFS_BLOCK_RSV_TRANS,
1762306a36Sopenharmony_ci	BTRFS_BLOCK_RSV_CHUNK,
1862306a36Sopenharmony_ci	BTRFS_BLOCK_RSV_DELOPS,
1962306a36Sopenharmony_ci	BTRFS_BLOCK_RSV_DELREFS,
2062306a36Sopenharmony_ci	BTRFS_BLOCK_RSV_EMPTY,
2162306a36Sopenharmony_ci	BTRFS_BLOCK_RSV_TEMP,
2262306a36Sopenharmony_ci};
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_cistruct btrfs_block_rsv {
2562306a36Sopenharmony_ci	u64 size;
2662306a36Sopenharmony_ci	u64 reserved;
2762306a36Sopenharmony_ci	struct btrfs_space_info *space_info;
2862306a36Sopenharmony_ci	spinlock_t lock;
2962306a36Sopenharmony_ci	bool full;
3062306a36Sopenharmony_ci	bool failfast;
3162306a36Sopenharmony_ci	/* Block reserve type, one of BTRFS_BLOCK_RSV_* */
3262306a36Sopenharmony_ci	enum btrfs_rsv_type type:8;
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci	/*
3562306a36Sopenharmony_ci	 * Qgroup equivalent for @size @reserved
3662306a36Sopenharmony_ci	 *
3762306a36Sopenharmony_ci	 * Unlike normal @size/@reserved for inode rsv, qgroup doesn't care
3862306a36Sopenharmony_ci	 * about things like csum size nor how many tree blocks it will need to
3962306a36Sopenharmony_ci	 * reserve.
4062306a36Sopenharmony_ci	 *
4162306a36Sopenharmony_ci	 * Qgroup cares more about net change of the extent usage.
4262306a36Sopenharmony_ci	 *
4362306a36Sopenharmony_ci	 * So for one newly inserted file extent, in worst case it will cause
4462306a36Sopenharmony_ci	 * leaf split and level increase, nodesize for each file extent is
4562306a36Sopenharmony_ci	 * already too much.
4662306a36Sopenharmony_ci	 *
4762306a36Sopenharmony_ci	 * In short, qgroup_size/reserved is the upper limit of possible needed
4862306a36Sopenharmony_ci	 * qgroup metadata reservation.
4962306a36Sopenharmony_ci	 */
5062306a36Sopenharmony_ci	u64 qgroup_rsv_size;
5162306a36Sopenharmony_ci	u64 qgroup_rsv_reserved;
5262306a36Sopenharmony_ci};
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_civoid btrfs_init_block_rsv(struct btrfs_block_rsv *rsv, enum btrfs_rsv_type type);
5562306a36Sopenharmony_civoid btrfs_init_root_block_rsv(struct btrfs_root *root);
5662306a36Sopenharmony_cistruct btrfs_block_rsv *btrfs_alloc_block_rsv(struct btrfs_fs_info *fs_info,
5762306a36Sopenharmony_ci					      enum btrfs_rsv_type type);
5862306a36Sopenharmony_civoid btrfs_init_metadata_block_rsv(struct btrfs_fs_info *fs_info,
5962306a36Sopenharmony_ci				   struct btrfs_block_rsv *rsv,
6062306a36Sopenharmony_ci				   enum btrfs_rsv_type type);
6162306a36Sopenharmony_civoid btrfs_free_block_rsv(struct btrfs_fs_info *fs_info,
6262306a36Sopenharmony_ci			  struct btrfs_block_rsv *rsv);
6362306a36Sopenharmony_ciint btrfs_block_rsv_add(struct btrfs_fs_info *fs_info,
6462306a36Sopenharmony_ci			struct btrfs_block_rsv *block_rsv, u64 num_bytes,
6562306a36Sopenharmony_ci			enum btrfs_reserve_flush_enum flush);
6662306a36Sopenharmony_ciint btrfs_block_rsv_check(struct btrfs_block_rsv *block_rsv, int min_percent);
6762306a36Sopenharmony_ciint btrfs_block_rsv_refill(struct btrfs_fs_info *fs_info,
6862306a36Sopenharmony_ci			   struct btrfs_block_rsv *block_rsv, u64 num_bytes,
6962306a36Sopenharmony_ci			   enum btrfs_reserve_flush_enum flush);
7062306a36Sopenharmony_ciint btrfs_block_rsv_migrate(struct btrfs_block_rsv *src_rsv,
7162306a36Sopenharmony_ci			    struct btrfs_block_rsv *dst_rsv, u64 num_bytes,
7262306a36Sopenharmony_ci			    bool update_size);
7362306a36Sopenharmony_ciint btrfs_block_rsv_use_bytes(struct btrfs_block_rsv *block_rsv, u64 num_bytes);
7462306a36Sopenharmony_civoid btrfs_block_rsv_add_bytes(struct btrfs_block_rsv *block_rsv,
7562306a36Sopenharmony_ci			       u64 num_bytes, bool update_size);
7662306a36Sopenharmony_ciu64 btrfs_block_rsv_release(struct btrfs_fs_info *fs_info,
7762306a36Sopenharmony_ci			      struct btrfs_block_rsv *block_rsv,
7862306a36Sopenharmony_ci			      u64 num_bytes, u64 *qgroup_to_release);
7962306a36Sopenharmony_civoid btrfs_update_global_block_rsv(struct btrfs_fs_info *fs_info);
8062306a36Sopenharmony_civoid btrfs_init_global_block_rsv(struct btrfs_fs_info *fs_info);
8162306a36Sopenharmony_civoid btrfs_release_global_block_rsv(struct btrfs_fs_info *fs_info);
8262306a36Sopenharmony_cistruct btrfs_block_rsv *btrfs_use_block_rsv(struct btrfs_trans_handle *trans,
8362306a36Sopenharmony_ci					    struct btrfs_root *root,
8462306a36Sopenharmony_ci					    u32 blocksize);
8562306a36Sopenharmony_ciint btrfs_check_trunc_cache_free_space(struct btrfs_fs_info *fs_info,
8662306a36Sopenharmony_ci				       struct btrfs_block_rsv *rsv);
8762306a36Sopenharmony_cistatic inline void btrfs_unuse_block_rsv(struct btrfs_fs_info *fs_info,
8862306a36Sopenharmony_ci					 struct btrfs_block_rsv *block_rsv,
8962306a36Sopenharmony_ci					 u32 blocksize)
9062306a36Sopenharmony_ci{
9162306a36Sopenharmony_ci	btrfs_block_rsv_add_bytes(block_rsv, blocksize, false);
9262306a36Sopenharmony_ci	btrfs_block_rsv_release(fs_info, block_rsv, 0, NULL);
9362306a36Sopenharmony_ci}
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci/*
9662306a36Sopenharmony_ci * Fast path to check if the reserve is full, may be carefully used outside of
9762306a36Sopenharmony_ci * locks.
9862306a36Sopenharmony_ci */
9962306a36Sopenharmony_cistatic inline bool btrfs_block_rsv_full(const struct btrfs_block_rsv *rsv)
10062306a36Sopenharmony_ci{
10162306a36Sopenharmony_ci	return data_race(rsv->full);
10262306a36Sopenharmony_ci}
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_ci/*
10562306a36Sopenharmony_ci * Get the reserved mount of a block reserve in a context where getting a stale
10662306a36Sopenharmony_ci * value is acceptable, instead of accessing it directly and trigger data race
10762306a36Sopenharmony_ci * warning from KCSAN.
10862306a36Sopenharmony_ci */
10962306a36Sopenharmony_cistatic inline u64 btrfs_block_rsv_reserved(struct btrfs_block_rsv *rsv)
11062306a36Sopenharmony_ci{
11162306a36Sopenharmony_ci	u64 ret;
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_ci	spin_lock(&rsv->lock);
11462306a36Sopenharmony_ci	ret = rsv->reserved;
11562306a36Sopenharmony_ci	spin_unlock(&rsv->lock);
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ci	return ret;
11862306a36Sopenharmony_ci}
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci/*
12162306a36Sopenharmony_ci * Get the size of a block reserve in a context where getting a stale value is
12262306a36Sopenharmony_ci * acceptable, instead of accessing it directly and trigger data race warning
12362306a36Sopenharmony_ci * from KCSAN.
12462306a36Sopenharmony_ci */
12562306a36Sopenharmony_cistatic inline u64 btrfs_block_rsv_size(struct btrfs_block_rsv *rsv)
12662306a36Sopenharmony_ci{
12762306a36Sopenharmony_ci	u64 ret;
12862306a36Sopenharmony_ci
12962306a36Sopenharmony_ci	spin_lock(&rsv->lock);
13062306a36Sopenharmony_ci	ret = rsv->size;
13162306a36Sopenharmony_ci	spin_unlock(&rsv->lock);
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci	return ret;
13462306a36Sopenharmony_ci}
13562306a36Sopenharmony_ci
13662306a36Sopenharmony_ci#endif /* BTRFS_BLOCK_RSV_H */
137