diff options
author | Chris Mason <chris.mason@oracle.com> | 2008-06-25 16:01:30 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-09-25 11:04:03 -0400 |
commit | a213501153fd66e2359e091b1612841305ba6551 (patch) | |
tree | 1f4c316c9d3cad0eb6d9be14cb0e67e46e815dce /fs/btrfs/transaction.c | |
parent | 925baeddc5b0764a53f2214a1253251bab0e0324 (diff) |
Btrfs: Replace the big fs_mutex with a collection of other locks
Extent alloctions are still protected by a large alloc_mutex.
Objectid allocations are covered by a objectid mutex
Other btree operations are protected by a lock on individual btree nodes
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/transaction.c')
-rw-r--r-- | fs/btrfs/transaction.c | 42 |
1 files changed, 16 insertions, 26 deletions
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 1ed433a71493..5a1ee0665ae8 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
@@ -370,6 +370,7 @@ int btrfs_defrag_root(struct btrfs_root *root, int cacheonly) | |||
370 | struct btrfs_trans_handle *trans; | 370 | struct btrfs_trans_handle *trans; |
371 | unsigned long nr; | 371 | unsigned long nr; |
372 | 372 | ||
373 | smp_mb(); | ||
373 | if (root->defrag_running) | 374 | if (root->defrag_running) |
374 | return 0; | 375 | return 0; |
375 | trans = btrfs_start_transaction(root, 1); | 376 | trans = btrfs_start_transaction(root, 1); |
@@ -378,16 +379,15 @@ int btrfs_defrag_root(struct btrfs_root *root, int cacheonly) | |||
378 | ret = btrfs_defrag_leaves(trans, root, cacheonly); | 379 | ret = btrfs_defrag_leaves(trans, root, cacheonly); |
379 | nr = trans->blocks_used; | 380 | nr = trans->blocks_used; |
380 | btrfs_end_transaction(trans, root); | 381 | btrfs_end_transaction(trans, root); |
381 | mutex_unlock(&info->fs_mutex); | ||
382 | btrfs_btree_balance_dirty(info->tree_root, nr); | 382 | btrfs_btree_balance_dirty(info->tree_root, nr); |
383 | cond_resched(); | 383 | cond_resched(); |
384 | 384 | ||
385 | mutex_lock(&info->fs_mutex); | ||
386 | trans = btrfs_start_transaction(root, 1); | 385 | trans = btrfs_start_transaction(root, 1); |
387 | if (ret != -EAGAIN) | 386 | if (ret != -EAGAIN) |
388 | break; | 387 | break; |
389 | } | 388 | } |
390 | root->defrag_running = 0; | 389 | root->defrag_running = 0; |
390 | smp_mb(); | ||
391 | radix_tree_tag_clear(&info->fs_roots_radix, | 391 | radix_tree_tag_clear(&info->fs_roots_radix, |
392 | (unsigned long)root->root_key.objectid, | 392 | (unsigned long)root->root_key.objectid, |
393 | BTRFS_ROOT_DEFRAG_TAG); | 393 | BTRFS_ROOT_DEFRAG_TAG); |
@@ -435,14 +435,14 @@ static noinline int drop_dirty_roots(struct btrfs_root *tree_root, | |||
435 | while(!list_empty(list)) { | 435 | while(!list_empty(list)) { |
436 | struct btrfs_root *root; | 436 | struct btrfs_root *root; |
437 | 437 | ||
438 | mutex_lock(&tree_root->fs_info->fs_mutex); | ||
439 | dirty = list_entry(list->next, struct dirty_root, list); | 438 | dirty = list_entry(list->next, struct dirty_root, list); |
440 | list_del_init(&dirty->list); | 439 | list_del_init(&dirty->list); |
441 | 440 | ||
442 | num_bytes = btrfs_root_used(&dirty->root->root_item); | 441 | num_bytes = btrfs_root_used(&dirty->root->root_item); |
443 | root = dirty->latest_root; | 442 | root = dirty->latest_root; |
444 | root->fs_info->throttles++; | 443 | atomic_inc(&root->fs_info->throttles); |
445 | 444 | ||
445 | mutex_lock(&root->fs_info->drop_mutex); | ||
446 | while(1) { | 446 | while(1) { |
447 | trans = btrfs_start_transaction(tree_root, 1); | 447 | trans = btrfs_start_transaction(tree_root, 1); |
448 | ret = btrfs_drop_snapshot(trans, dirty->root); | 448 | ret = btrfs_drop_snapshot(trans, dirty->root); |
@@ -459,14 +459,16 @@ static noinline int drop_dirty_roots(struct btrfs_root *tree_root, | |||
459 | nr = trans->blocks_used; | 459 | nr = trans->blocks_used; |
460 | ret = btrfs_end_transaction(trans, tree_root); | 460 | ret = btrfs_end_transaction(trans, tree_root); |
461 | BUG_ON(ret); | 461 | BUG_ON(ret); |
462 | mutex_unlock(&tree_root->fs_info->fs_mutex); | 462 | |
463 | mutex_unlock(&root->fs_info->drop_mutex); | ||
463 | btrfs_btree_balance_dirty(tree_root, nr); | 464 | btrfs_btree_balance_dirty(tree_root, nr); |
464 | cond_resched(); | 465 | cond_resched(); |
465 | mutex_lock(&tree_root->fs_info->fs_mutex); | 466 | mutex_lock(&root->fs_info->drop_mutex); |
466 | } | 467 | } |
467 | BUG_ON(ret); | 468 | BUG_ON(ret); |
468 | root->fs_info->throttles--; | 469 | atomic_dec(&root->fs_info->throttles); |
469 | 470 | ||
471 | mutex_lock(&root->fs_info->alloc_mutex); | ||
470 | num_bytes -= btrfs_root_used(&dirty->root->root_item); | 472 | num_bytes -= btrfs_root_used(&dirty->root->root_item); |
471 | bytes_used = btrfs_root_used(&root->root_item); | 473 | bytes_used = btrfs_root_used(&root->root_item); |
472 | if (num_bytes) { | 474 | if (num_bytes) { |
@@ -474,11 +476,15 @@ static noinline int drop_dirty_roots(struct btrfs_root *tree_root, | |||
474 | btrfs_set_root_used(&root->root_item, | 476 | btrfs_set_root_used(&root->root_item, |
475 | bytes_used - num_bytes); | 477 | bytes_used - num_bytes); |
476 | } | 478 | } |
479 | mutex_unlock(&root->fs_info->alloc_mutex); | ||
480 | |||
477 | ret = btrfs_del_root(trans, tree_root, &dirty->root->root_key); | 481 | ret = btrfs_del_root(trans, tree_root, &dirty->root->root_key); |
478 | if (ret) { | 482 | if (ret) { |
479 | BUG(); | 483 | BUG(); |
480 | break; | 484 | break; |
481 | } | 485 | } |
486 | mutex_unlock(&root->fs_info->drop_mutex); | ||
487 | |||
482 | nr = trans->blocks_used; | 488 | nr = trans->blocks_used; |
483 | ret = btrfs_end_transaction(trans, tree_root); | 489 | ret = btrfs_end_transaction(trans, tree_root); |
484 | BUG_ON(ret); | 490 | BUG_ON(ret); |
@@ -486,7 +492,6 @@ static noinline int drop_dirty_roots(struct btrfs_root *tree_root, | |||
486 | free_extent_buffer(dirty->root->node); | 492 | free_extent_buffer(dirty->root->node); |
487 | kfree(dirty->root); | 493 | kfree(dirty->root); |
488 | kfree(dirty); | 494 | kfree(dirty); |
489 | mutex_unlock(&tree_root->fs_info->fs_mutex); | ||
490 | 495 | ||
491 | btrfs_btree_balance_dirty(tree_root, nr); | 496 | btrfs_btree_balance_dirty(tree_root, nr); |
492 | cond_resched(); | 497 | cond_resched(); |
@@ -503,7 +508,7 @@ int btrfs_write_ordered_inodes(struct btrfs_trans_handle *trans, | |||
503 | u64 objectid = 0; | 508 | u64 objectid = 0; |
504 | int ret; | 509 | int ret; |
505 | 510 | ||
506 | root->fs_info->throttles++; | 511 | atomic_inc(&root->fs_info->throttles); |
507 | while(1) { | 512 | while(1) { |
508 | ret = btrfs_find_first_ordered_inode( | 513 | ret = btrfs_find_first_ordered_inode( |
509 | &cur_trans->ordered_inode_tree, | 514 | &cur_trans->ordered_inode_tree, |
@@ -512,7 +517,6 @@ int btrfs_write_ordered_inodes(struct btrfs_trans_handle *trans, | |||
512 | break; | 517 | break; |
513 | 518 | ||
514 | mutex_unlock(&root->fs_info->trans_mutex); | 519 | mutex_unlock(&root->fs_info->trans_mutex); |
515 | mutex_unlock(&root->fs_info->fs_mutex); | ||
516 | 520 | ||
517 | if (S_ISREG(inode->i_mode)) { | 521 | if (S_ISREG(inode->i_mode)) { |
518 | atomic_inc(&BTRFS_I(inode)->ordered_writeback); | 522 | atomic_inc(&BTRFS_I(inode)->ordered_writeback); |
@@ -521,7 +525,6 @@ int btrfs_write_ordered_inodes(struct btrfs_trans_handle *trans, | |||
521 | } | 525 | } |
522 | iput(inode); | 526 | iput(inode); |
523 | 527 | ||
524 | mutex_lock(&root->fs_info->fs_mutex); | ||
525 | mutex_lock(&root->fs_info->trans_mutex); | 528 | mutex_lock(&root->fs_info->trans_mutex); |
526 | } | 529 | } |
527 | while(1) { | 530 | while(1) { |
@@ -533,7 +536,6 @@ int btrfs_write_ordered_inodes(struct btrfs_trans_handle *trans, | |||
533 | if (!ret) | 536 | if (!ret) |
534 | break; | 537 | break; |
535 | mutex_unlock(&root->fs_info->trans_mutex); | 538 | mutex_unlock(&root->fs_info->trans_mutex); |
536 | mutex_unlock(&root->fs_info->fs_mutex); | ||
537 | 539 | ||
538 | if (S_ISREG(inode->i_mode)) { | 540 | if (S_ISREG(inode->i_mode)) { |
539 | atomic_inc(&BTRFS_I(inode)->ordered_writeback); | 541 | atomic_inc(&BTRFS_I(inode)->ordered_writeback); |
@@ -543,10 +545,9 @@ int btrfs_write_ordered_inodes(struct btrfs_trans_handle *trans, | |||
543 | atomic_dec(&inode->i_count); | 545 | atomic_dec(&inode->i_count); |
544 | iput(inode); | 546 | iput(inode); |
545 | 547 | ||
546 | mutex_lock(&root->fs_info->fs_mutex); | ||
547 | mutex_lock(&root->fs_info->trans_mutex); | 548 | mutex_lock(&root->fs_info->trans_mutex); |
548 | } | 549 | } |
549 | root->fs_info->throttles--; | 550 | atomic_dec(&root->fs_info->throttles); |
550 | return 0; | 551 | return 0; |
551 | } | 552 | } |
552 | 553 | ||
@@ -661,7 +662,6 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
661 | mutex_unlock(&root->fs_info->trans_mutex); | 662 | mutex_unlock(&root->fs_info->trans_mutex); |
662 | btrfs_end_transaction(trans, root); | 663 | btrfs_end_transaction(trans, root); |
663 | 664 | ||
664 | mutex_unlock(&root->fs_info->fs_mutex); | ||
665 | ret = wait_for_commit(root, cur_trans); | 665 | ret = wait_for_commit(root, cur_trans); |
666 | BUG_ON(ret); | 666 | BUG_ON(ret); |
667 | 667 | ||
@@ -669,7 +669,6 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
669 | put_transaction(cur_trans); | 669 | put_transaction(cur_trans); |
670 | mutex_unlock(&root->fs_info->trans_mutex); | 670 | mutex_unlock(&root->fs_info->trans_mutex); |
671 | 671 | ||
672 | mutex_lock(&root->fs_info->fs_mutex); | ||
673 | return 0; | 672 | return 0; |
674 | } | 673 | } |
675 | 674 | ||
@@ -687,12 +686,10 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
687 | struct btrfs_transaction, list); | 686 | struct btrfs_transaction, list); |
688 | if (!prev_trans->commit_done) { | 687 | if (!prev_trans->commit_done) { |
689 | prev_trans->use_count++; | 688 | prev_trans->use_count++; |
690 | mutex_unlock(&root->fs_info->fs_mutex); | ||
691 | mutex_unlock(&root->fs_info->trans_mutex); | 689 | mutex_unlock(&root->fs_info->trans_mutex); |
692 | 690 | ||
693 | wait_for_commit(root, prev_trans); | 691 | wait_for_commit(root, prev_trans); |
694 | 692 | ||
695 | mutex_lock(&root->fs_info->fs_mutex); | ||
696 | mutex_lock(&root->fs_info->trans_mutex); | 693 | mutex_lock(&root->fs_info->trans_mutex); |
697 | put_transaction(prev_trans); | 694 | put_transaction(prev_trans); |
698 | } | 695 | } |
@@ -709,12 +706,10 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
709 | else | 706 | else |
710 | timeout = 1; | 707 | timeout = 1; |
711 | 708 | ||
712 | mutex_unlock(&root->fs_info->fs_mutex); | ||
713 | mutex_unlock(&root->fs_info->trans_mutex); | 709 | mutex_unlock(&root->fs_info->trans_mutex); |
714 | 710 | ||
715 | schedule_timeout(timeout); | 711 | schedule_timeout(timeout); |
716 | 712 | ||
717 | mutex_lock(&root->fs_info->fs_mutex); | ||
718 | mutex_lock(&root->fs_info->trans_mutex); | 713 | mutex_lock(&root->fs_info->trans_mutex); |
719 | finish_wait(&cur_trans->writer_wait, &wait); | 714 | finish_wait(&cur_trans->writer_wait, &wait); |
720 | ret = btrfs_write_ordered_inodes(trans, root); | 715 | ret = btrfs_write_ordered_inodes(trans, root); |
@@ -755,12 +750,10 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
755 | btrfs_copy_pinned(root, pinned_copy); | 750 | btrfs_copy_pinned(root, pinned_copy); |
756 | 751 | ||
757 | mutex_unlock(&root->fs_info->trans_mutex); | 752 | mutex_unlock(&root->fs_info->trans_mutex); |
758 | mutex_unlock(&root->fs_info->fs_mutex); | ||
759 | ret = btrfs_write_and_wait_transaction(trans, root); | 753 | ret = btrfs_write_and_wait_transaction(trans, root); |
760 | BUG_ON(ret); | 754 | BUG_ON(ret); |
761 | write_ctree_super(trans, root); | 755 | write_ctree_super(trans, root); |
762 | 756 | ||
763 | mutex_lock(&root->fs_info->fs_mutex); | ||
764 | btrfs_finish_extent_commit(trans, root, pinned_copy); | 757 | btrfs_finish_extent_commit(trans, root, pinned_copy); |
765 | mutex_lock(&root->fs_info->trans_mutex); | 758 | mutex_lock(&root->fs_info->trans_mutex); |
766 | 759 | ||
@@ -781,9 +774,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
781 | kmem_cache_free(btrfs_trans_handle_cachep, trans); | 774 | kmem_cache_free(btrfs_trans_handle_cachep, trans); |
782 | 775 | ||
783 | if (root->fs_info->closing) { | 776 | if (root->fs_info->closing) { |
784 | mutex_unlock(&root->fs_info->fs_mutex); | ||
785 | drop_dirty_roots(root->fs_info->tree_root, &dirty_fs_roots); | 777 | drop_dirty_roots(root->fs_info->tree_root, &dirty_fs_roots); |
786 | mutex_lock(&root->fs_info->fs_mutex); | ||
787 | } | 778 | } |
788 | return ret; | 779 | return ret; |
789 | } | 780 | } |
@@ -823,7 +814,7 @@ void btrfs_transaction_cleaner(struct work_struct *work) | |||
823 | unsigned long delay = HZ * 30; | 814 | unsigned long delay = HZ * 30; |
824 | int ret; | 815 | int ret; |
825 | 816 | ||
826 | mutex_lock(&root->fs_info->fs_mutex); | 817 | smp_mb(); |
827 | if (root->fs_info->closing) | 818 | if (root->fs_info->closing) |
828 | goto out; | 819 | goto out; |
829 | 820 | ||
@@ -844,7 +835,6 @@ void btrfs_transaction_cleaner(struct work_struct *work) | |||
844 | trans = btrfs_start_transaction(root, 1); | 835 | trans = btrfs_start_transaction(root, 1); |
845 | ret = btrfs_commit_transaction(trans, root); | 836 | ret = btrfs_commit_transaction(trans, root); |
846 | out: | 837 | out: |
847 | mutex_unlock(&root->fs_info->fs_mutex); | ||
848 | btrfs_clean_old_snapshots(root); | 838 | btrfs_clean_old_snapshots(root); |
849 | btrfs_transaction_queue_work(root, delay); | 839 | btrfs_transaction_queue_work(root, delay); |
850 | } | 840 | } |