162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (C) 2014 Facebook.  All rights reserved.
462306a36Sopenharmony_ci */
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci#include <linux/sched.h>
762306a36Sopenharmony_ci#include <linux/stacktrace.h>
862306a36Sopenharmony_ci#include "messages.h"
962306a36Sopenharmony_ci#include "ctree.h"
1062306a36Sopenharmony_ci#include "disk-io.h"
1162306a36Sopenharmony_ci#include "locking.h"
1262306a36Sopenharmony_ci#include "delayed-ref.h"
1362306a36Sopenharmony_ci#include "ref-verify.h"
1462306a36Sopenharmony_ci#include "fs.h"
1562306a36Sopenharmony_ci#include "accessors.h"
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci/*
1862306a36Sopenharmony_ci * Used to keep track the roots and number of refs each root has for a given
1962306a36Sopenharmony_ci * bytenr.  This just tracks the number of direct references, no shared
2062306a36Sopenharmony_ci * references.
2162306a36Sopenharmony_ci */
2262306a36Sopenharmony_cistruct root_entry {
2362306a36Sopenharmony_ci	u64 root_objectid;
2462306a36Sopenharmony_ci	u64 num_refs;
2562306a36Sopenharmony_ci	struct rb_node node;
2662306a36Sopenharmony_ci};
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci/*
2962306a36Sopenharmony_ci * These are meant to represent what should exist in the extent tree, these can
3062306a36Sopenharmony_ci * be used to verify the extent tree is consistent as these should all match
3162306a36Sopenharmony_ci * what the extent tree says.
3262306a36Sopenharmony_ci */
3362306a36Sopenharmony_cistruct ref_entry {
3462306a36Sopenharmony_ci	u64 root_objectid;
3562306a36Sopenharmony_ci	u64 parent;
3662306a36Sopenharmony_ci	u64 owner;
3762306a36Sopenharmony_ci	u64 offset;
3862306a36Sopenharmony_ci	u64 num_refs;
3962306a36Sopenharmony_ci	struct rb_node node;
4062306a36Sopenharmony_ci};
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci#define MAX_TRACE	16
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci/*
4562306a36Sopenharmony_ci * Whenever we add/remove a reference we record the action.  The action maps
4662306a36Sopenharmony_ci * back to the delayed ref action.  We hold the ref we are changing in the
4762306a36Sopenharmony_ci * action so we can account for the history properly, and we record the root we
4862306a36Sopenharmony_ci * were called with since it could be different from ref_root.  We also store
4962306a36Sopenharmony_ci * stack traces because that's how I roll.
5062306a36Sopenharmony_ci */
5162306a36Sopenharmony_cistruct ref_action {
5262306a36Sopenharmony_ci	int action;
5362306a36Sopenharmony_ci	u64 root;
5462306a36Sopenharmony_ci	struct ref_entry ref;
5562306a36Sopenharmony_ci	struct list_head list;
5662306a36Sopenharmony_ci	unsigned long trace[MAX_TRACE];
5762306a36Sopenharmony_ci	unsigned int trace_len;
5862306a36Sopenharmony_ci};
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci/*
6162306a36Sopenharmony_ci * One of these for every block we reference, it holds the roots and references
6262306a36Sopenharmony_ci * to it as well as all of the ref actions that have occurred to it.  We never
6362306a36Sopenharmony_ci * free it until we unmount the file system in order to make sure re-allocations
6462306a36Sopenharmony_ci * are happening properly.
6562306a36Sopenharmony_ci */
6662306a36Sopenharmony_cistruct block_entry {
6762306a36Sopenharmony_ci	u64 bytenr;
6862306a36Sopenharmony_ci	u64 len;
6962306a36Sopenharmony_ci	u64 num_refs;
7062306a36Sopenharmony_ci	int metadata;
7162306a36Sopenharmony_ci	int from_disk;
7262306a36Sopenharmony_ci	struct rb_root roots;
7362306a36Sopenharmony_ci	struct rb_root refs;
7462306a36Sopenharmony_ci	struct rb_node node;
7562306a36Sopenharmony_ci	struct list_head actions;
7662306a36Sopenharmony_ci};
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_cistatic struct block_entry *insert_block_entry(struct rb_root *root,
7962306a36Sopenharmony_ci					      struct block_entry *be)
8062306a36Sopenharmony_ci{
8162306a36Sopenharmony_ci	struct rb_node **p = &root->rb_node;
8262306a36Sopenharmony_ci	struct rb_node *parent_node = NULL;
8362306a36Sopenharmony_ci	struct block_entry *entry;
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci	while (*p) {
8662306a36Sopenharmony_ci		parent_node = *p;
8762306a36Sopenharmony_ci		entry = rb_entry(parent_node, struct block_entry, node);
8862306a36Sopenharmony_ci		if (entry->bytenr > be->bytenr)
8962306a36Sopenharmony_ci			p = &(*p)->rb_left;
9062306a36Sopenharmony_ci		else if (entry->bytenr < be->bytenr)
9162306a36Sopenharmony_ci			p = &(*p)->rb_right;
9262306a36Sopenharmony_ci		else
9362306a36Sopenharmony_ci			return entry;
9462306a36Sopenharmony_ci	}
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ci	rb_link_node(&be->node, parent_node, p);
9762306a36Sopenharmony_ci	rb_insert_color(&be->node, root);
9862306a36Sopenharmony_ci	return NULL;
9962306a36Sopenharmony_ci}
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_cistatic struct block_entry *lookup_block_entry(struct rb_root *root, u64 bytenr)
10262306a36Sopenharmony_ci{
10362306a36Sopenharmony_ci	struct rb_node *n;
10462306a36Sopenharmony_ci	struct block_entry *entry = NULL;
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci	n = root->rb_node;
10762306a36Sopenharmony_ci	while (n) {
10862306a36Sopenharmony_ci		entry = rb_entry(n, struct block_entry, node);
10962306a36Sopenharmony_ci		if (entry->bytenr < bytenr)
11062306a36Sopenharmony_ci			n = n->rb_right;
11162306a36Sopenharmony_ci		else if (entry->bytenr > bytenr)
11262306a36Sopenharmony_ci			n = n->rb_left;
11362306a36Sopenharmony_ci		else
11462306a36Sopenharmony_ci			return entry;
11562306a36Sopenharmony_ci	}
11662306a36Sopenharmony_ci	return NULL;
11762306a36Sopenharmony_ci}
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_cistatic struct root_entry *insert_root_entry(struct rb_root *root,
12062306a36Sopenharmony_ci					    struct root_entry *re)
12162306a36Sopenharmony_ci{
12262306a36Sopenharmony_ci	struct rb_node **p = &root->rb_node;
12362306a36Sopenharmony_ci	struct rb_node *parent_node = NULL;
12462306a36Sopenharmony_ci	struct root_entry *entry;
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_ci	while (*p) {
12762306a36Sopenharmony_ci		parent_node = *p;
12862306a36Sopenharmony_ci		entry = rb_entry(parent_node, struct root_entry, node);
12962306a36Sopenharmony_ci		if (entry->root_objectid > re->root_objectid)
13062306a36Sopenharmony_ci			p = &(*p)->rb_left;
13162306a36Sopenharmony_ci		else if (entry->root_objectid < re->root_objectid)
13262306a36Sopenharmony_ci			p = &(*p)->rb_right;
13362306a36Sopenharmony_ci		else
13462306a36Sopenharmony_ci			return entry;
13562306a36Sopenharmony_ci	}
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_ci	rb_link_node(&re->node, parent_node, p);
13862306a36Sopenharmony_ci	rb_insert_color(&re->node, root);
13962306a36Sopenharmony_ci	return NULL;
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_ci}
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_cistatic int comp_refs(struct ref_entry *ref1, struct ref_entry *ref2)
14462306a36Sopenharmony_ci{
14562306a36Sopenharmony_ci	if (ref1->root_objectid < ref2->root_objectid)
14662306a36Sopenharmony_ci		return -1;
14762306a36Sopenharmony_ci	if (ref1->root_objectid > ref2->root_objectid)
14862306a36Sopenharmony_ci		return 1;
14962306a36Sopenharmony_ci	if (ref1->parent < ref2->parent)
15062306a36Sopenharmony_ci		return -1;
15162306a36Sopenharmony_ci	if (ref1->parent > ref2->parent)
15262306a36Sopenharmony_ci		return 1;
15362306a36Sopenharmony_ci	if (ref1->owner < ref2->owner)
15462306a36Sopenharmony_ci		return -1;
15562306a36Sopenharmony_ci	if (ref1->owner > ref2->owner)
15662306a36Sopenharmony_ci		return 1;
15762306a36Sopenharmony_ci	if (ref1->offset < ref2->offset)
15862306a36Sopenharmony_ci		return -1;
15962306a36Sopenharmony_ci	if (ref1->offset > ref2->offset)
16062306a36Sopenharmony_ci		return 1;
16162306a36Sopenharmony_ci	return 0;
16262306a36Sopenharmony_ci}
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_cistatic struct ref_entry *insert_ref_entry(struct rb_root *root,
16562306a36Sopenharmony_ci					  struct ref_entry *ref)
16662306a36Sopenharmony_ci{
16762306a36Sopenharmony_ci	struct rb_node **p = &root->rb_node;
16862306a36Sopenharmony_ci	struct rb_node *parent_node = NULL;
16962306a36Sopenharmony_ci	struct ref_entry *entry;
17062306a36Sopenharmony_ci	int cmp;
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_ci	while (*p) {
17362306a36Sopenharmony_ci		parent_node = *p;
17462306a36Sopenharmony_ci		entry = rb_entry(parent_node, struct ref_entry, node);
17562306a36Sopenharmony_ci		cmp = comp_refs(entry, ref);
17662306a36Sopenharmony_ci		if (cmp > 0)
17762306a36Sopenharmony_ci			p = &(*p)->rb_left;
17862306a36Sopenharmony_ci		else if (cmp < 0)
17962306a36Sopenharmony_ci			p = &(*p)->rb_right;
18062306a36Sopenharmony_ci		else
18162306a36Sopenharmony_ci			return entry;
18262306a36Sopenharmony_ci	}
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_ci	rb_link_node(&ref->node, parent_node, p);
18562306a36Sopenharmony_ci	rb_insert_color(&ref->node, root);
18662306a36Sopenharmony_ci	return NULL;
18762306a36Sopenharmony_ci
18862306a36Sopenharmony_ci}
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_cistatic struct root_entry *lookup_root_entry(struct rb_root *root, u64 objectid)
19162306a36Sopenharmony_ci{
19262306a36Sopenharmony_ci	struct rb_node *n;
19362306a36Sopenharmony_ci	struct root_entry *entry = NULL;
19462306a36Sopenharmony_ci
19562306a36Sopenharmony_ci	n = root->rb_node;
19662306a36Sopenharmony_ci	while (n) {
19762306a36Sopenharmony_ci		entry = rb_entry(n, struct root_entry, node);
19862306a36Sopenharmony_ci		if (entry->root_objectid < objectid)
19962306a36Sopenharmony_ci			n = n->rb_right;
20062306a36Sopenharmony_ci		else if (entry->root_objectid > objectid)
20162306a36Sopenharmony_ci			n = n->rb_left;
20262306a36Sopenharmony_ci		else
20362306a36Sopenharmony_ci			return entry;
20462306a36Sopenharmony_ci	}
20562306a36Sopenharmony_ci	return NULL;
20662306a36Sopenharmony_ci}
20762306a36Sopenharmony_ci
20862306a36Sopenharmony_ci#ifdef CONFIG_STACKTRACE
20962306a36Sopenharmony_cistatic void __save_stack_trace(struct ref_action *ra)
21062306a36Sopenharmony_ci{
21162306a36Sopenharmony_ci	ra->trace_len = stack_trace_save(ra->trace, MAX_TRACE, 2);
21262306a36Sopenharmony_ci}
21362306a36Sopenharmony_ci
21462306a36Sopenharmony_cistatic void __print_stack_trace(struct btrfs_fs_info *fs_info,
21562306a36Sopenharmony_ci				struct ref_action *ra)
21662306a36Sopenharmony_ci{
21762306a36Sopenharmony_ci	if (ra->trace_len == 0) {
21862306a36Sopenharmony_ci		btrfs_err(fs_info, "  ref-verify: no stacktrace");
21962306a36Sopenharmony_ci		return;
22062306a36Sopenharmony_ci	}
22162306a36Sopenharmony_ci	stack_trace_print(ra->trace, ra->trace_len, 2);
22262306a36Sopenharmony_ci}
22362306a36Sopenharmony_ci#else
22462306a36Sopenharmony_cistatic inline void __save_stack_trace(struct ref_action *ra)
22562306a36Sopenharmony_ci{
22662306a36Sopenharmony_ci}
22762306a36Sopenharmony_ci
22862306a36Sopenharmony_cistatic inline void __print_stack_trace(struct btrfs_fs_info *fs_info,
22962306a36Sopenharmony_ci				       struct ref_action *ra)
23062306a36Sopenharmony_ci{
23162306a36Sopenharmony_ci	btrfs_err(fs_info, "  ref-verify: no stacktrace support");
23262306a36Sopenharmony_ci}
23362306a36Sopenharmony_ci#endif
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_cistatic void free_block_entry(struct block_entry *be)
23662306a36Sopenharmony_ci{
23762306a36Sopenharmony_ci	struct root_entry *re;
23862306a36Sopenharmony_ci	struct ref_entry *ref;
23962306a36Sopenharmony_ci	struct ref_action *ra;
24062306a36Sopenharmony_ci	struct rb_node *n;
24162306a36Sopenharmony_ci
24262306a36Sopenharmony_ci	while ((n = rb_first(&be->roots))) {
24362306a36Sopenharmony_ci		re = rb_entry(n, struct root_entry, node);
24462306a36Sopenharmony_ci		rb_erase(&re->node, &be->roots);
24562306a36Sopenharmony_ci		kfree(re);
24662306a36Sopenharmony_ci	}
24762306a36Sopenharmony_ci
24862306a36Sopenharmony_ci	while((n = rb_first(&be->refs))) {
24962306a36Sopenharmony_ci		ref = rb_entry(n, struct ref_entry, node);
25062306a36Sopenharmony_ci		rb_erase(&ref->node, &be->refs);
25162306a36Sopenharmony_ci		kfree(ref);
25262306a36Sopenharmony_ci	}
25362306a36Sopenharmony_ci
25462306a36Sopenharmony_ci	while (!list_empty(&be->actions)) {
25562306a36Sopenharmony_ci		ra = list_first_entry(&be->actions, struct ref_action,
25662306a36Sopenharmony_ci				      list);
25762306a36Sopenharmony_ci		list_del(&ra->list);
25862306a36Sopenharmony_ci		kfree(ra);
25962306a36Sopenharmony_ci	}
26062306a36Sopenharmony_ci	kfree(be);
26162306a36Sopenharmony_ci}
26262306a36Sopenharmony_ci
26362306a36Sopenharmony_cistatic struct block_entry *add_block_entry(struct btrfs_fs_info *fs_info,
26462306a36Sopenharmony_ci					   u64 bytenr, u64 len,
26562306a36Sopenharmony_ci					   u64 root_objectid)
26662306a36Sopenharmony_ci{
26762306a36Sopenharmony_ci	struct block_entry *be = NULL, *exist;
26862306a36Sopenharmony_ci	struct root_entry *re = NULL;
26962306a36Sopenharmony_ci
27062306a36Sopenharmony_ci	re = kzalloc(sizeof(struct root_entry), GFP_NOFS);
27162306a36Sopenharmony_ci	be = kzalloc(sizeof(struct block_entry), GFP_NOFS);
27262306a36Sopenharmony_ci	if (!be || !re) {
27362306a36Sopenharmony_ci		kfree(re);
27462306a36Sopenharmony_ci		kfree(be);
27562306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
27662306a36Sopenharmony_ci	}
27762306a36Sopenharmony_ci	be->bytenr = bytenr;
27862306a36Sopenharmony_ci	be->len = len;
27962306a36Sopenharmony_ci
28062306a36Sopenharmony_ci	re->root_objectid = root_objectid;
28162306a36Sopenharmony_ci	re->num_refs = 0;
28262306a36Sopenharmony_ci
28362306a36Sopenharmony_ci	spin_lock(&fs_info->ref_verify_lock);
28462306a36Sopenharmony_ci	exist = insert_block_entry(&fs_info->block_tree, be);
28562306a36Sopenharmony_ci	if (exist) {
28662306a36Sopenharmony_ci		if (root_objectid) {
28762306a36Sopenharmony_ci			struct root_entry *exist_re;
28862306a36Sopenharmony_ci
28962306a36Sopenharmony_ci			exist_re = insert_root_entry(&exist->roots, re);
29062306a36Sopenharmony_ci			if (exist_re)
29162306a36Sopenharmony_ci				kfree(re);
29262306a36Sopenharmony_ci		} else {
29362306a36Sopenharmony_ci			kfree(re);
29462306a36Sopenharmony_ci		}
29562306a36Sopenharmony_ci		kfree(be);
29662306a36Sopenharmony_ci		return exist;
29762306a36Sopenharmony_ci	}
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_ci	be->num_refs = 0;
30062306a36Sopenharmony_ci	be->metadata = 0;
30162306a36Sopenharmony_ci	be->from_disk = 0;
30262306a36Sopenharmony_ci	be->roots = RB_ROOT;
30362306a36Sopenharmony_ci	be->refs = RB_ROOT;
30462306a36Sopenharmony_ci	INIT_LIST_HEAD(&be->actions);
30562306a36Sopenharmony_ci	if (root_objectid)
30662306a36Sopenharmony_ci		insert_root_entry(&be->roots, re);
30762306a36Sopenharmony_ci	else
30862306a36Sopenharmony_ci		kfree(re);
30962306a36Sopenharmony_ci	return be;
31062306a36Sopenharmony_ci}
31162306a36Sopenharmony_ci
31262306a36Sopenharmony_cistatic int add_tree_block(struct btrfs_fs_info *fs_info, u64 ref_root,
31362306a36Sopenharmony_ci			  u64 parent, u64 bytenr, int level)
31462306a36Sopenharmony_ci{
31562306a36Sopenharmony_ci	struct block_entry *be;
31662306a36Sopenharmony_ci	struct root_entry *re;
31762306a36Sopenharmony_ci	struct ref_entry *ref = NULL, *exist;
31862306a36Sopenharmony_ci
31962306a36Sopenharmony_ci	ref = kmalloc(sizeof(struct ref_entry), GFP_NOFS);
32062306a36Sopenharmony_ci	if (!ref)
32162306a36Sopenharmony_ci		return -ENOMEM;
32262306a36Sopenharmony_ci
32362306a36Sopenharmony_ci	if (parent)
32462306a36Sopenharmony_ci		ref->root_objectid = 0;
32562306a36Sopenharmony_ci	else
32662306a36Sopenharmony_ci		ref->root_objectid = ref_root;
32762306a36Sopenharmony_ci	ref->parent = parent;
32862306a36Sopenharmony_ci	ref->owner = level;
32962306a36Sopenharmony_ci	ref->offset = 0;
33062306a36Sopenharmony_ci	ref->num_refs = 1;
33162306a36Sopenharmony_ci
33262306a36Sopenharmony_ci	be = add_block_entry(fs_info, bytenr, fs_info->nodesize, ref_root);
33362306a36Sopenharmony_ci	if (IS_ERR(be)) {
33462306a36Sopenharmony_ci		kfree(ref);
33562306a36Sopenharmony_ci		return PTR_ERR(be);
33662306a36Sopenharmony_ci	}
33762306a36Sopenharmony_ci	be->num_refs++;
33862306a36Sopenharmony_ci	be->from_disk = 1;
33962306a36Sopenharmony_ci	be->metadata = 1;
34062306a36Sopenharmony_ci
34162306a36Sopenharmony_ci	if (!parent) {
34262306a36Sopenharmony_ci		ASSERT(ref_root);
34362306a36Sopenharmony_ci		re = lookup_root_entry(&be->roots, ref_root);
34462306a36Sopenharmony_ci		ASSERT(re);
34562306a36Sopenharmony_ci		re->num_refs++;
34662306a36Sopenharmony_ci	}
34762306a36Sopenharmony_ci	exist = insert_ref_entry(&be->refs, ref);
34862306a36Sopenharmony_ci	if (exist) {
34962306a36Sopenharmony_ci		exist->num_refs++;
35062306a36Sopenharmony_ci		kfree(ref);
35162306a36Sopenharmony_ci	}
35262306a36Sopenharmony_ci	spin_unlock(&fs_info->ref_verify_lock);
35362306a36Sopenharmony_ci
35462306a36Sopenharmony_ci	return 0;
35562306a36Sopenharmony_ci}
35662306a36Sopenharmony_ci
35762306a36Sopenharmony_cistatic int add_shared_data_ref(struct btrfs_fs_info *fs_info,
35862306a36Sopenharmony_ci			       u64 parent, u32 num_refs, u64 bytenr,
35962306a36Sopenharmony_ci			       u64 num_bytes)
36062306a36Sopenharmony_ci{
36162306a36Sopenharmony_ci	struct block_entry *be;
36262306a36Sopenharmony_ci	struct ref_entry *ref;
36362306a36Sopenharmony_ci
36462306a36Sopenharmony_ci	ref = kzalloc(sizeof(struct ref_entry), GFP_NOFS);
36562306a36Sopenharmony_ci	if (!ref)
36662306a36Sopenharmony_ci		return -ENOMEM;
36762306a36Sopenharmony_ci	be = add_block_entry(fs_info, bytenr, num_bytes, 0);
36862306a36Sopenharmony_ci	if (IS_ERR(be)) {
36962306a36Sopenharmony_ci		kfree(ref);
37062306a36Sopenharmony_ci		return PTR_ERR(be);
37162306a36Sopenharmony_ci	}
37262306a36Sopenharmony_ci	be->num_refs += num_refs;
37362306a36Sopenharmony_ci
37462306a36Sopenharmony_ci	ref->parent = parent;
37562306a36Sopenharmony_ci	ref->num_refs = num_refs;
37662306a36Sopenharmony_ci	if (insert_ref_entry(&be->refs, ref)) {
37762306a36Sopenharmony_ci		spin_unlock(&fs_info->ref_verify_lock);
37862306a36Sopenharmony_ci		btrfs_err(fs_info, "existing shared ref when reading from disk?");
37962306a36Sopenharmony_ci		kfree(ref);
38062306a36Sopenharmony_ci		return -EINVAL;
38162306a36Sopenharmony_ci	}
38262306a36Sopenharmony_ci	spin_unlock(&fs_info->ref_verify_lock);
38362306a36Sopenharmony_ci	return 0;
38462306a36Sopenharmony_ci}
38562306a36Sopenharmony_ci
38662306a36Sopenharmony_cistatic int add_extent_data_ref(struct btrfs_fs_info *fs_info,
38762306a36Sopenharmony_ci			       struct extent_buffer *leaf,
38862306a36Sopenharmony_ci			       struct btrfs_extent_data_ref *dref,
38962306a36Sopenharmony_ci			       u64 bytenr, u64 num_bytes)
39062306a36Sopenharmony_ci{
39162306a36Sopenharmony_ci	struct block_entry *be;
39262306a36Sopenharmony_ci	struct ref_entry *ref;
39362306a36Sopenharmony_ci	struct root_entry *re;
39462306a36Sopenharmony_ci	u64 ref_root = btrfs_extent_data_ref_root(leaf, dref);
39562306a36Sopenharmony_ci	u64 owner = btrfs_extent_data_ref_objectid(leaf, dref);
39662306a36Sopenharmony_ci	u64 offset = btrfs_extent_data_ref_offset(leaf, dref);
39762306a36Sopenharmony_ci	u32 num_refs = btrfs_extent_data_ref_count(leaf, dref);
39862306a36Sopenharmony_ci
39962306a36Sopenharmony_ci	ref = kzalloc(sizeof(struct ref_entry), GFP_NOFS);
40062306a36Sopenharmony_ci	if (!ref)
40162306a36Sopenharmony_ci		return -ENOMEM;
40262306a36Sopenharmony_ci	be = add_block_entry(fs_info, bytenr, num_bytes, ref_root);
40362306a36Sopenharmony_ci	if (IS_ERR(be)) {
40462306a36Sopenharmony_ci		kfree(ref);
40562306a36Sopenharmony_ci		return PTR_ERR(be);
40662306a36Sopenharmony_ci	}
40762306a36Sopenharmony_ci	be->num_refs += num_refs;
40862306a36Sopenharmony_ci
40962306a36Sopenharmony_ci	ref->parent = 0;
41062306a36Sopenharmony_ci	ref->owner = owner;
41162306a36Sopenharmony_ci	ref->root_objectid = ref_root;
41262306a36Sopenharmony_ci	ref->offset = offset;
41362306a36Sopenharmony_ci	ref->num_refs = num_refs;
41462306a36Sopenharmony_ci	if (insert_ref_entry(&be->refs, ref)) {
41562306a36Sopenharmony_ci		spin_unlock(&fs_info->ref_verify_lock);
41662306a36Sopenharmony_ci		btrfs_err(fs_info, "existing ref when reading from disk?");
41762306a36Sopenharmony_ci		kfree(ref);
41862306a36Sopenharmony_ci		return -EINVAL;
41962306a36Sopenharmony_ci	}
42062306a36Sopenharmony_ci
42162306a36Sopenharmony_ci	re = lookup_root_entry(&be->roots, ref_root);
42262306a36Sopenharmony_ci	if (!re) {
42362306a36Sopenharmony_ci		spin_unlock(&fs_info->ref_verify_lock);
42462306a36Sopenharmony_ci		btrfs_err(fs_info, "missing root in new block entry?");
42562306a36Sopenharmony_ci		return -EINVAL;
42662306a36Sopenharmony_ci	}
42762306a36Sopenharmony_ci	re->num_refs += num_refs;
42862306a36Sopenharmony_ci	spin_unlock(&fs_info->ref_verify_lock);
42962306a36Sopenharmony_ci	return 0;
43062306a36Sopenharmony_ci}
43162306a36Sopenharmony_ci
43262306a36Sopenharmony_cistatic int process_extent_item(struct btrfs_fs_info *fs_info,
43362306a36Sopenharmony_ci			       struct btrfs_path *path, struct btrfs_key *key,
43462306a36Sopenharmony_ci			       int slot, int *tree_block_level)
43562306a36Sopenharmony_ci{
43662306a36Sopenharmony_ci	struct btrfs_extent_item *ei;
43762306a36Sopenharmony_ci	struct btrfs_extent_inline_ref *iref;
43862306a36Sopenharmony_ci	struct btrfs_extent_data_ref *dref;
43962306a36Sopenharmony_ci	struct btrfs_shared_data_ref *sref;
44062306a36Sopenharmony_ci	struct extent_buffer *leaf = path->nodes[0];
44162306a36Sopenharmony_ci	u32 item_size = btrfs_item_size(leaf, slot);
44262306a36Sopenharmony_ci	unsigned long end, ptr;
44362306a36Sopenharmony_ci	u64 offset, flags, count;
44462306a36Sopenharmony_ci	int type, ret;
44562306a36Sopenharmony_ci
44662306a36Sopenharmony_ci	ei = btrfs_item_ptr(leaf, slot, struct btrfs_extent_item);
44762306a36Sopenharmony_ci	flags = btrfs_extent_flags(leaf, ei);
44862306a36Sopenharmony_ci
44962306a36Sopenharmony_ci	if ((key->type == BTRFS_EXTENT_ITEM_KEY) &&
45062306a36Sopenharmony_ci	    flags & BTRFS_EXTENT_FLAG_TREE_BLOCK) {
45162306a36Sopenharmony_ci		struct btrfs_tree_block_info *info;
45262306a36Sopenharmony_ci
45362306a36Sopenharmony_ci		info = (struct btrfs_tree_block_info *)(ei + 1);
45462306a36Sopenharmony_ci		*tree_block_level = btrfs_tree_block_level(leaf, info);
45562306a36Sopenharmony_ci		iref = (struct btrfs_extent_inline_ref *)(info + 1);
45662306a36Sopenharmony_ci	} else {
45762306a36Sopenharmony_ci		if (key->type == BTRFS_METADATA_ITEM_KEY)
45862306a36Sopenharmony_ci			*tree_block_level = key->offset;
45962306a36Sopenharmony_ci		iref = (struct btrfs_extent_inline_ref *)(ei + 1);
46062306a36Sopenharmony_ci	}
46162306a36Sopenharmony_ci
46262306a36Sopenharmony_ci	ptr = (unsigned long)iref;
46362306a36Sopenharmony_ci	end = (unsigned long)ei + item_size;
46462306a36Sopenharmony_ci	while (ptr < end) {
46562306a36Sopenharmony_ci		iref = (struct btrfs_extent_inline_ref *)ptr;
46662306a36Sopenharmony_ci		type = btrfs_extent_inline_ref_type(leaf, iref);
46762306a36Sopenharmony_ci		offset = btrfs_extent_inline_ref_offset(leaf, iref);
46862306a36Sopenharmony_ci		switch (type) {
46962306a36Sopenharmony_ci		case BTRFS_TREE_BLOCK_REF_KEY:
47062306a36Sopenharmony_ci			ret = add_tree_block(fs_info, offset, 0, key->objectid,
47162306a36Sopenharmony_ci					     *tree_block_level);
47262306a36Sopenharmony_ci			break;
47362306a36Sopenharmony_ci		case BTRFS_SHARED_BLOCK_REF_KEY:
47462306a36Sopenharmony_ci			ret = add_tree_block(fs_info, 0, offset, key->objectid,
47562306a36Sopenharmony_ci					     *tree_block_level);
47662306a36Sopenharmony_ci			break;
47762306a36Sopenharmony_ci		case BTRFS_EXTENT_DATA_REF_KEY:
47862306a36Sopenharmony_ci			dref = (struct btrfs_extent_data_ref *)(&iref->offset);
47962306a36Sopenharmony_ci			ret = add_extent_data_ref(fs_info, leaf, dref,
48062306a36Sopenharmony_ci						  key->objectid, key->offset);
48162306a36Sopenharmony_ci			break;
48262306a36Sopenharmony_ci		case BTRFS_SHARED_DATA_REF_KEY:
48362306a36Sopenharmony_ci			sref = (struct btrfs_shared_data_ref *)(iref + 1);
48462306a36Sopenharmony_ci			count = btrfs_shared_data_ref_count(leaf, sref);
48562306a36Sopenharmony_ci			ret = add_shared_data_ref(fs_info, offset, count,
48662306a36Sopenharmony_ci						  key->objectid, key->offset);
48762306a36Sopenharmony_ci			break;
48862306a36Sopenharmony_ci		default:
48962306a36Sopenharmony_ci			btrfs_err(fs_info, "invalid key type in iref");
49062306a36Sopenharmony_ci			ret = -EINVAL;
49162306a36Sopenharmony_ci			break;
49262306a36Sopenharmony_ci		}
49362306a36Sopenharmony_ci		if (ret)
49462306a36Sopenharmony_ci			break;
49562306a36Sopenharmony_ci		ptr += btrfs_extent_inline_ref_size(type);
49662306a36Sopenharmony_ci	}
49762306a36Sopenharmony_ci	return ret;
49862306a36Sopenharmony_ci}
49962306a36Sopenharmony_ci
50062306a36Sopenharmony_cistatic int process_leaf(struct btrfs_root *root,
50162306a36Sopenharmony_ci			struct btrfs_path *path, u64 *bytenr, u64 *num_bytes,
50262306a36Sopenharmony_ci			int *tree_block_level)
50362306a36Sopenharmony_ci{
50462306a36Sopenharmony_ci	struct btrfs_fs_info *fs_info = root->fs_info;
50562306a36Sopenharmony_ci	struct extent_buffer *leaf = path->nodes[0];
50662306a36Sopenharmony_ci	struct btrfs_extent_data_ref *dref;
50762306a36Sopenharmony_ci	struct btrfs_shared_data_ref *sref;
50862306a36Sopenharmony_ci	u32 count;
50962306a36Sopenharmony_ci	int i = 0, ret = 0;
51062306a36Sopenharmony_ci	struct btrfs_key key;
51162306a36Sopenharmony_ci	int nritems = btrfs_header_nritems(leaf);
51262306a36Sopenharmony_ci
51362306a36Sopenharmony_ci	for (i = 0; i < nritems; i++) {
51462306a36Sopenharmony_ci		btrfs_item_key_to_cpu(leaf, &key, i);
51562306a36Sopenharmony_ci		switch (key.type) {
51662306a36Sopenharmony_ci		case BTRFS_EXTENT_ITEM_KEY:
51762306a36Sopenharmony_ci			*num_bytes = key.offset;
51862306a36Sopenharmony_ci			fallthrough;
51962306a36Sopenharmony_ci		case BTRFS_METADATA_ITEM_KEY:
52062306a36Sopenharmony_ci			*bytenr = key.objectid;
52162306a36Sopenharmony_ci			ret = process_extent_item(fs_info, path, &key, i,
52262306a36Sopenharmony_ci						  tree_block_level);
52362306a36Sopenharmony_ci			break;
52462306a36Sopenharmony_ci		case BTRFS_TREE_BLOCK_REF_KEY:
52562306a36Sopenharmony_ci			ret = add_tree_block(fs_info, key.offset, 0,
52662306a36Sopenharmony_ci					     key.objectid, *tree_block_level);
52762306a36Sopenharmony_ci			break;
52862306a36Sopenharmony_ci		case BTRFS_SHARED_BLOCK_REF_KEY:
52962306a36Sopenharmony_ci			ret = add_tree_block(fs_info, 0, key.offset,
53062306a36Sopenharmony_ci					     key.objectid, *tree_block_level);
53162306a36Sopenharmony_ci			break;
53262306a36Sopenharmony_ci		case BTRFS_EXTENT_DATA_REF_KEY:
53362306a36Sopenharmony_ci			dref = btrfs_item_ptr(leaf, i,
53462306a36Sopenharmony_ci					      struct btrfs_extent_data_ref);
53562306a36Sopenharmony_ci			ret = add_extent_data_ref(fs_info, leaf, dref, *bytenr,
53662306a36Sopenharmony_ci						  *num_bytes);
53762306a36Sopenharmony_ci			break;
53862306a36Sopenharmony_ci		case BTRFS_SHARED_DATA_REF_KEY:
53962306a36Sopenharmony_ci			sref = btrfs_item_ptr(leaf, i,
54062306a36Sopenharmony_ci					      struct btrfs_shared_data_ref);
54162306a36Sopenharmony_ci			count = btrfs_shared_data_ref_count(leaf, sref);
54262306a36Sopenharmony_ci			ret = add_shared_data_ref(fs_info, key.offset, count,
54362306a36Sopenharmony_ci						  *bytenr, *num_bytes);
54462306a36Sopenharmony_ci			break;
54562306a36Sopenharmony_ci		default:
54662306a36Sopenharmony_ci			break;
54762306a36Sopenharmony_ci		}
54862306a36Sopenharmony_ci		if (ret)
54962306a36Sopenharmony_ci			break;
55062306a36Sopenharmony_ci	}
55162306a36Sopenharmony_ci	return ret;
55262306a36Sopenharmony_ci}
55362306a36Sopenharmony_ci
55462306a36Sopenharmony_ci/* Walk down to the leaf from the given level */
55562306a36Sopenharmony_cistatic int walk_down_tree(struct btrfs_root *root, struct btrfs_path *path,
55662306a36Sopenharmony_ci			  int level, u64 *bytenr, u64 *num_bytes,
55762306a36Sopenharmony_ci			  int *tree_block_level)
55862306a36Sopenharmony_ci{
55962306a36Sopenharmony_ci	struct extent_buffer *eb;
56062306a36Sopenharmony_ci	int ret = 0;
56162306a36Sopenharmony_ci
56262306a36Sopenharmony_ci	while (level >= 0) {
56362306a36Sopenharmony_ci		if (level) {
56462306a36Sopenharmony_ci			eb = btrfs_read_node_slot(path->nodes[level],
56562306a36Sopenharmony_ci						  path->slots[level]);
56662306a36Sopenharmony_ci			if (IS_ERR(eb))
56762306a36Sopenharmony_ci				return PTR_ERR(eb);
56862306a36Sopenharmony_ci			btrfs_tree_read_lock(eb);
56962306a36Sopenharmony_ci			path->nodes[level-1] = eb;
57062306a36Sopenharmony_ci			path->slots[level-1] = 0;
57162306a36Sopenharmony_ci			path->locks[level-1] = BTRFS_READ_LOCK;
57262306a36Sopenharmony_ci		} else {
57362306a36Sopenharmony_ci			ret = process_leaf(root, path, bytenr, num_bytes,
57462306a36Sopenharmony_ci					   tree_block_level);
57562306a36Sopenharmony_ci			if (ret)
57662306a36Sopenharmony_ci				break;
57762306a36Sopenharmony_ci		}
57862306a36Sopenharmony_ci		level--;
57962306a36Sopenharmony_ci	}
58062306a36Sopenharmony_ci	return ret;
58162306a36Sopenharmony_ci}
58262306a36Sopenharmony_ci
58362306a36Sopenharmony_ci/* Walk up to the next node that needs to be processed */
58462306a36Sopenharmony_cistatic int walk_up_tree(struct btrfs_path *path, int *level)
58562306a36Sopenharmony_ci{
58662306a36Sopenharmony_ci	int l;
58762306a36Sopenharmony_ci
58862306a36Sopenharmony_ci	for (l = 0; l < BTRFS_MAX_LEVEL; l++) {
58962306a36Sopenharmony_ci		if (!path->nodes[l])
59062306a36Sopenharmony_ci			continue;
59162306a36Sopenharmony_ci		if (l) {
59262306a36Sopenharmony_ci			path->slots[l]++;
59362306a36Sopenharmony_ci			if (path->slots[l] <
59462306a36Sopenharmony_ci			    btrfs_header_nritems(path->nodes[l])) {
59562306a36Sopenharmony_ci				*level = l;
59662306a36Sopenharmony_ci				return 0;
59762306a36Sopenharmony_ci			}
59862306a36Sopenharmony_ci		}
59962306a36Sopenharmony_ci		btrfs_tree_unlock_rw(path->nodes[l], path->locks[l]);
60062306a36Sopenharmony_ci		free_extent_buffer(path->nodes[l]);
60162306a36Sopenharmony_ci		path->nodes[l] = NULL;
60262306a36Sopenharmony_ci		path->slots[l] = 0;
60362306a36Sopenharmony_ci		path->locks[l] = 0;
60462306a36Sopenharmony_ci	}
60562306a36Sopenharmony_ci
60662306a36Sopenharmony_ci	return 1;
60762306a36Sopenharmony_ci}
60862306a36Sopenharmony_ci
60962306a36Sopenharmony_cistatic void dump_ref_action(struct btrfs_fs_info *fs_info,
61062306a36Sopenharmony_ci			    struct ref_action *ra)
61162306a36Sopenharmony_ci{
61262306a36Sopenharmony_ci	btrfs_err(fs_info,
61362306a36Sopenharmony_ci"  Ref action %d, root %llu, ref_root %llu, parent %llu, owner %llu, offset %llu, num_refs %llu",
61462306a36Sopenharmony_ci		  ra->action, ra->root, ra->ref.root_objectid, ra->ref.parent,
61562306a36Sopenharmony_ci		  ra->ref.owner, ra->ref.offset, ra->ref.num_refs);
61662306a36Sopenharmony_ci	__print_stack_trace(fs_info, ra);
61762306a36Sopenharmony_ci}
61862306a36Sopenharmony_ci
61962306a36Sopenharmony_ci/*
62062306a36Sopenharmony_ci * Dumps all the information from the block entry to printk, it's going to be
62162306a36Sopenharmony_ci * awesome.
62262306a36Sopenharmony_ci */
62362306a36Sopenharmony_cistatic void dump_block_entry(struct btrfs_fs_info *fs_info,
62462306a36Sopenharmony_ci			     struct block_entry *be)
62562306a36Sopenharmony_ci{
62662306a36Sopenharmony_ci	struct ref_entry *ref;
62762306a36Sopenharmony_ci	struct root_entry *re;
62862306a36Sopenharmony_ci	struct ref_action *ra;
62962306a36Sopenharmony_ci	struct rb_node *n;
63062306a36Sopenharmony_ci
63162306a36Sopenharmony_ci	btrfs_err(fs_info,
63262306a36Sopenharmony_ci"dumping block entry [%llu %llu], num_refs %llu, metadata %d, from disk %d",
63362306a36Sopenharmony_ci		  be->bytenr, be->len, be->num_refs, be->metadata,
63462306a36Sopenharmony_ci		  be->from_disk);
63562306a36Sopenharmony_ci
63662306a36Sopenharmony_ci	for (n = rb_first(&be->refs); n; n = rb_next(n)) {
63762306a36Sopenharmony_ci		ref = rb_entry(n, struct ref_entry, node);
63862306a36Sopenharmony_ci		btrfs_err(fs_info,
63962306a36Sopenharmony_ci"  ref root %llu, parent %llu, owner %llu, offset %llu, num_refs %llu",
64062306a36Sopenharmony_ci			  ref->root_objectid, ref->parent, ref->owner,
64162306a36Sopenharmony_ci			  ref->offset, ref->num_refs);
64262306a36Sopenharmony_ci	}
64362306a36Sopenharmony_ci
64462306a36Sopenharmony_ci	for (n = rb_first(&be->roots); n; n = rb_next(n)) {
64562306a36Sopenharmony_ci		re = rb_entry(n, struct root_entry, node);
64662306a36Sopenharmony_ci		btrfs_err(fs_info, "  root entry %llu, num_refs %llu",
64762306a36Sopenharmony_ci			  re->root_objectid, re->num_refs);
64862306a36Sopenharmony_ci	}
64962306a36Sopenharmony_ci
65062306a36Sopenharmony_ci	list_for_each_entry(ra, &be->actions, list)
65162306a36Sopenharmony_ci		dump_ref_action(fs_info, ra);
65262306a36Sopenharmony_ci}
65362306a36Sopenharmony_ci
65462306a36Sopenharmony_ci/*
65562306a36Sopenharmony_ci * btrfs_ref_tree_mod: called when we modify a ref for a bytenr
65662306a36Sopenharmony_ci *
65762306a36Sopenharmony_ci * This will add an action item to the given bytenr and do sanity checks to make
65862306a36Sopenharmony_ci * sure we haven't messed something up.  If we are making a new allocation and
65962306a36Sopenharmony_ci * this block entry has history we will delete all previous actions as long as
66062306a36Sopenharmony_ci * our sanity checks pass as they are no longer needed.
66162306a36Sopenharmony_ci */
66262306a36Sopenharmony_ciint btrfs_ref_tree_mod(struct btrfs_fs_info *fs_info,
66362306a36Sopenharmony_ci		       struct btrfs_ref *generic_ref)
66462306a36Sopenharmony_ci{
66562306a36Sopenharmony_ci	struct ref_entry *ref = NULL, *exist;
66662306a36Sopenharmony_ci	struct ref_action *ra = NULL;
66762306a36Sopenharmony_ci	struct block_entry *be = NULL;
66862306a36Sopenharmony_ci	struct root_entry *re = NULL;
66962306a36Sopenharmony_ci	int action = generic_ref->action;
67062306a36Sopenharmony_ci	int ret = 0;
67162306a36Sopenharmony_ci	bool metadata;
67262306a36Sopenharmony_ci	u64 bytenr = generic_ref->bytenr;
67362306a36Sopenharmony_ci	u64 num_bytes = generic_ref->len;
67462306a36Sopenharmony_ci	u64 parent = generic_ref->parent;
67562306a36Sopenharmony_ci	u64 ref_root = 0;
67662306a36Sopenharmony_ci	u64 owner = 0;
67762306a36Sopenharmony_ci	u64 offset = 0;
67862306a36Sopenharmony_ci
67962306a36Sopenharmony_ci	if (!btrfs_test_opt(fs_info, REF_VERIFY))
68062306a36Sopenharmony_ci		return 0;
68162306a36Sopenharmony_ci
68262306a36Sopenharmony_ci	if (generic_ref->type == BTRFS_REF_METADATA) {
68362306a36Sopenharmony_ci		if (!parent)
68462306a36Sopenharmony_ci			ref_root = generic_ref->tree_ref.owning_root;
68562306a36Sopenharmony_ci		owner = generic_ref->tree_ref.level;
68662306a36Sopenharmony_ci	} else if (!parent) {
68762306a36Sopenharmony_ci		ref_root = generic_ref->data_ref.owning_root;
68862306a36Sopenharmony_ci		owner = generic_ref->data_ref.ino;
68962306a36Sopenharmony_ci		offset = generic_ref->data_ref.offset;
69062306a36Sopenharmony_ci	}
69162306a36Sopenharmony_ci	metadata = owner < BTRFS_FIRST_FREE_OBJECTID;
69262306a36Sopenharmony_ci
69362306a36Sopenharmony_ci	ref = kzalloc(sizeof(struct ref_entry), GFP_NOFS);
69462306a36Sopenharmony_ci	ra = kmalloc(sizeof(struct ref_action), GFP_NOFS);
69562306a36Sopenharmony_ci	if (!ra || !ref) {
69662306a36Sopenharmony_ci		kfree(ref);
69762306a36Sopenharmony_ci		kfree(ra);
69862306a36Sopenharmony_ci		ret = -ENOMEM;
69962306a36Sopenharmony_ci		goto out;
70062306a36Sopenharmony_ci	}
70162306a36Sopenharmony_ci
70262306a36Sopenharmony_ci	ref->parent = parent;
70362306a36Sopenharmony_ci	ref->owner = owner;
70462306a36Sopenharmony_ci	ref->root_objectid = ref_root;
70562306a36Sopenharmony_ci	ref->offset = offset;
70662306a36Sopenharmony_ci	ref->num_refs = (action == BTRFS_DROP_DELAYED_REF) ? -1 : 1;
70762306a36Sopenharmony_ci
70862306a36Sopenharmony_ci	memcpy(&ra->ref, ref, sizeof(struct ref_entry));
70962306a36Sopenharmony_ci	/*
71062306a36Sopenharmony_ci	 * Save the extra info from the delayed ref in the ref action to make it
71162306a36Sopenharmony_ci	 * easier to figure out what is happening.  The real ref's we add to the
71262306a36Sopenharmony_ci	 * ref tree need to reflect what we save on disk so it matches any
71362306a36Sopenharmony_ci	 * on-disk refs we pre-loaded.
71462306a36Sopenharmony_ci	 */
71562306a36Sopenharmony_ci	ra->ref.owner = owner;
71662306a36Sopenharmony_ci	ra->ref.offset = offset;
71762306a36Sopenharmony_ci	ra->ref.root_objectid = ref_root;
71862306a36Sopenharmony_ci	__save_stack_trace(ra);
71962306a36Sopenharmony_ci
72062306a36Sopenharmony_ci	INIT_LIST_HEAD(&ra->list);
72162306a36Sopenharmony_ci	ra->action = action;
72262306a36Sopenharmony_ci	ra->root = generic_ref->real_root;
72362306a36Sopenharmony_ci
72462306a36Sopenharmony_ci	/*
72562306a36Sopenharmony_ci	 * This is an allocation, preallocate the block_entry in case we haven't
72662306a36Sopenharmony_ci	 * used it before.
72762306a36Sopenharmony_ci	 */
72862306a36Sopenharmony_ci	ret = -EINVAL;
72962306a36Sopenharmony_ci	if (action == BTRFS_ADD_DELAYED_EXTENT) {
73062306a36Sopenharmony_ci		/*
73162306a36Sopenharmony_ci		 * For subvol_create we'll just pass in whatever the parent root
73262306a36Sopenharmony_ci		 * is and the new root objectid, so let's not treat the passed
73362306a36Sopenharmony_ci		 * in root as if it really has a ref for this bytenr.
73462306a36Sopenharmony_ci		 */
73562306a36Sopenharmony_ci		be = add_block_entry(fs_info, bytenr, num_bytes, ref_root);
73662306a36Sopenharmony_ci		if (IS_ERR(be)) {
73762306a36Sopenharmony_ci			kfree(ref);
73862306a36Sopenharmony_ci			kfree(ra);
73962306a36Sopenharmony_ci			ret = PTR_ERR(be);
74062306a36Sopenharmony_ci			goto out;
74162306a36Sopenharmony_ci		}
74262306a36Sopenharmony_ci		be->num_refs++;
74362306a36Sopenharmony_ci		if (metadata)
74462306a36Sopenharmony_ci			be->metadata = 1;
74562306a36Sopenharmony_ci
74662306a36Sopenharmony_ci		if (be->num_refs != 1) {
74762306a36Sopenharmony_ci			btrfs_err(fs_info,
74862306a36Sopenharmony_ci			"re-allocated a block that still has references to it!");
74962306a36Sopenharmony_ci			dump_block_entry(fs_info, be);
75062306a36Sopenharmony_ci			dump_ref_action(fs_info, ra);
75162306a36Sopenharmony_ci			kfree(ref);
75262306a36Sopenharmony_ci			kfree(ra);
75362306a36Sopenharmony_ci			goto out_unlock;
75462306a36Sopenharmony_ci		}
75562306a36Sopenharmony_ci
75662306a36Sopenharmony_ci		while (!list_empty(&be->actions)) {
75762306a36Sopenharmony_ci			struct ref_action *tmp;
75862306a36Sopenharmony_ci
75962306a36Sopenharmony_ci			tmp = list_first_entry(&be->actions, struct ref_action,
76062306a36Sopenharmony_ci					       list);
76162306a36Sopenharmony_ci			list_del(&tmp->list);
76262306a36Sopenharmony_ci			kfree(tmp);
76362306a36Sopenharmony_ci		}
76462306a36Sopenharmony_ci	} else {
76562306a36Sopenharmony_ci		struct root_entry *tmp;
76662306a36Sopenharmony_ci
76762306a36Sopenharmony_ci		if (!parent) {
76862306a36Sopenharmony_ci			re = kmalloc(sizeof(struct root_entry), GFP_NOFS);
76962306a36Sopenharmony_ci			if (!re) {
77062306a36Sopenharmony_ci				kfree(ref);
77162306a36Sopenharmony_ci				kfree(ra);
77262306a36Sopenharmony_ci				ret = -ENOMEM;
77362306a36Sopenharmony_ci				goto out;
77462306a36Sopenharmony_ci			}
77562306a36Sopenharmony_ci			/*
77662306a36Sopenharmony_ci			 * This is the root that is modifying us, so it's the
77762306a36Sopenharmony_ci			 * one we want to lookup below when we modify the
77862306a36Sopenharmony_ci			 * re->num_refs.
77962306a36Sopenharmony_ci			 */
78062306a36Sopenharmony_ci			ref_root = generic_ref->real_root;
78162306a36Sopenharmony_ci			re->root_objectid = generic_ref->real_root;
78262306a36Sopenharmony_ci			re->num_refs = 0;
78362306a36Sopenharmony_ci		}
78462306a36Sopenharmony_ci
78562306a36Sopenharmony_ci		spin_lock(&fs_info->ref_verify_lock);
78662306a36Sopenharmony_ci		be = lookup_block_entry(&fs_info->block_tree, bytenr);
78762306a36Sopenharmony_ci		if (!be) {
78862306a36Sopenharmony_ci			btrfs_err(fs_info,
78962306a36Sopenharmony_ci"trying to do action %d to bytenr %llu num_bytes %llu but there is no existing entry!",
79062306a36Sopenharmony_ci				  action, bytenr, num_bytes);
79162306a36Sopenharmony_ci			dump_ref_action(fs_info, ra);
79262306a36Sopenharmony_ci			kfree(ref);
79362306a36Sopenharmony_ci			kfree(ra);
79462306a36Sopenharmony_ci			kfree(re);
79562306a36Sopenharmony_ci			goto out_unlock;
79662306a36Sopenharmony_ci		} else if (be->num_refs == 0) {
79762306a36Sopenharmony_ci			btrfs_err(fs_info,
79862306a36Sopenharmony_ci		"trying to do action %d for a bytenr that has 0 total references",
79962306a36Sopenharmony_ci				action);
80062306a36Sopenharmony_ci			dump_block_entry(fs_info, be);
80162306a36Sopenharmony_ci			dump_ref_action(fs_info, ra);
80262306a36Sopenharmony_ci			kfree(ref);
80362306a36Sopenharmony_ci			kfree(ra);
80462306a36Sopenharmony_ci			kfree(re);
80562306a36Sopenharmony_ci			goto out_unlock;
80662306a36Sopenharmony_ci		}
80762306a36Sopenharmony_ci
80862306a36Sopenharmony_ci		if (!parent) {
80962306a36Sopenharmony_ci			tmp = insert_root_entry(&be->roots, re);
81062306a36Sopenharmony_ci			if (tmp) {
81162306a36Sopenharmony_ci				kfree(re);
81262306a36Sopenharmony_ci				re = tmp;
81362306a36Sopenharmony_ci			}
81462306a36Sopenharmony_ci		}
81562306a36Sopenharmony_ci	}
81662306a36Sopenharmony_ci
81762306a36Sopenharmony_ci	exist = insert_ref_entry(&be->refs, ref);
81862306a36Sopenharmony_ci	if (exist) {
81962306a36Sopenharmony_ci		if (action == BTRFS_DROP_DELAYED_REF) {
82062306a36Sopenharmony_ci			if (exist->num_refs == 0) {
82162306a36Sopenharmony_ci				btrfs_err(fs_info,
82262306a36Sopenharmony_ci"dropping a ref for a existing root that doesn't have a ref on the block");
82362306a36Sopenharmony_ci				dump_block_entry(fs_info, be);
82462306a36Sopenharmony_ci				dump_ref_action(fs_info, ra);
82562306a36Sopenharmony_ci				kfree(ref);
82662306a36Sopenharmony_ci				kfree(ra);
82762306a36Sopenharmony_ci				goto out_unlock;
82862306a36Sopenharmony_ci			}
82962306a36Sopenharmony_ci			exist->num_refs--;
83062306a36Sopenharmony_ci			if (exist->num_refs == 0) {
83162306a36Sopenharmony_ci				rb_erase(&exist->node, &be->refs);
83262306a36Sopenharmony_ci				kfree(exist);
83362306a36Sopenharmony_ci			}
83462306a36Sopenharmony_ci		} else if (!be->metadata) {
83562306a36Sopenharmony_ci			exist->num_refs++;
83662306a36Sopenharmony_ci		} else {
83762306a36Sopenharmony_ci			btrfs_err(fs_info,
83862306a36Sopenharmony_ci"attempting to add another ref for an existing ref on a tree block");
83962306a36Sopenharmony_ci			dump_block_entry(fs_info, be);
84062306a36Sopenharmony_ci			dump_ref_action(fs_info, ra);
84162306a36Sopenharmony_ci			kfree(ref);
84262306a36Sopenharmony_ci			kfree(ra);
84362306a36Sopenharmony_ci			goto out_unlock;
84462306a36Sopenharmony_ci		}
84562306a36Sopenharmony_ci		kfree(ref);
84662306a36Sopenharmony_ci	} else {
84762306a36Sopenharmony_ci		if (action == BTRFS_DROP_DELAYED_REF) {
84862306a36Sopenharmony_ci			btrfs_err(fs_info,
84962306a36Sopenharmony_ci"dropping a ref for a root that doesn't have a ref on the block");
85062306a36Sopenharmony_ci			dump_block_entry(fs_info, be);
85162306a36Sopenharmony_ci			dump_ref_action(fs_info, ra);
85262306a36Sopenharmony_ci			kfree(ref);
85362306a36Sopenharmony_ci			kfree(ra);
85462306a36Sopenharmony_ci			goto out_unlock;
85562306a36Sopenharmony_ci		}
85662306a36Sopenharmony_ci	}
85762306a36Sopenharmony_ci
85862306a36Sopenharmony_ci	if (!parent && !re) {
85962306a36Sopenharmony_ci		re = lookup_root_entry(&be->roots, ref_root);
86062306a36Sopenharmony_ci		if (!re) {
86162306a36Sopenharmony_ci			/*
86262306a36Sopenharmony_ci			 * This shouldn't happen because we will add our re
86362306a36Sopenharmony_ci			 * above when we lookup the be with !parent, but just in
86462306a36Sopenharmony_ci			 * case catch this case so we don't panic because I
86562306a36Sopenharmony_ci			 * didn't think of some other corner case.
86662306a36Sopenharmony_ci			 */
86762306a36Sopenharmony_ci			btrfs_err(fs_info, "failed to find root %llu for %llu",
86862306a36Sopenharmony_ci				  generic_ref->real_root, be->bytenr);
86962306a36Sopenharmony_ci			dump_block_entry(fs_info, be);
87062306a36Sopenharmony_ci			dump_ref_action(fs_info, ra);
87162306a36Sopenharmony_ci			kfree(ra);
87262306a36Sopenharmony_ci			goto out_unlock;
87362306a36Sopenharmony_ci		}
87462306a36Sopenharmony_ci	}
87562306a36Sopenharmony_ci	if (action == BTRFS_DROP_DELAYED_REF) {
87662306a36Sopenharmony_ci		if (re)
87762306a36Sopenharmony_ci			re->num_refs--;
87862306a36Sopenharmony_ci		be->num_refs--;
87962306a36Sopenharmony_ci	} else if (action == BTRFS_ADD_DELAYED_REF) {
88062306a36Sopenharmony_ci		be->num_refs++;
88162306a36Sopenharmony_ci		if (re)
88262306a36Sopenharmony_ci			re->num_refs++;
88362306a36Sopenharmony_ci	}
88462306a36Sopenharmony_ci	list_add_tail(&ra->list, &be->actions);
88562306a36Sopenharmony_ci	ret = 0;
88662306a36Sopenharmony_ciout_unlock:
88762306a36Sopenharmony_ci	spin_unlock(&fs_info->ref_verify_lock);
88862306a36Sopenharmony_ciout:
88962306a36Sopenharmony_ci	if (ret) {
89062306a36Sopenharmony_ci		btrfs_free_ref_cache(fs_info);
89162306a36Sopenharmony_ci		btrfs_clear_opt(fs_info->mount_opt, REF_VERIFY);
89262306a36Sopenharmony_ci	}
89362306a36Sopenharmony_ci	return ret;
89462306a36Sopenharmony_ci}
89562306a36Sopenharmony_ci
89662306a36Sopenharmony_ci/* Free up the ref cache */
89762306a36Sopenharmony_civoid btrfs_free_ref_cache(struct btrfs_fs_info *fs_info)
89862306a36Sopenharmony_ci{
89962306a36Sopenharmony_ci	struct block_entry *be;
90062306a36Sopenharmony_ci	struct rb_node *n;
90162306a36Sopenharmony_ci
90262306a36Sopenharmony_ci	if (!btrfs_test_opt(fs_info, REF_VERIFY))
90362306a36Sopenharmony_ci		return;
90462306a36Sopenharmony_ci
90562306a36Sopenharmony_ci	spin_lock(&fs_info->ref_verify_lock);
90662306a36Sopenharmony_ci	while ((n = rb_first(&fs_info->block_tree))) {
90762306a36Sopenharmony_ci		be = rb_entry(n, struct block_entry, node);
90862306a36Sopenharmony_ci		rb_erase(&be->node, &fs_info->block_tree);
90962306a36Sopenharmony_ci		free_block_entry(be);
91062306a36Sopenharmony_ci		cond_resched_lock(&fs_info->ref_verify_lock);
91162306a36Sopenharmony_ci	}
91262306a36Sopenharmony_ci	spin_unlock(&fs_info->ref_verify_lock);
91362306a36Sopenharmony_ci}
91462306a36Sopenharmony_ci
91562306a36Sopenharmony_civoid btrfs_free_ref_tree_range(struct btrfs_fs_info *fs_info, u64 start,
91662306a36Sopenharmony_ci			       u64 len)
91762306a36Sopenharmony_ci{
91862306a36Sopenharmony_ci	struct block_entry *be = NULL, *entry;
91962306a36Sopenharmony_ci	struct rb_node *n;
92062306a36Sopenharmony_ci
92162306a36Sopenharmony_ci	if (!btrfs_test_opt(fs_info, REF_VERIFY))
92262306a36Sopenharmony_ci		return;
92362306a36Sopenharmony_ci
92462306a36Sopenharmony_ci	spin_lock(&fs_info->ref_verify_lock);
92562306a36Sopenharmony_ci	n = fs_info->block_tree.rb_node;
92662306a36Sopenharmony_ci	while (n) {
92762306a36Sopenharmony_ci		entry = rb_entry(n, struct block_entry, node);
92862306a36Sopenharmony_ci		if (entry->bytenr < start) {
92962306a36Sopenharmony_ci			n = n->rb_right;
93062306a36Sopenharmony_ci		} else if (entry->bytenr > start) {
93162306a36Sopenharmony_ci			n = n->rb_left;
93262306a36Sopenharmony_ci		} else {
93362306a36Sopenharmony_ci			be = entry;
93462306a36Sopenharmony_ci			break;
93562306a36Sopenharmony_ci		}
93662306a36Sopenharmony_ci		/* We want to get as close to start as possible */
93762306a36Sopenharmony_ci		if (be == NULL ||
93862306a36Sopenharmony_ci		    (entry->bytenr < start && be->bytenr > start) ||
93962306a36Sopenharmony_ci		    (entry->bytenr < start && entry->bytenr > be->bytenr))
94062306a36Sopenharmony_ci			be = entry;
94162306a36Sopenharmony_ci	}
94262306a36Sopenharmony_ci
94362306a36Sopenharmony_ci	/*
94462306a36Sopenharmony_ci	 * Could have an empty block group, maybe have something to check for
94562306a36Sopenharmony_ci	 * this case to verify we were actually empty?
94662306a36Sopenharmony_ci	 */
94762306a36Sopenharmony_ci	if (!be) {
94862306a36Sopenharmony_ci		spin_unlock(&fs_info->ref_verify_lock);
94962306a36Sopenharmony_ci		return;
95062306a36Sopenharmony_ci	}
95162306a36Sopenharmony_ci
95262306a36Sopenharmony_ci	n = &be->node;
95362306a36Sopenharmony_ci	while (n) {
95462306a36Sopenharmony_ci		be = rb_entry(n, struct block_entry, node);
95562306a36Sopenharmony_ci		n = rb_next(n);
95662306a36Sopenharmony_ci		if (be->bytenr < start && be->bytenr + be->len > start) {
95762306a36Sopenharmony_ci			btrfs_err(fs_info,
95862306a36Sopenharmony_ci				"block entry overlaps a block group [%llu,%llu]!",
95962306a36Sopenharmony_ci				start, len);
96062306a36Sopenharmony_ci			dump_block_entry(fs_info, be);
96162306a36Sopenharmony_ci			continue;
96262306a36Sopenharmony_ci		}
96362306a36Sopenharmony_ci		if (be->bytenr < start)
96462306a36Sopenharmony_ci			continue;
96562306a36Sopenharmony_ci		if (be->bytenr >= start + len)
96662306a36Sopenharmony_ci			break;
96762306a36Sopenharmony_ci		if (be->bytenr + be->len > start + len) {
96862306a36Sopenharmony_ci			btrfs_err(fs_info,
96962306a36Sopenharmony_ci				"block entry overlaps a block group [%llu,%llu]!",
97062306a36Sopenharmony_ci				start, len);
97162306a36Sopenharmony_ci			dump_block_entry(fs_info, be);
97262306a36Sopenharmony_ci		}
97362306a36Sopenharmony_ci		rb_erase(&be->node, &fs_info->block_tree);
97462306a36Sopenharmony_ci		free_block_entry(be);
97562306a36Sopenharmony_ci	}
97662306a36Sopenharmony_ci	spin_unlock(&fs_info->ref_verify_lock);
97762306a36Sopenharmony_ci}
97862306a36Sopenharmony_ci
97962306a36Sopenharmony_ci/* Walk down all roots and build the ref tree, meant to be called at mount */
98062306a36Sopenharmony_ciint btrfs_build_ref_tree(struct btrfs_fs_info *fs_info)
98162306a36Sopenharmony_ci{
98262306a36Sopenharmony_ci	struct btrfs_root *extent_root;
98362306a36Sopenharmony_ci	struct btrfs_path *path;
98462306a36Sopenharmony_ci	struct extent_buffer *eb;
98562306a36Sopenharmony_ci	int tree_block_level = 0;
98662306a36Sopenharmony_ci	u64 bytenr = 0, num_bytes = 0;
98762306a36Sopenharmony_ci	int ret, level;
98862306a36Sopenharmony_ci
98962306a36Sopenharmony_ci	if (!btrfs_test_opt(fs_info, REF_VERIFY))
99062306a36Sopenharmony_ci		return 0;
99162306a36Sopenharmony_ci
99262306a36Sopenharmony_ci	path = btrfs_alloc_path();
99362306a36Sopenharmony_ci	if (!path)
99462306a36Sopenharmony_ci		return -ENOMEM;
99562306a36Sopenharmony_ci
99662306a36Sopenharmony_ci	extent_root = btrfs_extent_root(fs_info, 0);
99762306a36Sopenharmony_ci	eb = btrfs_read_lock_root_node(extent_root);
99862306a36Sopenharmony_ci	level = btrfs_header_level(eb);
99962306a36Sopenharmony_ci	path->nodes[level] = eb;
100062306a36Sopenharmony_ci	path->slots[level] = 0;
100162306a36Sopenharmony_ci	path->locks[level] = BTRFS_READ_LOCK;
100262306a36Sopenharmony_ci
100362306a36Sopenharmony_ci	while (1) {
100462306a36Sopenharmony_ci		/*
100562306a36Sopenharmony_ci		 * We have to keep track of the bytenr/num_bytes we last hit
100662306a36Sopenharmony_ci		 * because we could have run out of space for an inline ref, and
100762306a36Sopenharmony_ci		 * would have had to added a ref key item which may appear on a
100862306a36Sopenharmony_ci		 * different leaf from the original extent item.
100962306a36Sopenharmony_ci		 */
101062306a36Sopenharmony_ci		ret = walk_down_tree(extent_root, path, level,
101162306a36Sopenharmony_ci				     &bytenr, &num_bytes, &tree_block_level);
101262306a36Sopenharmony_ci		if (ret)
101362306a36Sopenharmony_ci			break;
101462306a36Sopenharmony_ci		ret = walk_up_tree(path, &level);
101562306a36Sopenharmony_ci		if (ret < 0)
101662306a36Sopenharmony_ci			break;
101762306a36Sopenharmony_ci		if (ret > 0) {
101862306a36Sopenharmony_ci			ret = 0;
101962306a36Sopenharmony_ci			break;
102062306a36Sopenharmony_ci		}
102162306a36Sopenharmony_ci	}
102262306a36Sopenharmony_ci	if (ret) {
102362306a36Sopenharmony_ci		btrfs_free_ref_cache(fs_info);
102462306a36Sopenharmony_ci		btrfs_clear_opt(fs_info->mount_opt, REF_VERIFY);
102562306a36Sopenharmony_ci	}
102662306a36Sopenharmony_ci	btrfs_free_path(path);
102762306a36Sopenharmony_ci	return ret;
102862306a36Sopenharmony_ci}
1029