• Jan Kara's avatar
    quota: Fix race between dqput() and dquot_scan_active() · 1362f4ea
    Jan Kara authored
    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.
    
    CC: stable@vger.kernel.org # >= 2.6.29
    Signed-off-by: default avatarJan Kara <jack@suse.cz>
    1362f4ea
dquot.c 74.7 KB