btrfs: assert commit root semaphore is held when accessing backref cache
authorFilipe Manana <fdmanana@suse.com>
Tue, 17 Jan 2023 11:21:38 +0000 (11:21 +0000)
committerDavid Sterba <dsterba@suse.com>
Wed, 15 Feb 2023 18:38:50 +0000 (19:38 +0100)
During fiemap, when accessing the cache that stores the sharedness of an
extent, we need to either be holding a transaction handle or the commit
root semaphore. I left comments about this in the comment that precedes
store_backref_shared_cache() and lookup_backref_shared_cache(), but have
actually not enforced it through assertions. So assert that the commit
root semaphore is held if we are not holding a transaction handle.

Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/backref.c

index 4685151..f846fec 100644 (file)
@@ -1252,8 +1252,12 @@ static bool lookup_backref_shared_cache(struct btrfs_backref_share_check_ctx *ct
                                        struct btrfs_root *root,
                                        u64 bytenr, int level, bool *is_shared)
 {
+       const struct btrfs_fs_info *fs_info = root->fs_info;
        struct btrfs_backref_shared_cache_entry *entry;
 
+       if (!current->journal_info)
+               lockdep_assert_held(&fs_info->commit_root_sem);
+
        if (!ctx->use_path_cache)
                return false;
 
@@ -1288,7 +1292,7 @@ static bool lookup_backref_shared_cache(struct btrfs_backref_share_check_ctx *ct
         * could be a snapshot sharing this extent buffer.
         */
        if (entry->is_shared &&
-           entry->gen != btrfs_get_last_root_drop_gen(root->fs_info))
+           entry->gen != btrfs_get_last_root_drop_gen(fs_info))
                return false;
 
        *is_shared = entry->is_shared;
@@ -1318,9 +1322,13 @@ static void store_backref_shared_cache(struct btrfs_backref_share_check_ctx *ctx
                                       struct btrfs_root *root,
                                       u64 bytenr, int level, bool is_shared)
 {
+       const struct btrfs_fs_info *fs_info = root->fs_info;
        struct btrfs_backref_shared_cache_entry *entry;
        u64 gen;
 
+       if (!current->journal_info)
+               lockdep_assert_held(&fs_info->commit_root_sem);
+
        if (!ctx->use_path_cache)
                return;
 
@@ -1336,7 +1344,7 @@ static void store_backref_shared_cache(struct btrfs_backref_share_check_ctx *ctx
        ASSERT(level >= 0);
 
        if (is_shared)
-               gen = btrfs_get_last_root_drop_gen(root->fs_info);
+               gen = btrfs_get_last_root_drop_gen(fs_info);
        else
                gen = btrfs_root_last_snapshot(&root->root_item);