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

Commit 0c8c2053 authored by Al Viro's avatar Al Viro Committed by Greg Kroah-Hartman
Browse files

new helper: lookup_positive_unlocked()



[ Upstream commit 6c2d4798a8d16cf4f3a28c3cd4af4f1dcbbb4d04 ]

Most of the callers of lookup_one_len_unlocked() treat negatives are
ERR_PTR(-ENOENT).  Provide a helper that would do just that.  Note
that a pinned positive dentry remains positive - it's ->d_inode is
stable, etc.; a pinned _negative_ dentry can become positive at any
point as long as you are not holding its parent at least shared.
So using lookup_one_len_unlocked() needs to be careful;
lookup_positive_unlocked() is safer and that's what the callers
end up open-coding anyway.

Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
Stable-dep-of: 0d5a4f8f775f ("fs: Fix error checking for d_hash_and_lookup()")
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 0a2b1eb8
Loading
Loading
Loading
Loading
+1 −6
Original line number Diff line number Diff line
@@ -738,11 +738,6 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb)
		struct inode *dir = d_inode(dentry);
		struct dentry *child;

		if (!dir) {
			dput(dentry);
			dentry = ERR_PTR(-ENOENT);
			break;
		}
		if (!S_ISDIR(dir->i_mode)) {
			dput(dentry);
			dentry = ERR_PTR(-ENOTDIR);
@@ -759,7 +754,7 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb)
		while (*s && *s != sep)
			s++;

		child = lookup_one_len_unlocked(p, dentry, s - p);
		child = lookup_positive_unlocked(p, dentry, s - p);
		dput(dentry);
		dentry = child;
	} while (!IS_ERR(dentry));
+1 −5
Original line number Diff line number Diff line
@@ -299,13 +299,9 @@ struct dentry *debugfs_lookup(const char *name, struct dentry *parent)
	if (!parent)
		parent = debugfs_mount->mnt_root;

	dentry = lookup_one_len_unlocked(name, parent, strlen(name));
	dentry = lookup_positive_unlocked(name, parent, strlen(name));
	if (IS_ERR(dentry))
		return NULL;
	if (!d_really_is_positive(dentry)) {
		dput(dentry);
		return NULL;
	}
	return dentry;
}
EXPORT_SYMBOL_GPL(debugfs_lookup);
+1 −1
Original line number Diff line number Diff line
@@ -200,7 +200,7 @@ struct dentry *kernfs_node_dentry(struct kernfs_node *kn,
			dput(dentry);
			return ERR_PTR(-EINVAL);
		}
		dtmp = lookup_one_len_unlocked(kntmp->name, dentry,
		dtmp = lookup_positive_unlocked(kntmp->name, dentry,
					       strlen(kntmp->name));
		dput(dentry);
		if (IS_ERR(dtmp))
+20 −0
Original line number Diff line number Diff line
@@ -2565,6 +2565,26 @@ struct dentry *lookup_one_len_unlocked(const char *name,
}
EXPORT_SYMBOL(lookup_one_len_unlocked);

/*
 * Like lookup_one_len_unlocked(), except that it yields ERR_PTR(-ENOENT)
 * on negatives.  Returns known positive or ERR_PTR(); that's what
 * most of the users want.  Note that pinned negative with unlocked parent
 * _can_ become positive at any time, so callers of lookup_one_len_unlocked()
 * need to be very careful; pinned positives have ->d_inode stable, so
 * this one avoids such problems.
 */
struct dentry *lookup_positive_unlocked(const char *name,
				       struct dentry *base, int len)
{
	struct dentry *ret = lookup_one_len_unlocked(name, base, len);
	if (!IS_ERR(ret) && d_is_negative(ret)) {
		dput(ret);
		ret = ERR_PTR(-ENOENT);
	}
	return ret;
}
EXPORT_SYMBOL(lookup_positive_unlocked);

#ifdef CONFIG_UNIX98_PTYS
int path_pts(struct path *path)
{
+1 −3
Original line number Diff line number Diff line
@@ -868,13 +868,11 @@ compose_entry_fh(struct nfsd3_readdirres *cd, struct svc_fh *fhp,
		} else
			dchild = dget(dparent);
	} else
		dchild = lookup_one_len_unlocked(name, dparent, namlen);
		dchild = lookup_positive_unlocked(name, dparent, namlen);
	if (IS_ERR(dchild))
		return rv;
	if (d_mountpoint(dchild))
		goto out;
	if (d_really_is_negative(dchild))
		goto out;
	if (dchild->d_inode->i_ino != ino)
		goto out;
	rv = fh_compose(fhp, exp, dchild, &cd->fh);
Loading