Blame view

lib/test_rhashtable.c 10.6 KB
9d6dbe1bb   Geert Uytterhoeven   rhashtable: Make ...
1
2
3
  /*
   * Resizable, Scalable, Concurrent Hash Table
   *
1aa661f5c   Thomas Graf   rhashtable-test: ...
4
   * Copyright (c) 2014-2015 Thomas Graf <tgraf@suug.ch>
9d6dbe1bb   Geert Uytterhoeven   rhashtable: Make ...
5
6
   * Copyright (c) 2008-2014 Patrick McHardy <kaber@trash.net>
   *
9d6dbe1bb   Geert Uytterhoeven   rhashtable: Make ...
7
8
9
10
11
12
13
14
15
16
17
18
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License version 2 as
   * published by the Free Software Foundation.
   */
  
  /**************************************************************************
   * Self Test
   **************************************************************************/
  
  #include <linux/init.h>
  #include <linux/jhash.h>
  #include <linux/kernel.h>
f4a3e90ba   Phil Sutter   rhashtable-test: ...
19
  #include <linux/kthread.h>
9d6dbe1bb   Geert Uytterhoeven   rhashtable: Make ...
20
21
22
  #include <linux/module.h>
  #include <linux/rcupdate.h>
  #include <linux/rhashtable.h>
f4a3e90ba   Phil Sutter   rhashtable-test: ...
23
  #include <linux/semaphore.h>
9d6dbe1bb   Geert Uytterhoeven   rhashtable: Make ...
24
  #include <linux/slab.h>
685a015e4   Thomas Graf   rhashtable: Allow...
25
  #include <linux/sched.h>
f4a3e90ba   Phil Sutter   rhashtable-test: ...
26
  #include <linux/vmalloc.h>
9d6dbe1bb   Geert Uytterhoeven   rhashtable: Make ...
27

1aa661f5c   Thomas Graf   rhashtable-test: ...
28
  #define MAX_ENTRIES	1000000
67b7cbf42   Thomas Graf   rhashtable-test: ...
29
  #define TEST_INSERT_FAIL INT_MAX
1aa661f5c   Thomas Graf   rhashtable-test: ...
30
31
32
33
34
35
36
37
  
  static int entries = 50000;
  module_param(entries, int, 0);
  MODULE_PARM_DESC(entries, "Number of entries to add (default: 50000)");
  
  static int runs = 4;
  module_param(runs, int, 0);
  MODULE_PARM_DESC(runs, "Number of test runs per variant (default: 4)");
95e435afe   Phil Sutter   rhashtable-test: ...
38
  static int max_size = 0;
1aa661f5c   Thomas Graf   rhashtable-test: ...
39
  module_param(max_size, int, 0);
3b3bf80b9   Phil Sutter   rhashtable-test: ...
40
  MODULE_PARM_DESC(max_size, "Maximum table size (default: calculated)");
1aa661f5c   Thomas Graf   rhashtable-test: ...
41
42
43
44
45
46
47
48
  
  static bool shrinking = false;
  module_param(shrinking, bool, 0);
  MODULE_PARM_DESC(shrinking, "Enable automatic shrinking (default: off)");
  
  static int size = 8;
  module_param(size, int, 0);
  MODULE_PARM_DESC(size, "Initial size hint of table (default: 8)");
9d6dbe1bb   Geert Uytterhoeven   rhashtable: Make ...
49

f4a3e90ba   Phil Sutter   rhashtable-test: ...
50
51
52
  static int tcount = 10;
  module_param(tcount, int, 0);
  MODULE_PARM_DESC(tcount, "Number of threads to spawn (default: 10)");
d662e037f   Phil Sutter   rhashtable-test: ...
53
54
55
  static bool enomem_retry = false;
  module_param(enomem_retry, bool, 0);
  MODULE_PARM_DESC(enomem_retry, "Retry insert even if -ENOMEM was returned (default: off)");
e859afe1e   Phil Sutter   lib: test_rhashta...
56
57
58
59
  struct test_obj_val {
  	int	id;
  	int	tid;
  };
