d2912cb15bdda (Thomas Gleixner 2019-06-04 10:11:33 +0200 1) // SPDX-License-Identifier: GPL-2.0-only
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 2) /*
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 3) * Resizable, Scalable, Concurrent Hash Table
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 4) *
1aa661f5c3df1 (Thomas Graf 2015-04-30 22:37:41 +0000 5) * Copyright (c) 2014-2015 Thomas Graf <tgraf@suug.ch>
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 6) * Copyright (c) 2008-2014 Patrick McHardy <kaber@trash.net>
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 7) */
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 8)
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 9) /**************************************************************************
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 10) * Self Test
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 11) **************************************************************************/
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 12)
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 13) #include <linux/init.h>
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 14) #include <linux/jhash.h>
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 15) #include <linux/kernel.h>
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 16) #include <linux/kthread.h>
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 17) #include <linux/module.h>
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 18) #include <linux/rcupdate.h>
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 19) #include <linux/rhashtable.h>
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 20) #include <linux/slab.h>
685a015e44dcd (Thomas Graf 2015-07-17 10:52:48 +0200 21) #include <linux/sched.h>
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 22) #include <linux/random.h>
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 23) #include <linux/vmalloc.h>
809c67059162e (Arnd Bergmann 2018-12-16 20:48:21 +0100 24) #include <linux/wait.h>
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 25)
1aa661f5c3df1 (Thomas Graf 2015-04-30 22:37:41 +0000 26) #define MAX_ENTRIES 1000000
67b7cbf4203f7 (Thomas Graf 2015-04-30 22:37:45 +0000 27) #define TEST_INSERT_FAIL INT_MAX
1aa661f5c3df1 (Thomas Graf 2015-04-30 22:37:41 +0000 28)
f651616e799ff (Florian Westphal 2017-09-20 01:12:12 +0200 29) static int parm_entries = 50000;
f651616e799ff (Florian Westphal 2017-09-20 01:12:12 +0200 30) module_param(parm_entries, int, 0);
f651616e799ff (Florian Westphal 2017-09-20 01:12:12 +0200 31) MODULE_PARM_DESC(parm_entries, "Number of entries to add (default: 50000)");
1aa661f5c3df1 (Thomas Graf 2015-04-30 22:37:41 +0000 32)
1aa661f5c3df1 (Thomas Graf 2015-04-30 22:37:41 +0000 33) static int runs = 4;
1aa661f5c3df1 (Thomas Graf 2015-04-30 22:37:41 +0000 34) module_param(runs, int, 0);
1aa661f5c3df1 (Thomas Graf 2015-04-30 22:37:41 +0000 35) MODULE_PARM_DESC(runs, "Number of test runs per variant (default: 4)");
1aa661f5c3df1 (Thomas Graf 2015-04-30 22:37:41 +0000 36)
95e435afefe98 (Phil Sutter 2015-11-20 18:17:19 +0100 37) static int max_size = 0;
1aa661f5c3df1 (Thomas Graf 2015-04-30 22:37:41 +0000 38) module_param(max_size, int, 0);
3b3bf80b994f0 (Phil Sutter 2016-08-04 12:37:17 +0200 39) MODULE_PARM_DESC(max_size, "Maximum table size (default: calculated)");
1aa661f5c3df1 (Thomas Graf 2015-04-30 22:37:41 +0000 40)
1aa661f5c3df1 (Thomas Graf 2015-04-30 22:37:41 +0000 41) static bool shrinking = false;
1aa661f5c3df1 (Thomas Graf 2015-04-30 22:37:41 +0000 42) module_param(shrinking, bool, 0);
1aa661f5c3df1 (Thomas Graf 2015-04-30 22:37:41 +0000 43) MODULE_PARM_DESC(shrinking, "Enable automatic shrinking (default: off)");
1aa661f5c3df1 (Thomas Graf 2015-04-30 22:37:41 +0000 44)
1aa661f5c3df1 (Thomas Graf 2015-04-30 22:37:41 +0000 45) static int size = 8;
1aa661f5c3df1 (Thomas Graf 2015-04-30 22:37:41 +0000 46) module_param(size, int, 0);
1aa661f5c3df1 (Thomas Graf 2015-04-30 22:37:41 +0000 47) MODULE_PARM_DESC(size, "Initial size hint of table (default: 8)");
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 48)
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 49) static int tcount = 10;
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 50) module_param(tcount, int, 0);
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 51) MODULE_PARM_DESC(tcount, "Number of threads to spawn (default: 10)");
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 52)
d662e037fc88b (Phil Sutter 2015-11-20 18:17:20 +0100 53) static bool enomem_retry = false;
d662e037fc88b (Phil Sutter 2015-11-20 18:17:20 +0100 54) module_param(enomem_retry, bool, 0);
d662e037fc88b (Phil Sutter 2015-11-20 18:17:20 +0100 55) MODULE_PARM_DESC(enomem_retry, "Retry insert even if -ENOMEM was returned (default: off)");
d662e037fc88b (Phil Sutter 2015-11-20 18:17:20 +0100 56)
e859afe1ee0c5 (Phil Sutter 2017-07-21 16:51:31 +0200 57) struct test_obj_val {
e859afe1ee0c5 (Phil Sutter 2017-07-21 16:51:31 +0200 58) int id;
e859afe1ee0c5 (Phil Sutter 2017-07-21 16:51:31 +0200 59) int tid;
e859afe1ee0c5 (Phil Sutter 2017-07-21 16:51:31 +0200 60) };
e859afe1ee0c5 (Phil Sutter 2017-07-21 16:51:31 +0200 61)
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 62) struct test_obj {
e859afe1ee0c5 (Phil Sutter 2017-07-21 16:51:31 +0200 63) struct test_obj_val value;
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 64) struct rhash_head node;
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 65) };
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 66)
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 67) struct test_obj_rhl {
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 68) struct test_obj_val value;
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 69) struct rhlist_head list_node;
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 70) };
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 71)
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 72) struct thread_data {
f651616e799ff (Florian Westphal 2017-09-20 01:12:12 +0200 73) unsigned int entries;
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 74) int id;
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 75) struct task_struct *task;
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 76) struct test_obj *objs;
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 77) };
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 78)
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 79) static u32 my_hashfn(const void *data, u32 len, u32 seed)
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 80) {
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 81) const struct test_obj_rhl *obj = data;
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 82)
9f9a707738aa7 (NeilBrown 2018-06-18 12:52:50 +1000 83) return (obj->value.id % 10);
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 84) }
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 85)
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 86) static int my_cmpfn(struct rhashtable_compare_arg *arg, const void *obj)
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 87) {
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 88) const struct test_obj_rhl *test_obj = obj;
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 89) const struct test_obj_val *val = arg->key;
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 90)
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 91) return test_obj->value.id - val->id;
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 92) }
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 93)
1aa661f5c3df1 (Thomas Graf 2015-04-30 22:37:41 +0000 94) static struct rhashtable_params test_rht_params = {
b182aa6e967e8 (Herbert Xu 2015-03-20 21:57:04 +1100 95) .head_offset = offsetof(struct test_obj, node),
b182aa6e967e8 (Herbert Xu 2015-03-20 21:57:04 +1100 96) .key_offset = offsetof(struct test_obj, value),
e859afe1ee0c5 (Phil Sutter 2017-07-21 16:51:31 +0200 97) .key_len = sizeof(struct test_obj_val),
b182aa6e967e8 (Herbert Xu 2015-03-20 21:57:04 +1100 98) .hashfn = jhash,
b182aa6e967e8 (Herbert Xu 2015-03-20 21:57:04 +1100 99) };
b182aa6e967e8 (Herbert Xu 2015-03-20 21:57:04 +1100 100)
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 101) static struct rhashtable_params test_rht_params_dup = {
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 102) .head_offset = offsetof(struct test_obj_rhl, list_node),
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 103) .key_offset = offsetof(struct test_obj_rhl, value),
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 104) .key_len = sizeof(struct test_obj_val),
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 105) .hashfn = jhash,
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 106) .obj_hashfn = my_hashfn,
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 107) .obj_cmpfn = my_cmpfn,
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 108) .nelem_hint = 128,
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 109) .automatic_shrinking = false,
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 110) };
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 111)
809c67059162e (Arnd Bergmann 2018-12-16 20:48:21 +0100 112) static atomic_t startup_count;
809c67059162e (Arnd Bergmann 2018-12-16 20:48:21 +0100 113) static DECLARE_WAIT_QUEUE_HEAD(startup_wait);
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 114)
7e936bd73483e (Florian Westphal 2017-09-20 01:12:11 +0200 115) static int insert_retry(struct rhashtable *ht, struct test_obj *obj,
9e9089e5a2d78 (Phil Sutter 2015-11-20 18:17:18 +0100 116) const struct rhashtable_params params)
9e9089e5a2d78 (Phil Sutter 2015-11-20 18:17:18 +0100 117) {
d662e037fc88b (Phil Sutter 2015-11-20 18:17:20 +0100 118) int err, retries = -1, enomem_retries = 0;
9e9089e5a2d78 (Phil Sutter 2015-11-20 18:17:18 +0100 119)
9e9089e5a2d78 (Phil Sutter 2015-11-20 18:17:18 +0100 120) do {
9e9089e5a2d78 (Phil Sutter 2015-11-20 18:17:18 +0100 121) retries++;
9e9089e5a2d78 (Phil Sutter 2015-11-20 18:17:18 +0100 122) cond_resched();
7e936bd73483e (Florian Westphal 2017-09-20 01:12:11 +0200 123) err = rhashtable_insert_fast(ht, &obj->node, params);
d662e037fc88b (Phil Sutter 2015-11-20 18:17:20 +0100 124) if (err == -ENOMEM && enomem_retry) {
d662e037fc88b (Phil Sutter 2015-11-20 18:17:20 +0100 125) enomem_retries++;
d662e037fc88b (Phil Sutter 2015-11-20 18:17:20 +0100 126) err = -EBUSY;
d662e037fc88b (Phil Sutter 2015-11-20 18:17:20 +0100 127) }
9e9089e5a2d78 (Phil Sutter 2015-11-20 18:17:18 +0100 128) } while (err == -EBUSY);
9e9089e5a2d78 (Phil Sutter 2015-11-20 18:17:18 +0100 129)
d662e037fc88b (Phil Sutter 2015-11-20 18:17:20 +0100 130) if (enomem_retries)
d662e037fc88b (Phil Sutter 2015-11-20 18:17:20 +0100 131) pr_info(" %u insertions retried after -ENOMEM\n",
d662e037fc88b (Phil Sutter 2015-11-20 18:17:20 +0100 132) enomem_retries);
d662e037fc88b (Phil Sutter 2015-11-20 18:17:20 +0100 133)
9e9089e5a2d78 (Phil Sutter 2015-11-20 18:17:18 +0100 134) return err ? : retries;
9e9089e5a2d78 (Phil Sutter 2015-11-20 18:17:18 +0100 135) }
9e9089e5a2d78 (Phil Sutter 2015-11-20 18:17:18 +0100 136)
f651616e799ff (Florian Westphal 2017-09-20 01:12:12 +0200 137) static int __init test_rht_lookup(struct rhashtable *ht, struct test_obj *array,
f651616e799ff (Florian Westphal 2017-09-20 01:12:12 +0200 138) unsigned int entries)
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 139) {
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 140) unsigned int i;
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 141)
f651616e799ff (Florian Westphal 2017-09-20 01:12:12 +0200 142) for (i = 0; i < entries; i++) {
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 143) struct test_obj *obj;
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 144) bool expected = !(i % 2);
e859afe1ee0c5 (Phil Sutter 2017-07-21 16:51:31 +0200 145) struct test_obj_val key = {
e859afe1ee0c5 (Phil Sutter 2017-07-21 16:51:31 +0200 146) .id = i,
e859afe1ee0c5 (Phil Sutter 2017-07-21 16:51:31 +0200 147) };
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 148)
e859afe1ee0c5 (Phil Sutter 2017-07-21 16:51:31 +0200 149) if (array[i / 2].value.id == TEST_INSERT_FAIL)
67b7cbf4203f7 (Thomas Graf 2015-04-30 22:37:45 +0000 150) expected = false;
67b7cbf4203f7 (Thomas Graf 2015-04-30 22:37:45 +0000 151)
b182aa6e967e8 (Herbert Xu 2015-03-20 21:57:04 +1100 152) obj = rhashtable_lookup_fast(ht, &key, test_rht_params);
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 153)
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 154) if (expected && !obj) {
e859afe1ee0c5 (Phil Sutter 2017-07-21 16:51:31 +0200 155) pr_warn("Test failed: Could not find key %u\n", key.id);
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 156) return -ENOENT;
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 157) } else if (!expected && obj) {
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 158) pr_warn("Test failed: Unexpected entry found for key %u\n",
e859afe1ee0c5 (Phil Sutter 2017-07-21 16:51:31 +0200 159) key.id);
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 160) return -EEXIST;
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 161) } else if (expected && obj) {
e859afe1ee0c5 (Phil Sutter 2017-07-21 16:51:31 +0200 162) if (obj->value.id != i) {
c2c8a901660dc (Thomas Graf 2015-04-30 22:37:42 +0000 163) pr_warn("Test failed: Lookup value mismatch %u!=%u\n",
e859afe1ee0c5 (Phil Sutter 2017-07-21 16:51:31 +0200 164) obj->value.id, i);
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 165) return -EINVAL;
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 166) }
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 167) }
685a015e44dcd (Thomas Graf 2015-07-17 10:52:48 +0200 168)
685a015e44dcd (Thomas Graf 2015-07-17 10:52:48 +0200 169) cond_resched_rcu();
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 170) }
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 171)
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 172) return 0;
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 173) }
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 174)
f651616e799ff (Florian Westphal 2017-09-20 01:12:12 +0200 175) static void test_bucket_stats(struct rhashtable *ht, unsigned int entries)
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 176) {
6c4128f658571 (Herbert Xu 2019-02-14 22:03:27 +0800 177) unsigned int total = 0, chain_len = 0;
246b23a7695bd (Thomas Graf 2015-04-30 22:37:44 +0000 178) struct rhashtable_iter hti;
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 179) struct rhash_head *pos;
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 180)
6c4128f658571 (Herbert Xu 2019-02-14 22:03:27 +0800 181) rhashtable_walk_enter(ht, &hti);
97a6ec4ac021f (Tom Herbert 2017-12-04 10:31:41 -0800 182) rhashtable_walk_start(&hti);
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 183)
246b23a7695bd (Thomas Graf 2015-04-30 22:37:44 +0000 184) while ((pos = rhashtable_walk_next(&hti))) {
246b23a7695bd (Thomas Graf 2015-04-30 22:37:44 +0000 185) if (PTR_ERR(pos) == -EAGAIN) {
246b23a7695bd (Thomas Graf 2015-04-30 22:37:44 +0000 186) pr_info("Info: encountered resize\n");
246b23a7695bd (Thomas Graf 2015-04-30 22:37:44 +0000 187) chain_len++;
246b23a7695bd (Thomas Graf 2015-04-30 22:37:44 +0000 188) continue;
246b23a7695bd (Thomas Graf 2015-04-30 22:37:44 +0000 189) } else if (IS_ERR(pos)) {
246b23a7695bd (Thomas Graf 2015-04-30 22:37:44 +0000 190) pr_warn("Test failed: rhashtable_walk_next() error: %ld\n",
246b23a7695bd (Thomas Graf 2015-04-30 22:37:44 +0000 191) PTR_ERR(pos));
246b23a7695bd (Thomas Graf 2015-04-30 22:37:44 +0000 192) break;
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 193) }
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 194)
246b23a7695bd (Thomas Graf 2015-04-30 22:37:44 +0000 195) total++;
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 196) }
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 197)
246b23a7695bd (Thomas Graf 2015-04-30 22:37:44 +0000 198) rhashtable_walk_stop(&hti);
246b23a7695bd (Thomas Graf 2015-04-30 22:37:44 +0000 199) rhashtable_walk_exit(&hti);
246b23a7695bd (Thomas Graf 2015-04-30 22:37:44 +0000 200)
246b23a7695bd (Thomas Graf 2015-04-30 22:37:44 +0000 201) pr_info(" Traversal complete: counted=%u, nelems=%u, entries=%d, table-jumps=%u\n",
246b23a7695bd (Thomas Graf 2015-04-30 22:37:44 +0000 202) total, atomic_read(&ht->nelems), entries, chain_len);
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 203)
1aa661f5c3df1 (Thomas Graf 2015-04-30 22:37:41 +0000 204) if (total != atomic_read(&ht->nelems) || total != entries)
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 205) pr_warn("Test failed: Total count mismatch ^^^");
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 206) }
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 207)
f651616e799ff (Florian Westphal 2017-09-20 01:12:12 +0200 208) static s64 __init test_rhashtable(struct rhashtable *ht, struct test_obj *array,
f651616e799ff (Florian Westphal 2017-09-20 01:12:12 +0200 209) unsigned int entries)
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 210) {
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 211) struct test_obj *obj;
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 212) int err;
9e9089e5a2d78 (Phil Sutter 2015-11-20 18:17:18 +0100 213) unsigned int i, insert_retries = 0;
1aa661f5c3df1 (Thomas Graf 2015-04-30 22:37:41 +0000 214) s64 start, end;
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 215)
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 216) /*
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 217) * Insertion Test:
1aa661f5c3df1 (Thomas Graf 2015-04-30 22:37:41 +0000 218) * Insert entries into table with all keys even numbers
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 219) */
1aa661f5c3df1 (Thomas Graf 2015-04-30 22:37:41 +0000 220) pr_info(" Adding %d keys\n", entries);
1aa661f5c3df1 (Thomas Graf 2015-04-30 22:37:41 +0000 221) start = ktime_get_ns();
1aa661f5c3df1 (Thomas Graf 2015-04-30 22:37:41 +0000 222) for (i = 0; i < entries; i++) {
fcc570207c1e7 (Thomas Graf 2015-04-30 22:37:43 +0000 223) struct test_obj *obj = &array[i];
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 224)
e859afe1ee0c5 (Phil Sutter 2017-07-21 16:51:31 +0200 225) obj->value.id = i * 2;
7e936bd73483e (Florian Westphal 2017-09-20 01:12:11 +0200 226) err = insert_retry(ht, obj, test_rht_params);
9e9089e5a2d78 (Phil Sutter 2015-11-20 18:17:18 +0100 227) if (err > 0)
9e9089e5a2d78 (Phil Sutter 2015-11-20 18:17:18 +0100 228) insert_retries += err;
9e9089e5a2d78 (Phil Sutter 2015-11-20 18:17:18 +0100 229) else if (err)
fcc570207c1e7 (Thomas Graf 2015-04-30 22:37:43 +0000 230) return err;
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 231) }
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 232)
9e9089e5a2d78 (Phil Sutter 2015-11-20 18:17:18 +0100 233) if (insert_retries)
9e9089e5a2d78 (Phil Sutter 2015-11-20 18:17:18 +0100 234) pr_info(" %u insertions retried due to memory pressure\n",
9e9089e5a2d78 (Phil Sutter 2015-11-20 18:17:18 +0100 235) insert_retries);
67b7cbf4203f7 (Thomas Graf 2015-04-30 22:37:45 +0000 236)
f651616e799ff (Florian Westphal 2017-09-20 01:12:12 +0200 237) test_bucket_stats(ht, entries);
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 238) rcu_read_lock();
f651616e799ff (Florian Westphal 2017-09-20 01:12:12 +0200 239) test_rht_lookup(ht, array, entries);
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 240) rcu_read_unlock();
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 241)
f651616e799ff (Florian Westphal 2017-09-20 01:12:12 +0200 242) test_bucket_stats(ht, entries);
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 243)
1aa661f5c3df1 (Thomas Graf 2015-04-30 22:37:41 +0000 244) pr_info(" Deleting %d keys\n", entries);
1aa661f5c3df1 (Thomas Graf 2015-04-30 22:37:41 +0000 245) for (i = 0; i < entries; i++) {
783692558a60c (Phil Sutter 2017-07-25 13:36:21 +0200 246) struct test_obj_val key = {
783692558a60c (Phil Sutter 2017-07-25 13:36:21 +0200 247) .id = i * 2,
783692558a60c (Phil Sutter 2017-07-25 13:36:21 +0200 248) };
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 249)
e859afe1ee0c5 (Phil Sutter 2017-07-21 16:51:31 +0200 250) if (array[i].value.id != TEST_INSERT_FAIL) {
67b7cbf4203f7 (Thomas Graf 2015-04-30 22:37:45 +0000 251) obj = rhashtable_lookup_fast(ht, &key, test_rht_params);
67b7cbf4203f7 (Thomas Graf 2015-04-30 22:37:45 +0000 252) BUG_ON(!obj);
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 253)
67b7cbf4203f7 (Thomas Graf 2015-04-30 22:37:45 +0000 254) rhashtable_remove_fast(ht, &obj->node, test_rht_params);
67b7cbf4203f7 (Thomas Graf 2015-04-30 22:37:45 +0000 255) }
685a015e44dcd (Thomas Graf 2015-07-17 10:52:48 +0200 256)
685a015e44dcd (Thomas Graf 2015-07-17 10:52:48 +0200 257) cond_resched();
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 258) }
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 259)
1aa661f5c3df1 (Thomas Graf 2015-04-30 22:37:41 +0000 260) end = ktime_get_ns();
1aa661f5c3df1 (Thomas Graf 2015-04-30 22:37:41 +0000 261) pr_info(" Duration of test: %lld ns\n", end - start);
1aa661f5c3df1 (Thomas Graf 2015-04-30 22:37:41 +0000 262)
1aa661f5c3df1 (Thomas Graf 2015-04-30 22:37:41 +0000 263) return end - start;
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 264) }
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 265)
b7f5e5c7f8ced (Daniel Borkmann 2015-02-20 21:14:21 +0100 266) static struct rhashtable ht;
411d788a23f7e (Florian Westphal 2017-09-21 17:36:08 +0200 267) static struct rhltable rhlt;
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 268)
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 269) static int __init test_rhltable(unsigned int entries)
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 270) {
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 271) struct test_obj_rhl *rhl_test_objects;
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 272) unsigned long *obj_in_table;
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 273) unsigned int i, j, k;
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 274) int ret, err;
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 275)
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 276) if (entries == 0)
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 277) entries = 1;
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 278)
fad953ce0b22c (Kees Cook 2018-06-12 14:27:37 -0700 279) rhl_test_objects = vzalloc(array_size(entries,
fad953ce0b22c (Kees Cook 2018-06-12 14:27:37 -0700 280) sizeof(*rhl_test_objects)));
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 281) if (!rhl_test_objects)
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 282) return -ENOMEM;
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 283)
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 284) ret = -ENOMEM;
fad953ce0b22c (Kees Cook 2018-06-12 14:27:37 -0700 285) obj_in_table = vzalloc(array_size(sizeof(unsigned long),
fad953ce0b22c (Kees Cook 2018-06-12 14:27:37 -0700 286) BITS_TO_LONGS(entries)));
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 287) if (!obj_in_table)
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 288) goto out_free;
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 289)
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 290) err = rhltable_init(&rhlt, &test_rht_params);
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 291) if (WARN_ON(err))
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 292) goto out_free;
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 293)
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 294) k = prandom_u32();
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 295) ret = 0;
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 296) for (i = 0; i < entries; i++) {
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 297) rhl_test_objects[i].value.id = k;
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 298) err = rhltable_insert(&rhlt, &rhl_test_objects[i].list_node,
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 299) test_rht_params);
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 300) if (WARN(err, "error %d on element %d\n", err, i))
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 301) break;
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 302) if (err == 0)
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 303) set_bit(i, obj_in_table);
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 304) }
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 305)
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 306) if (err)
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 307) ret = err;
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 308)
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 309) pr_info("test %d add/delete pairs into rhlist\n", entries);
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 310) for (i = 0; i < entries; i++) {
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 311) struct rhlist_head *h, *pos;
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 312) struct test_obj_rhl *obj;
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 313) struct test_obj_val key = {
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 314) .id = k,
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 315) };
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 316) bool found;
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 317)
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 318) rcu_read_lock();
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 319) h = rhltable_lookup(&rhlt, &key, test_rht_params);
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 320) if (WARN(!h, "key not found during iteration %d of %d", i, entries)) {
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 321) rcu_read_unlock();
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 322) break;
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 323) }
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 324)
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 325) if (i) {
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 326) j = i - 1;
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 327) rhl_for_each_entry_rcu(obj, pos, h, list_node) {
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 328) if (WARN(pos == &rhl_test_objects[j].list_node, "old element found, should be gone"))
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 329) break;
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 330) }
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 331) }
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 332)
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 333) cond_resched_rcu();
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 334)
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 335) found = false;
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 336)
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 337) rhl_for_each_entry_rcu(obj, pos, h, list_node) {
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 338) if (pos == &rhl_test_objects[i].list_node) {
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 339) found = true;
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 340) break;
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 341) }
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 342) }
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 343)
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 344) rcu_read_unlock();
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 345)
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 346) if (WARN(!found, "element %d not found", i))
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 347) break;
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 348)
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 349) err = rhltable_remove(&rhlt, &rhl_test_objects[i].list_node, test_rht_params);
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 350) WARN(err, "rhltable_remove: err %d for iteration %d\n", err, i);
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 351) if (err == 0)
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 352) clear_bit(i, obj_in_table);
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 353) }
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 354)
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 355) if (ret == 0 && err)
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 356) ret = err;
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 357)
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 358) for (i = 0; i < entries; i++) {
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 359) WARN(test_bit(i, obj_in_table), "elem %d allegedly still present", i);
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 360)
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 361) err = rhltable_insert(&rhlt, &rhl_test_objects[i].list_node,
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 362) test_rht_params);
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 363) if (WARN(err, "error %d on element %d\n", err, i))
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 364) break;
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 365) if (err == 0)
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 366) set_bit(i, obj_in_table);
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 367) }
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 368)
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 369) pr_info("test %d random rhlist add/delete operations\n", entries);
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 370) for (j = 0; j < entries; j++) {
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 371) u32 i = prandom_u32_max(entries);
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 372) u32 prand = prandom_u32();
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 373)
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 374) cond_resched();
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 375)
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 376) if (prand == 0)
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 377) prand = prandom_u32();
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 378)
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 379) if (prand & 1) {
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 380) prand >>= 1;
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 381) continue;
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 382) }
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 383)
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 384) err = rhltable_remove(&rhlt, &rhl_test_objects[i].list_node, test_rht_params);
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 385) if (test_bit(i, obj_in_table)) {
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 386) clear_bit(i, obj_in_table);
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 387) if (WARN(err, "cannot remove element at slot %d", i))
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 388) continue;
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 389) } else {
56b90fa02214e (Colin Ian King 2019-02-17 22:52:09 +0000 390) if (WARN(err != -ENOENT, "removed non-existent element %d, error %d not %d",
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 391) i, err, -ENOENT))
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 392) continue;
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 393) }
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 394)
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 395) if (prand & 1) {
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 396) prand >>= 1;
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 397) continue;
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 398) }
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 399)
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 400) err = rhltable_insert(&rhlt, &rhl_test_objects[i].list_node, test_rht_params);
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 401) if (err == 0) {
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 402) if (WARN(test_and_set_bit(i, obj_in_table), "succeeded to insert same object %d", i))
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 403) continue;
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 404) } else {
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 405) if (WARN(!test_bit(i, obj_in_table), "failed to insert object %d", i))
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 406) continue;
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 407) }
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 408)
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 409) if (prand & 1) {
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 410) prand >>= 1;
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 411) continue;
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 412) }
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 413)
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 414) i = prandom_u32_max(entries);
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 415) if (test_bit(i, obj_in_table)) {
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 416) err = rhltable_remove(&rhlt, &rhl_test_objects[i].list_node, test_rht_params);
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 417) WARN(err, "cannot remove element at slot %d", i);
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 418) if (err == 0)
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 419) clear_bit(i, obj_in_table);
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 420) } else {
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 421) err = rhltable_insert(&rhlt, &rhl_test_objects[i].list_node, test_rht_params);
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 422) WARN(err, "failed to insert object %d", i);
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 423) if (err == 0)
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 424) set_bit(i, obj_in_table);
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 425) }
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 426) }
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 427)
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 428) for (i = 0; i < entries; i++) {
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 429) cond_resched();
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 430) err = rhltable_remove(&rhlt, &rhl_test_objects[i].list_node, test_rht_params);
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 431) if (test_bit(i, obj_in_table)) {
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 432) if (WARN(err, "cannot remove element at slot %d", i))
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 433) continue;
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 434) } else {
56b90fa02214e (Colin Ian King 2019-02-17 22:52:09 +0000 435) if (WARN(err != -ENOENT, "removed non-existent element, error %d not %d",
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 436) err, -ENOENT))
769f5083c5e2d (Colin Ian King 2020-09-18 22:51:26 +0100 437) continue;
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 438) }
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 439) }
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 440)
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 441) rhltable_destroy(&rhlt);
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 442) out_free:
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 443) vfree(rhl_test_objects);
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 444) vfree(obj_in_table);
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 445) return ret;
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 446) }
b7f5e5c7f8ced (Daniel Borkmann 2015-02-20 21:14:21 +0100 447)
a6359bd8dd1c3 (Florian Westphal 2017-09-20 01:12:13 +0200 448) static int __init test_rhashtable_max(struct test_obj *array,
a6359bd8dd1c3 (Florian Westphal 2017-09-20 01:12:13 +0200 449) unsigned int entries)
a6359bd8dd1c3 (Florian Westphal 2017-09-20 01:12:13 +0200 450) {
a6359bd8dd1c3 (Florian Westphal 2017-09-20 01:12:13 +0200 451) unsigned int i, insert_retries = 0;
a6359bd8dd1c3 (Florian Westphal 2017-09-20 01:12:13 +0200 452) int err;
a6359bd8dd1c3 (Florian Westphal 2017-09-20 01:12:13 +0200 453)
a6359bd8dd1c3 (Florian Westphal 2017-09-20 01:12:13 +0200 454) test_rht_params.max_size = roundup_pow_of_two(entries / 8);
a6359bd8dd1c3 (Florian Westphal 2017-09-20 01:12:13 +0200 455) err = rhashtable_init(&ht, &test_rht_params);
a6359bd8dd1c3 (Florian Westphal 2017-09-20 01:12:13 +0200 456) if (err)
a6359bd8dd1c3 (Florian Westphal 2017-09-20 01:12:13 +0200 457) return err;
a6359bd8dd1c3 (Florian Westphal 2017-09-20 01:12:13 +0200 458)
a6359bd8dd1c3 (Florian Westphal 2017-09-20 01:12:13 +0200 459) for (i = 0; i < ht.max_elems; i++) {
a6359bd8dd1c3 (Florian Westphal 2017-09-20 01:12:13 +0200 460) struct test_obj *obj = &array[i];
a6359bd8dd1c3 (Florian Westphal 2017-09-20 01:12:13 +0200 461)
a6359bd8dd1c3 (Florian Westphal 2017-09-20 01:12:13 +0200 462) obj->value.id = i * 2;
a6359bd8dd1c3 (Florian Westphal 2017-09-20 01:12:13 +0200 463) err = insert_retry(&ht, obj, test_rht_params);
a6359bd8dd1c3 (Florian Westphal 2017-09-20 01:12:13 +0200 464) if (err > 0)
a6359bd8dd1c3 (Florian Westphal 2017-09-20 01:12:13 +0200 465) insert_retries += err;
a6359bd8dd1c3 (Florian Westphal 2017-09-20 01:12:13 +0200 466) else if (err)
a6359bd8dd1c3 (Florian Westphal 2017-09-20 01:12:13 +0200 467) return err;
a6359bd8dd1c3 (Florian Westphal 2017-09-20 01:12:13 +0200 468) }
a6359bd8dd1c3 (Florian Westphal 2017-09-20 01:12:13 +0200 469)
a6359bd8dd1c3 (Florian Westphal 2017-09-20 01:12:13 +0200 470) err = insert_retry(&ht, &array[ht.max_elems], test_rht_params);
a6359bd8dd1c3 (Florian Westphal 2017-09-20 01:12:13 +0200 471) if (err == -E2BIG) {
a6359bd8dd1c3 (Florian Westphal 2017-09-20 01:12:13 +0200 472) err = 0;
a6359bd8dd1c3 (Florian Westphal 2017-09-20 01:12:13 +0200 473) } else {
a6359bd8dd1c3 (Florian Westphal 2017-09-20 01:12:13 +0200 474) pr_info("insert element %u should have failed with %d, got %d\n",
a6359bd8dd1c3 (Florian Westphal 2017-09-20 01:12:13 +0200 475) ht.max_elems, -E2BIG, err);
a6359bd8dd1c3 (Florian Westphal 2017-09-20 01:12:13 +0200 476) if (err == 0)
a6359bd8dd1c3 (Florian Westphal 2017-09-20 01:12:13 +0200 477) err = -1;
a6359bd8dd1c3 (Florian Westphal 2017-09-20 01:12:13 +0200 478) }
a6359bd8dd1c3 (Florian Westphal 2017-09-20 01:12:13 +0200 479)
a6359bd8dd1c3 (Florian Westphal 2017-09-20 01:12:13 +0200 480) rhashtable_destroy(&ht);
a6359bd8dd1c3 (Florian Westphal 2017-09-20 01:12:13 +0200 481)
a6359bd8dd1c3 (Florian Westphal 2017-09-20 01:12:13 +0200 482) return err;
a6359bd8dd1c3 (Florian Westphal 2017-09-20 01:12:13 +0200 483) }
a6359bd8dd1c3 (Florian Westphal 2017-09-20 01:12:13 +0200 484)
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 485) static unsigned int __init print_ht(struct rhltable *rhlt)
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 486) {
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 487) struct rhashtable *ht;
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 488) const struct bucket_table *tbl;
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 489) char buff[512] = "";
4adec7f81df8e (Arnd Bergmann 2021-03-23 14:03:32 +0100 490) int offset = 0;
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 491) unsigned int i, cnt = 0;
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 492)
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 493) ht = &rhlt->ht;
cbab901296232 (NeilBrown 2018-06-18 12:52:50 +1000 494) /* Take the mutex to avoid RCU warning */
cbab901296232 (NeilBrown 2018-06-18 12:52:50 +1000 495) mutex_lock(&ht->mutex);
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 496) tbl = rht_dereference(ht->tbl, ht);
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 497) for (i = 0; i < tbl->size; i++) {
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 498) struct rhash_head *pos, *next;
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 499) struct test_obj_rhl *p;
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 500)
adc6a3ab192eb (NeilBrown 2019-04-12 11:52:08 +1000 501) pos = rht_ptr_exclusive(tbl->buckets + i);
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 502) next = !rht_is_a_nulls(pos) ? rht_dereference(pos->next, ht) : NULL;
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 503)
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 504) if (!rht_is_a_nulls(pos)) {
4adec7f81df8e (Arnd Bergmann 2021-03-23 14:03:32 +0100 505) offset += sprintf(buff + offset, "\nbucket[%d] -> ", i);
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 506) }
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 507)
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 508) while (!rht_is_a_nulls(pos)) {
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 509) struct rhlist_head *list = container_of(pos, struct rhlist_head, rhead);
4adec7f81df8e (Arnd Bergmann 2021-03-23 14:03:32 +0100 510) offset += sprintf(buff + offset, "[[");
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 511) do {
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 512) pos = &list->rhead;
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 513) list = rht_dereference(list->next, ht);
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 514) p = rht_obj(ht, pos);
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 515)
4adec7f81df8e (Arnd Bergmann 2021-03-23 14:03:32 +0100 516) offset += sprintf(buff + offset, " val %d (tid=%d)%s", p->value.id, p->value.tid,
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 517) list? ", " : " ");
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 518) cnt++;
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 519) } while (list);
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 520)
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 521) pos = next,
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 522) next = !rht_is_a_nulls(pos) ?
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 523) rht_dereference(pos->next, ht) : NULL;
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 524)
4adec7f81df8e (Arnd Bergmann 2021-03-23 14:03:32 +0100 525) offset += sprintf(buff + offset, "]]%s", !rht_is_a_nulls(pos) ? " -> " : "");
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 526) }
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 527) }
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 528) printk(KERN_ERR "\n---- ht: ----%s\n-------------\n", buff);
cbab901296232 (NeilBrown 2018-06-18 12:52:50 +1000 529) mutex_unlock(&ht->mutex);
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 530)
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 531) return cnt;
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 532) }
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 533)
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 534) static int __init test_insert_dup(struct test_obj_rhl *rhl_test_objects,
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 535) int cnt, bool slow)
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 536) {
fc42a689c4c09 (Bart Van Assche 2019-01-30 10:42:30 -0800 537) struct rhltable *rhlt;
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 538) unsigned int i, ret;
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 539) const char *key;
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 540) int err = 0;
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 541)
fc42a689c4c09 (Bart Van Assche 2019-01-30 10:42:30 -0800 542) rhlt = kmalloc(sizeof(*rhlt), GFP_KERNEL);
fc42a689c4c09 (Bart Van Assche 2019-01-30 10:42:30 -0800 543) if (WARN_ON(!rhlt))
fc42a689c4c09 (Bart Van Assche 2019-01-30 10:42:30 -0800 544) return -EINVAL;
fc42a689c4c09 (Bart Van Assche 2019-01-30 10:42:30 -0800 545)
fc42a689c4c09 (Bart Van Assche 2019-01-30 10:42:30 -0800 546) err = rhltable_init(rhlt, &test_rht_params_dup);
fc42a689c4c09 (Bart Van Assche 2019-01-30 10:42:30 -0800 547) if (WARN_ON(err)) {
fc42a689c4c09 (Bart Van Assche 2019-01-30 10:42:30 -0800 548) kfree(rhlt);
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 549) return err;
fc42a689c4c09 (Bart Van Assche 2019-01-30 10:42:30 -0800 550) }
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 551)
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 552) for (i = 0; i < cnt; i++) {
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 553) rhl_test_objects[i].value.tid = i;
fc42a689c4c09 (Bart Van Assche 2019-01-30 10:42:30 -0800 554) key = rht_obj(&rhlt->ht, &rhl_test_objects[i].list_node.rhead);
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 555) key += test_rht_params_dup.key_offset;
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 556)
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 557) if (slow) {
fc42a689c4c09 (Bart Van Assche 2019-01-30 10:42:30 -0800 558) err = PTR_ERR(rhashtable_insert_slow(&rhlt->ht, key,
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 559) &rhl_test_objects[i].list_node.rhead));
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 560) if (err == -EAGAIN)
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 561) err = 0;
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 562) } else
fc42a689c4c09 (Bart Van Assche 2019-01-30 10:42:30 -0800 563) err = rhltable_insert(rhlt,
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 564) &rhl_test_objects[i].list_node,
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 565) test_rht_params_dup);
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 566) if (WARN(err, "error %d on element %d/%d (%s)\n", err, i, cnt, slow? "slow" : "fast"))
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 567) goto skip_print;
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 568) }
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 569)
fc42a689c4c09 (Bart Van Assche 2019-01-30 10:42:30 -0800 570) ret = print_ht(rhlt);
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 571) WARN(ret != cnt, "missing rhltable elements (%d != %d, %s)\n", ret, cnt, slow? "slow" : "fast");
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 572)
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 573) skip_print:
fc42a689c4c09 (Bart Van Assche 2019-01-30 10:42:30 -0800 574) rhltable_destroy(rhlt);
fc42a689c4c09 (Bart Van Assche 2019-01-30 10:42:30 -0800 575) kfree(rhlt);
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 576)
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 577) return 0;
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 578) }
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 579)
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 580) static int __init test_insert_duplicates_run(void)
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 581) {
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 582) struct test_obj_rhl rhl_test_objects[3] = {};
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 583)
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 584) pr_info("test inserting duplicates\n");
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 585)
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 586) /* two different values that map to same bucket */
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 587) rhl_test_objects[0].value.id = 1;
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 588) rhl_test_objects[1].value.id = 21;
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 589)
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 590) /* and another duplicate with same as [0] value
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 591) * which will be second on the bucket list */
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 592) rhl_test_objects[2].value.id = rhl_test_objects[0].value.id;
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 593)
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 594) test_insert_dup(rhl_test_objects, 2, false);
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 595) test_insert_dup(rhl_test_objects, 3, false);
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 596) test_insert_dup(rhl_test_objects, 2, true);
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 597) test_insert_dup(rhl_test_objects, 3, true);
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 598)
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 599) return 0;
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 600) }
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 601)
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 602) static int thread_lookup_test(struct thread_data *tdata)
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 603) {
f651616e799ff (Florian Westphal 2017-09-20 01:12:12 +0200 604) unsigned int entries = tdata->entries;
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 605) int i, err = 0;
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 606)
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 607) for (i = 0; i < entries; i++) {
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 608) struct test_obj *obj;
e859afe1ee0c5 (Phil Sutter 2017-07-21 16:51:31 +0200 609) struct test_obj_val key = {
e859afe1ee0c5 (Phil Sutter 2017-07-21 16:51:31 +0200 610) .id = i,
e859afe1ee0c5 (Phil Sutter 2017-07-21 16:51:31 +0200 611) .tid = tdata->id,
e859afe1ee0c5 (Phil Sutter 2017-07-21 16:51:31 +0200 612) };
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 613)
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 614) obj = rhashtable_lookup_fast(&ht, &key, test_rht_params);
e859afe1ee0c5 (Phil Sutter 2017-07-21 16:51:31 +0200 615) if (obj && (tdata->objs[i].value.id == TEST_INSERT_FAIL)) {
e859afe1ee0c5 (Phil Sutter 2017-07-21 16:51:31 +0200 616) pr_err(" found unexpected object %d-%d\n", key.tid, key.id);
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 617) err++;
e859afe1ee0c5 (Phil Sutter 2017-07-21 16:51:31 +0200 618) } else if (!obj && (tdata->objs[i].value.id != TEST_INSERT_FAIL)) {
e859afe1ee0c5 (Phil Sutter 2017-07-21 16:51:31 +0200 619) pr_err(" object %d-%d not found!\n", key.tid, key.id);
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 620) err++;
e859afe1ee0c5 (Phil Sutter 2017-07-21 16:51:31 +0200 621) } else if (obj && memcmp(&obj->value, &key, sizeof(key))) {
e859afe1ee0c5 (Phil Sutter 2017-07-21 16:51:31 +0200 622) pr_err(" wrong object returned (got %d-%d, expected %d-%d)\n",
e859afe1ee0c5 (Phil Sutter 2017-07-21 16:51:31 +0200 623) obj->value.tid, obj->value.id, key.tid, key.id);
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 624) err++;
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 625) }
cd5b318daf4ae (Phil Sutter 2015-11-20 18:17:17 +0100 626)
cd5b318daf4ae (Phil Sutter 2015-11-20 18:17:17 +0100 627) cond_resched();
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 628) }
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 629) return err;
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 630) }
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 631)
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 632) static int threadfunc(void *data)
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 633) {
9e9089e5a2d78 (Phil Sutter 2015-11-20 18:17:18 +0100 634) int i, step, err = 0, insert_retries = 0;
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 635) struct thread_data *tdata = data;
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 636)
809c67059162e (Arnd Bergmann 2018-12-16 20:48:21 +0100 637) if (atomic_dec_and_test(&startup_count))
809c67059162e (Arnd Bergmann 2018-12-16 20:48:21 +0100 638) wake_up(&startup_wait);
809c67059162e (Arnd Bergmann 2018-12-16 20:48:21 +0100 639) if (wait_event_interruptible(startup_wait, atomic_read(&startup_count) == -1)) {
809c67059162e (Arnd Bergmann 2018-12-16 20:48:21 +0100 640) pr_err(" thread[%d]: interrupted\n", tdata->id);
809c67059162e (Arnd Bergmann 2018-12-16 20:48:21 +0100 641) goto out;
809c67059162e (Arnd Bergmann 2018-12-16 20:48:21 +0100 642) }
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 643)
f651616e799ff (Florian Westphal 2017-09-20 01:12:12 +0200 644) for (i = 0; i < tdata->entries; i++) {
e859afe1ee0c5 (Phil Sutter 2017-07-21 16:51:31 +0200 645) tdata->objs[i].value.id = i;
e859afe1ee0c5 (Phil Sutter 2017-07-21 16:51:31 +0200 646) tdata->objs[i].value.tid = tdata->id;
7e936bd73483e (Florian Westphal 2017-09-20 01:12:11 +0200 647) err = insert_retry(&ht, &tdata->objs[i], test_rht_params);
9e9089e5a2d78 (Phil Sutter 2015-11-20 18:17:18 +0100 648) if (err > 0) {
9e9089e5a2d78 (Phil Sutter 2015-11-20 18:17:18 +0100 649) insert_retries += err;
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 650) } else if (err) {
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 651) pr_err(" thread[%d]: rhashtable_insert_fast failed\n",
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 652) tdata->id);
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 653) goto out;
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 654) }
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 655) }
9e9089e5a2d78 (Phil Sutter 2015-11-20 18:17:18 +0100 656) if (insert_retries)
9e9089e5a2d78 (Phil Sutter 2015-11-20 18:17:18 +0100 657) pr_info(" thread[%d]: %u insertions retried due to memory pressure\n",
9e9089e5a2d78 (Phil Sutter 2015-11-20 18:17:18 +0100 658) tdata->id, insert_retries);
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 659)
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 660) err = thread_lookup_test(tdata);
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 661) if (err) {
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 662) pr_err(" thread[%d]: rhashtable_lookup_test failed\n",
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 663) tdata->id);
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 664) goto out;
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 665) }
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 666)
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 667) for (step = 10; step > 0; step--) {
f651616e799ff (Florian Westphal 2017-09-20 01:12:12 +0200 668) for (i = 0; i < tdata->entries; i += step) {
e859afe1ee0c5 (Phil Sutter 2017-07-21 16:51:31 +0200 669) if (tdata->objs[i].value.id == TEST_INSERT_FAIL)
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 670) continue;
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 671) err = rhashtable_remove_fast(&ht, &tdata->objs[i].node,
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 672) test_rht_params);
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 673) if (err) {
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 674) pr_err(" thread[%d]: rhashtable_remove_fast failed\n",
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 675) tdata->id);
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 676) goto out;
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 677) }
e859afe1ee0c5 (Phil Sutter 2017-07-21 16:51:31 +0200 678) tdata->objs[i].value.id = TEST_INSERT_FAIL;
cd5b318daf4ae (Phil Sutter 2015-11-20 18:17:17 +0100 679)
cd5b318daf4ae (Phil Sutter 2015-11-20 18:17:17 +0100 680) cond_resched();
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 681) }
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 682) err = thread_lookup_test(tdata);
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 683) if (err) {
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 684) pr_err(" thread[%d]: rhashtable_lookup_test (2) failed\n",
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 685) tdata->id);
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 686) goto out;
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 687) }
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 688) }
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 689) out:
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 690) while (!kthread_should_stop()) {
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 691) set_current_state(TASK_INTERRUPTIBLE);
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 692) schedule();
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 693) }
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 694) return err;
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 695) }
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 696)
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 697) static int __init test_rht_init(void)
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 698) {
f651616e799ff (Florian Westphal 2017-09-20 01:12:12 +0200 699) unsigned int entries;
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 700) int i, err, started_threads = 0, failed_threads = 0;
1aa661f5c3df1 (Thomas Graf 2015-04-30 22:37:41 +0000 701) u64 total_time = 0;
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 702) struct thread_data *tdata;
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 703) struct test_obj *objs;
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 704)
f651616e799ff (Florian Westphal 2017-09-20 01:12:12 +0200 705) if (parm_entries < 0)
f651616e799ff (Florian Westphal 2017-09-20 01:12:12 +0200 706) parm_entries = 1;
f651616e799ff (Florian Westphal 2017-09-20 01:12:12 +0200 707)
f651616e799ff (Florian Westphal 2017-09-20 01:12:12 +0200 708) entries = min(parm_entries, MAX_ENTRIES);
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 709)
1aa661f5c3df1 (Thomas Graf 2015-04-30 22:37:41 +0000 710) test_rht_params.automatic_shrinking = shrinking;
95e435afefe98 (Phil Sutter 2015-11-20 18:17:19 +0100 711) test_rht_params.max_size = max_size ? : roundup_pow_of_two(entries);
1aa661f5c3df1 (Thomas Graf 2015-04-30 22:37:41 +0000 712) test_rht_params.nelem_hint = size;
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 713)
fad953ce0b22c (Kees Cook 2018-06-12 14:27:37 -0700 714) objs = vzalloc(array_size(sizeof(struct test_obj),
fad953ce0b22c (Kees Cook 2018-06-12 14:27:37 -0700 715) test_rht_params.max_size + 1));
7e936bd73483e (Florian Westphal 2017-09-20 01:12:11 +0200 716) if (!objs)
7e936bd73483e (Florian Westphal 2017-09-20 01:12:11 +0200 717) return -ENOMEM;
7e936bd73483e (Florian Westphal 2017-09-20 01:12:11 +0200 718)
1aa661f5c3df1 (Thomas Graf 2015-04-30 22:37:41 +0000 719) pr_info("Running rhashtable test nelem=%d, max_size=%d, shrinking=%d\n",
1aa661f5c3df1 (Thomas Graf 2015-04-30 22:37:41 +0000 720) size, max_size, shrinking);
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 721)
1aa661f5c3df1 (Thomas Graf 2015-04-30 22:37:41 +0000 722) for (i = 0; i < runs; i++) {
1aa661f5c3df1 (Thomas Graf 2015-04-30 22:37:41 +0000 723) s64 time;
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 724)
1aa661f5c3df1 (Thomas Graf 2015-04-30 22:37:41 +0000 725) pr_info("Test %02d:\n", i);
7e936bd73483e (Florian Westphal 2017-09-20 01:12:11 +0200 726) memset(objs, 0, test_rht_params.max_size * sizeof(struct test_obj));
7e936bd73483e (Florian Westphal 2017-09-20 01:12:11 +0200 727)
1aa661f5c3df1 (Thomas Graf 2015-04-30 22:37:41 +0000 728) err = rhashtable_init(&ht, &test_rht_params);
1aa661f5c3df1 (Thomas Graf 2015-04-30 22:37:41 +0000 729) if (err < 0) {
1aa661f5c3df1 (Thomas Graf 2015-04-30 22:37:41 +0000 730) pr_warn("Test failed: Unable to initialize hashtable: %d\n",
1aa661f5c3df1 (Thomas Graf 2015-04-30 22:37:41 +0000 731) err);
1aa661f5c3df1 (Thomas Graf 2015-04-30 22:37:41 +0000 732) continue;
1aa661f5c3df1 (Thomas Graf 2015-04-30 22:37:41 +0000 733) }
1aa661f5c3df1 (Thomas Graf 2015-04-30 22:37:41 +0000 734)
f651616e799ff (Florian Westphal 2017-09-20 01:12:12 +0200 735) time = test_rhashtable(&ht, objs, entries);
1aa661f5c3df1 (Thomas Graf 2015-04-30 22:37:41 +0000 736) rhashtable_destroy(&ht);
1aa661f5c3df1 (Thomas Graf 2015-04-30 22:37:41 +0000 737) if (time < 0) {
7e936bd73483e (Florian Westphal 2017-09-20 01:12:11 +0200 738) vfree(objs);
1aa661f5c3df1 (Thomas Graf 2015-04-30 22:37:41 +0000 739) pr_warn("Test failed: return code %lld\n", time);
1aa661f5c3df1 (Thomas Graf 2015-04-30 22:37:41 +0000 740) return -EINVAL;
1aa661f5c3df1 (Thomas Graf 2015-04-30 22:37:41 +0000 741) }
1aa661f5c3df1 (Thomas Graf 2015-04-30 22:37:41 +0000 742)
1aa661f5c3df1 (Thomas Graf 2015-04-30 22:37:41 +0000 743) total_time += time;
1aa661f5c3df1 (Thomas Graf 2015-04-30 22:37:41 +0000 744) }
1aa661f5c3df1 (Thomas Graf 2015-04-30 22:37:41 +0000 745)
a6359bd8dd1c3 (Florian Westphal 2017-09-20 01:12:13 +0200 746) pr_info("test if its possible to exceed max_size %d: %s\n",
a6359bd8dd1c3 (Florian Westphal 2017-09-20 01:12:13 +0200 747) test_rht_params.max_size, test_rhashtable_max(objs, entries) == 0 ?
a6359bd8dd1c3 (Florian Westphal 2017-09-20 01:12:13 +0200 748) "no, ok" : "YES, failed");
7e936bd73483e (Florian Westphal 2017-09-20 01:12:11 +0200 749) vfree(objs);
a6359bd8dd1c3 (Florian Westphal 2017-09-20 01:12:13 +0200 750)
6decd63acacb3 (Thomas Graf 2015-05-05 02:27:02 +0200 751) do_div(total_time, runs);
6decd63acacb3 (Thomas Graf 2015-05-05 02:27:02 +0200 752) pr_info("Average test time: %llu\n", total_time);
1aa661f5c3df1 (Thomas Graf 2015-04-30 22:37:41 +0000 753)
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 754) test_insert_duplicates_run();
499ac3b60f657 (Paul Blakey 2018-03-04 17:29:49 +0200 755)
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 756) if (!tcount)
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 757) return 0;
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 758)
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 759) pr_info("Testing concurrent rhashtable access from %d threads\n",
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 760) tcount);
809c67059162e (Arnd Bergmann 2018-12-16 20:48:21 +0100 761) atomic_set(&startup_count, tcount);
fad953ce0b22c (Kees Cook 2018-06-12 14:27:37 -0700 762) tdata = vzalloc(array_size(tcount, sizeof(struct thread_data)));
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 763) if (!tdata)
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 764) return -ENOMEM;
fad953ce0b22c (Kees Cook 2018-06-12 14:27:37 -0700 765) objs = vzalloc(array3_size(sizeof(struct test_obj), tcount, entries));
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 766) if (!objs) {
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 767) vfree(tdata);
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 768) return -ENOMEM;
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 769) }
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 770)
95e435afefe98 (Phil Sutter 2015-11-20 18:17:19 +0100 771) test_rht_params.max_size = max_size ? :
95e435afefe98 (Phil Sutter 2015-11-20 18:17:19 +0100 772) roundup_pow_of_two(tcount * entries);
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 773) err = rhashtable_init(&ht, &test_rht_params);
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 774) if (err < 0) {
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 775) pr_warn("Test failed: Unable to initialize hashtable: %d\n",
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 776) err);
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 777) vfree(tdata);
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 778) vfree(objs);
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 779) return -EINVAL;
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 780) }
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 781) for (i = 0; i < tcount; i++) {
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 782) tdata[i].id = i;
f651616e799ff (Florian Westphal 2017-09-20 01:12:12 +0200 783) tdata[i].entries = entries;
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 784) tdata[i].objs = objs + i * entries;
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 785) tdata[i].task = kthread_run(threadfunc, &tdata[i],
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 786) "rhashtable_thrad[%d]", i);
809c67059162e (Arnd Bergmann 2018-12-16 20:48:21 +0100 787) if (IS_ERR(tdata[i].task)) {
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 788) pr_err(" kthread_run failed for thread %d\n", i);
809c67059162e (Arnd Bergmann 2018-12-16 20:48:21 +0100 789) atomic_dec(&startup_count);
809c67059162e (Arnd Bergmann 2018-12-16 20:48:21 +0100 790) } else {
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 791) started_threads++;
809c67059162e (Arnd Bergmann 2018-12-16 20:48:21 +0100 792) }
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 793) }
809c67059162e (Arnd Bergmann 2018-12-16 20:48:21 +0100 794) if (wait_event_interruptible(startup_wait, atomic_read(&startup_count) == 0))
809c67059162e (Arnd Bergmann 2018-12-16 20:48:21 +0100 795) pr_err(" wait_event interruptible failed\n");
809c67059162e (Arnd Bergmann 2018-12-16 20:48:21 +0100 796) /* count is 0 now, set it to -1 and wake up all threads together */
809c67059162e (Arnd Bergmann 2018-12-16 20:48:21 +0100 797) atomic_dec(&startup_count);
809c67059162e (Arnd Bergmann 2018-12-16 20:48:21 +0100 798) wake_up_all(&startup_wait);
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 799) for (i = 0; i < tcount; i++) {
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 800) if (IS_ERR(tdata[i].task))
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 801) continue;
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 802) if ((err = kthread_stop(tdata[i].task))) {
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 803) pr_warn("Test failed: thread %d returned: %d\n",
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 804) i, err);
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 805) failed_threads++;
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 806) }
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 807) }
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 808) rhashtable_destroy(&ht);
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 809) vfree(tdata);
f4a3e90ba5739 (Phil Sutter 2015-08-15 00:37:15 +0200 810) vfree(objs);
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 811)
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 812) /*
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 813) * rhltable_remove is very expensive, default values can cause test
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 814) * to run for 2 minutes or more, use a smaller number instead.
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 815) */
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 816) err = test_rhltable(entries / 16);
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 817) pr_info("Started %d threads, %d failed, rhltable test returns %d\n",
cdd4de372ea06 (Florian Westphal 2017-09-20 01:12:14 +0200 818) started_threads, failed_threads, err);
1aa661f5c3df1 (Thomas Graf 2015-04-30 22:37:41 +0000 819) return 0;
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 820) }
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 821)
6dd0c1655be26 (Daniel Borkmann 2015-02-20 00:53:39 +0100 822) static void __exit test_rht_exit(void)
6dd0c1655be26 (Daniel Borkmann 2015-02-20 00:53:39 +0100 823) {
6dd0c1655be26 (Daniel Borkmann 2015-02-20 00:53:39 +0100 824) }
6dd0c1655be26 (Daniel Borkmann 2015-02-20 00:53:39 +0100 825)
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 826) module_init(test_rht_init);
6dd0c1655be26 (Daniel Borkmann 2015-02-20 00:53:39 +0100 827) module_exit(test_rht_exit);
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 828)
9d6dbe1bbaf8b (Geert Uytterhoeven 2015-01-29 15:40:25 +0100 829) MODULE_LICENSE("GPL v2");