btrfs: use READ/WRITE_ONCE for fs_devices->read_policy
authorNaohiro Aota <naohiro.aota@wdc.com>
Fri, 2 Feb 2024 04:23:28 +0000 (13:23 +0900)
committerDavid Sterba <dsterba@suse.com>
Mon, 4 Mar 2024 15:24:47 +0000 (16:24 +0100)
Since we can read/modify the value from the sysfs interface concurrently,
it would be better to protect it from compiler optimizations.

Currently, there is only one read policy BTRFS_READ_POLICY_PID available,
so no actual problem can happen now. This is a preparation for the future
expansion.

Reviewed-by: Anand Jain <anand.jain@oracle.com>
Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/sysfs.c
fs/btrfs/volumes.c

index 84c05246ffd8ad4b23b622c1ef3d4087307d6c02..21586ecc35bf9c616b21c4165e6b0b8dbc786f7a 100644 (file)
@@ -1228,11 +1228,12 @@ static ssize_t btrfs_read_policy_show(struct kobject *kobj,
                                      struct kobj_attribute *a, char *buf)
 {
        struct btrfs_fs_devices *fs_devices = to_fs_devs(kobj);
+       const enum btrfs_read_policy policy = READ_ONCE(fs_devices->read_policy);
        ssize_t ret = 0;
        int i;
 
        for (i = 0; i < BTRFS_NR_READ_POLICY; i++) {
-               if (fs_devices->read_policy == i)
+               if (policy == i)
                        ret += sysfs_emit_at(buf, ret, "%s[%s]",
                                         (ret == 0 ? "" : " "),
                                         btrfs_read_policy_name[i]);
@@ -1256,8 +1257,8 @@ static ssize_t btrfs_read_policy_store(struct kobject *kobj,
 
        for (i = 0; i < BTRFS_NR_READ_POLICY; i++) {
                if (sysfs_streq(buf, btrfs_read_policy_name[i])) {
-                       if (i != fs_devices->read_policy) {
-                               fs_devices->read_policy = i;
+                       if (i != READ_ONCE(fs_devices->read_policy)) {
+                               WRITE_ONCE(fs_devices->read_policy, i);
                                btrfs_info(fs_devices->fs_info,
                                           "read policy set to '%s'",
                                           btrfs_read_policy_name[i]);
index 474ab7ed65ea92fc8d86588b963c9d91f817c88c..224345658ea556ac1e945743e6d8078dc5c13dad 100644 (file)
@@ -5942,6 +5942,7 @@ static int find_live_mirror(struct btrfs_fs_info *fs_info,
                            struct btrfs_chunk_map *map, int first,
                            int dev_replace_is_ongoing)
 {
+       const enum btrfs_read_policy policy = READ_ONCE(fs_info->fs_devices->read_policy);
        int i;
        int num_stripes;
        int preferred_mirror;
@@ -5956,13 +5957,12 @@ static int find_live_mirror(struct btrfs_fs_info *fs_info,
        else
                num_stripes = map->num_stripes;
 
-       switch (fs_info->fs_devices->read_policy) {
+       switch (policy) {
        default:
                /* Shouldn't happen, just warn and use pid instead of failing */
-               btrfs_warn_rl(fs_info,
-                             "unknown read_policy type %u, reset to pid",
-                             fs_info->fs_devices->read_policy);
-               fs_info->fs_devices->read_policy = BTRFS_READ_POLICY_PID;
+               btrfs_warn_rl(fs_info, "unknown read_policy type %u, reset to pid",
+                             policy);
+               WRITE_ONCE(fs_info->fs_devices->read_policy, BTRFS_READ_POLICY_PID);
                fallthrough;
        case BTRFS_READ_POLICY_PID:
                preferred_mirror = first + (current->pid % num_stripes);