aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2012-01-06 15:23:57 -0500
committerChris Mason <chris.mason@oracle.com>2012-01-06 15:23:57 -0500
commit203bf287cb01a5dc26c20bd3737cecf3aeba1d48 (patch)
treef9ce9d7c82360bd6059b5ef16166cf79d16b1380
parentc1111b1fcee6359922ad8e5f6d72ed43815ad8f9 (diff)
Btrfs: run chunk allocations while we do delayed refs
Btrfs tries to batch extent allocation tree changes to improve performance and reduce metadata trashing. But it doesn't allocate new metadata chunks while it is doing allocations for the extent allocation tree. This commit changes the delayed refence code to do chunk allocations if we're getting low on room. It prevents crashes and improves performance. Signed-off-by: Chris Mason <chris.mason@oracle.com>
-rw-r--r--fs/btrfs/extent-tree.c14
-rw-r--r--fs/btrfs/transaction.c9
2 files changed, 11 insertions, 12 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index f5fbe576d2ba..71549d11a09e 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -2267,9 +2267,7 @@ static noinline int run_clustered_refs(struct btrfs_trans_handle *trans,
2267 BUG_ON(ret); 2267 BUG_ON(ret);
2268 kfree(extent_op); 2268 kfree(extent_op);
2269 2269
2270 cond_resched(); 2270 goto next;
2271 spin_lock(&delayed_refs->lock);
2272 continue;
2273 } 2271 }
2274 2272
2275 list_del_init(&locked_ref->cluster); 2273 list_del_init(&locked_ref->cluster);
@@ -2289,7 +2287,11 @@ static noinline int run_clustered_refs(struct btrfs_trans_handle *trans,
2289 btrfs_put_delayed_ref(ref); 2287 btrfs_put_delayed_ref(ref);
2290 kfree(extent_op); 2288 kfree(extent_op);
2291 count++; 2289 count++;
2292 2290next:
2291 do_chunk_alloc(trans, root->fs_info->extent_root,
2292 2 * 1024 * 1024,
2293 btrfs_get_alloc_profile(root, 0),
2294 CHUNK_ALLOC_NO_FORCE);
2293 cond_resched(); 2295 cond_resched();
2294 spin_lock(&delayed_refs->lock); 2296 spin_lock(&delayed_refs->lock);
2295 } 2297 }
@@ -2317,6 +2319,10 @@ int btrfs_run_delayed_refs(struct btrfs_trans_handle *trans,
2317 if (root == root->fs_info->extent_root) 2319 if (root == root->fs_info->extent_root)
2318 root = root->fs_info->tree_root; 2320 root = root->fs_info->tree_root;
2319 2321
2322 do_chunk_alloc(trans, root->fs_info->extent_root,
2323 2 * 1024 * 1024, btrfs_get_alloc_profile(root, 0),
2324 CHUNK_ALLOC_NO_FORCE);
2325
2320 delayed_refs = &trans->transaction->delayed_refs; 2326 delayed_refs = &trans->transaction->delayed_refs;
2321 INIT_LIST_HEAD(&cluster); 2327 INIT_LIST_HEAD(&cluster);
2322again: 2328again:
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index 81376d94cd3c..360c2dfd1ee6 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -467,19 +467,12 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans,
467 467
468 btrfs_trans_release_metadata(trans, root); 468 btrfs_trans_release_metadata(trans, root);
469 trans->block_rsv = NULL; 469 trans->block_rsv = NULL;
470 while (count < 4) { 470 while (count < 2) {
471 unsigned long cur = trans->delayed_ref_updates; 471 unsigned long cur = trans->delayed_ref_updates;
472 trans->delayed_ref_updates = 0; 472 trans->delayed_ref_updates = 0;
473 if (cur && 473 if (cur &&
474 trans->transaction->delayed_refs.num_heads_ready > 64) { 474 trans->transaction->delayed_refs.num_heads_ready > 64) {
475 trans->delayed_ref_updates = 0; 475 trans->delayed_ref_updates = 0;
476
477 /*
478 * do a full flush if the transaction is trying
479 * to close
480 */
481 if (trans->transaction->delayed_refs.flushing)
482 cur = 0;
483 btrfs_run_delayed_refs(trans, root, cur); 476 btrfs_run_delayed_refs(trans, root, cur);
484 } else { 477 } else {
485 break; 478 break;