• Josef Bacik's avatar
    btrfs: fix bytes_may_use underflow in prealloc error condtition · b778cf96
    Josef Bacik authored
    I hit the following warning while running my error injection stress
    testing:
    
      WARNING: CPU: 3 PID: 1453 at fs/btrfs/space-info.h:108 btrfs_free_reserved_data_space_noquota+0xfd/0x160 [btrfs]
      RIP: 0010:btrfs_free_reserved_data_space_noquota+0xfd/0x160 [btrfs]
      Call Trace:
      btrfs_free_reserved_data_space+0x4f/0x70 [btrfs]
      __btrfs_prealloc_file_range+0x378/0x470 [btrfs]
      elfcorehdr_read+0x40/0x40
      ? elfcorehdr_read+0x40/0x40
      ? btrfs_commit_transaction+0xca/0xa50 [btrfs]
      ? dput+0xb4/0x2a0
      ? btrfs_log_dentry_safe+0x55/0x70 [btrfs]
      ? btrfs_sync_file+0x30e/0x420 [btrfs]
      ? do_fsync+0x38/0x70
      ? __x64_sys_fdatasync+0x13/0x20
      ? do_syscall_64+0x5b/0x1b0
      ? entry_SYSCALL_64_after_hwframe+0x44/0xa9
    
    This happens if we fail to insert our reserved file extent.  At this
    point we've already converted our reservation from ->bytes_may_use to
    ->bytes_reserved.  However once we break we will attempt to free
    everything from [cur_offset, end] from ->bytes_may_use, but our extent
    reservation will overlap part of this.
    
    Fix this problem by adding ins.offset (our extent allocation size) to
    cur_offset so we remove the actual remaining part from ->bytes_may_use.
    
    I validated this fix using my inject-error.py script
    
    python inject-error.py -o should_fail_bio -t cache_save_setup -t \
    	__btrfs_prealloc_file_range \
    	-t insert_reserved_file_extent.constprop.0 \
    	-r "-5" ./run-fsstress.sh
    
    where run-fsstress.sh simply mounts and runs fsstress on a disk.
    
    CC: stable@vger.kernel.org # 4.4+
    Reviewed-by: default avatarQu Wenruo <wqu@suse.com>
    Signed-off-by: default avatarJosef Bacik <josef@toxicpanda.com>
    Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
    Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
    b778cf96
inode.c 288 KB