Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

quota: Get rid of nested I_MUTEX_QUOTA locking subclass

So far i_mutex was ranking above dqonoff_mutex and i_mutex on quota files
was special and ranking below dqonoff_mutex (and several other locks).
However there's no real need for i_mutex on quota files to be special.
IO on quota files is serialized by dqio_mutex anyway so we don't need to
take i_mutex when writing to quota files. Other places where we take i_mutex
on quota file can accomodate standard i_mutex lock ranking, we only need
to change the lock ranking to be dqonoff_mutex > i_mutex which is a matter
of changing documentation because there's no place which would enforce
ordering in the other direction.

Signed-off-by: Jan Kara <jack@suse.cz>

Jan Kara a80b12c3 f9ef1784

+6 -8
+6 -8
fs/quota/dquot.c
··· 116 116 * spinlock to internal buffers before writing. 117 117 * 118 118 * Lock ordering (including related VFS locks) is the following: 119 - * i_mutex > dqonoff_sem > journal_lock > dqptr_sem > dquot->dq_lock > 119 + * dqonoff_mutex > i_mutex > journal_lock > dqptr_sem > dquot->dq_lock > 120 120 * dqio_mutex 121 + * dqonoff_mutex > i_mutex comes from dquot_quota_sync, dquot_enable, etc. 121 122 * The lock ordering of dqptr_sem imposed by quota code is only dqonoff_sem > 122 123 * dqptr_sem. But filesystem has to count with the fact that functions such as 123 124 * dquot_alloc_space() acquire dqptr_sem and they usually have to be called 124 125 * from inside a transaction to keep filesystem consistency after a crash. Also 125 126 * filesystems usually want to do some IO on dquot from ->mark_dirty which is 126 127 * called with dqptr_sem held. 127 - * i_mutex on quota files is special (it's below dqio_mutex) 128 128 */ 129 129 130 130 static __cacheline_aligned_in_smp DEFINE_SPINLOCK(dq_list_lock); ··· 658 658 continue; 659 659 if (!sb_has_quota_active(sb, cnt)) 660 660 continue; 661 - mutex_lock_nested(&dqopt->files[cnt]->i_mutex, 662 - I_MUTEX_QUOTA); 661 + mutex_lock(&dqopt->files[cnt]->i_mutex); 663 662 truncate_inode_pages(&dqopt->files[cnt]->i_data, 0); 664 663 mutex_unlock(&dqopt->files[cnt]->i_mutex); 665 664 } ··· 2036 2037 /* If quota was reenabled in the meantime, we have 2037 2038 * nothing to do */ 2038 2039 if (!sb_has_quota_loaded(sb, cnt)) { 2039 - mutex_lock_nested(&toputinode[cnt]->i_mutex, 2040 - I_MUTEX_QUOTA); 2040 + mutex_lock(&toputinode[cnt]->i_mutex); 2041 2041 toputinode[cnt]->i_flags &= ~(S_IMMUTABLE | 2042 2042 S_NOATIME | S_NOQUOTA); 2043 2043 truncate_inode_pages(&toputinode[cnt]->i_data, ··· 2131 2133 /* We don't want quota and atime on quota files (deadlocks 2132 2134 * possible) Also nobody should write to the file - we use 2133 2135 * special IO operations which ignore the immutable bit. */ 2134 - mutex_lock_nested(&inode->i_mutex, I_MUTEX_QUOTA); 2136 + mutex_lock(&inode->i_mutex); 2135 2137 oldflags = inode->i_flags & (S_NOATIME | S_IMMUTABLE | 2136 2138 S_NOQUOTA); 2137 2139 inode->i_flags |= S_NOQUOTA | S_NOATIME | S_IMMUTABLE; ··· 2178 2180 iput(inode); 2179 2181 out_lock: 2180 2182 if (oldflags != -1) { 2181 - mutex_lock_nested(&inode->i_mutex, I_MUTEX_QUOTA); 2183 + mutex_lock(&inode->i_mutex); 2182 2184 /* Set the flags back (in the case of accidental quotaon() 2183 2185 * on a wrong file we don't want to mess up the flags) */ 2184 2186 inode->i_flags &= ~(S_NOATIME | S_NOQUOTA | S_IMMUTABLE);