VisionFive2 Linux kernel

StarFive Tech Linux Kernel for VisionFive (JH7110) boards (mirror)

More than 9999 Commits   32 Branches   54 Tags
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");