diff options
-rw-r--r-- | fs/btrfs/free-space-cache.c | 2 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 45 | ||||
-rw-r--r-- | fs/btrfs/transaction.c | 2 | ||||
-rw-r--r-- | fs/btrfs/tree-log.c | 8 |
4 files changed, 52 insertions, 5 deletions
diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index 764528a4f6fd..c51482031edf 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c | |||
@@ -235,6 +235,8 @@ int btrfs_truncate_free_space_cache(struct btrfs_root *root, | |||
235 | /* | 235 | /* |
236 | * We don't need an orphan item because truncating the free space cache | 236 | * We don't need an orphan item because truncating the free space cache |
237 | * will never be split across transactions. | 237 | * will never be split across transactions. |
238 | * We don't need to check for -EAGAIN because we're a free space | ||
239 | * cache inode | ||
238 | */ | 240 | */ |
239 | ret = btrfs_truncate_inode_items(trans, root, inode, | 241 | ret = btrfs_truncate_inode_items(trans, root, inode, |
240 | 0, BTRFS_EXTENT_DATA_KEY); | 242 | 0, BTRFS_EXTENT_DATA_KEY); |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 97bc1ffc9c7b..e3fe137fb826 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -4197,10 +4197,20 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans, | |||
4197 | int extent_type = -1; | 4197 | int extent_type = -1; |
4198 | int ret; | 4198 | int ret; |
4199 | int err = 0; | 4199 | int err = 0; |
4200 | int be_nice = 0; | ||
4200 | u64 ino = btrfs_ino(inode); | 4201 | u64 ino = btrfs_ino(inode); |
4202 | u64 bytes_deleted = 0; | ||
4201 | 4203 | ||
4202 | BUG_ON(new_size > 0 && min_type != BTRFS_EXTENT_DATA_KEY); | 4204 | BUG_ON(new_size > 0 && min_type != BTRFS_EXTENT_DATA_KEY); |
4203 | 4205 | ||
4206 | /* | ||
4207 | * for non-free space inodes and ref cows, we want to back off from | ||
4208 | * time to time | ||
4209 | */ | ||
4210 | if (!btrfs_is_free_space_inode(inode) && | ||
4211 | test_bit(BTRFS_ROOT_REF_COWS, &root->state)) | ||
4212 | be_nice = 1; | ||
4213 | |||
4204 | path = btrfs_alloc_path(); | 4214 | path = btrfs_alloc_path(); |
4205 | if (!path) | 4215 | if (!path) |
4206 | return -ENOMEM; | 4216 | return -ENOMEM; |
@@ -4230,6 +4240,19 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans, | |||
4230 | key.type = (u8)-1; | 4240 | key.type = (u8)-1; |
4231 | 4241 | ||
4232 | search_again: | 4242 | search_again: |
4243 | /* | ||
4244 | * with a 16K leaf size and 128MB extents, you can actually queue | ||
4245 | * up a huge file in a single leaf. Most of the time that | ||
4246 | * bytes_deleted is > 0, it will be huge by the time we get here | ||
4247 | */ | ||
4248 | if (be_nice && bytes_deleted > 32 * 1024 * 1024) { | ||
4249 | if (btrfs_should_end_transaction(trans, root)) { | ||
4250 | err = -EAGAIN; | ||
4251 | goto error; | ||
4252 | } | ||
4253 | } | ||
4254 | |||
4255 | |||
4233 | path->leave_spinning = 1; | 4256 | path->leave_spinning = 1; |
4234 | ret = btrfs_search_slot(trans, root, &key, path, -1, 1); | 4257 | ret = btrfs_search_slot(trans, root, &key, path, -1, 1); |
4235 | if (ret < 0) { | 4258 | if (ret < 0) { |
@@ -4376,11 +4399,18 @@ delete: | |||
4376 | (test_bit(BTRFS_ROOT_REF_COWS, &root->state) || | 4399 | (test_bit(BTRFS_ROOT_REF_COWS, &root->state) || |
4377 | root == root->fs_info->tree_root)) { | 4400 | root == root->fs_info->tree_root)) { |
4378 | btrfs_set_path_blocking(path); | 4401 | btrfs_set_path_blocking(path); |
4402 | bytes_deleted += extent_num_bytes; | ||
4379 | ret = btrfs_free_extent(trans, root, extent_start, | 4403 | ret = btrfs_free_extent(trans, root, extent_start, |
4380 | extent_num_bytes, 0, | 4404 | extent_num_bytes, 0, |
4381 | btrfs_header_owner(leaf), | 4405 | btrfs_header_owner(leaf), |
4382 | ino, extent_offset, 0); | 4406 | ino, extent_offset, 0); |
4383 | BUG_ON(ret); | 4407 | BUG_ON(ret); |
4408 | if (be_nice && pending_del_nr && | ||
4409 | (pending_del_nr % 16 == 0) && | ||
4410 | bytes_deleted > 1024 * 1024) { | ||
4411 | btrfs_async_run_delayed_refs(root, | ||
4412 | trans->delayed_ref_updates * 2, 0); | ||
4413 | } | ||
4384 | } | 4414 | } |
4385 | 4415 | ||
4386 | if (found_type == BTRFS_INODE_ITEM_KEY) | 4416 | if (found_type == BTRFS_INODE_ITEM_KEY) |
@@ -4416,7 +4446,18 @@ error: | |||
4416 | if (last_size != (u64)-1 && | 4446 | if (last_size != (u64)-1 && |
4417 | root->root_key.objectid != BTRFS_TREE_LOG_OBJECTID) | 4447 | root->root_key.objectid != BTRFS_TREE_LOG_OBJECTID) |
4418 | btrfs_ordered_update_i_size(inode, last_size, NULL); | 4448 | btrfs_ordered_update_i_size(inode, last_size, NULL); |
4449 | |||
4419 | btrfs_free_path(path); | 4450 | btrfs_free_path(path); |
4451 | |||
4452 | if (be_nice && bytes_deleted > 32 * 1024 * 1024) { | ||
4453 | unsigned long updates = trans->delayed_ref_updates; | ||
4454 | if (updates) { | ||
4455 | trans->delayed_ref_updates = 0; | ||
4456 | ret = btrfs_run_delayed_refs(trans, root, updates * 2); | ||
4457 | if (ret && !err) | ||
4458 | err = ret; | ||
4459 | } | ||
4460 | } | ||
4420 | return err; | 4461 | return err; |
4421 | } | 4462 | } |
4422 | 4463 | ||
@@ -5013,7 +5054,7 @@ void btrfs_evict_inode(struct inode *inode) | |||
5013 | trans->block_rsv = rsv; | 5054 | trans->block_rsv = rsv; |
5014 | 5055 | ||
5015 | ret = btrfs_truncate_inode_items(trans, root, inode, 0, 0); | 5056 | ret = btrfs_truncate_inode_items(trans, root, inode, 0, 0); |
5016 | if (ret != -ENOSPC) | 5057 | if (ret != -ENOSPC && ret != -EAGAIN) |
5017 | break; | 5058 | break; |
5018 | 5059 | ||
5019 | trans->block_rsv = &root->fs_info->trans_block_rsv; | 5060 | trans->block_rsv = &root->fs_info->trans_block_rsv; |
@@ -8582,7 +8623,7 @@ static int btrfs_truncate(struct inode *inode) | |||
8582 | ret = btrfs_truncate_inode_items(trans, root, inode, | 8623 | ret = btrfs_truncate_inode_items(trans, root, inode, |
8583 | inode->i_size, | 8624 | inode->i_size, |
8584 | BTRFS_EXTENT_DATA_KEY); | 8625 | BTRFS_EXTENT_DATA_KEY); |
8585 | if (ret != -ENOSPC) { | 8626 | if (ret != -ENOSPC && ret != -EAGAIN) { |
8586 | err = ret; | 8627 | err = ret; |
8587 | break; | 8628 | break; |
8588 | } | 8629 | } |
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 91c303ac40b6..ba831ee41891 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
@@ -718,7 +718,7 @@ int btrfs_should_end_transaction(struct btrfs_trans_handle *trans, | |||
718 | updates = trans->delayed_ref_updates; | 718 | updates = trans->delayed_ref_updates; |
719 | trans->delayed_ref_updates = 0; | 719 | trans->delayed_ref_updates = 0; |
720 | if (updates) { | 720 | if (updates) { |
721 | err = btrfs_run_delayed_refs(trans, root, updates); | 721 | err = btrfs_run_delayed_refs(trans, root, updates * 2); |
722 | if (err) /* Error code will also eval true */ | 722 | if (err) /* Error code will also eval true */ |
723 | return err; | 723 | return err; |
724 | } | 724 | } |
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index 016c90fc85db..a089b5944efc 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c | |||
@@ -4251,8 +4251,12 @@ static int btrfs_log_inode(struct btrfs_trans_handle *trans, | |||
4251 | &BTRFS_I(inode)->runtime_flags); | 4251 | &BTRFS_I(inode)->runtime_flags); |
4252 | clear_bit(BTRFS_INODE_COPY_EVERYTHING, | 4252 | clear_bit(BTRFS_INODE_COPY_EVERYTHING, |
4253 | &BTRFS_I(inode)->runtime_flags); | 4253 | &BTRFS_I(inode)->runtime_flags); |
4254 | ret = btrfs_truncate_inode_items(trans, log, | 4254 | while(1) { |
4255 | inode, 0, 0); | 4255 | ret = btrfs_truncate_inode_items(trans, |
4256 | log, inode, 0, 0); | ||
4257 | if (ret != -EAGAIN) | ||
4258 | break; | ||
4259 | } | ||
4256 | } | 4260 | } |
4257 | } else if (test_and_clear_bit(BTRFS_INODE_COPY_EVERYTHING, | 4261 | } else if (test_and_clear_bit(BTRFS_INODE_COPY_EVERYTHING, |
4258 | &BTRFS_I(inode)->runtime_flags) || | 4262 | &BTRFS_I(inode)->runtime_flags) || |