]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/4.19.34/btrfs-qgroup-make-qgroup-async-transaction-commit-mo.patch
Linux 4.19.34
[thirdparty/kernel/stable-queue.git] / releases / 4.19.34 / btrfs-qgroup-make-qgroup-async-transaction-commit-mo.patch
1 From a9cfc8c42ebaad8c3a321f57c17cc19b204103bd Mon Sep 17 00:00:00 2001
2 From: Qu Wenruo <wqu@suse.com>
3 Date: Fri, 25 Jan 2019 07:55:27 +0800
4 Subject: btrfs: qgroup: Make qgroup async transaction commit more aggressive
5
6 [ Upstream commit f5fef4593653dfa2a865c485bb81415de51d5c99 ]
7
8 [BUG]
9 Btrfs qgroup will still hit EDQUOT under the following case:
10
11 $ dev=/dev/test/test
12 $ mnt=/mnt/btrfs
13 $ umount $mnt &> /dev/null
14 $ umount $dev &> /dev/null
15
16 $ mkfs.btrfs -f $dev
17 $ mount $dev $mnt -o nospace_cache
18
19 $ btrfs subv create $mnt/subv
20 $ btrfs quota enable $mnt
21 $ btrfs quota rescan -w $mnt
22 $ btrfs qgroup limit -e 1G $mnt/subv
23
24 $ fallocate -l 900M $mnt/subv/padding
25 $ sync
26
27 $ rm $mnt/subv/padding
28
29 # Hit EDQUOT
30 $ xfs_io -f -c "pwrite 0 512M" $mnt/subv/real_file
31
32 [CAUSE]
33 Since commit a514d63882c3 ("btrfs: qgroup: Commit transaction in advance
34 to reduce early EDQUOT"), btrfs is not forced to commit transaction to
35 reclaim more quota space.
36
37 Instead, we just check pertrans metadata reservation against some
38 threshold and try to do asynchronously transaction commit.
39
40 However in above case, the pertrans metadata reservation is pretty small
41 thus it will never trigger asynchronous transaction commit.
42
43 [FIX]
44 Instead of only accounting pertrans metadata reservation, we calculate
45 how much free space we have, and if there isn't much free space left,
46 commit transaction asynchronously to try to free some space.
47
48 This may slow down the fs when we have less than 32M free qgroup space,
49 but should reduce a lot of false EDQUOT, so the cost should be
50 acceptable.
51
52 Signed-off-by: Qu Wenruo <wqu@suse.com>
53 Signed-off-by: David Sterba <dsterba@suse.com>
54 Signed-off-by: Sasha Levin <sashal@kernel.org>
55 ---
56 fs/btrfs/qgroup.c | 28 ++++++++++++++--------------
57 1 file changed, 14 insertions(+), 14 deletions(-)
58
59 diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c
60 index e1fcb28ad4cc..e46e83e87600 100644
61 --- a/fs/btrfs/qgroup.c
62 +++ b/fs/btrfs/qgroup.c
63 @@ -2427,16 +2427,15 @@ out:
64 /*
65 * Two limits to commit transaction in advance.
66 *
67 - * For RATIO, it will be 1/RATIO of the remaining limit
68 - * (excluding data and prealloc meta) as threshold.
69 + * For RATIO, it will be 1/RATIO of the remaining limit as threshold.
70 * For SIZE, it will be in byte unit as threshold.
71 */
72 -#define QGROUP_PERTRANS_RATIO 32
73 -#define QGROUP_PERTRANS_SIZE SZ_32M
74 +#define QGROUP_FREE_RATIO 32
75 +#define QGROUP_FREE_SIZE SZ_32M
76 static bool qgroup_check_limits(struct btrfs_fs_info *fs_info,
77 const struct btrfs_qgroup *qg, u64 num_bytes)
78 {
79 - u64 limit;
80 + u64 free;
81 u64 threshold;
82
83 if ((qg->lim_flags & BTRFS_QGROUP_LIMIT_MAX_RFER) &&
84 @@ -2455,20 +2454,21 @@ static bool qgroup_check_limits(struct btrfs_fs_info *fs_info,
85 */
86 if ((qg->lim_flags & (BTRFS_QGROUP_LIMIT_MAX_RFER |
87 BTRFS_QGROUP_LIMIT_MAX_EXCL))) {
88 - if (qg->lim_flags & BTRFS_QGROUP_LIMIT_MAX_EXCL)
89 - limit = qg->max_excl;
90 - else
91 - limit = qg->max_rfer;
92 - threshold = (limit - qg->rsv.values[BTRFS_QGROUP_RSV_DATA] -
93 - qg->rsv.values[BTRFS_QGROUP_RSV_META_PREALLOC]) /
94 - QGROUP_PERTRANS_RATIO;
95 - threshold = min_t(u64, threshold, QGROUP_PERTRANS_SIZE);
96 + if (qg->lim_flags & BTRFS_QGROUP_LIMIT_MAX_EXCL) {
97 + free = qg->max_excl - qgroup_rsv_total(qg) - qg->excl;
98 + threshold = min_t(u64, qg->max_excl / QGROUP_FREE_RATIO,
99 + QGROUP_FREE_SIZE);
100 + } else {
101 + free = qg->max_rfer - qgroup_rsv_total(qg) - qg->rfer;
102 + threshold = min_t(u64, qg->max_rfer / QGROUP_FREE_RATIO,
103 + QGROUP_FREE_SIZE);
104 + }
105
106 /*
107 * Use transaction_kthread to commit transaction, so we no
108 * longer need to bother nested transaction nor lock context.
109 */
110 - if (qg->rsv.values[BTRFS_QGROUP_RSV_META_PERTRANS] > threshold)
111 + if (free < threshold)
112 btrfs_commit_transaction_locksafe(fs_info);
113 }
114
115 --
116 2.19.1
117