diff --git a/fs/ocfs2/quota_global.c b/fs/ocfs2/quota_global.c index e85b1ccf81be..136aaaae27f3 100644 --- a/fs/ocfs2/quota_global.c +++ b/fs/ocfs2/quota_global.c @@ -821,6 +821,19 @@ static int ocfs2_acquire_dquot(struct dquot *dquot) trace_ocfs2_acquire_dquot(from_kqid(&init_user_ns, dquot->dq_id), type); mutex_lock(&dquot->dq_lock); + /* + * Extend global quota file before acquiring global qf lock to avoid + * lock inversion with sb_internal (via ocfs2_start_trans). + */ + if (need_alloc) { + WARN_ON(journal_current_handle()); + status = ocfs2_extend_no_holes(gqinode, NULL, + i_size_read(gqinode) + (need_alloc << sb->s_blocksize_bits), + i_size_read(gqinode)); + if (status < 0) + goto out; + } + /* * We need an exclusive lock, because we're going to update use count * and instantiate possibly new dquot structure @@ -843,19 +856,8 @@ static int ocfs2_acquire_dquot(struct dquot *dquot) OCFS2_DQUOT(dquot)->dq_use_count++; OCFS2_DQUOT(dquot)->dq_origspace = dquot->dq_dqb.dqb_curspace; OCFS2_DQUOT(dquot)->dq_originodes = dquot->dq_dqb.dqb_curinodes; - if (!dquot->dq_off) { /* No real quota entry? */ + if (!dquot->dq_off) /* No real quota entry? */ ex = 1; - /* - * Add blocks to quota file before we start a transaction since - * locking allocators ranks above a transaction start - */ - WARN_ON(journal_current_handle()); - status = ocfs2_extend_no_holes(gqinode, NULL, - i_size_read(gqinode) + (need_alloc << sb->s_blocksize_bits), - i_size_read(gqinode)); - if (status < 0) - goto out_dq; - } handle = ocfs2_start_trans(osb, ocfs2_calc_global_qinit_credits(sb, type));