diff options
| -rw-r--r-- | fs/btrfs/ctree.h | 4 | ||||
| -rw-r--r-- | fs/btrfs/disk-io.c | 2 | ||||
| -rw-r--r-- | fs/btrfs/extent-tree.c | 11 | ||||
| -rw-r--r-- | fs/btrfs/transaction.c | 22 | ||||
| -rw-r--r-- | fs/btrfs/transaction.h | 1 |
5 files changed, 28 insertions, 12 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 215ef8cae823..837435ce84ca 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
| @@ -825,6 +825,7 @@ struct btrfs_fs_info { | |||
| 825 | struct mutex drop_mutex; | 825 | struct mutex drop_mutex; |
| 826 | struct mutex volume_mutex; | 826 | struct mutex volume_mutex; |
| 827 | struct mutex tree_reloc_mutex; | 827 | struct mutex tree_reloc_mutex; |
| 828 | struct rw_semaphore extent_commit_sem; | ||
| 828 | 829 | ||
| 829 | /* | 830 | /* |
| 830 | * this protects the ordered operations list only while we are | 831 | * this protects the ordered operations list only while we are |
| @@ -959,9 +960,6 @@ struct btrfs_root { | |||
| 959 | /* the node lock is held while changing the node pointer */ | 960 | /* the node lock is held while changing the node pointer */ |
| 960 | spinlock_t node_lock; | 961 | spinlock_t node_lock; |
| 961 | 962 | ||
| 962 | /* taken when updating the commit root */ | ||
| 963 | struct rw_semaphore commit_root_sem; | ||
| 964 | |||
| 965 | struct extent_buffer *commit_root; | 963 | struct extent_buffer *commit_root; |
| 966 | struct btrfs_root *log_root; | 964 | struct btrfs_root *log_root; |
| 967 | struct btrfs_root *reloc_root; | 965 | struct btrfs_root *reloc_root; |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 7dcaa8138864..e83be2e4602c 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
| @@ -909,7 +909,6 @@ static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize, | |||
| 909 | spin_lock_init(&root->inode_lock); | 909 | spin_lock_init(&root->inode_lock); |
| 910 | mutex_init(&root->objectid_mutex); | 910 | mutex_init(&root->objectid_mutex); |
| 911 | mutex_init(&root->log_mutex); | 911 | mutex_init(&root->log_mutex); |
| 912 | init_rwsem(&root->commit_root_sem); | ||
| 913 | init_waitqueue_head(&root->log_writer_wait); | 912 | init_waitqueue_head(&root->log_writer_wait); |
| 914 | init_waitqueue_head(&root->log_commit_wait[0]); | 913 | init_waitqueue_head(&root->log_commit_wait[0]); |
| 915 | init_waitqueue_head(&root->log_commit_wait[1]); | 914 | init_waitqueue_head(&root->log_commit_wait[1]); |
| @@ -1640,6 +1639,7 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
| 1640 | mutex_init(&fs_info->cleaner_mutex); | 1639 | mutex_init(&fs_info->cleaner_mutex); |
| 1641 | mutex_init(&fs_info->volume_mutex); | 1640 | mutex_init(&fs_info->volume_mutex); |
| 1642 | mutex_init(&fs_info->tree_reloc_mutex); | 1641 | mutex_init(&fs_info->tree_reloc_mutex); |
| 1642 | init_rwsem(&fs_info->extent_commit_sem); | ||
| 1643 | 1643 | ||
| 1644 | btrfs_init_free_cluster(&fs_info->meta_alloc_cluster); | 1644 | btrfs_init_free_cluster(&fs_info->meta_alloc_cluster); |
| 1645 | btrfs_init_free_cluster(&fs_info->data_alloc_cluster); | 1645 | btrfs_init_free_cluster(&fs_info->data_alloc_cluster); |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index fadf69a2764b..dc84daee6bc4 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
| @@ -267,7 +267,7 @@ static int caching_kthread(void *data) | |||
| 267 | last = max_t(u64, block_group->key.objectid, BTRFS_SUPER_INFO_OFFSET); | 267 | last = max_t(u64, block_group->key.objectid, BTRFS_SUPER_INFO_OFFSET); |
| 268 | again: | 268 | again: |
| 269 | /* need to make sure the commit_root doesn't disappear */ | 269 | /* need to make sure the commit_root doesn't disappear */ |
| 270 | down_read(&fs_info->extent_root->commit_root_sem); | 270 | down_read(&fs_info->extent_commit_sem); |
| 271 | 271 | ||
| 272 | /* | 272 | /* |
| 273 | * We don't want to deadlock with somebody trying to allocate a new | 273 | * We don't want to deadlock with somebody trying to allocate a new |
| @@ -302,10 +302,11 @@ again: | |||
| 302 | else if (ret) | 302 | else if (ret) |
| 303 | break; | 303 | break; |
| 304 | 304 | ||
| 305 | if (need_resched()) { | 305 | if (need_resched() || |
| 306 | btrfs_transaction_in_commit(fs_info)) { | ||
| 306 | btrfs_release_path(fs_info->extent_root, path); | 307 | btrfs_release_path(fs_info->extent_root, path); |
| 307 | up_read(&fs_info->extent_root->commit_root_sem); | 308 | up_read(&fs_info->extent_commit_sem); |
| 308 | cond_resched(); | 309 | schedule_timeout(1); |
| 309 | goto again; | 310 | goto again; |
| 310 | } | 311 | } |
| 311 | 312 | ||
| @@ -345,7 +346,7 @@ next: | |||
| 345 | 346 | ||
| 346 | err: | 347 | err: |
| 347 | btrfs_free_path(path); | 348 | btrfs_free_path(path); |
| 348 | up_read(&fs_info->extent_root->commit_root_sem); | 349 | up_read(&fs_info->extent_commit_sem); |
| 349 | atomic_dec(&block_group->space_info->caching_threads); | 350 | atomic_dec(&block_group->space_info->caching_threads); |
| 350 | wake_up(&block_group->caching_q); | 351 | wake_up(&block_group->caching_q); |
| 351 | 352 | ||
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index e51d2bc532f8..cdbb5022da52 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
| @@ -42,10 +42,8 @@ static noinline void put_transaction(struct btrfs_transaction *transaction) | |||
| 42 | 42 | ||
| 43 | static noinline void switch_commit_root(struct btrfs_root *root) | 43 | static noinline void switch_commit_root(struct btrfs_root *root) |
| 44 | { | 44 | { |
| 45 | down_write(&root->commit_root_sem); | ||
| 46 | free_extent_buffer(root->commit_root); | 45 | free_extent_buffer(root->commit_root); |
| 47 | root->commit_root = btrfs_root_node(root); | 46 | root->commit_root = btrfs_root_node(root); |
| 48 | up_write(&root->commit_root_sem); | ||
| 49 | } | 47 | } |
| 50 | 48 | ||
| 51 | /* | 49 | /* |
| @@ -466,7 +464,10 @@ static int update_cowonly_root(struct btrfs_trans_handle *trans, | |||
| 466 | ret = btrfs_write_dirty_block_groups(trans, root); | 464 | ret = btrfs_write_dirty_block_groups(trans, root); |
| 467 | BUG_ON(ret); | 465 | BUG_ON(ret); |
| 468 | } | 466 | } |
| 469 | switch_commit_root(root); | 467 | |
| 468 | if (root != root->fs_info->extent_root) | ||
| 469 | switch_commit_root(root); | ||
| 470 | |||
| 470 | return 0; | 471 | return 0; |
| 471 | } | 472 | } |
| 472 | 473 | ||
| @@ -499,6 +500,11 @@ static noinline int commit_cowonly_roots(struct btrfs_trans_handle *trans, | |||
| 499 | 500 | ||
| 500 | update_cowonly_root(trans, root); | 501 | update_cowonly_root(trans, root); |
| 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 | ||
| @@ -851,6 +857,16 @@ static void update_super_roots(struct btrfs_root *root) | |||
| 851 | super->root_level = root_item->level; | 857 | super->root_level = root_item->level; |
| 852 | } | 858 | } |
| 853 | 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 | |||
| 854 | int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | 870 | int btrfs_commit_transaction(struct btrfs_trans_handle *trans, |
| 855 | struct btrfs_root *root) | 871 | struct btrfs_root *root) |
| 856 | { | 872 | { |
diff --git a/fs/btrfs/transaction.h b/fs/btrfs/transaction.h index 961c3ee5a2e1..663c67404918 100644 --- a/fs/btrfs/transaction.h +++ b/fs/btrfs/transaction.h | |||
| @@ -107,4 +107,5 @@ int btrfs_record_root_in_trans(struct btrfs_trans_handle *trans, | |||
| 107 | struct btrfs_root *root); | 107 | struct btrfs_root *root); |
| 108 | int btrfs_write_and_wait_marked_extents(struct btrfs_root *root, | 108 | int btrfs_write_and_wait_marked_extents(struct btrfs_root *root, |
| 109 | struct extent_io_tree *dirty_pages); | 109 | struct extent_io_tree *dirty_pages); |
| 110 | int btrfs_transaction_in_commit(struct btrfs_fs_info *info); | ||
| 110 | #endif | 111 | #endif |
