diff options
author | Sage Weil <sage@inktank.com> | 2013-08-15 14:11:45 -0400 |
---|---|---|
committer | Sage Weil <sage@inktank.com> | 2013-08-15 14:11:45 -0400 |
commit | ee3e542fec6e69bc9fb668698889a37d93950ddf (patch) | |
tree | e74ee766a4764769ef1d3d45d266b4dea64101d3 /fs/btrfs/volumes.c | |
parent | fe2a801b50c0bb8039d627e5ae1fec249d10ff39 (diff) | |
parent | f1d6e17f540af37bb1891480143669ba7636c4cf (diff) |
Merge remote-tracking branch 'linus/master' into testing
Diffstat (limited to 'fs/btrfs/volumes.c')
-rw-r--r-- | fs/btrfs/volumes.c | 351 |
1 files changed, 156 insertions, 195 deletions
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 8bffb9174afb..78b871753cb6 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
@@ -982,6 +982,35 @@ out: | |||
982 | return ret; | 982 | return ret; |
983 | } | 983 | } |
984 | 984 | ||
985 | static int contains_pending_extent(struct btrfs_trans_handle *trans, | ||
986 | struct btrfs_device *device, | ||
987 | u64 *start, u64 len) | ||
988 | { | ||
989 | struct extent_map *em; | ||
990 | int ret = 0; | ||
991 | |||
992 | list_for_each_entry(em, &trans->transaction->pending_chunks, list) { | ||
993 | struct map_lookup *map; | ||
994 | int i; | ||
995 | |||
996 | map = (struct map_lookup *)em->bdev; | ||
997 | for (i = 0; i < map->num_stripes; i++) { | ||
998 | if (map->stripes[i].dev != device) | ||
999 | continue; | ||
1000 | if (map->stripes[i].physical >= *start + len || | ||
1001 | map->stripes[i].physical + em->orig_block_len <= | ||
1002 | *start) | ||
1003 | continue; | ||
1004 | *start = map->stripes[i].physical + | ||
1005 | em->orig_block_len; | ||
1006 | ret = 1; | ||
1007 | } | ||
1008 | } | ||
1009 | |||
1010 | return ret; | ||
1011 | } | ||
1012 | |||
1013 | |||
985 | /* | 1014 | /* |
986 | * find_free_dev_extent - find free space in the specified device | 1015 | * find_free_dev_extent - find free space in the specified device |
987 | * @device: the device which we search the free space in | 1016 | * @device: the device which we search the free space in |
@@ -1002,7 +1031,8 @@ out: | |||
1002 | * But if we don't find suitable free space, it is used to store the size of | 1031 | * But if we don't find suitable free space, it is used to store the size of |
1003 | * the max free space. | 1032 | * the max free space. |
1004 | */ | 1033 | */ |
1005 | int find_free_dev_extent(struct btrfs_device *device, u64 num_bytes, | 1034 | int find_free_dev_extent(struct btrfs_trans_handle *trans, |
1035 | struct btrfs_device *device, u64 num_bytes, | ||
1006 | u64 *start, u64 *len) | 1036 | u64 *start, u64 *len) |
1007 | { | 1037 | { |
1008 | struct btrfs_key key; | 1038 | struct btrfs_key key; |
@@ -1026,21 +1056,22 @@ int find_free_dev_extent(struct btrfs_device *device, u64 num_bytes, | |||
1026 | */ | 1056 | */ |
1027 | search_start = max(root->fs_info->alloc_start, 1024ull * 1024); | 1057 | search_start = max(root->fs_info->alloc_start, 1024ull * 1024); |
1028 | 1058 | ||
1059 | path = btrfs_alloc_path(); | ||
1060 | if (!path) | ||
1061 | return -ENOMEM; | ||
1062 | again: | ||
1029 | max_hole_start = search_start; | 1063 | max_hole_start = search_start; |
1030 | max_hole_size = 0; | 1064 | max_hole_size = 0; |
1031 | hole_size = 0; | 1065 | hole_size = 0; |
1032 | 1066 | ||
1033 | if (search_start >= search_end || device->is_tgtdev_for_dev_replace) { | 1067 | if (search_start >= search_end || device->is_tgtdev_for_dev_replace) { |
1034 | ret = -ENOSPC; | 1068 | ret = -ENOSPC; |
1035 | goto error; | 1069 | goto out; |
1036 | } | 1070 | } |
1037 | 1071 | ||
1038 | path = btrfs_alloc_path(); | ||
1039 | if (!path) { | ||
1040 | ret = -ENOMEM; | ||
1041 | goto error; | ||
1042 | } | ||
1043 | path->reada = 2; | 1072 | path->reada = 2; |
1073 | path->search_commit_root = 1; | ||
1074 | path->skip_locking = 1; | ||
1044 | 1075 | ||
1045 | key.objectid = device->devid; | 1076 | key.objectid = device->devid; |
1046 | key.offset = search_start; | 1077 | key.offset = search_start; |
@@ -1081,6 +1112,15 @@ int find_free_dev_extent(struct btrfs_device *device, u64 num_bytes, | |||
1081 | if (key.offset > search_start) { | 1112 | if (key.offset > search_start) { |
1082 | hole_size = key.offset - search_start; | 1113 | hole_size = key.offset - search_start; |
1083 | 1114 | ||
1115 | /* | ||
1116 | * Have to check before we set max_hole_start, otherwise | ||
1117 | * we could end up sending back this offset anyway. | ||
1118 | */ | ||
1119 | if (contains_pending_extent(trans, device, | ||
1120 | &search_start, | ||
1121 | hole_size)) | ||
1122 | hole_size = 0; | ||
1123 | |||
1084 | if (hole_size > max_hole_size) { | 1124 | if (hole_size > max_hole_size) { |
1085 | max_hole_start = search_start; | 1125 | max_hole_start = search_start; |
1086 | max_hole_size = hole_size; | 1126 | max_hole_size = hole_size; |
@@ -1124,6 +1164,11 @@ next: | |||
1124 | max_hole_size = hole_size; | 1164 | max_hole_size = hole_size; |
1125 | } | 1165 | } |
1126 | 1166 | ||
1167 | if (contains_pending_extent(trans, device, &search_start, hole_size)) { | ||
1168 | btrfs_release_path(path); | ||
1169 | goto again; | ||
1170 | } | ||
1171 | |||
1127 | /* See above. */ | 1172 | /* See above. */ |
1128 | if (hole_size < num_bytes) | 1173 | if (hole_size < num_bytes) |
1129 | ret = -ENOSPC; | 1174 | ret = -ENOSPC; |
@@ -1132,7 +1177,6 @@ next: | |||
1132 | 1177 | ||
1133 | out: | 1178 | out: |
1134 | btrfs_free_path(path); | 1179 | btrfs_free_path(path); |
1135 | error: | ||
1136 | *start = max_hole_start; | 1180 | *start = max_hole_start; |
1137 | if (len) | 1181 | if (len) |
1138 | *len = max_hole_size; | 1182 | *len = max_hole_size; |
@@ -1244,47 +1288,22 @@ out: | |||
1244 | return ret; | 1288 | return ret; |
1245 | } | 1289 | } |
1246 | 1290 | ||
1247 | static noinline int find_next_chunk(struct btrfs_root *root, | 1291 | static u64 find_next_chunk(struct btrfs_fs_info *fs_info) |
1248 | u64 objectid, u64 *offset) | ||
1249 | { | 1292 | { |
1250 | struct btrfs_path *path; | 1293 | struct extent_map_tree *em_tree; |
1251 | int ret; | 1294 | struct extent_map *em; |
1252 | struct btrfs_key key; | 1295 | struct rb_node *n; |
1253 | struct btrfs_chunk *chunk; | 1296 | u64 ret = 0; |
1254 | struct btrfs_key found_key; | ||
1255 | |||
1256 | path = btrfs_alloc_path(); | ||
1257 | if (!path) | ||
1258 | return -ENOMEM; | ||
1259 | |||
1260 | key.objectid = objectid; | ||
1261 | key.offset = (u64)-1; | ||
1262 | key.type = BTRFS_CHUNK_ITEM_KEY; | ||
1263 | |||
1264 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); | ||
1265 | if (ret < 0) | ||
1266 | goto error; | ||
1267 | |||
1268 | BUG_ON(ret == 0); /* Corruption */ | ||
1269 | 1297 | ||
1270 | ret = btrfs_previous_item(root, path, 0, BTRFS_CHUNK_ITEM_KEY); | 1298 | em_tree = &fs_info->mapping_tree.map_tree; |
1271 | if (ret) { | 1299 | read_lock(&em_tree->lock); |
1272 | *offset = 0; | 1300 | n = rb_last(&em_tree->map); |
1273 | } else { | 1301 | if (n) { |
1274 | btrfs_item_key_to_cpu(path->nodes[0], &found_key, | 1302 | em = rb_entry(n, struct extent_map, rb_node); |
1275 | path->slots[0]); | 1303 | ret = em->start + em->len; |
1276 | if (found_key.objectid != objectid) | ||
1277 | *offset = 0; | ||
1278 | else { | ||
1279 | chunk = btrfs_item_ptr(path->nodes[0], path->slots[0], | ||
1280 | struct btrfs_chunk); | ||
1281 | *offset = found_key.offset + | ||
1282 | btrfs_chunk_length(path->nodes[0], chunk); | ||
1283 | } | ||
1284 | } | 1304 | } |
1285 | ret = 0; | 1305 | read_unlock(&em_tree->lock); |
1286 | error: | 1306 | |
1287 | btrfs_free_path(path); | ||
1288 | return ret; | 1307 | return ret; |
1289 | } | 1308 | } |
1290 | 1309 | ||
@@ -1462,31 +1481,23 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path) | |||
1462 | btrfs_dev_replace_unlock(&root->fs_info->dev_replace); | 1481 | btrfs_dev_replace_unlock(&root->fs_info->dev_replace); |
1463 | 1482 | ||
1464 | if ((all_avail & BTRFS_BLOCK_GROUP_RAID10) && num_devices <= 4) { | 1483 | if ((all_avail & BTRFS_BLOCK_GROUP_RAID10) && num_devices <= 4) { |
1465 | printk(KERN_ERR "btrfs: unable to go below four devices " | 1484 | ret = BTRFS_ERROR_DEV_RAID10_MIN_NOT_MET; |
1466 | "on raid10\n"); | ||
1467 | ret = -EINVAL; | ||
1468 | goto out; | 1485 | goto out; |
1469 | } | 1486 | } |
1470 | 1487 | ||
1471 | if ((all_avail & BTRFS_BLOCK_GROUP_RAID1) && num_devices <= 2) { | 1488 | if ((all_avail & BTRFS_BLOCK_GROUP_RAID1) && num_devices <= 2) { |
1472 | printk(KERN_ERR "btrfs: unable to go below two " | 1489 | ret = BTRFS_ERROR_DEV_RAID1_MIN_NOT_MET; |
1473 | "devices on raid1\n"); | ||
1474 | ret = -EINVAL; | ||
1475 | goto out; | 1490 | goto out; |
1476 | } | 1491 | } |
1477 | 1492 | ||
1478 | if ((all_avail & BTRFS_BLOCK_GROUP_RAID5) && | 1493 | if ((all_avail & BTRFS_BLOCK_GROUP_RAID5) && |
1479 | root->fs_info->fs_devices->rw_devices <= 2) { | 1494 | root->fs_info->fs_devices->rw_devices <= 2) { |
1480 | printk(KERN_ERR "btrfs: unable to go below two " | 1495 | ret = BTRFS_ERROR_DEV_RAID5_MIN_NOT_MET; |
1481 | "devices on raid5\n"); | ||
1482 | ret = -EINVAL; | ||
1483 | goto out; | 1496 | goto out; |
1484 | } | 1497 | } |
1485 | if ((all_avail & BTRFS_BLOCK_GROUP_RAID6) && | 1498 | if ((all_avail & BTRFS_BLOCK_GROUP_RAID6) && |
1486 | root->fs_info->fs_devices->rw_devices <= 3) { | 1499 | root->fs_info->fs_devices->rw_devices <= 3) { |
1487 | printk(KERN_ERR "btrfs: unable to go below three " | 1500 | ret = BTRFS_ERROR_DEV_RAID6_MIN_NOT_MET; |
1488 | "devices on raid6\n"); | ||
1489 | ret = -EINVAL; | ||
1490 | goto out; | 1501 | goto out; |
1491 | } | 1502 | } |
1492 | 1503 | ||
@@ -1512,8 +1523,7 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path) | |||
1512 | bh = NULL; | 1523 | bh = NULL; |
1513 | disk_super = NULL; | 1524 | disk_super = NULL; |
1514 | if (!device) { | 1525 | if (!device) { |
1515 | printk(KERN_ERR "btrfs: no missing devices found to " | 1526 | ret = BTRFS_ERROR_DEV_MISSING_NOT_FOUND; |
1516 | "remove\n"); | ||
1517 | goto out; | 1527 | goto out; |
1518 | } | 1528 | } |
1519 | } else { | 1529 | } else { |
@@ -1535,15 +1545,12 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path) | |||
1535 | } | 1545 | } |
1536 | 1546 | ||
1537 | if (device->is_tgtdev_for_dev_replace) { | 1547 | if (device->is_tgtdev_for_dev_replace) { |
1538 | pr_err("btrfs: unable to remove the dev_replace target dev\n"); | 1548 | ret = BTRFS_ERROR_DEV_TGT_REPLACE; |
1539 | ret = -EINVAL; | ||
1540 | goto error_brelse; | 1549 | goto error_brelse; |
1541 | } | 1550 | } |
1542 | 1551 | ||
1543 | if (device->writeable && root->fs_info->fs_devices->rw_devices == 1) { | 1552 | if (device->writeable && root->fs_info->fs_devices->rw_devices == 1) { |
1544 | printk(KERN_ERR "btrfs: unable to remove the only writeable " | 1553 | ret = BTRFS_ERROR_DEV_ONLY_WRITABLE; |
1545 | "device\n"); | ||
1546 | ret = -EINVAL; | ||
1547 | goto error_brelse; | 1554 | goto error_brelse; |
1548 | } | 1555 | } |
1549 | 1556 | ||
@@ -3295,10 +3302,7 @@ int btrfs_resume_balance_async(struct btrfs_fs_info *fs_info) | |||
3295 | } | 3302 | } |
3296 | 3303 | ||
3297 | tsk = kthread_run(balance_kthread, fs_info, "btrfs-balance"); | 3304 | tsk = kthread_run(balance_kthread, fs_info, "btrfs-balance"); |
3298 | if (IS_ERR(tsk)) | 3305 | return PTR_RET(tsk); |
3299 | return PTR_ERR(tsk); | ||
3300 | |||
3301 | return 0; | ||
3302 | } | 3306 | } |
3303 | 3307 | ||
3304 | int btrfs_recover_balance(struct btrfs_fs_info *fs_info) | 3308 | int btrfs_recover_balance(struct btrfs_fs_info *fs_info) |
@@ -3681,10 +3685,8 @@ static void check_raid56_incompat_flag(struct btrfs_fs_info *info, u64 type) | |||
3681 | } | 3685 | } |
3682 | 3686 | ||
3683 | static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans, | 3687 | static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans, |
3684 | struct btrfs_root *extent_root, | 3688 | struct btrfs_root *extent_root, u64 start, |
3685 | struct map_lookup **map_ret, | 3689 | u64 type) |
3686 | u64 *num_bytes_out, u64 *stripe_size_out, | ||
3687 | u64 start, u64 type) | ||
3688 | { | 3690 | { |
3689 | struct btrfs_fs_info *info = extent_root->fs_info; | 3691 | struct btrfs_fs_info *info = extent_root->fs_info; |
3690 | struct btrfs_fs_devices *fs_devices = info->fs_devices; | 3692 | struct btrfs_fs_devices *fs_devices = info->fs_devices; |
@@ -3791,7 +3793,7 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans, | |||
3791 | if (total_avail == 0) | 3793 | if (total_avail == 0) |
3792 | continue; | 3794 | continue; |
3793 | 3795 | ||
3794 | ret = find_free_dev_extent(device, | 3796 | ret = find_free_dev_extent(trans, device, |
3795 | max_stripe_size * dev_stripes, | 3797 | max_stripe_size * dev_stripes, |
3796 | &dev_offset, &max_avail); | 3798 | &dev_offset, &max_avail); |
3797 | if (ret && ret != -ENOSPC) | 3799 | if (ret && ret != -ENOSPC) |
@@ -3903,12 +3905,8 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans, | |||
3903 | map->type = type; | 3905 | map->type = type; |
3904 | map->sub_stripes = sub_stripes; | 3906 | map->sub_stripes = sub_stripes; |
3905 | 3907 | ||
3906 | *map_ret = map; | ||
3907 | num_bytes = stripe_size * data_stripes; | 3908 | num_bytes = stripe_size * data_stripes; |
3908 | 3909 | ||
3909 | *stripe_size_out = stripe_size; | ||
3910 | *num_bytes_out = num_bytes; | ||
3911 | |||
3912 | trace_btrfs_chunk_alloc(info->chunk_root, map, start, num_bytes); | 3910 | trace_btrfs_chunk_alloc(info->chunk_root, map, start, num_bytes); |
3913 | 3911 | ||
3914 | em = alloc_extent_map(); | 3912 | em = alloc_extent_map(); |
@@ -3921,38 +3919,26 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans, | |||
3921 | em->len = num_bytes; | 3919 | em->len = num_bytes; |
3922 | em->block_start = 0; | 3920 | em->block_start = 0; |
3923 | em->block_len = em->len; | 3921 | em->block_len = em->len; |
3922 | em->orig_block_len = stripe_size; | ||
3924 | 3923 | ||
3925 | em_tree = &extent_root->fs_info->mapping_tree.map_tree; | 3924 | em_tree = &extent_root->fs_info->mapping_tree.map_tree; |
3926 | write_lock(&em_tree->lock); | 3925 | write_lock(&em_tree->lock); |
3927 | ret = add_extent_mapping(em_tree, em, 0); | 3926 | ret = add_extent_mapping(em_tree, em, 0); |
3927 | if (!ret) { | ||
3928 | list_add_tail(&em->list, &trans->transaction->pending_chunks); | ||
3929 | atomic_inc(&em->refs); | ||
3930 | } | ||
3928 | write_unlock(&em_tree->lock); | 3931 | write_unlock(&em_tree->lock); |
3929 | if (ret) { | 3932 | if (ret) { |
3930 | free_extent_map(em); | 3933 | free_extent_map(em); |
3931 | goto error; | 3934 | goto error; |
3932 | } | 3935 | } |
3933 | 3936 | ||
3934 | for (i = 0; i < map->num_stripes; ++i) { | ||
3935 | struct btrfs_device *device; | ||
3936 | u64 dev_offset; | ||
3937 | |||
3938 | device = map->stripes[i].dev; | ||
3939 | dev_offset = map->stripes[i].physical; | ||
3940 | |||
3941 | ret = btrfs_alloc_dev_extent(trans, device, | ||
3942 | info->chunk_root->root_key.objectid, | ||
3943 | BTRFS_FIRST_CHUNK_TREE_OBJECTID, | ||
3944 | start, dev_offset, stripe_size); | ||
3945 | if (ret) | ||
3946 | goto error_dev_extent; | ||
3947 | } | ||
3948 | |||
3949 | ret = btrfs_make_block_group(trans, extent_root, 0, type, | 3937 | ret = btrfs_make_block_group(trans, extent_root, 0, type, |
3950 | BTRFS_FIRST_CHUNK_TREE_OBJECTID, | 3938 | BTRFS_FIRST_CHUNK_TREE_OBJECTID, |
3951 | start, num_bytes); | 3939 | start, num_bytes); |
3952 | if (ret) { | 3940 | if (ret) |
3953 | i = map->num_stripes - 1; | 3941 | goto error_del_extent; |
3954 | goto error_dev_extent; | ||
3955 | } | ||
3956 | 3942 | ||
3957 | free_extent_map(em); | 3943 | free_extent_map(em); |
3958 | check_raid56_incompat_flag(extent_root->fs_info, type); | 3944 | check_raid56_incompat_flag(extent_root->fs_info, type); |
@@ -3960,18 +3946,7 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans, | |||
3960 | kfree(devices_info); | 3946 | kfree(devices_info); |
3961 | return 0; | 3947 | return 0; |
3962 | 3948 | ||
3963 | error_dev_extent: | 3949 | error_del_extent: |
3964 | for (; i >= 0; i--) { | ||
3965 | struct btrfs_device *device; | ||
3966 | int err; | ||
3967 | |||
3968 | device = map->stripes[i].dev; | ||
3969 | err = btrfs_free_dev_extent(trans, device, start); | ||
3970 | if (err) { | ||
3971 | btrfs_abort_transaction(trans, extent_root, err); | ||
3972 | break; | ||
3973 | } | ||
3974 | } | ||
3975 | write_lock(&em_tree->lock); | 3950 | write_lock(&em_tree->lock); |
3976 | remove_extent_mapping(em_tree, em); | 3951 | remove_extent_mapping(em_tree, em); |
3977 | write_unlock(&em_tree->lock); | 3952 | write_unlock(&em_tree->lock); |
@@ -3986,33 +3961,68 @@ error: | |||
3986 | return ret; | 3961 | return ret; |
3987 | } | 3962 | } |
3988 | 3963 | ||
3989 | static int __finish_chunk_alloc(struct btrfs_trans_handle *trans, | 3964 | int btrfs_finish_chunk_alloc(struct btrfs_trans_handle *trans, |
3990 | struct btrfs_root *extent_root, | 3965 | struct btrfs_root *extent_root, |
3991 | struct map_lookup *map, u64 chunk_offset, | 3966 | u64 chunk_offset, u64 chunk_size) |
3992 | u64 chunk_size, u64 stripe_size) | ||
3993 | { | 3967 | { |
3994 | u64 dev_offset; | ||
3995 | struct btrfs_key key; | 3968 | struct btrfs_key key; |
3996 | struct btrfs_root *chunk_root = extent_root->fs_info->chunk_root; | 3969 | struct btrfs_root *chunk_root = extent_root->fs_info->chunk_root; |
3997 | struct btrfs_device *device; | 3970 | struct btrfs_device *device; |
3998 | struct btrfs_chunk *chunk; | 3971 | struct btrfs_chunk *chunk; |
3999 | struct btrfs_stripe *stripe; | 3972 | struct btrfs_stripe *stripe; |
4000 | size_t item_size = btrfs_chunk_item_size(map->num_stripes); | 3973 | struct extent_map_tree *em_tree; |
4001 | int index = 0; | 3974 | struct extent_map *em; |
3975 | struct map_lookup *map; | ||
3976 | size_t item_size; | ||
3977 | u64 dev_offset; | ||
3978 | u64 stripe_size; | ||
3979 | int i = 0; | ||
4002 | int ret; | 3980 | int ret; |
4003 | 3981 | ||
3982 | em_tree = &extent_root->fs_info->mapping_tree.map_tree; | ||
3983 | read_lock(&em_tree->lock); | ||
3984 | em = lookup_extent_mapping(em_tree, chunk_offset, chunk_size); | ||
3985 | read_unlock(&em_tree->lock); | ||
3986 | |||
3987 | if (!em) { | ||
3988 | btrfs_crit(extent_root->fs_info, "unable to find logical " | ||
3989 | "%Lu len %Lu", chunk_offset, chunk_size); | ||
3990 | return -EINVAL; | ||
3991 | } | ||
3992 | |||
3993 | if (em->start != chunk_offset || em->len != chunk_size) { | ||
3994 | btrfs_crit(extent_root->fs_info, "found a bad mapping, wanted" | ||
3995 | " %Lu-%Lu, found %Lu-%Lu\n", chunk_offset, | ||
3996 | chunk_size, em->start, em->len); | ||
3997 | free_extent_map(em); | ||
3998 | return -EINVAL; | ||
3999 | } | ||
4000 | |||
4001 | map = (struct map_lookup *)em->bdev; | ||
4002 | item_size = btrfs_chunk_item_size(map->num_stripes); | ||
4003 | stripe_size = em->orig_block_len; | ||
4004 | |||
4004 | chunk = kzalloc(item_size, GFP_NOFS); | 4005 | chunk = kzalloc(item_size, GFP_NOFS); |
4005 | if (!chunk) | 4006 | if (!chunk) { |
4006 | return -ENOMEM; | 4007 | ret = -ENOMEM; |
4008 | goto out; | ||
4009 | } | ||
4010 | |||
4011 | for (i = 0; i < map->num_stripes; i++) { | ||
4012 | device = map->stripes[i].dev; | ||
4013 | dev_offset = map->stripes[i].physical; | ||
4007 | 4014 | ||
4008 | index = 0; | ||
4009 | while (index < map->num_stripes) { | ||
4010 | device = map->stripes[index].dev; | ||
4011 | device->bytes_used += stripe_size; | 4015 | device->bytes_used += stripe_size; |
4012 | ret = btrfs_update_device(trans, device); | 4016 | ret = btrfs_update_device(trans, device); |
4013 | if (ret) | 4017 | if (ret) |
4014 | goto out_free; | 4018 | goto out; |
4015 | index++; | 4019 | ret = btrfs_alloc_dev_extent(trans, device, |
4020 | chunk_root->root_key.objectid, | ||
4021 | BTRFS_FIRST_CHUNK_TREE_OBJECTID, | ||
4022 | chunk_offset, dev_offset, | ||
4023 | stripe_size); | ||
4024 | if (ret) | ||
4025 | goto out; | ||
4016 | } | 4026 | } |
4017 | 4027 | ||
4018 | spin_lock(&extent_root->fs_info->free_chunk_lock); | 4028 | spin_lock(&extent_root->fs_info->free_chunk_lock); |
@@ -4020,17 +4030,15 @@ static int __finish_chunk_alloc(struct btrfs_trans_handle *trans, | |||
4020 | map->num_stripes); | 4030 | map->num_stripes); |
4021 | spin_unlock(&extent_root->fs_info->free_chunk_lock); | 4031 | spin_unlock(&extent_root->fs_info->free_chunk_lock); |
4022 | 4032 | ||
4023 | index = 0; | ||
4024 | stripe = &chunk->stripe; | 4033 | stripe = &chunk->stripe; |
4025 | while (index < map->num_stripes) { | 4034 | for (i = 0; i < map->num_stripes; i++) { |
4026 | device = map->stripes[index].dev; | 4035 | device = map->stripes[i].dev; |
4027 | dev_offset = map->stripes[index].physical; | 4036 | dev_offset = map->stripes[i].physical; |
4028 | 4037 | ||
4029 | btrfs_set_stack_stripe_devid(stripe, device->devid); | 4038 | btrfs_set_stack_stripe_devid(stripe, device->devid); |
4030 | btrfs_set_stack_stripe_offset(stripe, dev_offset); | 4039 | btrfs_set_stack_stripe_offset(stripe, dev_offset); |
4031 | memcpy(stripe->dev_uuid, device->uuid, BTRFS_UUID_SIZE); | 4040 | memcpy(stripe->dev_uuid, device->uuid, BTRFS_UUID_SIZE); |
4032 | stripe++; | 4041 | stripe++; |
4033 | index++; | ||
4034 | } | 4042 | } |
4035 | 4043 | ||
4036 | btrfs_set_stack_chunk_length(chunk, chunk_size); | 4044 | btrfs_set_stack_chunk_length(chunk, chunk_size); |
@@ -4048,7 +4056,6 @@ static int __finish_chunk_alloc(struct btrfs_trans_handle *trans, | |||
4048 | key.offset = chunk_offset; | 4056 | key.offset = chunk_offset; |
4049 | 4057 | ||
4050 | ret = btrfs_insert_item(trans, chunk_root, &key, chunk, item_size); | 4058 | ret = btrfs_insert_item(trans, chunk_root, &key, chunk, item_size); |
4051 | |||
4052 | if (ret == 0 && map->type & BTRFS_BLOCK_GROUP_SYSTEM) { | 4059 | if (ret == 0 && map->type & BTRFS_BLOCK_GROUP_SYSTEM) { |
4053 | /* | 4060 | /* |
4054 | * TODO: Cleanup of inserted chunk root in case of | 4061 | * TODO: Cleanup of inserted chunk root in case of |
@@ -4058,8 +4065,9 @@ static int __finish_chunk_alloc(struct btrfs_trans_handle *trans, | |||
4058 | item_size); | 4065 | item_size); |
4059 | } | 4066 | } |
4060 | 4067 | ||
4061 | out_free: | 4068 | out: |
4062 | kfree(chunk); | 4069 | kfree(chunk); |
4070 | free_extent_map(em); | ||
4063 | return ret; | 4071 | return ret; |
4064 | } | 4072 | } |
4065 | 4073 | ||
@@ -4074,27 +4082,9 @@ int btrfs_alloc_chunk(struct btrfs_trans_handle *trans, | |||
4074 | struct btrfs_root *extent_root, u64 type) | 4082 | struct btrfs_root *extent_root, u64 type) |
4075 | { | 4083 | { |
4076 | u64 chunk_offset; | 4084 | u64 chunk_offset; |
4077 | u64 chunk_size; | ||
4078 | u64 stripe_size; | ||
4079 | struct map_lookup *map; | ||
4080 | struct btrfs_root *chunk_root = extent_root->fs_info->chunk_root; | ||
4081 | int ret; | ||
4082 | |||
4083 | ret = find_next_chunk(chunk_root, BTRFS_FIRST_CHUNK_TREE_OBJECTID, | ||
4084 | &chunk_offset); | ||
4085 | if (ret) | ||
4086 | return ret; | ||
4087 | 4085 | ||
4088 | ret = __btrfs_alloc_chunk(trans, extent_root, &map, &chunk_size, | 4086 | chunk_offset = find_next_chunk(extent_root->fs_info); |
4089 | &stripe_size, chunk_offset, type); | 4087 | return __btrfs_alloc_chunk(trans, extent_root, chunk_offset, type); |
4090 | if (ret) | ||
4091 | return ret; | ||
4092 | |||
4093 | ret = __finish_chunk_alloc(trans, extent_root, map, chunk_offset, | ||
4094 | chunk_size, stripe_size); | ||
4095 | if (ret) | ||
4096 | return ret; | ||
4097 | return 0; | ||
4098 | } | 4088 | } |
4099 | 4089 | ||
4100 | static noinline int init_first_rw_device(struct btrfs_trans_handle *trans, | 4090 | static noinline int init_first_rw_device(struct btrfs_trans_handle *trans, |
@@ -4103,66 +4093,31 @@ static noinline int init_first_rw_device(struct btrfs_trans_handle *trans, | |||
4103 | { | 4093 | { |
4104 | u64 chunk_offset; | 4094 | u64 chunk_offset; |
4105 | u64 sys_chunk_offset; | 4095 | u64 sys_chunk_offset; |
4106 | u64 chunk_size; | ||
4107 | u64 sys_chunk_size; | ||
4108 | u64 stripe_size; | ||
4109 | u64 sys_stripe_size; | ||
4110 | u64 alloc_profile; | 4096 | u64 alloc_profile; |
4111 | struct map_lookup *map; | ||
4112 | struct map_lookup *sys_map; | ||
4113 | struct btrfs_fs_info *fs_info = root->fs_info; | 4097 | struct btrfs_fs_info *fs_info = root->fs_info; |
4114 | struct btrfs_root *extent_root = fs_info->extent_root; | 4098 | struct btrfs_root *extent_root = fs_info->extent_root; |
4115 | int ret; | 4099 | int ret; |
4116 | 4100 | ||
4117 | ret = find_next_chunk(fs_info->chunk_root, | 4101 | chunk_offset = find_next_chunk(fs_info); |
4118 | BTRFS_FIRST_CHUNK_TREE_OBJECTID, &chunk_offset); | ||
4119 | if (ret) | ||
4120 | return ret; | ||
4121 | |||
4122 | alloc_profile = btrfs_get_alloc_profile(extent_root, 0); | 4102 | alloc_profile = btrfs_get_alloc_profile(extent_root, 0); |
4123 | ret = __btrfs_alloc_chunk(trans, extent_root, &map, &chunk_size, | 4103 | ret = __btrfs_alloc_chunk(trans, extent_root, chunk_offset, |
4124 | &stripe_size, chunk_offset, alloc_profile); | 4104 | alloc_profile); |
4125 | if (ret) | 4105 | if (ret) |
4126 | return ret; | 4106 | return ret; |
4127 | 4107 | ||
4128 | sys_chunk_offset = chunk_offset + chunk_size; | 4108 | sys_chunk_offset = find_next_chunk(root->fs_info); |
4129 | |||
4130 | alloc_profile = btrfs_get_alloc_profile(fs_info->chunk_root, 0); | 4109 | alloc_profile = btrfs_get_alloc_profile(fs_info->chunk_root, 0); |
4131 | ret = __btrfs_alloc_chunk(trans, extent_root, &sys_map, | 4110 | ret = __btrfs_alloc_chunk(trans, extent_root, sys_chunk_offset, |
4132 | &sys_chunk_size, &sys_stripe_size, | 4111 | alloc_profile); |
4133 | sys_chunk_offset, alloc_profile); | ||
4134 | if (ret) { | 4112 | if (ret) { |
4135 | btrfs_abort_transaction(trans, root, ret); | 4113 | btrfs_abort_transaction(trans, root, ret); |
4136 | goto out; | 4114 | goto out; |
4137 | } | 4115 | } |
4138 | 4116 | ||
4139 | ret = btrfs_add_device(trans, fs_info->chunk_root, device); | 4117 | ret = btrfs_add_device(trans, fs_info->chunk_root, device); |
4140 | if (ret) { | ||
4141 | btrfs_abort_transaction(trans, root, ret); | ||
4142 | goto out; | ||
4143 | } | ||
4144 | |||
4145 | /* | ||
4146 | * Modifying chunk tree needs allocating new blocks from both | ||
4147 | * system block group and metadata block group. So we only can | ||
4148 | * do operations require modifying the chunk tree after both | ||
4149 | * block groups were created. | ||
4150 | */ | ||
4151 | ret = __finish_chunk_alloc(trans, extent_root, map, chunk_offset, | ||
4152 | chunk_size, stripe_size); | ||
4153 | if (ret) { | ||
4154 | btrfs_abort_transaction(trans, root, ret); | ||
4155 | goto out; | ||
4156 | } | ||
4157 | |||
4158 | ret = __finish_chunk_alloc(trans, extent_root, sys_map, | ||
4159 | sys_chunk_offset, sys_chunk_size, | ||
4160 | sys_stripe_size); | ||
4161 | if (ret) | 4118 | if (ret) |
4162 | btrfs_abort_transaction(trans, root, ret); | 4119 | btrfs_abort_transaction(trans, root, ret); |
4163 | |||
4164 | out: | 4120 | out: |
4165 | |||
4166 | return ret; | 4121 | return ret; |
4167 | } | 4122 | } |
4168 | 4123 | ||
@@ -4435,9 +4390,6 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info, int rw, | |||
4435 | map = (struct map_lookup *)em->bdev; | 4390 | map = (struct map_lookup *)em->bdev; |
4436 | offset = logical - em->start; | 4391 | offset = logical - em->start; |
4437 | 4392 | ||
4438 | if (mirror_num > map->num_stripes) | ||
4439 | mirror_num = 0; | ||
4440 | |||
4441 | stripe_len = map->stripe_len; | 4393 | stripe_len = map->stripe_len; |
4442 | stripe_nr = offset; | 4394 | stripe_nr = offset; |
4443 | /* | 4395 | /* |
@@ -5367,7 +5319,6 @@ static struct btrfs_device *add_missing_dev(struct btrfs_root *root, | |||
5367 | return NULL; | 5319 | return NULL; |
5368 | list_add(&device->dev_list, | 5320 | list_add(&device->dev_list, |
5369 | &fs_devices->devices); | 5321 | &fs_devices->devices); |
5370 | device->dev_root = root->fs_info->dev_root; | ||
5371 | device->devid = devid; | 5322 | device->devid = devid; |
5372 | device->work.func = pending_bios_fn; | 5323 | device->work.func = pending_bios_fn; |
5373 | device->fs_devices = fs_devices; | 5324 | device->fs_devices = fs_devices; |
@@ -5593,7 +5544,6 @@ static int read_one_dev(struct btrfs_root *root, | |||
5593 | } | 5544 | } |
5594 | 5545 | ||
5595 | fill_device_from_item(leaf, dev_item, device); | 5546 | fill_device_from_item(leaf, dev_item, device); |
5596 | device->dev_root = root->fs_info->dev_root; | ||
5597 | device->in_fs_metadata = 1; | 5547 | device->in_fs_metadata = 1; |
5598 | if (device->writeable && !device->is_tgtdev_for_dev_replace) { | 5548 | if (device->writeable && !device->is_tgtdev_for_dev_replace) { |
5599 | device->fs_devices->total_rw_bytes += device->total_bytes; | 5549 | device->fs_devices->total_rw_bytes += device->total_bytes; |
@@ -5751,6 +5701,17 @@ error: | |||
5751 | return ret; | 5701 | return ret; |
5752 | } | 5702 | } |
5753 | 5703 | ||
5704 | void btrfs_init_devices_late(struct btrfs_fs_info *fs_info) | ||
5705 | { | ||
5706 | struct btrfs_fs_devices *fs_devices = fs_info->fs_devices; | ||
5707 | struct btrfs_device *device; | ||
5708 | |||
5709 | mutex_lock(&fs_devices->device_list_mutex); | ||
5710 | list_for_each_entry(device, &fs_devices->devices, dev_list) | ||
5711 | device->dev_root = fs_info->dev_root; | ||
5712 | mutex_unlock(&fs_devices->device_list_mutex); | ||
5713 | } | ||
5714 | |||
5754 | static void __btrfs_reset_dev_stats(struct btrfs_device *dev) | 5715 | static void __btrfs_reset_dev_stats(struct btrfs_device *dev) |
5755 | { | 5716 | { |
5756 | int i; | 5717 | int i; |