forked from mirrors/linux
		
	namei: teach lookup_slow() to skip revalidate
... and make mountpoint_last() use it. That makes all candidates for lookup with parent locked shared go through lookup_slow(). Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
		
							parent
							
								
									e3c1392808
								
							
						
					
					
						commit
						949a852e46
					
				
					 2 changed files with 36 additions and 23 deletions
				
			
		
							
								
								
									
										50
									
								
								fs/namei.c
									
									
									
									
									
								
							
							
						
						
									
										50
									
								
								fs/namei.c
									
									
									
									
									
								
							|  | @ -1605,7 +1605,29 @@ static struct dentry *lookup_slow(const struct qstr *name, | |||
| { | ||||
| 	struct dentry *dentry; | ||||
| 	inode_lock(dir->d_inode); | ||||
| 	dentry = __lookup_hash(name, dir, flags); | ||||
| 	dentry = d_lookup(dir, name); | ||||
| 	if (unlikely(dentry)) { | ||||
| 		if ((dentry->d_flags & DCACHE_OP_REVALIDATE) && | ||||
| 		    !(flags & LOOKUP_NO_REVAL)) { | ||||
| 			int error = d_revalidate(dentry, flags); | ||||
| 			if (unlikely(error <= 0)) { | ||||
| 				if (!error) | ||||
| 					d_invalidate(dentry); | ||||
| 				dput(dentry); | ||||
| 				dentry = ERR_PTR(error); | ||||
| 			} | ||||
| 		} | ||||
| 		if (dentry) { | ||||
| 			inode_unlock(dir->d_inode); | ||||
| 			return dentry; | ||||
| 		} | ||||
| 	} | ||||
| 	dentry = d_alloc(dir, name); | ||||
| 	if (unlikely(!dentry)) { | ||||
| 		inode_unlock(dir->d_inode); | ||||
| 		return ERR_PTR(-ENOMEM); | ||||
| 	} | ||||
| 	dentry = lookup_real(dir->d_inode, dentry, flags); | ||||
| 	inode_unlock(dir->d_inode); | ||||
| 	return dentry; | ||||
| } | ||||
|  | @ -2425,31 +2447,21 @@ mountpoint_last(struct nameidata *nd, struct path *path) | |||
| 		if (error) | ||||
| 			return error; | ||||
| 		dentry = dget(nd->path.dentry); | ||||
| 		goto done; | ||||
| 	} | ||||
| 
 | ||||
| 	inode_lock(dir->d_inode); | ||||
| 	} else { | ||||
| 		dentry = d_lookup(dir, &nd->last); | ||||
| 		if (!dentry) { | ||||
| 			/*
 | ||||
| 		 * No cached dentry. Mounted dentries are pinned in the cache, | ||||
| 		 * so that means that this dentry is probably a symlink or the | ||||
| 		 * path doesn't actually point to a mounted dentry. | ||||
| 			 * No cached dentry. Mounted dentries are pinned in the | ||||
| 			 * cache, so that means that this dentry is probably | ||||
| 			 * a symlink or the path doesn't actually point | ||||
| 			 * to a mounted dentry. | ||||
| 			 */ | ||||
| 		dentry = d_alloc(dir, &nd->last); | ||||
| 		if (!dentry) { | ||||
| 			inode_unlock(dir->d_inode); | ||||
| 			return -ENOMEM; | ||||
| 		} | ||||
| 		dentry = lookup_real(dir->d_inode, dentry, nd->flags); | ||||
| 		if (IS_ERR(dentry)) { | ||||
| 			inode_unlock(dir->d_inode); | ||||
| 			dentry = lookup_slow(&nd->last, dir, | ||||
| 					     nd->flags | LOOKUP_NO_REVAL); | ||||
| 			if (IS_ERR(dentry)) | ||||
| 				return PTR_ERR(dentry); | ||||
| 		} | ||||
| 	} | ||||
| 	inode_unlock(dir->d_inode); | ||||
| 
 | ||||
| done: | ||||
| 	if (d_is_negative(dentry)) { | ||||
| 		dput(dentry); | ||||
| 		return -ENOENT; | ||||
|  |  | |||
|  | @ -31,6 +31,7 @@ enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT, LAST_BIND}; | |||
| #define LOOKUP_PARENT		0x0010 | ||||
| #define LOOKUP_REVAL		0x0020 | ||||
| #define LOOKUP_RCU		0x0040 | ||||
| #define LOOKUP_NO_REVAL		0x0080 | ||||
| 
 | ||||
| /*
 | ||||
|  * Intent data | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Al Viro
						Al Viro