Merge tag 'for-5.19-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux
[linux-2.6-microblaze.git] / fs / btrfs / volumes.c
index b6b0033..9c20049 100644 (file)
@@ -164,24 +164,12 @@ const struct btrfs_raid_attr btrfs_raid_array[BTRFS_NR_RAID_TYPES] = {
  */
 enum btrfs_raid_types __attribute_const__ btrfs_bg_flags_to_raid_index(u64 flags)
 {
-       if (flags & BTRFS_BLOCK_GROUP_RAID10)
-               return BTRFS_RAID_RAID10;
-       else if (flags & BTRFS_BLOCK_GROUP_RAID1)
-               return BTRFS_RAID_RAID1;
-       else if (flags & BTRFS_BLOCK_GROUP_RAID1C3)
-               return BTRFS_RAID_RAID1C3;
-       else if (flags & BTRFS_BLOCK_GROUP_RAID1C4)
-               return BTRFS_RAID_RAID1C4;
-       else if (flags & BTRFS_BLOCK_GROUP_DUP)
-               return BTRFS_RAID_DUP;
-       else if (flags & BTRFS_BLOCK_GROUP_RAID0)
-               return BTRFS_RAID_RAID0;
-       else if (flags & BTRFS_BLOCK_GROUP_RAID5)
-               return BTRFS_RAID_RAID5;
-       else if (flags & BTRFS_BLOCK_GROUP_RAID6)
-               return BTRFS_RAID_RAID6;
-
-       return BTRFS_RAID_SINGLE; /* BTRFS_BLOCK_GROUP_SINGLE */
+       const u64 profile = (flags & BTRFS_BLOCK_GROUP_PROFILE_MASK);
+
+       if (!profile)
+               return BTRFS_RAID_SINGLE;
+
+       return BTRFS_BG_FLAG_TO_INDEX(profile);
 }
 
 const char *btrfs_bg_type_to_raid_name(u64 flags)
@@ -4062,13 +4050,6 @@ static inline int validate_convert_profile(struct btrfs_fs_info *fs_info,
        if (!(bargs->flags & BTRFS_BALANCE_ARGS_CONVERT))
                return true;
 
-       if (fs_info->sectorsize < PAGE_SIZE &&
-               bargs->target & BTRFS_BLOCK_GROUP_RAID56_MASK) {
-               btrfs_err(fs_info,
-               "RAID56 is not yet supported for sectorsize %u with page size %lu",
-                         fs_info->sectorsize, PAGE_SIZE);
-               return false;
-       }
        /* Profile is valid and does not have bits outside of the allowed set */
        if (alloc_profile_is_valid(bargs->target, 1) &&
            (bargs->target & ~allowed) == 0)
@@ -6312,7 +6293,7 @@ int btrfs_get_io_geometry(struct btrfs_fs_info *fs_info, struct extent_map *em,
        u64 offset;
        u64 stripe_offset;
        u64 stripe_nr;
-       u64 stripe_len;
+       u32 stripe_len;
        u64 raid56_full_stripe_start = (u64)-1;
        int data_stripes;
 
@@ -6323,19 +6304,13 @@ int btrfs_get_io_geometry(struct btrfs_fs_info *fs_info, struct extent_map *em,
        offset = logical - em->start;
        /* Len of a stripe in a chunk */
        stripe_len = map->stripe_len;
-       /* Stripe where this block falls in */
-       stripe_nr = div64_u64(offset, stripe_len);
-       /* Offset of stripe in the chunk */
-       stripe_offset = stripe_nr * stripe_len;
-       if (offset < stripe_offset) {
-               btrfs_crit(fs_info,
-"stripe math has gone wrong, stripe_offset=%llu offset=%llu start=%llu logical=%llu stripe_len=%llu",
-                       stripe_offset, offset, em->start, logical, stripe_len);
-               return -EINVAL;
-       }
+       /*
+        * Stripe_nr is where this block falls in
+        * stripe_offset is the offset of this block in its stripe.
+        */
+       stripe_nr = div64_u64_rem(offset, stripe_len, &stripe_offset);
+       ASSERT(stripe_offset < U32_MAX);
 
-       /* stripe_offset is the offset of this block in its stripe */
-       stripe_offset = offset - stripe_offset;
        data_stripes = nr_data_stripes(map);
 
        /* Only stripe based profiles needs to check against stripe length. */
@@ -6737,11 +6712,11 @@ static void submit_stripe_bio(struct btrfs_io_context *bioc, struct bio *bio,
                bio_op(bio), bio->bi_opf, bio->bi_iter.bi_sector,
                (unsigned long)dev->bdev->bd_dev, rcu_str_deref(dev->name),
                dev->devid, bio->bi_iter.bi_size);
-       bio_set_dev(bio, dev->bdev);
 
        btrfs_bio_counter_inc_noblocked(fs_info);
 
-       btrfsic_submit_bio(bio);
+       btrfsic_check_bio(bio);
+       submit_bio(bio);
 }
 
 static void bioc_error(struct btrfs_io_context *bioc, struct bio *bio, u64 logical)
@@ -6823,10 +6798,12 @@ blk_status_t btrfs_map_bio(struct btrfs_fs_info *fs_info, struct bio *bio,
                        continue;
                }
 
-               if (dev_nr < total_devs - 1)
-                       bio = btrfs_bio_clone(first_bio);
-               else
+               if (dev_nr < total_devs - 1) {
+                       bio = btrfs_bio_clone(dev->bdev, first_bio);
+               } else {
                        bio = first_bio;
+                       bio_set_dev(bio, dev->bdev);
+               }
 
                submit_stripe_bio(bioc, bio, bioc->stripes[dev_nr].physical, dev);
        }
@@ -7359,7 +7336,6 @@ static int read_one_dev(struct extent_buffer *leaf,
 
 int btrfs_read_sys_array(struct btrfs_fs_info *fs_info)
 {
-       struct btrfs_root *root = fs_info->tree_root;
        struct btrfs_super_block *super_copy = fs_info->super_copy;
        struct extent_buffer *sb;
        struct btrfs_disk_key *disk_key;
@@ -7375,30 +7351,16 @@ int btrfs_read_sys_array(struct btrfs_fs_info *fs_info)
        struct btrfs_key key;
 
        ASSERT(BTRFS_SUPER_INFO_SIZE <= fs_info->nodesize);
+
        /*
-        * This will create extent buffer of nodesize, superblock size is
-        * fixed to BTRFS_SUPER_INFO_SIZE. If nodesize > sb size, this will
-        * overallocate but we can keep it as-is, only the first page is used.
+        * We allocated a dummy extent, just to use extent buffer accessors.
+        * There will be unused space after BTRFS_SUPER_INFO_SIZE, but
+        * that's fine, we will not go beyond system chunk array anyway.
         */
-       sb = btrfs_find_create_tree_block(fs_info, BTRFS_SUPER_INFO_OFFSET,
-                                         root->root_key.objectid, 0);
-       if (IS_ERR(sb))
-               return PTR_ERR(sb);
+       sb = alloc_dummy_extent_buffer(fs_info, BTRFS_SUPER_INFO_OFFSET);
+       if (!sb)
+               return -ENOMEM;
        set_extent_buffer_uptodate(sb);
-       /*
-        * The sb extent buffer is artificial and just used to read the system array.
-        * set_extent_buffer_uptodate() call does not properly mark all it's
-        * pages up-to-date when the page is larger: extent does not cover the
-        * whole page and consequently check_page_uptodate does not find all
-        * the page's extents up-to-date (the hole beyond sb),
-        * write_extent_buffer then triggers a WARN_ON.
-        *
-        * Regular short extents go through mark_extent_buffer_dirty/writeback cycle,
-        * but sb spans only this function. Add an explicit SetPageUptodate call
-        * to silence the warning eg. on PowerPC 64.
-        */
-       if (PAGE_SIZE > BTRFS_SUPER_INFO_SIZE)
-               SetPageUptodate(sb->pages[0]);
 
        write_extent_buffer(sb, super_copy, 0, BTRFS_SUPER_INFO_SIZE);
        array_size = btrfs_super_sys_array_size(super_copy);
@@ -7561,6 +7523,7 @@ int btrfs_read_chunk_tree(struct btrfs_fs_info *fs_info)
        struct btrfs_key found_key;
        int ret;
        int slot;
+       int iter_ret = 0;
        u64 total_dev = 0;
        u64 last_ra_node = 0;
 
@@ -7604,30 +7567,18 @@ int btrfs_read_chunk_tree(struct btrfs_fs_info *fs_info)
        key.objectid = BTRFS_DEV_ITEMS_OBJECTID;
        key.offset = 0;
        key.type = 0;
-       ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
-       if (ret < 0)
-               goto error;
-       while (1) {
-               struct extent_buffer *node;
+       btrfs_for_each_slot(root, &key, &found_key, path, iter_ret) {
+               struct extent_buffer *node = path->nodes[1];
 
                leaf = path->nodes[0];
                slot = path->slots[0];
-               if (slot >= btrfs_header_nritems(leaf)) {
-                       ret = btrfs_next_leaf(root, path);
-                       if (ret == 0)
-                               continue;
-                       if (ret < 0)
-                               goto error;
-                       break;
-               }
-               node = path->nodes[1];
+
                if (node) {
                        if (last_ra_node != node->start) {
                                readahead_tree_node_children(node);
                                last_ra_node = node->start;
                        }
                }
-               btrfs_item_key_to_cpu(leaf, &found_key, slot);
                if (found_key.type == BTRFS_DEV_ITEM_KEY) {
                        struct btrfs_dev_item *dev_item;
                        dev_item = btrfs_item_ptr(leaf, slot,
@@ -7652,7 +7603,11 @@ int btrfs_read_chunk_tree(struct btrfs_fs_info *fs_info)
                        if (ret)
                                goto error;
                }
-               path->slots[0]++;
+       }
+       /* Catch error found during iteration */
+       if (iter_ret < 0) {
+               ret = iter_ret;
+               goto error;
        }
 
        /*
@@ -7660,12 +7615,12 @@ int btrfs_read_chunk_tree(struct btrfs_fs_info *fs_info)
         * do another round of validation checks.
         */
        if (total_dev != fs_info->fs_devices->total_devices) {
-               btrfs_err(fs_info,
-          "super_num_devices %llu mismatch with num_devices %llu found here",
+               btrfs_warn(fs_info,
+"super block num_devices %llu mismatch with DEV_ITEM count %llu, will be repaired on next transaction commit",
                          btrfs_super_num_devices(fs_info->super_copy),
                          total_dev);
-               ret = -EINVAL;
-               goto error;
+               fs_info->fs_devices->total_devices = total_dev;
+               btrfs_set_super_num_devices(fs_info->super_copy, total_dev);
        }
        if (btrfs_super_total_bytes(fs_info->super_copy) <
            fs_info->fs_devices->total_rw_bytes) {
@@ -8277,7 +8232,7 @@ bool btrfs_pinned_by_swapfile(struct btrfs_fs_info *fs_info, void *ptr)
 
 static int relocating_repair_kthread(void *data)
 {
-       struct btrfs_block_group *cache = (struct btrfs_block_group *)data;
+       struct btrfs_block_group *cache = data;
        struct btrfs_fs_info *fs_info = cache->fs_info;
        u64 target;
        int ret = 0;