mirror of
https://github.com/torvalds/linux.git
synced 2026-07-31 19:47:08 +02:00
btrfs: assert tree lock is held when removing free space entries
Removing a free space entry from an in memory space cache requires having the corresponding btrfs_free_space_ctl's 'tree_lock' held. We have several code paths that remove an entry, so add assertions where appropriate to verify we are holding the lock, as the lock is acquired by some other function up in the call chain, which makes it easy to miss in the future. Note: for this to work we need to lock the local btrfs_free_space_ctl at load_free_space_cache(), which was not being done because it's local, declared on the stack, so no other task has access to it. Signed-off-by: Filipe Manana <fdmanana@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
9649bd9a29
commit
7e5ba55994
|
|
@ -927,25 +927,27 @@ static int copy_free_space_cache(struct btrfs_block_group *block_group,
|
|||
const u64 bytes = info->bytes;
|
||||
|
||||
unlink_free_space(ctl, info, true);
|
||||
spin_unlock(&ctl->tree_lock);
|
||||
kmem_cache_free(btrfs_free_space_cachep, info);
|
||||
ret = btrfs_add_free_space(block_group, offset, bytes);
|
||||
spin_lock(&ctl->tree_lock);
|
||||
} else {
|
||||
u64 offset = info->offset;
|
||||
u64 bytes = ctl->unit;
|
||||
|
||||
while (search_bitmap(ctl, info, &offset, &bytes,
|
||||
false) == 0) {
|
||||
ret = search_bitmap(ctl, info, &offset, &bytes, false);
|
||||
if (ret == 0) {
|
||||
bitmap_clear_bits(ctl, info, offset, bytes, true);
|
||||
spin_unlock(&ctl->tree_lock);
|
||||
ret = btrfs_add_free_space(block_group, offset,
|
||||
bytes);
|
||||
if (ret)
|
||||
break;
|
||||
bitmap_clear_bits(ctl, info, offset, bytes, true);
|
||||
offset = info->offset;
|
||||
bytes = ctl->unit;
|
||||
spin_lock(&ctl->tree_lock);
|
||||
} else {
|
||||
free_bitmap(ctl, info);
|
||||
ret = 0;
|
||||
}
|
||||
free_bitmap(ctl, info);
|
||||
}
|
||||
cond_resched();
|
||||
cond_resched_lock(&ctl->tree_lock);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -1039,7 +1041,9 @@ int load_free_space_cache(struct btrfs_block_group *block_group)
|
|||
block_group->bytes_super));
|
||||
|
||||
if (matched) {
|
||||
spin_lock(&tmp_ctl.tree_lock);
|
||||
ret = copy_free_space_cache(block_group, &tmp_ctl);
|
||||
spin_unlock(&tmp_ctl.tree_lock);
|
||||
/*
|
||||
* ret == 1 means we successfully loaded the free space cache,
|
||||
* so we need to re-set it here.
|
||||
|
|
@ -1832,6 +1836,8 @@ static inline void unlink_free_space(struct btrfs_free_space_ctl *ctl,
|
|||
struct btrfs_free_space *info,
|
||||
bool update_stat)
|
||||
{
|
||||
lockdep_assert_held(&ctl->tree_lock);
|
||||
|
||||
rb_erase(&info->offset_index, &ctl->free_space_offset);
|
||||
rb_erase_cached(&info->bytes_index, &ctl->free_space_bytes);
|
||||
ctl->free_extents--;
|
||||
|
|
@ -1881,6 +1887,8 @@ static void relink_bitmap_entry(struct btrfs_free_space_ctl *ctl,
|
|||
if (RB_EMPTY_NODE(&info->bytes_index))
|
||||
return;
|
||||
|
||||
lockdep_assert_held(&ctl->tree_lock);
|
||||
|
||||
rb_erase_cached(&info->bytes_index, &ctl->free_space_bytes);
|
||||
rb_add_cached(&info->bytes_index, &ctl->free_space_bytes, entry_less);
|
||||
}
|
||||
|
|
@ -2990,8 +2998,11 @@ static void __btrfs_return_cluster_to_free_space(
|
|||
struct btrfs_block_group *block_group,
|
||||
struct btrfs_free_cluster *cluster)
|
||||
{
|
||||
struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl;
|
||||
struct rb_node *node;
|
||||
|
||||
lockdep_assert_held(&ctl->tree_lock);
|
||||
|
||||
spin_lock(&cluster->lock);
|
||||
if (cluster->block_group != block_group) {
|
||||
spin_unlock(&cluster->lock);
|
||||
|
|
@ -3004,7 +3015,6 @@ static void __btrfs_return_cluster_to_free_space(
|
|||
|
||||
node = rb_first(&cluster->root);
|
||||
while (node) {
|
||||
struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl;
|
||||
struct btrfs_free_space *entry;
|
||||
|
||||
entry = rb_entry(node, struct btrfs_free_space, offset_index);
|
||||
|
|
@ -3343,6 +3353,8 @@ static int btrfs_bitmap_cluster(struct btrfs_block_group *block_group,
|
|||
unsigned long total_found = 0;
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(&ctl->tree_lock);
|
||||
|
||||
i = offset_to_bit(entry->offset, ctl->unit,
|
||||
max_t(u64, offset, entry->offset));
|
||||
want_bits = bytes_to_bits(bytes, ctl->unit);
|
||||
|
|
@ -3432,6 +3444,8 @@ setup_cluster_no_bitmap(struct btrfs_block_group *block_group,
|
|||
u64 max_extent;
|
||||
u64 total_size = 0;
|
||||
|
||||
lockdep_assert_held(&ctl->tree_lock);
|
||||
|
||||
entry = tree_search_offset(ctl, offset, 0, 1);
|
||||
if (!entry)
|
||||
return -ENOSPC;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user