aboutsummaryrefslogtreecommitdiffstats
path: root/lib/rhashtable.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/rhashtable.c')
-rw-r--r--lib/rhashtable.c23
1 files changed, 20 insertions, 3 deletions
diff --git a/lib/rhashtable.c b/lib/rhashtable.c
index 4898442b837f..8609378e6505 100644
--- a/lib/rhashtable.c
+++ b/lib/rhashtable.c
@@ -14,6 +14,7 @@
14 * published by the Free Software Foundation. 14 * published by the Free Software Foundation.
15 */ 15 */
16 16
17#include <linux/atomic.h>
17#include <linux/kernel.h> 18#include <linux/kernel.h>
18#include <linux/init.h> 19#include <linux/init.h>
19#include <linux/log2.h> 20#include <linux/log2.h>
@@ -25,6 +26,7 @@
25#include <linux/random.h> 26#include <linux/random.h>
26#include <linux/rhashtable.h> 27#include <linux/rhashtable.h>
27#include <linux/err.h> 28#include <linux/err.h>
29#include <linux/export.h>
28 30
29#define HASH_DEFAULT_SIZE 64UL 31#define HASH_DEFAULT_SIZE 64UL
30#define HASH_MIN_SIZE 4U 32#define HASH_MIN_SIZE 4U
@@ -405,13 +407,18 @@ int rhashtable_insert_rehash(struct rhashtable *ht)
405 407
406 if (rht_grow_above_75(ht, tbl)) 408 if (rht_grow_above_75(ht, tbl))
407 size *= 2; 409 size *= 2;
408 /* More than two rehashes (not resizes) detected. */ 410 /* Do not schedule more than one rehash */
409 else if (WARN_ON(old_tbl != tbl && old_tbl->size == size)) 411 else if (old_tbl != tbl)
410 return -EBUSY; 412 return -EBUSY;
411 413
412 new_tbl = bucket_table_alloc(ht, size, GFP_ATOMIC); 414 new_tbl = bucket_table_alloc(ht, size, GFP_ATOMIC);
413 if (new_tbl == NULL) 415 if (new_tbl == NULL) {
416 /* Schedule async resize/rehash to try allocation
417 * non-atomic context.
418 */
419 schedule_work(&ht->run_work);
414 return -ENOMEM; 420 return -ENOMEM;
421 }
415 422
416 err = rhashtable_rehash_attach(ht, tbl, new_tbl); 423 err = rhashtable_rehash_attach(ht, tbl, new_tbl);
417 if (err) { 424 if (err) {
@@ -441,6 +448,10 @@ int rhashtable_insert_slow(struct rhashtable *ht, const void *key,
441 if (key && rhashtable_lookup_fast(ht, key, ht->p)) 448 if (key && rhashtable_lookup_fast(ht, key, ht->p))
442 goto exit; 449 goto exit;
443 450
451 err = -E2BIG;
452 if (unlikely(rht_grow_above_max(ht, tbl)))
453 goto exit;
454
444 err = -EAGAIN; 455 err = -EAGAIN;
445 if (rhashtable_check_elasticity(ht, tbl, hash) || 456 if (rhashtable_check_elasticity(ht, tbl, hash) ||
446 rht_grow_above_100(ht, tbl)) 457 rht_grow_above_100(ht, tbl))
@@ -733,6 +744,12 @@ int rhashtable_init(struct rhashtable *ht,
733 if (params->max_size) 744 if (params->max_size)
734 ht->p.max_size = rounddown_pow_of_two(params->max_size); 745 ht->p.max_size = rounddown_pow_of_two(params->max_size);
735 746
747 if (params->insecure_max_entries)
748 ht->p.insecure_max_entries =
749 rounddown_pow_of_two(params->insecure_max_entries);
750 else
751 ht->p.insecure_max_entries = ht->p.max_size * 2;
752
736 ht->p.min_size = max(ht->p.min_size, HASH_MIN_SIZE); 753 ht->p.min_size = max(ht->p.min_size, HASH_MIN_SIZE);
737 754
738 /* The maximum (not average) chain length grows with the 755 /* The maximum (not average) chain length grows with the