aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYan Zheng <zheng.yan@oracle.com>2009-07-30 09:40:40 -0400
committerChris Mason <chris.mason@oracle.com>2009-07-30 09:40:40 -0400
commit276e680d192a67d222fcea51af37b056feffb665 (patch)
tree137bae016c30f24e7fafcbc8073e3411b732eb31
parentf25784b35f590c81d5fb8245a8cd45e1afb6f1b2 (diff)
Btrfs: preserve commit_root for async caching
The async block group caching code uses the commit_root pointer to get a stable version of the extent allocation tree for scanning. This copy of the tree root isn't going to change and it significantly reduces the complexity of the scanning code. During a commit, we have a loop where we update the extent allocation tree root. We need to loop because updating the root pointer in the tree of tree roots may allocate blocks which may change the extent allocation tree. Right now the commit_root pointer is changed inside this loop. It is more correct to change the commit_root pointer only after all the looping is done. Signed-off-by: Yan Zheng <zheng.yan@oracle.com> Signed-off-by: Chris Mason <chris.mason@oracle.com>
-rw-r--r--fs/btrfs/ctree.h4
-rw-r--r--fs/btrfs/disk-io.c2
-rw-r--r--fs/btrfs/extent-tree.c6
-rw-r--r--fs/btrfs/transaction.c12
4 files changed, 14 insertions, 10 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 17ad92c29cfd..38eeb6c49c8a 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -827,6 +827,7 @@ struct btrfs_fs_info {
827 struct mutex drop_mutex; 827 struct mutex drop_mutex;
828 struct mutex volume_mutex; 828 struct mutex volume_mutex;
829 struct mutex tree_reloc_mutex; 829 struct mutex tree_reloc_mutex;
830 struct rw_semaphore extent_commit_sem;
830 831
831 /* 832 /*
832 * this protects the ordered operations list only while we are 833 * this protects the ordered operations list only while we are
@@ -961,9 +962,6 @@ struct btrfs_root {
961 /* the node lock is held while changing the node pointer */ 962 /* the node lock is held while changing the node pointer */
962 spinlock_t node_lock; 963 spinlock_t node_lock;
963 964
964 /* taken when updating the commit root */
965 struct rw_semaphore commit_root_sem;
966
967 struct extent_buffer *commit_root; 965 struct extent_buffer *commit_root;
968 struct btrfs_root *log_root; 966 struct btrfs_root *log_root;
969 struct btrfs_root *reloc_root; 967 struct btrfs_root *reloc_root;
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 3a9b88759880..3cf4cfa575c8 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -907,7 +907,6 @@ static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize,
907 spin_lock_init(&root->inode_lock); 907 spin_lock_init(&root->inode_lock);
908 mutex_init(&root->objectid_mutex); 908 mutex_init(&root->objectid_mutex);
909 mutex_init(&root->log_mutex); 909 mutex_init(&root->log_mutex);
910 init_rwsem(&root->commit_root_sem);
911 init_waitqueue_head(&root->log_writer_wait); 910 init_waitqueue_head(&root->log_writer_wait);
912 init_waitqueue_head(&root->log_commit_wait[0]); 911 init_waitqueue_head(&root->log_commit_wait[0]);
913 init_waitqueue_head(&root->log_commit_wait[1]); 912 init_waitqueue_head(&root->log_commit_wait[1]);
@@ -1624,6 +1623,7 @@ struct btrfs_root *open_ctree(struct super_block *sb,
1624 mutex_init(&fs_info->cleaner_mutex); 1623 mutex_init(&fs_info->cleaner_mutex);
1625 mutex_init(&fs_info->volume_mutex); 1624 mutex_init(&fs_info->volume_mutex);
1626 mutex_init(&fs_info->tree_reloc_mutex); 1625 mutex_init(&fs_info->tree_reloc_mutex);
1626 init_rwsem(&fs_info->extent_commit_sem);
1627 1627
1628 btrfs_init_free_cluster(&fs_info->meta_alloc_cluster); 1628 btrfs_init_free_cluster(&fs_info->meta_alloc_cluster);
1629 btrfs_init_free_cluster(&fs_info->data_alloc_cluster); 1629 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..2fe21fa74913 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);
268again: 268again:
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
@@ -304,7 +304,7 @@ again:
304 304
305 if (need_resched()) { 305 if (need_resched()) {
306 btrfs_release_path(fs_info->extent_root, path); 306 btrfs_release_path(fs_info->extent_root, path);
307 up_read(&fs_info->extent_root->commit_root_sem); 307 up_read(&fs_info->extent_commit_sem);
308 cond_resched(); 308 cond_resched();
309 goto again; 309 goto again;
310 } 310 }
@@ -345,7 +345,7 @@ next:
345 345
346err: 346err:
347 btrfs_free_path(path); 347 btrfs_free_path(path);
348 up_read(&fs_info->extent_root->commit_root_sem); 348 up_read(&fs_info->extent_commit_sem);
349 atomic_dec(&block_group->space_info->caching_threads); 349 atomic_dec(&block_group->space_info->caching_threads);
350 wake_up(&block_group->caching_q); 350 wake_up(&block_group->caching_q);
351 351
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index e51d2bc532f8..de48e4ec808c 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
43static noinline void switch_commit_root(struct btrfs_root *root) 43static 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