Merge tag 'for-6.2-rc2-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave...
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 6 Jan 2023 20:01:49 +0000 (12:01 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 6 Jan 2023 20:01:49 +0000 (12:01 -0800)
Pull btrfs fixes from David Sterba:
 "A few more regression and regular fixes:

   - regressions:
       - fix assertion condition using = instead of ==
       - fix false alert on bad tree level check
       - fix off-by-one error in delalloc search during lseek

   - fix compat ro feature check at read-write remount

   - handle case when read-repair happens with ongoing device replace

   - updated error messages"

* tag 'for-6.2-rc2-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux:
  btrfs: fix compat_ro checks against remount
  btrfs: always report error in run_one_delayed_ref()
  btrfs: handle case when repair happens with dev-replace
  btrfs: fix off-by-one in delalloc search during lseek
  btrfs: fix false alert on bad tree level check
  btrfs: add error message for metadata level mismatch
  btrfs: fix ASSERT em->len condition in btrfs_get_extent

fs/btrfs/bio.c
fs/btrfs/disk-io.c
fs/btrfs/disk-io.h
fs/btrfs/extent-io-tree.c
fs/btrfs/extent-tree.c
fs/btrfs/extent_io.c
fs/btrfs/file.c
fs/btrfs/inode.c
fs/btrfs/super.c

index b8fb7ef..8affc88 100644 (file)
@@ -329,7 +329,16 @@ int btrfs_repair_io_failure(struct btrfs_fs_info *fs_info, u64 ino, u64 start,
                                      &map_length, &bioc, mirror_num);
                if (ret)
                        goto out_counter_dec;
-               BUG_ON(mirror_num != bioc->mirror_num);
+               /*
+                * This happens when dev-replace is also running, and the
+                * mirror_num indicates the dev-replace target.
+                *
+                * In this case, we don't need to do anything, as the read
+                * error just means the replace progress hasn't reached our
+                * read range, and later replace routine would handle it well.
+                */
+               if (mirror_num != bioc->mirror_num)
+                       goto out_counter_dec;
        }
 
        sector = bioc->stripes[bioc->mirror_num - 1].physical >> 9;
index 0888d48..8aeaada 100644 (file)
@@ -530,6 +530,9 @@ static int validate_extent_buffer(struct extent_buffer *eb,
        }
 
        if (found_level != check->level) {
+               btrfs_err(fs_info,
+               "level verify failed on logical %llu mirror %u wanted %u found %u",
+                         eb->start, eb->read_mirror, check->level, found_level);
                ret = -EIO;
                goto out;
        }
@@ -3381,6 +3384,8 @@ out:
 /*
  * Do various sanity and dependency checks of different features.
  *
+ * @is_rw_mount:       If the mount is read-write.
+ *
  * This is the place for less strict checks (like for subpage or artificial
  * feature dependencies).
  *
@@ -3391,7 +3396,7 @@ out:
  * (space cache related) can modify on-disk format like free space tree and
  * screw up certain feature dependencies.
  */
