vfs: dcache: use DCACHE_DENTRY_KILLED instead of DCACHE_DISCONNECTED in d_kill()
IBM reported a soft lockup after applying the fix for the rename_lock
deadlock.  Commit c83ce989cb ("VFS: Fix the nfs sillyrename regression
in kernel 2.6.38") was found to be the culprit.
The nfs sillyrename fix used DCACHE_DISCONNECTED to indicate that the
dentry was killed.  This flag can be set on non-killed dentries too,
which results in infinite retries when trying to traverse the dentry
tree.
This patch introduces a separate flag: DCACHE_DENTRY_KILLED, which is
only set in d_kill() and makes try_to_ascend() test only this flag.
IBM reported successful test results with this patch.
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
Cc: Trond Myklebust <Trond.Myklebust@netapp.com>
Cc: stable@vger.kernel.org
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
	
	
This commit is contained in:
		
					parent
					
						
							
								4651afbbae
							
						
					
				
			
			
				commit
				
					
						b161dfa693
					
				
			
		
					 2 changed files with 4 additions and 2 deletions
				
			
		|  | @ -389,7 +389,7 @@ static struct dentry *d_kill(struct dentry *dentry, struct dentry *parent) | ||||||
| 	 * Inform try_to_ascend() that we are no longer attached to the | 	 * Inform try_to_ascend() that we are no longer attached to the | ||||||
| 	 * dentry tree | 	 * dentry tree | ||||||
| 	 */ | 	 */ | ||||||
| 	dentry->d_flags |= DCACHE_DISCONNECTED; | 	dentry->d_flags |= DCACHE_DENTRY_KILLED; | ||||||
| 	if (parent) | 	if (parent) | ||||||
| 		spin_unlock(&parent->d_lock); | 		spin_unlock(&parent->d_lock); | ||||||
| 	dentry_iput(dentry); | 	dentry_iput(dentry); | ||||||
|  | @ -1048,7 +1048,7 @@ static struct dentry *try_to_ascend(struct dentry *old, int locked, unsigned seq | ||||||
| 	 * or deletion | 	 * or deletion | ||||||
| 	 */ | 	 */ | ||||||
| 	if (new != old->d_parent || | 	if (new != old->d_parent || | ||||||
| 		 (old->d_flags & DCACHE_DISCONNECTED) || | 		 (old->d_flags & DCACHE_DENTRY_KILLED) || | ||||||
| 		 (!locked && read_seqretry(&rename_lock, seq))) { | 		 (!locked && read_seqretry(&rename_lock, seq))) { | ||||||
| 		spin_unlock(&new->d_lock); | 		spin_unlock(&new->d_lock); | ||||||
| 		new = NULL; | 		new = NULL; | ||||||
|  |  | ||||||
|  | @ -206,6 +206,8 @@ struct dentry_operations { | ||||||
| #define DCACHE_MANAGED_DENTRY \ | #define DCACHE_MANAGED_DENTRY \ | ||||||
| 	(DCACHE_MOUNTED|DCACHE_NEED_AUTOMOUNT|DCACHE_MANAGE_TRANSIT) | 	(DCACHE_MOUNTED|DCACHE_NEED_AUTOMOUNT|DCACHE_MANAGE_TRANSIT) | ||||||
| 
 | 
 | ||||||
|  | #define DCACHE_DENTRY_KILLED	0x100000 | ||||||
|  | 
 | ||||||
| extern seqlock_t rename_lock; | extern seqlock_t rename_lock; | ||||||
| 
 | 
 | ||||||
| static inline int dname_external(struct dentry *dentry) | static inline int dname_external(struct dentry *dentry) | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Miklos Szeredi
				Miklos Szeredi