Commit dccb07f2 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull btrfs fixes from David Sterba:
 "Two more fixes, both have some visible effects on user space:

   - add check if quotas are enabled when passing qgroup inheritance
     info, this affects snapper that could fail to create a snapshot

   - do check for leaf/node flag WRITTEN earlier so that nodes are
     completely validated before access, this used to be done by
     integrity checker but it's been removed and left an unhandled case"

* tag 'for-6.9-rc7-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux:
  btrfs: make sure that WRITTEN is set on all metadata blocks
  btrfs: qgroup: do not check qgroup inherit if qgroup is disabled
parents 3628e038 e03418ab
...@@ -3045,6 +3045,8 @@ int btrfs_qgroup_check_inherit(struct btrfs_fs_info *fs_info, ...@@ -3045,6 +3045,8 @@ int btrfs_qgroup_check_inherit(struct btrfs_fs_info *fs_info,
struct btrfs_qgroup_inherit *inherit, struct btrfs_qgroup_inherit *inherit,
size_t size) size_t size)
{ {
if (!btrfs_qgroup_enabled(fs_info))
return 0;
if (inherit->flags & ~BTRFS_QGROUP_INHERIT_FLAGS_SUPP) if (inherit->flags & ~BTRFS_QGROUP_INHERIT_FLAGS_SUPP)
return -EOPNOTSUPP; return -EOPNOTSUPP;
if (size < sizeof(*inherit) || size > PAGE_SIZE) if (size < sizeof(*inherit) || size > PAGE_SIZE)
......
...@@ -1797,6 +1797,11 @@ enum btrfs_tree_block_status __btrfs_check_leaf(struct extent_buffer *leaf) ...@@ -1797,6 +1797,11 @@ enum btrfs_tree_block_status __btrfs_check_leaf(struct extent_buffer *leaf)
return BTRFS_TREE_BLOCK_INVALID_LEVEL; return BTRFS_TREE_BLOCK_INVALID_LEVEL;
} }
if (unlikely(!btrfs_header_flag(leaf, BTRFS_HEADER_FLAG_WRITTEN))) {
generic_err(leaf, 0, "invalid flag for leaf, WRITTEN not set");
return BTRFS_TREE_BLOCK_WRITTEN_NOT_SET;
}
/* /*
* Extent buffers from a relocation tree have a owner field that * Extent buffers from a relocation tree have a owner field that
* corresponds to the subvolume tree they are based on. So just from an * corresponds to the subvolume tree they are based on. So just from an
...@@ -1858,6 +1863,7 @@ enum btrfs_tree_block_status __btrfs_check_leaf(struct extent_buffer *leaf) ...@@ -1858,6 +1863,7 @@ enum btrfs_tree_block_status __btrfs_check_leaf(struct extent_buffer *leaf)
for (slot = 0; slot < nritems; slot++) { for (slot = 0; slot < nritems; slot++) {
u32 item_end_expected; u32 item_end_expected;
u64 item_data_end; u64 item_data_end;
enum btrfs_tree_block_status ret;
btrfs_item_key_to_cpu(leaf, &key, slot); btrfs_item_key_to_cpu(leaf, &key, slot);
...@@ -1913,21 +1919,10 @@ enum btrfs_tree_block_status __btrfs_check_leaf(struct extent_buffer *leaf) ...@@ -1913,21 +1919,10 @@ enum btrfs_tree_block_status __btrfs_check_leaf(struct extent_buffer *leaf)
return BTRFS_TREE_BLOCK_INVALID_OFFSETS; return BTRFS_TREE_BLOCK_INVALID_OFFSETS;
} }
/* /* Check if the item size and content meet other criteria. */
* We only want to do this if WRITTEN is set, otherwise the leaf ret = check_leaf_item(leaf, &key, slot, &prev_key);
* may be in some intermediate state and won't appear valid. if (unlikely(ret != BTRFS_TREE_BLOCK_CLEAN))
*/ return ret;
if (btrfs_header_flag(leaf, BTRFS_HEADER_FLAG_WRITTEN)) {
enum btrfs_tree_block_status ret;
/*
* Check if the item size and content meet other
* criteria
*/
ret = check_leaf_item(leaf, &key, slot, &prev_key);
if (unlikely(ret != BTRFS_TREE_BLOCK_CLEAN))
return ret;
}
prev_key.objectid = key.objectid; prev_key.objectid = key.objectid;
prev_key.type = key.type; prev_key.type = key.type;
...@@ -1957,6 +1952,11 @@ enum btrfs_tree_block_status __btrfs_check_node(struct extent_buffer *node) ...@@ -1957,6 +1952,11 @@ enum btrfs_tree_block_status __btrfs_check_node(struct extent_buffer *node)
int level = btrfs_header_level(node); int level = btrfs_header_level(node);
u64 bytenr; u64 bytenr;
if (unlikely(!btrfs_header_flag(node, BTRFS_HEADER_FLAG_WRITTEN))) {
generic_err(node, 0, "invalid flag for node, WRITTEN not set");
return BTRFS_TREE_BLOCK_WRITTEN_NOT_SET;
}
if (unlikely(level <= 0 || level >= BTRFS_MAX_LEVEL)) { if (unlikely(level <= 0 || level >= BTRFS_MAX_LEVEL)) {
generic_err(node, 0, generic_err(node, 0,
"invalid level for node, have %d expect [1, %d]", "invalid level for node, have %d expect [1, %d]",
......
...@@ -53,6 +53,7 @@ enum btrfs_tree_block_status { ...@@ -53,6 +53,7 @@ enum btrfs_tree_block_status {
BTRFS_TREE_BLOCK_INVALID_BLOCKPTR, BTRFS_TREE_BLOCK_INVALID_BLOCKPTR,
BTRFS_TREE_BLOCK_INVALID_ITEM, BTRFS_TREE_BLOCK_INVALID_ITEM,
BTRFS_TREE_BLOCK_INVALID_OWNER, BTRFS_TREE_BLOCK_INVALID_OWNER,
BTRFS_TREE_BLOCK_WRITTEN_NOT_SET,
}; };
/* /*
......
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