From 1f51066386dfe2495d393dee9bbc6548aac8f846 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Thu, 7 Jun 2012 13:57:50 +0000 Subject: [PATCH] NFSv4: Reduce the footprint of the idmapper (Closes: #657078) svn path=/dists/sid/linux/; revision=19096 --- debian/changelog | 1 + ...reduce-the-footprint-of-the-idmapper.patch | 124 ++++++++++++++++++ ...Reduce-the-footprint-of-the-idmapper.patch | 62 +++++++++ debian/patches/series-all | 3 + 4 files changed, 190 insertions(+) create mode 100644 debian/patches/bugfix/all/NFSv4-Further-reduce-the-footprint-of-the-idmapper.patch create mode 100644 debian/patches/bugfix/all/NFSv4-Reduce-the-footprint-of-the-idmapper.patch diff --git a/debian/changelog b/debian/changelog index 4fbdca55b..231e435eb 100644 --- a/debian/changelog +++ b/debian/changelog @@ -22,6 +22,7 @@ linux (3.2.19-2) UNRELEASED; urgency=low * filter: Allow to create sk-unattached filters * net: Backport team driver from Linux 3.5-rc1 * proc: Backport hidepid mount option from Linux 3.4 (Closes: #669028) + * NFSv4: Reduce the footprint of the idmapper (Closes: #657078) -- Ben Hutchings Sat, 02 Jun 2012 20:31:53 +0100 diff --git a/debian/patches/bugfix/all/NFSv4-Further-reduce-the-footprint-of-the-idmapper.patch b/debian/patches/bugfix/all/NFSv4-Further-reduce-the-footprint-of-the-idmapper.patch new file mode 100644 index 000000000..7f1f81532 --- /dev/null +++ b/debian/patches/bugfix/all/NFSv4-Further-reduce-the-footprint-of-the-idmapper.patch @@ -0,0 +1,124 @@ +From: Trond Myklebust +Date: Wed, 8 Feb 2012 13:39:15 -0500 +Subject: [2/2] NFSv4: Further reduce the footprint of the idmapper + +commit 685f50f9188ac1e8244d0340a9d6ea36b6136cec upstream. + +Don't allocate the legacy idmapper tables until we actually need +them. + +Signed-off-by: Trond Myklebust +Reviewed-by: Jeff Layton +[bwh: Backported to 3.2: adjust context in nfs_idmap_delete()] +--- + fs/nfs/idmap.c | 42 ++++++++++++++++++++++++++++++++++++------ + 1 file changed, 36 insertions(+), 6 deletions(-) + +--- a/fs/nfs/idmap.c ++++ b/fs/nfs/idmap.c +@@ -323,7 +323,7 @@ + + struct idmap_hashtable { + __u8 h_type; +- struct idmap_hashent h_entries[IDMAP_HASH_SZ]; ++ struct idmap_hashent *h_entries; + }; + + struct idmap { +@@ -378,20 +378,39 @@ + return 0; + } + ++static void ++idmap_alloc_hashtable(struct idmap_hashtable *h) ++{ ++ if (h->h_entries != NULL) ++ return; ++ h->h_entries = kcalloc(IDMAP_HASH_SZ, ++ sizeof(*h->h_entries), ++ GFP_KERNEL); ++} ++ ++static void ++idmap_free_hashtable(struct idmap_hashtable *h) ++{ ++ int i; ++ ++ if (h->h_entries == NULL) ++ return; ++ for (i = 0; i < IDMAP_HASH_SZ; i++) ++ kfree(h->h_entries[i].ih_name); ++ kfree(h->h_entries); ++} ++ + void + nfs_idmap_delete(struct nfs_client *clp) + { + struct idmap *idmap = clp->cl_idmap; +- int i; + + if (!idmap) + return; + rpc_unlink(idmap->idmap_dentry); + clp->cl_idmap = NULL; +- for (i = 0; i < ARRAY_SIZE(idmap->idmap_user_hash.h_entries); i++) +- kfree(idmap->idmap_user_hash.h_entries[i].ih_name); +- for (i = 0; i < ARRAY_SIZE(idmap->idmap_group_hash.h_entries); i++) +- kfree(idmap->idmap_group_hash.h_entries[i].ih_name); ++ idmap_free_hashtable(&idmap->idmap_user_hash); ++ idmap_free_hashtable(&idmap->idmap_group_hash); + kfree(idmap); + } + +@@ -401,6 +420,8 @@ + static inline struct idmap_hashent * + idmap_name_hash(struct idmap_hashtable* h, const char *name, size_t len) + { ++ if (h->h_entries == NULL) ++ return NULL; + return &h->h_entries[fnvhash32(name, len) % IDMAP_HASH_SZ]; + } + +@@ -409,6 +430,8 @@ + { + struct idmap_hashent *he = idmap_name_hash(h, name, len); + ++ if (he == NULL) ++ return NULL; + if (he->ih_namelen != len || memcmp(he->ih_name, name, len) != 0) + return NULL; + if (time_after(jiffies, he->ih_expires)) +@@ -419,6 +442,8 @@ + static inline struct idmap_hashent * + idmap_id_hash(struct idmap_hashtable* h, __u32 id) + { ++ if (h->h_entries == NULL) ++ return NULL; + return &h->h_entries[fnvhash32(&id, sizeof(id)) % IDMAP_HASH_SZ]; + } + +@@ -426,6 +451,9 @@ + idmap_lookup_id(struct idmap_hashtable *h, __u32 id) + { + struct idmap_hashent *he = idmap_id_hash(h, id); ++ ++ if (he == NULL) ++ return NULL; + if (he->ih_id != id || he->ih_namelen == 0) + return NULL; + if (time_after(jiffies, he->ih_expires)) +@@ -441,12 +469,14 @@ + static inline struct idmap_hashent * + idmap_alloc_name(struct idmap_hashtable *h, char *name, size_t len) + { ++ idmap_alloc_hashtable(h); + return idmap_name_hash(h, name, len); + } + + static inline struct idmap_hashent * + idmap_alloc_id(struct idmap_hashtable *h, __u32 id) + { ++ idmap_alloc_hashtable(h); + return idmap_id_hash(h, id); + } + diff --git a/debian/patches/bugfix/all/NFSv4-Reduce-the-footprint-of-the-idmapper.patch b/debian/patches/bugfix/all/NFSv4-Reduce-the-footprint-of-the-idmapper.patch new file mode 100644 index 000000000..e7babc2f3 --- /dev/null +++ b/debian/patches/bugfix/all/NFSv4-Reduce-the-footprint-of-the-idmapper.patch @@ -0,0 +1,62 @@ +From: Trond Myklebust +Date: Tue, 7 Feb 2012 14:59:05 -0500 +Subject: [1/2] NFSv4: Reduce the footprint of the idmapper + +commit d073e9b541e1ac3f52d72c3a153855d9a9ee3278 upstream. + +Instead of pre-allocating the storage for all the strings, we can +significantly reduce the size of that table by doing the allocation +when we do the downcall. + +Signed-off-by: Trond Myklebust +Reviewed-by: Jeff Layton +[bwh: Backported to 3.2: adjust context in nfs_idmap_delete()] +--- + fs/nfs/idmap.c | 16 +++++++++++++--- + 1 file changed, 13 insertions(+), 3 deletions(-) + +--- a/fs/nfs/idmap.c ++++ b/fs/nfs/idmap.c +@@ -318,7 +318,7 @@ + unsigned long ih_expires; + __u32 ih_id; + size_t ih_namelen; +- char ih_name[IDMAP_NAMESZ]; ++ const char *ih_name; + }; + + struct idmap_hashtable { +@@ -382,11 +382,16 @@ + nfs_idmap_delete(struct nfs_client *clp) + { + struct idmap *idmap = clp->cl_idmap; ++ int i; + + if (!idmap) + return; + rpc_unlink(idmap->idmap_dentry); + clp->cl_idmap = NULL; ++ for (i = 0; i < ARRAY_SIZE(idmap->idmap_user_hash.h_entries); i++) ++ kfree(idmap->idmap_user_hash.h_entries[i].ih_name); ++ for (i = 0; i < ARRAY_SIZE(idmap->idmap_group_hash.h_entries); i++) ++ kfree(idmap->idmap_group_hash.h_entries[i].ih_name); + kfree(idmap); + } + +@@ -449,9 +454,14 @@ + idmap_update_entry(struct idmap_hashent *he, const char *name, + size_t namelen, __u32 id) + { ++ char *str = kmalloc(namelen + 1, GFP_KERNEL); ++ if (str == NULL) ++ return; ++ kfree(he->ih_name); + he->ih_id = id; +- memcpy(he->ih_name, name, namelen); +- he->ih_name[namelen] = '\0'; ++ memcpy(str, name, namelen); ++ str[namelen] = '\0'; ++ he->ih_name = str; + he->ih_namelen = namelen; + he->ih_expires = jiffies + nfs_idmap_cache_timeout; + } diff --git a/debian/patches/series-all b/debian/patches/series-all index 1448a6f5b..73aee6ca3 100644 --- a/debian/patches/series-all +++ b/debian/patches/series-all @@ -343,3 +343,6 @@ features/all/hidepid/0001-procfs-parse-mount-options.patch features/all/hidepid/0002-procfs-add-hidepid-and-gid-mount-options.patch features/all/hidepid/0003-proc-fix-null-pointer-deref-in-proc_pid_permission.patch features/all/hidepid/0004-proc-fix-mount-t-proc-o-AAA.patch + +bugfix/all/NFSv4-Reduce-the-footprint-of-the-idmapper.patch +bugfix/all/NFSv4-Further-reduce-the-footprint-of-the-idmapper.patch