static noinline void switch_commit_roots(struct btrfs_trans_handle *trans)
{
	struct btrfs_transaction *cur_trans = trans->transaction;
	struct btrfs_fs_info *fs_info = trans->fs_info;
	struct btrfs_root *root, *tmp;
	struct btrfs_caching_control *caching_ctl, *next;

	down_write(&fs_info->commit_root_sem);
	list_for_each_entry_safe(root, tmp, &cur_trans->switch_commits,
				 dirty_list) {
		list_del_init(&root->dirty_list);
		free_extent_buffer(root->commit_root);
		root->commit_root = btrfs_root_node(root);
		extent_io_tree_release(&root->dirty_log_pages);
		btrfs_qgroup_clean_swapped_blocks(root);
	}

	/* We can free old roots now. */
	spin_lock(&cur_trans->dropped_roots_lock);
	while (!list_empty(&cur_trans->dropped_roots)) {
		root = list_first_entry(&cur_trans->dropped_roots,
					struct btrfs_root, root_list);
		list_del_init(&root->root_list);
		spin_unlock(&cur_trans->dropped_roots_lock);
		btrfs_free_log(trans, root);
		btrfs_drop_and_free_fs_root(fs_info, root);
		spin_lock(&cur_trans->dropped_roots_lock);
	}
	spin_unlock(&cur_trans->dropped_roots_lock);

	/*
	 * We have to update the last_byte_to_unpin under the commit_root_sem,
	 * at the same time we swap out the commit roots.
	 *
	 * This is because we must have a real view of the last spot the caching
	 * kthreads were while caching.  Consider the following views of the
	 * extent tree for a block group
	 *
	 * commit root
	 * +----+----+----+----+----+----+----+
	 * |\\\\|    |\\\\|\\\\|    |\\\\|\\\\|
	 * +----+----+----+----+----+----+----+
	 * 0    1    2    3    4    5    6    7
	 *
	 * new commit root
	 * +----+----+----+----+----+----+----+
	 * |    |    |    |\\\\|    |    |\\\\|
	 * +----+----+----+----+----+----+----+
	 * 0    1    2    3    4    5    6    7
	 *
	 * If the cache_ctl->progress was at 3, then we are only allowed to
	 * unpin [0,1) and [2,3], because the caching thread has already
	 * processed those extents.  We are not allowed to unpin [5,6), because
	 * the caching thread will re-start it's search from 3, and thus find
	 * the hole from [4,6) to add to the free space cache.
	 */
	spin_lock(&fs_info->block_group_cache_lock);
	list_for_each_entry_safe(caching_ctl, next,
				 &fs_info->caching_block_groups, list) {
		struct btrfs_block_group *cache = caching_ctl->block_group;

		if (btrfs_block_group_done(cache)) {
			cache->last_byte_to_unpin = (u64)-1;
			list_del_init(&caching_ctl->list);
			btrfs_put_caching_control(caching_ctl);
		} else {
			cache->last_byte_to_unpin = caching_ctl->progress;
		}
	}
	spin_unlock(&fs_info->block_group_cache_lock);
	up_write(&fs_info->commit_root_sem);
}
static noinline void switch_commit_roots(struct btrfs_trans_handle *trans)
{
	struct btrfs_transaction *cur_trans = trans->transaction;
	struct btrfs_fs_info *fs_info = trans->fs_info;
	struct btrfs_root *root, *tmp;
	struct btrfs_caching_control *caching_ctl, *next;

	down_write(&fs_info->commit_root_sem);
	list_for_each_entry_safe(root, tmp, &cur_trans->switch_commits,
				 dirty_list) {
		list_del_init(&root->dirty_list);
		free_extent_buffer(root->commit_root);
		root->commit_root = btrfs_root_node(root);
		extent_io_tree_release(&root->dirty_log_pages);
		btrfs_qgroup_clean_swapped_blocks(root);
	}

	 
	spin_lock(&cur_trans->dropped_roots_lock);
	while (!list_empty(&cur_trans->dropped_roots)) {
		root = list_first_entry(&cur_trans->dropped_roots,
					struct btrfs_root, root_list);
		list_del_init(&root->root_list);
		spin_unlock(&cur_trans->dropped_roots_lock);
		btrfs_free_log(trans, root);
		btrfs_drop_and_free_fs_root(fs_info, root);
		spin_lock(&cur_trans->dropped_roots_lock);
	}
	spin_unlock(&cur_trans->dropped_roots_lock);

	 
	spin_lock(&fs_info->block_group_cache_lock);
	list_for_each_entry_safe(caching_ctl, next,
				 &fs_info->caching_block_groups, list) {
		struct btrfs_block_group *cache = caching_ctl->block_group;

		if (btrfs_block_group_done(cache)) {
			cache->last_byte_to_unpin = (u64)-1;
			list_del_init(&caching_ctl->list);
			btrfs_put_caching_control(caching_ctl);
		} else {
			cache->last_byte_to_unpin = caching_ctl->progress;
		}
	}
	spin_unlock(&fs_info->block_group_cache_lock);
	up_write(&fs_info->commit_root_sem);
}