9d6dbe1bb   Geert Uytterhoeven   rhashtable: Make ...
60
  struct test_obj {
e859afe1e   Phil Sutter   lib: test_rhashta...
61
  	struct test_obj_val	value;
9d6dbe1bb   Geert Uytterhoeven   rhashtable: Make ...
62
63
  	struct rhash_head	node;
  };
f4a3e90ba   Phil Sutter   rhashtable-test: ...
64
65
66
67
68
  struct thread_data {
  	int id;
  	struct task_struct *task;
  	struct test_obj *objs;
  };
fcc570207   Thomas Graf   rhashtable-test: ...
69
  static struct test_obj array[MAX_ENTRIES];
1aa661f5c   Thomas Graf   rhashtable-test: ...
70
  static struct rhashtable_params test_rht_params = {
b182aa6e9   Herbert Xu   test_rhashtable: ...
71
72
  	.head_offset = offsetof(struct test_obj, node),
  	.key_offset = offsetof(struct test_obj, value),
e859afe1e   Phil Sutter   lib: test_rhashta...
73
  	.key_len = sizeof(struct test_obj_val),
b182aa6e9   Herbert Xu   test_rhashtable: ...
74
  	.hashfn = jhash,
b182aa6e9   Herbert Xu   test_rhashtable: ...
75
76
  	.nulls_base = (3U << RHT_BASE_SHIFT),
  };
f4a3e90ba   Phil Sutter   rhashtable-test: ...
77
78
  static struct semaphore prestart_sem;
  static struct semaphore startup_sem = __SEMAPHORE_INITIALIZER(startup_sem, 0);
9e9089e5a   Phil Sutter   rhashtable-test: ...
79
80
81
  static int insert_retry(struct rhashtable *ht, struct rhash_head *obj,
                          const struct rhashtable_params params)
  {
d662e037f   Phil Sutter   rhashtable-test: ...
82
  	int err, retries = -1, enomem_retries = 0;
9e9089e5a   Phil Sutter   rhashtable-test: ...
83
84
85
86
87
  
  	do {
  		retries++;
  		cond_resched();
  		err = rhashtable_insert_fast(ht, obj, params);
d662e037f   Phil Sutter   rhashtable-test: ...
88
89
90
91
  		if (err == -ENOMEM && enomem_retry) {
  			enomem_retries++;
  			err = -EBUSY;
  		}
9e9089e5a   Phil Sutter   rhashtable-test: ...
92
  	} while (err == -EBUSY);
d662e037f   Phil Sutter   rhashtable-test: ...
93
94
95
96
  	if (enomem_retries)
  		pr_info(" %u insertions retried after -ENOMEM
  ",
  			enomem_retries);
9e9089e5a   Phil Sutter   rhashtable-test: ...
97
98
  	return err ? : retries;
  }
