All of lore.kernel.org
 help / color / mirror / Atom feed
From: Chengguang Xu <cgxu519@gmx.com>
To: linux-unionfs@vger.kernel.org
Cc: miklos@szeredi.hu, amir73il@gmail.com, Chengguang Xu <cgxu519@gmx.com>
Subject: [PATCH 3/3] ovl: introduce a dedicated cache pool for ovl_entry
Date: Tue, 17 Apr 2018 10:42:45 +0800	[thread overview]
Message-ID: <1523932965-25792-3-git-send-email-cgxu519@gmx.com> (raw)
In-Reply-To: <1523932965-25792-1-git-send-email-cgxu519@gmx.com>

Introduce a dedicated cache pool for ovl_entry to optimize
memory allocation adn deallocation.

Signed-off-by: Chengguang Xu <cgxu519@gmx.com>
---
 fs/overlayfs/export.c    | 11 +++++++----
 fs/overlayfs/namei.c     |  7 +++++--
 fs/overlayfs/overlayfs.h |  4 ++++
 fs/overlayfs/ovl_entry.h |  9 +++++----
 fs/overlayfs/super.c     | 38 +++++++++++++++++++++++++++++---------
 fs/overlayfs/util.c      | 28 ++++++++++++++++++++++++----
 6 files changed, 74 insertions(+), 23 deletions(-)

