Skip to content

Commit e45e8aa

Browse files
jankaraSasha Levin
authored and
Sasha Levin
committed
quota: Fix rcu annotations of inode dquot pointers
[ Upstream commit 179b8c9 ] Dquot pointers in i_dquot array in the inode are protected by dquot_srcu. Annotate the array pointers with __rcu, perform the locked dereferences with srcu_dereference_check() instead of plain reads, and set the array elements with rcu_assign_pointer(). Fixes: b9ba6f9 ("quota: remove dqptr_sem") Reported-by: kernel test robot <[email protected]> Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/ Signed-off-by: Jan Kara <[email protected]> Signed-off-by: Sasha Levin <[email protected]>
1 parent 40a673b commit e45e8aa

File tree

1 file changed

+39
-27
lines changed

1 file changed

+39
-27
lines changed

fs/quota/dquot.c

+39-27
Original file line numberDiff line numberDiff line change
@@ -399,7 +399,7 @@ int dquot_mark_dquot_dirty(struct dquot *dquot)
399399
EXPORT_SYMBOL(dquot_mark_dquot_dirty);
400400

401401
/* Dirtify all the dquots - this can block when journalling */
402-
static inline int mark_all_dquot_dirty(struct dquot * const *dquots)
402+
static inline int mark_all_dquot_dirty(struct dquot __rcu * const *dquots)
403403
{
404404
int ret, err, cnt;
405405
struct dquot *dquot;
@@ -1006,14 +1006,15 @@ struct dquot *dqget(struct super_block *sb, struct kqid qid)
10061006
}
10071007
EXPORT_SYMBOL(dqget);
10081008

1009-
static inline struct dquot **i_dquot(struct inode *inode)
1009+
static inline struct dquot __rcu **i_dquot(struct inode *inode)
10101010
{
1011-
return inode->i_sb->s_op->get_dquots(inode);
1011+
/* Force __rcu for now until filesystems are fixed */
1012+
return (struct dquot __rcu **)inode->i_sb->s_op->get_dquots(inode);
10121013
}
10131014