9d6dbe1bb   Geert Uytterhoeven   rhashtable: Make ...
99
100
101
  static int __init test_rht_lookup(struct rhashtable *ht)
  {
  	unsigned int i;
1aa661f5c   Thomas Graf   rhashtable-test: ...
102
  	for (i = 0; i < entries * 2; i++) {
9d6dbe1bb   Geert Uytterhoeven   rhashtable: Make ...
103
104
  		struct test_obj *obj;
  		bool expected = !(i % 2);
e859afe1e   Phil Sutter   lib: test_rhashta...
105
106
107
  		struct test_obj_val key = {
  			.id = i,
  		};
9d6dbe1bb   Geert Uytterhoeven   rhashtable: Make ...
108

e859afe1e   Phil Sutter   lib: test_rhashta...
109
  		if (array[i / 2].value.id == TEST_INSERT_FAIL)
67b7cbf42   Thomas Graf   rhashtable-test: ...
110
  			expected = false;
b182aa6e9   Herbert Xu   test_rhashtable: ...
111
  		obj = rhashtable_lookup_fast(ht, &key, test_rht_params);
9d6dbe1bb   Geert Uytterhoeven   rhashtable: Make ...
112
113
  
  		if (expected && !obj) {
e859afe1e   Phil Sutter   lib: test_rhashta...
114
115
  			pr_warn("Test failed: Could not find key %u
  ", key.id);
9d6dbe1bb   Geert Uytterhoeven   rhashtable: Make ...
116
117
118
119
  			return -ENOENT;
  		} else if (!expected && obj) {
  			pr_warn("Test failed: Unexpected entry found for key %u
  ",
e859afe1e   Phil Sutter   lib: test_rhashta...
120
  				key.id);
9d6dbe1bb   Geert Uytterhoeven   rhashtable: Make ...
121
122
  			return -EEXIST;
  		} else if (expected && obj) {
e859afe1e   Phil Sutter   lib: test_rhashta...
123
  			if (obj->value.id != i) {
c2c8a9016   Thomas Graf   rhashtable-test: ...
124
125
  				pr_warn("Test failed: Lookup value mismatch %u!=%u
  ",
e859afe1e   Phil Sutter   lib: test_rhashta...
126
  					obj->value.id, i);
9d6dbe1bb   Geert Uytterhoeven   rhashtable: Make ...
127
128
129
  				return -EINVAL;
  			}
  		}
685a015e4   Thomas Graf   rhashtable: Allow...
130
131
  
  		cond_resched_rcu();
9d6dbe1bb   Geert Uytterhoeven   rhashtable: Make ...
132
133
134
135
  	}
  
  	return 0;
  }
246b23a76   Thomas Graf   rhashtable-test: ...
136
  static void test_bucket_stats(struct rhashtable *ht)
9d6dbe1bb   Geert Uytterhoeven   rhashtable: Make ...
137
  {
246b23a76   Thomas Graf   rhashtable-test: ...
138
139
  	unsigned int err, total = 0, chain_len = 0;
  	struct rhashtable_iter hti;
9d6dbe1bb   Geert Uytterhoeven   rhashtable: Make ...
140
  	struct rhash_head *pos;
9d6dbe1bb   Geert Uytterhoeven   rhashtable: Make ...
141

8f6fd83c6   Bob Copeland   rhashtable: accep...
142
  	err = rhashtable_walk_init(ht, &hti, GFP_KERNEL);
246b23a76   Thomas Graf   rhashtable-test: ...
143
144
145
146
  	if (err) {
  		pr_warn("Test failed: allocation error");
  		return;
  	}
9d6dbe1bb   Geert Uytterhoeven   rhashtable: Make ...
147

246b23a76   Thomas Graf   rhashtable-test: ...
148
149
150
151
152
153
  	err = rhashtable_walk_start(&hti);
  	if (err && err != -EAGAIN) {
  		pr_warn("Test failed: iterator failed: %d
  ", err);
  		return;
  	}
9d6dbe1bb   Geert Uytterhoeven   rhashtable: Make ...
154

246b23a76   Thomas Graf   rhashtable-test: ...
155
156
157
158
159
160
161
162
163
164
165
  	while ((pos = rhashtable_walk_next(&hti))) {
  		if (PTR_ERR(pos) == -EAGAIN) {
  			pr_info("Info: encountered resize
  ");
  			chain_len++;
  			continue;
  		} else if (IS_ERR(pos)) {
  			pr_warn("Test failed: rhashtable_walk_next() error: %ld
  ",
  				PTR_ERR(pos));
  			break;
9d6dbe1bb   Geert Uytterhoeven   rhashtable: Make ...
166
  		}
246b23a76   Thomas Graf   rhashtable-test: ...
167
  		total++;
9d6dbe1bb   Geert Uytterhoeven   rhashtable: Make ...
168
  	}
246b23a76   Thomas Graf   rhashtable-test: ...
169
170
171
172
173
174
  	rhashtable_walk_stop(&hti);
  	rhashtable_walk_exit(&hti);
  
  	pr_info("  Traversal complete: counted=%u, nelems=%u, entries=%d, table-jumps=%u
  ",
  		total, atomic_read(&ht->nelems), entries, chain_len);
9d6dbe1bb   Geert Uytterhoeven   rhashtable: Make ...
175

1aa661f5c   Thomas Graf   rhashtable-test: ...
176
  	if (total != atomic_read(&ht->nelems) || total != entries)
9d6dbe1bb   Geert Uytterhoeven   rhashtable: Make ...
177
178
  		pr_warn("Test failed: Total count mismatch ^^^");
  }
1aa661f5c   Thomas Graf   rhashtable-test: ...
179
  static s64 __init test_rhashtable(struct rhashtable *ht)
9d6dbe1bb   Geert Uytterhoeven   rhashtable: Make ...
180
  {
9d6dbe1bb   Geert Uytterhoeven   rhashtable: Make ...
181
  	struct test_obj *obj;
9d6dbe1bb   Geert Uytterhoeven   rhashtable: Make ...
182
  	int err;
9e9089e5a   Phil Sutter   rhashtable-test: ...
183
  	unsigned int i, insert_retries = 0;
1aa661f5c   Thomas Graf   rhashtable-test: ...
184
  	s64 start, end;
9d6dbe1bb   Geert Uytterhoeven   rhashtable: Make ...
185
186
187
  
  	/*
  	 * Insertion Test:
1aa661f5c   Thomas Graf   rhashtable-test: ...
188
  	 * Insert entries into table with all keys even numbers
9d6dbe1bb   Geert Uytterhoeven   rhashtable: Make ...
189
  	 */
1aa661f5c   Thomas Graf   rhashtable-test: ...
190
191
192
193
  	pr_info("  Adding %d keys
  ", entries);
  	start = ktime_get_ns();
  	for (i = 0; i < entries; i++) {
fcc570207   Thomas Graf   rhashtable-test: ...
194
  		struct test_obj *obj = &array[i];
9d6dbe1bb   Geert Uytterhoeven   rhashtable: Make ...
195

e859afe1e   Phil Sutter   lib: test_rhashta...
196
  		obj->value.id = i * 2;
9e9089e5a   Phil Sutter   rhashtable-test: ...
197
198
199
200
  		err = insert_retry(ht, &obj->node, test_rht_params);
  		if (err > 0)
  			insert_retries += err;
  		else if (err)
fcc570207   Thomas Graf   rhashtable-test: ...
201
  			return err;
9d6dbe1bb   Geert Uytterhoeven   rhashtable: Make ...
202
  	}
9e9089e5a   Phil Sutter   rhashtable-test: ...
203
204
205
206
  	if (insert_retries)
  		pr_info("  %u insertions retried due to memory pressure
  ",
  			insert_retries);
67b7cbf42   Thomas Graf   rhashtable-test: ...
207

246b23a76   Thomas Graf   rhashtable-test: ...
208
  	test_bucket_stats(ht);
9d6dbe1bb   Geert Uytterhoeven   rhashtable: Make ...
209
  	rcu_read_lock();
9d6dbe1bb   Geert Uytterhoeven   rhashtable: Make ...
210
211
  	test_rht_lookup(ht);
  	rcu_read_unlock();
246b23a76   Thomas Graf   rhashtable-test: ...
212
  	test_bucket_stats(ht);
9d6dbe1bb   Geert Uytterhoeven   rhashtable: Make ...
213

1aa661f5c   Thomas Graf   rhashtable-test: ...
214
215
216
  	pr_info("  Deleting %d keys
  ", entries);
  	for (i = 0; i < entries; i++) {
783692558   Phil Sutter   lib: test_rhashta...
217
218
219
  		struct test_obj_val key = {
  			.id = i * 2,
  		};
9d6dbe1bb   Geert Uytterhoeven   rhashtable: Make ...
220

e859afe1e   Phil Sutter   lib: test_rhashta...
221
  		if (array[i].value.id != TEST_INSERT_FAIL) {
67b7cbf42   Thomas Graf   rhashtable-test: ...
222
223
  			obj = rhashtable_lookup_fast(ht, &key, test_rht_params);
  			BUG_ON(!obj);
9d6dbe1bb   Geert Uytterhoeven   rhashtable: Make ...
224

67b7cbf42   Thomas Graf   rhashtable-test: ...
225
226
  			rhashtable_remove_fast(ht, &obj->node, test_rht_params);
  		}
685a015e4   Thomas Graf   rhashtable: Allow...
227
228
  
  		cond_resched();
9d6dbe1bb   Geert Uytterhoeven   rhashtable: Make ...
229
  	}
1aa661f5c   Thomas Graf   rhashtable-test: ...
230
231
232
233
234
  	end = ktime_get_ns();
  	pr_info("  Duration of test: %lld ns
  ", end - start);
  
  	return end - start;
9d6dbe1bb   Geert Uytterhoeven   rhashtable: Make ...
235
  }
b7f5e5c7f   Daniel Borkmann   rhashtable: don't...
236
  static struct rhashtable ht;
f4a3e90ba   Phil Sutter   rhashtable-test: ...
237
238
239
240
241
242
  static int thread_lookup_test(struct thread_data *tdata)
  {
  	int i, err = 0;
  
  	for (i = 0; i < entries; i++) {
  		struct test_obj *obj;
e859afe1e   Phil Sutter   lib: test_rhashta...
243
244
245
246
  		struct test_obj_val key = {
  			.id = i,
  			.tid = tdata->id,
  		};
f4a3e90ba   Phil Sutter   rhashtable-test: ...
247
248
  
  		obj = rhashtable_lookup_fast(&ht, &key, test_rht_params);
e859afe1e   Phil Sutter   lib: test_rhashta...
249
250
251
  		if (obj && (tdata->objs[i].value.id == TEST_INSERT_FAIL)) {
  			pr_err("  found unexpected object %d-%d
  ", key.tid, key.id);
f4a3e90ba   Phil Sutter   rhashtable-test: ...
252
  			err++;
e859afe1e   Phil Sutter   lib: test_rhashta...
253
254
255
  		} else if (!obj && (tdata->objs[i].value.id != TEST_INSERT_FAIL)) {
  			pr_err("  object %d-%d not found!
  ", key.tid, key.id);
f4a3e90ba   Phil Sutter   rhashtable-test: ...
256
  			err++;
e859afe1e   Phil Sutter   lib: test_rhashta...
257
258
259
260
  		} else if (obj && memcmp(&obj->value, &key, sizeof(key))) {
  			pr_err("  wrong object returned (got %d-%d, expected %d-%d)
  ",
  			       obj->value.tid, obj->value.id, key.tid, key.id);
f4a3e90ba   Phil Sutter   rhashtable-test: ...
261
262
  			err++;
  		}
cd5b318da   Phil Sutter   rhashtable-test: ...
263
264
  
  		cond_resched();
f4a3e90ba   Phil Sutter   rhashtable-test: ...
265
266
267
268
269
270
  	}
  	return err;
  }
  
  static int threadfunc(void *data)
  {
9e9089e5a   Phil Sutter   rhashtable-test: ...
271
  	int i, step, err = 0, insert_retries = 0;
f4a3e90ba   Phil Sutter   rhashtable-test: ...
272
273
274
275
276
277
278
279
  	struct thread_data *tdata = data;
  
  	up(&prestart_sem);
  	if (down_interruptible(&startup_sem))
  		pr_err("  thread[%d]: down_interruptible failed
  ", tdata->id);
  
  	for (i = 0; i < entries; i++) {
e859afe1e   Phil Sutter   lib: test_rhashta...
280
281
  		tdata->objs[i].value.id = i;
  		tdata->objs[i].value.tid = tdata->id;
9e9089e5a   Phil Sutter   rhashtable-test: ...
282
283
284
  		err = insert_retry(&ht, &tdata->objs[i].node, test_rht_params);
  		if (err > 0) {
  			insert_retries += err;
f4a3e90ba   Phil Sutter   rhashtable-test: ...
285
286
287
288
289
290
291
  		} else if (err) {
  			pr_err("  thread[%d]: rhashtable_insert_fast failed
  ",
  			       tdata->id);
  			goto out;
  		}
  	}
9e9089e5a   Phil Sutter   rhashtable-test: ...
292
293
294
295
  	if (insert_retries)
  		pr_info("  thread[%d]: %u insertions retried due to memory pressure
  ",
  			tdata->id, insert_retries);
f4a3e90ba   Phil Sutter   rhashtable-test: ...
296
297
298
299
300
301
302
303
304
305
306
  
  	err = thread_lookup_test(tdata);
  	if (err) {
  		pr_err("  thread[%d]: rhashtable_lookup_test failed
  ",
  		       tdata->id);
  		goto out;
  	}
  
  	for (step = 10; step > 0; step--) {
  		for (i = 0; i < entries; i += step) {
e859afe1e   Phil Sutter   lib: test_rhashta...
307
  			if (tdata->objs[i].value.id == TEST_INSERT_FAIL)
f4a3e90ba   Phil Sutter   rhashtable-test: ...
308
309
310
311
312
313
314
315
316
  				continue;
  			err = rhashtable_remove_fast(&ht, &tdata->objs[i].node,
  			                             test_rht_params);
  			if (err) {
  				pr_err("  thread[%d]: rhashtable_remove_fast failed
  ",
  				       tdata->id);
  				goto out;
  			}
e859afe1e   Phil Sutter   lib: test_rhashta...
317
  			tdata->objs[i].value.id = TEST_INSERT_FAIL;
cd5b318da   Phil Sutter   rhashtable-test: ...
318
319
  
  			cond_resched();
f4a3e90ba   Phil Sutter   rhashtable-test: ...
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
  		}
  		err = thread_lookup_test(tdata);
  		if (err) {
  			pr_err("  thread[%d]: rhashtable_lookup_test (2) failed
  ",
  			       tdata->id);
  			goto out;
  		}
  	}
  out:
  	while (!kthread_should_stop()) {
  		set_current_state(TASK_INTERRUPTIBLE);
  		schedule();
  	}
  	return err;
  }
9d6dbe1bb   Geert Uytterhoeven   rhashtable: Make ...
336
337
  static int __init test_rht_init(void)
  {
f4a3e90ba   Phil Sutter   rhashtable-test: ...
338
  	int i, err, started_threads = 0, failed_threads = 0;
1aa661f5c   Thomas Graf   rhashtable-test: ...
339
  	u64 total_time = 0;
f4a3e90ba   Phil Sutter   rhashtable-test: ...
340
341
  	struct thread_data *tdata;
  	struct test_obj *objs;
9d6dbe1bb   Geert Uytterhoeven   rhashtable: Make ...
342

1aa661f5c   Thomas Graf   rhashtable-test: ...
343
  	entries = min(entries, MAX_ENTRIES);
9d6dbe1bb   Geert Uytterhoeven   rhashtable: Make ...
344

1aa661f5c   Thomas Graf   rhashtable-test: ...
345
  	test_rht_params.automatic_shrinking = shrinking;
95e435afe   Phil Sutter   rhashtable-test: ...
346
  	test_rht_params.max_size = max_size ? : roundup_pow_of_two(entries);
1aa661f5c   Thomas Graf   rhashtable-test: ...
347
  	test_rht_params.nelem_hint = size;
9d6dbe1bb   Geert Uytterhoeven   rhashtable: Make ...
348

1aa661f5c   Thomas Graf   rhashtable-test: ...
349
350
351
  	pr_info("Running rhashtable test nelem=%d, max_size=%d, shrinking=%d
  ",
  		size, max_size, shrinking);
9d6dbe1bb   Geert Uytterhoeven   rhashtable: Make ...
352

1aa661f5c   Thomas Graf   rhashtable-test: ...
353
354
  	for (i = 0; i < runs; i++) {
  		s64 time;
9d6dbe1bb   Geert Uytterhoeven   rhashtable: Make ...
355

1aa661f5c   Thomas Graf   rhashtable-test: ...
356
357
  		pr_info("Test %02d:
  ", i);
fcc570207   Thomas Graf   rhashtable-test: ...
358
  		memset(&array, 0, sizeof(array));
1aa661f5c   Thomas Graf   rhashtable-test: ...
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
  		err = rhashtable_init(&ht, &test_rht_params);
  		if (err < 0) {
  			pr_warn("Test failed: Unable to initialize hashtable: %d
  ",
  				err);
  			continue;
  		}
  
  		time = test_rhashtable(&ht);
  		rhashtable_destroy(&ht);
  		if (time < 0) {
  			pr_warn("Test failed: return code %lld
  ", time);
  			return -EINVAL;
  		}
  
  		total_time += time;
  	}
6decd63ac   Thomas Graf   rhashtable-test: ...
377
378
379
  	do_div(total_time, runs);
  	pr_info("Average test time: %llu
  ", total_time);
1aa661f5c   Thomas Graf   rhashtable-test: ...
380

f4a3e90ba   Phil Sutter   rhashtable-test: ...
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
  	if (!tcount)
  		return 0;
  
  	pr_info("Testing concurrent rhashtable access from %d threads
  ",
  	        tcount);
  	sema_init(&prestart_sem, 1 - tcount);
  	tdata = vzalloc(tcount * sizeof(struct thread_data));
  	if (!tdata)
  		return -ENOMEM;
  	objs  = vzalloc(tcount * entries * sizeof(struct test_obj));
  	if (!objs) {
  		vfree(tdata);
  		return -ENOMEM;
  	}
95e435afe   Phil Sutter   rhashtable-test: ...
396
397
  	test_rht_params.max_size = max_size ? :
  	                           roundup_pow_of_two(tcount * entries);
f4a3e90ba   Phil Sutter   rhashtable-test: ...
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
  	err = rhashtable_init(&ht, &test_rht_params);
  	if (err < 0) {
  		pr_warn("Test failed: Unable to initialize hashtable: %d
  ",
  			err);
  		vfree(tdata);
  		vfree(objs);
  		return -EINVAL;
  	}
  	for (i = 0; i < tcount; i++) {
  		tdata[i].id = i;
  		tdata[i].objs = objs + i * entries;
  		tdata[i].task = kthread_run(threadfunc, &tdata[i],
  		                            "rhashtable_thrad[%d]", i);
  		if (IS_ERR(tdata[i].task))
  			pr_err(" kthread_run failed for thread %d
  ", i);
  		else
  			started_threads++;
  	}
  	if (down_interruptible(&prestart_sem))
  		pr_err("  down interruptible failed
  ");
  	for (i = 0; i < tcount; i++)
  		up(&startup_sem);
  	for (i = 0; i < tcount; i++) {
  		if (IS_ERR(tdata[i].task))
  			continue;
  		if ((err = kthread_stop(tdata[i].task))) {
  			pr_warn("Test failed: thread %d returned: %d
  ",
  			        i, err);
  			failed_threads++;
  		}
  	}
  	pr_info("Started %d threads, %d failed
  ",
  	        started_threads, failed_threads);
  	rhashtable_destroy(&ht);
  	vfree(tdata);
  	vfree(objs);
1aa661f5c   Thomas Graf   rhashtable-test: ...
439
  	return 0;
9d6dbe1bb   Geert Uytterhoeven   rhashtable: Make ...
440
  }
6dd0c1655   Daniel Borkmann   rhashtable: allow...
441
442
443
  static void __exit test_rht_exit(void)
  {
  }
9d6dbe1bb   Geert Uytterhoeven   rhashtable: Make ...
444
  module_init(test_rht_init);
6dd0c1655   Daniel Borkmann   rhashtable: allow...
445
  module_exit(test_rht_exit);
9d6dbe1bb   Geert Uytterhoeven   rhashtable: Make ...
446
447
  
  MODULE_LICENSE("GPL v2");