diff options
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r-- | fs/btrfs/extent-tree.c | 132 |
1 files changed, 60 insertions, 72 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 673ff59c288a..1cc89246ee2f 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -53,10 +53,6 @@ static int finish_current_insert(struct btrfs_trans_handle *trans, struct | |||
53 | btrfs_root *extent_root, int all); | 53 | btrfs_root *extent_root, int all); |
54 | static int del_pending_extents(struct btrfs_trans_handle *trans, struct | 54 | static int del_pending_extents(struct btrfs_trans_handle *trans, struct |
55 | btrfs_root *extent_root, int all); | 55 | btrfs_root *extent_root, int all); |
56 | static struct btrfs_block_group_cache * | ||
57 | __btrfs_find_block_group(struct btrfs_root *root, | ||
58 | struct btrfs_block_group_cache *hint, | ||
59 | u64 search_start, int data, int owner); | ||
60 | static int pin_down_bytes(struct btrfs_trans_handle *trans, | 56 | static int pin_down_bytes(struct btrfs_trans_handle *trans, |
61 | struct btrfs_root *root, | 57 | struct btrfs_root *root, |
62 | u64 bytenr, u64 num_bytes, int is_data); | 58 | u64 bytenr, u64 num_bytes, int is_data); |
@@ -142,6 +138,8 @@ block_group_cache_tree_search(struct btrfs_fs_info *info, u64 bytenr, | |||
142 | break; | 138 | break; |
143 | } | 139 | } |
144 | } | 140 | } |
141 | if (ret) | ||
142 | atomic_inc(&ret->count); | ||
145 | spin_unlock(&info->block_group_cache_lock); | 143 | spin_unlock(&info->block_group_cache_lock); |
146 | 144 | ||
147 | return ret; | 145 | return ret; |
@@ -318,6 +316,12 @@ struct btrfs_block_group_cache *btrfs_lookup_block_group(struct | |||
318 | return cache; | 316 | return cache; |
319 | } | 317 | } |
320 | 318 | ||
319 | static inline void put_block_group(struct btrfs_block_group_cache *cache) | ||
320 | { | ||
321 | if (atomic_dec_and_test(&cache->count)) | ||
322 | kfree(cache); | ||
323 | } | ||
324 | |||
321 | static struct btrfs_space_info *__find_space_info(struct btrfs_fs_info *info, | 325 | static struct btrfs_space_info *__find_space_info(struct btrfs_fs_info *info, |
322 | u64 flags) | 326 | u64 flags) |
323 | { | 327 | { |
@@ -341,54 +345,16 @@ static u64 div_factor(u64 num, int factor) | |||
341 | return num; | 345 | return num; |
342 | } | 346 | } |
343 | 347 | ||
344 | static struct btrfs_block_group_cache * | 348 | u64 btrfs_find_block_group(struct btrfs_root *root, |
345 | __btrfs_find_block_group(struct btrfs_root *root, | 349 | u64 search_start, u64 search_hint, int owner) |
346 | struct btrfs_block_group_cache *hint, | ||
347 | u64 search_start, int data, int owner) | ||
348 | { | 350 | { |
349 | struct btrfs_block_group_cache *cache; | 351 | struct btrfs_block_group_cache *cache; |
350 | struct btrfs_block_group_cache *found_group = NULL; | ||
351 | struct btrfs_fs_info *info = root->fs_info; | ||
352 | u64 used; | 352 | u64 used; |
353 | u64 last = 0; | 353 | u64 last = max(search_hint, search_start); |
354 | u64 free_check; | 354 | u64 group_start = 0; |
355 | int full_search = 0; | 355 | int full_search = 0; |
356 | int factor = 10; | 356 | int factor = 9; |
357 | int wrapped = 0; | 357 | int wrapped = 0; |
358 | |||
359 | if (data & BTRFS_BLOCK_GROUP_METADATA) | ||
360 | factor = 9; | ||
361 | |||
362 | if (search_start) { | ||
363 | struct btrfs_block_group_cache *shint; | ||
364 | shint = btrfs_lookup_first_block_group(info, search_start); | ||
365 | if (shint && block_group_bits(shint, data)) { | ||
366 | spin_lock(&shint->lock); | ||
367 | used = btrfs_block_group_used(&shint->item); | ||
368 | if (used + shint->pinned + shint->reserved < | ||
369 | div_factor(shint->key.offset, factor)) { | ||
370 | spin_unlock(&shint->lock); | ||
371 | return shint; | ||
372 | } | ||
373 | spin_unlock(&shint->lock); | ||
374 | } | ||
375 | } | ||
376 | if (hint && block_group_bits(hint, data)) { | ||
377 | spin_lock(&hint->lock); | ||
378 | used = btrfs_block_group_used(&hint->item); | ||
379 | if (used + hint->pinned + hint->reserved < | ||
380 | div_factor(hint->key.offset, factor)) { | ||
381 | spin_unlock(&hint->lock); | ||
382 | return hint; | ||
383 | } | ||
384 | spin_unlock(&hint->lock); | ||
385 | last = hint->key.objectid + hint->key.offset; | ||
386 | } else { | ||
387 | if (hint) | ||
388 | last = max(hint->key.objectid, search_start); | ||
389 | else | ||
390 | last = search_start; | ||
391 | } | ||
392 | again: | 358 | again: |
393 | while (1) { | 359 | while (1) { |
394 | cache = btrfs_lookup_first_block_group(root->fs_info, last); | 360 | cache = btrfs_lookup_first_block_group(root->fs_info, last); |
@@ -399,16 +365,18 @@ again: | |||
399 | last = cache->key.objectid + cache->key.offset; | 365 | last = cache->key.objectid + cache->key.offset; |
400 | used = btrfs_block_group_used(&cache->item); | 366 | used = btrfs_block_group_used(&cache->item); |
401 | 367 | ||
402 | if (block_group_bits(cache, data)) { | 368 | if ((full_search || !cache->ro) && |
403 | free_check = div_factor(cache->key.offset, factor); | 369 | block_group_bits(cache, BTRFS_BLOCK_GROUP_METADATA)) { |
404 | if (used + cache->pinned + cache->reserved < | 370 | if (used + cache->pinned + cache->reserved < |
405 | free_check) { | 371 | div_factor(cache->key.offset, factor)) { |
406 | found_group = cache; | 372 | group_start = cache->key.objectid; |
407 | spin_unlock(&cache->lock); | 373 | spin_unlock(&cache->lock); |
374 | put_block_group(cache); | ||
408 | goto found; | 375 | goto found; |
409 | } | 376 | } |
410 | } | 377 | } |
411 | spin_unlock(&cache->lock); | 378 | spin_unlock(&cache->lock); |
379 | put_block_group(cache); | ||
412 | cond_resched(); | 380 | cond_resched(); |
413 | } | 381 | } |
414 | if (!wrapped) { | 382 | if (!wrapped) { |
@@ -423,18 +391,7 @@ again: | |||
423 | goto again; | 391 | goto again; |
424 | } | 392 | } |
425 | found: | 393 | found: |
426 | return found_group; | 394 | return group_start; |
427 | } | ||
428 | |||
429 | struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root, | ||
430 | struct btrfs_block_group_cache | ||
431 | *hint, u64 search_start, | ||
432 | int data, int owner) | ||
433 | { | ||
434 | |||
435 | struct btrfs_block_group_cache *ret; | ||
436 | ret = __btrfs_find_block_group(root, hint, search_start, data, owner); | ||
437 | return ret; | ||
438 | } | 395 | } |
439 | 396 | ||
440 | /* simple helper to search for an existing extent at a given offset */ | 397 | /* simple helper to search for an existing extent at a given offset */ |
@@ -1809,6 +1766,19 @@ int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans, | |||
1809 | return werr; | 1766 | return werr; |
1810 | } | 1767 | } |
1811 | 1768 | ||
1769 | int btrfs_extent_readonly(struct btrfs_root *root, u64 bytenr) | ||
1770 | { | ||
1771 | struct btrfs_block_group_cache *block_group; | ||
1772 | int readonly = 0; | ||
1773 | |||
1774 | block_group = btrfs_lookup_block_group(root->fs_info, bytenr); | ||
1775 | if (!block_group || block_group->ro) | ||
1776 | readonly = 1; | ||
1777 | if (block_group) | ||
1778 | put_block_group(block_group); | ||
1779 | return readonly; | ||
1780 | } | ||
1781 | |||
1812 | static int update_space_info(struct btrfs_fs_info *info, u64 flags, | 1782 | static int update_space_info(struct btrfs_fs_info *info, u64 flags, |
1813 | u64 total_bytes, u64 bytes_used, | 1783 | u64 total_bytes, u64 bytes_used, |
1814 | struct btrfs_space_info **space_info) | 1784 | struct btrfs_space_info **space_info) |
@@ -1995,10 +1965,10 @@ static int update_block_group(struct btrfs_trans_handle *trans, | |||
1995 | int ret; | 1965 | int ret; |
1996 | ret = btrfs_add_free_space(cache, bytenr, | 1966 | ret = btrfs_add_free_space(cache, bytenr, |
1997 | num_bytes); | 1967 | num_bytes); |
1998 | if (ret) | 1968 | WARN_ON(ret); |
1999 | return -1; | ||
2000 | } | 1969 | } |
2001 | } | 1970 | } |
1971 | put_block_group(cache); | ||
2002 | total -= num_bytes; | 1972 | total -= num_bytes; |
2003 | bytenr += num_bytes; | 1973 | bytenr += num_bytes; |
2004 | } | 1974 | } |
@@ -2008,12 +1978,16 @@ static int update_block_group(struct btrfs_trans_handle *trans, | |||
2008 | static u64 first_logical_byte(struct btrfs_root *root, u64 search_start) | 1978 | static u64 first_logical_byte(struct btrfs_root *root, u64 search_start) |
2009 | { | 1979 | { |
2010 | struct btrfs_block_group_cache *cache; | 1980 | struct btrfs_block_group_cache *cache; |
1981 | u64 bytenr; | ||
2011 | 1982 | ||
2012 | cache = btrfs_lookup_first_block_group(root->fs_info, search_start); | 1983 | cache = btrfs_lookup_first_block_group(root->fs_info, search_start); |
2013 | if (!cache) | 1984 | if (!cache) |
2014 | return 0; | 1985 | return 0; |
2015 | 1986 | ||
2016 | return cache->key.objectid; | 1987 | bytenr = cache->key.objectid; |
1988 | put_block_group(cache); | ||
1989 | |||
1990 | return bytenr; | ||
2017 | } | 1991 | } |
2018 | 1992 | ||
2019 | int btrfs_update_pinned_extents(struct btrfs_root *root, | 1993 | int btrfs_update_pinned_extents(struct btrfs_root *root, |
@@ -2055,6 +2029,7 @@ int btrfs_update_pinned_extents(struct btrfs_root *root, | |||
2055 | if (cache->cached) | 2029 | if (cache->cached) |
2056 | btrfs_add_free_space(cache, bytenr, len); | 2030 | btrfs_add_free_space(cache, bytenr, len); |
2057 | } | 2031 | } |
2032 | put_block_group(cache); | ||
2058 | bytenr += len; | 2033 | bytenr += len; |
2059 | num -= len; | 2034 | num -= len; |
2060 | } | 2035 | } |
@@ -2085,6 +2060,7 @@ static int update_reserved_extents(struct btrfs_root *root, | |||
2085 | } | 2060 | } |
2086 | spin_unlock(&cache->lock); | 2061 | spin_unlock(&cache->lock); |
2087 | spin_unlock(&cache->space_info->lock); | 2062 | spin_unlock(&cache->space_info->lock); |
2063 | put_block_group(cache); | ||
2088 | bytenr += len; | 2064 | bytenr += len; |
2089 | num -= len; | 2065 | num -= len; |
2090 | } | 2066 | } |
@@ -2724,6 +2700,7 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans, | |||
2724 | cache = btrfs_lookup_block_group(root->fs_info, bytenr); | 2700 | cache = btrfs_lookup_block_group(root->fs_info, bytenr); |
2725 | BUG_ON(!cache); | 2701 | BUG_ON(!cache); |
2726 | btrfs_add_free_space(cache, bytenr, num_bytes); | 2702 | btrfs_add_free_space(cache, bytenr, num_bytes); |
2703 | put_block_group(cache); | ||
2727 | update_reserved_extents(root, bytenr, num_bytes, 0); | 2704 | update_reserved_extents(root, bytenr, num_bytes, 0); |
2728 | return 0; | 2705 | return 0; |
2729 | } | 2706 | } |
@@ -2928,6 +2905,8 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans, | |||
2928 | } | 2905 | } |
2929 | new_group: | 2906 | new_group: |
2930 | mutex_unlock(&block_group->alloc_mutex); | 2907 | mutex_unlock(&block_group->alloc_mutex); |
2908 | put_block_group(block_group); | ||
2909 | block_group = NULL; | ||
2931 | new_group_no_lock: | 2910 | new_group_no_lock: |
2932 | /* don't try to compare new allocations against the | 2911 | /* don't try to compare new allocations against the |
2933 | * last allocation any more | 2912 | * last allocation any more |
@@ -2997,6 +2976,8 @@ loop_check: | |||
2997 | 2976 | ||
2998 | block_group = list_entry(cur, struct btrfs_block_group_cache, | 2977 | block_group = list_entry(cur, struct btrfs_block_group_cache, |
2999 | list); | 2978 | list); |
2979 | atomic_inc(&block_group->count); | ||
2980 | |||
3000 | search_start = block_group->key.objectid; | 2981 | search_start = block_group->key.objectid; |
3001 | cur = cur->next; | 2982 | cur = cur->next; |
3002 | } | 2983 | } |
@@ -3004,7 +2985,7 @@ loop_check: | |||
3004 | /* we found what we needed */ | 2985 | /* we found what we needed */ |
3005 | if (ins->objectid) { | 2986 | if (ins->objectid) { |
3006 | if (!(data & BTRFS_BLOCK_GROUP_DATA)) | 2987 | if (!(data & BTRFS_BLOCK_GROUP_DATA)) |
3007 | trans->block_group = block_group; | 2988 | trans->block_group = block_group->key.objectid; |
3008 | 2989 | ||
3009 | if (last_ptr) | 2990 | if (last_ptr) |
3010 | *last_ptr = ins->objectid + ins->offset; | 2991 | *last_ptr = ins->objectid + ins->offset; |
@@ -3015,6 +2996,8 @@ loop_check: | |||
3015 | loop, allowed_chunk_alloc); | 2996 | loop, allowed_chunk_alloc); |
3016 | ret = -ENOSPC; | 2997 | ret = -ENOSPC; |
3017 | } | 2998 | } |
2999 | if (block_group) | ||
3000 | put_block_group(block_group); | ||
3018 | 3001 | ||
3019 | up_read(&space_info->groups_sem); | 3002 | up_read(&space_info->groups_sem); |
3020 | return ret; | 3003 | return ret; |
@@ -3124,6 +3107,7 @@ int btrfs_free_reserved_extent(struct btrfs_root *root, u64 start, u64 len) | |||
3124 | return -ENOSPC; | 3107 | return -ENOSPC; |
3125 | } | 3108 | } |
3126 | btrfs_add_free_space(cache, start, len); | 3109 | btrfs_add_free_space(cache, start, len); |
3110 | put_block_group(cache); | ||
3127 | update_reserved_extents(root, start, len, 0); | 3111 | update_reserved_extents(root, start, len, 0); |
3128 | return 0; | 3112 | return 0; |
3129 | } | 3113 | } |
@@ -3288,6 +3272,7 @@ int btrfs_alloc_logged_extent(struct btrfs_trans_handle *trans, | |||
3288 | ret = btrfs_remove_free_space(block_group, ins->objectid, | 3272 | ret = btrfs_remove_free_space(block_group, ins->objectid, |
3289 | ins->offset); | 3273 | ins->offset); |
3290 | BUG_ON(ret); | 3274 | BUG_ON(ret); |
3275 | put_block_group(block_group); | ||
3291 | ret = __btrfs_alloc_reserved_extent(trans, root, parent, root_objectid, | 3276 | ret = __btrfs_alloc_reserved_extent(trans, root, parent, root_objectid, |
3292 | ref_generation, owner, ins); | 3277 | ref_generation, owner, ins); |
3293 | return ret; | 3278 | return ret; |
@@ -5703,6 +5688,7 @@ next: | |||
5703 | WARN_ON(block_group->reserved > 0); | 5688 | WARN_ON(block_group->reserved > 0); |
5704 | WARN_ON(btrfs_block_group_used(&block_group->item) > 0); | 5689 | WARN_ON(btrfs_block_group_used(&block_group->item) > 0); |
5705 | spin_unlock(&block_group->lock); | 5690 | spin_unlock(&block_group->lock); |
5691 | put_block_group(block_group); | ||
5706 | ret = 0; | 5692 | ret = 0; |
5707 | out: | 5693 | out: |
5708 | btrfs_free_path(path); | 5694 | btrfs_free_path(path); |
@@ -5763,6 +5749,8 @@ int btrfs_free_block_groups(struct btrfs_fs_info *info) | |||
5763 | down_write(&block_group->space_info->groups_sem); | 5749 | down_write(&block_group->space_info->groups_sem); |
5764 | list_del(&block_group->list); | 5750 | list_del(&block_group->list); |
5765 | up_write(&block_group->space_info->groups_sem); | 5751 | up_write(&block_group->space_info->groups_sem); |
5752 | |||
5753 | WARN_ON(atomic_read(&block_group->count) != 1); | ||
5766 | kfree(block_group); | 5754 | kfree(block_group); |
5767 | 5755 | ||
5768 | spin_lock(&info->block_group_cache_lock); | 5756 | spin_lock(&info->block_group_cache_lock); |
@@ -5807,6 +5795,7 @@ int btrfs_read_block_groups(struct btrfs_root *root) | |||
5807 | break; | 5795 | break; |
5808 | } | 5796 | } |
5809 | 5797 | ||
5798 | atomic_set(&cache->count, 1); | ||
5810 | spin_lock_init(&cache->lock); | 5799 | spin_lock_init(&cache->lock); |
5811 | mutex_init(&cache->alloc_mutex); | 5800 | mutex_init(&cache->alloc_mutex); |
5812 | mutex_init(&cache->cache_mutex); | 5801 | mutex_init(&cache->cache_mutex); |
@@ -5861,11 +5850,12 @@ int btrfs_make_block_group(struct btrfs_trans_handle *trans, | |||
5861 | 5850 | ||
5862 | cache->key.objectid = chunk_offset; | 5851 | cache->key.objectid = chunk_offset; |
5863 | cache->key.offset = size; | 5852 | cache->key.offset = size; |
5853 | cache->key.type = BTRFS_BLOCK_GROUP_ITEM_KEY; | ||
5854 | atomic_set(&cache->count, 1); | ||
5864 | spin_lock_init(&cache->lock); | 5855 | spin_lock_init(&cache->lock); |
5865 | mutex_init(&cache->alloc_mutex); | 5856 | mutex_init(&cache->alloc_mutex); |
5866 | mutex_init(&cache->cache_mutex); | 5857 | mutex_init(&cache->cache_mutex); |
5867 | INIT_LIST_HEAD(&cache->list); | 5858 | INIT_LIST_HEAD(&cache->list); |
5868 | btrfs_set_key_type(&cache->key, BTRFS_BLOCK_GROUP_ITEM_KEY); | ||
5869 | 5859 | ||
5870 | btrfs_set_block_group_used(&cache->item, bytes_used); | 5860 | btrfs_set_block_group_used(&cache->item, bytes_used); |
5871 | btrfs_set_block_group_chunk_objectid(&cache->item, chunk_objectid); | 5861 | btrfs_set_block_group_chunk_objectid(&cache->item, chunk_objectid); |
@@ -5926,10 +5916,8 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans, | |||
5926 | spin_unlock(&block_group->space_info->lock); | 5916 | spin_unlock(&block_group->space_info->lock); |
5927 | block_group->space_info->full = 0; | 5917 | block_group->space_info->full = 0; |
5928 | 5918 | ||
5929 | /* | 5919 | put_block_group(block_group); |
5930 | memset(shrink_block_group, 0, sizeof(*shrink_block_group)); | 5920 | put_block_group(block_group); |
5931 | kfree(shrink_block_group); | ||
5932 | */ | ||
5933 | 5921 | ||
5934 | ret = btrfs_search_slot(trans, root, &key, path, -1, 1); | 5922 | ret = btrfs_search_slot(trans, root, &key, path, -1, 1); |
5935 | if (ret > 0) | 5923 | if (ret > 0) |