diff options
Diffstat (limited to 'fs/btrfs/delayed-ref.h')
| -rw-r--r-- | fs/btrfs/delayed-ref.h | 107 | 
1 files changed, 81 insertions, 26 deletions
diff --git a/fs/btrfs/delayed-ref.h b/fs/btrfs/delayed-ref.h index 50e3cf92fbd..a764e2340d4 100644 --- a/fs/btrfs/delayed-ref.h +++ b/fs/btrfs/delayed-ref.h @@ -18,7 +18,7 @@  #ifndef __DELAYED_REF__  #define __DELAYED_REF__ -/* these are the possible values of struct btrfs_delayed_ref->action */ +/* these are the possible values of struct btrfs_delayed_ref_node->action */  #define BTRFS_ADD_DELAYED_REF    1 /* add one backref to the tree */  #define BTRFS_DROP_DELAYED_REF   2 /* delete one backref from the tree */  #define BTRFS_ADD_DELAYED_EXTENT 3 /* record a full extent allocation */ @@ -33,6 +33,9 @@ struct btrfs_delayed_ref_node {  	/* the size of the extent */  	u64 num_bytes; +	/* seq number to keep track of insertion order */ +	u64 seq; +  	/* ref count on this data structure */  	atomic_t refs; @@ -49,6 +52,7 @@ struct btrfs_delayed_ref_node {  	unsigned int action:8;  	unsigned int type:8; +	unsigned int no_quota:1;  	/* is this node still in the rbtree? */  	unsigned int is_head:1;  	unsigned int in_tree:1; @@ -57,6 +61,7 @@ struct btrfs_delayed_ref_node {  struct btrfs_delayed_extent_op {  	struct btrfs_disk_key key;  	u64 flags_to_set; +	int level;  	unsigned int update_key:1;  	unsigned int update_flags:1;  	unsigned int is_data:1; @@ -77,7 +82,10 @@ struct btrfs_delayed_ref_head {  	 */  	struct mutex mutex; -	struct list_head cluster; +	spinlock_t lock; +	struct rb_root ref_root; + +	struct rb_node href_node;  	struct btrfs_delayed_extent_op *extent_op;  	/* @@ -94,29 +102,27 @@ struct btrfs_delayed_ref_head {  	 */  	unsigned int must_insert_reserved:1;  	unsigned int is_data:1; +	unsigned int processing:1;  };  struct btrfs_delayed_tree_ref {  	struct btrfs_delayed_ref_node node; -	union { -		u64 root; -		u64 parent; -	}; +	u64 root; +	u64 parent;  	int level;  };  struct btrfs_delayed_data_ref {  	struct btrfs_delayed_ref_node node; -	union { -		u64 root; -		u64 parent; -	}; +	u64 root; +	u64 parent;  	u64 objectid;  	u64 offset;  };  struct btrfs_delayed_ref_root { -	struct rb_root root; +	/* head ref rbtree */ +	struct rb_root href_root;  	/* this spin lock protects the rbtree and the entries inside */  	spinlock_t lock; @@ -124,7 +130,7 @@ struct btrfs_delayed_ref_root {  	/* how many delayed ref updates we've queued, used by the  	 * throttling code  	 */ -	unsigned long num_entries; +	atomic_t num_entries;  	/* total number of head nodes in tree */  	unsigned long num_heads; @@ -142,40 +148,89 @@ struct btrfs_delayed_ref_root {  	u64 run_delayed_start;  }; +extern struct kmem_cache *btrfs_delayed_ref_head_cachep; +extern struct kmem_cache *btrfs_delayed_tree_ref_cachep; +extern struct kmem_cache *btrfs_delayed_data_ref_cachep; +extern struct kmem_cache *btrfs_delayed_extent_op_cachep; + +int btrfs_delayed_ref_init(void); +void btrfs_delayed_ref_exit(void); + +static inline struct btrfs_delayed_extent_op * +btrfs_alloc_delayed_extent_op(void) +{ +	return kmem_cache_alloc(btrfs_delayed_extent_op_cachep, GFP_NOFS); +} + +static inline void +btrfs_free_delayed_extent_op(struct btrfs_delayed_extent_op *op) +{ +	if (op) +		kmem_cache_free(btrfs_delayed_extent_op_cachep, op); +} +  static inline void btrfs_put_delayed_ref(struct btrfs_delayed_ref_node *ref)  {  	WARN_ON(atomic_read(&ref->refs) == 0);  	if (atomic_dec_and_test(&ref->refs)) {  		WARN_ON(ref->in_tree); -		kfree(ref); +		switch (ref->type) { +		case BTRFS_TREE_BLOCK_REF_KEY: +		case BTRFS_SHARED_BLOCK_REF_KEY: +			kmem_cache_free(btrfs_delayed_tree_ref_cachep, ref); +			break; +		case BTRFS_EXTENT_DATA_REF_KEY: +		case BTRFS_SHARED_DATA_REF_KEY: +			kmem_cache_free(btrfs_delayed_data_ref_cachep, ref); +			break; +		case 0: +			kmem_cache_free(btrfs_delayed_ref_head_cachep, ref); +			break; +		default: +			BUG(); +		}  	}  } -int btrfs_add_delayed_tree_ref(struct btrfs_trans_handle *trans, +int btrfs_add_delayed_tree_ref(struct btrfs_fs_info *fs_info, +			       struct btrfs_trans_handle *trans,  			       u64 bytenr, u64 num_bytes, u64 parent,  			       u64 ref_root, int level, int action, -			       struct btrfs_delayed_extent_op *extent_op); -int btrfs_add_delayed_data_ref(struct btrfs_trans_handle *trans, +			       struct btrfs_delayed_extent_op *extent_op, +			       int no_quota); +int btrfs_add_delayed_data_ref(struct btrfs_fs_info *fs_info, +			       struct btrfs_trans_handle *trans,  			       u64 bytenr, u64 num_bytes,  			       u64 parent, u64 ref_root,  			       u64 owner, u64 offset, int action, -			       struct btrfs_delayed_extent_op *extent_op); -int btrfs_add_delayed_extent_op(struct btrfs_trans_handle *trans, +			       struct btrfs_delayed_extent_op *extent_op, +			       int no_quota); +int btrfs_add_delayed_extent_op(struct btrfs_fs_info *fs_info, +				struct btrfs_trans_handle *trans,  				u64 bytenr, u64 num_bytes,  				struct btrfs_delayed_extent_op *extent_op); +void btrfs_merge_delayed_refs(struct btrfs_trans_handle *trans, +			      struct btrfs_fs_info *fs_info, +			      struct btrfs_delayed_ref_root *delayed_refs, +			      struct btrfs_delayed_ref_head *head);  struct btrfs_delayed_ref_head *  btrfs_find_delayed_ref_head(struct btrfs_trans_handle *trans, u64 bytenr); -int btrfs_delayed_ref_pending(struct btrfs_trans_handle *trans, u64 bytenr); -int btrfs_update_delayed_ref(struct btrfs_trans_handle *trans, -			  u64 bytenr, u64 num_bytes, u64 orig_parent, -			  u64 parent, u64 orig_ref_root, u64 ref_root, -			  u64 orig_ref_generation, u64 ref_generation, -			  u64 owner_objectid, int pin);  int btrfs_delayed_ref_lock(struct btrfs_trans_handle *trans,  			   struct btrfs_delayed_ref_head *head); -int btrfs_find_ref_cluster(struct btrfs_trans_handle *trans, -			   struct list_head *cluster, u64 search_start); +static inline void btrfs_delayed_ref_unlock(struct btrfs_delayed_ref_head *head) +{ +	mutex_unlock(&head->mutex); +} + + +struct btrfs_delayed_ref_head * +btrfs_select_ref_head(struct btrfs_trans_handle *trans); + +int btrfs_check_delayed_seq(struct btrfs_fs_info *fs_info, +			    struct btrfs_delayed_ref_root *delayed_refs, +			    u64 seq); +  /*   * a node might live in a head or a regular ref, this lets you   * test for the proper type to use.  | 
