btrfs: move the space_info handling code to space-info.c
These are the basic init and lookup functions and some helper functions, fairly straightforward before the bad stuff starts. Reviewed-by: Nikolay Borisov <nborisov@suse.com> Signed-off-by: Josef Bacik <josef@toxicpanda.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
		
							parent
							
								
									d44b72aa12
								
							
						
					
					
						commit
						280c290881
					
				| @ -10,7 +10,7 @@ btrfs-y += super.o ctree.o extent-tree.o print-tree.o root-tree.o dir-item.o \ | ||||
| 	   export.o tree-log.o free-space-cache.o zlib.o lzo.o zstd.o \
 | ||||
| 	   compression.o delayed-ref.o relocation.o delayed-inode.o scrub.o \
 | ||||
| 	   reada.o backref.o ulist.o qgroup.o send.o dev-replace.o raid56.o \
 | ||||
| 	   uuid-tree.o props.o free-space-tree.o tree-checker.o | ||||
| 	   uuid-tree.o props.o free-space-tree.o tree-checker.o space-info.o | ||||
| 
 | ||||
| btrfs-$(CONFIG_BTRFS_FS_POSIX_ACL) += acl.o | ||||
| btrfs-$(CONFIG_BTRFS_FS_CHECK_INTEGRITY) += check-integrity.o | ||||
|  | ||||
| @ -713,25 +713,6 @@ struct btrfs_block_group_cache *btrfs_lookup_block_group( | ||||
| 	return block_group_cache_tree_search(info, bytenr, 1); | ||||
| } | ||||
| 
 | ||||
| static struct btrfs_space_info *__find_space_info(struct btrfs_fs_info *info, | ||||
| 						  u64 flags) | ||||
| { | ||||
| 	struct list_head *head = &info->space_info; | ||||
| 	struct btrfs_space_info *found; | ||||
| 
 | ||||
| 	flags &= BTRFS_BLOCK_GROUP_TYPE_MASK; | ||||
| 
 | ||||
| 	rcu_read_lock(); | ||||
| 	list_for_each_entry_rcu(found, head, list) { | ||||
| 		if (found->flags & flags) { | ||||
| 			rcu_read_unlock(); | ||||
| 			return found; | ||||
| 		} | ||||
| 	} | ||||
| 	rcu_read_unlock(); | ||||
| 	return NULL; | ||||
| } | ||||
| 
 | ||||
