]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/6.1.83/quota-fix-rcu-annotations-of-inode-dquot-pointers.patch
Linux 6.1.83
[thirdparty/kernel/stable-queue.git] / releases / 6.1.83 / quota-fix-rcu-annotations-of-inode-dquot-pointers.patch
1 From 40287aff4b5937a5c23db1e30b8522081d98e327 Mon Sep 17 00:00:00 2001
2 From: Sasha Levin <sashal@kernel.org>
3 Date: Tue, 6 Feb 2024 15:32:09 +0100
4 Subject: quota: Fix rcu annotations of inode dquot pointers
5
6 From: Jan Kara <jack@suse.cz>
7
8 [ Upstream commit 179b8c97ebf63429589f5afeba59a181fe70603e ]
9
10 Dquot pointers in i_dquot array in the inode are protected by
11 dquot_srcu. Annotate the array pointers with __rcu, perform the locked
12 dereferences with srcu_dereference_check() instead of plain reads, and
13 set the array elements with rcu_assign_pointer().
14
15 Fixes: b9ba6f94b238 ("quota: remove dqptr_sem")
16 Reported-by: kernel test robot <lkp@intel.com>
17 Closes: https://lore.kernel.org/oe-kbuild-all/202402061900.rTuYDlo6-lkp@intel.com/
18 Signed-off-by: Jan Kara <jack@suse.cz>
19 Signed-off-by: Sasha Levin <sashal@kernel.org>
20 ---
21 fs/quota/dquot.c | 66 ++++++++++++++++++++++++++++--------------------
22 1 file changed, 39 insertions(+), 27 deletions(-)
23
24 diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c
25 index 44c4da364c994..b67557647d61f 100644
26 --- a/fs/quota/dquot.c
27 +++ b/fs/quota/dquot.c
28 @@ -399,7 +399,7 @@ int dquot_mark_dquot_dirty(struct dquot *dquot)
29 EXPORT_SYMBOL(dquot_mark_dquot_dirty);
30
31 /* Dirtify all the dquots - this can block when journalling */
32 -static inline int mark_all_dquot_dirty(struct dquot * const *dquots)
33 +static inline int mark_all_dquot_dirty(struct dquot __rcu * const *dquots)
34 {
35 int ret, err, cnt;
36 struct dquot *dquot;
37 @@ -1006,14 +1006,15 @@ struct dquot *dqget(struct super_block *sb, struct kqid qid)
38 }
39 EXPORT_SYMBOL(dqget);
40
41 -static inline struct dquot **i_dquot(struct inode *inode)
42 +static inline struct dquot __rcu **i_dquot(struct inode *inode)
43 {
44 - return inode->i_sb->s_op->get_dquots(inode);
45 + /* Force __rcu for now until filesystems are fixed */
46 + return (struct dquot __rcu **)inode->i_sb->s_op->get_dquots(inode);
47 }
48
49 static int dqinit_needed(struct inode *inode, int type)
50 {
51 - struct dquot * const *dquots;
52 + struct dquot __rcu * const *dquots;
53 int cnt;
54
55 if (IS_NOQUOTA(inode))
56 @@ -1103,14 +1104,16 @@ static void remove_dquot_ref(struct super_block *sb, int type)
57 */
58 spin_lock(&dq_data_lock);
59 if (!IS_NOQUOTA(inode)) {
60 - struct dquot **dquots = i_dquot(inode);
61 - struct dquot *dquot = dquots[type];
62 + struct dquot __rcu **dquots = i_dquot(inode);
63 + struct dquot *dquot = srcu_dereference_check(
64 + dquots[type], &dquot_srcu,
65 + lockdep_is_held(&dq_data_lock));
66
67 #ifdef CONFIG_QUOTA_DEBUG
68 if (unlikely(inode_get_rsv_space(inode) > 0))
69 reserved = 1;
70 #endif
71 - dquots[type] = NULL;
72 + rcu_assign_pointer(dquots[type], NULL);
73 if (dquot)
74 dqput(dquot);
75 }
76 @@ -1463,7 +1466,8 @@ static int inode_quota_active(const struct inode *inode)
77 static int __dquot_initialize(struct inode *inode, int type)
78 {
79 int cnt, init_needed = 0;
80 - struct dquot **dquots, *got[MAXQUOTAS] = {};
81 + struct dquot __rcu **dquots;
82 + struct dquot *got[MAXQUOTAS] = {};
83 struct super_block *sb = inode->i_sb;
84 qsize_t rsv;
85 int ret = 0;
86 @@ -1538,7 +1542,7 @@ static int __dquot_initialize(struct inode *inode, int type)
87 if (!got[cnt])
88 continue;
89 if (!dquots[cnt]) {
90 - dquots[cnt] = got[cnt];
91 + rcu_assign_pointer(dquots[cnt], got[cnt]);
92 got[cnt] = NULL;
93 /*
94 * Make quota reservation system happy if someone
95 @@ -1546,12 +1550,16 @@ static int __dquot_initialize(struct inode *inode, int type)
96 */
97 rsv = inode_get_rsv_space(inode);
98 if (unlikely(rsv)) {
99 + struct dquot *dquot = srcu_dereference_check(
100 + dquots[cnt], &dquot_srcu,
101 + lockdep_is_held(&dq_data_lock));
102 +
103 spin_lock(&inode->i_lock);
104 /* Get reservation again under proper lock */
105 rsv = __inode_get_rsv_space(inode);
106 - spin_lock(&dquots[cnt]->dq_dqb_lock);
107 - dquots[cnt]->dq_dqb.dqb_rsvspace += rsv;
108 - spin_unlock(&dquots[cnt]->dq_dqb_lock);
109 + spin_lock(&dquot->dq_dqb_lock);
110 + dquot->dq_dqb.dqb_rsvspace += rsv;
111 + spin_unlock(&dquot->dq_dqb_lock);
112 spin_unlock(&inode->i_lock);
113 }
114 }
115 @@ -1573,7 +1581,7 @@ EXPORT_SYMBOL(dquot_initialize);
116
117 bool dquot_initialize_needed(struct inode *inode)
118 {
119 - struct dquot **dquots;
120 + struct dquot __rcu **dquots;
121 int i;
122
123 if (!inode_quota_active(inode))
124 @@ -1598,13 +1606,14 @@ EXPORT_SYMBOL(dquot_initialize_needed);
125 static void __dquot_drop(struct inode *inode)
126 {
127 int cnt;
128 - struct dquot **dquots = i_dquot(inode);
129 + struct dquot __rcu **dquots = i_dquot(inode);
130 struct dquot *put[MAXQUOTAS];
131
132 spin_lock(&dq_data_lock);
133 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
134 - put[cnt] = dquots[cnt];
135 - dquots[cnt] = NULL;
136 + put[cnt] = srcu_dereference_check(dquots[cnt], &dquot_srcu,
137 + lockdep_is_held(&dq_data_lock));
138 + rcu_assign_pointer(dquots[cnt], NULL);
139 }
140 spin_unlock(&dq_data_lock);
141 dqput_all(put);
142 @@ -1612,7 +1621,7 @@ static void __dquot_drop(struct inode *inode)
143
144 void dquot_drop(struct inode *inode)
145 {
146 - struct dquot * const *dquots;
147 + struct dquot __rcu * const *dquots;
148 int cnt;
149
150 if (IS_NOQUOTA(inode))
151 @@ -1685,7 +1694,7 @@ int __dquot_alloc_space(struct inode *inode, qsize_t number, int flags)
152 int cnt, ret = 0, index;
153 struct dquot_warn warn[MAXQUOTAS];
154 int reserve = flags & DQUOT_SPACE_RESERVE;
155 - struct dquot **dquots;
156 + struct dquot __rcu **dquots;
157 struct dquot *dquot;
158
159 if (!inode_quota_active(inode)) {
160 @@ -1755,7 +1764,7 @@ int dquot_alloc_inode(struct inode *inode)
161 {
162 int cnt, ret = 0, index;
163 struct dquot_warn warn[MAXQUOTAS];
164 - struct dquot * const *dquots;
165 + struct dquot __rcu * const *dquots;
166 struct dquot *dquot;
167
168 if (!inode_quota_active(inode))
169 @@ -1800,7 +1809,7 @@ EXPORT_SYMBOL(dquot_alloc_inode);
170 */
171 int dquot_claim_space_nodirty(struct inode *inode, qsize_t number)
172 {
173 - struct dquot **dquots;
174 + struct dquot __rcu **dquots;
175 struct dquot *dquot;
176 int cnt, index;
177
178 @@ -1842,7 +1851,7 @@ EXPORT_SYMBOL(dquot_claim_space_nodirty);
179 */
180 void dquot_reclaim_space_nodirty(struct inode *inode, qsize_t number)
181 {
182 - struct dquot **dquots;
183 + struct dquot __rcu **dquots;
184 struct dquot *dquot;
185 int cnt, index;
186
187 @@ -1886,7 +1895,7 @@ void __dquot_free_space(struct inode *inode, qsize_t number, int flags)
188 {
189 unsigned int cnt;
190 struct dquot_warn warn[MAXQUOTAS];
191 - struct dquot **dquots;
192 + struct dquot __rcu **dquots;
193 struct dquot *dquot;
194 int reserve = flags & DQUOT_SPACE_RESERVE, index;
195
196 @@ -1943,7 +1952,7 @@ void dquot_free_inode(struct inode *inode)
197 {
198 unsigned int cnt;
199 struct dquot_warn warn[MAXQUOTAS];
200 - struct dquot * const *dquots;
201 + struct dquot __rcu * const *dquots;
202 struct dquot *dquot;
203 int index;
204
205 @@ -1990,6 +1999,7 @@ int __dquot_transfer(struct inode *inode, struct dquot **transfer_to)
206 qsize_t cur_space;
207 qsize_t rsv_space = 0;
208 qsize_t inode_usage = 1;
209 + struct dquot __rcu **dquots;
210 struct dquot *transfer_from[MAXQUOTAS] = {};
211 int cnt, index, ret = 0;
212 char is_valid[MAXQUOTAS] = {};
213 @@ -2022,6 +2032,7 @@ int __dquot_transfer(struct inode *inode, struct dquot **transfer_to)
214 }
215 cur_space = __inode_get_bytes(inode);
216 rsv_space = __inode_get_rsv_space(inode);
217 + dquots = i_dquot(inode);
218 /*
219 * Build the transfer_from list, check limits, and update usage in
220 * the target structures.
221 @@ -2036,7 +2047,8 @@ int __dquot_transfer(struct inode *inode, struct dquot **transfer_to)
222 if (!sb_has_quota_active(inode->i_sb, cnt))
223 continue;
224 is_valid[cnt] = 1;
225 - transfer_from[cnt] = i_dquot(inode)[cnt];
226 + transfer_from[cnt] = srcu_dereference_check(dquots[cnt],
227 + &dquot_srcu, lockdep_is_held(&dq_data_lock));
228 ret = dquot_add_inodes(transfer_to[cnt], inode_usage,
229 &warn_to[cnt]);
230 if (ret)
231 @@ -2075,7 +2087,7 @@ int __dquot_transfer(struct inode *inode, struct dquot **transfer_to)
232 rsv_space);
233 spin_unlock(&transfer_from[cnt]->dq_dqb_lock);
234 }
235 - i_dquot(inode)[cnt] = transfer_to[cnt];
236 + rcu_assign_pointer(dquots[cnt], transfer_to[cnt]);
237 }
238 spin_unlock(&inode->i_lock);
239 spin_unlock(&dq_data_lock);
240 @@ -2086,8 +2098,8 @@ int __dquot_transfer(struct inode *inode, struct dquot **transfer_to)
241 * mark_all_dquot_dirty().
242 */
243 index = srcu_read_lock(&dquot_srcu);
244 - mark_all_dquot_dirty(transfer_from);
245 - mark_all_dquot_dirty(transfer_to);
246 + mark_all_dquot_dirty((struct dquot __rcu **)transfer_from);
247 + mark_all_dquot_dirty((struct dquot __rcu **)transfer_to);
248 srcu_read_unlock(&dquot_srcu, index);
249
250 flush_warnings(warn_to);
251 --
252 2.43.0
253