return 0;
 }
 
-/* Helper function for writing quotas on sync - we need to start transaction
- * before quota file is locked for write. Otherwise the are possible deadlocks:
- * Process 1                         Process 2
- * ext4_create()                     quota_sync()
- *   jbd2_journal_start()                  write_dquot()
- *   dquot_initialize()                         down(dqio_mutex)
- *     down(dqio_mutex)                    jbd2_journal_start()
- *
- */
 
 #ifdef CONFIG_QUOTA
 
+/*
+ * Helper functions so that transaction is started before we acquire dqio_sem
+ * to keep correct lock ordering of transaction > dqio_sem
+ */
 static inline struct inode *dquot_to_inode(struct dquot *dquot)
 {
        return sb_dqopt(dquot->dq_sb)->files[dquot->dq_id.type];
 
  * Locking of quotas with OCFS2 is rather complex. Here are rules that
  * should be obeyed by all the functions:
  * - any write of quota structure (either to local or global file) is protected
- *   by dqio_mutex or dquot->dq_lock.
+ *   by dqio_sem or dquot->dq_lock.
  * - any modification of global quota file holds inode cluster lock, i_mutex,
  *   and ip_alloc_sem of the global quota file (achieved by
  *   ocfs2_lock_global_qf). It also has to hold qinfo_lock.
  *
  * A rough sketch of locking dependencies (lf = local file, gf = global file):
  * Normal filesystem operation:
- *   start_trans -> dqio_mutex -> write to lf
+ *   start_trans -> dqio_sem -> write to lf
  * Syncing of local and global file:
- *   ocfs2_lock_global_qf -> start_trans -> dqio_mutex -> qinfo_lock ->
+ *   ocfs2_lock_global_qf -> start_trans -> dqio_sem -> qinfo_lock ->
  *     write to gf
  *                                                    -> write to lf
  * Acquire dquot for the first time:
  * Recovery:
  *   inode cluster lock of recovered lf
  *     -> read bitmaps -> ip_alloc_sem of lf
- *     -> ocfs2_lock_global_qf -> start_trans -> dqio_mutex -> qinfo_lock ->
+ *     -> ocfs2_lock_global_qf -> start_trans -> dqio_sem -> qinfo_lock ->
  *        write to gf
  */
 
                mlog_errno(status);
                goto out_ilock;
        }
-       mutex_lock(&sb_dqopt(sb)->dqio_mutex);
+       down_write(&sb_dqopt(sb)->dqio_sem);
        status = ocfs2_sync_dquot(dquot);
        if (status < 0)
                mlog_errno(status);
        status = ocfs2_local_write_dquot(dquot);
        if (status < 0)
                mlog_errno(status);
-       mutex_unlock(&sb_dqopt(sb)->dqio_mutex);
+       up_write(&sb_dqopt(sb)->dqio_sem);
        ocfs2_commit_trans(osb, handle);
 out_ilock:
        ocfs2_unlock_global_qf(oinfo, 1);
                mlog_errno(status);
                goto out;
        }
-       mutex_lock(&sb_dqopt(dquot->dq_sb)->dqio_mutex);
+       down_write(&sb_dqopt(dquot->dq_sb)->dqio_sem);
        status = ocfs2_local_write_dquot(dquot);
-       mutex_unlock(&sb_dqopt(dquot->dq_sb)->dqio_mutex);
+       up_write(&sb_dqopt(dquot->dq_sb)->dqio_sem);
        ocfs2_commit_trans(osb, handle);
 out:
        return status;
                mlog_errno(status);
                goto out_ilock;
        }
