diff options
Diffstat (limited to 'fs/btrfs/transaction.c')
-rw-r--r-- | fs/btrfs/transaction.c | 62 |
1 files changed, 55 insertions, 7 deletions
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 903edab3659a..01c9620bb001 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
@@ -192,6 +192,7 @@ static struct btrfs_trans_handle *start_transaction(struct btrfs_root *root, | |||
192 | h->alloc_exclude_nr = 0; | 192 | h->alloc_exclude_nr = 0; |
193 | h->alloc_exclude_start = 0; | 193 | h->alloc_exclude_start = 0; |
194 | h->delayed_ref_updates = 0; | 194 | h->delayed_ref_updates = 0; |
195 | |||
195 | root->fs_info->running_transaction->use_count++; | 196 | root->fs_info->running_transaction->use_count++; |
196 | mutex_unlock(&root->fs_info->trans_mutex); | 197 | mutex_unlock(&root->fs_info->trans_mutex); |
197 | return h; | 198 | return h; |
@@ -281,7 +282,6 @@ void btrfs_throttle(struct btrfs_root *root) | |||
281 | if (!root->fs_info->open_ioctl_trans) | 282 | if (!root->fs_info->open_ioctl_trans) |
282 | wait_current_trans(root); | 283 | wait_current_trans(root); |
283 | mutex_unlock(&root->fs_info->trans_mutex); | 284 | mutex_unlock(&root->fs_info->trans_mutex); |
284 | |||
285 | throttle_on_drops(root); | 285 | throttle_on_drops(root); |
286 | } | 286 | } |
287 | 287 | ||
@@ -298,6 +298,13 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans, | |||
298 | if (cur && | 298 | if (cur && |
299 | trans->transaction->delayed_refs.num_heads_ready > 64) { | 299 | trans->transaction->delayed_refs.num_heads_ready > 64) { |
300 | trans->delayed_ref_updates = 0; | 300 | trans->delayed_ref_updates = 0; |
301 | |||
302 | /* | ||
303 | * do a full flush if the transaction is trying | ||
304 | * to close | ||
305 | */ | ||
306 | if (trans->transaction->delayed_refs.flushing) | ||
307 | cur = 0; | ||
301 | btrfs_run_delayed_refs(trans, root, cur); | 308 | btrfs_run_delayed_refs(trans, root, cur); |
302 | } else { | 309 | } else { |
303 | break; | 310 | break; |
@@ -666,6 +673,31 @@ int btrfs_defrag_root(struct btrfs_root *root, int cacheonly) | |||
666 | } | 673 | } |
667 | 674 | ||
668 | /* | 675 | /* |
676 | * when dropping snapshots, we generate a ton of delayed refs, and it makes | ||
677 | * sense not to join the transaction while it is trying to flush the current | ||
678 | * queue of delayed refs out. | ||
679 | * | ||
680 | * This is used by the drop snapshot code only | ||
681 | */ | ||
682 | static noinline int wait_transaction_pre_flush(struct btrfs_fs_info *info) | ||
683 | { | ||
684 | DEFINE_WAIT(wait); | ||
685 | |||
686 | mutex_lock(&info->trans_mutex); | ||
687 | while (info->running_transaction && | ||
688 | info->running_transaction->delayed_refs.flushing) { | ||
689 | prepare_to_wait(&info->transaction_wait, &wait, | ||
690 | TASK_UNINTERRUPTIBLE); | ||
691 | mutex_unlock(&info->trans_mutex); | ||
692 | schedule(); | ||
693 | mutex_lock(&info->trans_mutex); | ||
694 | finish_wait(&info->transaction_wait, &wait); | ||
695 | } | ||
696 | mutex_unlock(&info->trans_mutex); | ||
697 | return 0; | ||
698 | } | ||
699 | |||
700 | /* | ||
669 | * Given a list of roots that need to be deleted, call btrfs_drop_snapshot on | 701 | * Given a list of roots that need to be deleted, call btrfs_drop_snapshot on |
670 | * all of them | 702 | * all of them |
671 | */ | 703 | */ |
@@ -692,7 +724,22 @@ static noinline int drop_dirty_roots(struct btrfs_root *tree_root, | |||
692 | atomic_inc(&root->fs_info->throttles); | 724 | atomic_inc(&root->fs_info->throttles); |
693 | 725 | ||
694 | while (1) { | 726 | while (1) { |
727 | /* | ||
728 | * we don't want to jump in and create a bunch of | ||
729 | * delayed refs if the transaction is starting to close | ||
730 | */ | ||
731 | wait_transaction_pre_flush(tree_root->fs_info); | ||
695 | trans = btrfs_start_transaction(tree_root, 1); | 732 | trans = btrfs_start_transaction(tree_root, 1); |
733 | |||
734 | /* | ||
735 | * we've joined a transaction, make sure it isn't | ||
736 | * closing right now | ||
737 | */ | ||
738 | if (trans->transaction->delayed_refs.flushing) { | ||
739 | btrfs_end_transaction(trans, tree_root); | ||
740 | continue; | ||
741 | } | ||
742 | |||
696 | mutex_lock(&root->fs_info->drop_mutex); | 743 | mutex_lock(&root->fs_info->drop_mutex); |
697 | ret = btrfs_drop_snapshot(trans, dirty->root); | 744 | ret = btrfs_drop_snapshot(trans, dirty->root); |
698 | if (ret != -EAGAIN) | 745 | if (ret != -EAGAIN) |
@@ -932,20 +979,20 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
932 | ret = btrfs_run_delayed_refs(trans, root, 0); | 979 | ret = btrfs_run_delayed_refs(trans, root, 0); |
933 | BUG_ON(ret); | 980 | BUG_ON(ret); |
934 | 981 | ||
982 | cur_trans = trans->transaction; | ||
935 | /* | 983 | /* |
936 | * set the flushing flag so procs in this transaction have to | 984 | * set the flushing flag so procs in this transaction have to |
937 | * start sending their work down. | 985 | * start sending their work down. |
938 | */ | 986 | */ |
939 | trans->transaction->delayed_refs.flushing = 1; | 987 | cur_trans->delayed_refs.flushing = 1; |
940 | 988 | ||
941 | ret = btrfs_run_delayed_refs(trans, root, 0); | 989 | ret = btrfs_run_delayed_refs(trans, root, 0); |
942 | BUG_ON(ret); | 990 | BUG_ON(ret); |
943 | 991 | ||
944 | INIT_LIST_HEAD(&dirty_fs_roots); | ||
945 | mutex_lock(&root->fs_info->trans_mutex); | 992 | mutex_lock(&root->fs_info->trans_mutex); |
946 | if (trans->transaction->in_commit) { | 993 | INIT_LIST_HEAD(&dirty_fs_roots); |
947 | cur_trans = trans->transaction; | 994 | if (cur_trans->in_commit) { |
948 | trans->transaction->use_count++; | 995 | cur_trans->use_count++; |
949 | mutex_unlock(&root->fs_info->trans_mutex); | 996 | mutex_unlock(&root->fs_info->trans_mutex); |
950 | btrfs_end_transaction(trans, root); | 997 | btrfs_end_transaction(trans, root); |
951 | 998 | ||
@@ -968,7 +1015,6 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
968 | 1015 | ||
969 | trans->transaction->in_commit = 1; | 1016 | trans->transaction->in_commit = 1; |
970 | trans->transaction->blocked = 1; | 1017 | trans->transaction->blocked = 1; |
971 | cur_trans = trans->transaction; | ||
972 | if (cur_trans->list.prev != &root->fs_info->trans_list) { | 1018 | if (cur_trans->list.prev != &root->fs_info->trans_list) { |
973 | prev_trans = list_entry(cur_trans->list.prev, | 1019 | prev_trans = list_entry(cur_trans->list.prev, |
974 | struct btrfs_transaction, list); | 1020 | struct btrfs_transaction, list); |
@@ -1081,6 +1127,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
1081 | btrfs_copy_pinned(root, pinned_copy); | 1127 | btrfs_copy_pinned(root, pinned_copy); |
1082 | 1128 | ||
1083 | trans->transaction->blocked = 0; | 1129 | trans->transaction->blocked = 0; |
1130 | |||
1084 | wake_up(&root->fs_info->transaction_throttle); | 1131 | wake_up(&root->fs_info->transaction_throttle); |
1085 | wake_up(&root->fs_info->transaction_wait); | 1132 | wake_up(&root->fs_info->transaction_wait); |
1086 | 1133 | ||
@@ -1107,6 +1154,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
1107 | mutex_lock(&root->fs_info->trans_mutex); | 1154 | mutex_lock(&root->fs_info->trans_mutex); |
1108 | 1155 | ||
1109 | cur_trans->commit_done = 1; | 1156 | cur_trans->commit_done = 1; |
1157 | |||
1110 | root->fs_info->last_trans_committed = cur_trans->transid; | 1158 | root->fs_info->last_trans_committed = cur_trans->transid; |
1111 | wake_up(&cur_trans->commit_wait); | 1159 | wake_up(&cur_trans->commit_wait); |
1112 | 1160 | ||