1 /* SPDX-License-Identifier: GPL-2.0 */ 2 3 #ifndef BTRFS_EXTENT_MAP_H 4 #define BTRFS_EXTENT_MAP_H 5 6 #include <linux/rbtree.h> 7 #include <linux/refcount.h> 8 #include "compression.h" 9 10 #define EXTENT_MAP_LAST_BYTE ((u64)-4) 11 #define EXTENT_MAP_HOLE ((u64)-3) 12 #define EXTENT_MAP_INLINE ((u64)-2) 13 14 /* bits for the extent_map::flags field */ 15 enum { 16 /* this entry not yet on disk, don't free it */ 17 ENUM_BIT(EXTENT_FLAG_PINNED), 18 ENUM_BIT(EXTENT_FLAG_COMPRESS_ZLIB), 19 ENUM_BIT(EXTENT_FLAG_COMPRESS_LZO), 20 ENUM_BIT(EXTENT_FLAG_COMPRESS_ZSTD), 21 /* pre-allocated extent */ 22 ENUM_BIT(EXTENT_FLAG_PREALLOC), 23 /* Logging this extent */ 24 ENUM_BIT(EXTENT_FLAG_LOGGING), 25 /* Filling in a preallocated extent */ 26 ENUM_BIT(EXTENT_FLAG_FILLING), 27 /* This em is merged from two or more physically adjacent ems */ 28 ENUM_BIT(EXTENT_FLAG_MERGED), 29 }; 30 31 /* 32 * Keep this structure as compact as possible, as we can have really large 33 * amounts of allocated extent maps at any time. 34 */ 35 struct extent_map { 36 struct rb_node rb_node; 37 38 /* all of these are in bytes */ 39 u64 start; 40 u64 len; 41 u64 mod_start; 42 u64 mod_len; 43 u64 orig_start; 44 u64 orig_block_len; 45 u64 ram_bytes; 46 u64 block_start; 47 u64 block_len; 48 49 /* 50 * Generation of the extent map, for merged em it's the highest 51 * generation of all merged ems. 52 * For non-merged extents, it's from btrfs_file_extent_item::generation. 53 */ 54 u64 generation; 55 u32 flags; 56 refcount_t refs; 57 struct list_head list; 58 }; 59 60 struct extent_map_tree { 61 struct rb_root_cached map; 62 struct list_head modified_extents; 63 rwlock_t lock; 64 }; 65 66 struct btrfs_inode; 67 68 static inline void extent_map_set_compression(struct extent_map *em, 69 enum btrfs_compression_type type) 70 { 71 if (type == BTRFS_COMPRESS_ZLIB) 72 em->flags |= EXTENT_FLAG_COMPRESS_ZLIB; 73 else if (type == BTRFS_COMPRESS_LZO) 74 em->flags |= EXTENT_FLAG_COMPRESS_LZO; 75 else if (type == BTRFS_COMPRESS_ZSTD) 76 em->flags |= EXTENT_FLAG_COMPRESS_ZSTD; 77 } 78 79 static inline enum btrfs_compression_type extent_map_compression(const struct extent_map *em) 80 { 81 if (em->flags & EXTENT_FLAG_COMPRESS_ZLIB) 82 return BTRFS_COMPRESS_ZLIB; 83 84 if (em->flags & EXTENT_FLAG_COMPRESS_LZO) 85 return BTRFS_COMPRESS_LZO; 86 87 if (em->flags & EXTENT_FLAG_COMPRESS_ZSTD) 88 return BTRFS_COMPRESS_ZSTD; 89 90 return BTRFS_COMPRESS_NONE; 91 } 92 93 /* 94 * More efficient way to determine if extent is compressed, instead of using 95 * 'extent_map_compression() != BTRFS_COMPRESS_NONE'. 96 */ 97 static inline bool extent_map_is_compressed(const struct extent_map *em) 98 { 99 return (em->flags & (EXTENT_FLAG_COMPRESS_ZLIB | 100 EXTENT_FLAG_COMPRESS_LZO | 101 EXTENT_FLAG_COMPRESS_ZSTD)) != 0; 102 } 103 104 static inline int extent_map_in_tree(const struct extent_map *em) 105 { 106 return !RB_EMPTY_NODE(&em->rb_node); 107 } 108 109 static inline u64 extent_map_end(const struct extent_map *em) 110 { 111 if (em->start + em->len < em->start) 112 return (u64)-1; 113 return em->start + em->len; 114 } 115 116 void extent_map_tree_init(struct extent_map_tree *tree); 117 struct extent_map *lookup_extent_mapping(struct extent_map_tree *tree, 118 u64 start, u64 len); 119 void remove_extent_mapping(struct extent_map_tree *tree, struct extent_map *em); 120 int split_extent_map(struct btrfs_inode *inode, u64 start, u64 len, u64 pre, 121 u64 new_logical); 122 123 struct extent_map *alloc_extent_map(void); 124 void free_extent_map(struct extent_map *em); 125 int __init extent_map_init(void); 126 void __cold extent_map_exit(void); 127 int unpin_extent_cache(struct btrfs_inode *inode, u64 start, u64 len, u64 gen); 128 void clear_em_logging(struct extent_map_tree *tree, struct extent_map *em); 129 struct extent_map *search_extent_mapping(struct extent_map_tree *tree, 130 u64 start, u64 len); 131 int btrfs_add_extent_mapping(struct btrfs_fs_info *fs_info, 132 struct extent_map_tree *em_tree, 133 struct extent_map **em_in, u64 start, u64 len); 134 void btrfs_drop_extent_map_range(struct btrfs_inode *inode, 135 u64 start, u64 end, 136 bool skip_pinned); 137 int btrfs_replace_extent_map_range(struct btrfs_inode *inode, 138 struct extent_map *new_em, 139 bool modified); 140 141 #endif 142