btrfs: tree-checker: Verify dev item
[sfrench/cifs-2.6.git] / fs / btrfs / volumes.c
index db934ceae9c109f39eade85457a25b8ce99604ae..77bca3a61e2605646a30b462a14624363b2c3389 100644 (file)
@@ -27,6 +27,7 @@
 #include "math.h"
 #include "dev-replace.h"
 #include "sysfs.h"
+#include "tree-checker.h"
 
 const struct btrfs_raid_attr btrfs_raid_array[BTRFS_NR_RAID_TYPES] = {
        [BTRFS_RAID_RAID10] = {
@@ -4957,15 +4958,6 @@ static void check_raid56_incompat_flag(struct btrfs_fs_info *info, u64 type)
        btrfs_set_fs_incompat(info, RAID56);
 }
 
-#define BTRFS_MAX_DEVS(info) ((BTRFS_MAX_ITEM_SIZE(info)       \
-                       - sizeof(struct btrfs_chunk))           \
-                       / sizeof(struct btrfs_stripe) + 1)
-
-#define BTRFS_MAX_DEVS_SYS_CHUNK ((BTRFS_SYSTEM_CHUNK_ARRAY_SIZE       \
-                               - 2 * sizeof(struct btrfs_disk_key)     \
-                               - 2 * sizeof(struct btrfs_chunk))       \
-                               / sizeof(struct btrfs_stripe) + 1)
-
 static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
                               u64 start, u64 type)
 {
@@ -5038,7 +5030,7 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
        } else {
                btrfs_err(info, "invalid chunk type 0x%llx requested",
                       type);
-               BUG_ON(1);
+               BUG();
        }
 
        /* We don't want a chunk larger than 10% of writable space */
@@ -6714,99 +6706,6 @@ struct btrfs_device *btrfs_alloc_device(struct btrfs_fs_info *fs_info,
        return dev;
 }
 
-/* Return -EIO if any error, otherwise return 0. */
-static int btrfs_check_chunk_valid(struct btrfs_fs_info *fs_info,
-                                  struct extent_buffer *leaf,
-                                  struct btrfs_chunk *chunk, u64 logical)
-{
-       u64 length;
-       u64 stripe_len;
-       u16 num_stripes;
-       u16 sub_stripes;
-       u64 type;
-       u64 features;
-       bool mixed = false;
-
-       length = btrfs_chunk_length(leaf, chunk);
-       stripe_len = btrfs_chunk_stripe_len(leaf, chunk);
-       num_stripes = btrfs_chunk_num_stripes(leaf, chunk);
-       sub_stripes = btrfs_chunk_sub_stripes(leaf, chunk);
-       type = btrfs_chunk_type(leaf, chunk);
-
-       if (!num_stripes) {
-               btrfs_err(fs_info, "invalid chunk num_stripes: %u",
-                         num_stripes);
-               return -EIO;
-       }
-       if (!IS_ALIGNED(logical, fs_info->sectorsize)) {
-               btrfs_err(fs_info, "invalid chunk logical %llu", logical);
-               return -EIO;
-       }
-       if (btrfs_chunk_sector_size(leaf, chunk) != fs_info->sectorsize) {
-               btrfs_err(fs_info, "invalid chunk sectorsize %u",
-                         btrfs_chunk_sector_size(leaf, chunk));
-               return -EIO;
-       }
-       if (!length || !IS_ALIGNED(length, fs_info->sectorsize)) {
-               btrfs_err(fs_info, "invalid chunk length %llu", length);
-               return -EIO;
-       }
-       if (!is_power_of_2(stripe_len) || stripe_len != BTRFS_STRIPE_LEN) {
-               btrfs_err(fs_info, "invalid chunk stripe length: %llu",
-                         stripe_len);
-               return -EIO;
-       }
-       if (~(BTRFS_BLOCK_GROUP_TYPE_MASK | BTRFS_BLOCK_GROUP_PROFILE_MASK) &
-           type) {
-               btrfs_err(fs_info, "unrecognized chunk type: %llu",
-                         ~(BTRFS_BLOCK_GROUP_TYPE_MASK |
-                           BTRFS_BLOCK_GROUP_PROFILE_MASK) &
-                         btrfs_chunk_type(leaf, chunk));
-               return -EIO;
-       }
-
-       if ((type & BTRFS_BLOCK_GROUP_TYPE_MASK) == 0) {
-               btrfs_err(fs_info, "missing chunk type flag: 0x%llx", type);
-               return -EIO;
-       }
-
-       if ((type & BTRFS_BLOCK_GROUP_SYSTEM) &&
-           (type & (BTRFS_BLOCK_GROUP_METADATA | BTRFS_BLOCK_GROUP_DATA))) {
-               btrfs_err(fs_info,
-                       "system chunk with data or metadata type: 0x%llx", type);
-               return -EIO;
-       }
-
-       features = btrfs_super_incompat_flags(fs_info->super_copy);
-       if (features & BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS)
-               mixed = true;
-
-       if (!mixed) {
-               if ((type & BTRFS_BLOCK_GROUP_METADATA) &&
-                   (type & BTRFS_BLOCK_GROUP_DATA)) {
-                       btrfs_err(fs_info,
-                       "mixed chunk type in non-mixed mode: 0x%llx", type);
-                       return -EIO;
-               }
-       }
-
-       if ((type & BTRFS_BLOCK_GROUP_RAID10 && sub_stripes != 2) ||
-           (type & BTRFS_BLOCK_GROUP_RAID1 && num_stripes != 2) ||
-           (type & BTRFS_BLOCK_GROUP_RAID5 && num_stripes < 2) ||
-           (type & BTRFS_BLOCK_GROUP_RAID6 && num_stripes < 3) ||
-           (type & BTRFS_BLOCK_GROUP_DUP && num_stripes != 2) ||
-           ((type & BTRFS_BLOCK_GROUP_PROFILE_MASK) == 0 &&
-            num_stripes != 1)) {
-               btrfs_err(fs_info,
-                       "invalid num_stripes:sub_stripes %u:%u for profile %llu",
-                       num_stripes, sub_stripes,
-                       type & BTRFS_BLOCK_GROUP_PROFILE_MASK);
-               return -EIO;
-       }
-
-       return 0;
-}
-
 static void btrfs_report_missing_device(struct btrfs_fs_info *fs_info,
                                        u64 devid, u8 *uuid, bool error)
 {
@@ -6837,9 +6736,15 @@ static int read_one_chunk(struct btrfs_fs_info *fs_info, struct btrfs_key *key,
        length = btrfs_chunk_length(leaf, chunk);
        num_stripes = btrfs_chunk_num_stripes(leaf, chunk);
 
-       ret = btrfs_check_chunk_valid(fs_info, leaf, chunk, logical);
-       if (ret)
-               return ret;
+       /*
+        * Only need to verify chunk item if we're reading from sys chunk array,
+        * as chunk item in tree block is already verified by tree-checker.
+        */
+       if (leaf->start == BTRFS_SUPER_INFO_OFFSET) {
+               ret = btrfs_check_chunk_valid(fs_info, leaf, chunk, logical);
+               if (ret)
+                       return ret;
+       }
 
        read_lock(&map_tree->map_tree.lock);
        em = lookup_extent_mapping(&map_tree->map_tree, logical, 1);