aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/transaction.c
diff options
context:
space:
mode:
authorJosef Bacik <josef@redhat.com>2009-07-13 21:29:25 -0400
committerChris Mason <chris.mason@oracle.com>2009-07-24 09:23:39 -0400
commit817d52f8dba26d0295c26035531c30ce5f1e3c3e (patch)
tree5230153e86323de48e7e1440352d1b74d2d9961d /fs/btrfs/transaction.c
parent963030817060e4f109be1993b9ae8f81dbf5e11a (diff)
Btrfs: async block group caching
This patch moves the caching of the block group off to a kthread in order to allow people to allocate sooner. Instead of blocking up behind the caching mutex, we instead kick of the caching kthread, and then attempt to make an allocation. If we cannot, we wait on the block groups caching waitqueue, which the caching kthread will wake the waiting threads up everytime it finds 2 meg worth of space, and then again when its finished caching. This is how I tested the speedup from this mkfs the disk mount the disk fill the disk up with fs_mark unmount the disk mount the disk time touch /mnt/foo Without my changes this took 11 seconds on my box, with these changes it now takes 1 second. Another change thats been put in place is we lock the super mirror's in the pinned extent map in order to keep us from adding that stuff as free space when caching the block group. This doesn't really change anything else as far as the pinned extent map is concerned, since for actual pinned extents we use EXTENT_DIRTY, but it does mean that when we unmount we have to go in and unlock those extents to keep from leaking memory. I've also added a check where when we are reading block groups from disk, if the amount of space used == the size of the block group, we go ahead and mark the block group as cached. This drastically reduces the amount of time it takes to cache the block groups. Using the same test as above, except doing a dd to a file and then unmounting, it used to take 33 seconds to umount, now it takes 3 seconds. This version uses the commit_root in the caching kthread, and then keeps track of how many async caching threads are running at any given time so if one of the async threads is still running as we cross transactions we can wait until its finished before handling the pinned extents. Thank you, Signed-off-by: Josef Bacik <jbacik@redhat.com> Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/transaction.c')
-rw-r--r--fs/btrfs/transaction.c23
1 files changed, 13 insertions, 10 deletions
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index 81f7124c3051..32454d1c566f 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -40,6 +40,14 @@ static noinline void put_transaction(struct btrfs_transaction *transaction)
40 } 40 }
41} 41}
42 42
43static noinline void switch_commit_root(struct btrfs_root *root)
44{
45 down_write(&root->commit_root_sem);
46 free_extent_buffer(root->commit_root);
47 root->commit_root = btrfs_root_node(root);
48 up_write(&root->commit_root_sem);
49}
50
43/* 51/*
44 * either allocate a new transaction or hop into the existing one 52 * either allocate a new transaction or hop into the existing one
45 */ 53 */
@@ -458,8 +466,7 @@ static int update_cowonly_root(struct btrfs_trans_handle *trans,
458 ret = btrfs_write_dirty_block_groups(trans, root); 466 ret = btrfs_write_dirty_block_groups(trans, root);
459 BUG_ON(ret); 467 BUG_ON(ret);
460 } 468 }
461 free_extent_buffer(root->commit_root); 469 switch_commit_root(root);
462 root->commit_root = btrfs_root_node(root);
463 return 0; 470 return 0;
464} 471}
465 472
@@ -537,8 +544,7 @@ static noinline int commit_fs_roots(struct btrfs_trans_handle *trans,
537 btrfs_update_reloc_root(trans, root); 544 btrfs_update_reloc_root(trans, root);
538 545
539 if (root->commit_root != root->node) { 546 if (root->commit_root != root->node) {
540 free_extent_buffer(root->commit_root); 547 switch_commit_root(root);
541 root->commit_root = btrfs_root_node(root);
542 btrfs_set_root_node(&root->root_item, 548 btrfs_set_root_node(&root->root_item,
543 root->node); 549 root->node);
544 } 550 }
@@ -1002,15 +1008,11 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
1002 1008
1003 btrfs_set_root_node(&root->fs_info->tree_root->root_item, 1009 btrfs_set_root_node(&root->fs_info->tree_root->root_item,
1004 root->fs_info->tree_root->node); 1010 root->fs_info->tree_root->node);
1005 free_extent_buffer(root->fs_info->tree_root->commit_root); 1011 switch_commit_root(root->fs_info->tree_root);
1006 root->fs_info->tree_root->commit_root =
1007 btrfs_root_node(root->fs_info->tree_root);
1008 1012
1009 btrfs_set_root_node(&root->fs_info->chunk_root->root_item, 1013 btrfs_set_root_node(&root->fs_info->chunk_root->root_item,
1010 root->fs_info->chunk_root->node); 1014 root->fs_info->chunk_root->node);
1011 free_extent_buffer(root->fs_info->chunk_root->commit_root); 1015 switch_commit_root(root->fs_info->chunk_root);
1012 root->fs_info->chunk_root->commit_root =
1013 btrfs_root_node(root->fs_info->chunk_root);
1014 1016
1015 update_super_roots(root); 1017 update_super_roots(root);
1016 1018
@@ -1050,6 +1052,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
1050 cur_trans->commit_done = 1; 1052 cur_trans->commit_done = 1;
1051 1053
1052 root->fs_info->last_trans_committed = cur_trans->transid; 1054 root->fs_info->last_trans_committed = cur_trans->transid;
1055
1053 wake_up(&cur_trans->commit_wait); 1056 wake_up(&cur_trans->commit_wait);
1054 1057
1055 put_transaction(cur_trans); 1058 put_transaction(cur_trans);