]> git.ipfire.org Git - people/arne_f/kernel.git/commit
quota: Fix race between dqput() and dquot_scan_active()
authorJan Kara <jack@suse.cz>
Thu, 20 Feb 2014 16:02:27 +0000 (17:02 +0100)
committerJiri Slaby <jslaby@suse.cz>
Wed, 5 Mar 2014 16:13:53 +0000 (17:13 +0100)
commitd1ea22966e9187b0b92f878a02686cbad4ab0d50
treeae33b17002fbc010259bc94d15884f5ef5d231c6
parentfea84e6b1cbfec4e124e06633a0d6febe7fad69a
quota: Fix race between dqput() and dquot_scan_active()

commit 1362f4ea20fa63688ba6026e586d9746ff13a846 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: Jiri Slaby <jslaby@suse.cz>
fs/quota/dquot.c