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