David Sterba | 9888c34 | 2018-04-03 19:16:55 +0200 | [diff] [blame] | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
Jan Schmidt | a542ad1 | 2011-06-13 19:52:59 +0200 | [diff] [blame] | 2 | /* |
| 3 | * Copyright (C) 2011 STRATO. All rights reserved. |
Jan Schmidt | a542ad1 | 2011-06-13 19:52:59 +0200 | [diff] [blame] | 4 | */ |
| 5 | |
David Sterba | 9888c34 | 2018-04-03 19:16:55 +0200 | [diff] [blame] | 6 | #ifndef BTRFS_BACKREF_H |
| 7 | #define BTRFS_BACKREF_H |
Jan Schmidt | a542ad1 | 2011-06-13 19:52:59 +0200 | [diff] [blame] | 8 | |
Filipe Brandenburger | 55e301f | 2013-01-29 06:04:50 +0000 | [diff] [blame] | 9 | #include <linux/btrfs.h> |
Jan Schmidt | 8da6d58 | 2011-11-23 18:55:04 +0100 | [diff] [blame] | 10 | #include "ulist.h" |
Qu Wenruo | 741188d | 2020-03-03 13:26:12 +0800 | [diff] [blame] | 11 | #include "disk-io.h" |
Alexander Block | 91cb916 | 2012-06-03 14:23:23 +0200 | [diff] [blame] | 12 | #include "extent_io.h" |
Jan Schmidt | a542ad1 | 2011-06-13 19:52:59 +0200 | [diff] [blame] | 13 | |
| 14 | struct inode_fs_paths { |
| 15 | struct btrfs_path *btrfs_path; |
| 16 | struct btrfs_root *fs_root; |
| 17 | struct btrfs_data_container *fspath; |
| 18 | }; |
| 19 | |
| 20 | typedef int (iterate_extent_inodes_t)(u64 inum, u64 offset, u64 root, |
| 21 | void *ctx); |
Jan Schmidt | a542ad1 | 2011-06-13 19:52:59 +0200 | [diff] [blame] | 22 | |
Jan Schmidt | a542ad1 | 2011-06-13 19:52:59 +0200 | [diff] [blame] | 23 | int extent_from_logical(struct btrfs_fs_info *fs_info, u64 logical, |
Liu Bo | 69917e4 | 2012-09-07 20:01:28 -0600 | [diff] [blame] | 24 | struct btrfs_path *path, struct btrfs_key *found_key, |
| 25 | u64 *flags); |
Jan Schmidt | a542ad1 | 2011-06-13 19:52:59 +0200 | [diff] [blame] | 26 | |
| 27 | int tree_backref_for_extent(unsigned long *ptr, struct extent_buffer *eb, |
Liu Bo | 6eda71d | 2014-06-09 10:54:07 +0800 | [diff] [blame] | 28 | struct btrfs_key *key, struct btrfs_extent_item *ei, |
| 29 | u32 item_size, u64 *out_root, u8 *out_level); |
Jan Schmidt | a542ad1 | 2011-06-13 19:52:59 +0200 | [diff] [blame] | 30 | |
| 31 | int iterate_extent_inodes(struct btrfs_fs_info *fs_info, |
Jan Schmidt | a542ad1 | 2011-06-13 19:52:59 +0200 | [diff] [blame] | 32 | u64 extent_item_objectid, |
Jan Schmidt | 7a3ae2f | 2012-03-23 17:32:28 +0100 | [diff] [blame] | 33 | u64 extent_offset, int search_commit_root, |
Zygo Blaxell | c995ab3 | 2017-09-22 13:58:45 -0400 | [diff] [blame] | 34 | iterate_extent_inodes_t *iterate, void *ctx, |
| 35 | bool ignore_offset); |
Jan Schmidt | a542ad1 | 2011-06-13 19:52:59 +0200 | [diff] [blame] | 36 | |
| 37 | int iterate_inodes_from_logical(u64 logical, struct btrfs_fs_info *fs_info, |
| 38 | struct btrfs_path *path, |
Zygo Blaxell | c995ab3 | 2017-09-22 13:58:45 -0400 | [diff] [blame] | 39 | iterate_extent_inodes_t *iterate, void *ctx, |
| 40 | bool ignore_offset); |
Jan Schmidt | a542ad1 | 2011-06-13 19:52:59 +0200 | [diff] [blame] | 41 | |
| 42 | int paths_from_inode(u64 inum, struct inode_fs_paths *ipath); |
| 43 | |
Qu Wenruo | 19b546d | 2020-03-10 16:14:15 +0800 | [diff] [blame] | 44 | int btrfs_find_all_leafs(struct btrfs_trans_handle *trans, |
| 45 | struct btrfs_fs_info *fs_info, u64 bytenr, |
| 46 | u64 time_seq, struct ulist **leafs, |
| 47 | const u64 *extent_item_pos, bool ignore_offset); |
Jan Schmidt | 8da6d58 | 2011-11-23 18:55:04 +0100 | [diff] [blame] | 48 | int btrfs_find_all_roots(struct btrfs_trans_handle *trans, |
Josef Bacik | fcebe45 | 2014-05-13 17:30:47 -0700 | [diff] [blame] | 49 | struct btrfs_fs_info *fs_info, u64 bytenr, |
Filipe Manana | c7bcbb2 | 2021-07-22 15:58:10 +0100 | [diff] [blame] | 50 | u64 time_seq, struct ulist **roots, |
Filipe Manana | 8949b9a | 2021-07-21 17:31:48 +0100 | [diff] [blame] | 51 | bool skip_commit_root_sem); |
Jan Schmidt | 96b5bd7 | 2012-10-15 08:30:45 +0000 | [diff] [blame] | 52 | char *btrfs_ref_to_path(struct btrfs_root *fs_root, struct btrfs_path *path, |
| 53 | u32 name_len, unsigned long name_off, |
| 54 | struct extent_buffer *eb_in, u64 parent, |
| 55 | char *dest, u32 size); |
Jan Schmidt | 8da6d58 | 2011-11-23 18:55:04 +0100 | [diff] [blame] | 56 | |
Jan Schmidt | a542ad1 | 2011-06-13 19:52:59 +0200 | [diff] [blame] | 57 | struct btrfs_data_container *init_data_container(u32 total_bytes); |
| 58 | struct inode_fs_paths *init_ipath(s32 total_bytes, struct btrfs_root *fs_root, |
| 59 | struct btrfs_path *path); |
| 60 | void free_ipath(struct inode_fs_paths *ipath); |
| 61 | |
Mark Fasheh | f186373 | 2012-08-08 11:32:27 -0700 | [diff] [blame] | 62 | int btrfs_find_one_extref(struct btrfs_root *root, u64 inode_objectid, |
| 63 | u64 start_off, struct btrfs_path *path, |
| 64 | struct btrfs_inode_extref **ret_extref, |
| 65 | u64 *found_off); |
David Sterba | 5911c8f | 2019-05-15 15:31:04 +0200 | [diff] [blame] | 66 | int btrfs_check_shared(struct btrfs_root *root, u64 inum, u64 bytenr, |
| 67 | struct ulist *roots, struct ulist *tmp_ulist); |
Mark Fasheh | f186373 | 2012-08-08 11:32:27 -0700 | [diff] [blame] | 68 | |
Wang Shilong | b9e9a6c | 2013-08-09 13:25:36 +0800 | [diff] [blame] | 69 | int __init btrfs_prelim_ref_init(void); |
David Sterba | e67c718 | 2018-02-19 17:24:18 +0100 | [diff] [blame] | 70 | void __cold btrfs_prelim_ref_exit(void); |
Jeff Mahoney | 0014275 | 2017-07-12 16:20:08 -0600 | [diff] [blame] | 71 | |
| 72 | struct prelim_ref { |
| 73 | struct rb_node rbnode; |
| 74 | u64 root_id; |
| 75 | struct btrfs_key key_for_search; |
| 76 | int level; |
| 77 | int count; |
| 78 | struct extent_inode_elem *inode_list; |
| 79 | u64 parent; |
| 80 | u64 wanted_disk_byte; |
| 81 | }; |
| 82 | |
Qu Wenruo | a37f232 | 2020-02-13 14:11:04 +0800 | [diff] [blame] | 83 | /* |
| 84 | * Iterate backrefs of one extent. |
| 85 | * |
| 86 | * Now it only supports iteration of tree block in commit root. |
| 87 | */ |
| 88 | struct btrfs_backref_iter { |
| 89 | u64 bytenr; |
| 90 | struct btrfs_path *path; |
| 91 | struct btrfs_fs_info *fs_info; |
| 92 | struct btrfs_key cur_key; |
| 93 | u32 item_ptr; |
| 94 | u32 cur_ptr; |
| 95 | u32 end_ptr; |
| 96 | }; |
| 97 | |
| 98 | struct btrfs_backref_iter *btrfs_backref_iter_alloc( |
| 99 | struct btrfs_fs_info *fs_info, gfp_t gfp_flag); |
| 100 | |
| 101 | static inline void btrfs_backref_iter_free(struct btrfs_backref_iter *iter) |
| 102 | { |
| 103 | if (!iter) |
| 104 | return; |
| 105 | btrfs_free_path(iter->path); |
| 106 | kfree(iter); |
| 107 | } |
| 108 | |
Qu Wenruo | c39c2dd | 2020-02-13 15:04:04 +0800 | [diff] [blame] | 109 | static inline struct extent_buffer *btrfs_backref_get_eb( |
| 110 | struct btrfs_backref_iter *iter) |
| 111 | { |
| 112 | if (!iter) |
| 113 | return NULL; |
| 114 | return iter->path->nodes[0]; |
| 115 | } |
| 116 | |
| 117 | /* |
| 118 | * For metadata with EXTENT_ITEM key (non-skinny) case, the first inline data |
| 119 | * is btrfs_tree_block_info, without a btrfs_extent_inline_ref header. |
| 120 | * |
| 121 | * This helper determines if that's the case. |
| 122 | */ |
| 123 | static inline bool btrfs_backref_has_tree_block_info( |
| 124 | struct btrfs_backref_iter *iter) |
| 125 | { |
| 126 | if (iter->cur_key.type == BTRFS_EXTENT_ITEM_KEY && |
| 127 | iter->cur_ptr - iter->item_ptr == sizeof(struct btrfs_extent_item)) |
| 128 | return true; |
| 129 | return false; |
| 130 | } |
| 131 | |
Qu Wenruo | a37f232 | 2020-02-13 14:11:04 +0800 | [diff] [blame] | 132 | int btrfs_backref_iter_start(struct btrfs_backref_iter *iter, u64 bytenr); |
| 133 | |
Qu Wenruo | c39c2dd | 2020-02-13 15:04:04 +0800 | [diff] [blame] | 134 | int btrfs_backref_iter_next(struct btrfs_backref_iter *iter); |
| 135 | |
| 136 | static inline bool btrfs_backref_iter_is_inline_ref( |
| 137 | struct btrfs_backref_iter *iter) |
| 138 | { |
| 139 | if (iter->cur_key.type == BTRFS_EXTENT_ITEM_KEY || |
| 140 | iter->cur_key.type == BTRFS_METADATA_ITEM_KEY) |
| 141 | return true; |
| 142 | return false; |
| 143 | } |
| 144 | |
Qu Wenruo | a37f232 | 2020-02-13 14:11:04 +0800 | [diff] [blame] | 145 | static inline void btrfs_backref_iter_release(struct btrfs_backref_iter *iter) |
| 146 | { |
| 147 | iter->bytenr = 0; |
| 148 | iter->item_ptr = 0; |
| 149 | iter->cur_ptr = 0; |
| 150 | iter->end_ptr = 0; |
| 151 | btrfs_release_path(iter->path); |
| 152 | memset(&iter->cur_key, 0, sizeof(iter->cur_key)); |
| 153 | } |
| 154 | |
Qu Wenruo | 7053544 | 2020-03-23 15:03:56 +0800 | [diff] [blame] | 155 | /* |
| 156 | * Backref cache related structures |
| 157 | * |
| 158 | * The whole objective of backref_cache is to build a bi-directional map |
| 159 | * of tree blocks (represented by backref_node) and all their parents. |
| 160 | */ |
| 161 | |
| 162 | /* |
| 163 | * Represent a tree block in the backref cache |
| 164 | */ |
| 165 | struct btrfs_backref_node { |
Qu Wenruo | e9a28dc | 2020-03-26 14:11:09 +0800 | [diff] [blame] | 166 | struct { |
| 167 | struct rb_node rb_node; |
| 168 | u64 bytenr; |
| 169 | }; /* Use rb_simple_node for search/insert */ |
Qu Wenruo | 7053544 | 2020-03-23 15:03:56 +0800 | [diff] [blame] | 170 | |
| 171 | u64 new_bytenr; |
| 172 | /* Objectid of tree block owner, can be not uptodate */ |
| 173 | u64 owner; |
| 174 | /* Link to pending, changed or detached list */ |
| 175 | struct list_head list; |
| 176 | |
| 177 | /* List of upper level edges, which link this node to its parents */ |
| 178 | struct list_head upper; |
| 179 | /* List of lower level edges, which link this node to its children */ |
| 180 | struct list_head lower; |
| 181 | |
| 182 | /* NULL if this node is not tree root */ |
| 183 | struct btrfs_root *root; |
| 184 | /* Extent buffer got by COWing the block */ |
| 185 | struct extent_buffer *eb; |
| 186 | /* Level of the tree block */ |
| 187 | unsigned int level:8; |
Qu Wenruo | 92a7cc4 | 2020-05-15 14:01:40 +0800 | [diff] [blame] | 188 | /* Is the block in a non-shareable tree */ |
Qu Wenruo | 7053544 | 2020-03-23 15:03:56 +0800 | [diff] [blame] | 189 | unsigned int cowonly:1; |
| 190 | /* 1 if no child node is in the cache */ |
| 191 | unsigned int lowest:1; |
| 192 | /* Is the extent buffer locked */ |
| 193 | unsigned int locked:1; |
| 194 | /* Has the block been processed */ |
| 195 | unsigned int processed:1; |
| 196 | /* Have backrefs of this block been checked */ |
| 197 | unsigned int checked:1; |
| 198 | /* |
| 199 | * 1 if corresponding block has been COWed but some upper level block |
| 200 | * pointers may not point to the new location |
| 201 | */ |
| 202 | unsigned int pending:1; |
| 203 | /* 1 if the backref node isn't connected to any other backref node */ |
| 204 | unsigned int detached:1; |
| 205 | |
| 206 | /* |
| 207 | * For generic purpose backref cache, where we only care if it's a reloc |
| 208 | * root, doesn't care the source subvolid. |
| 209 | */ |
| 210 | unsigned int is_reloc_root:1; |
| 211 | }; |
| 212 | |
| 213 | #define LOWER 0 |
| 214 | #define UPPER 1 |
| 215 | |
| 216 | /* |
| 217 | * Represent an edge connecting upper and lower backref nodes. |
| 218 | */ |
| 219 | struct btrfs_backref_edge { |
| 220 | /* |
| 221 | * list[LOWER] is linked to btrfs_backref_node::upper of lower level |
| 222 | * node, and list[UPPER] is linked to btrfs_backref_node::lower of |
| 223 | * upper level node. |
| 224 | * |
| 225 | * Also, build_backref_tree() uses list[UPPER] for pending edges, before |
| 226 | * linking list[UPPER] to its upper level nodes. |
| 227 | */ |
| 228 | struct list_head list[2]; |
| 229 | |
| 230 | /* Two related nodes */ |
| 231 | struct btrfs_backref_node *node[2]; |
| 232 | }; |
| 233 | |
| 234 | struct btrfs_backref_cache { |
| 235 | /* Red black tree of all backref nodes in the cache */ |
| 236 | struct rb_root rb_root; |
| 237 | /* For passing backref nodes to btrfs_reloc_cow_block */ |
| 238 | struct btrfs_backref_node *path[BTRFS_MAX_LEVEL]; |
| 239 | /* |
| 240 | * List of blocks that have been COWed but some block pointers in upper |
| 241 | * level blocks may not reflect the new location |
| 242 | */ |
| 243 | struct list_head pending[BTRFS_MAX_LEVEL]; |
| 244 | /* List of backref nodes with no child node */ |
| 245 | struct list_head leaves; |
| 246 | /* List of blocks that have been COWed in current transaction */ |
| 247 | struct list_head changed; |
| 248 | /* List of detached backref node. */ |
| 249 | struct list_head detached; |
| 250 | |
| 251 | u64 last_trans; |
| 252 | |
| 253 | int nr_nodes; |
| 254 | int nr_edges; |
| 255 | |
| 256 | /* List of unchecked backref edges during backref cache build */ |
| 257 | struct list_head pending_edge; |
| 258 | |
| 259 | /* List of useless backref nodes during backref cache build */ |
| 260 | struct list_head useless_node; |
| 261 | |
| 262 | struct btrfs_fs_info *fs_info; |
| 263 | |
| 264 | /* |
| 265 | * Whether this cache is for relocation |
| 266 | * |
| 267 | * Reloction backref cache require more info for reloc root compared |
| 268 | * to generic backref cache. |
| 269 | */ |
| 270 | unsigned int is_reloc; |
| 271 | }; |
| 272 | |
Qu Wenruo | 584fb12 | 2020-03-03 13:14:41 +0800 | [diff] [blame] | 273 | void btrfs_backref_init_cache(struct btrfs_fs_info *fs_info, |
| 274 | struct btrfs_backref_cache *cache, int is_reloc); |
Qu Wenruo | b1818da | 2020-03-03 13:21:30 +0800 | [diff] [blame] | 275 | struct btrfs_backref_node *btrfs_backref_alloc_node( |
| 276 | struct btrfs_backref_cache *cache, u64 bytenr, int level); |
Qu Wenruo | 47254d0 | 2020-03-03 13:22:57 +0800 | [diff] [blame] | 277 | struct btrfs_backref_edge *btrfs_backref_alloc_edge( |
| 278 | struct btrfs_backref_cache *cache); |
Qu Wenruo | 584fb12 | 2020-03-03 13:14:41 +0800 | [diff] [blame] | 279 | |
Qu Wenruo | f39911e5 | 2020-03-03 13:24:06 +0800 | [diff] [blame] | 280 | #define LINK_LOWER (1 << 0) |
| 281 | #define LINK_UPPER (1 << 1) |
| 282 | static inline void btrfs_backref_link_edge(struct btrfs_backref_edge *edge, |
| 283 | struct btrfs_backref_node *lower, |
| 284 | struct btrfs_backref_node *upper, |
| 285 | int link_which) |
| 286 | { |
| 287 | ASSERT(upper && lower && upper->level == lower->level + 1); |
| 288 | edge->node[LOWER] = lower; |
| 289 | edge->node[UPPER] = upper; |
| 290 | if (link_which & LINK_LOWER) |
| 291 | list_add_tail(&edge->list[LOWER], &lower->upper); |
| 292 | if (link_which & LINK_UPPER) |
| 293 | list_add_tail(&edge->list[UPPER], &upper->lower); |
| 294 | } |
| 295 | |
Qu Wenruo | 741188d | 2020-03-03 13:26:12 +0800 | [diff] [blame] | 296 | static inline void btrfs_backref_free_node(struct btrfs_backref_cache *cache, |
| 297 | struct btrfs_backref_node *node) |
| 298 | { |
| 299 | if (node) { |
Josef Bacik | eddda68 | 2021-01-14 14:02:45 -0500 | [diff] [blame] | 300 | ASSERT(list_empty(&node->list)); |
| 301 | ASSERT(list_empty(&node->lower)); |
| 302 | ASSERT(node->eb == NULL); |
Qu Wenruo | 741188d | 2020-03-03 13:26:12 +0800 | [diff] [blame] | 303 | cache->nr_nodes--; |
| 304 | btrfs_put_root(node->root); |
| 305 | kfree(node); |
| 306 | } |
| 307 | } |
| 308 | |
| 309 | static inline void btrfs_backref_free_edge(struct btrfs_backref_cache *cache, |
| 310 | struct btrfs_backref_edge *edge) |
| 311 | { |
| 312 | if (edge) { |
| 313 | cache->nr_edges--; |
| 314 | kfree(edge); |
| 315 | } |
| 316 | } |
| 317 | |
Qu Wenruo | b0fe707 | 2020-03-03 13:35:27 +0800 | [diff] [blame] | 318 | static inline void btrfs_backref_unlock_node_buffer( |
| 319 | struct btrfs_backref_node *node) |
| 320 | { |
| 321 | if (node->locked) { |
| 322 | btrfs_tree_unlock(node->eb); |
| 323 | node->locked = 0; |
| 324 | } |
| 325 | } |
| 326 | |
| 327 | static inline void btrfs_backref_drop_node_buffer( |
| 328 | struct btrfs_backref_node *node) |
| 329 | { |
| 330 | if (node->eb) { |
| 331 | btrfs_backref_unlock_node_buffer(node); |
| 332 | free_extent_buffer(node->eb); |
| 333 | node->eb = NULL; |
| 334 | } |
| 335 | } |
| 336 | |
| 337 | /* |
| 338 | * Drop the backref node from cache without cleaning up its children |
| 339 | * edges. |
| 340 | * |
| 341 | * This can only be called on node without parent edges. |
| 342 | * The children edges are still kept as is. |
| 343 | */ |
| 344 | static inline void btrfs_backref_drop_node(struct btrfs_backref_cache *tree, |
| 345 | struct btrfs_backref_node *node) |
| 346 | { |
Josef Bacik | eddda68 | 2021-01-14 14:02:45 -0500 | [diff] [blame] | 347 | ASSERT(list_empty(&node->upper)); |
Qu Wenruo | b0fe707 | 2020-03-03 13:35:27 +0800 | [diff] [blame] | 348 | |
| 349 | btrfs_backref_drop_node_buffer(node); |
Josef Bacik | eddda68 | 2021-01-14 14:02:45 -0500 | [diff] [blame] | 350 | list_del_init(&node->list); |
| 351 | list_del_init(&node->lower); |
Qu Wenruo | b0fe707 | 2020-03-03 13:35:27 +0800 | [diff] [blame] | 352 | if (!RB_EMPTY_NODE(&node->rb_node)) |
| 353 | rb_erase(&node->rb_node, &tree->rb_root); |
| 354 | btrfs_backref_free_node(tree, node); |
| 355 | } |
| 356 | |
Qu Wenruo | 023acb0 | 2020-03-23 15:42:25 +0800 | [diff] [blame] | 357 | void btrfs_backref_cleanup_node(struct btrfs_backref_cache *cache, |
| 358 | struct btrfs_backref_node *node); |
| 359 | |
Qu Wenruo | 13fe1bd | 2020-03-03 13:55:12 +0800 | [diff] [blame] | 360 | void btrfs_backref_release_cache(struct btrfs_backref_cache *cache); |
| 361 | |
Qu Wenruo | 982c92c | 2020-03-26 14:21:36 +0800 | [diff] [blame] | 362 | static inline void btrfs_backref_panic(struct btrfs_fs_info *fs_info, |
| 363 | u64 bytenr, int errno) |
| 364 | { |
| 365 | btrfs_panic(fs_info, errno, |
| 366 | "Inconsistency in backref cache found at offset %llu", |
| 367 | bytenr); |
| 368 | } |
| 369 | |
Qu Wenruo | 1b60d2e | 2020-03-23 16:08:34 +0800 | [diff] [blame] | 370 | int btrfs_backref_add_tree_node(struct btrfs_backref_cache *cache, |
| 371 | struct btrfs_path *path, |
| 372 | struct btrfs_backref_iter *iter, |
| 373 | struct btrfs_key *node_key, |
| 374 | struct btrfs_backref_node *cur); |
| 375 | |
Qu Wenruo | fc997ed | 2020-03-23 16:14:08 +0800 | [diff] [blame] | 376 | int btrfs_backref_finish_upper_links(struct btrfs_backref_cache *cache, |
| 377 | struct btrfs_backref_node *start); |
| 378 | |
Qu Wenruo | 1b23ea1 | 2020-03-23 16:57:15 +0800 | [diff] [blame] | 379 | void btrfs_backref_error_cleanup(struct btrfs_backref_cache *cache, |
| 380 | struct btrfs_backref_node *node); |
| 381 | |
Jan Schmidt | a542ad1 | 2011-06-13 19:52:59 +0200 | [diff] [blame] | 382 | #endif |