[PATCH 5/6] NLM: Create a SLAB/SLUB cache for nlm_host entries

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Now that we have a couple of large text buffers in the nlm_host struct,
the nlm_host cache should use a slab to reduce memory utilization and
fragmentation on systems that manage a large number of NLM peers.

We keep these hardware cache-aligned to speed up the linked list search
in nlm_lookup_host().

The overhead of creating a fresh nlm_host entry is also reduced using
SLAB's init_once callback instead of using kzalloc().

Signed-off-by: Chuck Lever <chuck.lever@xxxxxxxxxx>
---

 fs/lockd/host.c             |   44 ++++++++++++++++++++++++++++++++++++++++++-
 fs/lockd/svc.c              |   12 +++++++++---
 include/linux/lockd/lockd.h |    2 ++
 3 files changed, 54 insertions(+), 4 deletions(-)

diff --git a/fs/lockd/host.c b/fs/lockd/host.c
index 4dfe250..015c787 100644
--- a/fs/lockd/host.c
+++ b/fs/lockd/host.c
@@ -25,6 +25,8 @@
 #define NLM_HOST_EXPIRE		(300 * HZ)
 #define NLM_HOST_COLLECT	(120 * HZ)
 
+static struct kmem_cache	*nlm_host_cachep;
+
 static struct hlist_head	nlm_hosts[NLM_HOST_NRHASH];
 static unsigned long		nlm_next_gc;
 static unsigned long		nlm_nrhosts;
@@ -609,7 +611,8 @@ nlm_shutdown_hosts(void)
 					host->h_inuse, host->h_expires);
 			}
 		}
-	}
+	} else
+		nlm_destroy_host_cache();
 }
 
 /*
@@ -651,3 +654,42 @@ nlm_gc_hosts(void)
 
 	nlm_next_gc = jiffies + NLM_HOST_COLLECT;
 }
+
+static void nlm_host_init_once(void *foo)
+{
+	struct nlm_host *host = (struct nlm_host *)foo;
+
+	INIT_HLIST_NODE(&host->h_hash);
+	host->h_rpcclnt = NULL;
+	init_waitqueue_head(&host->h_gracewait);
+	init_rwsem(&host->h_rwsem);
+	mutex_init(&host->h_mutex);
+	INIT_LIST_HEAD(&host->h_lockowners);
+	spin_lock_init(&host->h_lock);
+	INIT_LIST_HEAD(&host->h_granted);
+	INIT_LIST_HEAD(&host->h_reclaim);
+}
+
+/**
+ * nlm_init_host_cache - create a slab cache for nlm_host entries
+ *
+ */
+int __init nlm_init_host_cache(void)
+{
+	nlm_host_cachep = kmem_cache_create("nlm_host_cache",
+						sizeof(struct nlm_host), 0,
+						SLAB_HWCACHE_ALIGN,
+						nlm_host_init_once);
+	if (nlm_host_cachep == NULL)
+		return -ENOMEM;
+	return 0;
+}
+
+/**
+ * nlm_destroy_host_cache - destroy the slab cache for nlm_host entries
+ *
+ */
+void nlm_destroy_host_cache(void)
+{
+	kmem_cache_destroy(nlm_host_cachep);
+}
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
index cdfdc4e..e747e48 100644
--- a/fs/lockd/svc.c
+++ b/fs/lockd/svc.c
@@ -508,12 +508,18 @@ module_param(nsm_use_hostnames, bool, 0644);
 
 static int __init init_nlm(void)
 {
+	if (nlm_init_host_cache())
+		return -ENOMEM;
+
 #ifdef CONFIG_SYSCTL
 	nlm_sysctl_table = register_sysctl_table(nlm_sysctl_root);
-	return nlm_sysctl_table ? 0 : -ENOMEM;
-#else
-	return 0;
+	if (!nlm_sysctl_table) {
+		nlm_destroy_host_cache();
+		return -ENOMEM;
+	}
 #endif
+
+	return 0;
 }
 
 static void __exit exit_nlm(void)
diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h
index 6fc4f3e..73b3b0c 100644
--- a/include/linux/lockd/lockd.h
+++ b/include/linux/lockd/lockd.h
@@ -214,6 +214,8 @@ void		  nlmclnt_next_cookie(struct nlm_cookie *);
 /*
  * Host cache
  */
+int __init	  nlm_init_host_cache(void);
+void		  nlm_destroy_host_cache(void);
 struct nlm_host  *nlmclnt_lookup_host(const struct sockaddr *sap,
 					const size_t salen,
 					const unsigned short protocol,

--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Filesystem Development]     [Linux USB Development]     [Linux Media Development]     [Video for Linux]     [Linux NILFS]     [Linux Audio Users]     [Yosemite Info]     [Linux SCSI]

  Powered by Linux