aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
authorMiao Xie <miaox@cn.fujitsu.com>2013-05-16 23:53:43 -0400
committerJosef Bacik <jbacik@fusionio.com>2013-06-14 11:29:51 -0400
commit4a9d8bdee368de78ace8b36da4eb2186afea162d (patch)
treed7a34e5414a25f24f48d4b9bb4284ef2ebe16313 /fs/btrfs
parent581227d0d2b8735f899182f50b3a05089d02fa24 (diff)
Btrfs: make the state of the transaction more readable
We used 3 variants to track the state of the transaction, it was complex and wasted the memory space. Besides that, it was hard to understand that which types of the transaction handles should be blocked in each transaction state, so the developers often made mistakes. This patch improved the above problem. In this patch, we define 6 states for the transaction, enum btrfs_trans_state { TRANS_STATE_RUNNING = 0, TRANS_STATE_BLOCKED = 1, TRANS_STATE_COMMIT_START = 2, TRANS_STATE_COMMIT_DOING = 3, TRANS_STATE_UNBLOCKED = 4, TRANS_STATE_COMPLETED = 5, TRANS_STATE_MAX = 6, } and just use 1 variant to track those state. In order to make the blocked handle types for each state more clear, we introduce a array: unsigned int btrfs_blocked_trans_types[TRANS_STATE_MAX] = { [TRANS_STATE_RUNNING] = 0U, [TRANS_STATE_BLOCKED] = (__TRANS_USERSPACE | __TRANS_START), [TRANS_STATE_COMMIT_START] = (__TRANS_USERSPACE | __TRANS_START | __TRANS_ATTACH), [TRANS_STATE_COMMIT_DOING] = (__TRANS_USERSPACE | __TRANS_START | __TRANS_ATTACH | __TRANS_JOIN), [TRANS_STATE_UNBLOCKED] = (__TRANS_USERSPACE | __TRANS_START | __TRANS_ATTACH | __TRANS_JOIN | __TRANS_JOIN_NOLOCK), [TRANS_STATE_COMPLETED] = (__TRANS_USERSPACE | __TRANS_START | __TRANS_ATTACH | __TRANS_JOIN | __TRANS_JOIN_NOLOCK), } it is very intuitionistic. Besides that, because we remove ->in_commit in transaction structure, so the lock ->commit_lock which was used to protect it is unnecessary, remove ->commit_lock. Signed-off-by: Miao Xie <miaox@cn.fujitsu.com> Signed-off-by: Josef Bacik <jbacik@fusionio.com>
Diffstat (limited to 'fs/btrfs')
-rw-r--r--fs/btrfs/ctree.h1
-rw-r--r--fs/btrfs/disk-io.c36
-rw-r--r--fs/btrfs/transaction.c157
-rw-r--r--fs/btrfs/transaction.h16
4 files changed, 116 insertions, 94 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 905f7c6c82f3..fd62aa856d1b 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -1496,7 +1496,6 @@ struct btrfs_fs_info {
1496 int closing; 1496 int closing;
1497 int log_root_recovering; 1497 int log_root_recovering;
1498 int enospc_unlink; 1498 int enospc_unlink;
1499 int trans_no_join;
1500 1499
1501 u64 total_pinned; 1500 u64 total_pinned;
1502 1501
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 885245f5acdc..b9eaa0f21144 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -1747,7 +1747,7 @@ static int transaction_kthread(void *arg)
1747 } 1747 }
1748 1748
1749 now = get_seconds(); 1749 now = get_seconds();
1750 if (!cur->blocked && 1750 if (cur->state < TRANS_STATE_BLOCKED &&
1751 (now < cur->start_time || now - cur->start_time < 30)) { 1751 (now < cur->start_time || now - cur->start_time < 30)) {
1752 spin_unlock(&root->fs_info->trans_lock); 1752 spin_unlock(&root->fs_info->trans_lock);
1753 delay = HZ * 5; 1753 delay = HZ * 5;
@@ -2186,7 +2186,6 @@ int open_ctree(struct super_block *sb,
2186 fs_info->max_inline = 8192 * 1024; 2186 fs_info->max_inline = 8192 * 1024;
2187 fs_info->metadata_ratio = 0; 2187 fs_info->metadata_ratio = 0;
2188 fs_info->defrag_inodes = RB_ROOT; 2188 fs_info->defrag_inodes = RB_ROOT;
2189 fs_info->trans_no_join = 0;
2190 fs_info->free_chunk_space = 0; 2189 fs_info->free_chunk_space = 0;
2191 fs_info->tree_mod_log = RB_ROOT; 2190 fs_info->tree_mod_log = RB_ROOT;
2192 2191
@@ -3958,19 +3957,14 @@ void btrfs_cleanup_one_transaction(struct btrfs_transaction *cur_trans,
3958 btrfs_block_rsv_release(root, &root->fs_info->trans_block_rsv, 3957 btrfs_block_rsv_release(root, &root->fs_info->trans_block_rsv,
3959 cur_trans->dirty_pages.dirty_bytes); 3958 cur_trans->dirty_pages.dirty_bytes);
3960 3959
3961 /* FIXME: cleanup wait for commit */ 3960 cur_trans->state = TRANS_STATE_COMMIT_START;
3962 cur_trans->in_commit = 1;
3963 cur_trans->blocked = 1;
3964 wake_up(&root->fs_info->transaction_blocked_wait); 3961 wake_up(&root->fs_info->transaction_blocked_wait);
3965 3962
3966 btrfs_evict_pending_snapshots(cur_trans); 3963 btrfs_evict_pending_snapshots(cur_trans);
3967 3964
3968 cur_trans->blocked = 0; 3965 cur_trans->state = TRANS_STATE_UNBLOCKED;
3969 wake_up(&root->fs_info->transaction_wait); 3966 wake_up(&root->fs_info->transaction_wait);
3970 3967
3971 cur_trans->commit_done = 1;
3972 wake_up(&cur_trans->commit_wait);
3973
3974 btrfs_destroy_delayed_inodes(root); 3968 btrfs_destroy_delayed_inodes(root);
3975 btrfs_assert_delayed_root_empty(root); 3969 btrfs_assert_delayed_root_empty(root);
3976 3970
@@ -3979,6 +3973,9 @@ void btrfs_cleanup_one_transaction(struct btrfs_transaction *cur_trans,
3979 btrfs_destroy_pinned_extent(root, 3973 btrfs_destroy_pinned_extent(root,
3980 root->fs_info->pinned_extents); 3974 root->fs_info->pinned_extents);
3981 3975
3976 cur_trans->state =TRANS_STATE_COMPLETED;
3977 wake_up(&cur_trans->commit_wait);
3978
3982 /* 3979 /*
3983 memset(cur_trans, 0, sizeof(*cur_trans)); 3980 memset(cur_trans, 0, sizeof(*cur_trans));
3984 kmem_cache_free(btrfs_transaction_cachep, cur_trans); 3981 kmem_cache_free(btrfs_transaction_cachep, cur_trans);
@@ -4006,25 +4003,23 @@ static int btrfs_cleanup_transaction(struct btrfs_root *root)
4006 4003
4007 btrfs_destroy_delayed_refs(t, root); 4004 btrfs_destroy_delayed_refs(t, root);
4008 4005
4009 /* FIXME: cleanup wait for commit */ 4006 /*
4010 t->in_commit = 1; 4007 * FIXME: cleanup wait for commit
4011 t->blocked = 1; 4008 * We needn't acquire the lock here, because we are during
4009 * the umount, there is no other task which will change it.
4010 */
4011 t->state = TRANS_STATE_COMMIT_START;
4012 smp_mb(); 4012 smp_mb();
4013 if (waitqueue_active(&root->fs_info->transaction_blocked_wait)) 4013 if (waitqueue_active(&root->fs_info->transaction_blocked_wait))
4014 wake_up(&root->fs_info->transaction_blocked_wait); 4014 wake_up(&root->fs_info->transaction_blocked_wait);
4015 4015
4016 btrfs_evict_pending_snapshots(t); 4016 btrfs_evict_pending_snapshots(t);
4017 4017
4018 t->blocked = 0; 4018 t->state = TRANS_STATE_UNBLOCKED;
4019 smp_mb(); 4019 smp_mb();
4020 if (waitqueue_active(&root->fs_info->transaction_wait)) 4020 if (waitqueue_active(&root->fs_info->transaction_wait))
4021 wake_up(&root->fs_info->transaction_wait); 4021 wake_up(&root->fs_info->transaction_wait);
4022 4022
4023 t->commit_done = 1;
4024 smp_mb();
4025 if (waitqueue_active(&t->commit_wait))
4026 wake_up(&t->commit_wait);
4027
4028 btrfs_destroy_delayed_inodes(root); 4023 btrfs_destroy_delayed_inodes(root);
4029 btrfs_assert_delayed_root_empty(root); 4024 btrfs_assert_delayed_root_empty(root);
4030 4025
@@ -4036,6 +4031,11 @@ static int btrfs_cleanup_transaction(struct btrfs_root *root)
4036 btrfs_destroy_pinned_extent(root, 4031 btrfs_destroy_pinned_extent(root,
4037 root->fs_info->pinned_extents); 4032 root->fs_info->pinned_extents);
4038 4033
4034 t->state = TRANS_STATE_COMPLETED;
4035 smp_mb();
4036 if (waitqueue_active(&t->commit_wait))
4037 wake_up(&t->commit_wait);
4038
4039 atomic_set(&t->use_count, 0); 4039 atomic_set(&t->use_count, 0);
4040 list_del_init(&t->list); 4040 list_del_init(&t->list);
4041 memset(t, 0, sizeof(*t)); 4041 memset(t, 0, sizeof(*t));
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index 5e75ff486daf..eec8686416ca 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -34,6 +34,29 @@
34 34
35#define BTRFS_ROOT_TRANS_TAG 0 35#define BTRFS_ROOT_TRANS_TAG 0
36 36
37static unsigned int btrfs_blocked_trans_types[TRANS_STATE_MAX] = {
38 [TRANS_STATE_RUNNING] = 0U,
39 [TRANS_STATE_BLOCKED] = (__TRANS_USERSPACE |
40 __TRANS_START),
41 [TRANS_STATE_COMMIT_START] = (__TRANS_USERSPACE |
42 __TRANS_START |
43 __TRANS_ATTACH),
44 [TRANS_STATE_COMMIT_DOING] = (__TRANS_USERSPACE |
45 __TRANS_START |
46 __TRANS_ATTACH |
47 __TRANS_JOIN),
48 [TRANS_STATE_UNBLOCKED] = (__TRANS_USERSPACE |
49 __TRANS_START |
50 __TRANS_ATTACH |
51 __TRANS_JOIN |
52 __TRANS_JOIN_NOLOCK),
53 [TRANS_STATE_COMPLETED] = (__TRANS_USERSPACE |
54 __TRANS_START |
55 __TRANS_ATTACH |
56 __TRANS_JOIN |
57 __TRANS_JOIN_NOLOCK),
58};
59
37static void put_transaction(struct btrfs_transaction *transaction) 60static void put_transaction(struct btrfs_transaction *transaction)
38{ 61{
39 WARN_ON(atomic_read(&transaction->use_count) == 0); 62 WARN_ON(atomic_read(&transaction->use_count) == 0);
@@ -50,13 +73,6 @@ static noinline void switch_commit_root(struct btrfs_root *root)
50 root->commit_root = btrfs_root_node(root); 73 root->commit_root = btrfs_root_node(root);
51} 74}
52 75
53static inline int can_join_transaction(struct btrfs_transaction *trans,
54 unsigned int type)
55{
56 return !(trans->in_commit &&
57 (type & TRANS_EXTWRITERS));
58}
59
60static inline void extwriter_counter_inc(struct btrfs_transaction *trans, 76static inline void extwriter_counter_inc(struct btrfs_transaction *trans,
61 unsigned int type) 77 unsigned int type)
62{ 78{
@@ -98,26 +114,13 @@ loop:
98 return -EROFS; 114 return -EROFS;
99 } 115 }
100 116
101 if (fs_info->trans_no_join) {
102 /*
103 * If we are JOIN_NOLOCK we're already committing a current
104 * transaction, we just need a handle to deal with something
105 * when committing the transaction, such as inode cache and
106 * space cache. It is a special case.
107 */
108 if (type != TRANS_JOIN_NOLOCK) {
109 spin_unlock(&fs_info->trans_lock);
110 return -EBUSY;
111 }
112 }
113
114 cur_trans = fs_info->running_transaction; 117 cur_trans = fs_info->running_transaction;
115 if (cur_trans) { 118 if (cur_trans) {
116 if (cur_trans->aborted) { 119 if (cur_trans->aborted) {
117 spin_unlock(&fs_info->trans_lock); 120 spin_unlock(&fs_info->trans_lock);
118 return cur_trans->aborted; 121 return cur_trans->aborted;
119 } 122 }
120 if (!can_join_transaction(cur_trans, type)) { 123 if (btrfs_blocked_trans_types[cur_trans->state] & type) {
121 spin_unlock(&fs_info->trans_lock); 124 spin_unlock(&fs_info->trans_lock);
122 return -EBUSY; 125 return -EBUSY;
123 } 126 }
@@ -136,6 +139,12 @@ loop:
136 if (type == TRANS_ATTACH) 139 if (type == TRANS_ATTACH)
137 return -ENOENT; 140 return -ENOENT;
138 141
142 /*
143 * JOIN_NOLOCK only happens during the transaction commit, so
144 * it is impossible that ->running_transaction is NULL
145 */
146 BUG_ON(type == TRANS_JOIN_NOLOCK);
147
139 cur_trans = kmem_cache_alloc(btrfs_transaction_cachep, GFP_NOFS); 148 cur_trans = kmem_cache_alloc(btrfs_transaction_cachep, GFP_NOFS);
140 if (!cur_trans) 149 if (!cur_trans)
141 return -ENOMEM; 150 return -ENOMEM;
@@ -144,7 +153,7 @@ loop:
144 if (fs_info->running_transaction) { 153 if (fs_info->running_transaction) {
145 /* 154 /*
146 * someone started a transaction after we unlocked. Make sure 155 * someone started a transaction after we unlocked. Make sure
147 * to redo the trans_no_join checks above 156 * to redo the checks above
148 */ 157 */
149 kmem_cache_free(btrfs_transaction_cachep, cur_trans); 158 kmem_cache_free(btrfs_transaction_cachep, cur_trans);
150 goto loop; 159 goto loop;
@@ -158,14 +167,12 @@ loop:
158 extwriter_counter_init(cur_trans, type); 167 extwriter_counter_init(cur_trans, type);
159 init_waitqueue_head(&cur_trans->writer_wait); 168 init_waitqueue_head(&cur_trans->writer_wait);
160 init_waitqueue_head(&cur_trans->commit_wait); 169 init_waitqueue_head(&cur_trans->commit_wait);
161 cur_trans->in_commit = 0; 170 cur_trans->state = TRANS_STATE_RUNNING;
162 cur_trans->blocked = 0;
163 /* 171 /*
164 * One for this trans handle, one so it will live on until we 172 * One for this trans handle, one so it will live on until we
165 * commit the transaction. 173 * commit the transaction.
166 */ 174 */
167 atomic_set(&cur_trans->use_count, 2); 175 atomic_set(&cur_trans->use_count, 2);
168 cur_trans->commit_done = 0;
169 cur_trans->start_time = get_seconds(); 176 cur_trans->start_time = get_seconds();
170 177
171 cur_trans->delayed_refs.root = RB_ROOT; 178 cur_trans->delayed_refs.root = RB_ROOT;
@@ -188,7 +195,6 @@ loop:
188 "creating a fresh transaction\n"); 195 "creating a fresh transaction\n");
189 atomic64_set(&fs_info->tree_mod_seq, 0); 196 atomic64_set(&fs_info->tree_mod_seq, 0);
190 197
191 spin_lock_init(&cur_trans->commit_lock);
192 spin_lock_init(&cur_trans->delayed_refs.lock); 198 spin_lock_init(&cur_trans->delayed_refs.lock);
193 atomic_set(&cur_trans->delayed_refs.procs_running_refs, 0); 199 atomic_set(&cur_trans->delayed_refs.procs_running_refs, 0);
194 atomic_set(&cur_trans->delayed_refs.ref_seq, 0); 200 atomic_set(&cur_trans->delayed_refs.ref_seq, 0);
@@ -293,6 +299,12 @@ int btrfs_record_root_in_trans(struct btrfs_trans_handle *trans,
293 return 0; 299 return 0;
294} 300}
295 301
302static inline int is_transaction_blocked(struct btrfs_transaction *trans)
303{
304 return (trans->state >= TRANS_STATE_BLOCKED &&
305 trans->state < TRANS_STATE_UNBLOCKED);
306}
307
296/* wait for commit against the current transaction to become unblocked 308/* wait for commit against the current transaction to become unblocked
297 * when this is done, it is safe to start a new transaction, but the current 309 * when this is done, it is safe to start a new transaction, but the current
298 * transaction might not be fully on disk. 310 * transaction might not be fully on disk.
@@ -303,12 +315,12 @@ static void wait_current_trans(struct btrfs_root *root)
303 315
304 spin_lock(&root->fs_info->trans_lock); 316 spin_lock(&root->fs_info->trans_lock);
305 cur_trans = root->fs_info->running_transaction; 317 cur_trans = root->fs_info->running_transaction;
306 if (cur_trans && cur_trans->blocked) { 318 if (cur_trans && is_transaction_blocked(cur_trans)) {
307 atomic_inc(&cur_trans->use_count); 319 atomic_inc(&cur_trans->use_count);
308 spin_unlock(&root->fs_info->trans_lock); 320 spin_unlock(&root->fs_info->trans_lock);
309 321
310 wait_event(root->fs_info->transaction_wait, 322 wait_event(root->fs_info->transaction_wait,
311 !cur_trans->blocked); 323 cur_trans->state >= TRANS_STATE_UNBLOCKED);
312 put_transaction(cur_trans); 324 put_transaction(cur_trans);
313 } else { 325 } else {
314 spin_unlock(&root->fs_info->trans_lock); 326 spin_unlock(&root->fs_info->trans_lock);
@@ -432,7 +444,8 @@ again:
432 INIT_LIST_HEAD(&h->new_bgs); 444 INIT_LIST_HEAD(&h->new_bgs);
433 445
434 smp_mb(); 446 smp_mb();
435 if (cur_trans->blocked && may_wait_transaction(root, type)) { 447 if (cur_trans->state >= TRANS_STATE_BLOCKED &&
448 may_wait_transaction(root, type)) {
436 btrfs_commit_transaction(h, root); 449 btrfs_commit_transaction(h, root);
437 goto again; 450 goto again;
438 } 451 }
@@ -536,7 +549,7 @@ btrfs_attach_transaction_barrier(struct btrfs_root *root)
536static noinline void wait_for_commit(struct btrfs_root *root, 549static noinline void wait_for_commit(struct btrfs_root *root,
537 struct btrfs_transaction *commit) 550 struct btrfs_transaction *commit)
538{ 551{
539 wait_event(commit->commit_wait, commit->commit_done); 552 wait_event(commit->commit_wait, commit->state == TRANS_STATE_COMPLETED);
540} 553}
541 554
542int btrfs_wait_for_commit(struct btrfs_root *root, u64 transid) 555int btrfs_wait_for_commit(struct btrfs_root *root, u64 transid)
@@ -572,8 +585,8 @@ int btrfs_wait_for_commit(struct btrfs_root *root, u64 transid)
572 spin_lock(&root->fs_info->trans_lock); 585 spin_lock(&root->fs_info->trans_lock);
573 list_for_each_entry_reverse(t, &root->fs_info->trans_list, 586 list_for_each_entry_reverse(t, &root->fs_info->trans_list,
574 list) { 587 list) {
575 if (t->in_commit) { 588 if (t->state >= TRANS_STATE_COMMIT_START) {
576 if (t->commit_done) 589 if (t->state == TRANS_STATE_COMPLETED)
577 break; 590 break;
578 cur_trans = t; 591 cur_trans = t;
579 atomic_inc(&cur_trans->use_count); 592 atomic_inc(&cur_trans->use_count);
@@ -614,7 +627,8 @@ int btrfs_should_end_transaction(struct btrfs_trans_handle *trans,
614 int err; 627 int err;
615 628
616 smp_mb(); 629 smp_mb();
617 if (cur_trans->blocked || cur_trans->delayed_refs.flushing) 630 if (cur_trans->state >= TRANS_STATE_BLOCKED ||
631 cur_trans->delayed_refs.flushing)
618 return 1; 632 return 1;
619 633
620 updates = trans->delayed_ref_updates; 634 updates = trans->delayed_ref_updates;
@@ -682,12 +696,15 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans,
682 btrfs_create_pending_block_groups(trans, root); 696 btrfs_create_pending_block_groups(trans, root);
683 697
684 if (lock && !atomic_read(&root->fs_info->open_ioctl_trans) && 698 if (lock && !atomic_read(&root->fs_info->open_ioctl_trans) &&
685 should_end_transaction(trans, root)) { 699 should_end_transaction(trans, root) &&
686 trans->transaction->blocked = 1; 700 ACCESS_ONCE(cur_trans->state) == TRANS_STATE_RUNNING) {
687 smp_wmb(); 701 spin_lock(&info->trans_lock);
702 if (cur_trans->state == TRANS_STATE_RUNNING)
703 cur_trans->state = TRANS_STATE_BLOCKED;
704 spin_unlock(&info->trans_lock);
688 } 705 }
689 706
690 if (lock && cur_trans->blocked && !cur_trans->in_commit) { 707 if (lock && ACCESS_ONCE(cur_trans->state) == TRANS_STATE_BLOCKED) {
691 if (throttle) { 708 if (throttle) {
692 /* 709 /*
693 * We may race with somebody else here so end up having 710 * We may race with somebody else here so end up having
@@ -1343,20 +1360,26 @@ static void update_super_roots(struct btrfs_root *root)
1343 1360
1344int btrfs_transaction_in_commit(struct btrfs_fs_info *info) 1361int btrfs_transaction_in_commit(struct btrfs_fs_info *info)
1345{ 1362{
1363 struct btrfs_transaction *trans;
1346 int ret = 0; 1364 int ret = 0;
1365
1347 spin_lock(&info->trans_lock); 1366 spin_lock(&info->trans_lock);
1348 if (info->running_transaction) 1367 trans = info->running_transaction;
1349 ret = info->running_transaction->in_commit; 1368 if (trans)
1369 ret = (trans->state >= TRANS_STATE_COMMIT_START);
1350 spin_unlock(&info->trans_lock); 1370 spin_unlock(&info->trans_lock);
1351 return ret; 1371 return ret;
1352} 1372}
1353 1373
1354int btrfs_transaction_blocked(struct btrfs_fs_info *info) 1374int btrfs_transaction_blocked(struct btrfs_fs_info *info)
1355{ 1375{
1376 struct btrfs_transaction *trans;
1356 int ret = 0; 1377 int ret = 0;
1378
1357 spin_lock(&info->trans_lock); 1379 spin_lock(&info->trans_lock);
1358 if (info->running_transaction) 1380 trans = info->running_transaction;
1359 ret = info->running_transaction->blocked; 1381 if (trans)
1382 ret = is_transaction_blocked(trans);
1360 spin_unlock(&info->trans_lock); 1383 spin_unlock(&info->trans_lock);
1361 return ret; 1384 return ret;
1362} 1385}
@@ -1368,7 +1391,8 @@ int btrfs_transaction_blocked(struct btrfs_fs_info *info)
1368static void wait_current_trans_commit_start(struct btrfs_root *root, 1391static void wait_current_trans_commit_start(struct btrfs_root *root,
1369 struct btrfs_transaction *trans) 1392 struct btrfs_transaction *trans)
1370{ 1393{
1371 wait_event(root->fs_info->transaction_blocked_wait, trans->in_commit); 1394 wait_event(root->fs_info->transaction_blocked_wait,
1395 trans->state >= TRANS_STATE_COMMIT_START);
1372} 1396}
1373 1397
1374/* 1398/*
@@ -1379,7 +1403,7 @@ static void wait_current_trans_commit_start_and_unblock(struct btrfs_root *root,
1379 struct btrfs_transaction *trans) 1403 struct btrfs_transaction *trans)
1380{ 1404{
1381 wait_event(root->fs_info->transaction_wait, 1405 wait_event(root->fs_info->transaction_wait,
1382 trans->commit_done || (trans->in_commit && !trans->blocked)); 1406 trans->state >= TRANS_STATE_UNBLOCKED);
1383} 1407}
1384 1408
1385/* 1409/*
@@ -1484,18 +1508,22 @@ static void cleanup_transaction(struct btrfs_trans_handle *trans,
1484 1508
1485 list_del_init(&cur_trans->list); 1509 list_del_init(&cur_trans->list);
1486 if (cur_trans == root->fs_info->running_transaction) { 1510 if (cur_trans == root->fs_info->running_transaction) {
1487 root->fs_info->trans_no_join = 1; 1511 cur_trans->state = TRANS_STATE_COMMIT_DOING;
1488 spin_unlock(&root->fs_info->trans_lock); 1512 spin_unlock(&root->fs_info->trans_lock);
1489 wait_event(cur_trans->writer_wait, 1513 wait_event(cur_trans->writer_wait,
1490 atomic_read(&cur_trans->num_writers) == 1); 1514 atomic_read(&cur_trans->num_writers) == 1);
1491 1515
1492 spin_lock(&root->fs_info->trans_lock); 1516 spin_lock(&root->fs_info->trans_lock);
1493 root->fs_info->running_transaction = NULL;
1494 } 1517 }
1495 spin_unlock(&root->fs_info->trans_lock); 1518 spin_unlock(&root->fs_info->trans_lock);
1496 1519
1497 btrfs_cleanup_one_transaction(trans->transaction, root); 1520 btrfs_cleanup_one_transaction(trans->transaction, root);
1498 1521
1522 spin_lock(&root->fs_info->trans_lock);
1523 if (cur_trans == root->fs_info->running_transaction)
1524 root->fs_info->running_transaction = NULL;
1525 spin_unlock(&root->fs_info->trans_lock);
1526
1499 put_transaction(cur_trans); 1527 put_transaction(cur_trans);
1500 put_transaction(cur_trans); 1528 put_transaction(cur_trans);
1501 1529
@@ -1507,10 +1535,6 @@ static void cleanup_transaction(struct btrfs_trans_handle *trans,
1507 current->journal_info = NULL; 1535 current->journal_info = NULL;
1508 1536
1509 kmem_cache_free(btrfs_trans_handle_cachep, trans); 1537 kmem_cache_free(btrfs_trans_handle_cachep, trans);
1510
1511 spin_lock(&root->fs_info->trans_lock);
1512 root->fs_info->trans_no_join = 0;
1513 spin_unlock(&root->fs_info->trans_lock);
1514} 1538}
1515 1539
1516static int btrfs_flush_all_pending_stuffs(struct btrfs_trans_handle *trans, 1540static int btrfs_flush_all_pending_stuffs(struct btrfs_trans_handle *trans,
@@ -1554,13 +1578,6 @@ static inline void btrfs_wait_delalloc_flush(struct btrfs_fs_info *fs_info)
1554 btrfs_wait_all_ordered_extents(fs_info, 1); 1578 btrfs_wait_all_ordered_extents(fs_info, 1);
1555} 1579}
1556 1580
1557/*
1558 * btrfs_transaction state sequence:
1559 * in_commit = 0, blocked = 0 (initial)
1560 * in_commit = 1, blocked = 1
1561 * blocked = 0
1562 * commit_done = 1
1563 */
1564int btrfs_commit_transaction(struct btrfs_trans_handle *trans, 1581int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
1565 struct btrfs_root *root) 1582 struct btrfs_root *root)
1566{ 1583{
@@ -1615,9 +1632,9 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
1615 return ret; 1632 return ret;
1616 } 1633 }
1617 1634
1618 spin_lock(&cur_trans->commit_lock); 1635 spin_lock(&root->fs_info->trans_lock);
1619 if (cur_trans->in_commit) { 1636 if (cur_trans->state >= TRANS_STATE_COMMIT_START) {
1620 spin_unlock(&cur_trans->commit_lock); 1637 spin_unlock(&root->fs_info->trans_lock);
1621 atomic_inc(&cur_trans->use_count); 1638 atomic_inc(&cur_trans->use_count);
1622 ret = btrfs_end_transaction(trans, root); 1639 ret = btrfs_end_transaction(trans, root);
1623 1640
@@ -1628,16 +1645,13 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
1628 return ret; 1645 return ret;
1629 } 1646 }
1630 1647
1631 trans->transaction->in_commit = 1; 1648 cur_trans->state = TRANS_STATE_COMMIT_START;
1632 trans->transaction->blocked = 1;
1633 spin_unlock(&cur_trans->commit_lock);
1634 wake_up(&root->fs_info->transaction_blocked_wait); 1649 wake_up(&root->fs_info->transaction_blocked_wait);
1635 1650
1636 spin_lock(&root->fs_info->trans_lock);
1637 if (cur_trans->list.prev != &root->fs_info->trans_list) { 1651 if (cur_trans->list.prev != &root->fs_info->trans_list) {
1638 prev_trans = list_entry(cur_trans->list.prev, 1652 prev_trans = list_entry(cur_trans->list.prev,
1639 struct btrfs_transaction, list); 1653 struct btrfs_transaction, list);
1640 if (!prev_trans->commit_done) { 1654 if (prev_trans->state != TRANS_STATE_COMPLETED) {
1641 atomic_inc(&prev_trans->use_count); 1655 atomic_inc(&prev_trans->use_count);
1642 spin_unlock(&root->fs_info->trans_lock); 1656 spin_unlock(&root->fs_info->trans_lock);
1643 1657
@@ -1673,10 +1687,10 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
1673 /* 1687 /*
1674 * Ok now we need to make sure to block out any other joins while we 1688 * Ok now we need to make sure to block out any other joins while we
1675 * commit the transaction. We could have started a join before setting 1689 * commit the transaction. We could have started a join before setting
1676 * no_join so make sure to wait for num_writers to == 1 again. 1690 * COMMIT_DOING so make sure to wait for num_writers to == 1 again.
1677 */ 1691 */
1678 spin_lock(&root->fs_info->trans_lock); 1692 spin_lock(&root->fs_info->trans_lock);
1679 root->fs_info->trans_no_join = 1; 1693 cur_trans->state = TRANS_STATE_COMMIT_DOING;
1680 spin_unlock(&root->fs_info->trans_lock); 1694 spin_unlock(&root->fs_info->trans_lock);
1681 wait_event(cur_trans->writer_wait, 1695 wait_event(cur_trans->writer_wait,
1682 atomic_read(&cur_trans->num_writers) == 1); 1696 atomic_read(&cur_trans->num_writers) == 1);
@@ -1803,10 +1817,9 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
1803 memcpy(root->fs_info->super_for_commit, root->fs_info->super_copy, 1817 memcpy(root->fs_info->super_for_commit, root->fs_info->super_copy,
1804 sizeof(*root->fs_info->super_copy)); 1818 sizeof(*root->fs_info->super_copy));
1805 1819
1806 trans->transaction->blocked = 0;
1807 spin_lock(&root->fs_info->trans_lock); 1820 spin_lock(&root->fs_info->trans_lock);
1821 cur_trans->state = TRANS_STATE_UNBLOCKED;
1808 root->fs_info->running_transaction = NULL; 1822 root->fs_info->running_transaction = NULL;
1809 root->fs_info->trans_no_join = 0;
1810 spin_unlock(&root->fs_info->trans_lock); 1823 spin_unlock(&root->fs_info->trans_lock);
1811 mutex_unlock(&root->fs_info->reloc_mutex); 1824 mutex_unlock(&root->fs_info->reloc_mutex);
1812 1825
@@ -1834,10 +1847,12 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
1834 1847
1835 btrfs_finish_extent_commit(trans, root); 1848 btrfs_finish_extent_commit(trans, root);
1836 1849
1837 cur_trans->commit_done = 1;
1838
1839 root->fs_info->last_trans_committed = cur_trans->transid; 1850 root->fs_info->last_trans_committed = cur_trans->transid;
1840 1851 /*
1852 * We needn't acquire the lock here because there is no other task
1853 * which can change it.
1854 */
1855 cur_trans->state = TRANS_STATE_COMPLETED;
1841 wake_up(&cur_trans->commit_wait); 1856 wake_up(&cur_trans->commit_wait);
1842 1857
1843 spin_lock(&root->fs_info->trans_lock); 1858 spin_lock(&root->fs_info->trans_lock);
diff --git a/fs/btrfs/transaction.h b/fs/btrfs/transaction.h
index 0fc45e2a5139..66d2a6ccbf05 100644
--- a/fs/btrfs/transaction.h
+++ b/fs/btrfs/transaction.h
@@ -22,6 +22,16 @@
22#include "delayed-ref.h" 22#include "delayed-ref.h"
23#include "ctree.h" 23#include "ctree.h"
24 24
25enum btrfs_trans_state {
26 TRANS_STATE_RUNNING = 0,
27 TRANS_STATE_BLOCKED = 1,
28 TRANS_STATE_COMMIT_START = 2,
29 TRANS_STATE_COMMIT_DOING = 3,
30 TRANS_STATE_UNBLOCKED = 4,
31 TRANS_STATE_COMPLETED = 5,
32 TRANS_STATE_MAX = 6,
33};
34
25struct btrfs_transaction { 35struct btrfs_transaction {
26 u64 transid; 36 u64 transid;
27 /* 37 /*
@@ -37,10 +47,8 @@ struct btrfs_transaction {
37 atomic_t num_writers; 47 atomic_t num_writers;
38 atomic_t use_count; 48 atomic_t use_count;
39 49
40 spinlock_t commit_lock; 50 /* Be protected by fs_info->trans_lock when we want to change it. */
41 int in_commit; 51 enum btrfs_trans_state state;
42 int commit_done;
43 int blocked;
44 struct list_head list; 52 struct list_head list;
45 struct extent_io_tree dirty_pages; 53 struct extent_io_tree dirty_pages;
46 unsigned long start_time; 54 unsigned long start_time;