diff options
Diffstat (limited to 'fs/btrfs/transaction.c')
| -rw-r--r-- | fs/btrfs/transaction.c | 56 | 
1 files changed, 35 insertions, 21 deletions
| diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 2dbf1c1f56ee..cdbb5022da52 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
| @@ -40,6 +40,12 @@ static noinline void put_transaction(struct btrfs_transaction *transaction) | |||
| 40 | } | 40 | } | 
| 41 | } | 41 | } | 
| 42 | 42 | ||
| 43 | static noinline void switch_commit_root(struct btrfs_root *root) | ||
| 44 | { | ||
| 45 | free_extent_buffer(root->commit_root); | ||
| 46 | root->commit_root = btrfs_root_node(root); | ||
| 47 | } | ||
| 48 | |||
| 43 | /* | 49 | /* | 
| 44 | * either allocate a new transaction or hop into the existing one | 50 | * either allocate a new transaction or hop into the existing one | 
| 45 | */ | 51 | */ | 
| @@ -444,9 +450,6 @@ static int update_cowonly_root(struct btrfs_trans_handle *trans, | |||
| 444 | 450 | ||
| 445 | btrfs_write_dirty_block_groups(trans, root); | 451 | btrfs_write_dirty_block_groups(trans, root); | 
| 446 | 452 | ||
| 447 | ret = btrfs_run_delayed_refs(trans, root, (unsigned long)-1); | ||
| 448 | BUG_ON(ret); | ||
| 449 | |||
| 450 | while (1) { | 453 | while (1) { | 
| 451 | old_root_bytenr = btrfs_root_bytenr(&root->root_item); | 454 | old_root_bytenr = btrfs_root_bytenr(&root->root_item); | 
| 452 | if (old_root_bytenr == root->node->start) | 455 | if (old_root_bytenr == root->node->start) | 
| @@ -457,13 +460,14 @@ static int update_cowonly_root(struct btrfs_trans_handle *trans, | |||
| 457 | &root->root_key, | 460 | &root->root_key, | 
| 458 | &root->root_item); | 461 | &root->root_item); | 
| 459 | BUG_ON(ret); | 462 | BUG_ON(ret); | 
| 460 | btrfs_write_dirty_block_groups(trans, root); | ||
| 461 | 463 | ||
| 462 | ret = btrfs_run_delayed_refs(trans, root, (unsigned long)-1); | 464 | ret = btrfs_write_dirty_block_groups(trans, root); | 
| 463 | BUG_ON(ret); | 465 | BUG_ON(ret); | 
| 464 | } | 466 | } | 
| 465 | free_extent_buffer(root->commit_root); | 467 | |
| 466 | root->commit_root = btrfs_root_node(root); | 468 | if (root != root->fs_info->extent_root) | 
| 469 | switch_commit_root(root); | ||
| 470 | |||
| 467 | return 0; | 471 | return 0; | 
| 468 | } | 472 | } | 
| 469 | 473 | ||
| @@ -495,10 +499,12 @@ static noinline int commit_cowonly_roots(struct btrfs_trans_handle *trans, | |||
| 495 | root = list_entry(next, struct btrfs_root, dirty_list); | 499 | root = list_entry(next, struct btrfs_root, dirty_list); | 
| 496 | 500 | ||
| 497 | update_cowonly_root(trans, root); | 501 | update_cowonly_root(trans, root); | 
| 498 | |||
| 499 | ret = btrfs_run_delayed_refs(trans, root, (unsigned long)-1); | ||
| 500 | BUG_ON(ret); | ||
| 501 | } | 502 | } | 
| 503 | |||
| 504 | down_write(&fs_info->extent_commit_sem); | ||
| 505 | switch_commit_root(fs_info->extent_root); | ||
| 506 | up_write(&fs_info->extent_commit_sem); | ||
| 507 | |||
| 502 | return 0; | 508 | return 0; | 
| 503 | } | 509 | } | 
| 504 | 510 | ||
| @@ -544,8 +550,7 @@ static noinline int commit_fs_roots(struct btrfs_trans_handle *trans, | |||
| 544 | btrfs_update_reloc_root(trans, root); | 550 | btrfs_update_reloc_root(trans, root); | 
| 545 | 551 | ||
| 546 | if (root->commit_root != root->node) { | 552 | if (root->commit_root != root->node) { | 
| 547 | free_extent_buffer(root->commit_root); | 553 | switch_commit_root(root); | 
| 548 | root->commit_root = btrfs_root_node(root); | ||
| 549 | btrfs_set_root_node(&root->root_item, | 554 | btrfs_set_root_node(&root->root_item, | 
| 550 | root->node); | 555 | root->node); | 
| 551 | } | 556 | } | 
| @@ -852,6 +857,16 @@ static void update_super_roots(struct btrfs_root *root) | |||
| 852 | super->root_level = root_item->level; | 857 | super->root_level = root_item->level; | 
| 853 | } | 858 | } | 
| 854 | 859 | ||
| 860 | int btrfs_transaction_in_commit(struct btrfs_fs_info *info) | ||
| 861 | { | ||
| 862 | int ret = 0; | ||
| 863 | spin_lock(&info->new_trans_lock); | ||
| 864 | if (info->running_transaction) | ||
| 865 | ret = info->running_transaction->in_commit; | ||
| 866 | spin_unlock(&info->new_trans_lock); | ||
| 867 | return ret; | ||
| 868 | } | ||
| 869 | |||
| 855 | int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | 870 | int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | 
| 856 | struct btrfs_root *root) | 871 | struct btrfs_root *root) | 
| 857 | { | 872 | { | 
| @@ -943,9 +958,11 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
| 943 | 958 | ||
| 944 | mutex_unlock(&root->fs_info->trans_mutex); | 959 | mutex_unlock(&root->fs_info->trans_mutex); | 
| 945 | 960 | ||
| 946 | if (flush_on_commit || snap_pending) { | 961 | if (flush_on_commit) { | 
| 947 | if (flush_on_commit) | 962 | btrfs_start_delalloc_inodes(root); | 
| 948 | btrfs_start_delalloc_inodes(root); | 963 | ret = btrfs_wait_ordered_extents(root, 0); | 
| 964 | BUG_ON(ret); | ||
| 965 | } else if (snap_pending) { | ||
| 949 | ret = btrfs_wait_ordered_extents(root, 1); | 966 | ret = btrfs_wait_ordered_extents(root, 1); | 
| 950 | BUG_ON(ret); | 967 | BUG_ON(ret); | 
| 951 | } | 968 | } | 
| @@ -1009,15 +1026,11 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
| 1009 | 1026 | ||
| 1010 | btrfs_set_root_node(&root->fs_info->tree_root->root_item, | 1027 | btrfs_set_root_node(&root->fs_info->tree_root->root_item, | 
| 1011 | root->fs_info->tree_root->node); | 1028 | root->fs_info->tree_root->node); | 
| 1012 | free_extent_buffer(root->fs_info->tree_root->commit_root); | 1029 | switch_commit_root(root->fs_info->tree_root); | 
| 1013 | root->fs_info->tree_root->commit_root = | ||
| 1014 | btrfs_root_node(root->fs_info->tree_root); | ||
| 1015 | 1030 | ||
| 1016 | btrfs_set_root_node(&root->fs_info->chunk_root->root_item, | 1031 | btrfs_set_root_node(&root->fs_info->chunk_root->root_item, | 
| 1017 | root->fs_info->chunk_root->node); | 1032 | root->fs_info->chunk_root->node); | 
| 1018 | free_extent_buffer(root->fs_info->chunk_root->commit_root); | 1033 | switch_commit_root(root->fs_info->chunk_root); | 
| 1019 | root->fs_info->chunk_root->commit_root = | ||
| 1020 | btrfs_root_node(root->fs_info->chunk_root); | ||
| 1021 | 1034 | ||
| 1022 | update_super_roots(root); | 1035 | update_super_roots(root); | 
| 1023 | 1036 | ||
| @@ -1057,6 +1070,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
| 1057 | cur_trans->commit_done = 1; | 1070 | cur_trans->commit_done = 1; | 
| 1058 | 1071 | ||
| 1059 | root->fs_info->last_trans_committed = cur_trans->transid; | 1072 | root->fs_info->last_trans_committed = cur_trans->transid; | 
| 1073 | |||
| 1060 | wake_up(&cur_trans->commit_wait); | 1074 | wake_up(&cur_trans->commit_wait); | 
| 1061 | 1075 | ||
| 1062 | put_transaction(cur_trans); | 1076 | put_transaction(cur_trans); | 
