diff options
-rw-r--r-- | fs/btrfs/extent-tree.c | 5 | ||||
-rw-r--r-- | fs/btrfs/free-space-cache.c | 39 | ||||
-rw-r--r-- | fs/btrfs/free-space-cache.h | 2 | ||||
-rw-r--r-- | fs/btrfs/inode-map.c | 5 | ||||
-rw-r--r-- | fs/btrfs/relocation.c | 5 |
5 files changed, 34 insertions, 22 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index c4c94b30c729..162a66bfbffd 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -3106,6 +3106,11 @@ again: | |||
3106 | WARN_ON(ret); | 3106 | WARN_ON(ret); |
3107 | 3107 | ||
3108 | if (i_size_read(inode) > 0) { | 3108 | if (i_size_read(inode) > 0) { |
3109 | ret = btrfs_check_trunc_cache_free_space(root, | ||
3110 | &root->fs_info->global_block_rsv); | ||
3111 | if (ret) | ||
3112 | goto out_put; | ||
3113 | |||
3109 | ret = btrfs_truncate_free_space_cache(root, trans, path, | 3114 | ret = btrfs_truncate_free_space_cache(root, trans, path, |
3110 | inode); | 3115 | inode); |
3111 | if (ret) | 3116 | if (ret) |
diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index 6a8bb9c79674..e53009657f0e 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c | |||
@@ -197,30 +197,32 @@ int create_free_space_inode(struct btrfs_root *root, | |||
197 | block_group->key.objectid); | 197 | block_group->key.objectid); |
198 | } | 198 | } |
199 | 199 | ||
200 | int btrfs_truncate_free_space_cache(struct btrfs_root *root, | 200 | int btrfs_check_trunc_cache_free_space(struct btrfs_root *root, |
201 | struct btrfs_trans_handle *trans, | 201 | struct btrfs_block_rsv *rsv) |
202 | struct btrfs_path *path, | ||
203 | struct inode *inode) | ||
204 | { | 202 | { |
205 | struct btrfs_block_rsv *rsv; | ||
206 | u64 needed_bytes; | 203 | u64 needed_bytes; |
207 | loff_t oldsize; | 204 | int ret; |
208 | int ret = 0; | ||
209 | |||
210 | rsv = trans->block_rsv; | ||
211 | trans->block_rsv = &root->fs_info->global_block_rsv; | ||
212 | 205 | ||
213 | /* 1 for slack space, 1 for updating the inode */ | 206 | /* 1 for slack space, 1 for updating the inode */ |
214 | needed_bytes = btrfs_calc_trunc_metadata_size(root, 1) + | 207 | needed_bytes = btrfs_calc_trunc_metadata_size(root, 1) + |
215 | btrfs_calc_trans_metadata_size(root, 1); | 208 | btrfs_calc_trans_metadata_size(root, 1); |
216 | 209 | ||
217 | spin_lock(&trans->block_rsv->lock); | 210 | spin_lock(&rsv->lock); |
218 | if (trans->block_rsv->reserved < needed_bytes) { | 211 | if (rsv->reserved < needed_bytes) |
219 | spin_unlock(&trans->block_rsv->lock); | 212 | ret = -ENOSPC; |
220 | trans->block_rsv = rsv; | 213 | else |
221 | return -ENOSPC; | 214 | ret = 0; |
222 | } | 215 | spin_unlock(&rsv->lock); |
223 | spin_unlock(&trans->block_rsv->lock); | 216 | return 0; |
217 | } | ||
218 | |||
219 | int btrfs_truncate_free_space_cache(struct btrfs_root *root, | ||
220 | struct btrfs_trans_handle *trans, | ||
221 | struct btrfs_path *path, | ||
222 | struct inode *inode) | ||
223 | { | ||
224 | loff_t oldsize; | ||
225 | int ret = 0; | ||
224 | 226 | ||
225 | oldsize = i_size_read(inode); | 227 | oldsize = i_size_read(inode); |
226 | btrfs_i_size_write(inode, 0); | 228 | btrfs_i_size_write(inode, 0); |
@@ -232,9 +234,7 @@ int btrfs_truncate_free_space_cache(struct btrfs_root *root, | |||
232 | */ | 234 | */ |
233 | ret = btrfs_truncate_inode_items(trans, root, inode, | 235 | ret = btrfs_truncate_inode_items(trans, root, inode, |
234 | 0, BTRFS_EXTENT_DATA_KEY); | 236 | 0, BTRFS_EXTENT_DATA_KEY); |
235 | |||
236 | if (ret) { | 237 | if (ret) { |
237 | trans->block_rsv = rsv; | ||
238 | btrfs_abort_transaction(trans, root, ret); | 238 | btrfs_abort_transaction(trans, root, ret); |
239 | return ret; | 239 | return ret; |
240 | } | 240 | } |
@@ -242,7 +242,6 @@ int btrfs_truncate_free_space_cache(struct btrfs_root *root, | |||
242 | ret = btrfs_update_inode(trans, root, inode); | 242 | ret = btrfs_update_inode(trans, root, inode); |
243 | if (ret) | 243 | if (ret) |
244 | btrfs_abort_transaction(trans, root, ret); | 244 | btrfs_abort_transaction(trans, root, ret); |
245 | trans->block_rsv = rsv; | ||
246 | 245 | ||
247 | return ret; | 246 | return ret; |
248 | } | 247 | } |
diff --git a/fs/btrfs/free-space-cache.h b/fs/btrfs/free-space-cache.h index 4dc17d8809c7..8b7f19f44961 100644 --- a/fs/btrfs/free-space-cache.h +++ b/fs/btrfs/free-space-cache.h | |||
@@ -54,6 +54,8 @@ int create_free_space_inode(struct btrfs_root *root, | |||
54 | struct btrfs_block_group_cache *block_group, | 54 | struct btrfs_block_group_cache *block_group, |
55 | struct btrfs_path *path); | 55 | struct btrfs_path *path); |
56 | 56 | ||
57 | int btrfs_check_trunc_cache_free_space(struct btrfs_root *root, | ||
58 | struct btrfs_block_rsv *rsv); | ||
57 | int btrfs_truncate_free_space_cache(struct btrfs_root *root, | 59 | int btrfs_truncate_free_space_cache(struct btrfs_root *root, |
58 | struct btrfs_trans_handle *trans, | 60 | struct btrfs_trans_handle *trans, |
59 | struct btrfs_path *path, | 61 | struct btrfs_path *path, |
diff --git a/fs/btrfs/inode-map.c b/fs/btrfs/inode-map.c index 9818d4a3f829..2c66ddbbe670 100644 --- a/fs/btrfs/inode-map.c +++ b/fs/btrfs/inode-map.c | |||
@@ -429,11 +429,12 @@ int btrfs_save_ino_cache(struct btrfs_root *root, | |||
429 | num_bytes = trans->bytes_reserved; | 429 | num_bytes = trans->bytes_reserved; |
430 | /* | 430 | /* |
431 | * 1 item for inode item insertion if need | 431 | * 1 item for inode item insertion if need |
432 | * 3 items for inode item update (in the worst case) | 432 | * 4 items for inode item update (in the worst case) |
433 | * 1 items for slack space if we need do truncation | ||
433 | * 1 item for free space object | 434 | * 1 item for free space object |
434 | * 3 items for pre-allocation | 435 | * 3 items for pre-allocation |
435 | */ | 436 | */ |
436 | trans->bytes_reserved = btrfs_calc_trans_metadata_size(root, 8); | 437 | trans->bytes_reserved = btrfs_calc_trans_metadata_size(root, 10); |
437 | ret = btrfs_block_rsv_add(root, trans->block_rsv, | 438 | ret = btrfs_block_rsv_add(root, trans->block_rsv, |
438 | trans->bytes_reserved, | 439 | trans->bytes_reserved, |
439 | BTRFS_RESERVE_NO_FLUSH); | 440 | BTRFS_RESERVE_NO_FLUSH); |
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index 5c5b8bb44ee5..395b82031a42 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c | |||
@@ -3350,6 +3350,11 @@ static int delete_block_group_cache(struct btrfs_fs_info *fs_info, | |||
3350 | } | 3350 | } |
3351 | 3351 | ||
3352 | truncate: | 3352 | truncate: |
3353 | ret = btrfs_check_trunc_cache_free_space(root, | ||
3354 | &fs_info->global_block_rsv); | ||
3355 | if (ret) | ||
3356 | goto out; | ||
3357 | |||
3353 | path = btrfs_alloc_path(); | 3358 | path = btrfs_alloc_path(); |
3354 | if (!path) { | 3359 | if (!path) { |
3355 | ret = -ENOMEM; | 3360 | ret = -ENOMEM; |