aboutsummaryrefslogtreecommitdiffstats
path: root/lib/test_rhashtable.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/test_rhashtable.c')
-rw-r--r--lib/test_rhashtable.c134
1 files changed, 134 insertions, 0 deletions
diff --git a/lib/test_rhashtable.c b/lib/test_rhashtable.c
index 76d3667fdea2..f4000c137dbe 100644
--- a/lib/test_rhashtable.c
+++ b/lib/test_rhashtable.c
@@ -79,6 +79,21 @@ struct thread_data {
79 struct test_obj *objs; 79 struct test_obj *objs;
80}; 80};
81 81
82static u32 my_hashfn(const void *data, u32 len, u32 seed)
83{
84 const struct test_obj_rhl *obj = data;
85
86 return (obj->value.id % 10) << RHT_HASH_RESERVED_SPACE;
87}
88
89static int my_cmpfn(struct rhashtable_compare_arg *arg, const void *obj)
90{
91 const struct test_obj_rhl *test_obj = obj;
92 const struct test_obj_val *val = arg->key;
93
94 return test_obj->value.id - val->id;
95}
96
82static struct rhashtable_params test_rht_params = { 97static struct rhashtable_params test_rht_params = {
83 .head_offset = offsetof(struct test_obj, node), 98 .head_offset = offsetof(struct test_obj, node),
84 .key_offset = offsetof(struct test_obj, value), 99 .key_offset = offsetof(struct test_obj, value),
@@ -87,6 +102,17 @@ static struct rhashtable_params test_rht_params = {
87 .nulls_base = (3U << RHT_BASE_SHIFT), 102 .nulls_base = (3U << RHT_BASE_SHIFT),
88}; 103};
89 104
105static struct rhashtable_params test_rht_params_dup = {
106 .head_offset = offsetof(struct test_obj_rhl, list_node),
107 .key_offset = offsetof(struct test_obj_rhl, value),
108 .key_len = sizeof(struct test_obj_val),
109 .hashfn = jhash,
110 .obj_hashfn = my_hashfn,
111 .obj_cmpfn = my_cmpfn,
112 .nelem_hint = 128,
113 .automatic_shrinking = false,
114};
115
90static struct semaphore prestart_sem; 116static struct semaphore prestart_sem;
91static struct semaphore startup_sem = __SEMAPHORE_INITIALIZER(startup_sem, 0); 117static struct semaphore startup_sem = __SEMAPHORE_INITIALIZER(startup_sem, 0);
92 118
@@ -465,6 +491,112 @@ static int __init test_rhashtable_max(struct test_obj *array,
465 return err; 491 return err;
466} 492}
467 493
494static unsigned int __init print_ht(struct rhltable *rhlt)
495{
496 struct rhashtable *ht;
497 const struct bucket_table *tbl;
498 char buff[512] = "";
499 unsigned int i, cnt = 0;
500
501 ht = &rhlt->ht;
502 tbl = rht_dereference(ht->tbl, ht);
503 for (i = 0; i < tbl->size; i++) {
504 struct rhash_head *pos, *next;
505 struct test_obj_rhl *p;
506
507 pos = rht_dereference(tbl->buckets[i], ht);
508 next = !rht_is_a_nulls(pos) ? rht_dereference(pos->next, ht) : NULL;
509
510 if (!rht_is_a_nulls(pos)) {
511 sprintf(buff, "%s\nbucket[%d] -> ", buff, i);
512 }
513
514 while (!rht_is_a_nulls(pos)) {
515 struct rhlist_head *list = container_of(pos, struct rhlist_head, rhead);
516 sprintf(buff, "%s[[", buff);
517 do {
518 pos = &list->rhead;
519 list = rht_dereference(list->next, ht);
520 p = rht_obj(ht, pos);
521
522 sprintf(buff, "%s val %d (tid=%d)%s", buff, p->value.id, p->value.tid,
523 list? ", " : " ");
524 cnt++;
525 } while (list);
526
527 pos = next,
528 next = !rht_is_a_nulls(pos) ?
529 rht_dereference(pos->next, ht) : NULL;
530
531 sprintf(buff, "%s]]%s", buff, !rht_is_a_nulls(pos) ? " -> " : "");
532 }
533 }
534 printk(KERN_ERR "\n---- ht: ----%s\n-------------\n", buff);
535
536 return cnt;
537}
538
539static int __init test_insert_dup(struct test_obj_rhl *rhl_test_objects,
540 int cnt, bool slow)
541{
542 struct rhltable rhlt;
543 unsigned int i, ret;
544 const char *key;
545 int err = 0;
546
547 err = rhltable_init(&rhlt, &test_rht_params_dup);
548 if (WARN_ON(err))
549 return err;
550
551 for (i = 0; i < cnt; i++) {
552 rhl_test_objects[i].value.tid = i;
553 key = rht_obj(&rhlt.ht, &rhl_test_objects[i].list_node.rhead);
554 key += test_rht_params_dup.key_offset;
555
556 if (slow) {
557 err = PTR_ERR(rhashtable_insert_slow(&rhlt.ht, key,
558 &rhl_test_objects[i].list_node.rhead));
559 if (err == -EAGAIN)
560 err = 0;
561 } else
562 err = rhltable_insert(&rhlt,
563 &rhl_test_objects[i].list_node,
564 test_rht_params_dup);
565 if (WARN(err, "error %d on element %d/%d (%s)\n", err, i, cnt, slow? "slow" : "fast"))
566 goto skip_print;
567 }
568
569 ret = print_ht(&rhlt);
570 WARN(ret != cnt, "missing rhltable elements (%d != %d, %s)\n", ret, cnt, slow? "slow" : "fast");
571
572skip_print:
573 rhltable_destroy(&rhlt);
574
575 return 0;
576}
577
578static int __init test_insert_duplicates_run(void)
579{
580 struct test_obj_rhl rhl_test_objects[3] = {};
581
582 pr_info("test inserting duplicates\n");
583
584 /* two different values that map to same bucket */
585 rhl_test_objects[0].value.id = 1;
586 rhl_test_objects[1].value.id = 21;
587
588 /* and another duplicate with same as [0] value
589 * which will be second on the bucket list */
590 rhl_test_objects[2].value.id = rhl_test_objects[0].value.id;
591
592 test_insert_dup(rhl_test_objects, 2, false);
593 test_insert_dup(rhl_test_objects, 3, false);
594 test_insert_dup(rhl_test_objects, 2, true);
595 test_insert_dup(rhl_test_objects, 3, true);
596
597 return 0;
598}
599
468static int thread_lookup_test(struct thread_data *tdata) 600static int thread_lookup_test(struct thread_data *tdata)
469{ 601{
470 unsigned int entries = tdata->entries; 602 unsigned int entries = tdata->entries;
@@ -613,6 +745,8 @@ static int __init test_rht_init(void)
613 do_div(total_time, runs); 745 do_div(total_time, runs);
614 pr_info("Average test time: %llu\n", total_time); 746 pr_info("Average test time: %llu\n", total_time);
615 747
748 test_insert_duplicates_run();
749
616 if (!tcount) 750 if (!tcount)
617 return 0; 751 return 0;
618 752