···52635263 return 0;52645264}5265526552665266-/* Helper function for writing quotas on sync - we need to start transaction52675267- * before quota file is locked for write. Otherwise the are possible deadlocks:52685268- * Process 1 Process 252695269- * ext4_create() quota_sync()52705270- * jbd2_journal_start() write_dquot()52715271- * dquot_initialize() down(dqio_mutex)52725272- * down(dqio_mutex) jbd2_journal_start()52735273- *52745274- */5275526652765267#ifdef CONFIG_QUOTA5277526852695269+/*52705270+ * Helper functions so that transaction is started before we acquire dqio_sem52715271+ * to keep correct lock ordering of transaction > dqio_sem52725272+ */52785273static inline struct inode *dquot_to_inode(struct dquot *dquot)52795274{52805275 return sb_dqopt(dquot->dq_sb)->files[dquot->dq_id.type];
+10-10
fs/ocfs2/quota_global.c
···3333 * Locking of quotas with OCFS2 is rather complex. Here are rules that3434 * should be obeyed by all the functions:3535 * - any write of quota structure (either to local or global file) is protected3636- * by dqio_mutex or dquot->dq_lock.3636+ * by dqio_sem or dquot->dq_lock.3737 * - any modification of global quota file holds inode cluster lock, i_mutex,3838 * and ip_alloc_sem of the global quota file (achieved by3939 * ocfs2_lock_global_qf). It also has to hold qinfo_lock.···4242 *4343 * A rough sketch of locking dependencies (lf = local file, gf = global file):4444 * Normal filesystem operation:4545- * start_trans -> dqio_mutex -> write to lf4545+ * start_trans -> dqio_sem -> write to lf4646 * Syncing of local and global file:4747- * ocfs2_lock_global_qf -> start_trans -> dqio_mutex -> qinfo_lock ->4747+ * ocfs2_lock_global_qf -> start_trans -> dqio_sem -> qinfo_lock ->4848 * write to gf4949 * -> write to lf5050 * Acquire dquot for the first time:···6060 * Recovery:6161 * inode cluster lock of recovered lf6262 * -> read bitmaps -> ip_alloc_sem of lf6363- * -> ocfs2_lock_global_qf -> start_trans -> dqio_mutex -> qinfo_lock ->6363+ * -> ocfs2_lock_global_qf -> start_trans -> dqio_sem -> qinfo_lock ->6464 * write to gf6565 */6666···611611 mlog_errno(status);612612 goto out_ilock;613613 }614614- mutex_lock(&sb_dqopt(sb)->dqio_mutex);614614+ down_write(&sb_dqopt(sb)->dqio_sem);615615 status = ocfs2_sync_dquot(dquot);616616 if (status < 0)617617 mlog_errno(status);···619619 status = ocfs2_local_write_dquot(dquot);620620 if (status < 0)621621 mlog_errno(status);622622- mutex_unlock(&sb_dqopt(sb)->dqio_mutex);622622+ up_write(&sb_dqopt(sb)->dqio_sem);623623 ocfs2_commit_trans(osb, handle);624624out_ilock:625625 ocfs2_unlock_global_qf(oinfo, 1);···666666 mlog_errno(status);667667 goto out;668668 }669669- mutex_lock(&sb_dqopt(dquot->dq_sb)->dqio_mutex);669669+ down_write(&sb_dqopt(dquot->dq_sb)->dqio_sem);670670 status = ocfs2_local_write_dquot(dquot);671671- mutex_unlock(&sb_dqopt(dquot->dq_sb)->dqio_mutex);671671+ up_write(&sb_dqopt(dquot->dq_sb)->dqio_sem);672672 ocfs2_commit_trans(osb, handle);673673out:674674 return status;···939939 mlog_errno(status);940940 goto out_ilock;941941 }942942- mutex_lock(&sb_dqopt(sb)->dqio_mutex);942942+ down_write(&sb_dqopt(sb)->dqio_sem);943943 status = ocfs2_sync_dquot(dquot);944944 if (status < 0) {945945 mlog_errno(status);···948948 /* Now write updated local dquot structure */949949 status = ocfs2_local_write_dquot(dquot);950950out_dlock:951951- mutex_unlock(&sb_dqopt(sb)->dqio_mutex);951951+ up_write(&sb_dqopt(sb)->dqio_sem);952952 ocfs2_commit_trans(osb, handle);953953out_ilock:954954 ocfs2_unlock_global_qf(oinfo, 1);
+5-5
fs/ocfs2/quota_local.c
···520520 mlog_errno(status);521521 goto out_drop_lock;522522 }523523- mutex_lock(&sb_dqopt(sb)->dqio_mutex);523523+ down_write(&sb_dqopt(sb)->dqio_sem);524524 spin_lock(&dq_data_lock);525525 /* Add usage from quota entry into quota changes526526 * of our node. Auxiliary variables are important···553553 unlock_buffer(qbh);554554 ocfs2_journal_dirty(handle, qbh);555555out_commit:556556- mutex_unlock(&sb_dqopt(sb)->dqio_mutex);556556+ up_write(&sb_dqopt(sb)->dqio_sem);557557 ocfs2_commit_trans(OCFS2_SB(sb), handle);558558out_drop_lock:559559 ocfs2_unlock_global_qf(oinfo, 1);···693693694694 /* We don't need the lock and we have to acquire quota file locks695695 * which will later depend on this lock */696696- mutex_unlock(&sb_dqopt(sb)->dqio_mutex);696696+ up_write(&sb_dqopt(sb)->dqio_sem);697697 info->dqi_max_spc_limit = 0x7fffffffffffffffLL;698698 info->dqi_max_ino_limit = 0x7fffffffffffffffLL;699699 oinfo = kmalloc(sizeof(struct ocfs2_mem_dqinfo), GFP_NOFS);···772772 goto out_err;773773 }774774775775- mutex_lock(&sb_dqopt(sb)->dqio_mutex);775775+ down_write(&sb_dqopt(sb)->dqio_sem);776776 return 0;777777out_err:778778 if (oinfo) {···786786 kfree(oinfo);787787 }788788 brelse(bh);789789- mutex_lock(&sb_dqopt(sb)->dqio_mutex);789789+ down_write(&sb_dqopt(sb)->dqio_sem);790790 return -1;791791}792792
+14-14
fs/quota/dquot.c
···120120 * spinlock to internal buffers before writing.121121 *122122 * Lock ordering (including related VFS locks) is the following:123123- * s_umount > i_mutex > journal_lock > dquot->dq_lock > dqio_mutex123123+ * s_umount > i_mutex > journal_lock > dquot->dq_lock > dqio_sem124124 */125125126126static __cacheline_aligned_in_smp DEFINE_SPINLOCK(dq_list_lock);···406406 struct quota_info *dqopt = sb_dqopt(dquot->dq_sb);407407408408 mutex_lock(&dquot->dq_lock);409409- mutex_lock(&dqopt->dqio_mutex);409409+ down_write(&dqopt->dqio_sem);410410 if (!test_bit(DQ_READ_B, &dquot->dq_flags))411411 ret = dqopt->ops[dquot->dq_id.type]->read_dqblk(dquot);412412 if (ret < 0)···436436 smp_mb__before_atomic();437437 set_bit(DQ_ACTIVE_B, &dquot->dq_flags);438438out_iolock:439439- mutex_unlock(&dqopt->dqio_mutex);439439+ up_write(&dqopt->dqio_sem);440440 mutex_unlock(&dquot->dq_lock);441441 return ret;442442}···450450 int ret = 0;451451 struct quota_info *dqopt = sb_dqopt(dquot->dq_sb);452452453453- mutex_lock(&dqopt->dqio_mutex);453453+ down_write(&dqopt->dqio_sem);454454 spin_lock(&dq_list_lock);455455 if (!clear_dquot_dirty(dquot)) {456456 spin_unlock(&dq_list_lock);···464464 else465465 ret = -EIO;466466out_sem:467467- mutex_unlock(&dqopt->dqio_mutex);467467+ up_write(&dqopt->dqio_sem);468468 return ret;469469}470470EXPORT_SYMBOL(dquot_commit);···481481 /* Check whether we are not racing with some other dqget() */482482 if (atomic_read(&dquot->dq_count) > 1)483483 goto out_dqlock;484484- mutex_lock(&dqopt->dqio_mutex);484484+ down_write(&dqopt->dqio_sem);485485 if (dqopt->ops[dquot->dq_id.type]->release_dqblk) {486486 ret = dqopt->ops[dquot->dq_id.type]->release_dqblk(dquot);487487 /* Write the info */···493493 ret = ret2;494494 }495495 clear_bit(DQ_ACTIVE_B, &dquot->dq_flags);496496- mutex_unlock(&dqopt->dqio_mutex);496496+ up_write(&dqopt->dqio_sem);497497out_dqlock:498498 mutex_unlock(&dquot->dq_lock);499499 return ret;···20602060 int ret;20612061 struct quota_info *dqopt = sb_dqopt(sb);2062206220632063- mutex_lock(&dqopt->dqio_mutex);20632063+ down_write(&dqopt->dqio_sem);20642064 ret = dqopt->ops[type]->write_file_info(sb, type);20652065- mutex_unlock(&dqopt->dqio_mutex);20652065+ up_write(&dqopt->dqio_sem);20662066 return ret;20672067}20682068EXPORT_SYMBOL(dquot_commit_info);···20762076 return -ESRCH;20772077 if (!dqopt->ops[qid->type]->get_next_id)20782078 return -ENOSYS;20792079- mutex_lock(&dqopt->dqio_mutex);20792079+ down_write(&dqopt->dqio_sem);20802080 err = dqopt->ops[qid->type]->get_next_id(sb, qid);20812081- mutex_unlock(&dqopt->dqio_mutex);20812081+ up_write(&dqopt->dqio_sem);20822082 return err;20832083}20842084EXPORT_SYMBOL(dquot_get_next_id);···23282328 dqopt->info[type].dqi_format = fmt;23292329 dqopt->info[type].dqi_fmt_id = format_id;23302330 INIT_LIST_HEAD(&dqopt->info[type].dqi_dirty_list);23312331- mutex_lock(&dqopt->dqio_mutex);23312331+ down_write(&dqopt->dqio_sem);23322332 error = dqopt->ops[type]->read_file_info(sb, type);23332333 if (error < 0) {23342334- mutex_unlock(&dqopt->dqio_mutex);23342334+ up_write(&dqopt->dqio_sem);23352335 goto out_file_init;23362336 }23372337 if (dqopt->flags & DQUOT_QUOTA_SYS_FILE)23382338 dqopt->info[type].dqi_flags |= DQF_SYS_FILE;23392339- mutex_unlock(&dqopt->dqio_mutex);23392339+ up_write(&dqopt->dqio_sem);23402340 spin_lock(&dq_state_lock);23412341 dqopt->flags |= dquot_state_flag(flags, type);23422342 spin_unlock(&dq_state_lock);
+1-1
fs/quota/quota_tree.c
···379379 if (!ddquot)380380 return -ENOMEM;381381382382- /* dq_off is guarded by dqio_mutex */382382+ /* dq_off is guarded by dqio_sem */383383 if (!dquot->dq_off) {384384 ret = dq_insert_tree(info, dquot);385385 if (ret < 0) {
···521521522522struct quota_info {523523 unsigned int flags; /* Flags for diskquotas on this device */524524- struct mutex dqio_mutex; /* lock device while I/O in progress */524524+ struct rw_semaphore dqio_sem; /* Lock quota file while I/O in progress */525525 struct inode *files[MAXQUOTAS]; /* inodes of quotafiles */526526 struct mem_dqinfo info[MAXQUOTAS]; /* Information for each quota type */527527 const struct quota_format_ops *ops[MAXQUOTAS]; /* Operations for each type */