[vz7,v2,1/2] nfsd: more robust allocation failure handling in nfsd_reply_cache_init

Submitted by Oleg Babin on May 10, 2018, 5:09 p.m.

Details

Message ID 1525972194-231410-2-git-send-email-obabin@virtuozzo.com
State New
Series "nfsd: use kvzalloc() to allocate memory for drc_hashtbl"
Headers show

Commit Message

Oleg Babin May 10, 2018, 5:09 p.m.
From: Jeff Layton <jlayton@redhat.com>

Currently, we try to allocate the cache as a single, large chunk, which
can fail if no big chunks of memory are available. We _do_ try to size
it according to the amount of memory in the box, but if the server is
started well after boot time, then the allocation can fail due to memory
fragmentation.

Fall back to doing a vzalloc if the kcalloc fails, and switch the
shutdown code to do a kvfree to handle freeing correctly.

Reported-by: Olaf Hering <olaf@aepfle.de>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>

ms commit 8f97514b423a0983e4c600099882a9c6613142d2

https://jira.sw.ru/browse/PSBM-84234
Signed-off-by: Oleg Babin <obabin@virtuozzo.com>
---
 fs/nfsd/nfscache.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

Patch hide | download patch | download mbox

diff --git a/fs/nfsd/nfscache.c b/fs/nfsd/nfscache.c
index a4fa08e..b5c25ea 100644
--- a/fs/nfsd/nfscache.c
+++ b/fs/nfsd/nfscache.c
@@ -9,6 +9,7 @@ 
  */
 
 #include <linux/slab.h>
+#include <linux/vmalloc.h>
 #include <linux/sunrpc/addr.h>
 #include <linux/highmem.h>
 #include <linux/log2.h>
@@ -178,8 +179,12 @@  int nfsd_reply_cache_init(void)
 		goto out_nomem;
 
 	drc_hashtbl = kcalloc(hashsize, sizeof(*drc_hashtbl), GFP_KERNEL);
-	if (!drc_hashtbl)
-		goto out_nomem;
+	if (!drc_hashtbl) {
+		drc_hashtbl = vzalloc(hashsize * sizeof(*drc_hashtbl));
+		if (!drc_hashtbl)
+			goto out_nomem;
+	}
+
 	for (i = 0; i < hashsize; i++) {
 		INIT_LIST_HEAD(&drc_hashtbl[i].lru_head);
 		spin_lock_init(&drc_hashtbl[i].cache_lock);
@@ -209,7 +214,7 @@  void nfsd_reply_cache_shutdown(void)
 		}
 	}
 
-	kfree (drc_hashtbl);
+	kvfree(drc_hashtbl);
 	drc_hashtbl = NULL;
 	drc_hashsize = 0;