btrfs: fix harmless race getting delayed ref head count when running delayed refs
authorFilipe Manana <fdmanana@suse.com>
Mon, 12 May 2025 11:31:24 +0000 (12:31 +0100)
committerDavid Sterba <dsterba@suse.com>
Thu, 15 May 2025 12:30:57 +0000 (14:30 +0200)
When running delayed references we are reading the number of ready delayed
ref heads without taking any lock which can make KCSAN report a race since
we can have concurrent tasks updating that number, such as for example
when freeing a tree block which will end up decrementing that counter or
when adding a new delayed ref while COWing a tree block which will
increment that counter.

This is a harmless race since running one more or one less delayed ref
head doesn't result in any problem, in the critical section of a
transaction commit we always run any remaining delayed refs and at that
point no one can create more.

So fix this harmless race by annotating the read with data_race().

Reported-by: cen zhang <zzzccc427@gmail.com>
Link: https://lore.kernel.org/linux-btrfs/CAFRLqsUCLMz0hY-GaPj1Z=fhkgRHjxVXHZ8kz0PvkFN0b=8L2Q@mail.gmail.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/extent-tree.c

index 1aa584a79422aa88ddee19c1f0526862f0e39869..cb6128778a836068dfe700bee304f23e2eb17d3f 100644 (file)
@@ -2006,7 +2006,12 @@ static noinline int __btrfs_run_delayed_refs(struct btrfs_trans_handle *trans,
 
        delayed_refs = &trans->transaction->delayed_refs;
        if (min_bytes == 0) {
-               max_count = delayed_refs->num_heads_ready;
+               /*
+                * We may be subject to a harmless race if some task is
+                * concurrently adding or removing a delayed ref, so silence
+                * KCSAN and similar tools.
+                */
+               max_count = data_race(delayed_refs->num_heads_ready);
                min_bytes = U64_MAX;
        }