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>

authored by Yan Zheng and committed by Chris Mason 276e680d f25784b3

+14 -10
+1 -3
fs/btrfs/ctree.h
··· 827 struct mutex drop_mutex; 828 struct mutex volume_mutex; 829 struct mutex tree_reloc_mutex; 830 831 /* 832 * this protects the ordered operations list only while we are ··· 961 962 /* the node lock is held while changing the node pointer */ 963 spinlock_t node_lock; 964 - 965 - /* taken when updating the commit root */ 966 - struct rw_semaphore commit_root_sem; 967 968 struct extent_buffer *commit_root; 969 struct btrfs_root *log_root;
··· 827 struct mutex drop_mutex; 828 struct mutex volume_mutex; 829 struct mutex tree_reloc_mutex; 830 + struct rw_semaphore extent_commit_sem; 831 832 /* 833 * this protects the ordered operations list only while we are ··· 960 961 /* the node lock is held while changing the node pointer */ 962 spinlock_t node_lock; 963 964 struct extent_buffer *commit_root; 965 struct btrfs_root *log_root;
+1 -1
fs/btrfs/disk-io.c
··· 907 spin_lock_init(&root->inode_lock); 908 mutex_init(&root->objectid_mutex); 909 mutex_init(&root->log_mutex); 910 - init_rwsem(&root->commit_root_sem); 911 init_waitqueue_head(&root->log_writer_wait); 912 init_waitqueue_head(&root->log_commit_wait[0]); 913 init_waitqueue_head(&root->log_commit_wait[1]); ··· 1623 mutex_init(&fs_info->cleaner_mutex); 1624 mutex_init(&fs_info->volume_mutex); 1625 mutex_init(&fs_info->tree_reloc_mutex); 1626 1627 btrfs_init_free_cluster(&fs_info->meta_alloc_cluster); 1628 btrfs_init_free_cluster(&fs_info->data_alloc_cluster);
··· 907 spin_lock_init(&root->inode_lock); 908 mutex_init(&root->objectid_mutex); 909 mutex_init(&root->log_mutex); 910 init_waitqueue_head(&root->log_writer_wait); 911 init_waitqueue_head(&root->log_commit_wait[0]); 912 init_waitqueue_head(&root->log_commit_wait[1]); ··· 1624 mutex_init(&fs_info->cleaner_mutex); 1625 mutex_init(&fs_info->volume_mutex); 1626 mutex_init(&fs_info->tree_reloc_mutex); 1627 + init_rwsem(&fs_info->extent_commit_sem); 1628 1629 btrfs_init_free_cluster(&fs_info->meta_alloc_cluster); 1630 btrfs_init_free_cluster(&fs_info->data_alloc_cluster);
+3 -3
fs/btrfs/extent-tree.c
··· 267 last = max_t(u64, block_group->key.objectid, BTRFS_SUPER_INFO_OFFSET); 268 again: 269 /* need to make sure the commit_root doesn't disappear */ 270 - down_read(&fs_info->extent_root->commit_root_sem); 271 272 /* 273 * We don't want to deadlock with somebody trying to allocate a new ··· 304 305 if (need_resched()) { 306 btrfs_release_path(fs_info->extent_root, path); 307 - up_read(&fs_info->extent_root->commit_root_sem); 308 cond_resched(); 309 goto again; 310 } ··· 345 346 err: 347 btrfs_free_path(path); 348 - up_read(&fs_info->extent_root->commit_root_sem); 349 atomic_dec(&block_group->space_info->caching_threads); 350 wake_up(&block_group->caching_q); 351
··· 267 last = max_t(u64, block_group->key.objectid, BTRFS_SUPER_INFO_OFFSET); 268 again: 269 /* need to make sure the commit_root doesn't disappear */ 270 + down_read(&fs_info->extent_commit_sem); 271 272 /* 273 * We don't want to deadlock with somebody trying to allocate a new ··· 304 305 if (need_resched()) { 306 btrfs_release_path(fs_info->extent_root, path); 307 + up_read(&fs_info->extent_commit_sem); 308 cond_resched(); 309 goto again; 310 } ··· 345 346 err: 347 btrfs_free_path(path); 348 + up_read(&fs_info->extent_commit_sem); 349 atomic_dec(&block_group->space_info->caching_threads); 350 wake_up(&block_group->caching_q); 351
+9 -3
fs/btrfs/transaction.c
··· 42 43 static noinline void switch_commit_root(struct btrfs_root *root) 44 { 45 - down_write(&root->commit_root_sem); 46 free_extent_buffer(root->commit_root); 47 root->commit_root = btrfs_root_node(root); 48 - up_write(&root->commit_root_sem); 49 } 50 51 /* ··· 464 ret = btrfs_write_dirty_block_groups(trans, root); 465 BUG_ON(ret); 466 } 467 - switch_commit_root(root); 468 return 0; 469 } 470 ··· 500 501 update_cowonly_root(trans, root); 502 } 503 return 0; 504 } 505
··· 42 43 static noinline void switch_commit_root(struct btrfs_root *root) 44 { 45 free_extent_buffer(root->commit_root); 46 root->commit_root = btrfs_root_node(root); 47 } 48 49 /* ··· 466 ret = btrfs_write_dirty_block_groups(trans, root); 467 BUG_ON(ret); 468 } 469 + 470 + if (root != root->fs_info->extent_root) 471 + switch_commit_root(root); 472 + 473 return 0; 474 } 475 ··· 499 500 update_cowonly_root(trans, root); 501 } 502 + 503 + down_write(&fs_info->extent_commit_sem); 504 + switch_commit_root(fs_info->extent_root); 505 + up_write(&fs_info->extent_commit_sem); 506 + 507 return 0; 508 } 509