diff options
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r-- | fs/btrfs/extent-tree.c | 102 |
1 files changed, 90 insertions, 12 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 178df4c67de4..35af93355063 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -312,7 +312,7 @@ btrfs_lookup_first_block_group(struct btrfs_fs_info *info, u64 bytenr) | |||
312 | } | 312 | } |
313 | 313 | ||
314 | /* | 314 | /* |
315 | * return the block group that contains teh given bytenr | 315 | * return the block group that contains the given bytenr |
316 | */ | 316 | */ |
317 | struct btrfs_block_group_cache *btrfs_lookup_block_group( | 317 | struct btrfs_block_group_cache *btrfs_lookup_block_group( |
318 | struct btrfs_fs_info *info, | 318 | struct btrfs_fs_info *info, |
@@ -1844,10 +1844,14 @@ again: | |||
1844 | printk(KERN_ERR "no space left, need %llu, %llu delalloc bytes" | 1844 | printk(KERN_ERR "no space left, need %llu, %llu delalloc bytes" |
1845 | ", %llu bytes_used, %llu bytes_reserved, " | 1845 | ", %llu bytes_used, %llu bytes_reserved, " |
1846 | "%llu bytes_pinned, %llu bytes_readonly, %llu may use" | 1846 | "%llu bytes_pinned, %llu bytes_readonly, %llu may use" |
1847 | "%llu total\n", bytes, data_sinfo->bytes_delalloc, | 1847 | "%llu total\n", (unsigned long long)bytes, |
1848 | data_sinfo->bytes_used, data_sinfo->bytes_reserved, | 1848 | (unsigned long long)data_sinfo->bytes_delalloc, |
1849 | data_sinfo->bytes_pinned, data_sinfo->bytes_readonly, | 1849 | (unsigned long long)data_sinfo->bytes_used, |
1850 | data_sinfo->bytes_may_use, data_sinfo->total_bytes); | 1850 | (unsigned long long)data_sinfo->bytes_reserved, |
1851 | (unsigned long long)data_sinfo->bytes_pinned, | ||
1852 | (unsigned long long)data_sinfo->bytes_readonly, | ||
1853 | (unsigned long long)data_sinfo->bytes_may_use, | ||
1854 | (unsigned long long)data_sinfo->total_bytes); | ||
1851 | return -ENOSPC; | 1855 | return -ENOSPC; |
1852 | } | 1856 | } |
1853 | data_sinfo->bytes_may_use += bytes; | 1857 | data_sinfo->bytes_may_use += bytes; |
@@ -1918,15 +1922,29 @@ void btrfs_delalloc_free_space(struct btrfs_root *root, struct inode *inode, | |||
1918 | spin_unlock(&info->lock); | 1922 | spin_unlock(&info->lock); |
1919 | } | 1923 | } |
1920 | 1924 | ||
1925 | static void force_metadata_allocation(struct btrfs_fs_info *info) | ||
1926 | { | ||
1927 | struct list_head *head = &info->space_info; | ||
1928 | struct btrfs_space_info *found; | ||
1929 | |||
1930 | rcu_read_lock(); | ||
1931 | list_for_each_entry_rcu(found, head, list) { | ||
1932 | if (found->flags & BTRFS_BLOCK_GROUP_METADATA) | ||
1933 | found->force_alloc = 1; | ||
1934 | } | ||
1935 | rcu_read_unlock(); | ||
1936 | } | ||
1937 | |||
1921 | static int do_chunk_alloc(struct btrfs_trans_handle *trans, | 1938 | static int do_chunk_alloc(struct btrfs_trans_handle *trans, |
1922 | struct btrfs_root *extent_root, u64 alloc_bytes, | 1939 | struct btrfs_root *extent_root, u64 alloc_bytes, |
1923 | u64 flags, int force) | 1940 | u64 flags, int force) |
1924 | { | 1941 | { |
1925 | struct btrfs_space_info *space_info; | 1942 | struct btrfs_space_info *space_info; |
1943 | struct btrfs_fs_info *fs_info = extent_root->fs_info; | ||
1926 | u64 thresh; | 1944 | u64 thresh; |
1927 | int ret = 0; | 1945 | int ret = 0; |
1928 | 1946 | ||
1929 | mutex_lock(&extent_root->fs_info->chunk_mutex); | 1947 | mutex_lock(&fs_info->chunk_mutex); |
1930 | 1948 | ||
1931 | flags = btrfs_reduce_alloc_profile(extent_root, flags); | 1949 | flags = btrfs_reduce_alloc_profile(extent_root, flags); |
1932 | 1950 | ||
@@ -1958,6 +1976,18 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans, | |||
1958 | } | 1976 | } |
1959 | spin_unlock(&space_info->lock); | 1977 | spin_unlock(&space_info->lock); |
1960 | 1978 | ||
1979 | /* | ||
1980 | * if we're doing a data chunk, go ahead and make sure that | ||
1981 | * we keep a reasonable number of metadata chunks allocated in the | ||
1982 | * FS as well. | ||
1983 | */ | ||
1984 | if (flags & BTRFS_BLOCK_GROUP_DATA) { | ||
1985 | fs_info->data_chunk_allocations++; | ||
1986 | if (!(fs_info->data_chunk_allocations % | ||
1987 | fs_info->metadata_ratio)) | ||
1988 | force_metadata_allocation(fs_info); | ||
1989 | } | ||
1990 | |||
1961 | ret = btrfs_alloc_chunk(trans, extent_root, flags); | 1991 | ret = btrfs_alloc_chunk(trans, extent_root, flags); |
1962 | if (ret) | 1992 | if (ret) |
1963 | space_info->full = 1; | 1993 | space_info->full = 1; |
@@ -2592,7 +2622,18 @@ static noinline int find_free_extent(struct btrfs_trans_handle *trans, | |||
2592 | search_start); | 2622 | search_start); |
2593 | if (block_group && block_group_bits(block_group, data)) { | 2623 | if (block_group && block_group_bits(block_group, data)) { |
2594 | down_read(&space_info->groups_sem); | 2624 | down_read(&space_info->groups_sem); |
2595 | goto have_block_group; | 2625 | if (list_empty(&block_group->list) || |
2626 | block_group->ro) { | ||
2627 | /* | ||
2628 | * someone is removing this block group, | ||
2629 | * we can't jump into the have_block_group | ||
2630 | * target because our list pointers are not | ||
2631 | * valid | ||
2632 | */ | ||
2633 | btrfs_put_block_group(block_group); | ||
2634 | up_read(&space_info->groups_sem); | ||
2635 | } else | ||
2636 | goto have_block_group; | ||
2596 | } else if (block_group) { | 2637 | } else if (block_group) { |
2597 | btrfs_put_block_group(block_group); | 2638 | btrfs_put_block_group(block_group); |
2598 | } | 2639 | } |
@@ -2626,6 +2667,13 @@ have_block_group: | |||
2626 | * people trying to start a new cluster | 2667 | * people trying to start a new cluster |
2627 | */ | 2668 | */ |
2628 | spin_lock(&last_ptr->refill_lock); | 2669 | spin_lock(&last_ptr->refill_lock); |
2670 | if (last_ptr->block_group && | ||
2671 | (last_ptr->block_group->ro || | ||
2672 | !block_group_bits(last_ptr->block_group, data))) { | ||
2673 | offset = 0; | ||
2674 | goto refill_cluster; | ||
2675 | } | ||
2676 | |||
2629 | offset = btrfs_alloc_from_cluster(block_group, last_ptr, | 2677 | offset = btrfs_alloc_from_cluster(block_group, last_ptr, |
2630 | num_bytes, search_start); | 2678 | num_bytes, search_start); |
2631 | if (offset) { | 2679 | if (offset) { |
@@ -2651,10 +2699,17 @@ have_block_group: | |||
2651 | 2699 | ||
2652 | last_ptr_loop = 1; | 2700 | last_ptr_loop = 1; |
2653 | search_start = block_group->key.objectid; | 2701 | search_start = block_group->key.objectid; |
2702 | /* | ||
2703 | * we know this block group is properly | ||
2704 | * in the list because | ||
2705 | * btrfs_remove_block_group, drops the | ||
2706 | * cluster before it removes the block | ||
2707 | * group from the list | ||
2708 | */ | ||
2654 | goto have_block_group; | 2709 | goto have_block_group; |
2655 | } | 2710 | } |
2656 | spin_unlock(&last_ptr->lock); | 2711 | spin_unlock(&last_ptr->lock); |
2657 | 2712 | refill_cluster: | |
2658 | /* | 2713 | /* |
2659 | * this cluster didn't work out, free it and | 2714 | * this cluster didn't work out, free it and |
2660 | * start over | 2715 | * start over |
@@ -2798,9 +2853,12 @@ static void dump_space_info(struct btrfs_space_info *info, u64 bytes) | |||
2798 | info->bytes_pinned - info->bytes_reserved), | 2853 | info->bytes_pinned - info->bytes_reserved), |
2799 | (info->full) ? "" : "not "); | 2854 | (info->full) ? "" : "not "); |
2800 | printk(KERN_INFO "space_info total=%llu, pinned=%llu, delalloc=%llu," | 2855 | printk(KERN_INFO "space_info total=%llu, pinned=%llu, delalloc=%llu," |
2801 | " may_use=%llu, used=%llu\n", info->total_bytes, | 2856 | " may_use=%llu, used=%llu\n", |
2802 | info->bytes_pinned, info->bytes_delalloc, info->bytes_may_use, | 2857 | (unsigned long long)info->total_bytes, |
2803 | info->bytes_used); | 2858 | (unsigned long long)info->bytes_pinned, |
2859 | (unsigned long long)info->bytes_delalloc, | ||
2860 | (unsigned long long)info->bytes_may_use, | ||
2861 | (unsigned long long)info->bytes_used); | ||
2804 | 2862 | ||
2805 | down_read(&info->groups_sem); | 2863 | down_read(&info->groups_sem); |
2806 | list_for_each_entry(cache, &info->block_groups, list) { | 2864 | list_for_each_entry(cache, &info->block_groups, list) { |
@@ -5935,6 +5993,7 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans, | |||
5935 | { | 5993 | { |
5936 | struct btrfs_path *path; | 5994 | struct btrfs_path *path; |
5937 | struct btrfs_block_group_cache *block_group; | 5995 | struct btrfs_block_group_cache *block_group; |
5996 | struct btrfs_free_cluster *cluster; | ||
5938 | struct btrfs_key key; | 5997 | struct btrfs_key key; |
5939 | int ret; | 5998 | int ret; |
5940 | 5999 | ||
@@ -5946,6 +6005,21 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans, | |||
5946 | 6005 | ||
5947 | memcpy(&key, &block_group->key, sizeof(key)); | 6006 | memcpy(&key, &block_group->key, sizeof(key)); |
5948 | 6007 | ||
6008 | /* make sure this block group isn't part of an allocation cluster */ | ||
6009 | cluster = &root->fs_info->data_alloc_cluster; | ||
6010 | spin_lock(&cluster->refill_lock); | ||
6011 | btrfs_return_cluster_to_free_space(block_group, cluster); | ||
6012 | spin_unlock(&cluster->refill_lock); | ||
6013 | |||
6014 | /* | ||
6015 | * make sure this block group isn't part of a metadata | ||
6016 | * allocation cluster | ||
6017 | */ | ||
6018 | cluster = &root->fs_info->meta_alloc_cluster; | ||
6019 | spin_lock(&cluster->refill_lock); | ||
6020 | btrfs_return_cluster_to_free_space(block_group, cluster); | ||
6021 | spin_unlock(&cluster->refill_lock); | ||
6022 | |||
5949 | path = btrfs_alloc_path(); | 6023 | path = btrfs_alloc_path(); |
5950 | BUG_ON(!path); | 6024 | BUG_ON(!path); |
5951 | 6025 | ||
@@ -5955,7 +6029,11 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans, | |||
5955 | spin_unlock(&root->fs_info->block_group_cache_lock); | 6029 | spin_unlock(&root->fs_info->block_group_cache_lock); |
5956 | btrfs_remove_free_space_cache(block_group); | 6030 | btrfs_remove_free_space_cache(block_group); |
5957 | down_write(&block_group->space_info->groups_sem); | 6031 | down_write(&block_group->space_info->groups_sem); |
5958 | list_del(&block_group->list); | 6032 | /* |
6033 | * we must use list_del_init so people can check to see if they | ||
6034 | * are still on the list after taking the semaphore | ||
6035 | */ | ||
6036 | list_del_init(&block_group->list); | ||
5959 | up_write(&block_group->space_info->groups_sem); | 6037 | up_write(&block_group->space_info->groups_sem); |
5960 | 6038 | ||
5961 | spin_lock(&block_group->space_info->lock); | 6039 | spin_lock(&block_group->space_info->lock); |