diff options
Diffstat (limited to 'fs/btrfs/disk-io.c')
| -rw-r--r-- | fs/btrfs/disk-io.c | 27 | 
1 files changed, 18 insertions, 9 deletions
| diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 02b6afbd745..009e3bd18f2 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -892,6 +892,8 @@ static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize,  	root->stripesize = stripesize;  	root->ref_cows = 0;  	root->track_dirty = 0; +	root->in_radix = 0; +	root->clean_orphans = 0;  	root->fs_info = fs_info;  	root->objectid = objectid; @@ -928,7 +930,6 @@ static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize,  	root->defrag_trans_start = fs_info->generation;  	init_completion(&root->kobj_unregister);  	root->defrag_running = 0; -	root->defrag_level = 0;  	root->root_key.objectid = objectid;  	root->anon_super.s_root = NULL;  	root->anon_super.s_dev = 0; @@ -980,12 +981,12 @@ int btrfs_free_log_root_tree(struct btrfs_trans_handle *trans,  	while (1) {  		ret = find_first_extent_bit(&log_root_tree->dirty_log_pages, -				    0, &start, &end, EXTENT_DIRTY); +				0, &start, &end, EXTENT_DIRTY | EXTENT_NEW);  		if (ret)  			break; -		clear_extent_dirty(&log_root_tree->dirty_log_pages, -				   start, end, GFP_NOFS); +		clear_extent_bits(&log_root_tree->dirty_log_pages, start, end, +				  EXTENT_DIRTY | EXTENT_NEW, GFP_NOFS);  	}  	eb = fs_info->log_root_tree->node; @@ -1210,8 +1211,10 @@ again:  	ret = radix_tree_insert(&fs_info->fs_roots_radix,  				(unsigned long)root->root_key.objectid,  				root); -	if (ret == 0) +	if (ret == 0) {  		root->in_radix = 1; +		root->clean_orphans = 1; +	}  	spin_unlock(&fs_info->fs_roots_radix_lock);  	radix_tree_preload_end();  	if (ret) { @@ -1225,10 +1228,6 @@ again:  	ret = btrfs_find_dead_roots(fs_info->tree_root,  				    root->root_key.objectid);  	WARN_ON(ret); - -	if (!(fs_info->sb->s_flags & MS_RDONLY)) -		btrfs_orphan_cleanup(root); -  	return root;  fail:  	free_fs_root(root); @@ -1477,6 +1476,7 @@ static int cleaner_kthread(void *arg)  		if (!(root->fs_info->sb->s_flags & MS_RDONLY) &&  		    mutex_trylock(&root->fs_info->cleaner_mutex)) { +			btrfs_run_delayed_iputs(root);  			btrfs_clean_old_snapshots(root);  			mutex_unlock(&root->fs_info->cleaner_mutex);  		} @@ -1606,6 +1606,7 @@ struct btrfs_root *open_ctree(struct super_block *sb,  	INIT_RADIX_TREE(&fs_info->fs_roots_radix, GFP_ATOMIC);  	INIT_LIST_HEAD(&fs_info->trans_list);  	INIT_LIST_HEAD(&fs_info->dead_roots); +	INIT_LIST_HEAD(&fs_info->delayed_iputs);  	INIT_LIST_HEAD(&fs_info->hashers);  	INIT_LIST_HEAD(&fs_info->delalloc_inodes);  	INIT_LIST_HEAD(&fs_info->ordered_operations); @@ -1614,6 +1615,7 @@ struct btrfs_root *open_ctree(struct super_block *sb,  	spin_lock_init(&fs_info->new_trans_lock);  	spin_lock_init(&fs_info->ref_cache_lock);  	spin_lock_init(&fs_info->fs_roots_radix_lock); +	spin_lock_init(&fs_info->delayed_iput_lock);  	init_completion(&fs_info->kobj_unregister);  	fs_info->tree_root = tree_root; @@ -1689,6 +1691,7 @@ struct btrfs_root *open_ctree(struct super_block *sb,  	mutex_init(&fs_info->cleaner_mutex);  	mutex_init(&fs_info->volume_mutex);  	init_rwsem(&fs_info->extent_commit_sem); +	init_rwsem(&fs_info->cleanup_work_sem);  	init_rwsem(&fs_info->subvol_sem);  	btrfs_init_free_cluster(&fs_info->meta_alloc_cluster); @@ -2386,8 +2389,14 @@ int btrfs_commit_super(struct btrfs_root *root)  	int ret;  	mutex_lock(&root->fs_info->cleaner_mutex); +	btrfs_run_delayed_iputs(root);  	btrfs_clean_old_snapshots(root);  	mutex_unlock(&root->fs_info->cleaner_mutex); + +	/* wait until ongoing cleanup work done */ +	down_write(&root->fs_info->cleanup_work_sem); +	up_write(&root->fs_info->cleanup_work_sem); +  	trans = btrfs_start_transaction(root, 1);  	ret = btrfs_commit_transaction(trans, root);  	BUG_ON(ret); | 
