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