]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - lib/rhashtable.c
Merge branch 'akpm' (patches from Andrew)
[linux.git] / lib / rhashtable.c
index ae4223e0f5bcb68610511b2cb7ba2e12b7f7d086..30526afa8343124f06f0649592ee246dc4d88fbe 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/rhashtable.h>
 #include <linux/err.h>
 #include <linux/export.h>
-#include <linux/rhashtable.h>
 
 #define HASH_DEFAULT_SIZE      64UL
 #define HASH_MIN_SIZE          4U
@@ -174,17 +173,15 @@ static struct bucket_table *bucket_table_alloc(struct rhashtable *ht,
        int i;
 
        size = sizeof(*tbl) + nbuckets * sizeof(tbl->buckets[0]);
-       if (gfp != GFP_KERNEL)
-               tbl = kzalloc(size, gfp | __GFP_NOWARN | __GFP_NORETRY);
-       else
-               tbl = kvzalloc(size, gfp);
+       tbl = kvzalloc(size, gfp);
 
        size = nbuckets;
 
-       if (tbl == NULL && gfp != GFP_KERNEL) {
+       if (tbl == NULL && (gfp & ~__GFP_NOFAIL) != GFP_KERNEL) {
                tbl = nested_bucket_table_alloc(ht, nbuckets, gfp);
                nbuckets = 0;
        }
+
        if (tbl == NULL)
                return NULL;
 
@@ -450,7 +447,7 @@ static int rhashtable_insert_rehash(struct rhashtable *ht,
 
        err = -ENOMEM;
 
-       new_tbl = bucket_table_alloc(ht, size, GFP_ATOMIC);
+       new_tbl = bucket_table_alloc(ht, size, GFP_ATOMIC | __GFP_NOWARN);
        if (new_tbl == NULL)
                goto fail;
 
@@ -1060,9 +1057,16 @@ int rhashtable_init(struct rhashtable *ht,
                }
        }
 
+       /*
+        * This is api initialization and thus we need to guarantee the
+        * initial rhashtable allocation. Upon failure, retry with the
+        * smallest possible size with __GFP_NOFAIL semantics.
+        */
        tbl = bucket_table_alloc(ht, size, GFP_KERNEL);
-       if (tbl == NULL)
-               return -ENOMEM;
+       if (unlikely(tbl == NULL)) {
+               size = max_t(u16, ht->p.min_size, HASH_MIN_SIZE);
+               tbl = bucket_table_alloc(ht, size, GFP_KERNEL | __GFP_NOFAIL);
+       }
 
        atomic_set(&ht->nelems, 0);