Commit 15c34a76 authored by Jan Kara's avatar Jan Kara Committed by Linus Torvalds

ocfs2: fix quota file corruption

Global quota files are accessed from different nodes.  Thus we cannot
cache offset of quota structure in the quota file after we drop our node
reference count to it because after that moment quota structure may be
freed and reallocated elsewhere by a different node resulting in
corruption of quota file.

Fix the problem by clearing dq_off when we are releasing dquot structure.
We also remove the DB_READ_B handling because it is useless -
DQ_ACTIVE_B is set iff DQ_READ_B is set.
Signed-off-by: default avatarJan Kara <jack@suse.cz>
Cc: Goldwyn Rodrigues <rgoldwyn@suse.de>
Cc: Joel Becker <jlbec@evilplan.org>
Reviewed-by: default avatarMark Fasheh <mfasheh@suse.de>
Cc: <stable@vger.kernel.org>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 40d2d968
...@@ -717,6 +717,12 @@ static int ocfs2_release_dquot(struct dquot *dquot) ...@@ -717,6 +717,12 @@ static int ocfs2_release_dquot(struct dquot *dquot)
*/ */
if (status < 0) if (status < 0)
mlog_errno(status); mlog_errno(status);
/*
* Clear dq_off so that we search for the structure in quota file next
* time we acquire it. The structure might be deleted and reallocated
* elsewhere by another node while our dquot structure is on freelist.
*/
dquot->dq_off = 0;
clear_bit(DQ_ACTIVE_B, &dquot->dq_flags); clear_bit(DQ_ACTIVE_B, &dquot->dq_flags);
out_trans: out_trans:
ocfs2_commit_trans(osb, handle); ocfs2_commit_trans(osb, handle);
...@@ -756,16 +762,17 @@ static int ocfs2_acquire_dquot(struct dquot *dquot) ...@@ -756,16 +762,17 @@ static int ocfs2_acquire_dquot(struct dquot *dquot)
status = ocfs2_lock_global_qf(info, 1); status = ocfs2_lock_global_qf(info, 1);
if (status < 0) if (status < 0)
goto out; goto out;
if (!test_bit(DQ_READ_B, &dquot->dq_flags)) { status = ocfs2_qinfo_lock(info, 0);
status = ocfs2_qinfo_lock(info, 0); if (status < 0)
if (status < 0) goto out_dq;
goto out_dq; /*
status = qtree_read_dquot(&info->dqi_gi, dquot); * We always want to read dquot structure from disk because we don't
ocfs2_qinfo_unlock(info, 0); * know what happened with it while it was on freelist.
if (status < 0) */
goto out_dq; status = qtree_read_dquot(&info->dqi_gi, dquot);
} ocfs2_qinfo_unlock(info, 0);
set_bit(DQ_READ_B, &dquot->dq_flags); if (status < 0)
goto out_dq;
OCFS2_DQUOT(dquot)->dq_use_count++; OCFS2_DQUOT(dquot)->dq_use_count++;
OCFS2_DQUOT(dquot)->dq_origspace = dquot->dq_dqb.dqb_curspace; OCFS2_DQUOT(dquot)->dq_origspace = dquot->dq_dqb.dqb_curspace;
......
...@@ -1303,10 +1303,6 @@ int ocfs2_local_release_dquot(handle_t *handle, struct dquot *dquot) ...@@ -1303,10 +1303,6 @@ int ocfs2_local_release_dquot(handle_t *handle, struct dquot *dquot)
ocfs2_journal_dirty(handle, od->dq_chunk->qc_headerbh); ocfs2_journal_dirty(handle, od->dq_chunk->qc_headerbh);
out: out:
/* Clear the read bit so that next time someone uses this
* dquot he reads fresh info from disk and allocates local
* dquot structure */
clear_bit(DQ_READ_B, &dquot->dq_flags);
return status; return status;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment