diff options
| author | Chris Mason <chris.mason@fusionio.com> | 2013-05-17 21:53:17 -0400 | 
|---|---|---|
| committer | Chris Mason <chris.mason@fusionio.com> | 2013-05-17 21:53:17 -0400 | 
| commit | c5cb6a0573bef87e098ee3cd946115ebe60a910e (patch) | |
| tree | 49b64747b7af6b1024b25470cba583fa7dafe531 /fs/btrfs/extent-tree.c | |
| parent | 9be3395bcd4ad4af76476ac38152b4cafa6b6159 (diff) | |
| parent | 655b09fe540b73edeaabfb4c2d700be51a1f8bce (diff) | |
| download | olio-linux-3.10-c5cb6a0573bef87e098ee3cd946115ebe60a910e.tar.xz olio-linux-3.10-c5cb6a0573bef87e098ee3cd946115ebe60a910e.zip  | |
Merge branch 'for-chris' of git://git.kernel.org/pub/scm/linux/kernel/git/josef/btrfs-next
Diffstat (limited to 'fs/btrfs/extent-tree.c')
| -rw-r--r-- | fs/btrfs/extent-tree.c | 94 | 
1 files changed, 50 insertions, 44 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 2305b5c5cf0..df472ab1b5a 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -2070,8 +2070,7 @@ static int run_delayed_extent_op(struct btrfs_trans_handle *trans,  	u32 item_size;  	int ret;  	int err = 0; -	int metadata = (node->type == BTRFS_TREE_BLOCK_REF_KEY || -			node->type == BTRFS_SHARED_BLOCK_REF_KEY); +	int metadata = !extent_op->is_data;  	if (trans->aborted)  		return 0; @@ -2086,11 +2085,8 @@ static int run_delayed_extent_op(struct btrfs_trans_handle *trans,  	key.objectid = node->bytenr;  	if (metadata) { -		struct btrfs_delayed_tree_ref *tree_ref; - -		tree_ref = btrfs_delayed_node_to_tree_ref(node);  		key.type = BTRFS_METADATA_ITEM_KEY; -		key.offset = tree_ref->level; +		key.offset = extent_op->level;  	} else {  		key.type = BTRFS_EXTENT_ITEM_KEY;  		key.offset = node->num_bytes; @@ -2719,7 +2715,7 @@ out:  int btrfs_set_disk_extent_flags(struct btrfs_trans_handle *trans,  				struct btrfs_root *root,  				u64 bytenr, u64 num_bytes, u64 flags, -				int is_data) +				int level, int is_data)  {  	struct btrfs_delayed_extent_op *extent_op;  	int ret; @@ -2732,6 +2728,7 @@ int btrfs_set_disk_extent_flags(struct btrfs_trans_handle *trans,  	extent_op->update_flags = 1;  	extent_op->update_key = 0;  	extent_op->is_data = is_data ? 1 : 0; +	extent_op->level = level;  	ret = btrfs_add_delayed_extent_op(root->fs_info, trans, bytenr,  					  num_bytes, extent_op); @@ -3109,6 +3106,11 @@ again:  	WARN_ON(ret);  	if (i_size_read(inode) > 0) { +		ret = btrfs_check_trunc_cache_free_space(root, +					&root->fs_info->global_block_rsv); +		if (ret) +			goto out_put; +  		ret = btrfs_truncate_free_space_cache(root, trans, path,  						      inode);  		if (ret) @@ -4562,6 +4564,8 @@ static void init_global_block_rsv(struct btrfs_fs_info *fs_info)  	fs_info->csum_root->block_rsv = &fs_info->global_block_rsv;  	fs_info->dev_root->block_rsv = &fs_info->global_block_rsv;  	fs_info->tree_root->block_rsv = &fs_info->global_block_rsv; +	if (fs_info->quota_root) +		fs_info->quota_root->block_rsv = &fs_info->global_block_rsv;  	fs_info->chunk_root->block_rsv = &fs_info->chunk_block_rsv;  	update_global_block_rsv(fs_info); @@ -6651,51 +6655,51 @@ use_block_rsv(struct btrfs_trans_handle *trans,  	struct btrfs_block_rsv *block_rsv;  	struct btrfs_block_rsv *global_rsv = &root->fs_info->global_block_rsv;  	int ret; +	bool global_updated = false;  	block_rsv = get_block_rsv(trans, root); -	if (block_rsv->size == 0) { -		ret = reserve_metadata_bytes(root, block_rsv, blocksize, -					     BTRFS_RESERVE_NO_FLUSH); -		/* -		 * If we couldn't reserve metadata bytes try and use some from -		 * the global reserve. -		 */ -		if (ret && block_rsv != global_rsv) { -			ret = block_rsv_use_bytes(global_rsv, blocksize); -			if (!ret) -				return global_rsv; -			return ERR_PTR(ret); -		} else if (ret) { -			return ERR_PTR(ret); -		} +	if (unlikely(block_rsv->size == 0)) +		goto try_reserve; +again: +	ret = block_rsv_use_bytes(block_rsv, blocksize); +	if (!ret)  		return block_rsv; + +	if (block_rsv->failfast) +		return ERR_PTR(ret); + +	if (block_rsv->type == BTRFS_BLOCK_RSV_GLOBAL && !global_updated) { +		global_updated = true; +		update_global_block_rsv(root->fs_info); +		goto again;  	} -	ret = block_rsv_use_bytes(block_rsv, blocksize); +	if (btrfs_test_opt(root, ENOSPC_DEBUG)) { +		static DEFINE_RATELIMIT_STATE(_rs, +				DEFAULT_RATELIMIT_INTERVAL * 10, +				/*DEFAULT_RATELIMIT_BURST*/ 1); +		if (__ratelimit(&_rs)) +			WARN(1, KERN_DEBUG +				"btrfs: block rsv returned %d\n", ret); +	} +try_reserve: +	ret = reserve_metadata_bytes(root, block_rsv, blocksize, +				     BTRFS_RESERVE_NO_FLUSH);  	if (!ret)  		return block_rsv; -	if (ret && !block_rsv->failfast) { -		if (btrfs_test_opt(root, ENOSPC_DEBUG)) { -			static DEFINE_RATELIMIT_STATE(_rs, -					DEFAULT_RATELIMIT_INTERVAL * 10, -					/*DEFAULT_RATELIMIT_BURST*/ 1); -			if (__ratelimit(&_rs)) -				WARN(1, KERN_DEBUG -					"btrfs: block rsv returned %d\n", ret); -		} -		ret = reserve_metadata_bytes(root, block_rsv, blocksize, -					     BTRFS_RESERVE_NO_FLUSH); -		if (!ret) { -			return block_rsv; -		} else if (ret && block_rsv != global_rsv) { -			ret = block_rsv_use_bytes(global_rsv, blocksize); -			if (!ret) -				return global_rsv; -		} +	/* +	 * If we couldn't reserve metadata bytes try and use some from +	 * the global reserve if its space type is the same as the global +	 * reservation. +	 */ +	if (block_rsv->type != BTRFS_BLOCK_RSV_GLOBAL && +	    block_rsv->space_info == global_rsv->space_info) { +		ret = block_rsv_use_bytes(global_rsv, blocksize); +		if (!ret) +			return global_rsv;  	} - -	return ERR_PTR(-ENOSPC); +	return ERR_PTR(ret);  }  static void unuse_block_rsv(struct btrfs_fs_info *fs_info, @@ -6763,6 +6767,7 @@ struct extent_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans,  			extent_op->update_key = 1;  		extent_op->update_flags = 1;  		extent_op->is_data = 0; +		extent_op->level = level;  		ret = btrfs_add_delayed_tree_ref(root->fs_info, trans,  					ins.objectid, @@ -6934,7 +6939,8 @@ static noinline int walk_down_proc(struct btrfs_trans_handle *trans,  		ret = btrfs_dec_ref(trans, root, eb, 0, wc->for_reloc);  		BUG_ON(ret); /* -ENOMEM */  		ret = btrfs_set_disk_extent_flags(trans, root, eb->start, -						  eb->len, flag, 0); +						  eb->len, flag, +						  btrfs_header_level(eb), 0);  		BUG_ON(ret); /* -ENOMEM */  		wc->flags[level] |= flag;  	}  |