for-7.3-rc2-tag

-----BEGIN PGP SIGNATURE-----
 
 iQJPBAABCgA5FiEE8rQSAMVO+zA4DBdWxWXV+ddtWDsFAmqkjz8bFIAAAAAABAAO
 bWFudTIsMi41KzEuMTIsMiwyAAoJEMVl1fnXbVg72aYP/iJfylH6S+RbQMRFvon2
 TixmsPcGaFgUUAyAG4uLmfVX7KS4Z7uJD8zoZKqP0DMBbCOUwEjWriY2Fy9dKAJm
 I8UNJpPfQzXV7Oalpdy5UaNVVtdk/mE1Rhv4+G4EdqNLf9GuxTd+kuO1Tn1EK/Ql
 gQKL1WZgYmHBHDv9R1uip/ibEMsTzow2RDQGDI/AKILlnWjoMthd22NXdX0bC7Tb
 sKZfEmDKbIpiVkoMaJdoXsXnDifsAb31W0KqiqOvG3PGS5bY/TJgV9l5x9heExvR
 pQ4CCSY/wH+dWKetl3YvHiWBiSXdKlsufnYwsO00PxJAr+Q7pNsBrXH5fys9bORC
 G7qCWiEmTJElNnTBTv0yUaJq+FQ6/FSzTPZXQgGhUctamiM2hgnEVv4vc8YiEGcN
 dk7rBSKMfA08BXqGhEwLZkVwleM09uUa89kK9gG/pdh0aY5twHB4CQ2EQFwitJgE
 QhtTrKLa8yjP7HpzR82VEioTkj7KZlI+jYDksaIACANjbxk7tZ73F81lPi7vNhRj
 YyYOXZOQaD081d+h09NM89C/XTXrKMND6Ft8iRSzSec/U75YWeDRFHJ2O986n0dj
 DAxzArrAR18lQwCmFODJbRMi6ELcnSjSbiIusNjUpwXsVSOuZR/ulriTRktPvptq
 UtDnhWOvBjHwoeqUlgB4OAEG
 =DZIQ
 -----END PGP SIGNATURE-----

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

Pull btrfs fixes from David Sterba:

 - tree-checker updates, validate values in b-tree item keys, other item
   length checks

 - don't do unnecessary transaction commit fallback when logging parent
   directories

 - in zoned mode, initialize space info of a block group early enough so
   it does not lead to NULL pointer dereference

* tag 'for-7.3-rc2-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux:
  btrfs: tree-checker: validate name length for extref items
  btrfs: tree-checker: validate parent field for inode extref items
  btrfs: tree-checker: validate key offset for inode ref keys
  btrfs: fix unnecessary transaction commit fallback from btrfs_log_all_parents()
  btrfs: set space_info before adding new free space in btrfs_make_block_group()
This commit is contained in:
Linus Torvalds 2026-09-12 08:31:48 -07:00
commit 95deca8dd9
3 changed files with 57 additions and 8 deletions

View File

@ -3074,6 +3074,18 @@ struct btrfs_block_group *btrfs_make_block_group(struct btrfs_trans_handle *tran
return ERR_PTR(ret);
}
/*
* Ensure the corresponding space_info object is created and
* assigned to our block group. We want our bg to be added to the rbtree
* with its ->space_info set.
*
* On a zoned filesystem btrfs_add_new_free_space() ends up in
* __btrfs_add_free_space_zoned(), which dereferences
* block_group->space_info, so it has to be set beforehand.
*/
cache->space_info = space_info;
ASSERT(cache->space_info);
ret = btrfs_add_new_free_space(cache, chunk_offset, chunk_offset + size, NULL);
btrfs_free_excluded_extents(cache);
if (ret) {
@ -3081,14 +3093,6 @@ struct btrfs_block_group *btrfs_make_block_group(struct btrfs_trans_handle *tran
return ERR_PTR(ret);
}
/*
* Ensure the corresponding space_info object is created and
* assigned to our block group. We want our bg to be added to the rbtree
* with its ->space_info set.
*/
cache->space_info = space_info;
ASSERT(cache->space_info);
ret = btrfs_add_block_group_cache(cache);
if (ret) {
btrfs_remove_free_space_cache(cache);

View File

@ -1909,6 +1909,16 @@ static int check_inode_ref(struct extent_buffer *leaf,
return -EUCLEAN;
}
if (unlikely(btrfs_is_fstree(btrfs_header_owner(leaf)) &&
(key->offset < BTRFS_FIRST_FREE_OBJECTID ||
key->offset > BTRFS_LAST_FREE_OBJECTID))) {
inode_ref_err(leaf, slot,
"invalid offset for ref key, have %llu expect [%llu, %lld]",
key->offset, BTRFS_FIRST_FREE_OBJECTID,
BTRFS_LAST_FREE_OBJECTID);
return -EUCLEAN;
}
ptr = btrfs_item_ptr_offset(leaf, slot);
end = ptr + btrfs_item_size(leaf, slot);
while (ptr < end) {
@ -1952,12 +1962,14 @@ static int check_inode_extref(struct extent_buffer *leaf,
{
unsigned long ptr = btrfs_item_ptr_offset(leaf, slot);
unsigned long end = ptr + btrfs_item_size(leaf, slot);
const bool is_fstree = btrfs_is_fstree(btrfs_header_owner(leaf));
if (unlikely(!check_prev_ino(leaf, key, slot, prev_key)))
return -EUCLEAN;
while (ptr < end) {
struct btrfs_inode_extref *extref = (struct btrfs_inode_extref *)ptr;
u64 parent;
u16 namelen;
if (unlikely(ptr + sizeof(*extref) > end)) {
@ -1967,7 +1979,24 @@ static int check_inode_extref(struct extent_buffer *leaf,
return -EUCLEAN;
}
parent = btrfs_inode_extref_parent(leaf, extref);
if (unlikely(is_fstree && (parent < BTRFS_FIRST_FREE_OBJECTID ||
parent > BTRFS_LAST_FREE_OBJECTID))) {
inode_ref_err(leaf, slot,
"invalid parent for extref key, have %llu expect [%llu, %lld]",
parent, BTRFS_FIRST_FREE_OBJECTID,
BTRFS_LAST_FREE_OBJECTID);
return -EUCLEAN;
}
namelen = btrfs_inode_extref_name_len(leaf, extref);
if (unlikely(namelen == 0 || namelen > BTRFS_NAME_LEN)) {
inode_ref_err(leaf, slot,
"invalid inode extref name length, has %u expect [1, %u]",
namelen, BTRFS_NAME_LEN);
return -EUCLEAN;
}
if (unlikely(ptr + sizeof(*extref) + namelen > end)) {
inode_ref_err(leaf, slot,
"inode extref overflow, ptr %lu end %lu namelen %u",

View File

@ -7286,6 +7286,22 @@ static int btrfs_log_all_parents(struct btrfs_trans_handle *trans,
ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
if (ret < 0)
goto out;
/*
* There can't be an inode ref key with offset 0 because inode numbers
* start at BTRFS_FIRST_FREE_OBJECTID.
*/
if (WARN_ON_ONCE(ret == 0)) {
btrfs_err(trans->fs_info,
"found inode ref key with offset 0 for root %llu inode %llu",
btrfs_root_id(root), ino);
ret = BTRFS_LOG_FORCE_COMMIT;
goto out;
}
/*
* Set to 0 so that in case we don't do any work below, we won't return
* 1 and trigger an unnecessary transaction commit.
*/
ret = 0;
while (true) {
struct extent_buffer *leaf = path->nodes[0];