public inbox for linux-unionfs@vger.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH v2] ovl: suppress negative dentry in lookup
@ 2020-05-12  7:13 Chengguang Xu
  2020-05-12  7:50 ` Amir Goldstein
  0 siblings, 1 reply; 6+ messages in thread
From: Chengguang Xu @ 2020-05-12  7:13 UTC (permalink / raw)
  To: miklos, amir73il; +Cc: linux-unionfs, Chengguang Xu

When a file is only in a lower layer or in no layer at all, after
lookup a negative dentry will be generated in the upper layer or
even worse many negetive dentries will be generated in upper/lower
layers. These negative dentries will be useless after construction
of overlayfs' own dentry and may keep in the memory long time even
after unmount of overlayfs instance. This patch tries to kill
unnecessary negative dentry during lookup.

Signed-off-by: Chengguang Xu <cgxu519@mykernel.net>
---
v1->v2:
- Only drop negative dentry after slow lookup.

 fs/namei.c            |  9 ++++++---
 fs/overlayfs/namei.c  | 35 ++++++++++++++++++++++++++++++++++-
 include/linux/namei.h |  8 ++++++++
 3 files changed, 48 insertions(+), 4 deletions(-)

diff --git a/fs/namei.c b/fs/namei.c
index a320371899cf..1cc2960c7804 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1386,7 +1386,7 @@ static inline int handle_mounts(struct nameidata *nd, struct dentry *dentry,
  * This looks up the name in dcache and possibly revalidates the found dentry.
  * NULL is returned if the dentry does not exist in the cache.
  */
-static struct dentry *lookup_dcache(const struct qstr *name,
+struct dentry *lookup_dcache(const struct qstr *name,
 				    struct dentry *dir,
 				    unsigned int flags)
 {
@@ -1402,6 +1402,7 @@ static struct dentry *lookup_dcache(const struct qstr *name,
 	}
 	return dentry;
 }
+EXPORT_SYMBOL(lookup_dcache);
 
 /*
  * Parent directory has inode locked exclusive.  This is one
@@ -1500,7 +1501,7 @@ static struct dentry *lookup_fast(struct nameidata *nd,
 }
 
 /* Fast lookup failed, do it the slow way */
-static struct dentry *__lookup_slow(const struct qstr *name,
+struct dentry *__lookup_slow(const struct qstr *name,
 				    struct dentry *dir,
 				    unsigned int flags)
 {
@@ -1536,6 +1537,7 @@ static struct dentry *__lookup_slow(const struct qstr *name,
 	}
 	return dentry;
 }
+EXPORT_SYMBOL(__lookup_slow);
 
 static struct dentry *lookup_slow(const struct qstr *name,
 				  struct dentry *dir,
@@ -2460,7 +2462,7 @@ int vfs_path_lookup(struct dentry *dentry, struct vfsmount *mnt,
 }
 EXPORT_SYMBOL(vfs_path_lookup);
 
-static int lookup_one_len_common(const char *name, struct dentry *base,
+int lookup_one_len_common(const char *name, struct dentry *base,
 				 int len, struct qstr *this)
 {
 	this->name = name;
@@ -2491,6 +2493,7 @@ static int lookup_one_len_common(const char *name, struct dentry *base,
 
 	return inode_permission(base->d_inode, MAY_EXEC);
 }
+EXPORT_SYMBOL(lookup_one_len_common);
 
 /**
  * try_lookup_one_len - filesystem helper to lookup single pathname component
diff --git a/fs/overlayfs/namei.c b/fs/overlayfs/namei.c
index 723d17744758..d8e71173ea75 100644
--- a/fs/overlayfs/namei.c
+++ b/fs/overlayfs/namei.c
@@ -191,6 +191,39 @@ static bool ovl_is_opaquedir(struct dentry *dentry)
 	return ovl_check_dir_xattr(dentry, OVL_XATTR_OPAQUE);
 }
 
+static struct dentry *ovl_lookup_positive_unlocked(const char *name,
+						   struct dentry *base,
+						   int len)
+{
+	struct qstr this;
+	struct dentry *ret;
+	bool not_found = false;
+	int err;
+
+	err = lookup_one_len_common(name, base, len, &this);
+	if (err)
+		return ERR_PTR(err);
+
+	ret = lookup_dcache(&this, base, 0);
+	if (ret)
+		return ret;
+
+	inode_lock_shared(base->d_inode);
+	ret = __lookup_slow(&this, base, 0);
+	if (!IS_ERR(ret) &&
+	    d_flags_negative(ret->d_flags)) {
+		not_found = true;
+		d_drop(ret);
+	}
+	inode_unlock_shared(base->d_inode);
+
+	if (not_found) {
+		dput(ret);
+		ret = ERR_PTR(-ENOENT);
+	}
+	return ret;
+}
+
 static int ovl_lookup_single(struct dentry *base, struct ovl_lookup_data *d,
 			     const char *name, unsigned int namelen,
 			     size_t prelen, const char *post,
@@ -200,7 +233,7 @@ static int ovl_lookup_single(struct dentry *base, struct ovl_lookup_data *d,
 	int err;
 	bool last_element = !post[0];
 
-	this = lookup_positive_unlocked(name, base, namelen);
+	this = ovl_lookup_positive_unlocked(name, base, namelen);
 	if (IS_ERR(this)) {
 		err = PTR_ERR(this);
 		this = NULL;
diff --git a/include/linux/namei.h b/include/linux/namei.h
index a4bb992623c4..c65b863657eb 100644
--- a/include/linux/namei.h
+++ b/include/linux/namei.h
@@ -66,6 +66,14 @@ extern struct dentry *user_path_create(int, const char __user *, struct path *,
 extern void done_path_create(struct path *, struct dentry *);
 extern struct dentry *kern_path_locked(const char *, struct path *);
 
+extern int lookup_one_len_common(const char *name, struct dentry *base,
+				 int len, struct qstr *this);
+extern struct dentry *lookup_dcache(const struct qstr *name,
+				    struct dentry *base,
+				    unsigned int flags);
+extern struct dentry *__lookup_slow(const struct qstr *name,
+				    struct dentry *dir,
+				    unsigned int flags);
 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);
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2020-05-13  2:48 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2020-05-12  7:13 [RFC PATCH v2] ovl: suppress negative dentry in lookup Chengguang Xu
2020-05-12  7:50 ` Amir Goldstein
2020-05-12  8:32   ` Miklos Szeredi
2020-05-12  8:55     ` Amir Goldstein
2020-05-12  9:30       ` Miklos Szeredi
2020-05-13  2:15         ` Dave Chinner

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox