quota: fix dquot_disable vs dquot_transfer race v2
commit9e32784b71c2c84895016ca6ab271591669c02aa
authorDmitry <dmonakhov@openvz.org>
Sat, 9 Oct 2010 19:15:30 +0000 (9 23:15 +0400)
committerJan Kara <jack@suse.cz>
Wed, 27 Oct 2010 23:30:02 +0000 (28 01:30 +0200)
treedb69a152de57f65666408591a06f15cb865c695f
parenta910eefa511f9d1118effc13fba6773163502c4f
quota: fix dquot_disable vs dquot_transfer race v2

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>
fs/quota/dquot.c