rhashtable: fix a memory leak in alloc_bucket_locks()
authorEric Dumazet <[email protected]>
Fri, 26 Aug 2016 15:51:39 +0000 (08:51 -0700)
committerDavid S. Miller <[email protected]>
Sat, 27 Aug 2016 04:59:53 +0000 (21:59 -0700)
If vmalloc() was successful, do not attempt a kmalloc_array()

Fixes: 4cf0b354d92e ("rhashtable: avoid large lock-array allocations")
Reported-by: CAI Qian <[email protected]>
Signed-off-by: Eric Dumazet <[email protected]>
Cc: Florian Westphal <[email protected]>
Acked-by: Herbert Xu <[email protected]>
Tested-by: CAI Qian <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
lib/rhashtable.c

index 5ba520b544d73ff1a62705584d1971aeee6ec2ba..56054e541a0f92fb69d1de4502c4230d8b4f6c3d 100644 (file)
@@ -77,17 +77,18 @@ static int alloc_bucket_locks(struct rhashtable *ht, struct bucket_table *tbl,
        size = min_t(unsigned int, size, tbl->size >> 1);
 
        if (sizeof(spinlock_t) != 0) {
+               tbl->locks = NULL;
 #ifdef CONFIG_NUMA
                if (size * sizeof(spinlock_t) > PAGE_SIZE &&
                    gfp == GFP_KERNEL)
                        tbl->locks = vmalloc(size * sizeof(spinlock_t));
-               else
 #endif
                if (gfp != GFP_KERNEL)
                        gfp |= __GFP_NOWARN | __GFP_NORETRY;
 
-               tbl->locks = kmalloc_array(size, sizeof(spinlock_t),
-                                          gfp);
+               if (!tbl->locks)
+                       tbl->locks = kmalloc_array(size, sizeof(spinlock_t),
+                                                  gfp);
                if (!tbl->locks)
                        return -ENOMEM;
                for (i = 0; i < size; i++)