| static u64 generic_ref_to_space_flags(struct btrfs_ref *ref) | ||||
| { | ||||
| 	if (ref->type == BTRFS_REF_METADATA) { | ||||
| @ -749,7 +730,7 @@ static void add_pinned_bytes(struct btrfs_fs_info *fs_info, | ||||
| 	struct btrfs_space_info *space_info; | ||||
| 	u64 flags = generic_ref_to_space_flags(ref); | ||||
| 
 | ||||
| 	space_info = __find_space_info(fs_info, flags); | ||||
| 	space_info = btrfs_find_space_info(fs_info, flags); | ||||
| 	ASSERT(space_info); | ||||
| 	percpu_counter_add_batch(&space_info->total_bytes_pinned, ref->len, | ||||
| 		    BTRFS_TOTAL_BYTES_PINNED_BATCH); | ||||
| @ -761,27 +742,12 @@ static void sub_pinned_bytes(struct btrfs_fs_info *fs_info, | ||||
| 	struct btrfs_space_info *space_info; | ||||
| 	u64 flags = generic_ref_to_space_flags(ref); | ||||
| 
 | ||||
| 	space_info = __find_space_info(fs_info, flags); | ||||
| 	space_info = btrfs_find_space_info(fs_info, flags); | ||||
| 	ASSERT(space_info); | ||||
| 	percpu_counter_add_batch(&space_info->total_bytes_pinned, -ref->len, | ||||
| 		    BTRFS_TOTAL_BYTES_PINNED_BATCH); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * after adding space to the filesystem, we need to clear the full flags | ||||
|  * on all the space infos. | ||||
|  */ | ||||
| void btrfs_clear_space_info_full(struct btrfs_fs_info *info) | ||||
| { | ||||
| 	struct list_head *head = &info->space_info; | ||||
| 	struct btrfs_space_info *found; | ||||
| 
 | ||||
| 	rcu_read_lock(); | ||||
| 	list_for_each_entry_rcu(found, head, list) | ||||
| 		found->full = 0; | ||||
| 	rcu_read_unlock(); | ||||
| } | ||||
| 
 | ||||
| /* simple helper to search for an existing data extent at a given offset */ | ||||
| int btrfs_lookup_data_extent(struct btrfs_fs_info *fs_info, u64 start, u64 len) | ||||
| { | ||||
| @ -2449,7 +2415,7 @@ void btrfs_cleanup_ref_head_accounting(struct btrfs_fs_info *fs_info, | ||||
| 			flags = BTRFS_BLOCK_GROUP_SYSTEM; | ||||
| 		else | ||||
| 			flags = BTRFS_BLOCK_GROUP_METADATA; | ||||
| 		space_info = __find_space_info(fs_info, flags); | ||||
| 		space_info = btrfs_find_space_info(fs_info, flags); | ||||
| 		ASSERT(space_info); | ||||
| 		percpu_counter_add_batch(&space_info->total_bytes_pinned, | ||||
| 				   -head->num_bytes, | ||||
| @ -3821,93 +3787,6 @@ void btrfs_wait_nocow_writers(struct btrfs_block_group_cache *bg) | ||||
| 	wait_var_event(&bg->nocow_writers, !atomic_read(&bg->nocow_writers)); | ||||
| } | ||||
| 
 | ||||
| static const char *alloc_name(u64 flags) | ||||
| { | ||||
| 	switch (flags) { | ||||
| 	case BTRFS_BLOCK_GROUP_METADATA|BTRFS_BLOCK_GROUP_DATA: | ||||
| 		return "mixed"; | ||||
| 	case BTRFS_BLOCK_GROUP_METADATA: | ||||
| 		return "metadata"; | ||||
| 	case BTRFS_BLOCK_GROUP_DATA: | ||||
| 		return "data"; | ||||
| 	case BTRFS_BLOCK_GROUP_SYSTEM: | ||||
| 		return "system"; | ||||
| 	default: | ||||
| 		WARN_ON(1); | ||||
| 		return "invalid-combination"; | ||||
| 	}; | ||||
| } | ||||
| 
 | ||||
| static int create_space_info(struct btrfs_fs_info *info, u64 flags) | ||||
| { | ||||
| 
 | ||||
| 	struct btrfs_space_info *space_info; | ||||
| 	int i; | ||||
| 	int ret; | ||||
| 
 | ||||
| 	space_info = kzalloc(sizeof(*space_info), GFP_NOFS); | ||||
| 	if (!space_info) | ||||
| 		return -ENOMEM; | ||||
| 
 | ||||
| 	ret = percpu_counter_init(&space_info->total_bytes_pinned, 0, | ||||
| 				 GFP_KERNEL); | ||||
| 	if (ret) { | ||||
| 		kfree(space_info); | ||||
| 		return ret; | ||||
| 	} | ||||
| 
 | ||||
| 	for (i = 0; i < BTRFS_NR_RAID_TYPES; i++) | ||||
| 		INIT_LIST_HEAD(&space_info->block_groups[i]); | ||||
| 	init_rwsem(&space_info->groups_sem); | ||||
| 	spin_lock_init(&space_info->lock); | ||||
| 	space_info->flags = flags & BTRFS_BLOCK_GROUP_TYPE_MASK; | ||||
| 	space_info->force_alloc = CHUNK_ALLOC_NO_FORCE; | ||||
| 	init_waitqueue_head(&space_info->wait); | ||||
| 	INIT_LIST_HEAD(&space_info->ro_bgs); | ||||
| 	INIT_LIST_HEAD(&space_info->tickets); | ||||
| 	INIT_LIST_HEAD(&space_info->priority_tickets); | ||||
| 
 | ||||
| 	ret = kobject_init_and_add(&space_info->kobj, &space_info_ktype, | ||||
| 				    info->space_info_kobj, "%s", | ||||
| 				    alloc_name(space_info->flags)); | ||||
| 	if (ret) { | ||||
| 		kobject_put(&space_info->kobj); | ||||
| 		return ret; | ||||
| 	} | ||||
| 
 | ||||
| 	list_add_rcu(&space_info->list, &info->space_info); | ||||
| 	if (flags & BTRFS_BLOCK_GROUP_DATA) | ||||
| 		info->data_sinfo = space_info; | ||||
| 
 | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| static void update_space_info(struct btrfs_fs_info *info, u64 flags, | ||||
| 			     u64 total_bytes, u64 bytes_used, | ||||
| 			     u64 bytes_readonly, | ||||
| 			     struct btrfs_space_info **space_info) | ||||
| { | ||||
| 	struct btrfs_space_info *found; | ||||
| 	int factor; | ||||
| 
 | ||||
| 	factor = btrfs_bg_type_to_factor(flags); | ||||
| 
 | ||||
| 	found = __find_space_info(info, flags); | ||||
| 	ASSERT(found); | ||||
| 	spin_lock(&found->lock); | ||||
| 	found->total_bytes += total_bytes; | ||||
| 	found->disk_total += total_bytes * factor; | ||||
| 	found->bytes_used += bytes_used; | ||||
| 	found->disk_used += bytes_used * factor; | ||||
| 	found->bytes_readonly += bytes_readonly; | ||||
| 	if (total_bytes > 0) | ||||
| 		found->full = 0; | ||||
| 	btrfs_space_info_add_new_bytes(info, found, total_bytes - | ||||
| 				       bytes_used - bytes_readonly); | ||||
| 	spin_unlock(&found->lock); | ||||
| 	*space_info = found; | ||||
| } | ||||
| 
 | ||||
| static void set_avail_alloc_bits(struct btrfs_fs_info *fs_info, u64 flags) | ||||
| { | ||||
| 	u64 extra_flags = chunk_to_extended(flags) & | ||||
| @ -4055,15 +3934,6 @@ u64 btrfs_system_alloc_profile(struct btrfs_fs_info *fs_info) | ||||
| 	return get_alloc_profile(fs_info, BTRFS_BLOCK_GROUP_SYSTEM); | ||||
| } | ||||
| 
 | ||||
| static u64 btrfs_space_info_used(struct btrfs_space_info *s_info, | ||||
| 				 bool may_use_included) | ||||
| { | ||||
| 	ASSERT(s_info); | ||||
| 	return s_info->bytes_used + s_info->bytes_reserved + | ||||
| 		s_info->bytes_pinned + s_info->bytes_readonly + | ||||
| 		(may_use_included ? s_info->bytes_may_use : 0); | ||||
| } | ||||
| 
 | ||||
| int btrfs_alloc_data_chunk_ondemand(struct btrfs_inode *inode, u64 bytes) | ||||
| { | ||||
| 	struct btrfs_root *root = inode->root; | ||||
| @ -4339,7 +4209,7 @@ void check_system_chunk(struct btrfs_trans_handle *trans, u64 type) | ||||
| 	 */ | ||||
| 	lockdep_assert_held(&fs_info->chunk_mutex); | ||||
| 
 | ||||
| 	info = __find_space_info(fs_info, BTRFS_BLOCK_GROUP_SYSTEM); | ||||
| 	info = btrfs_find_space_info(fs_info, BTRFS_BLOCK_GROUP_SYSTEM); | ||||
| 	spin_lock(&info->lock); | ||||
| 	left = info->total_bytes - btrfs_space_info_used(info, true); | ||||
| 	spin_unlock(&info->lock); | ||||
| @ -4399,7 +4269,7 @@ int btrfs_chunk_alloc(struct btrfs_trans_handle *trans, u64 flags, | ||||
| 	if (trans->allocating_chunk) | ||||
| 		return -ENOSPC; | ||||
| 
 | ||||
| 	space_info = __find_space_info(fs_info, flags); | ||||
| 	space_info = btrfs_find_space_info(fs_info, flags); | ||||
| 	ASSERT(space_info); | ||||
| 
 | ||||
| 	do { | ||||
| @ -4627,7 +4497,7 @@ static void shrink_delalloc(struct btrfs_fs_info *fs_info, u64 to_reclaim, | ||||
| 	to_reclaim = items * EXTENT_SIZE_PER_ITEM; | ||||
| 
 | ||||
| 	trans = (struct btrfs_trans_handle *)current->journal_info; | ||||
| 	space_info = __find_space_info(fs_info, BTRFS_BLOCK_GROUP_METADATA); | ||||
| 	space_info = btrfs_find_space_info(fs_info, BTRFS_BLOCK_GROUP_METADATA); | ||||
| 
 | ||||
| 	delalloc_bytes = percpu_counter_sum_positive( | ||||
| 						&fs_info->delalloc_bytes); | ||||
| @ -4965,7 +4835,7 @@ static void btrfs_async_reclaim_metadata_space(struct work_struct *work) | ||||
| 	u64 last_tickets_id; | ||||
| 
 | ||||
| 	fs_info = container_of(work, struct btrfs_fs_info, async_reclaim_work); | ||||
| 	space_info = __find_space_info(fs_info, BTRFS_BLOCK_GROUP_METADATA); | ||||
| 	space_info = btrfs_find_space_info(fs_info, BTRFS_BLOCK_GROUP_METADATA); | ||||
| 
 | ||||
| 	spin_lock(&space_info->lock); | ||||
| 	to_reclaim = btrfs_calc_reclaim_metadata_size(fs_info, space_info, | ||||
| @ -5611,7 +5481,7 @@ void btrfs_init_metadata_block_rsv(struct btrfs_fs_info *fs_info, | ||||
| 				   unsigned short type) | ||||
| { | ||||
| 	btrfs_init_block_rsv(rsv, type); | ||||
| 	rsv->space_info = __find_space_info(fs_info, | ||||
| 	rsv->space_info = btrfs_find_space_info(fs_info, | ||||
| 					    BTRFS_BLOCK_GROUP_METADATA); | ||||
| } | ||||
| 
 | ||||
| @ -5836,10 +5706,10 @@ static void init_global_block_rsv(struct btrfs_fs_info *fs_info) | ||||
| { | ||||
| 	struct btrfs_space_info *space_info; | ||||
| 
 | ||||
| 	space_info = __find_space_info(fs_info, BTRFS_BLOCK_GROUP_SYSTEM); | ||||
| 	space_info = btrfs_find_space_info(fs_info, BTRFS_BLOCK_GROUP_SYSTEM); | ||||
| 	fs_info->chunk_block_rsv.space_info = space_info; | ||||
| 
 | ||||
| 	space_info = __find_space_info(fs_info, BTRFS_BLOCK_GROUP_METADATA); | ||||
| 	space_info = btrfs_find_space_info(fs_info, BTRFS_BLOCK_GROUP_METADATA); | ||||
| 	fs_info->global_block_rsv.space_info = space_info; | ||||
| 	fs_info->trans_block_rsv.space_info = space_info; | ||||
| 	fs_info->empty_block_rsv.space_info = space_info; | ||||
| @ -5948,7 +5818,7 @@ int btrfs_subvolume_reserve_metadata(struct btrfs_root *root, | ||||
| 	} | ||||
| 
 | ||||
| 	num_bytes = btrfs_calc_trans_metadata_size(fs_info, items); | ||||
| 	rsv->space_info = __find_space_info(fs_info, | ||||
| 	rsv->space_info = btrfs_find_space_info(fs_info, | ||||
| 					    BTRFS_BLOCK_GROUP_METADATA); | ||||
| 	ret = btrfs_block_rsv_add(root, rsv, num_bytes, | ||||
| 				  BTRFS_RESERVE_FLUSH_ALL); | ||||
| @ -7743,7 +7613,7 @@ static noinline int find_free_extent(struct btrfs_fs_info *fs_info, | ||||
| 
 | ||||
| 	trace_find_free_extent(fs_info, num_bytes, empty_size, flags); | ||||
| 
 | ||||
| 	space_info = __find_space_info(fs_info, flags); | ||||
| 	space_info = btrfs_find_space_info(fs_info, flags); | ||||
| 	if (!space_info) { | ||||
| 		btrfs_err(fs_info, "No space info for %llu", flags); | ||||
| 		return -ENOSPC; | ||||
| @ -8097,7 +7967,7 @@ again: | ||||
| 		} else if (btrfs_test_opt(fs_info, ENOSPC_DEBUG)) { | ||||
| 			struct btrfs_space_info *sinfo; | ||||
| 
 | ||||
| 			sinfo = __find_space_info(fs_info, flags); | ||||
| 			sinfo = btrfs_find_space_info(fs_info, flags); | ||||
| 			btrfs_err(fs_info, | ||||
| 				  "allocation failed flags %llu, wanted %llu", | ||||
| 				  flags, num_bytes); | ||||
| @ -10130,7 +10000,7 @@ void btrfs_add_raid_kobjects(struct btrfs_fs_info *fs_info) | ||||
| 	spin_unlock(&fs_info->pending_raid_kobjs_lock); | ||||
| 
 | ||||
| 	list_for_each_entry(rkobj, &list, list) { | ||||
| 		space_info = __find_space_info(fs_info, rkobj->flags); | ||||
| 		space_info = btrfs_find_space_info(fs_info, rkobj->flags); | ||||
| 
 | ||||
| 		ret = kobject_add(&rkobj->kobj, &space_info->kobj, | ||||
| 				"%s", btrfs_bg_type_to_raid_name(rkobj->flags)); | ||||
| @ -10397,9 +10267,9 @@ int btrfs_read_block_groups(struct btrfs_fs_info *info) | ||||
| 		} | ||||
| 
 | ||||
| 		trace_btrfs_add_block_group(info, cache, 0); | ||||
| 		update_space_info(info, cache->flags, found_key.offset, | ||||
| 				  btrfs_block_group_used(&cache->item), | ||||
| 				  cache->bytes_super, &space_info); | ||||
| 		btrfs_update_space_info(info, cache->flags, found_key.offset, | ||||
| 					btrfs_block_group_used(&cache->item), | ||||
| 					cache->bytes_super, &space_info); | ||||
| 
 | ||||
| 		cache->space_info = space_info; | ||||
| 
 | ||||
| @ -10533,7 +10403,7 @@ int btrfs_make_block_group(struct btrfs_trans_handle *trans, u64 bytes_used, | ||||
| 	 * assigned to our block group. We want our bg to be added to the rbtree | ||||
| 	 * with its ->space_info set. | ||||
| 	 */ | ||||
| 	cache->space_info = __find_space_info(fs_info, cache->flags); | ||||
| 	cache->space_info = btrfs_find_space_info(fs_info, cache->flags); | ||||
| 	ASSERT(cache->space_info); | ||||
| 
 | ||||
| 	ret = btrfs_add_block_group_cache(fs_info, cache); | ||||
| @ -10548,7 +10418,7 @@ int btrfs_make_block_group(struct btrfs_trans_handle *trans, u64 bytes_used, | ||||
| 	 * the rbtree, update the space info's counters. | ||||
| 	 */ | ||||
| 	trace_btrfs_add_block_group(fs_info, cache, 1); | ||||
| 	update_space_info(fs_info, cache->flags, size, bytes_used, | ||||
| 	btrfs_update_space_info(fs_info, cache->flags, size, bytes_used, | ||||
| 				cache->bytes_super, &cache->space_info); | ||||
| 	update_global_block_rsv(fs_info); | ||||
| 
 | ||||
| @ -11085,43 +10955,6 @@ next: | ||||
| 	spin_unlock(&fs_info->unused_bgs_lock); | ||||
| } | ||||
| 
 | ||||
| int btrfs_init_space_info(struct btrfs_fs_info *fs_info) | ||||
| { | ||||
| 	struct btrfs_super_block *disk_super; | ||||
| 	u64 features; | ||||
| 	u64 flags; | ||||
| 	int mixed = 0; | ||||
| 	int ret; | ||||
| 
 | ||||
| 	disk_super = fs_info->super_copy; | ||||
| 	if (!btrfs_super_root(disk_super)) | ||||
| 		return -EINVAL; | ||||
| 
 | ||||
| 	features = btrfs_super_incompat_flags(disk_super); | ||||
| 	if (features & BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS) | ||||
| 		mixed = 1; | ||||
| 
 | ||||
| 	flags = BTRFS_BLOCK_GROUP_SYSTEM; | ||||
| 	ret = create_space_info(fs_info, flags); | ||||
| 	if (ret) | ||||
| 		goto out; | ||||
| 
 | ||||
| 	if (mixed) { | ||||
| 		flags = BTRFS_BLOCK_GROUP_METADATA | BTRFS_BLOCK_GROUP_DATA; | ||||
| 		ret = create_space_info(fs_info, flags); | ||||
| 	} else { | ||||
| 		flags = BTRFS_BLOCK_GROUP_METADATA; | ||||
| 		ret = create_space_info(fs_info, flags); | ||||
| 		if (ret) | ||||
| 			goto out; | ||||
| 
 | ||||
| 		flags = BTRFS_BLOCK_GROUP_DATA; | ||||
| 		ret = create_space_info(fs_info, flags); | ||||
| 	} | ||||
| out: | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| int btrfs_error_unpin_extent_range(struct btrfs_fs_info *fs_info, | ||||
| 				   u64 start, u64 end) | ||||
| { | ||||
|  | ||||
							
								
								
									
										174
									
								
								fs/btrfs/space-info.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										174
									
								
								fs/btrfs/space-info.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,174 @@ | ||||
| // SPDX-License-Identifier: GPL-2.0
 | ||||
| 
 | ||||
| #include "ctree.h" | ||||
| #include "space-info.h" | ||||
| #include "sysfs.h" | ||||
| #include "volumes.h" | ||||
| 
 | ||||
| u64 btrfs_space_info_used(struct btrfs_space_info *s_info, | ||||
| 			  bool may_use_included) | ||||
| { | ||||
| 	ASSERT(s_info); | ||||
| 	return s_info->bytes_used + s_info->bytes_reserved + | ||||
| 		s_info->bytes_pinned + s_info->bytes_readonly + | ||||
| 		(may_use_included ? s_info->bytes_may_use : 0); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * after adding space to the filesystem, we need to clear the full flags | ||||
|  * on all the space infos. | ||||
|  */ | ||||
| void btrfs_clear_space_info_full(struct btrfs_fs_info *info) | ||||
| { | ||||
| 	struct list_head *head = &info->space_info; | ||||
| 	struct btrfs_space_info *found; | ||||
| 
 | ||||
| 	rcu_read_lock(); | ||||
| 	list_for_each_entry_rcu(found, head, list) | ||||
| 		found->full = 0; | ||||
| 	rcu_read_unlock(); | ||||
| } | ||||
| 
 | ||||
| static const char *alloc_name(u64 flags) | ||||
| { | ||||
| 	switch (flags) { | ||||
| 	case BTRFS_BLOCK_GROUP_METADATA|BTRFS_BLOCK_GROUP_DATA: | ||||
| 		return "mixed"; | ||||
| 	case BTRFS_BLOCK_GROUP_METADATA: | ||||
| 		return "metadata"; | ||||
| 	case BTRFS_BLOCK_GROUP_DATA: | ||||
| 		return "data"; | ||||
| 	case BTRFS_BLOCK_GROUP_SYSTEM: | ||||
| 		return "system"; | ||||
| 	default: | ||||
| 		WARN_ON(1); | ||||
| 		return "invalid-combination"; | ||||
| 	}; | ||||
| } | ||||
| 
 | ||||
| static int create_space_info(struct btrfs_fs_info *info, u64 flags) | ||||
| { | ||||
| 
 | ||||
| 	struct btrfs_space_info *space_info; | ||||
| 	int i; | ||||
| 	int ret; | ||||
| 
 | ||||
| 	space_info = kzalloc(sizeof(*space_info), GFP_NOFS); | ||||
| 	if (!space_info) | ||||
| 		return -ENOMEM; | ||||
| 
 | ||||
| 	ret = percpu_counter_init(&space_info->total_bytes_pinned, 0, | ||||
| 				 GFP_KERNEL); | ||||
| 	if (ret) { | ||||
| 		kfree(space_info); | ||||
| 		return ret; | ||||
| 	} | ||||
| 
 | ||||
| 	for (i = 0; i < BTRFS_NR_RAID_TYPES; i++) | ||||
| 		INIT_LIST_HEAD(&space_info->block_groups[i]); | ||||
| 	init_rwsem(&space_info->groups_sem); | ||||
| 	spin_lock_init(&space_info->lock); | ||||
| 	space_info->flags = flags & BTRFS_BLOCK_GROUP_TYPE_MASK; | ||||
| 	space_info->force_alloc = CHUNK_ALLOC_NO_FORCE; | ||||
| 	init_waitqueue_head(&space_info->wait); | ||||
| 	INIT_LIST_HEAD(&space_info->ro_bgs); | ||||
| 	INIT_LIST_HEAD(&space_info->tickets); | ||||
| 	INIT_LIST_HEAD(&space_info->priority_tickets); | ||||
| 
 | ||||
| 	ret = kobject_init_and_add(&space_info->kobj, &space_info_ktype, | ||||
| 				    info->space_info_kobj, "%s", | ||||
| 				    alloc_name(space_info->flags)); | ||||
| 	if (ret) { | ||||
| 		kobject_put(&space_info->kobj); | ||||
| 		return ret; | ||||
| 	} | ||||
| 
 | ||||
| 	list_add_rcu(&space_info->list, &info->space_info); | ||||
| 	if (flags & BTRFS_BLOCK_GROUP_DATA) | ||||
| 		info->data_sinfo = space_info; | ||||
| 
 | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| int btrfs_init_space_info(struct btrfs_fs_info *fs_info) | ||||
| { | ||||
| 	struct btrfs_super_block *disk_super; | ||||
| 	u64 features; | ||||
| 	u64 flags; | ||||
| 	int mixed = 0; | ||||
| 	int ret; | ||||
| 
 | ||||
| 	disk_super = fs_info->super_copy; | ||||
| 	if (!btrfs_super_root(disk_super)) | ||||
| 		return -EINVAL; | ||||
| 
 | ||||
| 	features = btrfs_super_incompat_flags(disk_super); | ||||
| 	if (features & BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS) | ||||
| 		mixed = 1; | ||||
| 
 | ||||
| 	flags = BTRFS_BLOCK_GROUP_SYSTEM; | ||||
| 	ret = create_space_info(fs_info, flags); | ||||
| 	if (ret) | ||||
| 		goto out; | ||||
| 
 | ||||
| 	if (mixed) { | ||||
| 		flags = BTRFS_BLOCK_GROUP_METADATA | BTRFS_BLOCK_GROUP_DATA; | ||||
| 		ret = create_space_info(fs_info, flags); | ||||
| 	} else { | ||||
| 		flags = BTRFS_BLOCK_GROUP_METADATA; | ||||
| 		ret = create_space_info(fs_info, flags); | ||||
| 		if (ret) | ||||
| 			goto out; | ||||
| 
 | ||||
| 		flags = BTRFS_BLOCK_GROUP_DATA; | ||||
| 		ret = create_space_info(fs_info, flags); | ||||
| 	} | ||||
| out: | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| void btrfs_update_space_info(struct btrfs_fs_info *info, u64 flags, | ||||
| 			     u64 total_bytes, u64 bytes_used, | ||||
| 			     u64 bytes_readonly, | ||||
| 			     struct btrfs_space_info **space_info) | ||||
| { | ||||
| 	struct btrfs_space_info *found; | ||||
| 	int factor; | ||||
| 
 | ||||
| 	factor = btrfs_bg_type_to_factor(flags); | ||||
| 
 | ||||
| 	found = btrfs_find_space_info(info, flags); | ||||
| 	ASSERT(found); | ||||
| 	spin_lock(&found->lock); | ||||
| 	found->total_bytes += total_bytes; | ||||
| 	found->disk_total += total_bytes * factor; | ||||
| 	found->bytes_used += bytes_used; | ||||
| 	found->disk_used += bytes_used * factor; | ||||
| 	found->bytes_readonly += bytes_readonly; | ||||
| 	if (total_bytes > 0) | ||||
| 		found->full = 0; | ||||
| 	btrfs_space_info_add_new_bytes(info, found, | ||||
| 				       total_bytes - bytes_used - | ||||
| 				       bytes_readonly); | ||||
| 	spin_unlock(&found->lock); | ||||
| 	*space_info = found; | ||||
| } | ||||
| 
 | ||||
| struct btrfs_space_info *btrfs_find_space_info(struct btrfs_fs_info *info, | ||||
| 					       u64 flags) | ||||
| { | ||||
| 	struct list_head *head = &info->space_info; | ||||
| 	struct btrfs_space_info *found; | ||||
| 
 | ||||
| 	flags &= BTRFS_BLOCK_GROUP_TYPE_MASK; | ||||
| 
 | ||||
| 	rcu_read_lock(); | ||||
| 	list_for_each_entry_rcu(found, head, list) { | ||||
| 		if (found->flags & flags) { | ||||
| 			rcu_read_unlock(); | ||||
| 			return found; | ||||
| 		} | ||||
| 	} | ||||
| 	rcu_read_unlock(); | ||||
| 	return NULL; | ||||
| } | ||||
| @ -81,5 +81,15 @@ void btrfs_space_info_add_new_bytes(struct btrfs_fs_info *fs_info, | ||||
| void btrfs_space_info_add_old_bytes(struct btrfs_fs_info *fs_info, | ||||
| 				    struct btrfs_space_info *space_info, | ||||
| 				    u64 num_bytes); | ||||
| int btrfs_init_space_info(struct btrfs_fs_info *fs_info); | ||||
| void btrfs_update_space_info(struct btrfs_fs_info *info, u64 flags, | ||||
| 			     u64 total_bytes, u64 bytes_used, | ||||
| 			     u64 bytes_readonly, | ||||
| 			     struct btrfs_space_info **space_info); | ||||
| struct btrfs_space_info *btrfs_find_space_info(struct btrfs_fs_info *info, | ||||
| 					       u64 flags); | ||||
| u64 btrfs_space_info_used(struct btrfs_space_info *s_info, | ||||
| 			  bool may_use_included); | ||||
| void btrfs_clear_space_info_full(struct btrfs_fs_info *info); | ||||
| 
 | ||||
| #endif /* BTRFS_SPACE_INFO_H */ | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user