diff options
Diffstat (limited to 'fs/btrfs/inode-map.c')
| -rw-r--r-- | fs/btrfs/inode-map.c | 28 | 
1 files changed, 24 insertions, 4 deletions
diff --git a/fs/btrfs/inode-map.c b/fs/btrfs/inode-map.c index 53dcbdf446c..f8962a957d6 100644 --- a/fs/btrfs/inode-map.c +++ b/fs/btrfs/inode-map.c @@ -398,6 +398,8 @@ int btrfs_save_ino_cache(struct btrfs_root *root,  	struct btrfs_free_space_ctl *ctl = root->free_ino_ctl;  	struct btrfs_path *path;  	struct inode *inode; +	struct btrfs_block_rsv *rsv; +	u64 num_bytes;  	u64 alloc_hint = 0;  	int ret;  	int prealloc; @@ -421,11 +423,26 @@ int btrfs_save_ino_cache(struct btrfs_root *root,  	if (!path)  		return -ENOMEM; +	rsv = trans->block_rsv; +	trans->block_rsv = &root->fs_info->trans_block_rsv; + +	num_bytes = trans->bytes_reserved; +	/* +	 * 1 item for inode item insertion if need +	 * 3 items for inode item update (in the worst case) +	 * 1 item for free space object +	 * 3 items for pre-allocation +	 */ +	trans->bytes_reserved = btrfs_calc_trans_metadata_size(root, 8); +	ret = btrfs_block_rsv_add_noflush(root, trans->block_rsv, +					  trans->bytes_reserved); +	if (ret) +		goto out;  again:  	inode = lookup_free_ino_inode(root, path);  	if (IS_ERR(inode) && PTR_ERR(inode) != -ENOENT) {  		ret = PTR_ERR(inode); -		goto out; +		goto out_release;  	}  	if (IS_ERR(inode)) { @@ -434,7 +451,7 @@ again:  		ret = create_free_ino_inode(root, trans, path);  		if (ret) -			goto out; +			goto out_release;  		goto again;  	} @@ -477,11 +494,14 @@ again:  	}  	btrfs_free_reserved_data_space(inode, prealloc); +	ret = btrfs_write_out_ino_cache(root, trans, path);  out_put:  	iput(inode); +out_release: +	btrfs_block_rsv_release(root, trans->block_rsv, trans->bytes_reserved);  out: -	if (ret == 0) -		ret = btrfs_write_out_ino_cache(root, trans, path); +	trans->block_rsv = rsv; +	trans->bytes_reserved = num_bytes;  	btrfs_free_path(path);  	return ret;  |