summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/btrfs/free-space-cache.c2
-rw-r--r--fs/btrfs/inode.c45
-rw-r--r--fs/btrfs/transaction.c2
-rw-r--r--fs/btrfs/tree-log.c8
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
4232search_again: 4242search_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) ||