diff options
author | Chris Mason <chris.mason@oracle.com> | 2008-04-25 16:53:30 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-09-25 11:04:02 -0400 |
commit | 8f18cf13396caae5a3d7ae91201cfb15181a9642 (patch) | |
tree | ff4bfc2e7f45f10d176b969408cdb469ae3f7194 | |
parent | 5e478dc9828ad33d7b08dcdf277e13f14a7c1be7 (diff) |
Btrfs: Make the resizer work based on shrinking and growing devices
Signed-off-by: Chris Mason <chris.mason@oracle.com>
-rw-r--r-- | fs/btrfs/ctree.h | 1 | ||||
-rw-r--r-- | fs/btrfs/disk-io.c | 4 | ||||
-rw-r--r-- | fs/btrfs/extent-tree.c | 145 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 36 | ||||
-rw-r--r-- | fs/btrfs/volumes.c | 324 | ||||
-rw-r--r-- | fs/btrfs/volumes.h | 5 |
6 files changed, 407 insertions, 108 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index f00c4be59ad6..ac7106ec5357 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -474,6 +474,7 @@ struct btrfs_block_group_cache { | |||
474 | u64 pinned; | 474 | u64 pinned; |
475 | u64 flags; | 475 | u64 flags; |
476 | int cached; | 476 | int cached; |
477 | int ro; | ||
477 | }; | 478 | }; |
478 | 479 | ||
479 | struct btrfs_device; | 480 | struct btrfs_device; |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 71838264ca6b..a9ce491d279b 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -818,6 +818,10 @@ struct btrfs_root *btrfs_read_fs_root_no_name(struct btrfs_fs_info *fs_info, | |||
818 | return fs_info->tree_root; | 818 | return fs_info->tree_root; |
819 | if (location->objectid == BTRFS_EXTENT_TREE_OBJECTID) | 819 | if (location->objectid == BTRFS_EXTENT_TREE_OBJECTID) |
820 | return fs_info->extent_root; | 820 | return fs_info->extent_root; |
821 | if (location->objectid == BTRFS_CHUNK_TREE_OBJECTID) | ||
822 | return fs_info->chunk_root; | ||
823 | if (location->objectid == BTRFS_DEV_TREE_OBJECTID) | ||
824 | return fs_info->dev_root; | ||
821 | 825 | ||
822 | root = radix_tree_lookup(&fs_info->fs_roots_radix, | 826 | root = radix_tree_lookup(&fs_info->fs_roots_radix, |
823 | (unsigned long)location->objectid); | 827 | (unsigned long)location->objectid); |
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 | } |
1726 | again: | 1729 | again: |
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 | ||
2476 | int btrfs_shrink_extent_tree(struct btrfs_root *root, u64 new_size) | 2475 | int 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; | ||
2500 | printk("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 | ||
2500 | again: | 2505 | again: |
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); | ||
2599 | bg_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, |
2640 | resched_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); |
2650 | out: | 2630 | out: |
@@ -2652,13 +2632,6 @@ out: | |||
2652 | return ret; | 2632 | return ret; |
2653 | } | 2633 | } |
2654 | 2634 | ||
2655 | int 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 | |||
2662 | int find_first_block_group(struct btrfs_root *root, struct btrfs_path *path, | 2635 | int 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)); |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index b31f52d4f2ca..4d12aa532c5b 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -16,6 +16,7 @@ | |||
16 | * Boston, MA 021110-1307, USA. | 16 | * Boston, MA 021110-1307, USA. |
17 | */ | 17 | */ |
18 | 18 | ||
19 | #include <linux/kernel.h> | ||
19 | #include <linux/bio.h> | 20 | #include <linux/bio.h> |
20 | #include <linux/buffer_head.h> | 21 | #include <linux/buffer_head.h> |
21 | #include <linux/fs.h> | 22 | #include <linux/fs.h> |
@@ -2887,9 +2888,12 @@ static int btrfs_ioctl_resize(struct btrfs_root *root, void __user *arg) | |||
2887 | { | 2888 | { |
2888 | u64 new_size; | 2889 | u64 new_size; |
2889 | u64 old_size; | 2890 | u64 old_size; |
2891 | u64 devid = 1; | ||
2890 | struct btrfs_ioctl_vol_args *vol_args; | 2892 | struct btrfs_ioctl_vol_args *vol_args; |
2891 | struct btrfs_trans_handle *trans; | 2893 | struct btrfs_trans_handle *trans; |
2894 | struct btrfs_device *device = NULL; | ||
2892 | char *sizestr; | 2895 | char *sizestr; |
2896 | char *devstr = NULL; | ||
2893 | int ret = 0; | 2897 | int ret = 0; |
2894 | int namelen; | 2898 | int namelen; |
2895 | int mod = 0; | 2899 | int mod = 0; |
@@ -2909,9 +2913,25 @@ static int btrfs_ioctl_resize(struct btrfs_root *root, void __user *arg) | |||
2909 | goto out; | 2913 | goto out; |
2910 | } | 2914 | } |
2911 | 2915 | ||
2916 | mutex_lock(&root->fs_info->fs_mutex); | ||
2912 | sizestr = vol_args->name; | 2917 | sizestr = vol_args->name; |
2918 | devstr = strchr(sizestr, ':'); | ||
2919 | if (devstr) { | ||
2920 | char *end; | ||
2921 | sizestr = devstr + 1; | ||
2922 | *devstr = '\0'; | ||
2923 | devstr = vol_args->name; | ||
2924 | devid = simple_strtoull(devstr, &end, 10); | ||
2925 | printk("resizing devid %Lu\n", devid); | ||
2926 | } | ||
2927 | device = btrfs_find_device(root, devid, NULL); | ||
2928 | if (!device) { | ||
2929 | printk("resizer unable to find device %Lu\n", devid); | ||
2930 | ret = -EINVAL; | ||
2931 | goto out_unlock; | ||
2932 | } | ||
2913 | if (!strcmp(sizestr, "max")) | 2933 | if (!strcmp(sizestr, "max")) |
2914 | new_size = root->fs_info->sb->s_bdev->bd_inode->i_size; | 2934 | new_size = device->bdev->bd_inode->i_size; |
2915 | else { | 2935 | else { |
2916 | if (sizestr[0] == '-') { | 2936 | if (sizestr[0] == '-') { |
2917 | mod = -1; | 2937 | mod = -1; |
@@ -2923,12 +2943,11 @@ static int btrfs_ioctl_resize(struct btrfs_root *root, void __user *arg) | |||
2923 | new_size = btrfs_parse_size(sizestr); | 2943 | new_size = btrfs_parse_size(sizestr); |
2924 | if (new_size == 0) { | 2944 | if (new_size == 0) { |
2925 | ret = -EINVAL; | 2945 | ret = -EINVAL; |
2926 | goto out; | 2946 | goto out_unlock; |
2927 | } | 2947 | } |
2928 | } | 2948 | } |
2929 | 2949 | ||
2930 | mutex_lock(&root->fs_info->fs_mutex); | 2950 | old_size = device->total_bytes; |
2931 | old_size = btrfs_super_total_bytes(&root->fs_info->super_copy); | ||
2932 | 2951 | ||
2933 | if (mod < 0) { | 2952 | if (mod < 0) { |
2934 | if (new_size > old_size) { | 2953 | if (new_size > old_size) { |
@@ -2944,7 +2963,7 @@ static int btrfs_ioctl_resize(struct btrfs_root *root, void __user *arg) | |||
2944 | ret = -EINVAL; | 2963 | ret = -EINVAL; |
2945 | goto out_unlock; | 2964 | goto out_unlock; |
2946 | } | 2965 | } |
2947 | if (new_size > root->fs_info->sb->s_bdev->bd_inode->i_size) { | 2966 | if (new_size > device->bdev->bd_inode->i_size) { |
2948 | ret = -EFBIG; | 2967 | ret = -EFBIG; |
2949 | goto out_unlock; | 2968 | goto out_unlock; |
2950 | } | 2969 | } |
@@ -2952,13 +2971,14 @@ static int btrfs_ioctl_resize(struct btrfs_root *root, void __user *arg) | |||
2952 | do_div(new_size, root->sectorsize); | 2971 | do_div(new_size, root->sectorsize); |
2953 | new_size *= root->sectorsize; | 2972 | new_size *= root->sectorsize; |
2954 | 2973 | ||
2955 | printk("new size is %Lu\n", new_size); | 2974 | printk("new size for %s is %llu\n", device->name, (unsigned long long)new_size); |
2975 | |||
2956 | if (new_size > old_size) { | 2976 | if (new_size > old_size) { |
2957 | trans = btrfs_start_transaction(root, 1); | 2977 | trans = btrfs_start_transaction(root, 1); |
2958 | ret = btrfs_grow_extent_tree(trans, root, new_size); | 2978 | ret = btrfs_grow_device(trans, device, new_size); |
2959 | btrfs_commit_transaction(trans, root); | 2979 | btrfs_commit_transaction(trans, root); |
2960 | } else { | 2980 | } else { |
2961 | ret = btrfs_shrink_extent_tree(root, new_size); | 2981 | ret = btrfs_shrink_device(device, new_size); |
2962 | } | 2982 | } |
2963 | 2983 | ||
2964 | out_unlock: | 2984 | out_unlock: |
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index c63a982e31d0..a2c56de1548a 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
@@ -77,7 +77,7 @@ static struct btrfs_device *__find_device(struct list_head *head, u64 devid, | |||
77 | list_for_each(cur, head) { | 77 | list_for_each(cur, head) { |
78 | dev = list_entry(cur, struct btrfs_device, dev_list); | 78 | dev = list_entry(cur, struct btrfs_device, dev_list); |
79 | if (dev->devid == devid && | 79 | if (dev->devid == devid && |
80 | !memcmp(dev->uuid, uuid, BTRFS_UUID_SIZE)) { | 80 | (!uuid || !memcmp(dev->uuid, uuid, BTRFS_UUID_SIZE))) { |
81 | return dev; | 81 | return dev; |
82 | } | 82 | } |
83 | } | 83 | } |
@@ -293,6 +293,10 @@ static int find_free_dev_extent(struct btrfs_trans_handle *trans, | |||
293 | * so we make sure to start at an offset of at least 1MB | 293 | * so we make sure to start at an offset of at least 1MB |
294 | */ | 294 | */ |
295 | search_start = max((u64)1024 * 1024, search_start); | 295 | search_start = max((u64)1024 * 1024, search_start); |
296 | |||
297 | if (root->fs_info->alloc_start + num_bytes <= device->total_bytes) | ||
298 | search_start = max(root->fs_info->alloc_start, search_start); | ||
299 | |||
296 | key.objectid = device->devid; | 300 | key.objectid = device->devid; |
297 | key.offset = search_start; | 301 | key.offset = search_start; |
298 | key.type = BTRFS_DEV_EXTENT_KEY; | 302 | key.type = BTRFS_DEV_EXTENT_KEY; |
@@ -380,6 +384,33 @@ error: | |||
380 | return ret; | 384 | return ret; |
381 | } | 385 | } |
382 | 386 | ||
387 | int btrfs_free_dev_extent(struct btrfs_trans_handle *trans, | ||
388 | struct btrfs_device *device, | ||
389 | u64 start) | ||
390 | { | ||
391 | int ret; | ||
392 | struct btrfs_path *path; | ||
393 | struct btrfs_root *root = device->dev_root; | ||
394 | struct btrfs_key key; | ||
395 | |||
396 | path = btrfs_alloc_path(); | ||
397 | if (!path) | ||
398 | return -ENOMEM; | ||
399 | |||
400 | key.objectid = device->devid; | ||
401 | key.offset = start; | ||
402 | key.type = BTRFS_DEV_EXTENT_KEY; | ||
403 | |||
404 | ret = btrfs_search_slot(trans, root, &key, path, -1, 1); | ||
405 | BUG_ON(ret); | ||
406 | |||
407 | ret = btrfs_del_item(trans, root, path); | ||
408 | BUG_ON(ret); | ||
409 | |||
410 | btrfs_free_path(path); | ||
411 | return ret; | ||
412 | } | ||
413 | |||
383 | int btrfs_alloc_dev_extent(struct btrfs_trans_handle *trans, | 414 | int btrfs_alloc_dev_extent(struct btrfs_trans_handle *trans, |
384 | struct btrfs_device *device, | 415 | struct btrfs_device *device, |
385 | u64 chunk_tree, u64 chunk_objectid, | 416 | u64 chunk_tree, u64 chunk_objectid, |
@@ -560,6 +591,7 @@ out: | |||
560 | btrfs_free_path(path); | 591 | btrfs_free_path(path); |
561 | return ret; | 592 | return ret; |
562 | } | 593 | } |
594 | |||
563 | int btrfs_update_device(struct btrfs_trans_handle *trans, | 595 | int btrfs_update_device(struct btrfs_trans_handle *trans, |
564 | struct btrfs_device *device) | 596 | struct btrfs_device *device) |
565 | { | 597 | { |
@@ -606,6 +638,254 @@ out: | |||
606 | return ret; | 638 | return ret; |
607 | } | 639 | } |
608 | 640 | ||
641 | int btrfs_grow_device(struct btrfs_trans_handle *trans, | ||
642 | struct btrfs_device *device, u64 new_size) | ||
643 | { | ||
644 | struct btrfs_super_block *super_copy = | ||
645 | &device->dev_root->fs_info->super_copy; | ||
646 | u64 old_total = btrfs_super_total_bytes(super_copy); | ||
647 | u64 diff = new_size - device->total_bytes; | ||
648 | |||
649 | btrfs_set_super_total_bytes(super_copy, old_total + diff); | ||
650 | return btrfs_update_device(trans, device); | ||
651 | } | ||
652 | |||
653 | static int btrfs_free_chunk(struct btrfs_trans_handle *trans, | ||
654 | struct btrfs_root *root, | ||
655 | u64 chunk_tree, u64 chunk_objectid, | ||
656 | u64 chunk_offset) | ||
657 | { | ||
658 | int ret; | ||
659 | struct btrfs_path *path; | ||
660 | struct btrfs_key key; | ||
661 | |||
662 | root = root->fs_info->chunk_root; | ||
663 | path = btrfs_alloc_path(); | ||
664 | if (!path) | ||
665 | return -ENOMEM; | ||
666 | |||
667 | key.objectid = chunk_objectid; | ||
668 | key.offset = chunk_offset; | ||
669 | key.type = BTRFS_CHUNK_ITEM_KEY; | ||
670 | |||
671 | ret = btrfs_search_slot(trans, root, &key, path, -1, 1); | ||
672 | BUG_ON(ret); | ||
673 | |||
674 | ret = btrfs_del_item(trans, root, path); | ||
675 | BUG_ON(ret); | ||
676 | |||
677 | btrfs_free_path(path); | ||
678 | return 0; | ||
679 | } | ||
680 | |||
681 | int btrfs_del_sys_chunk(struct btrfs_root *root, u64 chunk_objectid, u64 | ||
682 | chunk_offset) | ||
683 | { | ||
684 | struct btrfs_super_block *super_copy = &root->fs_info->super_copy; | ||
685 | struct btrfs_disk_key *disk_key; | ||
686 | struct btrfs_chunk *chunk; | ||
687 | u8 *ptr; | ||
688 | int ret = 0; | ||
689 | u32 num_stripes; | ||
690 | u32 array_size; | ||
691 | u32 len = 0; | ||
692 | u32 cur; | ||
693 | struct btrfs_key key; | ||
694 | |||
695 | array_size = btrfs_super_sys_array_size(super_copy); | ||
696 | |||
697 | ptr = super_copy->sys_chunk_array; | ||
698 | cur = 0; | ||
699 | |||
700 | while (cur < array_size) { | ||
701 | disk_key = (struct btrfs_disk_key *)ptr; | ||
702 | btrfs_disk_key_to_cpu(&key, disk_key); | ||
703 | |||
704 | len = sizeof(*disk_key); | ||
705 | |||
706 | if (key.type == BTRFS_CHUNK_ITEM_KEY) { | ||
707 | chunk = (struct btrfs_chunk *)(ptr + len); | ||
708 | num_stripes = btrfs_stack_chunk_num_stripes(chunk); | ||
709 | len += btrfs_chunk_item_size(num_stripes); | ||
710 | } else { | ||
711 | ret = -EIO; | ||
712 | break; | ||
713 | } | ||
714 | if (key.objectid == chunk_objectid && | ||
715 | key.offset == chunk_offset) { | ||
716 | memmove(ptr, ptr + len, array_size - (cur + len)); | ||
717 | array_size -= len; | ||
718 | btrfs_set_super_sys_array_size(super_copy, array_size); | ||
719 | } else { | ||
720 | ptr += len; | ||
721 | cur += len; | ||
722 | } | ||
723 | } | ||
724 | return ret; | ||
725 | } | ||
726 | |||
727 | |||
728 | int btrfs_relocate_chunk(struct btrfs_root *root, | ||
729 | u64 chunk_tree, u64 chunk_objectid, | ||
730 | u64 chunk_offset) | ||
731 | { | ||
732 | struct extent_map_tree *em_tree; | ||
733 | struct btrfs_root *extent_root; | ||
734 | struct btrfs_trans_handle *trans; | ||
735 | struct extent_map *em; | ||
736 | struct map_lookup *map; | ||
737 | int ret; | ||
738 | int i; | ||
739 | |||
740 | root = root->fs_info->chunk_root; | ||
741 | extent_root = root->fs_info->extent_root; | ||
742 | em_tree = &root->fs_info->mapping_tree.map_tree; | ||
743 | |||
744 | /* step one, relocate all the extents inside this chunk */ | ||
745 | ret = btrfs_shrink_extent_tree(extent_root, chunk_offset); | ||
746 | BUG_ON(ret); | ||
747 | |||
748 | trans = btrfs_start_transaction(root, 1); | ||
749 | BUG_ON(!trans); | ||
750 | |||
751 | /* | ||
752 | * step two, delete the device extents and the | ||
753 | * chunk tree entries | ||
754 | */ | ||
755 | spin_lock(&em_tree->lock); | ||
756 | em = lookup_extent_mapping(em_tree, chunk_offset, 1); | ||
757 | spin_unlock(&em_tree->lock); | ||
758 | |||
759 | BUG_ON(em->start > chunk_offset || em->start + em->len < chunk_offset); | ||
760 | map = (struct map_lookup *)em->bdev; | ||
761 | |||
762 | for (i = 0; i < map->num_stripes; i++) { | ||
763 | ret = btrfs_free_dev_extent(trans, map->stripes[i].dev, | ||
764 | map->stripes[i].physical); | ||
765 | BUG_ON(ret); | ||
766 | } | ||
767 | ret = btrfs_free_chunk(trans, root, chunk_tree, chunk_objectid, | ||
768 | chunk_offset); | ||
769 | |||
770 | BUG_ON(ret); | ||
771 | |||
772 | if (map->type & BTRFS_BLOCK_GROUP_SYSTEM) { | ||
773 | ret = btrfs_del_sys_chunk(root, chunk_objectid, chunk_offset); | ||
774 | BUG_ON(ret); | ||
775 | goto out; | ||
776 | } | ||
777 | |||
778 | |||
779 | |||
780 | spin_lock(&em_tree->lock); | ||
781 | remove_extent_mapping(em_tree, em); | ||
782 | kfree(map); | ||
783 | em->bdev = NULL; | ||
784 | |||
785 | /* once for the tree */ | ||
786 | free_extent_map(em); | ||
787 | spin_unlock(&em_tree->lock); | ||
788 | |||
789 | out: | ||
790 | /* once for us */ | ||
791 | free_extent_map(em); | ||
792 | |||
793 | btrfs_end_transaction(trans, root); | ||
794 | return 0; | ||
795 | } | ||
796 | |||
797 | /* | ||
798 | * shrinking a device means finding all of the device extents past | ||
799 | * the new size, and then following the back refs to the chunks. | ||
800 | * The chunk relocation code actually frees the device extent | ||
801 | */ | ||
802 | int btrfs_shrink_device(struct btrfs_device *device, u64 new_size) | ||
803 | { | ||
804 | struct btrfs_trans_handle *trans; | ||
805 | struct btrfs_root *root = device->dev_root; | ||
806 | struct btrfs_dev_extent *dev_extent = NULL; | ||
807 | struct btrfs_path *path; | ||
808 | u64 length; | ||
809 | u64 chunk_tree; | ||
810 | u64 chunk_objectid; | ||
811 | u64 chunk_offset; | ||
812 | int ret; | ||
813 | int slot; | ||
814 | struct extent_buffer *l; | ||
815 | struct btrfs_key key; | ||
816 | struct btrfs_super_block *super_copy = &root->fs_info->super_copy; | ||
817 | u64 old_total = btrfs_super_total_bytes(super_copy); | ||
818 | u64 diff = device->total_bytes - new_size; | ||
819 | |||
820 | |||
821 | path = btrfs_alloc_path(); | ||
822 | if (!path) | ||
823 | return -ENOMEM; | ||
824 | |||
825 | trans = btrfs_start_transaction(root, 1); | ||
826 | if (!trans) { | ||
827 | ret = -ENOMEM; | ||
828 | goto done; | ||
829 | } | ||
830 | |||
831 | path->reada = 2; | ||
832 | |||
833 | device->total_bytes = new_size; | ||
834 | ret = btrfs_update_device(trans, device); | ||
835 | if (ret) { | ||
836 | btrfs_end_transaction(trans, root); | ||
837 | goto done; | ||
838 | } | ||
839 | WARN_ON(diff > old_total); | ||
840 | btrfs_set_super_total_bytes(super_copy, old_total - diff); | ||
841 | btrfs_end_transaction(trans, root); | ||
842 | |||
843 | key.objectid = device->devid; | ||
844 | key.offset = (u64)-1; | ||
845 | key.type = BTRFS_DEV_EXTENT_KEY; | ||
846 | |||
847 | while (1) { | ||
848 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); | ||
849 | if (ret < 0) | ||
850 | goto done; | ||
851 | |||
852 | ret = btrfs_previous_item(root, path, 0, key.type); | ||
853 | if (ret < 0) | ||
854 | goto done; | ||
855 | if (ret) { | ||
856 | ret = 0; | ||
857 | goto done; | ||
858 | } | ||
859 | |||
860 | l = path->nodes[0]; | ||
861 | slot = path->slots[0]; | ||
862 | btrfs_item_key_to_cpu(l, &key, path->slots[0]); | ||
863 | |||
864 | if (key.objectid != device->devid) | ||
865 | goto done; | ||
866 | |||
867 | dev_extent = btrfs_item_ptr(l, slot, struct btrfs_dev_extent); | ||
868 | length = btrfs_dev_extent_length(l, dev_extent); | ||
869 | |||
870 | if (key.offset + length <= new_size) | ||
871 | goto done; | ||
872 | |||
873 | chunk_tree = btrfs_dev_extent_chunk_tree(l, dev_extent); | ||
874 | chunk_objectid = btrfs_dev_extent_chunk_objectid(l, dev_extent); | ||
875 | chunk_offset = btrfs_dev_extent_chunk_offset(l, dev_extent); | ||
876 | btrfs_release_path(root, path); | ||
877 | |||
878 | ret = btrfs_relocate_chunk(root, chunk_tree, chunk_objectid, | ||
879 | chunk_offset); | ||
880 | if (ret) | ||
881 | goto done; | ||
882 | } | ||
883 | |||
884 | done: | ||
885 | btrfs_free_path(path); | ||
886 | return ret; | ||
887 | } | ||
888 | |||
609 | int btrfs_add_system_chunk(struct btrfs_trans_handle *trans, | 889 | int btrfs_add_system_chunk(struct btrfs_trans_handle *trans, |
610 | struct btrfs_root *root, | 890 | struct btrfs_root *root, |
611 | struct btrfs_key *key, | 891 | struct btrfs_key *key, |
@@ -658,6 +938,7 @@ int btrfs_alloc_chunk(struct btrfs_trans_handle *trans, | |||
658 | u64 dev_offset; | 938 | u64 dev_offset; |
659 | struct btrfs_fs_info *info = extent_root->fs_info; | 939 | struct btrfs_fs_info *info = extent_root->fs_info; |
660 | struct btrfs_root *chunk_root = extent_root->fs_info->chunk_root; | 940 | struct btrfs_root *chunk_root = extent_root->fs_info->chunk_root; |
941 | struct btrfs_path *path; | ||
661 | struct btrfs_stripe *stripes; | 942 | struct btrfs_stripe *stripes; |
662 | struct btrfs_device *device = NULL; | 943 | struct btrfs_device *device = NULL; |
663 | struct btrfs_chunk *chunk; | 944 | struct btrfs_chunk *chunk; |
@@ -724,6 +1005,10 @@ int btrfs_alloc_chunk(struct btrfs_trans_handle *trans, | |||
724 | min_stripe_size = 1 * 1024 * 1024; | 1005 | min_stripe_size = 1 * 1024 * 1024; |
725 | } | 1006 | } |
726 | 1007 | ||
1008 | path = btrfs_alloc_path(); | ||
1009 | if (!path) | ||
1010 | return -ENOMEM; | ||
1011 | |||
727 | /* we don't want a chunk larger than 10% of the FS */ | 1012 | /* we don't want a chunk larger than 10% of the FS */ |
728 | percent_max = div_factor(btrfs_super_total_bytes(&info->super_copy), 1); | 1013 | percent_max = div_factor(btrfs_super_total_bytes(&info->super_copy), 1); |
729 | max_chunk_size = min(percent_max, max_chunk_size); | 1014 | max_chunk_size = min(percent_max, max_chunk_size); |
@@ -759,11 +1044,19 @@ again: | |||
759 | 1044 | ||
760 | avail = device->total_bytes - device->bytes_used; | 1045 | avail = device->total_bytes - device->bytes_used; |
761 | cur = cur->next; | 1046 | cur = cur->next; |
1047 | |||
762 | if (avail >= min_free) { | 1048 | if (avail >= min_free) { |
763 | list_move_tail(&device->dev_alloc_list, &private_devs); | 1049 | u64 ignored_start = 0; |
764 | index++; | 1050 | ret = find_free_dev_extent(trans, device, path, |
765 | if (type & BTRFS_BLOCK_GROUP_DUP) | 1051 | min_free, |
1052 | &ignored_start); | ||
1053 | if (ret == 0) { | ||
1054 | list_move_tail(&device->dev_alloc_list, | ||
1055 | &private_devs); | ||
766 | index++; | 1056 | index++; |
1057 | if (type & BTRFS_BLOCK_GROUP_DUP) | ||
1058 | index++; | ||
1059 | } | ||
767 | } else if (avail > max_avail) | 1060 | } else if (avail > max_avail) |
768 | max_avail = avail; | 1061 | max_avail = avail; |
769 | if (cur == dev_list) | 1062 | if (cur == dev_list) |
@@ -785,30 +1078,37 @@ again: | |||
785 | calc_size = max_avail; | 1078 | calc_size = max_avail; |
786 | goto again; | 1079 | goto again; |
787 | } | 1080 | } |
1081 | btrfs_free_path(path); | ||
788 | return -ENOSPC; | 1082 | return -ENOSPC; |
789 | } | 1083 | } |
790 | key.objectid = BTRFS_FIRST_CHUNK_TREE_OBJECTID; | 1084 | key.objectid = BTRFS_FIRST_CHUNK_TREE_OBJECTID; |
791 | key.type = BTRFS_CHUNK_ITEM_KEY; | 1085 | key.type = BTRFS_CHUNK_ITEM_KEY; |
792 | ret = find_next_chunk(chunk_root, BTRFS_FIRST_CHUNK_TREE_OBJECTID, | 1086 | ret = find_next_chunk(chunk_root, BTRFS_FIRST_CHUNK_TREE_OBJECTID, |
793 | &key.offset); | 1087 | &key.offset); |
794 | if (ret) | 1088 | if (ret) { |
1089 | btrfs_free_path(path); | ||
795 | return ret; | 1090 | return ret; |
1091 | } | ||
796 | 1092 | ||
797 | chunk = kmalloc(btrfs_chunk_item_size(num_stripes), GFP_NOFS); | 1093 | chunk = kmalloc(btrfs_chunk_item_size(num_stripes), GFP_NOFS); |
798 | if (!chunk) | 1094 | if (!chunk) { |
1095 | btrfs_free_path(path); | ||
799 | return -ENOMEM; | 1096 | return -ENOMEM; |
1097 | } | ||
800 | 1098 | ||
801 | map = kmalloc(map_lookup_size(num_stripes), GFP_NOFS); | 1099 | map = kmalloc(map_lookup_size(num_stripes), GFP_NOFS); |
802 | if (!map) { | 1100 | if (!map) { |
803 | kfree(chunk); | 1101 | kfree(chunk); |
1102 | btrfs_free_path(path); | ||
804 | return -ENOMEM; | 1103 | return -ENOMEM; |
805 | } | 1104 | } |
1105 | btrfs_free_path(path); | ||
1106 | path = NULL; | ||
806 | 1107 | ||
807 | stripes = &chunk->stripe; | 1108 | stripes = &chunk->stripe; |
808 | *num_bytes = chunk_bytes_by_type(type, calc_size, | 1109 | *num_bytes = chunk_bytes_by_type(type, calc_size, |
809 | num_stripes, sub_stripes); | 1110 | num_stripes, sub_stripes); |
810 | 1111 | ||
811 | |||
812 | index = 0; | 1112 | index = 0; |
813 | printk("new chunk type %Lu start %Lu size %Lu\n", type, key.offset, *num_bytes); | 1113 | printk("new chunk type %Lu start %Lu size %Lu\n", type, key.offset, *num_bytes); |
814 | while(index < num_stripes) { | 1114 | while(index < num_stripes) { |
@@ -874,6 +1174,11 @@ printk("alloc chunk start %Lu size %Lu from dev %Lu type %Lu\n", key.offset, cal | |||
874 | em->len = *num_bytes; | 1174 | em->len = *num_bytes; |
875 | em->block_start = 0; | 1175 | em->block_start = 0; |
876 | 1176 | ||
1177 | if (type & BTRFS_BLOCK_GROUP_SYSTEM) { | ||
1178 | ret = btrfs_add_system_chunk(trans, chunk_root, &key, | ||
1179 | chunk, btrfs_chunk_item_size(num_stripes)); | ||
1180 | BUG_ON(ret); | ||
1181 | } | ||
877 | kfree(chunk); | 1182 | kfree(chunk); |
878 | 1183 | ||
879 | em_tree = &extent_root->fs_info->mapping_tree.map_tree; | 1184 | em_tree = &extent_root->fs_info->mapping_tree.map_tree; |
@@ -1376,11 +1681,6 @@ int btrfs_read_sys_array(struct btrfs_root *root) | |||
1376 | 1681 | ||
1377 | array_size = btrfs_super_sys_array_size(super_copy); | 1682 | array_size = btrfs_super_sys_array_size(super_copy); |
1378 | 1683 | ||
1379 | /* | ||
1380 | * we do this loop twice, once for the device items and | ||
1381 | * once for all of the chunks. This way there are device | ||
1382 | * structs filled in for every chunk | ||
1383 | */ | ||
1384 | ptr = super_copy->sys_chunk_array; | 1684 | ptr = super_copy->sys_chunk_array; |
1385 | sb_ptr = offsetof(struct btrfs_super_block, sys_chunk_array); | 1685 | sb_ptr = offsetof(struct btrfs_super_block, sys_chunk_array); |
1386 | cur = 0; | 1686 | cur = 0; |
diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h index a2660d2b6b34..6fe8440b37a7 100644 --- a/fs/btrfs/volumes.h +++ b/fs/btrfs/volumes.h | |||
@@ -128,4 +128,9 @@ int btrfs_cleanup_fs_uuids(void); | |||
128 | int btrfs_num_copies(struct btrfs_mapping_tree *map_tree, u64 logical, u64 len); | 128 | int btrfs_num_copies(struct btrfs_mapping_tree *map_tree, u64 logical, u64 len); |
129 | int btrfs_unplug_page(struct btrfs_mapping_tree *map_tree, | 129 | int btrfs_unplug_page(struct btrfs_mapping_tree *map_tree, |
130 | u64 logical, struct page *page); | 130 | u64 logical, struct page *page); |
131 | int btrfs_grow_device(struct btrfs_trans_handle *trans, | ||
132 | struct btrfs_device *device, u64 new_size); | ||
133 | struct btrfs_device *btrfs_find_device(struct btrfs_root *root, u64 devid, | ||
134 | u8 *uuid); | ||
135 | int btrfs_shrink_device(struct btrfs_device *device, u64 new_size); | ||
131 | #endif | 136 | #endif |