]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
NFSv4: Further reduce the footprint of the idmapper
authorTrond Myklebust <Trond.Myklebust@netapp.com>
Wed, 8 Feb 2012 18:39:15 +0000 (13:39 -0500)
committerBen Hutchings <ben@decadent.org.uk>
Wed, 25 Jul 2012 03:11:02 +0000 (04:11 +0100)
commit 685f50f9188ac1e8244d0340a9d6ea36b6136cec upstream.

Don't allocate the legacy idmapper tables until we actually need
them.

Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Reviewed-by: Jeff Layton <jlayton@redhat.com>
[bwh: Backported to 3.2: adjust context in nfs_idmap_delete()]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
fs/nfs/idmap.c

index b8c41c3f259a6b759b2837bd706c67a3c38ea1be..b122af8d73452a1c8e7a58c587fa29868c0abee5 100644 (file)
@@ -323,7 +323,7 @@ struct idmap_hashent {
 
 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 @@ nfs_idmap_new(struct nfs_client *clp)
        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 @@ nfs_idmap_delete(struct nfs_client *clp)
 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 @@ idmap_lookup_name(struct idmap_hashtable *h, const char *name, size_t len)
 {
        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 @@ idmap_lookup_name(struct idmap_hashtable *h, const char *name, size_t len)
 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 @@ static struct idmap_hashent *
 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 @@ idmap_lookup_id(struct idmap_hashtable *h, __u32 id)
 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);
 }