aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/volumes.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2008-04-28 15:29:52 -0400
committerChris Mason <chris.mason@oracle.com>2008-09-25 11:04:02 -0400
commitec44a35cbeb26ab2da84cb280d778260f2312feb (patch)
treeafd48a9769125095922c931e3ad77f207c8fb025 /fs/btrfs/volumes.c
parent788f20eb5affef584e75ea84bb80a4c3352a2c0e (diff)
Btrfs: Add balance ioctl to restripe the chunks
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/volumes.c')
-rw-r--r--fs/btrfs/volumes.c115
1 files changed, 106 insertions, 9 deletions
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
872static 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
882int 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;
967error:
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
988static 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
997static u64 chunk_bytes_by_type(u64 type, u64 calc_size, int num_stripes, 1089static 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;