aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/btrfs/ctree.h11
-rw-r--r--fs/btrfs/extent-tree.c46
-rw-r--r--fs/btrfs/free-space-cache.c183
3 files changed, 83 insertions, 157 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index f48905ee5240..527744561f93 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -644,7 +644,6 @@ struct btrfs_block_group_cache {
644 struct btrfs_key key; 644 struct btrfs_key key;
645 struct btrfs_block_group_item item; 645 struct btrfs_block_group_item item;
646 spinlock_t lock; 646 spinlock_t lock;
647 struct mutex alloc_mutex;
648 struct mutex cache_mutex; 647 struct mutex cache_mutex;
649 u64 pinned; 648 u64 pinned;
650 u64 reserved; 649 u64 reserved;
@@ -656,6 +655,7 @@ struct btrfs_block_group_cache {
656 struct btrfs_space_info *space_info; 655 struct btrfs_space_info *space_info;
657 656
658 /* free space cache stuff */ 657 /* free space cache stuff */
658 spinlock_t tree_lock;
659 struct rb_root free_space_bytes; 659 struct rb_root free_space_bytes;
660 struct rb_root free_space_offset; 660 struct rb_root free_space_offset;
661 661
@@ -2177,17 +2177,12 @@ int btrfs_acl_chmod(struct inode *inode);
2177/* free-space-cache.c */ 2177/* free-space-cache.c */
2178int btrfs_add_free_space(struct btrfs_block_group_cache *block_group, 2178int btrfs_add_free_space(struct btrfs_block_group_cache *block_group,
2179 u64 bytenr, u64 size); 2179 u64 bytenr, u64 size);
2180int btrfs_add_free_space_lock(struct btrfs_block_group_cache *block_group,
2181 u64 offset, u64 bytes);
2182int btrfs_remove_free_space(struct btrfs_block_group_cache *block_group, 2180int btrfs_remove_free_space(struct btrfs_block_group_cache *block_group,
2183 u64 bytenr, u64 size); 2181 u64 bytenr, u64 size);
2184int btrfs_remove_free_space_lock(struct btrfs_block_group_cache *block_group,
2185 u64 offset, u64 bytes);
2186void btrfs_remove_free_space_cache(struct btrfs_block_group_cache 2182void btrfs_remove_free_space_cache(struct btrfs_block_group_cache
2187 *block_group); 2183 *block_group);
2188struct btrfs_free_space *btrfs_find_free_space(struct btrfs_block_group_cache 2184u64 btrfs_find_space_for_alloc(struct btrfs_block_group_cache *block_group,
2189 *block_group, u64 offset, 2185 u64 offset, u64 bytes, u64 empty_size);
2190 u64 bytes);
2191void btrfs_dump_free_space(struct btrfs_block_group_cache *block_group, 2186void btrfs_dump_free_space(struct btrfs_block_group_cache *block_group,
2192 u64 bytes); 2187 u64 bytes);
2193u64 btrfs_block_group_free_space(struct btrfs_block_group_cache *block_group); 2188u64 btrfs_block_group_free_space(struct btrfs_block_group_cache *block_group);
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index daff751ea6e2..6880a271975a 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -2554,7 +2554,6 @@ static noinline int find_free_extent(struct btrfs_trans_handle *trans,
2554{ 2554{
2555 int ret = 0; 2555 int ret = 0;
2556 struct btrfs_root *root = orig_root->fs_info->extent_root; 2556 struct btrfs_root *root = orig_root->fs_info->extent_root;
2557 u64 total_needed = num_bytes;
2558 u64 *last_ptr = NULL; 2557 u64 *last_ptr = NULL;
2559 struct btrfs_block_group_cache *block_group = NULL; 2558 struct btrfs_block_group_cache *block_group = NULL;
2560 int empty_cluster = 2 * 1024 * 1024; 2559 int empty_cluster = 2 * 1024 * 1024;
@@ -2597,7 +2596,6 @@ static noinline int find_free_extent(struct btrfs_trans_handle *trans,
2597 block_group = btrfs_lookup_block_group(root->fs_info, 2596 block_group = btrfs_lookup_block_group(root->fs_info,
2598 search_start); 2597 search_start);
2599 if (block_group && block_group_bits(block_group, data)) { 2598 if (block_group && block_group_bits(block_group, data)) {
2600 total_needed += empty_size;
2601 down_read(&space_info->groups_sem); 2599 down_read(&space_info->groups_sem);
2602 goto have_block_group; 2600 goto have_block_group;
2603 } else if (block_group) { 2601 } else if (block_group) {
@@ -2611,7 +2609,7 @@ static noinline int find_free_extent(struct btrfs_trans_handle *trans,
2611search: 2609search:
2612 down_read(&space_info->groups_sem); 2610 down_read(&space_info->groups_sem);
2613 list_for_each_entry(block_group, &space_info->block_groups, list) { 2611 list_for_each_entry(block_group, &space_info->block_groups, list) {
2614 struct btrfs_free_space *free_space; 2612 u64 offset;
2615 2613
2616 atomic_inc(&block_group->count); 2614 atomic_inc(&block_group->count);
2617 search_start = block_group->key.objectid; 2615 search_start = block_group->key.objectid;
@@ -2627,62 +2625,65 @@ have_block_group:
2627 } 2625 }
2628 } 2626 }
2629 2627
2630 mutex_lock(&block_group->alloc_mutex);
2631
2632 if (unlikely(block_group->ro)) 2628 if (unlikely(block_group->ro))
2633 goto loop; 2629 goto loop;
2634 2630
2635 free_space = btrfs_find_free_space(block_group, search_start, 2631 offset = btrfs_find_space_for_alloc(block_group, search_start,
2636 total_needed); 2632 num_bytes, empty_size);
2637 if (!free_space) 2633 if (!offset)
2638 goto loop; 2634 goto loop;
2639 2635
2640 search_start = stripe_align(root, free_space->offset); 2636 search_start = stripe_align(root, offset);
2641 2637
2642 /* move on to the next group */ 2638 /* move on to the next group */
2643 if (search_start + num_bytes >= search_end) 2639 if (search_start + num_bytes >= search_end) {
2640 btrfs_add_free_space(block_group, offset, num_bytes);
2644 goto loop; 2641 goto loop;
2642 }
2645 2643
2646 /* move on to the next group */ 2644 /* move on to the next group */
2647 if (search_start + num_bytes > 2645 if (search_start + num_bytes >
2648 block_group->key.objectid + block_group->key.offset) 2646 block_group->key.objectid + block_group->key.offset) {
2647 btrfs_add_free_space(block_group, offset, num_bytes);
2649 goto loop; 2648 goto loop;
2649 }
2650 2650
2651 if (using_hint && search_start > hint_byte) 2651 if (using_hint && search_start > hint_byte) {
2652 btrfs_add_free_space(block_group, offset, num_bytes);
2652 goto loop; 2653 goto loop;
2654 }
2653 2655
2654 if (exclude_nr > 0 && 2656 if (exclude_nr > 0 &&
2655 (search_start + num_bytes > exclude_start && 2657 (search_start + num_bytes > exclude_start &&
2656 search_start < exclude_start + exclude_nr)) { 2658 search_start < exclude_start + exclude_nr)) {
2657 search_start = exclude_start + exclude_nr; 2659 search_start = exclude_start + exclude_nr;
2658 2660
2661 btrfs_add_free_space(block_group, offset, num_bytes);
2659 /* 2662 /*
2660 * if search_start is still in this block group 2663 * if search_start is still in this block group
2661 * then we just re-search this block group 2664 * then we just re-search this block group
2662 */ 2665 */
2663 if (search_start >= block_group->key.objectid && 2666 if (search_start >= block_group->key.objectid &&
2664 search_start < (block_group->key.objectid + 2667 search_start < (block_group->key.objectid +
2665 block_group->key.offset)) { 2668 block_group->key.offset))
2666 mutex_unlock(&block_group->alloc_mutex);
2667 goto have_block_group; 2669 goto have_block_group;
2668 }
2669 goto loop; 2670 goto loop;
2670 } 2671 }
2671 2672
2672 ins->objectid = search_start; 2673 ins->objectid = search_start;
2673 ins->offset = num_bytes; 2674 ins->offset = num_bytes;
2674 2675
2675 btrfs_remove_free_space_lock(block_group, search_start, 2676 if (offset < search_start)
2676 num_bytes); 2677 btrfs_add_free_space(block_group, offset,
2678 search_start - offset);
2679 BUG_ON(offset > search_start);
2680
2677 /* we are all good, lets return */ 2681 /* we are all good, lets return */
2678 mutex_unlock(&block_group->alloc_mutex);
2679 break; 2682 break;
2680loop: 2683loop:
2681 mutex_unlock(&block_group->alloc_mutex);
2682 put_block_group(block_group); 2684 put_block_group(block_group);
2683 if (using_hint) { 2685 if (using_hint) {
2684 empty_size += empty_cluster; 2686 empty_size += empty_cluster;
2685 total_needed += empty_cluster;
2686 using_hint = 0; 2687 using_hint = 0;
2687 up_read(&space_info->groups_sem); 2688 up_read(&space_info->groups_sem);
2688 goto search; 2689 goto search;
@@ -2693,7 +2694,6 @@ loop:
2693 if (!ins->objectid && (empty_size || allowed_chunk_alloc)) { 2694 if (!ins->objectid && (empty_size || allowed_chunk_alloc)) {
2694 int try_again = empty_size; 2695 int try_again = empty_size;
2695 2696
2696 total_needed -= empty_size;
2697 empty_size = 0; 2697 empty_size = 0;
2698 2698
2699 if (allowed_chunk_alloc) { 2699 if (allowed_chunk_alloc) {
@@ -5782,7 +5782,7 @@ int btrfs_read_block_groups(struct btrfs_root *root)
5782 5782
5783 atomic_set(&cache->count, 1); 5783 atomic_set(&cache->count, 1);
5784 spin_lock_init(&cache->lock); 5784 spin_lock_init(&cache->lock);
5785 mutex_init(&cache->alloc_mutex); 5785 spin_lock_init(&cache->tree_lock);
5786 mutex_init(&cache->cache_mutex); 5786 mutex_init(&cache->cache_mutex);
5787 INIT_LIST_HEAD(&cache->list); 5787 INIT_LIST_HEAD(&cache->list);
5788 read_extent_buffer(leaf, &cache->item, 5788 read_extent_buffer(leaf, &cache->item,
@@ -5838,7 +5838,7 @@ int btrfs_make_block_group(struct btrfs_trans_handle *trans,
5838 cache->key.type = BTRFS_BLOCK_GROUP_ITEM_KEY; 5838 cache->key.type = BTRFS_BLOCK_GROUP_ITEM_KEY;
5839 atomic_set(&cache->count, 1); 5839 atomic_set(&cache->count, 1);
5840 spin_lock_init(&cache->lock); 5840 spin_lock_init(&cache->lock);
5841 mutex_init(&cache->alloc_mutex); 5841 spin_lock_init(&cache->tree_lock);
5842 mutex_init(&cache->cache_mutex); 5842 mutex_init(&cache->cache_mutex);
5843 INIT_LIST_HEAD(&cache->list); 5843 INIT_LIST_HEAD(&cache->list);
5844 5844
diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c
index 69b023ff6f72..df19b60eef61 100644
--- a/fs/btrfs/free-space-cache.c
+++ b/fs/btrfs/free-space-cache.c
@@ -182,6 +182,7 @@ static int link_free_space(struct btrfs_block_group_cache *block_group,
182 int ret = 0; 182 int ret = 0;
183 183
184 184
185 BUG_ON(!info->bytes);
185 ret = tree_insert_offset(&block_group->free_space_offset, info->offset, 186 ret = tree_insert_offset(&block_group->free_space_offset, info->offset,
186 &info->offset_index); 187 &info->offset_index);
187 if (ret) 188 if (ret)
@@ -195,14 +196,23 @@ static int link_free_space(struct btrfs_block_group_cache *block_group,
195 return ret; 196 return ret;
196} 197}
197 198
198static int __btrfs_add_free_space(struct btrfs_block_group_cache *block_group, 199int btrfs_add_free_space(struct btrfs_block_group_cache *block_group,
199 u64 offset, u64 bytes) 200 u64 offset, u64 bytes)
200{ 201{
201 struct btrfs_free_space *right_info; 202 struct btrfs_free_space *right_info;
202 struct btrfs_free_space *left_info; 203 struct btrfs_free_space *left_info;
203 struct btrfs_free_space *info = NULL; 204 struct btrfs_free_space *info = NULL;
204 int ret = 0; 205 int ret = 0;
205 206
207 info = kzalloc(sizeof(struct btrfs_free_space), GFP_NOFS);
208 if (!info)
209 return -ENOMEM;
210
211 info->offset = offset;
212 info->bytes = bytes;
213
214 spin_lock(&block_group->tree_lock);
215
206 /* 216 /*
207 * first we want to see if there is free space adjacent to the range we 217 * first we want to see if there is free space adjacent to the range we
208 * are adding, if there is remove that struct and add a new one to 218 * are adding, if there is remove that struct and add a new one to
@@ -215,42 +225,23 @@ static int __btrfs_add_free_space(struct btrfs_block_group_cache *block_group,
215 225
216 if (right_info) { 226 if (right_info) {
217 unlink_free_space(block_group, right_info); 227 unlink_free_space(block_group, right_info);
218 info = right_info; 228 info->bytes += right_info->bytes;
219 info->offset = offset; 229 kfree(right_info);
220 info->bytes += bytes;
221 } 230 }
222 231
223 if (left_info && left_info->offset + left_info->bytes == offset) { 232 if (left_info && left_info->offset + left_info->bytes == offset) {
224 unlink_free_space(block_group, left_info); 233 unlink_free_space(block_group, left_info);
225 234 info->offset = left_info->offset;
226 if (info) { 235 info->bytes += left_info->bytes;
227 info->offset = left_info->offset; 236 kfree(left_info);
228 info->bytes += left_info->bytes;
229 kfree(left_info);
230 } else {
231 info = left_info;
232 info->bytes += bytes;
233 }
234 }
235
236 if (info) {
237 ret = link_free_space(block_group, info);
238 if (ret)
239 kfree(info);
240 goto out;
241 } 237 }
242 238
243 info = kzalloc(sizeof(struct btrfs_free_space), GFP_NOFS);
244 if (!info)
245 return -ENOMEM;
246
247 info->offset = offset;
248 info->bytes = bytes;
249
250 ret = link_free_space(block_group, info); 239 ret = link_free_space(block_group, info);
251 if (ret) 240 if (ret)
252 kfree(info); 241 kfree(info);
253out: 242
243 spin_unlock(&block_group->tree_lock);
244
254 if (ret) { 245 if (ret) {
255 printk(KERN_ERR "btrfs: unable to add free space :%d\n", ret); 246 printk(KERN_ERR "btrfs: unable to add free space :%d\n", ret);
256 if (ret == -EEXIST) 247 if (ret == -EEXIST)
@@ -260,17 +251,16 @@ out:
260 return ret; 251 return ret;
261} 252}
262 253
263static int 254int btrfs_remove_free_space(struct btrfs_block_group_cache *block_group,
264__btrfs_remove_free_space(struct btrfs_block_group_cache *block_group, 255 u64 offset, u64 bytes)
265 u64 offset, u64 bytes)
266{ 256{
267 struct btrfs_free_space *info; 257 struct btrfs_free_space *info;
268 int ret = 0; 258 int ret = 0;
269 259
270 BUG_ON(!block_group->cached); 260 spin_lock(&block_group->tree_lock);
261
271 info = tree_search_offset(&block_group->free_space_offset, offset, 0, 262 info = tree_search_offset(&block_group->free_space_offset, offset, 0,
272 1); 263 1);
273
274 if (info && info->offset == offset) { 264 if (info && info->offset == offset) {
275 if (info->bytes < bytes) { 265 if (info->bytes < bytes) {
276 printk(KERN_ERR "Found free space at %llu, size %llu," 266 printk(KERN_ERR "Found free space at %llu, size %llu,"
@@ -280,12 +270,14 @@ __btrfs_remove_free_space(struct btrfs_block_group_cache *block_group,
280 (unsigned long long)bytes); 270 (unsigned long long)bytes);
281 WARN_ON(1); 271 WARN_ON(1);
282 ret = -EINVAL; 272 ret = -EINVAL;
273 spin_unlock(&block_group->tree_lock);
283 goto out; 274 goto out;
284 } 275 }
285 unlink_free_space(block_group, info); 276 unlink_free_space(block_group, info);
286 277
287 if (info->bytes == bytes) { 278 if (info->bytes == bytes) {
288 kfree(info); 279 kfree(info);
280 spin_unlock(&block_group->tree_lock);
289 goto out; 281 goto out;
290 } 282 }
291 283
@@ -293,6 +285,7 @@ __btrfs_remove_free_space(struct btrfs_block_group_cache *block_group,
293 info->bytes -= bytes; 285 info->bytes -= bytes;
294 286
295 ret = link_free_space(block_group, info); 287 ret = link_free_space(block_group, info);
288 spin_unlock(&block_group->tree_lock);
296 BUG_ON(ret); 289 BUG_ON(ret);
297 } else if (info && info->offset < offset && 290 } else if (info && info->offset < offset &&
298 info->offset + info->bytes >= offset + bytes) { 291 info->offset + info->bytes >= offset + bytes) {
@@ -318,14 +311,15 @@ __btrfs_remove_free_space(struct btrfs_block_group_cache *block_group,
318 */ 311 */
319 kfree(info); 312 kfree(info);
320 } 313 }
321 314 spin_unlock(&block_group->tree_lock);
322 /* step two, insert a new info struct to cover anything 315 /* step two, insert a new info struct to cover anything
323 * before the hole 316 * before the hole
324 */ 317 */
325 ret = __btrfs_add_free_space(block_group, old_start, 318 ret = btrfs_add_free_space(block_group, old_start,
326 offset - old_start); 319 offset - old_start);
327 BUG_ON(ret); 320 BUG_ON(ret);
328 } else { 321 } else {
322 spin_unlock(&block_group->tree_lock);
329 if (!info) { 323 if (!info) {
330 printk(KERN_ERR "couldn't find space %llu to free\n", 324 printk(KERN_ERR "couldn't find space %llu to free\n",
331 (unsigned long long)offset); 325 (unsigned long long)offset);
@@ -344,50 +338,6 @@ out:
344 return ret; 338 return ret;
345} 339}
346 340
347int btrfs_add_free_space(struct btrfs_block_group_cache *block_group,
348 u64 offset, u64 bytes)
349{
350 int ret;
351
352 mutex_lock(&block_group->alloc_mutex);
353 ret = __btrfs_add_free_space(block_group, offset, bytes);
354 mutex_unlock(&block_group->alloc_mutex);
355
356 return ret;
357}
358
359int btrfs_add_free_space_lock(struct btrfs_block_group_cache *block_group,
360 u64 offset, u64 bytes)
361{
362 int ret;
363
364 ret = __btrfs_add_free_space(block_group, offset, bytes);
365
366 return ret;
367}
368
369int btrfs_remove_free_space(struct btrfs_block_group_cache *block_group,
370 u64 offset, u64 bytes)
371{
372 int ret = 0;
373
374 mutex_lock(&block_group->alloc_mutex);
375 ret = __btrfs_remove_free_space(block_group, offset, bytes);
376 mutex_unlock(&block_group->alloc_mutex);
377
378 return ret;
379}
380
381int btrfs_remove_free_space_lock(struct btrfs_block_group_cache *block_group,
382 u64 offset, u64 bytes)
383{
384 int ret;
385
386 ret = __btrfs_remove_free_space(block_group, offset, bytes);
387
388 return ret;
389}
390
391void btrfs_dump_free_space(struct btrfs_block_group_cache *block_group, 341void btrfs_dump_free_space(struct btrfs_block_group_cache *block_group,
392 u64 bytes) 342 u64 bytes)
393{ 343{
@@ -426,63 +376,44 @@ void btrfs_remove_free_space_cache(struct btrfs_block_group_cache *block_group)
426 struct btrfs_free_space *info; 376 struct btrfs_free_space *info;
427 struct rb_node *node; 377 struct rb_node *node;
428 378
429 mutex_lock(&block_group->alloc_mutex); 379 spin_lock(&block_group->tree_lock);
430 while ((node = rb_last(&block_group->free_space_bytes)) != NULL) { 380 while ((node = rb_last(&block_group->free_space_bytes)) != NULL) {
431 info = rb_entry(node, struct btrfs_free_space, bytes_index); 381 info = rb_entry(node, struct btrfs_free_space, bytes_index);
432 unlink_free_space(block_group, info); 382 unlink_free_space(block_group, info);
433 kfree(info); 383 kfree(info);
434 if (need_resched()) { 384 if (need_resched()) {
435 mutex_unlock(&block_group->alloc_mutex); 385 spin_unlock(&block_group->tree_lock);
436 cond_resched(); 386 cond_resched();
437 mutex_lock(&block_group->alloc_mutex); 387 spin_lock(&block_group->tree_lock);
438 } 388 }
439 } 389 }
440 mutex_unlock(&block_group->alloc_mutex); 390 spin_unlock(&block_group->tree_lock);
441}
442
443#if 0
444static struct btrfs_free_space *btrfs_find_free_space_offset(struct
445 btrfs_block_group_cache
446 *block_group, u64 offset,
447 u64 bytes)
448{
449 struct btrfs_free_space *ret;
450
451 mutex_lock(&block_group->alloc_mutex);
452 ret = tree_search_offset(&block_group->free_space_offset, offset,
453 bytes, 0);
454 mutex_unlock(&block_group->alloc_mutex);
455
456 return ret;
457} 391}
458 392
459static struct btrfs_free_space *btrfs_find_free_space_bytes(struct 393u64 btrfs_find_space_for_alloc(struct btrfs_block_group_cache *block_group,
460 btrfs_block_group_cache 394 u64 offset, u64 bytes, u64 empty_size)
461 *block_group, u64 offset,
462 u64 bytes)
463{ 395{
464 struct btrfs_free_space *ret; 396 struct btrfs_free_space *entry = NULL;
465 397 u64 ret = 0;
466 mutex_lock(&block_group->alloc_mutex);
467
468 ret = tree_search_bytes(&block_group->free_space_bytes, offset, bytes);
469 mutex_unlock(&block_group->alloc_mutex);
470
471 return ret;
472}
473#endif
474
475struct btrfs_free_space *btrfs_find_free_space(struct btrfs_block_group_cache
476 *block_group, u64 offset,
477 u64 bytes)
478{
479 struct btrfs_free_space *ret = NULL;
480 398
481 ret = tree_search_offset(&block_group->free_space_offset, offset, 399 spin_lock(&block_group->tree_lock);
482 bytes, 1); 400 entry = tree_search_offset(&block_group->free_space_offset, offset,
483 if (!ret) 401 bytes + empty_size, 1);
484 ret = tree_search_bytes(&block_group->free_space_bytes, 402 if (!entry)
485 offset, bytes); 403 entry = tree_search_bytes(&block_group->free_space_bytes,
404 offset, bytes + empty_size);
405 if (entry) {
406 unlink_free_space(block_group, entry);
407 ret = entry->offset;
408 entry->offset += bytes;
409 entry->bytes -= bytes;
410
411 if (!entry->bytes)
412 kfree(entry);
413 else
414 link_free_space(block_group, entry);
415 }
416 spin_unlock(&block_group->tree_lock);
486 417
487 return ret; 418 return ret;
488} 419}