18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2007 Oracle. All rights reserved. 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#include <linux/sched.h> 78c2ecf20Sopenharmony_ci#include <linux/sched/signal.h> 88c2ecf20Sopenharmony_ci#include <linux/pagemap.h> 98c2ecf20Sopenharmony_ci#include <linux/writeback.h> 108c2ecf20Sopenharmony_ci#include <linux/blkdev.h> 118c2ecf20Sopenharmony_ci#include <linux/sort.h> 128c2ecf20Sopenharmony_ci#include <linux/rcupdate.h> 138c2ecf20Sopenharmony_ci#include <linux/kthread.h> 148c2ecf20Sopenharmony_ci#include <linux/slab.h> 158c2ecf20Sopenharmony_ci#include <linux/ratelimit.h> 168c2ecf20Sopenharmony_ci#include <linux/percpu_counter.h> 178c2ecf20Sopenharmony_ci#include <linux/lockdep.h> 188c2ecf20Sopenharmony_ci#include <linux/crc32c.h> 198c2ecf20Sopenharmony_ci#include "misc.h" 208c2ecf20Sopenharmony_ci#include "tree-log.h" 218c2ecf20Sopenharmony_ci#include "disk-io.h" 228c2ecf20Sopenharmony_ci#include "print-tree.h" 238c2ecf20Sopenharmony_ci#include "volumes.h" 248c2ecf20Sopenharmony_ci#include "raid56.h" 258c2ecf20Sopenharmony_ci#include "locking.h" 268c2ecf20Sopenharmony_ci#include "free-space-cache.h" 278c2ecf20Sopenharmony_ci#include "free-space-tree.h" 288c2ecf20Sopenharmony_ci#include "sysfs.h" 298c2ecf20Sopenharmony_ci#include "qgroup.h" 308c2ecf20Sopenharmony_ci#include "ref-verify.h" 318c2ecf20Sopenharmony_ci#include "space-info.h" 328c2ecf20Sopenharmony_ci#include "block-rsv.h" 338c2ecf20Sopenharmony_ci#include "delalloc-space.h" 348c2ecf20Sopenharmony_ci#include "block-group.h" 358c2ecf20Sopenharmony_ci#include "discard.h" 368c2ecf20Sopenharmony_ci#include "rcu-string.h" 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci#undef SCRAMBLE_DELAYED_REFS 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_cistatic int __btrfs_free_extent(struct btrfs_trans_handle *trans, 428c2ecf20Sopenharmony_ci struct btrfs_delayed_ref_node *node, u64 parent, 438c2ecf20Sopenharmony_ci u64 root_objectid, u64 owner_objectid, 448c2ecf20Sopenharmony_ci u64 owner_offset, int refs_to_drop, 458c2ecf20Sopenharmony_ci struct btrfs_delayed_extent_op *extra_op); 468c2ecf20Sopenharmony_cistatic void __run_delayed_extent_op(struct btrfs_delayed_extent_op *extent_op, 478c2ecf20Sopenharmony_ci struct extent_buffer *leaf, 488c2ecf20Sopenharmony_ci struct btrfs_extent_item *ei); 498c2ecf20Sopenharmony_cistatic int alloc_reserved_file_extent(struct btrfs_trans_handle *trans, 508c2ecf20Sopenharmony_ci u64 parent, u64 root_objectid, 518c2ecf20Sopenharmony_ci u64 flags, u64 owner, u64 offset, 528c2ecf20Sopenharmony_ci struct btrfs_key *ins, int ref_mod); 538c2ecf20Sopenharmony_cistatic int alloc_reserved_tree_block(struct btrfs_trans_handle *trans, 548c2ecf20Sopenharmony_ci struct btrfs_delayed_ref_node *node, 558c2ecf20Sopenharmony_ci struct btrfs_delayed_extent_op *extent_op); 568c2ecf20Sopenharmony_cistatic int find_next_key(struct btrfs_path *path, int level, 578c2ecf20Sopenharmony_ci struct btrfs_key *key); 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_cistatic int block_group_bits(struct btrfs_block_group *cache, u64 bits) 608c2ecf20Sopenharmony_ci{ 618c2ecf20Sopenharmony_ci return (cache->flags & bits) == bits; 628c2ecf20Sopenharmony_ci} 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ciint btrfs_add_excluded_extent(struct btrfs_fs_info *fs_info, 658c2ecf20Sopenharmony_ci u64 start, u64 num_bytes) 668c2ecf20Sopenharmony_ci{ 678c2ecf20Sopenharmony_ci u64 end = start + num_bytes - 1; 688c2ecf20Sopenharmony_ci set_extent_bits(&fs_info->excluded_extents, start, end, 698c2ecf20Sopenharmony_ci EXTENT_UPTODATE); 708c2ecf20Sopenharmony_ci return 0; 718c2ecf20Sopenharmony_ci} 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_civoid btrfs_free_excluded_extents(struct btrfs_block_group *cache) 748c2ecf20Sopenharmony_ci{ 758c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = cache->fs_info; 768c2ecf20Sopenharmony_ci u64 start, end; 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci start = cache->start; 798c2ecf20Sopenharmony_ci end = start + cache->length - 1; 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci clear_extent_bits(&fs_info->excluded_extents, start, end, 828c2ecf20Sopenharmony_ci EXTENT_UPTODATE); 838c2ecf20Sopenharmony_ci} 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci/* simple helper to search for an existing data extent at a given offset */ 868c2ecf20Sopenharmony_ciint btrfs_lookup_data_extent(struct btrfs_fs_info *fs_info, u64 start, u64 len) 878c2ecf20Sopenharmony_ci{ 888c2ecf20Sopenharmony_ci int ret; 898c2ecf20Sopenharmony_ci struct btrfs_key key; 908c2ecf20Sopenharmony_ci struct btrfs_path *path; 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci path = btrfs_alloc_path(); 938c2ecf20Sopenharmony_ci if (!path) 948c2ecf20Sopenharmony_ci return -ENOMEM; 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci key.objectid = start; 978c2ecf20Sopenharmony_ci key.offset = len; 988c2ecf20Sopenharmony_ci key.type = BTRFS_EXTENT_ITEM_KEY; 998c2ecf20Sopenharmony_ci ret = btrfs_search_slot(NULL, fs_info->extent_root, &key, path, 0, 0); 1008c2ecf20Sopenharmony_ci btrfs_free_path(path); 1018c2ecf20Sopenharmony_ci return ret; 1028c2ecf20Sopenharmony_ci} 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci/* 1058c2ecf20Sopenharmony_ci * helper function to lookup reference count and flags of a tree block. 1068c2ecf20Sopenharmony_ci * 1078c2ecf20Sopenharmony_ci * the head node for delayed ref is used to store the sum of all the 1088c2ecf20Sopenharmony_ci * reference count modifications queued up in the rbtree. the head 1098c2ecf20Sopenharmony_ci * node may also store the extent flags to set. This way you can check 1108c2ecf20Sopenharmony_ci * to see what the reference count and extent flags would be if all of 1118c2ecf20Sopenharmony_ci * the delayed refs are not processed. 1128c2ecf20Sopenharmony_ci */ 1138c2ecf20Sopenharmony_ciint btrfs_lookup_extent_info(struct btrfs_trans_handle *trans, 1148c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info, u64 bytenr, 1158c2ecf20Sopenharmony_ci u64 offset, int metadata, u64 *refs, u64 *flags) 1168c2ecf20Sopenharmony_ci{ 1178c2ecf20Sopenharmony_ci struct btrfs_delayed_ref_head *head; 1188c2ecf20Sopenharmony_ci struct btrfs_delayed_ref_root *delayed_refs; 1198c2ecf20Sopenharmony_ci struct btrfs_path *path; 1208c2ecf20Sopenharmony_ci struct btrfs_extent_item *ei; 1218c2ecf20Sopenharmony_ci struct extent_buffer *leaf; 1228c2ecf20Sopenharmony_ci struct btrfs_key key; 1238c2ecf20Sopenharmony_ci u32 item_size; 1248c2ecf20Sopenharmony_ci u64 num_refs; 1258c2ecf20Sopenharmony_ci u64 extent_flags; 1268c2ecf20Sopenharmony_ci int ret; 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci /* 1298c2ecf20Sopenharmony_ci * If we don't have skinny metadata, don't bother doing anything 1308c2ecf20Sopenharmony_ci * different 1318c2ecf20Sopenharmony_ci */ 1328c2ecf20Sopenharmony_ci if (metadata && !btrfs_fs_incompat(fs_info, SKINNY_METADATA)) { 1338c2ecf20Sopenharmony_ci offset = fs_info->nodesize; 1348c2ecf20Sopenharmony_ci metadata = 0; 1358c2ecf20Sopenharmony_ci } 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci path = btrfs_alloc_path(); 1388c2ecf20Sopenharmony_ci if (!path) 1398c2ecf20Sopenharmony_ci return -ENOMEM; 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci if (!trans) { 1428c2ecf20Sopenharmony_ci path->skip_locking = 1; 1438c2ecf20Sopenharmony_ci path->search_commit_root = 1; 1448c2ecf20Sopenharmony_ci } 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_cisearch_again: 1478c2ecf20Sopenharmony_ci key.objectid = bytenr; 1488c2ecf20Sopenharmony_ci key.offset = offset; 1498c2ecf20Sopenharmony_ci if (metadata) 1508c2ecf20Sopenharmony_ci key.type = BTRFS_METADATA_ITEM_KEY; 1518c2ecf20Sopenharmony_ci else 1528c2ecf20Sopenharmony_ci key.type = BTRFS_EXTENT_ITEM_KEY; 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci ret = btrfs_search_slot(trans, fs_info->extent_root, &key, path, 0, 0); 1558c2ecf20Sopenharmony_ci if (ret < 0) 1568c2ecf20Sopenharmony_ci goto out_free; 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci if (ret > 0 && metadata && key.type == BTRFS_METADATA_ITEM_KEY) { 1598c2ecf20Sopenharmony_ci if (path->slots[0]) { 1608c2ecf20Sopenharmony_ci path->slots[0]--; 1618c2ecf20Sopenharmony_ci btrfs_item_key_to_cpu(path->nodes[0], &key, 1628c2ecf20Sopenharmony_ci path->slots[0]); 1638c2ecf20Sopenharmony_ci if (key.objectid == bytenr && 1648c2ecf20Sopenharmony_ci key.type == BTRFS_EXTENT_ITEM_KEY && 1658c2ecf20Sopenharmony_ci key.offset == fs_info->nodesize) 1668c2ecf20Sopenharmony_ci ret = 0; 1678c2ecf20Sopenharmony_ci } 1688c2ecf20Sopenharmony_ci } 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ci if (ret == 0) { 1718c2ecf20Sopenharmony_ci leaf = path->nodes[0]; 1728c2ecf20Sopenharmony_ci item_size = btrfs_item_size_nr(leaf, path->slots[0]); 1738c2ecf20Sopenharmony_ci if (item_size >= sizeof(*ei)) { 1748c2ecf20Sopenharmony_ci ei = btrfs_item_ptr(leaf, path->slots[0], 1758c2ecf20Sopenharmony_ci struct btrfs_extent_item); 1768c2ecf20Sopenharmony_ci num_refs = btrfs_extent_refs(leaf, ei); 1778c2ecf20Sopenharmony_ci extent_flags = btrfs_extent_flags(leaf, ei); 1788c2ecf20Sopenharmony_ci } else { 1798c2ecf20Sopenharmony_ci ret = -EINVAL; 1808c2ecf20Sopenharmony_ci btrfs_print_v0_err(fs_info); 1818c2ecf20Sopenharmony_ci if (trans) 1828c2ecf20Sopenharmony_ci btrfs_abort_transaction(trans, ret); 1838c2ecf20Sopenharmony_ci else 1848c2ecf20Sopenharmony_ci btrfs_handle_fs_error(fs_info, ret, NULL); 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ci goto out_free; 1878c2ecf20Sopenharmony_ci } 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci BUG_ON(num_refs == 0); 1908c2ecf20Sopenharmony_ci } else { 1918c2ecf20Sopenharmony_ci num_refs = 0; 1928c2ecf20Sopenharmony_ci extent_flags = 0; 1938c2ecf20Sopenharmony_ci ret = 0; 1948c2ecf20Sopenharmony_ci } 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci if (!trans) 1978c2ecf20Sopenharmony_ci goto out; 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_ci delayed_refs = &trans->transaction->delayed_refs; 2008c2ecf20Sopenharmony_ci spin_lock(&delayed_refs->lock); 2018c2ecf20Sopenharmony_ci head = btrfs_find_delayed_ref_head(delayed_refs, bytenr); 2028c2ecf20Sopenharmony_ci if (head) { 2038c2ecf20Sopenharmony_ci if (!mutex_trylock(&head->mutex)) { 2048c2ecf20Sopenharmony_ci refcount_inc(&head->refs); 2058c2ecf20Sopenharmony_ci spin_unlock(&delayed_refs->lock); 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci btrfs_release_path(path); 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ci /* 2108c2ecf20Sopenharmony_ci * Mutex was contended, block until it's released and try 2118c2ecf20Sopenharmony_ci * again 2128c2ecf20Sopenharmony_ci */ 2138c2ecf20Sopenharmony_ci mutex_lock(&head->mutex); 2148c2ecf20Sopenharmony_ci mutex_unlock(&head->mutex); 2158c2ecf20Sopenharmony_ci btrfs_put_delayed_ref_head(head); 2168c2ecf20Sopenharmony_ci goto search_again; 2178c2ecf20Sopenharmony_ci } 2188c2ecf20Sopenharmony_ci spin_lock(&head->lock); 2198c2ecf20Sopenharmony_ci if (head->extent_op && head->extent_op->update_flags) 2208c2ecf20Sopenharmony_ci extent_flags |= head->extent_op->flags_to_set; 2218c2ecf20Sopenharmony_ci else 2228c2ecf20Sopenharmony_ci BUG_ON(num_refs == 0); 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ci num_refs += head->ref_mod; 2258c2ecf20Sopenharmony_ci spin_unlock(&head->lock); 2268c2ecf20Sopenharmony_ci mutex_unlock(&head->mutex); 2278c2ecf20Sopenharmony_ci } 2288c2ecf20Sopenharmony_ci spin_unlock(&delayed_refs->lock); 2298c2ecf20Sopenharmony_ciout: 2308c2ecf20Sopenharmony_ci WARN_ON(num_refs == 0); 2318c2ecf20Sopenharmony_ci if (refs) 2328c2ecf20Sopenharmony_ci *refs = num_refs; 2338c2ecf20Sopenharmony_ci if (flags) 2348c2ecf20Sopenharmony_ci *flags = extent_flags; 2358c2ecf20Sopenharmony_ciout_free: 2368c2ecf20Sopenharmony_ci btrfs_free_path(path); 2378c2ecf20Sopenharmony_ci return ret; 2388c2ecf20Sopenharmony_ci} 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ci/* 2418c2ecf20Sopenharmony_ci * Back reference rules. Back refs have three main goals: 2428c2ecf20Sopenharmony_ci * 2438c2ecf20Sopenharmony_ci * 1) differentiate between all holders of references to an extent so that 2448c2ecf20Sopenharmony_ci * when a reference is dropped we can make sure it was a valid reference 2458c2ecf20Sopenharmony_ci * before freeing the extent. 2468c2ecf20Sopenharmony_ci * 2478c2ecf20Sopenharmony_ci * 2) Provide enough information to quickly find the holders of an extent 2488c2ecf20Sopenharmony_ci * if we notice a given block is corrupted or bad. 2498c2ecf20Sopenharmony_ci * 2508c2ecf20Sopenharmony_ci * 3) Make it easy to migrate blocks for FS shrinking or storage pool 2518c2ecf20Sopenharmony_ci * maintenance. This is actually the same as #2, but with a slightly 2528c2ecf20Sopenharmony_ci * different use case. 2538c2ecf20Sopenharmony_ci * 2548c2ecf20Sopenharmony_ci * There are two kinds of back refs. The implicit back refs is optimized 2558c2ecf20Sopenharmony_ci * for pointers in non-shared tree blocks. For a given pointer in a block, 2568c2ecf20Sopenharmony_ci * back refs of this kind provide information about the block's owner tree 2578c2ecf20Sopenharmony_ci * and the pointer's key. These information allow us to find the block by 2588c2ecf20Sopenharmony_ci * b-tree searching. The full back refs is for pointers in tree blocks not 2598c2ecf20Sopenharmony_ci * referenced by their owner trees. The location of tree block is recorded 2608c2ecf20Sopenharmony_ci * in the back refs. Actually the full back refs is generic, and can be 2618c2ecf20Sopenharmony_ci * used in all cases the implicit back refs is used. The major shortcoming 2628c2ecf20Sopenharmony_ci * of the full back refs is its overhead. Every time a tree block gets 2638c2ecf20Sopenharmony_ci * COWed, we have to update back refs entry for all pointers in it. 2648c2ecf20Sopenharmony_ci * 2658c2ecf20Sopenharmony_ci * For a newly allocated tree block, we use implicit back refs for 2668c2ecf20Sopenharmony_ci * pointers in it. This means most tree related operations only involve 2678c2ecf20Sopenharmony_ci * implicit back refs. For a tree block created in old transaction, the 2688c2ecf20Sopenharmony_ci * only way to drop a reference to it is COW it. So we can detect the 2698c2ecf20Sopenharmony_ci * event that tree block loses its owner tree's reference and do the 2708c2ecf20Sopenharmony_ci * back refs conversion. 2718c2ecf20Sopenharmony_ci * 2728c2ecf20Sopenharmony_ci * When a tree block is COWed through a tree, there are four cases: 2738c2ecf20Sopenharmony_ci * 2748c2ecf20Sopenharmony_ci * The reference count of the block is one and the tree is the block's 2758c2ecf20Sopenharmony_ci * owner tree. Nothing to do in this case. 2768c2ecf20Sopenharmony_ci * 2778c2ecf20Sopenharmony_ci * The reference count of the block is one and the tree is not the 2788c2ecf20Sopenharmony_ci * block's owner tree. In this case, full back refs is used for pointers 2798c2ecf20Sopenharmony_ci * in the block. Remove these full back refs, add implicit back refs for 2808c2ecf20Sopenharmony_ci * every pointers in the new block. 2818c2ecf20Sopenharmony_ci * 2828c2ecf20Sopenharmony_ci * The reference count of the block is greater than one and the tree is 2838c2ecf20Sopenharmony_ci * the block's owner tree. In this case, implicit back refs is used for 2848c2ecf20Sopenharmony_ci * pointers in the block. Add full back refs for every pointers in the 2858c2ecf20Sopenharmony_ci * block, increase lower level extents' reference counts. The original 2868c2ecf20Sopenharmony_ci * implicit back refs are entailed to the new block. 2878c2ecf20Sopenharmony_ci * 2888c2ecf20Sopenharmony_ci * The reference count of the block is greater than one and the tree is 2898c2ecf20Sopenharmony_ci * not the block's owner tree. Add implicit back refs for every pointer in 2908c2ecf20Sopenharmony_ci * the new block, increase lower level extents' reference count. 2918c2ecf20Sopenharmony_ci * 2928c2ecf20Sopenharmony_ci * Back Reference Key composing: 2938c2ecf20Sopenharmony_ci * 2948c2ecf20Sopenharmony_ci * The key objectid corresponds to the first byte in the extent, 2958c2ecf20Sopenharmony_ci * The key type is used to differentiate between types of back refs. 2968c2ecf20Sopenharmony_ci * There are different meanings of the key offset for different types 2978c2ecf20Sopenharmony_ci * of back refs. 2988c2ecf20Sopenharmony_ci * 2998c2ecf20Sopenharmony_ci * File extents can be referenced by: 3008c2ecf20Sopenharmony_ci * 3018c2ecf20Sopenharmony_ci * - multiple snapshots, subvolumes, or different generations in one subvol 3028c2ecf20Sopenharmony_ci * - different files inside a single subvolume 3038c2ecf20Sopenharmony_ci * - different offsets inside a file (bookend extents in file.c) 3048c2ecf20Sopenharmony_ci * 3058c2ecf20Sopenharmony_ci * The extent ref structure for the implicit back refs has fields for: 3068c2ecf20Sopenharmony_ci * 3078c2ecf20Sopenharmony_ci * - Objectid of the subvolume root 3088c2ecf20Sopenharmony_ci * - objectid of the file holding the reference 3098c2ecf20Sopenharmony_ci * - original offset in the file 3108c2ecf20Sopenharmony_ci * - how many bookend extents 3118c2ecf20Sopenharmony_ci * 3128c2ecf20Sopenharmony_ci * The key offset for the implicit back refs is hash of the first 3138c2ecf20Sopenharmony_ci * three fields. 3148c2ecf20Sopenharmony_ci * 3158c2ecf20Sopenharmony_ci * The extent ref structure for the full back refs has field for: 3168c2ecf20Sopenharmony_ci * 3178c2ecf20Sopenharmony_ci * - number of pointers in the tree leaf 3188c2ecf20Sopenharmony_ci * 3198c2ecf20Sopenharmony_ci * The key offset for the implicit back refs is the first byte of 3208c2ecf20Sopenharmony_ci * the tree leaf 3218c2ecf20Sopenharmony_ci * 3228c2ecf20Sopenharmony_ci * When a file extent is allocated, The implicit back refs is used. 3238c2ecf20Sopenharmony_ci * the fields are filled in: 3248c2ecf20Sopenharmony_ci * 3258c2ecf20Sopenharmony_ci * (root_key.objectid, inode objectid, offset in file, 1) 3268c2ecf20Sopenharmony_ci * 3278c2ecf20Sopenharmony_ci * When a file extent is removed file truncation, we find the 3288c2ecf20Sopenharmony_ci * corresponding implicit back refs and check the following fields: 3298c2ecf20Sopenharmony_ci * 3308c2ecf20Sopenharmony_ci * (btrfs_header_owner(leaf), inode objectid, offset in file) 3318c2ecf20Sopenharmony_ci * 3328c2ecf20Sopenharmony_ci * Btree extents can be referenced by: 3338c2ecf20Sopenharmony_ci * 3348c2ecf20Sopenharmony_ci * - Different subvolumes 3358c2ecf20Sopenharmony_ci * 3368c2ecf20Sopenharmony_ci * Both the implicit back refs and the full back refs for tree blocks 3378c2ecf20Sopenharmony_ci * only consist of key. The key offset for the implicit back refs is 3388c2ecf20Sopenharmony_ci * objectid of block's owner tree. The key offset for the full back refs 3398c2ecf20Sopenharmony_ci * is the first byte of parent block. 3408c2ecf20Sopenharmony_ci * 3418c2ecf20Sopenharmony_ci * When implicit back refs is used, information about the lowest key and 3428c2ecf20Sopenharmony_ci * level of the tree block are required. These information are stored in 3438c2ecf20Sopenharmony_ci * tree block info structure. 3448c2ecf20Sopenharmony_ci */ 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_ci/* 3478c2ecf20Sopenharmony_ci * is_data == BTRFS_REF_TYPE_BLOCK, tree block type is required, 3488c2ecf20Sopenharmony_ci * is_data == BTRFS_REF_TYPE_DATA, data type is requiried, 3498c2ecf20Sopenharmony_ci * is_data == BTRFS_REF_TYPE_ANY, either type is OK. 3508c2ecf20Sopenharmony_ci */ 3518c2ecf20Sopenharmony_ciint btrfs_get_extent_inline_ref_type(const struct extent_buffer *eb, 3528c2ecf20Sopenharmony_ci struct btrfs_extent_inline_ref *iref, 3538c2ecf20Sopenharmony_ci enum btrfs_inline_ref_type is_data) 3548c2ecf20Sopenharmony_ci{ 3558c2ecf20Sopenharmony_ci int type = btrfs_extent_inline_ref_type(eb, iref); 3568c2ecf20Sopenharmony_ci u64 offset = btrfs_extent_inline_ref_offset(eb, iref); 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_ci if (type == BTRFS_TREE_BLOCK_REF_KEY || 3598c2ecf20Sopenharmony_ci type == BTRFS_SHARED_BLOCK_REF_KEY || 3608c2ecf20Sopenharmony_ci type == BTRFS_SHARED_DATA_REF_KEY || 3618c2ecf20Sopenharmony_ci type == BTRFS_EXTENT_DATA_REF_KEY) { 3628c2ecf20Sopenharmony_ci if (is_data == BTRFS_REF_TYPE_BLOCK) { 3638c2ecf20Sopenharmony_ci if (type == BTRFS_TREE_BLOCK_REF_KEY) 3648c2ecf20Sopenharmony_ci return type; 3658c2ecf20Sopenharmony_ci if (type == BTRFS_SHARED_BLOCK_REF_KEY) { 3668c2ecf20Sopenharmony_ci ASSERT(eb->fs_info); 3678c2ecf20Sopenharmony_ci /* 3688c2ecf20Sopenharmony_ci * Every shared one has parent tree block, 3698c2ecf20Sopenharmony_ci * which must be aligned to sector size. 3708c2ecf20Sopenharmony_ci */ 3718c2ecf20Sopenharmony_ci if (offset && 3728c2ecf20Sopenharmony_ci IS_ALIGNED(offset, eb->fs_info->sectorsize)) 3738c2ecf20Sopenharmony_ci return type; 3748c2ecf20Sopenharmony_ci } 3758c2ecf20Sopenharmony_ci } else if (is_data == BTRFS_REF_TYPE_DATA) { 3768c2ecf20Sopenharmony_ci if (type == BTRFS_EXTENT_DATA_REF_KEY) 3778c2ecf20Sopenharmony_ci return type; 3788c2ecf20Sopenharmony_ci if (type == BTRFS_SHARED_DATA_REF_KEY) { 3798c2ecf20Sopenharmony_ci ASSERT(eb->fs_info); 3808c2ecf20Sopenharmony_ci /* 3818c2ecf20Sopenharmony_ci * Every shared one has parent tree block, 3828c2ecf20Sopenharmony_ci * which must be aligned to sector size. 3838c2ecf20Sopenharmony_ci */ 3848c2ecf20Sopenharmony_ci if (offset && 3858c2ecf20Sopenharmony_ci IS_ALIGNED(offset, eb->fs_info->sectorsize)) 3868c2ecf20Sopenharmony_ci return type; 3878c2ecf20Sopenharmony_ci } 3888c2ecf20Sopenharmony_ci } else { 3898c2ecf20Sopenharmony_ci ASSERT(is_data == BTRFS_REF_TYPE_ANY); 3908c2ecf20Sopenharmony_ci return type; 3918c2ecf20Sopenharmony_ci } 3928c2ecf20Sopenharmony_ci } 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_ci btrfs_print_leaf((struct extent_buffer *)eb); 3958c2ecf20Sopenharmony_ci btrfs_err(eb->fs_info, 3968c2ecf20Sopenharmony_ci "eb %llu iref 0x%lx invalid extent inline ref type %d", 3978c2ecf20Sopenharmony_ci eb->start, (unsigned long)iref, type); 3988c2ecf20Sopenharmony_ci WARN_ON(1); 3998c2ecf20Sopenharmony_ci 4008c2ecf20Sopenharmony_ci return BTRFS_REF_TYPE_INVALID; 4018c2ecf20Sopenharmony_ci} 4028c2ecf20Sopenharmony_ci 4038c2ecf20Sopenharmony_ciu64 hash_extent_data_ref(u64 root_objectid, u64 owner, u64 offset) 4048c2ecf20Sopenharmony_ci{ 4058c2ecf20Sopenharmony_ci u32 high_crc = ~(u32)0; 4068c2ecf20Sopenharmony_ci u32 low_crc = ~(u32)0; 4078c2ecf20Sopenharmony_ci __le64 lenum; 4088c2ecf20Sopenharmony_ci 4098c2ecf20Sopenharmony_ci lenum = cpu_to_le64(root_objectid); 4108c2ecf20Sopenharmony_ci high_crc = btrfs_crc32c(high_crc, &lenum, sizeof(lenum)); 4118c2ecf20Sopenharmony_ci lenum = cpu_to_le64(owner); 4128c2ecf20Sopenharmony_ci low_crc = btrfs_crc32c(low_crc, &lenum, sizeof(lenum)); 4138c2ecf20Sopenharmony_ci lenum = cpu_to_le64(offset); 4148c2ecf20Sopenharmony_ci low_crc = btrfs_crc32c(low_crc, &lenum, sizeof(lenum)); 4158c2ecf20Sopenharmony_ci 4168c2ecf20Sopenharmony_ci return ((u64)high_crc << 31) ^ (u64)low_crc; 4178c2ecf20Sopenharmony_ci} 4188c2ecf20Sopenharmony_ci 4198c2ecf20Sopenharmony_cistatic u64 hash_extent_data_ref_item(struct extent_buffer *leaf, 4208c2ecf20Sopenharmony_ci struct btrfs_extent_data_ref *ref) 4218c2ecf20Sopenharmony_ci{ 4228c2ecf20Sopenharmony_ci return hash_extent_data_ref(btrfs_extent_data_ref_root(leaf, ref), 4238c2ecf20Sopenharmony_ci btrfs_extent_data_ref_objectid(leaf, ref), 4248c2ecf20Sopenharmony_ci btrfs_extent_data_ref_offset(leaf, ref)); 4258c2ecf20Sopenharmony_ci} 4268c2ecf20Sopenharmony_ci 4278c2ecf20Sopenharmony_cistatic int match_extent_data_ref(struct extent_buffer *leaf, 4288c2ecf20Sopenharmony_ci struct btrfs_extent_data_ref *ref, 4298c2ecf20Sopenharmony_ci u64 root_objectid, u64 owner, u64 offset) 4308c2ecf20Sopenharmony_ci{ 4318c2ecf20Sopenharmony_ci if (btrfs_extent_data_ref_root(leaf, ref) != root_objectid || 4328c2ecf20Sopenharmony_ci btrfs_extent_data_ref_objectid(leaf, ref) != owner || 4338c2ecf20Sopenharmony_ci btrfs_extent_data_ref_offset(leaf, ref) != offset) 4348c2ecf20Sopenharmony_ci return 0; 4358c2ecf20Sopenharmony_ci return 1; 4368c2ecf20Sopenharmony_ci} 4378c2ecf20Sopenharmony_ci 4388c2ecf20Sopenharmony_cistatic noinline int lookup_extent_data_ref(struct btrfs_trans_handle *trans, 4398c2ecf20Sopenharmony_ci struct btrfs_path *path, 4408c2ecf20Sopenharmony_ci u64 bytenr, u64 parent, 4418c2ecf20Sopenharmony_ci u64 root_objectid, 4428c2ecf20Sopenharmony_ci u64 owner, u64 offset) 4438c2ecf20Sopenharmony_ci{ 4448c2ecf20Sopenharmony_ci struct btrfs_root *root = trans->fs_info->extent_root; 4458c2ecf20Sopenharmony_ci struct btrfs_key key; 4468c2ecf20Sopenharmony_ci struct btrfs_extent_data_ref *ref; 4478c2ecf20Sopenharmony_ci struct extent_buffer *leaf; 4488c2ecf20Sopenharmony_ci u32 nritems; 4498c2ecf20Sopenharmony_ci int ret; 4508c2ecf20Sopenharmony_ci int recow; 4518c2ecf20Sopenharmony_ci int err = -ENOENT; 4528c2ecf20Sopenharmony_ci 4538c2ecf20Sopenharmony_ci key.objectid = bytenr; 4548c2ecf20Sopenharmony_ci if (parent) { 4558c2ecf20Sopenharmony_ci key.type = BTRFS_SHARED_DATA_REF_KEY; 4568c2ecf20Sopenharmony_ci key.offset = parent; 4578c2ecf20Sopenharmony_ci } else { 4588c2ecf20Sopenharmony_ci key.type = BTRFS_EXTENT_DATA_REF_KEY; 4598c2ecf20Sopenharmony_ci key.offset = hash_extent_data_ref(root_objectid, 4608c2ecf20Sopenharmony_ci owner, offset); 4618c2ecf20Sopenharmony_ci } 4628c2ecf20Sopenharmony_ciagain: 4638c2ecf20Sopenharmony_ci recow = 0; 4648c2ecf20Sopenharmony_ci ret = btrfs_search_slot(trans, root, &key, path, -1, 1); 4658c2ecf20Sopenharmony_ci if (ret < 0) { 4668c2ecf20Sopenharmony_ci err = ret; 4678c2ecf20Sopenharmony_ci goto fail; 4688c2ecf20Sopenharmony_ci } 4698c2ecf20Sopenharmony_ci 4708c2ecf20Sopenharmony_ci if (parent) { 4718c2ecf20Sopenharmony_ci if (!ret) 4728c2ecf20Sopenharmony_ci return 0; 4738c2ecf20Sopenharmony_ci goto fail; 4748c2ecf20Sopenharmony_ci } 4758c2ecf20Sopenharmony_ci 4768c2ecf20Sopenharmony_ci leaf = path->nodes[0]; 4778c2ecf20Sopenharmony_ci nritems = btrfs_header_nritems(leaf); 4788c2ecf20Sopenharmony_ci while (1) { 4798c2ecf20Sopenharmony_ci if (path->slots[0] >= nritems) { 4808c2ecf20Sopenharmony_ci ret = btrfs_next_leaf(root, path); 4818c2ecf20Sopenharmony_ci if (ret < 0) 4828c2ecf20Sopenharmony_ci err = ret; 4838c2ecf20Sopenharmony_ci if (ret) 4848c2ecf20Sopenharmony_ci goto fail; 4858c2ecf20Sopenharmony_ci 4868c2ecf20Sopenharmony_ci leaf = path->nodes[0]; 4878c2ecf20Sopenharmony_ci nritems = btrfs_header_nritems(leaf); 4888c2ecf20Sopenharmony_ci recow = 1; 4898c2ecf20Sopenharmony_ci } 4908c2ecf20Sopenharmony_ci 4918c2ecf20Sopenharmony_ci btrfs_item_key_to_cpu(leaf, &key, path->slots[0]); 4928c2ecf20Sopenharmony_ci if (key.objectid != bytenr || 4938c2ecf20Sopenharmony_ci key.type != BTRFS_EXTENT_DATA_REF_KEY) 4948c2ecf20Sopenharmony_ci goto fail; 4958c2ecf20Sopenharmony_ci 4968c2ecf20Sopenharmony_ci ref = btrfs_item_ptr(leaf, path->slots[0], 4978c2ecf20Sopenharmony_ci struct btrfs_extent_data_ref); 4988c2ecf20Sopenharmony_ci 4998c2ecf20Sopenharmony_ci if (match_extent_data_ref(leaf, ref, root_objectid, 5008c2ecf20Sopenharmony_ci owner, offset)) { 5018c2ecf20Sopenharmony_ci if (recow) { 5028c2ecf20Sopenharmony_ci btrfs_release_path(path); 5038c2ecf20Sopenharmony_ci goto again; 5048c2ecf20Sopenharmony_ci } 5058c2ecf20Sopenharmony_ci err = 0; 5068c2ecf20Sopenharmony_ci break; 5078c2ecf20Sopenharmony_ci } 5088c2ecf20Sopenharmony_ci path->slots[0]++; 5098c2ecf20Sopenharmony_ci } 5108c2ecf20Sopenharmony_cifail: 5118c2ecf20Sopenharmony_ci return err; 5128c2ecf20Sopenharmony_ci} 5138c2ecf20Sopenharmony_ci 5148c2ecf20Sopenharmony_cistatic noinline int insert_extent_data_ref(struct btrfs_trans_handle *trans, 5158c2ecf20Sopenharmony_ci struct btrfs_path *path, 5168c2ecf20Sopenharmony_ci u64 bytenr, u64 parent, 5178c2ecf20Sopenharmony_ci u64 root_objectid, u64 owner, 5188c2ecf20Sopenharmony_ci u64 offset, int refs_to_add) 5198c2ecf20Sopenharmony_ci{ 5208c2ecf20Sopenharmony_ci struct btrfs_root *root = trans->fs_info->extent_root; 5218c2ecf20Sopenharmony_ci struct btrfs_key key; 5228c2ecf20Sopenharmony_ci struct extent_buffer *leaf; 5238c2ecf20Sopenharmony_ci u32 size; 5248c2ecf20Sopenharmony_ci u32 num_refs; 5258c2ecf20Sopenharmony_ci int ret; 5268c2ecf20Sopenharmony_ci 5278c2ecf20Sopenharmony_ci key.objectid = bytenr; 5288c2ecf20Sopenharmony_ci if (parent) { 5298c2ecf20Sopenharmony_ci key.type = BTRFS_SHARED_DATA_REF_KEY; 5308c2ecf20Sopenharmony_ci key.offset = parent; 5318c2ecf20Sopenharmony_ci size = sizeof(struct btrfs_shared_data_ref); 5328c2ecf20Sopenharmony_ci } else { 5338c2ecf20Sopenharmony_ci key.type = BTRFS_EXTENT_DATA_REF_KEY; 5348c2ecf20Sopenharmony_ci key.offset = hash_extent_data_ref(root_objectid, 5358c2ecf20Sopenharmony_ci owner, offset); 5368c2ecf20Sopenharmony_ci size = sizeof(struct btrfs_extent_data_ref); 5378c2ecf20Sopenharmony_ci } 5388c2ecf20Sopenharmony_ci 5398c2ecf20Sopenharmony_ci ret = btrfs_insert_empty_item(trans, root, path, &key, size); 5408c2ecf20Sopenharmony_ci if (ret && ret != -EEXIST) 5418c2ecf20Sopenharmony_ci goto fail; 5428c2ecf20Sopenharmony_ci 5438c2ecf20Sopenharmony_ci leaf = path->nodes[0]; 5448c2ecf20Sopenharmony_ci if (parent) { 5458c2ecf20Sopenharmony_ci struct btrfs_shared_data_ref *ref; 5468c2ecf20Sopenharmony_ci ref = btrfs_item_ptr(leaf, path->slots[0], 5478c2ecf20Sopenharmony_ci struct btrfs_shared_data_ref); 5488c2ecf20Sopenharmony_ci if (ret == 0) { 5498c2ecf20Sopenharmony_ci btrfs_set_shared_data_ref_count(leaf, ref, refs_to_add); 5508c2ecf20Sopenharmony_ci } else { 5518c2ecf20Sopenharmony_ci num_refs = btrfs_shared_data_ref_count(leaf, ref); 5528c2ecf20Sopenharmony_ci num_refs += refs_to_add; 5538c2ecf20Sopenharmony_ci btrfs_set_shared_data_ref_count(leaf, ref, num_refs); 5548c2ecf20Sopenharmony_ci } 5558c2ecf20Sopenharmony_ci } else { 5568c2ecf20Sopenharmony_ci struct btrfs_extent_data_ref *ref; 5578c2ecf20Sopenharmony_ci while (ret == -EEXIST) { 5588c2ecf20Sopenharmony_ci ref = btrfs_item_ptr(leaf, path->slots[0], 5598c2ecf20Sopenharmony_ci struct btrfs_extent_data_ref); 5608c2ecf20Sopenharmony_ci if (match_extent_data_ref(leaf, ref, root_objectid, 5618c2ecf20Sopenharmony_ci owner, offset)) 5628c2ecf20Sopenharmony_ci break; 5638c2ecf20Sopenharmony_ci btrfs_release_path(path); 5648c2ecf20Sopenharmony_ci key.offset++; 5658c2ecf20Sopenharmony_ci ret = btrfs_insert_empty_item(trans, root, path, &key, 5668c2ecf20Sopenharmony_ci size); 5678c2ecf20Sopenharmony_ci if (ret && ret != -EEXIST) 5688c2ecf20Sopenharmony_ci goto fail; 5698c2ecf20Sopenharmony_ci 5708c2ecf20Sopenharmony_ci leaf = path->nodes[0]; 5718c2ecf20Sopenharmony_ci } 5728c2ecf20Sopenharmony_ci ref = btrfs_item_ptr(leaf, path->slots[0], 5738c2ecf20Sopenharmony_ci struct btrfs_extent_data_ref); 5748c2ecf20Sopenharmony_ci if (ret == 0) { 5758c2ecf20Sopenharmony_ci btrfs_set_extent_data_ref_root(leaf, ref, 5768c2ecf20Sopenharmony_ci root_objectid); 5778c2ecf20Sopenharmony_ci btrfs_set_extent_data_ref_objectid(leaf, ref, owner); 5788c2ecf20Sopenharmony_ci btrfs_set_extent_data_ref_offset(leaf, ref, offset); 5798c2ecf20Sopenharmony_ci btrfs_set_extent_data_ref_count(leaf, ref, refs_to_add); 5808c2ecf20Sopenharmony_ci } else { 5818c2ecf20Sopenharmony_ci num_refs = btrfs_extent_data_ref_count(leaf, ref); 5828c2ecf20Sopenharmony_ci num_refs += refs_to_add; 5838c2ecf20Sopenharmony_ci btrfs_set_extent_data_ref_count(leaf, ref, num_refs); 5848c2ecf20Sopenharmony_ci } 5858c2ecf20Sopenharmony_ci } 5868c2ecf20Sopenharmony_ci btrfs_mark_buffer_dirty(leaf); 5878c2ecf20Sopenharmony_ci ret = 0; 5888c2ecf20Sopenharmony_cifail: 5898c2ecf20Sopenharmony_ci btrfs_release_path(path); 5908c2ecf20Sopenharmony_ci return ret; 5918c2ecf20Sopenharmony_ci} 5928c2ecf20Sopenharmony_ci 5938c2ecf20Sopenharmony_cistatic noinline int remove_extent_data_ref(struct btrfs_trans_handle *trans, 5948c2ecf20Sopenharmony_ci struct btrfs_path *path, 5958c2ecf20Sopenharmony_ci int refs_to_drop, int *last_ref) 5968c2ecf20Sopenharmony_ci{ 5978c2ecf20Sopenharmony_ci struct btrfs_key key; 5988c2ecf20Sopenharmony_ci struct btrfs_extent_data_ref *ref1 = NULL; 5998c2ecf20Sopenharmony_ci struct btrfs_shared_data_ref *ref2 = NULL; 6008c2ecf20Sopenharmony_ci struct extent_buffer *leaf; 6018c2ecf20Sopenharmony_ci u32 num_refs = 0; 6028c2ecf20Sopenharmony_ci int ret = 0; 6038c2ecf20Sopenharmony_ci 6048c2ecf20Sopenharmony_ci leaf = path->nodes[0]; 6058c2ecf20Sopenharmony_ci btrfs_item_key_to_cpu(leaf, &key, path->slots[0]); 6068c2ecf20Sopenharmony_ci 6078c2ecf20Sopenharmony_ci if (key.type == BTRFS_EXTENT_DATA_REF_KEY) { 6088c2ecf20Sopenharmony_ci ref1 = btrfs_item_ptr(leaf, path->slots[0], 6098c2ecf20Sopenharmony_ci struct btrfs_extent_data_ref); 6108c2ecf20Sopenharmony_ci num_refs = btrfs_extent_data_ref_count(leaf, ref1); 6118c2ecf20Sopenharmony_ci } else if (key.type == BTRFS_SHARED_DATA_REF_KEY) { 6128c2ecf20Sopenharmony_ci ref2 = btrfs_item_ptr(leaf, path->slots[0], 6138c2ecf20Sopenharmony_ci struct btrfs_shared_data_ref); 6148c2ecf20Sopenharmony_ci num_refs = btrfs_shared_data_ref_count(leaf, ref2); 6158c2ecf20Sopenharmony_ci } else if (unlikely(key.type == BTRFS_EXTENT_REF_V0_KEY)) { 6168c2ecf20Sopenharmony_ci btrfs_print_v0_err(trans->fs_info); 6178c2ecf20Sopenharmony_ci btrfs_abort_transaction(trans, -EINVAL); 6188c2ecf20Sopenharmony_ci return -EINVAL; 6198c2ecf20Sopenharmony_ci } else { 6208c2ecf20Sopenharmony_ci BUG(); 6218c2ecf20Sopenharmony_ci } 6228c2ecf20Sopenharmony_ci 6238c2ecf20Sopenharmony_ci BUG_ON(num_refs < refs_to_drop); 6248c2ecf20Sopenharmony_ci num_refs -= refs_to_drop; 6258c2ecf20Sopenharmony_ci 6268c2ecf20Sopenharmony_ci if (num_refs == 0) { 6278c2ecf20Sopenharmony_ci ret = btrfs_del_item(trans, trans->fs_info->extent_root, path); 6288c2ecf20Sopenharmony_ci *last_ref = 1; 6298c2ecf20Sopenharmony_ci } else { 6308c2ecf20Sopenharmony_ci if (key.type == BTRFS_EXTENT_DATA_REF_KEY) 6318c2ecf20Sopenharmony_ci btrfs_set_extent_data_ref_count(leaf, ref1, num_refs); 6328c2ecf20Sopenharmony_ci else if (key.type == BTRFS_SHARED_DATA_REF_KEY) 6338c2ecf20Sopenharmony_ci btrfs_set_shared_data_ref_count(leaf, ref2, num_refs); 6348c2ecf20Sopenharmony_ci btrfs_mark_buffer_dirty(leaf); 6358c2ecf20Sopenharmony_ci } 6368c2ecf20Sopenharmony_ci return ret; 6378c2ecf20Sopenharmony_ci} 6388c2ecf20Sopenharmony_ci 6398c2ecf20Sopenharmony_cistatic noinline u32 extent_data_ref_count(struct btrfs_path *path, 6408c2ecf20Sopenharmony_ci struct btrfs_extent_inline_ref *iref) 6418c2ecf20Sopenharmony_ci{ 6428c2ecf20Sopenharmony_ci struct btrfs_key key; 6438c2ecf20Sopenharmony_ci struct extent_buffer *leaf; 6448c2ecf20Sopenharmony_ci struct btrfs_extent_data_ref *ref1; 6458c2ecf20Sopenharmony_ci struct btrfs_shared_data_ref *ref2; 6468c2ecf20Sopenharmony_ci u32 num_refs = 0; 6478c2ecf20Sopenharmony_ci int type; 6488c2ecf20Sopenharmony_ci 6498c2ecf20Sopenharmony_ci leaf = path->nodes[0]; 6508c2ecf20Sopenharmony_ci btrfs_item_key_to_cpu(leaf, &key, path->slots[0]); 6518c2ecf20Sopenharmony_ci 6528c2ecf20Sopenharmony_ci BUG_ON(key.type == BTRFS_EXTENT_REF_V0_KEY); 6538c2ecf20Sopenharmony_ci if (iref) { 6548c2ecf20Sopenharmony_ci /* 6558c2ecf20Sopenharmony_ci * If type is invalid, we should have bailed out earlier than 6568c2ecf20Sopenharmony_ci * this call. 6578c2ecf20Sopenharmony_ci */ 6588c2ecf20Sopenharmony_ci type = btrfs_get_extent_inline_ref_type(leaf, iref, BTRFS_REF_TYPE_DATA); 6598c2ecf20Sopenharmony_ci ASSERT(type != BTRFS_REF_TYPE_INVALID); 6608c2ecf20Sopenharmony_ci if (type == BTRFS_EXTENT_DATA_REF_KEY) { 6618c2ecf20Sopenharmony_ci ref1 = (struct btrfs_extent_data_ref *)(&iref->offset); 6628c2ecf20Sopenharmony_ci num_refs = btrfs_extent_data_ref_count(leaf, ref1); 6638c2ecf20Sopenharmony_ci } else { 6648c2ecf20Sopenharmony_ci ref2 = (struct btrfs_shared_data_ref *)(iref + 1); 6658c2ecf20Sopenharmony_ci num_refs = btrfs_shared_data_ref_count(leaf, ref2); 6668c2ecf20Sopenharmony_ci } 6678c2ecf20Sopenharmony_ci } else if (key.type == BTRFS_EXTENT_DATA_REF_KEY) { 6688c2ecf20Sopenharmony_ci ref1 = btrfs_item_ptr(leaf, path->slots[0], 6698c2ecf20Sopenharmony_ci struct btrfs_extent_data_ref); 6708c2ecf20Sopenharmony_ci num_refs = btrfs_extent_data_ref_count(leaf, ref1); 6718c2ecf20Sopenharmony_ci } else if (key.type == BTRFS_SHARED_DATA_REF_KEY) { 6728c2ecf20Sopenharmony_ci ref2 = btrfs_item_ptr(leaf, path->slots[0], 6738c2ecf20Sopenharmony_ci struct btrfs_shared_data_ref); 6748c2ecf20Sopenharmony_ci num_refs = btrfs_shared_data_ref_count(leaf, ref2); 6758c2ecf20Sopenharmony_ci } else { 6768c2ecf20Sopenharmony_ci WARN_ON(1); 6778c2ecf20Sopenharmony_ci } 6788c2ecf20Sopenharmony_ci return num_refs; 6798c2ecf20Sopenharmony_ci} 6808c2ecf20Sopenharmony_ci 6818c2ecf20Sopenharmony_cistatic noinline int lookup_tree_block_ref(struct btrfs_trans_handle *trans, 6828c2ecf20Sopenharmony_ci struct btrfs_path *path, 6838c2ecf20Sopenharmony_ci u64 bytenr, u64 parent, 6848c2ecf20Sopenharmony_ci u64 root_objectid) 6858c2ecf20Sopenharmony_ci{ 6868c2ecf20Sopenharmony_ci struct btrfs_root *root = trans->fs_info->extent_root; 6878c2ecf20Sopenharmony_ci struct btrfs_key key; 6888c2ecf20Sopenharmony_ci int ret; 6898c2ecf20Sopenharmony_ci 6908c2ecf20Sopenharmony_ci key.objectid = bytenr; 6918c2ecf20Sopenharmony_ci if (parent) { 6928c2ecf20Sopenharmony_ci key.type = BTRFS_SHARED_BLOCK_REF_KEY; 6938c2ecf20Sopenharmony_ci key.offset = parent; 6948c2ecf20Sopenharmony_ci } else { 6958c2ecf20Sopenharmony_ci key.type = BTRFS_TREE_BLOCK_REF_KEY; 6968c2ecf20Sopenharmony_ci key.offset = root_objectid; 6978c2ecf20Sopenharmony_ci } 6988c2ecf20Sopenharmony_ci 6998c2ecf20Sopenharmony_ci ret = btrfs_search_slot(trans, root, &key, path, -1, 1); 7008c2ecf20Sopenharmony_ci if (ret > 0) 7018c2ecf20Sopenharmony_ci ret = -ENOENT; 7028c2ecf20Sopenharmony_ci return ret; 7038c2ecf20Sopenharmony_ci} 7048c2ecf20Sopenharmony_ci 7058c2ecf20Sopenharmony_cistatic noinline int insert_tree_block_ref(struct btrfs_trans_handle *trans, 7068c2ecf20Sopenharmony_ci struct btrfs_path *path, 7078c2ecf20Sopenharmony_ci u64 bytenr, u64 parent, 7088c2ecf20Sopenharmony_ci u64 root_objectid) 7098c2ecf20Sopenharmony_ci{ 7108c2ecf20Sopenharmony_ci struct btrfs_key key; 7118c2ecf20Sopenharmony_ci int ret; 7128c2ecf20Sopenharmony_ci 7138c2ecf20Sopenharmony_ci key.objectid = bytenr; 7148c2ecf20Sopenharmony_ci if (parent) { 7158c2ecf20Sopenharmony_ci key.type = BTRFS_SHARED_BLOCK_REF_KEY; 7168c2ecf20Sopenharmony_ci key.offset = parent; 7178c2ecf20Sopenharmony_ci } else { 7188c2ecf20Sopenharmony_ci key.type = BTRFS_TREE_BLOCK_REF_KEY; 7198c2ecf20Sopenharmony_ci key.offset = root_objectid; 7208c2ecf20Sopenharmony_ci } 7218c2ecf20Sopenharmony_ci 7228c2ecf20Sopenharmony_ci ret = btrfs_insert_empty_item(trans, trans->fs_info->extent_root, 7238c2ecf20Sopenharmony_ci path, &key, 0); 7248c2ecf20Sopenharmony_ci btrfs_release_path(path); 7258c2ecf20Sopenharmony_ci return ret; 7268c2ecf20Sopenharmony_ci} 7278c2ecf20Sopenharmony_ci 7288c2ecf20Sopenharmony_cistatic inline int extent_ref_type(u64 parent, u64 owner) 7298c2ecf20Sopenharmony_ci{ 7308c2ecf20Sopenharmony_ci int type; 7318c2ecf20Sopenharmony_ci if (owner < BTRFS_FIRST_FREE_OBJECTID) { 7328c2ecf20Sopenharmony_ci if (parent > 0) 7338c2ecf20Sopenharmony_ci type = BTRFS_SHARED_BLOCK_REF_KEY; 7348c2ecf20Sopenharmony_ci else 7358c2ecf20Sopenharmony_ci type = BTRFS_TREE_BLOCK_REF_KEY; 7368c2ecf20Sopenharmony_ci } else { 7378c2ecf20Sopenharmony_ci if (parent > 0) 7388c2ecf20Sopenharmony_ci type = BTRFS_SHARED_DATA_REF_KEY; 7398c2ecf20Sopenharmony_ci else 7408c2ecf20Sopenharmony_ci type = BTRFS_EXTENT_DATA_REF_KEY; 7418c2ecf20Sopenharmony_ci } 7428c2ecf20Sopenharmony_ci return type; 7438c2ecf20Sopenharmony_ci} 7448c2ecf20Sopenharmony_ci 7458c2ecf20Sopenharmony_cistatic int find_next_key(struct btrfs_path *path, int level, 7468c2ecf20Sopenharmony_ci struct btrfs_key *key) 7478c2ecf20Sopenharmony_ci 7488c2ecf20Sopenharmony_ci{ 7498c2ecf20Sopenharmony_ci for (; level < BTRFS_MAX_LEVEL; level++) { 7508c2ecf20Sopenharmony_ci if (!path->nodes[level]) 7518c2ecf20Sopenharmony_ci break; 7528c2ecf20Sopenharmony_ci if (path->slots[level] + 1 >= 7538c2ecf20Sopenharmony_ci btrfs_header_nritems(path->nodes[level])) 7548c2ecf20Sopenharmony_ci continue; 7558c2ecf20Sopenharmony_ci if (level == 0) 7568c2ecf20Sopenharmony_ci btrfs_item_key_to_cpu(path->nodes[level], key, 7578c2ecf20Sopenharmony_ci path->slots[level] + 1); 7588c2ecf20Sopenharmony_ci else 7598c2ecf20Sopenharmony_ci btrfs_node_key_to_cpu(path->nodes[level], key, 7608c2ecf20Sopenharmony_ci path->slots[level] + 1); 7618c2ecf20Sopenharmony_ci return 0; 7628c2ecf20Sopenharmony_ci } 7638c2ecf20Sopenharmony_ci return 1; 7648c2ecf20Sopenharmony_ci} 7658c2ecf20Sopenharmony_ci 7668c2ecf20Sopenharmony_ci/* 7678c2ecf20Sopenharmony_ci * look for inline back ref. if back ref is found, *ref_ret is set 7688c2ecf20Sopenharmony_ci * to the address of inline back ref, and 0 is returned. 7698c2ecf20Sopenharmony_ci * 7708c2ecf20Sopenharmony_ci * if back ref isn't found, *ref_ret is set to the address where it 7718c2ecf20Sopenharmony_ci * should be inserted, and -ENOENT is returned. 7728c2ecf20Sopenharmony_ci * 7738c2ecf20Sopenharmony_ci * if insert is true and there are too many inline back refs, the path 7748c2ecf20Sopenharmony_ci * points to the extent item, and -EAGAIN is returned. 7758c2ecf20Sopenharmony_ci * 7768c2ecf20Sopenharmony_ci * NOTE: inline back refs are ordered in the same way that back ref 7778c2ecf20Sopenharmony_ci * items in the tree are ordered. 7788c2ecf20Sopenharmony_ci */ 7798c2ecf20Sopenharmony_cistatic noinline_for_stack 7808c2ecf20Sopenharmony_ciint lookup_inline_extent_backref(struct btrfs_trans_handle *trans, 7818c2ecf20Sopenharmony_ci struct btrfs_path *path, 7828c2ecf20Sopenharmony_ci struct btrfs_extent_inline_ref **ref_ret, 7838c2ecf20Sopenharmony_ci u64 bytenr, u64 num_bytes, 7848c2ecf20Sopenharmony_ci u64 parent, u64 root_objectid, 7858c2ecf20Sopenharmony_ci u64 owner, u64 offset, int insert) 7868c2ecf20Sopenharmony_ci{ 7878c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = trans->fs_info; 7888c2ecf20Sopenharmony_ci struct btrfs_root *root = fs_info->extent_root; 7898c2ecf20Sopenharmony_ci struct btrfs_key key; 7908c2ecf20Sopenharmony_ci struct extent_buffer *leaf; 7918c2ecf20Sopenharmony_ci struct btrfs_extent_item *ei; 7928c2ecf20Sopenharmony_ci struct btrfs_extent_inline_ref *iref; 7938c2ecf20Sopenharmony_ci u64 flags; 7948c2ecf20Sopenharmony_ci u64 item_size; 7958c2ecf20Sopenharmony_ci unsigned long ptr; 7968c2ecf20Sopenharmony_ci unsigned long end; 7978c2ecf20Sopenharmony_ci int extra_size; 7988c2ecf20Sopenharmony_ci int type; 7998c2ecf20Sopenharmony_ci int want; 8008c2ecf20Sopenharmony_ci int ret; 8018c2ecf20Sopenharmony_ci int err = 0; 8028c2ecf20Sopenharmony_ci bool skinny_metadata = btrfs_fs_incompat(fs_info, SKINNY_METADATA); 8038c2ecf20Sopenharmony_ci int needed; 8048c2ecf20Sopenharmony_ci 8058c2ecf20Sopenharmony_ci key.objectid = bytenr; 8068c2ecf20Sopenharmony_ci key.type = BTRFS_EXTENT_ITEM_KEY; 8078c2ecf20Sopenharmony_ci key.offset = num_bytes; 8088c2ecf20Sopenharmony_ci 8098c2ecf20Sopenharmony_ci want = extent_ref_type(parent, owner); 8108c2ecf20Sopenharmony_ci if (insert) { 8118c2ecf20Sopenharmony_ci extra_size = btrfs_extent_inline_ref_size(want); 8128c2ecf20Sopenharmony_ci path->keep_locks = 1; 8138c2ecf20Sopenharmony_ci } else 8148c2ecf20Sopenharmony_ci extra_size = -1; 8158c2ecf20Sopenharmony_ci 8168c2ecf20Sopenharmony_ci /* 8178c2ecf20Sopenharmony_ci * Owner is our level, so we can just add one to get the level for the 8188c2ecf20Sopenharmony_ci * block we are interested in. 8198c2ecf20Sopenharmony_ci */ 8208c2ecf20Sopenharmony_ci if (skinny_metadata && owner < BTRFS_FIRST_FREE_OBJECTID) { 8218c2ecf20Sopenharmony_ci key.type = BTRFS_METADATA_ITEM_KEY; 8228c2ecf20Sopenharmony_ci key.offset = owner; 8238c2ecf20Sopenharmony_ci } 8248c2ecf20Sopenharmony_ci 8258c2ecf20Sopenharmony_ciagain: 8268c2ecf20Sopenharmony_ci ret = btrfs_search_slot(trans, root, &key, path, extra_size, 1); 8278c2ecf20Sopenharmony_ci if (ret < 0) { 8288c2ecf20Sopenharmony_ci err = ret; 8298c2ecf20Sopenharmony_ci goto out; 8308c2ecf20Sopenharmony_ci } 8318c2ecf20Sopenharmony_ci 8328c2ecf20Sopenharmony_ci /* 8338c2ecf20Sopenharmony_ci * We may be a newly converted file system which still has the old fat 8348c2ecf20Sopenharmony_ci * extent entries for metadata, so try and see if we have one of those. 8358c2ecf20Sopenharmony_ci */ 8368c2ecf20Sopenharmony_ci if (ret > 0 && skinny_metadata) { 8378c2ecf20Sopenharmony_ci skinny_metadata = false; 8388c2ecf20Sopenharmony_ci if (path->slots[0]) { 8398c2ecf20Sopenharmony_ci path->slots[0]--; 8408c2ecf20Sopenharmony_ci btrfs_item_key_to_cpu(path->nodes[0], &key, 8418c2ecf20Sopenharmony_ci path->slots[0]); 8428c2ecf20Sopenharmony_ci if (key.objectid == bytenr && 8438c2ecf20Sopenharmony_ci key.type == BTRFS_EXTENT_ITEM_KEY && 8448c2ecf20Sopenharmony_ci key.offset == num_bytes) 8458c2ecf20Sopenharmony_ci ret = 0; 8468c2ecf20Sopenharmony_ci } 8478c2ecf20Sopenharmony_ci if (ret) { 8488c2ecf20Sopenharmony_ci key.objectid = bytenr; 8498c2ecf20Sopenharmony_ci key.type = BTRFS_EXTENT_ITEM_KEY; 8508c2ecf20Sopenharmony_ci key.offset = num_bytes; 8518c2ecf20Sopenharmony_ci btrfs_release_path(path); 8528c2ecf20Sopenharmony_ci goto again; 8538c2ecf20Sopenharmony_ci } 8548c2ecf20Sopenharmony_ci } 8558c2ecf20Sopenharmony_ci 8568c2ecf20Sopenharmony_ci if (ret && !insert) { 8578c2ecf20Sopenharmony_ci err = -ENOENT; 8588c2ecf20Sopenharmony_ci goto out; 8598c2ecf20Sopenharmony_ci } else if (WARN_ON(ret)) { 8608c2ecf20Sopenharmony_ci btrfs_print_leaf(path->nodes[0]); 8618c2ecf20Sopenharmony_ci btrfs_err(fs_info, 8628c2ecf20Sopenharmony_ci"extent item not found for insert, bytenr %llu num_bytes %llu parent %llu root_objectid %llu owner %llu offset %llu", 8638c2ecf20Sopenharmony_ci bytenr, num_bytes, parent, root_objectid, owner, 8648c2ecf20Sopenharmony_ci offset); 8658c2ecf20Sopenharmony_ci err = -EIO; 8668c2ecf20Sopenharmony_ci goto out; 8678c2ecf20Sopenharmony_ci } 8688c2ecf20Sopenharmony_ci 8698c2ecf20Sopenharmony_ci leaf = path->nodes[0]; 8708c2ecf20Sopenharmony_ci item_size = btrfs_item_size_nr(leaf, path->slots[0]); 8718c2ecf20Sopenharmony_ci if (unlikely(item_size < sizeof(*ei))) { 8728c2ecf20Sopenharmony_ci err = -EINVAL; 8738c2ecf20Sopenharmony_ci btrfs_print_v0_err(fs_info); 8748c2ecf20Sopenharmony_ci btrfs_abort_transaction(trans, err); 8758c2ecf20Sopenharmony_ci goto out; 8768c2ecf20Sopenharmony_ci } 8778c2ecf20Sopenharmony_ci 8788c2ecf20Sopenharmony_ci ei = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_extent_item); 8798c2ecf20Sopenharmony_ci flags = btrfs_extent_flags(leaf, ei); 8808c2ecf20Sopenharmony_ci 8818c2ecf20Sopenharmony_ci ptr = (unsigned long)(ei + 1); 8828c2ecf20Sopenharmony_ci end = (unsigned long)ei + item_size; 8838c2ecf20Sopenharmony_ci 8848c2ecf20Sopenharmony_ci if (flags & BTRFS_EXTENT_FLAG_TREE_BLOCK && !skinny_metadata) { 8858c2ecf20Sopenharmony_ci ptr += sizeof(struct btrfs_tree_block_info); 8868c2ecf20Sopenharmony_ci BUG_ON(ptr > end); 8878c2ecf20Sopenharmony_ci } 8888c2ecf20Sopenharmony_ci 8898c2ecf20Sopenharmony_ci if (owner >= BTRFS_FIRST_FREE_OBJECTID) 8908c2ecf20Sopenharmony_ci needed = BTRFS_REF_TYPE_DATA; 8918c2ecf20Sopenharmony_ci else 8928c2ecf20Sopenharmony_ci needed = BTRFS_REF_TYPE_BLOCK; 8938c2ecf20Sopenharmony_ci 8948c2ecf20Sopenharmony_ci err = -ENOENT; 8958c2ecf20Sopenharmony_ci while (1) { 8968c2ecf20Sopenharmony_ci if (ptr >= end) { 8978c2ecf20Sopenharmony_ci WARN_ON(ptr > end); 8988c2ecf20Sopenharmony_ci break; 8998c2ecf20Sopenharmony_ci } 9008c2ecf20Sopenharmony_ci iref = (struct btrfs_extent_inline_ref *)ptr; 9018c2ecf20Sopenharmony_ci type = btrfs_get_extent_inline_ref_type(leaf, iref, needed); 9028c2ecf20Sopenharmony_ci if (type == BTRFS_REF_TYPE_INVALID) { 9038c2ecf20Sopenharmony_ci err = -EUCLEAN; 9048c2ecf20Sopenharmony_ci goto out; 9058c2ecf20Sopenharmony_ci } 9068c2ecf20Sopenharmony_ci 9078c2ecf20Sopenharmony_ci if (want < type) 9088c2ecf20Sopenharmony_ci break; 9098c2ecf20Sopenharmony_ci if (want > type) { 9108c2ecf20Sopenharmony_ci ptr += btrfs_extent_inline_ref_size(type); 9118c2ecf20Sopenharmony_ci continue; 9128c2ecf20Sopenharmony_ci } 9138c2ecf20Sopenharmony_ci 9148c2ecf20Sopenharmony_ci if (type == BTRFS_EXTENT_DATA_REF_KEY) { 9158c2ecf20Sopenharmony_ci struct btrfs_extent_data_ref *dref; 9168c2ecf20Sopenharmony_ci dref = (struct btrfs_extent_data_ref *)(&iref->offset); 9178c2ecf20Sopenharmony_ci if (match_extent_data_ref(leaf, dref, root_objectid, 9188c2ecf20Sopenharmony_ci owner, offset)) { 9198c2ecf20Sopenharmony_ci err = 0; 9208c2ecf20Sopenharmony_ci break; 9218c2ecf20Sopenharmony_ci } 9228c2ecf20Sopenharmony_ci if (hash_extent_data_ref_item(leaf, dref) < 9238c2ecf20Sopenharmony_ci hash_extent_data_ref(root_objectid, owner, offset)) 9248c2ecf20Sopenharmony_ci break; 9258c2ecf20Sopenharmony_ci } else { 9268c2ecf20Sopenharmony_ci u64 ref_offset; 9278c2ecf20Sopenharmony_ci ref_offset = btrfs_extent_inline_ref_offset(leaf, iref); 9288c2ecf20Sopenharmony_ci if (parent > 0) { 9298c2ecf20Sopenharmony_ci if (parent == ref_offset) { 9308c2ecf20Sopenharmony_ci err = 0; 9318c2ecf20Sopenharmony_ci break; 9328c2ecf20Sopenharmony_ci } 9338c2ecf20Sopenharmony_ci if (ref_offset < parent) 9348c2ecf20Sopenharmony_ci break; 9358c2ecf20Sopenharmony_ci } else { 9368c2ecf20Sopenharmony_ci if (root_objectid == ref_offset) { 9378c2ecf20Sopenharmony_ci err = 0; 9388c2ecf20Sopenharmony_ci break; 9398c2ecf20Sopenharmony_ci } 9408c2ecf20Sopenharmony_ci if (ref_offset < root_objectid) 9418c2ecf20Sopenharmony_ci break; 9428c2ecf20Sopenharmony_ci } 9438c2ecf20Sopenharmony_ci } 9448c2ecf20Sopenharmony_ci ptr += btrfs_extent_inline_ref_size(type); 9458c2ecf20Sopenharmony_ci } 9468c2ecf20Sopenharmony_ci if (err == -ENOENT && insert) { 9478c2ecf20Sopenharmony_ci if (item_size + extra_size >= 9488c2ecf20Sopenharmony_ci BTRFS_MAX_EXTENT_ITEM_SIZE(root)) { 9498c2ecf20Sopenharmony_ci err = -EAGAIN; 9508c2ecf20Sopenharmony_ci goto out; 9518c2ecf20Sopenharmony_ci } 9528c2ecf20Sopenharmony_ci /* 9538c2ecf20Sopenharmony_ci * To add new inline back ref, we have to make sure 9548c2ecf20Sopenharmony_ci * there is no corresponding back ref item. 9558c2ecf20Sopenharmony_ci * For simplicity, we just do not add new inline back 9568c2ecf20Sopenharmony_ci * ref if there is any kind of item for this block 9578c2ecf20Sopenharmony_ci */ 9588c2ecf20Sopenharmony_ci if (find_next_key(path, 0, &key) == 0 && 9598c2ecf20Sopenharmony_ci key.objectid == bytenr && 9608c2ecf20Sopenharmony_ci key.type < BTRFS_BLOCK_GROUP_ITEM_KEY) { 9618c2ecf20Sopenharmony_ci err = -EAGAIN; 9628c2ecf20Sopenharmony_ci goto out; 9638c2ecf20Sopenharmony_ci } 9648c2ecf20Sopenharmony_ci } 9658c2ecf20Sopenharmony_ci *ref_ret = (struct btrfs_extent_inline_ref *)ptr; 9668c2ecf20Sopenharmony_ciout: 9678c2ecf20Sopenharmony_ci if (insert) { 9688c2ecf20Sopenharmony_ci path->keep_locks = 0; 9698c2ecf20Sopenharmony_ci btrfs_unlock_up_safe(path, 1); 9708c2ecf20Sopenharmony_ci } 9718c2ecf20Sopenharmony_ci return err; 9728c2ecf20Sopenharmony_ci} 9738c2ecf20Sopenharmony_ci 9748c2ecf20Sopenharmony_ci/* 9758c2ecf20Sopenharmony_ci * helper to add new inline back ref 9768c2ecf20Sopenharmony_ci */ 9778c2ecf20Sopenharmony_cistatic noinline_for_stack 9788c2ecf20Sopenharmony_civoid setup_inline_extent_backref(struct btrfs_fs_info *fs_info, 9798c2ecf20Sopenharmony_ci struct btrfs_path *path, 9808c2ecf20Sopenharmony_ci struct btrfs_extent_inline_ref *iref, 9818c2ecf20Sopenharmony_ci u64 parent, u64 root_objectid, 9828c2ecf20Sopenharmony_ci u64 owner, u64 offset, int refs_to_add, 9838c2ecf20Sopenharmony_ci struct btrfs_delayed_extent_op *extent_op) 9848c2ecf20Sopenharmony_ci{ 9858c2ecf20Sopenharmony_ci struct extent_buffer *leaf; 9868c2ecf20Sopenharmony_ci struct btrfs_extent_item *ei; 9878c2ecf20Sopenharmony_ci unsigned long ptr; 9888c2ecf20Sopenharmony_ci unsigned long end; 9898c2ecf20Sopenharmony_ci unsigned long item_offset; 9908c2ecf20Sopenharmony_ci u64 refs; 9918c2ecf20Sopenharmony_ci int size; 9928c2ecf20Sopenharmony_ci int type; 9938c2ecf20Sopenharmony_ci 9948c2ecf20Sopenharmony_ci leaf = path->nodes[0]; 9958c2ecf20Sopenharmony_ci ei = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_extent_item); 9968c2ecf20Sopenharmony_ci item_offset = (unsigned long)iref - (unsigned long)ei; 9978c2ecf20Sopenharmony_ci 9988c2ecf20Sopenharmony_ci type = extent_ref_type(parent, owner); 9998c2ecf20Sopenharmony_ci size = btrfs_extent_inline_ref_size(type); 10008c2ecf20Sopenharmony_ci 10018c2ecf20Sopenharmony_ci btrfs_extend_item(path, size); 10028c2ecf20Sopenharmony_ci 10038c2ecf20Sopenharmony_ci ei = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_extent_item); 10048c2ecf20Sopenharmony_ci refs = btrfs_extent_refs(leaf, ei); 10058c2ecf20Sopenharmony_ci refs += refs_to_add; 10068c2ecf20Sopenharmony_ci btrfs_set_extent_refs(leaf, ei, refs); 10078c2ecf20Sopenharmony_ci if (extent_op) 10088c2ecf20Sopenharmony_ci __run_delayed_extent_op(extent_op, leaf, ei); 10098c2ecf20Sopenharmony_ci 10108c2ecf20Sopenharmony_ci ptr = (unsigned long)ei + item_offset; 10118c2ecf20Sopenharmony_ci end = (unsigned long)ei + btrfs_item_size_nr(leaf, path->slots[0]); 10128c2ecf20Sopenharmony_ci if (ptr < end - size) 10138c2ecf20Sopenharmony_ci memmove_extent_buffer(leaf, ptr + size, ptr, 10148c2ecf20Sopenharmony_ci end - size - ptr); 10158c2ecf20Sopenharmony_ci 10168c2ecf20Sopenharmony_ci iref = (struct btrfs_extent_inline_ref *)ptr; 10178c2ecf20Sopenharmony_ci btrfs_set_extent_inline_ref_type(leaf, iref, type); 10188c2ecf20Sopenharmony_ci if (type == BTRFS_EXTENT_DATA_REF_KEY) { 10198c2ecf20Sopenharmony_ci struct btrfs_extent_data_ref *dref; 10208c2ecf20Sopenharmony_ci dref = (struct btrfs_extent_data_ref *)(&iref->offset); 10218c2ecf20Sopenharmony_ci btrfs_set_extent_data_ref_root(leaf, dref, root_objectid); 10228c2ecf20Sopenharmony_ci btrfs_set_extent_data_ref_objectid(leaf, dref, owner); 10238c2ecf20Sopenharmony_ci btrfs_set_extent_data_ref_offset(leaf, dref, offset); 10248c2ecf20Sopenharmony_ci btrfs_set_extent_data_ref_count(leaf, dref, refs_to_add); 10258c2ecf20Sopenharmony_ci } else if (type == BTRFS_SHARED_DATA_REF_KEY) { 10268c2ecf20Sopenharmony_ci struct btrfs_shared_data_ref *sref; 10278c2ecf20Sopenharmony_ci sref = (struct btrfs_shared_data_ref *)(iref + 1); 10288c2ecf20Sopenharmony_ci btrfs_set_shared_data_ref_count(leaf, sref, refs_to_add); 10298c2ecf20Sopenharmony_ci btrfs_set_extent_inline_ref_offset(leaf, iref, parent); 10308c2ecf20Sopenharmony_ci } else if (type == BTRFS_SHARED_BLOCK_REF_KEY) { 10318c2ecf20Sopenharmony_ci btrfs_set_extent_inline_ref_offset(leaf, iref, parent); 10328c2ecf20Sopenharmony_ci } else { 10338c2ecf20Sopenharmony_ci btrfs_set_extent_inline_ref_offset(leaf, iref, root_objectid); 10348c2ecf20Sopenharmony_ci } 10358c2ecf20Sopenharmony_ci btrfs_mark_buffer_dirty(leaf); 10368c2ecf20Sopenharmony_ci} 10378c2ecf20Sopenharmony_ci 10388c2ecf20Sopenharmony_cistatic int lookup_extent_backref(struct btrfs_trans_handle *trans, 10398c2ecf20Sopenharmony_ci struct btrfs_path *path, 10408c2ecf20Sopenharmony_ci struct btrfs_extent_inline_ref **ref_ret, 10418c2ecf20Sopenharmony_ci u64 bytenr, u64 num_bytes, u64 parent, 10428c2ecf20Sopenharmony_ci u64 root_objectid, u64 owner, u64 offset) 10438c2ecf20Sopenharmony_ci{ 10448c2ecf20Sopenharmony_ci int ret; 10458c2ecf20Sopenharmony_ci 10468c2ecf20Sopenharmony_ci ret = lookup_inline_extent_backref(trans, path, ref_ret, bytenr, 10478c2ecf20Sopenharmony_ci num_bytes, parent, root_objectid, 10488c2ecf20Sopenharmony_ci owner, offset, 0); 10498c2ecf20Sopenharmony_ci if (ret != -ENOENT) 10508c2ecf20Sopenharmony_ci return ret; 10518c2ecf20Sopenharmony_ci 10528c2ecf20Sopenharmony_ci btrfs_release_path(path); 10538c2ecf20Sopenharmony_ci *ref_ret = NULL; 10548c2ecf20Sopenharmony_ci 10558c2ecf20Sopenharmony_ci if (owner < BTRFS_FIRST_FREE_OBJECTID) { 10568c2ecf20Sopenharmony_ci ret = lookup_tree_block_ref(trans, path, bytenr, parent, 10578c2ecf20Sopenharmony_ci root_objectid); 10588c2ecf20Sopenharmony_ci } else { 10598c2ecf20Sopenharmony_ci ret = lookup_extent_data_ref(trans, path, bytenr, parent, 10608c2ecf20Sopenharmony_ci root_objectid, owner, offset); 10618c2ecf20Sopenharmony_ci } 10628c2ecf20Sopenharmony_ci return ret; 10638c2ecf20Sopenharmony_ci} 10648c2ecf20Sopenharmony_ci 10658c2ecf20Sopenharmony_ci/* 10668c2ecf20Sopenharmony_ci * helper to update/remove inline back ref 10678c2ecf20Sopenharmony_ci */ 10688c2ecf20Sopenharmony_cistatic noinline_for_stack 10698c2ecf20Sopenharmony_civoid update_inline_extent_backref(struct btrfs_path *path, 10708c2ecf20Sopenharmony_ci struct btrfs_extent_inline_ref *iref, 10718c2ecf20Sopenharmony_ci int refs_to_mod, 10728c2ecf20Sopenharmony_ci struct btrfs_delayed_extent_op *extent_op, 10738c2ecf20Sopenharmony_ci int *last_ref) 10748c2ecf20Sopenharmony_ci{ 10758c2ecf20Sopenharmony_ci struct extent_buffer *leaf = path->nodes[0]; 10768c2ecf20Sopenharmony_ci struct btrfs_extent_item *ei; 10778c2ecf20Sopenharmony_ci struct btrfs_extent_data_ref *dref = NULL; 10788c2ecf20Sopenharmony_ci struct btrfs_shared_data_ref *sref = NULL; 10798c2ecf20Sopenharmony_ci unsigned long ptr; 10808c2ecf20Sopenharmony_ci unsigned long end; 10818c2ecf20Sopenharmony_ci u32 item_size; 10828c2ecf20Sopenharmony_ci int size; 10838c2ecf20Sopenharmony_ci int type; 10848c2ecf20Sopenharmony_ci u64 refs; 10858c2ecf20Sopenharmony_ci 10868c2ecf20Sopenharmony_ci ei = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_extent_item); 10878c2ecf20Sopenharmony_ci refs = btrfs_extent_refs(leaf, ei); 10888c2ecf20Sopenharmony_ci WARN_ON(refs_to_mod < 0 && refs + refs_to_mod <= 0); 10898c2ecf20Sopenharmony_ci refs += refs_to_mod; 10908c2ecf20Sopenharmony_ci btrfs_set_extent_refs(leaf, ei, refs); 10918c2ecf20Sopenharmony_ci if (extent_op) 10928c2ecf20Sopenharmony_ci __run_delayed_extent_op(extent_op, leaf, ei); 10938c2ecf20Sopenharmony_ci 10948c2ecf20Sopenharmony_ci /* 10958c2ecf20Sopenharmony_ci * If type is invalid, we should have bailed out after 10968c2ecf20Sopenharmony_ci * lookup_inline_extent_backref(). 10978c2ecf20Sopenharmony_ci */ 10988c2ecf20Sopenharmony_ci type = btrfs_get_extent_inline_ref_type(leaf, iref, BTRFS_REF_TYPE_ANY); 10998c2ecf20Sopenharmony_ci ASSERT(type != BTRFS_REF_TYPE_INVALID); 11008c2ecf20Sopenharmony_ci 11018c2ecf20Sopenharmony_ci if (type == BTRFS_EXTENT_DATA_REF_KEY) { 11028c2ecf20Sopenharmony_ci dref = (struct btrfs_extent_data_ref *)(&iref->offset); 11038c2ecf20Sopenharmony_ci refs = btrfs_extent_data_ref_count(leaf, dref); 11048c2ecf20Sopenharmony_ci } else if (type == BTRFS_SHARED_DATA_REF_KEY) { 11058c2ecf20Sopenharmony_ci sref = (struct btrfs_shared_data_ref *)(iref + 1); 11068c2ecf20Sopenharmony_ci refs = btrfs_shared_data_ref_count(leaf, sref); 11078c2ecf20Sopenharmony_ci } else { 11088c2ecf20Sopenharmony_ci refs = 1; 11098c2ecf20Sopenharmony_ci BUG_ON(refs_to_mod != -1); 11108c2ecf20Sopenharmony_ci } 11118c2ecf20Sopenharmony_ci 11128c2ecf20Sopenharmony_ci BUG_ON(refs_to_mod < 0 && refs < -refs_to_mod); 11138c2ecf20Sopenharmony_ci refs += refs_to_mod; 11148c2ecf20Sopenharmony_ci 11158c2ecf20Sopenharmony_ci if (refs > 0) { 11168c2ecf20Sopenharmony_ci if (type == BTRFS_EXTENT_DATA_REF_KEY) 11178c2ecf20Sopenharmony_ci btrfs_set_extent_data_ref_count(leaf, dref, refs); 11188c2ecf20Sopenharmony_ci else 11198c2ecf20Sopenharmony_ci btrfs_set_shared_data_ref_count(leaf, sref, refs); 11208c2ecf20Sopenharmony_ci } else { 11218c2ecf20Sopenharmony_ci *last_ref = 1; 11228c2ecf20Sopenharmony_ci size = btrfs_extent_inline_ref_size(type); 11238c2ecf20Sopenharmony_ci item_size = btrfs_item_size_nr(leaf, path->slots[0]); 11248c2ecf20Sopenharmony_ci ptr = (unsigned long)iref; 11258c2ecf20Sopenharmony_ci end = (unsigned long)ei + item_size; 11268c2ecf20Sopenharmony_ci if (ptr + size < end) 11278c2ecf20Sopenharmony_ci memmove_extent_buffer(leaf, ptr, ptr + size, 11288c2ecf20Sopenharmony_ci end - ptr - size); 11298c2ecf20Sopenharmony_ci item_size -= size; 11308c2ecf20Sopenharmony_ci btrfs_truncate_item(path, item_size, 1); 11318c2ecf20Sopenharmony_ci } 11328c2ecf20Sopenharmony_ci btrfs_mark_buffer_dirty(leaf); 11338c2ecf20Sopenharmony_ci} 11348c2ecf20Sopenharmony_ci 11358c2ecf20Sopenharmony_cistatic noinline_for_stack 11368c2ecf20Sopenharmony_ciint insert_inline_extent_backref(struct btrfs_trans_handle *trans, 11378c2ecf20Sopenharmony_ci struct btrfs_path *path, 11388c2ecf20Sopenharmony_ci u64 bytenr, u64 num_bytes, u64 parent, 11398c2ecf20Sopenharmony_ci u64 root_objectid, u64 owner, 11408c2ecf20Sopenharmony_ci u64 offset, int refs_to_add, 11418c2ecf20Sopenharmony_ci struct btrfs_delayed_extent_op *extent_op) 11428c2ecf20Sopenharmony_ci{ 11438c2ecf20Sopenharmony_ci struct btrfs_extent_inline_ref *iref; 11448c2ecf20Sopenharmony_ci int ret; 11458c2ecf20Sopenharmony_ci 11468c2ecf20Sopenharmony_ci ret = lookup_inline_extent_backref(trans, path, &iref, bytenr, 11478c2ecf20Sopenharmony_ci num_bytes, parent, root_objectid, 11488c2ecf20Sopenharmony_ci owner, offset, 1); 11498c2ecf20Sopenharmony_ci if (ret == 0) { 11508c2ecf20Sopenharmony_ci /* 11518c2ecf20Sopenharmony_ci * We're adding refs to a tree block we already own, this 11528c2ecf20Sopenharmony_ci * should not happen at all. 11538c2ecf20Sopenharmony_ci */ 11548c2ecf20Sopenharmony_ci if (owner < BTRFS_FIRST_FREE_OBJECTID) { 11558c2ecf20Sopenharmony_ci btrfs_crit(trans->fs_info, 11568c2ecf20Sopenharmony_ci"adding refs to an existing tree ref, bytenr %llu num_bytes %llu root_objectid %llu", 11578c2ecf20Sopenharmony_ci bytenr, num_bytes, root_objectid); 11588c2ecf20Sopenharmony_ci if (IS_ENABLED(CONFIG_BTRFS_DEBUG)) { 11598c2ecf20Sopenharmony_ci WARN_ON(1); 11608c2ecf20Sopenharmony_ci btrfs_crit(trans->fs_info, 11618c2ecf20Sopenharmony_ci "path->slots[0]=%d path->nodes[0]:", path->slots[0]); 11628c2ecf20Sopenharmony_ci btrfs_print_leaf(path->nodes[0]); 11638c2ecf20Sopenharmony_ci } 11648c2ecf20Sopenharmony_ci return -EUCLEAN; 11658c2ecf20Sopenharmony_ci } 11668c2ecf20Sopenharmony_ci update_inline_extent_backref(path, iref, refs_to_add, 11678c2ecf20Sopenharmony_ci extent_op, NULL); 11688c2ecf20Sopenharmony_ci } else if (ret == -ENOENT) { 11698c2ecf20Sopenharmony_ci setup_inline_extent_backref(trans->fs_info, path, iref, parent, 11708c2ecf20Sopenharmony_ci root_objectid, owner, offset, 11718c2ecf20Sopenharmony_ci refs_to_add, extent_op); 11728c2ecf20Sopenharmony_ci ret = 0; 11738c2ecf20Sopenharmony_ci } 11748c2ecf20Sopenharmony_ci return ret; 11758c2ecf20Sopenharmony_ci} 11768c2ecf20Sopenharmony_ci 11778c2ecf20Sopenharmony_cistatic int remove_extent_backref(struct btrfs_trans_handle *trans, 11788c2ecf20Sopenharmony_ci struct btrfs_path *path, 11798c2ecf20Sopenharmony_ci struct btrfs_extent_inline_ref *iref, 11808c2ecf20Sopenharmony_ci int refs_to_drop, int is_data, int *last_ref) 11818c2ecf20Sopenharmony_ci{ 11828c2ecf20Sopenharmony_ci int ret = 0; 11838c2ecf20Sopenharmony_ci 11848c2ecf20Sopenharmony_ci BUG_ON(!is_data && refs_to_drop != 1); 11858c2ecf20Sopenharmony_ci if (iref) { 11868c2ecf20Sopenharmony_ci update_inline_extent_backref(path, iref, -refs_to_drop, NULL, 11878c2ecf20Sopenharmony_ci last_ref); 11888c2ecf20Sopenharmony_ci } else if (is_data) { 11898c2ecf20Sopenharmony_ci ret = remove_extent_data_ref(trans, path, refs_to_drop, 11908c2ecf20Sopenharmony_ci last_ref); 11918c2ecf20Sopenharmony_ci } else { 11928c2ecf20Sopenharmony_ci *last_ref = 1; 11938c2ecf20Sopenharmony_ci ret = btrfs_del_item(trans, trans->fs_info->extent_root, path); 11948c2ecf20Sopenharmony_ci } 11958c2ecf20Sopenharmony_ci return ret; 11968c2ecf20Sopenharmony_ci} 11978c2ecf20Sopenharmony_ci 11988c2ecf20Sopenharmony_cistatic int btrfs_issue_discard(struct block_device *bdev, u64 start, u64 len, 11998c2ecf20Sopenharmony_ci u64 *discarded_bytes) 12008c2ecf20Sopenharmony_ci{ 12018c2ecf20Sopenharmony_ci int j, ret = 0; 12028c2ecf20Sopenharmony_ci u64 bytes_left, end; 12038c2ecf20Sopenharmony_ci u64 aligned_start = ALIGN(start, 1 << 9); 12048c2ecf20Sopenharmony_ci 12058c2ecf20Sopenharmony_ci /* Adjust the range to be aligned to 512B sectors if necessary. */ 12068c2ecf20Sopenharmony_ci if (start != aligned_start) { 12078c2ecf20Sopenharmony_ci len -= aligned_start - start; 12088c2ecf20Sopenharmony_ci len = round_down(len, 1 << 9); 12098c2ecf20Sopenharmony_ci start = aligned_start; 12108c2ecf20Sopenharmony_ci } 12118c2ecf20Sopenharmony_ci 12128c2ecf20Sopenharmony_ci *discarded_bytes = 0; 12138c2ecf20Sopenharmony_ci 12148c2ecf20Sopenharmony_ci if (!len) 12158c2ecf20Sopenharmony_ci return 0; 12168c2ecf20Sopenharmony_ci 12178c2ecf20Sopenharmony_ci end = start + len; 12188c2ecf20Sopenharmony_ci bytes_left = len; 12198c2ecf20Sopenharmony_ci 12208c2ecf20Sopenharmony_ci /* Skip any superblocks on this device. */ 12218c2ecf20Sopenharmony_ci for (j = 0; j < BTRFS_SUPER_MIRROR_MAX; j++) { 12228c2ecf20Sopenharmony_ci u64 sb_start = btrfs_sb_offset(j); 12238c2ecf20Sopenharmony_ci u64 sb_end = sb_start + BTRFS_SUPER_INFO_SIZE; 12248c2ecf20Sopenharmony_ci u64 size = sb_start - start; 12258c2ecf20Sopenharmony_ci 12268c2ecf20Sopenharmony_ci if (!in_range(sb_start, start, bytes_left) && 12278c2ecf20Sopenharmony_ci !in_range(sb_end, start, bytes_left) && 12288c2ecf20Sopenharmony_ci !in_range(start, sb_start, BTRFS_SUPER_INFO_SIZE)) 12298c2ecf20Sopenharmony_ci continue; 12308c2ecf20Sopenharmony_ci 12318c2ecf20Sopenharmony_ci /* 12328c2ecf20Sopenharmony_ci * Superblock spans beginning of range. Adjust start and 12338c2ecf20Sopenharmony_ci * try again. 12348c2ecf20Sopenharmony_ci */ 12358c2ecf20Sopenharmony_ci if (sb_start <= start) { 12368c2ecf20Sopenharmony_ci start += sb_end - start; 12378c2ecf20Sopenharmony_ci if (start > end) { 12388c2ecf20Sopenharmony_ci bytes_left = 0; 12398c2ecf20Sopenharmony_ci break; 12408c2ecf20Sopenharmony_ci } 12418c2ecf20Sopenharmony_ci bytes_left = end - start; 12428c2ecf20Sopenharmony_ci continue; 12438c2ecf20Sopenharmony_ci } 12448c2ecf20Sopenharmony_ci 12458c2ecf20Sopenharmony_ci if (size) { 12468c2ecf20Sopenharmony_ci ret = blkdev_issue_discard(bdev, start >> 9, size >> 9, 12478c2ecf20Sopenharmony_ci GFP_NOFS, 0); 12488c2ecf20Sopenharmony_ci if (!ret) 12498c2ecf20Sopenharmony_ci *discarded_bytes += size; 12508c2ecf20Sopenharmony_ci else if (ret != -EOPNOTSUPP) 12518c2ecf20Sopenharmony_ci return ret; 12528c2ecf20Sopenharmony_ci } 12538c2ecf20Sopenharmony_ci 12548c2ecf20Sopenharmony_ci start = sb_end; 12558c2ecf20Sopenharmony_ci if (start > end) { 12568c2ecf20Sopenharmony_ci bytes_left = 0; 12578c2ecf20Sopenharmony_ci break; 12588c2ecf20Sopenharmony_ci } 12598c2ecf20Sopenharmony_ci bytes_left = end - start; 12608c2ecf20Sopenharmony_ci } 12618c2ecf20Sopenharmony_ci 12628c2ecf20Sopenharmony_ci if (bytes_left) { 12638c2ecf20Sopenharmony_ci ret = blkdev_issue_discard(bdev, start >> 9, bytes_left >> 9, 12648c2ecf20Sopenharmony_ci GFP_NOFS, 0); 12658c2ecf20Sopenharmony_ci if (!ret) 12668c2ecf20Sopenharmony_ci *discarded_bytes += bytes_left; 12678c2ecf20Sopenharmony_ci } 12688c2ecf20Sopenharmony_ci return ret; 12698c2ecf20Sopenharmony_ci} 12708c2ecf20Sopenharmony_ci 12718c2ecf20Sopenharmony_ciint btrfs_discard_extent(struct btrfs_fs_info *fs_info, u64 bytenr, 12728c2ecf20Sopenharmony_ci u64 num_bytes, u64 *actual_bytes) 12738c2ecf20Sopenharmony_ci{ 12748c2ecf20Sopenharmony_ci int ret = 0; 12758c2ecf20Sopenharmony_ci u64 discarded_bytes = 0; 12768c2ecf20Sopenharmony_ci u64 end = bytenr + num_bytes; 12778c2ecf20Sopenharmony_ci u64 cur = bytenr; 12788c2ecf20Sopenharmony_ci struct btrfs_bio *bbio = NULL; 12798c2ecf20Sopenharmony_ci 12808c2ecf20Sopenharmony_ci 12818c2ecf20Sopenharmony_ci /* 12828c2ecf20Sopenharmony_ci * Avoid races with device replace and make sure our bbio has devices 12838c2ecf20Sopenharmony_ci * associated to its stripes that don't go away while we are discarding. 12848c2ecf20Sopenharmony_ci */ 12858c2ecf20Sopenharmony_ci btrfs_bio_counter_inc_blocked(fs_info); 12868c2ecf20Sopenharmony_ci while (cur < end) { 12878c2ecf20Sopenharmony_ci struct btrfs_bio_stripe *stripe; 12888c2ecf20Sopenharmony_ci int i; 12898c2ecf20Sopenharmony_ci 12908c2ecf20Sopenharmony_ci num_bytes = end - cur; 12918c2ecf20Sopenharmony_ci /* Tell the block device(s) that the sectors can be discarded */ 12928c2ecf20Sopenharmony_ci ret = btrfs_map_block(fs_info, BTRFS_MAP_DISCARD, cur, 12938c2ecf20Sopenharmony_ci &num_bytes, &bbio, 0); 12948c2ecf20Sopenharmony_ci /* 12958c2ecf20Sopenharmony_ci * Error can be -ENOMEM, -ENOENT (no such chunk mapping) or 12968c2ecf20Sopenharmony_ci * -EOPNOTSUPP. For any such error, @num_bytes is not updated, 12978c2ecf20Sopenharmony_ci * thus we can't continue anyway. 12988c2ecf20Sopenharmony_ci */ 12998c2ecf20Sopenharmony_ci if (ret < 0) 13008c2ecf20Sopenharmony_ci goto out; 13018c2ecf20Sopenharmony_ci 13028c2ecf20Sopenharmony_ci stripe = bbio->stripes; 13038c2ecf20Sopenharmony_ci for (i = 0; i < bbio->num_stripes; i++, stripe++) { 13048c2ecf20Sopenharmony_ci u64 bytes; 13058c2ecf20Sopenharmony_ci struct request_queue *req_q; 13068c2ecf20Sopenharmony_ci struct btrfs_device *device = stripe->dev; 13078c2ecf20Sopenharmony_ci 13088c2ecf20Sopenharmony_ci if (!device->bdev) { 13098c2ecf20Sopenharmony_ci ASSERT(btrfs_test_opt(fs_info, DEGRADED)); 13108c2ecf20Sopenharmony_ci continue; 13118c2ecf20Sopenharmony_ci } 13128c2ecf20Sopenharmony_ci req_q = bdev_get_queue(device->bdev); 13138c2ecf20Sopenharmony_ci if (!blk_queue_discard(req_q)) 13148c2ecf20Sopenharmony_ci continue; 13158c2ecf20Sopenharmony_ci 13168c2ecf20Sopenharmony_ci if (!test_bit(BTRFS_DEV_STATE_WRITEABLE, &device->dev_state)) 13178c2ecf20Sopenharmony_ci continue; 13188c2ecf20Sopenharmony_ci 13198c2ecf20Sopenharmony_ci ret = btrfs_issue_discard(device->bdev, 13208c2ecf20Sopenharmony_ci stripe->physical, 13218c2ecf20Sopenharmony_ci stripe->length, 13228c2ecf20Sopenharmony_ci &bytes); 13238c2ecf20Sopenharmony_ci if (!ret) { 13248c2ecf20Sopenharmony_ci discarded_bytes += bytes; 13258c2ecf20Sopenharmony_ci } else if (ret != -EOPNOTSUPP) { 13268c2ecf20Sopenharmony_ci /* 13278c2ecf20Sopenharmony_ci * Logic errors or -ENOMEM, or -EIO, but 13288c2ecf20Sopenharmony_ci * unlikely to happen. 13298c2ecf20Sopenharmony_ci * 13308c2ecf20Sopenharmony_ci * And since there are two loops, explicitly 13318c2ecf20Sopenharmony_ci * go to out to avoid confusion. 13328c2ecf20Sopenharmony_ci */ 13338c2ecf20Sopenharmony_ci btrfs_put_bbio(bbio); 13348c2ecf20Sopenharmony_ci goto out; 13358c2ecf20Sopenharmony_ci } 13368c2ecf20Sopenharmony_ci 13378c2ecf20Sopenharmony_ci /* 13388c2ecf20Sopenharmony_ci * Just in case we get back EOPNOTSUPP for some reason, 13398c2ecf20Sopenharmony_ci * just ignore the return value so we don't screw up 13408c2ecf20Sopenharmony_ci * people calling discard_extent. 13418c2ecf20Sopenharmony_ci */ 13428c2ecf20Sopenharmony_ci ret = 0; 13438c2ecf20Sopenharmony_ci } 13448c2ecf20Sopenharmony_ci btrfs_put_bbio(bbio); 13458c2ecf20Sopenharmony_ci cur += num_bytes; 13468c2ecf20Sopenharmony_ci } 13478c2ecf20Sopenharmony_ciout: 13488c2ecf20Sopenharmony_ci btrfs_bio_counter_dec(fs_info); 13498c2ecf20Sopenharmony_ci 13508c2ecf20Sopenharmony_ci if (actual_bytes) 13518c2ecf20Sopenharmony_ci *actual_bytes = discarded_bytes; 13528c2ecf20Sopenharmony_ci 13538c2ecf20Sopenharmony_ci 13548c2ecf20Sopenharmony_ci if (ret == -EOPNOTSUPP) 13558c2ecf20Sopenharmony_ci ret = 0; 13568c2ecf20Sopenharmony_ci return ret; 13578c2ecf20Sopenharmony_ci} 13588c2ecf20Sopenharmony_ci 13598c2ecf20Sopenharmony_ci/* Can return -ENOMEM */ 13608c2ecf20Sopenharmony_ciint btrfs_inc_extent_ref(struct btrfs_trans_handle *trans, 13618c2ecf20Sopenharmony_ci struct btrfs_ref *generic_ref) 13628c2ecf20Sopenharmony_ci{ 13638c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = trans->fs_info; 13648c2ecf20Sopenharmony_ci int ret; 13658c2ecf20Sopenharmony_ci 13668c2ecf20Sopenharmony_ci ASSERT(generic_ref->type != BTRFS_REF_NOT_SET && 13678c2ecf20Sopenharmony_ci generic_ref->action); 13688c2ecf20Sopenharmony_ci BUG_ON(generic_ref->type == BTRFS_REF_METADATA && 13698c2ecf20Sopenharmony_ci generic_ref->tree_ref.root == BTRFS_TREE_LOG_OBJECTID); 13708c2ecf20Sopenharmony_ci 13718c2ecf20Sopenharmony_ci if (generic_ref->type == BTRFS_REF_METADATA) 13728c2ecf20Sopenharmony_ci ret = btrfs_add_delayed_tree_ref(trans, generic_ref, NULL); 13738c2ecf20Sopenharmony_ci else 13748c2ecf20Sopenharmony_ci ret = btrfs_add_delayed_data_ref(trans, generic_ref, 0); 13758c2ecf20Sopenharmony_ci 13768c2ecf20Sopenharmony_ci btrfs_ref_tree_mod(fs_info, generic_ref); 13778c2ecf20Sopenharmony_ci 13788c2ecf20Sopenharmony_ci return ret; 13798c2ecf20Sopenharmony_ci} 13808c2ecf20Sopenharmony_ci 13818c2ecf20Sopenharmony_ci/* 13828c2ecf20Sopenharmony_ci * __btrfs_inc_extent_ref - insert backreference for a given extent 13838c2ecf20Sopenharmony_ci * 13848c2ecf20Sopenharmony_ci * The counterpart is in __btrfs_free_extent(), with examples and more details 13858c2ecf20Sopenharmony_ci * how it works. 13868c2ecf20Sopenharmony_ci * 13878c2ecf20Sopenharmony_ci * @trans: Handle of transaction 13888c2ecf20Sopenharmony_ci * 13898c2ecf20Sopenharmony_ci * @node: The delayed ref node used to get the bytenr/length for 13908c2ecf20Sopenharmony_ci * extent whose references are incremented. 13918c2ecf20Sopenharmony_ci * 13928c2ecf20Sopenharmony_ci * @parent: If this is a shared extent (BTRFS_SHARED_DATA_REF_KEY/ 13938c2ecf20Sopenharmony_ci * BTRFS_SHARED_BLOCK_REF_KEY) then it holds the logical 13948c2ecf20Sopenharmony_ci * bytenr of the parent block. Since new extents are always 13958c2ecf20Sopenharmony_ci * created with indirect references, this will only be the case 13968c2ecf20Sopenharmony_ci * when relocating a shared extent. In that case, root_objectid 13978c2ecf20Sopenharmony_ci * will be BTRFS_TREE_RELOC_OBJECTID. Otheriwse, parent must 13988c2ecf20Sopenharmony_ci * be 0 13998c2ecf20Sopenharmony_ci * 14008c2ecf20Sopenharmony_ci * @root_objectid: The id of the root where this modification has originated, 14018c2ecf20Sopenharmony_ci * this can be either one of the well-known metadata trees or 14028c2ecf20Sopenharmony_ci * the subvolume id which references this extent. 14038c2ecf20Sopenharmony_ci * 14048c2ecf20Sopenharmony_ci * @owner: For data extents it is the inode number of the owning file. 14058c2ecf20Sopenharmony_ci * For metadata extents this parameter holds the level in the 14068c2ecf20Sopenharmony_ci * tree of the extent. 14078c2ecf20Sopenharmony_ci * 14088c2ecf20Sopenharmony_ci * @offset: For metadata extents the offset is ignored and is currently 14098c2ecf20Sopenharmony_ci * always passed as 0. For data extents it is the fileoffset 14108c2ecf20Sopenharmony_ci * this extent belongs to. 14118c2ecf20Sopenharmony_ci * 14128c2ecf20Sopenharmony_ci * @refs_to_add Number of references to add 14138c2ecf20Sopenharmony_ci * 14148c2ecf20Sopenharmony_ci * @extent_op Pointer to a structure, holding information necessary when 14158c2ecf20Sopenharmony_ci * updating a tree block's flags 14168c2ecf20Sopenharmony_ci * 14178c2ecf20Sopenharmony_ci */ 14188c2ecf20Sopenharmony_cistatic int __btrfs_inc_extent_ref(struct btrfs_trans_handle *trans, 14198c2ecf20Sopenharmony_ci struct btrfs_delayed_ref_node *node, 14208c2ecf20Sopenharmony_ci u64 parent, u64 root_objectid, 14218c2ecf20Sopenharmony_ci u64 owner, u64 offset, int refs_to_add, 14228c2ecf20Sopenharmony_ci struct btrfs_delayed_extent_op *extent_op) 14238c2ecf20Sopenharmony_ci{ 14248c2ecf20Sopenharmony_ci struct btrfs_path *path; 14258c2ecf20Sopenharmony_ci struct extent_buffer *leaf; 14268c2ecf20Sopenharmony_ci struct btrfs_extent_item *item; 14278c2ecf20Sopenharmony_ci struct btrfs_key key; 14288c2ecf20Sopenharmony_ci u64 bytenr = node->bytenr; 14298c2ecf20Sopenharmony_ci u64 num_bytes = node->num_bytes; 14308c2ecf20Sopenharmony_ci u64 refs; 14318c2ecf20Sopenharmony_ci int ret; 14328c2ecf20Sopenharmony_ci 14338c2ecf20Sopenharmony_ci path = btrfs_alloc_path(); 14348c2ecf20Sopenharmony_ci if (!path) 14358c2ecf20Sopenharmony_ci return -ENOMEM; 14368c2ecf20Sopenharmony_ci 14378c2ecf20Sopenharmony_ci path->leave_spinning = 1; 14388c2ecf20Sopenharmony_ci /* this will setup the path even if it fails to insert the back ref */ 14398c2ecf20Sopenharmony_ci ret = insert_inline_extent_backref(trans, path, bytenr, num_bytes, 14408c2ecf20Sopenharmony_ci parent, root_objectid, owner, 14418c2ecf20Sopenharmony_ci offset, refs_to_add, extent_op); 14428c2ecf20Sopenharmony_ci if ((ret < 0 && ret != -EAGAIN) || !ret) 14438c2ecf20Sopenharmony_ci goto out; 14448c2ecf20Sopenharmony_ci 14458c2ecf20Sopenharmony_ci /* 14468c2ecf20Sopenharmony_ci * Ok we had -EAGAIN which means we didn't have space to insert and 14478c2ecf20Sopenharmony_ci * inline extent ref, so just update the reference count and add a 14488c2ecf20Sopenharmony_ci * normal backref. 14498c2ecf20Sopenharmony_ci */ 14508c2ecf20Sopenharmony_ci leaf = path->nodes[0]; 14518c2ecf20Sopenharmony_ci btrfs_item_key_to_cpu(leaf, &key, path->slots[0]); 14528c2ecf20Sopenharmony_ci item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_extent_item); 14538c2ecf20Sopenharmony_ci refs = btrfs_extent_refs(leaf, item); 14548c2ecf20Sopenharmony_ci btrfs_set_extent_refs(leaf, item, refs + refs_to_add); 14558c2ecf20Sopenharmony_ci if (extent_op) 14568c2ecf20Sopenharmony_ci __run_delayed_extent_op(extent_op, leaf, item); 14578c2ecf20Sopenharmony_ci 14588c2ecf20Sopenharmony_ci btrfs_mark_buffer_dirty(leaf); 14598c2ecf20Sopenharmony_ci btrfs_release_path(path); 14608c2ecf20Sopenharmony_ci 14618c2ecf20Sopenharmony_ci path->leave_spinning = 1; 14628c2ecf20Sopenharmony_ci /* now insert the actual backref */ 14638c2ecf20Sopenharmony_ci if (owner < BTRFS_FIRST_FREE_OBJECTID) { 14648c2ecf20Sopenharmony_ci BUG_ON(refs_to_add != 1); 14658c2ecf20Sopenharmony_ci ret = insert_tree_block_ref(trans, path, bytenr, parent, 14668c2ecf20Sopenharmony_ci root_objectid); 14678c2ecf20Sopenharmony_ci } else { 14688c2ecf20Sopenharmony_ci ret = insert_extent_data_ref(trans, path, bytenr, parent, 14698c2ecf20Sopenharmony_ci root_objectid, owner, offset, 14708c2ecf20Sopenharmony_ci refs_to_add); 14718c2ecf20Sopenharmony_ci } 14728c2ecf20Sopenharmony_ci if (ret) 14738c2ecf20Sopenharmony_ci btrfs_abort_transaction(trans, ret); 14748c2ecf20Sopenharmony_ciout: 14758c2ecf20Sopenharmony_ci btrfs_free_path(path); 14768c2ecf20Sopenharmony_ci return ret; 14778c2ecf20Sopenharmony_ci} 14788c2ecf20Sopenharmony_ci 14798c2ecf20Sopenharmony_cistatic int run_delayed_data_ref(struct btrfs_trans_handle *trans, 14808c2ecf20Sopenharmony_ci struct btrfs_delayed_ref_node *node, 14818c2ecf20Sopenharmony_ci struct btrfs_delayed_extent_op *extent_op, 14828c2ecf20Sopenharmony_ci int insert_reserved) 14838c2ecf20Sopenharmony_ci{ 14848c2ecf20Sopenharmony_ci int ret = 0; 14858c2ecf20Sopenharmony_ci struct btrfs_delayed_data_ref *ref; 14868c2ecf20Sopenharmony_ci struct btrfs_key ins; 14878c2ecf20Sopenharmony_ci u64 parent = 0; 14888c2ecf20Sopenharmony_ci u64 ref_root = 0; 14898c2ecf20Sopenharmony_ci u64 flags = 0; 14908c2ecf20Sopenharmony_ci 14918c2ecf20Sopenharmony_ci ins.objectid = node->bytenr; 14928c2ecf20Sopenharmony_ci ins.offset = node->num_bytes; 14938c2ecf20Sopenharmony_ci ins.type = BTRFS_EXTENT_ITEM_KEY; 14948c2ecf20Sopenharmony_ci 14958c2ecf20Sopenharmony_ci ref = btrfs_delayed_node_to_data_ref(node); 14968c2ecf20Sopenharmony_ci trace_run_delayed_data_ref(trans->fs_info, node, ref, node->action); 14978c2ecf20Sopenharmony_ci 14988c2ecf20Sopenharmony_ci if (node->type == BTRFS_SHARED_DATA_REF_KEY) 14998c2ecf20Sopenharmony_ci parent = ref->parent; 15008c2ecf20Sopenharmony_ci ref_root = ref->root; 15018c2ecf20Sopenharmony_ci 15028c2ecf20Sopenharmony_ci if (node->action == BTRFS_ADD_DELAYED_REF && insert_reserved) { 15038c2ecf20Sopenharmony_ci if (extent_op) 15048c2ecf20Sopenharmony_ci flags |= extent_op->flags_to_set; 15058c2ecf20Sopenharmony_ci ret = alloc_reserved_file_extent(trans, parent, ref_root, 15068c2ecf20Sopenharmony_ci flags, ref->objectid, 15078c2ecf20Sopenharmony_ci ref->offset, &ins, 15088c2ecf20Sopenharmony_ci node->ref_mod); 15098c2ecf20Sopenharmony_ci } else if (node->action == BTRFS_ADD_DELAYED_REF) { 15108c2ecf20Sopenharmony_ci ret = __btrfs_inc_extent_ref(trans, node, parent, ref_root, 15118c2ecf20Sopenharmony_ci ref->objectid, ref->offset, 15128c2ecf20Sopenharmony_ci node->ref_mod, extent_op); 15138c2ecf20Sopenharmony_ci } else if (node->action == BTRFS_DROP_DELAYED_REF) { 15148c2ecf20Sopenharmony_ci ret = __btrfs_free_extent(trans, node, parent, 15158c2ecf20Sopenharmony_ci ref_root, ref->objectid, 15168c2ecf20Sopenharmony_ci ref->offset, node->ref_mod, 15178c2ecf20Sopenharmony_ci extent_op); 15188c2ecf20Sopenharmony_ci } else { 15198c2ecf20Sopenharmony_ci BUG(); 15208c2ecf20Sopenharmony_ci } 15218c2ecf20Sopenharmony_ci return ret; 15228c2ecf20Sopenharmony_ci} 15238c2ecf20Sopenharmony_ci 15248c2ecf20Sopenharmony_cistatic void __run_delayed_extent_op(struct btrfs_delayed_extent_op *extent_op, 15258c2ecf20Sopenharmony_ci struct extent_buffer *leaf, 15268c2ecf20Sopenharmony_ci struct btrfs_extent_item *ei) 15278c2ecf20Sopenharmony_ci{ 15288c2ecf20Sopenharmony_ci u64 flags = btrfs_extent_flags(leaf, ei); 15298c2ecf20Sopenharmony_ci if (extent_op->update_flags) { 15308c2ecf20Sopenharmony_ci flags |= extent_op->flags_to_set; 15318c2ecf20Sopenharmony_ci btrfs_set_extent_flags(leaf, ei, flags); 15328c2ecf20Sopenharmony_ci } 15338c2ecf20Sopenharmony_ci 15348c2ecf20Sopenharmony_ci if (extent_op->update_key) { 15358c2ecf20Sopenharmony_ci struct btrfs_tree_block_info *bi; 15368c2ecf20Sopenharmony_ci BUG_ON(!(flags & BTRFS_EXTENT_FLAG_TREE_BLOCK)); 15378c2ecf20Sopenharmony_ci bi = (struct btrfs_tree_block_info *)(ei + 1); 15388c2ecf20Sopenharmony_ci btrfs_set_tree_block_key(leaf, bi, &extent_op->key); 15398c2ecf20Sopenharmony_ci } 15408c2ecf20Sopenharmony_ci} 15418c2ecf20Sopenharmony_ci 15428c2ecf20Sopenharmony_cistatic int run_delayed_extent_op(struct btrfs_trans_handle *trans, 15438c2ecf20Sopenharmony_ci struct btrfs_delayed_ref_head *head, 15448c2ecf20Sopenharmony_ci struct btrfs_delayed_extent_op *extent_op) 15458c2ecf20Sopenharmony_ci{ 15468c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = trans->fs_info; 15478c2ecf20Sopenharmony_ci struct btrfs_key key; 15488c2ecf20Sopenharmony_ci struct btrfs_path *path; 15498c2ecf20Sopenharmony_ci struct btrfs_extent_item *ei; 15508c2ecf20Sopenharmony_ci struct extent_buffer *leaf; 15518c2ecf20Sopenharmony_ci u32 item_size; 15528c2ecf20Sopenharmony_ci int ret; 15538c2ecf20Sopenharmony_ci int err = 0; 15548c2ecf20Sopenharmony_ci int metadata = !extent_op->is_data; 15558c2ecf20Sopenharmony_ci 15568c2ecf20Sopenharmony_ci if (TRANS_ABORTED(trans)) 15578c2ecf20Sopenharmony_ci return 0; 15588c2ecf20Sopenharmony_ci 15598c2ecf20Sopenharmony_ci if (metadata && !btrfs_fs_incompat(fs_info, SKINNY_METADATA)) 15608c2ecf20Sopenharmony_ci metadata = 0; 15618c2ecf20Sopenharmony_ci 15628c2ecf20Sopenharmony_ci path = btrfs_alloc_path(); 15638c2ecf20Sopenharmony_ci if (!path) 15648c2ecf20Sopenharmony_ci return -ENOMEM; 15658c2ecf20Sopenharmony_ci 15668c2ecf20Sopenharmony_ci key.objectid = head->bytenr; 15678c2ecf20Sopenharmony_ci 15688c2ecf20Sopenharmony_ci if (metadata) { 15698c2ecf20Sopenharmony_ci key.type = BTRFS_METADATA_ITEM_KEY; 15708c2ecf20Sopenharmony_ci key.offset = extent_op->level; 15718c2ecf20Sopenharmony_ci } else { 15728c2ecf20Sopenharmony_ci key.type = BTRFS_EXTENT_ITEM_KEY; 15738c2ecf20Sopenharmony_ci key.offset = head->num_bytes; 15748c2ecf20Sopenharmony_ci } 15758c2ecf20Sopenharmony_ci 15768c2ecf20Sopenharmony_ciagain: 15778c2ecf20Sopenharmony_ci path->leave_spinning = 1; 15788c2ecf20Sopenharmony_ci ret = btrfs_search_slot(trans, fs_info->extent_root, &key, path, 0, 1); 15798c2ecf20Sopenharmony_ci if (ret < 0) { 15808c2ecf20Sopenharmony_ci err = ret; 15818c2ecf20Sopenharmony_ci goto out; 15828c2ecf20Sopenharmony_ci } 15838c2ecf20Sopenharmony_ci if (ret > 0) { 15848c2ecf20Sopenharmony_ci if (metadata) { 15858c2ecf20Sopenharmony_ci if (path->slots[0] > 0) { 15868c2ecf20Sopenharmony_ci path->slots[0]--; 15878c2ecf20Sopenharmony_ci btrfs_item_key_to_cpu(path->nodes[0], &key, 15888c2ecf20Sopenharmony_ci path->slots[0]); 15898c2ecf20Sopenharmony_ci if (key.objectid == head->bytenr && 15908c2ecf20Sopenharmony_ci key.type == BTRFS_EXTENT_ITEM_KEY && 15918c2ecf20Sopenharmony_ci key.offset == head->num_bytes) 15928c2ecf20Sopenharmony_ci ret = 0; 15938c2ecf20Sopenharmony_ci } 15948c2ecf20Sopenharmony_ci if (ret > 0) { 15958c2ecf20Sopenharmony_ci btrfs_release_path(path); 15968c2ecf20Sopenharmony_ci metadata = 0; 15978c2ecf20Sopenharmony_ci 15988c2ecf20Sopenharmony_ci key.objectid = head->bytenr; 15998c2ecf20Sopenharmony_ci key.offset = head->num_bytes; 16008c2ecf20Sopenharmony_ci key.type = BTRFS_EXTENT_ITEM_KEY; 16018c2ecf20Sopenharmony_ci goto again; 16028c2ecf20Sopenharmony_ci } 16038c2ecf20Sopenharmony_ci } else { 16048c2ecf20Sopenharmony_ci err = -EIO; 16058c2ecf20Sopenharmony_ci goto out; 16068c2ecf20Sopenharmony_ci } 16078c2ecf20Sopenharmony_ci } 16088c2ecf20Sopenharmony_ci 16098c2ecf20Sopenharmony_ci leaf = path->nodes[0]; 16108c2ecf20Sopenharmony_ci item_size = btrfs_item_size_nr(leaf, path->slots[0]); 16118c2ecf20Sopenharmony_ci 16128c2ecf20Sopenharmony_ci if (unlikely(item_size < sizeof(*ei))) { 16138c2ecf20Sopenharmony_ci err = -EINVAL; 16148c2ecf20Sopenharmony_ci btrfs_print_v0_err(fs_info); 16158c2ecf20Sopenharmony_ci btrfs_abort_transaction(trans, err); 16168c2ecf20Sopenharmony_ci goto out; 16178c2ecf20Sopenharmony_ci } 16188c2ecf20Sopenharmony_ci 16198c2ecf20Sopenharmony_ci ei = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_extent_item); 16208c2ecf20Sopenharmony_ci __run_delayed_extent_op(extent_op, leaf, ei); 16218c2ecf20Sopenharmony_ci 16228c2ecf20Sopenharmony_ci btrfs_mark_buffer_dirty(leaf); 16238c2ecf20Sopenharmony_ciout: 16248c2ecf20Sopenharmony_ci btrfs_free_path(path); 16258c2ecf20Sopenharmony_ci return err; 16268c2ecf20Sopenharmony_ci} 16278c2ecf20Sopenharmony_ci 16288c2ecf20Sopenharmony_cistatic int run_delayed_tree_ref(struct btrfs_trans_handle *trans, 16298c2ecf20Sopenharmony_ci struct btrfs_delayed_ref_node *node, 16308c2ecf20Sopenharmony_ci struct btrfs_delayed_extent_op *extent_op, 16318c2ecf20Sopenharmony_ci int insert_reserved) 16328c2ecf20Sopenharmony_ci{ 16338c2ecf20Sopenharmony_ci int ret = 0; 16348c2ecf20Sopenharmony_ci struct btrfs_delayed_tree_ref *ref; 16358c2ecf20Sopenharmony_ci u64 parent = 0; 16368c2ecf20Sopenharmony_ci u64 ref_root = 0; 16378c2ecf20Sopenharmony_ci 16388c2ecf20Sopenharmony_ci ref = btrfs_delayed_node_to_tree_ref(node); 16398c2ecf20Sopenharmony_ci trace_run_delayed_tree_ref(trans->fs_info, node, ref, node->action); 16408c2ecf20Sopenharmony_ci 16418c2ecf20Sopenharmony_ci if (node->type == BTRFS_SHARED_BLOCK_REF_KEY) 16428c2ecf20Sopenharmony_ci parent = ref->parent; 16438c2ecf20Sopenharmony_ci ref_root = ref->root; 16448c2ecf20Sopenharmony_ci 16458c2ecf20Sopenharmony_ci if (unlikely(node->ref_mod != 1)) { 16468c2ecf20Sopenharmony_ci btrfs_err(trans->fs_info, 16478c2ecf20Sopenharmony_ci "btree block %llu has %d references rather than 1: action %d ref_root %llu parent %llu", 16488c2ecf20Sopenharmony_ci node->bytenr, node->ref_mod, node->action, ref_root, 16498c2ecf20Sopenharmony_ci parent); 16508c2ecf20Sopenharmony_ci return -EUCLEAN; 16518c2ecf20Sopenharmony_ci } 16528c2ecf20Sopenharmony_ci if (node->action == BTRFS_ADD_DELAYED_REF && insert_reserved) { 16538c2ecf20Sopenharmony_ci BUG_ON(!extent_op || !extent_op->update_flags); 16548c2ecf20Sopenharmony_ci ret = alloc_reserved_tree_block(trans, node, extent_op); 16558c2ecf20Sopenharmony_ci } else if (node->action == BTRFS_ADD_DELAYED_REF) { 16568c2ecf20Sopenharmony_ci ret = __btrfs_inc_extent_ref(trans, node, parent, ref_root, 16578c2ecf20Sopenharmony_ci ref->level, 0, 1, extent_op); 16588c2ecf20Sopenharmony_ci } else if (node->action == BTRFS_DROP_DELAYED_REF) { 16598c2ecf20Sopenharmony_ci ret = __btrfs_free_extent(trans, node, parent, ref_root, 16608c2ecf20Sopenharmony_ci ref->level, 0, 1, extent_op); 16618c2ecf20Sopenharmony_ci } else { 16628c2ecf20Sopenharmony_ci BUG(); 16638c2ecf20Sopenharmony_ci } 16648c2ecf20Sopenharmony_ci return ret; 16658c2ecf20Sopenharmony_ci} 16668c2ecf20Sopenharmony_ci 16678c2ecf20Sopenharmony_ci/* helper function to actually process a single delayed ref entry */ 16688c2ecf20Sopenharmony_cistatic int run_one_delayed_ref(struct btrfs_trans_handle *trans, 16698c2ecf20Sopenharmony_ci struct btrfs_delayed_ref_node *node, 16708c2ecf20Sopenharmony_ci struct btrfs_delayed_extent_op *extent_op, 16718c2ecf20Sopenharmony_ci int insert_reserved) 16728c2ecf20Sopenharmony_ci{ 16738c2ecf20Sopenharmony_ci int ret = 0; 16748c2ecf20Sopenharmony_ci 16758c2ecf20Sopenharmony_ci if (TRANS_ABORTED(trans)) { 16768c2ecf20Sopenharmony_ci if (insert_reserved) 16778c2ecf20Sopenharmony_ci btrfs_pin_extent(trans, node->bytenr, node->num_bytes, 1); 16788c2ecf20Sopenharmony_ci return 0; 16798c2ecf20Sopenharmony_ci } 16808c2ecf20Sopenharmony_ci 16818c2ecf20Sopenharmony_ci if (node->type == BTRFS_TREE_BLOCK_REF_KEY || 16828c2ecf20Sopenharmony_ci node->type == BTRFS_SHARED_BLOCK_REF_KEY) 16838c2ecf20Sopenharmony_ci ret = run_delayed_tree_ref(trans, node, extent_op, 16848c2ecf20Sopenharmony_ci insert_reserved); 16858c2ecf20Sopenharmony_ci else if (node->type == BTRFS_EXTENT_DATA_REF_KEY || 16868c2ecf20Sopenharmony_ci node->type == BTRFS_SHARED_DATA_REF_KEY) 16878c2ecf20Sopenharmony_ci ret = run_delayed_data_ref(trans, node, extent_op, 16888c2ecf20Sopenharmony_ci insert_reserved); 16898c2ecf20Sopenharmony_ci else 16908c2ecf20Sopenharmony_ci BUG(); 16918c2ecf20Sopenharmony_ci if (ret && insert_reserved) 16928c2ecf20Sopenharmony_ci btrfs_pin_extent(trans, node->bytenr, node->num_bytes, 1); 16938c2ecf20Sopenharmony_ci if (ret < 0) 16948c2ecf20Sopenharmony_ci btrfs_err(trans->fs_info, 16958c2ecf20Sopenharmony_ci"failed to run delayed ref for logical %llu num_bytes %llu type %u action %u ref_mod %d: %d", 16968c2ecf20Sopenharmony_ci node->bytenr, node->num_bytes, node->type, 16978c2ecf20Sopenharmony_ci node->action, node->ref_mod, ret); 16988c2ecf20Sopenharmony_ci return ret; 16998c2ecf20Sopenharmony_ci} 17008c2ecf20Sopenharmony_ci 17018c2ecf20Sopenharmony_cistatic inline struct btrfs_delayed_ref_node * 17028c2ecf20Sopenharmony_ciselect_delayed_ref(struct btrfs_delayed_ref_head *head) 17038c2ecf20Sopenharmony_ci{ 17048c2ecf20Sopenharmony_ci struct btrfs_delayed_ref_node *ref; 17058c2ecf20Sopenharmony_ci 17068c2ecf20Sopenharmony_ci if (RB_EMPTY_ROOT(&head->ref_tree.rb_root)) 17078c2ecf20Sopenharmony_ci return NULL; 17088c2ecf20Sopenharmony_ci 17098c2ecf20Sopenharmony_ci /* 17108c2ecf20Sopenharmony_ci * Select a delayed ref of type BTRFS_ADD_DELAYED_REF first. 17118c2ecf20Sopenharmony_ci * This is to prevent a ref count from going down to zero, which deletes 17128c2ecf20Sopenharmony_ci * the extent item from the extent tree, when there still are references 17138c2ecf20Sopenharmony_ci * to add, which would fail because they would not find the extent item. 17148c2ecf20Sopenharmony_ci */ 17158c2ecf20Sopenharmony_ci if (!list_empty(&head->ref_add_list)) 17168c2ecf20Sopenharmony_ci return list_first_entry(&head->ref_add_list, 17178c2ecf20Sopenharmony_ci struct btrfs_delayed_ref_node, add_list); 17188c2ecf20Sopenharmony_ci 17198c2ecf20Sopenharmony_ci ref = rb_entry(rb_first_cached(&head->ref_tree), 17208c2ecf20Sopenharmony_ci struct btrfs_delayed_ref_node, ref_node); 17218c2ecf20Sopenharmony_ci ASSERT(list_empty(&ref->add_list)); 17228c2ecf20Sopenharmony_ci return ref; 17238c2ecf20Sopenharmony_ci} 17248c2ecf20Sopenharmony_ci 17258c2ecf20Sopenharmony_cistatic void unselect_delayed_ref_head(struct btrfs_delayed_ref_root *delayed_refs, 17268c2ecf20Sopenharmony_ci struct btrfs_delayed_ref_head *head) 17278c2ecf20Sopenharmony_ci{ 17288c2ecf20Sopenharmony_ci spin_lock(&delayed_refs->lock); 17298c2ecf20Sopenharmony_ci head->processing = 0; 17308c2ecf20Sopenharmony_ci delayed_refs->num_heads_ready++; 17318c2ecf20Sopenharmony_ci spin_unlock(&delayed_refs->lock); 17328c2ecf20Sopenharmony_ci btrfs_delayed_ref_unlock(head); 17338c2ecf20Sopenharmony_ci} 17348c2ecf20Sopenharmony_ci 17358c2ecf20Sopenharmony_cistatic struct btrfs_delayed_extent_op *cleanup_extent_op( 17368c2ecf20Sopenharmony_ci struct btrfs_delayed_ref_head *head) 17378c2ecf20Sopenharmony_ci{ 17388c2ecf20Sopenharmony_ci struct btrfs_delayed_extent_op *extent_op = head->extent_op; 17398c2ecf20Sopenharmony_ci 17408c2ecf20Sopenharmony_ci if (!extent_op) 17418c2ecf20Sopenharmony_ci return NULL; 17428c2ecf20Sopenharmony_ci 17438c2ecf20Sopenharmony_ci if (head->must_insert_reserved) { 17448c2ecf20Sopenharmony_ci head->extent_op = NULL; 17458c2ecf20Sopenharmony_ci btrfs_free_delayed_extent_op(extent_op); 17468c2ecf20Sopenharmony_ci return NULL; 17478c2ecf20Sopenharmony_ci } 17488c2ecf20Sopenharmony_ci return extent_op; 17498c2ecf20Sopenharmony_ci} 17508c2ecf20Sopenharmony_ci 17518c2ecf20Sopenharmony_cistatic int run_and_cleanup_extent_op(struct btrfs_trans_handle *trans, 17528c2ecf20Sopenharmony_ci struct btrfs_delayed_ref_head *head) 17538c2ecf20Sopenharmony_ci{ 17548c2ecf20Sopenharmony_ci struct btrfs_delayed_extent_op *extent_op; 17558c2ecf20Sopenharmony_ci int ret; 17568c2ecf20Sopenharmony_ci 17578c2ecf20Sopenharmony_ci extent_op = cleanup_extent_op(head); 17588c2ecf20Sopenharmony_ci if (!extent_op) 17598c2ecf20Sopenharmony_ci return 0; 17608c2ecf20Sopenharmony_ci head->extent_op = NULL; 17618c2ecf20Sopenharmony_ci spin_unlock(&head->lock); 17628c2ecf20Sopenharmony_ci ret = run_delayed_extent_op(trans, head, extent_op); 17638c2ecf20Sopenharmony_ci btrfs_free_delayed_extent_op(extent_op); 17648c2ecf20Sopenharmony_ci return ret ? ret : 1; 17658c2ecf20Sopenharmony_ci} 17668c2ecf20Sopenharmony_ci 17678c2ecf20Sopenharmony_civoid btrfs_cleanup_ref_head_accounting(struct btrfs_fs_info *fs_info, 17688c2ecf20Sopenharmony_ci struct btrfs_delayed_ref_root *delayed_refs, 17698c2ecf20Sopenharmony_ci struct btrfs_delayed_ref_head *head) 17708c2ecf20Sopenharmony_ci{ 17718c2ecf20Sopenharmony_ci int nr_items = 1; /* Dropping this ref head update. */ 17728c2ecf20Sopenharmony_ci 17738c2ecf20Sopenharmony_ci /* 17748c2ecf20Sopenharmony_ci * We had csum deletions accounted for in our delayed refs rsv, we need 17758c2ecf20Sopenharmony_ci * to drop the csum leaves for this update from our delayed_refs_rsv. 17768c2ecf20Sopenharmony_ci */ 17778c2ecf20Sopenharmony_ci if (head->total_ref_mod < 0 && head->is_data) { 17788c2ecf20Sopenharmony_ci spin_lock(&delayed_refs->lock); 17798c2ecf20Sopenharmony_ci delayed_refs->pending_csums -= head->num_bytes; 17808c2ecf20Sopenharmony_ci spin_unlock(&delayed_refs->lock); 17818c2ecf20Sopenharmony_ci nr_items += btrfs_csum_bytes_to_leaves(fs_info, head->num_bytes); 17828c2ecf20Sopenharmony_ci } 17838c2ecf20Sopenharmony_ci 17848c2ecf20Sopenharmony_ci /* 17858c2ecf20Sopenharmony_ci * We were dropping refs, or had a new ref and dropped it, and thus must 17868c2ecf20Sopenharmony_ci * adjust down our total_bytes_pinned, the space may or may not have 17878c2ecf20Sopenharmony_ci * been pinned and so is accounted for properly in the pinned space by 17888c2ecf20Sopenharmony_ci * now. 17898c2ecf20Sopenharmony_ci */ 17908c2ecf20Sopenharmony_ci if (head->total_ref_mod < 0 || 17918c2ecf20Sopenharmony_ci (head->total_ref_mod == 0 && head->must_insert_reserved)) { 17928c2ecf20Sopenharmony_ci u64 flags = btrfs_ref_head_to_space_flags(head); 17938c2ecf20Sopenharmony_ci 17948c2ecf20Sopenharmony_ci btrfs_mod_total_bytes_pinned(fs_info, flags, -head->num_bytes); 17958c2ecf20Sopenharmony_ci } 17968c2ecf20Sopenharmony_ci 17978c2ecf20Sopenharmony_ci btrfs_delayed_refs_rsv_release(fs_info, nr_items); 17988c2ecf20Sopenharmony_ci} 17998c2ecf20Sopenharmony_ci 18008c2ecf20Sopenharmony_cistatic int cleanup_ref_head(struct btrfs_trans_handle *trans, 18018c2ecf20Sopenharmony_ci struct btrfs_delayed_ref_head *head) 18028c2ecf20Sopenharmony_ci{ 18038c2ecf20Sopenharmony_ci 18048c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = trans->fs_info; 18058c2ecf20Sopenharmony_ci struct btrfs_delayed_ref_root *delayed_refs; 18068c2ecf20Sopenharmony_ci int ret; 18078c2ecf20Sopenharmony_ci 18088c2ecf20Sopenharmony_ci delayed_refs = &trans->transaction->delayed_refs; 18098c2ecf20Sopenharmony_ci 18108c2ecf20Sopenharmony_ci ret = run_and_cleanup_extent_op(trans, head); 18118c2ecf20Sopenharmony_ci if (ret < 0) { 18128c2ecf20Sopenharmony_ci unselect_delayed_ref_head(delayed_refs, head); 18138c2ecf20Sopenharmony_ci btrfs_debug(fs_info, "run_delayed_extent_op returned %d", ret); 18148c2ecf20Sopenharmony_ci return ret; 18158c2ecf20Sopenharmony_ci } else if (ret) { 18168c2ecf20Sopenharmony_ci return ret; 18178c2ecf20Sopenharmony_ci } 18188c2ecf20Sopenharmony_ci 18198c2ecf20Sopenharmony_ci /* 18208c2ecf20Sopenharmony_ci * Need to drop our head ref lock and re-acquire the delayed ref lock 18218c2ecf20Sopenharmony_ci * and then re-check to make sure nobody got added. 18228c2ecf20Sopenharmony_ci */ 18238c2ecf20Sopenharmony_ci spin_unlock(&head->lock); 18248c2ecf20Sopenharmony_ci spin_lock(&delayed_refs->lock); 18258c2ecf20Sopenharmony_ci spin_lock(&head->lock); 18268c2ecf20Sopenharmony_ci if (!RB_EMPTY_ROOT(&head->ref_tree.rb_root) || head->extent_op) { 18278c2ecf20Sopenharmony_ci spin_unlock(&head->lock); 18288c2ecf20Sopenharmony_ci spin_unlock(&delayed_refs->lock); 18298c2ecf20Sopenharmony_ci return 1; 18308c2ecf20Sopenharmony_ci } 18318c2ecf20Sopenharmony_ci btrfs_delete_ref_head(delayed_refs, head); 18328c2ecf20Sopenharmony_ci spin_unlock(&head->lock); 18338c2ecf20Sopenharmony_ci spin_unlock(&delayed_refs->lock); 18348c2ecf20Sopenharmony_ci 18358c2ecf20Sopenharmony_ci if (head->must_insert_reserved) { 18368c2ecf20Sopenharmony_ci btrfs_pin_extent(trans, head->bytenr, head->num_bytes, 1); 18378c2ecf20Sopenharmony_ci if (head->is_data) { 18388c2ecf20Sopenharmony_ci ret = btrfs_del_csums(trans, fs_info->csum_root, 18398c2ecf20Sopenharmony_ci head->bytenr, head->num_bytes); 18408c2ecf20Sopenharmony_ci } 18418c2ecf20Sopenharmony_ci } 18428c2ecf20Sopenharmony_ci 18438c2ecf20Sopenharmony_ci btrfs_cleanup_ref_head_accounting(fs_info, delayed_refs, head); 18448c2ecf20Sopenharmony_ci 18458c2ecf20Sopenharmony_ci trace_run_delayed_ref_head(fs_info, head, 0); 18468c2ecf20Sopenharmony_ci btrfs_delayed_ref_unlock(head); 18478c2ecf20Sopenharmony_ci btrfs_put_delayed_ref_head(head); 18488c2ecf20Sopenharmony_ci return ret; 18498c2ecf20Sopenharmony_ci} 18508c2ecf20Sopenharmony_ci 18518c2ecf20Sopenharmony_cistatic struct btrfs_delayed_ref_head *btrfs_obtain_ref_head( 18528c2ecf20Sopenharmony_ci struct btrfs_trans_handle *trans) 18538c2ecf20Sopenharmony_ci{ 18548c2ecf20Sopenharmony_ci struct btrfs_delayed_ref_root *delayed_refs = 18558c2ecf20Sopenharmony_ci &trans->transaction->delayed_refs; 18568c2ecf20Sopenharmony_ci struct btrfs_delayed_ref_head *head = NULL; 18578c2ecf20Sopenharmony_ci int ret; 18588c2ecf20Sopenharmony_ci 18598c2ecf20Sopenharmony_ci spin_lock(&delayed_refs->lock); 18608c2ecf20Sopenharmony_ci head = btrfs_select_ref_head(delayed_refs); 18618c2ecf20Sopenharmony_ci if (!head) { 18628c2ecf20Sopenharmony_ci spin_unlock(&delayed_refs->lock); 18638c2ecf20Sopenharmony_ci return head; 18648c2ecf20Sopenharmony_ci } 18658c2ecf20Sopenharmony_ci 18668c2ecf20Sopenharmony_ci /* 18678c2ecf20Sopenharmony_ci * Grab the lock that says we are going to process all the refs for 18688c2ecf20Sopenharmony_ci * this head 18698c2ecf20Sopenharmony_ci */ 18708c2ecf20Sopenharmony_ci ret = btrfs_delayed_ref_lock(delayed_refs, head); 18718c2ecf20Sopenharmony_ci spin_unlock(&delayed_refs->lock); 18728c2ecf20Sopenharmony_ci 18738c2ecf20Sopenharmony_ci /* 18748c2ecf20Sopenharmony_ci * We may have dropped the spin lock to get the head mutex lock, and 18758c2ecf20Sopenharmony_ci * that might have given someone else time to free the head. If that's 18768c2ecf20Sopenharmony_ci * true, it has been removed from our list and we can move on. 18778c2ecf20Sopenharmony_ci */ 18788c2ecf20Sopenharmony_ci if (ret == -EAGAIN) 18798c2ecf20Sopenharmony_ci head = ERR_PTR(-EAGAIN); 18808c2ecf20Sopenharmony_ci 18818c2ecf20Sopenharmony_ci return head; 18828c2ecf20Sopenharmony_ci} 18838c2ecf20Sopenharmony_ci 18848c2ecf20Sopenharmony_cistatic int btrfs_run_delayed_refs_for_head(struct btrfs_trans_handle *trans, 18858c2ecf20Sopenharmony_ci struct btrfs_delayed_ref_head *locked_ref, 18868c2ecf20Sopenharmony_ci unsigned long *run_refs) 18878c2ecf20Sopenharmony_ci{ 18888c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = trans->fs_info; 18898c2ecf20Sopenharmony_ci struct btrfs_delayed_ref_root *delayed_refs; 18908c2ecf20Sopenharmony_ci struct btrfs_delayed_extent_op *extent_op; 18918c2ecf20Sopenharmony_ci struct btrfs_delayed_ref_node *ref; 18928c2ecf20Sopenharmony_ci int must_insert_reserved = 0; 18938c2ecf20Sopenharmony_ci int ret; 18948c2ecf20Sopenharmony_ci 18958c2ecf20Sopenharmony_ci delayed_refs = &trans->transaction->delayed_refs; 18968c2ecf20Sopenharmony_ci 18978c2ecf20Sopenharmony_ci lockdep_assert_held(&locked_ref->mutex); 18988c2ecf20Sopenharmony_ci lockdep_assert_held(&locked_ref->lock); 18998c2ecf20Sopenharmony_ci 19008c2ecf20Sopenharmony_ci while ((ref = select_delayed_ref(locked_ref))) { 19018c2ecf20Sopenharmony_ci if (ref->seq && 19028c2ecf20Sopenharmony_ci btrfs_check_delayed_seq(fs_info, ref->seq)) { 19038c2ecf20Sopenharmony_ci spin_unlock(&locked_ref->lock); 19048c2ecf20Sopenharmony_ci unselect_delayed_ref_head(delayed_refs, locked_ref); 19058c2ecf20Sopenharmony_ci return -EAGAIN; 19068c2ecf20Sopenharmony_ci } 19078c2ecf20Sopenharmony_ci 19088c2ecf20Sopenharmony_ci (*run_refs)++; 19098c2ecf20Sopenharmony_ci ref->in_tree = 0; 19108c2ecf20Sopenharmony_ci rb_erase_cached(&ref->ref_node, &locked_ref->ref_tree); 19118c2ecf20Sopenharmony_ci RB_CLEAR_NODE(&ref->ref_node); 19128c2ecf20Sopenharmony_ci if (!list_empty(&ref->add_list)) 19138c2ecf20Sopenharmony_ci list_del(&ref->add_list); 19148c2ecf20Sopenharmony_ci /* 19158c2ecf20Sopenharmony_ci * When we play the delayed ref, also correct the ref_mod on 19168c2ecf20Sopenharmony_ci * head 19178c2ecf20Sopenharmony_ci */ 19188c2ecf20Sopenharmony_ci switch (ref->action) { 19198c2ecf20Sopenharmony_ci case BTRFS_ADD_DELAYED_REF: 19208c2ecf20Sopenharmony_ci case BTRFS_ADD_DELAYED_EXTENT: 19218c2ecf20Sopenharmony_ci locked_ref->ref_mod -= ref->ref_mod; 19228c2ecf20Sopenharmony_ci break; 19238c2ecf20Sopenharmony_ci case BTRFS_DROP_DELAYED_REF: 19248c2ecf20Sopenharmony_ci locked_ref->ref_mod += ref->ref_mod; 19258c2ecf20Sopenharmony_ci break; 19268c2ecf20Sopenharmony_ci default: 19278c2ecf20Sopenharmony_ci WARN_ON(1); 19288c2ecf20Sopenharmony_ci } 19298c2ecf20Sopenharmony_ci atomic_dec(&delayed_refs->num_entries); 19308c2ecf20Sopenharmony_ci 19318c2ecf20Sopenharmony_ci /* 19328c2ecf20Sopenharmony_ci * Record the must_insert_reserved flag before we drop the 19338c2ecf20Sopenharmony_ci * spin lock. 19348c2ecf20Sopenharmony_ci */ 19358c2ecf20Sopenharmony_ci must_insert_reserved = locked_ref->must_insert_reserved; 19368c2ecf20Sopenharmony_ci locked_ref->must_insert_reserved = 0; 19378c2ecf20Sopenharmony_ci 19388c2ecf20Sopenharmony_ci extent_op = locked_ref->extent_op; 19398c2ecf20Sopenharmony_ci locked_ref->extent_op = NULL; 19408c2ecf20Sopenharmony_ci spin_unlock(&locked_ref->lock); 19418c2ecf20Sopenharmony_ci 19428c2ecf20Sopenharmony_ci ret = run_one_delayed_ref(trans, ref, extent_op, 19438c2ecf20Sopenharmony_ci must_insert_reserved); 19448c2ecf20Sopenharmony_ci 19458c2ecf20Sopenharmony_ci btrfs_free_delayed_extent_op(extent_op); 19468c2ecf20Sopenharmony_ci if (ret) { 19478c2ecf20Sopenharmony_ci unselect_delayed_ref_head(delayed_refs, locked_ref); 19488c2ecf20Sopenharmony_ci btrfs_put_delayed_ref(ref); 19498c2ecf20Sopenharmony_ci return ret; 19508c2ecf20Sopenharmony_ci } 19518c2ecf20Sopenharmony_ci 19528c2ecf20Sopenharmony_ci btrfs_put_delayed_ref(ref); 19538c2ecf20Sopenharmony_ci cond_resched(); 19548c2ecf20Sopenharmony_ci 19558c2ecf20Sopenharmony_ci spin_lock(&locked_ref->lock); 19568c2ecf20Sopenharmony_ci btrfs_merge_delayed_refs(trans, delayed_refs, locked_ref); 19578c2ecf20Sopenharmony_ci } 19588c2ecf20Sopenharmony_ci 19598c2ecf20Sopenharmony_ci return 0; 19608c2ecf20Sopenharmony_ci} 19618c2ecf20Sopenharmony_ci 19628c2ecf20Sopenharmony_ci/* 19638c2ecf20Sopenharmony_ci * Returns 0 on success or if called with an already aborted transaction. 19648c2ecf20Sopenharmony_ci * Returns -ENOMEM or -EIO on failure and will abort the transaction. 19658c2ecf20Sopenharmony_ci */ 19668c2ecf20Sopenharmony_cistatic noinline int __btrfs_run_delayed_refs(struct btrfs_trans_handle *trans, 19678c2ecf20Sopenharmony_ci unsigned long nr) 19688c2ecf20Sopenharmony_ci{ 19698c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = trans->fs_info; 19708c2ecf20Sopenharmony_ci struct btrfs_delayed_ref_root *delayed_refs; 19718c2ecf20Sopenharmony_ci struct btrfs_delayed_ref_head *locked_ref = NULL; 19728c2ecf20Sopenharmony_ci ktime_t start = ktime_get(); 19738c2ecf20Sopenharmony_ci int ret; 19748c2ecf20Sopenharmony_ci unsigned long count = 0; 19758c2ecf20Sopenharmony_ci unsigned long actual_count = 0; 19768c2ecf20Sopenharmony_ci 19778c2ecf20Sopenharmony_ci delayed_refs = &trans->transaction->delayed_refs; 19788c2ecf20Sopenharmony_ci do { 19798c2ecf20Sopenharmony_ci if (!locked_ref) { 19808c2ecf20Sopenharmony_ci locked_ref = btrfs_obtain_ref_head(trans); 19818c2ecf20Sopenharmony_ci if (IS_ERR_OR_NULL(locked_ref)) { 19828c2ecf20Sopenharmony_ci if (PTR_ERR(locked_ref) == -EAGAIN) { 19838c2ecf20Sopenharmony_ci continue; 19848c2ecf20Sopenharmony_ci } else { 19858c2ecf20Sopenharmony_ci break; 19868c2ecf20Sopenharmony_ci } 19878c2ecf20Sopenharmony_ci } 19888c2ecf20Sopenharmony_ci count++; 19898c2ecf20Sopenharmony_ci } 19908c2ecf20Sopenharmony_ci /* 19918c2ecf20Sopenharmony_ci * We need to try and merge add/drops of the same ref since we 19928c2ecf20Sopenharmony_ci * can run into issues with relocate dropping the implicit ref 19938c2ecf20Sopenharmony_ci * and then it being added back again before the drop can 19948c2ecf20Sopenharmony_ci * finish. If we merged anything we need to re-loop so we can 19958c2ecf20Sopenharmony_ci * get a good ref. 19968c2ecf20Sopenharmony_ci * Or we can get node references of the same type that weren't 19978c2ecf20Sopenharmony_ci * merged when created due to bumps in the tree mod seq, and 19988c2ecf20Sopenharmony_ci * we need to merge them to prevent adding an inline extent 19998c2ecf20Sopenharmony_ci * backref before dropping it (triggering a BUG_ON at 20008c2ecf20Sopenharmony_ci * insert_inline_extent_backref()). 20018c2ecf20Sopenharmony_ci */ 20028c2ecf20Sopenharmony_ci spin_lock(&locked_ref->lock); 20038c2ecf20Sopenharmony_ci btrfs_merge_delayed_refs(trans, delayed_refs, locked_ref); 20048c2ecf20Sopenharmony_ci 20058c2ecf20Sopenharmony_ci ret = btrfs_run_delayed_refs_for_head(trans, locked_ref, 20068c2ecf20Sopenharmony_ci &actual_count); 20078c2ecf20Sopenharmony_ci if (ret < 0 && ret != -EAGAIN) { 20088c2ecf20Sopenharmony_ci /* 20098c2ecf20Sopenharmony_ci * Error, btrfs_run_delayed_refs_for_head already 20108c2ecf20Sopenharmony_ci * unlocked everything so just bail out 20118c2ecf20Sopenharmony_ci */ 20128c2ecf20Sopenharmony_ci return ret; 20138c2ecf20Sopenharmony_ci } else if (!ret) { 20148c2ecf20Sopenharmony_ci /* 20158c2ecf20Sopenharmony_ci * Success, perform the usual cleanup of a processed 20168c2ecf20Sopenharmony_ci * head 20178c2ecf20Sopenharmony_ci */ 20188c2ecf20Sopenharmony_ci ret = cleanup_ref_head(trans, locked_ref); 20198c2ecf20Sopenharmony_ci if (ret > 0 ) { 20208c2ecf20Sopenharmony_ci /* We dropped our lock, we need to loop. */ 20218c2ecf20Sopenharmony_ci ret = 0; 20228c2ecf20Sopenharmony_ci continue; 20238c2ecf20Sopenharmony_ci } else if (ret) { 20248c2ecf20Sopenharmony_ci return ret; 20258c2ecf20Sopenharmony_ci } 20268c2ecf20Sopenharmony_ci } 20278c2ecf20Sopenharmony_ci 20288c2ecf20Sopenharmony_ci /* 20298c2ecf20Sopenharmony_ci * Either success case or btrfs_run_delayed_refs_for_head 20308c2ecf20Sopenharmony_ci * returned -EAGAIN, meaning we need to select another head 20318c2ecf20Sopenharmony_ci */ 20328c2ecf20Sopenharmony_ci 20338c2ecf20Sopenharmony_ci locked_ref = NULL; 20348c2ecf20Sopenharmony_ci cond_resched(); 20358c2ecf20Sopenharmony_ci } while ((nr != -1 && count < nr) || locked_ref); 20368c2ecf20Sopenharmony_ci 20378c2ecf20Sopenharmony_ci /* 20388c2ecf20Sopenharmony_ci * We don't want to include ref heads since we can have empty ref heads 20398c2ecf20Sopenharmony_ci * and those will drastically skew our runtime down since we just do 20408c2ecf20Sopenharmony_ci * accounting, no actual extent tree updates. 20418c2ecf20Sopenharmony_ci */ 20428c2ecf20Sopenharmony_ci if (actual_count > 0) { 20438c2ecf20Sopenharmony_ci u64 runtime = ktime_to_ns(ktime_sub(ktime_get(), start)); 20448c2ecf20Sopenharmony_ci u64 avg; 20458c2ecf20Sopenharmony_ci 20468c2ecf20Sopenharmony_ci /* 20478c2ecf20Sopenharmony_ci * We weigh the current average higher than our current runtime 20488c2ecf20Sopenharmony_ci * to avoid large swings in the average. 20498c2ecf20Sopenharmony_ci */ 20508c2ecf20Sopenharmony_ci spin_lock(&delayed_refs->lock); 20518c2ecf20Sopenharmony_ci avg = fs_info->avg_delayed_ref_runtime * 3 + runtime; 20528c2ecf20Sopenharmony_ci fs_info->avg_delayed_ref_runtime = avg >> 2; /* div by 4 */ 20538c2ecf20Sopenharmony_ci spin_unlock(&delayed_refs->lock); 20548c2ecf20Sopenharmony_ci } 20558c2ecf20Sopenharmony_ci return 0; 20568c2ecf20Sopenharmony_ci} 20578c2ecf20Sopenharmony_ci 20588c2ecf20Sopenharmony_ci#ifdef SCRAMBLE_DELAYED_REFS 20598c2ecf20Sopenharmony_ci/* 20608c2ecf20Sopenharmony_ci * Normally delayed refs get processed in ascending bytenr order. This 20618c2ecf20Sopenharmony_ci * correlates in most cases to the order added. To expose dependencies on this 20628c2ecf20Sopenharmony_ci * order, we start to process the tree in the middle instead of the beginning 20638c2ecf20Sopenharmony_ci */ 20648c2ecf20Sopenharmony_cistatic u64 find_middle(struct rb_root *root) 20658c2ecf20Sopenharmony_ci{ 20668c2ecf20Sopenharmony_ci struct rb_node *n = root->rb_node; 20678c2ecf20Sopenharmony_ci struct btrfs_delayed_ref_node *entry; 20688c2ecf20Sopenharmony_ci int alt = 1; 20698c2ecf20Sopenharmony_ci u64 middle; 20708c2ecf20Sopenharmony_ci u64 first = 0, last = 0; 20718c2ecf20Sopenharmony_ci 20728c2ecf20Sopenharmony_ci n = rb_first(root); 20738c2ecf20Sopenharmony_ci if (n) { 20748c2ecf20Sopenharmony_ci entry = rb_entry(n, struct btrfs_delayed_ref_node, rb_node); 20758c2ecf20Sopenharmony_ci first = entry->bytenr; 20768c2ecf20Sopenharmony_ci } 20778c2ecf20Sopenharmony_ci n = rb_last(root); 20788c2ecf20Sopenharmony_ci if (n) { 20798c2ecf20Sopenharmony_ci entry = rb_entry(n, struct btrfs_delayed_ref_node, rb_node); 20808c2ecf20Sopenharmony_ci last = entry->bytenr; 20818c2ecf20Sopenharmony_ci } 20828c2ecf20Sopenharmony_ci n = root->rb_node; 20838c2ecf20Sopenharmony_ci 20848c2ecf20Sopenharmony_ci while (n) { 20858c2ecf20Sopenharmony_ci entry = rb_entry(n, struct btrfs_delayed_ref_node, rb_node); 20868c2ecf20Sopenharmony_ci WARN_ON(!entry->in_tree); 20878c2ecf20Sopenharmony_ci 20888c2ecf20Sopenharmony_ci middle = entry->bytenr; 20898c2ecf20Sopenharmony_ci 20908c2ecf20Sopenharmony_ci if (alt) 20918c2ecf20Sopenharmony_ci n = n->rb_left; 20928c2ecf20Sopenharmony_ci else 20938c2ecf20Sopenharmony_ci n = n->rb_right; 20948c2ecf20Sopenharmony_ci 20958c2ecf20Sopenharmony_ci alt = 1 - alt; 20968c2ecf20Sopenharmony_ci } 20978c2ecf20Sopenharmony_ci return middle; 20988c2ecf20Sopenharmony_ci} 20998c2ecf20Sopenharmony_ci#endif 21008c2ecf20Sopenharmony_ci 21018c2ecf20Sopenharmony_ci/* 21028c2ecf20Sopenharmony_ci * Takes the number of bytes to be csumm'ed and figures out how many leaves it 21038c2ecf20Sopenharmony_ci * would require to store the csums for that many bytes. 21048c2ecf20Sopenharmony_ci */ 21058c2ecf20Sopenharmony_ciu64 btrfs_csum_bytes_to_leaves(struct btrfs_fs_info *fs_info, u64 csum_bytes) 21068c2ecf20Sopenharmony_ci{ 21078c2ecf20Sopenharmony_ci u64 csum_size; 21088c2ecf20Sopenharmony_ci u64 num_csums_per_leaf; 21098c2ecf20Sopenharmony_ci u64 num_csums; 21108c2ecf20Sopenharmony_ci 21118c2ecf20Sopenharmony_ci csum_size = BTRFS_MAX_ITEM_SIZE(fs_info); 21128c2ecf20Sopenharmony_ci num_csums_per_leaf = div64_u64(csum_size, 21138c2ecf20Sopenharmony_ci (u64)btrfs_super_csum_size(fs_info->super_copy)); 21148c2ecf20Sopenharmony_ci num_csums = div64_u64(csum_bytes, fs_info->sectorsize); 21158c2ecf20Sopenharmony_ci num_csums += num_csums_per_leaf - 1; 21168c2ecf20Sopenharmony_ci num_csums = div64_u64(num_csums, num_csums_per_leaf); 21178c2ecf20Sopenharmony_ci return num_csums; 21188c2ecf20Sopenharmony_ci} 21198c2ecf20Sopenharmony_ci 21208c2ecf20Sopenharmony_ci/* 21218c2ecf20Sopenharmony_ci * this starts processing the delayed reference count updates and 21228c2ecf20Sopenharmony_ci * extent insertions we have queued up so far. count can be 21238c2ecf20Sopenharmony_ci * 0, which means to process everything in the tree at the start 21248c2ecf20Sopenharmony_ci * of the run (but not newly added entries), or it can be some target 21258c2ecf20Sopenharmony_ci * number you'd like to process. 21268c2ecf20Sopenharmony_ci * 21278c2ecf20Sopenharmony_ci * Returns 0 on success or if called with an aborted transaction 21288c2ecf20Sopenharmony_ci * Returns <0 on error and aborts the transaction 21298c2ecf20Sopenharmony_ci */ 21308c2ecf20Sopenharmony_ciint btrfs_run_delayed_refs(struct btrfs_trans_handle *trans, 21318c2ecf20Sopenharmony_ci unsigned long count) 21328c2ecf20Sopenharmony_ci{ 21338c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = trans->fs_info; 21348c2ecf20Sopenharmony_ci struct rb_node *node; 21358c2ecf20Sopenharmony_ci struct btrfs_delayed_ref_root *delayed_refs; 21368c2ecf20Sopenharmony_ci struct btrfs_delayed_ref_head *head; 21378c2ecf20Sopenharmony_ci int ret; 21388c2ecf20Sopenharmony_ci int run_all = count == (unsigned long)-1; 21398c2ecf20Sopenharmony_ci 21408c2ecf20Sopenharmony_ci /* We'll clean this up in btrfs_cleanup_transaction */ 21418c2ecf20Sopenharmony_ci if (TRANS_ABORTED(trans)) 21428c2ecf20Sopenharmony_ci return 0; 21438c2ecf20Sopenharmony_ci 21448c2ecf20Sopenharmony_ci if (test_bit(BTRFS_FS_CREATING_FREE_SPACE_TREE, &fs_info->flags)) 21458c2ecf20Sopenharmony_ci return 0; 21468c2ecf20Sopenharmony_ci 21478c2ecf20Sopenharmony_ci delayed_refs = &trans->transaction->delayed_refs; 21488c2ecf20Sopenharmony_ci if (count == 0) 21498c2ecf20Sopenharmony_ci count = atomic_read(&delayed_refs->num_entries) * 2; 21508c2ecf20Sopenharmony_ci 21518c2ecf20Sopenharmony_ciagain: 21528c2ecf20Sopenharmony_ci#ifdef SCRAMBLE_DELAYED_REFS 21538c2ecf20Sopenharmony_ci delayed_refs->run_delayed_start = find_middle(&delayed_refs->root); 21548c2ecf20Sopenharmony_ci#endif 21558c2ecf20Sopenharmony_ci ret = __btrfs_run_delayed_refs(trans, count); 21568c2ecf20Sopenharmony_ci if (ret < 0) { 21578c2ecf20Sopenharmony_ci btrfs_abort_transaction(trans, ret); 21588c2ecf20Sopenharmony_ci return ret; 21598c2ecf20Sopenharmony_ci } 21608c2ecf20Sopenharmony_ci 21618c2ecf20Sopenharmony_ci if (run_all) { 21628c2ecf20Sopenharmony_ci btrfs_create_pending_block_groups(trans); 21638c2ecf20Sopenharmony_ci 21648c2ecf20Sopenharmony_ci spin_lock(&delayed_refs->lock); 21658c2ecf20Sopenharmony_ci node = rb_first_cached(&delayed_refs->href_root); 21668c2ecf20Sopenharmony_ci if (!node) { 21678c2ecf20Sopenharmony_ci spin_unlock(&delayed_refs->lock); 21688c2ecf20Sopenharmony_ci goto out; 21698c2ecf20Sopenharmony_ci } 21708c2ecf20Sopenharmony_ci head = rb_entry(node, struct btrfs_delayed_ref_head, 21718c2ecf20Sopenharmony_ci href_node); 21728c2ecf20Sopenharmony_ci refcount_inc(&head->refs); 21738c2ecf20Sopenharmony_ci spin_unlock(&delayed_refs->lock); 21748c2ecf20Sopenharmony_ci 21758c2ecf20Sopenharmony_ci /* Mutex was contended, block until it's released and retry. */ 21768c2ecf20Sopenharmony_ci mutex_lock(&head->mutex); 21778c2ecf20Sopenharmony_ci mutex_unlock(&head->mutex); 21788c2ecf20Sopenharmony_ci 21798c2ecf20Sopenharmony_ci btrfs_put_delayed_ref_head(head); 21808c2ecf20Sopenharmony_ci cond_resched(); 21818c2ecf20Sopenharmony_ci goto again; 21828c2ecf20Sopenharmony_ci } 21838c2ecf20Sopenharmony_ciout: 21848c2ecf20Sopenharmony_ci return 0; 21858c2ecf20Sopenharmony_ci} 21868c2ecf20Sopenharmony_ci 21878c2ecf20Sopenharmony_ciint btrfs_set_disk_extent_flags(struct btrfs_trans_handle *trans, 21888c2ecf20Sopenharmony_ci struct extent_buffer *eb, u64 flags, 21898c2ecf20Sopenharmony_ci int level, int is_data) 21908c2ecf20Sopenharmony_ci{ 21918c2ecf20Sopenharmony_ci struct btrfs_delayed_extent_op *extent_op; 21928c2ecf20Sopenharmony_ci int ret; 21938c2ecf20Sopenharmony_ci 21948c2ecf20Sopenharmony_ci extent_op = btrfs_alloc_delayed_extent_op(); 21958c2ecf20Sopenharmony_ci if (!extent_op) 21968c2ecf20Sopenharmony_ci return -ENOMEM; 21978c2ecf20Sopenharmony_ci 21988c2ecf20Sopenharmony_ci extent_op->flags_to_set = flags; 21998c2ecf20Sopenharmony_ci extent_op->update_flags = true; 22008c2ecf20Sopenharmony_ci extent_op->update_key = false; 22018c2ecf20Sopenharmony_ci extent_op->is_data = is_data ? true : false; 22028c2ecf20Sopenharmony_ci extent_op->level = level; 22038c2ecf20Sopenharmony_ci 22048c2ecf20Sopenharmony_ci ret = btrfs_add_delayed_extent_op(trans, eb->start, eb->len, extent_op); 22058c2ecf20Sopenharmony_ci if (ret) 22068c2ecf20Sopenharmony_ci btrfs_free_delayed_extent_op(extent_op); 22078c2ecf20Sopenharmony_ci return ret; 22088c2ecf20Sopenharmony_ci} 22098c2ecf20Sopenharmony_ci 22108c2ecf20Sopenharmony_cistatic noinline int check_delayed_ref(struct btrfs_root *root, 22118c2ecf20Sopenharmony_ci struct btrfs_path *path, 22128c2ecf20Sopenharmony_ci u64 objectid, u64 offset, u64 bytenr) 22138c2ecf20Sopenharmony_ci{ 22148c2ecf20Sopenharmony_ci struct btrfs_delayed_ref_head *head; 22158c2ecf20Sopenharmony_ci struct btrfs_delayed_ref_node *ref; 22168c2ecf20Sopenharmony_ci struct btrfs_delayed_data_ref *data_ref; 22178c2ecf20Sopenharmony_ci struct btrfs_delayed_ref_root *delayed_refs; 22188c2ecf20Sopenharmony_ci struct btrfs_transaction *cur_trans; 22198c2ecf20Sopenharmony_ci struct rb_node *node; 22208c2ecf20Sopenharmony_ci int ret = 0; 22218c2ecf20Sopenharmony_ci 22228c2ecf20Sopenharmony_ci spin_lock(&root->fs_info->trans_lock); 22238c2ecf20Sopenharmony_ci cur_trans = root->fs_info->running_transaction; 22248c2ecf20Sopenharmony_ci if (cur_trans) 22258c2ecf20Sopenharmony_ci refcount_inc(&cur_trans->use_count); 22268c2ecf20Sopenharmony_ci spin_unlock(&root->fs_info->trans_lock); 22278c2ecf20Sopenharmony_ci if (!cur_trans) 22288c2ecf20Sopenharmony_ci return 0; 22298c2ecf20Sopenharmony_ci 22308c2ecf20Sopenharmony_ci delayed_refs = &cur_trans->delayed_refs; 22318c2ecf20Sopenharmony_ci spin_lock(&delayed_refs->lock); 22328c2ecf20Sopenharmony_ci head = btrfs_find_delayed_ref_head(delayed_refs, bytenr); 22338c2ecf20Sopenharmony_ci if (!head) { 22348c2ecf20Sopenharmony_ci spin_unlock(&delayed_refs->lock); 22358c2ecf20Sopenharmony_ci btrfs_put_transaction(cur_trans); 22368c2ecf20Sopenharmony_ci return 0; 22378c2ecf20Sopenharmony_ci } 22388c2ecf20Sopenharmony_ci 22398c2ecf20Sopenharmony_ci if (!mutex_trylock(&head->mutex)) { 22408c2ecf20Sopenharmony_ci refcount_inc(&head->refs); 22418c2ecf20Sopenharmony_ci spin_unlock(&delayed_refs->lock); 22428c2ecf20Sopenharmony_ci 22438c2ecf20Sopenharmony_ci btrfs_release_path(path); 22448c2ecf20Sopenharmony_ci 22458c2ecf20Sopenharmony_ci /* 22468c2ecf20Sopenharmony_ci * Mutex was contended, block until it's released and let 22478c2ecf20Sopenharmony_ci * caller try again 22488c2ecf20Sopenharmony_ci */ 22498c2ecf20Sopenharmony_ci mutex_lock(&head->mutex); 22508c2ecf20Sopenharmony_ci mutex_unlock(&head->mutex); 22518c2ecf20Sopenharmony_ci btrfs_put_delayed_ref_head(head); 22528c2ecf20Sopenharmony_ci btrfs_put_transaction(cur_trans); 22538c2ecf20Sopenharmony_ci return -EAGAIN; 22548c2ecf20Sopenharmony_ci } 22558c2ecf20Sopenharmony_ci spin_unlock(&delayed_refs->lock); 22568c2ecf20Sopenharmony_ci 22578c2ecf20Sopenharmony_ci spin_lock(&head->lock); 22588c2ecf20Sopenharmony_ci /* 22598c2ecf20Sopenharmony_ci * XXX: We should replace this with a proper search function in the 22608c2ecf20Sopenharmony_ci * future. 22618c2ecf20Sopenharmony_ci */ 22628c2ecf20Sopenharmony_ci for (node = rb_first_cached(&head->ref_tree); node; 22638c2ecf20Sopenharmony_ci node = rb_next(node)) { 22648c2ecf20Sopenharmony_ci ref = rb_entry(node, struct btrfs_delayed_ref_node, ref_node); 22658c2ecf20Sopenharmony_ci /* If it's a shared ref we know a cross reference exists */ 22668c2ecf20Sopenharmony_ci if (ref->type != BTRFS_EXTENT_DATA_REF_KEY) { 22678c2ecf20Sopenharmony_ci ret = 1; 22688c2ecf20Sopenharmony_ci break; 22698c2ecf20Sopenharmony_ci } 22708c2ecf20Sopenharmony_ci 22718c2ecf20Sopenharmony_ci data_ref = btrfs_delayed_node_to_data_ref(ref); 22728c2ecf20Sopenharmony_ci 22738c2ecf20Sopenharmony_ci /* 22748c2ecf20Sopenharmony_ci * If our ref doesn't match the one we're currently looking at 22758c2ecf20Sopenharmony_ci * then we have a cross reference. 22768c2ecf20Sopenharmony_ci */ 22778c2ecf20Sopenharmony_ci if (data_ref->root != root->root_key.objectid || 22788c2ecf20Sopenharmony_ci data_ref->objectid != objectid || 22798c2ecf20Sopenharmony_ci data_ref->offset != offset) { 22808c2ecf20Sopenharmony_ci ret = 1; 22818c2ecf20Sopenharmony_ci break; 22828c2ecf20Sopenharmony_ci } 22838c2ecf20Sopenharmony_ci } 22848c2ecf20Sopenharmony_ci spin_unlock(&head->lock); 22858c2ecf20Sopenharmony_ci mutex_unlock(&head->mutex); 22868c2ecf20Sopenharmony_ci btrfs_put_transaction(cur_trans); 22878c2ecf20Sopenharmony_ci return ret; 22888c2ecf20Sopenharmony_ci} 22898c2ecf20Sopenharmony_ci 22908c2ecf20Sopenharmony_cistatic noinline int check_committed_ref(struct btrfs_root *root, 22918c2ecf20Sopenharmony_ci struct btrfs_path *path, 22928c2ecf20Sopenharmony_ci u64 objectid, u64 offset, u64 bytenr, 22938c2ecf20Sopenharmony_ci bool strict) 22948c2ecf20Sopenharmony_ci{ 22958c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = root->fs_info; 22968c2ecf20Sopenharmony_ci struct btrfs_root *extent_root = fs_info->extent_root; 22978c2ecf20Sopenharmony_ci struct extent_buffer *leaf; 22988c2ecf20Sopenharmony_ci struct btrfs_extent_data_ref *ref; 22998c2ecf20Sopenharmony_ci struct btrfs_extent_inline_ref *iref; 23008c2ecf20Sopenharmony_ci struct btrfs_extent_item *ei; 23018c2ecf20Sopenharmony_ci struct btrfs_key key; 23028c2ecf20Sopenharmony_ci u32 item_size; 23038c2ecf20Sopenharmony_ci int type; 23048c2ecf20Sopenharmony_ci int ret; 23058c2ecf20Sopenharmony_ci 23068c2ecf20Sopenharmony_ci key.objectid = bytenr; 23078c2ecf20Sopenharmony_ci key.offset = (u64)-1; 23088c2ecf20Sopenharmony_ci key.type = BTRFS_EXTENT_ITEM_KEY; 23098c2ecf20Sopenharmony_ci 23108c2ecf20Sopenharmony_ci ret = btrfs_search_slot(NULL, extent_root, &key, path, 0, 0); 23118c2ecf20Sopenharmony_ci if (ret < 0) 23128c2ecf20Sopenharmony_ci goto out; 23138c2ecf20Sopenharmony_ci BUG_ON(ret == 0); /* Corruption */ 23148c2ecf20Sopenharmony_ci 23158c2ecf20Sopenharmony_ci ret = -ENOENT; 23168c2ecf20Sopenharmony_ci if (path->slots[0] == 0) 23178c2ecf20Sopenharmony_ci goto out; 23188c2ecf20Sopenharmony_ci 23198c2ecf20Sopenharmony_ci path->slots[0]--; 23208c2ecf20Sopenharmony_ci leaf = path->nodes[0]; 23218c2ecf20Sopenharmony_ci btrfs_item_key_to_cpu(leaf, &key, path->slots[0]); 23228c2ecf20Sopenharmony_ci 23238c2ecf20Sopenharmony_ci if (key.objectid != bytenr || key.type != BTRFS_EXTENT_ITEM_KEY) 23248c2ecf20Sopenharmony_ci goto out; 23258c2ecf20Sopenharmony_ci 23268c2ecf20Sopenharmony_ci ret = 1; 23278c2ecf20Sopenharmony_ci item_size = btrfs_item_size_nr(leaf, path->slots[0]); 23288c2ecf20Sopenharmony_ci ei = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_extent_item); 23298c2ecf20Sopenharmony_ci 23308c2ecf20Sopenharmony_ci /* If extent item has more than 1 inline ref then it's shared */ 23318c2ecf20Sopenharmony_ci if (item_size != sizeof(*ei) + 23328c2ecf20Sopenharmony_ci btrfs_extent_inline_ref_size(BTRFS_EXTENT_DATA_REF_KEY)) 23338c2ecf20Sopenharmony_ci goto out; 23348c2ecf20Sopenharmony_ci 23358c2ecf20Sopenharmony_ci /* 23368c2ecf20Sopenharmony_ci * If extent created before last snapshot => it's shared unless the 23378c2ecf20Sopenharmony_ci * snapshot has been deleted. Use the heuristic if strict is false. 23388c2ecf20Sopenharmony_ci */ 23398c2ecf20Sopenharmony_ci if (!strict && 23408c2ecf20Sopenharmony_ci (btrfs_extent_generation(leaf, ei) <= 23418c2ecf20Sopenharmony_ci btrfs_root_last_snapshot(&root->root_item))) 23428c2ecf20Sopenharmony_ci goto out; 23438c2ecf20Sopenharmony_ci 23448c2ecf20Sopenharmony_ci iref = (struct btrfs_extent_inline_ref *)(ei + 1); 23458c2ecf20Sopenharmony_ci 23468c2ecf20Sopenharmony_ci /* If this extent has SHARED_DATA_REF then it's shared */ 23478c2ecf20Sopenharmony_ci type = btrfs_get_extent_inline_ref_type(leaf, iref, BTRFS_REF_TYPE_DATA); 23488c2ecf20Sopenharmony_ci if (type != BTRFS_EXTENT_DATA_REF_KEY) 23498c2ecf20Sopenharmony_ci goto out; 23508c2ecf20Sopenharmony_ci 23518c2ecf20Sopenharmony_ci ref = (struct btrfs_extent_data_ref *)(&iref->offset); 23528c2ecf20Sopenharmony_ci if (btrfs_extent_refs(leaf, ei) != 23538c2ecf20Sopenharmony_ci btrfs_extent_data_ref_count(leaf, ref) || 23548c2ecf20Sopenharmony_ci btrfs_extent_data_ref_root(leaf, ref) != 23558c2ecf20Sopenharmony_ci root->root_key.objectid || 23568c2ecf20Sopenharmony_ci btrfs_extent_data_ref_objectid(leaf, ref) != objectid || 23578c2ecf20Sopenharmony_ci btrfs_extent_data_ref_offset(leaf, ref) != offset) 23588c2ecf20Sopenharmony_ci goto out; 23598c2ecf20Sopenharmony_ci 23608c2ecf20Sopenharmony_ci ret = 0; 23618c2ecf20Sopenharmony_ciout: 23628c2ecf20Sopenharmony_ci return ret; 23638c2ecf20Sopenharmony_ci} 23648c2ecf20Sopenharmony_ci 23658c2ecf20Sopenharmony_ciint btrfs_cross_ref_exist(struct btrfs_root *root, u64 objectid, u64 offset, 23668c2ecf20Sopenharmony_ci u64 bytenr, bool strict) 23678c2ecf20Sopenharmony_ci{ 23688c2ecf20Sopenharmony_ci struct btrfs_path *path; 23698c2ecf20Sopenharmony_ci int ret; 23708c2ecf20Sopenharmony_ci 23718c2ecf20Sopenharmony_ci path = btrfs_alloc_path(); 23728c2ecf20Sopenharmony_ci if (!path) 23738c2ecf20Sopenharmony_ci return -ENOMEM; 23748c2ecf20Sopenharmony_ci 23758c2ecf20Sopenharmony_ci do { 23768c2ecf20Sopenharmony_ci ret = check_committed_ref(root, path, objectid, 23778c2ecf20Sopenharmony_ci offset, bytenr, strict); 23788c2ecf20Sopenharmony_ci if (ret && ret != -ENOENT) 23798c2ecf20Sopenharmony_ci goto out; 23808c2ecf20Sopenharmony_ci 23818c2ecf20Sopenharmony_ci ret = check_delayed_ref(root, path, objectid, offset, bytenr); 23828c2ecf20Sopenharmony_ci } while (ret == -EAGAIN); 23838c2ecf20Sopenharmony_ci 23848c2ecf20Sopenharmony_ciout: 23858c2ecf20Sopenharmony_ci btrfs_free_path(path); 23868c2ecf20Sopenharmony_ci if (root->root_key.objectid == BTRFS_DATA_RELOC_TREE_OBJECTID) 23878c2ecf20Sopenharmony_ci WARN_ON(ret > 0); 23888c2ecf20Sopenharmony_ci return ret; 23898c2ecf20Sopenharmony_ci} 23908c2ecf20Sopenharmony_ci 23918c2ecf20Sopenharmony_cistatic int __btrfs_mod_ref(struct btrfs_trans_handle *trans, 23928c2ecf20Sopenharmony_ci struct btrfs_root *root, 23938c2ecf20Sopenharmony_ci struct extent_buffer *buf, 23948c2ecf20Sopenharmony_ci int full_backref, int inc) 23958c2ecf20Sopenharmony_ci{ 23968c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = root->fs_info; 23978c2ecf20Sopenharmony_ci u64 bytenr; 23988c2ecf20Sopenharmony_ci u64 num_bytes; 23998c2ecf20Sopenharmony_ci u64 parent; 24008c2ecf20Sopenharmony_ci u64 ref_root; 24018c2ecf20Sopenharmony_ci u32 nritems; 24028c2ecf20Sopenharmony_ci struct btrfs_key key; 24038c2ecf20Sopenharmony_ci struct btrfs_file_extent_item *fi; 24048c2ecf20Sopenharmony_ci struct btrfs_ref generic_ref = { 0 }; 24058c2ecf20Sopenharmony_ci bool for_reloc = btrfs_header_flag(buf, BTRFS_HEADER_FLAG_RELOC); 24068c2ecf20Sopenharmony_ci int i; 24078c2ecf20Sopenharmony_ci int action; 24088c2ecf20Sopenharmony_ci int level; 24098c2ecf20Sopenharmony_ci int ret = 0; 24108c2ecf20Sopenharmony_ci 24118c2ecf20Sopenharmony_ci if (btrfs_is_testing(fs_info)) 24128c2ecf20Sopenharmony_ci return 0; 24138c2ecf20Sopenharmony_ci 24148c2ecf20Sopenharmony_ci ref_root = btrfs_header_owner(buf); 24158c2ecf20Sopenharmony_ci nritems = btrfs_header_nritems(buf); 24168c2ecf20Sopenharmony_ci level = btrfs_header_level(buf); 24178c2ecf20Sopenharmony_ci 24188c2ecf20Sopenharmony_ci if (!test_bit(BTRFS_ROOT_SHAREABLE, &root->state) && level == 0) 24198c2ecf20Sopenharmony_ci return 0; 24208c2ecf20Sopenharmony_ci 24218c2ecf20Sopenharmony_ci if (full_backref) 24228c2ecf20Sopenharmony_ci parent = buf->start; 24238c2ecf20Sopenharmony_ci else 24248c2ecf20Sopenharmony_ci parent = 0; 24258c2ecf20Sopenharmony_ci if (inc) 24268c2ecf20Sopenharmony_ci action = BTRFS_ADD_DELAYED_REF; 24278c2ecf20Sopenharmony_ci else 24288c2ecf20Sopenharmony_ci action = BTRFS_DROP_DELAYED_REF; 24298c2ecf20Sopenharmony_ci 24308c2ecf20Sopenharmony_ci for (i = 0; i < nritems; i++) { 24318c2ecf20Sopenharmony_ci if (level == 0) { 24328c2ecf20Sopenharmony_ci btrfs_item_key_to_cpu(buf, &key, i); 24338c2ecf20Sopenharmony_ci if (key.type != BTRFS_EXTENT_DATA_KEY) 24348c2ecf20Sopenharmony_ci continue; 24358c2ecf20Sopenharmony_ci fi = btrfs_item_ptr(buf, i, 24368c2ecf20Sopenharmony_ci struct btrfs_file_extent_item); 24378c2ecf20Sopenharmony_ci if (btrfs_file_extent_type(buf, fi) == 24388c2ecf20Sopenharmony_ci BTRFS_FILE_EXTENT_INLINE) 24398c2ecf20Sopenharmony_ci continue; 24408c2ecf20Sopenharmony_ci bytenr = btrfs_file_extent_disk_bytenr(buf, fi); 24418c2ecf20Sopenharmony_ci if (bytenr == 0) 24428c2ecf20Sopenharmony_ci continue; 24438c2ecf20Sopenharmony_ci 24448c2ecf20Sopenharmony_ci num_bytes = btrfs_file_extent_disk_num_bytes(buf, fi); 24458c2ecf20Sopenharmony_ci key.offset -= btrfs_file_extent_offset(buf, fi); 24468c2ecf20Sopenharmony_ci btrfs_init_generic_ref(&generic_ref, action, bytenr, 24478c2ecf20Sopenharmony_ci num_bytes, parent); 24488c2ecf20Sopenharmony_ci generic_ref.real_root = root->root_key.objectid; 24498c2ecf20Sopenharmony_ci btrfs_init_data_ref(&generic_ref, ref_root, key.objectid, 24508c2ecf20Sopenharmony_ci key.offset); 24518c2ecf20Sopenharmony_ci generic_ref.skip_qgroup = for_reloc; 24528c2ecf20Sopenharmony_ci if (inc) 24538c2ecf20Sopenharmony_ci ret = btrfs_inc_extent_ref(trans, &generic_ref); 24548c2ecf20Sopenharmony_ci else 24558c2ecf20Sopenharmony_ci ret = btrfs_free_extent(trans, &generic_ref); 24568c2ecf20Sopenharmony_ci if (ret) 24578c2ecf20Sopenharmony_ci goto fail; 24588c2ecf20Sopenharmony_ci } else { 24598c2ecf20Sopenharmony_ci bytenr = btrfs_node_blockptr(buf, i); 24608c2ecf20Sopenharmony_ci num_bytes = fs_info->nodesize; 24618c2ecf20Sopenharmony_ci btrfs_init_generic_ref(&generic_ref, action, bytenr, 24628c2ecf20Sopenharmony_ci num_bytes, parent); 24638c2ecf20Sopenharmony_ci generic_ref.real_root = root->root_key.objectid; 24648c2ecf20Sopenharmony_ci btrfs_init_tree_ref(&generic_ref, level - 1, ref_root); 24658c2ecf20Sopenharmony_ci generic_ref.skip_qgroup = for_reloc; 24668c2ecf20Sopenharmony_ci if (inc) 24678c2ecf20Sopenharmony_ci ret = btrfs_inc_extent_ref(trans, &generic_ref); 24688c2ecf20Sopenharmony_ci else 24698c2ecf20Sopenharmony_ci ret = btrfs_free_extent(trans, &generic_ref); 24708c2ecf20Sopenharmony_ci if (ret) 24718c2ecf20Sopenharmony_ci goto fail; 24728c2ecf20Sopenharmony_ci } 24738c2ecf20Sopenharmony_ci } 24748c2ecf20Sopenharmony_ci return 0; 24758c2ecf20Sopenharmony_cifail: 24768c2ecf20Sopenharmony_ci return ret; 24778c2ecf20Sopenharmony_ci} 24788c2ecf20Sopenharmony_ci 24798c2ecf20Sopenharmony_ciint btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, 24808c2ecf20Sopenharmony_ci struct extent_buffer *buf, int full_backref) 24818c2ecf20Sopenharmony_ci{ 24828c2ecf20Sopenharmony_ci return __btrfs_mod_ref(trans, root, buf, full_backref, 1); 24838c2ecf20Sopenharmony_ci} 24848c2ecf20Sopenharmony_ci 24858c2ecf20Sopenharmony_ciint btrfs_dec_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, 24868c2ecf20Sopenharmony_ci struct extent_buffer *buf, int full_backref) 24878c2ecf20Sopenharmony_ci{ 24888c2ecf20Sopenharmony_ci return __btrfs_mod_ref(trans, root, buf, full_backref, 0); 24898c2ecf20Sopenharmony_ci} 24908c2ecf20Sopenharmony_ci 24918c2ecf20Sopenharmony_ciint btrfs_extent_readonly(struct btrfs_fs_info *fs_info, u64 bytenr) 24928c2ecf20Sopenharmony_ci{ 24938c2ecf20Sopenharmony_ci struct btrfs_block_group *block_group; 24948c2ecf20Sopenharmony_ci int readonly = 0; 24958c2ecf20Sopenharmony_ci 24968c2ecf20Sopenharmony_ci block_group = btrfs_lookup_block_group(fs_info, bytenr); 24978c2ecf20Sopenharmony_ci if (!block_group || block_group->ro) 24988c2ecf20Sopenharmony_ci readonly = 1; 24998c2ecf20Sopenharmony_ci if (block_group) 25008c2ecf20Sopenharmony_ci btrfs_put_block_group(block_group); 25018c2ecf20Sopenharmony_ci return readonly; 25028c2ecf20Sopenharmony_ci} 25038c2ecf20Sopenharmony_ci 25048c2ecf20Sopenharmony_cistatic u64 get_alloc_profile_by_root(struct btrfs_root *root, int data) 25058c2ecf20Sopenharmony_ci{ 25068c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = root->fs_info; 25078c2ecf20Sopenharmony_ci u64 flags; 25088c2ecf20Sopenharmony_ci u64 ret; 25098c2ecf20Sopenharmony_ci 25108c2ecf20Sopenharmony_ci if (data) 25118c2ecf20Sopenharmony_ci flags = BTRFS_BLOCK_GROUP_DATA; 25128c2ecf20Sopenharmony_ci else if (root == fs_info->chunk_root) 25138c2ecf20Sopenharmony_ci flags = BTRFS_BLOCK_GROUP_SYSTEM; 25148c2ecf20Sopenharmony_ci else 25158c2ecf20Sopenharmony_ci flags = BTRFS_BLOCK_GROUP_METADATA; 25168c2ecf20Sopenharmony_ci 25178c2ecf20Sopenharmony_ci ret = btrfs_get_alloc_profile(fs_info, flags); 25188c2ecf20Sopenharmony_ci return ret; 25198c2ecf20Sopenharmony_ci} 25208c2ecf20Sopenharmony_ci 25218c2ecf20Sopenharmony_cistatic u64 first_logical_byte(struct btrfs_fs_info *fs_info, u64 search_start) 25228c2ecf20Sopenharmony_ci{ 25238c2ecf20Sopenharmony_ci struct btrfs_block_group *cache; 25248c2ecf20Sopenharmony_ci u64 bytenr; 25258c2ecf20Sopenharmony_ci 25268c2ecf20Sopenharmony_ci spin_lock(&fs_info->block_group_cache_lock); 25278c2ecf20Sopenharmony_ci bytenr = fs_info->first_logical_byte; 25288c2ecf20Sopenharmony_ci spin_unlock(&fs_info->block_group_cache_lock); 25298c2ecf20Sopenharmony_ci 25308c2ecf20Sopenharmony_ci if (bytenr < (u64)-1) 25318c2ecf20Sopenharmony_ci return bytenr; 25328c2ecf20Sopenharmony_ci 25338c2ecf20Sopenharmony_ci cache = btrfs_lookup_first_block_group(fs_info, search_start); 25348c2ecf20Sopenharmony_ci if (!cache) 25358c2ecf20Sopenharmony_ci return 0; 25368c2ecf20Sopenharmony_ci 25378c2ecf20Sopenharmony_ci bytenr = cache->start; 25388c2ecf20Sopenharmony_ci btrfs_put_block_group(cache); 25398c2ecf20Sopenharmony_ci 25408c2ecf20Sopenharmony_ci return bytenr; 25418c2ecf20Sopenharmony_ci} 25428c2ecf20Sopenharmony_ci 25438c2ecf20Sopenharmony_cistatic int pin_down_extent(struct btrfs_trans_handle *trans, 25448c2ecf20Sopenharmony_ci struct btrfs_block_group *cache, 25458c2ecf20Sopenharmony_ci u64 bytenr, u64 num_bytes, int reserved) 25468c2ecf20Sopenharmony_ci{ 25478c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = cache->fs_info; 25488c2ecf20Sopenharmony_ci 25498c2ecf20Sopenharmony_ci spin_lock(&cache->space_info->lock); 25508c2ecf20Sopenharmony_ci spin_lock(&cache->lock); 25518c2ecf20Sopenharmony_ci cache->pinned += num_bytes; 25528c2ecf20Sopenharmony_ci btrfs_space_info_update_bytes_pinned(fs_info, cache->space_info, 25538c2ecf20Sopenharmony_ci num_bytes); 25548c2ecf20Sopenharmony_ci if (reserved) { 25558c2ecf20Sopenharmony_ci cache->reserved -= num_bytes; 25568c2ecf20Sopenharmony_ci cache->space_info->bytes_reserved -= num_bytes; 25578c2ecf20Sopenharmony_ci } 25588c2ecf20Sopenharmony_ci spin_unlock(&cache->lock); 25598c2ecf20Sopenharmony_ci spin_unlock(&cache->space_info->lock); 25608c2ecf20Sopenharmony_ci 25618c2ecf20Sopenharmony_ci __btrfs_mod_total_bytes_pinned(cache->space_info, num_bytes); 25628c2ecf20Sopenharmony_ci set_extent_dirty(&trans->transaction->pinned_extents, bytenr, 25638c2ecf20Sopenharmony_ci bytenr + num_bytes - 1, GFP_NOFS | __GFP_NOFAIL); 25648c2ecf20Sopenharmony_ci return 0; 25658c2ecf20Sopenharmony_ci} 25668c2ecf20Sopenharmony_ci 25678c2ecf20Sopenharmony_ciint btrfs_pin_extent(struct btrfs_trans_handle *trans, 25688c2ecf20Sopenharmony_ci u64 bytenr, u64 num_bytes, int reserved) 25698c2ecf20Sopenharmony_ci{ 25708c2ecf20Sopenharmony_ci struct btrfs_block_group *cache; 25718c2ecf20Sopenharmony_ci 25728c2ecf20Sopenharmony_ci cache = btrfs_lookup_block_group(trans->fs_info, bytenr); 25738c2ecf20Sopenharmony_ci BUG_ON(!cache); /* Logic error */ 25748c2ecf20Sopenharmony_ci 25758c2ecf20Sopenharmony_ci pin_down_extent(trans, cache, bytenr, num_bytes, reserved); 25768c2ecf20Sopenharmony_ci 25778c2ecf20Sopenharmony_ci btrfs_put_block_group(cache); 25788c2ecf20Sopenharmony_ci return 0; 25798c2ecf20Sopenharmony_ci} 25808c2ecf20Sopenharmony_ci 25818c2ecf20Sopenharmony_ci/* 25828c2ecf20Sopenharmony_ci * this function must be called within transaction 25838c2ecf20Sopenharmony_ci */ 25848c2ecf20Sopenharmony_ciint btrfs_pin_extent_for_log_replay(struct btrfs_trans_handle *trans, 25858c2ecf20Sopenharmony_ci u64 bytenr, u64 num_bytes) 25868c2ecf20Sopenharmony_ci{ 25878c2ecf20Sopenharmony_ci struct btrfs_block_group *cache; 25888c2ecf20Sopenharmony_ci int ret; 25898c2ecf20Sopenharmony_ci 25908c2ecf20Sopenharmony_ci btrfs_add_excluded_extent(trans->fs_info, bytenr, num_bytes); 25918c2ecf20Sopenharmony_ci 25928c2ecf20Sopenharmony_ci cache = btrfs_lookup_block_group(trans->fs_info, bytenr); 25938c2ecf20Sopenharmony_ci if (!cache) 25948c2ecf20Sopenharmony_ci return -EINVAL; 25958c2ecf20Sopenharmony_ci 25968c2ecf20Sopenharmony_ci /* 25978c2ecf20Sopenharmony_ci * pull in the free space cache (if any) so that our pin 25988c2ecf20Sopenharmony_ci * removes the free space from the cache. We have load_only set 25998c2ecf20Sopenharmony_ci * to one because the slow code to read in the free extents does check 26008c2ecf20Sopenharmony_ci * the pinned extents. 26018c2ecf20Sopenharmony_ci */ 26028c2ecf20Sopenharmony_ci btrfs_cache_block_group(cache, 1); 26038c2ecf20Sopenharmony_ci 26048c2ecf20Sopenharmony_ci pin_down_extent(trans, cache, bytenr, num_bytes, 0); 26058c2ecf20Sopenharmony_ci 26068c2ecf20Sopenharmony_ci /* remove us from the free space cache (if we're there at all) */ 26078c2ecf20Sopenharmony_ci ret = btrfs_remove_free_space(cache, bytenr, num_bytes); 26088c2ecf20Sopenharmony_ci btrfs_put_block_group(cache); 26098c2ecf20Sopenharmony_ci return ret; 26108c2ecf20Sopenharmony_ci} 26118c2ecf20Sopenharmony_ci 26128c2ecf20Sopenharmony_cistatic int __exclude_logged_extent(struct btrfs_fs_info *fs_info, 26138c2ecf20Sopenharmony_ci u64 start, u64 num_bytes) 26148c2ecf20Sopenharmony_ci{ 26158c2ecf20Sopenharmony_ci int ret; 26168c2ecf20Sopenharmony_ci struct btrfs_block_group *block_group; 26178c2ecf20Sopenharmony_ci struct btrfs_caching_control *caching_ctl; 26188c2ecf20Sopenharmony_ci 26198c2ecf20Sopenharmony_ci block_group = btrfs_lookup_block_group(fs_info, start); 26208c2ecf20Sopenharmony_ci if (!block_group) 26218c2ecf20Sopenharmony_ci return -EINVAL; 26228c2ecf20Sopenharmony_ci 26238c2ecf20Sopenharmony_ci btrfs_cache_block_group(block_group, 0); 26248c2ecf20Sopenharmony_ci caching_ctl = btrfs_get_caching_control(block_group); 26258c2ecf20Sopenharmony_ci 26268c2ecf20Sopenharmony_ci if (!caching_ctl) { 26278c2ecf20Sopenharmony_ci /* Logic error */ 26288c2ecf20Sopenharmony_ci BUG_ON(!btrfs_block_group_done(block_group)); 26298c2ecf20Sopenharmony_ci ret = btrfs_remove_free_space(block_group, start, num_bytes); 26308c2ecf20Sopenharmony_ci } else { 26318c2ecf20Sopenharmony_ci mutex_lock(&caching_ctl->mutex); 26328c2ecf20Sopenharmony_ci 26338c2ecf20Sopenharmony_ci if (start >= caching_ctl->progress) { 26348c2ecf20Sopenharmony_ci ret = btrfs_add_excluded_extent(fs_info, start, 26358c2ecf20Sopenharmony_ci num_bytes); 26368c2ecf20Sopenharmony_ci } else if (start + num_bytes <= caching_ctl->progress) { 26378c2ecf20Sopenharmony_ci ret = btrfs_remove_free_space(block_group, 26388c2ecf20Sopenharmony_ci start, num_bytes); 26398c2ecf20Sopenharmony_ci } else { 26408c2ecf20Sopenharmony_ci num_bytes = caching_ctl->progress - start; 26418c2ecf20Sopenharmony_ci ret = btrfs_remove_free_space(block_group, 26428c2ecf20Sopenharmony_ci start, num_bytes); 26438c2ecf20Sopenharmony_ci if (ret) 26448c2ecf20Sopenharmony_ci goto out_lock; 26458c2ecf20Sopenharmony_ci 26468c2ecf20Sopenharmony_ci num_bytes = (start + num_bytes) - 26478c2ecf20Sopenharmony_ci caching_ctl->progress; 26488c2ecf20Sopenharmony_ci start = caching_ctl->progress; 26498c2ecf20Sopenharmony_ci ret = btrfs_add_excluded_extent(fs_info, start, 26508c2ecf20Sopenharmony_ci num_bytes); 26518c2ecf20Sopenharmony_ci } 26528c2ecf20Sopenharmony_ciout_lock: 26538c2ecf20Sopenharmony_ci mutex_unlock(&caching_ctl->mutex); 26548c2ecf20Sopenharmony_ci btrfs_put_caching_control(caching_ctl); 26558c2ecf20Sopenharmony_ci } 26568c2ecf20Sopenharmony_ci btrfs_put_block_group(block_group); 26578c2ecf20Sopenharmony_ci return ret; 26588c2ecf20Sopenharmony_ci} 26598c2ecf20Sopenharmony_ci 26608c2ecf20Sopenharmony_ciint btrfs_exclude_logged_extents(struct extent_buffer *eb) 26618c2ecf20Sopenharmony_ci{ 26628c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = eb->fs_info; 26638c2ecf20Sopenharmony_ci struct btrfs_file_extent_item *item; 26648c2ecf20Sopenharmony_ci struct btrfs_key key; 26658c2ecf20Sopenharmony_ci int found_type; 26668c2ecf20Sopenharmony_ci int i; 26678c2ecf20Sopenharmony_ci int ret = 0; 26688c2ecf20Sopenharmony_ci 26698c2ecf20Sopenharmony_ci if (!btrfs_fs_incompat(fs_info, MIXED_GROUPS)) 26708c2ecf20Sopenharmony_ci return 0; 26718c2ecf20Sopenharmony_ci 26728c2ecf20Sopenharmony_ci for (i = 0; i < btrfs_header_nritems(eb); i++) { 26738c2ecf20Sopenharmony_ci btrfs_item_key_to_cpu(eb, &key, i); 26748c2ecf20Sopenharmony_ci if (key.type != BTRFS_EXTENT_DATA_KEY) 26758c2ecf20Sopenharmony_ci continue; 26768c2ecf20Sopenharmony_ci item = btrfs_item_ptr(eb, i, struct btrfs_file_extent_item); 26778c2ecf20Sopenharmony_ci found_type = btrfs_file_extent_type(eb, item); 26788c2ecf20Sopenharmony_ci if (found_type == BTRFS_FILE_EXTENT_INLINE) 26798c2ecf20Sopenharmony_ci continue; 26808c2ecf20Sopenharmony_ci if (btrfs_file_extent_disk_bytenr(eb, item) == 0) 26818c2ecf20Sopenharmony_ci continue; 26828c2ecf20Sopenharmony_ci key.objectid = btrfs_file_extent_disk_bytenr(eb, item); 26838c2ecf20Sopenharmony_ci key.offset = btrfs_file_extent_disk_num_bytes(eb, item); 26848c2ecf20Sopenharmony_ci ret = __exclude_logged_extent(fs_info, key.objectid, key.offset); 26858c2ecf20Sopenharmony_ci if (ret) 26868c2ecf20Sopenharmony_ci break; 26878c2ecf20Sopenharmony_ci } 26888c2ecf20Sopenharmony_ci 26898c2ecf20Sopenharmony_ci return ret; 26908c2ecf20Sopenharmony_ci} 26918c2ecf20Sopenharmony_ci 26928c2ecf20Sopenharmony_cistatic void 26938c2ecf20Sopenharmony_cibtrfs_inc_block_group_reservations(struct btrfs_block_group *bg) 26948c2ecf20Sopenharmony_ci{ 26958c2ecf20Sopenharmony_ci atomic_inc(&bg->reservations); 26968c2ecf20Sopenharmony_ci} 26978c2ecf20Sopenharmony_ci 26988c2ecf20Sopenharmony_ci/* 26998c2ecf20Sopenharmony_ci * Returns the free cluster for the given space info and sets empty_cluster to 27008c2ecf20Sopenharmony_ci * what it should be based on the mount options. 27018c2ecf20Sopenharmony_ci */ 27028c2ecf20Sopenharmony_cistatic struct btrfs_free_cluster * 27038c2ecf20Sopenharmony_cifetch_cluster_info(struct btrfs_fs_info *fs_info, 27048c2ecf20Sopenharmony_ci struct btrfs_space_info *space_info, u64 *empty_cluster) 27058c2ecf20Sopenharmony_ci{ 27068c2ecf20Sopenharmony_ci struct btrfs_free_cluster *ret = NULL; 27078c2ecf20Sopenharmony_ci 27088c2ecf20Sopenharmony_ci *empty_cluster = 0; 27098c2ecf20Sopenharmony_ci if (btrfs_mixed_space_info(space_info)) 27108c2ecf20Sopenharmony_ci return ret; 27118c2ecf20Sopenharmony_ci 27128c2ecf20Sopenharmony_ci if (space_info->flags & BTRFS_BLOCK_GROUP_METADATA) { 27138c2ecf20Sopenharmony_ci ret = &fs_info->meta_alloc_cluster; 27148c2ecf20Sopenharmony_ci if (btrfs_test_opt(fs_info, SSD)) 27158c2ecf20Sopenharmony_ci *empty_cluster = SZ_2M; 27168c2ecf20Sopenharmony_ci else 27178c2ecf20Sopenharmony_ci *empty_cluster = SZ_64K; 27188c2ecf20Sopenharmony_ci } else if ((space_info->flags & BTRFS_BLOCK_GROUP_DATA) && 27198c2ecf20Sopenharmony_ci btrfs_test_opt(fs_info, SSD_SPREAD)) { 27208c2ecf20Sopenharmony_ci *empty_cluster = SZ_2M; 27218c2ecf20Sopenharmony_ci ret = &fs_info->data_alloc_cluster; 27228c2ecf20Sopenharmony_ci } 27238c2ecf20Sopenharmony_ci 27248c2ecf20Sopenharmony_ci return ret; 27258c2ecf20Sopenharmony_ci} 27268c2ecf20Sopenharmony_ci 27278c2ecf20Sopenharmony_cistatic int unpin_extent_range(struct btrfs_fs_info *fs_info, 27288c2ecf20Sopenharmony_ci u64 start, u64 end, 27298c2ecf20Sopenharmony_ci const bool return_free_space) 27308c2ecf20Sopenharmony_ci{ 27318c2ecf20Sopenharmony_ci struct btrfs_block_group *cache = NULL; 27328c2ecf20Sopenharmony_ci struct btrfs_space_info *space_info; 27338c2ecf20Sopenharmony_ci struct btrfs_block_rsv *global_rsv = &fs_info->global_block_rsv; 27348c2ecf20Sopenharmony_ci struct btrfs_free_cluster *cluster = NULL; 27358c2ecf20Sopenharmony_ci u64 len; 27368c2ecf20Sopenharmony_ci u64 total_unpinned = 0; 27378c2ecf20Sopenharmony_ci u64 empty_cluster = 0; 27388c2ecf20Sopenharmony_ci bool readonly; 27398c2ecf20Sopenharmony_ci 27408c2ecf20Sopenharmony_ci while (start <= end) { 27418c2ecf20Sopenharmony_ci readonly = false; 27428c2ecf20Sopenharmony_ci if (!cache || 27438c2ecf20Sopenharmony_ci start >= cache->start + cache->length) { 27448c2ecf20Sopenharmony_ci if (cache) 27458c2ecf20Sopenharmony_ci btrfs_put_block_group(cache); 27468c2ecf20Sopenharmony_ci total_unpinned = 0; 27478c2ecf20Sopenharmony_ci cache = btrfs_lookup_block_group(fs_info, start); 27488c2ecf20Sopenharmony_ci BUG_ON(!cache); /* Logic error */ 27498c2ecf20Sopenharmony_ci 27508c2ecf20Sopenharmony_ci cluster = fetch_cluster_info(fs_info, 27518c2ecf20Sopenharmony_ci cache->space_info, 27528c2ecf20Sopenharmony_ci &empty_cluster); 27538c2ecf20Sopenharmony_ci empty_cluster <<= 1; 27548c2ecf20Sopenharmony_ci } 27558c2ecf20Sopenharmony_ci 27568c2ecf20Sopenharmony_ci len = cache->start + cache->length - start; 27578c2ecf20Sopenharmony_ci len = min(len, end + 1 - start); 27588c2ecf20Sopenharmony_ci 27598c2ecf20Sopenharmony_ci if (start < cache->last_byte_to_unpin && return_free_space) { 27608c2ecf20Sopenharmony_ci u64 add_len = min(len, cache->last_byte_to_unpin - start); 27618c2ecf20Sopenharmony_ci 27628c2ecf20Sopenharmony_ci btrfs_add_free_space(cache, start, add_len); 27638c2ecf20Sopenharmony_ci } 27648c2ecf20Sopenharmony_ci 27658c2ecf20Sopenharmony_ci start += len; 27668c2ecf20Sopenharmony_ci total_unpinned += len; 27678c2ecf20Sopenharmony_ci space_info = cache->space_info; 27688c2ecf20Sopenharmony_ci 27698c2ecf20Sopenharmony_ci /* 27708c2ecf20Sopenharmony_ci * If this space cluster has been marked as fragmented and we've 27718c2ecf20Sopenharmony_ci * unpinned enough in this block group to potentially allow a 27728c2ecf20Sopenharmony_ci * cluster to be created inside of it go ahead and clear the 27738c2ecf20Sopenharmony_ci * fragmented check. 27748c2ecf20Sopenharmony_ci */ 27758c2ecf20Sopenharmony_ci if (cluster && cluster->fragmented && 27768c2ecf20Sopenharmony_ci total_unpinned > empty_cluster) { 27778c2ecf20Sopenharmony_ci spin_lock(&cluster->lock); 27788c2ecf20Sopenharmony_ci cluster->fragmented = 0; 27798c2ecf20Sopenharmony_ci spin_unlock(&cluster->lock); 27808c2ecf20Sopenharmony_ci } 27818c2ecf20Sopenharmony_ci 27828c2ecf20Sopenharmony_ci spin_lock(&space_info->lock); 27838c2ecf20Sopenharmony_ci spin_lock(&cache->lock); 27848c2ecf20Sopenharmony_ci cache->pinned -= len; 27858c2ecf20Sopenharmony_ci btrfs_space_info_update_bytes_pinned(fs_info, space_info, -len); 27868c2ecf20Sopenharmony_ci space_info->max_extent_size = 0; 27878c2ecf20Sopenharmony_ci __btrfs_mod_total_bytes_pinned(space_info, -len); 27888c2ecf20Sopenharmony_ci if (cache->ro) { 27898c2ecf20Sopenharmony_ci space_info->bytes_readonly += len; 27908c2ecf20Sopenharmony_ci readonly = true; 27918c2ecf20Sopenharmony_ci } 27928c2ecf20Sopenharmony_ci spin_unlock(&cache->lock); 27938c2ecf20Sopenharmony_ci if (!readonly && return_free_space && 27948c2ecf20Sopenharmony_ci global_rsv->space_info == space_info) { 27958c2ecf20Sopenharmony_ci u64 to_add = len; 27968c2ecf20Sopenharmony_ci 27978c2ecf20Sopenharmony_ci spin_lock(&global_rsv->lock); 27988c2ecf20Sopenharmony_ci if (!global_rsv->full) { 27998c2ecf20Sopenharmony_ci to_add = min(len, global_rsv->size - 28008c2ecf20Sopenharmony_ci global_rsv->reserved); 28018c2ecf20Sopenharmony_ci global_rsv->reserved += to_add; 28028c2ecf20Sopenharmony_ci btrfs_space_info_update_bytes_may_use(fs_info, 28038c2ecf20Sopenharmony_ci space_info, to_add); 28048c2ecf20Sopenharmony_ci if (global_rsv->reserved >= global_rsv->size) 28058c2ecf20Sopenharmony_ci global_rsv->full = 1; 28068c2ecf20Sopenharmony_ci len -= to_add; 28078c2ecf20Sopenharmony_ci } 28088c2ecf20Sopenharmony_ci spin_unlock(&global_rsv->lock); 28098c2ecf20Sopenharmony_ci } 28108c2ecf20Sopenharmony_ci /* Add to any tickets we may have */ 28118c2ecf20Sopenharmony_ci if (!readonly && return_free_space && len) 28128c2ecf20Sopenharmony_ci btrfs_try_granting_tickets(fs_info, space_info); 28138c2ecf20Sopenharmony_ci spin_unlock(&space_info->lock); 28148c2ecf20Sopenharmony_ci } 28158c2ecf20Sopenharmony_ci 28168c2ecf20Sopenharmony_ci if (cache) 28178c2ecf20Sopenharmony_ci btrfs_put_block_group(cache); 28188c2ecf20Sopenharmony_ci return 0; 28198c2ecf20Sopenharmony_ci} 28208c2ecf20Sopenharmony_ci 28218c2ecf20Sopenharmony_ciint btrfs_finish_extent_commit(struct btrfs_trans_handle *trans) 28228c2ecf20Sopenharmony_ci{ 28238c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = trans->fs_info; 28248c2ecf20Sopenharmony_ci struct btrfs_block_group *block_group, *tmp; 28258c2ecf20Sopenharmony_ci struct list_head *deleted_bgs; 28268c2ecf20Sopenharmony_ci struct extent_io_tree *unpin; 28278c2ecf20Sopenharmony_ci u64 start; 28288c2ecf20Sopenharmony_ci u64 end; 28298c2ecf20Sopenharmony_ci int ret; 28308c2ecf20Sopenharmony_ci 28318c2ecf20Sopenharmony_ci unpin = &trans->transaction->pinned_extents; 28328c2ecf20Sopenharmony_ci 28338c2ecf20Sopenharmony_ci while (!TRANS_ABORTED(trans)) { 28348c2ecf20Sopenharmony_ci struct extent_state *cached_state = NULL; 28358c2ecf20Sopenharmony_ci 28368c2ecf20Sopenharmony_ci mutex_lock(&fs_info->unused_bg_unpin_mutex); 28378c2ecf20Sopenharmony_ci ret = find_first_extent_bit(unpin, 0, &start, &end, 28388c2ecf20Sopenharmony_ci EXTENT_DIRTY, &cached_state); 28398c2ecf20Sopenharmony_ci if (ret) { 28408c2ecf20Sopenharmony_ci mutex_unlock(&fs_info->unused_bg_unpin_mutex); 28418c2ecf20Sopenharmony_ci break; 28428c2ecf20Sopenharmony_ci } 28438c2ecf20Sopenharmony_ci if (test_bit(BTRFS_FS_LOG_RECOVERING, &fs_info->flags)) 28448c2ecf20Sopenharmony_ci clear_extent_bits(&fs_info->excluded_extents, start, 28458c2ecf20Sopenharmony_ci end, EXTENT_UPTODATE); 28468c2ecf20Sopenharmony_ci 28478c2ecf20Sopenharmony_ci if (btrfs_test_opt(fs_info, DISCARD_SYNC)) 28488c2ecf20Sopenharmony_ci ret = btrfs_discard_extent(fs_info, start, 28498c2ecf20Sopenharmony_ci end + 1 - start, NULL); 28508c2ecf20Sopenharmony_ci 28518c2ecf20Sopenharmony_ci clear_extent_dirty(unpin, start, end, &cached_state); 28528c2ecf20Sopenharmony_ci unpin_extent_range(fs_info, start, end, true); 28538c2ecf20Sopenharmony_ci mutex_unlock(&fs_info->unused_bg_unpin_mutex); 28548c2ecf20Sopenharmony_ci free_extent_state(cached_state); 28558c2ecf20Sopenharmony_ci cond_resched(); 28568c2ecf20Sopenharmony_ci } 28578c2ecf20Sopenharmony_ci 28588c2ecf20Sopenharmony_ci if (btrfs_test_opt(fs_info, DISCARD_ASYNC)) { 28598c2ecf20Sopenharmony_ci btrfs_discard_calc_delay(&fs_info->discard_ctl); 28608c2ecf20Sopenharmony_ci btrfs_discard_schedule_work(&fs_info->discard_ctl, true); 28618c2ecf20Sopenharmony_ci } 28628c2ecf20Sopenharmony_ci 28638c2ecf20Sopenharmony_ci /* 28648c2ecf20Sopenharmony_ci * Transaction is finished. We don't need the lock anymore. We 28658c2ecf20Sopenharmony_ci * do need to clean up the block groups in case of a transaction 28668c2ecf20Sopenharmony_ci * abort. 28678c2ecf20Sopenharmony_ci */ 28688c2ecf20Sopenharmony_ci deleted_bgs = &trans->transaction->deleted_bgs; 28698c2ecf20Sopenharmony_ci list_for_each_entry_safe(block_group, tmp, deleted_bgs, bg_list) { 28708c2ecf20Sopenharmony_ci u64 trimmed = 0; 28718c2ecf20Sopenharmony_ci 28728c2ecf20Sopenharmony_ci ret = -EROFS; 28738c2ecf20Sopenharmony_ci if (!TRANS_ABORTED(trans)) 28748c2ecf20Sopenharmony_ci ret = btrfs_discard_extent(fs_info, 28758c2ecf20Sopenharmony_ci block_group->start, 28768c2ecf20Sopenharmony_ci block_group->length, 28778c2ecf20Sopenharmony_ci &trimmed); 28788c2ecf20Sopenharmony_ci 28798c2ecf20Sopenharmony_ci list_del_init(&block_group->bg_list); 28808c2ecf20Sopenharmony_ci btrfs_unfreeze_block_group(block_group); 28818c2ecf20Sopenharmony_ci btrfs_put_block_group(block_group); 28828c2ecf20Sopenharmony_ci 28838c2ecf20Sopenharmony_ci if (ret) { 28848c2ecf20Sopenharmony_ci const char *errstr = btrfs_decode_error(ret); 28858c2ecf20Sopenharmony_ci btrfs_warn(fs_info, 28868c2ecf20Sopenharmony_ci "discard failed while removing blockgroup: errno=%d %s", 28878c2ecf20Sopenharmony_ci ret, errstr); 28888c2ecf20Sopenharmony_ci } 28898c2ecf20Sopenharmony_ci } 28908c2ecf20Sopenharmony_ci 28918c2ecf20Sopenharmony_ci return 0; 28928c2ecf20Sopenharmony_ci} 28938c2ecf20Sopenharmony_ci 28948c2ecf20Sopenharmony_ci/* 28958c2ecf20Sopenharmony_ci * Drop one or more refs of @node. 28968c2ecf20Sopenharmony_ci * 28978c2ecf20Sopenharmony_ci * 1. Locate the extent refs. 28988c2ecf20Sopenharmony_ci * It's either inline in EXTENT/METADATA_ITEM or in keyed SHARED_* item. 28998c2ecf20Sopenharmony_ci * Locate it, then reduce the refs number or remove the ref line completely. 29008c2ecf20Sopenharmony_ci * 29018c2ecf20Sopenharmony_ci * 2. Update the refs count in EXTENT/METADATA_ITEM 29028c2ecf20Sopenharmony_ci * 29038c2ecf20Sopenharmony_ci * Inline backref case: 29048c2ecf20Sopenharmony_ci * 29058c2ecf20Sopenharmony_ci * in extent tree we have: 29068c2ecf20Sopenharmony_ci * 29078c2ecf20Sopenharmony_ci * item 0 key (13631488 EXTENT_ITEM 1048576) itemoff 16201 itemsize 82 29088c2ecf20Sopenharmony_ci * refs 2 gen 6 flags DATA 29098c2ecf20Sopenharmony_ci * extent data backref root FS_TREE objectid 258 offset 0 count 1 29108c2ecf20Sopenharmony_ci * extent data backref root FS_TREE objectid 257 offset 0 count 1 29118c2ecf20Sopenharmony_ci * 29128c2ecf20Sopenharmony_ci * This function gets called with: 29138c2ecf20Sopenharmony_ci * 29148c2ecf20Sopenharmony_ci * node->bytenr = 13631488 29158c2ecf20Sopenharmony_ci * node->num_bytes = 1048576 29168c2ecf20Sopenharmony_ci * root_objectid = FS_TREE 29178c2ecf20Sopenharmony_ci * owner_objectid = 257 29188c2ecf20Sopenharmony_ci * owner_offset = 0 29198c2ecf20Sopenharmony_ci * refs_to_drop = 1 29208c2ecf20Sopenharmony_ci * 29218c2ecf20Sopenharmony_ci * Then we should get some like: 29228c2ecf20Sopenharmony_ci * 29238c2ecf20Sopenharmony_ci * item 0 key (13631488 EXTENT_ITEM 1048576) itemoff 16201 itemsize 82 29248c2ecf20Sopenharmony_ci * refs 1 gen 6 flags DATA 29258c2ecf20Sopenharmony_ci * extent data backref root FS_TREE objectid 258 offset 0 count 1 29268c2ecf20Sopenharmony_ci * 29278c2ecf20Sopenharmony_ci * Keyed backref case: 29288c2ecf20Sopenharmony_ci * 29298c2ecf20Sopenharmony_ci * in extent tree we have: 29308c2ecf20Sopenharmony_ci * 29318c2ecf20Sopenharmony_ci * item 0 key (13631488 EXTENT_ITEM 1048576) itemoff 3971 itemsize 24 29328c2ecf20Sopenharmony_ci * refs 754 gen 6 flags DATA 29338c2ecf20Sopenharmony_ci * [...] 29348c2ecf20Sopenharmony_ci * item 2 key (13631488 EXTENT_DATA_REF <HASH>) itemoff 3915 itemsize 28 29358c2ecf20Sopenharmony_ci * extent data backref root FS_TREE objectid 866 offset 0 count 1 29368c2ecf20Sopenharmony_ci * 29378c2ecf20Sopenharmony_ci * This function get called with: 29388c2ecf20Sopenharmony_ci * 29398c2ecf20Sopenharmony_ci * node->bytenr = 13631488 29408c2ecf20Sopenharmony_ci * node->num_bytes = 1048576 29418c2ecf20Sopenharmony_ci * root_objectid = FS_TREE 29428c2ecf20Sopenharmony_ci * owner_objectid = 866 29438c2ecf20Sopenharmony_ci * owner_offset = 0 29448c2ecf20Sopenharmony_ci * refs_to_drop = 1 29458c2ecf20Sopenharmony_ci * 29468c2ecf20Sopenharmony_ci * Then we should get some like: 29478c2ecf20Sopenharmony_ci * 29488c2ecf20Sopenharmony_ci * item 0 key (13631488 EXTENT_ITEM 1048576) itemoff 3971 itemsize 24 29498c2ecf20Sopenharmony_ci * refs 753 gen 6 flags DATA 29508c2ecf20Sopenharmony_ci * 29518c2ecf20Sopenharmony_ci * And that (13631488 EXTENT_DATA_REF <HASH>) gets removed. 29528c2ecf20Sopenharmony_ci */ 29538c2ecf20Sopenharmony_cistatic int __btrfs_free_extent(struct btrfs_trans_handle *trans, 29548c2ecf20Sopenharmony_ci struct btrfs_delayed_ref_node *node, u64 parent, 29558c2ecf20Sopenharmony_ci u64 root_objectid, u64 owner_objectid, 29568c2ecf20Sopenharmony_ci u64 owner_offset, int refs_to_drop, 29578c2ecf20Sopenharmony_ci struct btrfs_delayed_extent_op *extent_op) 29588c2ecf20Sopenharmony_ci{ 29598c2ecf20Sopenharmony_ci struct btrfs_fs_info *info = trans->fs_info; 29608c2ecf20Sopenharmony_ci struct btrfs_key key; 29618c2ecf20Sopenharmony_ci struct btrfs_path *path; 29628c2ecf20Sopenharmony_ci struct btrfs_root *extent_root = info->extent_root; 29638c2ecf20Sopenharmony_ci struct extent_buffer *leaf; 29648c2ecf20Sopenharmony_ci struct btrfs_extent_item *ei; 29658c2ecf20Sopenharmony_ci struct btrfs_extent_inline_ref *iref; 29668c2ecf20Sopenharmony_ci int ret; 29678c2ecf20Sopenharmony_ci int is_data; 29688c2ecf20Sopenharmony_ci int extent_slot = 0; 29698c2ecf20Sopenharmony_ci int found_extent = 0; 29708c2ecf20Sopenharmony_ci int num_to_del = 1; 29718c2ecf20Sopenharmony_ci u32 item_size; 29728c2ecf20Sopenharmony_ci u64 refs; 29738c2ecf20Sopenharmony_ci u64 bytenr = node->bytenr; 29748c2ecf20Sopenharmony_ci u64 num_bytes = node->num_bytes; 29758c2ecf20Sopenharmony_ci int last_ref = 0; 29768c2ecf20Sopenharmony_ci bool skinny_metadata = btrfs_fs_incompat(info, SKINNY_METADATA); 29778c2ecf20Sopenharmony_ci 29788c2ecf20Sopenharmony_ci path = btrfs_alloc_path(); 29798c2ecf20Sopenharmony_ci if (!path) 29808c2ecf20Sopenharmony_ci return -ENOMEM; 29818c2ecf20Sopenharmony_ci 29828c2ecf20Sopenharmony_ci path->leave_spinning = 1; 29838c2ecf20Sopenharmony_ci 29848c2ecf20Sopenharmony_ci is_data = owner_objectid >= BTRFS_FIRST_FREE_OBJECTID; 29858c2ecf20Sopenharmony_ci 29868c2ecf20Sopenharmony_ci if (!is_data && refs_to_drop != 1) { 29878c2ecf20Sopenharmony_ci btrfs_crit(info, 29888c2ecf20Sopenharmony_ci"invalid refs_to_drop, dropping more than 1 refs for tree block %llu refs_to_drop %u", 29898c2ecf20Sopenharmony_ci node->bytenr, refs_to_drop); 29908c2ecf20Sopenharmony_ci ret = -EINVAL; 29918c2ecf20Sopenharmony_ci btrfs_abort_transaction(trans, ret); 29928c2ecf20Sopenharmony_ci goto out; 29938c2ecf20Sopenharmony_ci } 29948c2ecf20Sopenharmony_ci 29958c2ecf20Sopenharmony_ci if (is_data) 29968c2ecf20Sopenharmony_ci skinny_metadata = false; 29978c2ecf20Sopenharmony_ci 29988c2ecf20Sopenharmony_ci ret = lookup_extent_backref(trans, path, &iref, bytenr, num_bytes, 29998c2ecf20Sopenharmony_ci parent, root_objectid, owner_objectid, 30008c2ecf20Sopenharmony_ci owner_offset); 30018c2ecf20Sopenharmony_ci if (ret == 0) { 30028c2ecf20Sopenharmony_ci /* 30038c2ecf20Sopenharmony_ci * Either the inline backref or the SHARED_DATA_REF/ 30048c2ecf20Sopenharmony_ci * SHARED_BLOCK_REF is found 30058c2ecf20Sopenharmony_ci * 30068c2ecf20Sopenharmony_ci * Here is a quick path to locate EXTENT/METADATA_ITEM. 30078c2ecf20Sopenharmony_ci * It's possible the EXTENT/METADATA_ITEM is near current slot. 30088c2ecf20Sopenharmony_ci */ 30098c2ecf20Sopenharmony_ci extent_slot = path->slots[0]; 30108c2ecf20Sopenharmony_ci while (extent_slot >= 0) { 30118c2ecf20Sopenharmony_ci btrfs_item_key_to_cpu(path->nodes[0], &key, 30128c2ecf20Sopenharmony_ci extent_slot); 30138c2ecf20Sopenharmony_ci if (key.objectid != bytenr) 30148c2ecf20Sopenharmony_ci break; 30158c2ecf20Sopenharmony_ci if (key.type == BTRFS_EXTENT_ITEM_KEY && 30168c2ecf20Sopenharmony_ci key.offset == num_bytes) { 30178c2ecf20Sopenharmony_ci found_extent = 1; 30188c2ecf20Sopenharmony_ci break; 30198c2ecf20Sopenharmony_ci } 30208c2ecf20Sopenharmony_ci if (key.type == BTRFS_METADATA_ITEM_KEY && 30218c2ecf20Sopenharmony_ci key.offset == owner_objectid) { 30228c2ecf20Sopenharmony_ci found_extent = 1; 30238c2ecf20Sopenharmony_ci break; 30248c2ecf20Sopenharmony_ci } 30258c2ecf20Sopenharmony_ci 30268c2ecf20Sopenharmony_ci /* Quick path didn't find the EXTEMT/METADATA_ITEM */ 30278c2ecf20Sopenharmony_ci if (path->slots[0] - extent_slot > 5) 30288c2ecf20Sopenharmony_ci break; 30298c2ecf20Sopenharmony_ci extent_slot--; 30308c2ecf20Sopenharmony_ci } 30318c2ecf20Sopenharmony_ci 30328c2ecf20Sopenharmony_ci if (!found_extent) { 30338c2ecf20Sopenharmony_ci if (iref) { 30348c2ecf20Sopenharmony_ci btrfs_crit(info, 30358c2ecf20Sopenharmony_ci"invalid iref, no EXTENT/METADATA_ITEM found but has inline extent ref"); 30368c2ecf20Sopenharmony_ci btrfs_abort_transaction(trans, -EUCLEAN); 30378c2ecf20Sopenharmony_ci goto err_dump; 30388c2ecf20Sopenharmony_ci } 30398c2ecf20Sopenharmony_ci /* Must be SHARED_* item, remove the backref first */ 30408c2ecf20Sopenharmony_ci ret = remove_extent_backref(trans, path, NULL, 30418c2ecf20Sopenharmony_ci refs_to_drop, 30428c2ecf20Sopenharmony_ci is_data, &last_ref); 30438c2ecf20Sopenharmony_ci if (ret) { 30448c2ecf20Sopenharmony_ci btrfs_abort_transaction(trans, ret); 30458c2ecf20Sopenharmony_ci goto out; 30468c2ecf20Sopenharmony_ci } 30478c2ecf20Sopenharmony_ci btrfs_release_path(path); 30488c2ecf20Sopenharmony_ci path->leave_spinning = 1; 30498c2ecf20Sopenharmony_ci 30508c2ecf20Sopenharmony_ci /* Slow path to locate EXTENT/METADATA_ITEM */ 30518c2ecf20Sopenharmony_ci key.objectid = bytenr; 30528c2ecf20Sopenharmony_ci key.type = BTRFS_EXTENT_ITEM_KEY; 30538c2ecf20Sopenharmony_ci key.offset = num_bytes; 30548c2ecf20Sopenharmony_ci 30558c2ecf20Sopenharmony_ci if (!is_data && skinny_metadata) { 30568c2ecf20Sopenharmony_ci key.type = BTRFS_METADATA_ITEM_KEY; 30578c2ecf20Sopenharmony_ci key.offset = owner_objectid; 30588c2ecf20Sopenharmony_ci } 30598c2ecf20Sopenharmony_ci 30608c2ecf20Sopenharmony_ci ret = btrfs_search_slot(trans, extent_root, 30618c2ecf20Sopenharmony_ci &key, path, -1, 1); 30628c2ecf20Sopenharmony_ci if (ret > 0 && skinny_metadata && path->slots[0]) { 30638c2ecf20Sopenharmony_ci /* 30648c2ecf20Sopenharmony_ci * Couldn't find our skinny metadata item, 30658c2ecf20Sopenharmony_ci * see if we have ye olde extent item. 30668c2ecf20Sopenharmony_ci */ 30678c2ecf20Sopenharmony_ci path->slots[0]--; 30688c2ecf20Sopenharmony_ci btrfs_item_key_to_cpu(path->nodes[0], &key, 30698c2ecf20Sopenharmony_ci path->slots[0]); 30708c2ecf20Sopenharmony_ci if (key.objectid == bytenr && 30718c2ecf20Sopenharmony_ci key.type == BTRFS_EXTENT_ITEM_KEY && 30728c2ecf20Sopenharmony_ci key.offset == num_bytes) 30738c2ecf20Sopenharmony_ci ret = 0; 30748c2ecf20Sopenharmony_ci } 30758c2ecf20Sopenharmony_ci 30768c2ecf20Sopenharmony_ci if (ret > 0 && skinny_metadata) { 30778c2ecf20Sopenharmony_ci skinny_metadata = false; 30788c2ecf20Sopenharmony_ci key.objectid = bytenr; 30798c2ecf20Sopenharmony_ci key.type = BTRFS_EXTENT_ITEM_KEY; 30808c2ecf20Sopenharmony_ci key.offset = num_bytes; 30818c2ecf20Sopenharmony_ci btrfs_release_path(path); 30828c2ecf20Sopenharmony_ci ret = btrfs_search_slot(trans, extent_root, 30838c2ecf20Sopenharmony_ci &key, path, -1, 1); 30848c2ecf20Sopenharmony_ci } 30858c2ecf20Sopenharmony_ci 30868c2ecf20Sopenharmony_ci if (ret) { 30878c2ecf20Sopenharmony_ci btrfs_err(info, 30888c2ecf20Sopenharmony_ci "umm, got %d back from search, was looking for %llu", 30898c2ecf20Sopenharmony_ci ret, bytenr); 30908c2ecf20Sopenharmony_ci if (ret > 0) 30918c2ecf20Sopenharmony_ci btrfs_print_leaf(path->nodes[0]); 30928c2ecf20Sopenharmony_ci } 30938c2ecf20Sopenharmony_ci if (ret < 0) { 30948c2ecf20Sopenharmony_ci btrfs_abort_transaction(trans, ret); 30958c2ecf20Sopenharmony_ci goto out; 30968c2ecf20Sopenharmony_ci } 30978c2ecf20Sopenharmony_ci extent_slot = path->slots[0]; 30988c2ecf20Sopenharmony_ci } 30998c2ecf20Sopenharmony_ci } else if (WARN_ON(ret == -ENOENT)) { 31008c2ecf20Sopenharmony_ci btrfs_print_leaf(path->nodes[0]); 31018c2ecf20Sopenharmony_ci btrfs_err(info, 31028c2ecf20Sopenharmony_ci "unable to find ref byte nr %llu parent %llu root %llu owner %llu offset %llu", 31038c2ecf20Sopenharmony_ci bytenr, parent, root_objectid, owner_objectid, 31048c2ecf20Sopenharmony_ci owner_offset); 31058c2ecf20Sopenharmony_ci btrfs_abort_transaction(trans, ret); 31068c2ecf20Sopenharmony_ci goto out; 31078c2ecf20Sopenharmony_ci } else { 31088c2ecf20Sopenharmony_ci btrfs_abort_transaction(trans, ret); 31098c2ecf20Sopenharmony_ci goto out; 31108c2ecf20Sopenharmony_ci } 31118c2ecf20Sopenharmony_ci 31128c2ecf20Sopenharmony_ci leaf = path->nodes[0]; 31138c2ecf20Sopenharmony_ci item_size = btrfs_item_size_nr(leaf, extent_slot); 31148c2ecf20Sopenharmony_ci if (unlikely(item_size < sizeof(*ei))) { 31158c2ecf20Sopenharmony_ci ret = -EINVAL; 31168c2ecf20Sopenharmony_ci btrfs_print_v0_err(info); 31178c2ecf20Sopenharmony_ci btrfs_abort_transaction(trans, ret); 31188c2ecf20Sopenharmony_ci goto out; 31198c2ecf20Sopenharmony_ci } 31208c2ecf20Sopenharmony_ci ei = btrfs_item_ptr(leaf, extent_slot, 31218c2ecf20Sopenharmony_ci struct btrfs_extent_item); 31228c2ecf20Sopenharmony_ci if (owner_objectid < BTRFS_FIRST_FREE_OBJECTID && 31238c2ecf20Sopenharmony_ci key.type == BTRFS_EXTENT_ITEM_KEY) { 31248c2ecf20Sopenharmony_ci struct btrfs_tree_block_info *bi; 31258c2ecf20Sopenharmony_ci if (item_size < sizeof(*ei) + sizeof(*bi)) { 31268c2ecf20Sopenharmony_ci btrfs_crit(info, 31278c2ecf20Sopenharmony_ci"invalid extent item size for key (%llu, %u, %llu) owner %llu, has %u expect >= %zu", 31288c2ecf20Sopenharmony_ci key.objectid, key.type, key.offset, 31298c2ecf20Sopenharmony_ci owner_objectid, item_size, 31308c2ecf20Sopenharmony_ci sizeof(*ei) + sizeof(*bi)); 31318c2ecf20Sopenharmony_ci btrfs_abort_transaction(trans, -EUCLEAN); 31328c2ecf20Sopenharmony_ci goto err_dump; 31338c2ecf20Sopenharmony_ci } 31348c2ecf20Sopenharmony_ci bi = (struct btrfs_tree_block_info *)(ei + 1); 31358c2ecf20Sopenharmony_ci WARN_ON(owner_objectid != btrfs_tree_block_level(leaf, bi)); 31368c2ecf20Sopenharmony_ci } 31378c2ecf20Sopenharmony_ci 31388c2ecf20Sopenharmony_ci refs = btrfs_extent_refs(leaf, ei); 31398c2ecf20Sopenharmony_ci if (refs < refs_to_drop) { 31408c2ecf20Sopenharmony_ci btrfs_crit(info, 31418c2ecf20Sopenharmony_ci "trying to drop %d refs but we only have %llu for bytenr %llu", 31428c2ecf20Sopenharmony_ci refs_to_drop, refs, bytenr); 31438c2ecf20Sopenharmony_ci btrfs_abort_transaction(trans, -EUCLEAN); 31448c2ecf20Sopenharmony_ci goto err_dump; 31458c2ecf20Sopenharmony_ci } 31468c2ecf20Sopenharmony_ci refs -= refs_to_drop; 31478c2ecf20Sopenharmony_ci 31488c2ecf20Sopenharmony_ci if (refs > 0) { 31498c2ecf20Sopenharmony_ci if (extent_op) 31508c2ecf20Sopenharmony_ci __run_delayed_extent_op(extent_op, leaf, ei); 31518c2ecf20Sopenharmony_ci /* 31528c2ecf20Sopenharmony_ci * In the case of inline back ref, reference count will 31538c2ecf20Sopenharmony_ci * be updated by remove_extent_backref 31548c2ecf20Sopenharmony_ci */ 31558c2ecf20Sopenharmony_ci if (iref) { 31568c2ecf20Sopenharmony_ci if (!found_extent) { 31578c2ecf20Sopenharmony_ci btrfs_crit(info, 31588c2ecf20Sopenharmony_ci"invalid iref, got inlined extent ref but no EXTENT/METADATA_ITEM found"); 31598c2ecf20Sopenharmony_ci btrfs_abort_transaction(trans, -EUCLEAN); 31608c2ecf20Sopenharmony_ci goto err_dump; 31618c2ecf20Sopenharmony_ci } 31628c2ecf20Sopenharmony_ci } else { 31638c2ecf20Sopenharmony_ci btrfs_set_extent_refs(leaf, ei, refs); 31648c2ecf20Sopenharmony_ci btrfs_mark_buffer_dirty(leaf); 31658c2ecf20Sopenharmony_ci } 31668c2ecf20Sopenharmony_ci if (found_extent) { 31678c2ecf20Sopenharmony_ci ret = remove_extent_backref(trans, path, iref, 31688c2ecf20Sopenharmony_ci refs_to_drop, is_data, 31698c2ecf20Sopenharmony_ci &last_ref); 31708c2ecf20Sopenharmony_ci if (ret) { 31718c2ecf20Sopenharmony_ci btrfs_abort_transaction(trans, ret); 31728c2ecf20Sopenharmony_ci goto out; 31738c2ecf20Sopenharmony_ci } 31748c2ecf20Sopenharmony_ci } 31758c2ecf20Sopenharmony_ci } else { 31768c2ecf20Sopenharmony_ci /* In this branch refs == 1 */ 31778c2ecf20Sopenharmony_ci if (found_extent) { 31788c2ecf20Sopenharmony_ci if (is_data && refs_to_drop != 31798c2ecf20Sopenharmony_ci extent_data_ref_count(path, iref)) { 31808c2ecf20Sopenharmony_ci btrfs_crit(info, 31818c2ecf20Sopenharmony_ci "invalid refs_to_drop, current refs %u refs_to_drop %u", 31828c2ecf20Sopenharmony_ci extent_data_ref_count(path, iref), 31838c2ecf20Sopenharmony_ci refs_to_drop); 31848c2ecf20Sopenharmony_ci btrfs_abort_transaction(trans, -EUCLEAN); 31858c2ecf20Sopenharmony_ci goto err_dump; 31868c2ecf20Sopenharmony_ci } 31878c2ecf20Sopenharmony_ci if (iref) { 31888c2ecf20Sopenharmony_ci if (path->slots[0] != extent_slot) { 31898c2ecf20Sopenharmony_ci btrfs_crit(info, 31908c2ecf20Sopenharmony_ci"invalid iref, extent item key (%llu %u %llu) doesn't have wanted iref", 31918c2ecf20Sopenharmony_ci key.objectid, key.type, 31928c2ecf20Sopenharmony_ci key.offset); 31938c2ecf20Sopenharmony_ci btrfs_abort_transaction(trans, -EUCLEAN); 31948c2ecf20Sopenharmony_ci goto err_dump; 31958c2ecf20Sopenharmony_ci } 31968c2ecf20Sopenharmony_ci } else { 31978c2ecf20Sopenharmony_ci /* 31988c2ecf20Sopenharmony_ci * No inline ref, we must be at SHARED_* item, 31998c2ecf20Sopenharmony_ci * And it's single ref, it must be: 32008c2ecf20Sopenharmony_ci * | extent_slot ||extent_slot + 1| 32018c2ecf20Sopenharmony_ci * [ EXTENT/METADATA_ITEM ][ SHARED_* ITEM ] 32028c2ecf20Sopenharmony_ci */ 32038c2ecf20Sopenharmony_ci if (path->slots[0] != extent_slot + 1) { 32048c2ecf20Sopenharmony_ci btrfs_crit(info, 32058c2ecf20Sopenharmony_ci "invalid SHARED_* item, previous item is not EXTENT/METADATA_ITEM"); 32068c2ecf20Sopenharmony_ci btrfs_abort_transaction(trans, -EUCLEAN); 32078c2ecf20Sopenharmony_ci goto err_dump; 32088c2ecf20Sopenharmony_ci } 32098c2ecf20Sopenharmony_ci path->slots[0] = extent_slot; 32108c2ecf20Sopenharmony_ci num_to_del = 2; 32118c2ecf20Sopenharmony_ci } 32128c2ecf20Sopenharmony_ci } 32138c2ecf20Sopenharmony_ci 32148c2ecf20Sopenharmony_ci last_ref = 1; 32158c2ecf20Sopenharmony_ci ret = btrfs_del_items(trans, extent_root, path, path->slots[0], 32168c2ecf20Sopenharmony_ci num_to_del); 32178c2ecf20Sopenharmony_ci if (ret) { 32188c2ecf20Sopenharmony_ci btrfs_abort_transaction(trans, ret); 32198c2ecf20Sopenharmony_ci goto out; 32208c2ecf20Sopenharmony_ci } 32218c2ecf20Sopenharmony_ci btrfs_release_path(path); 32228c2ecf20Sopenharmony_ci 32238c2ecf20Sopenharmony_ci if (is_data) { 32248c2ecf20Sopenharmony_ci ret = btrfs_del_csums(trans, info->csum_root, bytenr, 32258c2ecf20Sopenharmony_ci num_bytes); 32268c2ecf20Sopenharmony_ci if (ret) { 32278c2ecf20Sopenharmony_ci btrfs_abort_transaction(trans, ret); 32288c2ecf20Sopenharmony_ci goto out; 32298c2ecf20Sopenharmony_ci } 32308c2ecf20Sopenharmony_ci } 32318c2ecf20Sopenharmony_ci 32328c2ecf20Sopenharmony_ci ret = add_to_free_space_tree(trans, bytenr, num_bytes); 32338c2ecf20Sopenharmony_ci if (ret) { 32348c2ecf20Sopenharmony_ci btrfs_abort_transaction(trans, ret); 32358c2ecf20Sopenharmony_ci goto out; 32368c2ecf20Sopenharmony_ci } 32378c2ecf20Sopenharmony_ci 32388c2ecf20Sopenharmony_ci ret = btrfs_update_block_group(trans, bytenr, num_bytes, 0); 32398c2ecf20Sopenharmony_ci if (ret) { 32408c2ecf20Sopenharmony_ci btrfs_abort_transaction(trans, ret); 32418c2ecf20Sopenharmony_ci goto out; 32428c2ecf20Sopenharmony_ci } 32438c2ecf20Sopenharmony_ci } 32448c2ecf20Sopenharmony_ci btrfs_release_path(path); 32458c2ecf20Sopenharmony_ci 32468c2ecf20Sopenharmony_ciout: 32478c2ecf20Sopenharmony_ci btrfs_free_path(path); 32488c2ecf20Sopenharmony_ci return ret; 32498c2ecf20Sopenharmony_cierr_dump: 32508c2ecf20Sopenharmony_ci /* 32518c2ecf20Sopenharmony_ci * Leaf dump can take up a lot of log buffer, so we only do full leaf 32528c2ecf20Sopenharmony_ci * dump for debug build. 32538c2ecf20Sopenharmony_ci */ 32548c2ecf20Sopenharmony_ci if (IS_ENABLED(CONFIG_BTRFS_DEBUG)) { 32558c2ecf20Sopenharmony_ci btrfs_crit(info, "path->slots[0]=%d extent_slot=%d", 32568c2ecf20Sopenharmony_ci path->slots[0], extent_slot); 32578c2ecf20Sopenharmony_ci btrfs_print_leaf(path->nodes[0]); 32588c2ecf20Sopenharmony_ci } 32598c2ecf20Sopenharmony_ci 32608c2ecf20Sopenharmony_ci btrfs_free_path(path); 32618c2ecf20Sopenharmony_ci return -EUCLEAN; 32628c2ecf20Sopenharmony_ci} 32638c2ecf20Sopenharmony_ci 32648c2ecf20Sopenharmony_ci/* 32658c2ecf20Sopenharmony_ci * when we free an block, it is possible (and likely) that we free the last 32668c2ecf20Sopenharmony_ci * delayed ref for that extent as well. This searches the delayed ref tree for 32678c2ecf20Sopenharmony_ci * a given extent, and if there are no other delayed refs to be processed, it 32688c2ecf20Sopenharmony_ci * removes it from the tree. 32698c2ecf20Sopenharmony_ci */ 32708c2ecf20Sopenharmony_cistatic noinline int check_ref_cleanup(struct btrfs_trans_handle *trans, 32718c2ecf20Sopenharmony_ci u64 bytenr) 32728c2ecf20Sopenharmony_ci{ 32738c2ecf20Sopenharmony_ci struct btrfs_delayed_ref_head *head; 32748c2ecf20Sopenharmony_ci struct btrfs_delayed_ref_root *delayed_refs; 32758c2ecf20Sopenharmony_ci int ret = 0; 32768c2ecf20Sopenharmony_ci 32778c2ecf20Sopenharmony_ci delayed_refs = &trans->transaction->delayed_refs; 32788c2ecf20Sopenharmony_ci spin_lock(&delayed_refs->lock); 32798c2ecf20Sopenharmony_ci head = btrfs_find_delayed_ref_head(delayed_refs, bytenr); 32808c2ecf20Sopenharmony_ci if (!head) 32818c2ecf20Sopenharmony_ci goto out_delayed_unlock; 32828c2ecf20Sopenharmony_ci 32838c2ecf20Sopenharmony_ci spin_lock(&head->lock); 32848c2ecf20Sopenharmony_ci if (!RB_EMPTY_ROOT(&head->ref_tree.rb_root)) 32858c2ecf20Sopenharmony_ci goto out; 32868c2ecf20Sopenharmony_ci 32878c2ecf20Sopenharmony_ci if (cleanup_extent_op(head) != NULL) 32888c2ecf20Sopenharmony_ci goto out; 32898c2ecf20Sopenharmony_ci 32908c2ecf20Sopenharmony_ci /* 32918c2ecf20Sopenharmony_ci * waiting for the lock here would deadlock. If someone else has it 32928c2ecf20Sopenharmony_ci * locked they are already in the process of dropping it anyway 32938c2ecf20Sopenharmony_ci */ 32948c2ecf20Sopenharmony_ci if (!mutex_trylock(&head->mutex)) 32958c2ecf20Sopenharmony_ci goto out; 32968c2ecf20Sopenharmony_ci 32978c2ecf20Sopenharmony_ci btrfs_delete_ref_head(delayed_refs, head); 32988c2ecf20Sopenharmony_ci head->processing = 0; 32998c2ecf20Sopenharmony_ci 33008c2ecf20Sopenharmony_ci spin_unlock(&head->lock); 33018c2ecf20Sopenharmony_ci spin_unlock(&delayed_refs->lock); 33028c2ecf20Sopenharmony_ci 33038c2ecf20Sopenharmony_ci BUG_ON(head->extent_op); 33048c2ecf20Sopenharmony_ci if (head->must_insert_reserved) 33058c2ecf20Sopenharmony_ci ret = 1; 33068c2ecf20Sopenharmony_ci 33078c2ecf20Sopenharmony_ci btrfs_cleanup_ref_head_accounting(trans->fs_info, delayed_refs, head); 33088c2ecf20Sopenharmony_ci mutex_unlock(&head->mutex); 33098c2ecf20Sopenharmony_ci btrfs_put_delayed_ref_head(head); 33108c2ecf20Sopenharmony_ci return ret; 33118c2ecf20Sopenharmony_ciout: 33128c2ecf20Sopenharmony_ci spin_unlock(&head->lock); 33138c2ecf20Sopenharmony_ci 33148c2ecf20Sopenharmony_ciout_delayed_unlock: 33158c2ecf20Sopenharmony_ci spin_unlock(&delayed_refs->lock); 33168c2ecf20Sopenharmony_ci return 0; 33178c2ecf20Sopenharmony_ci} 33188c2ecf20Sopenharmony_ci 33198c2ecf20Sopenharmony_civoid btrfs_free_tree_block(struct btrfs_trans_handle *trans, 33208c2ecf20Sopenharmony_ci struct btrfs_root *root, 33218c2ecf20Sopenharmony_ci struct extent_buffer *buf, 33228c2ecf20Sopenharmony_ci u64 parent, int last_ref) 33238c2ecf20Sopenharmony_ci{ 33248c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = root->fs_info; 33258c2ecf20Sopenharmony_ci struct btrfs_ref generic_ref = { 0 }; 33268c2ecf20Sopenharmony_ci int ret; 33278c2ecf20Sopenharmony_ci 33288c2ecf20Sopenharmony_ci btrfs_init_generic_ref(&generic_ref, BTRFS_DROP_DELAYED_REF, 33298c2ecf20Sopenharmony_ci buf->start, buf->len, parent); 33308c2ecf20Sopenharmony_ci btrfs_init_tree_ref(&generic_ref, btrfs_header_level(buf), 33318c2ecf20Sopenharmony_ci root->root_key.objectid); 33328c2ecf20Sopenharmony_ci 33338c2ecf20Sopenharmony_ci if (root->root_key.objectid != BTRFS_TREE_LOG_OBJECTID) { 33348c2ecf20Sopenharmony_ci btrfs_ref_tree_mod(fs_info, &generic_ref); 33358c2ecf20Sopenharmony_ci ret = btrfs_add_delayed_tree_ref(trans, &generic_ref, NULL); 33368c2ecf20Sopenharmony_ci BUG_ON(ret); /* -ENOMEM */ 33378c2ecf20Sopenharmony_ci } 33388c2ecf20Sopenharmony_ci 33398c2ecf20Sopenharmony_ci if (last_ref && btrfs_header_generation(buf) == trans->transid) { 33408c2ecf20Sopenharmony_ci struct btrfs_block_group *cache; 33418c2ecf20Sopenharmony_ci 33428c2ecf20Sopenharmony_ci if (root->root_key.objectid != BTRFS_TREE_LOG_OBJECTID) { 33438c2ecf20Sopenharmony_ci ret = check_ref_cleanup(trans, buf->start); 33448c2ecf20Sopenharmony_ci if (!ret) 33458c2ecf20Sopenharmony_ci goto out; 33468c2ecf20Sopenharmony_ci } 33478c2ecf20Sopenharmony_ci 33488c2ecf20Sopenharmony_ci cache = btrfs_lookup_block_group(fs_info, buf->start); 33498c2ecf20Sopenharmony_ci 33508c2ecf20Sopenharmony_ci if (btrfs_header_flag(buf, BTRFS_HEADER_FLAG_WRITTEN)) { 33518c2ecf20Sopenharmony_ci pin_down_extent(trans, cache, buf->start, buf->len, 1); 33528c2ecf20Sopenharmony_ci btrfs_put_block_group(cache); 33538c2ecf20Sopenharmony_ci goto out; 33548c2ecf20Sopenharmony_ci } 33558c2ecf20Sopenharmony_ci 33568c2ecf20Sopenharmony_ci WARN_ON(test_bit(EXTENT_BUFFER_DIRTY, &buf->bflags)); 33578c2ecf20Sopenharmony_ci 33588c2ecf20Sopenharmony_ci btrfs_add_free_space(cache, buf->start, buf->len); 33598c2ecf20Sopenharmony_ci btrfs_free_reserved_bytes(cache, buf->len, 0); 33608c2ecf20Sopenharmony_ci btrfs_put_block_group(cache); 33618c2ecf20Sopenharmony_ci trace_btrfs_reserved_extent_free(fs_info, buf->start, buf->len); 33628c2ecf20Sopenharmony_ci } 33638c2ecf20Sopenharmony_ciout: 33648c2ecf20Sopenharmony_ci if (last_ref) { 33658c2ecf20Sopenharmony_ci /* 33668c2ecf20Sopenharmony_ci * Deleting the buffer, clear the corrupt flag since it doesn't 33678c2ecf20Sopenharmony_ci * matter anymore. 33688c2ecf20Sopenharmony_ci */ 33698c2ecf20Sopenharmony_ci clear_bit(EXTENT_BUFFER_CORRUPT, &buf->bflags); 33708c2ecf20Sopenharmony_ci } 33718c2ecf20Sopenharmony_ci} 33728c2ecf20Sopenharmony_ci 33738c2ecf20Sopenharmony_ci/* Can return -ENOMEM */ 33748c2ecf20Sopenharmony_ciint btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_ref *ref) 33758c2ecf20Sopenharmony_ci{ 33768c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = trans->fs_info; 33778c2ecf20Sopenharmony_ci int ret; 33788c2ecf20Sopenharmony_ci 33798c2ecf20Sopenharmony_ci if (btrfs_is_testing(fs_info)) 33808c2ecf20Sopenharmony_ci return 0; 33818c2ecf20Sopenharmony_ci 33828c2ecf20Sopenharmony_ci /* 33838c2ecf20Sopenharmony_ci * tree log blocks never actually go into the extent allocation 33848c2ecf20Sopenharmony_ci * tree, just update pinning info and exit early. 33858c2ecf20Sopenharmony_ci */ 33868c2ecf20Sopenharmony_ci if ((ref->type == BTRFS_REF_METADATA && 33878c2ecf20Sopenharmony_ci ref->tree_ref.root == BTRFS_TREE_LOG_OBJECTID) || 33888c2ecf20Sopenharmony_ci (ref->type == BTRFS_REF_DATA && 33898c2ecf20Sopenharmony_ci ref->data_ref.ref_root == BTRFS_TREE_LOG_OBJECTID)) { 33908c2ecf20Sopenharmony_ci /* unlocks the pinned mutex */ 33918c2ecf20Sopenharmony_ci btrfs_pin_extent(trans, ref->bytenr, ref->len, 1); 33928c2ecf20Sopenharmony_ci ret = 0; 33938c2ecf20Sopenharmony_ci } else if (ref->type == BTRFS_REF_METADATA) { 33948c2ecf20Sopenharmony_ci ret = btrfs_add_delayed_tree_ref(trans, ref, NULL); 33958c2ecf20Sopenharmony_ci } else { 33968c2ecf20Sopenharmony_ci ret = btrfs_add_delayed_data_ref(trans, ref, 0); 33978c2ecf20Sopenharmony_ci } 33988c2ecf20Sopenharmony_ci 33998c2ecf20Sopenharmony_ci if (!((ref->type == BTRFS_REF_METADATA && 34008c2ecf20Sopenharmony_ci ref->tree_ref.root == BTRFS_TREE_LOG_OBJECTID) || 34018c2ecf20Sopenharmony_ci (ref->type == BTRFS_REF_DATA && 34028c2ecf20Sopenharmony_ci ref->data_ref.ref_root == BTRFS_TREE_LOG_OBJECTID))) 34038c2ecf20Sopenharmony_ci btrfs_ref_tree_mod(fs_info, ref); 34048c2ecf20Sopenharmony_ci 34058c2ecf20Sopenharmony_ci return ret; 34068c2ecf20Sopenharmony_ci} 34078c2ecf20Sopenharmony_ci 34088c2ecf20Sopenharmony_cienum btrfs_loop_type { 34098c2ecf20Sopenharmony_ci LOOP_CACHING_NOWAIT, 34108c2ecf20Sopenharmony_ci LOOP_CACHING_WAIT, 34118c2ecf20Sopenharmony_ci LOOP_ALLOC_CHUNK, 34128c2ecf20Sopenharmony_ci LOOP_NO_EMPTY_SIZE, 34138c2ecf20Sopenharmony_ci}; 34148c2ecf20Sopenharmony_ci 34158c2ecf20Sopenharmony_cistatic inline void 34168c2ecf20Sopenharmony_cibtrfs_lock_block_group(struct btrfs_block_group *cache, 34178c2ecf20Sopenharmony_ci int delalloc) 34188c2ecf20Sopenharmony_ci{ 34198c2ecf20Sopenharmony_ci if (delalloc) 34208c2ecf20Sopenharmony_ci down_read(&cache->data_rwsem); 34218c2ecf20Sopenharmony_ci} 34228c2ecf20Sopenharmony_ci 34238c2ecf20Sopenharmony_cistatic inline void btrfs_grab_block_group(struct btrfs_block_group *cache, 34248c2ecf20Sopenharmony_ci int delalloc) 34258c2ecf20Sopenharmony_ci{ 34268c2ecf20Sopenharmony_ci btrfs_get_block_group(cache); 34278c2ecf20Sopenharmony_ci if (delalloc) 34288c2ecf20Sopenharmony_ci down_read(&cache->data_rwsem); 34298c2ecf20Sopenharmony_ci} 34308c2ecf20Sopenharmony_ci 34318c2ecf20Sopenharmony_cistatic struct btrfs_block_group *btrfs_lock_cluster( 34328c2ecf20Sopenharmony_ci struct btrfs_block_group *block_group, 34338c2ecf20Sopenharmony_ci struct btrfs_free_cluster *cluster, 34348c2ecf20Sopenharmony_ci int delalloc) 34358c2ecf20Sopenharmony_ci __acquires(&cluster->refill_lock) 34368c2ecf20Sopenharmony_ci{ 34378c2ecf20Sopenharmony_ci struct btrfs_block_group *used_bg = NULL; 34388c2ecf20Sopenharmony_ci 34398c2ecf20Sopenharmony_ci spin_lock(&cluster->refill_lock); 34408c2ecf20Sopenharmony_ci while (1) { 34418c2ecf20Sopenharmony_ci used_bg = cluster->block_group; 34428c2ecf20Sopenharmony_ci if (!used_bg) 34438c2ecf20Sopenharmony_ci return NULL; 34448c2ecf20Sopenharmony_ci 34458c2ecf20Sopenharmony_ci if (used_bg == block_group) 34468c2ecf20Sopenharmony_ci return used_bg; 34478c2ecf20Sopenharmony_ci 34488c2ecf20Sopenharmony_ci btrfs_get_block_group(used_bg); 34498c2ecf20Sopenharmony_ci 34508c2ecf20Sopenharmony_ci if (!delalloc) 34518c2ecf20Sopenharmony_ci return used_bg; 34528c2ecf20Sopenharmony_ci 34538c2ecf20Sopenharmony_ci if (down_read_trylock(&used_bg->data_rwsem)) 34548c2ecf20Sopenharmony_ci return used_bg; 34558c2ecf20Sopenharmony_ci 34568c2ecf20Sopenharmony_ci spin_unlock(&cluster->refill_lock); 34578c2ecf20Sopenharmony_ci 34588c2ecf20Sopenharmony_ci /* We should only have one-level nested. */ 34598c2ecf20Sopenharmony_ci down_read_nested(&used_bg->data_rwsem, SINGLE_DEPTH_NESTING); 34608c2ecf20Sopenharmony_ci 34618c2ecf20Sopenharmony_ci spin_lock(&cluster->refill_lock); 34628c2ecf20Sopenharmony_ci if (used_bg == cluster->block_group) 34638c2ecf20Sopenharmony_ci return used_bg; 34648c2ecf20Sopenharmony_ci 34658c2ecf20Sopenharmony_ci up_read(&used_bg->data_rwsem); 34668c2ecf20Sopenharmony_ci btrfs_put_block_group(used_bg); 34678c2ecf20Sopenharmony_ci } 34688c2ecf20Sopenharmony_ci} 34698c2ecf20Sopenharmony_ci 34708c2ecf20Sopenharmony_cistatic inline void 34718c2ecf20Sopenharmony_cibtrfs_release_block_group(struct btrfs_block_group *cache, 34728c2ecf20Sopenharmony_ci int delalloc) 34738c2ecf20Sopenharmony_ci{ 34748c2ecf20Sopenharmony_ci if (delalloc) 34758c2ecf20Sopenharmony_ci up_read(&cache->data_rwsem); 34768c2ecf20Sopenharmony_ci btrfs_put_block_group(cache); 34778c2ecf20Sopenharmony_ci} 34788c2ecf20Sopenharmony_ci 34798c2ecf20Sopenharmony_cienum btrfs_extent_allocation_policy { 34808c2ecf20Sopenharmony_ci BTRFS_EXTENT_ALLOC_CLUSTERED, 34818c2ecf20Sopenharmony_ci}; 34828c2ecf20Sopenharmony_ci 34838c2ecf20Sopenharmony_ci/* 34848c2ecf20Sopenharmony_ci * Structure used internally for find_free_extent() function. Wraps needed 34858c2ecf20Sopenharmony_ci * parameters. 34868c2ecf20Sopenharmony_ci */ 34878c2ecf20Sopenharmony_cistruct find_free_extent_ctl { 34888c2ecf20Sopenharmony_ci /* Basic allocation info */ 34898c2ecf20Sopenharmony_ci u64 num_bytes; 34908c2ecf20Sopenharmony_ci u64 empty_size; 34918c2ecf20Sopenharmony_ci u64 flags; 34928c2ecf20Sopenharmony_ci int delalloc; 34938c2ecf20Sopenharmony_ci 34948c2ecf20Sopenharmony_ci /* Where to start the search inside the bg */ 34958c2ecf20Sopenharmony_ci u64 search_start; 34968c2ecf20Sopenharmony_ci 34978c2ecf20Sopenharmony_ci /* For clustered allocation */ 34988c2ecf20Sopenharmony_ci u64 empty_cluster; 34998c2ecf20Sopenharmony_ci struct btrfs_free_cluster *last_ptr; 35008c2ecf20Sopenharmony_ci bool use_cluster; 35018c2ecf20Sopenharmony_ci 35028c2ecf20Sopenharmony_ci bool have_caching_bg; 35038c2ecf20Sopenharmony_ci bool orig_have_caching_bg; 35048c2ecf20Sopenharmony_ci 35058c2ecf20Sopenharmony_ci /* RAID index, converted from flags */ 35068c2ecf20Sopenharmony_ci int index; 35078c2ecf20Sopenharmony_ci 35088c2ecf20Sopenharmony_ci /* 35098c2ecf20Sopenharmony_ci * Current loop number, check find_free_extent_update_loop() for details 35108c2ecf20Sopenharmony_ci */ 35118c2ecf20Sopenharmony_ci int loop; 35128c2ecf20Sopenharmony_ci 35138c2ecf20Sopenharmony_ci /* 35148c2ecf20Sopenharmony_ci * Whether we're refilling a cluster, if true we need to re-search 35158c2ecf20Sopenharmony_ci * current block group but don't try to refill the cluster again. 35168c2ecf20Sopenharmony_ci */ 35178c2ecf20Sopenharmony_ci bool retry_clustered; 35188c2ecf20Sopenharmony_ci 35198c2ecf20Sopenharmony_ci /* 35208c2ecf20Sopenharmony_ci * Whether we're updating free space cache, if true we need to re-search 35218c2ecf20Sopenharmony_ci * current block group but don't try updating free space cache again. 35228c2ecf20Sopenharmony_ci */ 35238c2ecf20Sopenharmony_ci bool retry_unclustered; 35248c2ecf20Sopenharmony_ci 35258c2ecf20Sopenharmony_ci /* If current block group is cached */ 35268c2ecf20Sopenharmony_ci int cached; 35278c2ecf20Sopenharmony_ci 35288c2ecf20Sopenharmony_ci /* Max contiguous hole found */ 35298c2ecf20Sopenharmony_ci u64 max_extent_size; 35308c2ecf20Sopenharmony_ci 35318c2ecf20Sopenharmony_ci /* Total free space from free space cache, not always contiguous */ 35328c2ecf20Sopenharmony_ci u64 total_free_space; 35338c2ecf20Sopenharmony_ci 35348c2ecf20Sopenharmony_ci /* Found result */ 35358c2ecf20Sopenharmony_ci u64 found_offset; 35368c2ecf20Sopenharmony_ci 35378c2ecf20Sopenharmony_ci /* Hint where to start looking for an empty space */ 35388c2ecf20Sopenharmony_ci u64 hint_byte; 35398c2ecf20Sopenharmony_ci 35408c2ecf20Sopenharmony_ci /* Allocation policy */ 35418c2ecf20Sopenharmony_ci enum btrfs_extent_allocation_policy policy; 35428c2ecf20Sopenharmony_ci}; 35438c2ecf20Sopenharmony_ci 35448c2ecf20Sopenharmony_ci 35458c2ecf20Sopenharmony_ci/* 35468c2ecf20Sopenharmony_ci * Helper function for find_free_extent(). 35478c2ecf20Sopenharmony_ci * 35488c2ecf20Sopenharmony_ci * Return -ENOENT to inform caller that we need fallback to unclustered mode. 35498c2ecf20Sopenharmony_ci * Return -EAGAIN to inform caller that we need to re-search this block group 35508c2ecf20Sopenharmony_ci * Return >0 to inform caller that we find nothing 35518c2ecf20Sopenharmony_ci * Return 0 means we have found a location and set ffe_ctl->found_offset. 35528c2ecf20Sopenharmony_ci */ 35538c2ecf20Sopenharmony_cistatic int find_free_extent_clustered(struct btrfs_block_group *bg, 35548c2ecf20Sopenharmony_ci struct find_free_extent_ctl *ffe_ctl, 35558c2ecf20Sopenharmony_ci struct btrfs_block_group **cluster_bg_ret) 35568c2ecf20Sopenharmony_ci{ 35578c2ecf20Sopenharmony_ci struct btrfs_block_group *cluster_bg; 35588c2ecf20Sopenharmony_ci struct btrfs_free_cluster *last_ptr = ffe_ctl->last_ptr; 35598c2ecf20Sopenharmony_ci u64 aligned_cluster; 35608c2ecf20Sopenharmony_ci u64 offset; 35618c2ecf20Sopenharmony_ci int ret; 35628c2ecf20Sopenharmony_ci 35638c2ecf20Sopenharmony_ci cluster_bg = btrfs_lock_cluster(bg, last_ptr, ffe_ctl->delalloc); 35648c2ecf20Sopenharmony_ci if (!cluster_bg) 35658c2ecf20Sopenharmony_ci goto refill_cluster; 35668c2ecf20Sopenharmony_ci if (cluster_bg != bg && (cluster_bg->ro || 35678c2ecf20Sopenharmony_ci !block_group_bits(cluster_bg, ffe_ctl->flags))) 35688c2ecf20Sopenharmony_ci goto release_cluster; 35698c2ecf20Sopenharmony_ci 35708c2ecf20Sopenharmony_ci offset = btrfs_alloc_from_cluster(cluster_bg, last_ptr, 35718c2ecf20Sopenharmony_ci ffe_ctl->num_bytes, cluster_bg->start, 35728c2ecf20Sopenharmony_ci &ffe_ctl->max_extent_size); 35738c2ecf20Sopenharmony_ci if (offset) { 35748c2ecf20Sopenharmony_ci /* We have a block, we're done */ 35758c2ecf20Sopenharmony_ci spin_unlock(&last_ptr->refill_lock); 35768c2ecf20Sopenharmony_ci trace_btrfs_reserve_extent_cluster(cluster_bg, 35778c2ecf20Sopenharmony_ci ffe_ctl->search_start, ffe_ctl->num_bytes); 35788c2ecf20Sopenharmony_ci *cluster_bg_ret = cluster_bg; 35798c2ecf20Sopenharmony_ci ffe_ctl->found_offset = offset; 35808c2ecf20Sopenharmony_ci return 0; 35818c2ecf20Sopenharmony_ci } 35828c2ecf20Sopenharmony_ci WARN_ON(last_ptr->block_group != cluster_bg); 35838c2ecf20Sopenharmony_ci 35848c2ecf20Sopenharmony_cirelease_cluster: 35858c2ecf20Sopenharmony_ci /* 35868c2ecf20Sopenharmony_ci * If we are on LOOP_NO_EMPTY_SIZE, we can't set up a new clusters, so 35878c2ecf20Sopenharmony_ci * lets just skip it and let the allocator find whatever block it can 35888c2ecf20Sopenharmony_ci * find. If we reach this point, we will have tried the cluster 35898c2ecf20Sopenharmony_ci * allocator plenty of times and not have found anything, so we are 35908c2ecf20Sopenharmony_ci * likely way too fragmented for the clustering stuff to find anything. 35918c2ecf20Sopenharmony_ci * 35928c2ecf20Sopenharmony_ci * However, if the cluster is taken from the current block group, 35938c2ecf20Sopenharmony_ci * release the cluster first, so that we stand a better chance of 35948c2ecf20Sopenharmony_ci * succeeding in the unclustered allocation. 35958c2ecf20Sopenharmony_ci */ 35968c2ecf20Sopenharmony_ci if (ffe_ctl->loop >= LOOP_NO_EMPTY_SIZE && cluster_bg != bg) { 35978c2ecf20Sopenharmony_ci spin_unlock(&last_ptr->refill_lock); 35988c2ecf20Sopenharmony_ci btrfs_release_block_group(cluster_bg, ffe_ctl->delalloc); 35998c2ecf20Sopenharmony_ci return -ENOENT; 36008c2ecf20Sopenharmony_ci } 36018c2ecf20Sopenharmony_ci 36028c2ecf20Sopenharmony_ci /* This cluster didn't work out, free it and start over */ 36038c2ecf20Sopenharmony_ci btrfs_return_cluster_to_free_space(NULL, last_ptr); 36048c2ecf20Sopenharmony_ci 36058c2ecf20Sopenharmony_ci if (cluster_bg != bg) 36068c2ecf20Sopenharmony_ci btrfs_release_block_group(cluster_bg, ffe_ctl->delalloc); 36078c2ecf20Sopenharmony_ci 36088c2ecf20Sopenharmony_cirefill_cluster: 36098c2ecf20Sopenharmony_ci if (ffe_ctl->loop >= LOOP_NO_EMPTY_SIZE) { 36108c2ecf20Sopenharmony_ci spin_unlock(&last_ptr->refill_lock); 36118c2ecf20Sopenharmony_ci return -ENOENT; 36128c2ecf20Sopenharmony_ci } 36138c2ecf20Sopenharmony_ci 36148c2ecf20Sopenharmony_ci aligned_cluster = max_t(u64, 36158c2ecf20Sopenharmony_ci ffe_ctl->empty_cluster + ffe_ctl->empty_size, 36168c2ecf20Sopenharmony_ci bg->full_stripe_len); 36178c2ecf20Sopenharmony_ci ret = btrfs_find_space_cluster(bg, last_ptr, ffe_ctl->search_start, 36188c2ecf20Sopenharmony_ci ffe_ctl->num_bytes, aligned_cluster); 36198c2ecf20Sopenharmony_ci if (ret == 0) { 36208c2ecf20Sopenharmony_ci /* Now pull our allocation out of this cluster */ 36218c2ecf20Sopenharmony_ci offset = btrfs_alloc_from_cluster(bg, last_ptr, 36228c2ecf20Sopenharmony_ci ffe_ctl->num_bytes, ffe_ctl->search_start, 36238c2ecf20Sopenharmony_ci &ffe_ctl->max_extent_size); 36248c2ecf20Sopenharmony_ci if (offset) { 36258c2ecf20Sopenharmony_ci /* We found one, proceed */ 36268c2ecf20Sopenharmony_ci spin_unlock(&last_ptr->refill_lock); 36278c2ecf20Sopenharmony_ci trace_btrfs_reserve_extent_cluster(bg, 36288c2ecf20Sopenharmony_ci ffe_ctl->search_start, 36298c2ecf20Sopenharmony_ci ffe_ctl->num_bytes); 36308c2ecf20Sopenharmony_ci ffe_ctl->found_offset = offset; 36318c2ecf20Sopenharmony_ci return 0; 36328c2ecf20Sopenharmony_ci } 36338c2ecf20Sopenharmony_ci } else if (!ffe_ctl->cached && ffe_ctl->loop > LOOP_CACHING_NOWAIT && 36348c2ecf20Sopenharmony_ci !ffe_ctl->retry_clustered) { 36358c2ecf20Sopenharmony_ci spin_unlock(&last_ptr->refill_lock); 36368c2ecf20Sopenharmony_ci 36378c2ecf20Sopenharmony_ci ffe_ctl->retry_clustered = true; 36388c2ecf20Sopenharmony_ci btrfs_wait_block_group_cache_progress(bg, ffe_ctl->num_bytes + 36398c2ecf20Sopenharmony_ci ffe_ctl->empty_cluster + ffe_ctl->empty_size); 36408c2ecf20Sopenharmony_ci return -EAGAIN; 36418c2ecf20Sopenharmony_ci } 36428c2ecf20Sopenharmony_ci /* 36438c2ecf20Sopenharmony_ci * At this point we either didn't find a cluster or we weren't able to 36448c2ecf20Sopenharmony_ci * allocate a block from our cluster. Free the cluster we've been 36458c2ecf20Sopenharmony_ci * trying to use, and go to the next block group. 36468c2ecf20Sopenharmony_ci */ 36478c2ecf20Sopenharmony_ci btrfs_return_cluster_to_free_space(NULL, last_ptr); 36488c2ecf20Sopenharmony_ci spin_unlock(&last_ptr->refill_lock); 36498c2ecf20Sopenharmony_ci return 1; 36508c2ecf20Sopenharmony_ci} 36518c2ecf20Sopenharmony_ci 36528c2ecf20Sopenharmony_ci/* 36538c2ecf20Sopenharmony_ci * Return >0 to inform caller that we find nothing 36548c2ecf20Sopenharmony_ci * Return 0 when we found an free extent and set ffe_ctrl->found_offset 36558c2ecf20Sopenharmony_ci * Return -EAGAIN to inform caller that we need to re-search this block group 36568c2ecf20Sopenharmony_ci */ 36578c2ecf20Sopenharmony_cistatic int find_free_extent_unclustered(struct btrfs_block_group *bg, 36588c2ecf20Sopenharmony_ci struct find_free_extent_ctl *ffe_ctl) 36598c2ecf20Sopenharmony_ci{ 36608c2ecf20Sopenharmony_ci struct btrfs_free_cluster *last_ptr = ffe_ctl->last_ptr; 36618c2ecf20Sopenharmony_ci u64 offset; 36628c2ecf20Sopenharmony_ci 36638c2ecf20Sopenharmony_ci /* 36648c2ecf20Sopenharmony_ci * We are doing an unclustered allocation, set the fragmented flag so 36658c2ecf20Sopenharmony_ci * we don't bother trying to setup a cluster again until we get more 36668c2ecf20Sopenharmony_ci * space. 36678c2ecf20Sopenharmony_ci */ 36688c2ecf20Sopenharmony_ci if (unlikely(last_ptr)) { 36698c2ecf20Sopenharmony_ci spin_lock(&last_ptr->lock); 36708c2ecf20Sopenharmony_ci last_ptr->fragmented = 1; 36718c2ecf20Sopenharmony_ci spin_unlock(&last_ptr->lock); 36728c2ecf20Sopenharmony_ci } 36738c2ecf20Sopenharmony_ci if (ffe_ctl->cached) { 36748c2ecf20Sopenharmony_ci struct btrfs_free_space_ctl *free_space_ctl; 36758c2ecf20Sopenharmony_ci 36768c2ecf20Sopenharmony_ci free_space_ctl = bg->free_space_ctl; 36778c2ecf20Sopenharmony_ci spin_lock(&free_space_ctl->tree_lock); 36788c2ecf20Sopenharmony_ci if (free_space_ctl->free_space < 36798c2ecf20Sopenharmony_ci ffe_ctl->num_bytes + ffe_ctl->empty_cluster + 36808c2ecf20Sopenharmony_ci ffe_ctl->empty_size) { 36818c2ecf20Sopenharmony_ci ffe_ctl->total_free_space = max_t(u64, 36828c2ecf20Sopenharmony_ci ffe_ctl->total_free_space, 36838c2ecf20Sopenharmony_ci free_space_ctl->free_space); 36848c2ecf20Sopenharmony_ci spin_unlock(&free_space_ctl->tree_lock); 36858c2ecf20Sopenharmony_ci return 1; 36868c2ecf20Sopenharmony_ci } 36878c2ecf20Sopenharmony_ci spin_unlock(&free_space_ctl->tree_lock); 36888c2ecf20Sopenharmony_ci } 36898c2ecf20Sopenharmony_ci 36908c2ecf20Sopenharmony_ci offset = btrfs_find_space_for_alloc(bg, ffe_ctl->search_start, 36918c2ecf20Sopenharmony_ci ffe_ctl->num_bytes, ffe_ctl->empty_size, 36928c2ecf20Sopenharmony_ci &ffe_ctl->max_extent_size); 36938c2ecf20Sopenharmony_ci 36948c2ecf20Sopenharmony_ci /* 36958c2ecf20Sopenharmony_ci * If we didn't find a chunk, and we haven't failed on this block group 36968c2ecf20Sopenharmony_ci * before, and this block group is in the middle of caching and we are 36978c2ecf20Sopenharmony_ci * ok with waiting, then go ahead and wait for progress to be made, and 36988c2ecf20Sopenharmony_ci * set @retry_unclustered to true. 36998c2ecf20Sopenharmony_ci * 37008c2ecf20Sopenharmony_ci * If @retry_unclustered is true then we've already waited on this 37018c2ecf20Sopenharmony_ci * block group once and should move on to the next block group. 37028c2ecf20Sopenharmony_ci */ 37038c2ecf20Sopenharmony_ci if (!offset && !ffe_ctl->retry_unclustered && !ffe_ctl->cached && 37048c2ecf20Sopenharmony_ci ffe_ctl->loop > LOOP_CACHING_NOWAIT) { 37058c2ecf20Sopenharmony_ci btrfs_wait_block_group_cache_progress(bg, ffe_ctl->num_bytes + 37068c2ecf20Sopenharmony_ci ffe_ctl->empty_size); 37078c2ecf20Sopenharmony_ci ffe_ctl->retry_unclustered = true; 37088c2ecf20Sopenharmony_ci return -EAGAIN; 37098c2ecf20Sopenharmony_ci } else if (!offset) { 37108c2ecf20Sopenharmony_ci return 1; 37118c2ecf20Sopenharmony_ci } 37128c2ecf20Sopenharmony_ci ffe_ctl->found_offset = offset; 37138c2ecf20Sopenharmony_ci return 0; 37148c2ecf20Sopenharmony_ci} 37158c2ecf20Sopenharmony_ci 37168c2ecf20Sopenharmony_cistatic int do_allocation_clustered(struct btrfs_block_group *block_group, 37178c2ecf20Sopenharmony_ci struct find_free_extent_ctl *ffe_ctl, 37188c2ecf20Sopenharmony_ci struct btrfs_block_group **bg_ret) 37198c2ecf20Sopenharmony_ci{ 37208c2ecf20Sopenharmony_ci int ret; 37218c2ecf20Sopenharmony_ci 37228c2ecf20Sopenharmony_ci /* We want to try and use the cluster allocator, so lets look there */ 37238c2ecf20Sopenharmony_ci if (ffe_ctl->last_ptr && ffe_ctl->use_cluster) { 37248c2ecf20Sopenharmony_ci ret = find_free_extent_clustered(block_group, ffe_ctl, bg_ret); 37258c2ecf20Sopenharmony_ci if (ret >= 0 || ret == -EAGAIN) 37268c2ecf20Sopenharmony_ci return ret; 37278c2ecf20Sopenharmony_ci /* ret == -ENOENT case falls through */ 37288c2ecf20Sopenharmony_ci } 37298c2ecf20Sopenharmony_ci 37308c2ecf20Sopenharmony_ci return find_free_extent_unclustered(block_group, ffe_ctl); 37318c2ecf20Sopenharmony_ci} 37328c2ecf20Sopenharmony_ci 37338c2ecf20Sopenharmony_cistatic int do_allocation(struct btrfs_block_group *block_group, 37348c2ecf20Sopenharmony_ci struct find_free_extent_ctl *ffe_ctl, 37358c2ecf20Sopenharmony_ci struct btrfs_block_group **bg_ret) 37368c2ecf20Sopenharmony_ci{ 37378c2ecf20Sopenharmony_ci switch (ffe_ctl->policy) { 37388c2ecf20Sopenharmony_ci case BTRFS_EXTENT_ALLOC_CLUSTERED: 37398c2ecf20Sopenharmony_ci return do_allocation_clustered(block_group, ffe_ctl, bg_ret); 37408c2ecf20Sopenharmony_ci default: 37418c2ecf20Sopenharmony_ci BUG(); 37428c2ecf20Sopenharmony_ci } 37438c2ecf20Sopenharmony_ci} 37448c2ecf20Sopenharmony_ci 37458c2ecf20Sopenharmony_cistatic void release_block_group(struct btrfs_block_group *block_group, 37468c2ecf20Sopenharmony_ci struct find_free_extent_ctl *ffe_ctl, 37478c2ecf20Sopenharmony_ci int delalloc) 37488c2ecf20Sopenharmony_ci{ 37498c2ecf20Sopenharmony_ci switch (ffe_ctl->policy) { 37508c2ecf20Sopenharmony_ci case BTRFS_EXTENT_ALLOC_CLUSTERED: 37518c2ecf20Sopenharmony_ci ffe_ctl->retry_clustered = false; 37528c2ecf20Sopenharmony_ci ffe_ctl->retry_unclustered = false; 37538c2ecf20Sopenharmony_ci break; 37548c2ecf20Sopenharmony_ci default: 37558c2ecf20Sopenharmony_ci BUG(); 37568c2ecf20Sopenharmony_ci } 37578c2ecf20Sopenharmony_ci 37588c2ecf20Sopenharmony_ci BUG_ON(btrfs_bg_flags_to_raid_index(block_group->flags) != 37598c2ecf20Sopenharmony_ci ffe_ctl->index); 37608c2ecf20Sopenharmony_ci btrfs_release_block_group(block_group, delalloc); 37618c2ecf20Sopenharmony_ci} 37628c2ecf20Sopenharmony_ci 37638c2ecf20Sopenharmony_cistatic void found_extent_clustered(struct find_free_extent_ctl *ffe_ctl, 37648c2ecf20Sopenharmony_ci struct btrfs_key *ins) 37658c2ecf20Sopenharmony_ci{ 37668c2ecf20Sopenharmony_ci struct btrfs_free_cluster *last_ptr = ffe_ctl->last_ptr; 37678c2ecf20Sopenharmony_ci 37688c2ecf20Sopenharmony_ci if (!ffe_ctl->use_cluster && last_ptr) { 37698c2ecf20Sopenharmony_ci spin_lock(&last_ptr->lock); 37708c2ecf20Sopenharmony_ci last_ptr->window_start = ins->objectid; 37718c2ecf20Sopenharmony_ci spin_unlock(&last_ptr->lock); 37728c2ecf20Sopenharmony_ci } 37738c2ecf20Sopenharmony_ci} 37748c2ecf20Sopenharmony_ci 37758c2ecf20Sopenharmony_cistatic void found_extent(struct find_free_extent_ctl *ffe_ctl, 37768c2ecf20Sopenharmony_ci struct btrfs_key *ins) 37778c2ecf20Sopenharmony_ci{ 37788c2ecf20Sopenharmony_ci switch (ffe_ctl->policy) { 37798c2ecf20Sopenharmony_ci case BTRFS_EXTENT_ALLOC_CLUSTERED: 37808c2ecf20Sopenharmony_ci found_extent_clustered(ffe_ctl, ins); 37818c2ecf20Sopenharmony_ci break; 37828c2ecf20Sopenharmony_ci default: 37838c2ecf20Sopenharmony_ci BUG(); 37848c2ecf20Sopenharmony_ci } 37858c2ecf20Sopenharmony_ci} 37868c2ecf20Sopenharmony_ci 37878c2ecf20Sopenharmony_cistatic int chunk_allocation_failed(struct find_free_extent_ctl *ffe_ctl) 37888c2ecf20Sopenharmony_ci{ 37898c2ecf20Sopenharmony_ci switch (ffe_ctl->policy) { 37908c2ecf20Sopenharmony_ci case BTRFS_EXTENT_ALLOC_CLUSTERED: 37918c2ecf20Sopenharmony_ci /* 37928c2ecf20Sopenharmony_ci * If we can't allocate a new chunk we've already looped through 37938c2ecf20Sopenharmony_ci * at least once, move on to the NO_EMPTY_SIZE case. 37948c2ecf20Sopenharmony_ci */ 37958c2ecf20Sopenharmony_ci ffe_ctl->loop = LOOP_NO_EMPTY_SIZE; 37968c2ecf20Sopenharmony_ci return 0; 37978c2ecf20Sopenharmony_ci default: 37988c2ecf20Sopenharmony_ci BUG(); 37998c2ecf20Sopenharmony_ci } 38008c2ecf20Sopenharmony_ci} 38018c2ecf20Sopenharmony_ci 38028c2ecf20Sopenharmony_ci/* 38038c2ecf20Sopenharmony_ci * Return >0 means caller needs to re-search for free extent 38048c2ecf20Sopenharmony_ci * Return 0 means we have the needed free extent. 38058c2ecf20Sopenharmony_ci * Return <0 means we failed to locate any free extent. 38068c2ecf20Sopenharmony_ci */ 38078c2ecf20Sopenharmony_cistatic int find_free_extent_update_loop(struct btrfs_fs_info *fs_info, 38088c2ecf20Sopenharmony_ci struct btrfs_key *ins, 38098c2ecf20Sopenharmony_ci struct find_free_extent_ctl *ffe_ctl, 38108c2ecf20Sopenharmony_ci bool full_search) 38118c2ecf20Sopenharmony_ci{ 38128c2ecf20Sopenharmony_ci struct btrfs_root *root = fs_info->extent_root; 38138c2ecf20Sopenharmony_ci int ret; 38148c2ecf20Sopenharmony_ci 38158c2ecf20Sopenharmony_ci if ((ffe_ctl->loop == LOOP_CACHING_NOWAIT) && 38168c2ecf20Sopenharmony_ci ffe_ctl->have_caching_bg && !ffe_ctl->orig_have_caching_bg) 38178c2ecf20Sopenharmony_ci ffe_ctl->orig_have_caching_bg = true; 38188c2ecf20Sopenharmony_ci 38198c2ecf20Sopenharmony_ci if (!ins->objectid && ffe_ctl->loop >= LOOP_CACHING_WAIT && 38208c2ecf20Sopenharmony_ci ffe_ctl->have_caching_bg) 38218c2ecf20Sopenharmony_ci return 1; 38228c2ecf20Sopenharmony_ci 38238c2ecf20Sopenharmony_ci if (!ins->objectid && ++(ffe_ctl->index) < BTRFS_NR_RAID_TYPES) 38248c2ecf20Sopenharmony_ci return 1; 38258c2ecf20Sopenharmony_ci 38268c2ecf20Sopenharmony_ci if (ins->objectid) { 38278c2ecf20Sopenharmony_ci found_extent(ffe_ctl, ins); 38288c2ecf20Sopenharmony_ci return 0; 38298c2ecf20Sopenharmony_ci } 38308c2ecf20Sopenharmony_ci 38318c2ecf20Sopenharmony_ci /* 38328c2ecf20Sopenharmony_ci * LOOP_CACHING_NOWAIT, search partially cached block groups, kicking 38338c2ecf20Sopenharmony_ci * caching kthreads as we move along 38348c2ecf20Sopenharmony_ci * LOOP_CACHING_WAIT, search everything, and wait if our bg is caching 38358c2ecf20Sopenharmony_ci * LOOP_ALLOC_CHUNK, force a chunk allocation and try again 38368c2ecf20Sopenharmony_ci * LOOP_NO_EMPTY_SIZE, set empty_size and empty_cluster to 0 and try 38378c2ecf20Sopenharmony_ci * again 38388c2ecf20Sopenharmony_ci */ 38398c2ecf20Sopenharmony_ci if (ffe_ctl->loop < LOOP_NO_EMPTY_SIZE) { 38408c2ecf20Sopenharmony_ci ffe_ctl->index = 0; 38418c2ecf20Sopenharmony_ci if (ffe_ctl->loop == LOOP_CACHING_NOWAIT) { 38428c2ecf20Sopenharmony_ci /* 38438c2ecf20Sopenharmony_ci * We want to skip the LOOP_CACHING_WAIT step if we 38448c2ecf20Sopenharmony_ci * don't have any uncached bgs and we've already done a 38458c2ecf20Sopenharmony_ci * full search through. 38468c2ecf20Sopenharmony_ci */ 38478c2ecf20Sopenharmony_ci if (ffe_ctl->orig_have_caching_bg || !full_search) 38488c2ecf20Sopenharmony_ci ffe_ctl->loop = LOOP_CACHING_WAIT; 38498c2ecf20Sopenharmony_ci else 38508c2ecf20Sopenharmony_ci ffe_ctl->loop = LOOP_ALLOC_CHUNK; 38518c2ecf20Sopenharmony_ci } else { 38528c2ecf20Sopenharmony_ci ffe_ctl->loop++; 38538c2ecf20Sopenharmony_ci } 38548c2ecf20Sopenharmony_ci 38558c2ecf20Sopenharmony_ci if (ffe_ctl->loop == LOOP_ALLOC_CHUNK) { 38568c2ecf20Sopenharmony_ci struct btrfs_trans_handle *trans; 38578c2ecf20Sopenharmony_ci int exist = 0; 38588c2ecf20Sopenharmony_ci 38598c2ecf20Sopenharmony_ci trans = current->journal_info; 38608c2ecf20Sopenharmony_ci if (trans) 38618c2ecf20Sopenharmony_ci exist = 1; 38628c2ecf20Sopenharmony_ci else 38638c2ecf20Sopenharmony_ci trans = btrfs_join_transaction(root); 38648c2ecf20Sopenharmony_ci 38658c2ecf20Sopenharmony_ci if (IS_ERR(trans)) { 38668c2ecf20Sopenharmony_ci ret = PTR_ERR(trans); 38678c2ecf20Sopenharmony_ci return ret; 38688c2ecf20Sopenharmony_ci } 38698c2ecf20Sopenharmony_ci 38708c2ecf20Sopenharmony_ci ret = btrfs_chunk_alloc(trans, ffe_ctl->flags, 38718c2ecf20Sopenharmony_ci CHUNK_ALLOC_FORCE); 38728c2ecf20Sopenharmony_ci 38738c2ecf20Sopenharmony_ci /* Do not bail out on ENOSPC since we can do more. */ 38748c2ecf20Sopenharmony_ci if (ret == -ENOSPC) 38758c2ecf20Sopenharmony_ci ret = chunk_allocation_failed(ffe_ctl); 38768c2ecf20Sopenharmony_ci else if (ret < 0) 38778c2ecf20Sopenharmony_ci btrfs_abort_transaction(trans, ret); 38788c2ecf20Sopenharmony_ci else 38798c2ecf20Sopenharmony_ci ret = 0; 38808c2ecf20Sopenharmony_ci if (!exist) 38818c2ecf20Sopenharmony_ci btrfs_end_transaction(trans); 38828c2ecf20Sopenharmony_ci if (ret) 38838c2ecf20Sopenharmony_ci return ret; 38848c2ecf20Sopenharmony_ci } 38858c2ecf20Sopenharmony_ci 38868c2ecf20Sopenharmony_ci if (ffe_ctl->loop == LOOP_NO_EMPTY_SIZE) { 38878c2ecf20Sopenharmony_ci if (ffe_ctl->policy != BTRFS_EXTENT_ALLOC_CLUSTERED) 38888c2ecf20Sopenharmony_ci return -ENOSPC; 38898c2ecf20Sopenharmony_ci 38908c2ecf20Sopenharmony_ci /* 38918c2ecf20Sopenharmony_ci * Don't loop again if we already have no empty_size and 38928c2ecf20Sopenharmony_ci * no empty_cluster. 38938c2ecf20Sopenharmony_ci */ 38948c2ecf20Sopenharmony_ci if (ffe_ctl->empty_size == 0 && 38958c2ecf20Sopenharmony_ci ffe_ctl->empty_cluster == 0) 38968c2ecf20Sopenharmony_ci return -ENOSPC; 38978c2ecf20Sopenharmony_ci ffe_ctl->empty_size = 0; 38988c2ecf20Sopenharmony_ci ffe_ctl->empty_cluster = 0; 38998c2ecf20Sopenharmony_ci } 39008c2ecf20Sopenharmony_ci return 1; 39018c2ecf20Sopenharmony_ci } 39028c2ecf20Sopenharmony_ci return -ENOSPC; 39038c2ecf20Sopenharmony_ci} 39048c2ecf20Sopenharmony_ci 39058c2ecf20Sopenharmony_cistatic int prepare_allocation_clustered(struct btrfs_fs_info *fs_info, 39068c2ecf20Sopenharmony_ci struct find_free_extent_ctl *ffe_ctl, 39078c2ecf20Sopenharmony_ci struct btrfs_space_info *space_info, 39088c2ecf20Sopenharmony_ci struct btrfs_key *ins) 39098c2ecf20Sopenharmony_ci{ 39108c2ecf20Sopenharmony_ci /* 39118c2ecf20Sopenharmony_ci * If our free space is heavily fragmented we may not be able to make 39128c2ecf20Sopenharmony_ci * big contiguous allocations, so instead of doing the expensive search 39138c2ecf20Sopenharmony_ci * for free space, simply return ENOSPC with our max_extent_size so we 39148c2ecf20Sopenharmony_ci * can go ahead and search for a more manageable chunk. 39158c2ecf20Sopenharmony_ci * 39168c2ecf20Sopenharmony_ci * If our max_extent_size is large enough for our allocation simply 39178c2ecf20Sopenharmony_ci * disable clustering since we will likely not be able to find enough 39188c2ecf20Sopenharmony_ci * space to create a cluster and induce latency trying. 39198c2ecf20Sopenharmony_ci */ 39208c2ecf20Sopenharmony_ci if (space_info->max_extent_size) { 39218c2ecf20Sopenharmony_ci spin_lock(&space_info->lock); 39228c2ecf20Sopenharmony_ci if (space_info->max_extent_size && 39238c2ecf20Sopenharmony_ci ffe_ctl->num_bytes > space_info->max_extent_size) { 39248c2ecf20Sopenharmony_ci ins->offset = space_info->max_extent_size; 39258c2ecf20Sopenharmony_ci spin_unlock(&space_info->lock); 39268c2ecf20Sopenharmony_ci return -ENOSPC; 39278c2ecf20Sopenharmony_ci } else if (space_info->max_extent_size) { 39288c2ecf20Sopenharmony_ci ffe_ctl->use_cluster = false; 39298c2ecf20Sopenharmony_ci } 39308c2ecf20Sopenharmony_ci spin_unlock(&space_info->lock); 39318c2ecf20Sopenharmony_ci } 39328c2ecf20Sopenharmony_ci 39338c2ecf20Sopenharmony_ci ffe_ctl->last_ptr = fetch_cluster_info(fs_info, space_info, 39348c2ecf20Sopenharmony_ci &ffe_ctl->empty_cluster); 39358c2ecf20Sopenharmony_ci if (ffe_ctl->last_ptr) { 39368c2ecf20Sopenharmony_ci struct btrfs_free_cluster *last_ptr = ffe_ctl->last_ptr; 39378c2ecf20Sopenharmony_ci 39388c2ecf20Sopenharmony_ci spin_lock(&last_ptr->lock); 39398c2ecf20Sopenharmony_ci if (last_ptr->block_group) 39408c2ecf20Sopenharmony_ci ffe_ctl->hint_byte = last_ptr->window_start; 39418c2ecf20Sopenharmony_ci if (last_ptr->fragmented) { 39428c2ecf20Sopenharmony_ci /* 39438c2ecf20Sopenharmony_ci * We still set window_start so we can keep track of the 39448c2ecf20Sopenharmony_ci * last place we found an allocation to try and save 39458c2ecf20Sopenharmony_ci * some time. 39468c2ecf20Sopenharmony_ci */ 39478c2ecf20Sopenharmony_ci ffe_ctl->hint_byte = last_ptr->window_start; 39488c2ecf20Sopenharmony_ci ffe_ctl->use_cluster = false; 39498c2ecf20Sopenharmony_ci } 39508c2ecf20Sopenharmony_ci spin_unlock(&last_ptr->lock); 39518c2ecf20Sopenharmony_ci } 39528c2ecf20Sopenharmony_ci 39538c2ecf20Sopenharmony_ci return 0; 39548c2ecf20Sopenharmony_ci} 39558c2ecf20Sopenharmony_ci 39568c2ecf20Sopenharmony_cistatic int prepare_allocation(struct btrfs_fs_info *fs_info, 39578c2ecf20Sopenharmony_ci struct find_free_extent_ctl *ffe_ctl, 39588c2ecf20Sopenharmony_ci struct btrfs_space_info *space_info, 39598c2ecf20Sopenharmony_ci struct btrfs_key *ins) 39608c2ecf20Sopenharmony_ci{ 39618c2ecf20Sopenharmony_ci switch (ffe_ctl->policy) { 39628c2ecf20Sopenharmony_ci case BTRFS_EXTENT_ALLOC_CLUSTERED: 39638c2ecf20Sopenharmony_ci return prepare_allocation_clustered(fs_info, ffe_ctl, 39648c2ecf20Sopenharmony_ci space_info, ins); 39658c2ecf20Sopenharmony_ci default: 39668c2ecf20Sopenharmony_ci BUG(); 39678c2ecf20Sopenharmony_ci } 39688c2ecf20Sopenharmony_ci} 39698c2ecf20Sopenharmony_ci 39708c2ecf20Sopenharmony_ci/* 39718c2ecf20Sopenharmony_ci * walks the btree of allocated extents and find a hole of a given size. 39728c2ecf20Sopenharmony_ci * The key ins is changed to record the hole: 39738c2ecf20Sopenharmony_ci * ins->objectid == start position 39748c2ecf20Sopenharmony_ci * ins->flags = BTRFS_EXTENT_ITEM_KEY 39758c2ecf20Sopenharmony_ci * ins->offset == the size of the hole. 39768c2ecf20Sopenharmony_ci * Any available blocks before search_start are skipped. 39778c2ecf20Sopenharmony_ci * 39788c2ecf20Sopenharmony_ci * If there is no suitable free space, we will record the max size of 39798c2ecf20Sopenharmony_ci * the free space extent currently. 39808c2ecf20Sopenharmony_ci * 39818c2ecf20Sopenharmony_ci * The overall logic and call chain: 39828c2ecf20Sopenharmony_ci * 39838c2ecf20Sopenharmony_ci * find_free_extent() 39848c2ecf20Sopenharmony_ci * |- Iterate through all block groups 39858c2ecf20Sopenharmony_ci * | |- Get a valid block group 39868c2ecf20Sopenharmony_ci * | |- Try to do clustered allocation in that block group 39878c2ecf20Sopenharmony_ci * | |- Try to do unclustered allocation in that block group 39888c2ecf20Sopenharmony_ci * | |- Check if the result is valid 39898c2ecf20Sopenharmony_ci * | | |- If valid, then exit 39908c2ecf20Sopenharmony_ci * | |- Jump to next block group 39918c2ecf20Sopenharmony_ci * | 39928c2ecf20Sopenharmony_ci * |- Push harder to find free extents 39938c2ecf20Sopenharmony_ci * |- If not found, re-iterate all block groups 39948c2ecf20Sopenharmony_ci */ 39958c2ecf20Sopenharmony_cistatic noinline int find_free_extent(struct btrfs_root *root, 39968c2ecf20Sopenharmony_ci u64 ram_bytes, u64 num_bytes, u64 empty_size, 39978c2ecf20Sopenharmony_ci u64 hint_byte_orig, struct btrfs_key *ins, 39988c2ecf20Sopenharmony_ci u64 flags, int delalloc) 39998c2ecf20Sopenharmony_ci{ 40008c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = root->fs_info; 40018c2ecf20Sopenharmony_ci int ret = 0; 40028c2ecf20Sopenharmony_ci int cache_block_group_error = 0; 40038c2ecf20Sopenharmony_ci struct btrfs_block_group *block_group = NULL; 40048c2ecf20Sopenharmony_ci struct find_free_extent_ctl ffe_ctl = {0}; 40058c2ecf20Sopenharmony_ci struct btrfs_space_info *space_info; 40068c2ecf20Sopenharmony_ci bool full_search = false; 40078c2ecf20Sopenharmony_ci 40088c2ecf20Sopenharmony_ci WARN_ON(num_bytes < fs_info->sectorsize); 40098c2ecf20Sopenharmony_ci 40108c2ecf20Sopenharmony_ci ffe_ctl.num_bytes = num_bytes; 40118c2ecf20Sopenharmony_ci ffe_ctl.empty_size = empty_size; 40128c2ecf20Sopenharmony_ci ffe_ctl.flags = flags; 40138c2ecf20Sopenharmony_ci ffe_ctl.search_start = 0; 40148c2ecf20Sopenharmony_ci ffe_ctl.delalloc = delalloc; 40158c2ecf20Sopenharmony_ci ffe_ctl.index = btrfs_bg_flags_to_raid_index(flags); 40168c2ecf20Sopenharmony_ci ffe_ctl.have_caching_bg = false; 40178c2ecf20Sopenharmony_ci ffe_ctl.orig_have_caching_bg = false; 40188c2ecf20Sopenharmony_ci ffe_ctl.found_offset = 0; 40198c2ecf20Sopenharmony_ci ffe_ctl.hint_byte = hint_byte_orig; 40208c2ecf20Sopenharmony_ci ffe_ctl.policy = BTRFS_EXTENT_ALLOC_CLUSTERED; 40218c2ecf20Sopenharmony_ci 40228c2ecf20Sopenharmony_ci /* For clustered allocation */ 40238c2ecf20Sopenharmony_ci ffe_ctl.retry_clustered = false; 40248c2ecf20Sopenharmony_ci ffe_ctl.retry_unclustered = false; 40258c2ecf20Sopenharmony_ci ffe_ctl.last_ptr = NULL; 40268c2ecf20Sopenharmony_ci ffe_ctl.use_cluster = true; 40278c2ecf20Sopenharmony_ci 40288c2ecf20Sopenharmony_ci ins->type = BTRFS_EXTENT_ITEM_KEY; 40298c2ecf20Sopenharmony_ci ins->objectid = 0; 40308c2ecf20Sopenharmony_ci ins->offset = 0; 40318c2ecf20Sopenharmony_ci 40328c2ecf20Sopenharmony_ci trace_find_free_extent(root, num_bytes, empty_size, flags); 40338c2ecf20Sopenharmony_ci 40348c2ecf20Sopenharmony_ci space_info = btrfs_find_space_info(fs_info, flags); 40358c2ecf20Sopenharmony_ci if (!space_info) { 40368c2ecf20Sopenharmony_ci btrfs_err(fs_info, "No space info for %llu", flags); 40378c2ecf20Sopenharmony_ci return -ENOSPC; 40388c2ecf20Sopenharmony_ci } 40398c2ecf20Sopenharmony_ci 40408c2ecf20Sopenharmony_ci ret = prepare_allocation(fs_info, &ffe_ctl, space_info, ins); 40418c2ecf20Sopenharmony_ci if (ret < 0) 40428c2ecf20Sopenharmony_ci return ret; 40438c2ecf20Sopenharmony_ci 40448c2ecf20Sopenharmony_ci ffe_ctl.search_start = max(ffe_ctl.search_start, 40458c2ecf20Sopenharmony_ci first_logical_byte(fs_info, 0)); 40468c2ecf20Sopenharmony_ci ffe_ctl.search_start = max(ffe_ctl.search_start, ffe_ctl.hint_byte); 40478c2ecf20Sopenharmony_ci if (ffe_ctl.search_start == ffe_ctl.hint_byte) { 40488c2ecf20Sopenharmony_ci block_group = btrfs_lookup_block_group(fs_info, 40498c2ecf20Sopenharmony_ci ffe_ctl.search_start); 40508c2ecf20Sopenharmony_ci /* 40518c2ecf20Sopenharmony_ci * we don't want to use the block group if it doesn't match our 40528c2ecf20Sopenharmony_ci * allocation bits, or if its not cached. 40538c2ecf20Sopenharmony_ci * 40548c2ecf20Sopenharmony_ci * However if we are re-searching with an ideal block group 40558c2ecf20Sopenharmony_ci * picked out then we don't care that the block group is cached. 40568c2ecf20Sopenharmony_ci */ 40578c2ecf20Sopenharmony_ci if (block_group && block_group_bits(block_group, flags) && 40588c2ecf20Sopenharmony_ci block_group->cached != BTRFS_CACHE_NO) { 40598c2ecf20Sopenharmony_ci down_read(&space_info->groups_sem); 40608c2ecf20Sopenharmony_ci if (list_empty(&block_group->list) || 40618c2ecf20Sopenharmony_ci block_group->ro) { 40628c2ecf20Sopenharmony_ci /* 40638c2ecf20Sopenharmony_ci * someone is removing this block group, 40648c2ecf20Sopenharmony_ci * we can't jump into the have_block_group 40658c2ecf20Sopenharmony_ci * target because our list pointers are not 40668c2ecf20Sopenharmony_ci * valid 40678c2ecf20Sopenharmony_ci */ 40688c2ecf20Sopenharmony_ci btrfs_put_block_group(block_group); 40698c2ecf20Sopenharmony_ci up_read(&space_info->groups_sem); 40708c2ecf20Sopenharmony_ci } else { 40718c2ecf20Sopenharmony_ci ffe_ctl.index = btrfs_bg_flags_to_raid_index( 40728c2ecf20Sopenharmony_ci block_group->flags); 40738c2ecf20Sopenharmony_ci btrfs_lock_block_group(block_group, delalloc); 40748c2ecf20Sopenharmony_ci goto have_block_group; 40758c2ecf20Sopenharmony_ci } 40768c2ecf20Sopenharmony_ci } else if (block_group) { 40778c2ecf20Sopenharmony_ci btrfs_put_block_group(block_group); 40788c2ecf20Sopenharmony_ci } 40798c2ecf20Sopenharmony_ci } 40808c2ecf20Sopenharmony_cisearch: 40818c2ecf20Sopenharmony_ci ffe_ctl.have_caching_bg = false; 40828c2ecf20Sopenharmony_ci if (ffe_ctl.index == btrfs_bg_flags_to_raid_index(flags) || 40838c2ecf20Sopenharmony_ci ffe_ctl.index == 0) 40848c2ecf20Sopenharmony_ci full_search = true; 40858c2ecf20Sopenharmony_ci down_read(&space_info->groups_sem); 40868c2ecf20Sopenharmony_ci list_for_each_entry(block_group, 40878c2ecf20Sopenharmony_ci &space_info->block_groups[ffe_ctl.index], list) { 40888c2ecf20Sopenharmony_ci struct btrfs_block_group *bg_ret; 40898c2ecf20Sopenharmony_ci 40908c2ecf20Sopenharmony_ci /* If the block group is read-only, we can skip it entirely. */ 40918c2ecf20Sopenharmony_ci if (unlikely(block_group->ro)) 40928c2ecf20Sopenharmony_ci continue; 40938c2ecf20Sopenharmony_ci 40948c2ecf20Sopenharmony_ci btrfs_grab_block_group(block_group, delalloc); 40958c2ecf20Sopenharmony_ci ffe_ctl.search_start = block_group->start; 40968c2ecf20Sopenharmony_ci 40978c2ecf20Sopenharmony_ci /* 40988c2ecf20Sopenharmony_ci * this can happen if we end up cycling through all the 40998c2ecf20Sopenharmony_ci * raid types, but we want to make sure we only allocate 41008c2ecf20Sopenharmony_ci * for the proper type. 41018c2ecf20Sopenharmony_ci */ 41028c2ecf20Sopenharmony_ci if (!block_group_bits(block_group, flags)) { 41038c2ecf20Sopenharmony_ci u64 extra = BTRFS_BLOCK_GROUP_DUP | 41048c2ecf20Sopenharmony_ci BTRFS_BLOCK_GROUP_RAID1_MASK | 41058c2ecf20Sopenharmony_ci BTRFS_BLOCK_GROUP_RAID56_MASK | 41068c2ecf20Sopenharmony_ci BTRFS_BLOCK_GROUP_RAID10; 41078c2ecf20Sopenharmony_ci 41088c2ecf20Sopenharmony_ci /* 41098c2ecf20Sopenharmony_ci * if they asked for extra copies and this block group 41108c2ecf20Sopenharmony_ci * doesn't provide them, bail. This does allow us to 41118c2ecf20Sopenharmony_ci * fill raid0 from raid1. 41128c2ecf20Sopenharmony_ci */ 41138c2ecf20Sopenharmony_ci if ((flags & extra) && !(block_group->flags & extra)) 41148c2ecf20Sopenharmony_ci goto loop; 41158c2ecf20Sopenharmony_ci 41168c2ecf20Sopenharmony_ci /* 41178c2ecf20Sopenharmony_ci * This block group has different flags than we want. 41188c2ecf20Sopenharmony_ci * It's possible that we have MIXED_GROUP flag but no 41198c2ecf20Sopenharmony_ci * block group is mixed. Just skip such block group. 41208c2ecf20Sopenharmony_ci */ 41218c2ecf20Sopenharmony_ci btrfs_release_block_group(block_group, delalloc); 41228c2ecf20Sopenharmony_ci continue; 41238c2ecf20Sopenharmony_ci } 41248c2ecf20Sopenharmony_ci 41258c2ecf20Sopenharmony_cihave_block_group: 41268c2ecf20Sopenharmony_ci ffe_ctl.cached = btrfs_block_group_done(block_group); 41278c2ecf20Sopenharmony_ci if (unlikely(!ffe_ctl.cached)) { 41288c2ecf20Sopenharmony_ci ffe_ctl.have_caching_bg = true; 41298c2ecf20Sopenharmony_ci ret = btrfs_cache_block_group(block_group, 0); 41308c2ecf20Sopenharmony_ci 41318c2ecf20Sopenharmony_ci /* 41328c2ecf20Sopenharmony_ci * If we get ENOMEM here or something else we want to 41338c2ecf20Sopenharmony_ci * try other block groups, because it may not be fatal. 41348c2ecf20Sopenharmony_ci * However if we can't find anything else we need to 41358c2ecf20Sopenharmony_ci * save our return here so that we return the actual 41368c2ecf20Sopenharmony_ci * error that caused problems, not ENOSPC. 41378c2ecf20Sopenharmony_ci */ 41388c2ecf20Sopenharmony_ci if (ret < 0) { 41398c2ecf20Sopenharmony_ci if (!cache_block_group_error) 41408c2ecf20Sopenharmony_ci cache_block_group_error = ret; 41418c2ecf20Sopenharmony_ci ret = 0; 41428c2ecf20Sopenharmony_ci goto loop; 41438c2ecf20Sopenharmony_ci } 41448c2ecf20Sopenharmony_ci ret = 0; 41458c2ecf20Sopenharmony_ci } 41468c2ecf20Sopenharmony_ci 41478c2ecf20Sopenharmony_ci if (unlikely(block_group->cached == BTRFS_CACHE_ERROR)) { 41488c2ecf20Sopenharmony_ci if (!cache_block_group_error) 41498c2ecf20Sopenharmony_ci cache_block_group_error = -EIO; 41508c2ecf20Sopenharmony_ci goto loop; 41518c2ecf20Sopenharmony_ci } 41528c2ecf20Sopenharmony_ci 41538c2ecf20Sopenharmony_ci bg_ret = NULL; 41548c2ecf20Sopenharmony_ci ret = do_allocation(block_group, &ffe_ctl, &bg_ret); 41558c2ecf20Sopenharmony_ci if (ret == 0) { 41568c2ecf20Sopenharmony_ci if (bg_ret && bg_ret != block_group) { 41578c2ecf20Sopenharmony_ci btrfs_release_block_group(block_group, delalloc); 41588c2ecf20Sopenharmony_ci block_group = bg_ret; 41598c2ecf20Sopenharmony_ci } 41608c2ecf20Sopenharmony_ci } else if (ret == -EAGAIN) { 41618c2ecf20Sopenharmony_ci goto have_block_group; 41628c2ecf20Sopenharmony_ci } else if (ret > 0) { 41638c2ecf20Sopenharmony_ci goto loop; 41648c2ecf20Sopenharmony_ci } 41658c2ecf20Sopenharmony_ci 41668c2ecf20Sopenharmony_ci /* Checks */ 41678c2ecf20Sopenharmony_ci ffe_ctl.search_start = round_up(ffe_ctl.found_offset, 41688c2ecf20Sopenharmony_ci fs_info->stripesize); 41698c2ecf20Sopenharmony_ci 41708c2ecf20Sopenharmony_ci /* move on to the next group */ 41718c2ecf20Sopenharmony_ci if (ffe_ctl.search_start + num_bytes > 41728c2ecf20Sopenharmony_ci block_group->start + block_group->length) { 41738c2ecf20Sopenharmony_ci btrfs_add_free_space(block_group, ffe_ctl.found_offset, 41748c2ecf20Sopenharmony_ci num_bytes); 41758c2ecf20Sopenharmony_ci goto loop; 41768c2ecf20Sopenharmony_ci } 41778c2ecf20Sopenharmony_ci 41788c2ecf20Sopenharmony_ci if (ffe_ctl.found_offset < ffe_ctl.search_start) 41798c2ecf20Sopenharmony_ci btrfs_add_free_space(block_group, ffe_ctl.found_offset, 41808c2ecf20Sopenharmony_ci ffe_ctl.search_start - ffe_ctl.found_offset); 41818c2ecf20Sopenharmony_ci 41828c2ecf20Sopenharmony_ci ret = btrfs_add_reserved_bytes(block_group, ram_bytes, 41838c2ecf20Sopenharmony_ci num_bytes, delalloc); 41848c2ecf20Sopenharmony_ci if (ret == -EAGAIN) { 41858c2ecf20Sopenharmony_ci btrfs_add_free_space(block_group, ffe_ctl.found_offset, 41868c2ecf20Sopenharmony_ci num_bytes); 41878c2ecf20Sopenharmony_ci goto loop; 41888c2ecf20Sopenharmony_ci } 41898c2ecf20Sopenharmony_ci btrfs_inc_block_group_reservations(block_group); 41908c2ecf20Sopenharmony_ci 41918c2ecf20Sopenharmony_ci /* we are all good, lets return */ 41928c2ecf20Sopenharmony_ci ins->objectid = ffe_ctl.search_start; 41938c2ecf20Sopenharmony_ci ins->offset = num_bytes; 41948c2ecf20Sopenharmony_ci 41958c2ecf20Sopenharmony_ci trace_btrfs_reserve_extent(block_group, ffe_ctl.search_start, 41968c2ecf20Sopenharmony_ci num_bytes); 41978c2ecf20Sopenharmony_ci btrfs_release_block_group(block_group, delalloc); 41988c2ecf20Sopenharmony_ci break; 41998c2ecf20Sopenharmony_ciloop: 42008c2ecf20Sopenharmony_ci release_block_group(block_group, &ffe_ctl, delalloc); 42018c2ecf20Sopenharmony_ci cond_resched(); 42028c2ecf20Sopenharmony_ci } 42038c2ecf20Sopenharmony_ci up_read(&space_info->groups_sem); 42048c2ecf20Sopenharmony_ci 42058c2ecf20Sopenharmony_ci ret = find_free_extent_update_loop(fs_info, ins, &ffe_ctl, full_search); 42068c2ecf20Sopenharmony_ci if (ret > 0) 42078c2ecf20Sopenharmony_ci goto search; 42088c2ecf20Sopenharmony_ci 42098c2ecf20Sopenharmony_ci if (ret == -ENOSPC && !cache_block_group_error) { 42108c2ecf20Sopenharmony_ci /* 42118c2ecf20Sopenharmony_ci * Use ffe_ctl->total_free_space as fallback if we can't find 42128c2ecf20Sopenharmony_ci * any contiguous hole. 42138c2ecf20Sopenharmony_ci */ 42148c2ecf20Sopenharmony_ci if (!ffe_ctl.max_extent_size) 42158c2ecf20Sopenharmony_ci ffe_ctl.max_extent_size = ffe_ctl.total_free_space; 42168c2ecf20Sopenharmony_ci spin_lock(&space_info->lock); 42178c2ecf20Sopenharmony_ci space_info->max_extent_size = ffe_ctl.max_extent_size; 42188c2ecf20Sopenharmony_ci spin_unlock(&space_info->lock); 42198c2ecf20Sopenharmony_ci ins->offset = ffe_ctl.max_extent_size; 42208c2ecf20Sopenharmony_ci } else if (ret == -ENOSPC) { 42218c2ecf20Sopenharmony_ci ret = cache_block_group_error; 42228c2ecf20Sopenharmony_ci } 42238c2ecf20Sopenharmony_ci return ret; 42248c2ecf20Sopenharmony_ci} 42258c2ecf20Sopenharmony_ci 42268c2ecf20Sopenharmony_ci/* 42278c2ecf20Sopenharmony_ci * btrfs_reserve_extent - entry point to the extent allocator. Tries to find a 42288c2ecf20Sopenharmony_ci * hole that is at least as big as @num_bytes. 42298c2ecf20Sopenharmony_ci * 42308c2ecf20Sopenharmony_ci * @root - The root that will contain this extent 42318c2ecf20Sopenharmony_ci * 42328c2ecf20Sopenharmony_ci * @ram_bytes - The amount of space in ram that @num_bytes take. This 42338c2ecf20Sopenharmony_ci * is used for accounting purposes. This value differs 42348c2ecf20Sopenharmony_ci * from @num_bytes only in the case of compressed extents. 42358c2ecf20Sopenharmony_ci * 42368c2ecf20Sopenharmony_ci * @num_bytes - Number of bytes to allocate on-disk. 42378c2ecf20Sopenharmony_ci * 42388c2ecf20Sopenharmony_ci * @min_alloc_size - Indicates the minimum amount of space that the 42398c2ecf20Sopenharmony_ci * allocator should try to satisfy. In some cases 42408c2ecf20Sopenharmony_ci * @num_bytes may be larger than what is required and if 42418c2ecf20Sopenharmony_ci * the filesystem is fragmented then allocation fails. 42428c2ecf20Sopenharmony_ci * However, the presence of @min_alloc_size gives a 42438c2ecf20Sopenharmony_ci * chance to try and satisfy the smaller allocation. 42448c2ecf20Sopenharmony_ci * 42458c2ecf20Sopenharmony_ci * @empty_size - A hint that you plan on doing more COW. This is the 42468c2ecf20Sopenharmony_ci * size in bytes the allocator should try to find free 42478c2ecf20Sopenharmony_ci * next to the block it returns. This is just a hint and 42488c2ecf20Sopenharmony_ci * may be ignored by the allocator. 42498c2ecf20Sopenharmony_ci * 42508c2ecf20Sopenharmony_ci * @hint_byte - Hint to the allocator to start searching above the byte 42518c2ecf20Sopenharmony_ci * address passed. It might be ignored. 42528c2ecf20Sopenharmony_ci * 42538c2ecf20Sopenharmony_ci * @ins - This key is modified to record the found hole. It will 42548c2ecf20Sopenharmony_ci * have the following values: 42558c2ecf20Sopenharmony_ci * ins->objectid == start position 42568c2ecf20Sopenharmony_ci * ins->flags = BTRFS_EXTENT_ITEM_KEY 42578c2ecf20Sopenharmony_ci * ins->offset == the size of the hole. 42588c2ecf20Sopenharmony_ci * 42598c2ecf20Sopenharmony_ci * @is_data - Boolean flag indicating whether an extent is 42608c2ecf20Sopenharmony_ci * allocated for data (true) or metadata (false) 42618c2ecf20Sopenharmony_ci * 42628c2ecf20Sopenharmony_ci * @delalloc - Boolean flag indicating whether this allocation is for 42638c2ecf20Sopenharmony_ci * delalloc or not. If 'true' data_rwsem of block groups 42648c2ecf20Sopenharmony_ci * is going to be acquired. 42658c2ecf20Sopenharmony_ci * 42668c2ecf20Sopenharmony_ci * 42678c2ecf20Sopenharmony_ci * Returns 0 when an allocation succeeded or < 0 when an error occurred. In 42688c2ecf20Sopenharmony_ci * case -ENOSPC is returned then @ins->offset will contain the size of the 42698c2ecf20Sopenharmony_ci * largest available hole the allocator managed to find. 42708c2ecf20Sopenharmony_ci */ 42718c2ecf20Sopenharmony_ciint btrfs_reserve_extent(struct btrfs_root *root, u64 ram_bytes, 42728c2ecf20Sopenharmony_ci u64 num_bytes, u64 min_alloc_size, 42738c2ecf20Sopenharmony_ci u64 empty_size, u64 hint_byte, 42748c2ecf20Sopenharmony_ci struct btrfs_key *ins, int is_data, int delalloc) 42758c2ecf20Sopenharmony_ci{ 42768c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = root->fs_info; 42778c2ecf20Sopenharmony_ci bool final_tried = num_bytes == min_alloc_size; 42788c2ecf20Sopenharmony_ci u64 flags; 42798c2ecf20Sopenharmony_ci int ret; 42808c2ecf20Sopenharmony_ci 42818c2ecf20Sopenharmony_ci flags = get_alloc_profile_by_root(root, is_data); 42828c2ecf20Sopenharmony_ciagain: 42838c2ecf20Sopenharmony_ci WARN_ON(num_bytes < fs_info->sectorsize); 42848c2ecf20Sopenharmony_ci ret = find_free_extent(root, ram_bytes, num_bytes, empty_size, 42858c2ecf20Sopenharmony_ci hint_byte, ins, flags, delalloc); 42868c2ecf20Sopenharmony_ci if (!ret && !is_data) { 42878c2ecf20Sopenharmony_ci btrfs_dec_block_group_reservations(fs_info, ins->objectid); 42888c2ecf20Sopenharmony_ci } else if (ret == -ENOSPC) { 42898c2ecf20Sopenharmony_ci if (!final_tried && ins->offset) { 42908c2ecf20Sopenharmony_ci num_bytes = min(num_bytes >> 1, ins->offset); 42918c2ecf20Sopenharmony_ci num_bytes = round_down(num_bytes, 42928c2ecf20Sopenharmony_ci fs_info->sectorsize); 42938c2ecf20Sopenharmony_ci num_bytes = max(num_bytes, min_alloc_size); 42948c2ecf20Sopenharmony_ci ram_bytes = num_bytes; 42958c2ecf20Sopenharmony_ci if (num_bytes == min_alloc_size) 42968c2ecf20Sopenharmony_ci final_tried = true; 42978c2ecf20Sopenharmony_ci goto again; 42988c2ecf20Sopenharmony_ci } else if (btrfs_test_opt(fs_info, ENOSPC_DEBUG)) { 42998c2ecf20Sopenharmony_ci struct btrfs_space_info *sinfo; 43008c2ecf20Sopenharmony_ci 43018c2ecf20Sopenharmony_ci sinfo = btrfs_find_space_info(fs_info, flags); 43028c2ecf20Sopenharmony_ci btrfs_err(fs_info, 43038c2ecf20Sopenharmony_ci "allocation failed flags %llu, wanted %llu", 43048c2ecf20Sopenharmony_ci flags, num_bytes); 43058c2ecf20Sopenharmony_ci if (sinfo) 43068c2ecf20Sopenharmony_ci btrfs_dump_space_info(fs_info, sinfo, 43078c2ecf20Sopenharmony_ci num_bytes, 1); 43088c2ecf20Sopenharmony_ci } 43098c2ecf20Sopenharmony_ci } 43108c2ecf20Sopenharmony_ci 43118c2ecf20Sopenharmony_ci return ret; 43128c2ecf20Sopenharmony_ci} 43138c2ecf20Sopenharmony_ci 43148c2ecf20Sopenharmony_ciint btrfs_free_reserved_extent(struct btrfs_fs_info *fs_info, 43158c2ecf20Sopenharmony_ci u64 start, u64 len, int delalloc) 43168c2ecf20Sopenharmony_ci{ 43178c2ecf20Sopenharmony_ci struct btrfs_block_group *cache; 43188c2ecf20Sopenharmony_ci 43198c2ecf20Sopenharmony_ci cache = btrfs_lookup_block_group(fs_info, start); 43208c2ecf20Sopenharmony_ci if (!cache) { 43218c2ecf20Sopenharmony_ci btrfs_err(fs_info, "Unable to find block group for %llu", 43228c2ecf20Sopenharmony_ci start); 43238c2ecf20Sopenharmony_ci return -ENOSPC; 43248c2ecf20Sopenharmony_ci } 43258c2ecf20Sopenharmony_ci 43268c2ecf20Sopenharmony_ci btrfs_add_free_space(cache, start, len); 43278c2ecf20Sopenharmony_ci btrfs_free_reserved_bytes(cache, len, delalloc); 43288c2ecf20Sopenharmony_ci trace_btrfs_reserved_extent_free(fs_info, start, len); 43298c2ecf20Sopenharmony_ci 43308c2ecf20Sopenharmony_ci btrfs_put_block_group(cache); 43318c2ecf20Sopenharmony_ci return 0; 43328c2ecf20Sopenharmony_ci} 43338c2ecf20Sopenharmony_ci 43348c2ecf20Sopenharmony_ciint btrfs_pin_reserved_extent(struct btrfs_trans_handle *trans, u64 start, 43358c2ecf20Sopenharmony_ci u64 len) 43368c2ecf20Sopenharmony_ci{ 43378c2ecf20Sopenharmony_ci struct btrfs_block_group *cache; 43388c2ecf20Sopenharmony_ci int ret = 0; 43398c2ecf20Sopenharmony_ci 43408c2ecf20Sopenharmony_ci cache = btrfs_lookup_block_group(trans->fs_info, start); 43418c2ecf20Sopenharmony_ci if (!cache) { 43428c2ecf20Sopenharmony_ci btrfs_err(trans->fs_info, "unable to find block group for %llu", 43438c2ecf20Sopenharmony_ci start); 43448c2ecf20Sopenharmony_ci return -ENOSPC; 43458c2ecf20Sopenharmony_ci } 43468c2ecf20Sopenharmony_ci 43478c2ecf20Sopenharmony_ci ret = pin_down_extent(trans, cache, start, len, 1); 43488c2ecf20Sopenharmony_ci btrfs_put_block_group(cache); 43498c2ecf20Sopenharmony_ci return ret; 43508c2ecf20Sopenharmony_ci} 43518c2ecf20Sopenharmony_ci 43528c2ecf20Sopenharmony_cistatic int alloc_reserved_file_extent(struct btrfs_trans_handle *trans, 43538c2ecf20Sopenharmony_ci u64 parent, u64 root_objectid, 43548c2ecf20Sopenharmony_ci u64 flags, u64 owner, u64 offset, 43558c2ecf20Sopenharmony_ci struct btrfs_key *ins, int ref_mod) 43568c2ecf20Sopenharmony_ci{ 43578c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = trans->fs_info; 43588c2ecf20Sopenharmony_ci int ret; 43598c2ecf20Sopenharmony_ci struct btrfs_extent_item *extent_item; 43608c2ecf20Sopenharmony_ci struct btrfs_extent_inline_ref *iref; 43618c2ecf20Sopenharmony_ci struct btrfs_path *path; 43628c2ecf20Sopenharmony_ci struct extent_buffer *leaf; 43638c2ecf20Sopenharmony_ci int type; 43648c2ecf20Sopenharmony_ci u32 size; 43658c2ecf20Sopenharmony_ci 43668c2ecf20Sopenharmony_ci if (parent > 0) 43678c2ecf20Sopenharmony_ci type = BTRFS_SHARED_DATA_REF_KEY; 43688c2ecf20Sopenharmony_ci else 43698c2ecf20Sopenharmony_ci type = BTRFS_EXTENT_DATA_REF_KEY; 43708c2ecf20Sopenharmony_ci 43718c2ecf20Sopenharmony_ci size = sizeof(*extent_item) + btrfs_extent_inline_ref_size(type); 43728c2ecf20Sopenharmony_ci 43738c2ecf20Sopenharmony_ci path = btrfs_alloc_path(); 43748c2ecf20Sopenharmony_ci if (!path) 43758c2ecf20Sopenharmony_ci return -ENOMEM; 43768c2ecf20Sopenharmony_ci 43778c2ecf20Sopenharmony_ci path->leave_spinning = 1; 43788c2ecf20Sopenharmony_ci ret = btrfs_insert_empty_item(trans, fs_info->extent_root, path, 43798c2ecf20Sopenharmony_ci ins, size); 43808c2ecf20Sopenharmony_ci if (ret) { 43818c2ecf20Sopenharmony_ci btrfs_free_path(path); 43828c2ecf20Sopenharmony_ci return ret; 43838c2ecf20Sopenharmony_ci } 43848c2ecf20Sopenharmony_ci 43858c2ecf20Sopenharmony_ci leaf = path->nodes[0]; 43868c2ecf20Sopenharmony_ci extent_item = btrfs_item_ptr(leaf, path->slots[0], 43878c2ecf20Sopenharmony_ci struct btrfs_extent_item); 43888c2ecf20Sopenharmony_ci btrfs_set_extent_refs(leaf, extent_item, ref_mod); 43898c2ecf20Sopenharmony_ci btrfs_set_extent_generation(leaf, extent_item, trans->transid); 43908c2ecf20Sopenharmony_ci btrfs_set_extent_flags(leaf, extent_item, 43918c2ecf20Sopenharmony_ci flags | BTRFS_EXTENT_FLAG_DATA); 43928c2ecf20Sopenharmony_ci 43938c2ecf20Sopenharmony_ci iref = (struct btrfs_extent_inline_ref *)(extent_item + 1); 43948c2ecf20Sopenharmony_ci btrfs_set_extent_inline_ref_type(leaf, iref, type); 43958c2ecf20Sopenharmony_ci if (parent > 0) { 43968c2ecf20Sopenharmony_ci struct btrfs_shared_data_ref *ref; 43978c2ecf20Sopenharmony_ci ref = (struct btrfs_shared_data_ref *)(iref + 1); 43988c2ecf20Sopenharmony_ci btrfs_set_extent_inline_ref_offset(leaf, iref, parent); 43998c2ecf20Sopenharmony_ci btrfs_set_shared_data_ref_count(leaf, ref, ref_mod); 44008c2ecf20Sopenharmony_ci } else { 44018c2ecf20Sopenharmony_ci struct btrfs_extent_data_ref *ref; 44028c2ecf20Sopenharmony_ci ref = (struct btrfs_extent_data_ref *)(&iref->offset); 44038c2ecf20Sopenharmony_ci btrfs_set_extent_data_ref_root(leaf, ref, root_objectid); 44048c2ecf20Sopenharmony_ci btrfs_set_extent_data_ref_objectid(leaf, ref, owner); 44058c2ecf20Sopenharmony_ci btrfs_set_extent_data_ref_offset(leaf, ref, offset); 44068c2ecf20Sopenharmony_ci btrfs_set_extent_data_ref_count(leaf, ref, ref_mod); 44078c2ecf20Sopenharmony_ci } 44088c2ecf20Sopenharmony_ci 44098c2ecf20Sopenharmony_ci btrfs_mark_buffer_dirty(path->nodes[0]); 44108c2ecf20Sopenharmony_ci btrfs_free_path(path); 44118c2ecf20Sopenharmony_ci 44128c2ecf20Sopenharmony_ci ret = remove_from_free_space_tree(trans, ins->objectid, ins->offset); 44138c2ecf20Sopenharmony_ci if (ret) 44148c2ecf20Sopenharmony_ci return ret; 44158c2ecf20Sopenharmony_ci 44168c2ecf20Sopenharmony_ci ret = btrfs_update_block_group(trans, ins->objectid, ins->offset, 1); 44178c2ecf20Sopenharmony_ci if (ret) { /* -ENOENT, logic error */ 44188c2ecf20Sopenharmony_ci btrfs_err(fs_info, "update block group failed for %llu %llu", 44198c2ecf20Sopenharmony_ci ins->objectid, ins->offset); 44208c2ecf20Sopenharmony_ci BUG(); 44218c2ecf20Sopenharmony_ci } 44228c2ecf20Sopenharmony_ci trace_btrfs_reserved_extent_alloc(fs_info, ins->objectid, ins->offset); 44238c2ecf20Sopenharmony_ci return ret; 44248c2ecf20Sopenharmony_ci} 44258c2ecf20Sopenharmony_ci 44268c2ecf20Sopenharmony_cistatic int alloc_reserved_tree_block(struct btrfs_trans_handle *trans, 44278c2ecf20Sopenharmony_ci struct btrfs_delayed_ref_node *node, 44288c2ecf20Sopenharmony_ci struct btrfs_delayed_extent_op *extent_op) 44298c2ecf20Sopenharmony_ci{ 44308c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = trans->fs_info; 44318c2ecf20Sopenharmony_ci int ret; 44328c2ecf20Sopenharmony_ci struct btrfs_extent_item *extent_item; 44338c2ecf20Sopenharmony_ci struct btrfs_key extent_key; 44348c2ecf20Sopenharmony_ci struct btrfs_tree_block_info *block_info; 44358c2ecf20Sopenharmony_ci struct btrfs_extent_inline_ref *iref; 44368c2ecf20Sopenharmony_ci struct btrfs_path *path; 44378c2ecf20Sopenharmony_ci struct extent_buffer *leaf; 44388c2ecf20Sopenharmony_ci struct btrfs_delayed_tree_ref *ref; 44398c2ecf20Sopenharmony_ci u32 size = sizeof(*extent_item) + sizeof(*iref); 44408c2ecf20Sopenharmony_ci u64 num_bytes; 44418c2ecf20Sopenharmony_ci u64 flags = extent_op->flags_to_set; 44428c2ecf20Sopenharmony_ci bool skinny_metadata = btrfs_fs_incompat(fs_info, SKINNY_METADATA); 44438c2ecf20Sopenharmony_ci 44448c2ecf20Sopenharmony_ci ref = btrfs_delayed_node_to_tree_ref(node); 44458c2ecf20Sopenharmony_ci 44468c2ecf20Sopenharmony_ci extent_key.objectid = node->bytenr; 44478c2ecf20Sopenharmony_ci if (skinny_metadata) { 44488c2ecf20Sopenharmony_ci extent_key.offset = ref->level; 44498c2ecf20Sopenharmony_ci extent_key.type = BTRFS_METADATA_ITEM_KEY; 44508c2ecf20Sopenharmony_ci num_bytes = fs_info->nodesize; 44518c2ecf20Sopenharmony_ci } else { 44528c2ecf20Sopenharmony_ci extent_key.offset = node->num_bytes; 44538c2ecf20Sopenharmony_ci extent_key.type = BTRFS_EXTENT_ITEM_KEY; 44548c2ecf20Sopenharmony_ci size += sizeof(*block_info); 44558c2ecf20Sopenharmony_ci num_bytes = node->num_bytes; 44568c2ecf20Sopenharmony_ci } 44578c2ecf20Sopenharmony_ci 44588c2ecf20Sopenharmony_ci path = btrfs_alloc_path(); 44598c2ecf20Sopenharmony_ci if (!path) 44608c2ecf20Sopenharmony_ci return -ENOMEM; 44618c2ecf20Sopenharmony_ci 44628c2ecf20Sopenharmony_ci path->leave_spinning = 1; 44638c2ecf20Sopenharmony_ci ret = btrfs_insert_empty_item(trans, fs_info->extent_root, path, 44648c2ecf20Sopenharmony_ci &extent_key, size); 44658c2ecf20Sopenharmony_ci if (ret) { 44668c2ecf20Sopenharmony_ci btrfs_free_path(path); 44678c2ecf20Sopenharmony_ci return ret; 44688c2ecf20Sopenharmony_ci } 44698c2ecf20Sopenharmony_ci 44708c2ecf20Sopenharmony_ci leaf = path->nodes[0]; 44718c2ecf20Sopenharmony_ci extent_item = btrfs_item_ptr(leaf, path->slots[0], 44728c2ecf20Sopenharmony_ci struct btrfs_extent_item); 44738c2ecf20Sopenharmony_ci btrfs_set_extent_refs(leaf, extent_item, 1); 44748c2ecf20Sopenharmony_ci btrfs_set_extent_generation(leaf, extent_item, trans->transid); 44758c2ecf20Sopenharmony_ci btrfs_set_extent_flags(leaf, extent_item, 44768c2ecf20Sopenharmony_ci flags | BTRFS_EXTENT_FLAG_TREE_BLOCK); 44778c2ecf20Sopenharmony_ci 44788c2ecf20Sopenharmony_ci if (skinny_metadata) { 44798c2ecf20Sopenharmony_ci iref = (struct btrfs_extent_inline_ref *)(extent_item + 1); 44808c2ecf20Sopenharmony_ci } else { 44818c2ecf20Sopenharmony_ci block_info = (struct btrfs_tree_block_info *)(extent_item + 1); 44828c2ecf20Sopenharmony_ci btrfs_set_tree_block_key(leaf, block_info, &extent_op->key); 44838c2ecf20Sopenharmony_ci btrfs_set_tree_block_level(leaf, block_info, ref->level); 44848c2ecf20Sopenharmony_ci iref = (struct btrfs_extent_inline_ref *)(block_info + 1); 44858c2ecf20Sopenharmony_ci } 44868c2ecf20Sopenharmony_ci 44878c2ecf20Sopenharmony_ci if (node->type == BTRFS_SHARED_BLOCK_REF_KEY) { 44888c2ecf20Sopenharmony_ci BUG_ON(!(flags & BTRFS_BLOCK_FLAG_FULL_BACKREF)); 44898c2ecf20Sopenharmony_ci btrfs_set_extent_inline_ref_type(leaf, iref, 44908c2ecf20Sopenharmony_ci BTRFS_SHARED_BLOCK_REF_KEY); 44918c2ecf20Sopenharmony_ci btrfs_set_extent_inline_ref_offset(leaf, iref, ref->parent); 44928c2ecf20Sopenharmony_ci } else { 44938c2ecf20Sopenharmony_ci btrfs_set_extent_inline_ref_type(leaf, iref, 44948c2ecf20Sopenharmony_ci BTRFS_TREE_BLOCK_REF_KEY); 44958c2ecf20Sopenharmony_ci btrfs_set_extent_inline_ref_offset(leaf, iref, ref->root); 44968c2ecf20Sopenharmony_ci } 44978c2ecf20Sopenharmony_ci 44988c2ecf20Sopenharmony_ci btrfs_mark_buffer_dirty(leaf); 44998c2ecf20Sopenharmony_ci btrfs_free_path(path); 45008c2ecf20Sopenharmony_ci 45018c2ecf20Sopenharmony_ci ret = remove_from_free_space_tree(trans, extent_key.objectid, 45028c2ecf20Sopenharmony_ci num_bytes); 45038c2ecf20Sopenharmony_ci if (ret) 45048c2ecf20Sopenharmony_ci return ret; 45058c2ecf20Sopenharmony_ci 45068c2ecf20Sopenharmony_ci ret = btrfs_update_block_group(trans, extent_key.objectid, 45078c2ecf20Sopenharmony_ci fs_info->nodesize, 1); 45088c2ecf20Sopenharmony_ci if (ret) { /* -ENOENT, logic error */ 45098c2ecf20Sopenharmony_ci btrfs_err(fs_info, "update block group failed for %llu %llu", 45108c2ecf20Sopenharmony_ci extent_key.objectid, extent_key.offset); 45118c2ecf20Sopenharmony_ci BUG(); 45128c2ecf20Sopenharmony_ci } 45138c2ecf20Sopenharmony_ci 45148c2ecf20Sopenharmony_ci trace_btrfs_reserved_extent_alloc(fs_info, extent_key.objectid, 45158c2ecf20Sopenharmony_ci fs_info->nodesize); 45168c2ecf20Sopenharmony_ci return ret; 45178c2ecf20Sopenharmony_ci} 45188c2ecf20Sopenharmony_ci 45198c2ecf20Sopenharmony_ciint btrfs_alloc_reserved_file_extent(struct btrfs_trans_handle *trans, 45208c2ecf20Sopenharmony_ci struct btrfs_root *root, u64 owner, 45218c2ecf20Sopenharmony_ci u64 offset, u64 ram_bytes, 45228c2ecf20Sopenharmony_ci struct btrfs_key *ins) 45238c2ecf20Sopenharmony_ci{ 45248c2ecf20Sopenharmony_ci struct btrfs_ref generic_ref = { 0 }; 45258c2ecf20Sopenharmony_ci 45268c2ecf20Sopenharmony_ci BUG_ON(root->root_key.objectid == BTRFS_TREE_LOG_OBJECTID); 45278c2ecf20Sopenharmony_ci 45288c2ecf20Sopenharmony_ci btrfs_init_generic_ref(&generic_ref, BTRFS_ADD_DELAYED_EXTENT, 45298c2ecf20Sopenharmony_ci ins->objectid, ins->offset, 0); 45308c2ecf20Sopenharmony_ci btrfs_init_data_ref(&generic_ref, root->root_key.objectid, owner, offset); 45318c2ecf20Sopenharmony_ci btrfs_ref_tree_mod(root->fs_info, &generic_ref); 45328c2ecf20Sopenharmony_ci 45338c2ecf20Sopenharmony_ci return btrfs_add_delayed_data_ref(trans, &generic_ref, ram_bytes); 45348c2ecf20Sopenharmony_ci} 45358c2ecf20Sopenharmony_ci 45368c2ecf20Sopenharmony_ci/* 45378c2ecf20Sopenharmony_ci * this is used by the tree logging recovery code. It records that 45388c2ecf20Sopenharmony_ci * an extent has been allocated and makes sure to clear the free 45398c2ecf20Sopenharmony_ci * space cache bits as well 45408c2ecf20Sopenharmony_ci */ 45418c2ecf20Sopenharmony_ciint btrfs_alloc_logged_file_extent(struct btrfs_trans_handle *trans, 45428c2ecf20Sopenharmony_ci u64 root_objectid, u64 owner, u64 offset, 45438c2ecf20Sopenharmony_ci struct btrfs_key *ins) 45448c2ecf20Sopenharmony_ci{ 45458c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = trans->fs_info; 45468c2ecf20Sopenharmony_ci int ret; 45478c2ecf20Sopenharmony_ci struct btrfs_block_group *block_group; 45488c2ecf20Sopenharmony_ci struct btrfs_space_info *space_info; 45498c2ecf20Sopenharmony_ci 45508c2ecf20Sopenharmony_ci /* 45518c2ecf20Sopenharmony_ci * Mixed block groups will exclude before processing the log so we only 45528c2ecf20Sopenharmony_ci * need to do the exclude dance if this fs isn't mixed. 45538c2ecf20Sopenharmony_ci */ 45548c2ecf20Sopenharmony_ci if (!btrfs_fs_incompat(fs_info, MIXED_GROUPS)) { 45558c2ecf20Sopenharmony_ci ret = __exclude_logged_extent(fs_info, ins->objectid, 45568c2ecf20Sopenharmony_ci ins->offset); 45578c2ecf20Sopenharmony_ci if (ret) 45588c2ecf20Sopenharmony_ci return ret; 45598c2ecf20Sopenharmony_ci } 45608c2ecf20Sopenharmony_ci 45618c2ecf20Sopenharmony_ci block_group = btrfs_lookup_block_group(fs_info, ins->objectid); 45628c2ecf20Sopenharmony_ci if (!block_group) 45638c2ecf20Sopenharmony_ci return -EINVAL; 45648c2ecf20Sopenharmony_ci 45658c2ecf20Sopenharmony_ci space_info = block_group->space_info; 45668c2ecf20Sopenharmony_ci spin_lock(&space_info->lock); 45678c2ecf20Sopenharmony_ci spin_lock(&block_group->lock); 45688c2ecf20Sopenharmony_ci space_info->bytes_reserved += ins->offset; 45698c2ecf20Sopenharmony_ci block_group->reserved += ins->offset; 45708c2ecf20Sopenharmony_ci spin_unlock(&block_group->lock); 45718c2ecf20Sopenharmony_ci spin_unlock(&space_info->lock); 45728c2ecf20Sopenharmony_ci 45738c2ecf20Sopenharmony_ci ret = alloc_reserved_file_extent(trans, 0, root_objectid, 0, owner, 45748c2ecf20Sopenharmony_ci offset, ins, 1); 45758c2ecf20Sopenharmony_ci if (ret) 45768c2ecf20Sopenharmony_ci btrfs_pin_extent(trans, ins->objectid, ins->offset, 1); 45778c2ecf20Sopenharmony_ci btrfs_put_block_group(block_group); 45788c2ecf20Sopenharmony_ci return ret; 45798c2ecf20Sopenharmony_ci} 45808c2ecf20Sopenharmony_ci 45818c2ecf20Sopenharmony_cistatic struct extent_buffer * 45828c2ecf20Sopenharmony_cibtrfs_init_new_buffer(struct btrfs_trans_handle *trans, struct btrfs_root *root, 45838c2ecf20Sopenharmony_ci u64 bytenr, int level, u64 owner, 45848c2ecf20Sopenharmony_ci enum btrfs_lock_nesting nest) 45858c2ecf20Sopenharmony_ci{ 45868c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = root->fs_info; 45878c2ecf20Sopenharmony_ci struct extent_buffer *buf; 45888c2ecf20Sopenharmony_ci 45898c2ecf20Sopenharmony_ci buf = btrfs_find_create_tree_block(fs_info, bytenr); 45908c2ecf20Sopenharmony_ci if (IS_ERR(buf)) 45918c2ecf20Sopenharmony_ci return buf; 45928c2ecf20Sopenharmony_ci 45938c2ecf20Sopenharmony_ci /* 45948c2ecf20Sopenharmony_ci * Extra safety check in case the extent tree is corrupted and extent 45958c2ecf20Sopenharmony_ci * allocator chooses to use a tree block which is already used and 45968c2ecf20Sopenharmony_ci * locked. 45978c2ecf20Sopenharmony_ci */ 45988c2ecf20Sopenharmony_ci if (buf->lock_owner == current->pid) { 45998c2ecf20Sopenharmony_ci btrfs_err_rl(fs_info, 46008c2ecf20Sopenharmony_ci"tree block %llu owner %llu already locked by pid=%d, extent tree corruption detected", 46018c2ecf20Sopenharmony_ci buf->start, btrfs_header_owner(buf), current->pid); 46028c2ecf20Sopenharmony_ci free_extent_buffer(buf); 46038c2ecf20Sopenharmony_ci return ERR_PTR(-EUCLEAN); 46048c2ecf20Sopenharmony_ci } 46058c2ecf20Sopenharmony_ci 46068c2ecf20Sopenharmony_ci btrfs_set_buffer_lockdep_class(owner, buf, level); 46078c2ecf20Sopenharmony_ci __btrfs_tree_lock(buf, nest); 46088c2ecf20Sopenharmony_ci btrfs_clean_tree_block(buf); 46098c2ecf20Sopenharmony_ci clear_bit(EXTENT_BUFFER_STALE, &buf->bflags); 46108c2ecf20Sopenharmony_ci 46118c2ecf20Sopenharmony_ci btrfs_set_lock_blocking_write(buf); 46128c2ecf20Sopenharmony_ci set_extent_buffer_uptodate(buf); 46138c2ecf20Sopenharmony_ci 46148c2ecf20Sopenharmony_ci memzero_extent_buffer(buf, 0, sizeof(struct btrfs_header)); 46158c2ecf20Sopenharmony_ci btrfs_set_header_level(buf, level); 46168c2ecf20Sopenharmony_ci btrfs_set_header_bytenr(buf, buf->start); 46178c2ecf20Sopenharmony_ci btrfs_set_header_generation(buf, trans->transid); 46188c2ecf20Sopenharmony_ci btrfs_set_header_backref_rev(buf, BTRFS_MIXED_BACKREF_REV); 46198c2ecf20Sopenharmony_ci btrfs_set_header_owner(buf, owner); 46208c2ecf20Sopenharmony_ci write_extent_buffer_fsid(buf, fs_info->fs_devices->metadata_uuid); 46218c2ecf20Sopenharmony_ci write_extent_buffer_chunk_tree_uuid(buf, fs_info->chunk_tree_uuid); 46228c2ecf20Sopenharmony_ci if (root->root_key.objectid == BTRFS_TREE_LOG_OBJECTID) { 46238c2ecf20Sopenharmony_ci buf->log_index = root->log_transid % 2; 46248c2ecf20Sopenharmony_ci /* 46258c2ecf20Sopenharmony_ci * we allow two log transactions at a time, use different 46268c2ecf20Sopenharmony_ci * EXTENT bit to differentiate dirty pages. 46278c2ecf20Sopenharmony_ci */ 46288c2ecf20Sopenharmony_ci if (buf->log_index == 0) 46298c2ecf20Sopenharmony_ci set_extent_dirty(&root->dirty_log_pages, buf->start, 46308c2ecf20Sopenharmony_ci buf->start + buf->len - 1, GFP_NOFS); 46318c2ecf20Sopenharmony_ci else 46328c2ecf20Sopenharmony_ci set_extent_new(&root->dirty_log_pages, buf->start, 46338c2ecf20Sopenharmony_ci buf->start + buf->len - 1); 46348c2ecf20Sopenharmony_ci } else { 46358c2ecf20Sopenharmony_ci buf->log_index = -1; 46368c2ecf20Sopenharmony_ci set_extent_dirty(&trans->transaction->dirty_pages, buf->start, 46378c2ecf20Sopenharmony_ci buf->start + buf->len - 1, GFP_NOFS); 46388c2ecf20Sopenharmony_ci } 46398c2ecf20Sopenharmony_ci trans->dirty = true; 46408c2ecf20Sopenharmony_ci /* this returns a buffer locked for blocking */ 46418c2ecf20Sopenharmony_ci return buf; 46428c2ecf20Sopenharmony_ci} 46438c2ecf20Sopenharmony_ci 46448c2ecf20Sopenharmony_ci/* 46458c2ecf20Sopenharmony_ci * finds a free extent and does all the dirty work required for allocation 46468c2ecf20Sopenharmony_ci * returns the tree buffer or an ERR_PTR on error. 46478c2ecf20Sopenharmony_ci */ 46488c2ecf20Sopenharmony_cistruct extent_buffer *btrfs_alloc_tree_block(struct btrfs_trans_handle *trans, 46498c2ecf20Sopenharmony_ci struct btrfs_root *root, 46508c2ecf20Sopenharmony_ci u64 parent, u64 root_objectid, 46518c2ecf20Sopenharmony_ci const struct btrfs_disk_key *key, 46528c2ecf20Sopenharmony_ci int level, u64 hint, 46538c2ecf20Sopenharmony_ci u64 empty_size, 46548c2ecf20Sopenharmony_ci enum btrfs_lock_nesting nest) 46558c2ecf20Sopenharmony_ci{ 46568c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = root->fs_info; 46578c2ecf20Sopenharmony_ci struct btrfs_key ins; 46588c2ecf20Sopenharmony_ci struct btrfs_block_rsv *block_rsv; 46598c2ecf20Sopenharmony_ci struct extent_buffer *buf; 46608c2ecf20Sopenharmony_ci struct btrfs_delayed_extent_op *extent_op; 46618c2ecf20Sopenharmony_ci struct btrfs_ref generic_ref = { 0 }; 46628c2ecf20Sopenharmony_ci u64 flags = 0; 46638c2ecf20Sopenharmony_ci int ret; 46648c2ecf20Sopenharmony_ci u32 blocksize = fs_info->nodesize; 46658c2ecf20Sopenharmony_ci bool skinny_metadata = btrfs_fs_incompat(fs_info, SKINNY_METADATA); 46668c2ecf20Sopenharmony_ci 46678c2ecf20Sopenharmony_ci#ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS 46688c2ecf20Sopenharmony_ci if (btrfs_is_testing(fs_info)) { 46698c2ecf20Sopenharmony_ci buf = btrfs_init_new_buffer(trans, root, root->alloc_bytenr, 46708c2ecf20Sopenharmony_ci level, root_objectid, nest); 46718c2ecf20Sopenharmony_ci if (!IS_ERR(buf)) 46728c2ecf20Sopenharmony_ci root->alloc_bytenr += blocksize; 46738c2ecf20Sopenharmony_ci return buf; 46748c2ecf20Sopenharmony_ci } 46758c2ecf20Sopenharmony_ci#endif 46768c2ecf20Sopenharmony_ci 46778c2ecf20Sopenharmony_ci block_rsv = btrfs_use_block_rsv(trans, root, blocksize); 46788c2ecf20Sopenharmony_ci if (IS_ERR(block_rsv)) 46798c2ecf20Sopenharmony_ci return ERR_CAST(block_rsv); 46808c2ecf20Sopenharmony_ci 46818c2ecf20Sopenharmony_ci ret = btrfs_reserve_extent(root, blocksize, blocksize, blocksize, 46828c2ecf20Sopenharmony_ci empty_size, hint, &ins, 0, 0); 46838c2ecf20Sopenharmony_ci if (ret) 46848c2ecf20Sopenharmony_ci goto out_unuse; 46858c2ecf20Sopenharmony_ci 46868c2ecf20Sopenharmony_ci buf = btrfs_init_new_buffer(trans, root, ins.objectid, level, 46878c2ecf20Sopenharmony_ci root_objectid, nest); 46888c2ecf20Sopenharmony_ci if (IS_ERR(buf)) { 46898c2ecf20Sopenharmony_ci ret = PTR_ERR(buf); 46908c2ecf20Sopenharmony_ci goto out_free_reserved; 46918c2ecf20Sopenharmony_ci } 46928c2ecf20Sopenharmony_ci 46938c2ecf20Sopenharmony_ci if (root_objectid == BTRFS_TREE_RELOC_OBJECTID) { 46948c2ecf20Sopenharmony_ci if (parent == 0) 46958c2ecf20Sopenharmony_ci parent = ins.objectid; 46968c2ecf20Sopenharmony_ci flags |= BTRFS_BLOCK_FLAG_FULL_BACKREF; 46978c2ecf20Sopenharmony_ci } else 46988c2ecf20Sopenharmony_ci BUG_ON(parent > 0); 46998c2ecf20Sopenharmony_ci 47008c2ecf20Sopenharmony_ci if (root_objectid != BTRFS_TREE_LOG_OBJECTID) { 47018c2ecf20Sopenharmony_ci extent_op = btrfs_alloc_delayed_extent_op(); 47028c2ecf20Sopenharmony_ci if (!extent_op) { 47038c2ecf20Sopenharmony_ci ret = -ENOMEM; 47048c2ecf20Sopenharmony_ci goto out_free_buf; 47058c2ecf20Sopenharmony_ci } 47068c2ecf20Sopenharmony_ci if (key) 47078c2ecf20Sopenharmony_ci memcpy(&extent_op->key, key, sizeof(extent_op->key)); 47088c2ecf20Sopenharmony_ci else 47098c2ecf20Sopenharmony_ci memset(&extent_op->key, 0, sizeof(extent_op->key)); 47108c2ecf20Sopenharmony_ci extent_op->flags_to_set = flags; 47118c2ecf20Sopenharmony_ci extent_op->update_key = skinny_metadata ? false : true; 47128c2ecf20Sopenharmony_ci extent_op->update_flags = true; 47138c2ecf20Sopenharmony_ci extent_op->is_data = false; 47148c2ecf20Sopenharmony_ci extent_op->level = level; 47158c2ecf20Sopenharmony_ci 47168c2ecf20Sopenharmony_ci btrfs_init_generic_ref(&generic_ref, BTRFS_ADD_DELAYED_EXTENT, 47178c2ecf20Sopenharmony_ci ins.objectid, ins.offset, parent); 47188c2ecf20Sopenharmony_ci generic_ref.real_root = root->root_key.objectid; 47198c2ecf20Sopenharmony_ci btrfs_init_tree_ref(&generic_ref, level, root_objectid); 47208c2ecf20Sopenharmony_ci btrfs_ref_tree_mod(fs_info, &generic_ref); 47218c2ecf20Sopenharmony_ci ret = btrfs_add_delayed_tree_ref(trans, &generic_ref, extent_op); 47228c2ecf20Sopenharmony_ci if (ret) 47238c2ecf20Sopenharmony_ci goto out_free_delayed; 47248c2ecf20Sopenharmony_ci } 47258c2ecf20Sopenharmony_ci return buf; 47268c2ecf20Sopenharmony_ci 47278c2ecf20Sopenharmony_ciout_free_delayed: 47288c2ecf20Sopenharmony_ci btrfs_free_delayed_extent_op(extent_op); 47298c2ecf20Sopenharmony_ciout_free_buf: 47308c2ecf20Sopenharmony_ci btrfs_tree_unlock(buf); 47318c2ecf20Sopenharmony_ci free_extent_buffer(buf); 47328c2ecf20Sopenharmony_ciout_free_reserved: 47338c2ecf20Sopenharmony_ci btrfs_free_reserved_extent(fs_info, ins.objectid, ins.offset, 0); 47348c2ecf20Sopenharmony_ciout_unuse: 47358c2ecf20Sopenharmony_ci btrfs_unuse_block_rsv(fs_info, block_rsv, blocksize); 47368c2ecf20Sopenharmony_ci return ERR_PTR(ret); 47378c2ecf20Sopenharmony_ci} 47388c2ecf20Sopenharmony_ci 47398c2ecf20Sopenharmony_cistruct walk_control { 47408c2ecf20Sopenharmony_ci u64 refs[BTRFS_MAX_LEVEL]; 47418c2ecf20Sopenharmony_ci u64 flags[BTRFS_MAX_LEVEL]; 47428c2ecf20Sopenharmony_ci struct btrfs_key update_progress; 47438c2ecf20Sopenharmony_ci struct btrfs_key drop_progress; 47448c2ecf20Sopenharmony_ci int drop_level; 47458c2ecf20Sopenharmony_ci int stage; 47468c2ecf20Sopenharmony_ci int level; 47478c2ecf20Sopenharmony_ci int shared_level; 47488c2ecf20Sopenharmony_ci int update_ref; 47498c2ecf20Sopenharmony_ci int keep_locks; 47508c2ecf20Sopenharmony_ci int reada_slot; 47518c2ecf20Sopenharmony_ci int reada_count; 47528c2ecf20Sopenharmony_ci int restarted; 47538c2ecf20Sopenharmony_ci}; 47548c2ecf20Sopenharmony_ci 47558c2ecf20Sopenharmony_ci#define DROP_REFERENCE 1 47568c2ecf20Sopenharmony_ci#define UPDATE_BACKREF 2 47578c2ecf20Sopenharmony_ci 47588c2ecf20Sopenharmony_cistatic noinline void reada_walk_down(struct btrfs_trans_handle *trans, 47598c2ecf20Sopenharmony_ci struct btrfs_root *root, 47608c2ecf20Sopenharmony_ci struct walk_control *wc, 47618c2ecf20Sopenharmony_ci struct btrfs_path *path) 47628c2ecf20Sopenharmony_ci{ 47638c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = root->fs_info; 47648c2ecf20Sopenharmony_ci u64 bytenr; 47658c2ecf20Sopenharmony_ci u64 generation; 47668c2ecf20Sopenharmony_ci u64 refs; 47678c2ecf20Sopenharmony_ci u64 flags; 47688c2ecf20Sopenharmony_ci u32 nritems; 47698c2ecf20Sopenharmony_ci struct btrfs_key key; 47708c2ecf20Sopenharmony_ci struct extent_buffer *eb; 47718c2ecf20Sopenharmony_ci int ret; 47728c2ecf20Sopenharmony_ci int slot; 47738c2ecf20Sopenharmony_ci int nread = 0; 47748c2ecf20Sopenharmony_ci 47758c2ecf20Sopenharmony_ci if (path->slots[wc->level] < wc->reada_slot) { 47768c2ecf20Sopenharmony_ci wc->reada_count = wc->reada_count * 2 / 3; 47778c2ecf20Sopenharmony_ci wc->reada_count = max(wc->reada_count, 2); 47788c2ecf20Sopenharmony_ci } else { 47798c2ecf20Sopenharmony_ci wc->reada_count = wc->reada_count * 3 / 2; 47808c2ecf20Sopenharmony_ci wc->reada_count = min_t(int, wc->reada_count, 47818c2ecf20Sopenharmony_ci BTRFS_NODEPTRS_PER_BLOCK(fs_info)); 47828c2ecf20Sopenharmony_ci } 47838c2ecf20Sopenharmony_ci 47848c2ecf20Sopenharmony_ci eb = path->nodes[wc->level]; 47858c2ecf20Sopenharmony_ci nritems = btrfs_header_nritems(eb); 47868c2ecf20Sopenharmony_ci 47878c2ecf20Sopenharmony_ci for (slot = path->slots[wc->level]; slot < nritems; slot++) { 47888c2ecf20Sopenharmony_ci if (nread >= wc->reada_count) 47898c2ecf20Sopenharmony_ci break; 47908c2ecf20Sopenharmony_ci 47918c2ecf20Sopenharmony_ci cond_resched(); 47928c2ecf20Sopenharmony_ci bytenr = btrfs_node_blockptr(eb, slot); 47938c2ecf20Sopenharmony_ci generation = btrfs_node_ptr_generation(eb, slot); 47948c2ecf20Sopenharmony_ci 47958c2ecf20Sopenharmony_ci if (slot == path->slots[wc->level]) 47968c2ecf20Sopenharmony_ci goto reada; 47978c2ecf20Sopenharmony_ci 47988c2ecf20Sopenharmony_ci if (wc->stage == UPDATE_BACKREF && 47998c2ecf20Sopenharmony_ci generation <= root->root_key.offset) 48008c2ecf20Sopenharmony_ci continue; 48018c2ecf20Sopenharmony_ci 48028c2ecf20Sopenharmony_ci /* We don't lock the tree block, it's OK to be racy here */ 48038c2ecf20Sopenharmony_ci ret = btrfs_lookup_extent_info(trans, fs_info, bytenr, 48048c2ecf20Sopenharmony_ci wc->level - 1, 1, &refs, 48058c2ecf20Sopenharmony_ci &flags); 48068c2ecf20Sopenharmony_ci /* We don't care about errors in readahead. */ 48078c2ecf20Sopenharmony_ci if (ret < 0) 48088c2ecf20Sopenharmony_ci continue; 48098c2ecf20Sopenharmony_ci BUG_ON(refs == 0); 48108c2ecf20Sopenharmony_ci 48118c2ecf20Sopenharmony_ci if (wc->stage == DROP_REFERENCE) { 48128c2ecf20Sopenharmony_ci if (refs == 1) 48138c2ecf20Sopenharmony_ci goto reada; 48148c2ecf20Sopenharmony_ci 48158c2ecf20Sopenharmony_ci if (wc->level == 1 && 48168c2ecf20Sopenharmony_ci (flags & BTRFS_BLOCK_FLAG_FULL_BACKREF)) 48178c2ecf20Sopenharmony_ci continue; 48188c2ecf20Sopenharmony_ci if (!wc->update_ref || 48198c2ecf20Sopenharmony_ci generation <= root->root_key.offset) 48208c2ecf20Sopenharmony_ci continue; 48218c2ecf20Sopenharmony_ci btrfs_node_key_to_cpu(eb, &key, slot); 48228c2ecf20Sopenharmony_ci ret = btrfs_comp_cpu_keys(&key, 48238c2ecf20Sopenharmony_ci &wc->update_progress); 48248c2ecf20Sopenharmony_ci if (ret < 0) 48258c2ecf20Sopenharmony_ci continue; 48268c2ecf20Sopenharmony_ci } else { 48278c2ecf20Sopenharmony_ci if (wc->level == 1 && 48288c2ecf20Sopenharmony_ci (flags & BTRFS_BLOCK_FLAG_FULL_BACKREF)) 48298c2ecf20Sopenharmony_ci continue; 48308c2ecf20Sopenharmony_ci } 48318c2ecf20Sopenharmony_cireada: 48328c2ecf20Sopenharmony_ci readahead_tree_block(fs_info, bytenr); 48338c2ecf20Sopenharmony_ci nread++; 48348c2ecf20Sopenharmony_ci } 48358c2ecf20Sopenharmony_ci wc->reada_slot = slot; 48368c2ecf20Sopenharmony_ci} 48378c2ecf20Sopenharmony_ci 48388c2ecf20Sopenharmony_ci/* 48398c2ecf20Sopenharmony_ci * helper to process tree block while walking down the tree. 48408c2ecf20Sopenharmony_ci * 48418c2ecf20Sopenharmony_ci * when wc->stage == UPDATE_BACKREF, this function updates 48428c2ecf20Sopenharmony_ci * back refs for pointers in the block. 48438c2ecf20Sopenharmony_ci * 48448c2ecf20Sopenharmony_ci * NOTE: return value 1 means we should stop walking down. 48458c2ecf20Sopenharmony_ci */ 48468c2ecf20Sopenharmony_cistatic noinline int walk_down_proc(struct btrfs_trans_handle *trans, 48478c2ecf20Sopenharmony_ci struct btrfs_root *root, 48488c2ecf20Sopenharmony_ci struct btrfs_path *path, 48498c2ecf20Sopenharmony_ci struct walk_control *wc, int lookup_info) 48508c2ecf20Sopenharmony_ci{ 48518c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = root->fs_info; 48528c2ecf20Sopenharmony_ci int level = wc->level; 48538c2ecf20Sopenharmony_ci struct extent_buffer *eb = path->nodes[level]; 48548c2ecf20Sopenharmony_ci u64 flag = BTRFS_BLOCK_FLAG_FULL_BACKREF; 48558c2ecf20Sopenharmony_ci int ret; 48568c2ecf20Sopenharmony_ci 48578c2ecf20Sopenharmony_ci if (wc->stage == UPDATE_BACKREF && 48588c2ecf20Sopenharmony_ci btrfs_header_owner(eb) != root->root_key.objectid) 48598c2ecf20Sopenharmony_ci return 1; 48608c2ecf20Sopenharmony_ci 48618c2ecf20Sopenharmony_ci /* 48628c2ecf20Sopenharmony_ci * when reference count of tree block is 1, it won't increase 48638c2ecf20Sopenharmony_ci * again. once full backref flag is set, we never clear it. 48648c2ecf20Sopenharmony_ci */ 48658c2ecf20Sopenharmony_ci if (lookup_info && 48668c2ecf20Sopenharmony_ci ((wc->stage == DROP_REFERENCE && wc->refs[level] != 1) || 48678c2ecf20Sopenharmony_ci (wc->stage == UPDATE_BACKREF && !(wc->flags[level] & flag)))) { 48688c2ecf20Sopenharmony_ci BUG_ON(!path->locks[level]); 48698c2ecf20Sopenharmony_ci ret = btrfs_lookup_extent_info(trans, fs_info, 48708c2ecf20Sopenharmony_ci eb->start, level, 1, 48718c2ecf20Sopenharmony_ci &wc->refs[level], 48728c2ecf20Sopenharmony_ci &wc->flags[level]); 48738c2ecf20Sopenharmony_ci BUG_ON(ret == -ENOMEM); 48748c2ecf20Sopenharmony_ci if (ret) 48758c2ecf20Sopenharmony_ci return ret; 48768c2ecf20Sopenharmony_ci BUG_ON(wc->refs[level] == 0); 48778c2ecf20Sopenharmony_ci } 48788c2ecf20Sopenharmony_ci 48798c2ecf20Sopenharmony_ci if (wc->stage == DROP_REFERENCE) { 48808c2ecf20Sopenharmony_ci if (wc->refs[level] > 1) 48818c2ecf20Sopenharmony_ci return 1; 48828c2ecf20Sopenharmony_ci 48838c2ecf20Sopenharmony_ci if (path->locks[level] && !wc->keep_locks) { 48848c2ecf20Sopenharmony_ci btrfs_tree_unlock_rw(eb, path->locks[level]); 48858c2ecf20Sopenharmony_ci path->locks[level] = 0; 48868c2ecf20Sopenharmony_ci } 48878c2ecf20Sopenharmony_ci return 0; 48888c2ecf20Sopenharmony_ci } 48898c2ecf20Sopenharmony_ci 48908c2ecf20Sopenharmony_ci /* wc->stage == UPDATE_BACKREF */ 48918c2ecf20Sopenharmony_ci if (!(wc->flags[level] & flag)) { 48928c2ecf20Sopenharmony_ci BUG_ON(!path->locks[level]); 48938c2ecf20Sopenharmony_ci ret = btrfs_inc_ref(trans, root, eb, 1); 48948c2ecf20Sopenharmony_ci BUG_ON(ret); /* -ENOMEM */ 48958c2ecf20Sopenharmony_ci ret = btrfs_dec_ref(trans, root, eb, 0); 48968c2ecf20Sopenharmony_ci BUG_ON(ret); /* -ENOMEM */ 48978c2ecf20Sopenharmony_ci ret = btrfs_set_disk_extent_flags(trans, eb, flag, 48988c2ecf20Sopenharmony_ci btrfs_header_level(eb), 0); 48998c2ecf20Sopenharmony_ci BUG_ON(ret); /* -ENOMEM */ 49008c2ecf20Sopenharmony_ci wc->flags[level] |= flag; 49018c2ecf20Sopenharmony_ci } 49028c2ecf20Sopenharmony_ci 49038c2ecf20Sopenharmony_ci /* 49048c2ecf20Sopenharmony_ci * the block is shared by multiple trees, so it's not good to 49058c2ecf20Sopenharmony_ci * keep the tree lock 49068c2ecf20Sopenharmony_ci */ 49078c2ecf20Sopenharmony_ci if (path->locks[level] && level > 0) { 49088c2ecf20Sopenharmony_ci btrfs_tree_unlock_rw(eb, path->locks[level]); 49098c2ecf20Sopenharmony_ci path->locks[level] = 0; 49108c2ecf20Sopenharmony_ci } 49118c2ecf20Sopenharmony_ci return 0; 49128c2ecf20Sopenharmony_ci} 49138c2ecf20Sopenharmony_ci 49148c2ecf20Sopenharmony_ci/* 49158c2ecf20Sopenharmony_ci * This is used to verify a ref exists for this root to deal with a bug where we 49168c2ecf20Sopenharmony_ci * would have a drop_progress key that hadn't been updated properly. 49178c2ecf20Sopenharmony_ci */ 49188c2ecf20Sopenharmony_cistatic int check_ref_exists(struct btrfs_trans_handle *trans, 49198c2ecf20Sopenharmony_ci struct btrfs_root *root, u64 bytenr, u64 parent, 49208c2ecf20Sopenharmony_ci int level) 49218c2ecf20Sopenharmony_ci{ 49228c2ecf20Sopenharmony_ci struct btrfs_path *path; 49238c2ecf20Sopenharmony_ci struct btrfs_extent_inline_ref *iref; 49248c2ecf20Sopenharmony_ci int ret; 49258c2ecf20Sopenharmony_ci 49268c2ecf20Sopenharmony_ci path = btrfs_alloc_path(); 49278c2ecf20Sopenharmony_ci if (!path) 49288c2ecf20Sopenharmony_ci return -ENOMEM; 49298c2ecf20Sopenharmony_ci 49308c2ecf20Sopenharmony_ci ret = lookup_extent_backref(trans, path, &iref, bytenr, 49318c2ecf20Sopenharmony_ci root->fs_info->nodesize, parent, 49328c2ecf20Sopenharmony_ci root->root_key.objectid, level, 0); 49338c2ecf20Sopenharmony_ci btrfs_free_path(path); 49348c2ecf20Sopenharmony_ci if (ret == -ENOENT) 49358c2ecf20Sopenharmony_ci return 0; 49368c2ecf20Sopenharmony_ci if (ret < 0) 49378c2ecf20Sopenharmony_ci return ret; 49388c2ecf20Sopenharmony_ci return 1; 49398c2ecf20Sopenharmony_ci} 49408c2ecf20Sopenharmony_ci 49418c2ecf20Sopenharmony_ci/* 49428c2ecf20Sopenharmony_ci * helper to process tree block pointer. 49438c2ecf20Sopenharmony_ci * 49448c2ecf20Sopenharmony_ci * when wc->stage == DROP_REFERENCE, this function checks 49458c2ecf20Sopenharmony_ci * reference count of the block pointed to. if the block 49468c2ecf20Sopenharmony_ci * is shared and we need update back refs for the subtree 49478c2ecf20Sopenharmony_ci * rooted at the block, this function changes wc->stage to 49488c2ecf20Sopenharmony_ci * UPDATE_BACKREF. if the block is shared and there is no 49498c2ecf20Sopenharmony_ci * need to update back, this function drops the reference 49508c2ecf20Sopenharmony_ci * to the block. 49518c2ecf20Sopenharmony_ci * 49528c2ecf20Sopenharmony_ci * NOTE: return value 1 means we should stop walking down. 49538c2ecf20Sopenharmony_ci */ 49548c2ecf20Sopenharmony_cistatic noinline int do_walk_down(struct btrfs_trans_handle *trans, 49558c2ecf20Sopenharmony_ci struct btrfs_root *root, 49568c2ecf20Sopenharmony_ci struct btrfs_path *path, 49578c2ecf20Sopenharmony_ci struct walk_control *wc, int *lookup_info) 49588c2ecf20Sopenharmony_ci{ 49598c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = root->fs_info; 49608c2ecf20Sopenharmony_ci u64 bytenr; 49618c2ecf20Sopenharmony_ci u64 generation; 49628c2ecf20Sopenharmony_ci u64 parent; 49638c2ecf20Sopenharmony_ci struct btrfs_key key; 49648c2ecf20Sopenharmony_ci struct btrfs_key first_key; 49658c2ecf20Sopenharmony_ci struct btrfs_ref ref = { 0 }; 49668c2ecf20Sopenharmony_ci struct extent_buffer *next; 49678c2ecf20Sopenharmony_ci int level = wc->level; 49688c2ecf20Sopenharmony_ci int reada = 0; 49698c2ecf20Sopenharmony_ci int ret = 0; 49708c2ecf20Sopenharmony_ci bool need_account = false; 49718c2ecf20Sopenharmony_ci 49728c2ecf20Sopenharmony_ci generation = btrfs_node_ptr_generation(path->nodes[level], 49738c2ecf20Sopenharmony_ci path->slots[level]); 49748c2ecf20Sopenharmony_ci /* 49758c2ecf20Sopenharmony_ci * if the lower level block was created before the snapshot 49768c2ecf20Sopenharmony_ci * was created, we know there is no need to update back refs 49778c2ecf20Sopenharmony_ci * for the subtree 49788c2ecf20Sopenharmony_ci */ 49798c2ecf20Sopenharmony_ci if (wc->stage == UPDATE_BACKREF && 49808c2ecf20Sopenharmony_ci generation <= root->root_key.offset) { 49818c2ecf20Sopenharmony_ci *lookup_info = 1; 49828c2ecf20Sopenharmony_ci return 1; 49838c2ecf20Sopenharmony_ci } 49848c2ecf20Sopenharmony_ci 49858c2ecf20Sopenharmony_ci bytenr = btrfs_node_blockptr(path->nodes[level], path->slots[level]); 49868c2ecf20Sopenharmony_ci btrfs_node_key_to_cpu(path->nodes[level], &first_key, 49878c2ecf20Sopenharmony_ci path->slots[level]); 49888c2ecf20Sopenharmony_ci 49898c2ecf20Sopenharmony_ci next = find_extent_buffer(fs_info, bytenr); 49908c2ecf20Sopenharmony_ci if (!next) { 49918c2ecf20Sopenharmony_ci next = btrfs_find_create_tree_block(fs_info, bytenr); 49928c2ecf20Sopenharmony_ci if (IS_ERR(next)) 49938c2ecf20Sopenharmony_ci return PTR_ERR(next); 49948c2ecf20Sopenharmony_ci 49958c2ecf20Sopenharmony_ci btrfs_set_buffer_lockdep_class(root->root_key.objectid, next, 49968c2ecf20Sopenharmony_ci level - 1); 49978c2ecf20Sopenharmony_ci reada = 1; 49988c2ecf20Sopenharmony_ci } 49998c2ecf20Sopenharmony_ci btrfs_tree_lock(next); 50008c2ecf20Sopenharmony_ci btrfs_set_lock_blocking_write(next); 50018c2ecf20Sopenharmony_ci 50028c2ecf20Sopenharmony_ci ret = btrfs_lookup_extent_info(trans, fs_info, bytenr, level - 1, 1, 50038c2ecf20Sopenharmony_ci &wc->refs[level - 1], 50048c2ecf20Sopenharmony_ci &wc->flags[level - 1]); 50058c2ecf20Sopenharmony_ci if (ret < 0) 50068c2ecf20Sopenharmony_ci goto out_unlock; 50078c2ecf20Sopenharmony_ci 50088c2ecf20Sopenharmony_ci if (unlikely(wc->refs[level - 1] == 0)) { 50098c2ecf20Sopenharmony_ci btrfs_err(fs_info, "Missing references."); 50108c2ecf20Sopenharmony_ci ret = -EIO; 50118c2ecf20Sopenharmony_ci goto out_unlock; 50128c2ecf20Sopenharmony_ci } 50138c2ecf20Sopenharmony_ci *lookup_info = 0; 50148c2ecf20Sopenharmony_ci 50158c2ecf20Sopenharmony_ci if (wc->stage == DROP_REFERENCE) { 50168c2ecf20Sopenharmony_ci if (wc->refs[level - 1] > 1) { 50178c2ecf20Sopenharmony_ci need_account = true; 50188c2ecf20Sopenharmony_ci if (level == 1 && 50198c2ecf20Sopenharmony_ci (wc->flags[0] & BTRFS_BLOCK_FLAG_FULL_BACKREF)) 50208c2ecf20Sopenharmony_ci goto skip; 50218c2ecf20Sopenharmony_ci 50228c2ecf20Sopenharmony_ci if (!wc->update_ref || 50238c2ecf20Sopenharmony_ci generation <= root->root_key.offset) 50248c2ecf20Sopenharmony_ci goto skip; 50258c2ecf20Sopenharmony_ci 50268c2ecf20Sopenharmony_ci btrfs_node_key_to_cpu(path->nodes[level], &key, 50278c2ecf20Sopenharmony_ci path->slots[level]); 50288c2ecf20Sopenharmony_ci ret = btrfs_comp_cpu_keys(&key, &wc->update_progress); 50298c2ecf20Sopenharmony_ci if (ret < 0) 50308c2ecf20Sopenharmony_ci goto skip; 50318c2ecf20Sopenharmony_ci 50328c2ecf20Sopenharmony_ci wc->stage = UPDATE_BACKREF; 50338c2ecf20Sopenharmony_ci wc->shared_level = level - 1; 50348c2ecf20Sopenharmony_ci } 50358c2ecf20Sopenharmony_ci } else { 50368c2ecf20Sopenharmony_ci if (level == 1 && 50378c2ecf20Sopenharmony_ci (wc->flags[0] & BTRFS_BLOCK_FLAG_FULL_BACKREF)) 50388c2ecf20Sopenharmony_ci goto skip; 50398c2ecf20Sopenharmony_ci } 50408c2ecf20Sopenharmony_ci 50418c2ecf20Sopenharmony_ci if (!btrfs_buffer_uptodate(next, generation, 0)) { 50428c2ecf20Sopenharmony_ci btrfs_tree_unlock(next); 50438c2ecf20Sopenharmony_ci free_extent_buffer(next); 50448c2ecf20Sopenharmony_ci next = NULL; 50458c2ecf20Sopenharmony_ci *lookup_info = 1; 50468c2ecf20Sopenharmony_ci } 50478c2ecf20Sopenharmony_ci 50488c2ecf20Sopenharmony_ci if (!next) { 50498c2ecf20Sopenharmony_ci if (reada && level == 1) 50508c2ecf20Sopenharmony_ci reada_walk_down(trans, root, wc, path); 50518c2ecf20Sopenharmony_ci next = read_tree_block(fs_info, bytenr, generation, level - 1, 50528c2ecf20Sopenharmony_ci &first_key); 50538c2ecf20Sopenharmony_ci if (IS_ERR(next)) { 50548c2ecf20Sopenharmony_ci return PTR_ERR(next); 50558c2ecf20Sopenharmony_ci } else if (!extent_buffer_uptodate(next)) { 50568c2ecf20Sopenharmony_ci free_extent_buffer(next); 50578c2ecf20Sopenharmony_ci return -EIO; 50588c2ecf20Sopenharmony_ci } 50598c2ecf20Sopenharmony_ci btrfs_tree_lock(next); 50608c2ecf20Sopenharmony_ci btrfs_set_lock_blocking_write(next); 50618c2ecf20Sopenharmony_ci } 50628c2ecf20Sopenharmony_ci 50638c2ecf20Sopenharmony_ci level--; 50648c2ecf20Sopenharmony_ci ASSERT(level == btrfs_header_level(next)); 50658c2ecf20Sopenharmony_ci if (level != btrfs_header_level(next)) { 50668c2ecf20Sopenharmony_ci btrfs_err(root->fs_info, "mismatched level"); 50678c2ecf20Sopenharmony_ci ret = -EIO; 50688c2ecf20Sopenharmony_ci goto out_unlock; 50698c2ecf20Sopenharmony_ci } 50708c2ecf20Sopenharmony_ci path->nodes[level] = next; 50718c2ecf20Sopenharmony_ci path->slots[level] = 0; 50728c2ecf20Sopenharmony_ci path->locks[level] = BTRFS_WRITE_LOCK_BLOCKING; 50738c2ecf20Sopenharmony_ci wc->level = level; 50748c2ecf20Sopenharmony_ci if (wc->level == 1) 50758c2ecf20Sopenharmony_ci wc->reada_slot = 0; 50768c2ecf20Sopenharmony_ci return 0; 50778c2ecf20Sopenharmony_ciskip: 50788c2ecf20Sopenharmony_ci wc->refs[level - 1] = 0; 50798c2ecf20Sopenharmony_ci wc->flags[level - 1] = 0; 50808c2ecf20Sopenharmony_ci if (wc->stage == DROP_REFERENCE) { 50818c2ecf20Sopenharmony_ci if (wc->flags[level] & BTRFS_BLOCK_FLAG_FULL_BACKREF) { 50828c2ecf20Sopenharmony_ci parent = path->nodes[level]->start; 50838c2ecf20Sopenharmony_ci } else { 50848c2ecf20Sopenharmony_ci ASSERT(root->root_key.objectid == 50858c2ecf20Sopenharmony_ci btrfs_header_owner(path->nodes[level])); 50868c2ecf20Sopenharmony_ci if (root->root_key.objectid != 50878c2ecf20Sopenharmony_ci btrfs_header_owner(path->nodes[level])) { 50888c2ecf20Sopenharmony_ci btrfs_err(root->fs_info, 50898c2ecf20Sopenharmony_ci "mismatched block owner"); 50908c2ecf20Sopenharmony_ci ret = -EIO; 50918c2ecf20Sopenharmony_ci goto out_unlock; 50928c2ecf20Sopenharmony_ci } 50938c2ecf20Sopenharmony_ci parent = 0; 50948c2ecf20Sopenharmony_ci } 50958c2ecf20Sopenharmony_ci 50968c2ecf20Sopenharmony_ci /* 50978c2ecf20Sopenharmony_ci * If we had a drop_progress we need to verify the refs are set 50988c2ecf20Sopenharmony_ci * as expected. If we find our ref then we know that from here 50998c2ecf20Sopenharmony_ci * on out everything should be correct, and we can clear the 51008c2ecf20Sopenharmony_ci * ->restarted flag. 51018c2ecf20Sopenharmony_ci */ 51028c2ecf20Sopenharmony_ci if (wc->restarted) { 51038c2ecf20Sopenharmony_ci ret = check_ref_exists(trans, root, bytenr, parent, 51048c2ecf20Sopenharmony_ci level - 1); 51058c2ecf20Sopenharmony_ci if (ret < 0) 51068c2ecf20Sopenharmony_ci goto out_unlock; 51078c2ecf20Sopenharmony_ci if (ret == 0) 51088c2ecf20Sopenharmony_ci goto no_delete; 51098c2ecf20Sopenharmony_ci ret = 0; 51108c2ecf20Sopenharmony_ci wc->restarted = 0; 51118c2ecf20Sopenharmony_ci } 51128c2ecf20Sopenharmony_ci 51138c2ecf20Sopenharmony_ci /* 51148c2ecf20Sopenharmony_ci * Reloc tree doesn't contribute to qgroup numbers, and we have 51158c2ecf20Sopenharmony_ci * already accounted them at merge time (replace_path), 51168c2ecf20Sopenharmony_ci * thus we could skip expensive subtree trace here. 51178c2ecf20Sopenharmony_ci */ 51188c2ecf20Sopenharmony_ci if (root->root_key.objectid != BTRFS_TREE_RELOC_OBJECTID && 51198c2ecf20Sopenharmony_ci need_account) { 51208c2ecf20Sopenharmony_ci ret = btrfs_qgroup_trace_subtree(trans, next, 51218c2ecf20Sopenharmony_ci generation, level - 1); 51228c2ecf20Sopenharmony_ci if (ret) { 51238c2ecf20Sopenharmony_ci btrfs_err_rl(fs_info, 51248c2ecf20Sopenharmony_ci "Error %d accounting shared subtree. Quota is out of sync, rescan required.", 51258c2ecf20Sopenharmony_ci ret); 51268c2ecf20Sopenharmony_ci } 51278c2ecf20Sopenharmony_ci } 51288c2ecf20Sopenharmony_ci 51298c2ecf20Sopenharmony_ci /* 51308c2ecf20Sopenharmony_ci * We need to update the next key in our walk control so we can 51318c2ecf20Sopenharmony_ci * update the drop_progress key accordingly. We don't care if 51328c2ecf20Sopenharmony_ci * find_next_key doesn't find a key because that means we're at 51338c2ecf20Sopenharmony_ci * the end and are going to clean up now. 51348c2ecf20Sopenharmony_ci */ 51358c2ecf20Sopenharmony_ci wc->drop_level = level; 51368c2ecf20Sopenharmony_ci find_next_key(path, level, &wc->drop_progress); 51378c2ecf20Sopenharmony_ci 51388c2ecf20Sopenharmony_ci btrfs_init_generic_ref(&ref, BTRFS_DROP_DELAYED_REF, bytenr, 51398c2ecf20Sopenharmony_ci fs_info->nodesize, parent); 51408c2ecf20Sopenharmony_ci btrfs_init_tree_ref(&ref, level - 1, root->root_key.objectid); 51418c2ecf20Sopenharmony_ci ret = btrfs_free_extent(trans, &ref); 51428c2ecf20Sopenharmony_ci if (ret) 51438c2ecf20Sopenharmony_ci goto out_unlock; 51448c2ecf20Sopenharmony_ci } 51458c2ecf20Sopenharmony_cino_delete: 51468c2ecf20Sopenharmony_ci *lookup_info = 1; 51478c2ecf20Sopenharmony_ci ret = 1; 51488c2ecf20Sopenharmony_ci 51498c2ecf20Sopenharmony_ciout_unlock: 51508c2ecf20Sopenharmony_ci btrfs_tree_unlock(next); 51518c2ecf20Sopenharmony_ci free_extent_buffer(next); 51528c2ecf20Sopenharmony_ci 51538c2ecf20Sopenharmony_ci return ret; 51548c2ecf20Sopenharmony_ci} 51558c2ecf20Sopenharmony_ci 51568c2ecf20Sopenharmony_ci/* 51578c2ecf20Sopenharmony_ci * helper to process tree block while walking up the tree. 51588c2ecf20Sopenharmony_ci * 51598c2ecf20Sopenharmony_ci * when wc->stage == DROP_REFERENCE, this function drops 51608c2ecf20Sopenharmony_ci * reference count on the block. 51618c2ecf20Sopenharmony_ci * 51628c2ecf20Sopenharmony_ci * when wc->stage == UPDATE_BACKREF, this function changes 51638c2ecf20Sopenharmony_ci * wc->stage back to DROP_REFERENCE if we changed wc->stage 51648c2ecf20Sopenharmony_ci * to UPDATE_BACKREF previously while processing the block. 51658c2ecf20Sopenharmony_ci * 51668c2ecf20Sopenharmony_ci * NOTE: return value 1 means we should stop walking up. 51678c2ecf20Sopenharmony_ci */ 51688c2ecf20Sopenharmony_cistatic noinline int walk_up_proc(struct btrfs_trans_handle *trans, 51698c2ecf20Sopenharmony_ci struct btrfs_root *root, 51708c2ecf20Sopenharmony_ci struct btrfs_path *path, 51718c2ecf20Sopenharmony_ci struct walk_control *wc) 51728c2ecf20Sopenharmony_ci{ 51738c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = root->fs_info; 51748c2ecf20Sopenharmony_ci int ret; 51758c2ecf20Sopenharmony_ci int level = wc->level; 51768c2ecf20Sopenharmony_ci struct extent_buffer *eb = path->nodes[level]; 51778c2ecf20Sopenharmony_ci u64 parent = 0; 51788c2ecf20Sopenharmony_ci 51798c2ecf20Sopenharmony_ci if (wc->stage == UPDATE_BACKREF) { 51808c2ecf20Sopenharmony_ci BUG_ON(wc->shared_level < level); 51818c2ecf20Sopenharmony_ci if (level < wc->shared_level) 51828c2ecf20Sopenharmony_ci goto out; 51838c2ecf20Sopenharmony_ci 51848c2ecf20Sopenharmony_ci ret = find_next_key(path, level + 1, &wc->update_progress); 51858c2ecf20Sopenharmony_ci if (ret > 0) 51868c2ecf20Sopenharmony_ci wc->update_ref = 0; 51878c2ecf20Sopenharmony_ci 51888c2ecf20Sopenharmony_ci wc->stage = DROP_REFERENCE; 51898c2ecf20Sopenharmony_ci wc->shared_level = -1; 51908c2ecf20Sopenharmony_ci path->slots[level] = 0; 51918c2ecf20Sopenharmony_ci 51928c2ecf20Sopenharmony_ci /* 51938c2ecf20Sopenharmony_ci * check reference count again if the block isn't locked. 51948c2ecf20Sopenharmony_ci * we should start walking down the tree again if reference 51958c2ecf20Sopenharmony_ci * count is one. 51968c2ecf20Sopenharmony_ci */ 51978c2ecf20Sopenharmony_ci if (!path->locks[level]) { 51988c2ecf20Sopenharmony_ci BUG_ON(level == 0); 51998c2ecf20Sopenharmony_ci btrfs_tree_lock(eb); 52008c2ecf20Sopenharmony_ci btrfs_set_lock_blocking_write(eb); 52018c2ecf20Sopenharmony_ci path->locks[level] = BTRFS_WRITE_LOCK_BLOCKING; 52028c2ecf20Sopenharmony_ci 52038c2ecf20Sopenharmony_ci ret = btrfs_lookup_extent_info(trans, fs_info, 52048c2ecf20Sopenharmony_ci eb->start, level, 1, 52058c2ecf20Sopenharmony_ci &wc->refs[level], 52068c2ecf20Sopenharmony_ci &wc->flags[level]); 52078c2ecf20Sopenharmony_ci if (ret < 0) { 52088c2ecf20Sopenharmony_ci btrfs_tree_unlock_rw(eb, path->locks[level]); 52098c2ecf20Sopenharmony_ci path->locks[level] = 0; 52108c2ecf20Sopenharmony_ci return ret; 52118c2ecf20Sopenharmony_ci } 52128c2ecf20Sopenharmony_ci BUG_ON(wc->refs[level] == 0); 52138c2ecf20Sopenharmony_ci if (wc->refs[level] == 1) { 52148c2ecf20Sopenharmony_ci btrfs_tree_unlock_rw(eb, path->locks[level]); 52158c2ecf20Sopenharmony_ci path->locks[level] = 0; 52168c2ecf20Sopenharmony_ci return 1; 52178c2ecf20Sopenharmony_ci } 52188c2ecf20Sopenharmony_ci } 52198c2ecf20Sopenharmony_ci } 52208c2ecf20Sopenharmony_ci 52218c2ecf20Sopenharmony_ci /* wc->stage == DROP_REFERENCE */ 52228c2ecf20Sopenharmony_ci BUG_ON(wc->refs[level] > 1 && !path->locks[level]); 52238c2ecf20Sopenharmony_ci 52248c2ecf20Sopenharmony_ci if (wc->refs[level] == 1) { 52258c2ecf20Sopenharmony_ci if (level == 0) { 52268c2ecf20Sopenharmony_ci if (wc->flags[level] & BTRFS_BLOCK_FLAG_FULL_BACKREF) 52278c2ecf20Sopenharmony_ci ret = btrfs_dec_ref(trans, root, eb, 1); 52288c2ecf20Sopenharmony_ci else 52298c2ecf20Sopenharmony_ci ret = btrfs_dec_ref(trans, root, eb, 0); 52308c2ecf20Sopenharmony_ci BUG_ON(ret); /* -ENOMEM */ 52318c2ecf20Sopenharmony_ci if (is_fstree(root->root_key.objectid)) { 52328c2ecf20Sopenharmony_ci ret = btrfs_qgroup_trace_leaf_items(trans, eb); 52338c2ecf20Sopenharmony_ci if (ret) { 52348c2ecf20Sopenharmony_ci btrfs_err_rl(fs_info, 52358c2ecf20Sopenharmony_ci "error %d accounting leaf items, quota is out of sync, rescan required", 52368c2ecf20Sopenharmony_ci ret); 52378c2ecf20Sopenharmony_ci } 52388c2ecf20Sopenharmony_ci } 52398c2ecf20Sopenharmony_ci } 52408c2ecf20Sopenharmony_ci /* make block locked assertion in btrfs_clean_tree_block happy */ 52418c2ecf20Sopenharmony_ci if (!path->locks[level] && 52428c2ecf20Sopenharmony_ci btrfs_header_generation(eb) == trans->transid) { 52438c2ecf20Sopenharmony_ci btrfs_tree_lock(eb); 52448c2ecf20Sopenharmony_ci btrfs_set_lock_blocking_write(eb); 52458c2ecf20Sopenharmony_ci path->locks[level] = BTRFS_WRITE_LOCK_BLOCKING; 52468c2ecf20Sopenharmony_ci } 52478c2ecf20Sopenharmony_ci btrfs_clean_tree_block(eb); 52488c2ecf20Sopenharmony_ci } 52498c2ecf20Sopenharmony_ci 52508c2ecf20Sopenharmony_ci if (eb == root->node) { 52518c2ecf20Sopenharmony_ci if (wc->flags[level] & BTRFS_BLOCK_FLAG_FULL_BACKREF) 52528c2ecf20Sopenharmony_ci parent = eb->start; 52538c2ecf20Sopenharmony_ci else if (root->root_key.objectid != btrfs_header_owner(eb)) 52548c2ecf20Sopenharmony_ci goto owner_mismatch; 52558c2ecf20Sopenharmony_ci } else { 52568c2ecf20Sopenharmony_ci if (wc->flags[level + 1] & BTRFS_BLOCK_FLAG_FULL_BACKREF) 52578c2ecf20Sopenharmony_ci parent = path->nodes[level + 1]->start; 52588c2ecf20Sopenharmony_ci else if (root->root_key.objectid != 52598c2ecf20Sopenharmony_ci btrfs_header_owner(path->nodes[level + 1])) 52608c2ecf20Sopenharmony_ci goto owner_mismatch; 52618c2ecf20Sopenharmony_ci } 52628c2ecf20Sopenharmony_ci 52638c2ecf20Sopenharmony_ci btrfs_free_tree_block(trans, root, eb, parent, wc->refs[level] == 1); 52648c2ecf20Sopenharmony_ciout: 52658c2ecf20Sopenharmony_ci wc->refs[level] = 0; 52668c2ecf20Sopenharmony_ci wc->flags[level] = 0; 52678c2ecf20Sopenharmony_ci return 0; 52688c2ecf20Sopenharmony_ci 52698c2ecf20Sopenharmony_ciowner_mismatch: 52708c2ecf20Sopenharmony_ci btrfs_err_rl(fs_info, "unexpected tree owner, have %llu expect %llu", 52718c2ecf20Sopenharmony_ci btrfs_header_owner(eb), root->root_key.objectid); 52728c2ecf20Sopenharmony_ci return -EUCLEAN; 52738c2ecf20Sopenharmony_ci} 52748c2ecf20Sopenharmony_ci 52758c2ecf20Sopenharmony_cistatic noinline int walk_down_tree(struct btrfs_trans_handle *trans, 52768c2ecf20Sopenharmony_ci struct btrfs_root *root, 52778c2ecf20Sopenharmony_ci struct btrfs_path *path, 52788c2ecf20Sopenharmony_ci struct walk_control *wc) 52798c2ecf20Sopenharmony_ci{ 52808c2ecf20Sopenharmony_ci int level = wc->level; 52818c2ecf20Sopenharmony_ci int lookup_info = 1; 52828c2ecf20Sopenharmony_ci int ret; 52838c2ecf20Sopenharmony_ci 52848c2ecf20Sopenharmony_ci while (level >= 0) { 52858c2ecf20Sopenharmony_ci ret = walk_down_proc(trans, root, path, wc, lookup_info); 52868c2ecf20Sopenharmony_ci if (ret > 0) 52878c2ecf20Sopenharmony_ci break; 52888c2ecf20Sopenharmony_ci 52898c2ecf20Sopenharmony_ci if (level == 0) 52908c2ecf20Sopenharmony_ci break; 52918c2ecf20Sopenharmony_ci 52928c2ecf20Sopenharmony_ci if (path->slots[level] >= 52938c2ecf20Sopenharmony_ci btrfs_header_nritems(path->nodes[level])) 52948c2ecf20Sopenharmony_ci break; 52958c2ecf20Sopenharmony_ci 52968c2ecf20Sopenharmony_ci ret = do_walk_down(trans, root, path, wc, &lookup_info); 52978c2ecf20Sopenharmony_ci if (ret > 0) { 52988c2ecf20Sopenharmony_ci path->slots[level]++; 52998c2ecf20Sopenharmony_ci continue; 53008c2ecf20Sopenharmony_ci } else if (ret < 0) 53018c2ecf20Sopenharmony_ci return ret; 53028c2ecf20Sopenharmony_ci level = wc->level; 53038c2ecf20Sopenharmony_ci } 53048c2ecf20Sopenharmony_ci return 0; 53058c2ecf20Sopenharmony_ci} 53068c2ecf20Sopenharmony_ci 53078c2ecf20Sopenharmony_cistatic noinline int walk_up_tree(struct btrfs_trans_handle *trans, 53088c2ecf20Sopenharmony_ci struct btrfs_root *root, 53098c2ecf20Sopenharmony_ci struct btrfs_path *path, 53108c2ecf20Sopenharmony_ci struct walk_control *wc, int max_level) 53118c2ecf20Sopenharmony_ci{ 53128c2ecf20Sopenharmony_ci int level = wc->level; 53138c2ecf20Sopenharmony_ci int ret; 53148c2ecf20Sopenharmony_ci 53158c2ecf20Sopenharmony_ci path->slots[level] = btrfs_header_nritems(path->nodes[level]); 53168c2ecf20Sopenharmony_ci while (level < max_level && path->nodes[level]) { 53178c2ecf20Sopenharmony_ci wc->level = level; 53188c2ecf20Sopenharmony_ci if (path->slots[level] + 1 < 53198c2ecf20Sopenharmony_ci btrfs_header_nritems(path->nodes[level])) { 53208c2ecf20Sopenharmony_ci path->slots[level]++; 53218c2ecf20Sopenharmony_ci return 0; 53228c2ecf20Sopenharmony_ci } else { 53238c2ecf20Sopenharmony_ci ret = walk_up_proc(trans, root, path, wc); 53248c2ecf20Sopenharmony_ci if (ret > 0) 53258c2ecf20Sopenharmony_ci return 0; 53268c2ecf20Sopenharmony_ci if (ret < 0) 53278c2ecf20Sopenharmony_ci return ret; 53288c2ecf20Sopenharmony_ci 53298c2ecf20Sopenharmony_ci if (path->locks[level]) { 53308c2ecf20Sopenharmony_ci btrfs_tree_unlock_rw(path->nodes[level], 53318c2ecf20Sopenharmony_ci path->locks[level]); 53328c2ecf20Sopenharmony_ci path->locks[level] = 0; 53338c2ecf20Sopenharmony_ci } 53348c2ecf20Sopenharmony_ci free_extent_buffer(path->nodes[level]); 53358c2ecf20Sopenharmony_ci path->nodes[level] = NULL; 53368c2ecf20Sopenharmony_ci level++; 53378c2ecf20Sopenharmony_ci } 53388c2ecf20Sopenharmony_ci } 53398c2ecf20Sopenharmony_ci return 1; 53408c2ecf20Sopenharmony_ci} 53418c2ecf20Sopenharmony_ci 53428c2ecf20Sopenharmony_ci/* 53438c2ecf20Sopenharmony_ci * drop a subvolume tree. 53448c2ecf20Sopenharmony_ci * 53458c2ecf20Sopenharmony_ci * this function traverses the tree freeing any blocks that only 53468c2ecf20Sopenharmony_ci * referenced by the tree. 53478c2ecf20Sopenharmony_ci * 53488c2ecf20Sopenharmony_ci * when a shared tree block is found. this function decreases its 53498c2ecf20Sopenharmony_ci * reference count by one. if update_ref is true, this function 53508c2ecf20Sopenharmony_ci * also make sure backrefs for the shared block and all lower level 53518c2ecf20Sopenharmony_ci * blocks are properly updated. 53528c2ecf20Sopenharmony_ci * 53538c2ecf20Sopenharmony_ci * If called with for_reloc == 0, may exit early with -EAGAIN 53548c2ecf20Sopenharmony_ci */ 53558c2ecf20Sopenharmony_ciint btrfs_drop_snapshot(struct btrfs_root *root, int update_ref, int for_reloc) 53568c2ecf20Sopenharmony_ci{ 53578c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = root->fs_info; 53588c2ecf20Sopenharmony_ci struct btrfs_path *path; 53598c2ecf20Sopenharmony_ci struct btrfs_trans_handle *trans; 53608c2ecf20Sopenharmony_ci struct btrfs_root *tree_root = fs_info->tree_root; 53618c2ecf20Sopenharmony_ci struct btrfs_root_item *root_item = &root->root_item; 53628c2ecf20Sopenharmony_ci struct walk_control *wc; 53638c2ecf20Sopenharmony_ci struct btrfs_key key; 53648c2ecf20Sopenharmony_ci int err = 0; 53658c2ecf20Sopenharmony_ci int ret; 53668c2ecf20Sopenharmony_ci int level; 53678c2ecf20Sopenharmony_ci bool root_dropped = false; 53688c2ecf20Sopenharmony_ci 53698c2ecf20Sopenharmony_ci btrfs_debug(fs_info, "Drop subvolume %llu", root->root_key.objectid); 53708c2ecf20Sopenharmony_ci 53718c2ecf20Sopenharmony_ci path = btrfs_alloc_path(); 53728c2ecf20Sopenharmony_ci if (!path) { 53738c2ecf20Sopenharmony_ci err = -ENOMEM; 53748c2ecf20Sopenharmony_ci goto out; 53758c2ecf20Sopenharmony_ci } 53768c2ecf20Sopenharmony_ci 53778c2ecf20Sopenharmony_ci wc = kzalloc(sizeof(*wc), GFP_NOFS); 53788c2ecf20Sopenharmony_ci if (!wc) { 53798c2ecf20Sopenharmony_ci btrfs_free_path(path); 53808c2ecf20Sopenharmony_ci err = -ENOMEM; 53818c2ecf20Sopenharmony_ci goto out; 53828c2ecf20Sopenharmony_ci } 53838c2ecf20Sopenharmony_ci 53848c2ecf20Sopenharmony_ci /* 53858c2ecf20Sopenharmony_ci * Use join to avoid potential EINTR from transaction start. See 53868c2ecf20Sopenharmony_ci * wait_reserve_ticket and the whole reservation callchain. 53878c2ecf20Sopenharmony_ci */ 53888c2ecf20Sopenharmony_ci if (for_reloc) 53898c2ecf20Sopenharmony_ci trans = btrfs_join_transaction(tree_root); 53908c2ecf20Sopenharmony_ci else 53918c2ecf20Sopenharmony_ci trans = btrfs_start_transaction(tree_root, 0); 53928c2ecf20Sopenharmony_ci if (IS_ERR(trans)) { 53938c2ecf20Sopenharmony_ci err = PTR_ERR(trans); 53948c2ecf20Sopenharmony_ci goto out_free; 53958c2ecf20Sopenharmony_ci } 53968c2ecf20Sopenharmony_ci 53978c2ecf20Sopenharmony_ci err = btrfs_run_delayed_items(trans); 53988c2ecf20Sopenharmony_ci if (err) 53998c2ecf20Sopenharmony_ci goto out_end_trans; 54008c2ecf20Sopenharmony_ci 54018c2ecf20Sopenharmony_ci /* 54028c2ecf20Sopenharmony_ci * This will help us catch people modifying the fs tree while we're 54038c2ecf20Sopenharmony_ci * dropping it. It is unsafe to mess with the fs tree while it's being 54048c2ecf20Sopenharmony_ci * dropped as we unlock the root node and parent nodes as we walk down 54058c2ecf20Sopenharmony_ci * the tree, assuming nothing will change. If something does change 54068c2ecf20Sopenharmony_ci * then we'll have stale information and drop references to blocks we've 54078c2ecf20Sopenharmony_ci * already dropped. 54088c2ecf20Sopenharmony_ci */ 54098c2ecf20Sopenharmony_ci set_bit(BTRFS_ROOT_DELETING, &root->state); 54108c2ecf20Sopenharmony_ci if (btrfs_disk_key_objectid(&root_item->drop_progress) == 0) { 54118c2ecf20Sopenharmony_ci level = btrfs_header_level(root->node); 54128c2ecf20Sopenharmony_ci path->nodes[level] = btrfs_lock_root_node(root); 54138c2ecf20Sopenharmony_ci btrfs_set_lock_blocking_write(path->nodes[level]); 54148c2ecf20Sopenharmony_ci path->slots[level] = 0; 54158c2ecf20Sopenharmony_ci path->locks[level] = BTRFS_WRITE_LOCK_BLOCKING; 54168c2ecf20Sopenharmony_ci memset(&wc->update_progress, 0, 54178c2ecf20Sopenharmony_ci sizeof(wc->update_progress)); 54188c2ecf20Sopenharmony_ci } else { 54198c2ecf20Sopenharmony_ci btrfs_disk_key_to_cpu(&key, &root_item->drop_progress); 54208c2ecf20Sopenharmony_ci memcpy(&wc->update_progress, &key, 54218c2ecf20Sopenharmony_ci sizeof(wc->update_progress)); 54228c2ecf20Sopenharmony_ci 54238c2ecf20Sopenharmony_ci level = root_item->drop_level; 54248c2ecf20Sopenharmony_ci BUG_ON(level == 0); 54258c2ecf20Sopenharmony_ci path->lowest_level = level; 54268c2ecf20Sopenharmony_ci ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); 54278c2ecf20Sopenharmony_ci path->lowest_level = 0; 54288c2ecf20Sopenharmony_ci if (ret < 0) { 54298c2ecf20Sopenharmony_ci err = ret; 54308c2ecf20Sopenharmony_ci goto out_end_trans; 54318c2ecf20Sopenharmony_ci } 54328c2ecf20Sopenharmony_ci WARN_ON(ret > 0); 54338c2ecf20Sopenharmony_ci 54348c2ecf20Sopenharmony_ci /* 54358c2ecf20Sopenharmony_ci * unlock our path, this is safe because only this 54368c2ecf20Sopenharmony_ci * function is allowed to delete this snapshot 54378c2ecf20Sopenharmony_ci */ 54388c2ecf20Sopenharmony_ci btrfs_unlock_up_safe(path, 0); 54398c2ecf20Sopenharmony_ci 54408c2ecf20Sopenharmony_ci level = btrfs_header_level(root->node); 54418c2ecf20Sopenharmony_ci while (1) { 54428c2ecf20Sopenharmony_ci btrfs_tree_lock(path->nodes[level]); 54438c2ecf20Sopenharmony_ci btrfs_set_lock_blocking_write(path->nodes[level]); 54448c2ecf20Sopenharmony_ci path->locks[level] = BTRFS_WRITE_LOCK_BLOCKING; 54458c2ecf20Sopenharmony_ci 54468c2ecf20Sopenharmony_ci ret = btrfs_lookup_extent_info(trans, fs_info, 54478c2ecf20Sopenharmony_ci path->nodes[level]->start, 54488c2ecf20Sopenharmony_ci level, 1, &wc->refs[level], 54498c2ecf20Sopenharmony_ci &wc->flags[level]); 54508c2ecf20Sopenharmony_ci if (ret < 0) { 54518c2ecf20Sopenharmony_ci err = ret; 54528c2ecf20Sopenharmony_ci goto out_end_trans; 54538c2ecf20Sopenharmony_ci } 54548c2ecf20Sopenharmony_ci BUG_ON(wc->refs[level] == 0); 54558c2ecf20Sopenharmony_ci 54568c2ecf20Sopenharmony_ci if (level == root_item->drop_level) 54578c2ecf20Sopenharmony_ci break; 54588c2ecf20Sopenharmony_ci 54598c2ecf20Sopenharmony_ci btrfs_tree_unlock(path->nodes[level]); 54608c2ecf20Sopenharmony_ci path->locks[level] = 0; 54618c2ecf20Sopenharmony_ci WARN_ON(wc->refs[level] != 1); 54628c2ecf20Sopenharmony_ci level--; 54638c2ecf20Sopenharmony_ci } 54648c2ecf20Sopenharmony_ci } 54658c2ecf20Sopenharmony_ci 54668c2ecf20Sopenharmony_ci wc->restarted = test_bit(BTRFS_ROOT_DEAD_TREE, &root->state); 54678c2ecf20Sopenharmony_ci wc->level = level; 54688c2ecf20Sopenharmony_ci wc->shared_level = -1; 54698c2ecf20Sopenharmony_ci wc->stage = DROP_REFERENCE; 54708c2ecf20Sopenharmony_ci wc->update_ref = update_ref; 54718c2ecf20Sopenharmony_ci wc->keep_locks = 0; 54728c2ecf20Sopenharmony_ci wc->reada_count = BTRFS_NODEPTRS_PER_BLOCK(fs_info); 54738c2ecf20Sopenharmony_ci 54748c2ecf20Sopenharmony_ci while (1) { 54758c2ecf20Sopenharmony_ci 54768c2ecf20Sopenharmony_ci ret = walk_down_tree(trans, root, path, wc); 54778c2ecf20Sopenharmony_ci if (ret < 0) { 54788c2ecf20Sopenharmony_ci err = ret; 54798c2ecf20Sopenharmony_ci break; 54808c2ecf20Sopenharmony_ci } 54818c2ecf20Sopenharmony_ci 54828c2ecf20Sopenharmony_ci ret = walk_up_tree(trans, root, path, wc, BTRFS_MAX_LEVEL); 54838c2ecf20Sopenharmony_ci if (ret < 0) { 54848c2ecf20Sopenharmony_ci err = ret; 54858c2ecf20Sopenharmony_ci break; 54868c2ecf20Sopenharmony_ci } 54878c2ecf20Sopenharmony_ci 54888c2ecf20Sopenharmony_ci if (ret > 0) { 54898c2ecf20Sopenharmony_ci BUG_ON(wc->stage != DROP_REFERENCE); 54908c2ecf20Sopenharmony_ci break; 54918c2ecf20Sopenharmony_ci } 54928c2ecf20Sopenharmony_ci 54938c2ecf20Sopenharmony_ci if (wc->stage == DROP_REFERENCE) { 54948c2ecf20Sopenharmony_ci wc->drop_level = wc->level; 54958c2ecf20Sopenharmony_ci btrfs_node_key_to_cpu(path->nodes[wc->drop_level], 54968c2ecf20Sopenharmony_ci &wc->drop_progress, 54978c2ecf20Sopenharmony_ci path->slots[wc->drop_level]); 54988c2ecf20Sopenharmony_ci } 54998c2ecf20Sopenharmony_ci btrfs_cpu_key_to_disk(&root_item->drop_progress, 55008c2ecf20Sopenharmony_ci &wc->drop_progress); 55018c2ecf20Sopenharmony_ci root_item->drop_level = wc->drop_level; 55028c2ecf20Sopenharmony_ci 55038c2ecf20Sopenharmony_ci BUG_ON(wc->level == 0); 55048c2ecf20Sopenharmony_ci if (btrfs_should_end_transaction(trans) || 55058c2ecf20Sopenharmony_ci (!for_reloc && btrfs_need_cleaner_sleep(fs_info))) { 55068c2ecf20Sopenharmony_ci ret = btrfs_update_root(trans, tree_root, 55078c2ecf20Sopenharmony_ci &root->root_key, 55088c2ecf20Sopenharmony_ci root_item); 55098c2ecf20Sopenharmony_ci if (ret) { 55108c2ecf20Sopenharmony_ci btrfs_abort_transaction(trans, ret); 55118c2ecf20Sopenharmony_ci err = ret; 55128c2ecf20Sopenharmony_ci goto out_end_trans; 55138c2ecf20Sopenharmony_ci } 55148c2ecf20Sopenharmony_ci 55158c2ecf20Sopenharmony_ci btrfs_end_transaction_throttle(trans); 55168c2ecf20Sopenharmony_ci if (!for_reloc && btrfs_need_cleaner_sleep(fs_info)) { 55178c2ecf20Sopenharmony_ci btrfs_debug(fs_info, 55188c2ecf20Sopenharmony_ci "drop snapshot early exit"); 55198c2ecf20Sopenharmony_ci err = -EAGAIN; 55208c2ecf20Sopenharmony_ci goto out_free; 55218c2ecf20Sopenharmony_ci } 55228c2ecf20Sopenharmony_ci 55238c2ecf20Sopenharmony_ci /* 55248c2ecf20Sopenharmony_ci * Use join to avoid potential EINTR from transaction 55258c2ecf20Sopenharmony_ci * start. See wait_reserve_ticket and the whole 55268c2ecf20Sopenharmony_ci * reservation callchain. 55278c2ecf20Sopenharmony_ci */ 55288c2ecf20Sopenharmony_ci if (for_reloc) 55298c2ecf20Sopenharmony_ci trans = btrfs_join_transaction(tree_root); 55308c2ecf20Sopenharmony_ci else 55318c2ecf20Sopenharmony_ci trans = btrfs_start_transaction(tree_root, 0); 55328c2ecf20Sopenharmony_ci if (IS_ERR(trans)) { 55338c2ecf20Sopenharmony_ci err = PTR_ERR(trans); 55348c2ecf20Sopenharmony_ci goto out_free; 55358c2ecf20Sopenharmony_ci } 55368c2ecf20Sopenharmony_ci } 55378c2ecf20Sopenharmony_ci } 55388c2ecf20Sopenharmony_ci btrfs_release_path(path); 55398c2ecf20Sopenharmony_ci if (err) 55408c2ecf20Sopenharmony_ci goto out_end_trans; 55418c2ecf20Sopenharmony_ci 55428c2ecf20Sopenharmony_ci ret = btrfs_del_root(trans, &root->root_key); 55438c2ecf20Sopenharmony_ci if (ret) { 55448c2ecf20Sopenharmony_ci btrfs_abort_transaction(trans, ret); 55458c2ecf20Sopenharmony_ci err = ret; 55468c2ecf20Sopenharmony_ci goto out_end_trans; 55478c2ecf20Sopenharmony_ci } 55488c2ecf20Sopenharmony_ci 55498c2ecf20Sopenharmony_ci if (root->root_key.objectid != BTRFS_TREE_RELOC_OBJECTID) { 55508c2ecf20Sopenharmony_ci ret = btrfs_find_root(tree_root, &root->root_key, path, 55518c2ecf20Sopenharmony_ci NULL, NULL); 55528c2ecf20Sopenharmony_ci if (ret < 0) { 55538c2ecf20Sopenharmony_ci btrfs_abort_transaction(trans, ret); 55548c2ecf20Sopenharmony_ci err = ret; 55558c2ecf20Sopenharmony_ci goto out_end_trans; 55568c2ecf20Sopenharmony_ci } else if (ret > 0) { 55578c2ecf20Sopenharmony_ci /* if we fail to delete the orphan item this time 55588c2ecf20Sopenharmony_ci * around, it'll get picked up the next time. 55598c2ecf20Sopenharmony_ci * 55608c2ecf20Sopenharmony_ci * The most common failure here is just -ENOENT. 55618c2ecf20Sopenharmony_ci */ 55628c2ecf20Sopenharmony_ci btrfs_del_orphan_item(trans, tree_root, 55638c2ecf20Sopenharmony_ci root->root_key.objectid); 55648c2ecf20Sopenharmony_ci } 55658c2ecf20Sopenharmony_ci } 55668c2ecf20Sopenharmony_ci 55678c2ecf20Sopenharmony_ci /* 55688c2ecf20Sopenharmony_ci * This subvolume is going to be completely dropped, and won't be 55698c2ecf20Sopenharmony_ci * recorded as dirty roots, thus pertrans meta rsv will not be freed at 55708c2ecf20Sopenharmony_ci * commit transaction time. So free it here manually. 55718c2ecf20Sopenharmony_ci */ 55728c2ecf20Sopenharmony_ci btrfs_qgroup_convert_reserved_meta(root, INT_MAX); 55738c2ecf20Sopenharmony_ci btrfs_qgroup_free_meta_all_pertrans(root); 55748c2ecf20Sopenharmony_ci 55758c2ecf20Sopenharmony_ci if (test_bit(BTRFS_ROOT_IN_RADIX, &root->state)) 55768c2ecf20Sopenharmony_ci btrfs_add_dropped_root(trans, root); 55778c2ecf20Sopenharmony_ci else 55788c2ecf20Sopenharmony_ci btrfs_put_root(root); 55798c2ecf20Sopenharmony_ci root_dropped = true; 55808c2ecf20Sopenharmony_ciout_end_trans: 55818c2ecf20Sopenharmony_ci btrfs_end_transaction_throttle(trans); 55828c2ecf20Sopenharmony_ciout_free: 55838c2ecf20Sopenharmony_ci kfree(wc); 55848c2ecf20Sopenharmony_ci btrfs_free_path(path); 55858c2ecf20Sopenharmony_ciout: 55868c2ecf20Sopenharmony_ci /* 55878c2ecf20Sopenharmony_ci * So if we need to stop dropping the snapshot for whatever reason we 55888c2ecf20Sopenharmony_ci * need to make sure to add it back to the dead root list so that we 55898c2ecf20Sopenharmony_ci * keep trying to do the work later. This also cleans up roots if we 55908c2ecf20Sopenharmony_ci * don't have it in the radix (like when we recover after a power fail 55918c2ecf20Sopenharmony_ci * or unmount) so we don't leak memory. 55928c2ecf20Sopenharmony_ci */ 55938c2ecf20Sopenharmony_ci if (!for_reloc && !root_dropped) 55948c2ecf20Sopenharmony_ci btrfs_add_dead_root(root); 55958c2ecf20Sopenharmony_ci return err; 55968c2ecf20Sopenharmony_ci} 55978c2ecf20Sopenharmony_ci 55988c2ecf20Sopenharmony_ci/* 55998c2ecf20Sopenharmony_ci * drop subtree rooted at tree block 'node'. 56008c2ecf20Sopenharmony_ci * 56018c2ecf20Sopenharmony_ci * NOTE: this function will unlock and release tree block 'node' 56028c2ecf20Sopenharmony_ci * only used by relocation code 56038c2ecf20Sopenharmony_ci */ 56048c2ecf20Sopenharmony_ciint btrfs_drop_subtree(struct btrfs_trans_handle *trans, 56058c2ecf20Sopenharmony_ci struct btrfs_root *root, 56068c2ecf20Sopenharmony_ci struct extent_buffer *node, 56078c2ecf20Sopenharmony_ci struct extent_buffer *parent) 56088c2ecf20Sopenharmony_ci{ 56098c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = root->fs_info; 56108c2ecf20Sopenharmony_ci struct btrfs_path *path; 56118c2ecf20Sopenharmony_ci struct walk_control *wc; 56128c2ecf20Sopenharmony_ci int level; 56138c2ecf20Sopenharmony_ci int parent_level; 56148c2ecf20Sopenharmony_ci int ret = 0; 56158c2ecf20Sopenharmony_ci int wret; 56168c2ecf20Sopenharmony_ci 56178c2ecf20Sopenharmony_ci BUG_ON(root->root_key.objectid != BTRFS_TREE_RELOC_OBJECTID); 56188c2ecf20Sopenharmony_ci 56198c2ecf20Sopenharmony_ci path = btrfs_alloc_path(); 56208c2ecf20Sopenharmony_ci if (!path) 56218c2ecf20Sopenharmony_ci return -ENOMEM; 56228c2ecf20Sopenharmony_ci 56238c2ecf20Sopenharmony_ci wc = kzalloc(sizeof(*wc), GFP_NOFS); 56248c2ecf20Sopenharmony_ci if (!wc) { 56258c2ecf20Sopenharmony_ci btrfs_free_path(path); 56268c2ecf20Sopenharmony_ci return -ENOMEM; 56278c2ecf20Sopenharmony_ci } 56288c2ecf20Sopenharmony_ci 56298c2ecf20Sopenharmony_ci btrfs_assert_tree_locked(parent); 56308c2ecf20Sopenharmony_ci parent_level = btrfs_header_level(parent); 56318c2ecf20Sopenharmony_ci atomic_inc(&parent->refs); 56328c2ecf20Sopenharmony_ci path->nodes[parent_level] = parent; 56338c2ecf20Sopenharmony_ci path->slots[parent_level] = btrfs_header_nritems(parent); 56348c2ecf20Sopenharmony_ci 56358c2ecf20Sopenharmony_ci btrfs_assert_tree_locked(node); 56368c2ecf20Sopenharmony_ci level = btrfs_header_level(node); 56378c2ecf20Sopenharmony_ci path->nodes[level] = node; 56388c2ecf20Sopenharmony_ci path->slots[level] = 0; 56398c2ecf20Sopenharmony_ci path->locks[level] = BTRFS_WRITE_LOCK_BLOCKING; 56408c2ecf20Sopenharmony_ci 56418c2ecf20Sopenharmony_ci wc->refs[parent_level] = 1; 56428c2ecf20Sopenharmony_ci wc->flags[parent_level] = BTRFS_BLOCK_FLAG_FULL_BACKREF; 56438c2ecf20Sopenharmony_ci wc->level = level; 56448c2ecf20Sopenharmony_ci wc->shared_level = -1; 56458c2ecf20Sopenharmony_ci wc->stage = DROP_REFERENCE; 56468c2ecf20Sopenharmony_ci wc->update_ref = 0; 56478c2ecf20Sopenharmony_ci wc->keep_locks = 1; 56488c2ecf20Sopenharmony_ci wc->reada_count = BTRFS_NODEPTRS_PER_BLOCK(fs_info); 56498c2ecf20Sopenharmony_ci 56508c2ecf20Sopenharmony_ci while (1) { 56518c2ecf20Sopenharmony_ci wret = walk_down_tree(trans, root, path, wc); 56528c2ecf20Sopenharmony_ci if (wret < 0) { 56538c2ecf20Sopenharmony_ci ret = wret; 56548c2ecf20Sopenharmony_ci break; 56558c2ecf20Sopenharmony_ci } 56568c2ecf20Sopenharmony_ci 56578c2ecf20Sopenharmony_ci wret = walk_up_tree(trans, root, path, wc, parent_level); 56588c2ecf20Sopenharmony_ci if (wret < 0) 56598c2ecf20Sopenharmony_ci ret = wret; 56608c2ecf20Sopenharmony_ci if (wret != 0) 56618c2ecf20Sopenharmony_ci break; 56628c2ecf20Sopenharmony_ci } 56638c2ecf20Sopenharmony_ci 56648c2ecf20Sopenharmony_ci kfree(wc); 56658c2ecf20Sopenharmony_ci btrfs_free_path(path); 56668c2ecf20Sopenharmony_ci return ret; 56678c2ecf20Sopenharmony_ci} 56688c2ecf20Sopenharmony_ci 56698c2ecf20Sopenharmony_ci/* 56708c2ecf20Sopenharmony_ci * helper to account the unused space of all the readonly block group in the 56718c2ecf20Sopenharmony_ci * space_info. takes mirrors into account. 56728c2ecf20Sopenharmony_ci */ 56738c2ecf20Sopenharmony_ciu64 btrfs_account_ro_block_groups_free_space(struct btrfs_space_info *sinfo) 56748c2ecf20Sopenharmony_ci{ 56758c2ecf20Sopenharmony_ci struct btrfs_block_group *block_group; 56768c2ecf20Sopenharmony_ci u64 free_bytes = 0; 56778c2ecf20Sopenharmony_ci int factor; 56788c2ecf20Sopenharmony_ci 56798c2ecf20Sopenharmony_ci /* It's df, we don't care if it's racy */ 56808c2ecf20Sopenharmony_ci if (list_empty(&sinfo->ro_bgs)) 56818c2ecf20Sopenharmony_ci return 0; 56828c2ecf20Sopenharmony_ci 56838c2ecf20Sopenharmony_ci spin_lock(&sinfo->lock); 56848c2ecf20Sopenharmony_ci list_for_each_entry(block_group, &sinfo->ro_bgs, ro_list) { 56858c2ecf20Sopenharmony_ci spin_lock(&block_group->lock); 56868c2ecf20Sopenharmony_ci 56878c2ecf20Sopenharmony_ci if (!block_group->ro) { 56888c2ecf20Sopenharmony_ci spin_unlock(&block_group->lock); 56898c2ecf20Sopenharmony_ci continue; 56908c2ecf20Sopenharmony_ci } 56918c2ecf20Sopenharmony_ci 56928c2ecf20Sopenharmony_ci factor = btrfs_bg_type_to_factor(block_group->flags); 56938c2ecf20Sopenharmony_ci free_bytes += (block_group->length - 56948c2ecf20Sopenharmony_ci block_group->used) * factor; 56958c2ecf20Sopenharmony_ci 56968c2ecf20Sopenharmony_ci spin_unlock(&block_group->lock); 56978c2ecf20Sopenharmony_ci } 56988c2ecf20Sopenharmony_ci spin_unlock(&sinfo->lock); 56998c2ecf20Sopenharmony_ci 57008c2ecf20Sopenharmony_ci return free_bytes; 57018c2ecf20Sopenharmony_ci} 57028c2ecf20Sopenharmony_ci 57038c2ecf20Sopenharmony_ciint btrfs_error_unpin_extent_range(struct btrfs_fs_info *fs_info, 57048c2ecf20Sopenharmony_ci u64 start, u64 end) 57058c2ecf20Sopenharmony_ci{ 57068c2ecf20Sopenharmony_ci return unpin_extent_range(fs_info, start, end, false); 57078c2ecf20Sopenharmony_ci} 57088c2ecf20Sopenharmony_ci 57098c2ecf20Sopenharmony_ci/* 57108c2ecf20Sopenharmony_ci * It used to be that old block groups would be left around forever. 57118c2ecf20Sopenharmony_ci * Iterating over them would be enough to trim unused space. Since we 57128c2ecf20Sopenharmony_ci * now automatically remove them, we also need to iterate over unallocated 57138c2ecf20Sopenharmony_ci * space. 57148c2ecf20Sopenharmony_ci * 57158c2ecf20Sopenharmony_ci * We don't want a transaction for this since the discard may take a 57168c2ecf20Sopenharmony_ci * substantial amount of time. We don't require that a transaction be 57178c2ecf20Sopenharmony_ci * running, but we do need to take a running transaction into account 57188c2ecf20Sopenharmony_ci * to ensure that we're not discarding chunks that were released or 57198c2ecf20Sopenharmony_ci * allocated in the current transaction. 57208c2ecf20Sopenharmony_ci * 57218c2ecf20Sopenharmony_ci * Holding the chunks lock will prevent other threads from allocating 57228c2ecf20Sopenharmony_ci * or releasing chunks, but it won't prevent a running transaction 57238c2ecf20Sopenharmony_ci * from committing and releasing the memory that the pending chunks 57248c2ecf20Sopenharmony_ci * list head uses. For that, we need to take a reference to the 57258c2ecf20Sopenharmony_ci * transaction and hold the commit root sem. We only need to hold 57268c2ecf20Sopenharmony_ci * it while performing the free space search since we have already 57278c2ecf20Sopenharmony_ci * held back allocations. 57288c2ecf20Sopenharmony_ci */ 57298c2ecf20Sopenharmony_cistatic int btrfs_trim_free_extents(struct btrfs_device *device, u64 *trimmed) 57308c2ecf20Sopenharmony_ci{ 57318c2ecf20Sopenharmony_ci u64 start = SZ_1M, len = 0, end = 0; 57328c2ecf20Sopenharmony_ci int ret; 57338c2ecf20Sopenharmony_ci 57348c2ecf20Sopenharmony_ci *trimmed = 0; 57358c2ecf20Sopenharmony_ci 57368c2ecf20Sopenharmony_ci /* Discard not supported = nothing to do. */ 57378c2ecf20Sopenharmony_ci if (!blk_queue_discard(bdev_get_queue(device->bdev))) 57388c2ecf20Sopenharmony_ci return 0; 57398c2ecf20Sopenharmony_ci 57408c2ecf20Sopenharmony_ci /* Not writable = nothing to do. */ 57418c2ecf20Sopenharmony_ci if (!test_bit(BTRFS_DEV_STATE_WRITEABLE, &device->dev_state)) 57428c2ecf20Sopenharmony_ci return 0; 57438c2ecf20Sopenharmony_ci 57448c2ecf20Sopenharmony_ci /* No free space = nothing to do. */ 57458c2ecf20Sopenharmony_ci if (device->total_bytes <= device->bytes_used) 57468c2ecf20Sopenharmony_ci return 0; 57478c2ecf20Sopenharmony_ci 57488c2ecf20Sopenharmony_ci ret = 0; 57498c2ecf20Sopenharmony_ci 57508c2ecf20Sopenharmony_ci while (1) { 57518c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = device->fs_info; 57528c2ecf20Sopenharmony_ci u64 bytes; 57538c2ecf20Sopenharmony_ci 57548c2ecf20Sopenharmony_ci ret = mutex_lock_interruptible(&fs_info->chunk_mutex); 57558c2ecf20Sopenharmony_ci if (ret) 57568c2ecf20Sopenharmony_ci break; 57578c2ecf20Sopenharmony_ci 57588c2ecf20Sopenharmony_ci find_first_clear_extent_bit(&device->alloc_state, start, 57598c2ecf20Sopenharmony_ci &start, &end, 57608c2ecf20Sopenharmony_ci CHUNK_TRIMMED | CHUNK_ALLOCATED); 57618c2ecf20Sopenharmony_ci 57628c2ecf20Sopenharmony_ci /* Check if there are any CHUNK_* bits left */ 57638c2ecf20Sopenharmony_ci if (start > device->total_bytes) { 57648c2ecf20Sopenharmony_ci WARN_ON(IS_ENABLED(CONFIG_BTRFS_DEBUG)); 57658c2ecf20Sopenharmony_ci btrfs_warn_in_rcu(fs_info, 57668c2ecf20Sopenharmony_ci"ignoring attempt to trim beyond device size: offset %llu length %llu device %s device size %llu", 57678c2ecf20Sopenharmony_ci start, end - start + 1, 57688c2ecf20Sopenharmony_ci rcu_str_deref(device->name), 57698c2ecf20Sopenharmony_ci device->total_bytes); 57708c2ecf20Sopenharmony_ci mutex_unlock(&fs_info->chunk_mutex); 57718c2ecf20Sopenharmony_ci ret = 0; 57728c2ecf20Sopenharmony_ci break; 57738c2ecf20Sopenharmony_ci } 57748c2ecf20Sopenharmony_ci 57758c2ecf20Sopenharmony_ci /* Ensure we skip the reserved area in the first 1M */ 57768c2ecf20Sopenharmony_ci start = max_t(u64, start, SZ_1M); 57778c2ecf20Sopenharmony_ci 57788c2ecf20Sopenharmony_ci /* 57798c2ecf20Sopenharmony_ci * If find_first_clear_extent_bit find a range that spans the 57808c2ecf20Sopenharmony_ci * end of the device it will set end to -1, in this case it's up 57818c2ecf20Sopenharmony_ci * to the caller to trim the value to the size of the device. 57828c2ecf20Sopenharmony_ci */ 57838c2ecf20Sopenharmony_ci end = min(end, device->total_bytes - 1); 57848c2ecf20Sopenharmony_ci 57858c2ecf20Sopenharmony_ci len = end - start + 1; 57868c2ecf20Sopenharmony_ci 57878c2ecf20Sopenharmony_ci /* We didn't find any extents */ 57888c2ecf20Sopenharmony_ci if (!len) { 57898c2ecf20Sopenharmony_ci mutex_unlock(&fs_info->chunk_mutex); 57908c2ecf20Sopenharmony_ci ret = 0; 57918c2ecf20Sopenharmony_ci break; 57928c2ecf20Sopenharmony_ci } 57938c2ecf20Sopenharmony_ci 57948c2ecf20Sopenharmony_ci ret = btrfs_issue_discard(device->bdev, start, len, 57958c2ecf20Sopenharmony_ci &bytes); 57968c2ecf20Sopenharmony_ci if (!ret) 57978c2ecf20Sopenharmony_ci set_extent_bits(&device->alloc_state, start, 57988c2ecf20Sopenharmony_ci start + bytes - 1, 57998c2ecf20Sopenharmony_ci CHUNK_TRIMMED); 58008c2ecf20Sopenharmony_ci mutex_unlock(&fs_info->chunk_mutex); 58018c2ecf20Sopenharmony_ci 58028c2ecf20Sopenharmony_ci if (ret) 58038c2ecf20Sopenharmony_ci break; 58048c2ecf20Sopenharmony_ci 58058c2ecf20Sopenharmony_ci start += len; 58068c2ecf20Sopenharmony_ci *trimmed += bytes; 58078c2ecf20Sopenharmony_ci 58088c2ecf20Sopenharmony_ci if (fatal_signal_pending(current)) { 58098c2ecf20Sopenharmony_ci ret = -ERESTARTSYS; 58108c2ecf20Sopenharmony_ci break; 58118c2ecf20Sopenharmony_ci } 58128c2ecf20Sopenharmony_ci 58138c2ecf20Sopenharmony_ci cond_resched(); 58148c2ecf20Sopenharmony_ci } 58158c2ecf20Sopenharmony_ci 58168c2ecf20Sopenharmony_ci return ret; 58178c2ecf20Sopenharmony_ci} 58188c2ecf20Sopenharmony_ci 58198c2ecf20Sopenharmony_ci/* 58208c2ecf20Sopenharmony_ci * Trim the whole filesystem by: 58218c2ecf20Sopenharmony_ci * 1) trimming the free space in each block group 58228c2ecf20Sopenharmony_ci * 2) trimming the unallocated space on each device 58238c2ecf20Sopenharmony_ci * 58248c2ecf20Sopenharmony_ci * This will also continue trimming even if a block group or device encounters 58258c2ecf20Sopenharmony_ci * an error. The return value will be the last error, or 0 if nothing bad 58268c2ecf20Sopenharmony_ci * happens. 58278c2ecf20Sopenharmony_ci */ 58288c2ecf20Sopenharmony_ciint btrfs_trim_fs(struct btrfs_fs_info *fs_info, struct fstrim_range *range) 58298c2ecf20Sopenharmony_ci{ 58308c2ecf20Sopenharmony_ci struct btrfs_block_group *cache = NULL; 58318c2ecf20Sopenharmony_ci struct btrfs_device *device; 58328c2ecf20Sopenharmony_ci struct list_head *devices; 58338c2ecf20Sopenharmony_ci u64 group_trimmed; 58348c2ecf20Sopenharmony_ci u64 range_end = U64_MAX; 58358c2ecf20Sopenharmony_ci u64 start; 58368c2ecf20Sopenharmony_ci u64 end; 58378c2ecf20Sopenharmony_ci u64 trimmed = 0; 58388c2ecf20Sopenharmony_ci u64 bg_failed = 0; 58398c2ecf20Sopenharmony_ci u64 dev_failed = 0; 58408c2ecf20Sopenharmony_ci int bg_ret = 0; 58418c2ecf20Sopenharmony_ci int dev_ret = 0; 58428c2ecf20Sopenharmony_ci int ret = 0; 58438c2ecf20Sopenharmony_ci 58448c2ecf20Sopenharmony_ci /* 58458c2ecf20Sopenharmony_ci * Check range overflow if range->len is set. 58468c2ecf20Sopenharmony_ci * The default range->len is U64_MAX. 58478c2ecf20Sopenharmony_ci */ 58488c2ecf20Sopenharmony_ci if (range->len != U64_MAX && 58498c2ecf20Sopenharmony_ci check_add_overflow(range->start, range->len, &range_end)) 58508c2ecf20Sopenharmony_ci return -EINVAL; 58518c2ecf20Sopenharmony_ci 58528c2ecf20Sopenharmony_ci cache = btrfs_lookup_first_block_group(fs_info, range->start); 58538c2ecf20Sopenharmony_ci for (; cache; cache = btrfs_next_block_group(cache)) { 58548c2ecf20Sopenharmony_ci if (cache->start >= range_end) { 58558c2ecf20Sopenharmony_ci btrfs_put_block_group(cache); 58568c2ecf20Sopenharmony_ci break; 58578c2ecf20Sopenharmony_ci } 58588c2ecf20Sopenharmony_ci 58598c2ecf20Sopenharmony_ci start = max(range->start, cache->start); 58608c2ecf20Sopenharmony_ci end = min(range_end, cache->start + cache->length); 58618c2ecf20Sopenharmony_ci 58628c2ecf20Sopenharmony_ci if (end - start >= range->minlen) { 58638c2ecf20Sopenharmony_ci if (!btrfs_block_group_done(cache)) { 58648c2ecf20Sopenharmony_ci ret = btrfs_cache_block_group(cache, 0); 58658c2ecf20Sopenharmony_ci if (ret) { 58668c2ecf20Sopenharmony_ci bg_failed++; 58678c2ecf20Sopenharmony_ci bg_ret = ret; 58688c2ecf20Sopenharmony_ci continue; 58698c2ecf20Sopenharmony_ci } 58708c2ecf20Sopenharmony_ci ret = btrfs_wait_block_group_cache_done(cache); 58718c2ecf20Sopenharmony_ci if (ret) { 58728c2ecf20Sopenharmony_ci bg_failed++; 58738c2ecf20Sopenharmony_ci bg_ret = ret; 58748c2ecf20Sopenharmony_ci continue; 58758c2ecf20Sopenharmony_ci } 58768c2ecf20Sopenharmony_ci } 58778c2ecf20Sopenharmony_ci ret = btrfs_trim_block_group(cache, 58788c2ecf20Sopenharmony_ci &group_trimmed, 58798c2ecf20Sopenharmony_ci start, 58808c2ecf20Sopenharmony_ci end, 58818c2ecf20Sopenharmony_ci range->minlen); 58828c2ecf20Sopenharmony_ci 58838c2ecf20Sopenharmony_ci trimmed += group_trimmed; 58848c2ecf20Sopenharmony_ci if (ret) { 58858c2ecf20Sopenharmony_ci bg_failed++; 58868c2ecf20Sopenharmony_ci bg_ret = ret; 58878c2ecf20Sopenharmony_ci continue; 58888c2ecf20Sopenharmony_ci } 58898c2ecf20Sopenharmony_ci } 58908c2ecf20Sopenharmony_ci } 58918c2ecf20Sopenharmony_ci 58928c2ecf20Sopenharmony_ci if (bg_failed) 58938c2ecf20Sopenharmony_ci btrfs_warn(fs_info, 58948c2ecf20Sopenharmony_ci "failed to trim %llu block group(s), last error %d", 58958c2ecf20Sopenharmony_ci bg_failed, bg_ret); 58968c2ecf20Sopenharmony_ci mutex_lock(&fs_info->fs_devices->device_list_mutex); 58978c2ecf20Sopenharmony_ci devices = &fs_info->fs_devices->devices; 58988c2ecf20Sopenharmony_ci list_for_each_entry(device, devices, dev_list) { 58998c2ecf20Sopenharmony_ci if (test_bit(BTRFS_DEV_STATE_MISSING, &device->dev_state)) 59008c2ecf20Sopenharmony_ci continue; 59018c2ecf20Sopenharmony_ci 59028c2ecf20Sopenharmony_ci ret = btrfs_trim_free_extents(device, &group_trimmed); 59038c2ecf20Sopenharmony_ci if (ret) { 59048c2ecf20Sopenharmony_ci dev_failed++; 59058c2ecf20Sopenharmony_ci dev_ret = ret; 59068c2ecf20Sopenharmony_ci break; 59078c2ecf20Sopenharmony_ci } 59088c2ecf20Sopenharmony_ci 59098c2ecf20Sopenharmony_ci trimmed += group_trimmed; 59108c2ecf20Sopenharmony_ci } 59118c2ecf20Sopenharmony_ci mutex_unlock(&fs_info->fs_devices->device_list_mutex); 59128c2ecf20Sopenharmony_ci 59138c2ecf20Sopenharmony_ci if (dev_failed) 59148c2ecf20Sopenharmony_ci btrfs_warn(fs_info, 59158c2ecf20Sopenharmony_ci "failed to trim %llu device(s), last error %d", 59168c2ecf20Sopenharmony_ci dev_failed, dev_ret); 59178c2ecf20Sopenharmony_ci range->len = trimmed; 59188c2ecf20Sopenharmony_ci if (bg_ret) 59198c2ecf20Sopenharmony_ci return bg_ret; 59208c2ecf20Sopenharmony_ci return dev_ret; 59218c2ecf20Sopenharmony_ci} 5922