diff options
author | Chris Mason <chris.mason@oracle.com> | 2008-04-28 15:29:52 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-09-25 11:04:02 -0400 |
commit | ec44a35cbeb26ab2da84cb280d778260f2312feb (patch) | |
tree | afd48a9769125095922c931e3ad77f207c8fb025 | |
parent | 788f20eb5affef584e75ea84bb80a4c3352a2c0e (diff) |
Btrfs: Add balance ioctl to restripe the chunks
Signed-off-by: Chris Mason <chris.mason@oracle.com>
-rw-r--r-- | fs/btrfs/ctree.h | 2 | ||||
-rw-r--r-- | fs/btrfs/extent-tree.c | 106 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 11 | ||||
-rw-r--r-- | fs/btrfs/volumes.c | 115 | ||||
-rw-r--r-- | fs/btrfs/volumes.h | 1 |
5 files changed, 208 insertions, 27 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index b9257b37bb96..73b92dd150ff 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -1364,7 +1364,7 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans, | |||
1364 | u64 root_objectid, u64 ref_generation, | 1364 | u64 root_objectid, u64 ref_generation, |
1365 | u64 owner, u64 owner_offset, | 1365 | u64 owner, u64 owner_offset, |
1366 | u64 empty_size, u64 hint_byte, | 1366 | u64 empty_size, u64 hint_byte, |
1367 | u64 search_end, struct btrfs_key *ins, int data); | 1367 | u64 search_end, struct btrfs_key *ins, u64 data); |
1368 | int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, | 1368 | int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
1369 | struct extent_buffer *buf); | 1369 | struct extent_buffer *buf); |
1370 | int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root | 1370 | int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index fe4fe709c312..95aee5a29375 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -17,6 +17,7 @@ | |||
17 | */ | 17 | */ |
18 | #include <linux/sched.h> | 18 | #include <linux/sched.h> |
19 | #include <linux/pagemap.h> | 19 | #include <linux/pagemap.h> |
20 | #include <linux/writeback.h> | ||
20 | #include "hash.h" | 21 | #include "hash.h" |
21 | #include "crc32c.h" | 22 | #include "crc32c.h" |
22 | #include "ctree.h" | 23 | #include "ctree.h" |
@@ -1058,6 +1059,26 @@ static void set_avail_alloc_bits(struct btrfs_fs_info *fs_info, u64 flags) | |||
1058 | } | 1059 | } |
1059 | } | 1060 | } |
1060 | 1061 | ||
1062 | static u64 reduce_alloc_profile(u64 flags) | ||
1063 | { | ||
1064 | if ((flags & BTRFS_BLOCK_GROUP_DUP) && | ||
1065 | (flags & (BTRFS_BLOCK_GROUP_RAID1 | | ||
1066 | BTRFS_BLOCK_GROUP_RAID10))) | ||
1067 | flags &= ~BTRFS_BLOCK_GROUP_DUP; | ||
1068 | |||
1069 | if ((flags & BTRFS_BLOCK_GROUP_RAID1) && | ||
1070 | (flags & BTRFS_BLOCK_GROUP_RAID10)) | ||
1071 | flags &= ~BTRFS_BLOCK_GROUP_RAID1; | ||
1072 | |||
1073 | if ((flags & BTRFS_BLOCK_GROUP_RAID0) && | ||
1074 | ((flags & BTRFS_BLOCK_GROUP_RAID1) | | ||
1075 | (flags & BTRFS_BLOCK_GROUP_RAID10) | | ||
1076 | (flags & BTRFS_BLOCK_GROUP_DUP))) | ||
1077 | flags &= ~BTRFS_BLOCK_GROUP_RAID0; | ||
1078 | return flags; | ||
1079 | } | ||
1080 | |||
1081 | |||
1061 | static int do_chunk_alloc(struct btrfs_trans_handle *trans, | 1082 | static int do_chunk_alloc(struct btrfs_trans_handle *trans, |
1062 | struct btrfs_root *extent_root, u64 alloc_bytes, | 1083 | struct btrfs_root *extent_root, u64 alloc_bytes, |
1063 | u64 flags) | 1084 | u64 flags) |
@@ -1068,6 +1089,8 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans, | |||
1068 | u64 num_bytes; | 1089 | u64 num_bytes; |
1069 | int ret; | 1090 | int ret; |
1070 | 1091 | ||
1092 | flags = reduce_alloc_profile(flags); | ||
1093 | |||
1071 | space_info = __find_space_info(extent_root->fs_info, flags); | 1094 | space_info = __find_space_info(extent_root->fs_info, flags); |
1072 | if (!space_info) { | 1095 | if (!space_info) { |
1073 | ret = update_space_info(extent_root->fs_info, flags, | 1096 | ret = update_space_info(extent_root->fs_info, flags, |
@@ -1684,6 +1707,7 @@ enospc: | |||
1684 | error: | 1707 | error: |
1685 | return ret; | 1708 | return ret; |
1686 | } | 1709 | } |
1710 | |||
1687 | /* | 1711 | /* |
1688 | * finds a free extent and does all the dirty work required for allocation | 1712 | * finds a free extent and does all the dirty work required for allocation |
1689 | * returns the key for the extent through ins, and a tree buffer for | 1713 | * returns the key for the extent through ins, and a tree buffer for |
@@ -1697,7 +1721,7 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans, | |||
1697 | u64 root_objectid, u64 ref_generation, | 1721 | u64 root_objectid, u64 ref_generation, |
1698 | u64 owner, u64 owner_offset, | 1722 | u64 owner, u64 owner_offset, |
1699 | u64 empty_size, u64 hint_byte, | 1723 | u64 empty_size, u64 hint_byte, |
1700 | u64 search_end, struct btrfs_key *ins, int data) | 1724 | u64 search_end, struct btrfs_key *ins, u64 data) |
1701 | { | 1725 | { |
1702 | int ret; | 1726 | int ret; |
1703 | int pending_ret; | 1727 | int pending_ret; |
@@ -1727,6 +1751,7 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans, | |||
1727 | data = BTRFS_BLOCK_GROUP_METADATA | alloc_profile; | 1751 | data = BTRFS_BLOCK_GROUP_METADATA | alloc_profile; |
1728 | } | 1752 | } |
1729 | again: | 1753 | again: |
1754 | data = reduce_alloc_profile(data); | ||
1730 | if (root->ref_cows) { | 1755 | if (root->ref_cows) { |
1731 | if (!(data & BTRFS_BLOCK_GROUP_METADATA)) { | 1756 | if (!(data & BTRFS_BLOCK_GROUP_METADATA)) { |
1732 | ret = do_chunk_alloc(trans, root->fs_info->extent_root, | 1757 | ret = do_chunk_alloc(trans, root->fs_info->extent_root, |
@@ -1752,6 +1777,9 @@ again: | |||
1752 | num_bytes = max(num_bytes, min_alloc_size); | 1777 | num_bytes = max(num_bytes, min_alloc_size); |
1753 | goto again; | 1778 | goto again; |
1754 | } | 1779 | } |
1780 | if (ret) { | ||
1781 | printk("allocation failed flags %Lu\n", data); | ||
1782 | } | ||
1755 | BUG_ON(ret); | 1783 | BUG_ON(ret); |
1756 | if (ret) | 1784 | if (ret) |
1757 | return ret; | 1785 | return ret; |
@@ -2274,8 +2302,6 @@ static int noinline relocate_inode_pages(struct inode *inode, u64 start, | |||
2274 | { | 2302 | { |
2275 | u64 page_start; | 2303 | u64 page_start; |
2276 | u64 page_end; | 2304 | u64 page_end; |
2277 | u64 delalloc_start; | ||
2278 | u64 existing_delalloc; | ||
2279 | unsigned long last_index; | 2305 | unsigned long last_index; |
2280 | unsigned long i; | 2306 | unsigned long i; |
2281 | struct page *page; | 2307 | struct page *page; |
@@ -2293,7 +2319,6 @@ static int noinline relocate_inode_pages(struct inode *inode, u64 start, | |||
2293 | ra_pages = BTRFS_I(inode)->root->fs_info->bdi.ra_pages; | 2319 | ra_pages = BTRFS_I(inode)->root->fs_info->bdi.ra_pages; |
2294 | 2320 | ||
2295 | file_ra_state_init(ra, inode->i_mapping); | 2321 | file_ra_state_init(ra, inode->i_mapping); |
2296 | kfree(ra); | ||
2297 | 2322 | ||
2298 | for (; i <= last_index; i++) { | 2323 | for (; i <= last_index; i++) { |
2299 | if (total_read % ra_pages == 0) { | 2324 | if (total_read % ra_pages == 0) { |
@@ -2313,26 +2338,30 @@ static int noinline relocate_inode_pages(struct inode *inode, u64 start, | |||
2313 | goto out_unlock; | 2338 | goto out_unlock; |
2314 | } | 2339 | } |
2315 | } | 2340 | } |
2341 | #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,18) | ||
2342 | ClearPageDirty(page); | ||
2343 | #else | ||
2344 | cancel_dirty_page(page, PAGE_CACHE_SIZE); | ||
2345 | #endif | ||
2346 | wait_on_page_writeback(page); | ||
2347 | set_page_extent_mapped(page); | ||
2316 | page_start = (u64)page->index << PAGE_CACHE_SHIFT; | 2348 | page_start = (u64)page->index << PAGE_CACHE_SHIFT; |
2317 | page_end = page_start + PAGE_CACHE_SIZE - 1; | 2349 | page_end = page_start + PAGE_CACHE_SIZE - 1; |
2318 | 2350 | ||
2319 | lock_extent(io_tree, page_start, page_end, GFP_NOFS); | 2351 | lock_extent(io_tree, page_start, page_end, GFP_NOFS); |
2320 | 2352 | ||
2321 | delalloc_start = page_start; | 2353 | set_page_dirty(page); |
2322 | existing_delalloc = count_range_bits(io_tree, | ||
2323 | &delalloc_start, page_end, | ||
2324 | PAGE_CACHE_SIZE, EXTENT_DELALLOC); | ||
2325 | |||
2326 | set_extent_delalloc(io_tree, page_start, | 2354 | set_extent_delalloc(io_tree, page_start, |
2327 | page_end, GFP_NOFS); | 2355 | page_end, GFP_NOFS); |
2328 | 2356 | ||
2329 | unlock_extent(io_tree, page_start, page_end, GFP_NOFS); | 2357 | unlock_extent(io_tree, page_start, page_end, GFP_NOFS); |
2330 | set_page_dirty(page); | ||
2331 | unlock_page(page); | 2358 | unlock_page(page); |
2332 | page_cache_release(page); | 2359 | page_cache_release(page); |
2360 | balance_dirty_pages_ratelimited_nr(inode->i_mapping, 1); | ||
2333 | } | 2361 | } |
2334 | 2362 | ||
2335 | out_unlock: | 2363 | out_unlock: |
2364 | kfree(ra); | ||
2336 | mutex_unlock(&inode->i_mutex); | 2365 | mutex_unlock(&inode->i_mutex); |
2337 | return 0; | 2366 | return 0; |
2338 | } | 2367 | } |
@@ -2397,8 +2426,6 @@ static int noinline relocate_one_reference(struct btrfs_root *extent_root, | |||
2397 | goto out; | 2426 | goto out; |
2398 | } | 2427 | } |
2399 | relocate_inode_pages(inode, ref_offset, extent_key->offset); | 2428 | relocate_inode_pages(inode, ref_offset, extent_key->offset); |
2400 | /* FIXME, data=ordered will help get rid of this */ | ||
2401 | filemap_fdatawrite(inode->i_mapping); | ||
2402 | iput(inode); | 2429 | iput(inode); |
2403 | mutex_lock(&extent_root->fs_info->fs_mutex); | 2430 | mutex_lock(&extent_root->fs_info->fs_mutex); |
2404 | } else { | 2431 | } else { |
@@ -2486,6 +2513,47 @@ out: | |||
2486 | return ret; | 2513 | return ret; |
2487 | } | 2514 | } |
2488 | 2515 | ||
2516 | static u64 update_block_group_flags(struct btrfs_root *root, u64 flags) | ||
2517 | { | ||
2518 | u64 num_devices; | ||
2519 | u64 stripped = BTRFS_BLOCK_GROUP_RAID0 | | ||
2520 | BTRFS_BLOCK_GROUP_RAID1 | BTRFS_BLOCK_GROUP_RAID10; | ||
2521 | |||
2522 | num_devices = btrfs_super_num_devices(&root->fs_info->super_copy); | ||
2523 | if (num_devices == 1) { | ||
2524 | stripped |= BTRFS_BLOCK_GROUP_DUP; | ||
2525 | stripped = flags & ~stripped; | ||
2526 | |||
2527 | /* turn raid0 into single device chunks */ | ||
2528 | if (flags & BTRFS_BLOCK_GROUP_RAID0) | ||
2529 | return stripped; | ||
2530 | |||
2531 | /* turn mirroring into duplication */ | ||
2532 | if (flags & (BTRFS_BLOCK_GROUP_RAID1 | | ||
2533 | BTRFS_BLOCK_GROUP_RAID10)) | ||
2534 | return stripped | BTRFS_BLOCK_GROUP_DUP; | ||
2535 | return flags; | ||
2536 | } else { | ||
2537 | /* they already had raid on here, just return */ | ||
2538 | if ((flags & BTRFS_BLOCK_GROUP_DUP) && | ||
2539 | (flags & BTRFS_BLOCK_GROUP_RAID1)) { | ||
2540 | } | ||
2541 | if (flags & stripped) | ||
2542 | return flags; | ||
2543 | |||
2544 | stripped |= BTRFS_BLOCK_GROUP_DUP; | ||
2545 | stripped = flags & ~stripped; | ||
2546 | |||
2547 | /* switch duplicated blocks with raid1 */ | ||
2548 | if (flags & BTRFS_BLOCK_GROUP_DUP) | ||
2549 | return stripped | BTRFS_BLOCK_GROUP_RAID1; | ||
2550 | |||
2551 | /* turn single device chunks into raid0 */ | ||
2552 | return stripped | BTRFS_BLOCK_GROUP_RAID0; | ||
2553 | } | ||
2554 | return flags; | ||
2555 | } | ||
2556 | |||
2489 | int btrfs_shrink_extent_tree(struct btrfs_root *root, u64 shrink_start) | 2557 | int btrfs_shrink_extent_tree(struct btrfs_root *root, u64 shrink_start) |
2490 | { | 2558 | { |
2491 | struct btrfs_trans_handle *trans; | 2559 | struct btrfs_trans_handle *trans; |
@@ -2494,6 +2562,7 @@ int btrfs_shrink_extent_tree(struct btrfs_root *root, u64 shrink_start) | |||
2494 | u64 cur_byte; | 2562 | u64 cur_byte; |
2495 | u64 total_found; | 2563 | u64 total_found; |
2496 | u64 shrink_last_byte; | 2564 | u64 shrink_last_byte; |
2565 | u64 new_alloc_flags; | ||
2497 | struct btrfs_block_group_cache *shrink_block_group; | 2566 | struct btrfs_block_group_cache *shrink_block_group; |
2498 | struct btrfs_fs_info *info = root->fs_info; | 2567 | struct btrfs_fs_info *info = root->fs_info; |
2499 | struct btrfs_key key; | 2568 | struct btrfs_key key; |
@@ -2511,17 +2580,20 @@ int btrfs_shrink_extent_tree(struct btrfs_root *root, u64 shrink_start) | |||
2511 | 2580 | ||
2512 | shrink_block_group->space_info->total_bytes -= | 2581 | shrink_block_group->space_info->total_bytes -= |
2513 | shrink_block_group->key.offset; | 2582 | shrink_block_group->key.offset; |
2514 | printk("shrink_extent_tree %Lu -> %Lu type %Lu\n", shrink_start, shrink_last_byte, shrink_block_group->flags); | ||
2515 | path = btrfs_alloc_path(); | 2583 | path = btrfs_alloc_path(); |
2516 | root = root->fs_info->extent_root; | 2584 | root = root->fs_info->extent_root; |
2517 | path->reada = 2; | 2585 | path->reada = 2; |
2518 | 2586 | ||
2519 | again: | 2587 | again: |
2520 | trans = btrfs_start_transaction(root, 1); | 2588 | if (btrfs_block_group_used(&shrink_block_group->item) > 0) { |
2521 | do_chunk_alloc(trans, root->fs_info->extent_root, | 2589 | trans = btrfs_start_transaction(root, 1); |
2590 | new_alloc_flags = update_block_group_flags(root, | ||
2591 | shrink_block_group->flags); | ||
2592 | do_chunk_alloc(trans, root->fs_info->extent_root, | ||
2522 | btrfs_block_group_used(&shrink_block_group->item) + | 2593 | btrfs_block_group_used(&shrink_block_group->item) + |
2523 | 2 * 1024 * 1024, shrink_block_group->flags); | 2594 | 2 * 1024 * 1024, new_alloc_flags); |
2524 | btrfs_end_transaction(trans, root); | 2595 | btrfs_end_transaction(trans, root); |
2596 | } | ||
2525 | shrink_block_group->ro = 1; | 2597 | shrink_block_group->ro = 1; |
2526 | 2598 | ||
2527 | total_found = 0; | 2599 | total_found = 0; |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 1a74b5018699..994834474590 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -2864,6 +2864,15 @@ int btrfs_defrag_file(struct file *file) { | |||
2864 | goto out_unlock; | 2864 | goto out_unlock; |
2865 | } | 2865 | } |
2866 | } | 2866 | } |
2867 | |||
2868 | #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,18) | ||
2869 | ClearPageDirty(page); | ||
2870 | #else | ||
2871 | cancel_dirty_page(page, PAGE_CACHE_SIZE); | ||
2872 | #endif | ||
2873 | wait_on_page_writeback(page); | ||
2874 | set_page_extent_mapped(page); | ||
2875 | |||
2867 | page_start = (u64)page->index << PAGE_CACHE_SHIFT; | 2876 | page_start = (u64)page->index << PAGE_CACHE_SHIFT; |
2868 | page_end = page_start + PAGE_CACHE_SIZE - 1; | 2877 | page_end = page_start + PAGE_CACHE_SIZE - 1; |
2869 | 2878 | ||
@@ -3105,6 +3114,8 @@ long btrfs_ioctl(struct file *file, unsigned int | |||
3105 | return btrfs_ioctl_resize(root, (void __user *)arg); | 3114 | return btrfs_ioctl_resize(root, (void __user *)arg); |
3106 | case BTRFS_IOC_ADD_DEV: | 3115 | case BTRFS_IOC_ADD_DEV: |
3107 | return btrfs_ioctl_add_dev(root, (void __user *)arg); | 3116 | return btrfs_ioctl_add_dev(root, (void __user *)arg); |
3117 | case BTRFS_IOC_BALANCE: | ||
3118 | return btrfs_balance(root->fs_info->dev_root); | ||
3108 | } | 3119 | } |
3109 | 3120 | ||
3110 | return -ENOTTY; | 3121 | return -ENOTTY; |
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index b93c15aa17db..6476ecbf132e 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
@@ -869,6 +869,107 @@ out: | |||
869 | return 0; | 869 | return 0; |
870 | } | 870 | } |
871 | 871 | ||
872 | static u64 div_factor(u64 num, int factor) | ||
873 | { | ||
874 | if (factor == 10) | ||
875 | return num; | ||
876 | num *= factor; | ||
877 | do_div(num, 10); | ||
878 | return num; | ||
879 | } | ||
880 | |||
881 | |||
882 | int btrfs_balance(struct btrfs_root *dev_root) | ||
883 | { | ||
884 | int ret; | ||
885 | struct list_head *cur; | ||
886 | struct list_head *devices = &dev_root->fs_info->fs_devices->devices; | ||
887 | struct btrfs_device *device; | ||
888 | u64 old_size; | ||
889 | u64 size_to_free; | ||
890 | struct btrfs_path *path; | ||
891 | struct btrfs_key key; | ||
892 | struct btrfs_chunk *chunk; | ||
893 | struct btrfs_root *chunk_root = dev_root->fs_info->chunk_root; | ||
894 | struct btrfs_trans_handle *trans; | ||
895 | struct btrfs_key found_key; | ||
896 | |||
897 | |||
898 | dev_root = dev_root->fs_info->dev_root; | ||
899 | |||
900 | mutex_lock(&dev_root->fs_info->fs_mutex); | ||
901 | /* step one make some room on all the devices */ | ||
902 | list_for_each(cur, devices) { | ||
903 | device = list_entry(cur, struct btrfs_device, dev_list); | ||
904 | old_size = device->total_bytes; | ||
905 | size_to_free = div_factor(old_size, 1); | ||
906 | size_to_free = min(size_to_free, (u64)1 * 1024 * 1024); | ||
907 | if (device->total_bytes - device->bytes_used > size_to_free) | ||
908 | continue; | ||
909 | |||
910 | ret = btrfs_shrink_device(device, old_size - size_to_free); | ||
911 | BUG_ON(ret); | ||
912 | |||
913 | trans = btrfs_start_transaction(dev_root, 1); | ||
914 | BUG_ON(!trans); | ||
915 | |||
916 | ret = btrfs_grow_device(trans, device, old_size); | ||
917 | BUG_ON(ret); | ||
918 | |||
919 | btrfs_end_transaction(trans, dev_root); | ||
920 | } | ||
921 | |||
922 | /* step two, relocate all the chunks */ | ||
923 | path = btrfs_alloc_path(); | ||
924 | BUG_ON(!path); | ||
925 | |||
926 | key.objectid = BTRFS_FIRST_CHUNK_TREE_OBJECTID; | ||
927 | key.offset = (u64)-1; | ||
928 | key.type = BTRFS_CHUNK_ITEM_KEY; | ||
929 | |||
930 | while(1) { | ||
931 | ret = btrfs_search_slot(NULL, chunk_root, &key, path, 0, 0); | ||
932 | if (ret < 0) | ||
933 | goto error; | ||
934 | |||
935 | /* | ||
936 | * this shouldn't happen, it means the last relocate | ||
937 | * failed | ||
938 | */ | ||
939 | if (ret == 0) | ||
940 | break; | ||
941 | |||
942 | ret = btrfs_previous_item(chunk_root, path, 0, | ||
943 | BTRFS_CHUNK_ITEM_KEY); | ||
944 | if (ret) { | ||
945 | break; | ||
946 | } | ||
947 | btrfs_item_key_to_cpu(path->nodes[0], &found_key, | ||
948 | path->slots[0]); | ||
949 | if (found_key.objectid != key.objectid) | ||
950 | break; | ||
951 | chunk = btrfs_item_ptr(path->nodes[0], | ||
952 | path->slots[0], | ||
953 | struct btrfs_chunk); | ||
954 | key.offset = found_key.offset; | ||
955 | /* chunk zero is special */ | ||
956 | if (key.offset == 0) | ||
957 | break; | ||
958 | |||
959 | ret = btrfs_relocate_chunk(chunk_root, | ||
960 | chunk_root->root_key.objectid, | ||
961 | found_key.objectid, | ||
962 | found_key.offset); | ||
963 | BUG_ON(ret); | ||
964 | btrfs_release_path(chunk_root, path); | ||
965 | } | ||
966 | ret = 0; | ||
967 | error: | ||
968 | btrfs_free_path(path); | ||
969 | mutex_unlock(&dev_root->fs_info->fs_mutex); | ||
970 | return ret; | ||
971 | } | ||
972 | |||
872 | /* | 973 | /* |
873 | * shrinking a device means finding all of the device extents past | 974 | * shrinking a device means finding all of the device extents past |
874 | * the new size, and then following the back refs to the chunks. | 975 | * the new size, and then following the back refs to the chunks. |
@@ -985,15 +1086,6 @@ int btrfs_add_system_chunk(struct btrfs_trans_handle *trans, | |||
985 | return 0; | 1086 | return 0; |
986 | } | 1087 | } |
987 | 1088 | ||
988 | static u64 div_factor(u64 num, int factor) | ||
989 | { | ||
990 | if (factor == 10) | ||
991 | return num; | ||
992 | num *= factor; | ||
993 | do_div(num, 10); | ||
994 | return num; | ||
995 | } | ||
996 | |||
997 | static u64 chunk_bytes_by_type(u64 type, u64 calc_size, int num_stripes, | 1089 | static u64 chunk_bytes_by_type(u64 type, u64 calc_size, int num_stripes, |
998 | int sub_stripes) | 1090 | int sub_stripes) |
999 | { | 1091 | { |
@@ -1040,6 +1132,11 @@ int btrfs_alloc_chunk(struct btrfs_trans_handle *trans, | |||
1040 | int stripe_len = 64 * 1024; | 1132 | int stripe_len = 64 * 1024; |
1041 | struct btrfs_key key; | 1133 | struct btrfs_key key; |
1042 | 1134 | ||
1135 | if ((type & BTRFS_BLOCK_GROUP_RAID1) && | ||
1136 | (type & BTRFS_BLOCK_GROUP_DUP)) { | ||
1137 | WARN_ON(1); | ||
1138 | type &= ~BTRFS_BLOCK_GROUP_DUP; | ||
1139 | } | ||
1043 | dev_list = &extent_root->fs_info->fs_devices->alloc_list; | 1140 | dev_list = &extent_root->fs_info->fs_devices->alloc_list; |
1044 | if (list_empty(dev_list)) | 1141 | if (list_empty(dev_list)) |
1045 | return -ENOSPC; | 1142 | return -ENOSPC; |
diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h index 6f173450378b..3f9a17f2e41b 100644 --- a/fs/btrfs/volumes.h +++ b/fs/btrfs/volumes.h | |||
@@ -134,4 +134,5 @@ struct btrfs_device *btrfs_find_device(struct btrfs_root *root, u64 devid, | |||
134 | u8 *uuid); | 134 | u8 *uuid); |
135 | int btrfs_shrink_device(struct btrfs_device *device, u64 new_size); | 135 | int btrfs_shrink_device(struct btrfs_device *device, u64 new_size); |
136 | int btrfs_init_new_device(struct btrfs_root *root, char *path); | 136 | int btrfs_init_new_device(struct btrfs_root *root, char *path); |
137 | int btrfs_balance(struct btrfs_root *dev_root); | ||
137 | #endif | 138 | #endif |