aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosef Bacik <josef@redhat.com>2011-04-11 15:45:29 -0400
committerJosef Bacik <josef@redhat.com>2011-04-11 20:43:52 -0400
commit13c5a93e7005d7dae0b6d070d25203593e692d13 (patch)
treeecbc7205618940bbba3f0d9ad000462a5364f763
parent93a54bc4c28a125978cddbe2db9e347391e3522d (diff)
Btrfs: avoid taking the trans_mutex in btrfs_end_transaction
I've been working on making our O_DIRECT latency not suck and I noticed we were taking the trans_mutex in btrfs_end_transaction. So to do this we convert num_writers and use_count to atomic_t's and just decrement them in btrfs_end_transaction. Instead of deleting the transaction from the trans list in put_transaction we do that in btrfs_commit_transaction() since that's the only time it actually needs to be removed from the list. Thanks, Signed-off-by: Josef Bacik <josef@redhat.com>
-rw-r--r--fs/btrfs/disk-io.c2
-rw-r--r--fs/btrfs/transaction.c37
-rw-r--r--fs/btrfs/transaction.h4
3 files changed, 19 insertions, 24 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index a272bfd74ea0..ef6865c17cd6 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -3136,7 +3136,7 @@ static int btrfs_cleanup_transaction(struct btrfs_root *root)
3136 btrfs_destroy_pinned_extent(root, 3136 btrfs_destroy_pinned_extent(root,
3137 root->fs_info->pinned_extents); 3137 root->fs_info->pinned_extents);
3138 3138
3139 t->use_count = 0; 3139 atomic_set(&t->use_count, 0);
3140 list_del_init(&t->list); 3140 list_del_init(&t->list);
3141 memset(t, 0, sizeof(*t)); 3141 memset(t, 0, sizeof(*t));
3142 kmem_cache_free(btrfs_transaction_cachep, t); 3142 kmem_cache_free(btrfs_transaction_cachep, t);
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index 4583008217e6..c571734d5e5a 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -32,10 +32,8 @@
32 32
33static noinline void put_transaction(struct btrfs_transaction *transaction) 33static noinline void put_transaction(struct btrfs_transaction *transaction)
34{ 34{
35 WARN_ON(transaction->use_count == 0); 35 WARN_ON(atomic_read(&transaction->use_count) == 0);
36 transaction->use_count--; 36 if (atomic_dec_and_test(&transaction->use_count)) {
37 if (transaction->use_count == 0) {
38 list_del_init(&transaction->list);
39 memset(transaction, 0, sizeof(*transaction)); 37 memset(transaction, 0, sizeof(*transaction));
40 kmem_cache_free(btrfs_transaction_cachep, transaction); 38 kmem_cache_free(btrfs_transaction_cachep, transaction);
41 } 39 }
@@ -60,14 +58,14 @@ static noinline int join_transaction(struct btrfs_root *root)
60 if (!cur_trans) 58 if (!cur_trans)
61 return -ENOMEM; 59 return -ENOMEM;
62 root->fs_info->generation++; 60 root->fs_info->generation++;
63 cur_trans->num_writers = 1; 61 atomic_set(&cur_trans->num_writers, 1);
64 cur_trans->num_joined = 0; 62 cur_trans->num_joined = 0;
65 cur_trans->transid = root->fs_info->generation; 63 cur_trans->transid = root->fs_info->generation;
66 init_waitqueue_head(&cur_trans->writer_wait); 64 init_waitqueue_head(&cur_trans->writer_wait);
67 init_waitqueue_head(&cur_trans->commit_wait); 65 init_waitqueue_head(&cur_trans->commit_wait);
68 cur_trans->in_commit = 0; 66 cur_trans->in_commit = 0;
69 cur_trans->blocked = 0; 67 cur_trans->blocked = 0;
70 cur_trans->use_count = 1; 68 atomic_set(&cur_trans->use_count, 1);
71 cur_trans->commit_done = 0; 69 cur_trans->commit_done = 0;
72 cur_trans->start_time = get_seconds(); 70 cur_trans->start_time = get_seconds();
73 71
@@ -88,7 +86,7 @@ static noinline int join_transaction(struct btrfs_root *root)
88 root->fs_info->running_transaction = cur_trans; 86 root->fs_info->running_transaction = cur_trans;
89 spin_unlock(&root->fs_info->new_trans_lock); 87 spin_unlock(&root->fs_info->new_trans_lock);
90 } else { 88 } else {
91 cur_trans->num_writers++; 89 atomic_inc(&cur_trans->num_writers);
92 cur_trans->num_joined++; 90 cur_trans->num_joined++;
93 } 91 }
94 92
@@ -145,7 +143,7 @@ static void wait_current_trans(struct btrfs_root *root)
145 cur_trans = root->fs_info->running_transaction; 143 cur_trans = root->fs_info->running_transaction;
146 if (cur_trans && cur_trans->blocked) { 144 if (cur_trans && cur_trans->blocked) {
147 DEFINE_WAIT(wait); 145 DEFINE_WAIT(wait);
148 cur_trans->use_count++; 146 atomic_inc(&cur_trans->use_count);
149 while (1) { 147 while (1) {
150 prepare_to_wait(&root->fs_info->transaction_wait, &wait, 148 prepare_to_wait(&root->fs_info->transaction_wait, &wait,
151 TASK_UNINTERRUPTIBLE); 149 TASK_UNINTERRUPTIBLE);
@@ -205,7 +203,7 @@ again:
205 } 203 }
206 204
207 cur_trans = root->fs_info->running_transaction; 205 cur_trans = root->fs_info->running_transaction;
208 cur_trans->use_count++; 206 atomic_inc(&cur_trans->use_count);
209 if (type != TRANS_JOIN_NOLOCK) 207 if (type != TRANS_JOIN_NOLOCK)
210 mutex_unlock(&root->fs_info->trans_mutex); 208 mutex_unlock(&root->fs_info->trans_mutex);
211 209
@@ -336,7 +334,7 @@ int btrfs_wait_for_commit(struct btrfs_root *root, u64 transid)
336 goto out_unlock; /* nothing committing|committed */ 334 goto out_unlock; /* nothing committing|committed */
337 } 335 }
338 336
339 cur_trans->use_count++; 337 atomic_inc(&cur_trans->use_count);
340 mutex_unlock(&root->fs_info->trans_mutex); 338 mutex_unlock(&root->fs_info->trans_mutex);
341 339
342 wait_for_commit(root, cur_trans); 340 wait_for_commit(root, cur_trans);
@@ -466,18 +464,14 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans,
466 wake_up_process(info->transaction_kthread); 464 wake_up_process(info->transaction_kthread);
467 } 465 }
468 466
469 if (lock)
470 mutex_lock(&info->trans_mutex);
471 WARN_ON(cur_trans != info->running_transaction); 467 WARN_ON(cur_trans != info->running_transaction);
472 WARN_ON(cur_trans->num_writers < 1); 468 WARN_ON(atomic_read(&cur_trans->num_writers) < 1);
473 cur_trans->num_writers--; 469 atomic_dec(&cur_trans->num_writers);
474 470
475 smp_mb(); 471 smp_mb();
476 if (waitqueue_active(&cur_trans->writer_wait)) 472 if (waitqueue_active(&cur_trans->writer_wait))
477 wake_up(&cur_trans->writer_wait); 473 wake_up(&cur_trans->writer_wait);
478 put_transaction(cur_trans); 474 put_transaction(cur_trans);
479 if (lock)
480 mutex_unlock(&info->trans_mutex);
481 475
482 if (current->journal_info == trans) 476 if (current->journal_info == trans)
483 current->journal_info = NULL; 477 current->journal_info = NULL;
@@ -1187,7 +1181,7 @@ int btrfs_commit_transaction_async(struct btrfs_trans_handle *trans,
1187 /* take transaction reference */ 1181 /* take transaction reference */
1188 mutex_lock(&root->fs_info->trans_mutex); 1182 mutex_lock(&root->fs_info->trans_mutex);
1189 cur_trans = trans->transaction; 1183 cur_trans = trans->transaction;
1190 cur_trans->use_count++; 1184 atomic_inc(&cur_trans->use_count);
1191 mutex_unlock(&root->fs_info->trans_mutex); 1185 mutex_unlock(&root->fs_info->trans_mutex);
1192 1186
1193 btrfs_end_transaction(trans, root); 1187 btrfs_end_transaction(trans, root);
@@ -1246,7 +1240,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
1246 1240
1247 mutex_lock(&root->fs_info->trans_mutex); 1241 mutex_lock(&root->fs_info->trans_mutex);
1248 if (cur_trans->in_commit) { 1242 if (cur_trans->in_commit) {
1249 cur_trans->use_count++; 1243 atomic_inc(&cur_trans->use_count);
1250 mutex_unlock(&root->fs_info->trans_mutex); 1244 mutex_unlock(&root->fs_info->trans_mutex);
1251 btrfs_end_transaction(trans, root); 1245 btrfs_end_transaction(trans, root);
1252 1246
@@ -1268,7 +1262,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
1268 prev_trans = list_entry(cur_trans->list.prev, 1262 prev_trans = list_entry(cur_trans->list.prev,
1269 struct btrfs_transaction, list); 1263 struct btrfs_transaction, list);
1270 if (!prev_trans->commit_done) { 1264 if (!prev_trans->commit_done) {
1271 prev_trans->use_count++; 1265 atomic_inc(&prev_trans->use_count);
1272 mutex_unlock(&root->fs_info->trans_mutex); 1266 mutex_unlock(&root->fs_info->trans_mutex);
1273 1267
1274 wait_for_commit(root, prev_trans); 1268 wait_for_commit(root, prev_trans);
@@ -1309,14 +1303,14 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
1309 TASK_UNINTERRUPTIBLE); 1303 TASK_UNINTERRUPTIBLE);
1310 1304
1311 smp_mb(); 1305 smp_mb();
1312 if (cur_trans->num_writers > 1) 1306 if (atomic_read(&cur_trans->num_writers) > 1)
1313 schedule_timeout(MAX_SCHEDULE_TIMEOUT); 1307 schedule_timeout(MAX_SCHEDULE_TIMEOUT);
1314 else if (should_grow) 1308 else if (should_grow)
1315 schedule_timeout(1); 1309 schedule_timeout(1);
1316 1310
1317 mutex_lock(&root->fs_info->trans_mutex); 1311 mutex_lock(&root->fs_info->trans_mutex);
1318 finish_wait(&cur_trans->writer_wait, &wait); 1312 finish_wait(&cur_trans->writer_wait, &wait);
1319 } while (cur_trans->num_writers > 1 || 1313 } while (atomic_read(&cur_trans->num_writers) > 1 ||
1320 (should_grow && cur_trans->num_joined != joined)); 1314 (should_grow && cur_trans->num_joined != joined));
1321 1315
1322 ret = create_pending_snapshots(trans, root->fs_info); 1316 ret = create_pending_snapshots(trans, root->fs_info);
@@ -1403,6 +1397,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
1403 1397
1404 wake_up(&cur_trans->commit_wait); 1398 wake_up(&cur_trans->commit_wait);
1405 1399
1400 list_del_init(&cur_trans->list);
1406 put_transaction(cur_trans); 1401 put_transaction(cur_trans);
1407 put_transaction(cur_trans); 1402 put_transaction(cur_trans);
1408 1403
diff --git a/fs/btrfs/transaction.h b/fs/btrfs/transaction.h
index 229a594cacd5..e441acc6c584 100644
--- a/fs/btrfs/transaction.h
+++ b/fs/btrfs/transaction.h
@@ -27,11 +27,11 @@ struct btrfs_transaction {
27 * total writers in this transaction, it must be zero before the 27 * total writers in this transaction, it must be zero before the
28 * transaction can end 28 * transaction can end
29 */ 29 */
30 unsigned long num_writers; 30 atomic_t num_writers;
31 31
32 unsigned long num_joined; 32 unsigned long num_joined;
33 int in_commit; 33 int in_commit;
34 int use_count; 34 atomic_t use_count;
35 int commit_done; 35 int commit_done;
36 int blocked; 36 int blocked;
37 struct list_head list; 37 struct list_head list;