Skip to content

Commit a6640b5

Browse files
committed
stress-bad-ioctl: improve per-ioctl timeouts
Make timeout checks shorter (0.10 sec) and also add itimer signals to interrupt ioctls calls in case they are interruptible (mostly they are not). Signed-off-by: Colin Ian King <colin.i.king@gmail.com>
1 parent d205850 commit a6640b5

1 file changed

Lines changed: 86 additions & 6 deletions

File tree

stress-bad-ioctl.c

Lines changed: 86 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ static const stress_help_t help[] = {
3636
{ NULL, NULL, NULL }
3737
};
3838

39+
#define IOCTL_TIMEOUT_US (100000)
40+
3941
/* Index order to stress_bad_ioctl_methods */
4042
#define STRESS_BAD_IOCTL_CMD_INC (0)
4143
#define STRESS_BAD_IOCTL_CMD_RANDOM (1)
@@ -85,6 +87,7 @@ static sigset_t set;
8587
static void *node_lock;
8688
static uint32_t mixup;
8789
static dev_ioctl_info_t *dev_ioctl_info_head;
90+
static size_t dev_ioctl_info_count;
8891
static volatile dev_ioctl_info_t *dev_ioctl_node;
8992

9093
typedef struct stress_bad_ioctl_func {
@@ -95,6 +98,24 @@ typedef struct stress_bad_ioctl_func {
9598

9699
static sigjmp_buf jmp_env;
97100

101+
static void stress_bad_ioctl_itimer_set(const suseconds_t usec)
102+
{
103+
#if defined(HAVE_SETITIMER) && \
104+
defined(SIGPROF)
105+
struct itimerval timer;
106+
107+
(void)shim_memset(&timer, 0, sizeof(timer));
108+
timer.it_value.tv_sec = usec / 1000000;
109+
timer.it_value.tv_usec = usec % 1000000;
110+
timer.it_interval.tv_sec = timer.it_value.tv_sec;
111+
timer.it_interval.tv_usec = timer.it_value.tv_usec;
112+
113+
(void)setitimer(ITIMER_PROF, &timer, NULL);
114+
#else
115+
(void)usec;
116+
#endif
117+
}
118+
98119
/*
99120
* stress_bad_ioctl_dev_new()
100121
* add a new ioctl device path to tree
@@ -122,6 +143,7 @@ static dev_ioctl_info_t *stress_bad_ioctl_dev_new(
122143
}
123144
node->ignore = false;
124145
node->ioctl_state = stress_mwc16();
146+
dev_ioctl_info_count++;
125147

126148
*head = node;
127149
return node;
@@ -223,9 +245,11 @@ static void stress_bad_ioctl_dev_dir(
223245
stress_fs_dirent_list_free(dlist, n);
224246
}
225247

226-
static void NORETURN MLOCKED_TEXT stress_segv_handler(int signum)
248+
static void MLOCKED_TEXT stress_sig_handler(int signum)
227249
{
228-
stress_signal_siglongjmp(signum, jmp_env, 1);
250+
stress_bad_ioctl_itimer_set(0);
251+
if (signum == SIGALRM)
252+
stress_signal_siglongjmp(signum, jmp_env, 1);
229253
}
230254

231255
/*
@@ -237,7 +261,7 @@ static inline void stress_bad_ioctl_rw(
237261
const bool is_pthread,
238262
const size_t thread_index)
239263
{
240-
const double threshold = 0.25;
264+
const double threshold = IOCTL_TIMEOUT_US / 1000000.0;
241265
const size_t page_size = args->page_size;
242266
uint64_t *buf;
243267
uint64_t *buf_page1;
@@ -291,6 +315,8 @@ static inline void stress_bad_ioctl_rw(
291315
uint64_t rnd = stress_mwc32();
292316
volatile dev_ioctl_info_t *node;
293317

318+
stress_bad_ioctl_itimer_set(0);
319+
294320
ret = stress_lock_acquire(node_lock);
295321
if (ret)
296322
break;
@@ -302,8 +328,6 @@ static inline void stress_bad_ioctl_rw(
302328
type = (node->ioctl_state >> 8) & 0xff;
303329
nr = (node->ioctl_state) & 0xff;
304330

305-
t_start = stress_time_now();
306-
307331
for (ptr = (uint32_t *)buf; ptr < buf_end; ptr++) {
308332
*ptr ^= rnd;
309333
}
@@ -319,121 +343,161 @@ static inline void stress_bad_ioctl_rw(
319343

320344
(void)shim_memset(buf, 0, page_size);
321345

346+
t_start = stress_time_now();
347+
stress_bad_ioctl_itimer_set(IOCTL_TIMEOUT_US);
322348
VOID_RET(int, ioctl(fd, _IOR(type, nr, uint64_t), buf64));
323349
if (stress_time_now() - t_start > threshold) {
324350
(void)close(fd);
325351
break;
326352
}
327353

354+
t_start = stress_time_now();
355+
stress_bad_ioctl_itimer_set(IOCTL_TIMEOUT_US);
328356
VOID_RET(int, ioctl(fd, _IOR(type, nr, uint32_t), buf32));
329357
if (stress_time_now() - t_start > threshold) {
330358
(void)close(fd);
331359
break;
332360
}
333361

362+
t_start = stress_time_now();
363+
stress_bad_ioctl_itimer_set(IOCTL_TIMEOUT_US);
334364
VOID_RET(int, ioctl(fd, _IOR(type, nr, uint16_t), buf16));
335365
if (stress_time_now() - t_start > threshold) {
336366
(void)close(fd);
337367
break;
338368
}
339369

370+
t_start = stress_time_now();
371+
stress_bad_ioctl_itimer_set(IOCTL_TIMEOUT_US);
340372
VOID_RET(int, ioctl(fd, _IOR(type, nr, uint8_t), buf8));
341373
if (stress_time_now() - t_start > threshold) {
342374
(void)close(fd);
343375
break;
344376
}
345377

378+
t_start = stress_time_now();
379+
stress_bad_ioctl_itimer_set(IOCTL_TIMEOUT_US);
346380
VOID_RET(int, ioctl(fd, _IOR(type, nr, stress_4k_page_t), buf));
347381
if (stress_time_now() - t_start > threshold) {
348382
(void)close(fd);
349383
break;
350384
}
351385

386+
t_start = stress_time_now();
387+
stress_bad_ioctl_itimer_set(IOCTL_TIMEOUT_US);
352388
VOID_RET(int, ioctl(fd, _IOR(type, nr, uint64_t), NULL));
353389
if (stress_time_now() - t_start > threshold) {
354390
(void)close(fd);
355391
break;
356392
}
357393

394+
t_start = stress_time_now();
395+
stress_bad_ioctl_itimer_set(IOCTL_TIMEOUT_US);
358396
VOID_RET(int, ioctl(fd, _IOR(type, nr, uint32_t), NULL));
359397
if (stress_time_now() - t_start > threshold) {
360398
(void)close(fd);
361399
break;
362400
}
363401

402+
t_start = stress_time_now();
403+
stress_bad_ioctl_itimer_set(IOCTL_TIMEOUT_US);
364404
VOID_RET(int, ioctl(fd, _IOR(type, nr, uint16_t), NULL));
365405
if (stress_time_now() - t_start > threshold) {
366406
(void)close(fd);
367407
break;
368408
}
369409

410+
t_start = stress_time_now();
411+
stress_bad_ioctl_itimer_set(IOCTL_TIMEOUT_US);
370412
VOID_RET(int, ioctl(fd, _IOR(type, nr, uint8_t), NULL));
371413
if (stress_time_now() - t_start > threshold) {
372414
(void)close(fd);
373415
break;
374416
}
375417

418+
t_start = stress_time_now();
419+
stress_bad_ioctl_itimer_set(IOCTL_TIMEOUT_US);
376420
VOID_RET(int, ioctl(fd, _IOR(type, nr, uint64_t), args->mapped->page_none));
377421
if (stress_time_now() - t_start > threshold) {
378422
(void)close(fd);
379423
break;
380424
}
381425

426+
t_start = stress_time_now();
427+
stress_bad_ioctl_itimer_set(IOCTL_TIMEOUT_US);
382428
VOID_RET(int, ioctl(fd, _IOR(type, nr, uint32_t), args->mapped->page_none));
383429
if (stress_time_now() - t_start > threshold) {
384430
(void)close(fd);
385431
break;
386432
}
387433

434+
t_start = stress_time_now();
435+
stress_bad_ioctl_itimer_set(IOCTL_TIMEOUT_US);
388436
VOID_RET(int, ioctl(fd, _IOR(type, nr, uint16_t), args->mapped->page_none));
389437
if (stress_time_now() - t_start > threshold) {
390438
(void)close(fd);
391439
break;
392440
}
393441

442+
t_start = stress_time_now();
443+
stress_bad_ioctl_itimer_set(IOCTL_TIMEOUT_US);
394444
VOID_RET(int, ioctl(fd, _IOR(type, nr, uint8_t), args->mapped->page_none));
395445
if (stress_time_now() - t_start > threshold) {
396446
(void)close(fd);
397447
break;
398448
}
399449

450+
t_start = stress_time_now();
451+
stress_bad_ioctl_itimer_set(IOCTL_TIMEOUT_US);
400452
VOID_RET(int, ioctl(fd, _IOR(type, nr, uint32_t), args->mapped->page_ro));
401453
if (stress_time_now() - t_start > threshold) {
402454
(void)close(fd);
403455
break;
404456
}
405457

458+
t_start = stress_time_now();
459+
stress_bad_ioctl_itimer_set(IOCTL_TIMEOUT_US);
406460
VOID_RET(int, ioctl(fd, _IOR(type, nr, uint16_t), args->mapped->page_ro));
407461
if (stress_time_now() - t_start > threshold) {
408462
(void)close(fd);
409463
break;
410464
}
411465

466+
t_start = stress_time_now();
467+
stress_bad_ioctl_itimer_set(IOCTL_TIMEOUT_US);
412468
VOID_RET(int, ioctl(fd, _IOR(type, nr, uint8_t), args->mapped->page_ro));
413469
if (stress_time_now() - t_start > threshold) {
414470
(void)close(fd);
415471
break;
416472
}
417473

418474
#if defined(_IOW)
475+
t_start = stress_time_now();
476+
stress_bad_ioctl_itimer_set(IOCTL_TIMEOUT_US);
419477
VOID_RET(int, ioctl(fd, _IOW(type, nr, uint64_t), args->mapped->page_none));
420478
if (stress_time_now() - t_start > threshold) {
421479
(void)close(fd);
422480
break;
423481
}
424482

483+
t_start = stress_time_now();
484+
stress_bad_ioctl_itimer_set(IOCTL_TIMEOUT_US);
425485
VOID_RET(int, ioctl(fd, _IOW(type, nr, uint32_t), args->mapped->page_none));
426486
if (stress_time_now() - t_start > threshold) {
427487
(void)close(fd);
428488
break;
429489
}
430490

491+
t_start = stress_time_now();
492+
stress_bad_ioctl_itimer_set(IOCTL_TIMEOUT_US);
431493
VOID_RET(int, ioctl(fd, _IOW(type, nr, uint16_t), args->mapped->page_none));
432494
if (stress_time_now() - t_start > threshold) {
433495
(void)close(fd);
434496
break;
435497
}
436498

499+
t_start = stress_time_now();
500+
stress_bad_ioctl_itimer_set(IOCTL_TIMEOUT_US);
437501
VOID_RET(int, ioctl(fd, _IOW(type, nr, uint8_t), args->mapped->page_none));
438502
if (stress_time_now() - t_start > threshold) {
439503
(void)close(fd);
@@ -442,6 +506,8 @@ static inline void stress_bad_ioctl_rw(
442506
#endif
443507

444508
(void)close(fd);
509+
stress_bad_ioctl_itimer_set(0);
510+
445511
if (thread_index < MAX_DEV_THREADS) {
446512
ret = stress_lock_acquire(node_lock);
447513
if (ret)
@@ -451,6 +517,7 @@ static inline void stress_bad_ioctl_rw(
451517
}
452518
} while (is_pthread);
453519

520+
stress_bad_ioctl_itimer_set(0);
454521
(void)munmap((void *)buf, page_size);
455522
}
456523

@@ -574,13 +641,17 @@ static int stress_bad_ioctl(stress_args_t *args)
574641

575642
node_lock = NULL;
576643
dev_ioctl_info_head = NULL;
644+
dev_ioctl_info_count = 0;
577645
dev_ioctl_node = NULL;
578646

579647
(void)stress_setting_get("bad-ioctl-method", &bad_ioctl_method);
580648

581649
stress_bad_ioctl_dev_dir(args, "/dev", 0);
582650
dev_ioctl_node = dev_ioctl_info_head;
583651

652+
if (stress_instance_zero(args))
653+
pr_inf("%s: %zu unique devices being exercised with ioctl calls\n", args->name, dev_ioctl_info_count);
654+
584655
stress_proc_state_set(args->name, STRESS_STATE_SYNC_WAIT);
585656
stress_sync_start_wait(args);
586657
stress_proc_state_set(args->name, STRESS_STATE_RUN);
@@ -622,14 +693,22 @@ static int stress_bad_ioctl(stress_args_t *args)
622693
uint32_t offset;
623694

624695
stress_proc_state_set(args->name, STRESS_STATE_RUN);
696+
697+
stress_bad_ioctl_itimer_set(0);
698+
625699
ssjret = sigsetjmp(jmp_env, 1);
626700
if (ssjret != 0) {
627701
pr_fail("%s: caught an unexpected segmentation fault\n", args->name);
628702
_exit(EXIT_FAILURE);
629703
}
630704

631-
if (stress_signal_handler(args->name, SIGSEGV, stress_segv_handler, NULL) < 0)
705+
if (stress_signal_handler(args->name, SIGSEGV, stress_sig_handler, NULL) < 0)
706+
_exit(EXIT_NO_RESOURCE);
707+
#if defined(HAVE_SETITIMER) && \
708+
defined(SIGPROF)
709+
if (stress_signal_handler(args->name, SIGPROF, stress_sig_handler, NULL) < 0)
632710
_exit(EXIT_NO_RESOURCE);
711+
#endif
633712

634713
stress_make_it_fail_set();
635714
stress_parent_died_alarm();
@@ -672,6 +751,7 @@ static int stress_bad_ioctl(stress_args_t *args)
672751
(void)pthread_join(threads[i].pthread, NULL);
673752
}
674753
(void)stress_lock_destroy(node_lock);
754+
675755
_exit(EXIT_SUCCESS);
676756
}
677757
} while (stress_continue(args));

0 commit comments

Comments
 (0)