summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosef Bacik <josef@toxicpanda.com>2019-06-18 16:09:19 -0400
committerDavid Sterba <dsterba@suse.com>2019-07-02 06:30:52 -0400
commit280c290881bc048bd5dbe02796173f55ca86e697 (patch)
tree8fef64c54f7016a89de2fc935e683cc6246be0b5
parentd44b72aa12d0a74b67ffabdcab2f64653282dccd (diff)
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>
-rw-r--r--fs/btrfs/Makefile2
-rw-r--r--fs/btrfs/extent-tree.c205
-rw-r--r--fs/btrfs/space-info.c174
-rw-r--r--fs/btrfs/space-info.h10
4 files changed, 204 insertions, 187 deletions
diff --git a/fs/btrfs/Makefile b/fs/btrfs/Makefile
index ca693dd554e9..ae5fad57bc9c 100644
--- a/fs/btrfs/Makefile
+++ b/fs/btrfs/Makefile
@@ -10,7 +10,7 @@ btrfs-y += super.o ctree.o extent-tree.o print-tree.o root-tree.o dir-item.o \
10 export.o tree-log.o free-space-cache.o zlib.o lzo.o zstd.o \ 10 export.o tree-log.o free-space-cache.o zlib.o lzo.o zstd.o \
11 compression.o delayed-ref.o relocation.o delayed-inode.o scrub.o \ 11 compression.o delayed-ref.o relocation.o delayed-inode.o scrub.o \
12 reada.o backref.o ulist.o qgroup.o send.o dev-replace.o raid56.o \ 12 reada.o backref.o ulist.o qgroup.o send.o dev-replace.o raid56.o \
13 uuid-tree.o props.o free-space-tree.o tree-checker.o 13 uuid-tree.o props.o free-space-tree.o tree-checker.o space-info.o
14 14
15btrfs-$(CONFIG_BTRFS_FS_POSIX_ACL) += acl.o 15btrfs-$(CONFIG_BTRFS_FS_POSIX_ACL) += acl.o
16btrfs-$(CONFIG_BTRFS_FS_CHECK_INTEGRITY) += check-integrity.o 16btrfs-$(CONFIG_BTRFS_FS_CHECK_INTEGRITY) += check-integrity.o
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 34d08fc8ba76..2ec0409fa2b5 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -713,25 +713,6 @@ struct btrfs_block_group_cache *btrfs_lookup_block_group(
713 return block_group_cache_tree_search(info, bytenr, 1); 713 return block_group_cache_tree_search(info, bytenr, 1);
714} 714}
715 715
716static struct btrfs_space_info *__find_space_info(struct btrfs_fs_info *info,
717 u64 flags)
718{
719 struct list_head *head = &info->space_info;
720 struct btrfs_space_info *found;
721
722 flags &= BTRFS_BLOCK_GROUP_TYPE_MASK;
723
724 rcu_read_lock();
725 list_for_each_entry_rcu(found, head, list) {
726 if (found->flags & flags) {
727 rcu_read_unlock();
728 return found;
729 }
730 }
731 rcu_read_unlock();
732 return NULL;
733}
734
735static u64 generic_ref_to_space_flags(struct btrfs_ref *ref) 716static u64 generic_ref_to_space_flags(struct btrfs_ref *ref)
736{ 717{
737 if (ref->type == BTRFS_REF_METADATA) { 718 if (ref->type == BTRFS_REF_METADATA) {
@@ -749,7 +730,7 @@ static void add_pinned_bytes(struct btrfs_fs_info *fs_info,
749 struct btrfs_space_info *space_info; 730 struct btrfs_space_info *space_info;
750 u64 flags = generic_ref_to_space_flags(ref); 731 u64 flags = generic_ref_to_space_flags(ref);
751 732
752 space_info = __find_space_info(fs_info, flags); 733 space_info = btrfs_find_space_info(fs_info, flags);
753 ASSERT(space_info); 734 ASSERT(space_info);
754 percpu_counter_add_batch(&space_info->total_bytes_pinned, ref->len, 735 percpu_counter_add_batch(&space_info->total_bytes_pinned, ref->len,
755 BTRFS_TOTAL_BYTES_PINNED_BATCH); 736 BTRFS_TOTAL_BYTES_PINNED_BATCH);
@@ -761,27 +742,12 @@ static void sub_pinned_bytes(struct btrfs_fs_info *fs_info,
761 struct btrfs_space_info *space_info; 742 struct btrfs_space_info *space_info;
762 u64 flags = generic_ref_to_space_flags(ref); 743 u64 flags = generic_ref_to_space_flags(ref);
763 744
764 space_info = __find_space_info(fs_info, flags); 745 space_info = btrfs_find_space_info(fs_info, flags);
765 ASSERT(space_info); 746 ASSERT(space_info);
766 percpu_counter_add_batch(&space_info->total_bytes_pinned, -ref->len, 747 percpu_counter_add_batch(&space_info->total_bytes_pinned, -ref->len,
767 BTRFS_TOTAL_BYTES_PINNED_BATCH); 748 BTRFS_TOTAL_BYTES_PINNED_BATCH);
768} 749}
769 750
770/*
771 * after adding space to the filesystem, we need to clear the full flags
772 * on all the space infos.
773 */
774void btrfs_clear_space_info_full(struct btrfs_fs_info *info)
775{
776 struct list_head *head = &info->space_info;
777 struct btrfs_space_info *found;
778
779 rcu_read_lock();
780 list_for_each_entry_rcu(found, head, list)
781 found->full = 0;
782 rcu_read_unlock();
783}
784
785/* simple helper to search for an existing data extent at a given offset */ 751/* simple helper to search for an existing data extent at a given offset */
786int btrfs_lookup_data_extent(struct btrfs_fs_info *fs_info, u64 start, u64 len) 752int btrfs_lookup_data_extent(struct btrfs_fs_info *fs_info, u64 start, u64 len)
787{ 753{
@@ -2449,7 +2415,7 @@ void btrfs_cleanup_ref_head_accounting(struct btrfs_fs_info *fs_info,
2449 flags = BTRFS_BLOCK_GROUP_SYSTEM; 2415 flags = BTRFS_BLOCK_GROUP_SYSTEM;
2450 else 2416 else
2451 flags = BTRFS_BLOCK_GROUP_METADATA; 2417 flags = BTRFS_BLOCK_GROUP_METADATA;
2452 space_info = __find_space_info(fs_info, flags); 2418 space_info = btrfs_find_space_info(fs_info, flags);
2453 ASSERT(space_info); 2419 ASSERT(space_info);
2454 percpu_counter_add_batch(&space_info->total_bytes_pinned, 2420 percpu_counter_add_batch(&space_info->total_bytes_pinned,
2455 -head->num_bytes, 2421 -head->num_bytes,
@@ -3821,93 +3787,6 @@ void btrfs_wait_nocow_writers(struct btrfs_block_group_cache *bg)
3821 wait_var_event(&bg->nocow_writers, !atomic_read(&bg->nocow_writers)); 3787 wait_var_event(&bg->nocow_writers, !atomic_read(&bg->nocow_writers));
3822} 3788}
3823 3789
3824static const char *alloc_name(u64 flags)
3825{
3826 switch (flags) {
3827 case BTRFS_BLOCK_GROUP_METADATA|BTRFS_BLOCK_GROUP_DATA:
3828 return "mixed";
3829 case BTRFS_BLOCK_GROUP_METADATA:
3830 return "metadata";
3831 case BTRFS_BLOCK_GROUP_DATA:
3832 return "data";
3833 case BTRFS_BLOCK_GROUP_SYSTEM:
3834 return "system";
3835 default:
3836 WARN_ON(1);
3837 return "invalid-combination";
3838 };
3839}
3840
3841static int create_space_info(struct btrfs_fs_info *info, u64 flags)
3842{
3843
3844 struct btrfs_space_info *space_info;
3845 int i;
3846 int ret;
3847
3848 space_info = kzalloc(sizeof(*space_info), GFP_NOFS);
3849 if (!space_info)
3850 return -ENOMEM;
3851
3852 ret = percpu_counter_init(&space_info->total_bytes_pinned, 0,
3853 GFP_KERNEL);
3854 if (ret) {
3855 kfree(space_info);
3856 return ret;
3857 }
3858
3859 for (i = 0; i < BTRFS_NR_RAID_TYPES; i++)
3860 INIT_LIST_HEAD(&space_info->block_groups[i]);
3861 init_rwsem(&space_info->groups_sem);
3862 spin_lock_init(&space_info->lock);
3863 space_info->flags = flags & BTRFS_BLOCK_GROUP_TYPE_MASK;
3864 space_info->force_alloc = CHUNK_ALLOC_NO_FORCE;
3865 init_waitqueue_head(&space_info->wait);
3866 INIT_LIST_HEAD(&space_info->ro_bgs);
3867 INIT_LIST_HEAD(&space_info->tickets);
3868 INIT_LIST_HEAD(&space_info->priority_tickets);
3869
3870 ret = kobject_init_and_add(&space_info->kobj, &space_info_ktype,
3871 info->space_info_kobj, "%s",
3872 alloc_name(space_info->flags));
3873 if (ret) {
3874 kobject_put(&space_info->kobj);
3875 return ret;
3876 }
3877
3878 list_add_rcu(&space_info->list, &info->space_info);
3879 if (flags & BTRFS_BLOCK_GROUP_DATA)
3880 info->data_sinfo = space_info;
3881
3882 return ret;
3883}
3884
3885static void update_space_info(struct btrfs_fs_info *info, u64 flags,
3886 u64 total_bytes, u64 bytes_used,
3887 u64 bytes_readonly,
3888 struct btrfs_space_info **space_info)
3889{
3890 struct btrfs_space_info *found;
3891 int factor;
3892
3893 factor = btrfs_bg_type_to_factor(flags);
3894
3895 found = __find_space_info(info, flags);
3896 ASSERT(found);
3897 spin_lock(&found->lock);
3898 found->total_bytes += total_bytes;
3899 found->disk_total += total_bytes * factor;
3900 found->bytes_used += bytes_used;
3901 found->disk_used += bytes_used * factor;
3902 found->bytes_readonly += bytes_readonly;
3903 if (total_bytes > 0)
3904 found->full = 0;
3905 btrfs_space_info_add_new_bytes(info, found, total_bytes -
3906 bytes_used - bytes_readonly);
3907 spin_unlock(&found->lock);
3908 *space_info = found;
3909}
3910
3911static void set_avail_alloc_bits(struct btrfs_fs_info *fs_info, u64 flags) 3790static void set_avail_alloc_bits(struct btrfs_fs_info *fs_info, u64 flags)
3912{ 3791{
3913 u64 extra_flags = chunk_to_extended(flags) & 3792 u64 extra_flags = chunk_to_extended(flags) &
@@ -4055,15 +3934,6 @@ u64 btrfs_system_alloc_profile(struct btrfs_fs_info *fs_info)
4055 return get_alloc_profile(fs_info, BTRFS_BLOCK_GROUP_SYSTEM); 3934 return get_alloc_profile(fs_info, BTRFS_BLOCK_GROUP_SYSTEM);
4056} 3935}
4057 3936
4058static u64 btrfs_space_info_used(struct btrfs_space_info *s_info,
4059 bool may_use_included)
4060{
4061 ASSERT(s_info);
4062 return s_info->bytes_used + s_info->bytes_reserved +
4063 s_info->bytes_pinned + s_info->bytes_readonly +
4064 (may_use_included ? s_info->bytes_may_use : 0);
4065}
4066
4067int btrfs_alloc_data_chunk_ondemand(struct btrfs_inode *inode, u64 bytes) 3937int btrfs_alloc_data_chunk_ondemand(struct btrfs_inode *inode, u64 bytes)
4068{ 3938{
4069 struct btrfs_root *root = inode->root; 3939 struct btrfs_root *root = inode->root;
@@ -4339,7 +4209,7 @@ void check_system_chunk(struct btrfs_trans_handle *trans, u64 type)
4339 */ 4209 */
4340 lockdep_assert_held(&fs_info->chunk_mutex); 4210 lockdep_assert_held(&fs_info->chunk_mutex);
4341 4211
4342 info = __find_space_info(fs_info, BTRFS_BLOCK_GROUP_SYSTEM); 4212 info = btrfs_find_space_info(fs_info, BTRFS_BLOCK_GROUP_SYSTEM);
4343 spin_lock(&info->lock); 4213 spin_lock(&info->lock);
4344 left = info->total_bytes - btrfs_space_info_used(info, true); 4214 left = info->total_bytes - btrfs_space_info_used(info, true);
4345 spin_unlock(&info->lock); 4215 spin_unlock(&info->lock);
@@ -4399,7 +4269,7 @@ int btrfs_chunk_alloc(struct btrfs_trans_handle *trans, u64 flags,
4399 if (trans->allocating_chunk) 4269 if (trans->allocating_chunk)
4400 return -ENOSPC; 4270 return -ENOSPC;
4401 4271
4402 space_info = __find_space_info(fs_info, flags); 4272 space_info = btrfs_find_space_info(fs_info, flags);
4403 ASSERT(space_info); 4273 ASSERT(space_info);
4404 4274
4405 do { 4275 do {
@@ -4627,7 +4497,7 @@ static void shrink_delalloc(struct btrfs_fs_info *fs_info, u64 to_reclaim,
4627 to_reclaim = items * EXTENT_SIZE_PER_ITEM; 4497 to_reclaim = items * EXTENT_SIZE_PER_ITEM;
4628 4498
4629 trans = (struct btrfs_trans_handle *)current->journal_info; 4499 trans = (struct btrfs_trans_handle *)current->journal_info;
4630 space_info = __find_space_info(fs_info, BTRFS_BLOCK_GROUP_METADATA); 4500 space_info = btrfs_find_space_info(fs_info, BTRFS_BLOCK_GROUP_METADATA);
4631 4501
4632 delalloc_bytes = percpu_counter_sum_positive( 4502 delalloc_bytes = percpu_counter_sum_positive(
4633 &fs_info->delalloc_bytes); 4503 &fs_info->delalloc_bytes);
@@ -4965,7 +4835,7 @@ static void btrfs_async_reclaim_metadata_space(struct work_struct *work)
4965 u64 last_tickets_id; 4835 u64 last_tickets_id;
4966 4836
4967 fs_info = container_of(work, struct btrfs_fs_info, async_reclaim_work); 4837 fs_info = container_of(work, struct btrfs_fs_info, async_reclaim_work);
4968 space_info = __find_space_info(fs_info, BTRFS_BLOCK_GROUP_METADATA); 4838 space_info = btrfs_find_space_info(fs_info, BTRFS_BLOCK_GROUP_METADATA);
4969 4839
4970 spin_lock(&space_info->lock); 4840 spin_lock(&space_info->lock);
4971 to_reclaim = btrfs_calc_reclaim_metadata_size(fs_info, space_info, 4841 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,
5611 unsigned short type) 5481 unsigned short type)
5612{ 5482{
5613 btrfs_init_block_rsv(rsv, type); 5483 btrfs_init_block_rsv(rsv, type);
5614 rsv->space_info = __find_space_info(fs_info, 5484 rsv->space_info = btrfs_find_space_info(fs_info,
5615 BTRFS_BLOCK_GROUP_METADATA); 5485 BTRFS_BLOCK_GROUP_METADATA);
5616} 5486}
5617 5487
@@ -5836,10 +5706,10 @@ static void init_global_block_rsv(struct btrfs_fs_info *fs_info)
5836{ 5706{
5837 struct btrfs_space_info *space_info; 5707 struct btrfs_space_info *space_info;
5838 5708
5839 space_info = __find_space_info(fs_info, BTRFS_BLOCK_GROUP_SYSTEM); 5709 space_info = btrfs_find_space_info(fs_info, BTRFS_BLOCK_GROUP_SYSTEM);
5840 fs_info->chunk_block_rsv.space_info = space_info; 5710 fs_info->chunk_block_rsv.space_info = space_info;
5841 5711
5842 space_info = __find_space_info(fs_info, BTRFS_BLOCK_GROUP_METADATA); 5712 space_info = btrfs_find_space_info(fs_info, BTRFS_BLOCK_GROUP_METADATA);
5843 fs_info->global_block_rsv.space_info = space_info; 5713 fs_info->global_block_rsv.space_info = space_info;
5844 fs_info->trans_block_rsv.space_info = space_info; 5714 fs_info->trans_block_rsv.space_info = space_info;
5845 fs_info->empty_block_rsv.space_info = space_info; 5715 fs_info->empty_block_rsv.space_info = space_info;
@@ -5948,7 +5818,7 @@ int btrfs_subvolume_reserve_metadata(struct btrfs_root *root,
5948 } 5818 }
5949 5819
5950 num_bytes = btrfs_calc_trans_metadata_size(fs_info, items); 5820 num_bytes = btrfs_calc_trans_metadata_size(fs_info, items);
5951 rsv->space_info = __find_space_info(fs_info, 5821 rsv->space_info = btrfs_find_space_info(fs_info,
5952 BTRFS_BLOCK_GROUP_METADATA); 5822 BTRFS_BLOCK_GROUP_METADATA);
5953 ret = btrfs_block_rsv_add(root, rsv, num_bytes, 5823 ret = btrfs_block_rsv_add(root, rsv, num_bytes,
5954 BTRFS_RESERVE_FLUSH_ALL); 5824 BTRFS_RESERVE_FLUSH_ALL);
@@ -7743,7 +7613,7 @@ static noinline int find_free_extent(struct btrfs_fs_info *fs_info,
7743 7613
7744 trace_find_free_extent(fs_info, num_bytes, empty_size, flags); 7614 trace_find_free_extent(fs_info, num_bytes, empty_size, flags);
7745 7615
7746 space_info = __find_space_info(fs_info, flags); 7616 space_info = btrfs_find_space_info(fs_info, flags);
7747 if (!space_info) { 7617 if (!space_info) {
7748 btrfs_err(fs_info, "No space info for %llu", flags); 7618 btrfs_err(fs_info, "No space info for %llu", flags);
7749 return -ENOSPC; 7619 return -ENOSPC;
@@ -8097,7 +7967,7 @@ again:
8097 } else if (btrfs_test_opt(fs_info, ENOSPC_DEBUG)) { 7967 } else if (btrfs_test_opt(fs_info, ENOSPC_DEBUG)) {
8098 struct btrfs_space_info *sinfo; 7968 struct btrfs_space_info *sinfo;
8099 7969
8100 sinfo = __find_space_info(fs_info, flags); 7970 sinfo = btrfs_find_space_info(fs_info, flags);
8101 btrfs_err(fs_info, 7971 btrfs_err(fs_info,
8102 "allocation failed flags %llu, wanted %llu", 7972 "allocation failed flags %llu, wanted %llu",
8103 flags, num_bytes); 7973 flags, num_bytes);
@@ -10130,7 +10000,7 @@ void btrfs_add_raid_kobjects(struct btrfs_fs_info *fs_info)
10130 spin_unlock(&fs_info->pending_raid_kobjs_lock); 10000 spin_unlock(&fs_info->pending_raid_kobjs_lock);
10131 10001
10132 list_for_each_entry(rkobj, &list, list) { 10002 list_for_each_entry(rkobj, &list, list) {
10133 space_info = __find_space_info(fs_info, rkobj->flags); 10003 space_info = btrfs_find_space_info(fs_info, rkobj->flags);
10134 10004
10135 ret = kobject_add(&rkobj->kobj, &space_info->kobj, 10005 ret = kobject_add(&rkobj->kobj, &space_info->kobj,
10136 "%s", btrfs_bg_type_to_raid_name(rkobj->flags)); 10006 "%s", btrfs_bg_type_to_raid_name(rkobj->flags));
@@ -10397,9 +10267,9 @@ int btrfs_read_block_groups(struct btrfs_fs_info *info)
10397 } 10267 }
10398 10268
10399 trace_btrfs_add_block_group(info, cache, 0); 10269 trace_btrfs_add_block_group(info, cache, 0);
10400 update_space_info(info, cache->flags, found_key.offset, 10270 btrfs_update_space_info(info, cache->flags, found_key.offset,
10401 btrfs_block_group_used(&cache->item), 10271 btrfs_block_group_used(&cache->item),
10402 cache->bytes_super, &space_info); 10272 cache->bytes_super, &space_info);
10403 10273
10404 cache->space_info = space_info; 10274 cache->space_info = space_info;
10405 10275
@@ -10533,7 +10403,7 @@ int btrfs_make_block_group(struct btrfs_trans_handle *trans, u64 bytes_used,
10533 * assigned to our block group. We want our bg to be added to the rbtree 10403 * assigned to our block group. We want our bg to be added to the rbtree
10534 * with its ->space_info set. 10404 * with its ->space_info set.
10535 */ 10405 */
10536 cache->space_info = __find_space_info(fs_info, cache->flags); 10406 cache->space_info = btrfs_find_space_info(fs_info, cache->flags);
10537 ASSERT(cache->space_info); 10407 ASSERT(cache->space_info);
10538 10408
10539 ret = btrfs_add_block_group_cache(fs_info, cache); 10409 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,
10548 * the rbtree, update the space info's counters. 10418 * the rbtree, update the space info's counters.
10549 */ 10419 */
10550 trace_btrfs_add_block_group(fs_info, cache, 1); 10420 trace_btrfs_add_block_group(fs_info, cache, 1);
10551 update_space_info(fs_info, cache->flags, size, bytes_used, 10421 btrfs_update_space_info(fs_info, cache->flags, size, bytes_used,
10552 cache->bytes_super, &cache->space_info); 10422 cache->bytes_super, &cache->space_info);
10553 update_global_block_rsv(fs_info); 10423 update_global_block_rsv(fs_info);
10554 10424
@@ -11085,43 +10955,6 @@ next:
11085 spin_unlock(&fs_info->unused_bgs_lock); 10955 spin_unlock(&fs_info->unused_bgs_lock);
11086} 10956}
11087 10957
11088int btrfs_init_space_info(struct btrfs_fs_info *fs_info)
11089{
11090 struct btrfs_super_block *disk_super;
11091 u64 features;
11092 u64 flags;
11093 int mixed = 0;
11094 int ret;
11095
11096 disk_super = fs_info->super_copy;
11097 if (!btrfs_super_root(disk_super))
11098 return -EINVAL;
11099
11100 features = btrfs_super_incompat_flags(disk_super);
11101 if (features & BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS)
11102 mixed = 1;
11103
11104 flags = BTRFS_BLOCK_GROUP_SYSTEM;
11105 ret = create_space_info(fs_info, flags);
11106 if (ret)
11107 goto out;
11108
11109 if (mixed) {
11110 flags = BTRFS_BLOCK_GROUP_METADATA | BTRFS_BLOCK_GROUP_DATA;
11111 ret = create_space_info(fs_info, flags);
11112 } else {
11113 flags = BTRFS_BLOCK_GROUP_METADATA;
11114 ret = create_space_info(fs_info, flags);
11115 if (ret)
11116 goto out;
11117
11118 flags = BTRFS_BLOCK_GROUP_DATA;
11119 ret = create_space_info(fs_info, flags);
11120 }
11121out:
11122 return ret;
11123}
11124
11125int btrfs_error_unpin_extent_range(struct btrfs_fs_info *fs_info, 10958int btrfs_error_unpin_extent_range(struct btrfs_fs_info *fs_info,
11126 u64 start, u64 end) 10959 u64 start, u64 end)
11127{ 10960{
diff --git a/fs/btrfs/space-info.c b/fs/btrfs/space-info.c
new file mode 100644
index 000000000000..6edcd9b7cab2
--- /dev/null
+++ b/fs/btrfs/space-info.c
@@ -0,0 +1,174 @@
1// SPDX-License-Identifier: GPL-2.0
2
3#include "ctree.h"
4#include "space-info.h"
5#include "sysfs.h"
6#include "volumes.h"
7
8u64 btrfs_space_info_used(struct btrfs_space_info *s_info,
9 bool may_use_included)
10{
11 ASSERT(s_info);
12 return s_info->bytes_used + s_info->bytes_reserved +
13 s_info->bytes_pinned + s_info->bytes_readonly +
14 (may_use_included ? s_info->bytes_may_use : 0);
15}
16
17/*
18 * after adding space to the filesystem, we need to clear the full flags
19 * on all the space infos.
20 */
21void btrfs_clear_space_info_full(struct btrfs_fs_info *info)
22{
23 struct list_head *head = &info->space_info;
24 struct btrfs_space_info *found;
25
26 rcu_read_lock();
27 list_for_each_entry_rcu(found, head, list)
28 found->full = 0;
29 rcu_read_unlock();
30}
31
32static const char *alloc_name(u64 flags)
33{
34 switch (flags) {
35 case BTRFS_BLOCK_GROUP_METADATA|BTRFS_BLOCK_GROUP_DATA:
36 return "mixed";
37 case BTRFS_BLOCK_GROUP_METADATA:
38 return "metadata";
39 case BTRFS_BLOCK_GROUP_DATA:
40 return "data";
41 case BTRFS_BLOCK_GROUP_SYSTEM:
42 return "system";
43 default:
44 WARN_ON(1);
45 return "invalid-combination";
46 };
47}
48
49static int create_space_info(struct btrfs_fs_info *info, u64 flags)
50{
51
52 struct btrfs_space_info *space_info;
53 int i;
54 int ret;
55
56 space_info = kzalloc(sizeof(*space_info), GFP_NOFS);
57 if (!space_info)
58 return -ENOMEM;
59
60 ret = percpu_counter_init(&space_info->total_bytes_pinned, 0,
61 GFP_KERNEL);
62 if (ret) {
63 kfree(space_info);
64 return ret;
65 }
66
67 for (i = 0; i < BTRFS_NR_RAID_TYPES; i++)
68 INIT_LIST_HEAD(&space_info->block_groups[i]);
69 init_rwsem(&space_info->groups_sem);
70 spin_lock_init(&space_info->lock);
71 space_info->flags = flags & BTRFS_BLOCK_GROUP_TYPE_MASK;
72 space_info->force_alloc = CHUNK_ALLOC_NO_FORCE;
73 init_waitqueue_head(&space_info->wait);
74 INIT_LIST_HEAD(&space_info->ro_bgs);
75 INIT_LIST_HEAD(&space_info->tickets);
76 INIT_LIST_HEAD(&space_info->priority_tickets);
77
78 ret = kobject_init_and_add(&space_info->kobj, &space_info_ktype,
79 info->space_info_kobj, "%s",
80 alloc_name(space_info->flags));
81 if (ret) {
82 kobject_put(&space_info->kobj);
83 return ret;
84 }
85
86 list_add_rcu(&space_info->list, &info->space_info);
87 if (flags & BTRFS_BLOCK_GROUP_DATA)
88 info->data_sinfo = space_info;
89
90 return ret;
91}
92
93int btrfs_init_space_info(struct btrfs_fs_info *fs_info)
94{
95 struct btrfs_super_block *disk_super;
96 u64 features;
97 u64 flags;
98 int mixed = 0;
99 int ret;
100
101 disk_super = fs_info->super_copy;
102 if (!btrfs_super_root(disk_super))
103 return -EINVAL;
104
105 features = btrfs_super_incompat_flags(disk_super);
106 if (features & BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS)
107 mixed = 1;
108
109 flags = BTRFS_BLOCK_GROUP_SYSTEM;
110 ret = create_space_info(fs_info, flags);
111 if (ret)
112 goto out;
113
114 if (mixed) {
115 flags = BTRFS_BLOCK_GROUP_METADATA | BTRFS_BLOCK_GROUP_DATA;
116 ret = create_space_info(fs_info, flags);
117 } else {
118 flags = BTRFS_BLOCK_GROUP_METADATA;
119 ret = create_space_info(fs_info, flags);
120 if (ret)
121 goto out;
122
123 flags = BTRFS_BLOCK_GROUP_DATA;
124 ret = create_space_info(fs_info, flags);
125 }
126out:
127 return ret;
128}
129
130void btrfs_update_space_info(struct btrfs_fs_info *info, u64 flags,
131 u64 total_bytes, u64 bytes_used,
132 u64 bytes_readonly,
133 struct btrfs_space_info **space_info)
134{
135 struct btrfs_space_info *found;
136 int factor;
137
138 factor = btrfs_bg_type_to_factor(flags);
139
140 found = btrfs_find_space_info(info, flags);
141 ASSERT(found);
142 spin_lock(&found->lock);
143 found->total_bytes += total_bytes;
144 found->disk_total += total_bytes * factor;
145 found->bytes_used += bytes_used;
146 found->disk_used += bytes_used * factor;
147 found->bytes_readonly += bytes_readonly;
148 if (total_bytes > 0)
149 found->full = 0;
150 btrfs_space_info_add_new_bytes(info, found,
151 total_bytes - bytes_used -
152 bytes_readonly);
153 spin_unlock(&found->lock);
154 *space_info = found;
155}
156
157struct btrfs_space_info *btrfs_find_space_info(struct btrfs_fs_info *info,
158 u64 flags)
159{
160 struct list_head *head = &info->space_info;
161 struct btrfs_space_info *found;
162
163 flags &= BTRFS_BLOCK_GROUP_TYPE_MASK;
164
165 rcu_read_lock();
166 list_for_each_entry_rcu(found, head, list) {
167 if (found->flags & flags) {
168 rcu_read_unlock();
169 return found;
170 }
171 }
172 rcu_read_unlock();
173 return NULL;
174}
diff --git a/fs/btrfs/space-info.h b/fs/btrfs/space-info.h
index 46f15b8c9ffc..d1264d9223f2 100644
--- a/fs/btrfs/space-info.h
+++ b/fs/btrfs/space-info.h
@@ -81,5 +81,15 @@ void btrfs_space_info_add_new_bytes(struct btrfs_fs_info *fs_info,
81void btrfs_space_info_add_old_bytes(struct btrfs_fs_info *fs_info, 81void btrfs_space_info_add_old_bytes(struct btrfs_fs_info *fs_info,
82 struct btrfs_space_info *space_info, 82 struct btrfs_space_info *space_info,
83 u64 num_bytes); 83 u64 num_bytes);
84int btrfs_init_space_info(struct btrfs_fs_info *fs_info);
85void btrfs_update_space_info(struct btrfs_fs_info *info, u64 flags,
86 u64 total_bytes, u64 bytes_used,
87 u64 bytes_readonly,
88 struct btrfs_space_info **space_info);
89struct btrfs_space_info *btrfs_find_space_info(struct btrfs_fs_info *info,
90 u64 flags);
91u64 btrfs_space_info_used(struct btrfs_space_info *s_info,
92 bool may_use_included);
93void btrfs_clear_space_info_full(struct btrfs_fs_info *info);
84 94
85#endif /* BTRFS_SPACE_INFO_H */ 95#endif /* BTRFS_SPACE_INFO_H */