diff --git a/fs/overlayfs/export.c b/fs/overlayfs/export.c
index f2ba5fb..b1047ae 100644
--- a/fs/overlayfs/export.c
+++ b/fs/overlayfs/export.c
@@ -321,8 +321,8 @@ static struct dentry *ovl_obtain_alias(struct super_block *sb,
 			goto nomem;
 
 		if (lower) {
-			oe->lowerstack->dentry = dget(lower);
-			oe->lowerstack->layer = lowerpath->layer;
+			oe->lowerstack.dentry = dget(lower);
+			oe->lowerstack.layer = lowerpath->layer;
 		}
 		dentry->d_fsdata = oe;
 		if (upper_alias)
@@ -346,9 +346,12 @@ static struct dentry *ovl_dentry_real_at(struct dentry *dentry, int idx)
 	if (!idx)
 		return ovl_dentry_upper(dentry);
 
+	if (oe->numlower == 1 && oe->lowerstack.layer->idx == idx)
+		return oe->lowerstack.dentry;
+
 	for (i = 0; i < oe->numlower; i++) {
-		if (oe->lowerstack[i].layer->idx == idx)
-			return oe->lowerstack[i].dentry;
+		if (oe->lowerstacks[i].layer->idx == idx)
+			return oe->lowerstacks[i].dentry;
 	}
 
 	return NULL;
diff --git a/fs/overlayfs/namei.c b/fs/overlayfs/namei.c
index eb3ec6c..51fd914 100644
--- a/fs/overlayfs/namei.c
+++ b/fs/overlayfs/namei.c
@@ -994,7 +994,10 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
 	if (!oe)
 		goto out_put;
 
-	memcpy(oe->lowerstack, stack, sizeof(struct ovl_path) * ctr);
+	if (oe->numlower == 1)
+		memcpy(&oe->lowerstack, stack, sizeof(struct ovl_path));
+	else
+		memcpy(oe->lowerstacks, stack, sizeof(struct ovl_path) * ctr);
 	dentry->d_fsdata = oe;
 
 	if (upperopaque)
@@ -1028,7 +1031,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
 
 out_free_oe:
 	dentry->d_fsdata = NULL;
-	kfree(oe);
+	ovl_free_entry(oe);
 out_put:
 	dput(index);
 	for (i = 0; i < ctr; i++)
diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h
index 8039602..a104e02 100644
--- a/fs/overlayfs/overlayfs.h
+++ b/fs/overlayfs/overlayfs.h
@@ -207,6 +207,7 @@ static inline struct dentry *ovl_do_tmpfile(struct dentry *dentry, umode_t mode)
 bool ovl_index_all(struct super_block *sb);
 bool ovl_verify_lower(struct super_block *sb);
 struct ovl_entry *ovl_alloc_entry(unsigned int numlower);
+void ovl_free_entry(struct ovl_entry *oe);
 bool ovl_dentry_remote(struct dentry *dentry);
 bool ovl_dentry_weird(struct dentry *dentry);
 enum ovl_path_type ovl_path_type(struct dentry *dentry);
@@ -378,3 +379,6 @@ int ovl_set_origin(struct dentry *dentry, struct dentry *lower,
 
 /* export.c */
 extern const struct export_operations ovl_export_operations;
+
+/* super.c */
+extern struct kmem_cache *ovl_entry_cachep;
diff --git a/fs/overlayfs/ovl_entry.h b/fs/overlayfs/ovl_entry.h
index 41655a7..3ed8ab4 100644
--- a/fs/overlayfs/ovl_entry.h
+++ b/fs/overlayfs/ovl_entry.h
@@ -71,13 +71,14 @@ struct ovl_fs {
 /* private information held for every overlayfs dentry */
 struct ovl_entry {
 	union {
-		struct {
-			unsigned long flags;
-		};
+		unsigned long flags;
 		struct rcu_head rcu;
 	};
 	unsigned numlower;
-	struct ovl_path lowerstack[];
+	union {
+		struct ovl_path lowerstack;
+		struct ovl_path *lowerstacks;
+	};
 };
 
 struct ovl_entry *ovl_alloc_entry(unsigned int numlower);
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
index 38c1dd1..6327497 100644
--- a/fs/overlayfs/super.c
+++ b/fs/overlayfs/super.c
@@ -60,8 +60,11 @@ static void ovl_entry_stack_free(struct ovl_entry *oe)
 {
 	unsigned int i;
 
-	for (i = 0; i < oe->numlower; i++)
-		dput(oe->lowerstack[i].dentry);
+	if (oe->numlower == 1)
+		dput(oe->lowerstack.dentry);
+	else
+		for (i = 0; i < oe->numlower; i++)
+			dput(oe->lowerstacks[i].dentry);
 }
 
 static void ovl_dentry_release(struct dentry *dentry)
@@ -191,6 +194,7 @@ static int ovl_dentry_weak_revalidate(struct dentry *dentry, unsigned int flags)
 };
 
 static struct kmem_cache *ovl_inode_cachep;
+struct kmem_cache *ovl_entry_cachep;
 
 static struct inode *ovl_alloc_inode(struct super_block *sb)
 {
@@ -1332,9 +1336,14 @@ static struct ovl_entry *ovl_get_lowerstack(struct super_block *sb,
 	if (!oe)
 		goto out_err;
 
-	for (i = 0; i < numlower; i++) {
-		oe->lowerstack[i].dentry = dget(stack[i].dentry);
-		oe->lowerstack[i].layer = &ofs->lower_layers[i];
+	if (numlower == 1) {
+		oe->lowerstack.dentry = stack[0].dentry;
+		oe->lowerstack.layer = &ofs->lower_layers[0];
+	} else {
+		for (i = 0; i < numlower; i++) {
+			oe->lowerstacks[i].dentry = dget(stack[i].dentry);
+			oe->lowerstacks[i].layer = &ofs->lower_layers[i];
+		}
 	}
 
 	if (remote)
@@ -1515,20 +1524,31 @@ static void ovl_inode_init_once(void *foo)
 
 static int __init ovl_init(void)
 {
-	int err;
+	int err = -ENOMEM;
 
 	ovl_inode_cachep = kmem_cache_create("ovl_inode",
 					     sizeof(struct ovl_inode), 0,
 					     (SLAB_RECLAIM_ACCOUNT|
 					      SLAB_MEM_SPREAD|SLAB_ACCOUNT),
 					     ovl_inode_init_once);
-	if (ovl_inode_cachep == NULL)
-		return -ENOMEM;
+	if (!ovl_inode_cachep)
+		return err;
+
+	ovl_entry_cachep = KMEM_CACHE(ovl_entry,
+				SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD);
+	if (!ovl_entry_cachep)
+		goto bad_entry_cachep;
 
 	err = register_filesystem(&ovl_fs_type);
 	if (err)
-		kmem_cache_destroy(ovl_inode_cachep);
+		goto err_out;
 
+	return 0;
+
+err_out:
+	kmem_cache_destroy(ovl_entry_cachep);
+bad_entry_cachep:
+	kmem_cache_destroy(ovl_inode_cachep);
 	return err;
 }
 
diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c
index a3459e6..7d4ff3e 100644
--- a/fs/overlayfs/util.c
+++ b/fs/overlayfs/util.c
@@ -95,13 +95,30 @@ bool ovl_verify_lower(struct super_block *sb)
 	return ofs->config.nfs_export && ofs->config.index;
 }
 
+void ovl_free_entry(struct ovl_entry *oe)
+{
+	if (oe->numlower > 1)
+		kfree(oe->lowerstacks);
+
+	kmem_cache_free(ovl_entry_cachep, oe);
+}
+
 struct ovl_entry *ovl_alloc_entry(unsigned int numlower)
 {
-	size_t size = offsetof(struct ovl_entry, lowerstack[numlower]);
-	struct ovl_entry *oe = kzalloc(size, GFP_KERNEL);
+	size_t size = sizeof(struct ovl_path) * numlower;
+	struct ovl_entry *oe;
 
-	if (oe)
+	oe = kmem_cache_zalloc(ovl_entry_cachep, GFP_KERNEL);
+	if (oe) {
 		oe->numlower = numlower;
+		if (numlower > 1) {
+			oe->lowerstacks = kzalloc(size, GFP_KERNEL);
+			if (!oe->lowerstacks) {
+				kmem_cache_free(ovl_entry_cachep, oe);
+				oe = NULL;
+			}
+		}
+	}
 
 	return oe;
 }
@@ -186,7 +203,10 @@ struct ovl_path *__ovl_path_lower(struct ovl_entry *oe, int layer)
 	if (layer > oe->numlower)
 		return NULL;
 
-	return &oe->lowerstack[layer - 1];
+	if (layer == 1 && oe->numlower == 1)
+		return &oe->lowerstack;
+	else
+		return &oe->lowerstacks[layer - 1];
 }
 
 struct vfsmount *ovl_mnt_lower(struct dentry *dentry)
-- 
1.8.3.1

  parent reply	other threads:[~2018-04-17  2:42 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-04-17  2:42 [PATCH 1/3] ovl: refactor lowerstack related functions Chengguang Xu
2018-04-17  2:42 ` [PATCH 2/3] ovl: using lowestack handling functions to replace bare array operation Chengguang Xu
2018-04-17 11:16   ` Amir Goldstein
2018-04-18  3:42     ` cgxu519
2018-04-17  2:42 ` Chengguang Xu [this message]
2018-04-17 10:41   ` [PATCH 3/3] ovl: introduce a dedicated cache pool for ovl_entry Amir Goldstein
2018-04-18  0:59     ` cgxu519
2018-04-17 11:04 ` [PATCH 1/3] ovl: refactor lowerstack related functions Amir Goldstein

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1523932965-25792-3-git-send-email-cgxu519@gmx.com \
    --to=cgxu519@gmx.com \
    --cc=amir73il@gmail.com \
    --cc=linux-unionfs@vger.kernel.org \
    --cc=miklos@szeredi.hu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.