18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2009 Oracle. All rights reserved. 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#include <linux/sched.h> 78c2ecf20Sopenharmony_ci#include <linux/pagemap.h> 88c2ecf20Sopenharmony_ci#include <linux/writeback.h> 98c2ecf20Sopenharmony_ci#include <linux/blkdev.h> 108c2ecf20Sopenharmony_ci#include <linux/rbtree.h> 118c2ecf20Sopenharmony_ci#include <linux/slab.h> 128c2ecf20Sopenharmony_ci#include <linux/error-injection.h> 138c2ecf20Sopenharmony_ci#include "ctree.h" 148c2ecf20Sopenharmony_ci#include "disk-io.h" 158c2ecf20Sopenharmony_ci#include "transaction.h" 168c2ecf20Sopenharmony_ci#include "volumes.h" 178c2ecf20Sopenharmony_ci#include "locking.h" 188c2ecf20Sopenharmony_ci#include "btrfs_inode.h" 198c2ecf20Sopenharmony_ci#include "async-thread.h" 208c2ecf20Sopenharmony_ci#include "free-space-cache.h" 218c2ecf20Sopenharmony_ci#include "inode-map.h" 228c2ecf20Sopenharmony_ci#include "qgroup.h" 238c2ecf20Sopenharmony_ci#include "print-tree.h" 248c2ecf20Sopenharmony_ci#include "delalloc-space.h" 258c2ecf20Sopenharmony_ci#include "block-group.h" 268c2ecf20Sopenharmony_ci#include "backref.h" 278c2ecf20Sopenharmony_ci#include "misc.h" 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci/* 308c2ecf20Sopenharmony_ci * Relocation overview 318c2ecf20Sopenharmony_ci * 328c2ecf20Sopenharmony_ci * [What does relocation do] 338c2ecf20Sopenharmony_ci * 348c2ecf20Sopenharmony_ci * The objective of relocation is to relocate all extents of the target block 358c2ecf20Sopenharmony_ci * group to other block groups. 368c2ecf20Sopenharmony_ci * This is utilized by resize (shrink only), profile converting, compacting 378c2ecf20Sopenharmony_ci * space, or balance routine to spread chunks over devices. 388c2ecf20Sopenharmony_ci * 398c2ecf20Sopenharmony_ci * Before | After 408c2ecf20Sopenharmony_ci * ------------------------------------------------------------------ 418c2ecf20Sopenharmony_ci * BG A: 10 data extents | BG A: deleted 428c2ecf20Sopenharmony_ci * BG B: 2 data extents | BG B: 10 data extents (2 old + 8 relocated) 438c2ecf20Sopenharmony_ci * BG C: 1 extents | BG C: 3 data extents (1 old + 2 relocated) 448c2ecf20Sopenharmony_ci * 458c2ecf20Sopenharmony_ci * [How does relocation work] 468c2ecf20Sopenharmony_ci * 478c2ecf20Sopenharmony_ci * 1. Mark the target block group read-only 488c2ecf20Sopenharmony_ci * New extents won't be allocated from the target block group. 498c2ecf20Sopenharmony_ci * 508c2ecf20Sopenharmony_ci * 2.1 Record each extent in the target block group 518c2ecf20Sopenharmony_ci * To build a proper map of extents to be relocated. 528c2ecf20Sopenharmony_ci * 538c2ecf20Sopenharmony_ci * 2.2 Build data reloc tree and reloc trees 548c2ecf20Sopenharmony_ci * Data reloc tree will contain an inode, recording all newly relocated 558c2ecf20Sopenharmony_ci * data extents. 568c2ecf20Sopenharmony_ci * There will be only one data reloc tree for one data block group. 578c2ecf20Sopenharmony_ci * 588c2ecf20Sopenharmony_ci * Reloc tree will be a special snapshot of its source tree, containing 598c2ecf20Sopenharmony_ci * relocated tree blocks. 608c2ecf20Sopenharmony_ci * Each tree referring to a tree block in target block group will get its 618c2ecf20Sopenharmony_ci * reloc tree built. 628c2ecf20Sopenharmony_ci * 638c2ecf20Sopenharmony_ci * 2.3 Swap source tree with its corresponding reloc tree 648c2ecf20Sopenharmony_ci * Each involved tree only refers to new extents after swap. 658c2ecf20Sopenharmony_ci * 668c2ecf20Sopenharmony_ci * 3. Cleanup reloc trees and data reloc tree. 678c2ecf20Sopenharmony_ci * As old extents in the target block group are still referenced by reloc 688c2ecf20Sopenharmony_ci * trees, we need to clean them up before really freeing the target block 698c2ecf20Sopenharmony_ci * group. 708c2ecf20Sopenharmony_ci * 718c2ecf20Sopenharmony_ci * The main complexity is in steps 2.2 and 2.3. 728c2ecf20Sopenharmony_ci * 738c2ecf20Sopenharmony_ci * The entry point of relocation is relocate_block_group() function. 748c2ecf20Sopenharmony_ci */ 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci#define RELOCATION_RESERVED_NODES 256 778c2ecf20Sopenharmony_ci/* 788c2ecf20Sopenharmony_ci * map address of tree root to tree 798c2ecf20Sopenharmony_ci */ 808c2ecf20Sopenharmony_cistruct mapping_node { 818c2ecf20Sopenharmony_ci struct { 828c2ecf20Sopenharmony_ci struct rb_node rb_node; 838c2ecf20Sopenharmony_ci u64 bytenr; 848c2ecf20Sopenharmony_ci }; /* Use rb_simle_node for search/insert */ 858c2ecf20Sopenharmony_ci void *data; 868c2ecf20Sopenharmony_ci}; 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_cistruct mapping_tree { 898c2ecf20Sopenharmony_ci struct rb_root rb_root; 908c2ecf20Sopenharmony_ci spinlock_t lock; 918c2ecf20Sopenharmony_ci}; 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci/* 948c2ecf20Sopenharmony_ci * present a tree block to process 958c2ecf20Sopenharmony_ci */ 968c2ecf20Sopenharmony_cistruct tree_block { 978c2ecf20Sopenharmony_ci struct { 988c2ecf20Sopenharmony_ci struct rb_node rb_node; 998c2ecf20Sopenharmony_ci u64 bytenr; 1008c2ecf20Sopenharmony_ci }; /* Use rb_simple_node for search/insert */ 1018c2ecf20Sopenharmony_ci struct btrfs_key key; 1028c2ecf20Sopenharmony_ci unsigned int level:8; 1038c2ecf20Sopenharmony_ci unsigned int key_ready:1; 1048c2ecf20Sopenharmony_ci}; 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci#define MAX_EXTENTS 128 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_cistruct file_extent_cluster { 1098c2ecf20Sopenharmony_ci u64 start; 1108c2ecf20Sopenharmony_ci u64 end; 1118c2ecf20Sopenharmony_ci u64 boundary[MAX_EXTENTS]; 1128c2ecf20Sopenharmony_ci unsigned int nr; 1138c2ecf20Sopenharmony_ci}; 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_cistruct reloc_control { 1168c2ecf20Sopenharmony_ci /* block group to relocate */ 1178c2ecf20Sopenharmony_ci struct btrfs_block_group *block_group; 1188c2ecf20Sopenharmony_ci /* extent tree */ 1198c2ecf20Sopenharmony_ci struct btrfs_root *extent_root; 1208c2ecf20Sopenharmony_ci /* inode for moving data */ 1218c2ecf20Sopenharmony_ci struct inode *data_inode; 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci struct btrfs_block_rsv *block_rsv; 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci struct btrfs_backref_cache backref_cache; 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci struct file_extent_cluster cluster; 1288c2ecf20Sopenharmony_ci /* tree blocks have been processed */ 1298c2ecf20Sopenharmony_ci struct extent_io_tree processed_blocks; 1308c2ecf20Sopenharmony_ci /* map start of tree root to corresponding reloc tree */ 1318c2ecf20Sopenharmony_ci struct mapping_tree reloc_root_tree; 1328c2ecf20Sopenharmony_ci /* list of reloc trees */ 1338c2ecf20Sopenharmony_ci struct list_head reloc_roots; 1348c2ecf20Sopenharmony_ci /* list of subvolume trees that get relocated */ 1358c2ecf20Sopenharmony_ci struct list_head dirty_subvol_roots; 1368c2ecf20Sopenharmony_ci /* size of metadata reservation for merging reloc trees */ 1378c2ecf20Sopenharmony_ci u64 merging_rsv_size; 1388c2ecf20Sopenharmony_ci /* size of relocated tree nodes */ 1398c2ecf20Sopenharmony_ci u64 nodes_relocated; 1408c2ecf20Sopenharmony_ci /* reserved size for block group relocation*/ 1418c2ecf20Sopenharmony_ci u64 reserved_bytes; 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci u64 search_start; 1448c2ecf20Sopenharmony_ci u64 extents_found; 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci unsigned int stage:8; 1478c2ecf20Sopenharmony_ci unsigned int create_reloc_tree:1; 1488c2ecf20Sopenharmony_ci unsigned int merge_reloc_tree:1; 1498c2ecf20Sopenharmony_ci unsigned int found_file_extent:1; 1508c2ecf20Sopenharmony_ci}; 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ci/* stages of data relocation */ 1538c2ecf20Sopenharmony_ci#define MOVE_DATA_EXTENTS 0 1548c2ecf20Sopenharmony_ci#define UPDATE_DATA_PTRS 1 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_cistatic void mark_block_processed(struct reloc_control *rc, 1578c2ecf20Sopenharmony_ci struct btrfs_backref_node *node) 1588c2ecf20Sopenharmony_ci{ 1598c2ecf20Sopenharmony_ci u32 blocksize; 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci if (node->level == 0 || 1628c2ecf20Sopenharmony_ci in_range(node->bytenr, rc->block_group->start, 1638c2ecf20Sopenharmony_ci rc->block_group->length)) { 1648c2ecf20Sopenharmony_ci blocksize = rc->extent_root->fs_info->nodesize; 1658c2ecf20Sopenharmony_ci set_extent_bits(&rc->processed_blocks, node->bytenr, 1668c2ecf20Sopenharmony_ci node->bytenr + blocksize - 1, EXTENT_DIRTY); 1678c2ecf20Sopenharmony_ci } 1688c2ecf20Sopenharmony_ci node->processed = 1; 1698c2ecf20Sopenharmony_ci} 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_cistatic void mapping_tree_init(struct mapping_tree *tree) 1738c2ecf20Sopenharmony_ci{ 1748c2ecf20Sopenharmony_ci tree->rb_root = RB_ROOT; 1758c2ecf20Sopenharmony_ci spin_lock_init(&tree->lock); 1768c2ecf20Sopenharmony_ci} 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci/* 1798c2ecf20Sopenharmony_ci * walk up backref nodes until reach node presents tree root 1808c2ecf20Sopenharmony_ci */ 1818c2ecf20Sopenharmony_cistatic struct btrfs_backref_node *walk_up_backref( 1828c2ecf20Sopenharmony_ci struct btrfs_backref_node *node, 1838c2ecf20Sopenharmony_ci struct btrfs_backref_edge *edges[], int *index) 1848c2ecf20Sopenharmony_ci{ 1858c2ecf20Sopenharmony_ci struct btrfs_backref_edge *edge; 1868c2ecf20Sopenharmony_ci int idx = *index; 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci while (!list_empty(&node->upper)) { 1898c2ecf20Sopenharmony_ci edge = list_entry(node->upper.next, 1908c2ecf20Sopenharmony_ci struct btrfs_backref_edge, list[LOWER]); 1918c2ecf20Sopenharmony_ci edges[idx++] = edge; 1928c2ecf20Sopenharmony_ci node = edge->node[UPPER]; 1938c2ecf20Sopenharmony_ci } 1948c2ecf20Sopenharmony_ci BUG_ON(node->detached); 1958c2ecf20Sopenharmony_ci *index = idx; 1968c2ecf20Sopenharmony_ci return node; 1978c2ecf20Sopenharmony_ci} 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_ci/* 2008c2ecf20Sopenharmony_ci * walk down backref nodes to find start of next reference path 2018c2ecf20Sopenharmony_ci */ 2028c2ecf20Sopenharmony_cistatic struct btrfs_backref_node *walk_down_backref( 2038c2ecf20Sopenharmony_ci struct btrfs_backref_edge *edges[], int *index) 2048c2ecf20Sopenharmony_ci{ 2058c2ecf20Sopenharmony_ci struct btrfs_backref_edge *edge; 2068c2ecf20Sopenharmony_ci struct btrfs_backref_node *lower; 2078c2ecf20Sopenharmony_ci int idx = *index; 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ci while (idx > 0) { 2108c2ecf20Sopenharmony_ci edge = edges[idx - 1]; 2118c2ecf20Sopenharmony_ci lower = edge->node[LOWER]; 2128c2ecf20Sopenharmony_ci if (list_is_last(&edge->list[LOWER], &lower->upper)) { 2138c2ecf20Sopenharmony_ci idx--; 2148c2ecf20Sopenharmony_ci continue; 2158c2ecf20Sopenharmony_ci } 2168c2ecf20Sopenharmony_ci edge = list_entry(edge->list[LOWER].next, 2178c2ecf20Sopenharmony_ci struct btrfs_backref_edge, list[LOWER]); 2188c2ecf20Sopenharmony_ci edges[idx - 1] = edge; 2198c2ecf20Sopenharmony_ci *index = idx; 2208c2ecf20Sopenharmony_ci return edge->node[UPPER]; 2218c2ecf20Sopenharmony_ci } 2228c2ecf20Sopenharmony_ci *index = 0; 2238c2ecf20Sopenharmony_ci return NULL; 2248c2ecf20Sopenharmony_ci} 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_cistatic void update_backref_node(struct btrfs_backref_cache *cache, 2278c2ecf20Sopenharmony_ci struct btrfs_backref_node *node, u64 bytenr) 2288c2ecf20Sopenharmony_ci{ 2298c2ecf20Sopenharmony_ci struct rb_node *rb_node; 2308c2ecf20Sopenharmony_ci rb_erase(&node->rb_node, &cache->rb_root); 2318c2ecf20Sopenharmony_ci node->bytenr = bytenr; 2328c2ecf20Sopenharmony_ci rb_node = rb_simple_insert(&cache->rb_root, node->bytenr, &node->rb_node); 2338c2ecf20Sopenharmony_ci if (rb_node) 2348c2ecf20Sopenharmony_ci btrfs_backref_panic(cache->fs_info, bytenr, -EEXIST); 2358c2ecf20Sopenharmony_ci} 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci/* 2388c2ecf20Sopenharmony_ci * update backref cache after a transaction commit 2398c2ecf20Sopenharmony_ci */ 2408c2ecf20Sopenharmony_cistatic int update_backref_cache(struct btrfs_trans_handle *trans, 2418c2ecf20Sopenharmony_ci struct btrfs_backref_cache *cache) 2428c2ecf20Sopenharmony_ci{ 2438c2ecf20Sopenharmony_ci struct btrfs_backref_node *node; 2448c2ecf20Sopenharmony_ci int level = 0; 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ci if (cache->last_trans == 0) { 2478c2ecf20Sopenharmony_ci cache->last_trans = trans->transid; 2488c2ecf20Sopenharmony_ci return 0; 2498c2ecf20Sopenharmony_ci } 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci if (cache->last_trans == trans->transid) 2528c2ecf20Sopenharmony_ci return 0; 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_ci /* 2558c2ecf20Sopenharmony_ci * detached nodes are used to avoid unnecessary backref 2568c2ecf20Sopenharmony_ci * lookup. transaction commit changes the extent tree. 2578c2ecf20Sopenharmony_ci * so the detached nodes are no longer useful. 2588c2ecf20Sopenharmony_ci */ 2598c2ecf20Sopenharmony_ci while (!list_empty(&cache->detached)) { 2608c2ecf20Sopenharmony_ci node = list_entry(cache->detached.next, 2618c2ecf20Sopenharmony_ci struct btrfs_backref_node, list); 2628c2ecf20Sopenharmony_ci btrfs_backref_cleanup_node(cache, node); 2638c2ecf20Sopenharmony_ci } 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_ci while (!list_empty(&cache->changed)) { 2668c2ecf20Sopenharmony_ci node = list_entry(cache->changed.next, 2678c2ecf20Sopenharmony_ci struct btrfs_backref_node, list); 2688c2ecf20Sopenharmony_ci list_del_init(&node->list); 2698c2ecf20Sopenharmony_ci BUG_ON(node->pending); 2708c2ecf20Sopenharmony_ci update_backref_node(cache, node, node->new_bytenr); 2718c2ecf20Sopenharmony_ci } 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci /* 2748c2ecf20Sopenharmony_ci * some nodes can be left in the pending list if there were 2758c2ecf20Sopenharmony_ci * errors during processing the pending nodes. 2768c2ecf20Sopenharmony_ci */ 2778c2ecf20Sopenharmony_ci for (level = 0; level < BTRFS_MAX_LEVEL; level++) { 2788c2ecf20Sopenharmony_ci list_for_each_entry(node, &cache->pending[level], list) { 2798c2ecf20Sopenharmony_ci BUG_ON(!node->pending); 2808c2ecf20Sopenharmony_ci if (node->bytenr == node->new_bytenr) 2818c2ecf20Sopenharmony_ci continue; 2828c2ecf20Sopenharmony_ci update_backref_node(cache, node, node->new_bytenr); 2838c2ecf20Sopenharmony_ci } 2848c2ecf20Sopenharmony_ci } 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ci cache->last_trans = 0; 2878c2ecf20Sopenharmony_ci return 1; 2888c2ecf20Sopenharmony_ci} 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_cistatic bool reloc_root_is_dead(struct btrfs_root *root) 2918c2ecf20Sopenharmony_ci{ 2928c2ecf20Sopenharmony_ci /* 2938c2ecf20Sopenharmony_ci * Pair with set_bit/clear_bit in clean_dirty_subvols and 2948c2ecf20Sopenharmony_ci * btrfs_update_reloc_root. We need to see the updated bit before 2958c2ecf20Sopenharmony_ci * trying to access reloc_root 2968c2ecf20Sopenharmony_ci */ 2978c2ecf20Sopenharmony_ci smp_rmb(); 2988c2ecf20Sopenharmony_ci if (test_bit(BTRFS_ROOT_DEAD_RELOC_TREE, &root->state)) 2998c2ecf20Sopenharmony_ci return true; 3008c2ecf20Sopenharmony_ci return false; 3018c2ecf20Sopenharmony_ci} 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_ci/* 3048c2ecf20Sopenharmony_ci * Check if this subvolume tree has valid reloc tree. 3058c2ecf20Sopenharmony_ci * 3068c2ecf20Sopenharmony_ci * Reloc tree after swap is considered dead, thus not considered as valid. 3078c2ecf20Sopenharmony_ci * This is enough for most callers, as they don't distinguish dead reloc root 3088c2ecf20Sopenharmony_ci * from no reloc root. But btrfs_should_ignore_reloc_root() below is a 3098c2ecf20Sopenharmony_ci * special case. 3108c2ecf20Sopenharmony_ci */ 3118c2ecf20Sopenharmony_cistatic bool have_reloc_root(struct btrfs_root *root) 3128c2ecf20Sopenharmony_ci{ 3138c2ecf20Sopenharmony_ci if (reloc_root_is_dead(root)) 3148c2ecf20Sopenharmony_ci return false; 3158c2ecf20Sopenharmony_ci if (!root->reloc_root) 3168c2ecf20Sopenharmony_ci return false; 3178c2ecf20Sopenharmony_ci return true; 3188c2ecf20Sopenharmony_ci} 3198c2ecf20Sopenharmony_ci 3208c2ecf20Sopenharmony_ciint btrfs_should_ignore_reloc_root(struct btrfs_root *root) 3218c2ecf20Sopenharmony_ci{ 3228c2ecf20Sopenharmony_ci struct btrfs_root *reloc_root; 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_ci if (!test_bit(BTRFS_ROOT_SHAREABLE, &root->state)) 3258c2ecf20Sopenharmony_ci return 0; 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci /* This root has been merged with its reloc tree, we can ignore it */ 3288c2ecf20Sopenharmony_ci if (reloc_root_is_dead(root)) 3298c2ecf20Sopenharmony_ci return 1; 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_ci reloc_root = root->reloc_root; 3328c2ecf20Sopenharmony_ci if (!reloc_root) 3338c2ecf20Sopenharmony_ci return 0; 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci if (btrfs_header_generation(reloc_root->commit_root) == 3368c2ecf20Sopenharmony_ci root->fs_info->running_transaction->transid) 3378c2ecf20Sopenharmony_ci return 0; 3388c2ecf20Sopenharmony_ci /* 3398c2ecf20Sopenharmony_ci * if there is reloc tree and it was created in previous 3408c2ecf20Sopenharmony_ci * transaction backref lookup can find the reloc tree, 3418c2ecf20Sopenharmony_ci * so backref node for the fs tree root is useless for 3428c2ecf20Sopenharmony_ci * relocation. 3438c2ecf20Sopenharmony_ci */ 3448c2ecf20Sopenharmony_ci return 1; 3458c2ecf20Sopenharmony_ci} 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_ci/* 3488c2ecf20Sopenharmony_ci * find reloc tree by address of tree root 3498c2ecf20Sopenharmony_ci */ 3508c2ecf20Sopenharmony_cistruct btrfs_root *find_reloc_root(struct btrfs_fs_info *fs_info, u64 bytenr) 3518c2ecf20Sopenharmony_ci{ 3528c2ecf20Sopenharmony_ci struct reloc_control *rc = fs_info->reloc_ctl; 3538c2ecf20Sopenharmony_ci struct rb_node *rb_node; 3548c2ecf20Sopenharmony_ci struct mapping_node *node; 3558c2ecf20Sopenharmony_ci struct btrfs_root *root = NULL; 3568c2ecf20Sopenharmony_ci 3578c2ecf20Sopenharmony_ci ASSERT(rc); 3588c2ecf20Sopenharmony_ci spin_lock(&rc->reloc_root_tree.lock); 3598c2ecf20Sopenharmony_ci rb_node = rb_simple_search(&rc->reloc_root_tree.rb_root, bytenr); 3608c2ecf20Sopenharmony_ci if (rb_node) { 3618c2ecf20Sopenharmony_ci node = rb_entry(rb_node, struct mapping_node, rb_node); 3628c2ecf20Sopenharmony_ci root = (struct btrfs_root *)node->data; 3638c2ecf20Sopenharmony_ci } 3648c2ecf20Sopenharmony_ci spin_unlock(&rc->reloc_root_tree.lock); 3658c2ecf20Sopenharmony_ci return btrfs_grab_root(root); 3668c2ecf20Sopenharmony_ci} 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_ci/* 3698c2ecf20Sopenharmony_ci * For useless nodes, do two major clean ups: 3708c2ecf20Sopenharmony_ci * 3718c2ecf20Sopenharmony_ci * - Cleanup the children edges and nodes 3728c2ecf20Sopenharmony_ci * If child node is also orphan (no parent) during cleanup, then the child 3738c2ecf20Sopenharmony_ci * node will also be cleaned up. 3748c2ecf20Sopenharmony_ci * 3758c2ecf20Sopenharmony_ci * - Freeing up leaves (level 0), keeps nodes detached 3768c2ecf20Sopenharmony_ci * For nodes, the node is still cached as "detached" 3778c2ecf20Sopenharmony_ci * 3788c2ecf20Sopenharmony_ci * Return false if @node is not in the @useless_nodes list. 3798c2ecf20Sopenharmony_ci * Return true if @node is in the @useless_nodes list. 3808c2ecf20Sopenharmony_ci */ 3818c2ecf20Sopenharmony_cistatic bool handle_useless_nodes(struct reloc_control *rc, 3828c2ecf20Sopenharmony_ci struct btrfs_backref_node *node) 3838c2ecf20Sopenharmony_ci{ 3848c2ecf20Sopenharmony_ci struct btrfs_backref_cache *cache = &rc->backref_cache; 3858c2ecf20Sopenharmony_ci struct list_head *useless_node = &cache->useless_node; 3868c2ecf20Sopenharmony_ci bool ret = false; 3878c2ecf20Sopenharmony_ci 3888c2ecf20Sopenharmony_ci while (!list_empty(useless_node)) { 3898c2ecf20Sopenharmony_ci struct btrfs_backref_node *cur; 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_ci cur = list_first_entry(useless_node, struct btrfs_backref_node, 3928c2ecf20Sopenharmony_ci list); 3938c2ecf20Sopenharmony_ci list_del_init(&cur->list); 3948c2ecf20Sopenharmony_ci 3958c2ecf20Sopenharmony_ci /* Only tree root nodes can be added to @useless_nodes */ 3968c2ecf20Sopenharmony_ci ASSERT(list_empty(&cur->upper)); 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_ci if (cur == node) 3998c2ecf20Sopenharmony_ci ret = true; 4008c2ecf20Sopenharmony_ci 4018c2ecf20Sopenharmony_ci /* The node is the lowest node */ 4028c2ecf20Sopenharmony_ci if (cur->lowest) { 4038c2ecf20Sopenharmony_ci list_del_init(&cur->lower); 4048c2ecf20Sopenharmony_ci cur->lowest = 0; 4058c2ecf20Sopenharmony_ci } 4068c2ecf20Sopenharmony_ci 4078c2ecf20Sopenharmony_ci /* Cleanup the lower edges */ 4088c2ecf20Sopenharmony_ci while (!list_empty(&cur->lower)) { 4098c2ecf20Sopenharmony_ci struct btrfs_backref_edge *edge; 4108c2ecf20Sopenharmony_ci struct btrfs_backref_node *lower; 4118c2ecf20Sopenharmony_ci 4128c2ecf20Sopenharmony_ci edge = list_entry(cur->lower.next, 4138c2ecf20Sopenharmony_ci struct btrfs_backref_edge, list[UPPER]); 4148c2ecf20Sopenharmony_ci list_del(&edge->list[UPPER]); 4158c2ecf20Sopenharmony_ci list_del(&edge->list[LOWER]); 4168c2ecf20Sopenharmony_ci lower = edge->node[LOWER]; 4178c2ecf20Sopenharmony_ci btrfs_backref_free_edge(cache, edge); 4188c2ecf20Sopenharmony_ci 4198c2ecf20Sopenharmony_ci /* Child node is also orphan, queue for cleanup */ 4208c2ecf20Sopenharmony_ci if (list_empty(&lower->upper)) 4218c2ecf20Sopenharmony_ci list_add(&lower->list, useless_node); 4228c2ecf20Sopenharmony_ci } 4238c2ecf20Sopenharmony_ci /* Mark this block processed for relocation */ 4248c2ecf20Sopenharmony_ci mark_block_processed(rc, cur); 4258c2ecf20Sopenharmony_ci 4268c2ecf20Sopenharmony_ci /* 4278c2ecf20Sopenharmony_ci * Backref nodes for tree leaves are deleted from the cache. 4288c2ecf20Sopenharmony_ci * Backref nodes for upper level tree blocks are left in the 4298c2ecf20Sopenharmony_ci * cache to avoid unnecessary backref lookup. 4308c2ecf20Sopenharmony_ci */ 4318c2ecf20Sopenharmony_ci if (cur->level > 0) { 4328c2ecf20Sopenharmony_ci list_add(&cur->list, &cache->detached); 4338c2ecf20Sopenharmony_ci cur->detached = 1; 4348c2ecf20Sopenharmony_ci } else { 4358c2ecf20Sopenharmony_ci rb_erase(&cur->rb_node, &cache->rb_root); 4368c2ecf20Sopenharmony_ci btrfs_backref_free_node(cache, cur); 4378c2ecf20Sopenharmony_ci } 4388c2ecf20Sopenharmony_ci } 4398c2ecf20Sopenharmony_ci return ret; 4408c2ecf20Sopenharmony_ci} 4418c2ecf20Sopenharmony_ci 4428c2ecf20Sopenharmony_ci/* 4438c2ecf20Sopenharmony_ci * Build backref tree for a given tree block. Root of the backref tree 4448c2ecf20Sopenharmony_ci * corresponds the tree block, leaves of the backref tree correspond roots of 4458c2ecf20Sopenharmony_ci * b-trees that reference the tree block. 4468c2ecf20Sopenharmony_ci * 4478c2ecf20Sopenharmony_ci * The basic idea of this function is check backrefs of a given block to find 4488c2ecf20Sopenharmony_ci * upper level blocks that reference the block, and then check backrefs of 4498c2ecf20Sopenharmony_ci * these upper level blocks recursively. The recursion stops when tree root is 4508c2ecf20Sopenharmony_ci * reached or backrefs for the block is cached. 4518c2ecf20Sopenharmony_ci * 4528c2ecf20Sopenharmony_ci * NOTE: if we find that backrefs for a block are cached, we know backrefs for 4538c2ecf20Sopenharmony_ci * all upper level blocks that directly/indirectly reference the block are also 4548c2ecf20Sopenharmony_ci * cached. 4558c2ecf20Sopenharmony_ci */ 4568c2ecf20Sopenharmony_cistatic noinline_for_stack struct btrfs_backref_node *build_backref_tree( 4578c2ecf20Sopenharmony_ci struct reloc_control *rc, struct btrfs_key *node_key, 4588c2ecf20Sopenharmony_ci int level, u64 bytenr) 4598c2ecf20Sopenharmony_ci{ 4608c2ecf20Sopenharmony_ci struct btrfs_backref_iter *iter; 4618c2ecf20Sopenharmony_ci struct btrfs_backref_cache *cache = &rc->backref_cache; 4628c2ecf20Sopenharmony_ci /* For searching parent of TREE_BLOCK_REF */ 4638c2ecf20Sopenharmony_ci struct btrfs_path *path; 4648c2ecf20Sopenharmony_ci struct btrfs_backref_node *cur; 4658c2ecf20Sopenharmony_ci struct btrfs_backref_node *node = NULL; 4668c2ecf20Sopenharmony_ci struct btrfs_backref_edge *edge; 4678c2ecf20Sopenharmony_ci int ret; 4688c2ecf20Sopenharmony_ci int err = 0; 4698c2ecf20Sopenharmony_ci 4708c2ecf20Sopenharmony_ci iter = btrfs_backref_iter_alloc(rc->extent_root->fs_info, GFP_NOFS); 4718c2ecf20Sopenharmony_ci if (!iter) 4728c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 4738c2ecf20Sopenharmony_ci path = btrfs_alloc_path(); 4748c2ecf20Sopenharmony_ci if (!path) { 4758c2ecf20Sopenharmony_ci err = -ENOMEM; 4768c2ecf20Sopenharmony_ci goto out; 4778c2ecf20Sopenharmony_ci } 4788c2ecf20Sopenharmony_ci 4798c2ecf20Sopenharmony_ci node = btrfs_backref_alloc_node(cache, bytenr, level); 4808c2ecf20Sopenharmony_ci if (!node) { 4818c2ecf20Sopenharmony_ci err = -ENOMEM; 4828c2ecf20Sopenharmony_ci goto out; 4838c2ecf20Sopenharmony_ci } 4848c2ecf20Sopenharmony_ci 4858c2ecf20Sopenharmony_ci node->lowest = 1; 4868c2ecf20Sopenharmony_ci cur = node; 4878c2ecf20Sopenharmony_ci 4888c2ecf20Sopenharmony_ci /* Breadth-first search to build backref cache */ 4898c2ecf20Sopenharmony_ci do { 4908c2ecf20Sopenharmony_ci ret = btrfs_backref_add_tree_node(cache, path, iter, node_key, 4918c2ecf20Sopenharmony_ci cur); 4928c2ecf20Sopenharmony_ci if (ret < 0) { 4938c2ecf20Sopenharmony_ci err = ret; 4948c2ecf20Sopenharmony_ci goto out; 4958c2ecf20Sopenharmony_ci } 4968c2ecf20Sopenharmony_ci edge = list_first_entry_or_null(&cache->pending_edge, 4978c2ecf20Sopenharmony_ci struct btrfs_backref_edge, list[UPPER]); 4988c2ecf20Sopenharmony_ci /* 4998c2ecf20Sopenharmony_ci * The pending list isn't empty, take the first block to 5008c2ecf20Sopenharmony_ci * process 5018c2ecf20Sopenharmony_ci */ 5028c2ecf20Sopenharmony_ci if (edge) { 5038c2ecf20Sopenharmony_ci list_del_init(&edge->list[UPPER]); 5048c2ecf20Sopenharmony_ci cur = edge->node[UPPER]; 5058c2ecf20Sopenharmony_ci } 5068c2ecf20Sopenharmony_ci } while (edge); 5078c2ecf20Sopenharmony_ci 5088c2ecf20Sopenharmony_ci /* Finish the upper linkage of newly added edges/nodes */ 5098c2ecf20Sopenharmony_ci ret = btrfs_backref_finish_upper_links(cache, node); 5108c2ecf20Sopenharmony_ci if (ret < 0) { 5118c2ecf20Sopenharmony_ci err = ret; 5128c2ecf20Sopenharmony_ci goto out; 5138c2ecf20Sopenharmony_ci } 5148c2ecf20Sopenharmony_ci 5158c2ecf20Sopenharmony_ci if (handle_useless_nodes(rc, node)) 5168c2ecf20Sopenharmony_ci node = NULL; 5178c2ecf20Sopenharmony_ciout: 5188c2ecf20Sopenharmony_ci btrfs_backref_iter_free(iter); 5198c2ecf20Sopenharmony_ci btrfs_free_path(path); 5208c2ecf20Sopenharmony_ci if (err) { 5218c2ecf20Sopenharmony_ci btrfs_backref_error_cleanup(cache, node); 5228c2ecf20Sopenharmony_ci return ERR_PTR(err); 5238c2ecf20Sopenharmony_ci } 5248c2ecf20Sopenharmony_ci ASSERT(!node || !node->detached); 5258c2ecf20Sopenharmony_ci ASSERT(list_empty(&cache->useless_node) && 5268c2ecf20Sopenharmony_ci list_empty(&cache->pending_edge)); 5278c2ecf20Sopenharmony_ci return node; 5288c2ecf20Sopenharmony_ci} 5298c2ecf20Sopenharmony_ci 5308c2ecf20Sopenharmony_ci/* 5318c2ecf20Sopenharmony_ci * helper to add backref node for the newly created snapshot. 5328c2ecf20Sopenharmony_ci * the backref node is created by cloning backref node that 5338c2ecf20Sopenharmony_ci * corresponds to root of source tree 5348c2ecf20Sopenharmony_ci */ 5358c2ecf20Sopenharmony_cistatic int clone_backref_node(struct btrfs_trans_handle *trans, 5368c2ecf20Sopenharmony_ci struct reloc_control *rc, 5378c2ecf20Sopenharmony_ci struct btrfs_root *src, 5388c2ecf20Sopenharmony_ci struct btrfs_root *dest) 5398c2ecf20Sopenharmony_ci{ 5408c2ecf20Sopenharmony_ci struct btrfs_root *reloc_root = src->reloc_root; 5418c2ecf20Sopenharmony_ci struct btrfs_backref_cache *cache = &rc->backref_cache; 5428c2ecf20Sopenharmony_ci struct btrfs_backref_node *node = NULL; 5438c2ecf20Sopenharmony_ci struct btrfs_backref_node *new_node; 5448c2ecf20Sopenharmony_ci struct btrfs_backref_edge *edge; 5458c2ecf20Sopenharmony_ci struct btrfs_backref_edge *new_edge; 5468c2ecf20Sopenharmony_ci struct rb_node *rb_node; 5478c2ecf20Sopenharmony_ci 5488c2ecf20Sopenharmony_ci if (cache->last_trans > 0) 5498c2ecf20Sopenharmony_ci update_backref_cache(trans, cache); 5508c2ecf20Sopenharmony_ci 5518c2ecf20Sopenharmony_ci rb_node = rb_simple_search(&cache->rb_root, src->commit_root->start); 5528c2ecf20Sopenharmony_ci if (rb_node) { 5538c2ecf20Sopenharmony_ci node = rb_entry(rb_node, struct btrfs_backref_node, rb_node); 5548c2ecf20Sopenharmony_ci if (node->detached) 5558c2ecf20Sopenharmony_ci node = NULL; 5568c2ecf20Sopenharmony_ci else 5578c2ecf20Sopenharmony_ci BUG_ON(node->new_bytenr != reloc_root->node->start); 5588c2ecf20Sopenharmony_ci } 5598c2ecf20Sopenharmony_ci 5608c2ecf20Sopenharmony_ci if (!node) { 5618c2ecf20Sopenharmony_ci rb_node = rb_simple_search(&cache->rb_root, 5628c2ecf20Sopenharmony_ci reloc_root->commit_root->start); 5638c2ecf20Sopenharmony_ci if (rb_node) { 5648c2ecf20Sopenharmony_ci node = rb_entry(rb_node, struct btrfs_backref_node, 5658c2ecf20Sopenharmony_ci rb_node); 5668c2ecf20Sopenharmony_ci BUG_ON(node->detached); 5678c2ecf20Sopenharmony_ci } 5688c2ecf20Sopenharmony_ci } 5698c2ecf20Sopenharmony_ci 5708c2ecf20Sopenharmony_ci if (!node) 5718c2ecf20Sopenharmony_ci return 0; 5728c2ecf20Sopenharmony_ci 5738c2ecf20Sopenharmony_ci new_node = btrfs_backref_alloc_node(cache, dest->node->start, 5748c2ecf20Sopenharmony_ci node->level); 5758c2ecf20Sopenharmony_ci if (!new_node) 5768c2ecf20Sopenharmony_ci return -ENOMEM; 5778c2ecf20Sopenharmony_ci 5788c2ecf20Sopenharmony_ci new_node->lowest = node->lowest; 5798c2ecf20Sopenharmony_ci new_node->checked = 1; 5808c2ecf20Sopenharmony_ci new_node->root = btrfs_grab_root(dest); 5818c2ecf20Sopenharmony_ci ASSERT(new_node->root); 5828c2ecf20Sopenharmony_ci 5838c2ecf20Sopenharmony_ci if (!node->lowest) { 5848c2ecf20Sopenharmony_ci list_for_each_entry(edge, &node->lower, list[UPPER]) { 5858c2ecf20Sopenharmony_ci new_edge = btrfs_backref_alloc_edge(cache); 5868c2ecf20Sopenharmony_ci if (!new_edge) 5878c2ecf20Sopenharmony_ci goto fail; 5888c2ecf20Sopenharmony_ci 5898c2ecf20Sopenharmony_ci btrfs_backref_link_edge(new_edge, edge->node[LOWER], 5908c2ecf20Sopenharmony_ci new_node, LINK_UPPER); 5918c2ecf20Sopenharmony_ci } 5928c2ecf20Sopenharmony_ci } else { 5938c2ecf20Sopenharmony_ci list_add_tail(&new_node->lower, &cache->leaves); 5948c2ecf20Sopenharmony_ci } 5958c2ecf20Sopenharmony_ci 5968c2ecf20Sopenharmony_ci rb_node = rb_simple_insert(&cache->rb_root, new_node->bytenr, 5978c2ecf20Sopenharmony_ci &new_node->rb_node); 5988c2ecf20Sopenharmony_ci if (rb_node) 5998c2ecf20Sopenharmony_ci btrfs_backref_panic(trans->fs_info, new_node->bytenr, -EEXIST); 6008c2ecf20Sopenharmony_ci 6018c2ecf20Sopenharmony_ci if (!new_node->lowest) { 6028c2ecf20Sopenharmony_ci list_for_each_entry(new_edge, &new_node->lower, list[UPPER]) { 6038c2ecf20Sopenharmony_ci list_add_tail(&new_edge->list[LOWER], 6048c2ecf20Sopenharmony_ci &new_edge->node[LOWER]->upper); 6058c2ecf20Sopenharmony_ci } 6068c2ecf20Sopenharmony_ci } 6078c2ecf20Sopenharmony_ci return 0; 6088c2ecf20Sopenharmony_cifail: 6098c2ecf20Sopenharmony_ci while (!list_empty(&new_node->lower)) { 6108c2ecf20Sopenharmony_ci new_edge = list_entry(new_node->lower.next, 6118c2ecf20Sopenharmony_ci struct btrfs_backref_edge, list[UPPER]); 6128c2ecf20Sopenharmony_ci list_del(&new_edge->list[UPPER]); 6138c2ecf20Sopenharmony_ci btrfs_backref_free_edge(cache, new_edge); 6148c2ecf20Sopenharmony_ci } 6158c2ecf20Sopenharmony_ci btrfs_backref_free_node(cache, new_node); 6168c2ecf20Sopenharmony_ci return -ENOMEM; 6178c2ecf20Sopenharmony_ci} 6188c2ecf20Sopenharmony_ci 6198c2ecf20Sopenharmony_ci/* 6208c2ecf20Sopenharmony_ci * helper to add 'address of tree root -> reloc tree' mapping 6218c2ecf20Sopenharmony_ci */ 6228c2ecf20Sopenharmony_cistatic int __must_check __add_reloc_root(struct btrfs_root *root) 6238c2ecf20Sopenharmony_ci{ 6248c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = root->fs_info; 6258c2ecf20Sopenharmony_ci struct rb_node *rb_node; 6268c2ecf20Sopenharmony_ci struct mapping_node *node; 6278c2ecf20Sopenharmony_ci struct reloc_control *rc = fs_info->reloc_ctl; 6288c2ecf20Sopenharmony_ci 6298c2ecf20Sopenharmony_ci node = kmalloc(sizeof(*node), GFP_NOFS); 6308c2ecf20Sopenharmony_ci if (!node) 6318c2ecf20Sopenharmony_ci return -ENOMEM; 6328c2ecf20Sopenharmony_ci 6338c2ecf20Sopenharmony_ci node->bytenr = root->commit_root->start; 6348c2ecf20Sopenharmony_ci node->data = root; 6358c2ecf20Sopenharmony_ci 6368c2ecf20Sopenharmony_ci spin_lock(&rc->reloc_root_tree.lock); 6378c2ecf20Sopenharmony_ci rb_node = rb_simple_insert(&rc->reloc_root_tree.rb_root, 6388c2ecf20Sopenharmony_ci node->bytenr, &node->rb_node); 6398c2ecf20Sopenharmony_ci spin_unlock(&rc->reloc_root_tree.lock); 6408c2ecf20Sopenharmony_ci if (rb_node) { 6418c2ecf20Sopenharmony_ci btrfs_panic(fs_info, -EEXIST, 6428c2ecf20Sopenharmony_ci "Duplicate root found for start=%llu while inserting into relocation tree", 6438c2ecf20Sopenharmony_ci node->bytenr); 6448c2ecf20Sopenharmony_ci } 6458c2ecf20Sopenharmony_ci 6468c2ecf20Sopenharmony_ci list_add_tail(&root->root_list, &rc->reloc_roots); 6478c2ecf20Sopenharmony_ci return 0; 6488c2ecf20Sopenharmony_ci} 6498c2ecf20Sopenharmony_ci 6508c2ecf20Sopenharmony_ci/* 6518c2ecf20Sopenharmony_ci * helper to delete the 'address of tree root -> reloc tree' 6528c2ecf20Sopenharmony_ci * mapping 6538c2ecf20Sopenharmony_ci */ 6548c2ecf20Sopenharmony_cistatic void __del_reloc_root(struct btrfs_root *root) 6558c2ecf20Sopenharmony_ci{ 6568c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = root->fs_info; 6578c2ecf20Sopenharmony_ci struct rb_node *rb_node; 6588c2ecf20Sopenharmony_ci struct mapping_node *node = NULL; 6598c2ecf20Sopenharmony_ci struct reloc_control *rc = fs_info->reloc_ctl; 6608c2ecf20Sopenharmony_ci bool put_ref = false; 6618c2ecf20Sopenharmony_ci 6628c2ecf20Sopenharmony_ci if (rc && root->node) { 6638c2ecf20Sopenharmony_ci spin_lock(&rc->reloc_root_tree.lock); 6648c2ecf20Sopenharmony_ci rb_node = rb_simple_search(&rc->reloc_root_tree.rb_root, 6658c2ecf20Sopenharmony_ci root->commit_root->start); 6668c2ecf20Sopenharmony_ci if (rb_node) { 6678c2ecf20Sopenharmony_ci node = rb_entry(rb_node, struct mapping_node, rb_node); 6688c2ecf20Sopenharmony_ci rb_erase(&node->rb_node, &rc->reloc_root_tree.rb_root); 6698c2ecf20Sopenharmony_ci RB_CLEAR_NODE(&node->rb_node); 6708c2ecf20Sopenharmony_ci } 6718c2ecf20Sopenharmony_ci spin_unlock(&rc->reloc_root_tree.lock); 6728c2ecf20Sopenharmony_ci ASSERT(!node || (struct btrfs_root *)node->data == root); 6738c2ecf20Sopenharmony_ci } 6748c2ecf20Sopenharmony_ci 6758c2ecf20Sopenharmony_ci /* 6768c2ecf20Sopenharmony_ci * We only put the reloc root here if it's on the list. There's a lot 6778c2ecf20Sopenharmony_ci * of places where the pattern is to splice the rc->reloc_roots, process 6788c2ecf20Sopenharmony_ci * the reloc roots, and then add the reloc root back onto 6798c2ecf20Sopenharmony_ci * rc->reloc_roots. If we call __del_reloc_root while it's off of the 6808c2ecf20Sopenharmony_ci * list we don't want the reference being dropped, because the guy 6818c2ecf20Sopenharmony_ci * messing with the list is in charge of the reference. 6828c2ecf20Sopenharmony_ci */ 6838c2ecf20Sopenharmony_ci spin_lock(&fs_info->trans_lock); 6848c2ecf20Sopenharmony_ci if (!list_empty(&root->root_list)) { 6858c2ecf20Sopenharmony_ci put_ref = true; 6868c2ecf20Sopenharmony_ci list_del_init(&root->root_list); 6878c2ecf20Sopenharmony_ci } 6888c2ecf20Sopenharmony_ci spin_unlock(&fs_info->trans_lock); 6898c2ecf20Sopenharmony_ci if (put_ref) 6908c2ecf20Sopenharmony_ci btrfs_put_root(root); 6918c2ecf20Sopenharmony_ci kfree(node); 6928c2ecf20Sopenharmony_ci} 6938c2ecf20Sopenharmony_ci 6948c2ecf20Sopenharmony_ci/* 6958c2ecf20Sopenharmony_ci * helper to update the 'address of tree root -> reloc tree' 6968c2ecf20Sopenharmony_ci * mapping 6978c2ecf20Sopenharmony_ci */ 6988c2ecf20Sopenharmony_cistatic int __update_reloc_root(struct btrfs_root *root) 6998c2ecf20Sopenharmony_ci{ 7008c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = root->fs_info; 7018c2ecf20Sopenharmony_ci struct rb_node *rb_node; 7028c2ecf20Sopenharmony_ci struct mapping_node *node = NULL; 7038c2ecf20Sopenharmony_ci struct reloc_control *rc = fs_info->reloc_ctl; 7048c2ecf20Sopenharmony_ci 7058c2ecf20Sopenharmony_ci spin_lock(&rc->reloc_root_tree.lock); 7068c2ecf20Sopenharmony_ci rb_node = rb_simple_search(&rc->reloc_root_tree.rb_root, 7078c2ecf20Sopenharmony_ci root->commit_root->start); 7088c2ecf20Sopenharmony_ci if (rb_node) { 7098c2ecf20Sopenharmony_ci node = rb_entry(rb_node, struct mapping_node, rb_node); 7108c2ecf20Sopenharmony_ci rb_erase(&node->rb_node, &rc->reloc_root_tree.rb_root); 7118c2ecf20Sopenharmony_ci } 7128c2ecf20Sopenharmony_ci spin_unlock(&rc->reloc_root_tree.lock); 7138c2ecf20Sopenharmony_ci 7148c2ecf20Sopenharmony_ci if (!node) 7158c2ecf20Sopenharmony_ci return 0; 7168c2ecf20Sopenharmony_ci BUG_ON((struct btrfs_root *)node->data != root); 7178c2ecf20Sopenharmony_ci 7188c2ecf20Sopenharmony_ci spin_lock(&rc->reloc_root_tree.lock); 7198c2ecf20Sopenharmony_ci node->bytenr = root->node->start; 7208c2ecf20Sopenharmony_ci rb_node = rb_simple_insert(&rc->reloc_root_tree.rb_root, 7218c2ecf20Sopenharmony_ci node->bytenr, &node->rb_node); 7228c2ecf20Sopenharmony_ci spin_unlock(&rc->reloc_root_tree.lock); 7238c2ecf20Sopenharmony_ci if (rb_node) 7248c2ecf20Sopenharmony_ci btrfs_backref_panic(fs_info, node->bytenr, -EEXIST); 7258c2ecf20Sopenharmony_ci return 0; 7268c2ecf20Sopenharmony_ci} 7278c2ecf20Sopenharmony_ci 7288c2ecf20Sopenharmony_cistatic struct btrfs_root *create_reloc_root(struct btrfs_trans_handle *trans, 7298c2ecf20Sopenharmony_ci struct btrfs_root *root, u64 objectid) 7308c2ecf20Sopenharmony_ci{ 7318c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = root->fs_info; 7328c2ecf20Sopenharmony_ci struct btrfs_root *reloc_root; 7338c2ecf20Sopenharmony_ci struct extent_buffer *eb; 7348c2ecf20Sopenharmony_ci struct btrfs_root_item *root_item; 7358c2ecf20Sopenharmony_ci struct btrfs_key root_key; 7368c2ecf20Sopenharmony_ci int ret = 0; 7378c2ecf20Sopenharmony_ci bool must_abort = false; 7388c2ecf20Sopenharmony_ci 7398c2ecf20Sopenharmony_ci root_item = kmalloc(sizeof(*root_item), GFP_NOFS); 7408c2ecf20Sopenharmony_ci if (!root_item) 7418c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 7428c2ecf20Sopenharmony_ci 7438c2ecf20Sopenharmony_ci root_key.objectid = BTRFS_TREE_RELOC_OBJECTID; 7448c2ecf20Sopenharmony_ci root_key.type = BTRFS_ROOT_ITEM_KEY; 7458c2ecf20Sopenharmony_ci root_key.offset = objectid; 7468c2ecf20Sopenharmony_ci 7478c2ecf20Sopenharmony_ci if (root->root_key.objectid == objectid) { 7488c2ecf20Sopenharmony_ci u64 commit_root_gen; 7498c2ecf20Sopenharmony_ci 7508c2ecf20Sopenharmony_ci /* called by btrfs_init_reloc_root */ 7518c2ecf20Sopenharmony_ci ret = btrfs_copy_root(trans, root, root->commit_root, &eb, 7528c2ecf20Sopenharmony_ci BTRFS_TREE_RELOC_OBJECTID); 7538c2ecf20Sopenharmony_ci if (ret) 7548c2ecf20Sopenharmony_ci goto fail; 7558c2ecf20Sopenharmony_ci 7568c2ecf20Sopenharmony_ci /* 7578c2ecf20Sopenharmony_ci * Set the last_snapshot field to the generation of the commit 7588c2ecf20Sopenharmony_ci * root - like this ctree.c:btrfs_block_can_be_shared() behaves 7598c2ecf20Sopenharmony_ci * correctly (returns true) when the relocation root is created 7608c2ecf20Sopenharmony_ci * either inside the critical section of a transaction commit 7618c2ecf20Sopenharmony_ci * (through transaction.c:qgroup_account_snapshot()) and when 7628c2ecf20Sopenharmony_ci * it's created before the transaction commit is started. 7638c2ecf20Sopenharmony_ci */ 7648c2ecf20Sopenharmony_ci commit_root_gen = btrfs_header_generation(root->commit_root); 7658c2ecf20Sopenharmony_ci btrfs_set_root_last_snapshot(&root->root_item, commit_root_gen); 7668c2ecf20Sopenharmony_ci } else { 7678c2ecf20Sopenharmony_ci /* 7688c2ecf20Sopenharmony_ci * called by btrfs_reloc_post_snapshot_hook. 7698c2ecf20Sopenharmony_ci * the source tree is a reloc tree, all tree blocks 7708c2ecf20Sopenharmony_ci * modified after it was created have RELOC flag 7718c2ecf20Sopenharmony_ci * set in their headers. so it's OK to not update 7728c2ecf20Sopenharmony_ci * the 'last_snapshot'. 7738c2ecf20Sopenharmony_ci */ 7748c2ecf20Sopenharmony_ci ret = btrfs_copy_root(trans, root, root->node, &eb, 7758c2ecf20Sopenharmony_ci BTRFS_TREE_RELOC_OBJECTID); 7768c2ecf20Sopenharmony_ci if (ret) 7778c2ecf20Sopenharmony_ci goto fail; 7788c2ecf20Sopenharmony_ci } 7798c2ecf20Sopenharmony_ci 7808c2ecf20Sopenharmony_ci /* 7818c2ecf20Sopenharmony_ci * We have changed references at this point, we must abort the 7828c2ecf20Sopenharmony_ci * transaction if anything fails. 7838c2ecf20Sopenharmony_ci */ 7848c2ecf20Sopenharmony_ci must_abort = true; 7858c2ecf20Sopenharmony_ci 7868c2ecf20Sopenharmony_ci memcpy(root_item, &root->root_item, sizeof(*root_item)); 7878c2ecf20Sopenharmony_ci btrfs_set_root_bytenr(root_item, eb->start); 7888c2ecf20Sopenharmony_ci btrfs_set_root_level(root_item, btrfs_header_level(eb)); 7898c2ecf20Sopenharmony_ci btrfs_set_root_generation(root_item, trans->transid); 7908c2ecf20Sopenharmony_ci 7918c2ecf20Sopenharmony_ci if (root->root_key.objectid == objectid) { 7928c2ecf20Sopenharmony_ci btrfs_set_root_refs(root_item, 0); 7938c2ecf20Sopenharmony_ci memset(&root_item->drop_progress, 0, 7948c2ecf20Sopenharmony_ci sizeof(struct btrfs_disk_key)); 7958c2ecf20Sopenharmony_ci root_item->drop_level = 0; 7968c2ecf20Sopenharmony_ci } 7978c2ecf20Sopenharmony_ci 7988c2ecf20Sopenharmony_ci btrfs_tree_unlock(eb); 7998c2ecf20Sopenharmony_ci free_extent_buffer(eb); 8008c2ecf20Sopenharmony_ci 8018c2ecf20Sopenharmony_ci ret = btrfs_insert_root(trans, fs_info->tree_root, 8028c2ecf20Sopenharmony_ci &root_key, root_item); 8038c2ecf20Sopenharmony_ci if (ret) 8048c2ecf20Sopenharmony_ci goto fail; 8058c2ecf20Sopenharmony_ci 8068c2ecf20Sopenharmony_ci kfree(root_item); 8078c2ecf20Sopenharmony_ci 8088c2ecf20Sopenharmony_ci reloc_root = btrfs_read_tree_root(fs_info->tree_root, &root_key); 8098c2ecf20Sopenharmony_ci if (IS_ERR(reloc_root)) { 8108c2ecf20Sopenharmony_ci ret = PTR_ERR(reloc_root); 8118c2ecf20Sopenharmony_ci goto abort; 8128c2ecf20Sopenharmony_ci } 8138c2ecf20Sopenharmony_ci set_bit(BTRFS_ROOT_SHAREABLE, &reloc_root->state); 8148c2ecf20Sopenharmony_ci reloc_root->last_trans = trans->transid; 8158c2ecf20Sopenharmony_ci return reloc_root; 8168c2ecf20Sopenharmony_cifail: 8178c2ecf20Sopenharmony_ci kfree(root_item); 8188c2ecf20Sopenharmony_ciabort: 8198c2ecf20Sopenharmony_ci if (must_abort) 8208c2ecf20Sopenharmony_ci btrfs_abort_transaction(trans, ret); 8218c2ecf20Sopenharmony_ci return ERR_PTR(ret); 8228c2ecf20Sopenharmony_ci} 8238c2ecf20Sopenharmony_ci 8248c2ecf20Sopenharmony_ci/* 8258c2ecf20Sopenharmony_ci * create reloc tree for a given fs tree. reloc tree is just a 8268c2ecf20Sopenharmony_ci * snapshot of the fs tree with special root objectid. 8278c2ecf20Sopenharmony_ci * 8288c2ecf20Sopenharmony_ci * The reloc_root comes out of here with two references, one for 8298c2ecf20Sopenharmony_ci * root->reloc_root, and another for being on the rc->reloc_roots list. 8308c2ecf20Sopenharmony_ci */ 8318c2ecf20Sopenharmony_ciint btrfs_init_reloc_root(struct btrfs_trans_handle *trans, 8328c2ecf20Sopenharmony_ci struct btrfs_root *root) 8338c2ecf20Sopenharmony_ci{ 8348c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = root->fs_info; 8358c2ecf20Sopenharmony_ci struct btrfs_root *reloc_root; 8368c2ecf20Sopenharmony_ci struct reloc_control *rc = fs_info->reloc_ctl; 8378c2ecf20Sopenharmony_ci struct btrfs_block_rsv *rsv; 8388c2ecf20Sopenharmony_ci int clear_rsv = 0; 8398c2ecf20Sopenharmony_ci int ret; 8408c2ecf20Sopenharmony_ci 8418c2ecf20Sopenharmony_ci if (!rc) 8428c2ecf20Sopenharmony_ci return 0; 8438c2ecf20Sopenharmony_ci 8448c2ecf20Sopenharmony_ci /* 8458c2ecf20Sopenharmony_ci * The subvolume has reloc tree but the swap is finished, no need to 8468c2ecf20Sopenharmony_ci * create/update the dead reloc tree 8478c2ecf20Sopenharmony_ci */ 8488c2ecf20Sopenharmony_ci if (reloc_root_is_dead(root)) 8498c2ecf20Sopenharmony_ci return 0; 8508c2ecf20Sopenharmony_ci 8518c2ecf20Sopenharmony_ci /* 8528c2ecf20Sopenharmony_ci * This is subtle but important. We do not do 8538c2ecf20Sopenharmony_ci * record_root_in_transaction for reloc roots, instead we record their 8548c2ecf20Sopenharmony_ci * corresponding fs root, and then here we update the last trans for the 8558c2ecf20Sopenharmony_ci * reloc root. This means that we have to do this for the entire life 8568c2ecf20Sopenharmony_ci * of the reloc root, regardless of which stage of the relocation we are 8578c2ecf20Sopenharmony_ci * in. 8588c2ecf20Sopenharmony_ci */ 8598c2ecf20Sopenharmony_ci if (root->reloc_root) { 8608c2ecf20Sopenharmony_ci reloc_root = root->reloc_root; 8618c2ecf20Sopenharmony_ci reloc_root->last_trans = trans->transid; 8628c2ecf20Sopenharmony_ci return 0; 8638c2ecf20Sopenharmony_ci } 8648c2ecf20Sopenharmony_ci 8658c2ecf20Sopenharmony_ci /* 8668c2ecf20Sopenharmony_ci * We are merging reloc roots, we do not need new reloc trees. Also 8678c2ecf20Sopenharmony_ci * reloc trees never need their own reloc tree. 8688c2ecf20Sopenharmony_ci */ 8698c2ecf20Sopenharmony_ci if (!rc->create_reloc_tree || 8708c2ecf20Sopenharmony_ci root->root_key.objectid == BTRFS_TREE_RELOC_OBJECTID) 8718c2ecf20Sopenharmony_ci return 0; 8728c2ecf20Sopenharmony_ci 8738c2ecf20Sopenharmony_ci if (!trans->reloc_reserved) { 8748c2ecf20Sopenharmony_ci rsv = trans->block_rsv; 8758c2ecf20Sopenharmony_ci trans->block_rsv = rc->block_rsv; 8768c2ecf20Sopenharmony_ci clear_rsv = 1; 8778c2ecf20Sopenharmony_ci } 8788c2ecf20Sopenharmony_ci reloc_root = create_reloc_root(trans, root, root->root_key.objectid); 8798c2ecf20Sopenharmony_ci if (clear_rsv) 8808c2ecf20Sopenharmony_ci trans->block_rsv = rsv; 8818c2ecf20Sopenharmony_ci 8828c2ecf20Sopenharmony_ci ret = __add_reloc_root(reloc_root); 8838c2ecf20Sopenharmony_ci BUG_ON(ret < 0); 8848c2ecf20Sopenharmony_ci root->reloc_root = btrfs_grab_root(reloc_root); 8858c2ecf20Sopenharmony_ci return 0; 8868c2ecf20Sopenharmony_ci} 8878c2ecf20Sopenharmony_ci 8888c2ecf20Sopenharmony_ci/* 8898c2ecf20Sopenharmony_ci * update root item of reloc tree 8908c2ecf20Sopenharmony_ci */ 8918c2ecf20Sopenharmony_ciint btrfs_update_reloc_root(struct btrfs_trans_handle *trans, 8928c2ecf20Sopenharmony_ci struct btrfs_root *root) 8938c2ecf20Sopenharmony_ci{ 8948c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = root->fs_info; 8958c2ecf20Sopenharmony_ci struct btrfs_root *reloc_root; 8968c2ecf20Sopenharmony_ci struct btrfs_root_item *root_item; 8978c2ecf20Sopenharmony_ci int ret; 8988c2ecf20Sopenharmony_ci 8998c2ecf20Sopenharmony_ci if (!have_reloc_root(root)) 9008c2ecf20Sopenharmony_ci return 0; 9018c2ecf20Sopenharmony_ci 9028c2ecf20Sopenharmony_ci reloc_root = root->reloc_root; 9038c2ecf20Sopenharmony_ci root_item = &reloc_root->root_item; 9048c2ecf20Sopenharmony_ci 9058c2ecf20Sopenharmony_ci /* 9068c2ecf20Sopenharmony_ci * We are probably ok here, but __del_reloc_root() will drop its ref of 9078c2ecf20Sopenharmony_ci * the root. We have the ref for root->reloc_root, but just in case 9088c2ecf20Sopenharmony_ci * hold it while we update the reloc root. 9098c2ecf20Sopenharmony_ci */ 9108c2ecf20Sopenharmony_ci btrfs_grab_root(reloc_root); 9118c2ecf20Sopenharmony_ci 9128c2ecf20Sopenharmony_ci /* root->reloc_root will stay until current relocation finished */ 9138c2ecf20Sopenharmony_ci if (fs_info->reloc_ctl->merge_reloc_tree && 9148c2ecf20Sopenharmony_ci btrfs_root_refs(root_item) == 0) { 9158c2ecf20Sopenharmony_ci set_bit(BTRFS_ROOT_DEAD_RELOC_TREE, &root->state); 9168c2ecf20Sopenharmony_ci /* 9178c2ecf20Sopenharmony_ci * Mark the tree as dead before we change reloc_root so 9188c2ecf20Sopenharmony_ci * have_reloc_root will not touch it from now on. 9198c2ecf20Sopenharmony_ci */ 9208c2ecf20Sopenharmony_ci smp_wmb(); 9218c2ecf20Sopenharmony_ci __del_reloc_root(reloc_root); 9228c2ecf20Sopenharmony_ci } 9238c2ecf20Sopenharmony_ci 9248c2ecf20Sopenharmony_ci if (reloc_root->commit_root != reloc_root->node) { 9258c2ecf20Sopenharmony_ci __update_reloc_root(reloc_root); 9268c2ecf20Sopenharmony_ci btrfs_set_root_node(root_item, reloc_root->node); 9278c2ecf20Sopenharmony_ci free_extent_buffer(reloc_root->commit_root); 9288c2ecf20Sopenharmony_ci reloc_root->commit_root = btrfs_root_node(reloc_root); 9298c2ecf20Sopenharmony_ci } 9308c2ecf20Sopenharmony_ci 9318c2ecf20Sopenharmony_ci ret = btrfs_update_root(trans, fs_info->tree_root, 9328c2ecf20Sopenharmony_ci &reloc_root->root_key, root_item); 9338c2ecf20Sopenharmony_ci btrfs_put_root(reloc_root); 9348c2ecf20Sopenharmony_ci return ret; 9358c2ecf20Sopenharmony_ci} 9368c2ecf20Sopenharmony_ci 9378c2ecf20Sopenharmony_ci/* 9388c2ecf20Sopenharmony_ci * helper to find first cached inode with inode number >= objectid 9398c2ecf20Sopenharmony_ci * in a subvolume 9408c2ecf20Sopenharmony_ci */ 9418c2ecf20Sopenharmony_cistatic struct inode *find_next_inode(struct btrfs_root *root, u64 objectid) 9428c2ecf20Sopenharmony_ci{ 9438c2ecf20Sopenharmony_ci struct rb_node *node; 9448c2ecf20Sopenharmony_ci struct rb_node *prev; 9458c2ecf20Sopenharmony_ci struct btrfs_inode *entry; 9468c2ecf20Sopenharmony_ci struct inode *inode; 9478c2ecf20Sopenharmony_ci 9488c2ecf20Sopenharmony_ci spin_lock(&root->inode_lock); 9498c2ecf20Sopenharmony_ciagain: 9508c2ecf20Sopenharmony_ci node = root->inode_tree.rb_node; 9518c2ecf20Sopenharmony_ci prev = NULL; 9528c2ecf20Sopenharmony_ci while (node) { 9538c2ecf20Sopenharmony_ci prev = node; 9548c2ecf20Sopenharmony_ci entry = rb_entry(node, struct btrfs_inode, rb_node); 9558c2ecf20Sopenharmony_ci 9568c2ecf20Sopenharmony_ci if (objectid < btrfs_ino(entry)) 9578c2ecf20Sopenharmony_ci node = node->rb_left; 9588c2ecf20Sopenharmony_ci else if (objectid > btrfs_ino(entry)) 9598c2ecf20Sopenharmony_ci node = node->rb_right; 9608c2ecf20Sopenharmony_ci else 9618c2ecf20Sopenharmony_ci break; 9628c2ecf20Sopenharmony_ci } 9638c2ecf20Sopenharmony_ci if (!node) { 9648c2ecf20Sopenharmony_ci while (prev) { 9658c2ecf20Sopenharmony_ci entry = rb_entry(prev, struct btrfs_inode, rb_node); 9668c2ecf20Sopenharmony_ci if (objectid <= btrfs_ino(entry)) { 9678c2ecf20Sopenharmony_ci node = prev; 9688c2ecf20Sopenharmony_ci break; 9698c2ecf20Sopenharmony_ci } 9708c2ecf20Sopenharmony_ci prev = rb_next(prev); 9718c2ecf20Sopenharmony_ci } 9728c2ecf20Sopenharmony_ci } 9738c2ecf20Sopenharmony_ci while (node) { 9748c2ecf20Sopenharmony_ci entry = rb_entry(node, struct btrfs_inode, rb_node); 9758c2ecf20Sopenharmony_ci inode = igrab(&entry->vfs_inode); 9768c2ecf20Sopenharmony_ci if (inode) { 9778c2ecf20Sopenharmony_ci spin_unlock(&root->inode_lock); 9788c2ecf20Sopenharmony_ci return inode; 9798c2ecf20Sopenharmony_ci } 9808c2ecf20Sopenharmony_ci 9818c2ecf20Sopenharmony_ci objectid = btrfs_ino(entry) + 1; 9828c2ecf20Sopenharmony_ci if (cond_resched_lock(&root->inode_lock)) 9838c2ecf20Sopenharmony_ci goto again; 9848c2ecf20Sopenharmony_ci 9858c2ecf20Sopenharmony_ci node = rb_next(node); 9868c2ecf20Sopenharmony_ci } 9878c2ecf20Sopenharmony_ci spin_unlock(&root->inode_lock); 9888c2ecf20Sopenharmony_ci return NULL; 9898c2ecf20Sopenharmony_ci} 9908c2ecf20Sopenharmony_ci 9918c2ecf20Sopenharmony_ci/* 9928c2ecf20Sopenharmony_ci * get new location of data 9938c2ecf20Sopenharmony_ci */ 9948c2ecf20Sopenharmony_cistatic int get_new_location(struct inode *reloc_inode, u64 *new_bytenr, 9958c2ecf20Sopenharmony_ci u64 bytenr, u64 num_bytes) 9968c2ecf20Sopenharmony_ci{ 9978c2ecf20Sopenharmony_ci struct btrfs_root *root = BTRFS_I(reloc_inode)->root; 9988c2ecf20Sopenharmony_ci struct btrfs_path *path; 9998c2ecf20Sopenharmony_ci struct btrfs_file_extent_item *fi; 10008c2ecf20Sopenharmony_ci struct extent_buffer *leaf; 10018c2ecf20Sopenharmony_ci int ret; 10028c2ecf20Sopenharmony_ci 10038c2ecf20Sopenharmony_ci path = btrfs_alloc_path(); 10048c2ecf20Sopenharmony_ci if (!path) 10058c2ecf20Sopenharmony_ci return -ENOMEM; 10068c2ecf20Sopenharmony_ci 10078c2ecf20Sopenharmony_ci bytenr -= BTRFS_I(reloc_inode)->index_cnt; 10088c2ecf20Sopenharmony_ci ret = btrfs_lookup_file_extent(NULL, root, path, 10098c2ecf20Sopenharmony_ci btrfs_ino(BTRFS_I(reloc_inode)), bytenr, 0); 10108c2ecf20Sopenharmony_ci if (ret < 0) 10118c2ecf20Sopenharmony_ci goto out; 10128c2ecf20Sopenharmony_ci if (ret > 0) { 10138c2ecf20Sopenharmony_ci ret = -ENOENT; 10148c2ecf20Sopenharmony_ci goto out; 10158c2ecf20Sopenharmony_ci } 10168c2ecf20Sopenharmony_ci 10178c2ecf20Sopenharmony_ci leaf = path->nodes[0]; 10188c2ecf20Sopenharmony_ci fi = btrfs_item_ptr(leaf, path->slots[0], 10198c2ecf20Sopenharmony_ci struct btrfs_file_extent_item); 10208c2ecf20Sopenharmony_ci 10218c2ecf20Sopenharmony_ci BUG_ON(btrfs_file_extent_offset(leaf, fi) || 10228c2ecf20Sopenharmony_ci btrfs_file_extent_compression(leaf, fi) || 10238c2ecf20Sopenharmony_ci btrfs_file_extent_encryption(leaf, fi) || 10248c2ecf20Sopenharmony_ci btrfs_file_extent_other_encoding(leaf, fi)); 10258c2ecf20Sopenharmony_ci 10268c2ecf20Sopenharmony_ci if (num_bytes != btrfs_file_extent_disk_num_bytes(leaf, fi)) { 10278c2ecf20Sopenharmony_ci ret = -EINVAL; 10288c2ecf20Sopenharmony_ci goto out; 10298c2ecf20Sopenharmony_ci } 10308c2ecf20Sopenharmony_ci 10318c2ecf20Sopenharmony_ci *new_bytenr = btrfs_file_extent_disk_bytenr(leaf, fi); 10328c2ecf20Sopenharmony_ci ret = 0; 10338c2ecf20Sopenharmony_ciout: 10348c2ecf20Sopenharmony_ci btrfs_free_path(path); 10358c2ecf20Sopenharmony_ci return ret; 10368c2ecf20Sopenharmony_ci} 10378c2ecf20Sopenharmony_ci 10388c2ecf20Sopenharmony_ci/* 10398c2ecf20Sopenharmony_ci * update file extent items in the tree leaf to point to 10408c2ecf20Sopenharmony_ci * the new locations. 10418c2ecf20Sopenharmony_ci */ 10428c2ecf20Sopenharmony_cistatic noinline_for_stack 10438c2ecf20Sopenharmony_ciint replace_file_extents(struct btrfs_trans_handle *trans, 10448c2ecf20Sopenharmony_ci struct reloc_control *rc, 10458c2ecf20Sopenharmony_ci struct btrfs_root *root, 10468c2ecf20Sopenharmony_ci struct extent_buffer *leaf) 10478c2ecf20Sopenharmony_ci{ 10488c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = root->fs_info; 10498c2ecf20Sopenharmony_ci struct btrfs_key key; 10508c2ecf20Sopenharmony_ci struct btrfs_file_extent_item *fi; 10518c2ecf20Sopenharmony_ci struct inode *inode = NULL; 10528c2ecf20Sopenharmony_ci u64 parent; 10538c2ecf20Sopenharmony_ci u64 bytenr; 10548c2ecf20Sopenharmony_ci u64 new_bytenr = 0; 10558c2ecf20Sopenharmony_ci u64 num_bytes; 10568c2ecf20Sopenharmony_ci u64 end; 10578c2ecf20Sopenharmony_ci u32 nritems; 10588c2ecf20Sopenharmony_ci u32 i; 10598c2ecf20Sopenharmony_ci int ret = 0; 10608c2ecf20Sopenharmony_ci int first = 1; 10618c2ecf20Sopenharmony_ci int dirty = 0; 10628c2ecf20Sopenharmony_ci 10638c2ecf20Sopenharmony_ci if (rc->stage != UPDATE_DATA_PTRS) 10648c2ecf20Sopenharmony_ci return 0; 10658c2ecf20Sopenharmony_ci 10668c2ecf20Sopenharmony_ci /* reloc trees always use full backref */ 10678c2ecf20Sopenharmony_ci if (root->root_key.objectid == BTRFS_TREE_RELOC_OBJECTID) 10688c2ecf20Sopenharmony_ci parent = leaf->start; 10698c2ecf20Sopenharmony_ci else 10708c2ecf20Sopenharmony_ci parent = 0; 10718c2ecf20Sopenharmony_ci 10728c2ecf20Sopenharmony_ci nritems = btrfs_header_nritems(leaf); 10738c2ecf20Sopenharmony_ci for (i = 0; i < nritems; i++) { 10748c2ecf20Sopenharmony_ci struct btrfs_ref ref = { 0 }; 10758c2ecf20Sopenharmony_ci 10768c2ecf20Sopenharmony_ci cond_resched(); 10778c2ecf20Sopenharmony_ci btrfs_item_key_to_cpu(leaf, &key, i); 10788c2ecf20Sopenharmony_ci if (key.type != BTRFS_EXTENT_DATA_KEY) 10798c2ecf20Sopenharmony_ci continue; 10808c2ecf20Sopenharmony_ci fi = btrfs_item_ptr(leaf, i, struct btrfs_file_extent_item); 10818c2ecf20Sopenharmony_ci if (btrfs_file_extent_type(leaf, fi) == 10828c2ecf20Sopenharmony_ci BTRFS_FILE_EXTENT_INLINE) 10838c2ecf20Sopenharmony_ci continue; 10848c2ecf20Sopenharmony_ci bytenr = btrfs_file_extent_disk_bytenr(leaf, fi); 10858c2ecf20Sopenharmony_ci num_bytes = btrfs_file_extent_disk_num_bytes(leaf, fi); 10868c2ecf20Sopenharmony_ci if (bytenr == 0) 10878c2ecf20Sopenharmony_ci continue; 10888c2ecf20Sopenharmony_ci if (!in_range(bytenr, rc->block_group->start, 10898c2ecf20Sopenharmony_ci rc->block_group->length)) 10908c2ecf20Sopenharmony_ci continue; 10918c2ecf20Sopenharmony_ci 10928c2ecf20Sopenharmony_ci /* 10938c2ecf20Sopenharmony_ci * if we are modifying block in fs tree, wait for readpage 10948c2ecf20Sopenharmony_ci * to complete and drop the extent cache 10958c2ecf20Sopenharmony_ci */ 10968c2ecf20Sopenharmony_ci if (root->root_key.objectid != BTRFS_TREE_RELOC_OBJECTID) { 10978c2ecf20Sopenharmony_ci if (first) { 10988c2ecf20Sopenharmony_ci inode = find_next_inode(root, key.objectid); 10998c2ecf20Sopenharmony_ci first = 0; 11008c2ecf20Sopenharmony_ci } else if (inode && btrfs_ino(BTRFS_I(inode)) < key.objectid) { 11018c2ecf20Sopenharmony_ci btrfs_add_delayed_iput(inode); 11028c2ecf20Sopenharmony_ci inode = find_next_inode(root, key.objectid); 11038c2ecf20Sopenharmony_ci } 11048c2ecf20Sopenharmony_ci if (inode && btrfs_ino(BTRFS_I(inode)) == key.objectid) { 11058c2ecf20Sopenharmony_ci end = key.offset + 11068c2ecf20Sopenharmony_ci btrfs_file_extent_num_bytes(leaf, fi); 11078c2ecf20Sopenharmony_ci WARN_ON(!IS_ALIGNED(key.offset, 11088c2ecf20Sopenharmony_ci fs_info->sectorsize)); 11098c2ecf20Sopenharmony_ci WARN_ON(!IS_ALIGNED(end, fs_info->sectorsize)); 11108c2ecf20Sopenharmony_ci end--; 11118c2ecf20Sopenharmony_ci ret = try_lock_extent(&BTRFS_I(inode)->io_tree, 11128c2ecf20Sopenharmony_ci key.offset, end); 11138c2ecf20Sopenharmony_ci if (!ret) 11148c2ecf20Sopenharmony_ci continue; 11158c2ecf20Sopenharmony_ci 11168c2ecf20Sopenharmony_ci btrfs_drop_extent_cache(BTRFS_I(inode), 11178c2ecf20Sopenharmony_ci key.offset, end, 1); 11188c2ecf20Sopenharmony_ci unlock_extent(&BTRFS_I(inode)->io_tree, 11198c2ecf20Sopenharmony_ci key.offset, end); 11208c2ecf20Sopenharmony_ci } 11218c2ecf20Sopenharmony_ci } 11228c2ecf20Sopenharmony_ci 11238c2ecf20Sopenharmony_ci ret = get_new_location(rc->data_inode, &new_bytenr, 11248c2ecf20Sopenharmony_ci bytenr, num_bytes); 11258c2ecf20Sopenharmony_ci if (ret) { 11268c2ecf20Sopenharmony_ci /* 11278c2ecf20Sopenharmony_ci * Don't have to abort since we've not changed anything 11288c2ecf20Sopenharmony_ci * in the file extent yet. 11298c2ecf20Sopenharmony_ci */ 11308c2ecf20Sopenharmony_ci break; 11318c2ecf20Sopenharmony_ci } 11328c2ecf20Sopenharmony_ci 11338c2ecf20Sopenharmony_ci btrfs_set_file_extent_disk_bytenr(leaf, fi, new_bytenr); 11348c2ecf20Sopenharmony_ci dirty = 1; 11358c2ecf20Sopenharmony_ci 11368c2ecf20Sopenharmony_ci key.offset -= btrfs_file_extent_offset(leaf, fi); 11378c2ecf20Sopenharmony_ci btrfs_init_generic_ref(&ref, BTRFS_ADD_DELAYED_REF, new_bytenr, 11388c2ecf20Sopenharmony_ci num_bytes, parent); 11398c2ecf20Sopenharmony_ci ref.real_root = root->root_key.objectid; 11408c2ecf20Sopenharmony_ci btrfs_init_data_ref(&ref, btrfs_header_owner(leaf), 11418c2ecf20Sopenharmony_ci key.objectid, key.offset); 11428c2ecf20Sopenharmony_ci ret = btrfs_inc_extent_ref(trans, &ref); 11438c2ecf20Sopenharmony_ci if (ret) { 11448c2ecf20Sopenharmony_ci btrfs_abort_transaction(trans, ret); 11458c2ecf20Sopenharmony_ci break; 11468c2ecf20Sopenharmony_ci } 11478c2ecf20Sopenharmony_ci 11488c2ecf20Sopenharmony_ci btrfs_init_generic_ref(&ref, BTRFS_DROP_DELAYED_REF, bytenr, 11498c2ecf20Sopenharmony_ci num_bytes, parent); 11508c2ecf20Sopenharmony_ci ref.real_root = root->root_key.objectid; 11518c2ecf20Sopenharmony_ci btrfs_init_data_ref(&ref, btrfs_header_owner(leaf), 11528c2ecf20Sopenharmony_ci key.objectid, key.offset); 11538c2ecf20Sopenharmony_ci ret = btrfs_free_extent(trans, &ref); 11548c2ecf20Sopenharmony_ci if (ret) { 11558c2ecf20Sopenharmony_ci btrfs_abort_transaction(trans, ret); 11568c2ecf20Sopenharmony_ci break; 11578c2ecf20Sopenharmony_ci } 11588c2ecf20Sopenharmony_ci } 11598c2ecf20Sopenharmony_ci if (dirty) 11608c2ecf20Sopenharmony_ci btrfs_mark_buffer_dirty(leaf); 11618c2ecf20Sopenharmony_ci if (inode) 11628c2ecf20Sopenharmony_ci btrfs_add_delayed_iput(inode); 11638c2ecf20Sopenharmony_ci return ret; 11648c2ecf20Sopenharmony_ci} 11658c2ecf20Sopenharmony_ci 11668c2ecf20Sopenharmony_cistatic noinline_for_stack 11678c2ecf20Sopenharmony_ciint memcmp_node_keys(struct extent_buffer *eb, int slot, 11688c2ecf20Sopenharmony_ci struct btrfs_path *path, int level) 11698c2ecf20Sopenharmony_ci{ 11708c2ecf20Sopenharmony_ci struct btrfs_disk_key key1; 11718c2ecf20Sopenharmony_ci struct btrfs_disk_key key2; 11728c2ecf20Sopenharmony_ci btrfs_node_key(eb, &key1, slot); 11738c2ecf20Sopenharmony_ci btrfs_node_key(path->nodes[level], &key2, path->slots[level]); 11748c2ecf20Sopenharmony_ci return memcmp(&key1, &key2, sizeof(key1)); 11758c2ecf20Sopenharmony_ci} 11768c2ecf20Sopenharmony_ci 11778c2ecf20Sopenharmony_ci/* 11788c2ecf20Sopenharmony_ci * try to replace tree blocks in fs tree with the new blocks 11798c2ecf20Sopenharmony_ci * in reloc tree. tree blocks haven't been modified since the 11808c2ecf20Sopenharmony_ci * reloc tree was create can be replaced. 11818c2ecf20Sopenharmony_ci * 11828c2ecf20Sopenharmony_ci * if a block was replaced, level of the block + 1 is returned. 11838c2ecf20Sopenharmony_ci * if no block got replaced, 0 is returned. if there are other 11848c2ecf20Sopenharmony_ci * errors, a negative error number is returned. 11858c2ecf20Sopenharmony_ci */ 11868c2ecf20Sopenharmony_cistatic noinline_for_stack 11878c2ecf20Sopenharmony_ciint replace_path(struct btrfs_trans_handle *trans, struct reloc_control *rc, 11888c2ecf20Sopenharmony_ci struct btrfs_root *dest, struct btrfs_root *src, 11898c2ecf20Sopenharmony_ci struct btrfs_path *path, struct btrfs_key *next_key, 11908c2ecf20Sopenharmony_ci int lowest_level, int max_level) 11918c2ecf20Sopenharmony_ci{ 11928c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = dest->fs_info; 11938c2ecf20Sopenharmony_ci struct extent_buffer *eb; 11948c2ecf20Sopenharmony_ci struct extent_buffer *parent; 11958c2ecf20Sopenharmony_ci struct btrfs_ref ref = { 0 }; 11968c2ecf20Sopenharmony_ci struct btrfs_key key; 11978c2ecf20Sopenharmony_ci u64 old_bytenr; 11988c2ecf20Sopenharmony_ci u64 new_bytenr; 11998c2ecf20Sopenharmony_ci u64 old_ptr_gen; 12008c2ecf20Sopenharmony_ci u64 new_ptr_gen; 12018c2ecf20Sopenharmony_ci u64 last_snapshot; 12028c2ecf20Sopenharmony_ci u32 blocksize; 12038c2ecf20Sopenharmony_ci int cow = 0; 12048c2ecf20Sopenharmony_ci int level; 12058c2ecf20Sopenharmony_ci int ret; 12068c2ecf20Sopenharmony_ci int slot; 12078c2ecf20Sopenharmony_ci 12088c2ecf20Sopenharmony_ci ASSERT(src->root_key.objectid == BTRFS_TREE_RELOC_OBJECTID); 12098c2ecf20Sopenharmony_ci ASSERT(dest->root_key.objectid != BTRFS_TREE_RELOC_OBJECTID); 12108c2ecf20Sopenharmony_ci 12118c2ecf20Sopenharmony_ci last_snapshot = btrfs_root_last_snapshot(&src->root_item); 12128c2ecf20Sopenharmony_ciagain: 12138c2ecf20Sopenharmony_ci slot = path->slots[lowest_level]; 12148c2ecf20Sopenharmony_ci btrfs_node_key_to_cpu(path->nodes[lowest_level], &key, slot); 12158c2ecf20Sopenharmony_ci 12168c2ecf20Sopenharmony_ci eb = btrfs_lock_root_node(dest); 12178c2ecf20Sopenharmony_ci btrfs_set_lock_blocking_write(eb); 12188c2ecf20Sopenharmony_ci level = btrfs_header_level(eb); 12198c2ecf20Sopenharmony_ci 12208c2ecf20Sopenharmony_ci if (level < lowest_level) { 12218c2ecf20Sopenharmony_ci btrfs_tree_unlock(eb); 12228c2ecf20Sopenharmony_ci free_extent_buffer(eb); 12238c2ecf20Sopenharmony_ci return 0; 12248c2ecf20Sopenharmony_ci } 12258c2ecf20Sopenharmony_ci 12268c2ecf20Sopenharmony_ci if (cow) { 12278c2ecf20Sopenharmony_ci ret = btrfs_cow_block(trans, dest, eb, NULL, 0, &eb, 12288c2ecf20Sopenharmony_ci BTRFS_NESTING_COW); 12298c2ecf20Sopenharmony_ci BUG_ON(ret); 12308c2ecf20Sopenharmony_ci } 12318c2ecf20Sopenharmony_ci btrfs_set_lock_blocking_write(eb); 12328c2ecf20Sopenharmony_ci 12338c2ecf20Sopenharmony_ci if (next_key) { 12348c2ecf20Sopenharmony_ci next_key->objectid = (u64)-1; 12358c2ecf20Sopenharmony_ci next_key->type = (u8)-1; 12368c2ecf20Sopenharmony_ci next_key->offset = (u64)-1; 12378c2ecf20Sopenharmony_ci } 12388c2ecf20Sopenharmony_ci 12398c2ecf20Sopenharmony_ci parent = eb; 12408c2ecf20Sopenharmony_ci while (1) { 12418c2ecf20Sopenharmony_ci struct btrfs_key first_key; 12428c2ecf20Sopenharmony_ci 12438c2ecf20Sopenharmony_ci level = btrfs_header_level(parent); 12448c2ecf20Sopenharmony_ci ASSERT(level >= lowest_level); 12458c2ecf20Sopenharmony_ci 12468c2ecf20Sopenharmony_ci ret = btrfs_bin_search(parent, &key, &slot); 12478c2ecf20Sopenharmony_ci if (ret < 0) 12488c2ecf20Sopenharmony_ci break; 12498c2ecf20Sopenharmony_ci if (ret && slot > 0) 12508c2ecf20Sopenharmony_ci slot--; 12518c2ecf20Sopenharmony_ci 12528c2ecf20Sopenharmony_ci if (next_key && slot + 1 < btrfs_header_nritems(parent)) 12538c2ecf20Sopenharmony_ci btrfs_node_key_to_cpu(parent, next_key, slot + 1); 12548c2ecf20Sopenharmony_ci 12558c2ecf20Sopenharmony_ci old_bytenr = btrfs_node_blockptr(parent, slot); 12568c2ecf20Sopenharmony_ci blocksize = fs_info->nodesize; 12578c2ecf20Sopenharmony_ci old_ptr_gen = btrfs_node_ptr_generation(parent, slot); 12588c2ecf20Sopenharmony_ci btrfs_node_key_to_cpu(parent, &first_key, slot); 12598c2ecf20Sopenharmony_ci 12608c2ecf20Sopenharmony_ci if (level <= max_level) { 12618c2ecf20Sopenharmony_ci eb = path->nodes[level]; 12628c2ecf20Sopenharmony_ci new_bytenr = btrfs_node_blockptr(eb, 12638c2ecf20Sopenharmony_ci path->slots[level]); 12648c2ecf20Sopenharmony_ci new_ptr_gen = btrfs_node_ptr_generation(eb, 12658c2ecf20Sopenharmony_ci path->slots[level]); 12668c2ecf20Sopenharmony_ci } else { 12678c2ecf20Sopenharmony_ci new_bytenr = 0; 12688c2ecf20Sopenharmony_ci new_ptr_gen = 0; 12698c2ecf20Sopenharmony_ci } 12708c2ecf20Sopenharmony_ci 12718c2ecf20Sopenharmony_ci if (WARN_ON(new_bytenr > 0 && new_bytenr == old_bytenr)) { 12728c2ecf20Sopenharmony_ci ret = level; 12738c2ecf20Sopenharmony_ci break; 12748c2ecf20Sopenharmony_ci } 12758c2ecf20Sopenharmony_ci 12768c2ecf20Sopenharmony_ci if (new_bytenr == 0 || old_ptr_gen > last_snapshot || 12778c2ecf20Sopenharmony_ci memcmp_node_keys(parent, slot, path, level)) { 12788c2ecf20Sopenharmony_ci if (level <= lowest_level) { 12798c2ecf20Sopenharmony_ci ret = 0; 12808c2ecf20Sopenharmony_ci break; 12818c2ecf20Sopenharmony_ci } 12828c2ecf20Sopenharmony_ci 12838c2ecf20Sopenharmony_ci eb = read_tree_block(fs_info, old_bytenr, old_ptr_gen, 12848c2ecf20Sopenharmony_ci level - 1, &first_key); 12858c2ecf20Sopenharmony_ci if (IS_ERR(eb)) { 12868c2ecf20Sopenharmony_ci ret = PTR_ERR(eb); 12878c2ecf20Sopenharmony_ci break; 12888c2ecf20Sopenharmony_ci } else if (!extent_buffer_uptodate(eb)) { 12898c2ecf20Sopenharmony_ci ret = -EIO; 12908c2ecf20Sopenharmony_ci free_extent_buffer(eb); 12918c2ecf20Sopenharmony_ci break; 12928c2ecf20Sopenharmony_ci } 12938c2ecf20Sopenharmony_ci btrfs_tree_lock(eb); 12948c2ecf20Sopenharmony_ci if (cow) { 12958c2ecf20Sopenharmony_ci ret = btrfs_cow_block(trans, dest, eb, parent, 12968c2ecf20Sopenharmony_ci slot, &eb, 12978c2ecf20Sopenharmony_ci BTRFS_NESTING_COW); 12988c2ecf20Sopenharmony_ci BUG_ON(ret); 12998c2ecf20Sopenharmony_ci } 13008c2ecf20Sopenharmony_ci btrfs_set_lock_blocking_write(eb); 13018c2ecf20Sopenharmony_ci 13028c2ecf20Sopenharmony_ci btrfs_tree_unlock(parent); 13038c2ecf20Sopenharmony_ci free_extent_buffer(parent); 13048c2ecf20Sopenharmony_ci 13058c2ecf20Sopenharmony_ci parent = eb; 13068c2ecf20Sopenharmony_ci continue; 13078c2ecf20Sopenharmony_ci } 13088c2ecf20Sopenharmony_ci 13098c2ecf20Sopenharmony_ci if (!cow) { 13108c2ecf20Sopenharmony_ci btrfs_tree_unlock(parent); 13118c2ecf20Sopenharmony_ci free_extent_buffer(parent); 13128c2ecf20Sopenharmony_ci cow = 1; 13138c2ecf20Sopenharmony_ci goto again; 13148c2ecf20Sopenharmony_ci } 13158c2ecf20Sopenharmony_ci 13168c2ecf20Sopenharmony_ci btrfs_node_key_to_cpu(path->nodes[level], &key, 13178c2ecf20Sopenharmony_ci path->slots[level]); 13188c2ecf20Sopenharmony_ci btrfs_release_path(path); 13198c2ecf20Sopenharmony_ci 13208c2ecf20Sopenharmony_ci path->lowest_level = level; 13218c2ecf20Sopenharmony_ci ret = btrfs_search_slot(trans, src, &key, path, 0, 1); 13228c2ecf20Sopenharmony_ci path->lowest_level = 0; 13238c2ecf20Sopenharmony_ci BUG_ON(ret); 13248c2ecf20Sopenharmony_ci 13258c2ecf20Sopenharmony_ci /* 13268c2ecf20Sopenharmony_ci * Info qgroup to trace both subtrees. 13278c2ecf20Sopenharmony_ci * 13288c2ecf20Sopenharmony_ci * We must trace both trees. 13298c2ecf20Sopenharmony_ci * 1) Tree reloc subtree 13308c2ecf20Sopenharmony_ci * If not traced, we will leak data numbers 13318c2ecf20Sopenharmony_ci * 2) Fs subtree 13328c2ecf20Sopenharmony_ci * If not traced, we will double count old data 13338c2ecf20Sopenharmony_ci * 13348c2ecf20Sopenharmony_ci * We don't scan the subtree right now, but only record 13358c2ecf20Sopenharmony_ci * the swapped tree blocks. 13368c2ecf20Sopenharmony_ci * The real subtree rescan is delayed until we have new 13378c2ecf20Sopenharmony_ci * CoW on the subtree root node before transaction commit. 13388c2ecf20Sopenharmony_ci */ 13398c2ecf20Sopenharmony_ci ret = btrfs_qgroup_add_swapped_blocks(trans, dest, 13408c2ecf20Sopenharmony_ci rc->block_group, parent, slot, 13418c2ecf20Sopenharmony_ci path->nodes[level], path->slots[level], 13428c2ecf20Sopenharmony_ci last_snapshot); 13438c2ecf20Sopenharmony_ci if (ret < 0) 13448c2ecf20Sopenharmony_ci break; 13458c2ecf20Sopenharmony_ci /* 13468c2ecf20Sopenharmony_ci * swap blocks in fs tree and reloc tree. 13478c2ecf20Sopenharmony_ci */ 13488c2ecf20Sopenharmony_ci btrfs_set_node_blockptr(parent, slot, new_bytenr); 13498c2ecf20Sopenharmony_ci btrfs_set_node_ptr_generation(parent, slot, new_ptr_gen); 13508c2ecf20Sopenharmony_ci btrfs_mark_buffer_dirty(parent); 13518c2ecf20Sopenharmony_ci 13528c2ecf20Sopenharmony_ci btrfs_set_node_blockptr(path->nodes[level], 13538c2ecf20Sopenharmony_ci path->slots[level], old_bytenr); 13548c2ecf20Sopenharmony_ci btrfs_set_node_ptr_generation(path->nodes[level], 13558c2ecf20Sopenharmony_ci path->slots[level], old_ptr_gen); 13568c2ecf20Sopenharmony_ci btrfs_mark_buffer_dirty(path->nodes[level]); 13578c2ecf20Sopenharmony_ci 13588c2ecf20Sopenharmony_ci btrfs_init_generic_ref(&ref, BTRFS_ADD_DELAYED_REF, old_bytenr, 13598c2ecf20Sopenharmony_ci blocksize, path->nodes[level]->start); 13608c2ecf20Sopenharmony_ci ref.skip_qgroup = true; 13618c2ecf20Sopenharmony_ci btrfs_init_tree_ref(&ref, level - 1, src->root_key.objectid); 13628c2ecf20Sopenharmony_ci ret = btrfs_inc_extent_ref(trans, &ref); 13638c2ecf20Sopenharmony_ci BUG_ON(ret); 13648c2ecf20Sopenharmony_ci btrfs_init_generic_ref(&ref, BTRFS_ADD_DELAYED_REF, new_bytenr, 13658c2ecf20Sopenharmony_ci blocksize, 0); 13668c2ecf20Sopenharmony_ci ref.skip_qgroup = true; 13678c2ecf20Sopenharmony_ci btrfs_init_tree_ref(&ref, level - 1, dest->root_key.objectid); 13688c2ecf20Sopenharmony_ci ret = btrfs_inc_extent_ref(trans, &ref); 13698c2ecf20Sopenharmony_ci BUG_ON(ret); 13708c2ecf20Sopenharmony_ci 13718c2ecf20Sopenharmony_ci btrfs_init_generic_ref(&ref, BTRFS_DROP_DELAYED_REF, new_bytenr, 13728c2ecf20Sopenharmony_ci blocksize, path->nodes[level]->start); 13738c2ecf20Sopenharmony_ci btrfs_init_tree_ref(&ref, level - 1, src->root_key.objectid); 13748c2ecf20Sopenharmony_ci ref.skip_qgroup = true; 13758c2ecf20Sopenharmony_ci ret = btrfs_free_extent(trans, &ref); 13768c2ecf20Sopenharmony_ci BUG_ON(ret); 13778c2ecf20Sopenharmony_ci 13788c2ecf20Sopenharmony_ci btrfs_init_generic_ref(&ref, BTRFS_DROP_DELAYED_REF, old_bytenr, 13798c2ecf20Sopenharmony_ci blocksize, 0); 13808c2ecf20Sopenharmony_ci btrfs_init_tree_ref(&ref, level - 1, dest->root_key.objectid); 13818c2ecf20Sopenharmony_ci ref.skip_qgroup = true; 13828c2ecf20Sopenharmony_ci ret = btrfs_free_extent(trans, &ref); 13838c2ecf20Sopenharmony_ci BUG_ON(ret); 13848c2ecf20Sopenharmony_ci 13858c2ecf20Sopenharmony_ci btrfs_unlock_up_safe(path, 0); 13868c2ecf20Sopenharmony_ci 13878c2ecf20Sopenharmony_ci ret = level; 13888c2ecf20Sopenharmony_ci break; 13898c2ecf20Sopenharmony_ci } 13908c2ecf20Sopenharmony_ci btrfs_tree_unlock(parent); 13918c2ecf20Sopenharmony_ci free_extent_buffer(parent); 13928c2ecf20Sopenharmony_ci return ret; 13938c2ecf20Sopenharmony_ci} 13948c2ecf20Sopenharmony_ci 13958c2ecf20Sopenharmony_ci/* 13968c2ecf20Sopenharmony_ci * helper to find next relocated block in reloc tree 13978c2ecf20Sopenharmony_ci */ 13988c2ecf20Sopenharmony_cistatic noinline_for_stack 13998c2ecf20Sopenharmony_ciint walk_up_reloc_tree(struct btrfs_root *root, struct btrfs_path *path, 14008c2ecf20Sopenharmony_ci int *level) 14018c2ecf20Sopenharmony_ci{ 14028c2ecf20Sopenharmony_ci struct extent_buffer *eb; 14038c2ecf20Sopenharmony_ci int i; 14048c2ecf20Sopenharmony_ci u64 last_snapshot; 14058c2ecf20Sopenharmony_ci u32 nritems; 14068c2ecf20Sopenharmony_ci 14078c2ecf20Sopenharmony_ci last_snapshot = btrfs_root_last_snapshot(&root->root_item); 14088c2ecf20Sopenharmony_ci 14098c2ecf20Sopenharmony_ci for (i = 0; i < *level; i++) { 14108c2ecf20Sopenharmony_ci free_extent_buffer(path->nodes[i]); 14118c2ecf20Sopenharmony_ci path->nodes[i] = NULL; 14128c2ecf20Sopenharmony_ci } 14138c2ecf20Sopenharmony_ci 14148c2ecf20Sopenharmony_ci for (i = *level; i < BTRFS_MAX_LEVEL && path->nodes[i]; i++) { 14158c2ecf20Sopenharmony_ci eb = path->nodes[i]; 14168c2ecf20Sopenharmony_ci nritems = btrfs_header_nritems(eb); 14178c2ecf20Sopenharmony_ci while (path->slots[i] + 1 < nritems) { 14188c2ecf20Sopenharmony_ci path->slots[i]++; 14198c2ecf20Sopenharmony_ci if (btrfs_node_ptr_generation(eb, path->slots[i]) <= 14208c2ecf20Sopenharmony_ci last_snapshot) 14218c2ecf20Sopenharmony_ci continue; 14228c2ecf20Sopenharmony_ci 14238c2ecf20Sopenharmony_ci *level = i; 14248c2ecf20Sopenharmony_ci return 0; 14258c2ecf20Sopenharmony_ci } 14268c2ecf20Sopenharmony_ci free_extent_buffer(path->nodes[i]); 14278c2ecf20Sopenharmony_ci path->nodes[i] = NULL; 14288c2ecf20Sopenharmony_ci } 14298c2ecf20Sopenharmony_ci return 1; 14308c2ecf20Sopenharmony_ci} 14318c2ecf20Sopenharmony_ci 14328c2ecf20Sopenharmony_ci/* 14338c2ecf20Sopenharmony_ci * walk down reloc tree to find relocated block of lowest level 14348c2ecf20Sopenharmony_ci */ 14358c2ecf20Sopenharmony_cistatic noinline_for_stack 14368c2ecf20Sopenharmony_ciint walk_down_reloc_tree(struct btrfs_root *root, struct btrfs_path *path, 14378c2ecf20Sopenharmony_ci int *level) 14388c2ecf20Sopenharmony_ci{ 14398c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = root->fs_info; 14408c2ecf20Sopenharmony_ci struct extent_buffer *eb = NULL; 14418c2ecf20Sopenharmony_ci int i; 14428c2ecf20Sopenharmony_ci u64 bytenr; 14438c2ecf20Sopenharmony_ci u64 ptr_gen = 0; 14448c2ecf20Sopenharmony_ci u64 last_snapshot; 14458c2ecf20Sopenharmony_ci u32 nritems; 14468c2ecf20Sopenharmony_ci 14478c2ecf20Sopenharmony_ci last_snapshot = btrfs_root_last_snapshot(&root->root_item); 14488c2ecf20Sopenharmony_ci 14498c2ecf20Sopenharmony_ci for (i = *level; i > 0; i--) { 14508c2ecf20Sopenharmony_ci struct btrfs_key first_key; 14518c2ecf20Sopenharmony_ci 14528c2ecf20Sopenharmony_ci eb = path->nodes[i]; 14538c2ecf20Sopenharmony_ci nritems = btrfs_header_nritems(eb); 14548c2ecf20Sopenharmony_ci while (path->slots[i] < nritems) { 14558c2ecf20Sopenharmony_ci ptr_gen = btrfs_node_ptr_generation(eb, path->slots[i]); 14568c2ecf20Sopenharmony_ci if (ptr_gen > last_snapshot) 14578c2ecf20Sopenharmony_ci break; 14588c2ecf20Sopenharmony_ci path->slots[i]++; 14598c2ecf20Sopenharmony_ci } 14608c2ecf20Sopenharmony_ci if (path->slots[i] >= nritems) { 14618c2ecf20Sopenharmony_ci if (i == *level) 14628c2ecf20Sopenharmony_ci break; 14638c2ecf20Sopenharmony_ci *level = i + 1; 14648c2ecf20Sopenharmony_ci return 0; 14658c2ecf20Sopenharmony_ci } 14668c2ecf20Sopenharmony_ci if (i == 1) { 14678c2ecf20Sopenharmony_ci *level = i; 14688c2ecf20Sopenharmony_ci return 0; 14698c2ecf20Sopenharmony_ci } 14708c2ecf20Sopenharmony_ci 14718c2ecf20Sopenharmony_ci bytenr = btrfs_node_blockptr(eb, path->slots[i]); 14728c2ecf20Sopenharmony_ci btrfs_node_key_to_cpu(eb, &first_key, path->slots[i]); 14738c2ecf20Sopenharmony_ci eb = read_tree_block(fs_info, bytenr, ptr_gen, i - 1, 14748c2ecf20Sopenharmony_ci &first_key); 14758c2ecf20Sopenharmony_ci if (IS_ERR(eb)) { 14768c2ecf20Sopenharmony_ci return PTR_ERR(eb); 14778c2ecf20Sopenharmony_ci } else if (!extent_buffer_uptodate(eb)) { 14788c2ecf20Sopenharmony_ci free_extent_buffer(eb); 14798c2ecf20Sopenharmony_ci return -EIO; 14808c2ecf20Sopenharmony_ci } 14818c2ecf20Sopenharmony_ci BUG_ON(btrfs_header_level(eb) != i - 1); 14828c2ecf20Sopenharmony_ci path->nodes[i - 1] = eb; 14838c2ecf20Sopenharmony_ci path->slots[i - 1] = 0; 14848c2ecf20Sopenharmony_ci } 14858c2ecf20Sopenharmony_ci return 1; 14868c2ecf20Sopenharmony_ci} 14878c2ecf20Sopenharmony_ci 14888c2ecf20Sopenharmony_ci/* 14898c2ecf20Sopenharmony_ci * invalidate extent cache for file extents whose key in range of 14908c2ecf20Sopenharmony_ci * [min_key, max_key) 14918c2ecf20Sopenharmony_ci */ 14928c2ecf20Sopenharmony_cistatic int invalidate_extent_cache(struct btrfs_root *root, 14938c2ecf20Sopenharmony_ci struct btrfs_key *min_key, 14948c2ecf20Sopenharmony_ci struct btrfs_key *max_key) 14958c2ecf20Sopenharmony_ci{ 14968c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = root->fs_info; 14978c2ecf20Sopenharmony_ci struct inode *inode = NULL; 14988c2ecf20Sopenharmony_ci u64 objectid; 14998c2ecf20Sopenharmony_ci u64 start, end; 15008c2ecf20Sopenharmony_ci u64 ino; 15018c2ecf20Sopenharmony_ci 15028c2ecf20Sopenharmony_ci objectid = min_key->objectid; 15038c2ecf20Sopenharmony_ci while (1) { 15048c2ecf20Sopenharmony_ci cond_resched(); 15058c2ecf20Sopenharmony_ci iput(inode); 15068c2ecf20Sopenharmony_ci 15078c2ecf20Sopenharmony_ci if (objectid > max_key->objectid) 15088c2ecf20Sopenharmony_ci break; 15098c2ecf20Sopenharmony_ci 15108c2ecf20Sopenharmony_ci inode = find_next_inode(root, objectid); 15118c2ecf20Sopenharmony_ci if (!inode) 15128c2ecf20Sopenharmony_ci break; 15138c2ecf20Sopenharmony_ci ino = btrfs_ino(BTRFS_I(inode)); 15148c2ecf20Sopenharmony_ci 15158c2ecf20Sopenharmony_ci if (ino > max_key->objectid) { 15168c2ecf20Sopenharmony_ci iput(inode); 15178c2ecf20Sopenharmony_ci break; 15188c2ecf20Sopenharmony_ci } 15198c2ecf20Sopenharmony_ci 15208c2ecf20Sopenharmony_ci objectid = ino + 1; 15218c2ecf20Sopenharmony_ci if (!S_ISREG(inode->i_mode)) 15228c2ecf20Sopenharmony_ci continue; 15238c2ecf20Sopenharmony_ci 15248c2ecf20Sopenharmony_ci if (unlikely(min_key->objectid == ino)) { 15258c2ecf20Sopenharmony_ci if (min_key->type > BTRFS_EXTENT_DATA_KEY) 15268c2ecf20Sopenharmony_ci continue; 15278c2ecf20Sopenharmony_ci if (min_key->type < BTRFS_EXTENT_DATA_KEY) 15288c2ecf20Sopenharmony_ci start = 0; 15298c2ecf20Sopenharmony_ci else { 15308c2ecf20Sopenharmony_ci start = min_key->offset; 15318c2ecf20Sopenharmony_ci WARN_ON(!IS_ALIGNED(start, fs_info->sectorsize)); 15328c2ecf20Sopenharmony_ci } 15338c2ecf20Sopenharmony_ci } else { 15348c2ecf20Sopenharmony_ci start = 0; 15358c2ecf20Sopenharmony_ci } 15368c2ecf20Sopenharmony_ci 15378c2ecf20Sopenharmony_ci if (unlikely(max_key->objectid == ino)) { 15388c2ecf20Sopenharmony_ci if (max_key->type < BTRFS_EXTENT_DATA_KEY) 15398c2ecf20Sopenharmony_ci continue; 15408c2ecf20Sopenharmony_ci if (max_key->type > BTRFS_EXTENT_DATA_KEY) { 15418c2ecf20Sopenharmony_ci end = (u64)-1; 15428c2ecf20Sopenharmony_ci } else { 15438c2ecf20Sopenharmony_ci if (max_key->offset == 0) 15448c2ecf20Sopenharmony_ci continue; 15458c2ecf20Sopenharmony_ci end = max_key->offset; 15468c2ecf20Sopenharmony_ci WARN_ON(!IS_ALIGNED(end, fs_info->sectorsize)); 15478c2ecf20Sopenharmony_ci end--; 15488c2ecf20Sopenharmony_ci } 15498c2ecf20Sopenharmony_ci } else { 15508c2ecf20Sopenharmony_ci end = (u64)-1; 15518c2ecf20Sopenharmony_ci } 15528c2ecf20Sopenharmony_ci 15538c2ecf20Sopenharmony_ci /* the lock_extent waits for readpage to complete */ 15548c2ecf20Sopenharmony_ci lock_extent(&BTRFS_I(inode)->io_tree, start, end); 15558c2ecf20Sopenharmony_ci btrfs_drop_extent_cache(BTRFS_I(inode), start, end, 1); 15568c2ecf20Sopenharmony_ci unlock_extent(&BTRFS_I(inode)->io_tree, start, end); 15578c2ecf20Sopenharmony_ci } 15588c2ecf20Sopenharmony_ci return 0; 15598c2ecf20Sopenharmony_ci} 15608c2ecf20Sopenharmony_ci 15618c2ecf20Sopenharmony_cistatic int find_next_key(struct btrfs_path *path, int level, 15628c2ecf20Sopenharmony_ci struct btrfs_key *key) 15638c2ecf20Sopenharmony_ci 15648c2ecf20Sopenharmony_ci{ 15658c2ecf20Sopenharmony_ci while (level < BTRFS_MAX_LEVEL) { 15668c2ecf20Sopenharmony_ci if (!path->nodes[level]) 15678c2ecf20Sopenharmony_ci break; 15688c2ecf20Sopenharmony_ci if (path->slots[level] + 1 < 15698c2ecf20Sopenharmony_ci btrfs_header_nritems(path->nodes[level])) { 15708c2ecf20Sopenharmony_ci btrfs_node_key_to_cpu(path->nodes[level], key, 15718c2ecf20Sopenharmony_ci path->slots[level] + 1); 15728c2ecf20Sopenharmony_ci return 0; 15738c2ecf20Sopenharmony_ci } 15748c2ecf20Sopenharmony_ci level++; 15758c2ecf20Sopenharmony_ci } 15768c2ecf20Sopenharmony_ci return 1; 15778c2ecf20Sopenharmony_ci} 15788c2ecf20Sopenharmony_ci 15798c2ecf20Sopenharmony_ci/* 15808c2ecf20Sopenharmony_ci * Insert current subvolume into reloc_control::dirty_subvol_roots 15818c2ecf20Sopenharmony_ci */ 15828c2ecf20Sopenharmony_cistatic void insert_dirty_subvol(struct btrfs_trans_handle *trans, 15838c2ecf20Sopenharmony_ci struct reloc_control *rc, 15848c2ecf20Sopenharmony_ci struct btrfs_root *root) 15858c2ecf20Sopenharmony_ci{ 15868c2ecf20Sopenharmony_ci struct btrfs_root *reloc_root = root->reloc_root; 15878c2ecf20Sopenharmony_ci struct btrfs_root_item *reloc_root_item; 15888c2ecf20Sopenharmony_ci 15898c2ecf20Sopenharmony_ci /* @root must be a subvolume tree root with a valid reloc tree */ 15908c2ecf20Sopenharmony_ci ASSERT(root->root_key.objectid != BTRFS_TREE_RELOC_OBJECTID); 15918c2ecf20Sopenharmony_ci ASSERT(reloc_root); 15928c2ecf20Sopenharmony_ci 15938c2ecf20Sopenharmony_ci reloc_root_item = &reloc_root->root_item; 15948c2ecf20Sopenharmony_ci memset(&reloc_root_item->drop_progress, 0, 15958c2ecf20Sopenharmony_ci sizeof(reloc_root_item->drop_progress)); 15968c2ecf20Sopenharmony_ci reloc_root_item->drop_level = 0; 15978c2ecf20Sopenharmony_ci btrfs_set_root_refs(reloc_root_item, 0); 15988c2ecf20Sopenharmony_ci btrfs_update_reloc_root(trans, root); 15998c2ecf20Sopenharmony_ci 16008c2ecf20Sopenharmony_ci if (list_empty(&root->reloc_dirty_list)) { 16018c2ecf20Sopenharmony_ci btrfs_grab_root(root); 16028c2ecf20Sopenharmony_ci list_add_tail(&root->reloc_dirty_list, &rc->dirty_subvol_roots); 16038c2ecf20Sopenharmony_ci } 16048c2ecf20Sopenharmony_ci} 16058c2ecf20Sopenharmony_ci 16068c2ecf20Sopenharmony_cistatic int clean_dirty_subvols(struct reloc_control *rc) 16078c2ecf20Sopenharmony_ci{ 16088c2ecf20Sopenharmony_ci struct btrfs_root *root; 16098c2ecf20Sopenharmony_ci struct btrfs_root *next; 16108c2ecf20Sopenharmony_ci int ret = 0; 16118c2ecf20Sopenharmony_ci int ret2; 16128c2ecf20Sopenharmony_ci 16138c2ecf20Sopenharmony_ci list_for_each_entry_safe(root, next, &rc->dirty_subvol_roots, 16148c2ecf20Sopenharmony_ci reloc_dirty_list) { 16158c2ecf20Sopenharmony_ci if (root->root_key.objectid != BTRFS_TREE_RELOC_OBJECTID) { 16168c2ecf20Sopenharmony_ci /* Merged subvolume, cleanup its reloc root */ 16178c2ecf20Sopenharmony_ci struct btrfs_root *reloc_root = root->reloc_root; 16188c2ecf20Sopenharmony_ci 16198c2ecf20Sopenharmony_ci list_del_init(&root->reloc_dirty_list); 16208c2ecf20Sopenharmony_ci root->reloc_root = NULL; 16218c2ecf20Sopenharmony_ci /* 16228c2ecf20Sopenharmony_ci * Need barrier to ensure clear_bit() only happens after 16238c2ecf20Sopenharmony_ci * root->reloc_root = NULL. Pairs with have_reloc_root. 16248c2ecf20Sopenharmony_ci */ 16258c2ecf20Sopenharmony_ci smp_wmb(); 16268c2ecf20Sopenharmony_ci clear_bit(BTRFS_ROOT_DEAD_RELOC_TREE, &root->state); 16278c2ecf20Sopenharmony_ci if (reloc_root) { 16288c2ecf20Sopenharmony_ci /* 16298c2ecf20Sopenharmony_ci * btrfs_drop_snapshot drops our ref we hold for 16308c2ecf20Sopenharmony_ci * ->reloc_root. If it fails however we must 16318c2ecf20Sopenharmony_ci * drop the ref ourselves. 16328c2ecf20Sopenharmony_ci */ 16338c2ecf20Sopenharmony_ci ret2 = btrfs_drop_snapshot(reloc_root, 0, 1); 16348c2ecf20Sopenharmony_ci if (ret2 < 0) { 16358c2ecf20Sopenharmony_ci btrfs_put_root(reloc_root); 16368c2ecf20Sopenharmony_ci if (!ret) 16378c2ecf20Sopenharmony_ci ret = ret2; 16388c2ecf20Sopenharmony_ci } 16398c2ecf20Sopenharmony_ci } 16408c2ecf20Sopenharmony_ci btrfs_put_root(root); 16418c2ecf20Sopenharmony_ci } else { 16428c2ecf20Sopenharmony_ci /* Orphan reloc tree, just clean it up */ 16438c2ecf20Sopenharmony_ci ret2 = btrfs_drop_snapshot(root, 0, 1); 16448c2ecf20Sopenharmony_ci if (ret2 < 0) { 16458c2ecf20Sopenharmony_ci btrfs_put_root(root); 16468c2ecf20Sopenharmony_ci if (!ret) 16478c2ecf20Sopenharmony_ci ret = ret2; 16488c2ecf20Sopenharmony_ci } 16498c2ecf20Sopenharmony_ci } 16508c2ecf20Sopenharmony_ci } 16518c2ecf20Sopenharmony_ci return ret; 16528c2ecf20Sopenharmony_ci} 16538c2ecf20Sopenharmony_ci 16548c2ecf20Sopenharmony_ci/* 16558c2ecf20Sopenharmony_ci * merge the relocated tree blocks in reloc tree with corresponding 16568c2ecf20Sopenharmony_ci * fs tree. 16578c2ecf20Sopenharmony_ci */ 16588c2ecf20Sopenharmony_cistatic noinline_for_stack int merge_reloc_root(struct reloc_control *rc, 16598c2ecf20Sopenharmony_ci struct btrfs_root *root) 16608c2ecf20Sopenharmony_ci{ 16618c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = rc->extent_root->fs_info; 16628c2ecf20Sopenharmony_ci struct btrfs_key key; 16638c2ecf20Sopenharmony_ci struct btrfs_key next_key; 16648c2ecf20Sopenharmony_ci struct btrfs_trans_handle *trans = NULL; 16658c2ecf20Sopenharmony_ci struct btrfs_root *reloc_root; 16668c2ecf20Sopenharmony_ci struct btrfs_root_item *root_item; 16678c2ecf20Sopenharmony_ci struct btrfs_path *path; 16688c2ecf20Sopenharmony_ci struct extent_buffer *leaf; 16698c2ecf20Sopenharmony_ci int reserve_level; 16708c2ecf20Sopenharmony_ci int level; 16718c2ecf20Sopenharmony_ci int max_level; 16728c2ecf20Sopenharmony_ci int replaced = 0; 16738c2ecf20Sopenharmony_ci int ret; 16748c2ecf20Sopenharmony_ci int err = 0; 16758c2ecf20Sopenharmony_ci u32 min_reserved; 16768c2ecf20Sopenharmony_ci 16778c2ecf20Sopenharmony_ci path = btrfs_alloc_path(); 16788c2ecf20Sopenharmony_ci if (!path) 16798c2ecf20Sopenharmony_ci return -ENOMEM; 16808c2ecf20Sopenharmony_ci path->reada = READA_FORWARD; 16818c2ecf20Sopenharmony_ci 16828c2ecf20Sopenharmony_ci reloc_root = root->reloc_root; 16838c2ecf20Sopenharmony_ci root_item = &reloc_root->root_item; 16848c2ecf20Sopenharmony_ci 16858c2ecf20Sopenharmony_ci if (btrfs_disk_key_objectid(&root_item->drop_progress) == 0) { 16868c2ecf20Sopenharmony_ci level = btrfs_root_level(root_item); 16878c2ecf20Sopenharmony_ci atomic_inc(&reloc_root->node->refs); 16888c2ecf20Sopenharmony_ci path->nodes[level] = reloc_root->node; 16898c2ecf20Sopenharmony_ci path->slots[level] = 0; 16908c2ecf20Sopenharmony_ci } else { 16918c2ecf20Sopenharmony_ci btrfs_disk_key_to_cpu(&key, &root_item->drop_progress); 16928c2ecf20Sopenharmony_ci 16938c2ecf20Sopenharmony_ci level = root_item->drop_level; 16948c2ecf20Sopenharmony_ci BUG_ON(level == 0); 16958c2ecf20Sopenharmony_ci path->lowest_level = level; 16968c2ecf20Sopenharmony_ci ret = btrfs_search_slot(NULL, reloc_root, &key, path, 0, 0); 16978c2ecf20Sopenharmony_ci path->lowest_level = 0; 16988c2ecf20Sopenharmony_ci if (ret < 0) { 16998c2ecf20Sopenharmony_ci btrfs_free_path(path); 17008c2ecf20Sopenharmony_ci return ret; 17018c2ecf20Sopenharmony_ci } 17028c2ecf20Sopenharmony_ci 17038c2ecf20Sopenharmony_ci btrfs_node_key_to_cpu(path->nodes[level], &next_key, 17048c2ecf20Sopenharmony_ci path->slots[level]); 17058c2ecf20Sopenharmony_ci WARN_ON(memcmp(&key, &next_key, sizeof(key))); 17068c2ecf20Sopenharmony_ci 17078c2ecf20Sopenharmony_ci btrfs_unlock_up_safe(path, 0); 17088c2ecf20Sopenharmony_ci } 17098c2ecf20Sopenharmony_ci 17108c2ecf20Sopenharmony_ci /* 17118c2ecf20Sopenharmony_ci * In merge_reloc_root(), we modify the upper level pointer to swap the 17128c2ecf20Sopenharmony_ci * tree blocks between reloc tree and subvolume tree. Thus for tree 17138c2ecf20Sopenharmony_ci * block COW, we COW at most from level 1 to root level for each tree. 17148c2ecf20Sopenharmony_ci * 17158c2ecf20Sopenharmony_ci * Thus the needed metadata size is at most root_level * nodesize, 17168c2ecf20Sopenharmony_ci * and * 2 since we have two trees to COW. 17178c2ecf20Sopenharmony_ci */ 17188c2ecf20Sopenharmony_ci reserve_level = max_t(int, 1, btrfs_root_level(root_item)); 17198c2ecf20Sopenharmony_ci min_reserved = fs_info->nodesize * reserve_level * 2; 17208c2ecf20Sopenharmony_ci memset(&next_key, 0, sizeof(next_key)); 17218c2ecf20Sopenharmony_ci 17228c2ecf20Sopenharmony_ci while (1) { 17238c2ecf20Sopenharmony_ci ret = btrfs_block_rsv_refill(root, rc->block_rsv, min_reserved, 17248c2ecf20Sopenharmony_ci BTRFS_RESERVE_FLUSH_LIMIT); 17258c2ecf20Sopenharmony_ci if (ret) { 17268c2ecf20Sopenharmony_ci err = ret; 17278c2ecf20Sopenharmony_ci goto out; 17288c2ecf20Sopenharmony_ci } 17298c2ecf20Sopenharmony_ci trans = btrfs_start_transaction(root, 0); 17308c2ecf20Sopenharmony_ci if (IS_ERR(trans)) { 17318c2ecf20Sopenharmony_ci err = PTR_ERR(trans); 17328c2ecf20Sopenharmony_ci trans = NULL; 17338c2ecf20Sopenharmony_ci goto out; 17348c2ecf20Sopenharmony_ci } 17358c2ecf20Sopenharmony_ci 17368c2ecf20Sopenharmony_ci /* 17378c2ecf20Sopenharmony_ci * At this point we no longer have a reloc_control, so we can't 17388c2ecf20Sopenharmony_ci * depend on btrfs_init_reloc_root to update our last_trans. 17398c2ecf20Sopenharmony_ci * 17408c2ecf20Sopenharmony_ci * But that's ok, we started the trans handle on our 17418c2ecf20Sopenharmony_ci * corresponding fs_root, which means it's been added to the 17428c2ecf20Sopenharmony_ci * dirty list. At commit time we'll still call 17438c2ecf20Sopenharmony_ci * btrfs_update_reloc_root() and update our root item 17448c2ecf20Sopenharmony_ci * appropriately. 17458c2ecf20Sopenharmony_ci */ 17468c2ecf20Sopenharmony_ci reloc_root->last_trans = trans->transid; 17478c2ecf20Sopenharmony_ci trans->block_rsv = rc->block_rsv; 17488c2ecf20Sopenharmony_ci 17498c2ecf20Sopenharmony_ci replaced = 0; 17508c2ecf20Sopenharmony_ci max_level = level; 17518c2ecf20Sopenharmony_ci 17528c2ecf20Sopenharmony_ci ret = walk_down_reloc_tree(reloc_root, path, &level); 17538c2ecf20Sopenharmony_ci if (ret < 0) { 17548c2ecf20Sopenharmony_ci err = ret; 17558c2ecf20Sopenharmony_ci goto out; 17568c2ecf20Sopenharmony_ci } 17578c2ecf20Sopenharmony_ci if (ret > 0) 17588c2ecf20Sopenharmony_ci break; 17598c2ecf20Sopenharmony_ci 17608c2ecf20Sopenharmony_ci if (!find_next_key(path, level, &key) && 17618c2ecf20Sopenharmony_ci btrfs_comp_cpu_keys(&next_key, &key) >= 0) { 17628c2ecf20Sopenharmony_ci ret = 0; 17638c2ecf20Sopenharmony_ci } else { 17648c2ecf20Sopenharmony_ci ret = replace_path(trans, rc, root, reloc_root, path, 17658c2ecf20Sopenharmony_ci &next_key, level, max_level); 17668c2ecf20Sopenharmony_ci } 17678c2ecf20Sopenharmony_ci if (ret < 0) { 17688c2ecf20Sopenharmony_ci err = ret; 17698c2ecf20Sopenharmony_ci goto out; 17708c2ecf20Sopenharmony_ci } 17718c2ecf20Sopenharmony_ci 17728c2ecf20Sopenharmony_ci if (ret > 0) { 17738c2ecf20Sopenharmony_ci level = ret; 17748c2ecf20Sopenharmony_ci btrfs_node_key_to_cpu(path->nodes[level], &key, 17758c2ecf20Sopenharmony_ci path->slots[level]); 17768c2ecf20Sopenharmony_ci replaced = 1; 17778c2ecf20Sopenharmony_ci } 17788c2ecf20Sopenharmony_ci 17798c2ecf20Sopenharmony_ci ret = walk_up_reloc_tree(reloc_root, path, &level); 17808c2ecf20Sopenharmony_ci if (ret > 0) 17818c2ecf20Sopenharmony_ci break; 17828c2ecf20Sopenharmony_ci 17838c2ecf20Sopenharmony_ci BUG_ON(level == 0); 17848c2ecf20Sopenharmony_ci /* 17858c2ecf20Sopenharmony_ci * save the merging progress in the drop_progress. 17868c2ecf20Sopenharmony_ci * this is OK since root refs == 1 in this case. 17878c2ecf20Sopenharmony_ci */ 17888c2ecf20Sopenharmony_ci btrfs_node_key(path->nodes[level], &root_item->drop_progress, 17898c2ecf20Sopenharmony_ci path->slots[level]); 17908c2ecf20Sopenharmony_ci root_item->drop_level = level; 17918c2ecf20Sopenharmony_ci 17928c2ecf20Sopenharmony_ci btrfs_end_transaction_throttle(trans); 17938c2ecf20Sopenharmony_ci trans = NULL; 17948c2ecf20Sopenharmony_ci 17958c2ecf20Sopenharmony_ci btrfs_btree_balance_dirty(fs_info); 17968c2ecf20Sopenharmony_ci 17978c2ecf20Sopenharmony_ci if (replaced && rc->stage == UPDATE_DATA_PTRS) 17988c2ecf20Sopenharmony_ci invalidate_extent_cache(root, &key, &next_key); 17998c2ecf20Sopenharmony_ci } 18008c2ecf20Sopenharmony_ci 18018c2ecf20Sopenharmony_ci /* 18028c2ecf20Sopenharmony_ci * handle the case only one block in the fs tree need to be 18038c2ecf20Sopenharmony_ci * relocated and the block is tree root. 18048c2ecf20Sopenharmony_ci */ 18058c2ecf20Sopenharmony_ci leaf = btrfs_lock_root_node(root); 18068c2ecf20Sopenharmony_ci ret = btrfs_cow_block(trans, root, leaf, NULL, 0, &leaf, 18078c2ecf20Sopenharmony_ci BTRFS_NESTING_COW); 18088c2ecf20Sopenharmony_ci btrfs_tree_unlock(leaf); 18098c2ecf20Sopenharmony_ci free_extent_buffer(leaf); 18108c2ecf20Sopenharmony_ci if (ret < 0) 18118c2ecf20Sopenharmony_ci err = ret; 18128c2ecf20Sopenharmony_ciout: 18138c2ecf20Sopenharmony_ci btrfs_free_path(path); 18148c2ecf20Sopenharmony_ci 18158c2ecf20Sopenharmony_ci if (err == 0) 18168c2ecf20Sopenharmony_ci insert_dirty_subvol(trans, rc, root); 18178c2ecf20Sopenharmony_ci 18188c2ecf20Sopenharmony_ci if (trans) 18198c2ecf20Sopenharmony_ci btrfs_end_transaction_throttle(trans); 18208c2ecf20Sopenharmony_ci 18218c2ecf20Sopenharmony_ci btrfs_btree_balance_dirty(fs_info); 18228c2ecf20Sopenharmony_ci 18238c2ecf20Sopenharmony_ci if (replaced && rc->stage == UPDATE_DATA_PTRS) 18248c2ecf20Sopenharmony_ci invalidate_extent_cache(root, &key, &next_key); 18258c2ecf20Sopenharmony_ci 18268c2ecf20Sopenharmony_ci return err; 18278c2ecf20Sopenharmony_ci} 18288c2ecf20Sopenharmony_ci 18298c2ecf20Sopenharmony_cistatic noinline_for_stack 18308c2ecf20Sopenharmony_ciint prepare_to_merge(struct reloc_control *rc, int err) 18318c2ecf20Sopenharmony_ci{ 18328c2ecf20Sopenharmony_ci struct btrfs_root *root = rc->extent_root; 18338c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = root->fs_info; 18348c2ecf20Sopenharmony_ci struct btrfs_root *reloc_root; 18358c2ecf20Sopenharmony_ci struct btrfs_trans_handle *trans; 18368c2ecf20Sopenharmony_ci LIST_HEAD(reloc_roots); 18378c2ecf20Sopenharmony_ci u64 num_bytes = 0; 18388c2ecf20Sopenharmony_ci int ret; 18398c2ecf20Sopenharmony_ci 18408c2ecf20Sopenharmony_ci mutex_lock(&fs_info->reloc_mutex); 18418c2ecf20Sopenharmony_ci rc->merging_rsv_size += fs_info->nodesize * (BTRFS_MAX_LEVEL - 1) * 2; 18428c2ecf20Sopenharmony_ci rc->merging_rsv_size += rc->nodes_relocated * 2; 18438c2ecf20Sopenharmony_ci mutex_unlock(&fs_info->reloc_mutex); 18448c2ecf20Sopenharmony_ci 18458c2ecf20Sopenharmony_ciagain: 18468c2ecf20Sopenharmony_ci if (!err) { 18478c2ecf20Sopenharmony_ci num_bytes = rc->merging_rsv_size; 18488c2ecf20Sopenharmony_ci ret = btrfs_block_rsv_add(root, rc->block_rsv, num_bytes, 18498c2ecf20Sopenharmony_ci BTRFS_RESERVE_FLUSH_ALL); 18508c2ecf20Sopenharmony_ci if (ret) 18518c2ecf20Sopenharmony_ci err = ret; 18528c2ecf20Sopenharmony_ci } 18538c2ecf20Sopenharmony_ci 18548c2ecf20Sopenharmony_ci trans = btrfs_join_transaction(rc->extent_root); 18558c2ecf20Sopenharmony_ci if (IS_ERR(trans)) { 18568c2ecf20Sopenharmony_ci if (!err) 18578c2ecf20Sopenharmony_ci btrfs_block_rsv_release(fs_info, rc->block_rsv, 18588c2ecf20Sopenharmony_ci num_bytes, NULL); 18598c2ecf20Sopenharmony_ci return PTR_ERR(trans); 18608c2ecf20Sopenharmony_ci } 18618c2ecf20Sopenharmony_ci 18628c2ecf20Sopenharmony_ci if (!err) { 18638c2ecf20Sopenharmony_ci if (num_bytes != rc->merging_rsv_size) { 18648c2ecf20Sopenharmony_ci btrfs_end_transaction(trans); 18658c2ecf20Sopenharmony_ci btrfs_block_rsv_release(fs_info, rc->block_rsv, 18668c2ecf20Sopenharmony_ci num_bytes, NULL); 18678c2ecf20Sopenharmony_ci goto again; 18688c2ecf20Sopenharmony_ci } 18698c2ecf20Sopenharmony_ci } 18708c2ecf20Sopenharmony_ci 18718c2ecf20Sopenharmony_ci rc->merge_reloc_tree = 1; 18728c2ecf20Sopenharmony_ci 18738c2ecf20Sopenharmony_ci while (!list_empty(&rc->reloc_roots)) { 18748c2ecf20Sopenharmony_ci reloc_root = list_entry(rc->reloc_roots.next, 18758c2ecf20Sopenharmony_ci struct btrfs_root, root_list); 18768c2ecf20Sopenharmony_ci list_del_init(&reloc_root->root_list); 18778c2ecf20Sopenharmony_ci 18788c2ecf20Sopenharmony_ci root = btrfs_get_fs_root(fs_info, reloc_root->root_key.offset, 18798c2ecf20Sopenharmony_ci false); 18808c2ecf20Sopenharmony_ci BUG_ON(IS_ERR(root)); 18818c2ecf20Sopenharmony_ci BUG_ON(root->reloc_root != reloc_root); 18828c2ecf20Sopenharmony_ci 18838c2ecf20Sopenharmony_ci /* 18848c2ecf20Sopenharmony_ci * set reference count to 1, so btrfs_recover_relocation 18858c2ecf20Sopenharmony_ci * knows it should resumes merging 18868c2ecf20Sopenharmony_ci */ 18878c2ecf20Sopenharmony_ci if (!err) 18888c2ecf20Sopenharmony_ci btrfs_set_root_refs(&reloc_root->root_item, 1); 18898c2ecf20Sopenharmony_ci btrfs_update_reloc_root(trans, root); 18908c2ecf20Sopenharmony_ci 18918c2ecf20Sopenharmony_ci list_add(&reloc_root->root_list, &reloc_roots); 18928c2ecf20Sopenharmony_ci btrfs_put_root(root); 18938c2ecf20Sopenharmony_ci } 18948c2ecf20Sopenharmony_ci 18958c2ecf20Sopenharmony_ci list_splice(&reloc_roots, &rc->reloc_roots); 18968c2ecf20Sopenharmony_ci 18978c2ecf20Sopenharmony_ci if (!err) 18988c2ecf20Sopenharmony_ci err = btrfs_commit_transaction(trans); 18998c2ecf20Sopenharmony_ci else 19008c2ecf20Sopenharmony_ci btrfs_end_transaction(trans); 19018c2ecf20Sopenharmony_ci return err; 19028c2ecf20Sopenharmony_ci} 19038c2ecf20Sopenharmony_ci 19048c2ecf20Sopenharmony_cistatic noinline_for_stack 19058c2ecf20Sopenharmony_civoid free_reloc_roots(struct list_head *list) 19068c2ecf20Sopenharmony_ci{ 19078c2ecf20Sopenharmony_ci struct btrfs_root *reloc_root, *tmp; 19088c2ecf20Sopenharmony_ci 19098c2ecf20Sopenharmony_ci list_for_each_entry_safe(reloc_root, tmp, list, root_list) 19108c2ecf20Sopenharmony_ci __del_reloc_root(reloc_root); 19118c2ecf20Sopenharmony_ci} 19128c2ecf20Sopenharmony_ci 19138c2ecf20Sopenharmony_cistatic noinline_for_stack 19148c2ecf20Sopenharmony_civoid merge_reloc_roots(struct reloc_control *rc) 19158c2ecf20Sopenharmony_ci{ 19168c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = rc->extent_root->fs_info; 19178c2ecf20Sopenharmony_ci struct btrfs_root *root; 19188c2ecf20Sopenharmony_ci struct btrfs_root *reloc_root; 19198c2ecf20Sopenharmony_ci LIST_HEAD(reloc_roots); 19208c2ecf20Sopenharmony_ci int found = 0; 19218c2ecf20Sopenharmony_ci int ret = 0; 19228c2ecf20Sopenharmony_ciagain: 19238c2ecf20Sopenharmony_ci root = rc->extent_root; 19248c2ecf20Sopenharmony_ci 19258c2ecf20Sopenharmony_ci /* 19268c2ecf20Sopenharmony_ci * this serializes us with btrfs_record_root_in_transaction, 19278c2ecf20Sopenharmony_ci * we have to make sure nobody is in the middle of 19288c2ecf20Sopenharmony_ci * adding their roots to the list while we are 19298c2ecf20Sopenharmony_ci * doing this splice 19308c2ecf20Sopenharmony_ci */ 19318c2ecf20Sopenharmony_ci mutex_lock(&fs_info->reloc_mutex); 19328c2ecf20Sopenharmony_ci list_splice_init(&rc->reloc_roots, &reloc_roots); 19338c2ecf20Sopenharmony_ci mutex_unlock(&fs_info->reloc_mutex); 19348c2ecf20Sopenharmony_ci 19358c2ecf20Sopenharmony_ci while (!list_empty(&reloc_roots)) { 19368c2ecf20Sopenharmony_ci found = 1; 19378c2ecf20Sopenharmony_ci reloc_root = list_entry(reloc_roots.next, 19388c2ecf20Sopenharmony_ci struct btrfs_root, root_list); 19398c2ecf20Sopenharmony_ci 19408c2ecf20Sopenharmony_ci root = btrfs_get_fs_root(fs_info, reloc_root->root_key.offset, 19418c2ecf20Sopenharmony_ci false); 19428c2ecf20Sopenharmony_ci if (btrfs_root_refs(&reloc_root->root_item) > 0) { 19438c2ecf20Sopenharmony_ci BUG_ON(IS_ERR(root)); 19448c2ecf20Sopenharmony_ci BUG_ON(root->reloc_root != reloc_root); 19458c2ecf20Sopenharmony_ci ret = merge_reloc_root(rc, root); 19468c2ecf20Sopenharmony_ci btrfs_put_root(root); 19478c2ecf20Sopenharmony_ci if (ret) { 19488c2ecf20Sopenharmony_ci if (list_empty(&reloc_root->root_list)) 19498c2ecf20Sopenharmony_ci list_add_tail(&reloc_root->root_list, 19508c2ecf20Sopenharmony_ci &reloc_roots); 19518c2ecf20Sopenharmony_ci goto out; 19528c2ecf20Sopenharmony_ci } 19538c2ecf20Sopenharmony_ci } else { 19548c2ecf20Sopenharmony_ci if (!IS_ERR(root)) { 19558c2ecf20Sopenharmony_ci if (root->reloc_root == reloc_root) { 19568c2ecf20Sopenharmony_ci root->reloc_root = NULL; 19578c2ecf20Sopenharmony_ci btrfs_put_root(reloc_root); 19588c2ecf20Sopenharmony_ci } 19598c2ecf20Sopenharmony_ci clear_bit(BTRFS_ROOT_DEAD_RELOC_TREE, 19608c2ecf20Sopenharmony_ci &root->state); 19618c2ecf20Sopenharmony_ci btrfs_put_root(root); 19628c2ecf20Sopenharmony_ci } 19638c2ecf20Sopenharmony_ci 19648c2ecf20Sopenharmony_ci list_del_init(&reloc_root->root_list); 19658c2ecf20Sopenharmony_ci /* Don't forget to queue this reloc root for cleanup */ 19668c2ecf20Sopenharmony_ci list_add_tail(&reloc_root->reloc_dirty_list, 19678c2ecf20Sopenharmony_ci &rc->dirty_subvol_roots); 19688c2ecf20Sopenharmony_ci } 19698c2ecf20Sopenharmony_ci } 19708c2ecf20Sopenharmony_ci 19718c2ecf20Sopenharmony_ci if (found) { 19728c2ecf20Sopenharmony_ci found = 0; 19738c2ecf20Sopenharmony_ci goto again; 19748c2ecf20Sopenharmony_ci } 19758c2ecf20Sopenharmony_ciout: 19768c2ecf20Sopenharmony_ci if (ret) { 19778c2ecf20Sopenharmony_ci btrfs_handle_fs_error(fs_info, ret, NULL); 19788c2ecf20Sopenharmony_ci free_reloc_roots(&reloc_roots); 19798c2ecf20Sopenharmony_ci 19808c2ecf20Sopenharmony_ci /* new reloc root may be added */ 19818c2ecf20Sopenharmony_ci mutex_lock(&fs_info->reloc_mutex); 19828c2ecf20Sopenharmony_ci list_splice_init(&rc->reloc_roots, &reloc_roots); 19838c2ecf20Sopenharmony_ci mutex_unlock(&fs_info->reloc_mutex); 19848c2ecf20Sopenharmony_ci free_reloc_roots(&reloc_roots); 19858c2ecf20Sopenharmony_ci } 19868c2ecf20Sopenharmony_ci 19878c2ecf20Sopenharmony_ci /* 19888c2ecf20Sopenharmony_ci * We used to have 19898c2ecf20Sopenharmony_ci * 19908c2ecf20Sopenharmony_ci * BUG_ON(!RB_EMPTY_ROOT(&rc->reloc_root_tree.rb_root)); 19918c2ecf20Sopenharmony_ci * 19928c2ecf20Sopenharmony_ci * here, but it's wrong. If we fail to start the transaction in 19938c2ecf20Sopenharmony_ci * prepare_to_merge() we will have only 0 ref reloc roots, none of which 19948c2ecf20Sopenharmony_ci * have actually been removed from the reloc_root_tree rb tree. This is 19958c2ecf20Sopenharmony_ci * fine because we're bailing here, and we hold a reference on the root 19968c2ecf20Sopenharmony_ci * for the list that holds it, so these roots will be cleaned up when we 19978c2ecf20Sopenharmony_ci * do the reloc_dirty_list afterwards. Meanwhile the root->reloc_root 19988c2ecf20Sopenharmony_ci * will be cleaned up on unmount. 19998c2ecf20Sopenharmony_ci * 20008c2ecf20Sopenharmony_ci * The remaining nodes will be cleaned up by free_reloc_control. 20018c2ecf20Sopenharmony_ci */ 20028c2ecf20Sopenharmony_ci} 20038c2ecf20Sopenharmony_ci 20048c2ecf20Sopenharmony_cistatic void free_block_list(struct rb_root *blocks) 20058c2ecf20Sopenharmony_ci{ 20068c2ecf20Sopenharmony_ci struct tree_block *block; 20078c2ecf20Sopenharmony_ci struct rb_node *rb_node; 20088c2ecf20Sopenharmony_ci while ((rb_node = rb_first(blocks))) { 20098c2ecf20Sopenharmony_ci block = rb_entry(rb_node, struct tree_block, rb_node); 20108c2ecf20Sopenharmony_ci rb_erase(rb_node, blocks); 20118c2ecf20Sopenharmony_ci kfree(block); 20128c2ecf20Sopenharmony_ci } 20138c2ecf20Sopenharmony_ci} 20148c2ecf20Sopenharmony_ci 20158c2ecf20Sopenharmony_cistatic int record_reloc_root_in_trans(struct btrfs_trans_handle *trans, 20168c2ecf20Sopenharmony_ci struct btrfs_root *reloc_root) 20178c2ecf20Sopenharmony_ci{ 20188c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = reloc_root->fs_info; 20198c2ecf20Sopenharmony_ci struct btrfs_root *root; 20208c2ecf20Sopenharmony_ci int ret; 20218c2ecf20Sopenharmony_ci 20228c2ecf20Sopenharmony_ci if (reloc_root->last_trans == trans->transid) 20238c2ecf20Sopenharmony_ci return 0; 20248c2ecf20Sopenharmony_ci 20258c2ecf20Sopenharmony_ci root = btrfs_get_fs_root(fs_info, reloc_root->root_key.offset, false); 20268c2ecf20Sopenharmony_ci BUG_ON(IS_ERR(root)); 20278c2ecf20Sopenharmony_ci BUG_ON(root->reloc_root != reloc_root); 20288c2ecf20Sopenharmony_ci ret = btrfs_record_root_in_trans(trans, root); 20298c2ecf20Sopenharmony_ci btrfs_put_root(root); 20308c2ecf20Sopenharmony_ci 20318c2ecf20Sopenharmony_ci return ret; 20328c2ecf20Sopenharmony_ci} 20338c2ecf20Sopenharmony_ci 20348c2ecf20Sopenharmony_cistatic noinline_for_stack 20358c2ecf20Sopenharmony_cistruct btrfs_root *select_reloc_root(struct btrfs_trans_handle *trans, 20368c2ecf20Sopenharmony_ci struct reloc_control *rc, 20378c2ecf20Sopenharmony_ci struct btrfs_backref_node *node, 20388c2ecf20Sopenharmony_ci struct btrfs_backref_edge *edges[]) 20398c2ecf20Sopenharmony_ci{ 20408c2ecf20Sopenharmony_ci struct btrfs_backref_node *next; 20418c2ecf20Sopenharmony_ci struct btrfs_root *root; 20428c2ecf20Sopenharmony_ci int index = 0; 20438c2ecf20Sopenharmony_ci 20448c2ecf20Sopenharmony_ci next = node; 20458c2ecf20Sopenharmony_ci while (1) { 20468c2ecf20Sopenharmony_ci cond_resched(); 20478c2ecf20Sopenharmony_ci next = walk_up_backref(next, edges, &index); 20488c2ecf20Sopenharmony_ci root = next->root; 20498c2ecf20Sopenharmony_ci BUG_ON(!root); 20508c2ecf20Sopenharmony_ci BUG_ON(!test_bit(BTRFS_ROOT_SHAREABLE, &root->state)); 20518c2ecf20Sopenharmony_ci 20528c2ecf20Sopenharmony_ci if (root->root_key.objectid == BTRFS_TREE_RELOC_OBJECTID) { 20538c2ecf20Sopenharmony_ci record_reloc_root_in_trans(trans, root); 20548c2ecf20Sopenharmony_ci break; 20558c2ecf20Sopenharmony_ci } 20568c2ecf20Sopenharmony_ci 20578c2ecf20Sopenharmony_ci btrfs_record_root_in_trans(trans, root); 20588c2ecf20Sopenharmony_ci root = root->reloc_root; 20598c2ecf20Sopenharmony_ci 20608c2ecf20Sopenharmony_ci if (next->new_bytenr != root->node->start) { 20618c2ecf20Sopenharmony_ci BUG_ON(next->new_bytenr); 20628c2ecf20Sopenharmony_ci BUG_ON(!list_empty(&next->list)); 20638c2ecf20Sopenharmony_ci next->new_bytenr = root->node->start; 20648c2ecf20Sopenharmony_ci btrfs_put_root(next->root); 20658c2ecf20Sopenharmony_ci next->root = btrfs_grab_root(root); 20668c2ecf20Sopenharmony_ci ASSERT(next->root); 20678c2ecf20Sopenharmony_ci list_add_tail(&next->list, 20688c2ecf20Sopenharmony_ci &rc->backref_cache.changed); 20698c2ecf20Sopenharmony_ci mark_block_processed(rc, next); 20708c2ecf20Sopenharmony_ci break; 20718c2ecf20Sopenharmony_ci } 20728c2ecf20Sopenharmony_ci 20738c2ecf20Sopenharmony_ci WARN_ON(1); 20748c2ecf20Sopenharmony_ci root = NULL; 20758c2ecf20Sopenharmony_ci next = walk_down_backref(edges, &index); 20768c2ecf20Sopenharmony_ci if (!next || next->level <= node->level) 20778c2ecf20Sopenharmony_ci break; 20788c2ecf20Sopenharmony_ci } 20798c2ecf20Sopenharmony_ci if (!root) 20808c2ecf20Sopenharmony_ci return NULL; 20818c2ecf20Sopenharmony_ci 20828c2ecf20Sopenharmony_ci next = node; 20838c2ecf20Sopenharmony_ci /* setup backref node path for btrfs_reloc_cow_block */ 20848c2ecf20Sopenharmony_ci while (1) { 20858c2ecf20Sopenharmony_ci rc->backref_cache.path[next->level] = next; 20868c2ecf20Sopenharmony_ci if (--index < 0) 20878c2ecf20Sopenharmony_ci break; 20888c2ecf20Sopenharmony_ci next = edges[index]->node[UPPER]; 20898c2ecf20Sopenharmony_ci } 20908c2ecf20Sopenharmony_ci return root; 20918c2ecf20Sopenharmony_ci} 20928c2ecf20Sopenharmony_ci 20938c2ecf20Sopenharmony_ci/* 20948c2ecf20Sopenharmony_ci * Select a tree root for relocation. 20958c2ecf20Sopenharmony_ci * 20968c2ecf20Sopenharmony_ci * Return NULL if the block is not shareable. We should use do_relocation() in 20978c2ecf20Sopenharmony_ci * this case. 20988c2ecf20Sopenharmony_ci * 20998c2ecf20Sopenharmony_ci * Return a tree root pointer if the block is shareable. 21008c2ecf20Sopenharmony_ci * Return -ENOENT if the block is root of reloc tree. 21018c2ecf20Sopenharmony_ci */ 21028c2ecf20Sopenharmony_cistatic noinline_for_stack 21038c2ecf20Sopenharmony_cistruct btrfs_root *select_one_root(struct btrfs_backref_node *node) 21048c2ecf20Sopenharmony_ci{ 21058c2ecf20Sopenharmony_ci struct btrfs_backref_node *next; 21068c2ecf20Sopenharmony_ci struct btrfs_root *root; 21078c2ecf20Sopenharmony_ci struct btrfs_root *fs_root = NULL; 21088c2ecf20Sopenharmony_ci struct btrfs_backref_edge *edges[BTRFS_MAX_LEVEL - 1]; 21098c2ecf20Sopenharmony_ci int index = 0; 21108c2ecf20Sopenharmony_ci 21118c2ecf20Sopenharmony_ci next = node; 21128c2ecf20Sopenharmony_ci while (1) { 21138c2ecf20Sopenharmony_ci cond_resched(); 21148c2ecf20Sopenharmony_ci next = walk_up_backref(next, edges, &index); 21158c2ecf20Sopenharmony_ci root = next->root; 21168c2ecf20Sopenharmony_ci BUG_ON(!root); 21178c2ecf20Sopenharmony_ci 21188c2ecf20Sopenharmony_ci /* No other choice for non-shareable tree */ 21198c2ecf20Sopenharmony_ci if (!test_bit(BTRFS_ROOT_SHAREABLE, &root->state)) 21208c2ecf20Sopenharmony_ci return root; 21218c2ecf20Sopenharmony_ci 21228c2ecf20Sopenharmony_ci if (root->root_key.objectid != BTRFS_TREE_RELOC_OBJECTID) 21238c2ecf20Sopenharmony_ci fs_root = root; 21248c2ecf20Sopenharmony_ci 21258c2ecf20Sopenharmony_ci if (next != node) 21268c2ecf20Sopenharmony_ci return NULL; 21278c2ecf20Sopenharmony_ci 21288c2ecf20Sopenharmony_ci next = walk_down_backref(edges, &index); 21298c2ecf20Sopenharmony_ci if (!next || next->level <= node->level) 21308c2ecf20Sopenharmony_ci break; 21318c2ecf20Sopenharmony_ci } 21328c2ecf20Sopenharmony_ci 21338c2ecf20Sopenharmony_ci if (!fs_root) 21348c2ecf20Sopenharmony_ci return ERR_PTR(-ENOENT); 21358c2ecf20Sopenharmony_ci return fs_root; 21368c2ecf20Sopenharmony_ci} 21378c2ecf20Sopenharmony_ci 21388c2ecf20Sopenharmony_cistatic noinline_for_stack 21398c2ecf20Sopenharmony_ciu64 calcu_metadata_size(struct reloc_control *rc, 21408c2ecf20Sopenharmony_ci struct btrfs_backref_node *node, int reserve) 21418c2ecf20Sopenharmony_ci{ 21428c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = rc->extent_root->fs_info; 21438c2ecf20Sopenharmony_ci struct btrfs_backref_node *next = node; 21448c2ecf20Sopenharmony_ci struct btrfs_backref_edge *edge; 21458c2ecf20Sopenharmony_ci struct btrfs_backref_edge *edges[BTRFS_MAX_LEVEL - 1]; 21468c2ecf20Sopenharmony_ci u64 num_bytes = 0; 21478c2ecf20Sopenharmony_ci int index = 0; 21488c2ecf20Sopenharmony_ci 21498c2ecf20Sopenharmony_ci BUG_ON(reserve && node->processed); 21508c2ecf20Sopenharmony_ci 21518c2ecf20Sopenharmony_ci while (next) { 21528c2ecf20Sopenharmony_ci cond_resched(); 21538c2ecf20Sopenharmony_ci while (1) { 21548c2ecf20Sopenharmony_ci if (next->processed && (reserve || next != node)) 21558c2ecf20Sopenharmony_ci break; 21568c2ecf20Sopenharmony_ci 21578c2ecf20Sopenharmony_ci num_bytes += fs_info->nodesize; 21588c2ecf20Sopenharmony_ci 21598c2ecf20Sopenharmony_ci if (list_empty(&next->upper)) 21608c2ecf20Sopenharmony_ci break; 21618c2ecf20Sopenharmony_ci 21628c2ecf20Sopenharmony_ci edge = list_entry(next->upper.next, 21638c2ecf20Sopenharmony_ci struct btrfs_backref_edge, list[LOWER]); 21648c2ecf20Sopenharmony_ci edges[index++] = edge; 21658c2ecf20Sopenharmony_ci next = edge->node[UPPER]; 21668c2ecf20Sopenharmony_ci } 21678c2ecf20Sopenharmony_ci next = walk_down_backref(edges, &index); 21688c2ecf20Sopenharmony_ci } 21698c2ecf20Sopenharmony_ci return num_bytes; 21708c2ecf20Sopenharmony_ci} 21718c2ecf20Sopenharmony_ci 21728c2ecf20Sopenharmony_cistatic int reserve_metadata_space(struct btrfs_trans_handle *trans, 21738c2ecf20Sopenharmony_ci struct reloc_control *rc, 21748c2ecf20Sopenharmony_ci struct btrfs_backref_node *node) 21758c2ecf20Sopenharmony_ci{ 21768c2ecf20Sopenharmony_ci struct btrfs_root *root = rc->extent_root; 21778c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = root->fs_info; 21788c2ecf20Sopenharmony_ci u64 num_bytes; 21798c2ecf20Sopenharmony_ci int ret; 21808c2ecf20Sopenharmony_ci u64 tmp; 21818c2ecf20Sopenharmony_ci 21828c2ecf20Sopenharmony_ci num_bytes = calcu_metadata_size(rc, node, 1) * 2; 21838c2ecf20Sopenharmony_ci 21848c2ecf20Sopenharmony_ci trans->block_rsv = rc->block_rsv; 21858c2ecf20Sopenharmony_ci rc->reserved_bytes += num_bytes; 21868c2ecf20Sopenharmony_ci 21878c2ecf20Sopenharmony_ci /* 21888c2ecf20Sopenharmony_ci * We are under a transaction here so we can only do limited flushing. 21898c2ecf20Sopenharmony_ci * If we get an enospc just kick back -EAGAIN so we know to drop the 21908c2ecf20Sopenharmony_ci * transaction and try to refill when we can flush all the things. 21918c2ecf20Sopenharmony_ci */ 21928c2ecf20Sopenharmony_ci ret = btrfs_block_rsv_refill(root, rc->block_rsv, num_bytes, 21938c2ecf20Sopenharmony_ci BTRFS_RESERVE_FLUSH_LIMIT); 21948c2ecf20Sopenharmony_ci if (ret) { 21958c2ecf20Sopenharmony_ci tmp = fs_info->nodesize * RELOCATION_RESERVED_NODES; 21968c2ecf20Sopenharmony_ci while (tmp <= rc->reserved_bytes) 21978c2ecf20Sopenharmony_ci tmp <<= 1; 21988c2ecf20Sopenharmony_ci /* 21998c2ecf20Sopenharmony_ci * only one thread can access block_rsv at this point, 22008c2ecf20Sopenharmony_ci * so we don't need hold lock to protect block_rsv. 22018c2ecf20Sopenharmony_ci * we expand more reservation size here to allow enough 22028c2ecf20Sopenharmony_ci * space for relocation and we will return earlier in 22038c2ecf20Sopenharmony_ci * enospc case. 22048c2ecf20Sopenharmony_ci */ 22058c2ecf20Sopenharmony_ci rc->block_rsv->size = tmp + fs_info->nodesize * 22068c2ecf20Sopenharmony_ci RELOCATION_RESERVED_NODES; 22078c2ecf20Sopenharmony_ci return -EAGAIN; 22088c2ecf20Sopenharmony_ci } 22098c2ecf20Sopenharmony_ci 22108c2ecf20Sopenharmony_ci return 0; 22118c2ecf20Sopenharmony_ci} 22128c2ecf20Sopenharmony_ci 22138c2ecf20Sopenharmony_ci/* 22148c2ecf20Sopenharmony_ci * relocate a block tree, and then update pointers in upper level 22158c2ecf20Sopenharmony_ci * blocks that reference the block to point to the new location. 22168c2ecf20Sopenharmony_ci * 22178c2ecf20Sopenharmony_ci * if called by link_to_upper, the block has already been relocated. 22188c2ecf20Sopenharmony_ci * in that case this function just updates pointers. 22198c2ecf20Sopenharmony_ci */ 22208c2ecf20Sopenharmony_cistatic int do_relocation(struct btrfs_trans_handle *trans, 22218c2ecf20Sopenharmony_ci struct reloc_control *rc, 22228c2ecf20Sopenharmony_ci struct btrfs_backref_node *node, 22238c2ecf20Sopenharmony_ci struct btrfs_key *key, 22248c2ecf20Sopenharmony_ci struct btrfs_path *path, int lowest) 22258c2ecf20Sopenharmony_ci{ 22268c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = rc->extent_root->fs_info; 22278c2ecf20Sopenharmony_ci struct btrfs_backref_node *upper; 22288c2ecf20Sopenharmony_ci struct btrfs_backref_edge *edge; 22298c2ecf20Sopenharmony_ci struct btrfs_backref_edge *edges[BTRFS_MAX_LEVEL - 1]; 22308c2ecf20Sopenharmony_ci struct btrfs_root *root; 22318c2ecf20Sopenharmony_ci struct extent_buffer *eb; 22328c2ecf20Sopenharmony_ci u32 blocksize; 22338c2ecf20Sopenharmony_ci u64 bytenr; 22348c2ecf20Sopenharmony_ci u64 generation; 22358c2ecf20Sopenharmony_ci int slot; 22368c2ecf20Sopenharmony_ci int ret; 22378c2ecf20Sopenharmony_ci int err = 0; 22388c2ecf20Sopenharmony_ci 22398c2ecf20Sopenharmony_ci BUG_ON(lowest && node->eb); 22408c2ecf20Sopenharmony_ci 22418c2ecf20Sopenharmony_ci path->lowest_level = node->level + 1; 22428c2ecf20Sopenharmony_ci rc->backref_cache.path[node->level] = node; 22438c2ecf20Sopenharmony_ci list_for_each_entry(edge, &node->upper, list[LOWER]) { 22448c2ecf20Sopenharmony_ci struct btrfs_key first_key; 22458c2ecf20Sopenharmony_ci struct btrfs_ref ref = { 0 }; 22468c2ecf20Sopenharmony_ci 22478c2ecf20Sopenharmony_ci cond_resched(); 22488c2ecf20Sopenharmony_ci 22498c2ecf20Sopenharmony_ci upper = edge->node[UPPER]; 22508c2ecf20Sopenharmony_ci root = select_reloc_root(trans, rc, upper, edges); 22518c2ecf20Sopenharmony_ci BUG_ON(!root); 22528c2ecf20Sopenharmony_ci 22538c2ecf20Sopenharmony_ci if (upper->eb && !upper->locked) { 22548c2ecf20Sopenharmony_ci if (!lowest) { 22558c2ecf20Sopenharmony_ci ret = btrfs_bin_search(upper->eb, key, &slot); 22568c2ecf20Sopenharmony_ci if (ret < 0) { 22578c2ecf20Sopenharmony_ci err = ret; 22588c2ecf20Sopenharmony_ci goto next; 22598c2ecf20Sopenharmony_ci } 22608c2ecf20Sopenharmony_ci BUG_ON(ret); 22618c2ecf20Sopenharmony_ci bytenr = btrfs_node_blockptr(upper->eb, slot); 22628c2ecf20Sopenharmony_ci if (node->eb->start == bytenr) 22638c2ecf20Sopenharmony_ci goto next; 22648c2ecf20Sopenharmony_ci } 22658c2ecf20Sopenharmony_ci btrfs_backref_drop_node_buffer(upper); 22668c2ecf20Sopenharmony_ci } 22678c2ecf20Sopenharmony_ci 22688c2ecf20Sopenharmony_ci if (!upper->eb) { 22698c2ecf20Sopenharmony_ci ret = btrfs_search_slot(trans, root, key, path, 0, 1); 22708c2ecf20Sopenharmony_ci if (ret) { 22718c2ecf20Sopenharmony_ci if (ret < 0) 22728c2ecf20Sopenharmony_ci err = ret; 22738c2ecf20Sopenharmony_ci else 22748c2ecf20Sopenharmony_ci err = -ENOENT; 22758c2ecf20Sopenharmony_ci 22768c2ecf20Sopenharmony_ci btrfs_release_path(path); 22778c2ecf20Sopenharmony_ci break; 22788c2ecf20Sopenharmony_ci } 22798c2ecf20Sopenharmony_ci 22808c2ecf20Sopenharmony_ci if (!upper->eb) { 22818c2ecf20Sopenharmony_ci upper->eb = path->nodes[upper->level]; 22828c2ecf20Sopenharmony_ci path->nodes[upper->level] = NULL; 22838c2ecf20Sopenharmony_ci } else { 22848c2ecf20Sopenharmony_ci BUG_ON(upper->eb != path->nodes[upper->level]); 22858c2ecf20Sopenharmony_ci } 22868c2ecf20Sopenharmony_ci 22878c2ecf20Sopenharmony_ci upper->locked = 1; 22888c2ecf20Sopenharmony_ci path->locks[upper->level] = 0; 22898c2ecf20Sopenharmony_ci 22908c2ecf20Sopenharmony_ci slot = path->slots[upper->level]; 22918c2ecf20Sopenharmony_ci btrfs_release_path(path); 22928c2ecf20Sopenharmony_ci } else { 22938c2ecf20Sopenharmony_ci ret = btrfs_bin_search(upper->eb, key, &slot); 22948c2ecf20Sopenharmony_ci if (ret < 0) { 22958c2ecf20Sopenharmony_ci err = ret; 22968c2ecf20Sopenharmony_ci goto next; 22978c2ecf20Sopenharmony_ci } 22988c2ecf20Sopenharmony_ci BUG_ON(ret); 22998c2ecf20Sopenharmony_ci } 23008c2ecf20Sopenharmony_ci 23018c2ecf20Sopenharmony_ci bytenr = btrfs_node_blockptr(upper->eb, slot); 23028c2ecf20Sopenharmony_ci if (lowest) { 23038c2ecf20Sopenharmony_ci if (bytenr != node->bytenr) { 23048c2ecf20Sopenharmony_ci btrfs_err(root->fs_info, 23058c2ecf20Sopenharmony_ci "lowest leaf/node mismatch: bytenr %llu node->bytenr %llu slot %d upper %llu", 23068c2ecf20Sopenharmony_ci bytenr, node->bytenr, slot, 23078c2ecf20Sopenharmony_ci upper->eb->start); 23088c2ecf20Sopenharmony_ci err = -EIO; 23098c2ecf20Sopenharmony_ci goto next; 23108c2ecf20Sopenharmony_ci } 23118c2ecf20Sopenharmony_ci } else { 23128c2ecf20Sopenharmony_ci if (node->eb->start == bytenr) 23138c2ecf20Sopenharmony_ci goto next; 23148c2ecf20Sopenharmony_ci } 23158c2ecf20Sopenharmony_ci 23168c2ecf20Sopenharmony_ci blocksize = root->fs_info->nodesize; 23178c2ecf20Sopenharmony_ci generation = btrfs_node_ptr_generation(upper->eb, slot); 23188c2ecf20Sopenharmony_ci btrfs_node_key_to_cpu(upper->eb, &first_key, slot); 23198c2ecf20Sopenharmony_ci eb = read_tree_block(fs_info, bytenr, generation, 23208c2ecf20Sopenharmony_ci upper->level - 1, &first_key); 23218c2ecf20Sopenharmony_ci if (IS_ERR(eb)) { 23228c2ecf20Sopenharmony_ci err = PTR_ERR(eb); 23238c2ecf20Sopenharmony_ci goto next; 23248c2ecf20Sopenharmony_ci } else if (!extent_buffer_uptodate(eb)) { 23258c2ecf20Sopenharmony_ci free_extent_buffer(eb); 23268c2ecf20Sopenharmony_ci err = -EIO; 23278c2ecf20Sopenharmony_ci goto next; 23288c2ecf20Sopenharmony_ci } 23298c2ecf20Sopenharmony_ci btrfs_tree_lock(eb); 23308c2ecf20Sopenharmony_ci btrfs_set_lock_blocking_write(eb); 23318c2ecf20Sopenharmony_ci 23328c2ecf20Sopenharmony_ci if (!node->eb) { 23338c2ecf20Sopenharmony_ci ret = btrfs_cow_block(trans, root, eb, upper->eb, 23348c2ecf20Sopenharmony_ci slot, &eb, BTRFS_NESTING_COW); 23358c2ecf20Sopenharmony_ci btrfs_tree_unlock(eb); 23368c2ecf20Sopenharmony_ci free_extent_buffer(eb); 23378c2ecf20Sopenharmony_ci if (ret < 0) { 23388c2ecf20Sopenharmony_ci err = ret; 23398c2ecf20Sopenharmony_ci goto next; 23408c2ecf20Sopenharmony_ci } 23418c2ecf20Sopenharmony_ci BUG_ON(node->eb != eb); 23428c2ecf20Sopenharmony_ci } else { 23438c2ecf20Sopenharmony_ci btrfs_set_node_blockptr(upper->eb, slot, 23448c2ecf20Sopenharmony_ci node->eb->start); 23458c2ecf20Sopenharmony_ci btrfs_set_node_ptr_generation(upper->eb, slot, 23468c2ecf20Sopenharmony_ci trans->transid); 23478c2ecf20Sopenharmony_ci btrfs_mark_buffer_dirty(upper->eb); 23488c2ecf20Sopenharmony_ci 23498c2ecf20Sopenharmony_ci btrfs_init_generic_ref(&ref, BTRFS_ADD_DELAYED_REF, 23508c2ecf20Sopenharmony_ci node->eb->start, blocksize, 23518c2ecf20Sopenharmony_ci upper->eb->start); 23528c2ecf20Sopenharmony_ci ref.real_root = root->root_key.objectid; 23538c2ecf20Sopenharmony_ci btrfs_init_tree_ref(&ref, node->level, 23548c2ecf20Sopenharmony_ci btrfs_header_owner(upper->eb)); 23558c2ecf20Sopenharmony_ci ret = btrfs_inc_extent_ref(trans, &ref); 23568c2ecf20Sopenharmony_ci BUG_ON(ret); 23578c2ecf20Sopenharmony_ci 23588c2ecf20Sopenharmony_ci ret = btrfs_drop_subtree(trans, root, eb, upper->eb); 23598c2ecf20Sopenharmony_ci BUG_ON(ret); 23608c2ecf20Sopenharmony_ci } 23618c2ecf20Sopenharmony_cinext: 23628c2ecf20Sopenharmony_ci if (!upper->pending) 23638c2ecf20Sopenharmony_ci btrfs_backref_drop_node_buffer(upper); 23648c2ecf20Sopenharmony_ci else 23658c2ecf20Sopenharmony_ci btrfs_backref_unlock_node_buffer(upper); 23668c2ecf20Sopenharmony_ci if (err) 23678c2ecf20Sopenharmony_ci break; 23688c2ecf20Sopenharmony_ci } 23698c2ecf20Sopenharmony_ci 23708c2ecf20Sopenharmony_ci if (!err && node->pending) { 23718c2ecf20Sopenharmony_ci btrfs_backref_drop_node_buffer(node); 23728c2ecf20Sopenharmony_ci list_move_tail(&node->list, &rc->backref_cache.changed); 23738c2ecf20Sopenharmony_ci node->pending = 0; 23748c2ecf20Sopenharmony_ci } 23758c2ecf20Sopenharmony_ci 23768c2ecf20Sopenharmony_ci path->lowest_level = 0; 23778c2ecf20Sopenharmony_ci BUG_ON(err == -ENOSPC); 23788c2ecf20Sopenharmony_ci return err; 23798c2ecf20Sopenharmony_ci} 23808c2ecf20Sopenharmony_ci 23818c2ecf20Sopenharmony_cistatic int link_to_upper(struct btrfs_trans_handle *trans, 23828c2ecf20Sopenharmony_ci struct reloc_control *rc, 23838c2ecf20Sopenharmony_ci struct btrfs_backref_node *node, 23848c2ecf20Sopenharmony_ci struct btrfs_path *path) 23858c2ecf20Sopenharmony_ci{ 23868c2ecf20Sopenharmony_ci struct btrfs_key key; 23878c2ecf20Sopenharmony_ci 23888c2ecf20Sopenharmony_ci btrfs_node_key_to_cpu(node->eb, &key, 0); 23898c2ecf20Sopenharmony_ci return do_relocation(trans, rc, node, &key, path, 0); 23908c2ecf20Sopenharmony_ci} 23918c2ecf20Sopenharmony_ci 23928c2ecf20Sopenharmony_cistatic int finish_pending_nodes(struct btrfs_trans_handle *trans, 23938c2ecf20Sopenharmony_ci struct reloc_control *rc, 23948c2ecf20Sopenharmony_ci struct btrfs_path *path, int err) 23958c2ecf20Sopenharmony_ci{ 23968c2ecf20Sopenharmony_ci LIST_HEAD(list); 23978c2ecf20Sopenharmony_ci struct btrfs_backref_cache *cache = &rc->backref_cache; 23988c2ecf20Sopenharmony_ci struct btrfs_backref_node *node; 23998c2ecf20Sopenharmony_ci int level; 24008c2ecf20Sopenharmony_ci int ret; 24018c2ecf20Sopenharmony_ci 24028c2ecf20Sopenharmony_ci for (level = 0; level < BTRFS_MAX_LEVEL; level++) { 24038c2ecf20Sopenharmony_ci while (!list_empty(&cache->pending[level])) { 24048c2ecf20Sopenharmony_ci node = list_entry(cache->pending[level].next, 24058c2ecf20Sopenharmony_ci struct btrfs_backref_node, list); 24068c2ecf20Sopenharmony_ci list_move_tail(&node->list, &list); 24078c2ecf20Sopenharmony_ci BUG_ON(!node->pending); 24088c2ecf20Sopenharmony_ci 24098c2ecf20Sopenharmony_ci if (!err) { 24108c2ecf20Sopenharmony_ci ret = link_to_upper(trans, rc, node, path); 24118c2ecf20Sopenharmony_ci if (ret < 0) 24128c2ecf20Sopenharmony_ci err = ret; 24138c2ecf20Sopenharmony_ci } 24148c2ecf20Sopenharmony_ci } 24158c2ecf20Sopenharmony_ci list_splice_init(&list, &cache->pending[level]); 24168c2ecf20Sopenharmony_ci } 24178c2ecf20Sopenharmony_ci return err; 24188c2ecf20Sopenharmony_ci} 24198c2ecf20Sopenharmony_ci 24208c2ecf20Sopenharmony_ci/* 24218c2ecf20Sopenharmony_ci * mark a block and all blocks directly/indirectly reference the block 24228c2ecf20Sopenharmony_ci * as processed. 24238c2ecf20Sopenharmony_ci */ 24248c2ecf20Sopenharmony_cistatic void update_processed_blocks(struct reloc_control *rc, 24258c2ecf20Sopenharmony_ci struct btrfs_backref_node *node) 24268c2ecf20Sopenharmony_ci{ 24278c2ecf20Sopenharmony_ci struct btrfs_backref_node *next = node; 24288c2ecf20Sopenharmony_ci struct btrfs_backref_edge *edge; 24298c2ecf20Sopenharmony_ci struct btrfs_backref_edge *edges[BTRFS_MAX_LEVEL - 1]; 24308c2ecf20Sopenharmony_ci int index = 0; 24318c2ecf20Sopenharmony_ci 24328c2ecf20Sopenharmony_ci while (next) { 24338c2ecf20Sopenharmony_ci cond_resched(); 24348c2ecf20Sopenharmony_ci while (1) { 24358c2ecf20Sopenharmony_ci if (next->processed) 24368c2ecf20Sopenharmony_ci break; 24378c2ecf20Sopenharmony_ci 24388c2ecf20Sopenharmony_ci mark_block_processed(rc, next); 24398c2ecf20Sopenharmony_ci 24408c2ecf20Sopenharmony_ci if (list_empty(&next->upper)) 24418c2ecf20Sopenharmony_ci break; 24428c2ecf20Sopenharmony_ci 24438c2ecf20Sopenharmony_ci edge = list_entry(next->upper.next, 24448c2ecf20Sopenharmony_ci struct btrfs_backref_edge, list[LOWER]); 24458c2ecf20Sopenharmony_ci edges[index++] = edge; 24468c2ecf20Sopenharmony_ci next = edge->node[UPPER]; 24478c2ecf20Sopenharmony_ci } 24488c2ecf20Sopenharmony_ci next = walk_down_backref(edges, &index); 24498c2ecf20Sopenharmony_ci } 24508c2ecf20Sopenharmony_ci} 24518c2ecf20Sopenharmony_ci 24528c2ecf20Sopenharmony_cistatic int tree_block_processed(u64 bytenr, struct reloc_control *rc) 24538c2ecf20Sopenharmony_ci{ 24548c2ecf20Sopenharmony_ci u32 blocksize = rc->extent_root->fs_info->nodesize; 24558c2ecf20Sopenharmony_ci 24568c2ecf20Sopenharmony_ci if (test_range_bit(&rc->processed_blocks, bytenr, 24578c2ecf20Sopenharmony_ci bytenr + blocksize - 1, EXTENT_DIRTY, 1, NULL)) 24588c2ecf20Sopenharmony_ci return 1; 24598c2ecf20Sopenharmony_ci return 0; 24608c2ecf20Sopenharmony_ci} 24618c2ecf20Sopenharmony_ci 24628c2ecf20Sopenharmony_cistatic int get_tree_block_key(struct btrfs_fs_info *fs_info, 24638c2ecf20Sopenharmony_ci struct tree_block *block) 24648c2ecf20Sopenharmony_ci{ 24658c2ecf20Sopenharmony_ci struct extent_buffer *eb; 24668c2ecf20Sopenharmony_ci 24678c2ecf20Sopenharmony_ci eb = read_tree_block(fs_info, block->bytenr, block->key.offset, 24688c2ecf20Sopenharmony_ci block->level, NULL); 24698c2ecf20Sopenharmony_ci if (IS_ERR(eb)) { 24708c2ecf20Sopenharmony_ci return PTR_ERR(eb); 24718c2ecf20Sopenharmony_ci } else if (!extent_buffer_uptodate(eb)) { 24728c2ecf20Sopenharmony_ci free_extent_buffer(eb); 24738c2ecf20Sopenharmony_ci return -EIO; 24748c2ecf20Sopenharmony_ci } 24758c2ecf20Sopenharmony_ci if (block->level == 0) 24768c2ecf20Sopenharmony_ci btrfs_item_key_to_cpu(eb, &block->key, 0); 24778c2ecf20Sopenharmony_ci else 24788c2ecf20Sopenharmony_ci btrfs_node_key_to_cpu(eb, &block->key, 0); 24798c2ecf20Sopenharmony_ci free_extent_buffer(eb); 24808c2ecf20Sopenharmony_ci block->key_ready = 1; 24818c2ecf20Sopenharmony_ci return 0; 24828c2ecf20Sopenharmony_ci} 24838c2ecf20Sopenharmony_ci 24848c2ecf20Sopenharmony_ci/* 24858c2ecf20Sopenharmony_ci * helper function to relocate a tree block 24868c2ecf20Sopenharmony_ci */ 24878c2ecf20Sopenharmony_cistatic int relocate_tree_block(struct btrfs_trans_handle *trans, 24888c2ecf20Sopenharmony_ci struct reloc_control *rc, 24898c2ecf20Sopenharmony_ci struct btrfs_backref_node *node, 24908c2ecf20Sopenharmony_ci struct btrfs_key *key, 24918c2ecf20Sopenharmony_ci struct btrfs_path *path) 24928c2ecf20Sopenharmony_ci{ 24938c2ecf20Sopenharmony_ci struct btrfs_root *root; 24948c2ecf20Sopenharmony_ci int ret = 0; 24958c2ecf20Sopenharmony_ci 24968c2ecf20Sopenharmony_ci if (!node) 24978c2ecf20Sopenharmony_ci return 0; 24988c2ecf20Sopenharmony_ci 24998c2ecf20Sopenharmony_ci /* 25008c2ecf20Sopenharmony_ci * If we fail here we want to drop our backref_node because we are going 25018c2ecf20Sopenharmony_ci * to start over and regenerate the tree for it. 25028c2ecf20Sopenharmony_ci */ 25038c2ecf20Sopenharmony_ci ret = reserve_metadata_space(trans, rc, node); 25048c2ecf20Sopenharmony_ci if (ret) 25058c2ecf20Sopenharmony_ci goto out; 25068c2ecf20Sopenharmony_ci 25078c2ecf20Sopenharmony_ci BUG_ON(node->processed); 25088c2ecf20Sopenharmony_ci root = select_one_root(node); 25098c2ecf20Sopenharmony_ci if (root == ERR_PTR(-ENOENT)) { 25108c2ecf20Sopenharmony_ci update_processed_blocks(rc, node); 25118c2ecf20Sopenharmony_ci goto out; 25128c2ecf20Sopenharmony_ci } 25138c2ecf20Sopenharmony_ci 25148c2ecf20Sopenharmony_ci if (root) { 25158c2ecf20Sopenharmony_ci if (test_bit(BTRFS_ROOT_SHAREABLE, &root->state)) { 25168c2ecf20Sopenharmony_ci BUG_ON(node->new_bytenr); 25178c2ecf20Sopenharmony_ci BUG_ON(!list_empty(&node->list)); 25188c2ecf20Sopenharmony_ci btrfs_record_root_in_trans(trans, root); 25198c2ecf20Sopenharmony_ci root = root->reloc_root; 25208c2ecf20Sopenharmony_ci node->new_bytenr = root->node->start; 25218c2ecf20Sopenharmony_ci btrfs_put_root(node->root); 25228c2ecf20Sopenharmony_ci node->root = btrfs_grab_root(root); 25238c2ecf20Sopenharmony_ci ASSERT(node->root); 25248c2ecf20Sopenharmony_ci list_add_tail(&node->list, &rc->backref_cache.changed); 25258c2ecf20Sopenharmony_ci } else { 25268c2ecf20Sopenharmony_ci path->lowest_level = node->level; 25278c2ecf20Sopenharmony_ci ret = btrfs_search_slot(trans, root, key, path, 0, 1); 25288c2ecf20Sopenharmony_ci btrfs_release_path(path); 25298c2ecf20Sopenharmony_ci if (ret > 0) 25308c2ecf20Sopenharmony_ci ret = 0; 25318c2ecf20Sopenharmony_ci } 25328c2ecf20Sopenharmony_ci if (!ret) 25338c2ecf20Sopenharmony_ci update_processed_blocks(rc, node); 25348c2ecf20Sopenharmony_ci } else { 25358c2ecf20Sopenharmony_ci ret = do_relocation(trans, rc, node, key, path, 1); 25368c2ecf20Sopenharmony_ci } 25378c2ecf20Sopenharmony_ciout: 25388c2ecf20Sopenharmony_ci if (ret || node->level == 0 || node->cowonly) 25398c2ecf20Sopenharmony_ci btrfs_backref_cleanup_node(&rc->backref_cache, node); 25408c2ecf20Sopenharmony_ci return ret; 25418c2ecf20Sopenharmony_ci} 25428c2ecf20Sopenharmony_ci 25438c2ecf20Sopenharmony_ci/* 25448c2ecf20Sopenharmony_ci * relocate a list of blocks 25458c2ecf20Sopenharmony_ci */ 25468c2ecf20Sopenharmony_cistatic noinline_for_stack 25478c2ecf20Sopenharmony_ciint relocate_tree_blocks(struct btrfs_trans_handle *trans, 25488c2ecf20Sopenharmony_ci struct reloc_control *rc, struct rb_root *blocks) 25498c2ecf20Sopenharmony_ci{ 25508c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = rc->extent_root->fs_info; 25518c2ecf20Sopenharmony_ci struct btrfs_backref_node *node; 25528c2ecf20Sopenharmony_ci struct btrfs_path *path; 25538c2ecf20Sopenharmony_ci struct tree_block *block; 25548c2ecf20Sopenharmony_ci struct tree_block *next; 25558c2ecf20Sopenharmony_ci int ret; 25568c2ecf20Sopenharmony_ci int err = 0; 25578c2ecf20Sopenharmony_ci 25588c2ecf20Sopenharmony_ci path = btrfs_alloc_path(); 25598c2ecf20Sopenharmony_ci if (!path) { 25608c2ecf20Sopenharmony_ci err = -ENOMEM; 25618c2ecf20Sopenharmony_ci goto out_free_blocks; 25628c2ecf20Sopenharmony_ci } 25638c2ecf20Sopenharmony_ci 25648c2ecf20Sopenharmony_ci /* Kick in readahead for tree blocks with missing keys */ 25658c2ecf20Sopenharmony_ci rbtree_postorder_for_each_entry_safe(block, next, blocks, rb_node) { 25668c2ecf20Sopenharmony_ci if (!block->key_ready) 25678c2ecf20Sopenharmony_ci readahead_tree_block(fs_info, block->bytenr); 25688c2ecf20Sopenharmony_ci } 25698c2ecf20Sopenharmony_ci 25708c2ecf20Sopenharmony_ci /* Get first keys */ 25718c2ecf20Sopenharmony_ci rbtree_postorder_for_each_entry_safe(block, next, blocks, rb_node) { 25728c2ecf20Sopenharmony_ci if (!block->key_ready) { 25738c2ecf20Sopenharmony_ci err = get_tree_block_key(fs_info, block); 25748c2ecf20Sopenharmony_ci if (err) 25758c2ecf20Sopenharmony_ci goto out_free_path; 25768c2ecf20Sopenharmony_ci } 25778c2ecf20Sopenharmony_ci } 25788c2ecf20Sopenharmony_ci 25798c2ecf20Sopenharmony_ci /* Do tree relocation */ 25808c2ecf20Sopenharmony_ci rbtree_postorder_for_each_entry_safe(block, next, blocks, rb_node) { 25818c2ecf20Sopenharmony_ci node = build_backref_tree(rc, &block->key, 25828c2ecf20Sopenharmony_ci block->level, block->bytenr); 25838c2ecf20Sopenharmony_ci if (IS_ERR(node)) { 25848c2ecf20Sopenharmony_ci err = PTR_ERR(node); 25858c2ecf20Sopenharmony_ci goto out; 25868c2ecf20Sopenharmony_ci } 25878c2ecf20Sopenharmony_ci 25888c2ecf20Sopenharmony_ci ret = relocate_tree_block(trans, rc, node, &block->key, 25898c2ecf20Sopenharmony_ci path); 25908c2ecf20Sopenharmony_ci if (ret < 0) { 25918c2ecf20Sopenharmony_ci err = ret; 25928c2ecf20Sopenharmony_ci break; 25938c2ecf20Sopenharmony_ci } 25948c2ecf20Sopenharmony_ci } 25958c2ecf20Sopenharmony_ciout: 25968c2ecf20Sopenharmony_ci err = finish_pending_nodes(trans, rc, path, err); 25978c2ecf20Sopenharmony_ci 25988c2ecf20Sopenharmony_ciout_free_path: 25998c2ecf20Sopenharmony_ci btrfs_free_path(path); 26008c2ecf20Sopenharmony_ciout_free_blocks: 26018c2ecf20Sopenharmony_ci free_block_list(blocks); 26028c2ecf20Sopenharmony_ci return err; 26038c2ecf20Sopenharmony_ci} 26048c2ecf20Sopenharmony_ci 26058c2ecf20Sopenharmony_cistatic noinline_for_stack int prealloc_file_extent_cluster( 26068c2ecf20Sopenharmony_ci struct btrfs_inode *inode, 26078c2ecf20Sopenharmony_ci struct file_extent_cluster *cluster) 26088c2ecf20Sopenharmony_ci{ 26098c2ecf20Sopenharmony_ci u64 alloc_hint = 0; 26108c2ecf20Sopenharmony_ci u64 start; 26118c2ecf20Sopenharmony_ci u64 end; 26128c2ecf20Sopenharmony_ci u64 offset = inode->index_cnt; 26138c2ecf20Sopenharmony_ci u64 num_bytes; 26148c2ecf20Sopenharmony_ci int nr; 26158c2ecf20Sopenharmony_ci int ret = 0; 26168c2ecf20Sopenharmony_ci u64 prealloc_start = cluster->start - offset; 26178c2ecf20Sopenharmony_ci u64 prealloc_end = cluster->end - offset; 26188c2ecf20Sopenharmony_ci u64 cur_offset = prealloc_start; 26198c2ecf20Sopenharmony_ci 26208c2ecf20Sopenharmony_ci BUG_ON(cluster->start != cluster->boundary[0]); 26218c2ecf20Sopenharmony_ci ret = btrfs_alloc_data_chunk_ondemand(inode, 26228c2ecf20Sopenharmony_ci prealloc_end + 1 - prealloc_start); 26238c2ecf20Sopenharmony_ci if (ret) 26248c2ecf20Sopenharmony_ci return ret; 26258c2ecf20Sopenharmony_ci 26268c2ecf20Sopenharmony_ci inode_lock(&inode->vfs_inode); 26278c2ecf20Sopenharmony_ci for (nr = 0; nr < cluster->nr; nr++) { 26288c2ecf20Sopenharmony_ci start = cluster->boundary[nr] - offset; 26298c2ecf20Sopenharmony_ci if (nr + 1 < cluster->nr) 26308c2ecf20Sopenharmony_ci end = cluster->boundary[nr + 1] - 1 - offset; 26318c2ecf20Sopenharmony_ci else 26328c2ecf20Sopenharmony_ci end = cluster->end - offset; 26338c2ecf20Sopenharmony_ci 26348c2ecf20Sopenharmony_ci lock_extent(&inode->io_tree, start, end); 26358c2ecf20Sopenharmony_ci num_bytes = end + 1 - start; 26368c2ecf20Sopenharmony_ci ret = btrfs_prealloc_file_range(&inode->vfs_inode, 0, start, 26378c2ecf20Sopenharmony_ci num_bytes, num_bytes, 26388c2ecf20Sopenharmony_ci end + 1, &alloc_hint); 26398c2ecf20Sopenharmony_ci cur_offset = end + 1; 26408c2ecf20Sopenharmony_ci unlock_extent(&inode->io_tree, start, end); 26418c2ecf20Sopenharmony_ci if (ret) 26428c2ecf20Sopenharmony_ci break; 26438c2ecf20Sopenharmony_ci } 26448c2ecf20Sopenharmony_ci inode_unlock(&inode->vfs_inode); 26458c2ecf20Sopenharmony_ci 26468c2ecf20Sopenharmony_ci if (cur_offset < prealloc_end) 26478c2ecf20Sopenharmony_ci btrfs_free_reserved_data_space_noquota(inode->root->fs_info, 26488c2ecf20Sopenharmony_ci prealloc_end + 1 - cur_offset); 26498c2ecf20Sopenharmony_ci return ret; 26508c2ecf20Sopenharmony_ci} 26518c2ecf20Sopenharmony_ci 26528c2ecf20Sopenharmony_cistatic noinline_for_stack 26538c2ecf20Sopenharmony_ciint setup_extent_mapping(struct inode *inode, u64 start, u64 end, 26548c2ecf20Sopenharmony_ci u64 block_start) 26558c2ecf20Sopenharmony_ci{ 26568c2ecf20Sopenharmony_ci struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree; 26578c2ecf20Sopenharmony_ci struct extent_map *em; 26588c2ecf20Sopenharmony_ci int ret = 0; 26598c2ecf20Sopenharmony_ci 26608c2ecf20Sopenharmony_ci em = alloc_extent_map(); 26618c2ecf20Sopenharmony_ci if (!em) 26628c2ecf20Sopenharmony_ci return -ENOMEM; 26638c2ecf20Sopenharmony_ci 26648c2ecf20Sopenharmony_ci em->start = start; 26658c2ecf20Sopenharmony_ci em->len = end + 1 - start; 26668c2ecf20Sopenharmony_ci em->block_len = em->len; 26678c2ecf20Sopenharmony_ci em->block_start = block_start; 26688c2ecf20Sopenharmony_ci set_bit(EXTENT_FLAG_PINNED, &em->flags); 26698c2ecf20Sopenharmony_ci 26708c2ecf20Sopenharmony_ci lock_extent(&BTRFS_I(inode)->io_tree, start, end); 26718c2ecf20Sopenharmony_ci while (1) { 26728c2ecf20Sopenharmony_ci write_lock(&em_tree->lock); 26738c2ecf20Sopenharmony_ci ret = add_extent_mapping(em_tree, em, 0); 26748c2ecf20Sopenharmony_ci write_unlock(&em_tree->lock); 26758c2ecf20Sopenharmony_ci if (ret != -EEXIST) { 26768c2ecf20Sopenharmony_ci free_extent_map(em); 26778c2ecf20Sopenharmony_ci break; 26788c2ecf20Sopenharmony_ci } 26798c2ecf20Sopenharmony_ci btrfs_drop_extent_cache(BTRFS_I(inode), start, end, 0); 26808c2ecf20Sopenharmony_ci } 26818c2ecf20Sopenharmony_ci unlock_extent(&BTRFS_I(inode)->io_tree, start, end); 26828c2ecf20Sopenharmony_ci return ret; 26838c2ecf20Sopenharmony_ci} 26848c2ecf20Sopenharmony_ci 26858c2ecf20Sopenharmony_ci/* 26868c2ecf20Sopenharmony_ci * Allow error injection to test balance cancellation 26878c2ecf20Sopenharmony_ci */ 26888c2ecf20Sopenharmony_ciint btrfs_should_cancel_balance(struct btrfs_fs_info *fs_info) 26898c2ecf20Sopenharmony_ci{ 26908c2ecf20Sopenharmony_ci return atomic_read(&fs_info->balance_cancel_req) || 26918c2ecf20Sopenharmony_ci fatal_signal_pending(current); 26928c2ecf20Sopenharmony_ci} 26938c2ecf20Sopenharmony_ciALLOW_ERROR_INJECTION(btrfs_should_cancel_balance, TRUE); 26948c2ecf20Sopenharmony_ci 26958c2ecf20Sopenharmony_cistatic int relocate_file_extent_cluster(struct inode *inode, 26968c2ecf20Sopenharmony_ci struct file_extent_cluster *cluster) 26978c2ecf20Sopenharmony_ci{ 26988c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); 26998c2ecf20Sopenharmony_ci u64 page_start; 27008c2ecf20Sopenharmony_ci u64 page_end; 27018c2ecf20Sopenharmony_ci u64 offset = BTRFS_I(inode)->index_cnt; 27028c2ecf20Sopenharmony_ci unsigned long index; 27038c2ecf20Sopenharmony_ci unsigned long last_index; 27048c2ecf20Sopenharmony_ci struct page *page; 27058c2ecf20Sopenharmony_ci struct file_ra_state *ra; 27068c2ecf20Sopenharmony_ci gfp_t mask = btrfs_alloc_write_mask(inode->i_mapping); 27078c2ecf20Sopenharmony_ci int nr = 0; 27088c2ecf20Sopenharmony_ci int ret = 0; 27098c2ecf20Sopenharmony_ci 27108c2ecf20Sopenharmony_ci if (!cluster->nr) 27118c2ecf20Sopenharmony_ci return 0; 27128c2ecf20Sopenharmony_ci 27138c2ecf20Sopenharmony_ci ra = kzalloc(sizeof(*ra), GFP_NOFS); 27148c2ecf20Sopenharmony_ci if (!ra) 27158c2ecf20Sopenharmony_ci return -ENOMEM; 27168c2ecf20Sopenharmony_ci 27178c2ecf20Sopenharmony_ci ret = prealloc_file_extent_cluster(BTRFS_I(inode), cluster); 27188c2ecf20Sopenharmony_ci if (ret) 27198c2ecf20Sopenharmony_ci goto out; 27208c2ecf20Sopenharmony_ci 27218c2ecf20Sopenharmony_ci file_ra_state_init(ra, inode->i_mapping); 27228c2ecf20Sopenharmony_ci 27238c2ecf20Sopenharmony_ci ret = setup_extent_mapping(inode, cluster->start - offset, 27248c2ecf20Sopenharmony_ci cluster->end - offset, cluster->start); 27258c2ecf20Sopenharmony_ci if (ret) 27268c2ecf20Sopenharmony_ci goto out; 27278c2ecf20Sopenharmony_ci 27288c2ecf20Sopenharmony_ci index = (cluster->start - offset) >> PAGE_SHIFT; 27298c2ecf20Sopenharmony_ci last_index = (cluster->end - offset) >> PAGE_SHIFT; 27308c2ecf20Sopenharmony_ci while (index <= last_index) { 27318c2ecf20Sopenharmony_ci ret = btrfs_delalloc_reserve_metadata(BTRFS_I(inode), 27328c2ecf20Sopenharmony_ci PAGE_SIZE); 27338c2ecf20Sopenharmony_ci if (ret) 27348c2ecf20Sopenharmony_ci goto out; 27358c2ecf20Sopenharmony_ci 27368c2ecf20Sopenharmony_ci page = find_lock_page(inode->i_mapping, index); 27378c2ecf20Sopenharmony_ci if (!page) { 27388c2ecf20Sopenharmony_ci page_cache_sync_readahead(inode->i_mapping, 27398c2ecf20Sopenharmony_ci ra, NULL, index, 27408c2ecf20Sopenharmony_ci last_index + 1 - index); 27418c2ecf20Sopenharmony_ci page = find_or_create_page(inode->i_mapping, index, 27428c2ecf20Sopenharmony_ci mask); 27438c2ecf20Sopenharmony_ci if (!page) { 27448c2ecf20Sopenharmony_ci btrfs_delalloc_release_metadata(BTRFS_I(inode), 27458c2ecf20Sopenharmony_ci PAGE_SIZE, true); 27468c2ecf20Sopenharmony_ci btrfs_delalloc_release_extents(BTRFS_I(inode), 27478c2ecf20Sopenharmony_ci PAGE_SIZE); 27488c2ecf20Sopenharmony_ci ret = -ENOMEM; 27498c2ecf20Sopenharmony_ci goto out; 27508c2ecf20Sopenharmony_ci } 27518c2ecf20Sopenharmony_ci } 27528c2ecf20Sopenharmony_ci 27538c2ecf20Sopenharmony_ci if (PageReadahead(page)) { 27548c2ecf20Sopenharmony_ci page_cache_async_readahead(inode->i_mapping, 27558c2ecf20Sopenharmony_ci ra, NULL, page, index, 27568c2ecf20Sopenharmony_ci last_index + 1 - index); 27578c2ecf20Sopenharmony_ci } 27588c2ecf20Sopenharmony_ci 27598c2ecf20Sopenharmony_ci if (!PageUptodate(page)) { 27608c2ecf20Sopenharmony_ci btrfs_readpage(NULL, page); 27618c2ecf20Sopenharmony_ci lock_page(page); 27628c2ecf20Sopenharmony_ci if (!PageUptodate(page)) { 27638c2ecf20Sopenharmony_ci unlock_page(page); 27648c2ecf20Sopenharmony_ci put_page(page); 27658c2ecf20Sopenharmony_ci btrfs_delalloc_release_metadata(BTRFS_I(inode), 27668c2ecf20Sopenharmony_ci PAGE_SIZE, true); 27678c2ecf20Sopenharmony_ci btrfs_delalloc_release_extents(BTRFS_I(inode), 27688c2ecf20Sopenharmony_ci PAGE_SIZE); 27698c2ecf20Sopenharmony_ci ret = -EIO; 27708c2ecf20Sopenharmony_ci goto out; 27718c2ecf20Sopenharmony_ci } 27728c2ecf20Sopenharmony_ci } 27738c2ecf20Sopenharmony_ci 27748c2ecf20Sopenharmony_ci page_start = page_offset(page); 27758c2ecf20Sopenharmony_ci page_end = page_start + PAGE_SIZE - 1; 27768c2ecf20Sopenharmony_ci 27778c2ecf20Sopenharmony_ci lock_extent(&BTRFS_I(inode)->io_tree, page_start, page_end); 27788c2ecf20Sopenharmony_ci 27798c2ecf20Sopenharmony_ci set_page_extent_mapped(page); 27808c2ecf20Sopenharmony_ci 27818c2ecf20Sopenharmony_ci if (nr < cluster->nr && 27828c2ecf20Sopenharmony_ci page_start + offset == cluster->boundary[nr]) { 27838c2ecf20Sopenharmony_ci set_extent_bits(&BTRFS_I(inode)->io_tree, 27848c2ecf20Sopenharmony_ci page_start, page_end, 27858c2ecf20Sopenharmony_ci EXTENT_BOUNDARY); 27868c2ecf20Sopenharmony_ci nr++; 27878c2ecf20Sopenharmony_ci } 27888c2ecf20Sopenharmony_ci 27898c2ecf20Sopenharmony_ci ret = btrfs_set_extent_delalloc(BTRFS_I(inode), page_start, 27908c2ecf20Sopenharmony_ci page_end, 0, NULL); 27918c2ecf20Sopenharmony_ci if (ret) { 27928c2ecf20Sopenharmony_ci unlock_page(page); 27938c2ecf20Sopenharmony_ci put_page(page); 27948c2ecf20Sopenharmony_ci btrfs_delalloc_release_metadata(BTRFS_I(inode), 27958c2ecf20Sopenharmony_ci PAGE_SIZE, true); 27968c2ecf20Sopenharmony_ci btrfs_delalloc_release_extents(BTRFS_I(inode), 27978c2ecf20Sopenharmony_ci PAGE_SIZE); 27988c2ecf20Sopenharmony_ci 27998c2ecf20Sopenharmony_ci clear_extent_bits(&BTRFS_I(inode)->io_tree, 28008c2ecf20Sopenharmony_ci page_start, page_end, 28018c2ecf20Sopenharmony_ci EXTENT_LOCKED | EXTENT_BOUNDARY); 28028c2ecf20Sopenharmony_ci goto out; 28038c2ecf20Sopenharmony_ci 28048c2ecf20Sopenharmony_ci } 28058c2ecf20Sopenharmony_ci set_page_dirty(page); 28068c2ecf20Sopenharmony_ci 28078c2ecf20Sopenharmony_ci unlock_extent(&BTRFS_I(inode)->io_tree, 28088c2ecf20Sopenharmony_ci page_start, page_end); 28098c2ecf20Sopenharmony_ci unlock_page(page); 28108c2ecf20Sopenharmony_ci put_page(page); 28118c2ecf20Sopenharmony_ci 28128c2ecf20Sopenharmony_ci index++; 28138c2ecf20Sopenharmony_ci btrfs_delalloc_release_extents(BTRFS_I(inode), PAGE_SIZE); 28148c2ecf20Sopenharmony_ci balance_dirty_pages_ratelimited(inode->i_mapping); 28158c2ecf20Sopenharmony_ci btrfs_throttle(fs_info); 28168c2ecf20Sopenharmony_ci if (btrfs_should_cancel_balance(fs_info)) { 28178c2ecf20Sopenharmony_ci ret = -ECANCELED; 28188c2ecf20Sopenharmony_ci goto out; 28198c2ecf20Sopenharmony_ci } 28208c2ecf20Sopenharmony_ci } 28218c2ecf20Sopenharmony_ci WARN_ON(nr != cluster->nr); 28228c2ecf20Sopenharmony_ciout: 28238c2ecf20Sopenharmony_ci kfree(ra); 28248c2ecf20Sopenharmony_ci return ret; 28258c2ecf20Sopenharmony_ci} 28268c2ecf20Sopenharmony_ci 28278c2ecf20Sopenharmony_cistatic noinline_for_stack 28288c2ecf20Sopenharmony_ciint relocate_data_extent(struct inode *inode, struct btrfs_key *extent_key, 28298c2ecf20Sopenharmony_ci struct file_extent_cluster *cluster) 28308c2ecf20Sopenharmony_ci{ 28318c2ecf20Sopenharmony_ci int ret; 28328c2ecf20Sopenharmony_ci 28338c2ecf20Sopenharmony_ci if (cluster->nr > 0 && extent_key->objectid != cluster->end + 1) { 28348c2ecf20Sopenharmony_ci ret = relocate_file_extent_cluster(inode, cluster); 28358c2ecf20Sopenharmony_ci if (ret) 28368c2ecf20Sopenharmony_ci return ret; 28378c2ecf20Sopenharmony_ci cluster->nr = 0; 28388c2ecf20Sopenharmony_ci } 28398c2ecf20Sopenharmony_ci 28408c2ecf20Sopenharmony_ci if (!cluster->nr) 28418c2ecf20Sopenharmony_ci cluster->start = extent_key->objectid; 28428c2ecf20Sopenharmony_ci else 28438c2ecf20Sopenharmony_ci BUG_ON(cluster->nr >= MAX_EXTENTS); 28448c2ecf20Sopenharmony_ci cluster->end = extent_key->objectid + extent_key->offset - 1; 28458c2ecf20Sopenharmony_ci cluster->boundary[cluster->nr] = extent_key->objectid; 28468c2ecf20Sopenharmony_ci cluster->nr++; 28478c2ecf20Sopenharmony_ci 28488c2ecf20Sopenharmony_ci if (cluster->nr >= MAX_EXTENTS) { 28498c2ecf20Sopenharmony_ci ret = relocate_file_extent_cluster(inode, cluster); 28508c2ecf20Sopenharmony_ci if (ret) 28518c2ecf20Sopenharmony_ci return ret; 28528c2ecf20Sopenharmony_ci cluster->nr = 0; 28538c2ecf20Sopenharmony_ci } 28548c2ecf20Sopenharmony_ci return 0; 28558c2ecf20Sopenharmony_ci} 28568c2ecf20Sopenharmony_ci 28578c2ecf20Sopenharmony_ci/* 28588c2ecf20Sopenharmony_ci * helper to add a tree block to the list. 28598c2ecf20Sopenharmony_ci * the major work is getting the generation and level of the block 28608c2ecf20Sopenharmony_ci */ 28618c2ecf20Sopenharmony_cistatic int add_tree_block(struct reloc_control *rc, 28628c2ecf20Sopenharmony_ci struct btrfs_key *extent_key, 28638c2ecf20Sopenharmony_ci struct btrfs_path *path, 28648c2ecf20Sopenharmony_ci struct rb_root *blocks) 28658c2ecf20Sopenharmony_ci{ 28668c2ecf20Sopenharmony_ci struct extent_buffer *eb; 28678c2ecf20Sopenharmony_ci struct btrfs_extent_item *ei; 28688c2ecf20Sopenharmony_ci struct btrfs_tree_block_info *bi; 28698c2ecf20Sopenharmony_ci struct tree_block *block; 28708c2ecf20Sopenharmony_ci struct rb_node *rb_node; 28718c2ecf20Sopenharmony_ci u32 item_size; 28728c2ecf20Sopenharmony_ci int level = -1; 28738c2ecf20Sopenharmony_ci u64 generation; 28748c2ecf20Sopenharmony_ci 28758c2ecf20Sopenharmony_ci eb = path->nodes[0]; 28768c2ecf20Sopenharmony_ci item_size = btrfs_item_size_nr(eb, path->slots[0]); 28778c2ecf20Sopenharmony_ci 28788c2ecf20Sopenharmony_ci if (extent_key->type == BTRFS_METADATA_ITEM_KEY || 28798c2ecf20Sopenharmony_ci item_size >= sizeof(*ei) + sizeof(*bi)) { 28808c2ecf20Sopenharmony_ci ei = btrfs_item_ptr(eb, path->slots[0], 28818c2ecf20Sopenharmony_ci struct btrfs_extent_item); 28828c2ecf20Sopenharmony_ci if (extent_key->type == BTRFS_EXTENT_ITEM_KEY) { 28838c2ecf20Sopenharmony_ci bi = (struct btrfs_tree_block_info *)(ei + 1); 28848c2ecf20Sopenharmony_ci level = btrfs_tree_block_level(eb, bi); 28858c2ecf20Sopenharmony_ci } else { 28868c2ecf20Sopenharmony_ci level = (int)extent_key->offset; 28878c2ecf20Sopenharmony_ci } 28888c2ecf20Sopenharmony_ci generation = btrfs_extent_generation(eb, ei); 28898c2ecf20Sopenharmony_ci } else if (unlikely(item_size == sizeof(struct btrfs_extent_item_v0))) { 28908c2ecf20Sopenharmony_ci btrfs_print_v0_err(eb->fs_info); 28918c2ecf20Sopenharmony_ci btrfs_handle_fs_error(eb->fs_info, -EINVAL, NULL); 28928c2ecf20Sopenharmony_ci return -EINVAL; 28938c2ecf20Sopenharmony_ci } else { 28948c2ecf20Sopenharmony_ci BUG(); 28958c2ecf20Sopenharmony_ci } 28968c2ecf20Sopenharmony_ci 28978c2ecf20Sopenharmony_ci btrfs_release_path(path); 28988c2ecf20Sopenharmony_ci 28998c2ecf20Sopenharmony_ci BUG_ON(level == -1); 29008c2ecf20Sopenharmony_ci 29018c2ecf20Sopenharmony_ci block = kmalloc(sizeof(*block), GFP_NOFS); 29028c2ecf20Sopenharmony_ci if (!block) 29038c2ecf20Sopenharmony_ci return -ENOMEM; 29048c2ecf20Sopenharmony_ci 29058c2ecf20Sopenharmony_ci block->bytenr = extent_key->objectid; 29068c2ecf20Sopenharmony_ci block->key.objectid = rc->extent_root->fs_info->nodesize; 29078c2ecf20Sopenharmony_ci block->key.offset = generation; 29088c2ecf20Sopenharmony_ci block->level = level; 29098c2ecf20Sopenharmony_ci block->key_ready = 0; 29108c2ecf20Sopenharmony_ci 29118c2ecf20Sopenharmony_ci rb_node = rb_simple_insert(blocks, block->bytenr, &block->rb_node); 29128c2ecf20Sopenharmony_ci if (rb_node) 29138c2ecf20Sopenharmony_ci btrfs_backref_panic(rc->extent_root->fs_info, block->bytenr, 29148c2ecf20Sopenharmony_ci -EEXIST); 29158c2ecf20Sopenharmony_ci 29168c2ecf20Sopenharmony_ci return 0; 29178c2ecf20Sopenharmony_ci} 29188c2ecf20Sopenharmony_ci 29198c2ecf20Sopenharmony_ci/* 29208c2ecf20Sopenharmony_ci * helper to add tree blocks for backref of type BTRFS_SHARED_DATA_REF_KEY 29218c2ecf20Sopenharmony_ci */ 29228c2ecf20Sopenharmony_cistatic int __add_tree_block(struct reloc_control *rc, 29238c2ecf20Sopenharmony_ci u64 bytenr, u32 blocksize, 29248c2ecf20Sopenharmony_ci struct rb_root *blocks) 29258c2ecf20Sopenharmony_ci{ 29268c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = rc->extent_root->fs_info; 29278c2ecf20Sopenharmony_ci struct btrfs_path *path; 29288c2ecf20Sopenharmony_ci struct btrfs_key key; 29298c2ecf20Sopenharmony_ci int ret; 29308c2ecf20Sopenharmony_ci bool skinny = btrfs_fs_incompat(fs_info, SKINNY_METADATA); 29318c2ecf20Sopenharmony_ci 29328c2ecf20Sopenharmony_ci if (tree_block_processed(bytenr, rc)) 29338c2ecf20Sopenharmony_ci return 0; 29348c2ecf20Sopenharmony_ci 29358c2ecf20Sopenharmony_ci if (rb_simple_search(blocks, bytenr)) 29368c2ecf20Sopenharmony_ci return 0; 29378c2ecf20Sopenharmony_ci 29388c2ecf20Sopenharmony_ci path = btrfs_alloc_path(); 29398c2ecf20Sopenharmony_ci if (!path) 29408c2ecf20Sopenharmony_ci return -ENOMEM; 29418c2ecf20Sopenharmony_ciagain: 29428c2ecf20Sopenharmony_ci key.objectid = bytenr; 29438c2ecf20Sopenharmony_ci if (skinny) { 29448c2ecf20Sopenharmony_ci key.type = BTRFS_METADATA_ITEM_KEY; 29458c2ecf20Sopenharmony_ci key.offset = (u64)-1; 29468c2ecf20Sopenharmony_ci } else { 29478c2ecf20Sopenharmony_ci key.type = BTRFS_EXTENT_ITEM_KEY; 29488c2ecf20Sopenharmony_ci key.offset = blocksize; 29498c2ecf20Sopenharmony_ci } 29508c2ecf20Sopenharmony_ci 29518c2ecf20Sopenharmony_ci path->search_commit_root = 1; 29528c2ecf20Sopenharmony_ci path->skip_locking = 1; 29538c2ecf20Sopenharmony_ci ret = btrfs_search_slot(NULL, rc->extent_root, &key, path, 0, 0); 29548c2ecf20Sopenharmony_ci if (ret < 0) 29558c2ecf20Sopenharmony_ci goto out; 29568c2ecf20Sopenharmony_ci 29578c2ecf20Sopenharmony_ci if (ret > 0 && skinny) { 29588c2ecf20Sopenharmony_ci if (path->slots[0]) { 29598c2ecf20Sopenharmony_ci path->slots[0]--; 29608c2ecf20Sopenharmony_ci btrfs_item_key_to_cpu(path->nodes[0], &key, 29618c2ecf20Sopenharmony_ci path->slots[0]); 29628c2ecf20Sopenharmony_ci if (key.objectid == bytenr && 29638c2ecf20Sopenharmony_ci (key.type == BTRFS_METADATA_ITEM_KEY || 29648c2ecf20Sopenharmony_ci (key.type == BTRFS_EXTENT_ITEM_KEY && 29658c2ecf20Sopenharmony_ci key.offset == blocksize))) 29668c2ecf20Sopenharmony_ci ret = 0; 29678c2ecf20Sopenharmony_ci } 29688c2ecf20Sopenharmony_ci 29698c2ecf20Sopenharmony_ci if (ret) { 29708c2ecf20Sopenharmony_ci skinny = false; 29718c2ecf20Sopenharmony_ci btrfs_release_path(path); 29728c2ecf20Sopenharmony_ci goto again; 29738c2ecf20Sopenharmony_ci } 29748c2ecf20Sopenharmony_ci } 29758c2ecf20Sopenharmony_ci if (ret) { 29768c2ecf20Sopenharmony_ci ASSERT(ret == 1); 29778c2ecf20Sopenharmony_ci btrfs_print_leaf(path->nodes[0]); 29788c2ecf20Sopenharmony_ci btrfs_err(fs_info, 29798c2ecf20Sopenharmony_ci "tree block extent item (%llu) is not found in extent tree", 29808c2ecf20Sopenharmony_ci bytenr); 29818c2ecf20Sopenharmony_ci WARN_ON(1); 29828c2ecf20Sopenharmony_ci ret = -EINVAL; 29838c2ecf20Sopenharmony_ci goto out; 29848c2ecf20Sopenharmony_ci } 29858c2ecf20Sopenharmony_ci 29868c2ecf20Sopenharmony_ci ret = add_tree_block(rc, &key, path, blocks); 29878c2ecf20Sopenharmony_ciout: 29888c2ecf20Sopenharmony_ci btrfs_free_path(path); 29898c2ecf20Sopenharmony_ci return ret; 29908c2ecf20Sopenharmony_ci} 29918c2ecf20Sopenharmony_ci 29928c2ecf20Sopenharmony_cistatic int delete_block_group_cache(struct btrfs_fs_info *fs_info, 29938c2ecf20Sopenharmony_ci struct btrfs_block_group *block_group, 29948c2ecf20Sopenharmony_ci struct inode *inode, 29958c2ecf20Sopenharmony_ci u64 ino) 29968c2ecf20Sopenharmony_ci{ 29978c2ecf20Sopenharmony_ci struct btrfs_root *root = fs_info->tree_root; 29988c2ecf20Sopenharmony_ci struct btrfs_trans_handle *trans; 29998c2ecf20Sopenharmony_ci int ret = 0; 30008c2ecf20Sopenharmony_ci 30018c2ecf20Sopenharmony_ci if (inode) 30028c2ecf20Sopenharmony_ci goto truncate; 30038c2ecf20Sopenharmony_ci 30048c2ecf20Sopenharmony_ci inode = btrfs_iget(fs_info->sb, ino, root); 30058c2ecf20Sopenharmony_ci if (IS_ERR(inode)) 30068c2ecf20Sopenharmony_ci return -ENOENT; 30078c2ecf20Sopenharmony_ci 30088c2ecf20Sopenharmony_citruncate: 30098c2ecf20Sopenharmony_ci ret = btrfs_check_trunc_cache_free_space(fs_info, 30108c2ecf20Sopenharmony_ci &fs_info->global_block_rsv); 30118c2ecf20Sopenharmony_ci if (ret) 30128c2ecf20Sopenharmony_ci goto out; 30138c2ecf20Sopenharmony_ci 30148c2ecf20Sopenharmony_ci trans = btrfs_join_transaction(root); 30158c2ecf20Sopenharmony_ci if (IS_ERR(trans)) { 30168c2ecf20Sopenharmony_ci ret = PTR_ERR(trans); 30178c2ecf20Sopenharmony_ci goto out; 30188c2ecf20Sopenharmony_ci } 30198c2ecf20Sopenharmony_ci 30208c2ecf20Sopenharmony_ci ret = btrfs_truncate_free_space_cache(trans, block_group, inode); 30218c2ecf20Sopenharmony_ci 30228c2ecf20Sopenharmony_ci btrfs_end_transaction(trans); 30238c2ecf20Sopenharmony_ci btrfs_btree_balance_dirty(fs_info); 30248c2ecf20Sopenharmony_ciout: 30258c2ecf20Sopenharmony_ci iput(inode); 30268c2ecf20Sopenharmony_ci return ret; 30278c2ecf20Sopenharmony_ci} 30288c2ecf20Sopenharmony_ci 30298c2ecf20Sopenharmony_ci/* 30308c2ecf20Sopenharmony_ci * Locate the free space cache EXTENT_DATA in root tree leaf and delete the 30318c2ecf20Sopenharmony_ci * cache inode, to avoid free space cache data extent blocking data relocation. 30328c2ecf20Sopenharmony_ci */ 30338c2ecf20Sopenharmony_cistatic int delete_v1_space_cache(struct extent_buffer *leaf, 30348c2ecf20Sopenharmony_ci struct btrfs_block_group *block_group, 30358c2ecf20Sopenharmony_ci u64 data_bytenr) 30368c2ecf20Sopenharmony_ci{ 30378c2ecf20Sopenharmony_ci u64 space_cache_ino; 30388c2ecf20Sopenharmony_ci struct btrfs_file_extent_item *ei; 30398c2ecf20Sopenharmony_ci struct btrfs_key key; 30408c2ecf20Sopenharmony_ci bool found = false; 30418c2ecf20Sopenharmony_ci int i; 30428c2ecf20Sopenharmony_ci int ret; 30438c2ecf20Sopenharmony_ci 30448c2ecf20Sopenharmony_ci if (btrfs_header_owner(leaf) != BTRFS_ROOT_TREE_OBJECTID) 30458c2ecf20Sopenharmony_ci return 0; 30468c2ecf20Sopenharmony_ci 30478c2ecf20Sopenharmony_ci for (i = 0; i < btrfs_header_nritems(leaf); i++) { 30488c2ecf20Sopenharmony_ci u8 type; 30498c2ecf20Sopenharmony_ci 30508c2ecf20Sopenharmony_ci btrfs_item_key_to_cpu(leaf, &key, i); 30518c2ecf20Sopenharmony_ci if (key.type != BTRFS_EXTENT_DATA_KEY) 30528c2ecf20Sopenharmony_ci continue; 30538c2ecf20Sopenharmony_ci ei = btrfs_item_ptr(leaf, i, struct btrfs_file_extent_item); 30548c2ecf20Sopenharmony_ci type = btrfs_file_extent_type(leaf, ei); 30558c2ecf20Sopenharmony_ci 30568c2ecf20Sopenharmony_ci if ((type == BTRFS_FILE_EXTENT_REG || 30578c2ecf20Sopenharmony_ci type == BTRFS_FILE_EXTENT_PREALLOC) && 30588c2ecf20Sopenharmony_ci btrfs_file_extent_disk_bytenr(leaf, ei) == data_bytenr) { 30598c2ecf20Sopenharmony_ci found = true; 30608c2ecf20Sopenharmony_ci space_cache_ino = key.objectid; 30618c2ecf20Sopenharmony_ci break; 30628c2ecf20Sopenharmony_ci } 30638c2ecf20Sopenharmony_ci } 30648c2ecf20Sopenharmony_ci if (!found) 30658c2ecf20Sopenharmony_ci return -ENOENT; 30668c2ecf20Sopenharmony_ci ret = delete_block_group_cache(leaf->fs_info, block_group, NULL, 30678c2ecf20Sopenharmony_ci space_cache_ino); 30688c2ecf20Sopenharmony_ci return ret; 30698c2ecf20Sopenharmony_ci} 30708c2ecf20Sopenharmony_ci 30718c2ecf20Sopenharmony_ci/* 30728c2ecf20Sopenharmony_ci * helper to find all tree blocks that reference a given data extent 30738c2ecf20Sopenharmony_ci */ 30748c2ecf20Sopenharmony_cistatic noinline_for_stack 30758c2ecf20Sopenharmony_ciint add_data_references(struct reloc_control *rc, 30768c2ecf20Sopenharmony_ci struct btrfs_key *extent_key, 30778c2ecf20Sopenharmony_ci struct btrfs_path *path, 30788c2ecf20Sopenharmony_ci struct rb_root *blocks) 30798c2ecf20Sopenharmony_ci{ 30808c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = rc->extent_root->fs_info; 30818c2ecf20Sopenharmony_ci struct ulist *leaves = NULL; 30828c2ecf20Sopenharmony_ci struct ulist_iterator leaf_uiter; 30838c2ecf20Sopenharmony_ci struct ulist_node *ref_node = NULL; 30848c2ecf20Sopenharmony_ci const u32 blocksize = fs_info->nodesize; 30858c2ecf20Sopenharmony_ci int ret = 0; 30868c2ecf20Sopenharmony_ci 30878c2ecf20Sopenharmony_ci btrfs_release_path(path); 30888c2ecf20Sopenharmony_ci ret = btrfs_find_all_leafs(NULL, fs_info, extent_key->objectid, 30898c2ecf20Sopenharmony_ci 0, &leaves, NULL, true); 30908c2ecf20Sopenharmony_ci if (ret < 0) 30918c2ecf20Sopenharmony_ci return ret; 30928c2ecf20Sopenharmony_ci 30938c2ecf20Sopenharmony_ci ULIST_ITER_INIT(&leaf_uiter); 30948c2ecf20Sopenharmony_ci while ((ref_node = ulist_next(leaves, &leaf_uiter))) { 30958c2ecf20Sopenharmony_ci struct extent_buffer *eb; 30968c2ecf20Sopenharmony_ci 30978c2ecf20Sopenharmony_ci eb = read_tree_block(fs_info, ref_node->val, 0, 0, NULL); 30988c2ecf20Sopenharmony_ci if (IS_ERR(eb)) { 30998c2ecf20Sopenharmony_ci ret = PTR_ERR(eb); 31008c2ecf20Sopenharmony_ci break; 31018c2ecf20Sopenharmony_ci } 31028c2ecf20Sopenharmony_ci ret = delete_v1_space_cache(eb, rc->block_group, 31038c2ecf20Sopenharmony_ci extent_key->objectid); 31048c2ecf20Sopenharmony_ci free_extent_buffer(eb); 31058c2ecf20Sopenharmony_ci if (ret < 0) 31068c2ecf20Sopenharmony_ci break; 31078c2ecf20Sopenharmony_ci ret = __add_tree_block(rc, ref_node->val, blocksize, blocks); 31088c2ecf20Sopenharmony_ci if (ret < 0) 31098c2ecf20Sopenharmony_ci break; 31108c2ecf20Sopenharmony_ci } 31118c2ecf20Sopenharmony_ci if (ret < 0) 31128c2ecf20Sopenharmony_ci free_block_list(blocks); 31138c2ecf20Sopenharmony_ci ulist_free(leaves); 31148c2ecf20Sopenharmony_ci return ret; 31158c2ecf20Sopenharmony_ci} 31168c2ecf20Sopenharmony_ci 31178c2ecf20Sopenharmony_ci/* 31188c2ecf20Sopenharmony_ci * helper to find next unprocessed extent 31198c2ecf20Sopenharmony_ci */ 31208c2ecf20Sopenharmony_cistatic noinline_for_stack 31218c2ecf20Sopenharmony_ciint find_next_extent(struct reloc_control *rc, struct btrfs_path *path, 31228c2ecf20Sopenharmony_ci struct btrfs_key *extent_key) 31238c2ecf20Sopenharmony_ci{ 31248c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = rc->extent_root->fs_info; 31258c2ecf20Sopenharmony_ci struct btrfs_key key; 31268c2ecf20Sopenharmony_ci struct extent_buffer *leaf; 31278c2ecf20Sopenharmony_ci u64 start, end, last; 31288c2ecf20Sopenharmony_ci int ret; 31298c2ecf20Sopenharmony_ci 31308c2ecf20Sopenharmony_ci last = rc->block_group->start + rc->block_group->length; 31318c2ecf20Sopenharmony_ci while (1) { 31328c2ecf20Sopenharmony_ci cond_resched(); 31338c2ecf20Sopenharmony_ci if (rc->search_start >= last) { 31348c2ecf20Sopenharmony_ci ret = 1; 31358c2ecf20Sopenharmony_ci break; 31368c2ecf20Sopenharmony_ci } 31378c2ecf20Sopenharmony_ci 31388c2ecf20Sopenharmony_ci key.objectid = rc->search_start; 31398c2ecf20Sopenharmony_ci key.type = BTRFS_EXTENT_ITEM_KEY; 31408c2ecf20Sopenharmony_ci key.offset = 0; 31418c2ecf20Sopenharmony_ci 31428c2ecf20Sopenharmony_ci path->search_commit_root = 1; 31438c2ecf20Sopenharmony_ci path->skip_locking = 1; 31448c2ecf20Sopenharmony_ci ret = btrfs_search_slot(NULL, rc->extent_root, &key, path, 31458c2ecf20Sopenharmony_ci 0, 0); 31468c2ecf20Sopenharmony_ci if (ret < 0) 31478c2ecf20Sopenharmony_ci break; 31488c2ecf20Sopenharmony_cinext: 31498c2ecf20Sopenharmony_ci leaf = path->nodes[0]; 31508c2ecf20Sopenharmony_ci if (path->slots[0] >= btrfs_header_nritems(leaf)) { 31518c2ecf20Sopenharmony_ci ret = btrfs_next_leaf(rc->extent_root, path); 31528c2ecf20Sopenharmony_ci if (ret != 0) 31538c2ecf20Sopenharmony_ci break; 31548c2ecf20Sopenharmony_ci leaf = path->nodes[0]; 31558c2ecf20Sopenharmony_ci } 31568c2ecf20Sopenharmony_ci 31578c2ecf20Sopenharmony_ci btrfs_item_key_to_cpu(leaf, &key, path->slots[0]); 31588c2ecf20Sopenharmony_ci if (key.objectid >= last) { 31598c2ecf20Sopenharmony_ci ret = 1; 31608c2ecf20Sopenharmony_ci break; 31618c2ecf20Sopenharmony_ci } 31628c2ecf20Sopenharmony_ci 31638c2ecf20Sopenharmony_ci if (key.type != BTRFS_EXTENT_ITEM_KEY && 31648c2ecf20Sopenharmony_ci key.type != BTRFS_METADATA_ITEM_KEY) { 31658c2ecf20Sopenharmony_ci path->slots[0]++; 31668c2ecf20Sopenharmony_ci goto next; 31678c2ecf20Sopenharmony_ci } 31688c2ecf20Sopenharmony_ci 31698c2ecf20Sopenharmony_ci if (key.type == BTRFS_EXTENT_ITEM_KEY && 31708c2ecf20Sopenharmony_ci key.objectid + key.offset <= rc->search_start) { 31718c2ecf20Sopenharmony_ci path->slots[0]++; 31728c2ecf20Sopenharmony_ci goto next; 31738c2ecf20Sopenharmony_ci } 31748c2ecf20Sopenharmony_ci 31758c2ecf20Sopenharmony_ci if (key.type == BTRFS_METADATA_ITEM_KEY && 31768c2ecf20Sopenharmony_ci key.objectid + fs_info->nodesize <= 31778c2ecf20Sopenharmony_ci rc->search_start) { 31788c2ecf20Sopenharmony_ci path->slots[0]++; 31798c2ecf20Sopenharmony_ci goto next; 31808c2ecf20Sopenharmony_ci } 31818c2ecf20Sopenharmony_ci 31828c2ecf20Sopenharmony_ci ret = find_first_extent_bit(&rc->processed_blocks, 31838c2ecf20Sopenharmony_ci key.objectid, &start, &end, 31848c2ecf20Sopenharmony_ci EXTENT_DIRTY, NULL); 31858c2ecf20Sopenharmony_ci 31868c2ecf20Sopenharmony_ci if (ret == 0 && start <= key.objectid) { 31878c2ecf20Sopenharmony_ci btrfs_release_path(path); 31888c2ecf20Sopenharmony_ci rc->search_start = end + 1; 31898c2ecf20Sopenharmony_ci } else { 31908c2ecf20Sopenharmony_ci if (key.type == BTRFS_EXTENT_ITEM_KEY) 31918c2ecf20Sopenharmony_ci rc->search_start = key.objectid + key.offset; 31928c2ecf20Sopenharmony_ci else 31938c2ecf20Sopenharmony_ci rc->search_start = key.objectid + 31948c2ecf20Sopenharmony_ci fs_info->nodesize; 31958c2ecf20Sopenharmony_ci memcpy(extent_key, &key, sizeof(key)); 31968c2ecf20Sopenharmony_ci return 0; 31978c2ecf20Sopenharmony_ci } 31988c2ecf20Sopenharmony_ci } 31998c2ecf20Sopenharmony_ci btrfs_release_path(path); 32008c2ecf20Sopenharmony_ci return ret; 32018c2ecf20Sopenharmony_ci} 32028c2ecf20Sopenharmony_ci 32038c2ecf20Sopenharmony_cistatic void set_reloc_control(struct reloc_control *rc) 32048c2ecf20Sopenharmony_ci{ 32058c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = rc->extent_root->fs_info; 32068c2ecf20Sopenharmony_ci 32078c2ecf20Sopenharmony_ci mutex_lock(&fs_info->reloc_mutex); 32088c2ecf20Sopenharmony_ci fs_info->reloc_ctl = rc; 32098c2ecf20Sopenharmony_ci mutex_unlock(&fs_info->reloc_mutex); 32108c2ecf20Sopenharmony_ci} 32118c2ecf20Sopenharmony_ci 32128c2ecf20Sopenharmony_cistatic void unset_reloc_control(struct reloc_control *rc) 32138c2ecf20Sopenharmony_ci{ 32148c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = rc->extent_root->fs_info; 32158c2ecf20Sopenharmony_ci 32168c2ecf20Sopenharmony_ci mutex_lock(&fs_info->reloc_mutex); 32178c2ecf20Sopenharmony_ci fs_info->reloc_ctl = NULL; 32188c2ecf20Sopenharmony_ci mutex_unlock(&fs_info->reloc_mutex); 32198c2ecf20Sopenharmony_ci} 32208c2ecf20Sopenharmony_ci 32218c2ecf20Sopenharmony_cistatic int check_extent_flags(u64 flags) 32228c2ecf20Sopenharmony_ci{ 32238c2ecf20Sopenharmony_ci if ((flags & BTRFS_EXTENT_FLAG_DATA) && 32248c2ecf20Sopenharmony_ci (flags & BTRFS_EXTENT_FLAG_TREE_BLOCK)) 32258c2ecf20Sopenharmony_ci return 1; 32268c2ecf20Sopenharmony_ci if (!(flags & BTRFS_EXTENT_FLAG_DATA) && 32278c2ecf20Sopenharmony_ci !(flags & BTRFS_EXTENT_FLAG_TREE_BLOCK)) 32288c2ecf20Sopenharmony_ci return 1; 32298c2ecf20Sopenharmony_ci if ((flags & BTRFS_EXTENT_FLAG_DATA) && 32308c2ecf20Sopenharmony_ci (flags & BTRFS_BLOCK_FLAG_FULL_BACKREF)) 32318c2ecf20Sopenharmony_ci return 1; 32328c2ecf20Sopenharmony_ci return 0; 32338c2ecf20Sopenharmony_ci} 32348c2ecf20Sopenharmony_ci 32358c2ecf20Sopenharmony_cistatic noinline_for_stack 32368c2ecf20Sopenharmony_ciint prepare_to_relocate(struct reloc_control *rc) 32378c2ecf20Sopenharmony_ci{ 32388c2ecf20Sopenharmony_ci struct btrfs_trans_handle *trans; 32398c2ecf20Sopenharmony_ci int ret; 32408c2ecf20Sopenharmony_ci 32418c2ecf20Sopenharmony_ci rc->block_rsv = btrfs_alloc_block_rsv(rc->extent_root->fs_info, 32428c2ecf20Sopenharmony_ci BTRFS_BLOCK_RSV_TEMP); 32438c2ecf20Sopenharmony_ci if (!rc->block_rsv) 32448c2ecf20Sopenharmony_ci return -ENOMEM; 32458c2ecf20Sopenharmony_ci 32468c2ecf20Sopenharmony_ci memset(&rc->cluster, 0, sizeof(rc->cluster)); 32478c2ecf20Sopenharmony_ci rc->search_start = rc->block_group->start; 32488c2ecf20Sopenharmony_ci rc->extents_found = 0; 32498c2ecf20Sopenharmony_ci rc->nodes_relocated = 0; 32508c2ecf20Sopenharmony_ci rc->merging_rsv_size = 0; 32518c2ecf20Sopenharmony_ci rc->reserved_bytes = 0; 32528c2ecf20Sopenharmony_ci rc->block_rsv->size = rc->extent_root->fs_info->nodesize * 32538c2ecf20Sopenharmony_ci RELOCATION_RESERVED_NODES; 32548c2ecf20Sopenharmony_ci ret = btrfs_block_rsv_refill(rc->extent_root, 32558c2ecf20Sopenharmony_ci rc->block_rsv, rc->block_rsv->size, 32568c2ecf20Sopenharmony_ci BTRFS_RESERVE_FLUSH_ALL); 32578c2ecf20Sopenharmony_ci if (ret) 32588c2ecf20Sopenharmony_ci return ret; 32598c2ecf20Sopenharmony_ci 32608c2ecf20Sopenharmony_ci rc->create_reloc_tree = 1; 32618c2ecf20Sopenharmony_ci set_reloc_control(rc); 32628c2ecf20Sopenharmony_ci 32638c2ecf20Sopenharmony_ci trans = btrfs_join_transaction(rc->extent_root); 32648c2ecf20Sopenharmony_ci if (IS_ERR(trans)) { 32658c2ecf20Sopenharmony_ci unset_reloc_control(rc); 32668c2ecf20Sopenharmony_ci /* 32678c2ecf20Sopenharmony_ci * extent tree is not a ref_cow tree and has no reloc_root to 32688c2ecf20Sopenharmony_ci * cleanup. And callers are responsible to free the above 32698c2ecf20Sopenharmony_ci * block rsv. 32708c2ecf20Sopenharmony_ci */ 32718c2ecf20Sopenharmony_ci return PTR_ERR(trans); 32728c2ecf20Sopenharmony_ci } 32738c2ecf20Sopenharmony_ci 32748c2ecf20Sopenharmony_ci ret = btrfs_commit_transaction(trans); 32758c2ecf20Sopenharmony_ci if (ret) 32768c2ecf20Sopenharmony_ci unset_reloc_control(rc); 32778c2ecf20Sopenharmony_ci 32788c2ecf20Sopenharmony_ci return ret; 32798c2ecf20Sopenharmony_ci} 32808c2ecf20Sopenharmony_ci 32818c2ecf20Sopenharmony_cistatic noinline_for_stack int relocate_block_group(struct reloc_control *rc) 32828c2ecf20Sopenharmony_ci{ 32838c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = rc->extent_root->fs_info; 32848c2ecf20Sopenharmony_ci struct rb_root blocks = RB_ROOT; 32858c2ecf20Sopenharmony_ci struct btrfs_key key; 32868c2ecf20Sopenharmony_ci struct btrfs_trans_handle *trans = NULL; 32878c2ecf20Sopenharmony_ci struct btrfs_path *path; 32888c2ecf20Sopenharmony_ci struct btrfs_extent_item *ei; 32898c2ecf20Sopenharmony_ci u64 flags; 32908c2ecf20Sopenharmony_ci u32 item_size; 32918c2ecf20Sopenharmony_ci int ret; 32928c2ecf20Sopenharmony_ci int err = 0; 32938c2ecf20Sopenharmony_ci int progress = 0; 32948c2ecf20Sopenharmony_ci 32958c2ecf20Sopenharmony_ci path = btrfs_alloc_path(); 32968c2ecf20Sopenharmony_ci if (!path) 32978c2ecf20Sopenharmony_ci return -ENOMEM; 32988c2ecf20Sopenharmony_ci path->reada = READA_FORWARD; 32998c2ecf20Sopenharmony_ci 33008c2ecf20Sopenharmony_ci ret = prepare_to_relocate(rc); 33018c2ecf20Sopenharmony_ci if (ret) { 33028c2ecf20Sopenharmony_ci err = ret; 33038c2ecf20Sopenharmony_ci goto out_free; 33048c2ecf20Sopenharmony_ci } 33058c2ecf20Sopenharmony_ci 33068c2ecf20Sopenharmony_ci while (1) { 33078c2ecf20Sopenharmony_ci rc->reserved_bytes = 0; 33088c2ecf20Sopenharmony_ci ret = btrfs_block_rsv_refill(rc->extent_root, 33098c2ecf20Sopenharmony_ci rc->block_rsv, rc->block_rsv->size, 33108c2ecf20Sopenharmony_ci BTRFS_RESERVE_FLUSH_ALL); 33118c2ecf20Sopenharmony_ci if (ret) { 33128c2ecf20Sopenharmony_ci err = ret; 33138c2ecf20Sopenharmony_ci break; 33148c2ecf20Sopenharmony_ci } 33158c2ecf20Sopenharmony_ci progress++; 33168c2ecf20Sopenharmony_ci trans = btrfs_start_transaction(rc->extent_root, 0); 33178c2ecf20Sopenharmony_ci if (IS_ERR(trans)) { 33188c2ecf20Sopenharmony_ci err = PTR_ERR(trans); 33198c2ecf20Sopenharmony_ci trans = NULL; 33208c2ecf20Sopenharmony_ci break; 33218c2ecf20Sopenharmony_ci } 33228c2ecf20Sopenharmony_cirestart: 33238c2ecf20Sopenharmony_ci if (update_backref_cache(trans, &rc->backref_cache)) { 33248c2ecf20Sopenharmony_ci btrfs_end_transaction(trans); 33258c2ecf20Sopenharmony_ci trans = NULL; 33268c2ecf20Sopenharmony_ci continue; 33278c2ecf20Sopenharmony_ci } 33288c2ecf20Sopenharmony_ci 33298c2ecf20Sopenharmony_ci ret = find_next_extent(rc, path, &key); 33308c2ecf20Sopenharmony_ci if (ret < 0) 33318c2ecf20Sopenharmony_ci err = ret; 33328c2ecf20Sopenharmony_ci if (ret != 0) 33338c2ecf20Sopenharmony_ci break; 33348c2ecf20Sopenharmony_ci 33358c2ecf20Sopenharmony_ci rc->extents_found++; 33368c2ecf20Sopenharmony_ci 33378c2ecf20Sopenharmony_ci ei = btrfs_item_ptr(path->nodes[0], path->slots[0], 33388c2ecf20Sopenharmony_ci struct btrfs_extent_item); 33398c2ecf20Sopenharmony_ci item_size = btrfs_item_size_nr(path->nodes[0], path->slots[0]); 33408c2ecf20Sopenharmony_ci if (item_size >= sizeof(*ei)) { 33418c2ecf20Sopenharmony_ci flags = btrfs_extent_flags(path->nodes[0], ei); 33428c2ecf20Sopenharmony_ci ret = check_extent_flags(flags); 33438c2ecf20Sopenharmony_ci BUG_ON(ret); 33448c2ecf20Sopenharmony_ci } else if (unlikely(item_size == sizeof(struct btrfs_extent_item_v0))) { 33458c2ecf20Sopenharmony_ci err = -EINVAL; 33468c2ecf20Sopenharmony_ci btrfs_print_v0_err(trans->fs_info); 33478c2ecf20Sopenharmony_ci btrfs_abort_transaction(trans, err); 33488c2ecf20Sopenharmony_ci break; 33498c2ecf20Sopenharmony_ci } else { 33508c2ecf20Sopenharmony_ci BUG(); 33518c2ecf20Sopenharmony_ci } 33528c2ecf20Sopenharmony_ci 33538c2ecf20Sopenharmony_ci if (flags & BTRFS_EXTENT_FLAG_TREE_BLOCK) { 33548c2ecf20Sopenharmony_ci ret = add_tree_block(rc, &key, path, &blocks); 33558c2ecf20Sopenharmony_ci } else if (rc->stage == UPDATE_DATA_PTRS && 33568c2ecf20Sopenharmony_ci (flags & BTRFS_EXTENT_FLAG_DATA)) { 33578c2ecf20Sopenharmony_ci ret = add_data_references(rc, &key, path, &blocks); 33588c2ecf20Sopenharmony_ci } else { 33598c2ecf20Sopenharmony_ci btrfs_release_path(path); 33608c2ecf20Sopenharmony_ci ret = 0; 33618c2ecf20Sopenharmony_ci } 33628c2ecf20Sopenharmony_ci if (ret < 0) { 33638c2ecf20Sopenharmony_ci err = ret; 33648c2ecf20Sopenharmony_ci break; 33658c2ecf20Sopenharmony_ci } 33668c2ecf20Sopenharmony_ci 33678c2ecf20Sopenharmony_ci if (!RB_EMPTY_ROOT(&blocks)) { 33688c2ecf20Sopenharmony_ci ret = relocate_tree_blocks(trans, rc, &blocks); 33698c2ecf20Sopenharmony_ci if (ret < 0) { 33708c2ecf20Sopenharmony_ci if (ret != -EAGAIN) { 33718c2ecf20Sopenharmony_ci err = ret; 33728c2ecf20Sopenharmony_ci break; 33738c2ecf20Sopenharmony_ci } 33748c2ecf20Sopenharmony_ci rc->extents_found--; 33758c2ecf20Sopenharmony_ci rc->search_start = key.objectid; 33768c2ecf20Sopenharmony_ci } 33778c2ecf20Sopenharmony_ci } 33788c2ecf20Sopenharmony_ci 33798c2ecf20Sopenharmony_ci btrfs_end_transaction_throttle(trans); 33808c2ecf20Sopenharmony_ci btrfs_btree_balance_dirty(fs_info); 33818c2ecf20Sopenharmony_ci trans = NULL; 33828c2ecf20Sopenharmony_ci 33838c2ecf20Sopenharmony_ci if (rc->stage == MOVE_DATA_EXTENTS && 33848c2ecf20Sopenharmony_ci (flags & BTRFS_EXTENT_FLAG_DATA)) { 33858c2ecf20Sopenharmony_ci rc->found_file_extent = 1; 33868c2ecf20Sopenharmony_ci ret = relocate_data_extent(rc->data_inode, 33878c2ecf20Sopenharmony_ci &key, &rc->cluster); 33888c2ecf20Sopenharmony_ci if (ret < 0) { 33898c2ecf20Sopenharmony_ci err = ret; 33908c2ecf20Sopenharmony_ci break; 33918c2ecf20Sopenharmony_ci } 33928c2ecf20Sopenharmony_ci } 33938c2ecf20Sopenharmony_ci if (btrfs_should_cancel_balance(fs_info)) { 33948c2ecf20Sopenharmony_ci err = -ECANCELED; 33958c2ecf20Sopenharmony_ci break; 33968c2ecf20Sopenharmony_ci } 33978c2ecf20Sopenharmony_ci } 33988c2ecf20Sopenharmony_ci if (trans && progress && err == -ENOSPC) { 33998c2ecf20Sopenharmony_ci ret = btrfs_force_chunk_alloc(trans, rc->block_group->flags); 34008c2ecf20Sopenharmony_ci if (ret == 1) { 34018c2ecf20Sopenharmony_ci err = 0; 34028c2ecf20Sopenharmony_ci progress = 0; 34038c2ecf20Sopenharmony_ci goto restart; 34048c2ecf20Sopenharmony_ci } 34058c2ecf20Sopenharmony_ci } 34068c2ecf20Sopenharmony_ci 34078c2ecf20Sopenharmony_ci btrfs_release_path(path); 34088c2ecf20Sopenharmony_ci clear_extent_bits(&rc->processed_blocks, 0, (u64)-1, EXTENT_DIRTY); 34098c2ecf20Sopenharmony_ci 34108c2ecf20Sopenharmony_ci if (trans) { 34118c2ecf20Sopenharmony_ci btrfs_end_transaction_throttle(trans); 34128c2ecf20Sopenharmony_ci btrfs_btree_balance_dirty(fs_info); 34138c2ecf20Sopenharmony_ci } 34148c2ecf20Sopenharmony_ci 34158c2ecf20Sopenharmony_ci if (!err) { 34168c2ecf20Sopenharmony_ci ret = relocate_file_extent_cluster(rc->data_inode, 34178c2ecf20Sopenharmony_ci &rc->cluster); 34188c2ecf20Sopenharmony_ci if (ret < 0) 34198c2ecf20Sopenharmony_ci err = ret; 34208c2ecf20Sopenharmony_ci } 34218c2ecf20Sopenharmony_ci 34228c2ecf20Sopenharmony_ci rc->create_reloc_tree = 0; 34238c2ecf20Sopenharmony_ci set_reloc_control(rc); 34248c2ecf20Sopenharmony_ci 34258c2ecf20Sopenharmony_ci btrfs_backref_release_cache(&rc->backref_cache); 34268c2ecf20Sopenharmony_ci btrfs_block_rsv_release(fs_info, rc->block_rsv, (u64)-1, NULL); 34278c2ecf20Sopenharmony_ci 34288c2ecf20Sopenharmony_ci /* 34298c2ecf20Sopenharmony_ci * Even in the case when the relocation is cancelled, we should all go 34308c2ecf20Sopenharmony_ci * through prepare_to_merge() and merge_reloc_roots(). 34318c2ecf20Sopenharmony_ci * 34328c2ecf20Sopenharmony_ci * For error (including cancelled balance), prepare_to_merge() will 34338c2ecf20Sopenharmony_ci * mark all reloc trees orphan, then queue them for cleanup in 34348c2ecf20Sopenharmony_ci * merge_reloc_roots() 34358c2ecf20Sopenharmony_ci */ 34368c2ecf20Sopenharmony_ci err = prepare_to_merge(rc, err); 34378c2ecf20Sopenharmony_ci 34388c2ecf20Sopenharmony_ci merge_reloc_roots(rc); 34398c2ecf20Sopenharmony_ci 34408c2ecf20Sopenharmony_ci rc->merge_reloc_tree = 0; 34418c2ecf20Sopenharmony_ci unset_reloc_control(rc); 34428c2ecf20Sopenharmony_ci btrfs_block_rsv_release(fs_info, rc->block_rsv, (u64)-1, NULL); 34438c2ecf20Sopenharmony_ci 34448c2ecf20Sopenharmony_ci /* get rid of pinned extents */ 34458c2ecf20Sopenharmony_ci trans = btrfs_join_transaction(rc->extent_root); 34468c2ecf20Sopenharmony_ci if (IS_ERR(trans)) { 34478c2ecf20Sopenharmony_ci err = PTR_ERR(trans); 34488c2ecf20Sopenharmony_ci goto out_free; 34498c2ecf20Sopenharmony_ci } 34508c2ecf20Sopenharmony_ci ret = btrfs_commit_transaction(trans); 34518c2ecf20Sopenharmony_ci if (ret && !err) 34528c2ecf20Sopenharmony_ci err = ret; 34538c2ecf20Sopenharmony_ciout_free: 34548c2ecf20Sopenharmony_ci ret = clean_dirty_subvols(rc); 34558c2ecf20Sopenharmony_ci if (ret < 0 && !err) 34568c2ecf20Sopenharmony_ci err = ret; 34578c2ecf20Sopenharmony_ci btrfs_free_block_rsv(fs_info, rc->block_rsv); 34588c2ecf20Sopenharmony_ci btrfs_free_path(path); 34598c2ecf20Sopenharmony_ci return err; 34608c2ecf20Sopenharmony_ci} 34618c2ecf20Sopenharmony_ci 34628c2ecf20Sopenharmony_cistatic int __insert_orphan_inode(struct btrfs_trans_handle *trans, 34638c2ecf20Sopenharmony_ci struct btrfs_root *root, u64 objectid) 34648c2ecf20Sopenharmony_ci{ 34658c2ecf20Sopenharmony_ci struct btrfs_path *path; 34668c2ecf20Sopenharmony_ci struct btrfs_inode_item *item; 34678c2ecf20Sopenharmony_ci struct extent_buffer *leaf; 34688c2ecf20Sopenharmony_ci int ret; 34698c2ecf20Sopenharmony_ci 34708c2ecf20Sopenharmony_ci path = btrfs_alloc_path(); 34718c2ecf20Sopenharmony_ci if (!path) 34728c2ecf20Sopenharmony_ci return -ENOMEM; 34738c2ecf20Sopenharmony_ci 34748c2ecf20Sopenharmony_ci ret = btrfs_insert_empty_inode(trans, root, path, objectid); 34758c2ecf20Sopenharmony_ci if (ret) 34768c2ecf20Sopenharmony_ci goto out; 34778c2ecf20Sopenharmony_ci 34788c2ecf20Sopenharmony_ci leaf = path->nodes[0]; 34798c2ecf20Sopenharmony_ci item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_inode_item); 34808c2ecf20Sopenharmony_ci memzero_extent_buffer(leaf, (unsigned long)item, sizeof(*item)); 34818c2ecf20Sopenharmony_ci btrfs_set_inode_generation(leaf, item, 1); 34828c2ecf20Sopenharmony_ci btrfs_set_inode_size(leaf, item, 0); 34838c2ecf20Sopenharmony_ci btrfs_set_inode_mode(leaf, item, S_IFREG | 0600); 34848c2ecf20Sopenharmony_ci btrfs_set_inode_flags(leaf, item, BTRFS_INODE_NOCOMPRESS | 34858c2ecf20Sopenharmony_ci BTRFS_INODE_PREALLOC); 34868c2ecf20Sopenharmony_ci btrfs_mark_buffer_dirty(leaf); 34878c2ecf20Sopenharmony_ciout: 34888c2ecf20Sopenharmony_ci btrfs_free_path(path); 34898c2ecf20Sopenharmony_ci return ret; 34908c2ecf20Sopenharmony_ci} 34918c2ecf20Sopenharmony_ci 34928c2ecf20Sopenharmony_ci/* 34938c2ecf20Sopenharmony_ci * helper to create inode for data relocation. 34948c2ecf20Sopenharmony_ci * the inode is in data relocation tree and its link count is 0 34958c2ecf20Sopenharmony_ci */ 34968c2ecf20Sopenharmony_cistatic noinline_for_stack 34978c2ecf20Sopenharmony_cistruct inode *create_reloc_inode(struct btrfs_fs_info *fs_info, 34988c2ecf20Sopenharmony_ci struct btrfs_block_group *group) 34998c2ecf20Sopenharmony_ci{ 35008c2ecf20Sopenharmony_ci struct inode *inode = NULL; 35018c2ecf20Sopenharmony_ci struct btrfs_trans_handle *trans; 35028c2ecf20Sopenharmony_ci struct btrfs_root *root; 35038c2ecf20Sopenharmony_ci u64 objectid; 35048c2ecf20Sopenharmony_ci int err = 0; 35058c2ecf20Sopenharmony_ci 35068c2ecf20Sopenharmony_ci root = btrfs_grab_root(fs_info->data_reloc_root); 35078c2ecf20Sopenharmony_ci trans = btrfs_start_transaction(root, 6); 35088c2ecf20Sopenharmony_ci if (IS_ERR(trans)) { 35098c2ecf20Sopenharmony_ci btrfs_put_root(root); 35108c2ecf20Sopenharmony_ci return ERR_CAST(trans); 35118c2ecf20Sopenharmony_ci } 35128c2ecf20Sopenharmony_ci 35138c2ecf20Sopenharmony_ci err = btrfs_find_free_objectid(root, &objectid); 35148c2ecf20Sopenharmony_ci if (err) 35158c2ecf20Sopenharmony_ci goto out; 35168c2ecf20Sopenharmony_ci 35178c2ecf20Sopenharmony_ci err = __insert_orphan_inode(trans, root, objectid); 35188c2ecf20Sopenharmony_ci BUG_ON(err); 35198c2ecf20Sopenharmony_ci 35208c2ecf20Sopenharmony_ci inode = btrfs_iget(fs_info->sb, objectid, root); 35218c2ecf20Sopenharmony_ci BUG_ON(IS_ERR(inode)); 35228c2ecf20Sopenharmony_ci BTRFS_I(inode)->index_cnt = group->start; 35238c2ecf20Sopenharmony_ci 35248c2ecf20Sopenharmony_ci err = btrfs_orphan_add(trans, BTRFS_I(inode)); 35258c2ecf20Sopenharmony_ciout: 35268c2ecf20Sopenharmony_ci btrfs_put_root(root); 35278c2ecf20Sopenharmony_ci btrfs_end_transaction(trans); 35288c2ecf20Sopenharmony_ci btrfs_btree_balance_dirty(fs_info); 35298c2ecf20Sopenharmony_ci if (err) { 35308c2ecf20Sopenharmony_ci if (inode) 35318c2ecf20Sopenharmony_ci iput(inode); 35328c2ecf20Sopenharmony_ci inode = ERR_PTR(err); 35338c2ecf20Sopenharmony_ci } 35348c2ecf20Sopenharmony_ci return inode; 35358c2ecf20Sopenharmony_ci} 35368c2ecf20Sopenharmony_ci 35378c2ecf20Sopenharmony_cistatic struct reloc_control *alloc_reloc_control(struct btrfs_fs_info *fs_info) 35388c2ecf20Sopenharmony_ci{ 35398c2ecf20Sopenharmony_ci struct reloc_control *rc; 35408c2ecf20Sopenharmony_ci 35418c2ecf20Sopenharmony_ci rc = kzalloc(sizeof(*rc), GFP_NOFS); 35428c2ecf20Sopenharmony_ci if (!rc) 35438c2ecf20Sopenharmony_ci return NULL; 35448c2ecf20Sopenharmony_ci 35458c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&rc->reloc_roots); 35468c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&rc->dirty_subvol_roots); 35478c2ecf20Sopenharmony_ci btrfs_backref_init_cache(fs_info, &rc->backref_cache, 1); 35488c2ecf20Sopenharmony_ci mapping_tree_init(&rc->reloc_root_tree); 35498c2ecf20Sopenharmony_ci extent_io_tree_init(fs_info, &rc->processed_blocks, 35508c2ecf20Sopenharmony_ci IO_TREE_RELOC_BLOCKS, NULL); 35518c2ecf20Sopenharmony_ci return rc; 35528c2ecf20Sopenharmony_ci} 35538c2ecf20Sopenharmony_ci 35548c2ecf20Sopenharmony_cistatic void free_reloc_control(struct reloc_control *rc) 35558c2ecf20Sopenharmony_ci{ 35568c2ecf20Sopenharmony_ci struct mapping_node *node, *tmp; 35578c2ecf20Sopenharmony_ci 35588c2ecf20Sopenharmony_ci free_reloc_roots(&rc->reloc_roots); 35598c2ecf20Sopenharmony_ci rbtree_postorder_for_each_entry_safe(node, tmp, 35608c2ecf20Sopenharmony_ci &rc->reloc_root_tree.rb_root, rb_node) 35618c2ecf20Sopenharmony_ci kfree(node); 35628c2ecf20Sopenharmony_ci 35638c2ecf20Sopenharmony_ci kfree(rc); 35648c2ecf20Sopenharmony_ci} 35658c2ecf20Sopenharmony_ci 35668c2ecf20Sopenharmony_ci/* 35678c2ecf20Sopenharmony_ci * Print the block group being relocated 35688c2ecf20Sopenharmony_ci */ 35698c2ecf20Sopenharmony_cistatic void describe_relocation(struct btrfs_fs_info *fs_info, 35708c2ecf20Sopenharmony_ci struct btrfs_block_group *block_group) 35718c2ecf20Sopenharmony_ci{ 35728c2ecf20Sopenharmony_ci char buf[128] = {'\0'}; 35738c2ecf20Sopenharmony_ci 35748c2ecf20Sopenharmony_ci btrfs_describe_block_groups(block_group->flags, buf, sizeof(buf)); 35758c2ecf20Sopenharmony_ci 35768c2ecf20Sopenharmony_ci btrfs_info(fs_info, 35778c2ecf20Sopenharmony_ci "relocating block group %llu flags %s", 35788c2ecf20Sopenharmony_ci block_group->start, buf); 35798c2ecf20Sopenharmony_ci} 35808c2ecf20Sopenharmony_ci 35818c2ecf20Sopenharmony_cistatic const char *stage_to_string(int stage) 35828c2ecf20Sopenharmony_ci{ 35838c2ecf20Sopenharmony_ci if (stage == MOVE_DATA_EXTENTS) 35848c2ecf20Sopenharmony_ci return "move data extents"; 35858c2ecf20Sopenharmony_ci if (stage == UPDATE_DATA_PTRS) 35868c2ecf20Sopenharmony_ci return "update data pointers"; 35878c2ecf20Sopenharmony_ci return "unknown"; 35888c2ecf20Sopenharmony_ci} 35898c2ecf20Sopenharmony_ci 35908c2ecf20Sopenharmony_ci/* 35918c2ecf20Sopenharmony_ci * function to relocate all extents in a block group. 35928c2ecf20Sopenharmony_ci */ 35938c2ecf20Sopenharmony_ciint btrfs_relocate_block_group(struct btrfs_fs_info *fs_info, u64 group_start) 35948c2ecf20Sopenharmony_ci{ 35958c2ecf20Sopenharmony_ci struct btrfs_block_group *bg; 35968c2ecf20Sopenharmony_ci struct btrfs_root *extent_root = fs_info->extent_root; 35978c2ecf20Sopenharmony_ci struct reloc_control *rc; 35988c2ecf20Sopenharmony_ci struct inode *inode; 35998c2ecf20Sopenharmony_ci struct btrfs_path *path; 36008c2ecf20Sopenharmony_ci int ret; 36018c2ecf20Sopenharmony_ci int rw = 0; 36028c2ecf20Sopenharmony_ci int err = 0; 36038c2ecf20Sopenharmony_ci 36048c2ecf20Sopenharmony_ci bg = btrfs_lookup_block_group(fs_info, group_start); 36058c2ecf20Sopenharmony_ci if (!bg) 36068c2ecf20Sopenharmony_ci return -ENOENT; 36078c2ecf20Sopenharmony_ci 36088c2ecf20Sopenharmony_ci if (btrfs_pinned_by_swapfile(fs_info, bg)) { 36098c2ecf20Sopenharmony_ci btrfs_put_block_group(bg); 36108c2ecf20Sopenharmony_ci return -ETXTBSY; 36118c2ecf20Sopenharmony_ci } 36128c2ecf20Sopenharmony_ci 36138c2ecf20Sopenharmony_ci rc = alloc_reloc_control(fs_info); 36148c2ecf20Sopenharmony_ci if (!rc) { 36158c2ecf20Sopenharmony_ci btrfs_put_block_group(bg); 36168c2ecf20Sopenharmony_ci return -ENOMEM; 36178c2ecf20Sopenharmony_ci } 36188c2ecf20Sopenharmony_ci 36198c2ecf20Sopenharmony_ci rc->extent_root = extent_root; 36208c2ecf20Sopenharmony_ci rc->block_group = bg; 36218c2ecf20Sopenharmony_ci 36228c2ecf20Sopenharmony_ci ret = btrfs_inc_block_group_ro(rc->block_group, true); 36238c2ecf20Sopenharmony_ci if (ret) { 36248c2ecf20Sopenharmony_ci err = ret; 36258c2ecf20Sopenharmony_ci goto out; 36268c2ecf20Sopenharmony_ci } 36278c2ecf20Sopenharmony_ci rw = 1; 36288c2ecf20Sopenharmony_ci 36298c2ecf20Sopenharmony_ci path = btrfs_alloc_path(); 36308c2ecf20Sopenharmony_ci if (!path) { 36318c2ecf20Sopenharmony_ci err = -ENOMEM; 36328c2ecf20Sopenharmony_ci goto out; 36338c2ecf20Sopenharmony_ci } 36348c2ecf20Sopenharmony_ci 36358c2ecf20Sopenharmony_ci inode = lookup_free_space_inode(rc->block_group, path); 36368c2ecf20Sopenharmony_ci btrfs_free_path(path); 36378c2ecf20Sopenharmony_ci 36388c2ecf20Sopenharmony_ci if (!IS_ERR(inode)) 36398c2ecf20Sopenharmony_ci ret = delete_block_group_cache(fs_info, rc->block_group, inode, 0); 36408c2ecf20Sopenharmony_ci else 36418c2ecf20Sopenharmony_ci ret = PTR_ERR(inode); 36428c2ecf20Sopenharmony_ci 36438c2ecf20Sopenharmony_ci if (ret && ret != -ENOENT) { 36448c2ecf20Sopenharmony_ci err = ret; 36458c2ecf20Sopenharmony_ci goto out; 36468c2ecf20Sopenharmony_ci } 36478c2ecf20Sopenharmony_ci 36488c2ecf20Sopenharmony_ci rc->data_inode = create_reloc_inode(fs_info, rc->block_group); 36498c2ecf20Sopenharmony_ci if (IS_ERR(rc->data_inode)) { 36508c2ecf20Sopenharmony_ci err = PTR_ERR(rc->data_inode); 36518c2ecf20Sopenharmony_ci rc->data_inode = NULL; 36528c2ecf20Sopenharmony_ci goto out; 36538c2ecf20Sopenharmony_ci } 36548c2ecf20Sopenharmony_ci 36558c2ecf20Sopenharmony_ci describe_relocation(fs_info, rc->block_group); 36568c2ecf20Sopenharmony_ci 36578c2ecf20Sopenharmony_ci btrfs_wait_block_group_reservations(rc->block_group); 36588c2ecf20Sopenharmony_ci btrfs_wait_nocow_writers(rc->block_group); 36598c2ecf20Sopenharmony_ci btrfs_wait_ordered_roots(fs_info, U64_MAX, 36608c2ecf20Sopenharmony_ci rc->block_group->start, 36618c2ecf20Sopenharmony_ci rc->block_group->length); 36628c2ecf20Sopenharmony_ci 36638c2ecf20Sopenharmony_ci while (1) { 36648c2ecf20Sopenharmony_ci int finishes_stage; 36658c2ecf20Sopenharmony_ci 36668c2ecf20Sopenharmony_ci mutex_lock(&fs_info->cleaner_mutex); 36678c2ecf20Sopenharmony_ci ret = relocate_block_group(rc); 36688c2ecf20Sopenharmony_ci mutex_unlock(&fs_info->cleaner_mutex); 36698c2ecf20Sopenharmony_ci if (ret < 0) 36708c2ecf20Sopenharmony_ci err = ret; 36718c2ecf20Sopenharmony_ci 36728c2ecf20Sopenharmony_ci finishes_stage = rc->stage; 36738c2ecf20Sopenharmony_ci /* 36748c2ecf20Sopenharmony_ci * We may have gotten ENOSPC after we already dirtied some 36758c2ecf20Sopenharmony_ci * extents. If writeout happens while we're relocating a 36768c2ecf20Sopenharmony_ci * different block group we could end up hitting the 36778c2ecf20Sopenharmony_ci * BUG_ON(rc->stage == UPDATE_DATA_PTRS) in 36788c2ecf20Sopenharmony_ci * btrfs_reloc_cow_block. Make sure we write everything out 36798c2ecf20Sopenharmony_ci * properly so we don't trip over this problem, and then break 36808c2ecf20Sopenharmony_ci * out of the loop if we hit an error. 36818c2ecf20Sopenharmony_ci */ 36828c2ecf20Sopenharmony_ci if (rc->stage == MOVE_DATA_EXTENTS && rc->found_file_extent) { 36838c2ecf20Sopenharmony_ci ret = btrfs_wait_ordered_range(rc->data_inode, 0, 36848c2ecf20Sopenharmony_ci (u64)-1); 36858c2ecf20Sopenharmony_ci if (ret) 36868c2ecf20Sopenharmony_ci err = ret; 36878c2ecf20Sopenharmony_ci invalidate_mapping_pages(rc->data_inode->i_mapping, 36888c2ecf20Sopenharmony_ci 0, -1); 36898c2ecf20Sopenharmony_ci rc->stage = UPDATE_DATA_PTRS; 36908c2ecf20Sopenharmony_ci } 36918c2ecf20Sopenharmony_ci 36928c2ecf20Sopenharmony_ci if (err < 0) 36938c2ecf20Sopenharmony_ci goto out; 36948c2ecf20Sopenharmony_ci 36958c2ecf20Sopenharmony_ci if (rc->extents_found == 0) 36968c2ecf20Sopenharmony_ci break; 36978c2ecf20Sopenharmony_ci 36988c2ecf20Sopenharmony_ci btrfs_info(fs_info, "found %llu extents, stage: %s", 36998c2ecf20Sopenharmony_ci rc->extents_found, stage_to_string(finishes_stage)); 37008c2ecf20Sopenharmony_ci } 37018c2ecf20Sopenharmony_ci 37028c2ecf20Sopenharmony_ci WARN_ON(rc->block_group->pinned > 0); 37038c2ecf20Sopenharmony_ci WARN_ON(rc->block_group->reserved > 0); 37048c2ecf20Sopenharmony_ci WARN_ON(rc->block_group->used > 0); 37058c2ecf20Sopenharmony_ciout: 37068c2ecf20Sopenharmony_ci if (err && rw) 37078c2ecf20Sopenharmony_ci btrfs_dec_block_group_ro(rc->block_group); 37088c2ecf20Sopenharmony_ci iput(rc->data_inode); 37098c2ecf20Sopenharmony_ci btrfs_put_block_group(rc->block_group); 37108c2ecf20Sopenharmony_ci free_reloc_control(rc); 37118c2ecf20Sopenharmony_ci return err; 37128c2ecf20Sopenharmony_ci} 37138c2ecf20Sopenharmony_ci 37148c2ecf20Sopenharmony_cistatic noinline_for_stack int mark_garbage_root(struct btrfs_root *root) 37158c2ecf20Sopenharmony_ci{ 37168c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = root->fs_info; 37178c2ecf20Sopenharmony_ci struct btrfs_trans_handle *trans; 37188c2ecf20Sopenharmony_ci int ret, err; 37198c2ecf20Sopenharmony_ci 37208c2ecf20Sopenharmony_ci trans = btrfs_start_transaction(fs_info->tree_root, 0); 37218c2ecf20Sopenharmony_ci if (IS_ERR(trans)) 37228c2ecf20Sopenharmony_ci return PTR_ERR(trans); 37238c2ecf20Sopenharmony_ci 37248c2ecf20Sopenharmony_ci memset(&root->root_item.drop_progress, 0, 37258c2ecf20Sopenharmony_ci sizeof(root->root_item.drop_progress)); 37268c2ecf20Sopenharmony_ci root->root_item.drop_level = 0; 37278c2ecf20Sopenharmony_ci btrfs_set_root_refs(&root->root_item, 0); 37288c2ecf20Sopenharmony_ci ret = btrfs_update_root(trans, fs_info->tree_root, 37298c2ecf20Sopenharmony_ci &root->root_key, &root->root_item); 37308c2ecf20Sopenharmony_ci 37318c2ecf20Sopenharmony_ci err = btrfs_end_transaction(trans); 37328c2ecf20Sopenharmony_ci if (err) 37338c2ecf20Sopenharmony_ci return err; 37348c2ecf20Sopenharmony_ci return ret; 37358c2ecf20Sopenharmony_ci} 37368c2ecf20Sopenharmony_ci 37378c2ecf20Sopenharmony_ci/* 37388c2ecf20Sopenharmony_ci * recover relocation interrupted by system crash. 37398c2ecf20Sopenharmony_ci * 37408c2ecf20Sopenharmony_ci * this function resumes merging reloc trees with corresponding fs trees. 37418c2ecf20Sopenharmony_ci * this is important for keeping the sharing of tree blocks 37428c2ecf20Sopenharmony_ci */ 37438c2ecf20Sopenharmony_ciint btrfs_recover_relocation(struct btrfs_root *root) 37448c2ecf20Sopenharmony_ci{ 37458c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = root->fs_info; 37468c2ecf20Sopenharmony_ci LIST_HEAD(reloc_roots); 37478c2ecf20Sopenharmony_ci struct btrfs_key key; 37488c2ecf20Sopenharmony_ci struct btrfs_root *fs_root; 37498c2ecf20Sopenharmony_ci struct btrfs_root *reloc_root; 37508c2ecf20Sopenharmony_ci struct btrfs_path *path; 37518c2ecf20Sopenharmony_ci struct extent_buffer *leaf; 37528c2ecf20Sopenharmony_ci struct reloc_control *rc = NULL; 37538c2ecf20Sopenharmony_ci struct btrfs_trans_handle *trans; 37548c2ecf20Sopenharmony_ci int ret; 37558c2ecf20Sopenharmony_ci int err = 0; 37568c2ecf20Sopenharmony_ci 37578c2ecf20Sopenharmony_ci path = btrfs_alloc_path(); 37588c2ecf20Sopenharmony_ci if (!path) 37598c2ecf20Sopenharmony_ci return -ENOMEM; 37608c2ecf20Sopenharmony_ci path->reada = READA_BACK; 37618c2ecf20Sopenharmony_ci 37628c2ecf20Sopenharmony_ci key.objectid = BTRFS_TREE_RELOC_OBJECTID; 37638c2ecf20Sopenharmony_ci key.type = BTRFS_ROOT_ITEM_KEY; 37648c2ecf20Sopenharmony_ci key.offset = (u64)-1; 37658c2ecf20Sopenharmony_ci 37668c2ecf20Sopenharmony_ci while (1) { 37678c2ecf20Sopenharmony_ci ret = btrfs_search_slot(NULL, fs_info->tree_root, &key, 37688c2ecf20Sopenharmony_ci path, 0, 0); 37698c2ecf20Sopenharmony_ci if (ret < 0) { 37708c2ecf20Sopenharmony_ci err = ret; 37718c2ecf20Sopenharmony_ci goto out; 37728c2ecf20Sopenharmony_ci } 37738c2ecf20Sopenharmony_ci if (ret > 0) { 37748c2ecf20Sopenharmony_ci if (path->slots[0] == 0) 37758c2ecf20Sopenharmony_ci break; 37768c2ecf20Sopenharmony_ci path->slots[0]--; 37778c2ecf20Sopenharmony_ci } 37788c2ecf20Sopenharmony_ci leaf = path->nodes[0]; 37798c2ecf20Sopenharmony_ci btrfs_item_key_to_cpu(leaf, &key, path->slots[0]); 37808c2ecf20Sopenharmony_ci btrfs_release_path(path); 37818c2ecf20Sopenharmony_ci 37828c2ecf20Sopenharmony_ci if (key.objectid != BTRFS_TREE_RELOC_OBJECTID || 37838c2ecf20Sopenharmony_ci key.type != BTRFS_ROOT_ITEM_KEY) 37848c2ecf20Sopenharmony_ci break; 37858c2ecf20Sopenharmony_ci 37868c2ecf20Sopenharmony_ci reloc_root = btrfs_read_tree_root(root, &key); 37878c2ecf20Sopenharmony_ci if (IS_ERR(reloc_root)) { 37888c2ecf20Sopenharmony_ci err = PTR_ERR(reloc_root); 37898c2ecf20Sopenharmony_ci goto out; 37908c2ecf20Sopenharmony_ci } 37918c2ecf20Sopenharmony_ci 37928c2ecf20Sopenharmony_ci set_bit(BTRFS_ROOT_SHAREABLE, &reloc_root->state); 37938c2ecf20Sopenharmony_ci list_add(&reloc_root->root_list, &reloc_roots); 37948c2ecf20Sopenharmony_ci 37958c2ecf20Sopenharmony_ci if (btrfs_root_refs(&reloc_root->root_item) > 0) { 37968c2ecf20Sopenharmony_ci fs_root = btrfs_get_fs_root(fs_info, 37978c2ecf20Sopenharmony_ci reloc_root->root_key.offset, false); 37988c2ecf20Sopenharmony_ci if (IS_ERR(fs_root)) { 37998c2ecf20Sopenharmony_ci ret = PTR_ERR(fs_root); 38008c2ecf20Sopenharmony_ci if (ret != -ENOENT) { 38018c2ecf20Sopenharmony_ci err = ret; 38028c2ecf20Sopenharmony_ci goto out; 38038c2ecf20Sopenharmony_ci } 38048c2ecf20Sopenharmony_ci ret = mark_garbage_root(reloc_root); 38058c2ecf20Sopenharmony_ci if (ret < 0) { 38068c2ecf20Sopenharmony_ci err = ret; 38078c2ecf20Sopenharmony_ci goto out; 38088c2ecf20Sopenharmony_ci } 38098c2ecf20Sopenharmony_ci } else { 38108c2ecf20Sopenharmony_ci btrfs_put_root(fs_root); 38118c2ecf20Sopenharmony_ci } 38128c2ecf20Sopenharmony_ci } 38138c2ecf20Sopenharmony_ci 38148c2ecf20Sopenharmony_ci if (key.offset == 0) 38158c2ecf20Sopenharmony_ci break; 38168c2ecf20Sopenharmony_ci 38178c2ecf20Sopenharmony_ci key.offset--; 38188c2ecf20Sopenharmony_ci } 38198c2ecf20Sopenharmony_ci btrfs_release_path(path); 38208c2ecf20Sopenharmony_ci 38218c2ecf20Sopenharmony_ci if (list_empty(&reloc_roots)) 38228c2ecf20Sopenharmony_ci goto out; 38238c2ecf20Sopenharmony_ci 38248c2ecf20Sopenharmony_ci rc = alloc_reloc_control(fs_info); 38258c2ecf20Sopenharmony_ci if (!rc) { 38268c2ecf20Sopenharmony_ci err = -ENOMEM; 38278c2ecf20Sopenharmony_ci goto out; 38288c2ecf20Sopenharmony_ci } 38298c2ecf20Sopenharmony_ci 38308c2ecf20Sopenharmony_ci rc->extent_root = fs_info->extent_root; 38318c2ecf20Sopenharmony_ci 38328c2ecf20Sopenharmony_ci set_reloc_control(rc); 38338c2ecf20Sopenharmony_ci 38348c2ecf20Sopenharmony_ci trans = btrfs_join_transaction(rc->extent_root); 38358c2ecf20Sopenharmony_ci if (IS_ERR(trans)) { 38368c2ecf20Sopenharmony_ci err = PTR_ERR(trans); 38378c2ecf20Sopenharmony_ci goto out_unset; 38388c2ecf20Sopenharmony_ci } 38398c2ecf20Sopenharmony_ci 38408c2ecf20Sopenharmony_ci rc->merge_reloc_tree = 1; 38418c2ecf20Sopenharmony_ci 38428c2ecf20Sopenharmony_ci while (!list_empty(&reloc_roots)) { 38438c2ecf20Sopenharmony_ci reloc_root = list_entry(reloc_roots.next, 38448c2ecf20Sopenharmony_ci struct btrfs_root, root_list); 38458c2ecf20Sopenharmony_ci list_del(&reloc_root->root_list); 38468c2ecf20Sopenharmony_ci 38478c2ecf20Sopenharmony_ci if (btrfs_root_refs(&reloc_root->root_item) == 0) { 38488c2ecf20Sopenharmony_ci list_add_tail(&reloc_root->root_list, 38498c2ecf20Sopenharmony_ci &rc->reloc_roots); 38508c2ecf20Sopenharmony_ci continue; 38518c2ecf20Sopenharmony_ci } 38528c2ecf20Sopenharmony_ci 38538c2ecf20Sopenharmony_ci fs_root = btrfs_get_fs_root(fs_info, reloc_root->root_key.offset, 38548c2ecf20Sopenharmony_ci false); 38558c2ecf20Sopenharmony_ci if (IS_ERR(fs_root)) { 38568c2ecf20Sopenharmony_ci err = PTR_ERR(fs_root); 38578c2ecf20Sopenharmony_ci list_add_tail(&reloc_root->root_list, &reloc_roots); 38588c2ecf20Sopenharmony_ci btrfs_end_transaction(trans); 38598c2ecf20Sopenharmony_ci goto out_unset; 38608c2ecf20Sopenharmony_ci } 38618c2ecf20Sopenharmony_ci 38628c2ecf20Sopenharmony_ci err = __add_reloc_root(reloc_root); 38638c2ecf20Sopenharmony_ci BUG_ON(err < 0); /* -ENOMEM or logic error */ 38648c2ecf20Sopenharmony_ci fs_root->reloc_root = btrfs_grab_root(reloc_root); 38658c2ecf20Sopenharmony_ci btrfs_put_root(fs_root); 38668c2ecf20Sopenharmony_ci } 38678c2ecf20Sopenharmony_ci 38688c2ecf20Sopenharmony_ci err = btrfs_commit_transaction(trans); 38698c2ecf20Sopenharmony_ci if (err) 38708c2ecf20Sopenharmony_ci goto out_unset; 38718c2ecf20Sopenharmony_ci 38728c2ecf20Sopenharmony_ci merge_reloc_roots(rc); 38738c2ecf20Sopenharmony_ci 38748c2ecf20Sopenharmony_ci unset_reloc_control(rc); 38758c2ecf20Sopenharmony_ci 38768c2ecf20Sopenharmony_ci trans = btrfs_join_transaction(rc->extent_root); 38778c2ecf20Sopenharmony_ci if (IS_ERR(trans)) { 38788c2ecf20Sopenharmony_ci err = PTR_ERR(trans); 38798c2ecf20Sopenharmony_ci goto out_clean; 38808c2ecf20Sopenharmony_ci } 38818c2ecf20Sopenharmony_ci err = btrfs_commit_transaction(trans); 38828c2ecf20Sopenharmony_ciout_clean: 38838c2ecf20Sopenharmony_ci ret = clean_dirty_subvols(rc); 38848c2ecf20Sopenharmony_ci if (ret < 0 && !err) 38858c2ecf20Sopenharmony_ci err = ret; 38868c2ecf20Sopenharmony_ciout_unset: 38878c2ecf20Sopenharmony_ci unset_reloc_control(rc); 38888c2ecf20Sopenharmony_ci free_reloc_control(rc); 38898c2ecf20Sopenharmony_ciout: 38908c2ecf20Sopenharmony_ci free_reloc_roots(&reloc_roots); 38918c2ecf20Sopenharmony_ci 38928c2ecf20Sopenharmony_ci btrfs_free_path(path); 38938c2ecf20Sopenharmony_ci 38948c2ecf20Sopenharmony_ci if (err == 0) { 38958c2ecf20Sopenharmony_ci /* cleanup orphan inode in data relocation tree */ 38968c2ecf20Sopenharmony_ci fs_root = btrfs_grab_root(fs_info->data_reloc_root); 38978c2ecf20Sopenharmony_ci ASSERT(fs_root); 38988c2ecf20Sopenharmony_ci err = btrfs_orphan_cleanup(fs_root); 38998c2ecf20Sopenharmony_ci btrfs_put_root(fs_root); 39008c2ecf20Sopenharmony_ci } 39018c2ecf20Sopenharmony_ci return err; 39028c2ecf20Sopenharmony_ci} 39038c2ecf20Sopenharmony_ci 39048c2ecf20Sopenharmony_ci/* 39058c2ecf20Sopenharmony_ci * helper to add ordered checksum for data relocation. 39068c2ecf20Sopenharmony_ci * 39078c2ecf20Sopenharmony_ci * cloning checksum properly handles the nodatasum extents. 39088c2ecf20Sopenharmony_ci * it also saves CPU time to re-calculate the checksum. 39098c2ecf20Sopenharmony_ci */ 39108c2ecf20Sopenharmony_ciint btrfs_reloc_clone_csums(struct btrfs_inode *inode, u64 file_pos, u64 len) 39118c2ecf20Sopenharmony_ci{ 39128c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = inode->root->fs_info; 39138c2ecf20Sopenharmony_ci struct btrfs_ordered_sum *sums; 39148c2ecf20Sopenharmony_ci struct btrfs_ordered_extent *ordered; 39158c2ecf20Sopenharmony_ci int ret; 39168c2ecf20Sopenharmony_ci u64 disk_bytenr; 39178c2ecf20Sopenharmony_ci u64 new_bytenr; 39188c2ecf20Sopenharmony_ci LIST_HEAD(list); 39198c2ecf20Sopenharmony_ci 39208c2ecf20Sopenharmony_ci ordered = btrfs_lookup_ordered_extent(inode, file_pos); 39218c2ecf20Sopenharmony_ci BUG_ON(ordered->file_offset != file_pos || ordered->num_bytes != len); 39228c2ecf20Sopenharmony_ci 39238c2ecf20Sopenharmony_ci disk_bytenr = file_pos + inode->index_cnt; 39248c2ecf20Sopenharmony_ci ret = btrfs_lookup_csums_range(fs_info->csum_root, disk_bytenr, 39258c2ecf20Sopenharmony_ci disk_bytenr + len - 1, &list, 0); 39268c2ecf20Sopenharmony_ci if (ret) 39278c2ecf20Sopenharmony_ci goto out; 39288c2ecf20Sopenharmony_ci 39298c2ecf20Sopenharmony_ci while (!list_empty(&list)) { 39308c2ecf20Sopenharmony_ci sums = list_entry(list.next, struct btrfs_ordered_sum, list); 39318c2ecf20Sopenharmony_ci list_del_init(&sums->list); 39328c2ecf20Sopenharmony_ci 39338c2ecf20Sopenharmony_ci /* 39348c2ecf20Sopenharmony_ci * We need to offset the new_bytenr based on where the csum is. 39358c2ecf20Sopenharmony_ci * We need to do this because we will read in entire prealloc 39368c2ecf20Sopenharmony_ci * extents but we may have written to say the middle of the 39378c2ecf20Sopenharmony_ci * prealloc extent, so we need to make sure the csum goes with 39388c2ecf20Sopenharmony_ci * the right disk offset. 39398c2ecf20Sopenharmony_ci * 39408c2ecf20Sopenharmony_ci * We can do this because the data reloc inode refers strictly 39418c2ecf20Sopenharmony_ci * to the on disk bytes, so we don't have to worry about 39428c2ecf20Sopenharmony_ci * disk_len vs real len like with real inodes since it's all 39438c2ecf20Sopenharmony_ci * disk length. 39448c2ecf20Sopenharmony_ci */ 39458c2ecf20Sopenharmony_ci new_bytenr = ordered->disk_bytenr + sums->bytenr - disk_bytenr; 39468c2ecf20Sopenharmony_ci sums->bytenr = new_bytenr; 39478c2ecf20Sopenharmony_ci 39488c2ecf20Sopenharmony_ci btrfs_add_ordered_sum(ordered, sums); 39498c2ecf20Sopenharmony_ci } 39508c2ecf20Sopenharmony_ciout: 39518c2ecf20Sopenharmony_ci btrfs_put_ordered_extent(ordered); 39528c2ecf20Sopenharmony_ci return ret; 39538c2ecf20Sopenharmony_ci} 39548c2ecf20Sopenharmony_ci 39558c2ecf20Sopenharmony_ciint btrfs_reloc_cow_block(struct btrfs_trans_handle *trans, 39568c2ecf20Sopenharmony_ci struct btrfs_root *root, struct extent_buffer *buf, 39578c2ecf20Sopenharmony_ci struct extent_buffer *cow) 39588c2ecf20Sopenharmony_ci{ 39598c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = root->fs_info; 39608c2ecf20Sopenharmony_ci struct reloc_control *rc; 39618c2ecf20Sopenharmony_ci struct btrfs_backref_node *node; 39628c2ecf20Sopenharmony_ci int first_cow = 0; 39638c2ecf20Sopenharmony_ci int level; 39648c2ecf20Sopenharmony_ci int ret = 0; 39658c2ecf20Sopenharmony_ci 39668c2ecf20Sopenharmony_ci rc = fs_info->reloc_ctl; 39678c2ecf20Sopenharmony_ci if (!rc) 39688c2ecf20Sopenharmony_ci return 0; 39698c2ecf20Sopenharmony_ci 39708c2ecf20Sopenharmony_ci BUG_ON(rc->stage == UPDATE_DATA_PTRS && 39718c2ecf20Sopenharmony_ci root->root_key.objectid == BTRFS_DATA_RELOC_TREE_OBJECTID); 39728c2ecf20Sopenharmony_ci 39738c2ecf20Sopenharmony_ci level = btrfs_header_level(buf); 39748c2ecf20Sopenharmony_ci if (btrfs_header_generation(buf) <= 39758c2ecf20Sopenharmony_ci btrfs_root_last_snapshot(&root->root_item)) 39768c2ecf20Sopenharmony_ci first_cow = 1; 39778c2ecf20Sopenharmony_ci 39788c2ecf20Sopenharmony_ci if (root->root_key.objectid == BTRFS_TREE_RELOC_OBJECTID && 39798c2ecf20Sopenharmony_ci rc->create_reloc_tree) { 39808c2ecf20Sopenharmony_ci WARN_ON(!first_cow && level == 0); 39818c2ecf20Sopenharmony_ci 39828c2ecf20Sopenharmony_ci node = rc->backref_cache.path[level]; 39838c2ecf20Sopenharmony_ci BUG_ON(node->bytenr != buf->start && 39848c2ecf20Sopenharmony_ci node->new_bytenr != buf->start); 39858c2ecf20Sopenharmony_ci 39868c2ecf20Sopenharmony_ci btrfs_backref_drop_node_buffer(node); 39878c2ecf20Sopenharmony_ci atomic_inc(&cow->refs); 39888c2ecf20Sopenharmony_ci node->eb = cow; 39898c2ecf20Sopenharmony_ci node->new_bytenr = cow->start; 39908c2ecf20Sopenharmony_ci 39918c2ecf20Sopenharmony_ci if (!node->pending) { 39928c2ecf20Sopenharmony_ci list_move_tail(&node->list, 39938c2ecf20Sopenharmony_ci &rc->backref_cache.pending[level]); 39948c2ecf20Sopenharmony_ci node->pending = 1; 39958c2ecf20Sopenharmony_ci } 39968c2ecf20Sopenharmony_ci 39978c2ecf20Sopenharmony_ci if (first_cow) 39988c2ecf20Sopenharmony_ci mark_block_processed(rc, node); 39998c2ecf20Sopenharmony_ci 40008c2ecf20Sopenharmony_ci if (first_cow && level > 0) 40018c2ecf20Sopenharmony_ci rc->nodes_relocated += buf->len; 40028c2ecf20Sopenharmony_ci } 40038c2ecf20Sopenharmony_ci 40048c2ecf20Sopenharmony_ci if (level == 0 && first_cow && rc->stage == UPDATE_DATA_PTRS) 40058c2ecf20Sopenharmony_ci ret = replace_file_extents(trans, rc, root, cow); 40068c2ecf20Sopenharmony_ci return ret; 40078c2ecf20Sopenharmony_ci} 40088c2ecf20Sopenharmony_ci 40098c2ecf20Sopenharmony_ci/* 40108c2ecf20Sopenharmony_ci * called before creating snapshot. it calculates metadata reservation 40118c2ecf20Sopenharmony_ci * required for relocating tree blocks in the snapshot 40128c2ecf20Sopenharmony_ci */ 40138c2ecf20Sopenharmony_civoid btrfs_reloc_pre_snapshot(struct btrfs_pending_snapshot *pending, 40148c2ecf20Sopenharmony_ci u64 *bytes_to_reserve) 40158c2ecf20Sopenharmony_ci{ 40168c2ecf20Sopenharmony_ci struct btrfs_root *root = pending->root; 40178c2ecf20Sopenharmony_ci struct reloc_control *rc = root->fs_info->reloc_ctl; 40188c2ecf20Sopenharmony_ci 40198c2ecf20Sopenharmony_ci if (!rc || !have_reloc_root(root)) 40208c2ecf20Sopenharmony_ci return; 40218c2ecf20Sopenharmony_ci 40228c2ecf20Sopenharmony_ci if (!rc->merge_reloc_tree) 40238c2ecf20Sopenharmony_ci return; 40248c2ecf20Sopenharmony_ci 40258c2ecf20Sopenharmony_ci root = root->reloc_root; 40268c2ecf20Sopenharmony_ci BUG_ON(btrfs_root_refs(&root->root_item) == 0); 40278c2ecf20Sopenharmony_ci /* 40288c2ecf20Sopenharmony_ci * relocation is in the stage of merging trees. the space 40298c2ecf20Sopenharmony_ci * used by merging a reloc tree is twice the size of 40308c2ecf20Sopenharmony_ci * relocated tree nodes in the worst case. half for cowing 40318c2ecf20Sopenharmony_ci * the reloc tree, half for cowing the fs tree. the space 40328c2ecf20Sopenharmony_ci * used by cowing the reloc tree will be freed after the 40338c2ecf20Sopenharmony_ci * tree is dropped. if we create snapshot, cowing the fs 40348c2ecf20Sopenharmony_ci * tree may use more space than it frees. so we need 40358c2ecf20Sopenharmony_ci * reserve extra space. 40368c2ecf20Sopenharmony_ci */ 40378c2ecf20Sopenharmony_ci *bytes_to_reserve += rc->nodes_relocated; 40388c2ecf20Sopenharmony_ci} 40398c2ecf20Sopenharmony_ci 40408c2ecf20Sopenharmony_ci/* 40418c2ecf20Sopenharmony_ci * called after snapshot is created. migrate block reservation 40428c2ecf20Sopenharmony_ci * and create reloc root for the newly created snapshot 40438c2ecf20Sopenharmony_ci * 40448c2ecf20Sopenharmony_ci * This is similar to btrfs_init_reloc_root(), we come out of here with two 40458c2ecf20Sopenharmony_ci * references held on the reloc_root, one for root->reloc_root and one for 40468c2ecf20Sopenharmony_ci * rc->reloc_roots. 40478c2ecf20Sopenharmony_ci */ 40488c2ecf20Sopenharmony_ciint btrfs_reloc_post_snapshot(struct btrfs_trans_handle *trans, 40498c2ecf20Sopenharmony_ci struct btrfs_pending_snapshot *pending) 40508c2ecf20Sopenharmony_ci{ 40518c2ecf20Sopenharmony_ci struct btrfs_root *root = pending->root; 40528c2ecf20Sopenharmony_ci struct btrfs_root *reloc_root; 40538c2ecf20Sopenharmony_ci struct btrfs_root *new_root; 40548c2ecf20Sopenharmony_ci struct reloc_control *rc = root->fs_info->reloc_ctl; 40558c2ecf20Sopenharmony_ci int ret; 40568c2ecf20Sopenharmony_ci 40578c2ecf20Sopenharmony_ci if (!rc || !have_reloc_root(root)) 40588c2ecf20Sopenharmony_ci return 0; 40598c2ecf20Sopenharmony_ci 40608c2ecf20Sopenharmony_ci rc = root->fs_info->reloc_ctl; 40618c2ecf20Sopenharmony_ci rc->merging_rsv_size += rc->nodes_relocated; 40628c2ecf20Sopenharmony_ci 40638c2ecf20Sopenharmony_ci if (rc->merge_reloc_tree) { 40648c2ecf20Sopenharmony_ci ret = btrfs_block_rsv_migrate(&pending->block_rsv, 40658c2ecf20Sopenharmony_ci rc->block_rsv, 40668c2ecf20Sopenharmony_ci rc->nodes_relocated, true); 40678c2ecf20Sopenharmony_ci if (ret) 40688c2ecf20Sopenharmony_ci return ret; 40698c2ecf20Sopenharmony_ci } 40708c2ecf20Sopenharmony_ci 40718c2ecf20Sopenharmony_ci new_root = pending->snap; 40728c2ecf20Sopenharmony_ci reloc_root = create_reloc_root(trans, root->reloc_root, 40738c2ecf20Sopenharmony_ci new_root->root_key.objectid); 40748c2ecf20Sopenharmony_ci if (IS_ERR(reloc_root)) 40758c2ecf20Sopenharmony_ci return PTR_ERR(reloc_root); 40768c2ecf20Sopenharmony_ci 40778c2ecf20Sopenharmony_ci ret = __add_reloc_root(reloc_root); 40788c2ecf20Sopenharmony_ci BUG_ON(ret < 0); 40798c2ecf20Sopenharmony_ci new_root->reloc_root = btrfs_grab_root(reloc_root); 40808c2ecf20Sopenharmony_ci 40818c2ecf20Sopenharmony_ci if (rc->create_reloc_tree) 40828c2ecf20Sopenharmony_ci ret = clone_backref_node(trans, rc, root, reloc_root); 40838c2ecf20Sopenharmony_ci return ret; 40848c2ecf20Sopenharmony_ci} 4085