diff options
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r-- | fs/btrfs/extent-tree.c | 136 |
1 files changed, 65 insertions, 71 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index fe4e11b31a43..3e2f969de42d 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -325,12 +325,9 @@ static int noinline find_free_space(struct btrfs_root *root, | |||
325 | struct btrfs_block_group_cache *cache = *cache_ret; | 325 | struct btrfs_block_group_cache *cache = *cache_ret; |
326 | struct btrfs_free_space *info = NULL; | 326 | struct btrfs_free_space *info = NULL; |
327 | u64 last; | 327 | u64 last; |
328 | u64 total_fs_bytes; | ||
329 | u64 search_start = *start_ret; | 328 | u64 search_start = *start_ret; |
330 | 329 | ||
331 | WARN_ON(!mutex_is_locked(&root->fs_info->alloc_mutex)); | 330 | WARN_ON(!mutex_is_locked(&root->fs_info->alloc_mutex)); |
332 | total_fs_bytes = btrfs_super_total_bytes(&root->fs_info->super_copy); | ||
333 | |||
334 | if (!cache) | 331 | if (!cache) |
335 | goto out; | 332 | goto out; |
336 | 333 | ||
@@ -354,7 +351,7 @@ new_group: | |||
354 | last = cache->key.objectid + cache->key.offset; | 351 | last = cache->key.objectid + cache->key.offset; |
355 | 352 | ||
356 | cache = btrfs_lookup_first_block_group(root->fs_info, last); | 353 | cache = btrfs_lookup_first_block_group(root->fs_info, last); |
357 | if (!cache || cache->key.objectid >= total_fs_bytes) | 354 | if (!cache) |
358 | goto out; | 355 | goto out; |
359 | 356 | ||
360 | *cache_ret = cache; | 357 | *cache_ret = cache; |
@@ -385,7 +382,6 @@ static struct btrfs_space_info *__find_space_info(struct btrfs_fs_info *info, | |||
385 | return found; | 382 | return found; |
386 | } | 383 | } |
387 | return NULL; | 384 | return NULL; |
388 | |||
389 | } | 385 | } |
390 | 386 | ||
391 | static struct btrfs_block_group_cache * | 387 | static struct btrfs_block_group_cache * |
@@ -396,7 +392,6 @@ __btrfs_find_block_group(struct btrfs_root *root, | |||
396 | struct btrfs_block_group_cache *cache; | 392 | struct btrfs_block_group_cache *cache; |
397 | struct btrfs_block_group_cache *found_group = NULL; | 393 | struct btrfs_block_group_cache *found_group = NULL; |
398 | struct btrfs_fs_info *info = root->fs_info; | 394 | struct btrfs_fs_info *info = root->fs_info; |
399 | struct btrfs_space_info *sinfo; | ||
400 | u64 used; | 395 | u64 used; |
401 | u64 last = 0; | 396 | u64 last = 0; |
402 | u64 free_check; | 397 | u64 free_check; |
@@ -413,7 +408,7 @@ __btrfs_find_block_group(struct btrfs_root *root, | |||
413 | if (shint && block_group_bits(shint, data) && !shint->ro) { | 408 | if (shint && block_group_bits(shint, data) && !shint->ro) { |
414 | spin_lock(&shint->lock); | 409 | spin_lock(&shint->lock); |
415 | used = btrfs_block_group_used(&shint->item); | 410 | used = btrfs_block_group_used(&shint->item); |
416 | if (used + shint->pinned < | 411 | if (used + shint->pinned + shint->reserved < |
417 | div_factor(shint->key.offset, factor)) { | 412 | div_factor(shint->key.offset, factor)) { |
418 | spin_unlock(&shint->lock); | 413 | spin_unlock(&shint->lock); |
419 | return shint; | 414 | return shint; |
@@ -424,7 +419,7 @@ __btrfs_find_block_group(struct btrfs_root *root, | |||
424 | if (hint && !hint->ro && block_group_bits(hint, data)) { | 419 | if (hint && !hint->ro && block_group_bits(hint, data)) { |
425 | spin_lock(&hint->lock); | 420 | spin_lock(&hint->lock); |
426 | used = btrfs_block_group_used(&hint->item); | 421 | used = btrfs_block_group_used(&hint->item); |
427 | if (used + hint->pinned < | 422 | if (used + hint->pinned + hint->reserved < |
428 | div_factor(hint->key.offset, factor)) { | 423 | div_factor(hint->key.offset, factor)) { |
429 | spin_unlock(&hint->lock); | 424 | spin_unlock(&hint->lock); |
430 | return hint; | 425 | return hint; |
@@ -437,27 +432,9 @@ __btrfs_find_block_group(struct btrfs_root *root, | |||
437 | else | 432 | else |
438 | last = search_start; | 433 | last = search_start; |
439 | } | 434 | } |
440 | sinfo = __find_space_info(root->fs_info, data); | ||
441 | if (!sinfo) | ||
442 | goto found; | ||
443 | again: | 435 | again: |
444 | while(1) { | 436 | while (1) { |
445 | struct list_head *l; | 437 | cache = btrfs_lookup_first_block_group(root->fs_info, last); |
446 | |||
447 | cache = NULL; | ||
448 | |||
449 | spin_lock(&sinfo->lock); | ||
450 | list_for_each(l, &sinfo->block_groups) { | ||
451 | struct btrfs_block_group_cache *entry; | ||
452 | entry = list_entry(l, struct btrfs_block_group_cache, | ||
453 | list); | ||
454 | if ((entry->key.objectid >= last) && | ||
455 | (!cache || (entry->key.objectid < | ||
456 | cache->key.objectid))) | ||
457 | cache = entry; | ||
458 | } | ||
459 | spin_unlock(&sinfo->lock); | ||
460 | |||
461 | if (!cache) | 438 | if (!cache) |
462 | break; | 439 | break; |
463 | 440 | ||
@@ -467,7 +444,8 @@ again: | |||
467 | 444 | ||
468 | if (!cache->ro && block_group_bits(cache, data)) { | 445 | if (!cache->ro && block_group_bits(cache, data)) { |
469 | free_check = div_factor(cache->key.offset, factor); | 446 | free_check = div_factor(cache->key.offset, factor); |
470 | if (used + cache->pinned < free_check) { | 447 | if (used + cache->pinned + cache->reserved < |
448 | free_check) { | ||
471 | found_group = cache; | 449 | found_group = cache; |
472 | spin_unlock(&cache->lock); | 450 | spin_unlock(&cache->lock); |
473 | goto found; | 451 | goto found; |
@@ -1414,6 +1392,7 @@ int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans, | |||
1414 | if (!cache) | 1392 | if (!cache) |
1415 | break; | 1393 | break; |
1416 | 1394 | ||
1395 | cache->dirty = 0; | ||
1417 | last += cache->key.offset; | 1396 | last += cache->key.offset; |
1418 | 1397 | ||
1419 | err = write_one_cache_group(trans, root, | 1398 | err = write_one_cache_group(trans, root, |
@@ -1427,8 +1406,6 @@ int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans, | |||
1427 | werr = err; | 1406 | werr = err; |
1428 | continue; | 1407 | continue; |
1429 | } | 1408 | } |
1430 | |||
1431 | cache->dirty = 0; | ||
1432 | } | 1409 | } |
1433 | btrfs_free_path(path); | 1410 | btrfs_free_path(path); |
1434 | mutex_unlock(&root->fs_info->alloc_mutex); | 1411 | mutex_unlock(&root->fs_info->alloc_mutex); |
@@ -1460,6 +1437,7 @@ static int update_space_info(struct btrfs_fs_info *info, u64 flags, | |||
1460 | found->total_bytes = total_bytes; | 1437 | found->total_bytes = total_bytes; |
1461 | found->bytes_used = bytes_used; | 1438 | found->bytes_used = bytes_used; |
1462 | found->bytes_pinned = 0; | 1439 | found->bytes_pinned = 0; |
1440 | found->bytes_reserved = 0; | ||
1463 | found->full = 0; | 1441 | found->full = 0; |
1464 | found->force_alloc = 0; | 1442 | found->force_alloc = 0; |
1465 | *space_info = found; | 1443 | *space_info = found; |
@@ -1539,8 +1517,8 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans, | |||
1539 | 1517 | ||
1540 | thresh = div_factor(space_info->total_bytes, 6); | 1518 | thresh = div_factor(space_info->total_bytes, 6); |
1541 | if (!force && | 1519 | if (!force && |
1542 | (space_info->bytes_used + space_info->bytes_pinned + alloc_bytes) < | 1520 | (space_info->bytes_used + space_info->bytes_pinned + |
1543 | thresh) | 1521 | space_info->bytes_reserved + alloc_bytes) < thresh) |
1544 | goto out; | 1522 | goto out; |
1545 | 1523 | ||
1546 | mutex_lock(&extent_root->fs_info->chunk_mutex); | 1524 | mutex_lock(&extent_root->fs_info->chunk_mutex); |
@@ -1621,7 +1599,6 @@ static u64 first_logical_byte(struct btrfs_root *root, u64 search_start) | |||
1621 | return cache->key.objectid; | 1599 | return cache->key.objectid; |
1622 | } | 1600 | } |
1623 | 1601 | ||
1624 | |||
1625 | int btrfs_update_pinned_extents(struct btrfs_root *root, | 1602 | int btrfs_update_pinned_extents(struct btrfs_root *root, |
1626 | u64 bytenr, u64 num, int pin) | 1603 | u64 bytenr, u64 num, int pin) |
1627 | { | 1604 | { |
@@ -1639,29 +1616,20 @@ int btrfs_update_pinned_extents(struct btrfs_root *root, | |||
1639 | } | 1616 | } |
1640 | while (num > 0) { | 1617 | while (num > 0) { |
1641 | cache = btrfs_lookup_block_group(fs_info, bytenr); | 1618 | cache = btrfs_lookup_block_group(fs_info, bytenr); |
1642 | if (!cache) { | 1619 | BUG_ON(!cache); |
1643 | u64 first = first_logical_byte(root, bytenr); | 1620 | len = min(num, cache->key.offset - |
1644 | WARN_ON(first < bytenr); | 1621 | (bytenr - cache->key.objectid)); |
1645 | len = min(first - bytenr, num); | ||
1646 | } else { | ||
1647 | len = min(num, cache->key.offset - | ||
1648 | (bytenr - cache->key.objectid)); | ||
1649 | } | ||
1650 | if (pin) { | 1622 | if (pin) { |
1651 | if (cache) { | 1623 | spin_lock(&cache->lock); |
1652 | spin_lock(&cache->lock); | 1624 | cache->pinned += len; |
1653 | cache->pinned += len; | 1625 | cache->space_info->bytes_pinned += len; |
1654 | cache->space_info->bytes_pinned += len; | 1626 | spin_unlock(&cache->lock); |
1655 | spin_unlock(&cache->lock); | ||
1656 | } | ||
1657 | fs_info->total_pinned += len; | 1627 | fs_info->total_pinned += len; |
1658 | } else { | 1628 | } else { |
1659 | if (cache) { | 1629 | spin_lock(&cache->lock); |
1660 | spin_lock(&cache->lock); | 1630 | cache->pinned -= len; |
1661 | cache->pinned -= len; | 1631 | cache->space_info->bytes_pinned -= len; |
1662 | cache->space_info->bytes_pinned -= len; | 1632 | spin_unlock(&cache->lock); |
1663 | spin_unlock(&cache->lock); | ||
1664 | } | ||
1665 | fs_info->total_pinned -= len; | 1633 | fs_info->total_pinned -= len; |
1666 | } | 1634 | } |
1667 | bytenr += len; | 1635 | bytenr += len; |
@@ -1670,6 +1638,36 @@ int btrfs_update_pinned_extents(struct btrfs_root *root, | |||
1670 | return 0; | 1638 | return 0; |
1671 | } | 1639 | } |
1672 | 1640 | ||
1641 | static int update_reserved_extents(struct btrfs_root *root, | ||
1642 | u64 bytenr, u64 num, int reserve) | ||
1643 | { | ||
1644 | u64 len; | ||
1645 | struct btrfs_block_group_cache *cache; | ||
1646 | struct btrfs_fs_info *fs_info = root->fs_info; | ||
1647 | |||
1648 | WARN_ON(!mutex_is_locked(&root->fs_info->alloc_mutex)); | ||
1649 | while (num > 0) { | ||
1650 | cache = btrfs_lookup_block_group(fs_info, bytenr); | ||
1651 | BUG_ON(!cache); | ||
1652 | len = min(num, cache->key.offset - | ||
1653 | (bytenr - cache->key.objectid)); | ||
1654 | if (reserve) { | ||
1655 | spin_lock(&cache->lock); | ||
1656 | cache->reserved += len; | ||
1657 | cache->space_info->bytes_reserved += len; | ||
1658 | spin_unlock(&cache->lock); | ||
1659 | } else { | ||
1660 | spin_lock(&cache->lock); | ||
1661 | cache->reserved -= len; | ||
1662 | cache->space_info->bytes_reserved -= len; | ||
1663 | spin_unlock(&cache->lock); | ||
1664 | } | ||
1665 | bytenr += len; | ||
1666 | num -= len; | ||
1667 | } | ||
1668 | return 0; | ||
1669 | } | ||
1670 | |||
1673 | int btrfs_copy_pinned(struct btrfs_root *root, struct extent_io_tree *copy) | 1671 | int btrfs_copy_pinned(struct btrfs_root *root, struct extent_io_tree *copy) |
1674 | { | 1672 | { |
1675 | u64 last = 0; | 1673 | u64 last = 0; |
@@ -2126,6 +2124,7 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans, | |||
2126 | cache = btrfs_lookup_block_group(root->fs_info, bytenr); | 2124 | cache = btrfs_lookup_block_group(root->fs_info, bytenr); |
2127 | BUG_ON(!cache); | 2125 | BUG_ON(!cache); |
2128 | btrfs_add_free_space(cache, bytenr, num_bytes); | 2126 | btrfs_add_free_space(cache, bytenr, num_bytes); |
2127 | update_reserved_extents(root, bytenr, num_bytes, 0); | ||
2129 | return 0; | 2128 | return 0; |
2130 | } | 2129 | } |
2131 | pin = 1; | 2130 | pin = 1; |
@@ -2225,14 +2224,11 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans, | |||
2225 | search_start = max(search_start, first_logical_byte(root, 0)); | 2224 | search_start = max(search_start, first_logical_byte(root, 0)); |
2226 | orig_search_start = search_start; | 2225 | orig_search_start = search_start; |
2227 | 2226 | ||
2228 | if (search_end == (u64)-1) | ||
2229 | search_end = btrfs_super_total_bytes(&info->super_copy); | ||
2230 | |||
2231 | search_start = max(search_start, hint_byte); | 2227 | search_start = max(search_start, hint_byte); |
2232 | total_needed += empty_size; | 2228 | total_needed += empty_size; |
2233 | 2229 | ||
2234 | new_group: | 2230 | new_group: |
2235 | block_group = btrfs_lookup_block_group(info, search_start); | 2231 | block_group = btrfs_lookup_first_block_group(info, search_start); |
2236 | 2232 | ||
2237 | /* | 2233 | /* |
2238 | * Ok this looks a little tricky, buts its really simple. First if we | 2234 | * Ok this looks a little tricky, buts its really simple. First if we |
@@ -2257,12 +2253,8 @@ new_group: | |||
2257 | ret = do_chunk_alloc(trans, root, | 2253 | ret = do_chunk_alloc(trans, root, |
2258 | num_bytes + 2 * 1024 * 1024, | 2254 | num_bytes + 2 * 1024 * 1024, |
2259 | data, 1); | 2255 | data, 1); |
2260 | if (ret < 0) { | 2256 | if (ret < 0) |
2261 | struct btrfs_space_info *info; | ||
2262 | |||
2263 | info = __find_space_info(root->fs_info, data); | ||
2264 | goto error; | 2257 | goto error; |
2265 | } | ||
2266 | BUG_ON(ret); | 2258 | BUG_ON(ret); |
2267 | chunk_alloc_done = 1; | 2259 | chunk_alloc_done = 1; |
2268 | search_start = orig_search_start; | 2260 | search_start = orig_search_start; |
@@ -2378,22 +2370,24 @@ static void dump_space_info(struct btrfs_space_info *info, u64 bytes) | |||
2378 | struct list_head *l; | 2370 | struct list_head *l; |
2379 | 2371 | ||
2380 | printk(KERN_INFO "space_info has %Lu free, is %sfull\n", | 2372 | printk(KERN_INFO "space_info has %Lu free, is %sfull\n", |
2381 | info->total_bytes - info->bytes_used - info->bytes_pinned, | 2373 | info->total_bytes - info->bytes_used - info->bytes_pinned - |
2382 | (info->full) ? "" : "not "); | 2374 | info->bytes_reserved, (info->full) ? "" : "not "); |
2383 | 2375 | ||
2384 | spin_lock(&info->lock); | 2376 | spin_lock(&info->lock); |
2385 | list_for_each(l, &info->block_groups) { | 2377 | list_for_each(l, &info->block_groups) { |
2386 | cache = list_entry(l, struct btrfs_block_group_cache, list); | 2378 | cache = list_entry(l, struct btrfs_block_group_cache, list); |
2387 | spin_lock(&cache->lock); | 2379 | spin_lock(&cache->lock); |
2388 | printk(KERN_INFO "block group %Lu has %Lu bytes, %Lu used " | 2380 | printk(KERN_INFO "block group %Lu has %Lu bytes, %Lu used " |
2389 | "%Lu pinned\n", | 2381 | "%Lu pinned %Lu reserved\n", |
2390 | cache->key.objectid, cache->key.offset, | 2382 | cache->key.objectid, cache->key.offset, |
2391 | btrfs_block_group_used(&cache->item), cache->pinned); | 2383 | btrfs_block_group_used(&cache->item), |
2384 | cache->pinned, cache->reserved); | ||
2392 | btrfs_dump_free_space(cache, bytes); | 2385 | btrfs_dump_free_space(cache, bytes); |
2393 | spin_unlock(&cache->lock); | 2386 | spin_unlock(&cache->lock); |
2394 | } | 2387 | } |
2395 | spin_unlock(&info->lock); | 2388 | spin_unlock(&info->lock); |
2396 | } | 2389 | } |
2390 | |||
2397 | static int __btrfs_reserve_extent(struct btrfs_trans_handle *trans, | 2391 | static int __btrfs_reserve_extent(struct btrfs_trans_handle *trans, |
2398 | struct btrfs_root *root, | 2392 | struct btrfs_root *root, |
2399 | u64 num_bytes, u64 min_alloc_size, | 2393 | u64 num_bytes, u64 min_alloc_size, |
@@ -2500,6 +2494,7 @@ int btrfs_reserve_extent(struct btrfs_trans_handle *trans, | |||
2500 | ret = __btrfs_reserve_extent(trans, root, num_bytes, min_alloc_size, | 2494 | ret = __btrfs_reserve_extent(trans, root, num_bytes, min_alloc_size, |
2501 | empty_size, hint_byte, search_end, ins, | 2495 | empty_size, hint_byte, search_end, ins, |
2502 | data); | 2496 | data); |
2497 | update_reserved_extents(root, ins->objectid, ins->offset, 1); | ||
2503 | maybe_unlock_mutex(root); | 2498 | maybe_unlock_mutex(root); |
2504 | return ret; | 2499 | return ret; |
2505 | } | 2500 | } |
@@ -2625,6 +2620,7 @@ int btrfs_alloc_reserved_extent(struct btrfs_trans_handle *trans, | |||
2625 | ret = __btrfs_alloc_reserved_extent(trans, root, parent, | 2620 | ret = __btrfs_alloc_reserved_extent(trans, root, parent, |
2626 | root_objectid, ref_generation, | 2621 | root_objectid, ref_generation, |
2627 | owner, owner_offset, ins); | 2622 | owner, owner_offset, ins); |
2623 | update_reserved_extents(root, ins->objectid, ins->offset, 0); | ||
2628 | maybe_unlock_mutex(root); | 2624 | maybe_unlock_mutex(root); |
2629 | return ret; | 2625 | return ret; |
2630 | } | 2626 | } |
@@ -2685,6 +2681,8 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans, | |||
2685 | owner_objectid, owner_offset, ins); | 2681 | owner_objectid, owner_offset, ins); |
2686 | BUG_ON(ret); | 2682 | BUG_ON(ret); |
2687 | 2683 | ||
2684 | } else { | ||
2685 | update_reserved_extents(root, ins->objectid, ins->offset, 1); | ||
2688 | } | 2686 | } |
2689 | maybe_unlock_mutex(root); | 2687 | maybe_unlock_mutex(root); |
2690 | return ret; | 2688 | return ret; |
@@ -3974,10 +3972,6 @@ int btrfs_read_block_groups(struct btrfs_root *root) | |||
3974 | 3972 | ||
3975 | ret = btrfs_add_block_group_cache(root->fs_info, cache); | 3973 | ret = btrfs_add_block_group_cache(root->fs_info, cache); |
3976 | BUG_ON(ret); | 3974 | BUG_ON(ret); |
3977 | |||
3978 | if (key.objectid >= | ||
3979 | btrfs_super_total_bytes(&info->super_copy)) | ||
3980 | break; | ||
3981 | } | 3975 | } |
3982 | ret = 0; | 3976 | ret = 0; |
3983 | error: | 3977 | error: |