aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/btrfs/disk-io.c11
-rw-r--r--fs/btrfs/hash.c5
-rw-r--r--fs/btrfs/hash.h1
-rw-r--r--fs/btrfs/super.c5
-rw-r--r--fs/btrfs/volumes.c109
-rw-r--r--include/uapi/linux/btrfs.h2
6 files changed, 115 insertions, 18 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index c3764ddb2a46..1142127f6e5e 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -4133,6 +4133,17 @@ static int btrfs_check_super_valid(struct btrfs_fs_info *fs_info,
4133 * Hint to catch really bogus numbers, bitflips or so, more exact checks are 4133 * Hint to catch really bogus numbers, bitflips or so, more exact checks are
4134 * done later 4134 * done later
4135 */ 4135 */
4136 if (btrfs_super_bytes_used(sb) < 6 * btrfs_super_nodesize(sb)) {
4137 btrfs_err(fs_info, "bytes_used is too small %llu",
4138 btrfs_super_bytes_used(sb));
4139 ret = -EINVAL;
4140 }
4141 if (!is_power_of_2(btrfs_super_stripesize(sb)) ||
4142 btrfs_super_stripesize(sb) != sectorsize) {
4143 btrfs_err(fs_info, "invalid stripesize %u",
4144 btrfs_super_stripesize(sb));
4145 ret = -EINVAL;
4146 }
4136 if (btrfs_super_num_devices(sb) > (1UL << 31)) 4147 if (btrfs_super_num_devices(sb) > (1UL << 31))
4137 printk(KERN_WARNING "BTRFS: suspicious number of devices: %llu\n", 4148 printk(KERN_WARNING "BTRFS: suspicious number of devices: %llu\n",
4138 btrfs_super_num_devices(sb)); 4149 btrfs_super_num_devices(sb));
diff --git a/fs/btrfs/hash.c b/fs/btrfs/hash.c
index aae520b2aee5..a97fdc156a03 100644
--- a/fs/btrfs/hash.c
+++ b/fs/btrfs/hash.c
@@ -24,6 +24,11 @@ int __init btrfs_hash_init(void)
24 return PTR_ERR_OR_ZERO(tfm); 24 return PTR_ERR_OR_ZERO(tfm);
25} 25}
26 26
27const char* btrfs_crc32c_impl(void)
28{
29 return crypto_tfm_alg_driver_name(crypto_shash_tfm(tfm));
30}
31
27void btrfs_hash_exit(void) 32void btrfs_hash_exit(void)
28{ 33{
29 crypto_free_shash(tfm); 34 crypto_free_shash(tfm);
diff --git a/fs/btrfs/hash.h b/fs/btrfs/hash.h
index 118a2316e5d3..c3a2ec554361 100644
--- a/fs/btrfs/hash.h
+++ b/fs/btrfs/hash.h
@@ -22,6 +22,7 @@
22int __init btrfs_hash_init(void); 22int __init btrfs_hash_init(void);
23 23
24void btrfs_hash_exit(void); 24void btrfs_hash_exit(void);
25const char* btrfs_crc32c_impl(void);
25 26
26u32 btrfs_crc32c(u32 crc, const void *address, unsigned int length); 27u32 btrfs_crc32c(u32 crc, const void *address, unsigned int length);
27 28
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index c49d7ae69617..4339b6613f19 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -2303,7 +2303,7 @@ static void btrfs_interface_exit(void)
2303 2303
2304static void btrfs_print_mod_info(void) 2304static void btrfs_print_mod_info(void)
2305{ 2305{
2306 printk(KERN_INFO "Btrfs loaded" 2306 printk(KERN_INFO "Btrfs loaded, crc32c=%s"
2307#ifdef CONFIG_BTRFS_DEBUG 2307#ifdef CONFIG_BTRFS_DEBUG
2308 ", debug=on" 2308 ", debug=on"
2309#endif 2309#endif
@@ -2313,7 +2313,8 @@ static void btrfs_print_mod_info(void)
2313#ifdef CONFIG_BTRFS_FS_CHECK_INTEGRITY 2313#ifdef CONFIG_BTRFS_FS_CHECK_INTEGRITY
2314 ", integrity-checker=on" 2314 ", integrity-checker=on"
2315#endif 2315#endif
2316 "\n"); 2316 "\n",
2317 btrfs_crc32c_impl());
2317} 2318}
2318 2319
2319static int btrfs_run_sanity_tests(void) 2320static int btrfs_run_sanity_tests(void)
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 765aabd9145f..fcbda4341f7d 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);
@@ -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);
diff --git a/include/uapi/linux/btrfs.h b/include/uapi/linux/btrfs.h
index 23c6960e94a4..2bdd1e3e7007 100644
--- a/include/uapi/linux/btrfs.h
+++ b/include/uapi/linux/btrfs.h
@@ -118,7 +118,7 @@ struct btrfs_ioctl_vol_args_v2 {
118 }; 118 };
119 union { 119 union {
120 char name[BTRFS_SUBVOL_NAME_MAX + 1]; 120 char name[BTRFS_SUBVOL_NAME_MAX + 1];
121 u64 devid; 121 __u64 devid;
122 }; 122 };
123}; 123};
124 124