Loading fs/ext4/super.c +4 −9 Original line number Diff line number Diff line Loading @@ -5263,18 +5263,13 @@ static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf) 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]; Loading fs/ocfs2/quota_global.c +10 −10 Original line number Diff line number Diff line Loading @@ -33,7 +33,7 @@ * 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. Loading @@ -42,9 +42,9 @@ * * 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: Loading @@ -60,7 +60,7 @@ * 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 */ Loading Loading @@ -611,7 +611,7 @@ static int ocfs2_sync_dquot_helper(struct dquot *dquot, unsigned long type) 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); Loading @@ -619,7 +619,7 @@ static int ocfs2_sync_dquot_helper(struct dquot *dquot, unsigned long type) 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); Loading Loading @@ -666,9 +666,9 @@ static int ocfs2_write_dquot(struct dquot *dquot) 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; Loading Loading @@ -939,7 +939,7 @@ static int ocfs2_mark_dquot_dirty(struct dquot *dquot) 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); Loading @@ -948,7 +948,7 @@ static int ocfs2_mark_dquot_dirty(struct dquot *dquot) /* 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); Loading fs/ocfs2/quota_local.c +5 −5 Original line number Diff line number Diff line Loading @@ -520,7 +520,7 @@ static int ocfs2_recover_local_quota_file(struct inode *lqinode, 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 Loading Loading @@ -553,7 +553,7 @@ static int ocfs2_recover_local_quota_file(struct inode *lqinode, 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); Loading Loading @@ -693,7 +693,7 @@ static int ocfs2_local_read_info(struct super_block *sb, int type) /* 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); Loading Loading @@ -772,7 +772,7 @@ static int ocfs2_local_read_info(struct super_block *sb, int type) goto out_err; } mutex_lock(&sb_dqopt(sb)->dqio_mutex); down_write(&sb_dqopt(sb)->dqio_sem); return 0; out_err: if (oinfo) { Loading @@ -786,7 +786,7 @@ static int ocfs2_local_read_info(struct super_block *sb, int type) kfree(oinfo); } brelse(bh); mutex_lock(&sb_dqopt(sb)->dqio_mutex); down_write(&sb_dqopt(sb)->dqio_sem); return -1; } Loading fs/quota/dquot.c +14 −14 Original line number Diff line number Diff line Loading @@ -120,7 +120,7 @@ * 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); Loading Loading @@ -406,7 +406,7 @@ int dquot_acquire(struct dquot *dquot) 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) Loading Loading @@ -436,7 +436,7 @@ int dquot_acquire(struct dquot *dquot) 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; } Loading @@ -450,7 +450,7 @@ int dquot_commit(struct dquot *dquot) 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); Loading @@ -464,7 +464,7 @@ int dquot_commit(struct dquot *dquot) else ret = -EIO; out_sem: mutex_unlock(&dqopt->dqio_mutex); up_write(&dqopt->dqio_sem); return ret; } EXPORT_SYMBOL(dquot_commit); Loading @@ -481,7 +481,7 @@ int dquot_release(struct dquot *dquot) /* 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 */ Loading @@ -493,7 +493,7 @@ int dquot_release(struct dquot *dquot) 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; Loading Loading @@ -2060,9 +2060,9 @@ int dquot_commit_info(struct super_block *sb, int type) 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); Loading @@ -2076,9 +2076,9 @@ int dquot_get_next_id(struct super_block *sb, struct kqid *qid) 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); Loading Loading @@ -2328,15 +2328,15 @@ static int vfs_load_quota_inode(struct inode *inode, int type, int format_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); Loading fs/quota/quota_tree.c +1 −1 Original line number Diff line number Diff line Loading @@ -379,7 +379,7 @@ int qtree_write_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot) 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) { Loading Loading
fs/ext4/super.c +4 −9 Original line number Diff line number Diff line Loading @@ -5263,18 +5263,13 @@ static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf) 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]; Loading
fs/ocfs2/quota_global.c +10 −10 Original line number Diff line number Diff line Loading @@ -33,7 +33,7 @@ * 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. Loading @@ -42,9 +42,9 @@ * * 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: Loading @@ -60,7 +60,7 @@ * 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 */ Loading Loading @@ -611,7 +611,7 @@ static int ocfs2_sync_dquot_helper(struct dquot *dquot, unsigned long type) 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); Loading @@ -619,7 +619,7 @@ static int ocfs2_sync_dquot_helper(struct dquot *dquot, unsigned long type) 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); Loading Loading @@ -666,9 +666,9 @@ static int ocfs2_write_dquot(struct dquot *dquot) 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; Loading Loading @@ -939,7 +939,7 @@ static int ocfs2_mark_dquot_dirty(struct dquot *dquot) 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); Loading @@ -948,7 +948,7 @@ static int ocfs2_mark_dquot_dirty(struct dquot *dquot) /* 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); Loading
fs/ocfs2/quota_local.c +5 −5 Original line number Diff line number Diff line Loading @@ -520,7 +520,7 @@ static int ocfs2_recover_local_quota_file(struct inode *lqinode, 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 Loading Loading @@ -553,7 +553,7 @@ static int ocfs2_recover_local_quota_file(struct inode *lqinode, 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); Loading Loading @@ -693,7 +693,7 @@ static int ocfs2_local_read_info(struct super_block *sb, int type) /* 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); Loading Loading @@ -772,7 +772,7 @@ static int ocfs2_local_read_info(struct super_block *sb, int type) goto out_err; } mutex_lock(&sb_dqopt(sb)->dqio_mutex); down_write(&sb_dqopt(sb)->dqio_sem); return 0; out_err: if (oinfo) { Loading @@ -786,7 +786,7 @@ static int ocfs2_local_read_info(struct super_block *sb, int type) kfree(oinfo); } brelse(bh); mutex_lock(&sb_dqopt(sb)->dqio_mutex); down_write(&sb_dqopt(sb)->dqio_sem); return -1; } Loading
fs/quota/dquot.c +14 −14 Original line number Diff line number Diff line Loading @@ -120,7 +120,7 @@ * 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); Loading Loading @@ -406,7 +406,7 @@ int dquot_acquire(struct dquot *dquot) 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) Loading Loading @@ -436,7 +436,7 @@ int dquot_acquire(struct dquot *dquot) 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; } Loading @@ -450,7 +450,7 @@ int dquot_commit(struct dquot *dquot) 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); Loading @@ -464,7 +464,7 @@ int dquot_commit(struct dquot *dquot) else ret = -EIO; out_sem: mutex_unlock(&dqopt->dqio_mutex); up_write(&dqopt->dqio_sem); return ret; } EXPORT_SYMBOL(dquot_commit); Loading @@ -481,7 +481,7 @@ int dquot_release(struct dquot *dquot) /* 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 */ Loading @@ -493,7 +493,7 @@ int dquot_release(struct dquot *dquot) 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; Loading Loading @@ -2060,9 +2060,9 @@ int dquot_commit_info(struct super_block *sb, int type) 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); Loading @@ -2076,9 +2076,9 @@ int dquot_get_next_id(struct super_block *sb, struct kqid *qid) 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); Loading Loading @@ -2328,15 +2328,15 @@ static int vfs_load_quota_inode(struct inode *inode, int type, int format_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); Loading
fs/quota/quota_tree.c +1 −1 Original line number Diff line number Diff line Loading @@ -379,7 +379,7 @@ int qtree_write_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot) 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) { Loading