Commit fc7b76c4 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'for-6.2-rc2-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux

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
parents a389e546 2ba48b20
...@@ -329,7 +329,16 @@ int btrfs_repair_io_failure(struct btrfs_fs_info *fs_info, u64 ino, u64 start, ...@@ -329,7 +329,16 @@ int btrfs_repair_io_failure(struct btrfs_fs_info *fs_info, u64 ino, u64 start,
&map_length, &bioc, mirror_num); &map_length, &bioc, mirror_num);
if (ret) if (ret)
goto out_counter_dec; 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; sector = bioc->stripes[bioc->mirror_num - 1].physical >> 9;
......
...@@ -530,6 +530,9 @@ static int validate_extent_buffer(struct extent_buffer *eb, ...@@ -530,6 +530,9 @@ static int validate_extent_buffer(struct extent_buffer *eb,
} }
if (found_level != check->level) { 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; ret = -EIO;
goto out; goto out;
} }
...@@ -3381,6 +3384,8 @@ int btrfs_start_pre_rw_mount(struct btrfs_fs_info *fs_info) ...@@ -3381,6 +3384,8 @@ int btrfs_start_pre_rw_mount(struct btrfs_fs_info *fs_info)
/* /*
* Do various sanity and dependency checks of different features. * 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 * This is the place for less strict checks (like for subpage or artificial
* feature dependencies). * feature dependencies).
* *
...@@ -3391,7 +3396,7 @@ int btrfs_start_pre_rw_mount(struct btrfs_fs_info *fs_info) ...@@ -3391,7 +3396,7 @@ int btrfs_start_pre_rw_mount(struct btrfs_fs_info *fs_info)
* (space cache related) can modify on-disk format like free space tree and * (space cache related) can modify on-disk format like free space tree and
* screw up certain feature dependencies. * 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; struct btrfs_super_block *disk_super = fs_info->super_copy;
u64 incompat = btrfs_super_incompat_flags(disk_super); 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) ...@@ -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) if (btrfs_super_nodesize(disk_super) > PAGE_SIZE)
incompat |= BTRFS_FEATURE_INCOMPAT_BIG_METADATA; incompat |= BTRFS_FEATURE_INCOMPAT_BIG_METADATA;
if (compat_ro_unsupp && !sb_rdonly(sb)) { if (compat_ro_unsupp && is_rw_mount) {
btrfs_err(fs_info, btrfs_err(fs_info,
"cannot mount read-write because of unknown compat_ro features (0x%llx)", "cannot mount read-write because of unknown compat_ro features (0x%llx)",
compat_ro); compat_ro);
...@@ -3633,7 +3638,7 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device ...@@ -3633,7 +3638,7 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device
goto fail_alloc; goto fail_alloc;
} }
ret = btrfs_check_features(fs_info, sb); ret = btrfs_check_features(fs_info, !sb_rdonly(sb));
if (ret < 0) { if (ret < 0) {
err = ret; err = ret;
goto fail_alloc; goto fail_alloc;
......
...@@ -50,7 +50,7 @@ int __cold open_ctree(struct super_block *sb, ...@@ -50,7 +50,7 @@ int __cold open_ctree(struct super_block *sb,
void __cold close_ctree(struct btrfs_fs_info *fs_info); void __cold close_ctree(struct btrfs_fs_info *fs_info);
int btrfs_validate_super(struct btrfs_fs_info *fs_info, int btrfs_validate_super(struct btrfs_fs_info *fs_info,
struct btrfs_super_block *sb, int mirror_num); 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); 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_super(struct block_device *bdev);
struct btrfs_super_block *btrfs_read_dev_one_super(struct block_device *bdev, struct btrfs_super_block *btrfs_read_dev_one_super(struct block_device *bdev,
......
...@@ -1551,7 +1551,7 @@ u64 count_range_bits(struct extent_io_tree *tree, ...@@ -1551,7 +1551,7 @@ u64 count_range_bits(struct extent_io_tree *tree,
u64 last = 0; u64 last = 0;
int found = 0; int found = 0;
if (WARN_ON(search_end <= cur_start)) if (WARN_ON(search_end < cur_start))
return 0; return 0;
spin_lock(&tree->lock); spin_lock(&tree->lock);
......
...@@ -1713,6 +1713,11 @@ static int run_one_delayed_ref(struct btrfs_trans_handle *trans, ...@@ -1713,6 +1713,11 @@ static int run_one_delayed_ref(struct btrfs_trans_handle *trans,
BUG(); BUG();
if (ret && insert_reserved) if (ret && insert_reserved)
btrfs_pin_extent(trans, node->bytenr, node->num_bytes, 1); 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; return ret;
} }
...@@ -1954,8 +1959,6 @@ static int btrfs_run_delayed_refs_for_head(struct btrfs_trans_handle *trans, ...@@ -1954,8 +1959,6 @@ static int btrfs_run_delayed_refs_for_head(struct btrfs_trans_handle *trans,
if (ret) { if (ret) {
unselect_delayed_ref_head(delayed_refs, locked_ref); unselect_delayed_ref_head(delayed_refs, locked_ref);
btrfs_put_delayed_ref(ref); btrfs_put_delayed_ref(ref);
btrfs_debug(fs_info, "run_one_delayed_ref returned %d",
ret);
return ret; return ret;
} }
......
...@@ -103,6 +103,15 @@ struct btrfs_bio_ctrl { ...@@ -103,6 +103,15 @@ struct btrfs_bio_ctrl {
u32 len_to_oe_boundary; u32 len_to_oe_boundary;
btrfs_bio_end_io_t end_io_func; 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 * Tell writepage not to lock the state bits for this range, it still
* does the unlocking. * does the unlocking.
...@@ -133,13 +142,24 @@ static void submit_one_bio(struct btrfs_bio_ctrl *bio_ctrl) ...@@ -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; 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); 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); btrfs_submit_data_write_bio(inode, bio, mirror_num);
else } else {
btrfs_submit_data_read_bio(inode, bio, mirror_num, btrfs_submit_data_read_bio(inode, bio, mirror_num,
bio_ctrl->compress_type); bio_ctrl->compress_type);
}
/* The bio is owned by the end_io handler now */ /* The bio is owned by the end_io handler now */
bio_ctrl->bio = NULL; bio_ctrl->bio = NULL;
...@@ -4829,6 +4849,7 @@ static int read_extent_buffer_subpage(struct extent_buffer *eb, int wait, ...@@ -4829,6 +4849,7 @@ static int read_extent_buffer_subpage(struct extent_buffer *eb, int wait,
struct extent_state *cached_state = NULL; struct extent_state *cached_state = NULL;
struct btrfs_bio_ctrl bio_ctrl = { struct btrfs_bio_ctrl bio_ctrl = {
.mirror_num = mirror_num, .mirror_num = mirror_num,
.parent_check = check,
}; };
int ret = 0; int ret = 0;
...@@ -4878,7 +4899,6 @@ static int read_extent_buffer_subpage(struct extent_buffer *eb, int wait, ...@@ -4878,7 +4899,6 @@ static int read_extent_buffer_subpage(struct extent_buffer *eb, int wait,
*/ */
atomic_dec(&eb->io_pages); atomic_dec(&eb->io_pages);
} }
memcpy(&btrfs_bio(bio_ctrl.bio)->parent_check, check, sizeof(*check));
submit_one_bio(&bio_ctrl); submit_one_bio(&bio_ctrl);
if (ret || wait != WAIT_COMPLETE) { if (ret || wait != WAIT_COMPLETE) {
free_extent_state(cached_state); free_extent_state(cached_state);
...@@ -4905,6 +4925,7 @@ int read_extent_buffer_pages(struct extent_buffer *eb, int wait, int mirror_num, ...@@ -4905,6 +4925,7 @@ int read_extent_buffer_pages(struct extent_buffer *eb, int wait, int mirror_num,
unsigned long num_reads = 0; unsigned long num_reads = 0;
struct btrfs_bio_ctrl bio_ctrl = { struct btrfs_bio_ctrl bio_ctrl = {
.mirror_num = mirror_num, .mirror_num = mirror_num,
.parent_check = check,
}; };
if (test_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags)) 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, ...@@ -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); submit_one_bio(&bio_ctrl);
if (ret || wait != WAIT_COMPLETE) if (ret || wait != WAIT_COMPLETE)
......
...@@ -3354,7 +3354,7 @@ bool btrfs_find_delalloc_in_range(struct btrfs_inode *inode, u64 start, u64 end, ...@@ -3354,7 +3354,7 @@ bool btrfs_find_delalloc_in_range(struct btrfs_inode *inode, u64 start, u64 end,
bool search_io_tree = true; bool search_io_tree = true;
bool ret = false; bool ret = false;
while (cur_offset < end) { while (cur_offset <= end) {
u64 delalloc_start; u64 delalloc_start;
u64 delalloc_end; u64 delalloc_end;
bool delalloc; bool delalloc;
......
...@@ -7092,7 +7092,7 @@ struct extent_map *btrfs_get_extent(struct btrfs_inode *inode, ...@@ -7092,7 +7092,7 @@ struct extent_map *btrfs_get_extent(struct btrfs_inode *inode,
* Other members are not utilized for inline extents. * Other members are not utilized for inline extents.
*/ */
ASSERT(em->block_start == EXTENT_MAP_INLINE); 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); ret = read_inline_extent(inode, path, page);
if (ret < 0) if (ret < 0)
......
...@@ -1705,7 +1705,7 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data) ...@@ -1705,7 +1705,7 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data)
if (ret) if (ret)
goto restore; goto restore;
ret = btrfs_check_features(fs_info, sb); ret = btrfs_check_features(fs_info, !(*flags & SB_RDONLY));
if (ret < 0) if (ret < 0)
goto restore; goto restore;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment