mirror of
				https://github.com/torvalds/linux.git
				synced 2025-10-31 08:38:45 +02:00 
			
		
		
		
	btrfs: kill the subvol_srcu
Now that we have proper root ref counting everywhere we can kill the subvol_srcu. * removal of fs_info::subvol_srcu reduces size of fs_info by 1176 bytes * the refcount_t used for the references checks for accidental 0->1 in cases where the root lifetime would not be properly protected * there's a leak detector for roots to catch unfreed roots at umount time * SRCU served us well over the years but is was not a proper synchronization mechanism for some cases Signed-off-by: Josef Bacik <josef@toxicpanda.com> Reviewed-by: David Sterba <dsterba@suse.com> [ update changelog ] Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
		
							parent
							
								
									efc3453494
								
							
						
					
					
						commit
						c75e839414
					
				
					 8 changed files with 14 additions and 88 deletions
				
			
		|  | @ -542,24 +542,19 @@ static int resolve_indirect_ref(struct btrfs_fs_info *fs_info, | ||||||
| 	int ret = 0; | 	int ret = 0; | ||||||
| 	int root_level; | 	int root_level; | ||||||
| 	int level = ref->level; | 	int level = ref->level; | ||||||
| 	int index; |  | ||||||
| 	struct btrfs_key search_key = ref->key_for_search; | 	struct btrfs_key search_key = ref->key_for_search; | ||||||
| 
 | 
 | ||||||
| 	root_key.objectid = ref->root_id; | 	root_key.objectid = ref->root_id; | ||||||
| 	root_key.type = BTRFS_ROOT_ITEM_KEY; | 	root_key.type = BTRFS_ROOT_ITEM_KEY; | ||||||
| 	root_key.offset = (u64)-1; | 	root_key.offset = (u64)-1; | ||||||
| 
 | 
 | ||||||
| 	index = srcu_read_lock(&fs_info->subvol_srcu); |  | ||||||
| 
 |  | ||||||
| 	root = btrfs_get_fs_root(fs_info, &root_key, false); | 	root = btrfs_get_fs_root(fs_info, &root_key, false); | ||||||
| 	if (IS_ERR(root)) { | 	if (IS_ERR(root)) { | ||||||
| 		srcu_read_unlock(&fs_info->subvol_srcu, index); |  | ||||||
| 		ret = PTR_ERR(root); | 		ret = PTR_ERR(root); | ||||||
| 		goto out_free; | 		goto out_free; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (btrfs_is_testing(fs_info)) { | 	if (btrfs_is_testing(fs_info)) { | ||||||
| 		srcu_read_unlock(&fs_info->subvol_srcu, index); |  | ||||||
| 		ret = -ENOENT; | 		ret = -ENOENT; | ||||||
| 		goto out; | 		goto out; | ||||||
| 	} | 	} | ||||||
|  | @ -571,10 +566,8 @@ static int resolve_indirect_ref(struct btrfs_fs_info *fs_info, | ||||||
| 	else | 	else | ||||||
| 		root_level = btrfs_old_root_level(root, time_seq); | 		root_level = btrfs_old_root_level(root, time_seq); | ||||||
| 
 | 
 | ||||||
| 	if (root_level + 1 == level) { | 	if (root_level + 1 == level) | ||||||
| 		srcu_read_unlock(&fs_info->subvol_srcu, index); |  | ||||||
| 		goto out; | 		goto out; | ||||||
| 	} |  | ||||||
| 
 | 
 | ||||||
| 	/*
 | 	/*
 | ||||||
| 	 * We can often find data backrefs with an offset that is too large | 	 * We can often find data backrefs with an offset that is too large | ||||||
|  | @ -604,9 +597,6 @@ static int resolve_indirect_ref(struct btrfs_fs_info *fs_info, | ||||||
| 	else | 	else | ||||||
| 		ret = btrfs_search_old_slot(root, &search_key, path, time_seq); | 		ret = btrfs_search_old_slot(root, &search_key, path, time_seq); | ||||||
| 
 | 
 | ||||||
| 	/* root node has been locked, we can release @subvol_srcu safely here */ |  | ||||||
| 	srcu_read_unlock(&fs_info->subvol_srcu, index); |  | ||||||
| 
 |  | ||||||
| 	btrfs_debug(fs_info, | 	btrfs_debug(fs_info, | ||||||
| 		"search slot in root %llu (level %d, ref count %d) returned %d for key (%llu %u %llu)", | 		"search slot in root %llu (level %d, ref count %d) returned %d for key (%llu %u %llu)", | ||||||
| 		 ref->root_id, level, ref->count, ret, | 		 ref->root_id, level, ref->count, ret, | ||||||
|  |  | ||||||
|  | @ -697,7 +697,6 @@ struct btrfs_fs_info { | ||||||
| 	struct rw_semaphore cleanup_work_sem; | 	struct rw_semaphore cleanup_work_sem; | ||||||
| 
 | 
 | ||||||
| 	struct rw_semaphore subvol_sem; | 	struct rw_semaphore subvol_sem; | ||||||
| 	struct srcu_struct subvol_srcu; |  | ||||||
| 
 | 
 | ||||||
| 	spinlock_t trans_lock; | 	spinlock_t trans_lock; | ||||||
| 	/*
 | 	/*
 | ||||||
|  |  | ||||||
|  | @ -2757,46 +2757,33 @@ static int init_mount_fs_info(struct btrfs_fs_info *fs_info, struct super_block | ||||||
| 	sb->s_blocksize = BTRFS_BDEV_BLOCKSIZE; | 	sb->s_blocksize = BTRFS_BDEV_BLOCKSIZE; | ||||||
| 	sb->s_blocksize_bits = blksize_bits(BTRFS_BDEV_BLOCKSIZE); | 	sb->s_blocksize_bits = blksize_bits(BTRFS_BDEV_BLOCKSIZE); | ||||||
| 
 | 
 | ||||||
| 	ret = init_srcu_struct(&fs_info->subvol_srcu); | 	ret = percpu_counter_init(&fs_info->dio_bytes, 0, GFP_KERNEL); | ||||||
| 	if (ret) | 	if (ret) | ||||||
| 		return ret; | 		return ret; | ||||||
| 
 | 
 | ||||||
| 	ret = percpu_counter_init(&fs_info->dio_bytes, 0, GFP_KERNEL); |  | ||||||
| 	if (ret) |  | ||||||
| 		goto fail; |  | ||||||
| 
 |  | ||||||
| 	ret = percpu_counter_init(&fs_info->dirty_metadata_bytes, 0, GFP_KERNEL); | 	ret = percpu_counter_init(&fs_info->dirty_metadata_bytes, 0, GFP_KERNEL); | ||||||
| 	if (ret) | 	if (ret) | ||||||
| 		goto fail; | 		return ret; | ||||||
| 
 | 
 | ||||||
| 	fs_info->dirty_metadata_batch = PAGE_SIZE * | 	fs_info->dirty_metadata_batch = PAGE_SIZE * | ||||||
| 					(1 + ilog2(nr_cpu_ids)); | 					(1 + ilog2(nr_cpu_ids)); | ||||||
| 
 | 
 | ||||||
| 	ret = percpu_counter_init(&fs_info->delalloc_bytes, 0, GFP_KERNEL); | 	ret = percpu_counter_init(&fs_info->delalloc_bytes, 0, GFP_KERNEL); | ||||||
| 	if (ret) | 	if (ret) | ||||||
| 		goto fail; | 		return ret; | ||||||
| 
 | 
 | ||||||
| 	ret = percpu_counter_init(&fs_info->dev_replace.bio_counter, 0, | 	ret = percpu_counter_init(&fs_info->dev_replace.bio_counter, 0, | ||||||
| 			GFP_KERNEL); | 			GFP_KERNEL); | ||||||
| 	if (ret) | 	if (ret) | ||||||
| 		goto fail; | 		return ret; | ||||||
| 
 | 
 | ||||||
| 	fs_info->delayed_root = kmalloc(sizeof(struct btrfs_delayed_root), | 	fs_info->delayed_root = kmalloc(sizeof(struct btrfs_delayed_root), | ||||||
| 					GFP_KERNEL); | 					GFP_KERNEL); | ||||||
| 	if (!fs_info->delayed_root) { | 	if (!fs_info->delayed_root) | ||||||
| 		ret = -ENOMEM; | 		return -ENOMEM; | ||||||
| 		goto fail; |  | ||||||
| 	} |  | ||||||
| 	btrfs_init_delayed_root(fs_info->delayed_root); | 	btrfs_init_delayed_root(fs_info->delayed_root); | ||||||
| 
 | 
 | ||||||
| 	ret = btrfs_alloc_stripe_hash_table(fs_info); | 	return btrfs_alloc_stripe_hash_table(fs_info); | ||||||
| 	if (ret) |  | ||||||
| 		goto fail; |  | ||||||
| 
 |  | ||||||
| 	return 0; |  | ||||||
| fail: |  | ||||||
| 	cleanup_srcu_struct(&fs_info->subvol_srcu); |  | ||||||
| 	return ret; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int btrfs_uuid_rescan_kthread(void *data) | static int btrfs_uuid_rescan_kthread(void *data) | ||||||
|  | @ -2870,13 +2857,13 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device | ||||||
| 	fs_info->chunk_root = chunk_root; | 	fs_info->chunk_root = chunk_root; | ||||||
| 	if (!tree_root || !chunk_root) { | 	if (!tree_root || !chunk_root) { | ||||||
| 		err = -ENOMEM; | 		err = -ENOMEM; | ||||||
| 		goto fail_srcu; | 		goto fail; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	fs_info->btree_inode = new_inode(sb); | 	fs_info->btree_inode = new_inode(sb); | ||||||
| 	if (!fs_info->btree_inode) { | 	if (!fs_info->btree_inode) { | ||||||
| 		err = -ENOMEM; | 		err = -ENOMEM; | ||||||
| 		goto fail_srcu; | 		goto fail; | ||||||
| 	} | 	} | ||||||
| 	mapping_set_gfp_mask(fs_info->btree_inode->i_mapping, GFP_NOFS); | 	mapping_set_gfp_mask(fs_info->btree_inode->i_mapping, GFP_NOFS); | ||||||
| 	btrfs_init_btree_inode(fs_info); | 	btrfs_init_btree_inode(fs_info); | ||||||
|  | @ -3398,8 +3385,6 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device | ||||||
| 	btrfs_mapping_tree_free(&fs_info->mapping_tree); | 	btrfs_mapping_tree_free(&fs_info->mapping_tree); | ||||||
| 
 | 
 | ||||||
| 	iput(fs_info->btree_inode); | 	iput(fs_info->btree_inode); | ||||||
| fail_srcu: |  | ||||||
| 	cleanup_srcu_struct(&fs_info->subvol_srcu); |  | ||||||
| fail: | fail: | ||||||
| 	btrfs_close_devices(fs_info->fs_devices); | 	btrfs_close_devices(fs_info->fs_devices); | ||||||
| 	return err; | 	return err; | ||||||
|  | @ -3902,9 +3887,6 @@ void btrfs_drop_and_free_fs_root(struct btrfs_fs_info *fs_info, | ||||||
| 		drop_ref = true; | 		drop_ref = true; | ||||||
| 	spin_unlock(&fs_info->fs_roots_radix_lock); | 	spin_unlock(&fs_info->fs_roots_radix_lock); | ||||||
| 
 | 
 | ||||||
| 	if (btrfs_root_refs(&root->root_item) == 0) |  | ||||||
| 		synchronize_srcu(&fs_info->subvol_srcu); |  | ||||||
| 
 |  | ||||||
| 	if (test_bit(BTRFS_FS_STATE_ERROR, &fs_info->fs_state)) { | 	if (test_bit(BTRFS_FS_STATE_ERROR, &fs_info->fs_state)) { | ||||||
| 		btrfs_free_log(NULL, root); | 		btrfs_free_log(NULL, root); | ||||||
| 		if (root->reloc_root) { | 		if (root->reloc_root) { | ||||||
|  | @ -4116,7 +4098,6 @@ void __cold close_ctree(struct btrfs_fs_info *fs_info) | ||||||
| 
 | 
 | ||||||
| 	btrfs_mapping_tree_free(&fs_info->mapping_tree); | 	btrfs_mapping_tree_free(&fs_info->mapping_tree); | ||||||
| 	btrfs_close_devices(fs_info->fs_devices); | 	btrfs_close_devices(fs_info->fs_devices); | ||||||
| 	cleanup_srcu_struct(&fs_info->subvol_srcu); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid, | int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid, | ||||||
|  |  | ||||||
|  | @ -65,8 +65,6 @@ struct dentry *btrfs_get_dentry(struct super_block *sb, u64 objectid, | ||||||
| 	struct btrfs_root *root; | 	struct btrfs_root *root; | ||||||
| 	struct inode *inode; | 	struct inode *inode; | ||||||
| 	struct btrfs_key key; | 	struct btrfs_key key; | ||||||
| 	int index; |  | ||||||
| 	int err = 0; |  | ||||||
| 
 | 
 | ||||||
| 	if (objectid < BTRFS_FIRST_FREE_OBJECTID) | 	if (objectid < BTRFS_FIRST_FREE_OBJECTID) | ||||||
| 		return ERR_PTR(-ESTALE); | 		return ERR_PTR(-ESTALE); | ||||||
|  | @ -75,13 +73,9 @@ struct dentry *btrfs_get_dentry(struct super_block *sb, u64 objectid, | ||||||
| 	key.type = BTRFS_ROOT_ITEM_KEY; | 	key.type = BTRFS_ROOT_ITEM_KEY; | ||||||
| 	key.offset = (u64)-1; | 	key.offset = (u64)-1; | ||||||
| 
 | 
 | ||||||
| 	index = srcu_read_lock(&fs_info->subvol_srcu); |  | ||||||
| 
 |  | ||||||
| 	root = btrfs_get_fs_root(fs_info, &key, true); | 	root = btrfs_get_fs_root(fs_info, &key, true); | ||||||
| 	if (IS_ERR(root)) { | 	if (IS_ERR(root)) | ||||||
| 		err = PTR_ERR(root); | 		return ERR_CAST(root); | ||||||
| 		goto fail; |  | ||||||
| 	} |  | ||||||
| 
 | 
 | ||||||
| 	key.objectid = objectid; | 	key.objectid = objectid; | ||||||
| 	key.type = BTRFS_INODE_ITEM_KEY; | 	key.type = BTRFS_INODE_ITEM_KEY; | ||||||
|  | @ -89,12 +83,8 @@ struct dentry *btrfs_get_dentry(struct super_block *sb, u64 objectid, | ||||||
| 
 | 
 | ||||||
| 	inode = btrfs_iget(sb, &key, root); | 	inode = btrfs_iget(sb, &key, root); | ||||||
| 	btrfs_put_root(root); | 	btrfs_put_root(root); | ||||||
| 	if (IS_ERR(inode)) { | 	if (IS_ERR(inode)) | ||||||
| 		err = PTR_ERR(inode); | 		return ERR_CAST(inode); | ||||||
| 		goto fail; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	srcu_read_unlock(&fs_info->subvol_srcu, index); |  | ||||||
| 
 | 
 | ||||||
| 	if (check_generation && generation != inode->i_generation) { | 	if (check_generation && generation != inode->i_generation) { | ||||||
| 		iput(inode); | 		iput(inode); | ||||||
|  | @ -102,9 +92,6 @@ struct dentry *btrfs_get_dentry(struct super_block *sb, u64 objectid, | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return d_obtain_alias(inode); | 	return d_obtain_alias(inode); | ||||||
| fail: |  | ||||||
| 	srcu_read_unlock(&fs_info->subvol_srcu, index); |  | ||||||
| 	return ERR_PTR(err); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static struct dentry *btrfs_fh_to_parent(struct super_block *sb, struct fid *fh, | static struct dentry *btrfs_fh_to_parent(struct super_block *sb, struct fid *fh, | ||||||
|  |  | ||||||
|  | @ -278,7 +278,6 @@ static int __btrfs_run_defrag_inode(struct btrfs_fs_info *fs_info, | ||||||
| 	struct btrfs_key key; | 	struct btrfs_key key; | ||||||
| 	struct btrfs_ioctl_defrag_range_args range; | 	struct btrfs_ioctl_defrag_range_args range; | ||||||
| 	int num_defrag; | 	int num_defrag; | ||||||
| 	int index; |  | ||||||
| 	int ret; | 	int ret; | ||||||
| 
 | 
 | ||||||
| 	/* get the inode */ | 	/* get the inode */ | ||||||
|  | @ -286,8 +285,6 @@ static int __btrfs_run_defrag_inode(struct btrfs_fs_info *fs_info, | ||||||
| 	key.type = BTRFS_ROOT_ITEM_KEY; | 	key.type = BTRFS_ROOT_ITEM_KEY; | ||||||
| 	key.offset = (u64)-1; | 	key.offset = (u64)-1; | ||||||
| 
 | 
 | ||||||
| 	index = srcu_read_lock(&fs_info->subvol_srcu); |  | ||||||
| 
 |  | ||||||
| 	inode_root = btrfs_get_fs_root(fs_info, &key, true); | 	inode_root = btrfs_get_fs_root(fs_info, &key, true); | ||||||
| 	if (IS_ERR(inode_root)) { | 	if (IS_ERR(inode_root)) { | ||||||
| 		ret = PTR_ERR(inode_root); | 		ret = PTR_ERR(inode_root); | ||||||
|  | @ -303,7 +300,6 @@ static int __btrfs_run_defrag_inode(struct btrfs_fs_info *fs_info, | ||||||
| 		ret = PTR_ERR(inode); | 		ret = PTR_ERR(inode); | ||||||
| 		goto cleanup; | 		goto cleanup; | ||||||
| 	} | 	} | ||||||
| 	srcu_read_unlock(&fs_info->subvol_srcu, index); |  | ||||||
| 
 | 
 | ||||||
| 	/* do a chunk of defrag */ | 	/* do a chunk of defrag */ | ||||||
| 	clear_bit(BTRFS_INODE_IN_DEFRAG, &BTRFS_I(inode)->runtime_flags); | 	clear_bit(BTRFS_INODE_IN_DEFRAG, &BTRFS_I(inode)->runtime_flags); | ||||||
|  | @ -339,7 +335,6 @@ static int __btrfs_run_defrag_inode(struct btrfs_fs_info *fs_info, | ||||||
| 	iput(inode); | 	iput(inode); | ||||||
| 	return 0; | 	return 0; | ||||||
| cleanup: | cleanup: | ||||||
| 	srcu_read_unlock(&fs_info->subvol_srcu, index); |  | ||||||
| 	kmem_cache_free(btrfs_inode_defrag_cachep, defrag); | 	kmem_cache_free(btrfs_inode_defrag_cachep, defrag); | ||||||
| 	return ret; | 	return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -5364,7 +5364,6 @@ struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry) | ||||||
| 	struct btrfs_root *sub_root = root; | 	struct btrfs_root *sub_root = root; | ||||||
| 	struct btrfs_key location; | 	struct btrfs_key location; | ||||||
| 	u8 di_type = 0; | 	u8 di_type = 0; | ||||||
| 	int index; |  | ||||||
| 	int ret = 0; | 	int ret = 0; | ||||||
| 
 | 
 | ||||||
| 	if (dentry->d_name.len > BTRFS_NAME_LEN) | 	if (dentry->d_name.len > BTRFS_NAME_LEN) | ||||||
|  | @ -5391,7 +5390,6 @@ struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry) | ||||||
| 		return inode; | 		return inode; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	index = srcu_read_lock(&fs_info->subvol_srcu); |  | ||||||
| 	ret = fixup_tree_root_location(fs_info, dir, dentry, | 	ret = fixup_tree_root_location(fs_info, dir, dentry, | ||||||
| 				       &location, &sub_root); | 				       &location, &sub_root); | ||||||
| 	if (ret < 0) { | 	if (ret < 0) { | ||||||
|  | @ -5404,7 +5402,6 @@ struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry) | ||||||
| 	} | 	} | ||||||
| 	if (root != sub_root) | 	if (root != sub_root) | ||||||
| 		btrfs_put_root(sub_root); | 		btrfs_put_root(sub_root); | ||||||
| 	srcu_read_unlock(&fs_info->subvol_srcu, index); |  | ||||||
| 
 | 
 | ||||||
| 	if (!IS_ERR(inode) && root != sub_root) { | 	if (!IS_ERR(inode) && root != sub_root) { | ||||||
| 		down_read(&fs_info->cleanup_work_sem); | 		down_read(&fs_info->cleanup_work_sem); | ||||||
|  |  | ||||||
|  | @ -7028,7 +7028,6 @@ long btrfs_ioctl_send(struct file *mnt_file, struct btrfs_ioctl_send_args *arg) | ||||||
| 	int clone_sources_to_rollback = 0; | 	int clone_sources_to_rollback = 0; | ||||||
| 	unsigned alloc_size; | 	unsigned alloc_size; | ||||||
| 	int sort_clone_roots = 0; | 	int sort_clone_roots = 0; | ||||||
| 	int index; |  | ||||||
| 
 | 
 | ||||||
| 	if (!capable(CAP_SYS_ADMIN)) | 	if (!capable(CAP_SYS_ADMIN)) | ||||||
| 		return -EPERM; | 		return -EPERM; | ||||||
|  | @ -7155,11 +7154,8 @@ long btrfs_ioctl_send(struct file *mnt_file, struct btrfs_ioctl_send_args *arg) | ||||||
| 			key.type = BTRFS_ROOT_ITEM_KEY; | 			key.type = BTRFS_ROOT_ITEM_KEY; | ||||||
| 			key.offset = (u64)-1; | 			key.offset = (u64)-1; | ||||||
| 
 | 
 | ||||||
| 			index = srcu_read_lock(&fs_info->subvol_srcu); |  | ||||||
| 
 |  | ||||||
| 			clone_root = btrfs_get_fs_root(fs_info, &key, true); | 			clone_root = btrfs_get_fs_root(fs_info, &key, true); | ||||||
| 			if (IS_ERR(clone_root)) { | 			if (IS_ERR(clone_root)) { | ||||||
| 				srcu_read_unlock(&fs_info->subvol_srcu, index); |  | ||||||
| 				ret = PTR_ERR(clone_root); | 				ret = PTR_ERR(clone_root); | ||||||
| 				goto out; | 				goto out; | ||||||
| 			} | 			} | ||||||
|  | @ -7168,7 +7164,6 @@ long btrfs_ioctl_send(struct file *mnt_file, struct btrfs_ioctl_send_args *arg) | ||||||
| 			    btrfs_root_dead(clone_root)) { | 			    btrfs_root_dead(clone_root)) { | ||||||
| 				spin_unlock(&clone_root->root_item_lock); | 				spin_unlock(&clone_root->root_item_lock); | ||||||
| 				btrfs_put_root(clone_root); | 				btrfs_put_root(clone_root); | ||||||
| 				srcu_read_unlock(&fs_info->subvol_srcu, index); |  | ||||||
| 				ret = -EPERM; | 				ret = -EPERM; | ||||||
| 				goto out; | 				goto out; | ||||||
| 			} | 			} | ||||||
|  | @ -7176,13 +7171,11 @@ long btrfs_ioctl_send(struct file *mnt_file, struct btrfs_ioctl_send_args *arg) | ||||||
| 				dedupe_in_progress_warn(clone_root); | 				dedupe_in_progress_warn(clone_root); | ||||||
| 				spin_unlock(&clone_root->root_item_lock); | 				spin_unlock(&clone_root->root_item_lock); | ||||||
| 				btrfs_put_root(clone_root); | 				btrfs_put_root(clone_root); | ||||||
| 				srcu_read_unlock(&fs_info->subvol_srcu, index); |  | ||||||
| 				ret = -EAGAIN; | 				ret = -EAGAIN; | ||||||
| 				goto out; | 				goto out; | ||||||
| 			} | 			} | ||||||
| 			clone_root->send_in_progress++; | 			clone_root->send_in_progress++; | ||||||
| 			spin_unlock(&clone_root->root_item_lock); | 			spin_unlock(&clone_root->root_item_lock); | ||||||
| 			srcu_read_unlock(&fs_info->subvol_srcu, index); |  | ||||||
| 
 | 
 | ||||||
| 			sctx->clone_roots[i].root = clone_root; | 			sctx->clone_roots[i].root = clone_root; | ||||||
| 			clone_sources_to_rollback = i + 1; | 			clone_sources_to_rollback = i + 1; | ||||||
|  | @ -7196,11 +7189,8 @@ long btrfs_ioctl_send(struct file *mnt_file, struct btrfs_ioctl_send_args *arg) | ||||||
| 		key.type = BTRFS_ROOT_ITEM_KEY; | 		key.type = BTRFS_ROOT_ITEM_KEY; | ||||||
| 		key.offset = (u64)-1; | 		key.offset = (u64)-1; | ||||||
| 
 | 
 | ||||||
| 		index = srcu_read_lock(&fs_info->subvol_srcu); |  | ||||||
| 
 |  | ||||||
| 		sctx->parent_root = btrfs_get_fs_root(fs_info, &key, true); | 		sctx->parent_root = btrfs_get_fs_root(fs_info, &key, true); | ||||||
| 		if (IS_ERR(sctx->parent_root)) { | 		if (IS_ERR(sctx->parent_root)) { | ||||||
| 			srcu_read_unlock(&fs_info->subvol_srcu, index); |  | ||||||
| 			ret = PTR_ERR(sctx->parent_root); | 			ret = PTR_ERR(sctx->parent_root); | ||||||
| 			goto out; | 			goto out; | ||||||
| 		} | 		} | ||||||
|  | @ -7210,20 +7200,16 @@ long btrfs_ioctl_send(struct file *mnt_file, struct btrfs_ioctl_send_args *arg) | ||||||
| 		if (!btrfs_root_readonly(sctx->parent_root) || | 		if (!btrfs_root_readonly(sctx->parent_root) || | ||||||
| 				btrfs_root_dead(sctx->parent_root)) { | 				btrfs_root_dead(sctx->parent_root)) { | ||||||
| 			spin_unlock(&sctx->parent_root->root_item_lock); | 			spin_unlock(&sctx->parent_root->root_item_lock); | ||||||
| 			srcu_read_unlock(&fs_info->subvol_srcu, index); |  | ||||||
| 			ret = -EPERM; | 			ret = -EPERM; | ||||||
| 			goto out; | 			goto out; | ||||||
| 		} | 		} | ||||||
| 		if (sctx->parent_root->dedupe_in_progress) { | 		if (sctx->parent_root->dedupe_in_progress) { | ||||||
| 			dedupe_in_progress_warn(sctx->parent_root); | 			dedupe_in_progress_warn(sctx->parent_root); | ||||||
| 			spin_unlock(&sctx->parent_root->root_item_lock); | 			spin_unlock(&sctx->parent_root->root_item_lock); | ||||||
| 			srcu_read_unlock(&fs_info->subvol_srcu, index); |  | ||||||
| 			ret = -EAGAIN; | 			ret = -EAGAIN; | ||||||
| 			goto out; | 			goto out; | ||||||
| 		} | 		} | ||||||
| 		spin_unlock(&sctx->parent_root->root_item_lock); | 		spin_unlock(&sctx->parent_root->root_item_lock); | ||||||
| 
 |  | ||||||
| 		srcu_read_unlock(&fs_info->subvol_srcu, index); |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/*
 | 	/*
 | ||||||
|  |  | ||||||
|  | @ -134,14 +134,6 @@ struct btrfs_fs_info *btrfs_alloc_dummy_fs_info(u32 nodesize, u32 sectorsize) | ||||||
| 
 | 
 | ||||||
| 	fs_info->nodesize = nodesize; | 	fs_info->nodesize = nodesize; | ||||||
| 	fs_info->sectorsize = sectorsize; | 	fs_info->sectorsize = sectorsize; | ||||||
| 
 |  | ||||||
| 	if (init_srcu_struct(&fs_info->subvol_srcu)) { |  | ||||||
| 		kfree(fs_info->fs_devices); |  | ||||||
| 		kfree(fs_info->super_copy); |  | ||||||
| 		kfree(fs_info); |  | ||||||
| 		return NULL; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	set_bit(BTRFS_FS_STATE_DUMMY_FS_INFO, &fs_info->fs_state); | 	set_bit(BTRFS_FS_STATE_DUMMY_FS_INFO, &fs_info->fs_state); | ||||||
| 
 | 
 | ||||||
| 	test_mnt->mnt_sb->s_fs_info = fs_info; | 	test_mnt->mnt_sb->s_fs_info = fs_info; | ||||||
|  | @ -191,7 +183,6 @@ void btrfs_free_dummy_fs_info(struct btrfs_fs_info *fs_info) | ||||||
| 	} | 	} | ||||||
| 	btrfs_free_qgroup_config(fs_info); | 	btrfs_free_qgroup_config(fs_info); | ||||||
| 	btrfs_free_fs_roots(fs_info); | 	btrfs_free_fs_roots(fs_info); | ||||||
| 	cleanup_srcu_struct(&fs_info->subvol_srcu); |  | ||||||
| 	kfree(fs_info->super_copy); | 	kfree(fs_info->super_copy); | ||||||
| 	btrfs_check_leaked_roots(fs_info); | 	btrfs_check_leaked_roots(fs_info); | ||||||
| 	btrfs_extent_buffer_leak_debug_check(fs_info); | 	btrfs_extent_buffer_leak_debug_check(fs_info); | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Josef Bacik
						Josef Bacik