|
@@ -7080,10 +7080,24 @@ int btrfs_run_dev_stats(struct btrfs_trans_handle *trans,
|
|
|
|
|
|
mutex_lock(&fs_devices->device_list_mutex);
|
|
|
list_for_each_entry(device, &fs_devices->devices, dev_list) {
|
|
|
- if (!device->dev_stats_valid || !btrfs_dev_stats_dirty(device))
|
|
|
+ stats_cnt = atomic_read(&device->dev_stats_ccnt);
|
|
|
+ if (!device->dev_stats_valid || stats_cnt == 0)
|
|
|
continue;
|
|
|
|
|
|
- stats_cnt = atomic_read(&device->dev_stats_ccnt);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * There is a LOAD-LOAD control dependency between the value of
|
|
|
+ * dev_stats_ccnt and updating the on-disk values which requires
|
|
|
+ * reading the in-memory counters. Such control dependencies
|
|
|
+ * require explicit read memory barriers.
|
|
|
+ *
|
|
|
+ * This memory barriers pairs with smp_mb__before_atomic in
|
|
|
+ * btrfs_dev_stat_inc/btrfs_dev_stat_set and with the full
|
|
|
+ * barrier implied by atomic_xchg in
|
|
|
+ * btrfs_dev_stats_read_and_reset
|
|
|
+ */
|
|
|
+ smp_rmb();
|
|
|
+
|
|
|
ret = update_dev_stat_item(trans, fs_info, device);
|
|
|
if (!ret)
|
|
|
atomic_sub(stats_cnt, &device->dev_stats_ccnt);
|