162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (C) 2009 Oracle.  All rights reserved.
462306a36Sopenharmony_ci */
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci#ifndef BTRFS_FREE_SPACE_CACHE_H
762306a36Sopenharmony_ci#define BTRFS_FREE_SPACE_CACHE_H
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci/*
1062306a36Sopenharmony_ci * This is the trim state of an extent or bitmap.
1162306a36Sopenharmony_ci *
1262306a36Sopenharmony_ci * BTRFS_TRIM_STATE_TRIMMING is special and used to maintain the state of a
1362306a36Sopenharmony_ci * bitmap as we may need several trims to fully trim a single bitmap entry.
1462306a36Sopenharmony_ci * This is reset should any free space other than trimmed space be added to the
1562306a36Sopenharmony_ci * bitmap.
1662306a36Sopenharmony_ci */
1762306a36Sopenharmony_cienum btrfs_trim_state {
1862306a36Sopenharmony_ci	BTRFS_TRIM_STATE_UNTRIMMED,
1962306a36Sopenharmony_ci	BTRFS_TRIM_STATE_TRIMMED,
2062306a36Sopenharmony_ci	BTRFS_TRIM_STATE_TRIMMING,
2162306a36Sopenharmony_ci};
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_cistruct btrfs_free_space {
2462306a36Sopenharmony_ci	struct rb_node offset_index;
2562306a36Sopenharmony_ci	struct rb_node bytes_index;
2662306a36Sopenharmony_ci	u64 offset;
2762306a36Sopenharmony_ci	u64 bytes;
2862306a36Sopenharmony_ci	u64 max_extent_size;
2962306a36Sopenharmony_ci	unsigned long *bitmap;
3062306a36Sopenharmony_ci	struct list_head list;
3162306a36Sopenharmony_ci	enum btrfs_trim_state trim_state;
3262306a36Sopenharmony_ci	s32 bitmap_extents;
3362306a36Sopenharmony_ci};
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_cistatic inline bool btrfs_free_space_trimmed(struct btrfs_free_space *info)
3662306a36Sopenharmony_ci{
3762306a36Sopenharmony_ci	return (info->trim_state == BTRFS_TRIM_STATE_TRIMMED);
3862306a36Sopenharmony_ci}
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_cistatic inline bool btrfs_free_space_trimming_bitmap(
4162306a36Sopenharmony_ci					    struct btrfs_free_space *info)
4262306a36Sopenharmony_ci{
4362306a36Sopenharmony_ci	return (info->trim_state == BTRFS_TRIM_STATE_TRIMMING);
4462306a36Sopenharmony_ci}
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci/*
4762306a36Sopenharmony_ci * Deltas are an effective way to populate global statistics.  Give macro names
4862306a36Sopenharmony_ci * to make it clear what we're doing.  An example is discard_extents in
4962306a36Sopenharmony_ci * btrfs_free_space_ctl.
5062306a36Sopenharmony_ci */
5162306a36Sopenharmony_cienum {
5262306a36Sopenharmony_ci	BTRFS_STAT_CURR,
5362306a36Sopenharmony_ci	BTRFS_STAT_PREV,
5462306a36Sopenharmony_ci	BTRFS_STAT_NR_ENTRIES,
5562306a36Sopenharmony_ci};
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_cistruct btrfs_free_space_ctl {
5862306a36Sopenharmony_ci	spinlock_t tree_lock;
5962306a36Sopenharmony_ci	struct rb_root free_space_offset;
6062306a36Sopenharmony_ci	struct rb_root_cached free_space_bytes;
6162306a36Sopenharmony_ci	u64 free_space;
6262306a36Sopenharmony_ci	int extents_thresh;
6362306a36Sopenharmony_ci	int free_extents;
6462306a36Sopenharmony_ci	int total_bitmaps;
6562306a36Sopenharmony_ci	int unit;
6662306a36Sopenharmony_ci	u64 start;
6762306a36Sopenharmony_ci	s32 discardable_extents[BTRFS_STAT_NR_ENTRIES];
6862306a36Sopenharmony_ci	s64 discardable_bytes[BTRFS_STAT_NR_ENTRIES];
6962306a36Sopenharmony_ci	const struct btrfs_free_space_op *op;
7062306a36Sopenharmony_ci	struct btrfs_block_group *block_group;
7162306a36Sopenharmony_ci	struct mutex cache_writeout_mutex;
7262306a36Sopenharmony_ci	struct list_head trimming_ranges;
7362306a36Sopenharmony_ci};
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_cistruct btrfs_free_space_op {
7662306a36Sopenharmony_ci	bool (*use_bitmap)(struct btrfs_free_space_ctl *ctl,
7762306a36Sopenharmony_ci			   struct btrfs_free_space *info);
7862306a36Sopenharmony_ci};
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_cistruct btrfs_io_ctl {
8162306a36Sopenharmony_ci	void *cur, *orig;
8262306a36Sopenharmony_ci	struct page *page;
8362306a36Sopenharmony_ci	struct page **pages;
8462306a36Sopenharmony_ci	struct btrfs_fs_info *fs_info;
8562306a36Sopenharmony_ci	struct inode *inode;
8662306a36Sopenharmony_ci	unsigned long size;
8762306a36Sopenharmony_ci	int index;
8862306a36Sopenharmony_ci	int num_pages;
8962306a36Sopenharmony_ci	int entries;
9062306a36Sopenharmony_ci	int bitmaps;
9162306a36Sopenharmony_ci};
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ciint __init btrfs_free_space_init(void);
9462306a36Sopenharmony_civoid __cold btrfs_free_space_exit(void);
9562306a36Sopenharmony_cistruct inode *lookup_free_space_inode(struct btrfs_block_group *block_group,
9662306a36Sopenharmony_ci		struct btrfs_path *path);
9762306a36Sopenharmony_ciint create_free_space_inode(struct btrfs_trans_handle *trans,
9862306a36Sopenharmony_ci			    struct btrfs_block_group *block_group,
9962306a36Sopenharmony_ci			    struct btrfs_path *path);
10062306a36Sopenharmony_ciint btrfs_remove_free_space_inode(struct btrfs_trans_handle *trans,
10162306a36Sopenharmony_ci				  struct inode *inode,
10262306a36Sopenharmony_ci				  struct btrfs_block_group *block_group);
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_ciint btrfs_truncate_free_space_cache(struct btrfs_trans_handle *trans,
10562306a36Sopenharmony_ci				    struct btrfs_block_group *block_group,
10662306a36Sopenharmony_ci				    struct inode *inode);
10762306a36Sopenharmony_ciint load_free_space_cache(struct btrfs_block_group *block_group);
10862306a36Sopenharmony_ciint btrfs_wait_cache_io(struct btrfs_trans_handle *trans,
10962306a36Sopenharmony_ci			struct btrfs_block_group *block_group,
11062306a36Sopenharmony_ci			struct btrfs_path *path);
11162306a36Sopenharmony_ciint btrfs_write_out_cache(struct btrfs_trans_handle *trans,
11262306a36Sopenharmony_ci			  struct btrfs_block_group *block_group,
11362306a36Sopenharmony_ci			  struct btrfs_path *path);
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_civoid btrfs_init_free_space_ctl(struct btrfs_block_group *block_group,
11662306a36Sopenharmony_ci			       struct btrfs_free_space_ctl *ctl);
11762306a36Sopenharmony_ciint __btrfs_add_free_space(struct btrfs_block_group *block_group, u64 bytenr,
11862306a36Sopenharmony_ci			   u64 size, enum btrfs_trim_state trim_state);
11962306a36Sopenharmony_ciint btrfs_add_free_space(struct btrfs_block_group *block_group,
12062306a36Sopenharmony_ci			 u64 bytenr, u64 size);
12162306a36Sopenharmony_ciint btrfs_add_free_space_unused(struct btrfs_block_group *block_group,
12262306a36Sopenharmony_ci				u64 bytenr, u64 size);
12362306a36Sopenharmony_ciint btrfs_add_free_space_async_trimmed(struct btrfs_block_group *block_group,
12462306a36Sopenharmony_ci				       u64 bytenr, u64 size);
12562306a36Sopenharmony_ciint btrfs_remove_free_space(struct btrfs_block_group *block_group,
12662306a36Sopenharmony_ci			    u64 bytenr, u64 size);
12762306a36Sopenharmony_civoid btrfs_remove_free_space_cache(struct btrfs_block_group *block_group);
12862306a36Sopenharmony_cibool btrfs_is_free_space_trimmed(struct btrfs_block_group *block_group);
12962306a36Sopenharmony_ciu64 btrfs_find_space_for_alloc(struct btrfs_block_group *block_group,
13062306a36Sopenharmony_ci			       u64 offset, u64 bytes, u64 empty_size,
13162306a36Sopenharmony_ci			       u64 *max_extent_size);
13262306a36Sopenharmony_civoid btrfs_dump_free_space(struct btrfs_block_group *block_group,
13362306a36Sopenharmony_ci			   u64 bytes);
13462306a36Sopenharmony_ciint btrfs_find_space_cluster(struct btrfs_block_group *block_group,
13562306a36Sopenharmony_ci			     struct btrfs_free_cluster *cluster,
13662306a36Sopenharmony_ci			     u64 offset, u64 bytes, u64 empty_size);
13762306a36Sopenharmony_civoid btrfs_init_free_cluster(struct btrfs_free_cluster *cluster);
13862306a36Sopenharmony_ciu64 btrfs_alloc_from_cluster(struct btrfs_block_group *block_group,
13962306a36Sopenharmony_ci			     struct btrfs_free_cluster *cluster, u64 bytes,
14062306a36Sopenharmony_ci			     u64 min_start, u64 *max_extent_size);
14162306a36Sopenharmony_civoid btrfs_return_cluster_to_free_space(
14262306a36Sopenharmony_ci			       struct btrfs_block_group *block_group,
14362306a36Sopenharmony_ci			       struct btrfs_free_cluster *cluster);
14462306a36Sopenharmony_ciint btrfs_trim_block_group(struct btrfs_block_group *block_group,
14562306a36Sopenharmony_ci			   u64 *trimmed, u64 start, u64 end, u64 minlen);
14662306a36Sopenharmony_ciint btrfs_trim_block_group_extents(struct btrfs_block_group *block_group,
14762306a36Sopenharmony_ci				   u64 *trimmed, u64 start, u64 end, u64 minlen,
14862306a36Sopenharmony_ci				   bool async);
14962306a36Sopenharmony_ciint btrfs_trim_block_group_bitmaps(struct btrfs_block_group *block_group,
15062306a36Sopenharmony_ci				   u64 *trimmed, u64 start, u64 end, u64 minlen,
15162306a36Sopenharmony_ci				   u64 maxlen, bool async);
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_cibool btrfs_free_space_cache_v1_active(struct btrfs_fs_info *fs_info);
15462306a36Sopenharmony_ciint btrfs_set_free_space_cache_v1_active(struct btrfs_fs_info *fs_info, bool active);
15562306a36Sopenharmony_ci/* Support functions for running our sanity tests */
15662306a36Sopenharmony_ci#ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS
15762306a36Sopenharmony_ciint test_add_free_space_entry(struct btrfs_block_group *cache,
15862306a36Sopenharmony_ci			      u64 offset, u64 bytes, bool bitmap);
15962306a36Sopenharmony_ciint test_check_exists(struct btrfs_block_group *cache, u64 offset, u64 bytes);
16062306a36Sopenharmony_ci#endif
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_ci#endif
163