diff options
author | Josef Bacik <josef@toxicpanda.com> | 2019-06-18 16:09:19 -0400 |
---|---|---|
committer | David Sterba <dsterba@suse.com> | 2019-07-02 06:30:52 -0400 |
commit | 280c290881bc048bd5dbe02796173f55ca86e697 (patch) | |
tree | 8fef64c54f7016a89de2fc935e683cc6246be0b5 | |
parent | d44b72aa12d0a74b67ffabdcab2f64653282dccd (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/Makefile | 2 | ||||
-rw-r--r-- | fs/btrfs/extent-tree.c | 205 | ||||
-rw-r--r-- | fs/btrfs/space-info.c | 174 | ||||
-rw-r--r-- | fs/btrfs/space-info.h | 10 |
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 | ||
15 | btrfs-$(CONFIG_BTRFS_FS_POSIX_ACL) += acl.o | 15 | btrfs-$(CONFIG_BTRFS_FS_POSIX_ACL) += acl.o |
16 | btrfs-$(CONFIG_BTRFS_FS_CHECK_INTEGRITY) += check-integrity.o | 16 | btrfs-$(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 | ||
716 | static 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 | |||
735 | static u64 generic_ref_to_space_flags(struct btrfs_ref *ref) | 716 | static 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 | */ | ||
774 | void 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 */ |
786 | int btrfs_lookup_data_extent(struct btrfs_fs_info *fs_info, u64 start, u64 len) | 752 | int 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 | ||
3824 | static 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 | |||
3841 | static 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 | |||
3885 | static 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 | |||
3911 | static void set_avail_alloc_bits(struct btrfs_fs_info *fs_info, u64 flags) | 3790 | static 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 | ||
4058 | static 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 | |||
4067 | int btrfs_alloc_data_chunk_ondemand(struct btrfs_inode *inode, u64 bytes) | 3937 | int 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 | ||
11088 | int 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 | } | ||
11121 | out: | ||
11122 | return ret; | ||
11123 | } | ||
11124 | |||
11125 | int btrfs_error_unpin_extent_range(struct btrfs_fs_info *fs_info, | 10958 | int 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 | |||
8 | u64 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 | */ | ||
21 | void 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 | |||
32 | static 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 | |||
49 | static 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 | |||
93 | int 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 | } | ||
126 | out: | ||
127 | return ret; | ||
128 | } | ||
129 | |||
130 | void 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 | |||
157 | struct 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, | |||
81 | void btrfs_space_info_add_old_bytes(struct btrfs_fs_info *fs_info, | 81 | void 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); |
84 | int btrfs_init_space_info(struct btrfs_fs_info *fs_info); | ||
85 | void 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); | ||
89 | struct btrfs_space_info *btrfs_find_space_info(struct btrfs_fs_info *info, | ||
90 | u64 flags); | ||
91 | u64 btrfs_space_info_used(struct btrfs_space_info *s_info, | ||
92 | bool may_use_included); | ||
93 | void btrfs_clear_space_info_full(struct btrfs_fs_info *info); | ||
84 | 94 | ||
85 | #endif /* BTRFS_SPACE_INFO_H */ | 95 | #endif /* BTRFS_SPACE_INFO_H */ |