• Qu Wenruo's avatar
    btrfs: qgroup: Fix qgroup reserved space underflow caused by buffered write... · a12b877b
    Qu Wenruo authored
    btrfs: qgroup: Fix qgroup reserved space underflow caused by buffered write and quotas being enabled
    
    [BUG]
    Under the following case, we can underflow qgroup reserved space.
    
                Task A                |            Task B
    ---------------------------------------------------------------
     Quota disabled                   |
     Buffered write                   |
     |- btrfs_check_data_free_space() |
     |  *NO* qgroup space is reserved |
     |  since quota is *DISABLED*     |
     |- All pages are copied to page  |
        cache                         |
                                      | Enable quota
                                      | Quota scan finished
                                      |
                                      | Sync_fs
                                      | |- run_delalloc_range
                                      | |- Write pages
                                      | |- btrfs_finish_ordered_io
                                      |    |- insert_reserved_file_extent
                                      |       |- btrfs_qgroup_release_data()
                                      |          Since no qgroup space is
                                                 reserved in Task A, we
                                                 underflow qgroup reserved
                                                 space
    This can be detected by fstest btrfs/104.
    
    [CAUSE]
    In insert_reserved_file_extent() we tell qgroup to release the @ram_bytes
    size of qgroup reserved_space in all cases.
    And btrfs_qgroup_release_data() will check if quotas are enabled.
    
    However in the above case, the buffered write happens before quota is
    enabled, so we don't have the reserved space for that range.
    
    [FIX]
    In insert_reserved_file_extent(), we tell qgroup to release the acctual
    byte number it released.
    In the above case, since we don't have the reserved space, we tell
    qgroups to release 0 byte, so the problem can be fixed.
    
    And thanks to the @reserved parameter introduced by the qgroup rework,
    and previous patch to return released bytes, the fix can be as small as
    10 lines.
    Signed-off-by: default avatarQu Wenruo <quwenruo@cn.fujitsu.com>
    [ changelog updates ]
    Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
    a12b877b
inode.c 289 KB