summaryrefslogtreecommitdiff
path: root/fs/namei.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2019-10-31 01:21:58 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2019-11-15 13:49:04 -0500
commit6c2d4798a8d16cf4f3a28c3cd4af4f1dcbbb4d04 (patch)
tree2b14c83985da30129911f7ad455e4cc587690e58 /fs/namei.c
parentd41efb522e902364ab09c782d511c1bedc388ddd (diff)
downloadlwn-6c2d4798a8d16cf4f3a28c3cd4af4f1dcbbb4d04.tar.gz
lwn-6c2d4798a8d16cf4f3a28c3cd4af4f1dcbbb4d04.zip
new helper: lookup_positive_unlocked()
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: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/namei.c')
-rw-r--r--fs/namei.c20
1 files changed, 20 insertions, 0 deletions
diff --git a/fs/namei.c b/fs/namei.c
index ef55155d152f..6f72fb7ef5ad 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2557,6 +2557,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)
{