diff options
| author | Qu Wenruo <[email protected]> | 2017-02-27 15:10:37 +0800 | 
|---|---|---|
| committer | David Sterba <[email protected]> | 2017-06-29 20:17:02 +0200 | 
| commit | a12b877b557dde885bdb6978cec86bf761e63c9a (patch) | |
| tree | 7c1466560dc4a5da520786b463851671c4449646 /kernel/bpf/arraymap.c | |
| parent | 7bc329c1836866ffac8b2613f780a51b3ffe786d (diff) | |
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: Qu Wenruo <[email protected]>
[ changelog updates ]
Signed-off-by: David Sterba <[email protected]>
Diffstat (limited to 'kernel/bpf/arraymap.c')
0 files changed, 0 insertions, 0 deletions