diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-09 15:33:09 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-09 15:33:09 -0400 |
commit | e3a0dd98e1ddfd135b7ef889fcc0269e8c2ca445 (patch) | |
tree | 7f942b10ffe7ea1498e4b1d3a206291692647040 /fs/btrfs/volumes.c | |
parent | da89bd213fe719ec3552abbeb8be12d0cc0337ca (diff) | |
parent | 0e267c44c3a402d35111d1935be1167240b5b79f (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs
Pull btrfs update from Chris Mason:
"These are the usual mixture of bugs, cleanups and performance fixes.
Miao has some really nice tuning of our crc code as well as our
transaction commits.
Josef is peeling off more and more problems related to early enospc,
and has a number of important bug fixes in here too"
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs: (81 commits)
Btrfs: wait ordered range before doing direct io
Btrfs: only do the tree_mod_log_free_eb if this is our last ref
Btrfs: hold the tree mod lock in __tree_mod_log_rewind
Btrfs: make backref walking code handle skinny metadata
Btrfs: fix crash regarding to ulist_add_merge
Btrfs: fix several potential problems in copy_nocow_pages_for_inode
Btrfs: cleanup the code of copy_nocow_pages_for_inode()
Btrfs: fix oops when recovering the file data by scrub function
Btrfs: make the chunk allocator completely tree lockless
Btrfs: cleanup orphaned root orphan item
Btrfs: fix wrong mirror number tuning
Btrfs: cleanup redundant code in btrfs_submit_direct()
Btrfs: remove btrfs_sector_sum structure
Btrfs: check if we can nocow if we don't have data space
Btrfs: stop using try_to_writeback_inodes_sb_nr to flush delalloc
Btrfs: use a percpu to keep track of possibly pinned bytes
Btrfs: check for actual acls rather than just xattrs when caching no acl
Btrfs: move btrfs_truncate_page to btrfs_cont_expand instead of btrfs_truncate
Btrfs: optimize reada_for_balance
Btrfs: optimize read_block_for_search
...
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; |