Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 949a852e authored by Al Viro's avatar Al Viro
Browse files

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: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent e3c13928
Loading
Loading
Loading
Loading
+35 −23
Original line number Diff line number Diff line
@@ -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;
+1 −0
Original line number Diff line number Diff line
@@ -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