diff options
| author | Thomas Gleixner <tglx@linutronix.de> | 2013-07-12 06:34:42 -0400 |
|---|---|---|
| committer | Thomas Gleixner <tglx@linutronix.de> | 2013-07-12 06:34:42 -0400 |
| commit | f2006e27396f55276f24434f56e208d86e7f9908 (patch) | |
| tree | 71896db916d33888b4286f80117d3cac0da40e6d /fs/btrfs/volumes.c | |
| parent | e399eb56a6110e13f97e644658648602e2b08de7 (diff) | |
| parent | 9903883f1dd6e86f286b7bfa6e4b423f98c1cd9e (diff) | |
Merge branch 'linus' into timers/urgent
Get upstream changes so we can apply fixes against them
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
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; |
