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