• Filipe Manana's avatar
    btrfs: fix data races when accessing the reserved amount of block reserves · e06cc894
    Filipe Manana authored
    At space_info.c we have several places where we access the ->reserved
    field of a block reserve without taking the block reserve's spinlock
    first, which makes KCSAN warn about a data race since that field is
    always updated while holding the spinlock.
    
    The reports from KCSAN are like the following:
    
      [117.193526] BUG: KCSAN: data-race in btrfs_block_rsv_release [btrfs] / need_preemptive_reclaim [btrfs]
    
      [117.195148] read to 0x000000017f587190 of 8 bytes by task 6303 on cpu 3:
      [117.195172]  need_preemptive_reclaim+0x222/0x2f0 [btrfs]
      [117.195992]  __reserve_bytes+0xbb0/0xdc8 [btrfs]
      [117.196807]  btrfs_reserve_metadata_bytes+0x4c/0x120 [btrfs]
      [117.197620]  btrfs_block_rsv_add+0x78/0xa8 [btrfs]
      [117.198434]  btrfs_delayed_update_inode+0x154/0x368 [btrfs]
      [117.199300]  btrfs_update_inode+0x108/0x1c8 [btrfs]
      [117.200122]  btrfs_dirty_inode+0xb4/0x140 [btrfs]
      [117.200937]  btrfs_update_time+0x8c/0xb0 [btrfs]
      [117.201754]  touch_atime+0x16c/0x1e0
      [117.201789]  filemap_read+0x674/0x728
      [117.201823]  btrfs_file_read_iter+0xf8/0x410 [btrfs]
      [117.202653]  vfs_read+0x2b6/0x498
      [117.203454]  ksys_read+0xa2/0x150
      [117.203473]  __s390x_sys_read+0x68/0x88
      [117.203495]  do_syscall+0x1c6/0x210
      [117.203517]  __do_syscall+0xc8/0xf0
      [117.203539]  system_call+0x70/0x98
    
      [117.203579] write to 0x000000017f587190 of 8 bytes by task 11 on cpu 0:
      [117.203604]  btrfs_block_rsv_release+0x2e8/0x578 [btrfs]
      [117.204432]  btrfs_delayed_inode_release_metadata+0x7c/0x1d0 [btrfs]
      [117.205259]  __btrfs_update_delayed_inode+0x37c/0x5e0 [btrfs]
      [117.206093]  btrfs_async_run_delayed_root+0x356/0x498 [btrfs]
      [117.206917]  btrfs_work_helper+0x160/0x7a0 [btrfs]
      [117.207738]  process_one_work+0x3b6/0x838
      [117.207768]  worker_thread+0x75e/0xb10
      [117.207797]  kthread+0x21a/0x230
      [117.207830]  __ret_from_fork+0x6c/0xb8
      [117.207861]  ret_from_fork+0xa/0x30
    
    So add a helper to get the reserved amount of a block reserve while
    holding the lock. The value may be not be up to date anymore when used by
    need_preemptive_reclaim() and btrfs_preempt_reclaim_metadata_space(), but
    that's ok since the worst it can do is cause more reclaim work do be done
    sooner rather than later. Reading the field while holding the lock instead
    of using the data_race() annotation is used in order to prevent load
    tearing.
    Signed-off-by: default avatarFilipe Manana <fdmanana@suse.com>
    Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
    Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
    e06cc894
space-info.c 59.3 KB