aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/extent-tree.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2008-04-25 16:53:30 -0400
committerChris Mason <chris.mason@oracle.com>2008-09-25 11:04:02 -0400
commit8f18cf13396caae5a3d7ae91201cfb15181a9642 (patch)
treeff4bfc2e7f45f10d176b969408cdb469ae3f7194 /fs/btrfs/extent-tree.c
parent5e478dc9828ad33d7b08dcdf277e13f14a7c1be7 (diff)
Btrfs: Make the resizer work based on shrinking and growing devices
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r--fs/btrfs/extent-tree.c145
1 files changed, 57 insertions, 88 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index c49592c5127a..6540095544e8 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -187,6 +187,7 @@ static int noinline find_search_start(struct btrfs_root *root,
187 187
188 if (!cache) 188 if (!cache)
189 goto out; 189 goto out;
190
190 total_fs_bytes = btrfs_super_total_bytes(&root->fs_info->super_copy); 191 total_fs_bytes = btrfs_super_total_bytes(&root->fs_info->super_copy);
191 free_space_cache = &root->fs_info->free_space_cache; 192 free_space_cache = &root->fs_info->free_space_cache;
192 193
@@ -196,7 +197,7 @@ again:
196 goto out; 197 goto out;
197 198
198 last = max(search_start, cache->key.objectid); 199 last = max(search_start, cache->key.objectid);
199 if (!block_group_bits(cache, data)) { 200 if (!block_group_bits(cache, data) || cache->ro) {
200 goto new_group; 201 goto new_group;
201 } 202 }
202 203
@@ -221,6 +222,8 @@ again:
221 continue; 222 continue;
222 } 223 }
223 spin_unlock_irq(&free_space_cache->lock); 224 spin_unlock_irq(&free_space_cache->lock);
225 if (cache->ro)
226 goto new_group;
224 if (start + num > cache->key.objectid + cache->key.offset) 227 if (start + num > cache->key.objectid + cache->key.offset)
225 goto new_group; 228 goto new_group;
226 if (start + num > total_fs_bytes) 229 if (start + num > total_fs_bytes)
@@ -319,7 +322,7 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root,
319 if (search_start && search_start < total_fs_bytes) { 322 if (search_start && search_start < total_fs_bytes) {
320 struct btrfs_block_group_cache *shint; 323 struct btrfs_block_group_cache *shint;
321 shint = btrfs_lookup_block_group(info, search_start); 324 shint = btrfs_lookup_block_group(info, search_start);
322 if (shint && block_group_bits(shint, data)) { 325 if (shint && block_group_bits(shint, data) && !shint->ro) {
323 used = btrfs_block_group_used(&shint->item); 326 used = btrfs_block_group_used(&shint->item);
324 if (used + shint->pinned < 327 if (used + shint->pinned <
325 div_factor(shint->key.offset, factor)) { 328 div_factor(shint->key.offset, factor)) {
@@ -327,7 +330,7 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root,
327 } 330 }
328 } 331 }
329 } 332 }
330 if (hint && block_group_bits(hint, data) && 333 if (hint && !hint->ro && block_group_bits(hint, data) &&
331 hint->key.objectid < total_fs_bytes) { 334 hint->key.objectid < total_fs_bytes) {
332 used = btrfs_block_group_used(&hint->item); 335 used = btrfs_block_group_used(&hint->item);
333 if (used + hint->pinned < 336 if (used + hint->pinned <
@@ -364,7 +367,7 @@ again:
364 if (cache->key.objectid > total_fs_bytes) 367 if (cache->key.objectid > total_fs_bytes)
365 break; 368 break;
366 369
367 if (block_group_bits(cache, data)) { 370 if (!cache->ro && block_group_bits(cache, data)) {
368 if (full_search) 371 if (full_search)
369 free_check = cache->key.offset; 372 free_check = cache->key.offset;
370 else 373 else
@@ -1020,6 +1023,7 @@ static int update_space_info(struct btrfs_fs_info *info, u64 flags,
1020 if (found) { 1023 if (found) {
1021 found->total_bytes += total_bytes; 1024 found->total_bytes += total_bytes;
1022 found->bytes_used += bytes_used; 1025 found->bytes_used += bytes_used;
1026 found->full = 0;
1023 WARN_ON(found->total_bytes < found->bytes_used); 1027 WARN_ON(found->total_bytes < found->bytes_used);
1024 *space_info = found; 1028 *space_info = found;
1025 return 0; 1029 return 0;
@@ -1700,7 +1704,6 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
1700 u64 super_used; 1704 u64 super_used;
1701 u64 root_used; 1705 u64 root_used;
1702 u64 search_start = 0; 1706 u64 search_start = 0;
1703 u64 new_hint;
1704 u64 alloc_profile; 1707 u64 alloc_profile;
1705 u32 sizes[2]; 1708 u32 sizes[2];
1706 struct btrfs_fs_info *info = root->fs_info; 1709 struct btrfs_fs_info *info = root->fs_info;
@@ -1724,7 +1727,7 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
1724 data = BTRFS_BLOCK_GROUP_METADATA | alloc_profile; 1727 data = BTRFS_BLOCK_GROUP_METADATA | alloc_profile;
1725 } 1728 }
1726again: 1729again:
1727 if (root->ref_cows) { 1730 if (root != root->fs_info->extent_root) {
1728 if (!(data & BTRFS_BLOCK_GROUP_METADATA)) { 1731 if (!(data & BTRFS_BLOCK_GROUP_METADATA)) {
1729 ret = do_chunk_alloc(trans, root->fs_info->extent_root, 1732 ret = do_chunk_alloc(trans, root->fs_info->extent_root,
1730 2 * 1024 * 1024, 1733 2 * 1024 * 1024,
@@ -1738,10 +1741,6 @@ again:
1738 BUG_ON(ret); 1741 BUG_ON(ret);
1739 } 1742 }
1740 1743
1741 new_hint = max(hint_byte, root->fs_info->alloc_start);
1742 if (new_hint < btrfs_super_total_bytes(&info->super_copy))
1743 hint_byte = new_hint;
1744
1745 WARN_ON(num_bytes < root->sectorsize); 1744 WARN_ON(num_bytes < root->sectorsize);
1746 ret = find_free_extent(trans, root, num_bytes, empty_size, 1745 ret = find_free_extent(trans, root, num_bytes, empty_size,
1747 search_start, search_end, hint_byte, ins, 1746 search_start, search_end, hint_byte, ins,
@@ -2473,15 +2472,16 @@ out:
2473 return ret; 2472 return ret;
2474} 2473}
2475 2474
2476int btrfs_shrink_extent_tree(struct btrfs_root *root, u64 new_size) 2475int btrfs_shrink_extent_tree(struct btrfs_root *root, u64 shrink_start)
2477{ 2476{
2478 struct btrfs_trans_handle *trans; 2477 struct btrfs_trans_handle *trans;
2479 struct btrfs_root *tree_root = root->fs_info->tree_root; 2478 struct btrfs_root *tree_root = root->fs_info->tree_root;
2480 struct btrfs_path *path; 2479 struct btrfs_path *path;
2481 u64 cur_byte; 2480 u64 cur_byte;
2482 u64 total_found; 2481 u64 total_found;
2482 u64 shrink_last_byte;
2483 struct btrfs_block_group_cache *shrink_block_group;
2483 struct btrfs_fs_info *info = root->fs_info; 2484 struct btrfs_fs_info *info = root->fs_info;
2484 struct extent_io_tree *block_group_cache;
2485 struct btrfs_key key; 2485 struct btrfs_key key;
2486 struct btrfs_key found_key; 2486 struct btrfs_key found_key;
2487 struct extent_buffer *leaf; 2487 struct extent_buffer *leaf;
@@ -2489,17 +2489,29 @@ int btrfs_shrink_extent_tree(struct btrfs_root *root, u64 new_size)
2489 int ret; 2489 int ret;
2490 int progress = 0; 2490 int progress = 0;
2491 2491
2492 btrfs_set_super_total_bytes(&info->super_copy, new_size); 2492 shrink_block_group = btrfs_lookup_block_group(root->fs_info,
2493 clear_extent_dirty(&info->free_space_cache, new_size, (u64)-1, 2493 shrink_start);
2494 GFP_NOFS); 2494 BUG_ON(!shrink_block_group);
2495 block_group_cache = &info->block_group_cache; 2495
2496 shrink_last_byte = shrink_start + shrink_block_group->key.offset;
2497
2498 shrink_block_group->space_info->total_bytes -=
2499 shrink_block_group->key.offset;
2500printk("shrink_extent_tree %Lu -> %Lu type %Lu\n", shrink_start, shrink_last_byte, shrink_block_group->flags);
2496 path = btrfs_alloc_path(); 2501 path = btrfs_alloc_path();
2497 root = root->fs_info->extent_root; 2502 root = root->fs_info->extent_root;
2498 path->reada = 2; 2503 path->reada = 2;
2499 2504
2500again: 2505again:
2506 trans = btrfs_start_transaction(root, 1);
2507 do_chunk_alloc(trans, root->fs_info->extent_root,
2508 btrfs_block_group_used(&shrink_block_group->item) +
2509 2 * 1024 * 1024, shrink_block_group->flags);
2510 btrfs_end_transaction(trans, root);
2511 shrink_block_group->ro = 1;
2512
2501 total_found = 0; 2513 total_found = 0;
2502 key.objectid = new_size; 2514 key.objectid = shrink_start;
2503 key.offset = 0; 2515 key.offset = 0;
2504 key.type = 0; 2516 key.type = 0;
2505 cur_byte = key.objectid; 2517 cur_byte = key.objectid;
@@ -2511,10 +2523,12 @@ again:
2511 ret = btrfs_previous_item(root, path, 0, BTRFS_EXTENT_ITEM_KEY); 2523 ret = btrfs_previous_item(root, path, 0, BTRFS_EXTENT_ITEM_KEY);
2512 if (ret < 0) 2524 if (ret < 0)
2513 goto out; 2525 goto out;
2526
2514 if (ret == 0) { 2527 if (ret == 0) {
2515 leaf = path->nodes[0]; 2528 leaf = path->nodes[0];
2516 btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); 2529 btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
2517 if (found_key.objectid + found_key.offset > new_size) { 2530 if (found_key.objectid + found_key.offset > shrink_start &&
2531 found_key.objectid < shrink_last_byte) {
2518 cur_byte = found_key.objectid; 2532 cur_byte = found_key.objectid;
2519 key.objectid = cur_byte; 2533 key.objectid = cur_byte;
2520 } 2534 }
@@ -2543,6 +2557,9 @@ next:
2543 2557
2544 btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); 2558 btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
2545 2559
2560 if (found_key.objectid >= shrink_last_byte)
2561 break;
2562
2546 if (progress && need_resched()) { 2563 if (progress && need_resched()) {
2547 memcpy(&key, &found_key, sizeof(key)); 2564 memcpy(&key, &found_key, sizeof(key));
2548 mutex_unlock(&root->fs_info->fs_mutex); 2565 mutex_unlock(&root->fs_info->fs_mutex);
@@ -2583,68 +2600,31 @@ next:
2583 goto again; 2600 goto again;
2584 } 2601 }
2585 2602
2603 /*
2604 * we've freed all the extents, now remove the block
2605 * group item from the tree
2606 */
2586 trans = btrfs_start_transaction(root, 1); 2607 trans = btrfs_start_transaction(root, 1);
2587 key.objectid = new_size; 2608 memcpy(&key, &shrink_block_group->key, sizeof(key));
2588 key.offset = 0;
2589 key.type = 0;
2590 while(1) {
2591 u64 ptr;
2592
2593 ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
2594 if (ret < 0)
2595 goto out;
2596
2597 leaf = path->nodes[0];
2598 nritems = btrfs_header_nritems(leaf);
2599bg_next:
2600 if (path->slots[0] >= nritems) {
2601 ret = btrfs_next_leaf(root, path);
2602 if (ret < 0)
2603 break;
2604 if (ret == 1) {
2605 ret = 0;
2606 break;
2607 }
2608 leaf = path->nodes[0];
2609 btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
2610 2609
2611 /* 2610 ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
2612 * btrfs_next_leaf doesn't cow buffers, we have to 2611 if (ret > 0)
2613 * do the search again 2612 ret = -EIO;
2614 */ 2613 if (ret < 0)
2615 memcpy(&key, &found_key, sizeof(key)); 2614 goto out;
2616 btrfs_release_path(root, path);
2617 goto resched_check;
2618 }
2619 2615
2620 btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); 2616 leaf = path->nodes[0];
2621 if (btrfs_key_type(&found_key) != BTRFS_BLOCK_GROUP_ITEM_KEY) { 2617 nritems = btrfs_header_nritems(leaf);
2622 printk("shrinker found key %Lu %u %Lu\n", 2618 btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
2623 found_key.objectid, found_key.type, 2619 kfree(shrink_block_group);
2624 found_key.offset);
2625 path->slots[0]++;
2626 goto bg_next;
2627 }
2628 ret = get_state_private(&info->block_group_cache,
2629 found_key.objectid, &ptr);
2630 if (!ret)
2631 kfree((void *)(unsigned long)ptr);
2632 2620
2633 clear_extent_bits(&info->block_group_cache, found_key.objectid, 2621 clear_extent_bits(&info->block_group_cache, found_key.objectid,
2634 found_key.objectid + found_key.offset - 1, 2622 found_key.objectid + found_key.offset - 1,
2635 (unsigned int)-1, GFP_NOFS); 2623 (unsigned int)-1, GFP_NOFS);
2636 2624
2637 key.objectid = found_key.objectid + 1; 2625 btrfs_del_item(trans, root, path);
2638 btrfs_del_item(trans, root, path); 2626 clear_extent_dirty(&info->free_space_cache,
2639 btrfs_release_path(root, path); 2627 shrink_start, shrink_last_byte - 1,
2640resched_check:
2641 if (need_resched()) {
2642 mutex_unlock(&root->fs_info->fs_mutex);
2643 cond_resched();
2644 mutex_lock(&root->fs_info->fs_mutex);
2645 }
2646 }
2647 clear_extent_dirty(&info->free_space_cache, new_size, (u64)-1,
2648 GFP_NOFS); 2628 GFP_NOFS);
2649 btrfs_commit_transaction(trans, root); 2629 btrfs_commit_transaction(trans, root);
2650out: 2630out:
@@ -2652,13 +2632,6 @@ out:
2652 return ret; 2632 return ret;
2653} 2633}
2654 2634
2655int btrfs_grow_extent_tree(struct btrfs_trans_handle *trans,
2656 struct btrfs_root *root, u64 new_size)
2657{
2658 btrfs_set_super_total_bytes(&root->fs_info->super_copy, new_size);
2659 return 0;
2660}
2661
2662int find_first_block_group(struct btrfs_root *root, struct btrfs_path *path, 2635int find_first_block_group(struct btrfs_root *root, struct btrfs_path *path,
2663 struct btrfs_key *key) 2636 struct btrfs_key *key)
2664{ 2637{
@@ -2726,7 +2699,7 @@ int btrfs_read_block_groups(struct btrfs_root *root)
2726 2699
2727 leaf = path->nodes[0]; 2700 leaf = path->nodes[0];
2728 btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); 2701 btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
2729 cache = kmalloc(sizeof(*cache), GFP_NOFS); 2702 cache = kzalloc(sizeof(*cache), GFP_NOFS);
2730 if (!cache) { 2703 if (!cache) {
2731 ret = -ENOMEM; 2704 ret = -ENOMEM;
2732 break; 2705 break;
@@ -2736,8 +2709,6 @@ int btrfs_read_block_groups(struct btrfs_root *root)
2736 btrfs_item_ptr_offset(leaf, path->slots[0]), 2709 btrfs_item_ptr_offset(leaf, path->slots[0]),
2737 sizeof(cache->item)); 2710 sizeof(cache->item));
2738 memcpy(&cache->key, &found_key, sizeof(found_key)); 2711 memcpy(&cache->key, &found_key, sizeof(found_key));
2739 cache->cached = 0;
2740 cache->pinned = 0;
2741 2712
2742 key.objectid = found_key.objectid + found_key.offset; 2713 key.objectid = found_key.objectid + found_key.offset;
2743 btrfs_release_path(root, path); 2714 btrfs_release_path(root, path);
@@ -2789,12 +2760,10 @@ int btrfs_make_block_group(struct btrfs_trans_handle *trans,
2789 extent_root = root->fs_info->extent_root; 2760 extent_root = root->fs_info->extent_root;
2790 block_group_cache = &root->fs_info->block_group_cache; 2761 block_group_cache = &root->fs_info->block_group_cache;
2791 2762
2792 cache = kmalloc(sizeof(*cache), GFP_NOFS); 2763 cache = kzalloc(sizeof(*cache), GFP_NOFS);
2793 BUG_ON(!cache); 2764 BUG_ON(!cache);
2794 cache->key.objectid = chunk_offset; 2765 cache->key.objectid = chunk_offset;
2795 cache->key.offset = size; 2766 cache->key.offset = size;
2796 cache->cached = 0;
2797 cache->pinned = 0;
2798 2767
2799 btrfs_set_key_type(&cache->key, BTRFS_BLOCK_GROUP_ITEM_KEY); 2768 btrfs_set_key_type(&cache->key, BTRFS_BLOCK_GROUP_ITEM_KEY);
2800 memset(&cache->item, 0, sizeof(cache->item)); 2769 memset(&cache->item, 0, sizeof(cache->item));