mirror of
https://github.com/followmsi/android_kernel_google_msm.git
synced 2024-11-06 23:17:41 +00:00
quota: Fix race between dqput() and dquot_scan_active()
commit 1362f4ea20
upstream.
Currently last dqput() can race with dquot_scan_active() causing it to
call callback for an already deactivated dquot. The race is as follows:
CPU1 CPU2
dqput()
spin_lock(&dq_list_lock);
if (atomic_read(&dquot->dq_count) > 1) {
- not taken
if (test_bit(DQ_ACTIVE_B, &dquot->dq_flags)) {
spin_unlock(&dq_list_lock);
->release_dquot(dquot);
if (atomic_read(&dquot->dq_count) > 1)
- not taken
dquot_scan_active()
spin_lock(&dq_list_lock);
if (!test_bit(DQ_ACTIVE_B, &dquot->dq_flags))
- not taken
atomic_inc(&dquot->dq_count);
spin_unlock(&dq_list_lock);
- proceeds to release dquot
ret = fn(dquot, priv);
- called for inactive dquot
Fix the problem by making sure possible ->release_dquot() is finished by
the time we call the callback and new calls to it will notice reference
dquot_scan_active() has taken and bail out.
Signed-off-by: Jan Kara <jack@suse.cz>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
186ef2385c
commit
54499e71ec
1 changed files with 11 additions and 3 deletions
|
@ -580,9 +580,17 @@ int dquot_scan_active(struct super_block *sb,
|
|||
dqstats_inc(DQST_LOOKUPS);
|
||||
dqput(old_dquot);
|
||||
old_dquot = dquot;
|
||||
ret = fn(dquot, priv);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
/*
|
||||
* ->release_dquot() can be racing with us. Our reference
|
||||
* protects us from new calls to it so just wait for any
|
||||
* outstanding call and recheck the DQ_ACTIVE_B after that.
|
||||
*/
|
||||
wait_on_dquot(dquot);
|
||||
if (test_bit(DQ_ACTIVE_B, &dquot->dq_flags)) {
|
||||
ret = fn(dquot, priv);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
}
|
||||
spin_lock(&dq_list_lock);
|
||||
/* We are safe to continue now because our dquot could not
|
||||
* be moved out of the inuse list while we hold the reference */
|
||||
|
|
Loading…
Reference in a new issue