quota: fix dquot_disable vs dquot_transfer race v2
authorDmitry <dmonakhov@openvz.org>
Sat, 9 Oct 2010 19:15:30 +0000 (23:15 +0400)
committerJan Kara <jack@suse.cz>
Wed, 27 Oct 2010 23:30:02 +0000 (01:30 +0200)
I've got following lockup:
dquot_disable                              dquot_transfer
                                            ->dqget()
       sb_has_quota_active
dqopt->flags &= ~dquot_state_flag(f, cnt)      atomic_inc(dq->dq_count)
 ->drop_dquot_ref(sb, cnt);
    down_write(dqptr_sem)
    inode->i_dquot[cnt] = NULL              ->__dquot_transfer
invalidate_dquots(sb, cnt);        down_write(&dqptr_sem)
  ->wait for dq_wait_unused        inode->i_dquot = new_dquot
  /* wait forever */                            ^^^^New quota user^^^^^^

We cannot allow new references to dquots from inodes after drop_dquot_ref()
has removed them.  We have to recheck quota state under dqptr_sem and before
assignment, as we do it in dquot_initialize().

Signed-off-by: Dmitry Monakhov <dmonakhov@gmail.com>
Signed-off-by: Jan Kara <jack@suse.cz>

No differences found