aboutsummaryrefslogtreecommitdiffstats
path: root/lib/rhashtable.c
diff options
context:
space:
mode:
authorThomas Graf <tgraf@suug.ch>2014-11-24 06:37:58 -0500
committerDavid S. Miller <davem@davemloft.net>2014-11-24 16:17:31 -0500
commit3e7b2ec4fe8ef4b05b33db3e84d1b1fbccde250e (patch)
tree518201f6e9babaab13de4c9c62de45ed43d8b31a /lib/rhashtable.c
parent08dcf9fd194cf19d3b282a81cc3539202e768ca4 (diff)
rhashtable: Check for count mismatch while iterating in selftest
Verify whether both the lock and RCU protected iterators see all test entries before and after expanding and shrinking has been performed. Also verify whether the number of entries in the hashtable remains stable during expansion and shrinking. Signed-off-by: Thomas Graf <tgraf@suug.ch> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'lib/rhashtable.c')
-rw-r--r--lib/rhashtable.c27
1 files changed, 20 insertions, 7 deletions
diff --git a/lib/rhashtable.c b/lib/rhashtable.c
index e5f5e69c7a7b..c7e987ab3361 100644
--- a/lib/rhashtable.c
+++ b/lib/rhashtable.c
@@ -653,15 +653,15 @@ static int __init test_rht_lookup(struct rhashtable *ht)
653 return 0; 653 return 0;
654} 654}
655 655
656static void test_bucket_stats(struct rhashtable *ht, 656static void test_bucket_stats(struct rhashtable *ht, bool quiet)
657 struct bucket_table *tbl,
658 bool quiet)
659{ 657{
660 unsigned int cnt, i, total = 0; 658 unsigned int cnt, rcu_cnt, i, total = 0;
661 struct test_obj *obj; 659 struct test_obj *obj;
660 struct bucket_table *tbl;
662 661
662 tbl = rht_dereference_rcu(ht->tbl, ht);
663 for (i = 0; i < tbl->size; i++) { 663 for (i = 0; i < tbl->size; i++) {
664 cnt = 0; 664 rcu_cnt = cnt = 0;
665 665
666 if (!quiet) 666 if (!quiet)
667 pr_info(" [%#4x/%zu]", i, tbl->size); 667 pr_info(" [%#4x/%zu]", i, tbl->size);
@@ -673,6 +673,13 @@ static void test_bucket_stats(struct rhashtable *ht,
673 pr_cont(" [%p],", obj); 673 pr_cont(" [%p],", obj);
674 } 674 }
675 675
676 rht_for_each_entry_rcu(obj, tbl->buckets[i], node)
677 rcu_cnt++;
678
679 if (rcu_cnt != cnt)
680 pr_warn("Test failed: Chain count mismach %d != %d",
681 cnt, rcu_cnt);
682
676 if (!quiet) 683 if (!quiet)
677 pr_cont("\n [%#x] first element: %p, chain length: %u\n", 684 pr_cont("\n [%#x] first element: %p, chain length: %u\n",
678 i, tbl->buckets[i], cnt); 685 i, tbl->buckets[i], cnt);
@@ -680,6 +687,9 @@ static void test_bucket_stats(struct rhashtable *ht,
680 687
681 pr_info(" Traversal complete: counted=%u, nelems=%zu, entries=%d\n", 688 pr_info(" Traversal complete: counted=%u, nelems=%zu, entries=%d\n",
682 total, ht->nelems, TEST_ENTRIES); 689 total, ht->nelems, TEST_ENTRIES);
690
691 if (total != ht->nelems || total != TEST_ENTRIES)
692 pr_warn("Test failed: Total count mismatch ^^^");
683} 693}
684 694
685static int __init test_rhashtable(struct rhashtable *ht) 695static int __init test_rhashtable(struct rhashtable *ht)
@@ -710,8 +720,7 @@ static int __init test_rhashtable(struct rhashtable *ht)
710 } 720 }
711 721
712 rcu_read_lock(); 722 rcu_read_lock();
713 tbl = rht_dereference_rcu(ht->tbl, ht); 723 test_bucket_stats(ht, true);
714 test_bucket_stats(ht, tbl, true);
715 test_rht_lookup(ht); 724 test_rht_lookup(ht);
716 rcu_read_unlock(); 725 rcu_read_unlock();
717 726
@@ -735,6 +744,10 @@ static int __init test_rhashtable(struct rhashtable *ht)
735 rcu_read_unlock(); 744 rcu_read_unlock();
736 } 745 }
737 746
747 rcu_read_lock();
748 test_bucket_stats(ht, true);
749 rcu_read_unlock();
750
738 pr_info(" Deleting %d keys\n", TEST_ENTRIES); 751 pr_info(" Deleting %d keys\n", TEST_ENTRIES);
739 for (i = 0; i < TEST_ENTRIES; i++) { 752 for (i = 0; i < TEST_ENTRIES; i++) {
740 u32 key = i * 2; 753 u32 key = i * 2;