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