diff options
Diffstat (limited to 'lib/test_rhashtable.c')
| -rw-r--r-- | lib/test_rhashtable.c | 124 |
1 files changed, 55 insertions, 69 deletions
diff --git a/lib/test_rhashtable.c b/lib/test_rhashtable.c index 6a8ac7626797..c63db03ebb9d 100644 --- a/lib/test_rhashtable.c +++ b/lib/test_rhashtable.c @@ -1,12 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Resizable, Scalable, Concurrent Hash Table * * Copyright (c) 2014-2015 Thomas Graf <tgraf@suug.ch> * Copyright (c) 2008-2014 Patrick McHardy <kaber@trash.net> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. */ /************************************************************************** @@ -19,6 +16,7 @@ #include <linux/kthread.h> #include <linux/module.h> #include <linux/rcupdate.h> +#include <linux/rcupdate_wait.h> #include <linux/rhashtable.h> #include <linux/slab.h> #include <linux/sched.h> @@ -177,16 +175,11 @@ static int __init test_rht_lookup(struct rhashtable *ht, struct test_obj *array, static void test_bucket_stats(struct rhashtable *ht, unsigned int entries) { - unsigned int err, total = 0, chain_len = 0; + unsigned int total = 0, chain_len = 0; struct rhashtable_iter hti; struct rhash_head *pos; - err = rhashtable_walk_init(ht, &hti, GFP_KERNEL); - if (err) { - pr_warn("Test failed: allocation error"); - return; - } - + rhashtable_walk_enter(ht, &hti); rhashtable_walk_start(&hti); while ((pos = rhashtable_walk_next(&hti))) { @@ -299,7 +292,7 @@ static int __init test_rhltable(unsigned int entries) if (WARN_ON(err)) goto out_free; - k = prandom_u32(); + k = get_random_u32(); ret = 0; for (i = 0; i < entries; i++) { rhl_test_objects[i].value.id = k; @@ -376,60 +369,46 @@ static int __init test_rhltable(unsigned int entries) pr_info("test %d random rhlist add/delete operations\n", entries); for (j = 0; j < entries; j++) { - u32 i = prandom_u32_max(entries); - u32 prand = prandom_u32(); + u32 i = get_random_u32_below(entries); + u32 prand = get_random_u32_below(4); cond_resched(); - if (prand == 0) - prand = prandom_u32(); - - if (prand & 1) { - prand >>= 1; - continue; - } - err = rhltable_remove(&rhlt, &rhl_test_objects[i].list_node, test_rht_params); if (test_bit(i, obj_in_table)) { clear_bit(i, obj_in_table); if (WARN(err, "cannot remove element at slot %d", i)) continue; } else { - if (WARN(err != -ENOENT, "removed non-existant element %d, error %d not %d", + if (WARN(err != -ENOENT, "removed non-existent element %d, error %d not %d", i, err, -ENOENT)) continue; } if (prand & 1) { - prand >>= 1; - continue; - } - - err = rhltable_insert(&rhlt, &rhl_test_objects[i].list_node, test_rht_params); - if (err == 0) { - if (WARN(test_and_set_bit(i, obj_in_table), "succeeded to insert same object %d", i)) - continue; - } else { - if (WARN(!test_bit(i, obj_in_table), "failed to insert object %d", i)) - continue; - } - - if (prand & 1) { - prand >>= 1; - continue; + err = rhltable_insert(&rhlt, &rhl_test_objects[i].list_node, test_rht_params); + if (err == 0) { + if (WARN(test_and_set_bit(i, obj_in_table), "succeeded to insert same object %d", i)) + continue; + } else { + if (WARN(!test_bit(i, obj_in_table), "failed to insert object %d", i)) + continue; + } } - i = prandom_u32_max(entries); - if (test_bit(i, obj_in_table)) { - err = rhltable_remove(&rhlt, &rhl_test_objects[i].list_node, test_rht_params); - WARN(err, "cannot remove element at slot %d", i); - if (err == 0) - clear_bit(i, obj_in_table); - } else { - err = rhltable_insert(&rhlt, &rhl_test_objects[i].list_node, test_rht_params); - WARN(err, "failed to insert object %d", i); - if (err == 0) - set_bit(i, obj_in_table); + if (prand & 2) { + i = get_random_u32_below(entries); + if (test_bit(i, obj_in_table)) { + err = rhltable_remove(&rhlt, &rhl_test_objects[i].list_node, test_rht_params); + WARN(err, "cannot remove element at slot %d", i); + if (err == 0) + clear_bit(i, obj_in_table); + } else { + err = rhltable_insert(&rhlt, &rhl_test_objects[i].list_node, test_rht_params); + WARN(err, "failed to insert object %d", i); + if (err == 0) + set_bit(i, obj_in_table); + } } } @@ -440,9 +419,9 @@ static int __init test_rhltable(unsigned int entries) if (WARN(err, "cannot remove element at slot %d", i)) continue; } else { - if (WARN(err != -ENOENT, "removed non-existant element, error %d not %d", + if (WARN(err != -ENOENT, "removed non-existent element, error %d not %d", err, -ENOENT)) - continue; + continue; } } @@ -456,7 +435,7 @@ out_free: static int __init test_rhashtable_max(struct test_obj *array, unsigned int entries) { - unsigned int i, insert_retries = 0; + unsigned int i; int err; test_rht_params.max_size = roundup_pow_of_two(entries / 8); @@ -469,9 +448,7 @@ static int __init test_rhashtable_max(struct test_obj *array, obj->value.id = i * 2; err = insert_retry(&ht, obj, test_rht_params); - if (err > 0) - insert_retries += err; - else if (err) + if (err < 0) return err; } @@ -495,6 +472,7 @@ static unsigned int __init print_ht(struct rhltable *rhlt) struct rhashtable *ht; const struct bucket_table *tbl; char buff[512] = ""; + int offset = 0; unsigned int i, cnt = 0; ht = &rhlt->ht; @@ -505,22 +483,22 @@ static unsigned int __init print_ht(struct rhltable *rhlt) struct rhash_head *pos, *next; struct test_obj_rhl *p; - pos = rht_dereference(tbl->buckets[i], ht); + pos = rht_ptr_exclusive(tbl->buckets + i); next = !rht_is_a_nulls(pos) ? rht_dereference(pos->next, ht) : NULL; if (!rht_is_a_nulls(pos)) { - sprintf(buff, "%s\nbucket[%d] -> ", buff, i); + offset += sprintf(buff + offset, "\nbucket[%d] -> ", i); } while (!rht_is_a_nulls(pos)) { struct rhlist_head *list = container_of(pos, struct rhlist_head, rhead); - sprintf(buff, "%s[[", buff); + offset += sprintf(buff + offset, "[["); do { pos = &list->rhead; list = rht_dereference(list->next, ht); p = rht_obj(ht, pos); - sprintf(buff, "%s val %d (tid=%d)%s", buff, p->value.id, p->value.tid, + offset += sprintf(buff + offset, " val %d (tid=%d)%s", p->value.id, p->value.tid, list? ", " : " "); cnt++; } while (list); @@ -529,7 +507,7 @@ static unsigned int __init print_ht(struct rhltable *rhlt) next = !rht_is_a_nulls(pos) ? rht_dereference(pos->next, ht) : NULL; - sprintf(buff, "%s]]%s", buff, !rht_is_a_nulls(pos) ? " -> " : ""); + offset += sprintf(buff + offset, "]]%s", !rht_is_a_nulls(pos) ? " -> " : ""); } } printk(KERN_ERR "\n---- ht: ----%s\n-------------\n", buff); @@ -541,38 +519,45 @@ static unsigned int __init print_ht(struct rhltable *rhlt) static int __init test_insert_dup(struct test_obj_rhl *rhl_test_objects, int cnt, bool slow) { - struct rhltable rhlt; + struct rhltable *rhlt; unsigned int i, ret; const char *key; int err = 0; - err = rhltable_init(&rhlt, &test_rht_params_dup); - if (WARN_ON(err)) + rhlt = kmalloc(sizeof(*rhlt), GFP_KERNEL); + if (WARN_ON(!rhlt)) + return -EINVAL; + + err = rhltable_init(rhlt, &test_rht_params_dup); + if (WARN_ON(err)) { + kfree(rhlt); return err; + } for (i = 0; i < cnt; i++) { rhl_test_objects[i].value.tid = i; - key = rht_obj(&rhlt.ht, &rhl_test_objects[i].list_node.rhead); + key = rht_obj(&rhlt->ht, &rhl_test_objects[i].list_node.rhead); key += test_rht_params_dup.key_offset; if (slow) { - err = PTR_ERR(rhashtable_insert_slow(&rhlt.ht, key, + err = PTR_ERR(rhashtable_insert_slow(&rhlt->ht, key, &rhl_test_objects[i].list_node.rhead)); if (err == -EAGAIN) err = 0; } else - err = rhltable_insert(&rhlt, + err = rhltable_insert(rhlt, &rhl_test_objects[i].list_node, test_rht_params_dup); if (WARN(err, "error %d on element %d/%d (%s)\n", err, i, cnt, slow? "slow" : "fast")) goto skip_print; } - ret = print_ht(&rhlt); + ret = print_ht(rhlt); WARN(ret != cnt, "missing rhltable elements (%d != %d, %s)\n", ret, cnt, slow? "slow" : "fast"); skip_print: - rhltable_destroy(&rhlt); + rhltable_destroy(rhlt); + kfree(rhlt); return 0; } @@ -826,4 +811,5 @@ static void __exit test_rht_exit(void) module_init(test_rht_init); module_exit(test_rht_exit); +MODULE_DESCRIPTION("Resizable, Scalable, Concurrent Hash Table test module"); MODULE_LICENSE("GPL v2"); |
