diff options
Diffstat (limited to 'fs/btrfs/relocation.c')
| -rw-r--r-- | fs/btrfs/relocation.c | 101 | 
1 files changed, 55 insertions, 46 deletions
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index f340f7c99d0..b1ef27cc673 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c @@ -30,6 +30,7 @@  #include "btrfs_inode.h"  #include "async-thread.h"  #include "free-space-cache.h" +#include "inode-map.h"  /*   * backref_node, mapping_node and tree_block start with this @@ -507,6 +508,7 @@ static int update_backref_cache(struct btrfs_trans_handle *trans,  	return 1;  } +  static int should_ignore_root(struct btrfs_root *root)  {  	struct btrfs_root *reloc_root; @@ -529,7 +531,6 @@ static int should_ignore_root(struct btrfs_root *root)  	 */  	return 1;  } -  /*   * find reloc tree by address of tree root   */ @@ -676,6 +677,8 @@ struct backref_node *build_backref_tree(struct reloc_control *rc,  		err = -ENOMEM;  		goto out;  	} +	path1->reada = 1; +	path2->reada = 2;  	node = alloc_backref_node(cache);  	if (!node) { @@ -961,7 +964,7 @@ again:  			lower = upper;  			upper = NULL;  		} -		btrfs_release_path(root, path2); +		btrfs_release_path(path2);  next:  		if (ptr < end) {  			ptr += btrfs_extent_inline_ref_size(key.type); @@ -974,7 +977,7 @@ next:  		if (ptr >= end)  			path1->slots[0]++;  	} -	btrfs_release_path(rc->extent_root, path1); +	btrfs_release_path(path1);  	cur->checked = 1;  	WARN_ON(exist); @@ -1409,9 +1412,9 @@ again:  		prev = node;  		entry = rb_entry(node, struct btrfs_inode, rb_node); -		if (objectid < entry->vfs_inode.i_ino) +		if (objectid < btrfs_ino(&entry->vfs_inode))  			node = node->rb_left; -		else if (objectid > entry->vfs_inode.i_ino) +		else if (objectid > btrfs_ino(&entry->vfs_inode))  			node = node->rb_right;  		else  			break; @@ -1419,7 +1422,7 @@ again:  	if (!node) {  		while (prev) {  			entry = rb_entry(prev, struct btrfs_inode, rb_node); -			if (objectid <= entry->vfs_inode.i_ino) { +			if (objectid <= btrfs_ino(&entry->vfs_inode)) {  				node = prev;  				break;  			} @@ -1434,7 +1437,7 @@ again:  			return inode;  		} -		objectid = entry->vfs_inode.i_ino + 1; +		objectid = btrfs_ino(&entry->vfs_inode) + 1;  		if (cond_resched_lock(&root->inode_lock))  			goto again; @@ -1470,7 +1473,7 @@ static int get_new_location(struct inode *reloc_inode, u64 *new_bytenr,  		return -ENOMEM;  	bytenr -= BTRFS_I(reloc_inode)->index_cnt; -	ret = btrfs_lookup_file_extent(NULL, root, path, reloc_inode->i_ino, +	ret = btrfs_lookup_file_extent(NULL, root, path, btrfs_ino(reloc_inode),  				       bytenr, 0);  	if (ret < 0)  		goto out; @@ -1558,11 +1561,11 @@ int replace_file_extents(struct btrfs_trans_handle *trans,  			if (first) {  				inode = find_next_inode(root, key.objectid);  				first = 0; -			} else if (inode && inode->i_ino < key.objectid) { +			} else if (inode && btrfs_ino(inode) < key.objectid) {  				btrfs_add_delayed_iput(inode);  				inode = find_next_inode(root, key.objectid);  			} -			if (inode && inode->i_ino == key.objectid) { +			if (inode && btrfs_ino(inode) == key.objectid) {  				end = key.offset +  				      btrfs_file_extent_num_bytes(leaf, fi);  				WARN_ON(!IS_ALIGNED(key.offset, @@ -1749,7 +1752,7 @@ again:  		btrfs_node_key_to_cpu(path->nodes[level], &key,  				      path->slots[level]); -		btrfs_release_path(src, path); +		btrfs_release_path(path);  		path->lowest_level = level;  		ret = btrfs_search_slot(trans, src, &key, path, 0, 1); @@ -1893,6 +1896,7 @@ static int invalidate_extent_cache(struct btrfs_root *root,  	struct inode *inode = NULL;  	u64 objectid;  	u64 start, end; +	u64 ino;  	objectid = min_key->objectid;  	while (1) { @@ -1905,17 +1909,18 @@ static int invalidate_extent_cache(struct btrfs_root *root,  		inode = find_next_inode(root, objectid);  		if (!inode)  			break; +		ino = btrfs_ino(inode); -		if (inode->i_ino > max_key->objectid) { +		if (ino > max_key->objectid) {  			iput(inode);  			break;  		} -		objectid = inode->i_ino + 1; +		objectid = ino + 1;  		if (!S_ISREG(inode->i_mode))  			continue; -		if (unlikely(min_key->objectid == inode->i_ino)) { +		if (unlikely(min_key->objectid == ino)) {  			if (min_key->type > BTRFS_EXTENT_DATA_KEY)  				continue;  			if (min_key->type < BTRFS_EXTENT_DATA_KEY) @@ -1928,7 +1933,7 @@ static int invalidate_extent_cache(struct btrfs_root *root,  			start = 0;  		} -		if (unlikely(max_key->objectid == inode->i_ino)) { +		if (unlikely(max_key->objectid == ino)) {  			if (max_key->type < BTRFS_EXTENT_DATA_KEY)  				continue;  			if (max_key->type > BTRFS_EXTENT_DATA_KEY) { @@ -1996,6 +2001,7 @@ static noinline_for_stack int merge_reloc_root(struct reloc_control *rc,  	path = btrfs_alloc_path();  	if (!path)  		return -ENOMEM; +	path->reada = 1;  	reloc_root = root->reloc_root;  	root_item = &reloc_root->root_item; @@ -2136,10 +2142,10 @@ int prepare_to_merge(struct reloc_control *rc, int err)  	u64 num_bytes = 0;  	int ret; -	mutex_lock(&root->fs_info->trans_mutex); +	spin_lock(&root->fs_info->trans_lock);  	rc->merging_rsv_size += root->nodesize * (BTRFS_MAX_LEVEL - 1) * 2;  	rc->merging_rsv_size += rc->nodes_relocated * 2; -	mutex_unlock(&root->fs_info->trans_mutex); +	spin_unlock(&root->fs_info->trans_lock);  again:  	if (!err) {  		num_bytes = rc->merging_rsv_size; @@ -2149,7 +2155,7 @@ again:  			err = ret;  	} -	trans = btrfs_join_transaction(rc->extent_root, 1); +	trans = btrfs_join_transaction(rc->extent_root);  	if (IS_ERR(trans)) {  		if (!err)  			btrfs_block_rsv_release(rc->extent_root, @@ -2208,9 +2214,9 @@ int merge_reloc_roots(struct reloc_control *rc)  	int ret;  again:  	root = rc->extent_root; -	mutex_lock(&root->fs_info->trans_mutex); +	spin_lock(&root->fs_info->trans_lock);  	list_splice_init(&rc->reloc_roots, &reloc_roots); -	mutex_unlock(&root->fs_info->trans_mutex); +	spin_unlock(&root->fs_info->trans_lock);  	while (!list_empty(&reloc_roots)) {  		found = 1; @@ -2496,7 +2502,7 @@ static int do_relocation(struct btrfs_trans_handle *trans,  			path->locks[upper->level] = 0;  			slot = path->slots[upper->level]; -			btrfs_release_path(NULL, path); +			btrfs_release_path(path);  		} else {  			ret = btrfs_bin_search(upper->eb, key, upper->level,  					       &slot); @@ -2737,7 +2743,7 @@ static int relocate_tree_block(struct btrfs_trans_handle *trans,  		} else {  			path->lowest_level = node->level;  			ret = btrfs_search_slot(trans, root, key, path, 0, 1); -			btrfs_release_path(root, path); +			btrfs_release_path(path);  			if (ret > 0)  				ret = 0;  		} @@ -2870,7 +2876,7 @@ int setup_extent_mapping(struct inode *inode, u64 start, u64 end,  	struct extent_map *em;  	int ret = 0; -	em = alloc_extent_map(GFP_NOFS); +	em = alloc_extent_map();  	if (!em)  		return -ENOMEM; @@ -3119,7 +3125,7 @@ static int add_tree_block(struct reloc_control *rc,  #endif  	} -	btrfs_release_path(rc->extent_root, path); +	btrfs_release_path(path);  	BUG_ON(level == -1); @@ -3220,7 +3226,7 @@ static int delete_block_group_cache(struct btrfs_fs_info *fs_info,  	key.offset = 0;  	inode = btrfs_iget(fs_info->sb, &key, root, NULL); -	if (!inode || IS_ERR(inode) || is_bad_inode(inode)) { +	if (IS_ERR_OR_NULL(inode) || is_bad_inode(inode)) {  		if (inode && !IS_ERR(inode))  			iput(inode);  		return -ENOENT; @@ -3233,7 +3239,7 @@ truncate:  		goto out;  	} -	trans = btrfs_join_transaction(root, 0); +	trans = btrfs_join_transaction(root);  	if (IS_ERR(trans)) {  		btrfs_free_path(path);  		ret = PTR_ERR(trans); @@ -3297,6 +3303,7 @@ static int find_data_references(struct reloc_control *rc,  	path = btrfs_alloc_path();  	if (!path)  		return -ENOMEM; +	path->reada = 1;  	root = read_fs_root(rc->extent_root->fs_info, ref_root);  	if (IS_ERR(root)) { @@ -3505,7 +3512,7 @@ int add_data_references(struct reloc_control *rc,  		}  		path->slots[0]++;  	} -	btrfs_release_path(rc->extent_root, path); +	btrfs_release_path(path);  	if (err)  		free_block_list(blocks);  	return err; @@ -3568,7 +3575,7 @@ next:  					    EXTENT_DIRTY);  		if (ret == 0 && start <= key.objectid) { -			btrfs_release_path(rc->extent_root, path); +			btrfs_release_path(path);  			rc->search_start = end + 1;  		} else {  			rc->search_start = key.objectid + key.offset; @@ -3576,24 +3583,24 @@ next:  			return 0;  		}  	} -	btrfs_release_path(rc->extent_root, path); +	btrfs_release_path(path);  	return ret;  }  static void set_reloc_control(struct reloc_control *rc)  {  	struct btrfs_fs_info *fs_info = rc->extent_root->fs_info; -	mutex_lock(&fs_info->trans_mutex); +	spin_lock(&fs_info->trans_lock);  	fs_info->reloc_ctl = rc; -	mutex_unlock(&fs_info->trans_mutex); +	spin_unlock(&fs_info->trans_lock);  }  static void unset_reloc_control(struct reloc_control *rc)  {  	struct btrfs_fs_info *fs_info = rc->extent_root->fs_info; -	mutex_lock(&fs_info->trans_mutex); +	spin_lock(&fs_info->trans_lock);  	fs_info->reloc_ctl = NULL; -	mutex_unlock(&fs_info->trans_mutex); +	spin_unlock(&fs_info->trans_lock);  }  static int check_extent_flags(u64 flags) @@ -3642,7 +3649,7 @@ int prepare_to_relocate(struct reloc_control *rc)  	rc->create_reloc_tree = 1;  	set_reloc_control(rc); -	trans = btrfs_join_transaction(rc->extent_root, 1); +	trans = btrfs_join_transaction(rc->extent_root);  	BUG_ON(IS_ERR(trans));  	btrfs_commit_transaction(trans, rc->extent_root);  	return 0; @@ -3665,6 +3672,7 @@ static noinline_for_stack int relocate_block_group(struct reloc_control *rc)  	path = btrfs_alloc_path();  	if (!path)  		return -ENOMEM; +	path->reada = 1;  	ret = prepare_to_relocate(rc);  	if (ret) { @@ -3713,7 +3721,7 @@ restart:  				flags = BTRFS_EXTENT_FLAG_DATA;  			if (path_change) { -				btrfs_release_path(rc->extent_root, path); +				btrfs_release_path(path);  				path->search_commit_root = 1;  				path->skip_locking = 1; @@ -3736,7 +3744,7 @@ restart:  			   (flags & BTRFS_EXTENT_FLAG_DATA)) {  			ret = add_data_references(rc, &key, path, &blocks);  		} else { -			btrfs_release_path(rc->extent_root, path); +			btrfs_release_path(path);  			ret = 0;  		}  		if (ret < 0) { @@ -3799,7 +3807,7 @@ restart:  		}  	} -	btrfs_release_path(rc->extent_root, path); +	btrfs_release_path(path);  	clear_extent_bits(&rc->processed_blocks, 0, (u64)-1, EXTENT_DIRTY,  			  GFP_NOFS); @@ -3831,7 +3839,7 @@ restart:  	btrfs_block_rsv_release(rc->extent_root, rc->block_rsv, (u64)-1);  	/* get rid of pinned extents */ -	trans = btrfs_join_transaction(rc->extent_root, 1); +	trans = btrfs_join_transaction(rc->extent_root);  	if (IS_ERR(trans))  		err = PTR_ERR(trans);  	else @@ -3867,7 +3875,7 @@ static int __insert_orphan_inode(struct btrfs_trans_handle *trans,  	btrfs_set_inode_flags(leaf, item, BTRFS_INODE_NOCOMPRESS |  					  BTRFS_INODE_PREALLOC);  	btrfs_mark_buffer_dirty(leaf); -	btrfs_release_path(root, path); +	btrfs_release_path(path);  out:  	btrfs_free_path(path);  	return ret; @@ -3897,7 +3905,7 @@ struct inode *create_reloc_inode(struct btrfs_fs_info *fs_info,  	if (IS_ERR(trans))  		return ERR_CAST(trans); -	err = btrfs_find_free_objectid(trans, root, objectid, &objectid); +	err = btrfs_find_free_objectid(root, &objectid);  	if (err)  		goto out; @@ -3935,7 +3943,7 @@ static struct reloc_control *alloc_reloc_control(void)  	INIT_LIST_HEAD(&rc->reloc_roots);  	backref_cache_init(&rc->backref_cache);  	mapping_tree_init(&rc->reloc_root_tree); -	extent_io_tree_init(&rc->processed_blocks, NULL, GFP_NOFS); +	extent_io_tree_init(&rc->processed_blocks, NULL);  	return rc;  } @@ -4090,6 +4098,7 @@ int btrfs_recover_relocation(struct btrfs_root *root)  	path = btrfs_alloc_path();  	if (!path)  		return -ENOMEM; +	path->reada = -1;  	key.objectid = BTRFS_TREE_RELOC_OBJECTID;  	key.type = BTRFS_ROOT_ITEM_KEY; @@ -4109,7 +4118,7 @@ int btrfs_recover_relocation(struct btrfs_root *root)  		}  		leaf = path->nodes[0];  		btrfs_item_key_to_cpu(leaf, &key, path->slots[0]); -		btrfs_release_path(root->fs_info->tree_root, path); +		btrfs_release_path(path);  		if (key.objectid != BTRFS_TREE_RELOC_OBJECTID ||  		    key.type != BTRFS_ROOT_ITEM_KEY) @@ -4141,7 +4150,7 @@ int btrfs_recover_relocation(struct btrfs_root *root)  		key.offset--;  	} -	btrfs_release_path(root->fs_info->tree_root, path); +	btrfs_release_path(path);  	if (list_empty(&reloc_roots))  		goto out; @@ -4156,7 +4165,7 @@ int btrfs_recover_relocation(struct btrfs_root *root)  	set_reloc_control(rc); -	trans = btrfs_join_transaction(rc->extent_root, 1); +	trans = btrfs_join_transaction(rc->extent_root);  	if (IS_ERR(trans)) {  		unset_reloc_control(rc);  		err = PTR_ERR(trans); @@ -4190,7 +4199,7 @@ int btrfs_recover_relocation(struct btrfs_root *root)  	unset_reloc_control(rc); -	trans = btrfs_join_transaction(rc->extent_root, 1); +	trans = btrfs_join_transaction(rc->extent_root);  	if (IS_ERR(trans))  		err = PTR_ERR(trans);  	else @@ -4242,7 +4251,7 @@ int btrfs_reloc_clone_csums(struct inode *inode, u64 file_pos, u64 len)  	disk_bytenr = file_pos + BTRFS_I(inode)->index_cnt;  	ret = btrfs_lookup_csums_range(root->fs_info->csum_root, disk_bytenr, -				       disk_bytenr + len - 1, &list); +				       disk_bytenr + len - 1, &list, 0);  	while (!list_empty(&list)) {  		sums = list_entry(list.next, struct btrfs_ordered_sum, list);  |