-int btrfs_check_features(struct btrfs_fs_info *fs_info, struct super_block *sb)
+int btrfs_check_features(struct btrfs_fs_info *fs_info, bool is_rw_mount)
 {
        struct btrfs_super_block *disk_super = fs_info->super_copy;
        u64 incompat = btrfs_super_incompat_flags(disk_super);
@@ -3430,7 +3435,7 @@ int btrfs_check_features(struct btrfs_fs_info *fs_info, struct super_block *sb)
        if (btrfs_super_nodesize(disk_super) > PAGE_SIZE)
                incompat |= BTRFS_FEATURE_INCOMPAT_BIG_METADATA;
 
-       if (compat_ro_unsupp && !sb_rdonly(sb)) {
+       if (compat_ro_unsupp && is_rw_mount) {
                btrfs_err(fs_info,
        "cannot mount read-write because of unknown compat_ro features (0x%llx)",
                       compat_ro);
@@ -3633,7 +3638,7 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device
                goto fail_alloc;
        }
 
-       ret = btrfs_check_features(fs_info, sb);
+       ret = btrfs_check_features(fs_info, !sb_rdonly(sb));
        if (ret < 0) {
                err = ret;
                goto fail_alloc;
index 363935c..f2f295e 100644 (file)
@@ -50,7 +50,7 @@ int __cold open_ctree(struct super_block *sb,
 void __cold close_ctree(struct btrfs_fs_info *fs_info);
 int btrfs_validate_super(struct btrfs_fs_info *fs_info,
                         struct btrfs_super_block *sb, int mirror_num);
-int btrfs_check_features(struct btrfs_fs_info *fs_info, struct super_block *sb);
+int btrfs_check_features(struct btrfs_fs_info *fs_info, bool is_rw_mount);
 int write_all_supers(struct btrfs_fs_info *fs_info, int max_mirrors);
 struct btrfs_super_block *btrfs_read_dev_super(struct block_device *bdev);
 struct btrfs_super_block *btrfs_read_dev_one_super(struct block_device *bdev,
index 9ae9cd1..3c7766d 100644 (file)
@@ -1551,7 +1551,7 @@ u64 count_range_bits(struct extent_io_tree *tree,
        u64 last = 0;
        int found = 0;
 
-       if (WARN_ON(search_end <= cur_start))
+       if (WARN_ON(search_end < cur_start))
                return 0;
 
        spin_lock(&tree->lock);
index 892d78c..72ba13b 100644 (file)
@@ -1713,6 +1713,11 @@ static int run_one_delayed_ref(struct btrfs_trans_handle *trans,
                BUG();
        if (ret && insert_reserved)
                btrfs_pin_extent(trans, node->bytenr, node->num_bytes, 1);
+       if (ret < 0)
+               btrfs_err(trans->fs_info,
+"failed to run delayed ref for logical %llu num_bytes %llu type %u action %u ref_mod %d: %d",
+                         node->bytenr, node->num_bytes, node->type,
+                         node->action, node->ref_mod, ret);
        return ret;
 }
 
@@ -1954,8 +1959,6 @@ static int btrfs_run_delayed_refs_for_head(struct btrfs_trans_handle *trans,
                if (ret) {
                        unselect_delayed_ref_head(delayed_refs, locked_ref);
                        btrfs_put_delayed_ref(ref);
-                       btrfs_debug(fs_info, "run_one_delayed_ref returned %d",
-                                   ret);
                        return ret;
                }
 
index 83dd3aa..9bd32da 100644 (file)
@@ -103,6 +103,15 @@ struct btrfs_bio_ctrl {
        u32 len_to_oe_boundary;
        btrfs_bio_end_io_t end_io_func;
 
+       /*
+        * This is for metadata read, to provide the extra needed verification
+        * info.  This has to be provided for submit_one_bio(), as
+        * submit_one_bio() can submit a bio if it ends at stripe boundary.  If
+        * no such parent_check is provided, the metadata can hit false alert at
+        * endio time.
+        */
+       struct btrfs_tree_parent_check *parent_check;
+
        /*
         * Tell writepage not to lock the state bits for this range, it still
         * does the unlocking.
@@ -133,13 +142,24 @@ static void submit_one_bio(struct btrfs_bio_ctrl *bio_ctrl)
 
        btrfs_bio(bio)->file_offset = page_offset(bv->bv_page) + bv->bv_offset;
 
-       if (!is_data_inode(&inode->vfs_inode))
+       if (!is_data_inode(&inode->vfs_inode)) {
+               if (btrfs_op(bio) != BTRFS_MAP_WRITE) {
+                       /*
+                        * For metadata read, we should have the parent_check,
+                        * and copy it to bbio for metadata verification.
+                        */
+                       ASSERT(bio_ctrl->parent_check);
+                       memcpy(&btrfs_bio(bio)->parent_check,
+                              bio_ctrl->parent_check,
+                              sizeof(struct btrfs_tree_parent_check));
+               }
                btrfs_submit_metadata_bio(inode, bio, mirror_num);
-       else if (btrfs_op(bio) == BTRFS_MAP_WRITE)
+       } else if (btrfs_op(bio) == BTRFS_MAP_WRITE) {
                btrfs_submit_data_write_bio(inode, bio, mirror_num);
-       else
+       } else {
                btrfs_submit_data_read_bio(inode, bio, mirror_num,
                                           bio_ctrl->compress_type);
+       }
 
        /* The bio is owned by the end_io handler now */
        bio_ctrl->bio = NULL;
@@ -4829,6 +4849,7 @@ static int read_extent_buffer_subpage(struct extent_buffer *eb, int wait,
        struct extent_state *cached_state = NULL;
        struct btrfs_bio_ctrl bio_ctrl = {
                .mirror_num = mirror_num,
+               .parent_check = check,
        };
        int ret = 0;
 
@@ -4878,7 +4899,6 @@ static int read_extent_buffer_subpage(struct extent_buffer *eb, int wait,
                 */
                atomic_dec(&eb->io_pages);
        }
-       memcpy(&btrfs_bio(bio_ctrl.bio)->parent_check, check, sizeof(*check));
        submit_one_bio(&bio_ctrl);
        if (ret || wait != WAIT_COMPLETE) {
                free_extent_state(cached_state);
@@ -4905,6 +4925,7 @@ int read_extent_buffer_pages(struct extent_buffer *eb, int wait, int mirror_num,
        unsigned long num_reads = 0;
        struct btrfs_bio_ctrl bio_ctrl = {
                .mirror_num = mirror_num,
+               .parent_check = check,
        };
 
        if (test_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags))
@@ -4996,7 +5017,6 @@ int read_extent_buffer_pages(struct extent_buffer *eb, int wait, int mirror_num,
                }
        }
 
-       memcpy(&btrfs_bio(bio_ctrl.bio)->parent_check, check, sizeof(*check));
        submit_one_bio(&bio_ctrl);
 
        if (ret || wait != WAIT_COMPLETE)
index 91b00eb..834bbcb 100644 (file)
@@ -3354,7 +3354,7 @@ bool btrfs_find_delalloc_in_range(struct btrfs_inode *inode, u64 start, u64 end,
        bool search_io_tree = true;
        bool ret = false;
 
-       while (cur_offset < end) {
+       while (cur_offset <= end) {
                u64 delalloc_start;
                u64 delalloc_end;
                bool delalloc;
index 2ead7b1..98a800b 100644 (file)
@@ -7092,7 +7092,7 @@ next:
                 * Other members are not utilized for inline extents.
                 */
                ASSERT(em->block_start == EXTENT_MAP_INLINE);
-               ASSERT(em->len = fs_info->sectorsize);
+               ASSERT(em->len == fs_info->sectorsize);
 
                ret = read_inline_extent(inode, path, page);
                if (ret < 0)
index d5de18d..433ce22 100644 (file)
@@ -1705,7 +1705,7 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data)
        if (ret)
                goto restore;
 
-       ret = btrfs_check_features(fs_info, sb);
+       ret = btrfs_check_features(fs_info, !(*flags & SB_RDONLY));
        if (ret < 0)
                goto restore;