mirror of
https://github.com/hardkernel/linux.git
synced 2026-03-24 19:40:21 +09:00
btrfs: assert delayed node locked when removing delayed item
[ Upstream commit a57c2d4e46 ]
When removing a delayed item, or releasing which will remove it as well,
we will modify one of the delayed node's rbtrees and item counter if the
delayed item is in one of the rbtrees. This require having the delayed
node's mutex locked, otherwise we will race with other tasks modifying
the rbtrees and the counter.
This is motivated by a previous version of another patch actually calling
btrfs_release_delayed_item() after unlocking the delayed node's mutex and
against a delayed item that is in a rbtree.
So assert at __btrfs_remove_delayed_item() that the delayed node's mutex
is locked.
Reviewed-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
11054f0b88
commit
45ad79c9cb
@@ -407,6 +407,7 @@ static void finish_one_item(struct btrfs_delayed_root *delayed_root)
|
||||
|
||||
static void __btrfs_remove_delayed_item(struct btrfs_delayed_item *delayed_item)
|
||||
{
|
||||
struct btrfs_delayed_node *delayed_node = delayed_item->delayed_node;
|
||||
struct rb_root_cached *root;
|
||||
struct btrfs_delayed_root *delayed_root;
|
||||
|
||||
@@ -414,18 +415,21 @@ static void __btrfs_remove_delayed_item(struct btrfs_delayed_item *delayed_item)
|
||||
if (RB_EMPTY_NODE(&delayed_item->rb_node))
|
||||
return;
|
||||
|
||||
delayed_root = delayed_item->delayed_node->root->fs_info->delayed_root;
|
||||
/* If it's in a rbtree, then we need to have delayed node locked. */
|
||||
lockdep_assert_held(&delayed_node->mutex);
|
||||
|
||||
delayed_root = delayed_node->root->fs_info->delayed_root;
|
||||
|
||||
BUG_ON(!delayed_root);
|
||||
|
||||
if (delayed_item->type == BTRFS_DELAYED_INSERTION_ITEM)
|
||||
root = &delayed_item->delayed_node->ins_root;
|
||||
root = &delayed_node->ins_root;
|
||||
else
|
||||
root = &delayed_item->delayed_node->del_root;
|
||||
root = &delayed_node->del_root;
|
||||
|
||||
rb_erase_cached(&delayed_item->rb_node, root);
|
||||
RB_CLEAR_NODE(&delayed_item->rb_node);
|
||||
delayed_item->delayed_node->count--;
|
||||
delayed_node->count--;
|
||||
|
||||
finish_one_item(delayed_root);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user