aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/extent-tree.c
diff options
context:
space:
mode:
authorYan Zheng <zheng.yan@oracle.com>2008-12-11 16:30:39 -0500
committerChris Mason <chris.mason@oracle.com>2008-12-11 16:30:39 -0500
commitd2fb3437e4d8d12c73c587615ad187d5288547ec (patch)
tree894e4c698970dd35226b2614b8a38fb8a96580e7 /fs/btrfs/extent-tree.c
parentcfc8ea87201dc9bb6aeb3fc80c61abee83e7cc06 (diff)
Btrfs: fix leaking block group on balance
The block group structs are referenced in many different places, and it's not safe to free while balancing. So, those block group structs were simply leaked instead. This patch replaces the block group pointer in the inode with the starting byte offset of the block group and adds reference counting to the block group struct. Signed-off-by: Yan Zheng <zheng.yan@oracle.com>
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r--fs/btrfs/extent-tree.c132
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);
54static int del_pending_extents(struct btrfs_trans_handle *trans, struct 54static int del_pending_extents(struct btrfs_trans_handle *trans, struct
55 btrfs_root *extent_root, int all); 55 btrfs_root *extent_root, int all);
56static 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);
60static int pin_down_bytes(struct btrfs_trans_handle *trans, 56static 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
319static 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
321static struct btrfs_space_info *__find_space_info(struct btrfs_fs_info *info, 325static 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
344static struct btrfs_block_group_cache * 348u64 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 }
392again: 358again:
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 }
425found: 393found:
426 return found_group; 394 return group_start;
427}
428
429struct 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
1769int 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
1812static int update_space_info(struct btrfs_fs_info *info, u64 flags, 1782static 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,
2008static u64 first_logical_byte(struct btrfs_root *root, u64 search_start) 1978static 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
2019int btrfs_update_pinned_extents(struct btrfs_root *root, 1993int 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 }
2929new_group: 2906new_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;
2931new_group_no_lock: 2910new_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;
5707out: 5693out:
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)