1 /* SPDX-License-Identifier: GPL-2.0 */
3 #ifndef BTRFS_EXTENT_MAP_H
4 #define BTRFS_EXTENT_MAP_H
6 #include <linux/rbtree.h>
7 #include <linux/refcount.h>
9 #include "compression.h"
11 #define EXTENT_MAP_LAST_BYTE ((u64)-4)
12 #define EXTENT_MAP_HOLE ((u64)-3)
13 #define EXTENT_MAP_INLINE ((u64)-2)
15 /* bits for the extent_map::flags field */
17 /* this entry not yet on disk, don't free it */
18 ENUM_BIT(EXTENT_FLAG_PINNED
),
19 ENUM_BIT(EXTENT_FLAG_COMPRESS_ZLIB
),
20 ENUM_BIT(EXTENT_FLAG_COMPRESS_LZO
),
21 ENUM_BIT(EXTENT_FLAG_COMPRESS_ZSTD
),
22 /* pre-allocated extent */
23 ENUM_BIT(EXTENT_FLAG_PREALLOC
),
24 /* Logging this extent */
25 ENUM_BIT(EXTENT_FLAG_LOGGING
),
26 /* Filling in a preallocated extent */
27 ENUM_BIT(EXTENT_FLAG_FILLING
),
28 /* This em is merged from two or more physically adjacent ems */
29 ENUM_BIT(EXTENT_FLAG_MERGED
),
33 * Keep this structure as compact as possible, as we can have really large
34 * amounts of allocated extent maps at any time.
37 struct rb_node rb_node
;
39 /* all of these are in bytes */
51 * Generation of the extent map, for merged em it's the highest
52 * generation of all merged ems.
53 * For non-merged extents, it's from btrfs_file_extent_item::generation.
58 struct list_head list
;
61 struct extent_map_tree
{
62 struct rb_root_cached map
;
63 struct list_head modified_extents
;
69 static inline void extent_map_set_compression(struct extent_map
*em
,
70 enum btrfs_compression_type type
)
72 if (type
== BTRFS_COMPRESS_ZLIB
)
73 em
->flags
|= EXTENT_FLAG_COMPRESS_ZLIB
;
74 else if (type
== BTRFS_COMPRESS_LZO
)
75 em
->flags
|= EXTENT_FLAG_COMPRESS_LZO
;
76 else if (type
== BTRFS_COMPRESS_ZSTD
)
77 em
->flags
|= EXTENT_FLAG_COMPRESS_ZSTD
;
80 static inline enum btrfs_compression_type
extent_map_compression(const struct extent_map
*em
)
82 if (em
->flags
& EXTENT_FLAG_COMPRESS_ZLIB
)
83 return BTRFS_COMPRESS_ZLIB
;
85 if (em
->flags
& EXTENT_FLAG_COMPRESS_LZO
)
86 return BTRFS_COMPRESS_LZO
;
88 if (em
->flags
& EXTENT_FLAG_COMPRESS_ZSTD
)
89 return BTRFS_COMPRESS_ZSTD
;
91 return BTRFS_COMPRESS_NONE
;
95 * More efficient way to determine if extent is compressed, instead of using
96 * 'extent_map_compression() != BTRFS_COMPRESS_NONE'.
98 static inline bool extent_map_is_compressed(const struct extent_map
*em
)
100 return (em
->flags
& (EXTENT_FLAG_COMPRESS_ZLIB
|
101 EXTENT_FLAG_COMPRESS_LZO
|
102 EXTENT_FLAG_COMPRESS_ZSTD
)) != 0;
105 static inline int extent_map_in_tree(const struct extent_map
*em
)
107 return !RB_EMPTY_NODE(&em
->rb_node
);
110 static inline u64
extent_map_end(const struct extent_map
*em
)
112 if (em
->start
+ em
->len
< em
->start
)
114 return em
->start
+ em
->len
;
117 void extent_map_tree_init(struct extent_map_tree
*tree
);
118 struct extent_map
*lookup_extent_mapping(struct extent_map_tree
*tree
,
120 void remove_extent_mapping(struct extent_map_tree
*tree
, struct extent_map
*em
);
121 int split_extent_map(struct btrfs_inode
*inode
, u64 start
, u64 len
, u64 pre
,
124 struct extent_map
*alloc_extent_map(void);
125 void free_extent_map(struct extent_map
*em
);
126 int __init
extent_map_init(void);
127 void __cold
extent_map_exit(void);
128 int unpin_extent_cache(struct btrfs_inode
*inode
, u64 start
, u64 len
, u64 gen
);
129 void clear_em_logging(struct extent_map_tree
*tree
, struct extent_map
*em
);
130 struct extent_map
*search_extent_mapping(struct extent_map_tree
*tree
,
132 int btrfs_add_extent_mapping(struct btrfs_fs_info
*fs_info
,
133 struct extent_map_tree
*em_tree
,
134 struct extent_map
**em_in
, u64 start
, u64 len
);
135 void btrfs_drop_extent_map_range(struct btrfs_inode
*inode
,
138 int btrfs_replace_extent_map_range(struct btrfs_inode
*inode
,
139 struct extent_map
*new_em
,