Commit 6d3b050e authored by Filipe Manana's avatar Filipe Manana Committed by David Sterba
Browse files

btrfs: assert we have a write lock when removing and replacing extent maps



Removing or replacing an extent map requires holding a write lock on the
extent map's tree. We currently do that everywhere, except in one of the
self tests, where it's harmless since there's no concurrency.

In order to catch possible races in the future, assert that we are holding
a write lock on the extent map tree before removing or replacing an extent
map in the tree, and update the self test to obtain a write lock before
removing extent maps.

Reviewed-by: default avatarJohannes Thumshirn <johannes.thumshirn@wdc.com>
Signed-off-by: default avatarFilipe Manana <fdmanana@suse.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent ad3fc794
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -492,6 +492,8 @@ struct extent_map *search_extent_mapping(struct extent_map_tree *tree,
 */
void remove_extent_mapping(struct extent_map_tree *tree, struct extent_map *em)
{
	lockdep_assert_held_write(&tree->lock);

	WARN_ON(test_bit(EXTENT_FLAG_PINNED, &em->flags));
	rb_erase_cached(&em->rb_node, &tree->map);
	if (!test_bit(EXTENT_FLAG_LOGGING, &em->flags))
@@ -506,6 +508,8 @@ void replace_extent_mapping(struct extent_map_tree *tree,
			    struct extent_map *new,
			    int modified)
{
	lockdep_assert_held_write(&tree->lock);

	WARN_ON(test_bit(EXTENT_FLAG_PINNED, &cur->flags));
	ASSERT(extent_map_in_tree(cur));
	if (!test_bit(EXTENT_FLAG_LOGGING, &cur->flags))
+2 −0
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@ static void free_extent_map_tree(struct extent_map_tree *em_tree)
	struct extent_map *em;
	struct rb_node *node;

	write_lock(&em_tree->lock);
	while (!RB_EMPTY_ROOT(&em_tree->map.rb_root)) {
		node = rb_first_cached(&em_tree->map);
		em = rb_entry(node, struct extent_map, rb_node);
@@ -32,6 +33,7 @@ static void free_extent_map_tree(struct extent_map_tree *em_tree)
#endif
		free_extent_map(em);
	}
	write_unlock(&em_tree->lock);
}

/*