diff mbox series

[2/3] btrfs: use READ_ONCE() when accessing delayed_node at btrfs_dirty_node()

Message ID 68f8da7780333faba472e44689f977abd7222ffc.1715951291.git.fdmanana@suse.com (mailing list archive)
State New
Headers show
Series btrfs: avoid data races when accessing an inode's delayed_node | expand

Commit Message

Filipe Manana May 17, 2024, 1:13 p.m. UTC
From: Filipe Manana <fdmanana@suse.com>

An inode's delayed_node is set while holding the root->delayed_nodes
xarray's lock, so accessing it without holding the lock at
btrfs_dirty_node() is racy and will likely trigger warnings from tools
like KCSAN.

Since we update the inode's delayed_node with WRITE_ONCE(), we can use
READ_ONCE() without taking the lock, as we do in several other places
at delayed-inode.c. So change btrfs_dirty_node() to use READ_ONCE().

Signed-off-by: Filipe Manana <fdmanana@suse.com>
---
 fs/btrfs/inode.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

Comments

Qu Wenruo May 17, 2024, 10:51 p.m. UTC | #1
在 2024/5/17 22:43, fdmanana@kernel.org 写道:
> From: Filipe Manana <fdmanana@suse.com>
>
> An inode's delayed_node is set while holding the root->delayed_nodes
> xarray's lock, so accessing it without holding the lock at
> btrfs_dirty_node() is racy and will likely trigger warnings from tools
> like KCSAN.
>
> Since we update the inode's delayed_node with WRITE_ONCE(), we can use
> READ_ONCE() without taking the lock, as we do in several other places
> at delayed-inode.c. So change btrfs_dirty_node() to use READ_ONCE().
>
> Signed-off-by: Filipe Manana <fdmanana@suse.com>

Reviewed-by: Qu Wenruo <wqu@suse.com>

Thanks,
Qu

> ---
>   fs/btrfs/inode.c | 2 +-
>   1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
> index 000809e16aba..11cad22d7b4c 100644
> --- a/fs/btrfs/inode.c
> +++ b/fs/btrfs/inode.c
> @@ -6100,7 +6100,7 @@ static int btrfs_dirty_inode(struct btrfs_inode *inode)
>   		ret = btrfs_update_inode(trans, inode);
>   	}
>   	btrfs_end_transaction(trans);
> -	if (inode->delayed_node)
> +	if (READ_ONCE(inode->delayed_node))
>   		btrfs_balance_delayed_items(fs_info);
>
>   	return ret;
diff mbox series

Patch

diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 000809e16aba..11cad22d7b4c 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -6100,7 +6100,7 @@  static int btrfs_dirty_inode(struct btrfs_inode *inode)
 		ret = btrfs_update_inode(trans, inode);
 	}
 	btrfs_end_transaction(trans);
-	if (inode->delayed_node)
+	if (READ_ONCE(inode->delayed_node))
 		btrfs_balance_delayed_items(fs_info);
 
 	return ret;