]> git.baikalelectronics.ru Git - kernel.git/commitdiff
btrfs: assert we have a write lock when removing and replacing extent maps
authorFilipe Manana <fdmanana@suse.com>
Thu, 3 Feb 2022 15:36:45 +0000 (15:36 +0000)
committerDavid Sterba <dsterba@suse.com>
Mon, 14 Mar 2022 12:13:50 +0000 (13:13 +0100)
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: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/extent_map.c
fs/btrfs/tests/extent-map-tests.c

index c28ceddefae4204c53d2a6d69744274b6daf6ab9..6fee14ce2e6b1c7b902f376941836d5d843b9023 100644 (file)
@@ -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))
index 319fed82d741fa846164fbfce0ba165364b532ad..c5b3a631bf4fb49f9df2a07db2cc46cfdf9a1b16 100644 (file)
@@ -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);
 }
 
 /*