1 // SPDX-License-Identifier: GPL-2.0 1 // SPDX-License-Identifier: GPL-2.0 2 2 3 /* 3 /* 4 * Test module for stress and analyze performa 4 * Test module for stress and analyze performance of vmalloc allocator. 5 * (C) 2018 Uladzislau Rezki (Sony) <urezki@gm 5 * (C) 2018 Uladzislau Rezki (Sony) <urezki@gmail.com> 6 */ 6 */ 7 #include <linux/init.h> 7 #include <linux/init.h> 8 #include <linux/kernel.h> 8 #include <linux/kernel.h> 9 #include <linux/module.h> 9 #include <linux/module.h> 10 #include <linux/vmalloc.h> 10 #include <linux/vmalloc.h> 11 #include <linux/random.h> 11 #include <linux/random.h> 12 #include <linux/kthread.h> 12 #include <linux/kthread.h> 13 #include <linux/moduleparam.h> 13 #include <linux/moduleparam.h> 14 #include <linux/completion.h> 14 #include <linux/completion.h> 15 #include <linux/delay.h> 15 #include <linux/delay.h> 16 #include <linux/rwsem.h> 16 #include <linux/rwsem.h> 17 #include <linux/mm.h> 17 #include <linux/mm.h> 18 #include <linux/rcupdate.h> << 19 #include <linux/slab.h> << 20 18 21 #define __param(type, name, init, msg) 19 #define __param(type, name, init, msg) \ 22 static type name = init; 20 static type name = init; \ 23 module_param(name, type, 0444); 21 module_param(name, type, 0444); \ 24 MODULE_PARM_DESC(name, msg) 22 MODULE_PARM_DESC(name, msg) \ 25 23 26 __param(int, nr_threads, 0, !! 24 __param(bool, single_cpu_test, false, 27 "Number of workers to perform tests(mi !! 25 "Use single first online CPU to run tests"); 28 26 29 __param(bool, sequential_test_order, false, 27 __param(bool, sequential_test_order, false, 30 "Use sequential stress tests order"); 28 "Use sequential stress tests order"); 31 29 32 __param(int, test_repeat_count, 1, 30 __param(int, test_repeat_count, 1, 33 "Set test repeat counter"); 31 "Set test repeat counter"); 34 32 35 __param(int, test_loop_count, 1000000, 33 __param(int, test_loop_count, 1000000, 36 "Set test loop counter"); 34 "Set test loop counter"); 37 35 38 __param(int, nr_pages, 0, << 39 "Set number of pages for fix_size_allo << 40 << 41 __param(bool, use_huge, false, << 42 "Use vmalloc_huge in fix_size_alloc_te << 43 << 44 __param(int, run_test_mask, INT_MAX, 36 __param(int, run_test_mask, INT_MAX, 45 "Set tests specified in the mask.\n\n" 37 "Set tests specified in the mask.\n\n" 46 "\t\tid: 1, name: fix_size_ !! 38 "\t\tid: 1, name: fix_size_alloc_test\n" 47 "\t\tid: 2, name: full_fit_ !! 39 "\t\tid: 2, name: full_fit_alloc_test\n" 48 "\t\tid: 4, name: long_busy !! 40 "\t\tid: 4, name: long_busy_list_alloc_test\n" 49 "\t\tid: 8, name: random_si !! 41 "\t\tid: 8, name: random_size_alloc_test\n" 50 "\t\tid: 16, name: fix_align !! 42 "\t\tid: 16, name: fix_align_alloc_test\n" 51 "\t\tid: 32, name: random_si !! 43 "\t\tid: 32, name: random_size_align_alloc_test\n" 52 "\t\tid: 64, name: align_shi !! 44 "\t\tid: 64, name: align_shift_alloc_test\n" 53 "\t\tid: 128, name: pcpu_allo !! 45 "\t\tid: 128, name: pcpu_alloc_test\n" 54 "\t\tid: 256, name: kvfree_rc << 55 "\t\tid: 512, name: kvfree_rc << 56 "\t\tid: 1024, name: vm_map_ra << 57 /* Add a new test case descrip 46 /* Add a new test case description here. */ 58 ); 47 ); 59 48 60 /* 49 /* >> 50 * Depends on single_cpu_test parameter. If it is true, then >> 51 * use first online CPU to trigger a test on, otherwise go with >> 52 * all online CPUs. >> 53 */ >> 54 static cpumask_t cpus_run_test_mask = CPU_MASK_NONE; >> 55 >> 56 /* 61 * Read write semaphore for synchronization of 57 * Read write semaphore for synchronization of setup 62 * phase that is done in main thread and worke 58 * phase that is done in main thread and workers. 63 */ 59 */ 64 static DECLARE_RWSEM(prepare_for_test_rwsem); 60 static DECLARE_RWSEM(prepare_for_test_rwsem); 65 61 66 /* 62 /* 67 * Completion tracking for worker threads. 63 * Completion tracking for worker threads. 68 */ 64 */ 69 static DECLARE_COMPLETION(test_all_done_comp); 65 static DECLARE_COMPLETION(test_all_done_comp); 70 static atomic_t test_n_undone = ATOMIC_INIT(0) 66 static atomic_t test_n_undone = ATOMIC_INIT(0); 71 67 72 static inline void 68 static inline void 73 test_report_one_done(void) 69 test_report_one_done(void) 74 { 70 { 75 if (atomic_dec_and_test(&test_n_undone 71 if (atomic_dec_and_test(&test_n_undone)) 76 complete(&test_all_done_comp); 72 complete(&test_all_done_comp); 77 } 73 } 78 74 79 static int random_size_align_alloc_test(void) 75 static int random_size_align_alloc_test(void) 80 { 76 { 81 unsigned long size, align; !! 77 unsigned long size, align, rnd; 82 unsigned int rnd; << 83 void *ptr; 78 void *ptr; 84 int i; 79 int i; 85 80 86 for (i = 0; i < test_loop_count; i++) 81 for (i = 0; i < test_loop_count; i++) { 87 rnd = get_random_u8(); !! 82 get_random_bytes(&rnd, sizeof(rnd)); 88 83 89 /* 84 /* 90 * Maximum 1024 pages, if PAGE 85 * Maximum 1024 pages, if PAGE_SIZE is 4096. 91 */ 86 */ 92 align = 1 << (rnd % 23); 87 align = 1 << (rnd % 23); 93 88 94 /* 89 /* 95 * Maximum 10 pages. 90 * Maximum 10 pages. 96 */ 91 */ 97 size = ((rnd % 10) + 1) * PAGE 92 size = ((rnd % 10) + 1) * PAGE_SIZE; 98 93 99 ptr = __vmalloc_node(size, ali !! 94 ptr = __vmalloc_node_range(size, align, 100 __builtin_retu !! 95 VMALLOC_START, VMALLOC_END, >> 96 GFP_KERNEL | __GFP_ZERO, >> 97 PAGE_KERNEL, >> 98 0, 0, __builtin_return_address(0)); >> 99 101 if (!ptr) 100 if (!ptr) 102 return -1; 101 return -1; 103 102 104 vfree(ptr); 103 vfree(ptr); 105 } 104 } 106 105 107 return 0; 106 return 0; 108 } 107 } 109 108 110 /* 109 /* 111 * This test case is supposed to be failed. 110 * This test case is supposed to be failed. 112 */ 111 */ 113 static int align_shift_alloc_test(void) 112 static int align_shift_alloc_test(void) 114 { 113 { 115 unsigned long align; 114 unsigned long align; 116 void *ptr; 115 void *ptr; 117 int i; 116 int i; 118 117 119 for (i = 0; i < BITS_PER_LONG; i++) { 118 for (i = 0; i < BITS_PER_LONG; i++) { 120 align = 1UL << i; !! 119 align = ((unsigned long) 1) << i; >> 120 >> 121 ptr = __vmalloc_node_range(PAGE_SIZE, align, >> 122 VMALLOC_START, VMALLOC_END, >> 123 GFP_KERNEL | __GFP_ZERO, >> 124 PAGE_KERNEL, >> 125 0, 0, __builtin_return_address(0)); 121 126 122 ptr = __vmalloc_node(PAGE_SIZE << 123 __builtin_retu << 124 if (!ptr) 127 if (!ptr) 125 return -1; 128 return -1; 126 129 127 vfree(ptr); 130 vfree(ptr); 128 } 131 } 129 132 130 return 0; 133 return 0; 131 } 134 } 132 135 133 static int fix_align_alloc_test(void) 136 static int fix_align_alloc_test(void) 134 { 137 { 135 void *ptr; 138 void *ptr; 136 int i; 139 int i; 137 140 138 for (i = 0; i < test_loop_count; i++) 141 for (i = 0; i < test_loop_count; i++) { 139 ptr = __vmalloc_node(5 * PAGE_ !! 142 ptr = __vmalloc_node_range(5 * PAGE_SIZE, 140 GFP_KERNEL | _ !! 143 THREAD_ALIGN << 1, 141 __builtin_retu !! 144 VMALLOC_START, VMALLOC_END, >> 145 GFP_KERNEL | __GFP_ZERO, >> 146 PAGE_KERNEL, >> 147 0, 0, __builtin_return_address(0)); >> 148 142 if (!ptr) 149 if (!ptr) 143 return -1; 150 return -1; 144 151 145 vfree(ptr); 152 vfree(ptr); 146 } 153 } 147 154 148 return 0; 155 return 0; 149 } 156 } 150 157 151 static int random_size_alloc_test(void) 158 static int random_size_alloc_test(void) 152 { 159 { 153 unsigned int n; 160 unsigned int n; 154 void *p; 161 void *p; 155 int i; 162 int i; 156 163 157 for (i = 0; i < test_loop_count; i++) 164 for (i = 0; i < test_loop_count; i++) { 158 n = get_random_u32_inclusive(1 !! 165 get_random_bytes(&n, sizeof(i)); >> 166 n = (n % 100) + 1; >> 167 159 p = vmalloc(n * PAGE_SIZE); 168 p = vmalloc(n * PAGE_SIZE); 160 169 161 if (!p) 170 if (!p) 162 return -1; 171 return -1; 163 172 164 *((__u8 *)p) = 1; 173 *((__u8 *)p) = 1; 165 vfree(p); 174 vfree(p); 166 } 175 } 167 176 168 return 0; 177 return 0; 169 } 178 } 170 179 171 static int long_busy_list_alloc_test(void) 180 static int long_busy_list_alloc_test(void) 172 { 181 { 173 void *ptr_1, *ptr_2; 182 void *ptr_1, *ptr_2; 174 void **ptr; 183 void **ptr; 175 int rv = -1; 184 int rv = -1; 176 int i; 185 int i; 177 186 178 ptr = vmalloc(sizeof(void *) * 15000); 187 ptr = vmalloc(sizeof(void *) * 15000); 179 if (!ptr) 188 if (!ptr) 180 return rv; 189 return rv; 181 190 182 for (i = 0; i < 15000; i++) 191 for (i = 0; i < 15000; i++) 183 ptr[i] = vmalloc(1 * PAGE_SIZE 192 ptr[i] = vmalloc(1 * PAGE_SIZE); 184 193 185 for (i = 0; i < test_loop_count; i++) 194 for (i = 0; i < test_loop_count; i++) { 186 ptr_1 = vmalloc(100 * PAGE_SIZ 195 ptr_1 = vmalloc(100 * PAGE_SIZE); 187 if (!ptr_1) 196 if (!ptr_1) 188 goto leave; 197 goto leave; 189 198 190 ptr_2 = vmalloc(1 * PAGE_SIZE) 199 ptr_2 = vmalloc(1 * PAGE_SIZE); 191 if (!ptr_2) { 200 if (!ptr_2) { 192 vfree(ptr_1); 201 vfree(ptr_1); 193 goto leave; 202 goto leave; 194 } 203 } 195 204 196 *((__u8 *)ptr_1) = 0; 205 *((__u8 *)ptr_1) = 0; 197 *((__u8 *)ptr_2) = 1; 206 *((__u8 *)ptr_2) = 1; 198 207 199 vfree(ptr_1); 208 vfree(ptr_1); 200 vfree(ptr_2); 209 vfree(ptr_2); 201 } 210 } 202 211 203 /* Success */ 212 /* Success */ 204 rv = 0; 213 rv = 0; 205 214 206 leave: 215 leave: 207 for (i = 0; i < 15000; i++) 216 for (i = 0; i < 15000; i++) 208 vfree(ptr[i]); 217 vfree(ptr[i]); 209 218 210 vfree(ptr); 219 vfree(ptr); 211 return rv; 220 return rv; 212 } 221 } 213 222 214 static int full_fit_alloc_test(void) 223 static int full_fit_alloc_test(void) 215 { 224 { 216 void **ptr, **junk_ptr, *tmp; 225 void **ptr, **junk_ptr, *tmp; 217 int junk_length; 226 int junk_length; 218 int rv = -1; 227 int rv = -1; 219 int i; 228 int i; 220 229 221 junk_length = fls(num_online_cpus()); 230 junk_length = fls(num_online_cpus()); 222 junk_length *= (32 * 1024 * 1024 / PAG 231 junk_length *= (32 * 1024 * 1024 / PAGE_SIZE); 223 232 224 ptr = vmalloc(sizeof(void *) * junk_le 233 ptr = vmalloc(sizeof(void *) * junk_length); 225 if (!ptr) 234 if (!ptr) 226 return rv; 235 return rv; 227 236 228 junk_ptr = vmalloc(sizeof(void *) * ju 237 junk_ptr = vmalloc(sizeof(void *) * junk_length); 229 if (!junk_ptr) { 238 if (!junk_ptr) { 230 vfree(ptr); 239 vfree(ptr); 231 return rv; 240 return rv; 232 } 241 } 233 242 234 for (i = 0; i < junk_length; i++) { 243 for (i = 0; i < junk_length; i++) { 235 ptr[i] = vmalloc(1 * PAGE_SIZE 244 ptr[i] = vmalloc(1 * PAGE_SIZE); 236 junk_ptr[i] = vmalloc(1 * PAGE 245 junk_ptr[i] = vmalloc(1 * PAGE_SIZE); 237 } 246 } 238 247 239 for (i = 0; i < junk_length; i++) 248 for (i = 0; i < junk_length; i++) 240 vfree(junk_ptr[i]); 249 vfree(junk_ptr[i]); 241 250 242 for (i = 0; i < test_loop_count; i++) 251 for (i = 0; i < test_loop_count; i++) { 243 tmp = vmalloc(1 * PAGE_SIZE); 252 tmp = vmalloc(1 * PAGE_SIZE); 244 253 245 if (!tmp) 254 if (!tmp) 246 goto error; 255 goto error; 247 256 248 *((__u8 *)tmp) = 1; 257 *((__u8 *)tmp) = 1; 249 vfree(tmp); 258 vfree(tmp); 250 } 259 } 251 260 252 /* Success */ 261 /* Success */ 253 rv = 0; 262 rv = 0; 254 263 255 error: 264 error: 256 for (i = 0; i < junk_length; i++) 265 for (i = 0; i < junk_length; i++) 257 vfree(ptr[i]); 266 vfree(ptr[i]); 258 267 259 vfree(ptr); 268 vfree(ptr); 260 vfree(junk_ptr); 269 vfree(junk_ptr); 261 270 262 return rv; 271 return rv; 263 } 272 } 264 273 265 static int fix_size_alloc_test(void) 274 static int fix_size_alloc_test(void) 266 { 275 { 267 void *ptr; 276 void *ptr; 268 int i; 277 int i; 269 278 270 for (i = 0; i < test_loop_count; i++) 279 for (i = 0; i < test_loop_count; i++) { 271 if (use_huge) !! 280 ptr = vmalloc(3 * PAGE_SIZE); 272 ptr = vmalloc_huge((nr << 273 else << 274 ptr = vmalloc((nr_page << 275 281 276 if (!ptr) 282 if (!ptr) 277 return -1; 283 return -1; 278 284 279 *((__u8 *)ptr) = 0; 285 *((__u8 *)ptr) = 0; 280 286 281 vfree(ptr); 287 vfree(ptr); 282 } 288 } 283 289 284 return 0; 290 return 0; 285 } 291 } 286 292 287 static int 293 static int 288 pcpu_alloc_test(void) 294 pcpu_alloc_test(void) 289 { 295 { 290 int rv = 0; 296 int rv = 0; 291 #ifndef CONFIG_NEED_PER_CPU_KM 297 #ifndef CONFIG_NEED_PER_CPU_KM 292 void __percpu **pcpu; 298 void __percpu **pcpu; 293 size_t size, align; 299 size_t size, align; 294 int i; 300 int i; 295 301 296 pcpu = vmalloc(sizeof(void __percpu *) 302 pcpu = vmalloc(sizeof(void __percpu *) * 35000); 297 if (!pcpu) 303 if (!pcpu) 298 return -1; 304 return -1; 299 305 300 for (i = 0; i < 35000; i++) { 306 for (i = 0; i < 35000; i++) { 301 size = get_random_u32_inclusiv !! 307 unsigned int r; >> 308 >> 309 get_random_bytes(&r, sizeof(i)); >> 310 size = (r % (PAGE_SIZE / 4)) + 1; 302 311 303 /* 312 /* 304 * Maximum PAGE_SIZE 313 * Maximum PAGE_SIZE 305 */ 314 */ 306 align = 1 << get_random_u32_in !! 315 get_random_bytes(&r, sizeof(i)); >> 316 align = 1 << ((i % 11) + 1); 307 317 308 pcpu[i] = __alloc_percpu(size, 318 pcpu[i] = __alloc_percpu(size, align); 309 if (!pcpu[i]) 319 if (!pcpu[i]) 310 rv = -1; 320 rv = -1; 311 } 321 } 312 322 313 for (i = 0; i < 35000; i++) 323 for (i = 0; i < 35000; i++) 314 free_percpu(pcpu[i]); 324 free_percpu(pcpu[i]); 315 325 316 vfree(pcpu); 326 vfree(pcpu); 317 #endif 327 #endif 318 return rv; 328 return rv; 319 } 329 } 320 330 321 struct test_kvfree_rcu { << 322 struct rcu_head rcu; << 323 unsigned char array[20]; << 324 }; << 325 << 326 static int << 327 kvfree_rcu_1_arg_vmalloc_test(void) << 328 { << 329 struct test_kvfree_rcu *p; << 330 int i; << 331 << 332 for (i = 0; i < test_loop_count; i++) << 333 p = vmalloc(1 * PAGE_SIZE); << 334 if (!p) << 335 return -1; << 336 << 337 p->array[0] = 'a'; << 338 kvfree_rcu_mightsleep(p); << 339 } << 340 << 341 return 0; << 342 } << 343 << 344 static int << 345 kvfree_rcu_2_arg_vmalloc_test(void) << 346 { << 347 struct test_kvfree_rcu *p; << 348 int i; << 349 << 350 for (i = 0; i < test_loop_count; i++) << 351 p = vmalloc(1 * PAGE_SIZE); << 352 if (!p) << 353 return -1; << 354 << 355 p->array[0] = 'a'; << 356 kvfree_rcu(p, rcu); << 357 } << 358 << 359 return 0; << 360 } << 361 << 362 static int << 363 vm_map_ram_test(void) << 364 { << 365 unsigned long nr_allocated; << 366 unsigned int map_nr_pages; << 367 unsigned char *v_ptr; << 368 struct page **pages; << 369 int i; << 370 << 371 map_nr_pages = nr_pages > 0 ? nr_pages << 372 pages = kcalloc(map_nr_pages, sizeof(s << 373 if (!pages) << 374 return -1; << 375 << 376 nr_allocated = alloc_pages_bulk_array( << 377 if (nr_allocated != map_nr_pages) << 378 goto cleanup; << 379 << 380 /* Run the test loop. */ << 381 for (i = 0; i < test_loop_count; i++) << 382 v_ptr = vm_map_ram(pages, map_ << 383 *v_ptr = 'a'; << 384 vm_unmap_ram(v_ptr, map_nr_pag << 385 } << 386 << 387 cleanup: << 388 for (i = 0; i < nr_allocated; i++) << 389 __free_page(pages[i]); << 390 << 391 kfree(pages); << 392 << 393 /* 0 indicates success. */ << 394 return nr_allocated != map_nr_pages; << 395 } << 396 << 397 struct test_case_desc { 331 struct test_case_desc { 398 const char *test_name; 332 const char *test_name; 399 int (*test_func)(void); 333 int (*test_func)(void); 400 }; 334 }; 401 335 402 static struct test_case_desc test_case_array[] 336 static struct test_case_desc test_case_array[] = { 403 { "fix_size_alloc_test", fix_size_allo 337 { "fix_size_alloc_test", fix_size_alloc_test }, 404 { "full_fit_alloc_test", full_fit_allo 338 { "full_fit_alloc_test", full_fit_alloc_test }, 405 { "long_busy_list_alloc_test", long_bu 339 { "long_busy_list_alloc_test", long_busy_list_alloc_test }, 406 { "random_size_alloc_test", random_siz 340 { "random_size_alloc_test", random_size_alloc_test }, 407 { "fix_align_alloc_test", fix_align_al 341 { "fix_align_alloc_test", fix_align_alloc_test }, 408 { "random_size_align_alloc_test", rand 342 { "random_size_align_alloc_test", random_size_align_alloc_test }, 409 { "align_shift_alloc_test", align_shif 343 { "align_shift_alloc_test", align_shift_alloc_test }, 410 { "pcpu_alloc_test", pcpu_alloc_test } 344 { "pcpu_alloc_test", pcpu_alloc_test }, 411 { "kvfree_rcu_1_arg_vmalloc_test", kvf << 412 { "kvfree_rcu_2_arg_vmalloc_test", kvf << 413 { "vm_map_ram_test", vm_map_ram_test } << 414 /* Add a new test case here. */ 345 /* Add a new test case here. */ 415 }; 346 }; 416 347 417 struct test_case_data { 348 struct test_case_data { 418 int test_failed; 349 int test_failed; 419 int test_passed; 350 int test_passed; 420 u64 time; 351 u64 time; 421 }; 352 }; 422 353 >> 354 /* Split it to get rid of: WARNING: line over 80 characters */ >> 355 static struct test_case_data >> 356 per_cpu_test_data[NR_CPUS][ARRAY_SIZE(test_case_array)]; >> 357 423 static struct test_driver { 358 static struct test_driver { 424 struct task_struct *task; 359 struct task_struct *task; 425 struct test_case_data data[ARRAY_SIZE( << 426 << 427 unsigned long start; 360 unsigned long start; 428 unsigned long stop; 361 unsigned long stop; 429 } *tdriver; !! 362 int cpu; >> 363 } per_cpu_test_driver[NR_CPUS]; 430 364 431 static void shuffle_array(int *arr, int n) 365 static void shuffle_array(int *arr, int n) 432 { 366 { 433 int i, j; !! 367 unsigned int rnd; >> 368 int i, j, x; 434 369 435 for (i = n - 1; i > 0; i--) { 370 for (i = n - 1; i > 0; i--) { >> 371 get_random_bytes(&rnd, sizeof(rnd)); >> 372 436 /* Cut the range. */ 373 /* Cut the range. */ 437 j = get_random_u32_below(i); !! 374 j = rnd % i; 438 375 439 /* Swap indexes. */ 376 /* Swap indexes. */ 440 swap(arr[i], arr[j]); !! 377 x = arr[i]; >> 378 arr[i] = arr[j]; >> 379 arr[j] = x; 441 } 380 } 442 } 381 } 443 382 444 static int test_func(void *private) 383 static int test_func(void *private) 445 { 384 { 446 struct test_driver *t = private; 385 struct test_driver *t = private; 447 int random_array[ARRAY_SIZE(test_case_ 386 int random_array[ARRAY_SIZE(test_case_array)]; 448 int index, i, j; 387 int index, i, j; 449 ktime_t kt; 388 ktime_t kt; 450 u64 delta; 389 u64 delta; 451 390 >> 391 if (set_cpus_allowed_ptr(current, cpumask_of(t->cpu)) < 0) >> 392 pr_err("Failed to set affinity to %d CPU\n", t->cpu); >> 393 452 for (i = 0; i < ARRAY_SIZE(test_case_a 394 for (i = 0; i < ARRAY_SIZE(test_case_array); i++) 453 random_array[i] = i; 395 random_array[i] = i; 454 396 455 if (!sequential_test_order) 397 if (!sequential_test_order) 456 shuffle_array(random_array, AR 398 shuffle_array(random_array, ARRAY_SIZE(test_case_array)); 457 399 458 /* 400 /* 459 * Block until initialization is done. 401 * Block until initialization is done. 460 */ 402 */ 461 down_read(&prepare_for_test_rwsem); 403 down_read(&prepare_for_test_rwsem); 462 404 463 t->start = get_cycles(); 405 t->start = get_cycles(); 464 for (i = 0; i < ARRAY_SIZE(test_case_a 406 for (i = 0; i < ARRAY_SIZE(test_case_array); i++) { 465 index = random_array[i]; 407 index = random_array[i]; 466 408 467 /* 409 /* 468 * Skip tests if run_test_mask 410 * Skip tests if run_test_mask has been specified. 469 */ 411 */ 470 if (!((run_test_mask & (1 << i 412 if (!((run_test_mask & (1 << index)) >> index)) 471 continue; 413 continue; 472 414 473 kt = ktime_get(); 415 kt = ktime_get(); 474 for (j = 0; j < test_repeat_co 416 for (j = 0; j < test_repeat_count; j++) { 475 if (!test_case_array[i 417 if (!test_case_array[index].test_func()) 476 t->data[index] !! 418 per_cpu_test_data[t->cpu][index].test_passed++; 477 else 419 else 478 t->data[index] !! 420 per_cpu_test_data[t->cpu][index].test_failed++; 479 } 421 } 480 422 481 /* 423 /* 482 * Take an average time that t 424 * Take an average time that test took. 483 */ 425 */ 484 delta = (u64) ktime_us_delta(k 426 delta = (u64) ktime_us_delta(ktime_get(), kt); 485 do_div(delta, (u32) test_repea 427 do_div(delta, (u32) test_repeat_count); 486 428 487 t->data[index].time = delta; !! 429 per_cpu_test_data[t->cpu][index].time = delta; 488 } 430 } 489 t->stop = get_cycles(); 431 t->stop = get_cycles(); 490 432 491 up_read(&prepare_for_test_rwsem); 433 up_read(&prepare_for_test_rwsem); 492 test_report_one_done(); 434 test_report_one_done(); 493 435 494 /* 436 /* 495 * Wait for the kthread_stop() call. 437 * Wait for the kthread_stop() call. 496 */ 438 */ 497 while (!kthread_should_stop()) 439 while (!kthread_should_stop()) 498 msleep(10); 440 msleep(10); 499 441 500 return 0; 442 return 0; 501 } 443 } 502 444 503 static int !! 445 static void 504 init_test_configuration(void) !! 446 init_test_configurtion(void) 505 { 447 { 506 /* 448 /* 507 * A maximum number of workers is defi !! 449 * Reset all data of all CPUs. 508 * value and set to USHRT_MAX. We add << 509 * case and for potential heavy stress << 510 */ 450 */ 511 nr_threads = clamp(nr_threads, 1, (int !! 451 memset(per_cpu_test_data, 0, sizeof(per_cpu_test_data)); 512 452 513 /* Allocate the space for test instanc !! 453 if (single_cpu_test) 514 tdriver = kvcalloc(nr_threads, sizeof( !! 454 cpumask_set_cpu(cpumask_first(cpu_online_mask), 515 if (tdriver == NULL) !! 455 &cpus_run_test_mask); 516 return -1; !! 456 else >> 457 cpumask_and(&cpus_run_test_mask, cpu_online_mask, >> 458 cpu_online_mask); 517 459 518 if (test_repeat_count <= 0) 460 if (test_repeat_count <= 0) 519 test_repeat_count = 1; 461 test_repeat_count = 1; 520 462 521 if (test_loop_count <= 0) 463 if (test_loop_count <= 0) 522 test_loop_count = 1; 464 test_loop_count = 1; 523 << 524 return 0; << 525 } 465 } 526 466 527 static void do_concurrent_test(void) 467 static void do_concurrent_test(void) 528 { 468 { 529 int i, ret; !! 469 int cpu, ret; 530 470 531 /* 471 /* 532 * Set some basic configurations plus 472 * Set some basic configurations plus sanity check. 533 */ 473 */ 534 ret = init_test_configuration(); !! 474 init_test_configurtion(); 535 if (ret < 0) << 536 return; << 537 475 538 /* 476 /* 539 * Put on hold all workers. 477 * Put on hold all workers. 540 */ 478 */ 541 down_write(&prepare_for_test_rwsem); 479 down_write(&prepare_for_test_rwsem); 542 480 543 for (i = 0; i < nr_threads; i++) { !! 481 for_each_cpu(cpu, &cpus_run_test_mask) { 544 struct test_driver *t = &tdriv !! 482 struct test_driver *t = &per_cpu_test_driver[cpu]; 545 483 546 t->task = kthread_run(test_fun !! 484 t->cpu = cpu; >> 485 t->task = kthread_run(test_func, t, "vmalloc_test/%d", cpu); 547 486 548 if (!IS_ERR(t->task)) 487 if (!IS_ERR(t->task)) 549 /* Success. */ 488 /* Success. */ 550 atomic_inc(&test_n_und 489 atomic_inc(&test_n_undone); 551 else 490 else 552 pr_err("Failed to star !! 491 pr_err("Failed to start kthread for %d CPU\n", cpu); 553 } 492 } 554 493 555 /* 494 /* 556 * Now let the workers do their job. 495 * Now let the workers do their job. 557 */ 496 */ 558 up_write(&prepare_for_test_rwsem); 497 up_write(&prepare_for_test_rwsem); 559 498 560 /* 499 /* 561 * Sleep quiet until all workers are d 500 * Sleep quiet until all workers are done with 1 second 562 * interval. Since the test can take a 501 * interval. Since the test can take a lot of time we 563 * can run into a stack trace of the h 502 * can run into a stack trace of the hung task. That is 564 * why we go with completion_timeout a 503 * why we go with completion_timeout and HZ value. 565 */ 504 */ 566 do { 505 do { 567 ret = wait_for_completion_time 506 ret = wait_for_completion_timeout(&test_all_done_comp, HZ); 568 } while (!ret); 507 } while (!ret); 569 508 570 for (i = 0; i < nr_threads; i++) { !! 509 for_each_cpu(cpu, &cpus_run_test_mask) { 571 struct test_driver *t = &tdriv !! 510 struct test_driver *t = &per_cpu_test_driver[cpu]; 572 int j; !! 511 int i; 573 512 574 if (!IS_ERR(t->task)) 513 if (!IS_ERR(t->task)) 575 kthread_stop(t->task); 514 kthread_stop(t->task); 576 515 577 for (j = 0; j < ARRAY_SIZE(tes !! 516 for (i = 0; i < ARRAY_SIZE(test_case_array); i++) { 578 if (!((run_test_mask & !! 517 if (!((run_test_mask & (1 << i)) >> i)) 579 continue; 518 continue; 580 519 581 pr_info( 520 pr_info( 582 "Summary: %s p 521 "Summary: %s passed: %d failed: %d repeat: %d loops: %d avg: %llu usec\n", 583 test_case_arra !! 522 test_case_array[i].test_name, 584 t->data[j].tes !! 523 per_cpu_test_data[cpu][i].test_passed, 585 t->data[j].tes !! 524 per_cpu_test_data[cpu][i].test_failed, 586 test_repeat_co 525 test_repeat_count, test_loop_count, 587 t->data[j].tim !! 526 per_cpu_test_data[cpu][i].time); 588 } 527 } 589 528 590 pr_info("All test took worker% !! 529 pr_info("All test took CPU%d=%lu cycles\n", 591 i, t->stop - t->start) !! 530 cpu, t->stop - t->start); 592 } 531 } 593 << 594 kvfree(tdriver); << 595 } 532 } 596 533 597 static int vmalloc_test_init(void) 534 static int vmalloc_test_init(void) 598 { 535 { 599 do_concurrent_test(); 536 do_concurrent_test(); 600 return -EAGAIN; /* Fail will directly 537 return -EAGAIN; /* Fail will directly unload the module */ 601 } 538 } 602 539 >> 540 static void vmalloc_test_exit(void) >> 541 { >> 542 } >> 543 603 module_init(vmalloc_test_init) 544 module_init(vmalloc_test_init) >> 545 module_exit(vmalloc_test_exit) 604 546 605 MODULE_LICENSE("GPL"); 547 MODULE_LICENSE("GPL"); 606 MODULE_AUTHOR("Uladzislau Rezki"); 548 MODULE_AUTHOR("Uladzislau Rezki"); 607 MODULE_DESCRIPTION("vmalloc test module"); 549 MODULE_DESCRIPTION("vmalloc test module"); 608 550
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.