Commit 57b14823 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull more btrfs fixes from David Sterba:
 "A more fixes. We got reports that shrinker added in 6.10 still causes
  latency spikes and the fixes don't handle all corner cases. Due to
  summer holidays we're taking a shortcut to disable it for release
  builds and will fix it in the near future.

   - only enable extent map shrinker for DEBUG builds, temporary quick
     fix to avoid latency spikes for regular builds

   - update target inode's ctime on unlink, mandated by POSIX

   - properly take lock to read/update block group's zoned variables

   - add counted_by() annotations"

* tag 'for-6.11-rc3-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux:
  btrfs: only enable extent map shrinker for DEBUG builds
  btrfs: zoned: properly take lock to read/update block group's zoned variables
  btrfs: tree-checker: add dev extent item checks
  btrfs: update target inode's ctime on unlink
  btrfs: send: annotate struct name_cache_entry with __counted_by()
parents 3c0da3d1 534f7eff
......@@ -2697,15 +2697,16 @@ static int __btrfs_add_free_space_zoned(struct btrfs_block_group *block_group,
u64 offset = bytenr - block_group->start;
u64 to_free, to_unusable;
int bg_reclaim_threshold = 0;
bool initial = ((size == block_group->length) && (block_group->alloc_offset == 0));
bool initial;
u64 reclaimable_unusable;
WARN_ON(!initial && offset + size > block_group->zone_capacity);
spin_lock(&block_group->lock);
initial = ((size == block_group->length) && (block_group->alloc_offset == 0));
WARN_ON(!initial && offset + size > block_group->zone_capacity);
if (!initial)
bg_reclaim_threshold = READ_ONCE(sinfo->bg_reclaim_threshold);
spin_lock(&ctl->tree_lock);
if (!used)
to_free = size;
else if (initial)
......@@ -2718,7 +2719,9 @@ static int __btrfs_add_free_space_zoned(struct btrfs_block_group *block_group,
to_free = offset + size - block_group->alloc_offset;
to_unusable = size - to_free;
spin_lock(&ctl->tree_lock);
ctl->free_space += to_free;
spin_unlock(&ctl->tree_lock);
/*
* If the block group is read-only, we should account freed space into
* bytes_readonly.
......@@ -2727,11 +2730,8 @@ static int __btrfs_add_free_space_zoned(struct btrfs_block_group *block_group,
block_group->zone_unusable += to_unusable;
WARN_ON(block_group->zone_unusable > block_group->length);
}
spin_unlock(&ctl->tree_lock);
if (!used) {
spin_lock(&block_group->lock);
block_group->alloc_offset -= size;
spin_unlock(&block_group->lock);
}
reclaimable_unusable = block_group->zone_unusable -
......@@ -2745,6 +2745,8 @@ static int __btrfs_add_free_space_zoned(struct btrfs_block_group *block_group,
btrfs_mark_bg_to_reclaim(block_group);
}
spin_unlock(&block_group->lock);
return 0;
}
......
......@@ -4195,6 +4195,7 @@ static int __btrfs_unlink_inode(struct btrfs_trans_handle *trans,
btrfs_i_size_write(dir, dir->vfs_inode.i_size - name->len * 2);
inode_inc_iversion(&inode->vfs_inode);
inode_set_ctime_current(&inode->vfs_inode);
inode_inc_iversion(&dir->vfs_inode);
inode_set_mtime_to_ts(&dir->vfs_inode, inode_set_ctime_current(&dir->vfs_inode));
ret = btrfs_update_inode(trans, dir);
......
......@@ -347,7 +347,7 @@ struct name_cache_entry {
int ret;
int need_later_update;
int name_len;
char name[];
char name[] __counted_by(name_len);
};
/* See the comment at lru_cache.h about struct btrfs_lru_cache_entry. */
......
......@@ -2402,7 +2402,13 @@ static long btrfs_nr_cached_objects(struct super_block *sb, struct shrink_contro
trace_btrfs_extent_map_shrinker_count(fs_info, nr);
/*
* Only report the real number for DEBUG builds, as there are reports of
* serious performance degradation caused by too frequent shrinks.
*/
if (IS_ENABLED(CONFIG_BTRFS_DEBUG))
return nr;
return 0;
}
static long btrfs_free_cached_objects(struct super_block *sb, struct shrink_control *sc)
......
......@@ -1764,6 +1764,72 @@ static int check_raid_stripe_extent(const struct extent_buffer *leaf,
return 0;
}
static int check_dev_extent_item(const struct extent_buffer *leaf,
const struct btrfs_key *key,
int slot,
struct btrfs_key *prev_key)
{
struct btrfs_dev_extent *de;
const u32 sectorsize = leaf->fs_info->sectorsize;
de = btrfs_item_ptr(leaf, slot, struct btrfs_dev_extent);
/* Basic fixed member checks. */
if (unlikely(btrfs_dev_extent_chunk_tree(leaf, de) !=
BTRFS_CHUNK_TREE_OBJECTID)) {
generic_err(leaf, slot,
"invalid dev extent chunk tree id, has %llu expect %llu",
btrfs_dev_extent_chunk_tree(leaf, de),
BTRFS_CHUNK_TREE_OBJECTID);
return -EUCLEAN;
}
if (unlikely(btrfs_dev_extent_chunk_objectid(leaf, de) !=
BTRFS_FIRST_CHUNK_TREE_OBJECTID)) {
generic_err(leaf, slot,
"invalid dev extent chunk objectid, has %llu expect %llu",
btrfs_dev_extent_chunk_objectid(leaf, de),
BTRFS_FIRST_CHUNK_TREE_OBJECTID);
return -EUCLEAN;
}
/* Alignment check. */
if (unlikely(!IS_ALIGNED(key->offset, sectorsize))) {
generic_err(leaf, slot,
"invalid dev extent key.offset, has %llu not aligned to %u",
key->offset, sectorsize);
return -EUCLEAN;
}
if (unlikely(!IS_ALIGNED(btrfs_dev_extent_chunk_offset(leaf, de),
sectorsize))) {
generic_err(leaf, slot,
"invalid dev extent chunk offset, has %llu not aligned to %u",
btrfs_dev_extent_chunk_objectid(leaf, de),
sectorsize);
return -EUCLEAN;
}
if (unlikely(!IS_ALIGNED(btrfs_dev_extent_length(leaf, de),
sectorsize))) {
generic_err(leaf, slot,
"invalid dev extent length, has %llu not aligned to %u",
btrfs_dev_extent_length(leaf, de), sectorsize);
return -EUCLEAN;
}
/* Overlap check with previous dev extent. */
if (slot && prev_key->objectid == key->objectid &&
prev_key->type == key->type) {
struct btrfs_dev_extent *prev_de;
u64 prev_len;
prev_de = btrfs_item_ptr(leaf, slot - 1, struct btrfs_dev_extent);
prev_len = btrfs_dev_extent_length(leaf, prev_de);
if (unlikely(prev_key->offset + prev_len > key->offset)) {
generic_err(leaf, slot,
"dev extent overlap, prev offset %llu len %llu current offset %llu",
prev_key->objectid, prev_len, key->offset);
return -EUCLEAN;
}
}
return 0;
}
/*
* Common point to switch the item-specific validation.
*/
......@@ -1800,6 +1866,9 @@ static enum btrfs_tree_block_status check_leaf_item(struct extent_buffer *leaf,
case BTRFS_DEV_ITEM_KEY:
ret = check_dev_item(leaf, key, slot);
break;
case BTRFS_DEV_EXTENT_KEY:
ret = check_dev_extent_item(leaf, key, slot, prev_key);
break;
case BTRFS_INODE_ITEM_KEY:
ret = check_inode_item(leaf, key, slot);
break;
......
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