summaryrefslogtreecommitdiffstats
path: root/fs/btrfs/inode.c
diff options
context:
space:
mode:
authorChris Mason <clm@fb.com>2014-12-17 12:41:04 -0500
committerChris Mason <clm@fb.com>2015-04-10 17:00:14 -0400
commit28ed1345a50491d78e1454ad4005dc5d3557a69e (patch)
treebd620b07d9b964680dca517d7dd052f294c13a2c /fs/btrfs/inode.c
parent4a3d1caf8a2c16c55424a0768eade54ee0922341 (diff)
btrfs: actively run the delayed refs while deleting large files
When we are deleting large files with large extents, we are building up a huge set of delayed refs for processing. Truncate isn't checking often enough to see if we need to back off and process those, or let a commit proceed. The end result is long stalls after the rm, and very long commit times. During the commits, other processes back up waiting to start new transactions and we get into trouble. Signed-off-by: Chris Mason <clm@fb.com>
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r--fs/btrfs/inode.c45
1 files changed, 43 insertions, 2 deletions
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 }