-       mutex_lock(&sb_dqopt(sb)->dqio_mutex);
+       down_write(&sb_dqopt(sb)->dqio_sem);
        status = ocfs2_sync_dquot(dquot);
        if (status < 0) {
                mlog_errno(status);
        /* Now write updated local dquot structure */
        status = ocfs2_local_write_dquot(dquot);
 out_dlock:
-       mutex_unlock(&sb_dqopt(sb)->dqio_mutex);
+       up_write(&sb_dqopt(sb)->dqio_sem);
        ocfs2_commit_trans(osb, handle);
 out_ilock:
        ocfs2_unlock_global_qf(oinfo, 1);
 
                                mlog_errno(status);
                                goto out_drop_lock;
                        }
-                       mutex_lock(&sb_dqopt(sb)->dqio_mutex);
+                       down_write(&sb_dqopt(sb)->dqio_sem);
                        spin_lock(&dq_data_lock);
                        /* Add usage from quota entry into quota changes
                         * of our node. Auxiliary variables are important
                        unlock_buffer(qbh);
                        ocfs2_journal_dirty(handle, qbh);
 out_commit:
-                       mutex_unlock(&sb_dqopt(sb)->dqio_mutex);
+                       up_write(&sb_dqopt(sb)->dqio_sem);
                        ocfs2_commit_trans(OCFS2_SB(sb), handle);
 out_drop_lock:
                        ocfs2_unlock_global_qf(oinfo, 1);
 
        /* We don't need the lock and we have to acquire quota file locks
         * which will later depend on this lock */
-       mutex_unlock(&sb_dqopt(sb)->dqio_mutex);
+       up_write(&sb_dqopt(sb)->dqio_sem);
        info->dqi_max_spc_limit = 0x7fffffffffffffffLL;
        info->dqi_max_ino_limit = 0x7fffffffffffffffLL;
        oinfo = kmalloc(sizeof(struct ocfs2_mem_dqinfo), GFP_NOFS);
                goto out_err;
        }
 
-       mutex_lock(&sb_dqopt(sb)->dqio_mutex);
+       down_write(&sb_dqopt(sb)->dqio_sem);
        return 0;
 out_err:
        if (oinfo) {
                kfree(oinfo);
        }
        brelse(bh);
-       mutex_lock(&sb_dqopt(sb)->dqio_mutex);
+       down_write(&sb_dqopt(sb)->dqio_sem);
        return -1;
 }
 
 
  * spinlock to internal buffers before writing.
  *
  * Lock ordering (including related VFS locks) is the following:
- *   s_umount > i_mutex > journal_lock > dquot->dq_lock > dqio_mutex
+ *   s_umount > i_mutex > journal_lock > dquot->dq_lock > dqio_sem
  */
 
 static __cacheline_aligned_in_smp DEFINE_SPINLOCK(dq_list_lock);
        struct quota_info *dqopt = sb_dqopt(dquot->dq_sb);
 
        mutex_lock(&dquot->dq_lock);
-       mutex_lock(&dqopt->dqio_mutex);
+       down_write(&dqopt->dqio_sem);
        if (!test_bit(DQ_READ_B, &dquot->dq_flags))
                ret = dqopt->ops[dquot->dq_id.type]->read_dqblk(dquot);
        if (ret < 0)
        smp_mb__before_atomic();
        set_bit(DQ_ACTIVE_B, &dquot->dq_flags);
 out_iolock:
-       mutex_unlock(&dqopt->dqio_mutex);
+       up_write(&dqopt->dqio_sem);
        mutex_unlock(&dquot->dq_lock);
        return ret;
 }
        int ret = 0;
        struct quota_info *dqopt = sb_dqopt(dquot->dq_sb);
 
-       mutex_lock(&dqopt->dqio_mutex);
+       down_write(&dqopt->dqio_sem);
        spin_lock(&dq_list_lock);
        if (!clear_dquot_dirty(dquot)) {
                spin_unlock(&dq_list_lock);
        else
                ret = -EIO;
 out_sem:
-       mutex_unlock(&dqopt->dqio_mutex);
+       up_write(&dqopt->dqio_sem);
        return ret;
 }
 EXPORT_SYMBOL(dquot_commit);
        /* Check whether we are not racing with some other dqget() */
        if (atomic_read(&dquot->dq_count) > 1)
                goto out_dqlock;
