1 From 1362f4ea20fa63688ba6026e586d9746ff13a846 Mon Sep 17 00:00:00 2001
2 From: Jan Kara <jack@suse.cz>
3 Date: Thu, 20 Feb 2014 17:02:27 +0100
4 Subject: quota: Fix race between dqput() and dquot_scan_active()
6 From: Jan Kara <jack@suse.cz>
8 commit 1362f4ea20fa63688ba6026e586d9746ff13a846 upstream.
10 Currently last dqput() can race with dquot_scan_active() causing it to
11 call callback for an already deactivated dquot. The race is as follows:
15 spin_lock(&dq_list_lock);
16 if (atomic_read(&dquot->dq_count) > 1) {
18 if (test_bit(DQ_ACTIVE_B, &dquot->dq_flags)) {
19 spin_unlock(&dq_list_lock);
20 ->release_dquot(dquot);
21 if (atomic_read(&dquot->dq_count) > 1)
24 spin_lock(&dq_list_lock);
25 if (!test_bit(DQ_ACTIVE_B, &dquot->dq_flags))
27 atomic_inc(&dquot->dq_count);
28 spin_unlock(&dq_list_lock);
29 - proceeds to release dquot
30 ret = fn(dquot, priv);
31 - called for inactive dquot
33 Fix the problem by making sure possible ->release_dquot() is finished by
34 the time we call the callback and new calls to it will notice reference
35 dquot_scan_active() has taken and bail out.
37 Signed-off-by: Jan Kara <jack@suse.cz>
38 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
41 fs/quota/dquot.c | 14 +++++++++++---
42 1 file changed, 11 insertions(+), 3 deletions(-)
44 --- a/fs/quota/dquot.c
45 +++ b/fs/quota/dquot.c
46 @@ -580,9 +580,17 @@ int dquot_scan_active(struct super_block
47 dqstats_inc(DQST_LOOKUPS);
50 - ret = fn(dquot, priv);
54 + * ->release_dquot() can be racing with us. Our reference
55 + * protects us from new calls to it so just wait for any
56 + * outstanding call and recheck the DQ_ACTIVE_B after that.
58 + wait_on_dquot(dquot);
59 + if (test_bit(DQ_ACTIVE_B, &dquot->dq_flags)) {
60 + ret = fn(dquot, priv);
64 spin_lock(&dq_list_lock);
65 /* We are safe to continue now because our dquot could not
66 * be moved out of the inuse list while we hold the reference */