10141015
static int dqinit_needed(struct inode *inode, int type)
10151016
{
1016-
struct dquot * const *dquots;
1017+
struct dquot __rcu * const *dquots;
10171018
int cnt;
10181019

10191020
if (IS_NOQUOTA(inode))
@@ -1103,14 +1104,16 @@ static void remove_dquot_ref(struct super_block *sb, int type)
11031104
*/
11041105
spin_lock(&dq_data_lock);
11051106
if (!IS_NOQUOTA(inode)) {
1106-
struct dquot **dquots = i_dquot(inode);
1107-
struct dquot *dquot = dquots[type];
1107+
struct dquot __rcu **dquots = i_dquot(inode);
1108+
struct dquot *dquot = srcu_dereference_check(
1109+
dquots[type], &dquot_srcu,
1110+
lockdep_is_held(&dq_data_lock));
11081111

11091112
#ifdef CONFIG_QUOTA_DEBUG
11101113
if (unlikely(inode_get_rsv_space(inode) > 0))
11111114
reserved = 1;
11121115
#endif
1113-
dquots[type] = NULL;
1116+
rcu_assign_pointer(dquots[type], NULL);
11141117
if (dquot)
11151118
dqput(dquot);
11161119
}
@@ -1463,7 +1466,8 @@ static int inode_quota_active(const struct inode *inode)
14631466
static int __dquot_initialize(struct inode *inode, int type)
14641467
{
14651468
int cnt, init_needed = 0;
1466-
struct dquot **dquots, *got[MAXQUOTAS] = {};
1469+
struct dquot __rcu **dquots;
1470+
struct dquot *got[MAXQUOTAS] = {};
14671471
struct super_block *sb = inode->i_sb;
14681472
qsize_t rsv;
14691473
int ret = 0;
@@ -1538,20 +1542,24 @@ static int __dquot_initialize(struct inode *inode, int type)
15381542
if (!got[cnt])
15391543
continue;
15401544
if (!dquots[cnt]) {
1541-
dquots[cnt] = got[cnt];
1545+
rcu_assign_pointer(dquots[cnt], got[cnt]);
15421546
got[cnt] = NULL;
15431547
/*
15441548
* Make quota reservation system happy if someone
15451549
* did a write before quota was turned on
15461550
*/
15471551
rsv = inode_get_rsv_space(inode);
15481552
if (unlikely(rsv)) {
1553+
struct dquot *dquot = srcu_dereference_check(
1554+
dquots[cnt], &dquot_srcu,
1555+
lockdep_is_held(&dq_data_lock));
1556+
15491557
spin_lock(&inode->i_lock);
15501558
/* Get reservation again under proper lock */
15511559
rsv = __inode_get_rsv_space(inode);
1552-
spin_lock(&dquots[cnt]->dq_dqb_lock);
1553-
dquots[cnt]->dq_dqb.dqb_rsvspace += rsv;
1554-
spin_unlock(&dquots[cnt]->dq_dqb_lock);
1560+
spin_lock(&dquot->dq_dqb_lock);
1561+
dquot->dq_dqb.dqb_rsvspace += rsv;
1562+
spin_unlock(&dquot->dq_dqb_lock);
15551563
spin_unlock(&inode->i_lock);
15561564
}
15571565
}
@@ -1573,7 +1581,7 @@ EXPORT_SYMBOL(dquot_initialize);
15731581

15741582
bool dquot_initialize_needed(struct inode *inode)
15751583
{
1576-
struct dquot **dquots;
1584+
struct dquot __rcu **dquots;
15771585
int i;
15781586

15791587
if (!inode_quota_active(inode))
@@ -1598,21 +1606,22 @@ EXPORT_SYMBOL(dquot_initialize_needed);
15981606
static void __dquot_drop(struct inode *inode)
15991607
{
16001608
int cnt;
1601-
struct dquot **dquots = i_dquot(inode);
1609+
struct dquot __rcu **dquots = i_dquot(inode);
16021610
struct dquot *put[MAXQUOTAS];
16031611

16041612
spin_lock(&dq_data_lock);
16051613
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
1606-
put[cnt] = dquots[cnt];
1607-
dquots[cnt] = NULL;
1614+
put[cnt] = srcu_dereference_check(dquots[cnt], &dquot_srcu,
1615+
lockdep_is_held(&dq_data_lock));
1616+
rcu_assign_pointer(dquots[cnt], NULL);
16081617
}
16091618
spin_unlock(&dq_data_lock);
16101619
dqput_all(put);
16111620
}
16121621

16131622
void dquot_drop(struct inode *inode)
16141623
{
1615-
struct dquot * const *dquots;
1624+
struct dquot __rcu * const *dquots;
16161625
int cnt;
16171626

16181627
if (IS_NOQUOTA(inode))
@@ -1685,7 +1694,7 @@ int __dquot_alloc_space(struct inode *inode, qsize_t number, int flags)
16851694
int cnt, ret = 0, index;
16861695
struct dquot_warn warn[MAXQUOTAS];
16871696
int reserve = flags & DQUOT_SPACE_RESERVE;
1688-
struct dquot **dquots;
1697+
struct dquot __rcu **dquots;
16891698
struct dquot *dquot;
16901699

16911700
if (!inode_quota_active(inode)) {
@@ -1755,7 +1764,7 @@ int dquot_alloc_inode(struct inode *inode)
17551764
{
17561765
int cnt, ret = 0, index;
17571766
struct dquot_warn warn[MAXQUOTAS];
1758-
struct dquot * const *dquots;
1767+
struct dquot __rcu * const *dquots;
17591768
struct dquot *dquot;
17601769

17611770
if (!inode_quota_active(inode))
@@ -1800,7 +1809,7 @@ EXPORT_SYMBOL(dquot_alloc_inode);
18001809
*/
18011810
int dquot_claim_space_nodirty(struct inode *inode, qsize_t number)
18021811
{
1803-
struct dquot **dquots;
1812+
struct dquot __rcu **dquots;
18041813
struct dquot *dquot;
18051814
int cnt, index;
18061815

@@ -1842,7 +1851,7 @@ EXPORT_SYMBOL(dquot_claim_space_nodirty);
18421851
*/
18431852
void dquot_reclaim_space_nodirty(struct inode *inode, qsize_t number)
18441853
{
1845-
struct dquot **dquots;
1854+
struct dquot __rcu **dquots;
18461855
struct dquot *dquot;
18471856
int cnt, index;
18481857

@@ -1886,7 +1895,7 @@ void __dquot_free_space(struct inode *inode, qsize_t number, int flags)
18861895
{
18871896
unsigned int cnt;
18881897
struct dquot_warn warn[MAXQUOTAS];
1889-
struct dquot **dquots;
1898+
struct dquot __rcu **dquots;
18901899
struct dquot *dquot;
18911900
int reserve = flags & DQUOT_SPACE_RESERVE, index;
18921901

@@ -1943,7 +1952,7 @@ void dquot_free_inode(struct inode *inode)
19431952
{
19441953
unsigned int cnt;
19451954
struct dquot_warn warn[MAXQUOTAS];
1946-
struct dquot * const *dquots;
1955+
struct dquot __rcu * const *dquots;
19471956
struct dquot *dquot;
19481957
int index;
19491958

@@ -1990,6 +1999,7 @@ int __dquot_transfer(struct inode *inode, struct dquot **transfer_to)
19901999
qsize_t cur_space;
19912000
qsize_t rsv_space = 0;
19922001
qsize_t inode_usage = 1;
2002+
struct dquot __rcu **dquots;
19932003
struct dquot *transfer_from[MAXQUOTAS] = {};
19942004
int cnt, index, ret = 0;
19952005
char is_valid[MAXQUOTAS] = {};
@@ -2022,6 +2032,7 @@ int __dquot_transfer(struct inode *inode, struct dquot **transfer_to)
20222032
}
20232033
cur_space = __inode_get_bytes(inode);
20242034
rsv_space = __inode_get_rsv_space(inode);
2035+
dquots = i_dquot(inode);
20252036
/*
20262037
* Build the transfer_from list, check limits, and update usage in
20272038
* the target structures.
@@ -2036,7 +2047,8 @@ int __dquot_transfer(struct inode *inode, struct dquot **transfer_to)
20362047
if (!sb_has_quota_active(inode->i_sb, cnt))
20372048
continue;
20382049
is_valid[cnt] = 1;
2039-
transfer_from[cnt] = i_dquot(inode)[cnt];
2050+
transfer_from[cnt] = srcu_dereference_check(dquots[cnt],
2051+
&dquot_srcu, lockdep_is_held(&dq_data_lock));
20402052
ret = dquot_add_inodes(transfer_to[cnt], inode_usage,
20412053
&warn_to[cnt]);
20422054
if (ret)
@@ -2075,7 +2087,7 @@ int __dquot_transfer(struct inode *inode, struct dquot **transfer_to)
20752087
rsv_space);
20762088
spin_unlock(&transfer_from[cnt]->dq_dqb_lock);
20772089
}
2078-
i_dquot(inode)[cnt] = transfer_to[cnt];
2090+
rcu_assign_pointer(dquots[cnt], transfer_to[cnt]);
20792091
}
20802092
spin_unlock(&inode->i_lock);
20812093
spin_unlock(&dq_data_lock);
@@ -2086,8 +2098,8 @@ int __dquot_transfer(struct inode *inode, struct dquot **transfer_to)
20862098
* mark_all_dquot_dirty().
20872099
*/
20882100
index = srcu_read_lock(&dquot_srcu);
2089-
mark_all_dquot_dirty(transfer_from);
2090-
mark_all_dquot_dirty(transfer_to);
2101+
mark_all_dquot_dirty((struct dquot __rcu **)transfer_from);
2102+
mark_all_dquot_dirty((struct dquot __rcu **)transfer_to);
20912103
srcu_read_unlock(&dquot_srcu, index);
20922104

20932105
flush_warnings(warn_to);

0 commit comments

Comments
 (0)