mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	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>
This commit is contained in:
		
							parent
							
								
									f9ef178412
								
							
						
					
					
						commit
						a80b12c3d0
					
				
					 1 changed files with 6 additions and 8 deletions
				
			
		| 
						 | 
				
			
			@ -116,15 +116,15 @@
 | 
			
		|||
 * spinlock to internal buffers before writing.
 | 
			
		||||
 *
 | 
			
		||||
 * Lock ordering (including related VFS locks) is the following:
 | 
			
		||||
 *   i_mutex > dqonoff_sem > journal_lock > dqptr_sem > dquot->dq_lock >
 | 
			
		||||
 *   dqonoff_mutex > i_mutex > journal_lock > dqptr_sem > dquot->dq_lock >
 | 
			
		||||
 *   dqio_mutex
 | 
			
		||||
 * dqonoff_mutex > i_mutex comes from dquot_quota_sync, dquot_enable, etc.
 | 
			
		||||
 * The lock ordering of dqptr_sem imposed by quota code is only dqonoff_sem >
 | 
			
		||||
 * dqptr_sem. But filesystem has to count with the fact that functions such as
 | 
			
		||||
 * dquot_alloc_space() acquire dqptr_sem and they usually have to be called
 | 
			
		||||
 * from inside a transaction to keep filesystem consistency after a crash. Also
 | 
			
		||||
 * filesystems usually want to do some IO on dquot from ->mark_dirty which is
 | 
			
		||||
 * called with dqptr_sem held.
 | 
			
		||||
 * i_mutex on quota files is special (it's below dqio_mutex)
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
static __cacheline_aligned_in_smp DEFINE_SPINLOCK(dq_list_lock);
 | 
			
		||||
| 
						 | 
				
			
			@ -658,8 +658,7 @@ int dquot_quota_sync(struct super_block *sb, int type, int wait)
 | 
			
		|||
			continue;
 | 
			
		||||
		if (!sb_has_quota_active(sb, cnt))
 | 
			
		||||
			continue;
 | 
			
		||||
		mutex_lock_nested(&dqopt->files[cnt]->i_mutex,
 | 
			
		||||
				  I_MUTEX_QUOTA);
 | 
			
		||||
		mutex_lock(&dqopt->files[cnt]->i_mutex);
 | 
			
		||||
		truncate_inode_pages(&dqopt->files[cnt]->i_data, 0);
 | 
			
		||||
		mutex_unlock(&dqopt->files[cnt]->i_mutex);
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -2037,8 +2036,7 @@ int dquot_disable(struct super_block *sb, int type, unsigned int flags)
 | 
			
		|||
			/* If quota was reenabled in the meantime, we have
 | 
			
		||||
			 * nothing to do */
 | 
			
		||||
			if (!sb_has_quota_loaded(sb, cnt)) {
 | 
			
		||||
				mutex_lock_nested(&toputinode[cnt]->i_mutex,
 | 
			
		||||
						  I_MUTEX_QUOTA);
 | 
			
		||||
				mutex_lock(&toputinode[cnt]->i_mutex);
 | 
			
		||||
				toputinode[cnt]->i_flags &= ~(S_IMMUTABLE |
 | 
			
		||||
				  S_NOATIME | S_NOQUOTA);
 | 
			
		||||
				truncate_inode_pages(&toputinode[cnt]->i_data,
 | 
			
		||||
| 
						 | 
				
			
			@ -2133,7 +2131,7 @@ static int vfs_load_quota_inode(struct inode *inode, int type, int format_id,
 | 
			
		|||
		/* We don't want quota and atime on quota files (deadlocks
 | 
			
		||||
		 * possible) Also nobody should write to the file - we use
 | 
			
		||||
		 * special IO operations which ignore the immutable bit. */
 | 
			
		||||
		mutex_lock_nested(&inode->i_mutex, I_MUTEX_QUOTA);
 | 
			
		||||
		mutex_lock(&inode->i_mutex);
 | 
			
		||||
		oldflags = inode->i_flags & (S_NOATIME | S_IMMUTABLE |
 | 
			
		||||
					     S_NOQUOTA);
 | 
			
		||||
		inode->i_flags |= S_NOQUOTA | S_NOATIME | S_IMMUTABLE;
 | 
			
		||||
| 
						 | 
				
			
			@ -2180,7 +2178,7 @@ static int vfs_load_quota_inode(struct inode *inode, int type, int format_id,
 | 
			
		|||
	iput(inode);
 | 
			
		||||
out_lock:
 | 
			
		||||
	if (oldflags != -1) {
 | 
			
		||||
		mutex_lock_nested(&inode->i_mutex, I_MUTEX_QUOTA);
 | 
			
		||||
		mutex_lock(&inode->i_mutex);
 | 
			
		||||
		/* Set the flags back (in the case of accidental quotaon()
 | 
			
		||||
		 * on a wrong file we don't want to mess up the flags) */
 | 
			
		||||
		inode->i_flags &= ~(S_NOATIME | S_NOQUOTA | S_IMMUTABLE);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue