mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-12-28 00:35:01 +00:00
for-6.13-rc3-tag
-----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEE8rQSAMVO+zA4DBdWxWXV+ddtWDsFAmdhyQAACgkQxWXV+ddt WDuveg//bJSuXHrA7jkijst8rdoAFrceiUXuQPZ6bqb9QrSqlDZlP5/XQpdXZ3yU qJh/aE13cy0zWTQ2+fMcc770WSvU1cRW/f5BZ+fdXgvO8lS516suXGYd2Q06Cl9/ DriAKGKtRfJn1BrEEv8+fjKS/chxZg6IR/W4kN6AinW31myY9jE5mEDAn+vyTDgQ 8USZ/ar/3KuWo+wO5h5JzrvGnhzK0W0HRs/A0NZ3gG8J5T4yj+8zG0VJR4Gf93AL iBlsnAR8VzAYJOZCi36SD3j3/eDxJio5GhDYsdt28tk1bL8FqSuI4Yxt+LuiZ2Fg Cq/31lELEkyEH8AoVFm9pX3HNyRmV6JhpvDXiyofHaOUZ3VeivVE59gOShLUUMkn f9Pl/uh5/t/ioWWHBnCMyRpI9GZUGCvW24k7HjT7QZhsDGFLTm07diCiRgZ7eaOu LZRKMOL5jifAnfxNSvIJV19H4lQLTZfbdjmJyb6Il39tIU/1U9pXicgih3iyidW2 N5n4pHf3OQFwG8kNw1mR1g1CPBALP62ja8kMv//IgH4YXXnm1Mo7B3CcJogAAmo4 HB9f/gFqZ8kWaiuIUJKfPZkkLFt5x0TNZQyyOhVUd7V4mFdtEzVtZRWo3juYuLGk 7Shp/MTlYokwnEropiWHU5ab3Bb9vLxlh8daGK/OmwBz01DaApI= =AAmb -----END PGP SIGNATURE----- Merge tag 'for-6.13-rc3-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux Pull btrfs fixes from David Sterba: - tree-checker catches invalid number of inline extent references - zoned mode fixes: - enhance zone append IO command so it also detects emulated writes - handle bio splitting at sectorsize boundary - when deleting a snapshot, fix a condition for visiting nodes in reloc trees * tag 'for-6.13-rc3-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux: btrfs: tree-checker: reject inline extent items with 0 ref count btrfs: split bios to the fs sector size boundary btrfs: use bio_is_zone_append() in the completion handler btrfs: fix improper generation check in snapshot delete
This commit is contained in:
commit
eabcdba3ad
@ -358,7 +358,7 @@ static void btrfs_simple_end_io(struct bio *bio)
|
||||
INIT_WORK(&bbio->end_io_work, btrfs_end_bio_work);
|
||||
queue_work(btrfs_end_io_wq(fs_info, bio), &bbio->end_io_work);
|
||||
} else {
|
||||
if (bio_op(bio) == REQ_OP_ZONE_APPEND && !bio->bi_status)
|
||||
if (bio_is_zone_append(bio) && !bio->bi_status)
|
||||
btrfs_record_physical_zoned(bbio);
|
||||
btrfs_bio_end_io(bbio, bbio->bio.bi_status);
|
||||
}
|
||||
@ -401,7 +401,7 @@ static void btrfs_orig_write_end_io(struct bio *bio)
|
||||
else
|
||||
bio->bi_status = BLK_STS_OK;
|
||||
|
||||
if (bio_op(bio) == REQ_OP_ZONE_APPEND && !bio->bi_status)
|
||||
if (bio_is_zone_append(bio) && !bio->bi_status)
|
||||
stripe->physical = bio->bi_iter.bi_sector << SECTOR_SHIFT;
|
||||
|
||||
btrfs_bio_end_io(bbio, bbio->bio.bi_status);
|
||||
@ -415,7 +415,7 @@ static void btrfs_clone_write_end_io(struct bio *bio)
|
||||
if (bio->bi_status) {
|
||||
atomic_inc(&stripe->bioc->error);
|
||||
btrfs_log_dev_io_error(bio, stripe->dev);
|
||||
} else if (bio_op(bio) == REQ_OP_ZONE_APPEND) {
|
||||
} else if (bio_is_zone_append(bio)) {
|
||||
stripe->physical = bio->bi_iter.bi_sector << SECTOR_SHIFT;
|
||||
}
|
||||
|
||||
@ -652,8 +652,14 @@ static u64 btrfs_append_map_length(struct btrfs_bio *bbio, u64 map_length)
|
||||
map_length = min(map_length, bbio->fs_info->max_zone_append_size);
|
||||
sector_offset = bio_split_rw_at(&bbio->bio, &bbio->fs_info->limits,
|
||||
&nr_segs, map_length);
|
||||
if (sector_offset)
|
||||
return sector_offset << SECTOR_SHIFT;
|
||||
if (sector_offset) {
|
||||
/*
|
||||
* bio_split_rw_at() could split at a size smaller than our
|
||||
* sectorsize and thus cause unaligned I/Os. Fix that by
|
||||
* always rounding down to the nearest boundary.
|
||||
*/
|
||||
return ALIGN_DOWN(sector_offset << SECTOR_SHIFT, bbio->fs_info->sectorsize);
|
||||
}
|
||||
return map_length;
|
||||
}
|
||||
|
||||
|
@ -370,6 +370,25 @@ static inline void btrfs_set_root_last_trans(struct btrfs_root *root, u64 transi
|
||||
WRITE_ONCE(root->last_trans, transid);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the generation this root started with.
|
||||
*
|
||||
* Every normal root that is created with root->root_key.offset set to it's
|
||||
* originating generation. If it is a snapshot it is the generation when the
|
||||
* snapshot was created.
|
||||
*
|
||||
* However for TREE_RELOC roots root_key.offset is the objectid of the owning
|
||||
* tree root. Thankfully we copy the root item of the owning tree root, which
|
||||
* has it's last_snapshot set to what we would have root_key.offset set to, so
|
||||
* return that if this is a TREE_RELOC root.
|
||||
*/
|
||||
static inline u64 btrfs_root_origin_generation(const struct btrfs_root *root)
|
||||
{
|
||||
if (btrfs_root_id(root) == BTRFS_TREE_RELOC_OBJECTID)
|
||||
return btrfs_root_last_snapshot(&root->root_item);
|
||||
return root->root_key.offset;
|
||||
}
|
||||
|
||||
/*
|
||||
* Structure that conveys information about an extent that is going to replace
|
||||
* all the extents in a file range.
|
||||
|
@ -5285,7 +5285,7 @@ static bool visit_node_for_delete(struct btrfs_root *root, struct walk_control *
|
||||
* reference to it.
|
||||
*/
|
||||
generation = btrfs_node_ptr_generation(eb, slot);
|
||||
if (!wc->update_ref || generation <= root->root_key.offset)
|
||||
if (!wc->update_ref || generation <= btrfs_root_origin_generation(root))
|
||||
return false;
|
||||
|
||||
/*
|
||||
@ -5340,7 +5340,7 @@ static noinline void reada_walk_down(struct btrfs_trans_handle *trans,
|
||||
goto reada;
|
||||
|
||||
if (wc->stage == UPDATE_BACKREF &&
|
||||
generation <= root->root_key.offset)
|
||||
generation <= btrfs_root_origin_generation(root))
|
||||
continue;
|
||||
|
||||
/* We don't lock the tree block, it's OK to be racy here */
|
||||
@ -5683,7 +5683,7 @@ static noinline int do_walk_down(struct btrfs_trans_handle *trans,
|
||||
* for the subtree
|
||||
*/
|
||||
if (wc->stage == UPDATE_BACKREF &&
|
||||
generation <= root->root_key.offset) {
|
||||
generation <= btrfs_root_origin_generation(root)) {
|
||||
wc->lookup_info = 1;
|
||||
return 1;
|
||||
}
|
||||
|
@ -1527,6 +1527,11 @@ static int check_extent_item(struct extent_buffer *leaf,
|
||||
dref_offset, fs_info->sectorsize);
|
||||
return -EUCLEAN;
|
||||
}
|
||||
if (unlikely(btrfs_extent_data_ref_count(leaf, dref) == 0)) {
|
||||
extent_err(leaf, slot,
|
||||
"invalid data ref count, should have non-zero value");
|
||||
return -EUCLEAN;
|
||||
}
|
||||
inline_refs += btrfs_extent_data_ref_count(leaf, dref);
|
||||
break;
|
||||
/* Contains parent bytenr and ref count */
|
||||
@ -1539,6 +1544,11 @@ static int check_extent_item(struct extent_buffer *leaf,
|
||||
inline_offset, fs_info->sectorsize);
|
||||
return -EUCLEAN;
|
||||
}
|
||||
if (unlikely(btrfs_shared_data_ref_count(leaf, sref) == 0)) {
|
||||
extent_err(leaf, slot,
|
||||
"invalid shared data ref count, should have non-zero value");
|
||||
return -EUCLEAN;
|
||||
}
|
||||
inline_refs += btrfs_shared_data_ref_count(leaf, sref);
|
||||
break;
|
||||
case BTRFS_EXTENT_OWNER_REF_KEY:
|
||||
@ -1611,8 +1621,18 @@ static int check_simple_keyed_refs(struct extent_buffer *leaf,
|
||||
{
|
||||
u32 expect_item_size = 0;
|
||||
|
||||
if (key->type == BTRFS_SHARED_DATA_REF_KEY)
|
||||
if (key->type == BTRFS_SHARED_DATA_REF_KEY) {
|
||||
struct btrfs_shared_data_ref *sref;
|
||||
|
||||
sref = btrfs_item_ptr(leaf, slot, struct btrfs_shared_data_ref);
|
||||
if (unlikely(btrfs_shared_data_ref_count(leaf, sref) == 0)) {
|
||||
extent_err(leaf, slot,
|
||||
"invalid shared data backref count, should have non-zero value");
|
||||
return -EUCLEAN;
|
||||
}
|
||||
|
||||
expect_item_size = sizeof(struct btrfs_shared_data_ref);
|
||||
}
|
||||
|
||||
if (unlikely(btrfs_item_size(leaf, slot) != expect_item_size)) {
|
||||
generic_err(leaf, slot,
|
||||
@ -1689,6 +1709,11 @@ static int check_extent_data_ref(struct extent_buffer *leaf,
|
||||
offset, leaf->fs_info->sectorsize);
|
||||
return -EUCLEAN;
|
||||
}
|
||||
if (unlikely(btrfs_extent_data_ref_count(leaf, dref) == 0)) {
|
||||
extent_err(leaf, slot,
|
||||
"invalid extent data backref count, should have non-zero value");
|
||||
return -EUCLEAN;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user