/*1* Copyright (C) 2008 Oracle. All rights reserved.2*3* This program is free software; you can redistribute it and/or4* modify it under the terms of the GNU General Public5* License v2 as published by the Free Software Foundation.6*7* This program is distributed in the hope that it will be useful,8* but WITHOUT ANY WARRANTY; without even the implied warranty of9* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU10* General Public License for more details.11*12* You should have received a copy of the GNU General Public13* License along with this program; if not, write to the14* Free Software Foundation, Inc., 59 Temple Place - Suite 330,15* Boston, MA 021110-1307, USA.16*/17#ifndef __DELAYED_REF__18#define __DELAYED_REF__1920/* these are the possible values of struct btrfs_delayed_ref->action */21#define BTRFS_ADD_DELAYED_REF 1 /* add one backref to the tree */22#define BTRFS_DROP_DELAYED_REF 2 /* delete one backref from the tree */23#define BTRFS_ADD_DELAYED_EXTENT 3 /* record a full extent allocation */24#define BTRFS_UPDATE_DELAYED_HEAD 4 /* not changing ref count on head ref */2526struct btrfs_delayed_ref_node {27struct rb_node rb_node;2829/* the starting bytenr of the extent */30u64 bytenr;3132/* the size of the extent */33u64 num_bytes;3435/* ref count on this data structure */36atomic_t refs;3738/*39* how many refs is this entry adding or deleting. For40* head refs, this may be a negative number because it is keeping41* track of the total mods done to the reference count.42* For individual refs, this will always be a positive number43*44* It may be more than one, since it is possible for a single45* parent to have more than one ref on an extent46*/47int ref_mod;4849unsigned int action:8;50unsigned int type:8;51/* is this node still in the rbtree? */52unsigned int is_head:1;53unsigned int in_tree:1;54};5556struct btrfs_delayed_extent_op {57struct btrfs_disk_key key;58u64 flags_to_set;59unsigned int update_key:1;60unsigned int update_flags:1;61unsigned int is_data:1;62};6364/*65* the head refs are used to hold a lock on a given extent, which allows us66* to make sure that only one process is running the delayed refs67* at a time for a single extent. They also store the sum of all the68* reference count modifications we've queued up.69*/70struct btrfs_delayed_ref_head {71struct btrfs_delayed_ref_node node;7273/*74* the mutex is held while running the refs, and it is also75* held when checking the sum of reference modifications.76*/77struct mutex mutex;7879struct list_head cluster;8081struct btrfs_delayed_extent_op *extent_op;82/*83* when a new extent is allocated, it is just reserved in memory84* The actual extent isn't inserted into the extent allocation tree85* until the delayed ref is processed. must_insert_reserved is86* used to flag a delayed ref so the accounting can be updated87* when a full insert is done.88*89* It is possible the extent will be freed before it is ever90* inserted into the extent allocation tree. In this case91* we need to update the in ram accounting to properly reflect92* the free has happened.93*/94unsigned int must_insert_reserved:1;95unsigned int is_data:1;96};9798struct btrfs_delayed_tree_ref {99struct btrfs_delayed_ref_node node;100union {101u64 root;102u64 parent;103};104int level;105};106107struct btrfs_delayed_data_ref {108struct btrfs_delayed_ref_node node;109union {110u64 root;111u64 parent;112};113u64 objectid;114u64 offset;115};116117struct btrfs_delayed_ref_root {118struct rb_root root;119120/* this spin lock protects the rbtree and the entries inside */121spinlock_t lock;122123/* how many delayed ref updates we've queued, used by the124* throttling code125*/126unsigned long num_entries;127128/* total number of head nodes in tree */129unsigned long num_heads;130131/* total number of head nodes ready for processing */132unsigned long num_heads_ready;133134/*135* set when the tree is flushing before a transaction commit,136* used by the throttling code to decide if new updates need137* to be run right away138*/139int flushing;140141u64 run_delayed_start;142};143144static inline void btrfs_put_delayed_ref(struct btrfs_delayed_ref_node *ref)145{146WARN_ON(atomic_read(&ref->refs) == 0);147if (atomic_dec_and_test(&ref->refs)) {148WARN_ON(ref->in_tree);149kfree(ref);150}151}152153int btrfs_add_delayed_tree_ref(struct btrfs_trans_handle *trans,154u64 bytenr, u64 num_bytes, u64 parent,155u64 ref_root, int level, int action,156struct btrfs_delayed_extent_op *extent_op);157int btrfs_add_delayed_data_ref(struct btrfs_trans_handle *trans,158u64 bytenr, u64 num_bytes,159u64 parent, u64 ref_root,160u64 owner, u64 offset, int action,161struct btrfs_delayed_extent_op *extent_op);162int btrfs_add_delayed_extent_op(struct btrfs_trans_handle *trans,163u64 bytenr, u64 num_bytes,164struct btrfs_delayed_extent_op *extent_op);165166struct btrfs_delayed_ref_head *167btrfs_find_delayed_ref_head(struct btrfs_trans_handle *trans, u64 bytenr);168int btrfs_delayed_ref_lock(struct btrfs_trans_handle *trans,169struct btrfs_delayed_ref_head *head);170int btrfs_find_ref_cluster(struct btrfs_trans_handle *trans,171struct list_head *cluster, u64 search_start);172/*173* a node might live in a head or a regular ref, this lets you174* test for the proper type to use.175*/176static int btrfs_delayed_ref_is_head(struct btrfs_delayed_ref_node *node)177{178return node->is_head;179}180181/*182* helper functions to cast a node into its container183*/184static inline struct btrfs_delayed_tree_ref *185btrfs_delayed_node_to_tree_ref(struct btrfs_delayed_ref_node *node)186{187WARN_ON(btrfs_delayed_ref_is_head(node));188return container_of(node, struct btrfs_delayed_tree_ref, node);189}190191static inline struct btrfs_delayed_data_ref *192btrfs_delayed_node_to_data_ref(struct btrfs_delayed_ref_node *node)193{194WARN_ON(btrfs_delayed_ref_is_head(node));195return container_of(node, struct btrfs_delayed_data_ref, node);196}197198static inline struct btrfs_delayed_ref_head *199btrfs_delayed_node_to_head(struct btrfs_delayed_ref_node *node)200{201WARN_ON(!btrfs_delayed_ref_is_head(node));202return container_of(node, struct btrfs_delayed_ref_head, node);203}204#endif205206207