-       mutex_lock(&dqopt->dqio_mutex);
+       down_write(&dqopt->dqio_sem);
        if (dqopt->ops[dquot->dq_id.type]->release_dqblk) {
                ret = dqopt->ops[dquot->dq_id.type]->release_dqblk(dquot);
                /* Write the info */
                        ret = ret2;
        }
        clear_bit(DQ_ACTIVE_B, &dquot->dq_flags);
-       mutex_unlock(&dqopt->dqio_mutex);
+       up_write(&dqopt->dqio_sem);
 out_dqlock:
        mutex_unlock(&dquot->dq_lock);
        return ret;
        int ret;
        struct quota_info *dqopt = sb_dqopt(sb);
 
-       mutex_lock(&dqopt->dqio_mutex);
+       down_write(&dqopt->dqio_sem);
        ret = dqopt->ops[type]->write_file_info(sb, type);
-       mutex_unlock(&dqopt->dqio_mutex);
+       up_write(&dqopt->dqio_sem);
        return ret;
 }
 EXPORT_SYMBOL(dquot_commit_info);
                return -ESRCH;
        if (!dqopt->ops[qid->type]->get_next_id)
                return -ENOSYS;
-       mutex_lock(&dqopt->dqio_mutex);
+       down_write(&dqopt->dqio_sem);
        err = dqopt->ops[qid->type]->get_next_id(sb, qid);
-       mutex_unlock(&dqopt->dqio_mutex);
+       up_write(&dqopt->dqio_sem);
        return err;
 }
 EXPORT_SYMBOL(dquot_get_next_id);
        dqopt->info[type].dqi_format = fmt;
        dqopt->info[type].dqi_fmt_id = format_id;
        INIT_LIST_HEAD(&dqopt->info[type].dqi_dirty_list);
-       mutex_lock(&dqopt->dqio_mutex);
+       down_write(&dqopt->dqio_sem);
        error = dqopt->ops[type]->read_file_info(sb, type);
        if (error < 0) {
-               mutex_unlock(&dqopt->dqio_mutex);
+               up_write(&dqopt->dqio_sem);
                goto out_file_init;
        }
        if (dqopt->flags & DQUOT_QUOTA_SYS_FILE)
                dqopt->info[type].dqi_flags |= DQF_SYS_FILE;
-       mutex_unlock(&dqopt->dqio_mutex);
+       up_write(&dqopt->dqio_sem);
        spin_lock(&dq_state_lock);
        dqopt->flags |= dquot_state_flag(flags, type);
        spin_unlock(&dq_state_lock);
 
        if (!ddquot)
                return -ENOMEM;
 
-       /* dq_off is guarded by dqio_mutex */
+       /* dq_off is guarded by dqio_sem */
        if (!dquot->dq_off) {
                ret = dq_insert_tree(info, dquot);
                if (ret < 0) {
 
        atomic_set(&s->s_active, 1);
        mutex_init(&s->s_vfs_rename_mutex);
        lockdep_set_class(&s->s_vfs_rename_mutex, &type->s_vfs_rename_key);
-       mutex_init(&s->s_dquot.dqio_mutex);
+       init_rwsem(&s->s_dquot.dqio_sem);
        s->s_maxbytes = MAX_NON_LFS;
        s->s_op = &default_op;
        s->s_time_gran = 1000000000;
 
 
 struct quota_info {
        unsigned int flags;                     /* Flags for diskquotas on this device */
-       struct mutex dqio_mutex;                /* lock device while I/O in progress */
+       struct rw_semaphore dqio_sem;           /* Lock quota file while I/O in progress */
        struct inode *files[MAXQUOTAS];         /* inodes of quotafiles */
        struct mem_dqinfo info[MAXQUOTAS];      /* Information for each quota type */
        const struct quota_format_ops *ops[MAXQUOTAS];  /* Operations for each type */