18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2011 STRATO. All rights reserved. 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#ifndef BTRFS_BACKREF_H 78c2ecf20Sopenharmony_ci#define BTRFS_BACKREF_H 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#include <linux/btrfs.h> 108c2ecf20Sopenharmony_ci#include "ulist.h" 118c2ecf20Sopenharmony_ci#include "disk-io.h" 128c2ecf20Sopenharmony_ci#include "extent_io.h" 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_cistruct inode_fs_paths { 158c2ecf20Sopenharmony_ci struct btrfs_path *btrfs_path; 168c2ecf20Sopenharmony_ci struct btrfs_root *fs_root; 178c2ecf20Sopenharmony_ci struct btrfs_data_container *fspath; 188c2ecf20Sopenharmony_ci}; 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_citypedef int (iterate_extent_inodes_t)(u64 inum, u64 offset, u64 root, 218c2ecf20Sopenharmony_ci void *ctx); 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ciint extent_from_logical(struct btrfs_fs_info *fs_info, u64 logical, 248c2ecf20Sopenharmony_ci struct btrfs_path *path, struct btrfs_key *found_key, 258c2ecf20Sopenharmony_ci u64 *flags); 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ciint tree_backref_for_extent(unsigned long *ptr, struct extent_buffer *eb, 288c2ecf20Sopenharmony_ci struct btrfs_key *key, struct btrfs_extent_item *ei, 298c2ecf20Sopenharmony_ci u32 item_size, u64 *out_root, u8 *out_level); 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ciint iterate_extent_inodes(struct btrfs_fs_info *fs_info, 328c2ecf20Sopenharmony_ci u64 extent_item_objectid, 338c2ecf20Sopenharmony_ci u64 extent_offset, int search_commit_root, 348c2ecf20Sopenharmony_ci iterate_extent_inodes_t *iterate, void *ctx, 358c2ecf20Sopenharmony_ci bool ignore_offset); 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ciint iterate_inodes_from_logical(u64 logical, struct btrfs_fs_info *fs_info, 388c2ecf20Sopenharmony_ci struct btrfs_path *path, void *ctx, 398c2ecf20Sopenharmony_ci bool ignore_offset); 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ciint paths_from_inode(u64 inum, struct inode_fs_paths *ipath); 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ciint btrfs_find_all_leafs(struct btrfs_trans_handle *trans, 448c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info, u64 bytenr, 458c2ecf20Sopenharmony_ci u64 time_seq, struct ulist **leafs, 468c2ecf20Sopenharmony_ci const u64 *extent_item_pos, bool ignore_offset); 478c2ecf20Sopenharmony_ciint btrfs_find_all_roots(struct btrfs_trans_handle *trans, 488c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info, u64 bytenr, 498c2ecf20Sopenharmony_ci u64 time_seq, struct ulist **roots, bool ignore_offset); 508c2ecf20Sopenharmony_cichar *btrfs_ref_to_path(struct btrfs_root *fs_root, struct btrfs_path *path, 518c2ecf20Sopenharmony_ci u32 name_len, unsigned long name_off, 528c2ecf20Sopenharmony_ci struct extent_buffer *eb_in, u64 parent, 538c2ecf20Sopenharmony_ci char *dest, u32 size); 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_cistruct btrfs_data_container *init_data_container(u32 total_bytes); 568c2ecf20Sopenharmony_cistruct inode_fs_paths *init_ipath(s32 total_bytes, struct btrfs_root *fs_root, 578c2ecf20Sopenharmony_ci struct btrfs_path *path); 588c2ecf20Sopenharmony_civoid free_ipath(struct inode_fs_paths *ipath); 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ciint btrfs_find_one_extref(struct btrfs_root *root, u64 inode_objectid, 618c2ecf20Sopenharmony_ci u64 start_off, struct btrfs_path *path, 628c2ecf20Sopenharmony_ci struct btrfs_inode_extref **ret_extref, 638c2ecf20Sopenharmony_ci u64 *found_off); 648c2ecf20Sopenharmony_ciint btrfs_check_shared(struct btrfs_root *root, u64 inum, u64 bytenr, 658c2ecf20Sopenharmony_ci struct ulist *roots, struct ulist *tmp_ulist); 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ciint __init btrfs_prelim_ref_init(void); 688c2ecf20Sopenharmony_civoid __cold btrfs_prelim_ref_exit(void); 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_cistruct prelim_ref { 718c2ecf20Sopenharmony_ci struct rb_node rbnode; 728c2ecf20Sopenharmony_ci u64 root_id; 738c2ecf20Sopenharmony_ci struct btrfs_key key_for_search; 748c2ecf20Sopenharmony_ci int level; 758c2ecf20Sopenharmony_ci int count; 768c2ecf20Sopenharmony_ci struct extent_inode_elem *inode_list; 778c2ecf20Sopenharmony_ci u64 parent; 788c2ecf20Sopenharmony_ci u64 wanted_disk_byte; 798c2ecf20Sopenharmony_ci}; 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci/* 828c2ecf20Sopenharmony_ci * Iterate backrefs of one extent. 838c2ecf20Sopenharmony_ci * 848c2ecf20Sopenharmony_ci * Now it only supports iteration of tree block in commit root. 858c2ecf20Sopenharmony_ci */ 868c2ecf20Sopenharmony_cistruct btrfs_backref_iter { 878c2ecf20Sopenharmony_ci u64 bytenr; 888c2ecf20Sopenharmony_ci struct btrfs_path *path; 898c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info; 908c2ecf20Sopenharmony_ci struct btrfs_key cur_key; 918c2ecf20Sopenharmony_ci u32 item_ptr; 928c2ecf20Sopenharmony_ci u32 cur_ptr; 938c2ecf20Sopenharmony_ci u32 end_ptr; 948c2ecf20Sopenharmony_ci}; 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_cistruct btrfs_backref_iter *btrfs_backref_iter_alloc( 978c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info, gfp_t gfp_flag); 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_cistatic inline void btrfs_backref_iter_free(struct btrfs_backref_iter *iter) 1008c2ecf20Sopenharmony_ci{ 1018c2ecf20Sopenharmony_ci if (!iter) 1028c2ecf20Sopenharmony_ci return; 1038c2ecf20Sopenharmony_ci btrfs_free_path(iter->path); 1048c2ecf20Sopenharmony_ci kfree(iter); 1058c2ecf20Sopenharmony_ci} 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_cistatic inline struct extent_buffer *btrfs_backref_get_eb( 1088c2ecf20Sopenharmony_ci struct btrfs_backref_iter *iter) 1098c2ecf20Sopenharmony_ci{ 1108c2ecf20Sopenharmony_ci if (!iter) 1118c2ecf20Sopenharmony_ci return NULL; 1128c2ecf20Sopenharmony_ci return iter->path->nodes[0]; 1138c2ecf20Sopenharmony_ci} 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci/* 1168c2ecf20Sopenharmony_ci * For metadata with EXTENT_ITEM key (non-skinny) case, the first inline data 1178c2ecf20Sopenharmony_ci * is btrfs_tree_block_info, without a btrfs_extent_inline_ref header. 1188c2ecf20Sopenharmony_ci * 1198c2ecf20Sopenharmony_ci * This helper determines if that's the case. 1208c2ecf20Sopenharmony_ci */ 1218c2ecf20Sopenharmony_cistatic inline bool btrfs_backref_has_tree_block_info( 1228c2ecf20Sopenharmony_ci struct btrfs_backref_iter *iter) 1238c2ecf20Sopenharmony_ci{ 1248c2ecf20Sopenharmony_ci if (iter->cur_key.type == BTRFS_EXTENT_ITEM_KEY && 1258c2ecf20Sopenharmony_ci iter->cur_ptr - iter->item_ptr == sizeof(struct btrfs_extent_item)) 1268c2ecf20Sopenharmony_ci return true; 1278c2ecf20Sopenharmony_ci return false; 1288c2ecf20Sopenharmony_ci} 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ciint btrfs_backref_iter_start(struct btrfs_backref_iter *iter, u64 bytenr); 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ciint btrfs_backref_iter_next(struct btrfs_backref_iter *iter); 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_cistatic inline bool btrfs_backref_iter_is_inline_ref( 1358c2ecf20Sopenharmony_ci struct btrfs_backref_iter *iter) 1368c2ecf20Sopenharmony_ci{ 1378c2ecf20Sopenharmony_ci if (iter->cur_key.type == BTRFS_EXTENT_ITEM_KEY || 1388c2ecf20Sopenharmony_ci iter->cur_key.type == BTRFS_METADATA_ITEM_KEY) 1398c2ecf20Sopenharmony_ci return true; 1408c2ecf20Sopenharmony_ci return false; 1418c2ecf20Sopenharmony_ci} 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_cistatic inline void btrfs_backref_iter_release(struct btrfs_backref_iter *iter) 1448c2ecf20Sopenharmony_ci{ 1458c2ecf20Sopenharmony_ci iter->bytenr = 0; 1468c2ecf20Sopenharmony_ci iter->item_ptr = 0; 1478c2ecf20Sopenharmony_ci iter->cur_ptr = 0; 1488c2ecf20Sopenharmony_ci iter->end_ptr = 0; 1498c2ecf20Sopenharmony_ci btrfs_release_path(iter->path); 1508c2ecf20Sopenharmony_ci memset(&iter->cur_key, 0, sizeof(iter->cur_key)); 1518c2ecf20Sopenharmony_ci} 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci/* 1548c2ecf20Sopenharmony_ci * Backref cache related structures 1558c2ecf20Sopenharmony_ci * 1568c2ecf20Sopenharmony_ci * The whole objective of backref_cache is to build a bi-directional map 1578c2ecf20Sopenharmony_ci * of tree blocks (represented by backref_node) and all their parents. 1588c2ecf20Sopenharmony_ci */ 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci/* 1618c2ecf20Sopenharmony_ci * Represent a tree block in the backref cache 1628c2ecf20Sopenharmony_ci */ 1638c2ecf20Sopenharmony_cistruct btrfs_backref_node { 1648c2ecf20Sopenharmony_ci struct { 1658c2ecf20Sopenharmony_ci struct rb_node rb_node; 1668c2ecf20Sopenharmony_ci u64 bytenr; 1678c2ecf20Sopenharmony_ci }; /* Use rb_simple_node for search/insert */ 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci u64 new_bytenr; 1708c2ecf20Sopenharmony_ci /* Objectid of tree block owner, can be not uptodate */ 1718c2ecf20Sopenharmony_ci u64 owner; 1728c2ecf20Sopenharmony_ci /* Link to pending, changed or detached list */ 1738c2ecf20Sopenharmony_ci struct list_head list; 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci /* List of upper level edges, which link this node to its parents */ 1768c2ecf20Sopenharmony_ci struct list_head upper; 1778c2ecf20Sopenharmony_ci /* List of lower level edges, which link this node to its children */ 1788c2ecf20Sopenharmony_ci struct list_head lower; 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci /* NULL if this node is not tree root */ 1818c2ecf20Sopenharmony_ci struct btrfs_root *root; 1828c2ecf20Sopenharmony_ci /* Extent buffer got by COWing the block */ 1838c2ecf20Sopenharmony_ci struct extent_buffer *eb; 1848c2ecf20Sopenharmony_ci /* Level of the tree block */ 1858c2ecf20Sopenharmony_ci unsigned int level:8; 1868c2ecf20Sopenharmony_ci /* Is the block in a non-shareable tree */ 1878c2ecf20Sopenharmony_ci unsigned int cowonly:1; 1888c2ecf20Sopenharmony_ci /* 1 if no child node is in the cache */ 1898c2ecf20Sopenharmony_ci unsigned int lowest:1; 1908c2ecf20Sopenharmony_ci /* Is the extent buffer locked */ 1918c2ecf20Sopenharmony_ci unsigned int locked:1; 1928c2ecf20Sopenharmony_ci /* Has the block been processed */ 1938c2ecf20Sopenharmony_ci unsigned int processed:1; 1948c2ecf20Sopenharmony_ci /* Have backrefs of this block been checked */ 1958c2ecf20Sopenharmony_ci unsigned int checked:1; 1968c2ecf20Sopenharmony_ci /* 1978c2ecf20Sopenharmony_ci * 1 if corresponding block has been COWed but some upper level block 1988c2ecf20Sopenharmony_ci * pointers may not point to the new location 1998c2ecf20Sopenharmony_ci */ 2008c2ecf20Sopenharmony_ci unsigned int pending:1; 2018c2ecf20Sopenharmony_ci /* 1 if the backref node isn't connected to any other backref node */ 2028c2ecf20Sopenharmony_ci unsigned int detached:1; 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci /* 2058c2ecf20Sopenharmony_ci * For generic purpose backref cache, where we only care if it's a reloc 2068c2ecf20Sopenharmony_ci * root, doesn't care the source subvolid. 2078c2ecf20Sopenharmony_ci */ 2088c2ecf20Sopenharmony_ci unsigned int is_reloc_root:1; 2098c2ecf20Sopenharmony_ci}; 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci#define LOWER 0 2128c2ecf20Sopenharmony_ci#define UPPER 1 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci/* 2158c2ecf20Sopenharmony_ci * Represent an edge connecting upper and lower backref nodes. 2168c2ecf20Sopenharmony_ci */ 2178c2ecf20Sopenharmony_cistruct btrfs_backref_edge { 2188c2ecf20Sopenharmony_ci /* 2198c2ecf20Sopenharmony_ci * list[LOWER] is linked to btrfs_backref_node::upper of lower level 2208c2ecf20Sopenharmony_ci * node, and list[UPPER] is linked to btrfs_backref_node::lower of 2218c2ecf20Sopenharmony_ci * upper level node. 2228c2ecf20Sopenharmony_ci * 2238c2ecf20Sopenharmony_ci * Also, build_backref_tree() uses list[UPPER] for pending edges, before 2248c2ecf20Sopenharmony_ci * linking list[UPPER] to its upper level nodes. 2258c2ecf20Sopenharmony_ci */ 2268c2ecf20Sopenharmony_ci struct list_head list[2]; 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci /* Two related nodes */ 2298c2ecf20Sopenharmony_ci struct btrfs_backref_node *node[2]; 2308c2ecf20Sopenharmony_ci}; 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_cistruct btrfs_backref_cache { 2338c2ecf20Sopenharmony_ci /* Red black tree of all backref nodes in the cache */ 2348c2ecf20Sopenharmony_ci struct rb_root rb_root; 2358c2ecf20Sopenharmony_ci /* For passing backref nodes to btrfs_reloc_cow_block */ 2368c2ecf20Sopenharmony_ci struct btrfs_backref_node *path[BTRFS_MAX_LEVEL]; 2378c2ecf20Sopenharmony_ci /* 2388c2ecf20Sopenharmony_ci * List of blocks that have been COWed but some block pointers in upper 2398c2ecf20Sopenharmony_ci * level blocks may not reflect the new location 2408c2ecf20Sopenharmony_ci */ 2418c2ecf20Sopenharmony_ci struct list_head pending[BTRFS_MAX_LEVEL]; 2428c2ecf20Sopenharmony_ci /* List of backref nodes with no child node */ 2438c2ecf20Sopenharmony_ci struct list_head leaves; 2448c2ecf20Sopenharmony_ci /* List of blocks that have been COWed in current transaction */ 2458c2ecf20Sopenharmony_ci struct list_head changed; 2468c2ecf20Sopenharmony_ci /* List of detached backref node. */ 2478c2ecf20Sopenharmony_ci struct list_head detached; 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci u64 last_trans; 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci int nr_nodes; 2528c2ecf20Sopenharmony_ci int nr_edges; 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_ci /* List of unchecked backref edges during backref cache build */ 2558c2ecf20Sopenharmony_ci struct list_head pending_edge; 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci /* List of useless backref nodes during backref cache build */ 2588c2ecf20Sopenharmony_ci struct list_head useless_node; 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info; 2618c2ecf20Sopenharmony_ci 2628c2ecf20Sopenharmony_ci /* 2638c2ecf20Sopenharmony_ci * Whether this cache is for relocation 2648c2ecf20Sopenharmony_ci * 2658c2ecf20Sopenharmony_ci * Reloction backref cache require more info for reloc root compared 2668c2ecf20Sopenharmony_ci * to generic backref cache. 2678c2ecf20Sopenharmony_ci */ 2688c2ecf20Sopenharmony_ci unsigned int is_reloc; 2698c2ecf20Sopenharmony_ci}; 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_civoid btrfs_backref_init_cache(struct btrfs_fs_info *fs_info, 2728c2ecf20Sopenharmony_ci struct btrfs_backref_cache *cache, int is_reloc); 2738c2ecf20Sopenharmony_cistruct btrfs_backref_node *btrfs_backref_alloc_node( 2748c2ecf20Sopenharmony_ci struct btrfs_backref_cache *cache, u64 bytenr, int level); 2758c2ecf20Sopenharmony_cistruct btrfs_backref_edge *btrfs_backref_alloc_edge( 2768c2ecf20Sopenharmony_ci struct btrfs_backref_cache *cache); 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_ci#define LINK_LOWER (1 << 0) 2798c2ecf20Sopenharmony_ci#define LINK_UPPER (1 << 1) 2808c2ecf20Sopenharmony_cistatic inline void btrfs_backref_link_edge(struct btrfs_backref_edge *edge, 2818c2ecf20Sopenharmony_ci struct btrfs_backref_node *lower, 2828c2ecf20Sopenharmony_ci struct btrfs_backref_node *upper, 2838c2ecf20Sopenharmony_ci int link_which) 2848c2ecf20Sopenharmony_ci{ 2858c2ecf20Sopenharmony_ci ASSERT(upper && lower && upper->level == lower->level + 1); 2868c2ecf20Sopenharmony_ci edge->node[LOWER] = lower; 2878c2ecf20Sopenharmony_ci edge->node[UPPER] = upper; 2888c2ecf20Sopenharmony_ci if (link_which & LINK_LOWER) 2898c2ecf20Sopenharmony_ci list_add_tail(&edge->list[LOWER], &lower->upper); 2908c2ecf20Sopenharmony_ci if (link_which & LINK_UPPER) 2918c2ecf20Sopenharmony_ci list_add_tail(&edge->list[UPPER], &upper->lower); 2928c2ecf20Sopenharmony_ci} 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_cistatic inline void btrfs_backref_free_node(struct btrfs_backref_cache *cache, 2958c2ecf20Sopenharmony_ci struct btrfs_backref_node *node) 2968c2ecf20Sopenharmony_ci{ 2978c2ecf20Sopenharmony_ci if (node) { 2988c2ecf20Sopenharmony_ci ASSERT(list_empty(&node->list)); 2998c2ecf20Sopenharmony_ci ASSERT(list_empty(&node->lower)); 3008c2ecf20Sopenharmony_ci ASSERT(node->eb == NULL); 3018c2ecf20Sopenharmony_ci cache->nr_nodes--; 3028c2ecf20Sopenharmony_ci btrfs_put_root(node->root); 3038c2ecf20Sopenharmony_ci kfree(node); 3048c2ecf20Sopenharmony_ci } 3058c2ecf20Sopenharmony_ci} 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_cistatic inline void btrfs_backref_free_edge(struct btrfs_backref_cache *cache, 3088c2ecf20Sopenharmony_ci struct btrfs_backref_edge *edge) 3098c2ecf20Sopenharmony_ci{ 3108c2ecf20Sopenharmony_ci if (edge) { 3118c2ecf20Sopenharmony_ci cache->nr_edges--; 3128c2ecf20Sopenharmony_ci kfree(edge); 3138c2ecf20Sopenharmony_ci } 3148c2ecf20Sopenharmony_ci} 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_cistatic inline void btrfs_backref_unlock_node_buffer( 3178c2ecf20Sopenharmony_ci struct btrfs_backref_node *node) 3188c2ecf20Sopenharmony_ci{ 3198c2ecf20Sopenharmony_ci if (node->locked) { 3208c2ecf20Sopenharmony_ci btrfs_tree_unlock(node->eb); 3218c2ecf20Sopenharmony_ci node->locked = 0; 3228c2ecf20Sopenharmony_ci } 3238c2ecf20Sopenharmony_ci} 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_cistatic inline void btrfs_backref_drop_node_buffer( 3268c2ecf20Sopenharmony_ci struct btrfs_backref_node *node) 3278c2ecf20Sopenharmony_ci{ 3288c2ecf20Sopenharmony_ci if (node->eb) { 3298c2ecf20Sopenharmony_ci btrfs_backref_unlock_node_buffer(node); 3308c2ecf20Sopenharmony_ci free_extent_buffer(node->eb); 3318c2ecf20Sopenharmony_ci node->eb = NULL; 3328c2ecf20Sopenharmony_ci } 3338c2ecf20Sopenharmony_ci} 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci/* 3368c2ecf20Sopenharmony_ci * Drop the backref node from cache without cleaning up its children 3378c2ecf20Sopenharmony_ci * edges. 3388c2ecf20Sopenharmony_ci * 3398c2ecf20Sopenharmony_ci * This can only be called on node without parent edges. 3408c2ecf20Sopenharmony_ci * The children edges are still kept as is. 3418c2ecf20Sopenharmony_ci */ 3428c2ecf20Sopenharmony_cistatic inline void btrfs_backref_drop_node(struct btrfs_backref_cache *tree, 3438c2ecf20Sopenharmony_ci struct btrfs_backref_node *node) 3448c2ecf20Sopenharmony_ci{ 3458c2ecf20Sopenharmony_ci ASSERT(list_empty(&node->upper)); 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_ci btrfs_backref_drop_node_buffer(node); 3488c2ecf20Sopenharmony_ci list_del_init(&node->list); 3498c2ecf20Sopenharmony_ci list_del_init(&node->lower); 3508c2ecf20Sopenharmony_ci if (!RB_EMPTY_NODE(&node->rb_node)) 3518c2ecf20Sopenharmony_ci rb_erase(&node->rb_node, &tree->rb_root); 3528c2ecf20Sopenharmony_ci btrfs_backref_free_node(tree, node); 3538c2ecf20Sopenharmony_ci} 3548c2ecf20Sopenharmony_ci 3558c2ecf20Sopenharmony_civoid btrfs_backref_cleanup_node(struct btrfs_backref_cache *cache, 3568c2ecf20Sopenharmony_ci struct btrfs_backref_node *node); 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_civoid btrfs_backref_release_cache(struct btrfs_backref_cache *cache); 3598c2ecf20Sopenharmony_ci 3608c2ecf20Sopenharmony_cistatic inline void btrfs_backref_panic(struct btrfs_fs_info *fs_info, 3618c2ecf20Sopenharmony_ci u64 bytenr, int errno) 3628c2ecf20Sopenharmony_ci{ 3638c2ecf20Sopenharmony_ci btrfs_panic(fs_info, errno, 3648c2ecf20Sopenharmony_ci "Inconsistency in backref cache found at offset %llu", 3658c2ecf20Sopenharmony_ci bytenr); 3668c2ecf20Sopenharmony_ci} 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_ciint btrfs_backref_add_tree_node(struct btrfs_backref_cache *cache, 3698c2ecf20Sopenharmony_ci struct btrfs_path *path, 3708c2ecf20Sopenharmony_ci struct btrfs_backref_iter *iter, 3718c2ecf20Sopenharmony_ci struct btrfs_key *node_key, 3728c2ecf20Sopenharmony_ci struct btrfs_backref_node *cur); 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ciint btrfs_backref_finish_upper_links(struct btrfs_backref_cache *cache, 3758c2ecf20Sopenharmony_ci struct btrfs_backref_node *start); 3768c2ecf20Sopenharmony_ci 3778c2ecf20Sopenharmony_civoid btrfs_backref_error_cleanup(struct btrfs_backref_cache *cache, 3788c2ecf20Sopenharmony_ci struct btrfs_backref_node *node); 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ci#endif 381