162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci
362306a36Sopenharmony_ci#ifndef BTRFS_EXTENT_MAP_H
462306a36Sopenharmony_ci#define BTRFS_EXTENT_MAP_H
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci#include <linux/rbtree.h>
762306a36Sopenharmony_ci#include <linux/refcount.h>
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#define EXTENT_MAP_LAST_BYTE ((u64)-4)
1062306a36Sopenharmony_ci#define EXTENT_MAP_HOLE ((u64)-3)
1162306a36Sopenharmony_ci#define EXTENT_MAP_INLINE ((u64)-2)
1262306a36Sopenharmony_ci/* used only during fiemap calls */
1362306a36Sopenharmony_ci#define EXTENT_MAP_DELALLOC ((u64)-1)
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci/* bits for the extent_map::flags field */
1662306a36Sopenharmony_cienum {
1762306a36Sopenharmony_ci	/* this entry not yet on disk, don't free it */
1862306a36Sopenharmony_ci	EXTENT_FLAG_PINNED,
1962306a36Sopenharmony_ci	EXTENT_FLAG_COMPRESSED,
2062306a36Sopenharmony_ci	/* pre-allocated extent */
2162306a36Sopenharmony_ci	EXTENT_FLAG_PREALLOC,
2262306a36Sopenharmony_ci	/* Logging this extent */
2362306a36Sopenharmony_ci	EXTENT_FLAG_LOGGING,
2462306a36Sopenharmony_ci	/* Filling in a preallocated extent */
2562306a36Sopenharmony_ci	EXTENT_FLAG_FILLING,
2662306a36Sopenharmony_ci	/* filesystem extent mapping type */
2762306a36Sopenharmony_ci	EXTENT_FLAG_FS_MAPPING,
2862306a36Sopenharmony_ci	/* This em is merged from two or more physically adjacent ems */
2962306a36Sopenharmony_ci	EXTENT_FLAG_MERGED,
3062306a36Sopenharmony_ci};
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_cistruct extent_map {
3362306a36Sopenharmony_ci	struct rb_node rb_node;
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci	/* all of these are in bytes */
3662306a36Sopenharmony_ci	u64 start;
3762306a36Sopenharmony_ci	u64 len;
3862306a36Sopenharmony_ci	u64 mod_start;
3962306a36Sopenharmony_ci	u64 mod_len;
4062306a36Sopenharmony_ci	u64 orig_start;
4162306a36Sopenharmony_ci	u64 orig_block_len;
4262306a36Sopenharmony_ci	u64 ram_bytes;
4362306a36Sopenharmony_ci	u64 block_start;
4462306a36Sopenharmony_ci	u64 block_len;
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci	/*
4762306a36Sopenharmony_ci	 * Generation of the extent map, for merged em it's the highest
4862306a36Sopenharmony_ci	 * generation of all merged ems.
4962306a36Sopenharmony_ci	 * For non-merged extents, it's from btrfs_file_extent_item::generation.
5062306a36Sopenharmony_ci	 */
5162306a36Sopenharmony_ci	u64 generation;
5262306a36Sopenharmony_ci	unsigned long flags;
5362306a36Sopenharmony_ci	/* Used for chunk mappings, flag EXTENT_FLAG_FS_MAPPING must be set */
5462306a36Sopenharmony_ci	struct map_lookup *map_lookup;
5562306a36Sopenharmony_ci	refcount_t refs;
5662306a36Sopenharmony_ci	unsigned int compress_type;
5762306a36Sopenharmony_ci	struct list_head list;
5862306a36Sopenharmony_ci};
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_cistruct extent_map_tree {
6162306a36Sopenharmony_ci	struct rb_root_cached map;
6262306a36Sopenharmony_ci	struct list_head modified_extents;
6362306a36Sopenharmony_ci	rwlock_t lock;
6462306a36Sopenharmony_ci};
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_cistruct btrfs_inode;
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_cistatic inline int extent_map_in_tree(const struct extent_map *em)
6962306a36Sopenharmony_ci{
7062306a36Sopenharmony_ci	return !RB_EMPTY_NODE(&em->rb_node);
7162306a36Sopenharmony_ci}
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_cistatic inline u64 extent_map_end(struct extent_map *em)
7462306a36Sopenharmony_ci{
7562306a36Sopenharmony_ci	if (em->start + em->len < em->start)
7662306a36Sopenharmony_ci		return (u64)-1;
7762306a36Sopenharmony_ci	return em->start + em->len;
7862306a36Sopenharmony_ci}
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_cistatic inline u64 extent_map_block_end(struct extent_map *em)
8162306a36Sopenharmony_ci{
8262306a36Sopenharmony_ci	if (em->block_start + em->block_len < em->block_start)
8362306a36Sopenharmony_ci		return (u64)-1;
8462306a36Sopenharmony_ci	return em->block_start + em->block_len;
8562306a36Sopenharmony_ci}
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_civoid extent_map_tree_init(struct extent_map_tree *tree);
8862306a36Sopenharmony_cistruct extent_map *lookup_extent_mapping(struct extent_map_tree *tree,
8962306a36Sopenharmony_ci					 u64 start, u64 len);
9062306a36Sopenharmony_ciint add_extent_mapping(struct extent_map_tree *tree,
9162306a36Sopenharmony_ci		       struct extent_map *em, int modified);
9262306a36Sopenharmony_civoid remove_extent_mapping(struct extent_map_tree *tree, struct extent_map *em);
9362306a36Sopenharmony_ciint split_extent_map(struct btrfs_inode *inode, u64 start, u64 len, u64 pre,
9462306a36Sopenharmony_ci		     u64 new_logical);
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_cistruct extent_map *alloc_extent_map(void);
9762306a36Sopenharmony_civoid free_extent_map(struct extent_map *em);
9862306a36Sopenharmony_ciint __init extent_map_init(void);
9962306a36Sopenharmony_civoid __cold extent_map_exit(void);
10062306a36Sopenharmony_ciint unpin_extent_cache(struct extent_map_tree *tree, u64 start, u64 len, u64 gen);
10162306a36Sopenharmony_civoid clear_em_logging(struct extent_map_tree *tree, struct extent_map *em);
10262306a36Sopenharmony_cistruct extent_map *search_extent_mapping(struct extent_map_tree *tree,
10362306a36Sopenharmony_ci					 u64 start, u64 len);
10462306a36Sopenharmony_ciint btrfs_add_extent_mapping(struct btrfs_fs_info *fs_info,
10562306a36Sopenharmony_ci			     struct extent_map_tree *em_tree,
10662306a36Sopenharmony_ci			     struct extent_map **em_in, u64 start, u64 len);
10762306a36Sopenharmony_civoid btrfs_drop_extent_map_range(struct btrfs_inode *inode,
10862306a36Sopenharmony_ci				 u64 start, u64 end,
10962306a36Sopenharmony_ci				 bool skip_pinned);
11062306a36Sopenharmony_ciint btrfs_replace_extent_map_range(struct btrfs_inode *inode,
11162306a36Sopenharmony_ci				   struct extent_map *new_em,
11262306a36Sopenharmony_ci				   bool modified);
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_ci#endif
115