aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/volumes.c
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2016-06-20 11:25:44 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2016-06-20 11:25:44 -0400
commitaf52739b922f656eb1f39016fabaabe4baeda2e2 (patch)
tree79a7aa810d0493cd0cf4adebac26d37f12e8b545 /fs/btrfs/volumes.c
parent25ed6a5e97809129a1bc852b6b5c7d03baa112c4 (diff)
parent33688abb2802ff3a230bd2441f765477b94cc89e (diff)
Merge 4.7-rc4 into staging-next
We want the fixes in here, and we can resolve a merge issue in drivers/iio/industrialio-trigger.c Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'fs/btrfs/volumes.c')
-rw-r--r--fs/btrfs/volumes.c113
1 files changed, 96 insertions, 17 deletions
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index da9e0036a864..2f631b58ae00 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -4241,6 +4241,7 @@ int btrfs_create_uuid_tree(struct btrfs_fs_info *fs_info)
4241 if (IS_ERR(uuid_root)) { 4241 if (IS_ERR(uuid_root)) {
4242 ret = PTR_ERR(uuid_root); 4242 ret = PTR_ERR(uuid_root);
4243 btrfs_abort_transaction(trans, tree_root, ret); 4243 btrfs_abort_transaction(trans, tree_root, ret);
4244 btrfs_end_transaction(trans, tree_root);
4244 return ret; 4245 return ret;
4245 } 4246 }
4246 4247
@@ -6258,27 +6259,23 @@ struct btrfs_device *btrfs_alloc_device(struct btrfs_fs_info *fs_info,
6258 return dev; 6259 return dev;
6259} 6260}
6260 6261
6261static int read_one_chunk(struct btrfs_root *root, struct btrfs_key *key, 6262/* Return -EIO if any error, otherwise return 0. */
6262 struct extent_buffer *leaf, 6263static int btrfs_check_chunk_valid(struct btrfs_root *root,
6263 struct btrfs_chunk *chunk) 6264 struct extent_buffer *leaf,
6265 struct btrfs_chunk *chunk, u64 logical)
6264{ 6266{
6265 struct btrfs_mapping_tree *map_tree = &root->fs_info->mapping_tree;
6266 struct map_lookup *map;
6267 struct extent_map *em;
6268 u64 logical;
6269 u64 length; 6267 u64 length;
6270 u64 stripe_len; 6268 u64 stripe_len;
6271 u64 devid; 6269 u16 num_stripes;
6272 u8 uuid[BTRFS_UUID_SIZE]; 6270 u16 sub_stripes;
6273 int num_stripes; 6271 u64 type;
6274 int ret;
6275 int i;
6276 6272
6277 logical = key->offset;
6278 length = btrfs_chunk_length(leaf, chunk); 6273 length = btrfs_chunk_length(leaf, chunk);
6279 stripe_len = btrfs_chunk_stripe_len(leaf, chunk); 6274 stripe_len = btrfs_chunk_stripe_len(leaf, chunk);
6280 num_stripes = btrfs_chunk_num_stripes(leaf, chunk); 6275 num_stripes = btrfs_chunk_num_stripes(leaf, chunk);
6281 /* Validation check */ 6276 sub_stripes = btrfs_chunk_sub_stripes(leaf, chunk);
6277 type = btrfs_chunk_type(leaf, chunk);
6278
6282 if (!num_stripes) { 6279 if (!num_stripes) {
6283 btrfs_err(root->fs_info, "invalid chunk num_stripes: %u", 6280 btrfs_err(root->fs_info, "invalid chunk num_stripes: %u",
6284 num_stripes); 6281 num_stripes);
@@ -6289,6 +6286,11 @@ static int read_one_chunk(struct btrfs_root *root, struct btrfs_key *key,
6289 "invalid chunk logical %llu", logical); 6286 "invalid chunk logical %llu", logical);
6290 return -EIO; 6287 return -EIO;
6291 } 6288 }
6289 if (btrfs_chunk_sector_size(leaf, chunk) != root->sectorsize) {
6290 btrfs_err(root->fs_info, "invalid chunk sectorsize %u",
6291 btrfs_chunk_sector_size(leaf, chunk));
6292 return -EIO;
6293 }
6292 if (!length || !IS_ALIGNED(length, root->sectorsize)) { 6294 if (!length || !IS_ALIGNED(length, root->sectorsize)) {
6293 btrfs_err(root->fs_info, 6295 btrfs_err(root->fs_info,
6294 "invalid chunk length %llu", length); 6296 "invalid chunk length %llu", length);
@@ -6300,13 +6302,54 @@ static int read_one_chunk(struct btrfs_root *root, struct btrfs_key *key,
6300 return -EIO; 6302 return -EIO;
6301 } 6303 }
6302 if (~(BTRFS_BLOCK_GROUP_TYPE_MASK | BTRFS_BLOCK_GROUP_PROFILE_MASK) & 6304 if (~(BTRFS_BLOCK_GROUP_TYPE_MASK | BTRFS_BLOCK_GROUP_PROFILE_MASK) &
6303 btrfs_chunk_type(leaf, chunk)) { 6305 type) {
6304 btrfs_err(root->fs_info, "unrecognized chunk type: %llu", 6306 btrfs_err(root->fs_info, "unrecognized chunk type: %llu",
6305 ~(BTRFS_BLOCK_GROUP_TYPE_MASK | 6307 ~(BTRFS_BLOCK_GROUP_TYPE_MASK |
6306 BTRFS_BLOCK_GROUP_PROFILE_MASK) & 6308 BTRFS_BLOCK_GROUP_PROFILE_MASK) &
6307 btrfs_chunk_type(leaf, chunk)); 6309 btrfs_chunk_type(leaf, chunk));
6308 return -EIO; 6310 return -EIO;
6309 } 6311 }
6312 if ((type & BTRFS_BLOCK_GROUP_RAID10 && sub_stripes != 2) ||
6313 (type & BTRFS_BLOCK_GROUP_RAID1 && num_stripes < 1) ||
6314 (type & BTRFS_BLOCK_GROUP_RAID5 && num_stripes < 2) ||
6315 (type & BTRFS_BLOCK_GROUP_RAID6 && num_stripes < 3) ||
6316 (type & BTRFS_BLOCK_GROUP_DUP && num_stripes > 2) ||
6317 ((type & BTRFS_BLOCK_GROUP_PROFILE_MASK) == 0 &&
6318 num_stripes != 1)) {
6319 btrfs_err(root->fs_info,
6320 "invalid num_stripes:sub_stripes %u:%u for profile %llu",
6321 num_stripes, sub_stripes,
6322 type & BTRFS_BLOCK_GROUP_PROFILE_MASK);
6323 return -EIO;
6324 }
6325
6326 return 0;
6327}
6328
6329static int read_one_chunk(struct btrfs_root *root, struct btrfs_key *key,
6330 struct extent_buffer *leaf,
6331 struct btrfs_chunk *chunk)
6332{
6333 struct btrfs_mapping_tree *map_tree = &root->fs_info->mapping_tree;
6334 struct map_lookup *map;
6335 struct extent_map *em;
6336 u64 logical;
6337 u64 length;
6338 u64 stripe_len;
6339 u64 devid;
6340 u8 uuid[BTRFS_UUID_SIZE];
6341 int num_stripes;
6342 int ret;
6343 int i;
6344
6345 logical = key->offset;
6346 length = btrfs_chunk_length(leaf, chunk);
6347 stripe_len = btrfs_chunk_stripe_len(leaf, chunk);
6348 num_stripes = btrfs_chunk_num_stripes(leaf, chunk);
6349
6350 ret = btrfs_check_chunk_valid(root, leaf, chunk, logical);
6351 if (ret)
6352 return ret;
6310 6353
6311 read_lock(&map_tree->map_tree.lock); 6354 read_lock(&map_tree->map_tree.lock);
6312 em = lookup_extent_mapping(&map_tree->map_tree, logical, 1); 6355 em = lookup_extent_mapping(&map_tree->map_tree, logical, 1);
@@ -6554,6 +6597,7 @@ int btrfs_read_sys_array(struct btrfs_root *root)
6554 u32 array_size; 6597 u32 array_size;
6555 u32 len = 0; 6598 u32 len = 0;
6556 u32 cur_offset; 6599 u32 cur_offset;
6600 u64 type;
6557 struct btrfs_key key; 6601 struct btrfs_key key;
6558 6602
6559 ASSERT(BTRFS_SUPER_INFO_SIZE <= root->nodesize); 6603 ASSERT(BTRFS_SUPER_INFO_SIZE <= root->nodesize);
@@ -6563,8 +6607,8 @@ int btrfs_read_sys_array(struct btrfs_root *root)
6563 * overallocate but we can keep it as-is, only the first page is used. 6607 * overallocate but we can keep it as-is, only the first page is used.
6564 */ 6608 */
6565 sb = btrfs_find_create_tree_block(root, BTRFS_SUPER_INFO_OFFSET); 6609 sb = btrfs_find_create_tree_block(root, BTRFS_SUPER_INFO_OFFSET);
6566 if (!sb) 6610 if (IS_ERR(sb))
6567 return -ENOMEM; 6611 return PTR_ERR(sb);
6568 set_extent_buffer_uptodate(sb); 6612 set_extent_buffer_uptodate(sb);
6569 btrfs_set_buffer_lockdep_class(root->root_key.objectid, sb, 0); 6613 btrfs_set_buffer_lockdep_class(root->root_key.objectid, sb, 0);
6570 /* 6614 /*
@@ -6620,6 +6664,15 @@ int btrfs_read_sys_array(struct btrfs_root *root)
6620 break; 6664 break;
6621 } 6665 }
6622 6666
6667 type = btrfs_chunk_type(sb, chunk);
6668 if ((type & BTRFS_BLOCK_GROUP_SYSTEM) == 0) {
6669 btrfs_err(root->fs_info,
6670 "invalid chunk type %llu in sys_array at offset %u",
6671 type, cur_offset);
6672 ret = -EIO;
6673 break;
6674 }
6675
6623 len = btrfs_chunk_item_size(num_stripes); 6676 len = btrfs_chunk_item_size(num_stripes);
6624 if (cur_offset + len > array_size) 6677 if (cur_offset + len > array_size)
6625 goto out_short_read; 6678 goto out_short_read;
@@ -6638,12 +6691,14 @@ int btrfs_read_sys_array(struct btrfs_root *root)
6638 sb_array_offset += len; 6691 sb_array_offset += len;
6639 cur_offset += len; 6692 cur_offset += len;
6640 } 6693 }
6694 clear_extent_buffer_uptodate(sb);
6641 free_extent_buffer_stale(sb); 6695 free_extent_buffer_stale(sb);
6642 return ret; 6696 return ret;
6643 6697
6644out_short_read: 6698out_short_read:
6645 printk(KERN_ERR "BTRFS: sys_array too short to read %u bytes at offset %u\n", 6699 printk(KERN_ERR "BTRFS: sys_array too short to read %u bytes at offset %u\n",
6646 len, cur_offset); 6700 len, cur_offset);
6701 clear_extent_buffer_uptodate(sb);
6647 free_extent_buffer_stale(sb); 6702 free_extent_buffer_stale(sb);
6648 return -EIO; 6703 return -EIO;
6649} 6704}
@@ -6656,6 +6711,7 @@ int btrfs_read_chunk_tree(struct btrfs_root *root)
6656 struct btrfs_key found_key; 6711 struct btrfs_key found_key;
6657 int ret; 6712 int ret;
6658 int slot; 6713 int slot;
6714 u64 total_dev = 0;
6659 6715
6660 root = root->fs_info->chunk_root; 6716 root = root->fs_info->chunk_root;
6661 6717
@@ -6697,6 +6753,7 @@ int btrfs_read_chunk_tree(struct btrfs_root *root)
6697 ret = read_one_dev(root, leaf, dev_item); 6753 ret = read_one_dev(root, leaf, dev_item);
6698 if (ret) 6754 if (ret)
6699 goto error; 6755 goto error;
6756 total_dev++;
6700 } else if (found_key.type == BTRFS_CHUNK_ITEM_KEY) { 6757 } else if (found_key.type == BTRFS_CHUNK_ITEM_KEY) {
6701 struct btrfs_chunk *chunk; 6758 struct btrfs_chunk *chunk;
6702 chunk = btrfs_item_ptr(leaf, slot, struct btrfs_chunk); 6759 chunk = btrfs_item_ptr(leaf, slot, struct btrfs_chunk);
@@ -6706,6 +6763,28 @@ int btrfs_read_chunk_tree(struct btrfs_root *root)
6706 } 6763 }
6707 path->slots[0]++; 6764 path->slots[0]++;
6708 } 6765 }
6766
6767 /*
6768 * After loading chunk tree, we've got all device information,
6769 * do another round of validation checks.
6770 */
6771 if (total_dev != root->fs_info->fs_devices->total_devices) {
6772 btrfs_err(root->fs_info,
6773 "super_num_devices %llu mismatch with num_devices %llu found here",
6774 btrfs_super_num_devices(root->fs_info->super_copy),
6775 total_dev);
6776 ret = -EINVAL;
6777 goto error;
6778 }
6779 if (btrfs_super_total_bytes(root->fs_info->super_copy) <
6780 root->fs_info->fs_devices->total_rw_bytes) {
6781 btrfs_err(root->fs_info,
6782 "super_total_bytes %llu mismatch with fs_devices total_rw_bytes %llu",
6783 btrfs_super_total_bytes(root->fs_info->super_copy),
6784 root->fs_info->fs_devices->total_rw_bytes);
6785 ret = -EINVAL;
6786 goto error;
6787 }
6709 ret = 0; 6788 ret = 0;
6710error: 6789error:
6711 unlock_chunks(root); 6790 unlock_chunks(root);