]>
Commit | Line | Data |
---|---|---|
9888c340 | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
a542ad1b JS |
2 | /* |
3 | * Copyright (C) 2011 STRATO. All rights reserved. | |
a542ad1b JS |
4 | */ |
5 | ||
9888c340 DS |
6 | #ifndef BTRFS_BACKREF_H |
7 | #define BTRFS_BACKREF_H | |
a542ad1b | 8 | |
55e301fd | 9 | #include <linux/btrfs.h> |
9b569ea0 | 10 | #include "messages.h" |
8da6d581 | 11 | #include "ulist.h" |
741188d3 | 12 | #include "disk-io.h" |
91cb916c | 13 | #include "extent_io.h" |
a542ad1b | 14 | |
88ffb665 FM |
15 | /* |
16 | * Used by implementations of iterate_extent_inodes_t (see definition below) to | |
17 | * signal that backref iteration can stop immediately and no error happened. | |
18 | * The value must be non-negative and must not be 0, 1 (which is a common return | |
19 | * value from things like btrfs_search_slot() and used internally in the backref | |
20 | * walking code) and different from BACKREF_FOUND_SHARED and | |
21 | * BACKREF_FOUND_NOT_SHARED | |
22 | */ | |
23 | #define BTRFS_ITERATE_EXTENT_INODES_STOP 5 | |
24 | ||
25 | /* | |
26 | * Should return 0 if no errors happened and iteration of backrefs should | |
27 | * continue. Can return BTRFS_ITERATE_EXTENT_INODES_STOP or any other non-zero | |
28 | * value to immediately stop iteration and possibly signal an error back to | |
29 | * the caller. | |
30 | */ | |
31 | typedef int (iterate_extent_inodes_t)(u64 inum, u64 offset, u64 num_bytes, | |
32 | u64 root, void *ctx); | |
33 | ||
6ce6ba53 | 34 | /* |
a2c8d27e FM |
35 | * Context and arguments for backref walking functions. Some of the fields are |
36 | * to be filled by the caller of such functions while other are filled by the | |
37 | * functions themselves, as described below. | |
6ce6ba53 | 38 | */ |
a2c8d27e FM |
39 | struct btrfs_backref_walk_ctx { |
40 | /* | |
41 | * The address of the extent for which we are doing backref walking. | |
42 | * Can be either a data extent or a metadata extent. | |
43 | * | |
44 | * Must always be set by the top level caller. | |
45 | */ | |
46 | u64 bytenr; | |
47 | /* | |
48 | * Offset relative to the target extent. This is only used for data | |
49 | * extents, and it's meaningful because we can have file extent items | |
50 | * that point only to a section of a data extent ("bookend" extents), | |
51 | * and we want to filter out any that don't point to a section of the | |
52 | * data extent containing the given offset. | |
53 | * | |
54 | * Must always be set by the top level caller. | |
55 | */ | |
56 | u64 extent_item_pos; | |
57 | /* | |
58 | * If true and bytenr corresponds to a data extent, then references from | |
59 | * all file extent items that point to the data extent are considered, | |
60 | * @extent_item_pos is ignored. | |
61 | */ | |
62 | bool ignore_extent_item_pos; | |
0cad8f14 FM |
63 | /* |
64 | * If true and bytenr corresponds to a data extent, then the inode list | |
65 | * (each member describing inode number, file offset and root) is not | |
66 | * added to each reference added to the @refs ulist. | |
67 | */ | |
68 | bool skip_inode_ref_list; | |
a2c8d27e FM |
69 | /* A valid transaction handle or NULL. */ |
70 | struct btrfs_trans_handle *trans; | |
71 | /* | |
72 | * The file system's info object, can not be NULL. | |
73 | * | |
74 | * Must always be set by the top level caller. | |
75 | */ | |
76 | struct btrfs_fs_info *fs_info; | |
77 | /* | |
78 | * Time sequence acquired from btrfs_get_tree_mod_seq(), in case the | |
79 | * caller joined the tree mod log to get a consistent view of b+trees | |
80 | * while we do backref walking, or BTRFS_SEQ_LAST. | |
81 | * When using BTRFS_SEQ_LAST, delayed refs are not checked and it uses | |
82 | * commit roots when searching b+trees - this is a special case for | |
83 | * qgroups used during a transaction commit. | |
84 | */ | |
85 | u64 time_seq; | |
86 | /* | |
87 | * Used to collect the bytenr of metadata extents that point to the | |
88 | * target extent. | |
89 | */ | |
90 | struct ulist *refs; | |
91 | /* | |
92 | * List used to collect the IDs of the roots from which the target | |
93 | * extent is accessible. Can be NULL in case the caller does not care | |
94 | * about collecting root IDs. | |
95 | */ | |
96 | struct ulist *roots; | |
66d04209 | 97 | /* |
88ffb665 FM |
98 | * Used by iterate_extent_inodes() and the main backref walk code |
99 | * (find_parent_nodes()). Lookup and store functions for an optional | |
100 | * cache which maps the logical address (bytenr) of leaves to an array | |
101 | * of root IDs. | |
66d04209 FM |
102 | */ |
103 | bool (*cache_lookup)(u64 leaf_bytenr, void *user_ctx, | |
104 | const u64 **root_ids_ret, int *root_count_ret); | |
105 | void (*cache_store)(u64 leaf_bytenr, const struct ulist *root_ids, | |
106 | void *user_ctx); | |
88ffb665 FM |
107 | /* |
108 | * If this is not NULL, then the backref walking code will call this | |
109 | * for each indirect data extent reference as soon as it finds one, | |
110 | * before collecting all the remaining backrefs and before resolving | |
111 | * indirect backrefs. This allows for the caller to terminate backref | |
112 | * walking as soon as it finds one backref that matches some specific | |
113 | * criteria. The @cache_lookup and @cache_store callbacks should not | |
114 | * be NULL in order to use this callback. | |
115 | */ | |
116 | iterate_extent_inodes_t *indirect_ref_iterator; | |
117 | /* | |
f73853c7 FM |
118 | * If this is not NULL, then the backref walking code will call this for |
119 | * each extent item it's meant to process before it actually starts | |
120 | * processing it. If this returns anything other than 0, then it stops | |
121 | * the backref walking code immediately. | |
88ffb665 | 122 | */ |
f73853c7 FM |
123 | int (*check_extent_item)(u64 bytenr, const struct btrfs_extent_item *ei, |
124 | const struct extent_buffer *leaf, void *user_ctx); | |
adf02418 FM |
125 | /* |
126 | * If this is not NULL, then the backref walking code will call this for | |
127 | * each extent data ref it finds (BTRFS_EXTENT_DATA_REF_KEY keys) before | |
128 | * processing that data ref. If this callback return false, then it will | |
129 | * ignore this data ref and it will never resolve the indirect data ref, | |
130 | * saving time searching for leaves in a fs tree with file extent items | |
131 | * matching the data ref. | |
132 | */ | |
133 | bool (*skip_data_ref)(u64 root, u64 ino, u64 offset, void *user_ctx); | |
f73853c7 | 134 | /* Context object to pass to the callbacks defined above. */ |
66d04209 | 135 | void *user_ctx; |
a2c8d27e | 136 | }; |
6ce6ba53 | 137 | |
a542ad1b JS |
138 | struct inode_fs_paths { |
139 | struct btrfs_path *btrfs_path; | |
140 | struct btrfs_root *fs_root; | |
141 | struct btrfs_data_container *fspath; | |
142 | }; | |
143 | ||
12a824dc FM |
144 | struct btrfs_backref_shared_cache_entry { |
145 | u64 bytenr; | |
146 | u64 gen; | |
147 | bool is_shared; | |
148 | }; | |
149 | ||
73e339e6 FM |
150 | #define BTRFS_BACKREF_CTX_PREV_EXTENTS_SIZE 8 |
151 | ||
61dbb952 | 152 | struct btrfs_backref_share_check_ctx { |
84a7949d FM |
153 | /* Ulists used during backref walking. */ |
154 | struct ulist refs; | |
877c1476 FM |
155 | /* |
156 | * The current leaf the caller of btrfs_is_data_extent_shared() is at. | |
157 | * Typically the caller (at the moment only fiemap) tries to determine | |
158 | * the sharedness of data extents point by file extent items from entire | |
159 | * leaves. | |
160 | */ | |
161 | u64 curr_leaf_bytenr; | |
162 | /* | |
163 | * The previous leaf the caller was at in the previous call to | |
164 | * btrfs_is_data_extent_shared(). This may be the same as the current | |
165 | * leaf. On the first call it must be 0. | |
166 | */ | |
167 | u64 prev_leaf_bytenr; | |
12a824dc FM |
168 | /* |
169 | * A path from a root to a leaf that has a file extent item pointing to | |
170 | * a given data extent should never exceed the maximum b+tree height. | |
171 | */ | |
61dbb952 FM |
172 | struct btrfs_backref_shared_cache_entry path_cache_entries[BTRFS_MAX_LEVEL]; |
173 | bool use_path_cache; | |
73e339e6 FM |
174 | /* |
175 | * Cache the sharedness result for the last few extents we have found, | |
176 | * but only for extents for which we have multiple file extent items | |
177 | * that point to them. | |
178 | * It's very common to have several file extent items that point to the | |
179 | * same extent (bytenr) but with different offsets and lengths. This | |
180 | * typically happens for COW writes, partial writes into prealloc | |
181 | * extents, NOCOW writes after snapshoting a root, hole punching or | |
182 | * reflinking within the same file (less common perhaps). | |
183 | * So keep a small cache with the lookup results for the extent pointed | |
184 | * by the last few file extent items. This cache is checked, with a | |
185 | * linear scan, whenever btrfs_is_data_extent_shared() is called, so | |
186 | * it must be small so that it does not negatively affect performance in | |
187 | * case we don't have multiple file extent items that point to the same | |
188 | * data extent. | |
189 | */ | |
190 | struct { | |
191 | u64 bytenr; | |
192 | bool is_shared; | |
193 | } prev_extents_cache[BTRFS_BACKREF_CTX_PREV_EXTENTS_SIZE]; | |
194 | /* | |
195 | * The slot in the prev_extents_cache array that will be used for | |
196 | * storing the sharedness result of a new data extent. | |
197 | */ | |
198 | int prev_extents_cache_slot; | |
12a824dc FM |
199 | }; |
200 | ||
84a7949d FM |
201 | struct btrfs_backref_share_check_ctx *btrfs_alloc_backref_share_check_ctx(void); |
202 | void btrfs_free_backref_share_ctx(struct btrfs_backref_share_check_ctx *ctx); | |
203 | ||
a542ad1b | 204 | int extent_from_logical(struct btrfs_fs_info *fs_info, u64 logical, |
69917e43 LB |
205 | struct btrfs_path *path, struct btrfs_key *found_key, |
206 | u64 *flags); | |
a542ad1b JS |
207 | |
208 | int tree_backref_for_extent(unsigned long *ptr, struct extent_buffer *eb, | |
6eda71d0 LB |
209 | struct btrfs_key *key, struct btrfs_extent_item *ei, |
210 | u32 item_size, u64 *out_root, u8 *out_level); | |
a542ad1b | 211 | |
a2c8d27e FM |
212 | int iterate_extent_inodes(struct btrfs_backref_walk_ctx *ctx, |
213 | bool search_commit_root, | |
214 | iterate_extent_inodes_t *iterate, void *user_ctx); | |
a542ad1b JS |
215 | |
216 | int iterate_inodes_from_logical(u64 logical, struct btrfs_fs_info *fs_info, | |
e3059ec0 | 217 | struct btrfs_path *path, void *ctx, |
c995ab3c | 218 | bool ignore_offset); |
a542ad1b JS |
219 | |
220 | int paths_from_inode(u64 inum, struct inode_fs_paths *ipath); | |
221 | ||
a2c8d27e FM |
222 | int btrfs_find_all_leafs(struct btrfs_backref_walk_ctx *ctx); |
223 | int btrfs_find_all_roots(struct btrfs_backref_walk_ctx *ctx, | |
8949b9a1 | 224 | bool skip_commit_root_sem); |
96b5bd77 JS |
225 | char *btrfs_ref_to_path(struct btrfs_root *fs_root, struct btrfs_path *path, |
226 | u32 name_len, unsigned long name_off, | |
227 | struct extent_buffer *eb_in, u64 parent, | |
228 | char *dest, u32 size); | |
8da6d581 | 229 | |
a542ad1b JS |
230 | struct btrfs_data_container *init_data_container(u32 total_bytes); |
231 | struct inode_fs_paths *init_ipath(s32 total_bytes, struct btrfs_root *fs_root, | |
232 | struct btrfs_path *path); | |
233 | void free_ipath(struct inode_fs_paths *ipath); | |
234 | ||
f186373f MF |
235 | int btrfs_find_one_extref(struct btrfs_root *root, u64 inode_objectid, |
236 | u64 start_off, struct btrfs_path *path, | |
237 | struct btrfs_inode_extref **ret_extref, | |
238 | u64 *found_off); | |
ceb707da | 239 | int btrfs_is_data_extent_shared(struct btrfs_inode *inode, u64 bytenr, |
b8f164e3 | 240 | u64 extent_gen, |
61dbb952 | 241 | struct btrfs_backref_share_check_ctx *ctx); |
f186373f | 242 | |
b9e9a6cb | 243 | int __init btrfs_prelim_ref_init(void); |
e67c718b | 244 | void __cold btrfs_prelim_ref_exit(void); |
00142756 JM |
245 | |
246 | struct prelim_ref { | |
247 | struct rb_node rbnode; | |
248 | u64 root_id; | |
249 | struct btrfs_key key_for_search; | |
105c8c42 | 250 | u8 level; |
00142756 JM |
251 | int count; |
252 | struct extent_inode_elem *inode_list; | |
253 | u64 parent; | |
254 | u64 wanted_disk_byte; | |
255 | }; | |
256 | ||
a37f232b QW |
257 | /* |
258 | * Iterate backrefs of one extent. | |
259 | * | |
260 | * Now it only supports iteration of tree block in commit root. | |
261 | */ | |
262 | struct btrfs_backref_iter { | |
263 | u64 bytenr; | |
264 | struct btrfs_path *path; | |
265 | struct btrfs_fs_info *fs_info; | |
266 | struct btrfs_key cur_key; | |
267 | u32 item_ptr; | |
268 | u32 cur_ptr; | |
269 | u32 end_ptr; | |
270 | }; | |
271 | ||
d68194b2 | 272 | struct btrfs_backref_iter *btrfs_backref_iter_alloc(struct btrfs_fs_info *fs_info); |
a37f232b QW |
273 | |
274 | static inline void btrfs_backref_iter_free(struct btrfs_backref_iter *iter) | |
275 | { | |
276 | if (!iter) | |
277 | return; | |
278 | btrfs_free_path(iter->path); | |
279 | kfree(iter); | |
280 | } | |
281 | ||
c39c2ddc QW |
282 | static inline struct extent_buffer *btrfs_backref_get_eb( |
283 | struct btrfs_backref_iter *iter) | |
284 | { | |
285 | if (!iter) | |
286 | return NULL; | |
287 | return iter->path->nodes[0]; | |
288 | } | |
289 | ||
290 | /* | |
291 | * For metadata with EXTENT_ITEM key (non-skinny) case, the first inline data | |
292 | * is btrfs_tree_block_info, without a btrfs_extent_inline_ref header. | |
293 | * | |
294 | * This helper determines if that's the case. | |
295 | */ | |
296 | static inline bool btrfs_backref_has_tree_block_info( | |
297 | struct btrfs_backref_iter *iter) | |
298 | { | |
299 | if (iter->cur_key.type == BTRFS_EXTENT_ITEM_KEY && | |
300 | iter->cur_ptr - iter->item_ptr == sizeof(struct btrfs_extent_item)) | |
301 | return true; | |
302 | return false; | |
303 | } | |
304 | ||
a37f232b QW |
305 | int btrfs_backref_iter_start(struct btrfs_backref_iter *iter, u64 bytenr); |
306 | ||
c39c2ddc QW |
307 | int btrfs_backref_iter_next(struct btrfs_backref_iter *iter); |
308 | ||
309 | static inline bool btrfs_backref_iter_is_inline_ref( | |
310 | struct btrfs_backref_iter *iter) | |
311 | { | |
312 | if (iter->cur_key.type == BTRFS_EXTENT_ITEM_KEY || | |
313 | iter->cur_key.type == BTRFS_METADATA_ITEM_KEY) | |
314 | return true; | |
315 | return false; | |
316 | } | |
317 | ||
a37f232b QW |
318 | static inline void btrfs_backref_iter_release(struct btrfs_backref_iter *iter) |
319 | { | |
320 | iter->bytenr = 0; | |
321 | iter->item_ptr = 0; | |
322 | iter->cur_ptr = 0; | |
323 | iter->end_ptr = 0; | |
324 | btrfs_release_path(iter->path); | |
325 | memset(&iter->cur_key, 0, sizeof(iter->cur_key)); | |
326 | } | |
327 | ||
70535441 QW |
328 | /* |
329 | * Backref cache related structures | |
330 | * | |
331 | * The whole objective of backref_cache is to build a bi-directional map | |
332 | * of tree blocks (represented by backref_node) and all their parents. | |
333 | */ | |
334 | ||
335 | /* | |
336 | * Represent a tree block in the backref cache | |
337 | */ | |
338 | struct btrfs_backref_node { | |
e9a28dc5 QW |
339 | struct { |
340 | struct rb_node rb_node; | |
341 | u64 bytenr; | |
342 | }; /* Use rb_simple_node for search/insert */ | |
70535441 QW |
343 | |
344 | u64 new_bytenr; | |
345 | /* Objectid of tree block owner, can be not uptodate */ | |
346 | u64 owner; | |
347 | /* Link to pending, changed or detached list */ | |
348 | struct list_head list; | |
349 | ||
350 | /* List of upper level edges, which link this node to its parents */ | |
351 | struct list_head upper; | |
352 | /* List of lower level edges, which link this node to its children */ | |
353 | struct list_head lower; | |
354 | ||
355 | /* NULL if this node is not tree root */ | |
356 | struct btrfs_root *root; | |
357 | /* Extent buffer got by COWing the block */ | |
358 | struct extent_buffer *eb; | |
359 | /* Level of the tree block */ | |
360 | unsigned int level:8; | |
92a7cc42 | 361 | /* Is the block in a non-shareable tree */ |
70535441 QW |
362 | unsigned int cowonly:1; |
363 | /* 1 if no child node is in the cache */ | |
364 | unsigned int lowest:1; | |
365 | /* Is the extent buffer locked */ | |
366 | unsigned int locked:1; | |
367 | /* Has the block been processed */ | |
368 | unsigned int processed:1; | |
369 | /* Have backrefs of this block been checked */ | |
370 | unsigned int checked:1; | |
371 | /* | |
372 | * 1 if corresponding block has been COWed but some upper level block | |
373 | * pointers may not point to the new location | |
374 | */ | |
375 | unsigned int pending:1; | |
376 | /* 1 if the backref node isn't connected to any other backref node */ | |
377 | unsigned int detached:1; | |
378 | ||
379 | /* | |
380 | * For generic purpose backref cache, where we only care if it's a reloc | |
381 | * root, doesn't care the source subvolid. | |
382 | */ | |
383 | unsigned int is_reloc_root:1; | |
384 | }; | |
385 | ||
386 | #define LOWER 0 | |
387 | #define UPPER 1 | |
388 | ||
389 | /* | |
390 | * Represent an edge connecting upper and lower backref nodes. | |
391 | */ | |
392 | struct btrfs_backref_edge { | |
393 | /* | |
394 | * list[LOWER] is linked to btrfs_backref_node::upper of lower level | |
395 | * node, and list[UPPER] is linked to btrfs_backref_node::lower of | |
396 | * upper level node. | |
397 | * | |
398 | * Also, build_backref_tree() uses list[UPPER] for pending edges, before | |
399 | * linking list[UPPER] to its upper level nodes. | |
400 | */ | |
401 | struct list_head list[2]; | |
402 | ||
403 | /* Two related nodes */ | |
404 | struct btrfs_backref_node *node[2]; | |
405 | }; | |
406 | ||
407 | struct btrfs_backref_cache { | |
408 | /* Red black tree of all backref nodes in the cache */ | |
409 | struct rb_root rb_root; | |
410 | /* For passing backref nodes to btrfs_reloc_cow_block */ | |
411 | struct btrfs_backref_node *path[BTRFS_MAX_LEVEL]; | |
412 | /* | |
413 | * List of blocks that have been COWed but some block pointers in upper | |
414 | * level blocks may not reflect the new location | |
415 | */ | |
416 | struct list_head pending[BTRFS_MAX_LEVEL]; | |
417 | /* List of backref nodes with no child node */ | |
418 | struct list_head leaves; | |
419 | /* List of blocks that have been COWed in current transaction */ | |
420 | struct list_head changed; | |
421 | /* List of detached backref node. */ | |
422 | struct list_head detached; | |
423 | ||
424 | u64 last_trans; | |
425 | ||
426 | int nr_nodes; | |
427 | int nr_edges; | |
428 | ||
429 | /* List of unchecked backref edges during backref cache build */ | |
430 | struct list_head pending_edge; | |
431 | ||
432 | /* List of useless backref nodes during backref cache build */ | |
433 | struct list_head useless_node; | |
434 | ||
435 | struct btrfs_fs_info *fs_info; | |
436 | ||
437 | /* | |
438 | * Whether this cache is for relocation | |
439 | * | |
440 | * Reloction backref cache require more info for reloc root compared | |
441 | * to generic backref cache. | |
442 | */ | |
c71d3c69 | 443 | bool is_reloc; |
70535441 QW |
444 | }; |
445 | ||
584fb121 | 446 | void btrfs_backref_init_cache(struct btrfs_fs_info *fs_info, |
c71d3c69 | 447 | struct btrfs_backref_cache *cache, bool is_reloc); |
b1818dab QW |
448 | struct btrfs_backref_node *btrfs_backref_alloc_node( |
449 | struct btrfs_backref_cache *cache, u64 bytenr, int level); | |
47254d07 QW |
450 | struct btrfs_backref_edge *btrfs_backref_alloc_edge( |
451 | struct btrfs_backref_cache *cache); | |
584fb121 | 452 | |
f39911e5 QW |
453 | #define LINK_LOWER (1 << 0) |
454 | #define LINK_UPPER (1 << 1) | |
455 | static inline void btrfs_backref_link_edge(struct btrfs_backref_edge *edge, | |
456 | struct btrfs_backref_node *lower, | |
457 | struct btrfs_backref_node *upper, | |
458 | int link_which) | |
459 | { | |
460 | ASSERT(upper && lower && upper->level == lower->level + 1); | |
461 | edge->node[LOWER] = lower; | |
462 | edge->node[UPPER] = upper; | |
463 | if (link_which & LINK_LOWER) | |
464 | list_add_tail(&edge->list[LOWER], &lower->upper); | |
465 | if (link_which & LINK_UPPER) | |
466 | list_add_tail(&edge->list[UPPER], &upper->lower); | |
467 | } | |
468 | ||
741188d3 QW |
469 | static inline void btrfs_backref_free_node(struct btrfs_backref_cache *cache, |
470 | struct btrfs_backref_node *node) | |
471 | { | |
472 | if (node) { | |
eddda68d JB |
473 | ASSERT(list_empty(&node->list)); |
474 | ASSERT(list_empty(&node->lower)); | |
475 | ASSERT(node->eb == NULL); | |
741188d3 QW |
476 | cache->nr_nodes--; |
477 | btrfs_put_root(node->root); | |
478 | kfree(node); | |
479 | } | |
480 | } | |
481 | ||
482 | static inline void btrfs_backref_free_edge(struct btrfs_backref_cache *cache, | |
483 | struct btrfs_backref_edge *edge) | |
484 | { | |
485 | if (edge) { | |
486 | cache->nr_edges--; | |
487 | kfree(edge); | |
488 | } | |
489 | } | |
490 | ||
b0fe7078 QW |
491 | static inline void btrfs_backref_unlock_node_buffer( |
492 | struct btrfs_backref_node *node) | |
493 | { | |
494 | if (node->locked) { | |
495 | btrfs_tree_unlock(node->eb); | |
496 | node->locked = 0; | |
497 | } | |
498 | } | |
499 | ||
500 | static inline void btrfs_backref_drop_node_buffer( | |
501 | struct btrfs_backref_node *node) | |
502 | { | |
503 | if (node->eb) { | |
504 | btrfs_backref_unlock_node_buffer(node); | |
505 | free_extent_buffer(node->eb); | |
506 | node->eb = NULL; | |
507 | } | |
508 | } | |
509 | ||
510 | /* | |
511 | * Drop the backref node from cache without cleaning up its children | |
512 | * edges. | |
513 | * | |
514 | * This can only be called on node without parent edges. | |
515 | * The children edges are still kept as is. | |
516 | */ | |
517 | static inline void btrfs_backref_drop_node(struct btrfs_backref_cache *tree, | |
518 | struct btrfs_backref_node *node) | |
519 | { | |
eddda68d | 520 | ASSERT(list_empty(&node->upper)); |
b0fe7078 QW |
521 | |
522 | btrfs_backref_drop_node_buffer(node); | |
eddda68d JB |
523 | list_del_init(&node->list); |
524 | list_del_init(&node->lower); | |
b0fe7078 QW |
525 | if (!RB_EMPTY_NODE(&node->rb_node)) |
526 | rb_erase(&node->rb_node, &tree->rb_root); | |
527 | btrfs_backref_free_node(tree, node); | |
528 | } | |
529 | ||
023acb07 QW |
530 | void btrfs_backref_cleanup_node(struct btrfs_backref_cache *cache, |
531 | struct btrfs_backref_node *node); | |
532 | ||
13fe1bdb QW |
533 | void btrfs_backref_release_cache(struct btrfs_backref_cache *cache); |
534 | ||
982c92cb | 535 | static inline void btrfs_backref_panic(struct btrfs_fs_info *fs_info, |
ed164802 | 536 | u64 bytenr, int error) |
982c92cb | 537 | { |
ed164802 | 538 | btrfs_panic(fs_info, error, |
982c92cb QW |
539 | "Inconsistency in backref cache found at offset %llu", |
540 | bytenr); | |
541 | } | |
542 | ||
eb96e221 FM |
543 | int btrfs_backref_add_tree_node(struct btrfs_trans_handle *trans, |
544 | struct btrfs_backref_cache *cache, | |
1b60d2ec QW |
545 | struct btrfs_path *path, |
546 | struct btrfs_backref_iter *iter, | |
547 | struct btrfs_key *node_key, | |
548 | struct btrfs_backref_node *cur); | |
549 | ||
fc997ed0 QW |
550 | int btrfs_backref_finish_upper_links(struct btrfs_backref_cache *cache, |
551 | struct btrfs_backref_node *start); | |
552 | ||
1b23ea18 QW |
553 | void btrfs_backref_error_cleanup(struct btrfs_backref_cache *cache, |
554 | struct btrfs_backref_node *node); | |
555 | ||
a542ad1b | 556 | #endif |