]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
btrfs: use smp_mb__after_atomic() when forcing COW in create_pending_snapshot()
authorFilipe Manana <fdmanana@suse.com>
Mon, 22 Sep 2025 11:09:14 +0000 (12:09 +0100)
committerDavid Sterba <dsterba@suse.com>
Tue, 23 Sep 2025 07:02:17 +0000 (09:02 +0200)
After setting the BTRFS_ROOT_FORCE_COW flag on the root we are doing a
full write barrier, smp_wmb(), but we don't need to, all we need is a
smp_mb__after_atomic().  The use of the smp_wmb() is from the old days
when we didn't use a bit and used instead an int field in the root to
signal if cow is forced. After the int field was changed to a bit in
the root's state (flags field), we forgot to update the memory barrier
in create_pending_snapshot() to smp_mb__after_atomic(), but we did the
change in commit_fs_roots() after clearing BTRFS_ROOT_FORCE_COW. That
happened in commit 27cdeb7096b8 ("Btrfs: use bitfield instead of integer
data type for the some variants in btrfs_root"). On the reader side, in
should_cow_block(), we also use the counterpart smp_mb__before_atomic()
which generates further confusion.

So change the smp_wmb() to smp_mb__after_atomic(). In fact we don't
even need any barrier at all since create_pending_snapshot() is called
in the critical section of a transaction commit and therefore no one
can concurrently join/attach the transaction, or start a new one, until
the transaction is unblocked. By the time someone starts a new transaction
and enters should_cow_block(), a lot of implicit memory barriers already
took place by having acquired several locks such as fs_info->trans_lock
and extent buffer locks on the root node at least. Nevertlheless, for
consistency use smp_mb__after_atomic() after setting the force cow bit
in create_pending_snapshot().

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/transaction.c

index 23bcd3c0fc1c2824b6498dcc7060eb0e09456280..89ae0c7a610aa5368722ae2d42e4b1c154e38033 100644 (file)
@@ -1802,7 +1802,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
        }
        /* see comments in should_cow_block() */
        set_bit(BTRFS_ROOT_FORCE_COW, &root->state);
-       smp_wmb();
+       smp_mb__after_atomic();
 
        btrfs_set_root_node(new_root_item, tmp);
        /* record when the snapshot was created in key.offset */