@@ -1532,6 +1532,9 @@ static struct dentry *__lookup_slow(const struct qstr *name,
if (unlikely(old)) {
dput(dentry);
dentry = old;
+ } else if ((flags & LOOKUP_DONTCACHE_NEGATIVE) &&
+ d_is_negative(dentry)) {
+ d_drop(dentry);
}
}
return dentry;
@@ -2554,6 +2557,7 @@ EXPORT_SYMBOL(lookup_one_len);
* @name: pathname component to lookup
* @base: base directory to lookup from
* @len: maximum length @len should be interpreted to
+ * @flags: lookup flags
*
* Note that this routine is purely a helper for filesystem usage and should
* not be called by generic code.
@@ -2562,7 +2566,8 @@ EXPORT_SYMBOL(lookup_one_len);
* i_mutex held, and will take the i_mutex itself if necessary.
*/
struct dentry *lookup_one_len_unlocked(const char *name,
- struct dentry *base, int len)
+ struct dentry *base, int len,
+ unsigned int flags)
{
struct qstr this;
int err;
@@ -2574,7 +2579,7 @@ struct dentry *lookup_one_len_unlocked(const char *name,
ret = lookup_dcache(&this, base, 0);
if (!ret)
- ret = lookup_slow(&this, base, 0);
+ ret = lookup_slow(&this, base, flags);
return ret;
}
EXPORT_SYMBOL(lookup_one_len_unlocked);
@@ -2588,9 +2593,10 @@ EXPORT_SYMBOL(lookup_one_len_unlocked);
* this one avoids such problems.
*/
struct dentry *lookup_positive_unlocked(const char *name,
- struct dentry *base, int len)
+ struct dentry *base, int len,
+ unsigned int flags)
{
- struct dentry *ret = lookup_one_len_unlocked(name, base, len);
+ struct dentry *ret = lookup_one_len_unlocked(name, base, len, flags);
if (!IS_ERR(ret) && d_flags_negative(smp_load_acquire(&ret->d_flags))) {
dput(ret);
ret = ERR_PTR(-ENOENT);
@@ -49,6 +49,9 @@ enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT};
/* LOOKUP_* flags which do scope-related checks based on the dirfd. */
#define LOOKUP_IS_SCOPED (LOOKUP_BENEATH | LOOKUP_IN_ROOT)
+/* Hint: don't cache negative. */
+#define LOOKUP_DONTCACHE_NEGATIVE 0x200000
+
extern int path_pts(struct path *path);
extern int user_path_at_empty(int, const char __user *, unsigned, struct path *, int *empty);
@@ -68,8 +71,10 @@ extern struct dentry *kern_path_locked(const char *, struct path *);
extern struct dentry *try_lookup_one_len(const char *, struct dentry *, int);
extern struct dentry *lookup_one_len(const char *, struct dentry *, int);
-extern struct dentry *lookup_one_len_unlocked(const char *, struct dentry *, int);
-extern struct dentry *lookup_positive_unlocked(const char *, struct dentry *, int);
+extern struct dentry *lookup_one_len_unlocked(const char *name,
+ struct dentry *base, int len, unsigned int flags);
+extern struct dentry *lookup_positive_unlocked(const char *name,
+ struct dentry *base, int len, unsigned int flags);
extern int follow_down_one(struct path *);
extern int follow_down(struct path *);
Introduce a new lookup flag LOOKUP_DONTCACHE_NEGATIVE to skip caching negative dentry in lookup. Signed-off-by: Chengguang Xu <cgxu519@mykernel.net> --- fs/namei.c | 14 ++++++++++---- include/linux/namei.h | 9 +++++++-- 2 files changed, 17 insertions(+), 6 deletions(-)