diff options
author | Filipe Manana <fdmanana@suse.com> | 2023-10-04 13:38:51 +0300 |
---|---|---|
committer | David Sterba <dsterba@suse.com> | 2023-10-12 17:44:17 +0300 |
commit | 0124855ff18b9bdfe6aec87f7b29d3fdc6f575db (patch) | |
tree | 9efcc94b959df93a18e6fecc165546b1f99f3fad /fs/btrfs/super.c | |
parent | 4a4f8fe2b0230c22aba40c9f8ea7b9c6fcfc8417 (diff) | |
download | linux-0124855ff18b9bdfe6aec87f7b29d3fdc6f575db.tar.xz |
btrfs: add and use helpers for reading and writing last_trans_committed
Currently the last_trans_committed field of struct btrfs_fs_info is
modified and read without any locking or other protection. For example
early in the fsync path, skip_inode_logging() is called which reads
fs_info->last_trans_committed, but at the same time we can have a
transaction commit completing and updating that field.
In the case of an fsync this is harmless and any data race should be
rare and at most cause an unnecessary logging of an inode.
To avoid data race warnings from tools like KCSAN and other issues such
as load and store tearing (amongst others, see [1]), create helpers to
access the last_trans_committed field of struct btrfs_fs_info using
READ_ONCE() and WRITE_ONCE(), and use these helpers everywhere.
[1] https://lwn.net/Articles/793253/
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
Diffstat (limited to 'fs/btrfs/super.c')
-rw-r--r-- | fs/btrfs/super.c | 7 |
1 files changed, 4 insertions, 3 deletions
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 55d308cd5de4..6ecf78d09694 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -2217,6 +2217,7 @@ static int check_dev_super(struct btrfs_device *dev) { struct btrfs_fs_info *fs_info = dev->fs_info; struct btrfs_super_block *sb; + u64 last_trans; u16 csum_type; int ret = 0; @@ -2252,10 +2253,10 @@ static int check_dev_super(struct btrfs_device *dev) if (ret < 0) goto out; - if (btrfs_super_generation(sb) != fs_info->last_trans_committed) { + last_trans = btrfs_get_last_trans_committed(fs_info); + if (btrfs_super_generation(sb) != last_trans) { btrfs_err(fs_info, "transid mismatch, has %llu expect %llu", - btrfs_super_generation(sb), - fs_info->last_trans_committed); + btrfs_super_generation(sb), last_trans); ret = -EUCLEAN; goto out; } |