1 /*
2 * Copyright (C) 2013-2021 Canonical, Ltd.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 *
18 * This code is a complete clean re-write of the stress tool by
19 * Colin Ian King <colin.king@canonical.com> and attempts to be
20 * backwardly compatible with the stress tool by Amos Waterland
21 * <apw@rossby.metr.ou.edu> but has more stress tests and more
22 * functionality.
23 *
24 */
25 #include "stress-ng.h"
26
27 static const stress_help_t help[] = {
28 { NULL, "dev N", "start N device entry thrashing stressors" },
29 { NULL, "dev-ops N", "stop after N device thrashing bogo ops" },
30 { NULL, "dev-file name","specify the /dev/ file to exercise" },
31 { NULL, NULL, NULL }
32 };
33
stress_set_dev_file(const char * opt)34 static int stress_set_dev_file(const char *opt)
35 {
36 return stress_set_setting("dev-file", TYPE_ID_STR, opt);
37 }
38
39 static const stress_opt_set_func_t opt_set_funcs[] = {
40 { OPT_dev_file, stress_set_dev_file },
41 { 0, NULL },
42 };
43
44 #if defined(HAVE_POLL_H) && \
45 defined(HAVE_LIB_PTHREAD) && \
46 !defined(__sun__) && \
47 !defined(__HAIKU__)
48
49 #define STRESS_DEV_THREADS_MAX (4)
50 #define STRESS_DEV_OPEN_TRIES_MAX (8)
51 #define STRESS_DEV_HASH_SIZE (113)
52
53 typedef struct stress_dev_func {
54 const char *devpath;
55 const size_t devpath_len;
56 void (*func)(const stress_args_t *args, const int fd, const char *devpath);
57 } stress_dev_func_t;
58
59 typedef struct stress_dev_hash_info {
60 char *dev_path; /* Device driver path */
61 struct stress_dev_hash_info *next; /* Next one in hash list */
62 bool open_fail; /* True if failed to open */
63 bool open_ok; /* True if open OK */
64 bool is_scsi; /* True if SCSI device */
65 } stress_dev_hash_info_t;
66
67 static sigset_t set;
68 static shim_pthread_spinlock_t lock;
69 static shim_pthread_spinlock_t parport_lock;
70 static stress_dev_hash_info_t *stress_dev_hash_info;
71 static stress_dev_hash_info_t *stress_dev_hash[STRESS_DEV_HASH_SIZE];
72
73 /*
74 * linux_xen_guest()
75 * return true if stress-ng is running
76 * as a Linux Xen guest.
77 */
linux_xen_guest(void)78 static bool linux_xen_guest(void)
79 {
80 #if defined(__linux__)
81 static bool xen_guest = false;
82 static bool xen_guest_cached = false;
83 struct stat statbuf;
84 int ret;
85 DIR *dp;
86 struct dirent *de;
87
88 if (xen_guest_cached)
89 return xen_guest;
90
91 /*
92 * The features file is a good indicator for a Xen guest
93 */
94 ret = stat("/sys/hypervisor/properties/features", &statbuf);
95 if (ret == 0) {
96 xen_guest = true;
97 goto done;
98 }
99 if (errno == EACCES) {
100 xen_guest = true;
101 goto done;
102 }
103
104 /*
105 * Non-dot files in /sys/bus/xen/devices indicate a Xen guest too
106 */
107 dp = opendir("/sys/bus/xen/devices");
108 if (dp) {
109 while ((de = readdir(dp)) != NULL) {
110 if (de->d_name[0] != '.') {
111 xen_guest = true;
112 break;
113 }
114 }
115 (void)closedir(dp);
116 if (xen_guest)
117 goto done;
118 }
119
120 /*
121 * At this point Xen is being sneaky and pretending, so
122 * apart from inspecting dmesg (which may not be possible),
123 * assume it's not a Xen hosted guest.
124 */
125 xen_guest = false;
126 done:
127 xen_guest_cached = true;
128
129 return xen_guest;
130 #else
131 return false;
132 #endif
133 }
134
135 /*
136 * stress_dev_new()
137 * add a new device path to hash
138 */
stress_dev_new(const char * dev_path)139 static stress_dev_hash_info_t *stress_dev_new(const char *dev_path)
140 {
141 stress_dev_hash_info_t *dev_hash_info;
142 const uint32_t hash = stress_hash_pjw(dev_path) % STRESS_DEV_HASH_SIZE;
143 dev_hash_info = stress_dev_hash[hash];
144
145 while (dev_hash_info) {
146 if (!strcmp(dev_path, dev_hash_info->dev_path))
147 return dev_hash_info;
148 dev_hash_info = dev_hash_info->next;
149 }
150
151 dev_hash_info = calloc(1, sizeof(*dev_hash_info));
152 dev_hash_info->dev_path = strdup(dev_path);
153 if (!dev_hash_info->dev_path) {
154 free(dev_hash_info);
155 return NULL;
156 }
157 dev_hash_info->open_fail = false;
158 dev_hash_info->open_ok = false;
159 dev_hash_info->is_scsi = false;
160
161 dev_hash_info->next = stress_dev_hash[hash];
162 stress_dev_hash[hash] = dev_hash_info;
163
164 return dev_hash_info;
165 }
166
167 /*
168 * stress_free()
169 * free tree
170 */
stress_dev_free(void)171 static void stress_dev_free(void)
172 {
173 size_t i;
174
175 for (i = 0; i < STRESS_DEV_HASH_SIZE; i++) {
176 stress_dev_hash_info_t *dev_hash_info = stress_dev_hash[i];
177
178 while (dev_hash_info) {
179 stress_dev_hash_info_t *next = dev_hash_info->next;
180
181 free(dev_hash_info->dev_path);
182 free(dev_hash_info);
183 dev_hash_info = next;
184 }
185 }
186 }
187
188 /*
189 * stress_dev_dir()
190 * read dev directory, add device information to tree
191 */
stress_dev_dir(const stress_args_t * args,const char * path,const int depth,const char * tty_name)192 static void stress_dev_dir(
193 const stress_args_t *args,
194 const char *path,
195 const int depth,
196 const char *tty_name)
197 {
198 struct dirent **dlist;
199 const mode_t flags = S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
200 int i, n;
201
202 if (!keep_stressing_flag())
203 return;
204
205 /* Don't want to go too deep */
206 if (depth > 20)
207 return;
208
209 dlist = NULL;
210 n = scandir(path, &dlist, NULL, alphasort);
211 if (n <= 0)
212 goto done;
213
214 for (i = 0; i < n; i++) {
215 int ret;
216 struct stat buf;
217 char tmp[PATH_MAX];
218 struct dirent *d = dlist[i];
219 size_t len;
220
221 if (!keep_stressing(args))
222 break;
223 if (stress_is_dot_filename(d->d_name))
224 continue;
225 /*
226 * Avoid https://bugs.xenserver.org/browse/XSO-809
227 * see: LP#1741409, so avoid opening /dev/hpet
228 */
229 if (!strcmp(d->d_name, "hpet") && linux_xen_guest())
230 continue;
231 if (!strncmp(d->d_name, "ttyS", 4))
232 continue;
233
234 len = strlen(d->d_name);
235
236 /*
237 * Exercise no more than 3 of the same device
238 * driver, e.g. ttyS0..ttyS1
239 */
240 if (len > 1) {
241 int dev_n;
242 char *ptr = d->d_name + len - 1;
243
244 while (ptr > d->d_name && isdigit((int)*ptr))
245 ptr--;
246 ptr++;
247 dev_n = atoi(ptr);
248 if (dev_n > 2)
249 continue;
250 }
251
252 (void)stress_mk_filename(tmp, sizeof(tmp), path, d->d_name);
253 /*
254 * Avoid any actions on owner's tty
255 */
256 if (tty_name && !strcmp(tty_name, tmp))
257 continue;
258
259 (void)stress_mk_filename(tmp, sizeof(tmp), path, d->d_name);
260 switch (d->d_type) {
261 case DT_DIR:
262 ret = stat(tmp, &buf);
263 if (ret < 0)
264 continue;
265 if ((buf.st_mode & flags) == 0)
266 continue;
267 stress_dev_dir(args, tmp, depth + 1, tty_name);
268 break;
269 case DT_BLK:
270 case DT_CHR:
271 if (strstr(tmp, "watchdog"))
272 continue;
273 stress_dev_new(tmp);
274 break;
275 default:
276 break;
277 }
278 }
279 done:
280 stress_dirent_list_free(dlist, n);
281 }
282
283 /*
284 * ioctl_set_timeout()
285 * set a itimer to interrupt ioctl call after secs seconds
286 */
ioctl_set_timeout(const double secs)287 static void ioctl_set_timeout(const double secs)
288 {
289 #if defined(ITIMER_REAL)
290 if (secs > 0.0) {
291 struct itimerval it;
292 int ret;
293 time_t tsecs = (time_t)secs;
294
295 it.it_interval.tv_sec = (time_t)secs;
296 it.it_interval.tv_usec = (suseconds_t)(1000000.0 * (secs - (double)tsecs));
297 it.it_value.tv_sec = it.it_interval.tv_sec;
298 it.it_value.tv_usec = it.it_interval.tv_usec;
299 ret = setitimer(ITIMER_REAL, &it, NULL);
300 (void)ret;
301 }
302 #else
303 (void)secs;
304 #endif
305 }
306
307 /*
308 * ioctl_clr_timeout()
309 * clear itimer ioctl timeout alarm
310 */
ioctl_clr_timeout(void)311 static void ioctl_clr_timeout(void)
312 {
313 #if defined(ITIMER_REAL)
314 struct itimerval it;
315 int ret;
316
317 (void)memset(&it, 0, sizeof(it));
318 ret = setitimer(ITIMER_REAL, &it, NULL);
319 (void)ret;
320 #endif
321 }
322
323 /*
324 * IOCTL_TIMEOUT()
325 * execute code, if time taken is > secs then
326 * execute the action. Note there are limitations
327 * to the code that can be passed into the macro,
328 * variable declarations must be one variable at a
329 * time without any commas
330 */
331 #define IOCTL_TIMEOUT(secs, code, action) \
332 do { \
333 static bool timed_out_ = false; \
334 double timeout_t_ = stress_time_now(); \
335 \
336 if (!timed_out_) { \
337 ioctl_set_timeout(secs); \
338 code \
339 ioctl_clr_timeout(); \
340 } \
341 if (stress_time_now() >= timeout_t_ + secs) { \
342 timed_out_ = true; \
343 action; \
344 } \
345 } while (0)
346
347
348 #if defined(__linux__) && \
349 defined(HAVE_LINUX_MEDIA_H) && \
350 defined(MEDIA_IOC_DEVICE_INFO)
stress_dev_media_linux(const stress_args_t * args,const int fd,const char * devpath)351 static void stress_dev_media_linux(
352 const stress_args_t *args,
353 const int fd,
354 const char *devpath)
355 {
356 (void)args;
357 (void)fd;
358 (void)devpath;
359
360 #if defined(MEDIA_IOC_DEVICE_INFO) && \
361 defined(HAVE_MEDIA_DEVICE_INFO)
362 {
363 struct media_device_info mdi;
364 int ret;
365
366 ret = ioctl(fd, MEDIA_IOC_DEVICE_INFO, &mdi);
367 if (ret < 0)
368 return;
369
370 if (!mdi.driver[0])
371 pr_inf("%s: ioctl MEDIA_IOC_DEVICE_INFO %s: null driver name\n",
372 args->name, devpath);
373 if (!mdi.model[0])
374 pr_inf("%s: ioctl MEDIA_IOC_DEVICE_INFO %s: null model name\n",
375 args->name, devpath);
376 if (!mdi.bus_info[0])
377 pr_inf("%s: ioctl MEDIA_IOC_DEVICE_INFO %s: null bus_info field\n",
378 args->name, devpath);
379 }
380 #endif
381 }
382 #endif
383
384 #if defined(HAVE_LINUX_VT_H)
stress_dev_vcs_linux(const stress_args_t * args,const int fd,const char * devpath)385 static void stress_dev_vcs_linux(
386 const stress_args_t *args,
387 const int fd,
388 const char *devpath)
389 {
390 (void)args;
391 (void)fd;
392 (void)devpath;
393
394 #if defined(VT_GETMODE) && \
395 defined(HAVE_VT_MODE)
396 {
397 struct vt_mode mode;
398 int ret;
399
400 ret = ioctl(fd, VT_GETMODE, &mode);
401 (void)ret;
402 }
403 #endif
404 #if defined(VT_GETSTATE) && \
405 defined(HAVE_VT_STAT)
406 {
407 struct vt_stat vt_stat;
408 int ret;
409
410 ret = ioctl(fd, VT_GETSTATE, &vt_stat);
411 (void)ret;
412 }
413 #endif
414 }
415 #endif
416
417 #if defined(HAVE_LINUX_DM_IOCTL_H)
stress_dev_dm_linux(const stress_args_t * args,const int fd,const char * devpath)418 static void stress_dev_dm_linux(
419 const stress_args_t *args,
420 const int fd,
421 const char *devpath)
422 {
423 (void)args;
424 (void)fd;
425 (void)devpath;
426
427 #if defined(DM_VERSION) && \
428 defined(HAVE_DM_IOCTL)
429 {
430 struct dm_ioctl dm;
431 int ret;
432
433 ret = ioctl(fd, DM_VERSION, &dm);
434 (void)ret;
435 }
436 #endif
437 #if defined(DM_STATUS) && \
438 defined(HAVE_DM_IOCTL)
439 {
440 struct dm_ioctl dm;
441 int ret;
442
443 ret = ioctl(fd, DM_STATUS, &dm);
444 (void)ret;
445 }
446 #endif
447 }
448 #endif
449
450 #if defined(HAVE_LINUX_VIDEODEV2_H)
stress_dev_video_linux(const stress_args_t * args,const int fd,const char * devpath)451 static void stress_dev_video_linux(
452 const stress_args_t *args,
453 const int fd,
454 const char *devpath)
455 {
456 (void)args;
457 (void)fd;
458 (void)devpath;
459
460 #if defined(VIDIOC_QUERYCAP) && \
461 defined(HAVE_V4L2_CAPABILITY)
462 {
463 struct v4l2_capability c;
464 int ret;
465
466 (void)memset(&c, 0, sizeof(c));
467 ret = ioctl(fd, VIDIOC_QUERYCAP, &c);
468 (void)ret;
469 }
470 #endif
471 #if defined(VIDIOC_G_FBUF) && \
472 defined(HAVE_V4L2_FRAMEBUFFER)
473 {
474 struct v4l2_framebuffer f;
475 int ret;
476
477 (void)memset(&f, 0, sizeof(f));
478 ret = ioctl(fd, VIDIOC_G_FBUF, &f);
479 (void)ret;
480 }
481 #endif
482 #if defined(VIDIOC_G_STD) && \
483 defined(HAVE_V4L2_STD_ID)
484 {
485 v4l2_std_id id;
486 int ret;
487
488 (void)memset(&id, 0, sizeof(id));
489 ret = ioctl(fd, VIDIOC_G_STD, &id);
490 (void)ret;
491 }
492 #endif
493 #if defined(VIDIOC_G_AUDIO) && \
494 defined(HAVE_V4L2_AUDIO)
495 {
496 struct v4l2_audio a;
497 int ret;
498
499 (void)memset(&a, 0, sizeof(a));
500 ret = ioctl(fd, VIDIOC_G_AUDIO, &a);
501 (void)ret;
502 }
503 #endif
504 #if defined(VIDIOC_G_INPUT)
505 {
506 int in = 0, ret;
507
508 ret = ioctl(fd, VIDIOC_G_INPUT, &in);
509 (void)ret;
510 }
511 #endif
512 #if defined(VIDIOC_G_OUTPUT)
513 {
514 int in = 0, ret;
515
516 ret = ioctl(fd, VIDIOC_G_OUTPUT, &in);
517 (void)ret;
518 }
519 #endif
520 #if defined(VIDIOC_G_AUDOUT) && \
521 defined(HAVE_V4L2_AUDIOOUT)
522 {
523 struct v4l2_audioout a;
524 int ret;
525
526 (void)memset(&a, 0, sizeof(a));
527 ret = ioctl(fd, VIDIOC_G_AUDOUT, &a);
528 (void)ret;
529 }
530 #endif
531 #if defined(VIDIOC_G_JPEGCOMP) && \
532 defined(HAVE_V4L2_JPEGCOMPRESSION)
533 {
534 struct v4l2_jpegcompression a;
535 int ret;
536
537 (void)memset(&a, 0, sizeof(a));
538 ret = ioctl(fd, VIDIOC_G_JPEGCOMP, &a);
539 (void)ret;
540 }
541 #endif
542 #if defined(VIDIOC_QUERYSTD) && \
543 defined(HAVE_V4L2_STD_ID)
544 {
545 v4l2_std_id a;
546 int ret;
547
548 (void)memset(&a, 0, sizeof(a));
549 ret = ioctl(fd, VIDIOC_QUERYSTD, &a);
550 (void)ret;
551 }
552 #endif
553 #if defined(VIDIOC_G_PRIORITY)
554 {
555 uint32_t a;
556 int ret;
557
558 ret = ioctl(fd, VIDIOC_G_PRIORITY, &a);
559 (void)ret;
560 }
561 #endif
562 #if defined(VIDIOC_G_ENC_INDEX) && \
563 defined(HAVE_V4L2_ENC_IDX)
564 {
565 struct v4l2_enc_idx a;
566 int ret;
567
568 (void)memset(&a, 0, sizeof(a));
569 ret = ioctl(fd, VIDIOC_G_ENC_INDEX, &a);
570 (void)ret;
571 }
572 #endif
573 #if defined(VIDIOC_QUERY_DV_TIMINGS) && \
574 defined(HAVE_V4L2_DV_TIMINGS)
575 {
576 struct v4l2_dv_timings a;
577 int ret;
578
579 (void)memset(&a, 0, sizeof(a));
580 ret = ioctl(fd, VIDIOC_QUERY_DV_TIMINGS, &a);
581 (void)ret;
582 }
583 #endif
584 }
585 #endif
586
587 #if defined(HAVE_TERMIOS_H) && \
588 defined(TCGETS) && \
589 defined(HAVE_TERMIOS)
stress_dev_tty(const stress_args_t * args,const int fd,const char * devpath)590 static void stress_dev_tty(
591 const stress_args_t *args,
592 const int fd,
593 const char *devpath)
594 {
595 int ret;
596 struct termios t;
597
598 (void)args;
599 (void)devpath;
600
601 if (!isatty(fd))
602 return;
603
604 ret = tcgetattr(fd, &t);
605 (void)ret;
606 #if defined(TCGETS)
607 {
608 ret = ioctl(fd, TCGETS, &t);
609 #if defined(TCSETS)
610 if (ret == 0) {
611 ret = ioctl(fd, TCSETS, &t);
612 }
613 #endif
614 (void)ret;
615 }
616 #endif
617 #if defined(TIOCGPTLCK)
618 {
619 int lck;
620
621 ret = ioctl(fd, TIOCGPTLCK, &lck);
622 #if defined(TIOCSPTLCK)
623 if (ret == 0) {
624 ret = ioctl(fd, TIOCSPTLCK, &lck);
625 }
626 #endif
627 (void)ret;
628 }
629 #endif
630 #if defined(TIOCGPKT)
631 {
632 int pktmode;
633
634 ret = ioctl(fd, TIOCGPKT, &pktmode);
635 #if defined(TIOCPKT)
636 if (ret == 0) {
637 ret = ioctl(fd, TIOCPKT, &pktmode);
638 }
639 #endif
640 (void)ret;
641 }
642 #endif
643 #if defined(TIOCGPTN)
644 {
645 int ptnum;
646
647 ret = ioctl(fd, TIOCGPTN, &ptnum);
648 (void)ret;
649 }
650 #endif
651 #if defined(TIOCSIG) && \
652 defined(SIGCONT)
653 {
654 int sig = SIGCONT;
655
656 /* generally causes EINVAL */
657 ret = ioctl(fd, TIOCSIG, &sig);
658 (void)ret;
659 }
660 #endif
661 #if defined(TIOCGWINSZ) && \
662 defined(HAVE_WINSIZE)
663 {
664 struct winsize ws;
665
666 ret = ioctl(fd, TIOCGWINSZ, &ws);
667 #if defined(TIOCSWINSZ)
668 if (ret == 0) {
669 ret = ioctl(fd, TIOCSWINSZ, &ws);
670 }
671 #endif
672 (void)ret;
673 }
674 #endif
675 #if defined(FIONREAD)
676 {
677 int n;
678
679 ret = ioctl(fd, FIONREAD, &n);
680 (void)ret;
681 }
682 #endif
683 #if defined(TIOCINQ)
684 {
685 int n;
686
687 ret = ioctl(fd, TIOCINQ, &n);
688 (void)ret;
689 }
690 #endif
691 #if defined(TIOCOUTQ)
692 {
693 int n;
694
695 ret = ioctl(fd, TIOCOUTQ, &n);
696 (void)ret;
697 }
698 #endif
699 #if defined(TIOCGPGRP)
700 {
701 pid_t pgrp;
702
703 ret = ioctl(fd, TIOCGPGRP, &pgrp);
704 #if defined(TIOCSPGRP)
705 if (ret == 0) {
706 ret = ioctl(fd, TIOCSPGRP, &pgrp);
707 }
708 #endif
709 (void)ret;
710 }
711 #endif
712 #if defined(TIOCGSID)
713 {
714 pid_t gsid;
715
716 ret = ioctl(fd, TIOCGSID, &gsid);
717 (void)ret;
718 }
719 #endif
720 #if defined(TIOCGEXCL)
721 {
722 int excl;
723
724 ret = ioctl(fd, TIOCGEXCL, &excl);
725 if (ret == 0) {
726 #if defined(TIOCNXCL) && \
727 defined(TIOCEXCL)
728 if (excl) {
729 ret = ioctl(fd, TIOCNXCL, NULL);
730 (void)ret;
731 ret = ioctl(fd, TIOCEXCL, NULL);
732 } else {
733 ret = ioctl(fd, TIOCEXCL, NULL);
734 (void)ret;
735 ret = ioctl(fd, TIOCNXCL, NULL);
736 }
737 #endif
738 }
739 (void)ret;
740 }
741 #endif
742 /*
743 * On some older 3.13 kernels this can lock up, need to add
744 * a method to detect and skip this somehow. For the moment
745 * disable this stress test.
746 */
747 #if defined(TIOCGETD) && 0
748 {
749 int ldis;
750
751 ret = ioctl(fd, TIOCGETD, &ldis);
752 #if defined(TIOCSETD)
753 if (ret == 0) {
754 ret = ioctl(fd, TIOCSETD, &ldis);
755 }
756 #endif
757 (void)ret;
758 }
759 #endif
760
761 #if defined(TIOCGPTPEER)
762 {
763 ret = ioctl(fd, TIOCGPTPEER, O_RDWR);
764 (void)ret;
765 }
766 #endif
767
768 #if defined(TCOOFF) && \
769 defined(TCOON)
770 {
771 ret = ioctl(fd, TCOOFF, 0);
772 if (ret == 0)
773 ret = ioctl(fd, TCOON, 0);
774 (void)ret;
775 }
776 #endif
777
778 #if defined(TCIOFF) && \
779 defined(TCION)
780 {
781 ret = ioctl(fd, TCIOFF, 0);
782 if (ret == 0)
783 ret = ioctl(fd, TCION, 0);
784 (void)ret;
785 }
786 #endif
787
788 /* Modem */
789 #if defined(TIOCGSOFTCAR)
790 {
791 int flag;
792
793 ret = ioctl(fd, TIOCGSOFTCAR, &flag);
794 #if defined(TIOCSSOFTCAR)
795 if (ret == 0) {
796 ret = ioctl(fd, TIOCSSOFTCAR, &flag);
797 }
798 #endif
799 (void)ret;
800 }
801 #endif
802
803 #if defined(KDGETLED)
804 {
805 char state;
806
807 ret = ioctl(fd, KDGETLED, &state);
808 (void)ret;
809 }
810 #endif
811
812 #if defined(KDGKBTYPE)
813 {
814 char type;
815
816 ret = ioctl(fd, KDGKBTYPE, &type);
817 (void)ret;
818 }
819 #endif
820
821 #if defined(KDGETMODE)
822 {
823 int mode;
824
825 ret = ioctl(fd, KDGETMODE, &mode);
826 (void)ret;
827 }
828 #endif
829
830 #if defined(KDGKBMODE)
831 {
832 long mode;
833
834 ret = ioctl(fd, KDGKBMODE, &mode);
835 (void)ret;
836 }
837 #endif
838
839 #if defined(KDGKBMETA)
840 {
841 long mode;
842
843 ret = ioctl(fd, KDGKBMETA, &mode);
844 (void)ret;
845 }
846 #endif
847 #if defined(TIOCMGET)
848 {
849 int status;
850
851 ret = ioctl(fd, TIOCMGET, &status);
852 #if defined(TIOCMSET)
853 if (ret == 0) {
854 #if defined(TIOCMBIC)
855 ret = ioctl(fd, TIOCMBIC, &status);
856 (void)ret;
857 #endif
858 #if defined(TIOCMBIS)
859 ret = ioctl(fd, TIOCMBIS, &status);
860 (void)ret;
861 #endif
862 ret = ioctl(fd, TIOCMSET, &status);
863 }
864 #endif
865 (void)ret;
866 }
867 #endif
868 #if defined(TIOCGICOUNT) && \
869 defined(HAVE_LINUX_SERIAL_H) && \
870 defined(HAVE_SERIAL_ICOUNTER)
871 {
872 struct serial_icounter_struct counter;
873
874 ret = ioctl(fd, TIOCGICOUNT, &counter);
875 (void)ret;
876 }
877 #endif
878 #if defined(TIOCGSERIAL) && \
879 defined(HAVE_LINUX_SERIAL_H) && \
880 defined(HAVE_SERIAL_STRUCT)
881 {
882 struct serial_struct serial;
883
884 ret = ioctl(fd, TIOCGSERIAL, &serial);
885 #if defined(TIOCSSERIAL)
886 if (ret == 0)
887 ret = ioctl(fd, TIOCSSERIAL, &serial);
888 #endif
889 (void)ret;
890 }
891 #endif
892
893 #if defined(HAVE_SHIM_TERMIOS2) && \
894 defined(TCGETS2)
895 {
896 #define termios2 shim_termios2
897 struct termios2 t2;
898
899 ret = ioctl(fd, TCGETS2, &t2);
900 (void)ret;
901 #if defined(TCSETS2) || \
902 defined(TCSETSW2) || \
903 defined(TCSETSF2)
904 if (ret == 0) {
905 #if defined(TCSETSF2)
906 ret = ioctl(fd, TCSETSF2, &t2);
907 (void)ret;
908 #endif
909 #if defined(TCSETSW2)
910 ret = ioctl(fd, TCSETSW2, &t2);
911 (void)ret;
912 #endif
913 #if defined(TCSETS2)
914 ret = ioctl(fd, TCSETS2, &t2);
915 (void)ret;
916 #endif
917 }
918 #endif
919 }
920 #endif
921 }
922 #endif
923
924 /*
925 * stress_dev_blk()
926 * block device specific ioctls
927 */
stress_dev_blk(const stress_args_t * args,const int fd,const char * devpath)928 static void stress_dev_blk(
929 const stress_args_t *args,
930 const int fd,
931 const char *devpath)
932 {
933 off_t offset;
934
935 (void)args;
936 (void)fd;
937 (void)devpath;
938
939 #if defined(BLKFLSBUF)
940 {
941 int ret;
942 ret = ioctl(fd, BLKFLSBUF, 0);
943 (void)ret;
944 }
945 #endif
946 #if defined(BLKRAGET)
947 /* readahead */
948 {
949 unsigned long ra;
950 int ret;
951
952 ret = ioctl(fd, BLKRAGET, &ra);
953 (void)ret;
954 }
955 #endif
956 #if defined(BLKROGET)
957 /* readonly state */
958 {
959 int ret, ro;
960
961 ret = ioctl(fd, BLKROGET, &ro);
962 (void)ret;
963 }
964 #endif
965 #if defined(BLKBSZGET)
966 /* get block device soft block size */
967 {
968 int ret, sz;
969
970 ret = ioctl(fd, BLKBSZGET, &sz);
971 (void)ret;
972 }
973 #endif
974 #if defined(BLKPBSZGET)
975 /* get block device physical block size */
976 {
977 unsigned int sz;
978 int ret;
979
980 ret = ioctl(fd, BLKPBSZGET, &sz);
981 (void)ret;
982 }
983 #endif
984 #if defined(BLKIOMIN)
985 {
986 unsigned int sz;
987 int ret;
988
989 ret = ioctl(fd, BLKIOMIN, &sz);
990 (void)ret;
991 }
992 #endif
993 #if defined(BLKIOOPT)
994 {
995 unsigned int sz;
996 int ret;
997
998 ret = ioctl(fd, BLKIOOPT, &sz);
999 (void)ret;
1000 }
1001 #endif
1002 #if defined(BLKALIGNOFF)
1003 {
1004 unsigned int sz;
1005 int ret;
1006
1007 ret = ioctl(fd, BLKALIGNOFF, &sz);
1008 (void)ret;
1009 }
1010 #endif
1011 #if defined(BLKROTATIONAL)
1012 {
1013 unsigned short rotational;
1014 int ret;
1015
1016 ret = ioctl(fd, BLKROTATIONAL, &rotational);
1017 (void)ret;
1018 }
1019 #endif
1020 #if defined(BLKSECTGET)
1021 {
1022 unsigned short max_sectors;
1023 int ret;
1024
1025 ret = ioctl(fd, BLKSECTGET, &max_sectors);
1026 (void)ret;
1027 }
1028 #endif
1029 #if defined(BLKGETSIZE)
1030 {
1031 unsigned long sz;
1032 int ret;
1033
1034 ret = ioctl(fd, BLKGETSIZE, &sz);
1035 (void)ret;
1036 }
1037 #endif
1038 #if defined(BLKGETSIZE64)
1039 {
1040 uint64_t sz;
1041 int ret;
1042
1043 ret = ioctl(fd, BLKGETSIZE64, &sz);
1044 (void)ret;
1045 }
1046 #endif
1047 #if defined(BLKGETZONESZ)
1048 {
1049 uint32_t sz;
1050 int ret;
1051
1052 ret = ioctl(fd, BLKGETZONESZ, &sz);
1053 (void)ret;
1054 }
1055 #endif
1056 #if defined(BLKGETNRZONES)
1057 {
1058 uint32_t sz;
1059 int ret;
1060
1061 ret = ioctl(fd, BLKGETNRZONES, &sz);
1062 (void)ret;
1063 }
1064 #endif
1065 offset = lseek(fd, 0, SEEK_END);
1066 stress_uint64_put((uint64_t)offset);
1067
1068 offset = lseek(fd, 0, SEEK_SET);
1069 stress_uint64_put((uint64_t)offset);
1070
1071 offset = lseek(fd, 0, SEEK_CUR);
1072 stress_uint64_put((uint64_t)offset);
1073 }
1074
1075 #if defined(__linux__)
dev_basename(const char * devpath)1076 static inline const char *dev_basename(const char *devpath)
1077 {
1078 const char *ptr = devpath;
1079 const char *base = devpath;
1080
1081 while (*ptr) {
1082 if ((*ptr == '/') && (*(ptr + 1)))
1083 base = ptr + 1;
1084 ptr++;
1085 }
1086
1087 return base;
1088 }
1089
is_scsi_dev(stress_dev_hash_info_t * dev_hash_info)1090 static inline bool is_scsi_dev(stress_dev_hash_info_t *dev_hash_info)
1091 {
1092 int i, n;
1093 static const char scsi_device_path[] = "/sys/class/scsi_device/";
1094 struct dirent **scsi_device_list;
1095 bool is_scsi = false;
1096 const char *devname = dev_basename(dev_hash_info->dev_path);
1097
1098 if (!*devname)
1099 return false;
1100
1101 if (dev_hash_info->is_scsi)
1102 return true;
1103
1104 scsi_device_list = NULL;
1105 n = scandir(scsi_device_path, &scsi_device_list, NULL, alphasort);
1106 if (n <= 0)
1107 return is_scsi;
1108
1109 for (i = 0; !is_scsi && (i < n); i++) {
1110 int j, m;
1111 char scsi_block_path[PATH_MAX];
1112 struct dirent **scsi_block_list;
1113
1114 if (scsi_device_list[i]->d_name[0] == '.')
1115 continue;
1116
1117 (void)snprintf(scsi_block_path, sizeof(scsi_block_path),
1118 "%s/%s/device/block", scsi_device_path,
1119 scsi_device_list[i]->d_name);
1120 scsi_block_list = NULL;
1121 m = scandir(scsi_block_path, &scsi_block_list, NULL, alphasort);
1122 if (m <= 0)
1123 continue;
1124
1125 for (j = 0; j < m; j++) {
1126 if (!strcmp(devname, scsi_block_list[j]->d_name)) {
1127 is_scsi = true;
1128 break;
1129 }
1130 }
1131
1132 stress_dirent_list_free(scsi_block_list, m);
1133 }
1134
1135 stress_dirent_list_free(scsi_device_list, n);
1136
1137 if (is_scsi)
1138 dev_hash_info->is_scsi = true;
1139
1140 return is_scsi;
1141 }
1142
1143 #else
is_scsi_dev(stress_dev_hash_info_t * dev_hash_info)1144 static inline bool is_scsi_dev(stress_dev_hash_info_t *dev_hash_info)
1145 {
1146 (void)dev_hash_info;
1147
1148 /* Assume not */
1149 return false;
1150 }
1151 #endif
1152
1153 /*
1154 * stress_dev_scsi_blk()
1155 * SCSI block device specific ioctls
1156 */
stress_dev_scsi_blk(const stress_args_t * args,const int fd,stress_dev_hash_info_t * dev_hash_info)1157 static void stress_dev_scsi_blk(
1158 const stress_args_t *args,
1159 const int fd,
1160 stress_dev_hash_info_t *dev_hash_info)
1161 {
1162 (void)args;
1163 (void)fd;
1164
1165 if (!is_scsi_dev(dev_hash_info))
1166 return;
1167
1168 #if defined(SG_GET_VERSION_NUM)
1169 {
1170 int ret, ver;
1171
1172 ret = ioctl(fd, SG_GET_VERSION_NUM, &ver);
1173 (void)ret;
1174 }
1175 #endif
1176 #if defined(SCSI_IOCTL_GET_IDLUN)
1177 {
1178 int ret;
1179 struct sng_scsi_idlun {
1180 int four_in_one;
1181 int host_unique_id;
1182 } lun;
1183
1184 (void)memset(&lun, 0, sizeof(lun));
1185 ret = ioctl(fd, SCSI_IOCTL_GET_IDLUN, &lun);
1186 (void)ret;
1187 }
1188 #endif
1189 #if defined(SCSI_IOCTL_GET_BUS_NUMBER)
1190 {
1191 int ret, bus;
1192
1193 ret = ioctl(fd, SCSI_IOCTL_GET_BUS_NUMBER, &bus);
1194 (void)ret;
1195 }
1196 #endif
1197 #if defined(SCSI_IOCTL_GET_TIMEOUT)
1198 {
1199 int ret;
1200
1201 ret = ioctl(fd, SCSI_IOCTL_GET_TIMEOUT, 0);
1202 (void)ret;
1203 }
1204 #endif
1205 #if defined(SCSI_IOCTL_GET_RESERVED_SIZE)
1206 {
1207 int ret, sz;
1208
1209 ret = ioctl(fd, SCSI_IOCTL_GET_RESERVED_SIZE, &sz);
1210 (void)ret;
1211 }
1212 #endif
1213 #if defined(SCSI_IOCTL_GET_PCI)
1214 {
1215 /* Old ioctl was 20 chars, new API 8 chars, 32 is plenty */
1216 char pci[32];
1217
1218 ret = ioctl(fd, SCSI_IOCTL_GET_PCI, pci);
1219 (void)ret;
1220 }
1221 #endif
1222 }
1223
1224 #if defined(__linux__)
1225 /*
1226 * stress_dev_scsi_generic_linux()
1227 * SCSI generic device specific ioctls for linux
1228 */
stress_dev_scsi_generic_linux(const stress_args_t * args,const int fd,const char * devpath)1229 static void stress_dev_scsi_generic_linux(
1230 const stress_args_t *args,
1231 const int fd,
1232 const char *devpath)
1233 {
1234 (void)args;
1235 (void)fd;
1236 (void)devpath;
1237
1238 #if defined(SG_GET_VERSION_NUM)
1239 {
1240 int ret, version = 0;
1241
1242 ret = ioctl(fd, SG_GET_VERSION_NUM, &version);
1243 (void)ret;
1244 }
1245 #endif
1246 #if defined(SG_GET_TIMEOUT)
1247 {
1248 int ret;
1249
1250 ret = ioctl(fd, SG_GET_TIMEOUT, 0);
1251 (void)ret;
1252 }
1253 #endif
1254 #if defined(SG_GET_LOW_DMA)
1255 {
1256 int ret, low;
1257
1258 ret = ioctl(fd, SG_GET_LOW_DMA, &low);
1259 (void)ret;
1260 }
1261 #endif
1262 #if defined(SG_GET_PACK_ID)
1263 {
1264 int ret, pack_id;
1265
1266 ret = ioctl(fd, SG_GET_PACK_ID, &pack_id);
1267 (void)ret;
1268 }
1269 #endif
1270 #if defined(SG_GET_NUM_WAITING)
1271 {
1272 int ret, n;
1273
1274 ret = ioctl(fd, SG_GET_NUM_WAITING, &n);
1275 (void)ret;
1276 }
1277 #endif
1278 #if defined(SG_GET_SG_TABLESIZE)
1279 {
1280 int ret, size;
1281
1282 ret = ioctl(fd, SG_GET_SG_TABLESIZE, &size);
1283 (void)ret;
1284 }
1285 #endif
1286 #if defined(SG_GET_RESERVED_SIZE)
1287 {
1288 int ret, size;
1289
1290 ret = ioctl(fd, SG_GET_RESERVED_SIZE, &size);
1291 (void)ret;
1292 }
1293 #endif
1294 #if defined(SG_GET_COMMAND_Q)
1295 {
1296 int ret, cmd_q;
1297
1298 ret = ioctl(fd, SG_GET_COMMAND_Q, &cmd_q);
1299 (void)ret;
1300 }
1301 #endif
1302 #if defined(SG_GET_ACCESS_COUNT)
1303 {
1304 int ret, n;
1305
1306 ret = ioctl(fd, SG_GET_ACCESS_COUNT, &n);
1307 (void)ret;
1308 }
1309 #endif
1310 #if defined(SCSI_IOCTL_GET_IDLUN)
1311 {
1312 int ret;
1313 struct shim_scsi_idlun {
1314 int four_in_one;
1315 int host_unique_id;
1316 } idlun;
1317
1318 ret = ioctl(fd, SCSI_IOCTL_GET_IDLUN, &idlun);
1319 (void)ret;
1320 }
1321 #endif
1322 #if defined(SCSI_IOCTL_GET_BUS_NUMBER)
1323 {
1324 int ret, bus;
1325
1326 ret = ioctl(fd, SCSI_IOCTL_GET_BUS_NUMBER, &bus);
1327 (void)ret;
1328 }
1329 #endif
1330 #if defined(SCSI_GET_TRANSFORM)
1331 {
1332 int ret, bus;
1333
1334 ret = ioctl(fd, SCSI_GET_TRANSFORM, 0);
1335 (void)ret;
1336 }
1337 #endif
1338 #if defined(SG_EMULATED_HOST)
1339 {
1340 int ret, emulated;
1341
1342 ret = ioctl(fd, SG_EMULATED_HOST, &emulated);
1343 (void)ret;
1344 }
1345 #endif
1346 #if defined(BLKSECTGET)
1347 {
1348 int ret, n;
1349
1350 ret = ioctl(fd, BLKSECTGET, &n);
1351 (void)ret;
1352 }
1353 #endif
1354 }
1355 #endif
1356
1357 #if defined(HAVE_LINUX_RANDOM_H)
1358 /*
1359 * stress_dev_random_linux()
1360 * Linux /dev/random ioctls
1361 */
stress_dev_random_linux(const stress_args_t * args,const int fd,const char * devpath)1362 static void stress_dev_random_linux(
1363 const stress_args_t *args,
1364 const int fd,
1365 const char *devpath)
1366 {
1367 (void)args;
1368 (void)fd;
1369 (void)devpath;
1370
1371 #if defined(RNDGETENTCNT)
1372 {
1373 long entropy;
1374 int ret;
1375
1376 ret = ioctl(fd, RNDGETENTCNT, &entropy);
1377 (void)ret;
1378 }
1379 #endif
1380
1381 #if defined(RNDRESEEDCRNG)
1382 {
1383 int ret;
1384
1385 ret = ioctl(fd, RNDRESEEDCRNG, NULL);
1386 (void)ret;
1387 }
1388 #endif
1389
1390 #if defined(RNDADDENTROPY)
1391 {
1392 char filename[PATH_MAX];
1393 int fd_rdwr;
1394
1395 /*
1396 * Re-open fd with O_RDWR
1397 */
1398 (void)snprintf(filename, sizeof(filename), "/proc/self/fd/%d", fd);
1399 fd_rdwr = open(filename, O_RDWR);
1400 if (fd_rdwr != -1) {
1401 int ret;
1402 const uint32_t rnd = stress_mwc32();
1403 struct shim_rand_pool_info {
1404 int entropy_count;
1405 int buf_size;
1406 uint8_t buf[4];
1407 } info;
1408 const size_t sz = sizeof(info.buf);
1409
1410 info.entropy_count = sz * 8;
1411 info.buf_size = sz;
1412 (void)memcpy(&info.buf, &rnd, sz);
1413
1414 ret = ioctl(fd_rdwr, RNDADDENTROPY, &info);
1415 (void)ret;
1416 (void)close(fd_rdwr);
1417 }
1418 }
1419 #endif
1420 }
1421 #endif
1422
1423 #if defined(__linux__)
1424 /*
1425 * stress_dev_mem_mmap_linux()
1426 * Linux mmap'ing on a device
1427 */
stress_dev_mem_mmap_linux(const int fd,const bool read_page)1428 static void stress_dev_mem_mmap_linux(const int fd, const bool read_page)
1429 {
1430 void *ptr;
1431 const size_t page_size = stress_get_pagesize();
1432
1433 ptr = mmap(NULL, page_size, PROT_READ, MAP_PRIVATE, fd, 0);
1434 if (ptr != MAP_FAILED) {
1435 (void)munmap(ptr, page_size);
1436 }
1437 if (read_page) {
1438 off_t off;
1439
1440 /* Try seeking */
1441 off = lseek(fd, (off_t)0, SEEK_SET);
1442 #if defined(STRESS_ARCH_X86)
1443 if (off == 0) {
1444 char buffer[page_size];
1445 ssize_t ret;
1446
1447 /* And try reading */
1448 ret = read(fd, buffer, page_size);
1449 (void)ret;
1450 }
1451 #else
1452 (void)off;
1453 #endif
1454 }
1455
1456 ptr = mmap(NULL, page_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
1457 if (ptr != MAP_FAILED) {
1458 (void)munmap(ptr, page_size);
1459 }
1460
1461 }
1462
stress_dev_mem_linux(const stress_args_t * args,const int fd,const char * devpath)1463 static void stress_dev_mem_linux(
1464 const stress_args_t *args,
1465 const int fd,
1466 const char *devpath)
1467 {
1468 (void)args;
1469 (void)devpath;
1470
1471 stress_dev_mem_mmap_linux(fd, true);
1472 }
1473 #endif
1474
1475 #if defined(__linux__)
stress_dev_kmem_linux(const stress_args_t * args,const int fd,const char * devpath)1476 static void stress_dev_kmem_linux(
1477 const stress_args_t *args,
1478 const int fd,
1479 const char *devpath)
1480 {
1481 (void)args;
1482 (void)devpath;
1483
1484 stress_dev_mem_mmap_linux(fd, false);
1485 }
1486 #endif
1487
1488 #if defined(__linux__) && \
1489 defined(CDROMREADTOCENTRY) && \
1490 defined(HAVE_CDROM_MSF) && \
1491 defined(HAVE_CDROM_TOCENTRY)
1492 /*
1493 * cdrom_get_address_msf()
1494 * Given a track and fd, the function returns
1495 * the address of the track in MSF format
1496 */
cdrom_get_address_msf(const int fd,int track,uint8_t * min,uint8_t * seconds,uint8_t * frames)1497 static void cdrom_get_address_msf(
1498 const int fd,
1499 int track,
1500 uint8_t *min,
1501 uint8_t *seconds,
1502 uint8_t *frames)
1503 {
1504 struct cdrom_tocentry entry;
1505
1506 (void)memset(&entry, 0, sizeof(entry));
1507 entry.cdte_track = (uint8_t)track;
1508 entry.cdte_format = CDROM_MSF;
1509
1510 if (ioctl(fd, CDROMREADTOCENTRY, &entry) == 0) {
1511 *min = entry.cdte_addr.msf.minute;
1512 *seconds = entry.cdte_addr.msf.second;
1513 *frames = entry.cdte_addr.msf.frame;
1514 }
1515 }
1516 #endif
1517
1518 #if defined(__linux__)
1519 /*
1520 * stress_cdrom_ioctl_msf()
1521 * tests all CDROM ioctl syscalls that
1522 * requires address argument in MSF Format
1523 */
stress_cdrom_ioctl_msf(const int fd)1524 static void stress_cdrom_ioctl_msf(const int fd)
1525 {
1526 int starttrk = 0, endtrk = 0;
1527
1528 (void)fd;
1529 (void)starttrk;
1530 (void)endtrk;
1531
1532 #if defined(CDROMREADTOCHDR) && \
1533 defined(HAVE_CDROM_MSF) && \
1534 defined(HAVE_CDROM_TOCHDR)
1535 IOCTL_TIMEOUT(0.10,
1536 {
1537 struct cdrom_tochdr header;
1538 /* Reading the number of tracks on disc */
1539
1540 (void)memset(&header, 0, sizeof(header));
1541 if (ioctl(fd, CDROMREADTOCHDR, &header) == 0) {
1542 starttrk = header.cdth_trk0;
1543 endtrk = header.cdth_trk1;
1544 }
1545 }, return);
1546
1547 /* Return if endtrack is not set or starttrk is invalid */
1548 if ((endtrk == 0) && (starttrk != 0)) {
1549 return;
1550 }
1551 #endif
1552
1553 #if defined(CDROMPLAYTRKIND) && \
1554 defined(HAVE_CDROM_TI) && \
1555 defined(CDROMPAUSE) && 0
1556 /* Play/pause is a bit rough on H/W, disable it for now */
1557 IOCTL_TIMEOUT(0.10, {
1558 struct cdrom_ti ti;
1559 int ret;
1560
1561 (void)memset(&ti, 0, sizeof(ti));
1562 ti.cdti_trk1 = endtrk;
1563 if (ioctl(fd, CDROMPLAYTRKIND, &ti) == 0) {
1564 ret = ioctl(fd, CDROMPAUSE, 0);
1565 (void)ret;
1566 }
1567 }, return);
1568 #endif
1569
1570 #if defined(CDROMREADTOCENTRY) && \
1571 defined(HAVE_CDROM_MSF) && \
1572 defined(HAVE_CDROM_TOCENTRY)
1573 {
1574 struct cdrom_msf msf;
1575 int ret;
1576
1577 /* Fetch address of start and end track in MSF format */
1578 (void)memset(&msf, 0, sizeof(msf));
1579 cdrom_get_address_msf(fd, starttrk, &msf.cdmsf_min0,
1580 &msf.cdmsf_sec0, &msf.cdmsf_frame0);
1581 cdrom_get_address_msf(fd, endtrk, &msf.cdmsf_min1,
1582 &msf.cdmsf_sec1, &msf.cdmsf_frame1);
1583
1584 #if defined(CDROMPLAYMSF) && \
1585 defined(CDROMPAUSE)
1586 IOCTL_TIMEOUT(0.10, {
1587 if (ioctl(fd, CDROMPLAYMSF, &msf) == 0) {
1588 ret = ioctl(fd, CDROMPAUSE, 0);
1589 (void)ret;
1590 }
1591 }, return);
1592 #endif
1593
1594 #if defined(CDROMREADRAW) && \
1595 defined(CD_FRAMESIZE_RAW)
1596 IOCTL_TIMEOUT(0.10, {
1597 union {
1598 struct cdrom_msf msf; /* input */
1599 char buffer[CD_FRAMESIZE_RAW]; /* return */
1600 } arg;
1601
1602 arg.msf = msf;
1603 ret = ioctl(fd, CDROMREADRAW, &arg);
1604 (void)ret;
1605 }, return);
1606 #endif
1607
1608 #if defined(CDROMREADMODE1) && \
1609 defined(CD_FRAMESIZE)
1610 IOCTL_TIMEOUT(0.10, {
1611 union {
1612 struct cdrom_msf msf; /* input */
1613 char buffer[CD_FRAMESIZE]; /* return */
1614 } arg;
1615
1616 arg.msf = msf;
1617 ret = ioctl(fd, CDROMREADMODE1, &arg);
1618 (void)ret;
1619 }, return);
1620 #endif
1621
1622 #if defined(CDROMREADMODE2) && \
1623 defined(CD_FRAMESIZE_RAW0)
1624 IOCTL_TIMEOUT(0.10, {
1625 union {
1626 struct cdrom_msf msf; /* input */
1627 char buffer[CD_FRAMESIZE_RAW0]; /* return */
1628 } arg;
1629
1630 arg.msf = msf;
1631 ret = ioctl(fd, CDROMREADMODE2, &arg);
1632 (void)ret;
1633 }, return);
1634 #endif
1635 }
1636 #endif
1637 }
1638 #endif
1639
1640 #if defined(__linux__)
stress_dev_cdrom_linux(const stress_args_t * args,const int fd,const char * devpath)1641 static void stress_dev_cdrom_linux(
1642 const stress_args_t *args,
1643 const int fd,
1644 const char *devpath)
1645 {
1646 (void)args;
1647 (void)fd;
1648 (void)devpath;
1649
1650 stress_cdrom_ioctl_msf(fd);
1651
1652 #if defined(CDROM_GET_MCN) && \
1653 defined(HAVE_CDROM_MCN)
1654 IOCTL_TIMEOUT(0.10, {
1655 struct cdrom_mcn mcn;
1656 int ret;
1657
1658 (void)memset(&mcn, 0, sizeof(mcn));
1659 ret = ioctl(fd, CDROM_GET_MCN, &mcn);
1660 (void)ret;
1661 }, return);
1662 #endif
1663 #if defined(CDROMREADTOCHDR) && \
1664 defined(HAVE_CDROM_TOCHDR)
1665 IOCTL_TIMEOUT(0.10, {
1666 struct cdrom_tochdr header;
1667 int ret;
1668
1669 (void)memset(&header, 0, sizeof(header));
1670 ret = ioctl(fd, CDROMREADTOCHDR, &header);
1671 (void)ret;
1672 }, return);
1673 #endif
1674 #if defined(CDROMREADTOCENTRY) && \
1675 defined(HAVE_CDROM_TOCENTRY)
1676 IOCTL_TIMEOUT(0.10, {
1677 struct cdrom_tocentry entry;
1678 int ret;
1679
1680 (void)memset(&entry, 0, sizeof(entry));
1681 ret = ioctl(fd, CDROMREADTOCENTRY, &entry);
1682 (void)ret;
1683 }, return);
1684 #endif
1685 #if defined(CDROMVOLREAD) && \
1686 defined(CDROMVOLCTRL) && \
1687 defined(HAVE_CDROM_VOLCTRL)
1688 IOCTL_TIMEOUT(0.10, {
1689 struct cdrom_volctrl volume;
1690 int ret;
1691
1692 (void)memset(&volume, 0, sizeof(volume));
1693 ret = ioctl(fd, CDROMVOLREAD, &volume);
1694 if (ret == 0)
1695 ret = ioctl(fd, CDROMVOLCTRL, &volume);
1696 (void)ret;
1697 }, return);
1698 #endif
1699 #if defined(CDROMSUBCHNL) && \
1700 defined(HAVE_CDROM_SUBCHNL)
1701 IOCTL_TIMEOUT(0.10, {
1702 struct cdrom_subchnl q;
1703 int ret;
1704
1705 (void)memset(&q, 0, sizeof(q));
1706 ret = ioctl(fd, CDROMSUBCHNL, &q);
1707 (void)ret;
1708 }, return);
1709 #endif
1710 #if defined(CDROMREADAUDIO) && \
1711 defined(HAVE_CDROM_READ_AUDIO)
1712 IOCTL_TIMEOUT(0.10, {
1713 struct cdrom_read_audio ra;
1714 int ret;
1715
1716 (void)memset(&ra, 0, sizeof(ra));
1717 ret = ioctl(fd, CDROMREADAUDIO, &ra);
1718 (void)ret;
1719 }, return);
1720 #endif
1721 #if defined(CDROMREADCOOKED) && \
1722 defined(CD_FRAMESIZE)
1723 IOCTL_TIMEOUT(0.10, {
1724 uint8_t buffer[CD_FRAMESIZE];
1725 int ret;
1726
1727 (void)memset(&buffer, 0, sizeof(buffer));
1728 ret = ioctl(fd, CDROMREADCOOKED, buffer);
1729 (void)ret;
1730 }, return);
1731 #endif
1732 #if defined(CDROMREADALL) && \
1733 defined(CD_FRAMESIZE)
1734 IOCTL_TIMEOUT(0.10, {
1735 uint8_t buffer[CD_FRAMESIZE];
1736 int ret;
1737
1738 (void)memset(&buffer, 0, sizeof(buffer));
1739 ret = ioctl(fd, CDROMREADALL, buffer);
1740 (void)ret;
1741 }, return);
1742 #endif
1743 #if defined(CDROMSEEK) && \
1744 defined(HAVE_CDROM_MSF)
1745 IOCTL_TIMEOUT(0.10, {
1746 struct cdrom_msf msf;
1747 int ret;
1748
1749 (void)memset(&msf, 0, sizeof(msf));
1750 ret = ioctl(fd, CDROMSEEK, &msf);
1751 (void)ret;
1752 }, return);
1753 #endif
1754 #if defined(CDROMGETSPINDOWN)
1755 {
1756 char spindown;
1757 int ret;
1758
1759 ret = ioctl(fd, CDROMGETSPINDOWN, &spindown);
1760 #if defined(CDROMSETSPINDOWN)
1761 if (ret == 0) {
1762 char bad_val = ~0;
1763
1764 ret = ioctl(fd, CDROMSETSPINDOWN, &spindown);
1765 (void)ret;
1766
1767 /*
1768 * Exercise Invalid CDROMSETSPINDOWN ioctl call with
1769 * invalid spindown as it could contain only 4 set bits
1770 */
1771 ret = ioctl(fd, CDROMSETSPINDOWN, bad_val);
1772 if (ret == 0) {
1773 /* Unexpected success, so set it back */
1774 ret = ioctl(fd, CDROMSETSPINDOWN, &spindown);
1775 }
1776 }
1777 #endif
1778 (void)ret;
1779 }
1780 #endif
1781
1782
1783 #if defined(CDROM_DISC_STATUS)
1784 IOCTL_TIMEOUT(0.10, {
1785 int ret;
1786
1787 ret = ioctl(fd, CDROM_DISC_STATUS, 0);
1788 (void)ret;
1789 }, return);
1790 #endif
1791 #if defined(CDROM_GET_CAPABILITY)
1792 IOCTL_TIMEOUT(0.10, {
1793 int ret;
1794
1795 ret = ioctl(fd, CDROM_GET_CAPABILITY, 0);
1796 (void)ret;
1797 }, return);
1798 #endif
1799 #if defined(CDROM_CHANGER_NSLOTS)
1800 IOCTL_TIMEOUT(0.10, {
1801 int ret;
1802
1803 ret = ioctl(fd, CDROM_CHANGER_NSLOTS, 0);
1804 (void)ret;
1805 }, return);
1806 #endif
1807 #if defined(CDROM_NEXT_WRITABLE)
1808 IOCTL_TIMEOUT(0.10, {
1809 int ret;
1810 long next;
1811
1812 ret = ioctl(fd, CDROM_NEXT_WRITABLE, &next);
1813 (void)ret;
1814 }, return);
1815 #endif
1816 #if defined(CDROM_LAST_WRITTEN)
1817 IOCTL_TIMEOUT(0.10, {
1818 int ret;
1819 long last;
1820
1821 ret = ioctl(fd, CDROM_LAST_WRITTEN, &last);
1822 (void)ret;
1823 }, return);
1824 #endif
1825 #if defined(CDROM_MEDIA_CHANGED) && 0
1826 IOCTL_TIMEOUT(0.10, {
1827 int ret;
1828 int slot = 0;
1829
1830 ret = ioctl(fd, CDROM_MEDIA_CHANGED, slot);
1831 (void)ret;
1832 }, return);
1833 #endif
1834 #if defined(CDSL_NONE)
1835 IOCTL_TIMEOUT(0.10, {
1836 int ret;
1837 int slot = CDSL_NONE;
1838
1839 ret = ioctl(fd, CDROM_MEDIA_CHANGED, slot);
1840 (void)ret;
1841 }, return);
1842 #endif
1843 #if defined(CDSL_CURRENT)
1844 IOCTL_TIMEOUT(0.10, {
1845 int ret;
1846 int slot = CDSL_CURRENT;
1847
1848 ret = ioctl(fd, CDROM_MEDIA_CHANGED, slot);
1849 (void)ret;
1850 }, return);
1851 #endif
1852 #if defined(CDROMPAUSE)
1853 IOCTL_TIMEOUT(0.10, {
1854 int ret;
1855
1856 ret = ioctl(fd, CDROMPAUSE, 0);
1857 (void)ret;
1858 }, return);
1859 #endif
1860 #if defined(CDROMRESUME)
1861 IOCTL_TIMEOUT(0.10, {
1862 int ret;
1863
1864 ret = ioctl(fd, CDROMRESUME, 0);
1865 (void)ret;
1866 }, return);
1867 #endif
1868 #if defined(CDROM_DRIVE_STATUS)
1869 IOCTL_TIMEOUT(0.10, {
1870 int ret;
1871 int slot = 0;
1872
1873 ret = ioctl(fd, CDROM_DRIVE_STATUS, slot);
1874 (void)ret;
1875 }, return);
1876 #if defined(CDSL_NONE)
1877 IOCTL_TIMEOUT(0.10, {
1878 int ret;
1879 int slot = CDSL_NONE;
1880
1881 ret = ioctl(fd, CDROM_DRIVE_STATUS, slot);
1882 (void)ret;
1883 }, return);
1884 #endif
1885 #if defined(CDSL_CURRENT)
1886 IOCTL_TIMEOUT(0.10, {
1887 int ret;
1888 int slot = CDSL_CURRENT;
1889
1890 ret = ioctl(fd, CDROM_DRIVE_STATUS, slot);
1891 (void)ret;
1892 }, return);
1893 #endif
1894 #endif
1895 #if defined(DVD_READ_STRUCT) && \
1896 defined(HAVE_DVD_STRUCT)
1897 IOCTL_TIMEOUT(0.10, {
1898 dvd_struct s;
1899 int ret;
1900
1901 /*
1902 * Invalid DVD_READ_STRUCT ioctl syscall with
1903 * invalid layer number resulting in EINVAL
1904 */
1905 (void)memset(&s, 0, sizeof(s));
1906 s.type = DVD_STRUCT_PHYSICAL;
1907 s.physical.layer_num = UINT8_MAX;
1908 ret = ioctl(fd, DVD_READ_STRUCT, &s);
1909 (void)ret;
1910
1911 /*
1912 * Exercise each DVD structure type to cover all the
1913 * respective functions to increase kernel coverage
1914 */
1915 (void)memset(&s, 0, sizeof(s));
1916 s.type = DVD_STRUCT_PHYSICAL;
1917 ret = ioctl(fd, DVD_READ_STRUCT, &s);
1918 (void)ret;
1919
1920 (void)memset(&s, 0, sizeof(s));
1921 s.type = DVD_STRUCT_COPYRIGHT;
1922 ret = ioctl(fd, DVD_READ_STRUCT, &s);
1923 (void)ret;
1924
1925 (void)memset(&s, 0, sizeof(s));
1926 s.type = DVD_STRUCT_DISCKEY;
1927 ret = ioctl(fd, DVD_READ_STRUCT, &s);
1928 (void)ret;
1929
1930 (void)memset(&s, 0, sizeof(s));
1931 s.type = DVD_STRUCT_BCA;
1932 ret = ioctl(fd, DVD_READ_STRUCT, &s);
1933 (void)ret;
1934
1935 (void)memset(&s, 0, sizeof(s));
1936 s.type = DVD_STRUCT_MANUFACT;
1937 ret = ioctl(fd, DVD_READ_STRUCT, &s);
1938 (void)ret;
1939
1940 /* Invalid DVD_READ_STRUCT call with invalid type argument */
1941 (void)memset(&s, 0, sizeof(s));
1942 s.type = UINT8_MAX;
1943 ret = ioctl(fd, DVD_READ_STRUCT, &s);
1944 (void)ret;
1945 }, return);
1946 #endif
1947 #if defined(CDROMAUDIOBUFSIZ)
1948 IOCTL_TIMEOUT(0.10, {
1949 int val = INT_MIN;
1950 int ret;
1951
1952 /* Invalid CDROMAUDIOBUFSIZ call with negative buffer size */
1953 ret = ioctl(fd, CDROMAUDIOBUFSIZ, val);
1954 (void)ret;
1955 }, return);
1956 #endif
1957 #if defined(DVD_AUTH) && \
1958 defined(HAVE_DVD_AUTHINFO)
1959 IOCTL_TIMEOUT(0.40, {
1960 int ret;
1961 dvd_authinfo ai;
1962
1963 /* Invalid DVD_AUTH call with no credentials */
1964 (void)memset(&ai, 0, sizeof(ai));
1965 ret = ioctl(fd, DVD_AUTH, &ai);
1966 (void)ret;
1967
1968 /*
1969 * Exercise each DVD AUTH type to cover all the
1970 * respective code to increase kernel coverage
1971 */
1972 (void)memset(&ai, 0, sizeof(ai));
1973 ai.type = DVD_LU_SEND_AGID;
1974 ret = ioctl(fd, DVD_AUTH, &ai);
1975 (void)ret;
1976
1977 (void)memset(&ai, 0, sizeof(ai));
1978 ai.type = DVD_LU_SEND_KEY1;
1979 ret = ioctl(fd, DVD_AUTH, &ai);
1980 (void)ret;
1981
1982 (void)memset(&ai, 0, sizeof(ai));
1983 ai.type = DVD_LU_SEND_CHALLENGE;
1984 ret = ioctl(fd, DVD_AUTH, &ai);
1985 (void)ret;
1986
1987 (void)memset(&ai, 0, sizeof(ai));
1988 ai.type = DVD_LU_SEND_TITLE_KEY;
1989 ret = ioctl(fd, DVD_AUTH, &ai);
1990 (void)ret;
1991
1992 (void)memset(&ai, 0, sizeof(ai));
1993 ai.type = DVD_LU_SEND_ASF;
1994 ret = ioctl(fd, DVD_AUTH, &ai);
1995 (void)ret;
1996
1997 (void)memset(&ai, 0, sizeof(ai));
1998 ai.type = DVD_HOST_SEND_CHALLENGE;
1999 ret = ioctl(fd, DVD_AUTH, &ai);
2000 (void)ret;
2001
2002 (void)memset(&ai, 0, sizeof(ai));
2003 ai.type = DVD_HOST_SEND_KEY2;
2004 ret = ioctl(fd, DVD_AUTH, &ai);
2005 (void)ret;
2006
2007 (void)memset(&ai, 0, sizeof(ai));
2008 ai.type = DVD_INVALIDATE_AGID;
2009 ret = ioctl(fd, DVD_AUTH, &ai);
2010 (void)ret;
2011
2012 (void)memset(&ai, 0, sizeof(ai));
2013 ai.type = DVD_LU_SEND_RPC_STATE;
2014 ret = ioctl(fd, DVD_AUTH, &ai);
2015 (void)ret;
2016
2017 (void)memset(&ai, 0, sizeof(ai));
2018 ai.type = DVD_HOST_SEND_RPC_STATE;
2019 ret = ioctl(fd, DVD_AUTH, &ai);
2020 (void)ret;
2021
2022 /* Invalid DVD_READ_STRUCT call with invalid type argument */
2023 (void)memset(&ai, 0, sizeof(ai));
2024 ai.type = (uint8_t)~0;
2025 ret = ioctl(fd, DVD_AUTH, &ai);
2026 (void)ret;
2027 }, return);
2028 #endif
2029
2030 #if defined(CDROM_DEBUG)
2031 IOCTL_TIMEOUT(0.10, {
2032 int debug;
2033 int ret;
2034
2035 /* Enable the DEBUG Messages */
2036 debug = 1;
2037 ret = ioctl(fd, CDROM_DEBUG, debug);
2038 (void)ret;
2039
2040 /* Disable the DEBUG Messages */
2041 debug = 0;
2042 ret = ioctl(fd, CDROM_DEBUG, debug);
2043 (void)ret;
2044 }, return);
2045 #endif
2046
2047 #if defined(CDROM_SELECT_SPEED)
2048 IOCTL_TIMEOUT(0.10, {
2049 unsigned int i;
2050 unsigned int speed;
2051 int ret;
2052
2053 for (i = 8; i < 16; i++) {
2054 speed = 1 << i;
2055 ret = ioctl(fd, CDROM_SELECT_SPEED, speed);
2056 (void)ret;
2057 }
2058 }, return);
2059 #endif
2060
2061 #if defined(CDROMPLAYBLK) && \
2062 defined(HAVE_CDROM_BLK)
2063 IOCTL_TIMEOUT(0.10, {
2064 struct cdrom_blk blk;
2065 int ret;
2066
2067 (void)memset(&blk, 0, sizeof(blk));
2068 ret = ioctl(fd, CDROMPLAYBLK, &blk);
2069 (void)ret;
2070 }, return);
2071 #endif
2072 }
2073 #endif
2074
2075 #if defined(__linux__)
stress_dev_console_linux(const stress_args_t * args,const int fd,const char * devpath)2076 static void stress_dev_console_linux(
2077 const stress_args_t *args,
2078 const int fd,
2079 const char *devpath)
2080 {
2081 (void)args;
2082 (void)fd;
2083 (void)devpath;
2084
2085 #if defined(HAVE_LINUX_KD_H) && \
2086 defined(KDGETLED)
2087 {
2088 char argp;
2089 int ret;
2090
2091 ret = ioctl(fd, KDGETLED, &argp);
2092 #if defined(KDSETLED)
2093 if (ret == 0) {
2094 const char bad_val = ~0;
2095
2096 ret = ioctl(fd, KDSETLED, &argp);
2097 (void)ret;
2098
2099 /* Exercise Invalid KDSETLED ioctl call with invalid flags */
2100 ret = ioctl(fd, KDSETLED, &bad_val);
2101 if (ret == 0) {
2102 /* Unexpected success, so set it back */
2103 ret = ioctl(fd, KDSETLED, &argp);
2104 }
2105 }
2106 #endif
2107 (void)ret;
2108 }
2109 #endif
2110
2111 #if defined(HAVE_LINUX_KD_H) && \
2112 defined(KDGKBLED)
2113 {
2114 char argp;
2115 int ret;
2116
2117 ret = ioctl(fd, KDGKBLED, &argp);
2118 #if defined(KDSKBLED)
2119 if (ret == 0) {
2120 unsigned long bad_val = ~0UL, val;
2121
2122 val = (unsigned long)argp;
2123 ret = ioctl(fd, KDSKBLED, val);
2124 (void)ret;
2125
2126 /* Exercise Invalid KDSKBLED ioctl call with invalid flags */
2127 ret = ioctl(fd, KDSKBLED, bad_val);
2128 if (ret == 0) {
2129 /* Unexpected success, so set it back */
2130 ret = ioctl(fd, KDSKBLED, val);
2131 }
2132 }
2133 #endif
2134 (void)ret;
2135 }
2136 #endif
2137
2138 #if defined(HAVE_LINUX_KD_H) && \
2139 defined(KDGETMODE)
2140 {
2141 int ret;
2142 unsigned long argp = 0;
2143
2144 ret = ioctl(fd, KDGETMODE, &argp);
2145 #if defined(KDSETMODE)
2146 if (ret == 0) {
2147 unsigned long bad_val = ~0UL;
2148
2149 ret = ioctl(fd, KDSETMODE, argp);
2150 (void)ret;
2151
2152 /* Exercise Invalid KDSETMODE ioctl call with invalid flags */
2153 ret = ioctl(fd, KDSETMODE, bad_val);
2154 if (ret == 0) {
2155 /* Unexpected success, so set it back */
2156 ret = ioctl(fd, KDSETMODE, argp);
2157 }
2158 }
2159 #endif
2160 (void)ret;
2161 }
2162 #endif
2163
2164 #if defined(HAVE_LINUX_KD_H) && \
2165 defined(KDGKBTYPE)
2166 {
2167 int val = 0, ret;
2168
2169 ret = ioctl(fd, KDGKBTYPE, &val);
2170 (void)ret;
2171 }
2172 #endif
2173
2174 #if defined(HAVE_LINUX_KD_H) && \
2175 defined(GIO_CMAP)
2176 {
2177 unsigned char colormap[3*16];
2178 int ret;
2179
2180 ret = ioctl(fd, GIO_CMAP, colormap);
2181 #if defined(PIO_CMAP)
2182 if (ret == 0) {
2183 ret = ioctl(fd, PIO_CMAP, colormap);
2184 }
2185 #endif
2186 (void)ret;
2187 }
2188 #endif
2189
2190 #if defined(HAVE_LINUX_KD_H) && \
2191 defined(GIO_FONTX) && \
2192 defined(HAVE_CONSOLEFONTDESC)
2193 {
2194 struct consolefontdesc font;
2195 int ret;
2196
2197 (void)memset(&font, 0, sizeof(font));
2198 ret = ioctl(fd, GIO_FONTX, &font);
2199 #if defined(PIO_FONTX)
2200 if (ret == 0) {
2201 ret = ioctl(fd, PIO_FONTX, &font);
2202 }
2203 #endif
2204 (void)ret;
2205 }
2206 #endif
2207
2208 #if defined(HAVE_LINUX_KD_H) && \
2209 defined(KDGETKEYCODE) && \
2210 defined(HAVE_KBKEYCODE)
2211 {
2212 int ret;
2213 struct kbkeycode argp;
2214
2215 (void)memset(&argp, 0, sizeof(argp));
2216 ret = ioctl(fd, KDGETKEYCODE, &argp);
2217 #if defined(KDSETKEYCODE)
2218 if (ret == 0) {
2219 struct kbkeycode bad_arg;
2220
2221 ret = ioctl(fd, KDSETKEYCODE, &argp);
2222 (void)ret;
2223
2224 /*
2225 * Exercise Invalid KDSETKEYCODE ioctl call
2226 * with invalid keycode having different values
2227 * of scancode and keycode for scancode < 89
2228 */
2229 (void)memset(&bad_arg, 0, sizeof(bad_arg));
2230 bad_arg.scancode = 1;
2231 bad_arg.keycode = 2;
2232
2233 ret = ioctl(fd, KDSETKEYCODE, &bad_arg);
2234 if (ret == 0) {
2235 /* Unexpected success, so set it back */
2236 ret = ioctl(fd, KDSETKEYCODE, &argp);
2237 }
2238 }
2239 #endif
2240 (void)ret;
2241 }
2242 #endif
2243
2244 #if defined(HAVE_LINUX_KD_H) && \
2245 defined(GIO_FONT)
2246 {
2247 unsigned char argp[8192];
2248 int ret;
2249
2250 ret = ioctl(fd, GIO_FONT, argp);
2251 #if defined(PIO_FONT)
2252 if (ret == 0) {
2253 ret = ioctl(fd, PIO_FONT, argp);
2254 }
2255 #endif
2256 (void)ret;
2257 }
2258 #endif
2259
2260 #if defined(HAVE_LINUX_KD_H) && \
2261 defined(GIO_SCRNMAP) && \
2262 defined(E_TABSZ)
2263 {
2264 unsigned char argp[E_TABSZ];
2265 int ret;
2266
2267 ret = ioctl(fd, GIO_SCRNMAP, argp);
2268 #if defined(PIO_SCRNMAP)
2269 if (ret == 0) {
2270 ret = ioctl(fd, PIO_SCRNMAP, argp);
2271 }
2272 #endif
2273 (void)ret;
2274 }
2275 #endif
2276
2277 #if defined(HAVE_LINUX_KD_H) && \
2278 defined(GIO_UNISCRNMAP) && \
2279 defined(E_TABSZ)
2280 {
2281 unsigned short argp[E_TABSZ];
2282 int ret;
2283
2284 ret = ioctl(fd, GIO_UNISCRNMAP, argp);
2285 #if defined(PIO_UNISCRNMAP)
2286 if (ret == 0) {
2287 ret = ioctl(fd, PIO_UNISCRNMAP, argp);
2288 }
2289 #endif
2290 (void)ret;
2291 }
2292 #endif
2293
2294 #if defined(HAVE_LINUX_KD_H) && \
2295 defined(KDGKBMODE)
2296 {
2297 int ret;
2298 unsigned long argp = 0;
2299
2300 ret = ioctl(fd, KDGKBMODE, &argp);
2301 #if defined(KDSKBMODE)
2302 if (ret == 0) {
2303 unsigned long bad_val = ~0UL;
2304
2305 ret = ioctl(fd, KDSKBMODE, argp);
2306 (void)ret;
2307
2308 /* Exercise Invalid KDSKBMODE ioctl call with invalid key mode */
2309 ret = ioctl(fd, KDSKBMODE, bad_val);
2310 if (ret == 0) {
2311 /* Unexpected success, so set it back */
2312 ret = ioctl(fd, KDSKBMODE, argp);
2313 }
2314 }
2315 #endif
2316 (void)ret;
2317 }
2318 #endif
2319
2320 #if defined(HAVE_LINUX_KD_H) && \
2321 defined(KDGKBMETA)
2322 {
2323 int ret;
2324 unsigned long argp = 0;
2325
2326 ret = ioctl(fd, KDGKBMETA, &argp);
2327 #if defined(KDSKBMETA)
2328 if (ret == 0) {
2329 unsigned long bad_val = ~0UL;
2330
2331 ret = ioctl(fd, KDSKBMETA, argp);
2332 (void)ret;
2333
2334 /* Exercise Invalid KDSKBMETA ioctl call with invalid key mode */
2335 ret = ioctl(fd, KDSKBMETA, bad_val);
2336 if (ret == 0) {
2337 /* Unexpected success, so set it back */
2338 ret = ioctl(fd, KDSKBMETA, argp);
2339 }
2340 }
2341 #endif
2342 (void)ret;
2343 }
2344 #endif
2345
2346 #if defined(HAVE_LINUX_KD_H) && \
2347 defined(GIO_UNIMAP) && \
2348 defined(HAVE_UNIMAPDESC)
2349 {
2350 int ret;
2351 struct unimapdesc argp;
2352
2353 (void)memset(&argp, 0, sizeof(argp));
2354 ret = ioctl(fd, GIO_UNIMAP, &argp);
2355 #if defined(PIO_UNIMAP)
2356 if (ret == 0) {
2357 ret = ioctl(fd, PIO_UNIMAP, &argp);
2358 (void)ret;
2359 }
2360 #endif
2361 (void)ret;
2362 }
2363 #endif
2364
2365 #if defined(HAVE_LINUX_KD_H) && \
2366 defined(KDGKBDIACR) && \
2367 defined(HAVE_KBDIACRS)
2368 {
2369 int ret;
2370 struct kbdiacrs argp;
2371
2372 (void)memset(&argp, 0, sizeof(argp));
2373 ret = ioctl(fd, KDGKBDIACR, &argp);
2374 (void)ret;
2375 }
2376 #endif
2377
2378 #if defined(HAVE_LINUX_KD_H) && \
2379 defined(VT_RESIZE) && \
2380 defined(HAVE_VT_SIZES) && \
2381 defined(CAP_SYS_TTY_CONFIG)
2382 {
2383 int ret;
2384 struct vt_sizes argp;
2385 bool perm = stress_check_capability(CAP_SYS_TTY_CONFIG);
2386
2387 /* Exercise only if permission is not present */
2388 if (!perm) {
2389 (void)memset(&argp, 0, sizeof(argp));
2390 ret = ioctl(fd, VT_RESIZE, &argp);
2391 (void)ret;
2392 }
2393 }
2394 #endif
2395
2396 #if defined(HAVE_LINUX_KD_H) && \
2397 defined(VT_RESIZEX) && \
2398 defined(HAVE_VT_CONSIZE) && \
2399 defined(CAP_SYS_TTY_CONFIG)
2400 {
2401 int ret;
2402 struct vt_consize argp;
2403 bool perm = stress_check_capability(CAP_SYS_TTY_CONFIG);
2404
2405 /* Exercise only if permission is not present */
2406 if (!perm) {
2407 (void)memset(&argp, 0, sizeof(argp));
2408 ret = ioctl(fd, VT_RESIZEX, &argp);
2409 (void)ret;
2410 }
2411 }
2412 #endif
2413
2414 #if defined(HAVE_LINUX_KD_H) && \
2415 defined(KDGKBSENT) && \
2416 defined(HAVE_KBSENTRY)
2417 {
2418 int ret;
2419 struct kbsentry argp;
2420
2421 (void)memset(&argp, 0, sizeof(argp));
2422 ret = ioctl(fd, KDGKBSENT, &argp);
2423 #if defined(KDSKBSENT)
2424 if (ret == 0) {
2425 ret = ioctl(fd, KDSKBSENT, &argp);
2426 (void)ret;
2427 }
2428 #endif
2429 (void)ret;
2430 }
2431 #endif
2432
2433 #if defined(HAVE_LINUX_VT_H) && \
2434 defined(VT_GETMODE) && \
2435 defined(HAVE_VT_MODE)
2436 {
2437 int ret;
2438 struct vt_mode mode;
2439
2440 (void)memset(&mode, 0, sizeof(mode));
2441 ret = ioctl(fd, VT_GETMODE, &mode);
2442 #if defined(VT_SETMODE)
2443 if (ret == 0) {
2444 ret = ioctl(fd, VT_SETMODE, &mode);
2445 (void)ret;
2446 }
2447 #endif
2448 (void)ret;
2449 }
2450 #endif
2451
2452 #if defined(HAVE_LINUX_KD_H) && \
2453 defined(KDGKBENT) && \
2454 defined(HAVE_KBENTRY)
2455 {
2456 int ret;
2457 struct kbentry entry;
2458
2459 (void)memset(&entry, 0, sizeof(entry));
2460 ret = ioctl(fd, KDGKBENT, &entry);
2461 #if defined(KDSKBENT)
2462 if (ret == 0) {
2463 ret = ioctl(fd, KDSKBENT, &entry);
2464 (void)ret;
2465
2466 #if defined(MAX_NR_KEYMAPS)
2467 struct kbentry bad_entry;
2468
2469 (void)memset(&bad_entry, 0, sizeof(bad_entry));
2470 bad_entry.kb_table = MAX_NR_KEYMAPS;
2471 ret = ioctl(fd, KDSKBENT, &bad_entry);
2472 if (ret == 0) {
2473 /* Unexpected success, so set it back */
2474 ret = ioctl(fd, KDSKBENT, &entry);
2475 }
2476 #endif
2477
2478 #if defined(HAVE_LINUX_KD_H) && \
2479 defined(KDSKBENT) && \
2480 defined(HAVE_KBENTRY) && \
2481 defined(NR_KEYS)
2482 struct kbentry bad_entry;
2483
2484 (void)memset(&entry, 0, sizeof(entry));
2485 bad_entry.kb_index = NR_KEYS;
2486 ret = ioctl(fd, KDSKBENT, &bad_entry);
2487 if (ret == 0) {
2488 /* Unexpected success, so set it back */
2489 ret = ioctl(fd, KDSKBENT, &entry);
2490 }
2491 #endif
2492 }
2493 #endif
2494 (void)ret;
2495 }
2496 #endif
2497
2498 }
2499 #endif
2500
2501 #if defined(__linux__)
stress_dev_kmsg_linux(const stress_args_t * args,const int fd,const char * devpath)2502 static void stress_dev_kmsg_linux(
2503 const stress_args_t *args,
2504 const int fd,
2505 const char *devpath)
2506 {
2507 (void)args;
2508 (void)devpath;
2509
2510 stress_dev_mem_mmap_linux(fd, true);
2511 }
2512 #endif
2513
2514 #if defined(__linux__)
stress_dev_nvram_linux(const stress_args_t * args,const int fd,const char * devpath)2515 static void stress_dev_nvram_linux(
2516 const stress_args_t *args,
2517 const int fd,
2518 const char *devpath)
2519 {
2520 (void)args;
2521 (void)devpath;
2522
2523 stress_dev_mem_mmap_linux(fd, true);
2524 }
2525 #endif
2526
2527 #if defined(HAVE_LINUX_HPET_H)
stress_dev_hpet_linux(const stress_args_t * args,const int fd,const char * devpath)2528 static void stress_dev_hpet_linux(
2529 const stress_args_t *args,
2530 const int fd,
2531 const char *devpath)
2532 {
2533 (void)args;
2534 (void)fd;
2535 (void)devpath;
2536
2537 /*
2538 * Avoid https://bugs.xenserver.org/browse/XSO-809
2539 */
2540 if (linux_xen_guest())
2541 return;
2542
2543 #if defined(HPET_INFO)
2544 {
2545 struct hpet_info info;
2546 int ret;
2547
2548 ret = ioctl(fd, HPET_INFO, &info);
2549 (void)ret;
2550 }
2551 #endif
2552 #if defined(HPET_IRQFREQ)
2553 {
2554 unsigned long freq;
2555 int ret;
2556
2557 ret = ioctl(fd, HPET_IRQFREQ, &freq);
2558 (void)ret;
2559 }
2560 #endif
2561 #if defined(CDROMMULTISESSION)
2562 {
2563 int ret;
2564 struct cdrom_multisession ms_info;
2565
2566 /*
2567 * Invalid CDROMMULTISESSION ioctl syscall with
2568 * invalid format number resulting in EINVAL
2569 */
2570 (void)memset(&ms_info, 0, sizeof(ms_info));
2571 ms_info.addr_format = UINT8_MAX;
2572 ret = ioctl(fd, CDROMMULTISESSION, &ms_info);
2573 (void)ret;
2574
2575 /* Valid CDROMMULTISESSION with address formats */
2576 (void)memset(&ms_info, 0, sizeof(ms_info));
2577 ms_info.addr_format = CDROM_MSF;
2578 ret = ioctl(fd, CDROMMULTISESSION, &ms_info);
2579 (void)ret;
2580
2581 (void)memset(&ms_info, 0, sizeof(ms_info));
2582 ms_info.addr_format = CDROM_LBA;
2583 ret = ioctl(fd, CDROMMULTISESSION, &ms_info);
2584 (void)ret;
2585 }
2586 #endif
2587 }
2588 #endif
2589
2590 #if defined(__linux__) && \
2591 defined(STRESS_ARCH_X86)
stress_dev_port_linux(const stress_args_t * args,const int fd,const char * devpath)2592 static void stress_dev_port_linux(
2593 const stress_args_t *args,
2594 const int fd,
2595 const char *devpath)
2596 {
2597 off_t off;
2598 uint8_t *ptr;
2599 const size_t page_size = stress_get_pagesize();
2600
2601 (void)args;
2602 (void)devpath;
2603
2604 /* seek and read port 0x80 */
2605 off = lseek(fd, (off_t)0x80, SEEK_SET);
2606 if (off == 0) {
2607 char data[1];
2608 ssize_t ret;
2609
2610 ret = read(fd, data, sizeof(data));
2611 (void)ret;
2612 }
2613
2614 /* Should fail */
2615 ptr = mmap(NULL, page_size, PROT_READ, MAP_PRIVATE, fd, 0);
2616 if (ptr != MAP_FAILED)
2617 (void)munmap(ptr, page_size);
2618 }
2619 #endif
2620
2621 #if defined(HAVE_LINUX_HDREG_H)
stress_dev_hd_linux_ioctl_long(int fd,unsigned long cmd)2622 static void stress_dev_hd_linux_ioctl_long(int fd, unsigned long cmd)
2623 {
2624 long val;
2625 int ret;
2626
2627 ret = ioctl(fd, cmd, &val);
2628 (void)ret;
2629 }
2630
2631 /*
2632 * stress_dev_hd_linux()
2633 * Linux HDIO ioctls
2634 */
stress_dev_hd_linux(const stress_args_t * args,const int fd,const char * devpath)2635 static void stress_dev_hd_linux(
2636 const stress_args_t *args,
2637 const int fd,
2638 const char *devpath)
2639 {
2640 (void)args;
2641 (void)devpath;
2642
2643 #if defined(HDIO_GETGEO)
2644 {
2645 struct hd_geometry geom;
2646 int ret;
2647
2648 ret = ioctl(fd, HDIO_GETGEO, &geom);
2649 (void)ret;
2650 }
2651 #endif
2652
2653 #if defined(HDIO_GET_UNMASKINTR)
2654 stress_dev_hd_linux_ioctl_long(fd, HDIO_GET_UNMASKINTR);
2655 #endif
2656
2657 #if defined(HDIO_GET_MULTCOUNT)
2658 {
2659 int val, ret;
2660
2661 ret = ioctl(fd, HDIO_GET_MULTCOUNT, &val);
2662 (void)ret;
2663 }
2664 #endif
2665
2666 #if defined(HDIO_GET_IDENTITY)
2667 {
2668 unsigned char identity[512];
2669 int ret;
2670
2671 ret = ioctl(fd, HDIO_GET_IDENTITY, identity);
2672 (void)ret;
2673 }
2674 #endif
2675
2676 #if defined(HDIO_GET_KEEPSETTINGS)
2677 stress_dev_hd_linux_ioctl_long(fd, HDIO_GET_KEEPSETTINGS);
2678 #endif
2679
2680 #if defined(HDIO_GET_32BIT)
2681 stress_dev_hd_linux_ioctl_long(fd, HDIO_GET_32BIT);
2682 #endif
2683
2684 #if defined(HDIO_GET_NOWERR)
2685 stress_dev_hd_linux_ioctl_long(fd, HDIO_GET_NOWERR);
2686 #endif
2687
2688 #if defined(HDIO_GET_DMA)
2689 stress_dev_hd_linux_ioctl_long(fd, HDIO_GET_DMA);
2690 #endif
2691
2692 #if defined(HDIO_GET_NICE)
2693 stress_dev_hd_linux_ioctl_long(fd, HDIO_GET_NICE);
2694 #endif
2695
2696 #if defined(HDIO_GET_WCACHE)
2697 stress_dev_hd_linux_ioctl_long(fd, HDIO_GET_WCACHE);
2698 #endif
2699
2700 #if defined(HDIO_GET_ACOUSTIC)
2701 stress_dev_hd_linux_ioctl_long(fd, HDIO_GET_ACOUSTIC);
2702 #endif
2703
2704 #if defined(HDIO_GET_ADDRESS)
2705 stress_dev_hd_linux_ioctl_long(fd, HDIO_GET_ADDRESS);
2706 #endif
2707
2708 #if defined(HDIO_GET_BUSSTATE)
2709 stress_dev_hd_linux_ioctl_long(fd, HDIO_GET_BUSSTATE);
2710 #endif
2711 }
2712 #endif
2713
stress_dev_null_nop(const stress_args_t * args,const int fd,const char * devpath)2714 static void stress_dev_null_nop(
2715 const stress_args_t *args,
2716 const int fd,
2717 const char *devpath)
2718 {
2719 (void)args;
2720 (void)fd;
2721 (void)devpath;
2722 }
2723
2724 /*
2725 * stress_dev_ptp_linux()
2726 * minor exercising of the PTP device
2727 */
stress_dev_ptp_linux(const stress_args_t * args,const int fd,const char * devpath)2728 static void stress_dev_ptp_linux(
2729 const stress_args_t *args,
2730 const int fd,
2731 const char *devpath)
2732 {
2733 #if defined(HAVE_LINUX_PTP_CLOCK_H) && \
2734 defined(PTP_CLOCK_GETCAPS) && \
2735 defined(PTP_PIN_GETFUNC)
2736 int ret;
2737 struct ptp_clock_caps caps;
2738
2739 (void)args;
2740 (void)devpath;
2741
2742 errno = 0;
2743 ret = ioctl(fd, PTP_CLOCK_GETCAPS, &caps);
2744 if (ret == 0) {
2745 int i, pins = caps.n_pins;
2746
2747 for (i = 0; i < pins; i++) {
2748 struct ptp_pin_desc desc;
2749
2750 (void)memset(&desc, 0, sizeof(desc));
2751 desc.index = (unsigned int)i;
2752 ret = ioctl(fd, PTP_PIN_GETFUNC, &desc);
2753 (void)ret;
2754 }
2755 }
2756 #else
2757 (void)args;
2758 (void)fd;
2759 (void)devpath;
2760 #endif
2761 }
2762
2763 #if defined(HAVE_LINUX_FD_H)
2764 /*
2765 * stress_dev_fd_linux()
2766 * minor exercising of the floppy device
2767 */
stress_dev_fd_linux(const stress_args_t * args,const int fd,const char * devpath)2768 static void stress_dev_fd_linux(
2769 const stress_args_t *args,
2770 const int fd,
2771 const char *devpath)
2772 {
2773 (void)args;
2774 (void)fd;
2775 (void)devpath;
2776
2777 #if defined(FDMSGON)
2778 {
2779 int ret;
2780
2781 ret = ioctl(fd, FDMSGON, 0);
2782 (void)ret;
2783 }
2784 #endif
2785
2786 #if defined(FDFLUSH)
2787 {
2788 int ret;
2789
2790 ret = ioctl(fd, FDFLUSH, 0);
2791 (void)ret;
2792 }
2793 #endif
2794
2795 #if defined(FDGETPRM) && \
2796 defined(HAVE_FLOPPY_STRUCT)
2797 {
2798 int ret;
2799 struct floppy_struct floppy;
2800
2801 ret = ioctl(fd, FDGETPRM, &floppy);
2802 if (ret == 0) {
2803 ret = ioctl(fd, FDSETPRM, &floppy);
2804 }
2805 (void)ret;
2806 }
2807 #endif
2808
2809 #if defined(FDGETDRVSTAT) && \
2810 defined(HAVE_FLOPPY_DRIVE_STRUCT)
2811 {
2812 int ret;
2813 struct floppy_drive_struct drive;
2814
2815 ret = ioctl(fd, FDGETDRVSTAT, &drive);
2816 (void)ret;
2817 }
2818 #endif
2819
2820 #if defined(FDPOLLDRVSTAT) && \
2821 defined(HAVE_FLOPPY_DRIVE_STRUCT)
2822 {
2823 int ret;
2824 struct floppy_drive_struct drive;
2825
2826 ret = ioctl(fd, FDPOLLDRVSTAT, &drive);
2827 (void)ret;
2828 }
2829 #endif
2830
2831 #if defined(FDGETDRVTYP)
2832 {
2833 int ret;
2834 char buf[64];
2835
2836 ret = ioctl(fd, FDGETDRVTYP, buf);
2837 (void)ret;
2838 }
2839 #endif
2840
2841 #if defined(FDGETFDCSTAT) && \
2842 defined(HAVE_FLOPPY_FDC_STATE)
2843 {
2844 int ret;
2845 struct floppy_fdc_state state;
2846
2847 ret = ioctl(fd, FDGETFDCSTAT, &state);
2848 (void)ret;
2849
2850 }
2851 #endif
2852
2853 #if defined(FDMSGOFF)
2854 {
2855 int ret;
2856
2857 ret = ioctl(fd, FDMSGOFF, 0);
2858 (void)ret;
2859 }
2860 #endif
2861 }
2862 #endif
2863
2864 /*
2865 * stress_dev_snd_control_linux()
2866 * exercise Linux sound devices
2867 */
stress_dev_snd_control_linux(const stress_args_t * args,const int fd,const char * devpath)2868 static void stress_dev_snd_control_linux(
2869 const stress_args_t *args,
2870 const int fd,
2871 const char *devpath)
2872 {
2873 (void)args;
2874 (void)fd;
2875 (void)devpath;
2876
2877 #if defined(SNDRV_CTL_IOCTL_PVERSION)
2878 {
2879 int ret, ver;
2880
2881 ret = ioctl(fd, SNDRV_CTL_IOCTL_PVERSION, &ver);
2882 (void)ret;
2883 }
2884 #endif
2885
2886 #if defined(SNDRV_CTL_IOCTL_CARD_INFO) && \
2887 defined(HAVE_SND_CTL_CARD_INFO)
2888 {
2889 int ret;
2890 struct snd_ctl_card_info card;
2891
2892 ret = ioctl(fd, SNDRV_CTL_IOCTL_CARD_INFO, &card);
2893 (void)ret;
2894 }
2895 #endif
2896
2897 #if defined(SNDRV_CTL_IOCTL_TLV_READ) && \
2898 defined(HAVE_SND_CTL_TLV)
2899 {
2900 int ret;
2901 struct tlv_buf {
2902 struct snd_ctl_tlv tlv;
2903 unsigned int data[4];
2904 } buf;
2905
2906 /* intentionally will fail with -EINVAL */
2907 buf.tlv.numid = 0;
2908 buf.tlv.length = sizeof(buf.data);
2909 ret = ioctl(fd, SNDRV_CTL_IOCTL_TLV_READ, (struct snd_ctl_tlv *)&buf.tlv);
2910 (void)ret;
2911
2912 /* intentionally will fail with -ENOENT */
2913 buf.tlv.numid = ~0U;
2914 buf.tlv.length = sizeof(buf.data);
2915 ret = ioctl(fd, SNDRV_CTL_IOCTL_TLV_READ, (struct snd_ctl_tlv *)&buf.tlv);
2916 (void)ret;
2917 }
2918 #endif
2919
2920 #if defined(SNDRV_CTL_IOCTL_POWER_STATE)
2921 {
2922 int ret, state;
2923
2924 ret = ioctl(fd, SNDRV_CTL_IOCTL_POWER_STATE, &state);
2925 #if defined(SNDRV_CTL_IOCTL_POWER)
2926 if (ret == 0)
2927 ret = ioctl(fd, SNDRV_CTL_IOCTL_POWER, &state);
2928 #endif
2929 (void)ret;
2930 }
2931 #endif
2932 }
2933
2934 #if defined(__linux__)
2935 /*
2936 * stress_dev_hwrng_linux()
2937 * Exercise Linux Hardware Random Number Generator
2938 */
stress_dev_hwrng_linux(const stress_args_t * args,const int fd,const char * devpath)2939 static void stress_dev_hwrng_linux(
2940 const stress_args_t *args,
2941 const int fd,
2942 const char *devpath)
2943 {
2944 ssize_t ret;
2945 off_t offset = (off_t)0;
2946 char buffer[8];
2947
2948 (void)args;
2949 (void)devpath;
2950
2951 offset = lseek(fd, offset, SEEK_SET);
2952 (void)offset;
2953
2954 ret = read(fd, buffer, sizeof(buffer));
2955 (void)ret;
2956 }
2957 #endif
2958
2959 #if defined(__linux__)
2960
2961 #if defined(PP_IOCT) && \
2962 !defined(PPGETTIME32)
2963 #define PPGETTIME32 _IOR(PP_IOCTL, 0x95, int32_t[2])
2964 #endif
2965 #if defined(PP_IOCT) && \
2966 !defined(PPGETTIME64)
2967 #define PPGETTIME64 _IOR(PP_IOCTL, 0x95, int64_t[2])
2968 #endif
2969
2970 /*
2971 * stress_dev_parport_linux()
2972 * Exercise Linux parallel port
2973 */
stress_dev_parport_linux(const stress_args_t * args,const int fd,const char * devpath)2974 static void stress_dev_parport_linux(
2975 const stress_args_t *args,
2976 const int fd,
2977 const char *devpath)
2978 {
2979 #if defined(PPCLAIM) && \
2980 defined(PPRELEASE)
2981 bool claimed = false;
2982 #endif
2983
2984 (void)args;
2985 (void)fd;
2986 (void)devpath;
2987
2988 /*
2989 * We don't do a PPCLAIM or PPRELEASE on all
2990 * the stressor instances since this the claim
2991 * can indefinitely block and this stops the
2992 * progress of the stressor. Just do this for
2993 * instance 0. For other instances we run
2994 * run without claiming and this will cause
2995 * some of the ioctls to fail.
2996 */
2997 #if defined(PPCLAIM) && \
2998 defined(PPRELEASE)
2999 if (args->instance == 0) {
3000 int ret;
3001
3002 ret = shim_pthread_spin_lock(&parport_lock);
3003 if (ret == 0) {
3004 ret = ioctl(fd, PPCLAIM);
3005 if (ret == 0)
3006 claimed = true;
3007 }
3008 }
3009 #endif
3010
3011 #if defined(PPGETMODE)
3012 {
3013 int ret, mode;
3014
3015 ret = ioctl(fd, PPGETMODE, &mode);
3016 #if defined(PPSETMODE)
3017 errno = 0;
3018 if (ret == 0)
3019 ret = ioctl(fd, PPSETMODE, &mode);
3020 #endif
3021 (void)ret;
3022 }
3023 #endif
3024
3025 #if defined(PPGETPHASE)
3026 {
3027 int ret, phase;
3028
3029 ret = ioctl(fd, PPGETPHASE, &phase);
3030 #if defined(PPSETPHASE)
3031 errno = 0;
3032 if (ret == 0)
3033 ret = ioctl(fd, PPSETPHASE, &phase);
3034 #endif
3035 (void)ret;
3036 }
3037 #endif
3038
3039 #if defined(PPGETMODES)
3040 {
3041 int ret, modes;
3042
3043 ret = ioctl(fd, PPGETMODES, &modes);
3044 (void)ret;
3045 }
3046 #endif
3047
3048 #if defined(PPGETFLAGS)
3049 {
3050 int ret, uflags;
3051
3052 ret = ioctl(fd, PPGETFLAGS, &uflags);
3053 #if defined(PPSETFLAGS)
3054 errno = 0;
3055 if (ret == 0)
3056 ret = ioctl(fd, PPSETFLAGS, &uflags);
3057 #endif
3058 (void)ret;
3059 }
3060 #endif
3061
3062 #if defined(PPRSTATUS)
3063 {
3064 int ret;
3065 char reg;
3066
3067 ret = ioctl(fd, PPRSTATUS, ®);
3068 (void)ret;
3069 }
3070 #endif
3071
3072 #if defined(PPRCONTROL)
3073 {
3074 int ret;
3075 char reg;
3076
3077 ret = ioctl(fd, PPRCONTROL, ®);
3078 (void)ret;
3079 }
3080 #endif
3081
3082 #if defined(PPGETTIME32)
3083 {
3084 int ret;
3085 int32_t time32[2];
3086
3087 ret = ioctl(fd, PPGETTIME32, time32);
3088 (void)ret;
3089 }
3090 #endif
3091
3092 #if defined(PPGETTIME64)
3093 {
3094 int ret;
3095 int64_t time64[2];
3096
3097 ret = ioctl(fd, PPGETTIME64, time64);
3098 (void)ret;
3099 }
3100 #endif
3101
3102 #if defined(PPYIELD)
3103 {
3104 int ret;
3105
3106 ret = ioctl(fd, PPYIELD);
3107 (void)ret;
3108 }
3109 #endif
3110
3111
3112 #if defined(PPCLAIM) && \
3113 defined(PPRELEASE)
3114 if ((args->instance == 0) && claimed) {
3115 int ret;
3116
3117 ret = ioctl(fd, PPRELEASE);
3118 (void)ret;
3119 ret = shim_pthread_spin_unlock(&parport_lock);
3120 (void)ret;
3121 }
3122 #endif
3123 }
3124 #endif
3125
3126
3127 #define DEV_FUNC(dev, func) \
3128 { dev, sizeof(dev) - 1, func }
3129
3130 static const stress_dev_func_t dev_funcs[] = {
3131 #if defined(__linux__) && \
3132 defined(HAVE_LINUX_MEDIA_H) && \
3133 defined(MEDIA_IOC_DEVICE_INFO)
3134 DEV_FUNC("/dev/media", stress_dev_media_linux),
3135 #endif
3136 #if defined(HAVE_LINUX_VT_H)
3137 DEV_FUNC("/dev/vcs", stress_dev_vcs_linux),
3138 #endif
3139 #if defined(HAVE_LINUX_DM_IOCTL_H)
3140 DEV_FUNC("/dev/dm", stress_dev_dm_linux),
3141 #endif
3142 #if defined(HAVE_LINUX_VIDEODEV2_H)
3143 DEV_FUNC("/dev/video", stress_dev_video_linux),
3144 #endif
3145 #if defined(HAVE_LINUX_RANDOM_H)
3146 DEV_FUNC("/dev/random", stress_dev_random_linux),
3147 #endif
3148 #if defined(__linux__)
3149 DEV_FUNC("/dev/mem", stress_dev_mem_linux),
3150 DEV_FUNC("/dev/kmem", stress_dev_kmem_linux),
3151 DEV_FUNC("/dev/kmsg", stress_dev_kmsg_linux),
3152 DEV_FUNC("/dev/nvram", stress_dev_nvram_linux),
3153 DEV_FUNC("/dev/cdrom", stress_dev_cdrom_linux),
3154 DEV_FUNC("/dev/sg", stress_dev_scsi_generic_linux),
3155 DEV_FUNC("/dev/sr0", stress_dev_cdrom_linux),
3156 DEV_FUNC("/dev/console",stress_dev_console_linux),
3157 #endif
3158 #if defined(__linux__) && \
3159 defined(STRESS_ARCH_X86)
3160 DEV_FUNC("/dev/port", stress_dev_port_linux),
3161 #endif
3162 #if defined(HAVE_LINUX_HPET_H)
3163 DEV_FUNC("/dev/hpet", stress_dev_hpet_linux),
3164 #endif
3165 DEV_FUNC("/dev/null", stress_dev_null_nop),
3166 DEV_FUNC("/dev/ptp", stress_dev_ptp_linux),
3167 DEV_FUNC("/dev/snd/control", stress_dev_snd_control_linux),
3168 #if defined(HAVE_LINUX_FD_H) && \
3169 defined(HAVE_FLOPPY_STRUCT)
3170 DEV_FUNC("/dev/fd", stress_dev_fd_linux),
3171 #endif
3172 #if defined(__linux__)
3173 DEV_FUNC("/dev/hwrng", stress_dev_hwrng_linux),
3174 #endif
3175 #if defined(__linux__)
3176 DEV_FUNC("/dev/parport",stress_dev_parport_linux),
3177 #endif
3178 };
3179
stress_dev_procname(const char * path)3180 static void stress_dev_procname(const char *path)
3181 {
3182 /*
3183 * Set process name to enable debugging if it gets stuck
3184 */
3185 if (!(g_opt_flags & OPT_FLAGS_KEEP_NAME)) {
3186 char procname[55];
3187
3188 (void)snprintf(procname, sizeof(procname), "stress-ng-dev:%-40.40s", path);
3189 #if defined(HAVE_BSD_UNISTD_H) && \
3190 defined(HAVE_SETPROCTITLE)
3191 /* Sets argv[0] */
3192 setproctitle("-%s", procname);
3193 #endif
3194 }
3195 }
3196
stress_dev_lock(const char * path,const int fd)3197 static inline int stress_dev_lock(const char *path, const int fd)
3198 {
3199 errno = 0;
3200 #if defined(TIOCEXCL) && \
3201 defined(TIOCNXCL)
3202 {
3203 int ret;
3204
3205 if (strncmp(path, "/dev/tty", 8))
3206 return 0;
3207
3208 ret = ioctl(fd, TIOCEXCL);
3209 if (ret < 0)
3210 return ret;
3211 }
3212
3213 #if defined(LOCK_EX) && \
3214 defined(LOCK_NB) && \
3215 defined(LOCK_UN)
3216 {
3217 int ret;
3218
3219 ret = flock(fd, LOCK_EX | LOCK_NB);
3220 if (ret < 0) {
3221 ret = ioctl(fd, TIOCNXCL);
3222 (void)ret;
3223 return -1;
3224 }
3225 }
3226 #endif
3227 return 0;
3228 #else
3229 (void)path;
3230 (void)fd;
3231
3232 return 0;
3233 #endif
3234 }
3235
stress_dev_unlock(const char * path,const int fd)3236 static inline void stress_dev_unlock(const char *path, const int fd)
3237 {
3238 #if defined(TIOCEXCL) && \
3239 defined(TIOCNXCL)
3240 int ret;
3241
3242 if (strncmp(path, "/dev/tty", 8))
3243 return;
3244
3245 #if defined(LOCK_EX) && \
3246 defined(LOCK_NB) && \
3247 defined(LOCK_UN)
3248 ret = flock(fd, LOCK_UN);
3249 (void)ret;
3250 #endif
3251 ret = ioctl(fd, TIOCNXCL);
3252 (void)ret;
3253 #else
3254 (void)path;
3255 (void)fd;
3256 #endif
3257 }
3258
stress_dev_open_lock(const stress_args_t * args,stress_dev_hash_info_t * dev_hash_info,const int mode)3259 static int stress_dev_open_lock(
3260 const stress_args_t *args,
3261 stress_dev_hash_info_t *dev_hash_info,
3262 const int mode)
3263 {
3264 int fd, ret;
3265
3266 fd = stress_open_timeout(args->name, dev_hash_info->dev_path, mode, 250000000);
3267 if (fd < 0) {
3268 if (errno == EBUSY)
3269 dev_hash_info->open_fail = true;
3270 return -1;
3271 }
3272 ret = stress_dev_lock(dev_hash_info->dev_path, fd);
3273 if (ret < 0) {
3274 (void)close(fd);
3275 return -1;
3276 }
3277 return fd;
3278 }
3279
stress_dev_close_unlock(const char * path,const int fd)3280 static int stress_dev_close_unlock(const char *path, const int fd)
3281 {
3282 stress_dev_unlock(path, fd);
3283 return close(fd);
3284 }
3285
3286 /*
3287 * stress_dev_rw()
3288 * exercise a dev entry
3289 */
stress_dev_rw(const stress_args_t * args,int32_t loops)3290 static inline void stress_dev_rw(
3291 const stress_args_t *args,
3292 int32_t loops)
3293 {
3294 int fd, ret;
3295 off_t offset;
3296 struct stat buf;
3297 struct pollfd fds[1];
3298 fd_set rfds;
3299 const double threshold = 0.25;
3300
3301 while ((loops == -1) || (loops > 0)) {
3302 double t_start;
3303 bool timeout = false;
3304 char *ptr;
3305 size_t i;
3306 #if defined(HAVE_TERMIOS_H) && \
3307 defined(TCGETS) && \
3308 defined(HAVE_TERMIOS)
3309 struct termios tios;
3310 #endif
3311 stress_dev_hash_info_t *dev_hash_info;
3312 char *path;
3313
3314 ret = shim_pthread_spin_lock(&lock);
3315 if (ret)
3316 return;
3317 dev_hash_info = stress_dev_hash_info;
3318 (void)shim_pthread_spin_unlock(&lock);
3319
3320 if (!dev_hash_info || !keep_stressing_flag())
3321 break;
3322
3323 path = dev_hash_info->dev_path;
3324
3325 if (dev_hash_info->open_fail)
3326 goto next;
3327
3328 t_start = stress_time_now();
3329
3330 fd = stress_dev_open_lock(args, dev_hash_info, O_RDONLY | O_NONBLOCK | O_NDELAY);
3331 if (fd < 0)
3332 goto next;
3333
3334 if (stress_time_now() - t_start > threshold) {
3335 timeout = true;
3336 stress_dev_close_unlock(path, fd);
3337 goto next;
3338 }
3339
3340 if (fstat(fd, &buf) < 0) {
3341 pr_fail("%s: stat failed on %s, errno=%d (%s)\n",
3342 args->name, path, errno, strerror(errno));
3343 } else {
3344 if ((S_ISBLK(buf.st_mode) | (S_ISCHR(buf.st_mode))) == 0) {
3345 stress_dev_close_unlock(path, fd);
3346 goto next;
3347 }
3348 }
3349
3350 if (S_ISBLK(buf.st_mode)) {
3351 stress_dev_blk(args, fd, path);
3352 stress_dev_scsi_blk(args, fd, dev_hash_info);
3353 #if defined(HAVE_LINUX_HDREG_H)
3354 stress_dev_hd_linux(args, fd, path);
3355 #endif
3356 }
3357 #if defined(HAVE_TERMIOS_H) && \
3358 defined(TCGETS) && \
3359 defined(HAVE_TERMIOS)
3360 if (S_ISCHR(buf.st_mode) &&
3361 strncmp("/dev/vsock", path, 10) &&
3362 strncmp("/dev/dri", path, 8) &&
3363 (ioctl(fd, TCGETS, &tios) == 0))
3364 stress_dev_tty(args, fd, path);
3365 #endif
3366
3367 offset = lseek(fd, 0, SEEK_SET);
3368 stress_uint64_put((uint64_t)offset);
3369 offset = lseek(fd, 0, SEEK_CUR);
3370 stress_uint64_put((uint64_t)offset);
3371 offset = lseek(fd, 0, SEEK_END);
3372 stress_uint64_put((uint64_t)offset);
3373
3374 if (stress_time_now() - t_start > threshold) {
3375 timeout = true;
3376 stress_dev_close_unlock(path, fd);
3377 goto next;
3378 }
3379
3380 FD_ZERO(&rfds);
3381 fds[0].fd = fd;
3382 fds[0].events = POLLIN;
3383 ret = poll(fds, 1, 0);
3384 (void)ret;
3385
3386 if (stress_time_now() - t_start > threshold) {
3387 timeout = true;
3388 stress_dev_close_unlock(path, fd);
3389 goto next;
3390 }
3391
3392 #if !defined(__NetBSD__)
3393 {
3394 struct timeval tv;
3395 fd_set wfds;
3396
3397 FD_ZERO(&rfds);
3398 FD_SET(fd, &rfds);
3399 FD_ZERO(&wfds);
3400 FD_SET(fd, &wfds);
3401 tv.tv_sec = 0;
3402 tv.tv_usec = 10000;
3403 ret = select(fd + 1, &rfds, &wfds, NULL, &tv);
3404 (void)ret;
3405
3406 if (stress_time_now() - t_start > threshold) {
3407 timeout = true;
3408 stress_dev_close_unlock(path, fd);
3409 goto next;
3410 }
3411 }
3412 #endif
3413
3414 #if defined(F_GETFD)
3415 ret = fcntl(fd, F_GETFD, NULL);
3416 (void)ret;
3417
3418 if (stress_time_now() - t_start > threshold) {
3419 timeout = true;
3420 stress_dev_close_unlock(path, fd);
3421 goto next;
3422 }
3423 #endif
3424 #if defined(F_GETFL)
3425 ret = fcntl(fd, F_GETFL, NULL);
3426 (void)ret;
3427
3428 if (stress_time_now() - t_start > threshold) {
3429 timeout = true;
3430 stress_dev_close_unlock(path, fd);
3431 goto next;
3432 }
3433 #endif
3434 #if defined(F_GETSIG)
3435 ret = fcntl(fd, F_GETSIG, NULL);
3436 (void)ret;
3437
3438 if (stress_time_now() - t_start > threshold) {
3439 timeout = true;
3440 stress_dev_close_unlock(path, fd);
3441 goto next;
3442 }
3443 #endif
3444 ptr = mmap(NULL, args->page_size, PROT_READ, MAP_PRIVATE, fd, 0);
3445 if (ptr != MAP_FAILED)
3446 (void)munmap(ptr, args->page_size);
3447 ptr = mmap(NULL, args->page_size, PROT_READ, MAP_SHARED, fd, 0);
3448 if (ptr != MAP_FAILED)
3449 (void)munmap(ptr, args->page_size);
3450 (void)stress_dev_close_unlock(path, fd);
3451
3452 if (stress_time_now() - t_start > threshold) {
3453 timeout = true;
3454 goto next;
3455 }
3456
3457 fd = stress_dev_open_lock(args, dev_hash_info, O_RDONLY | O_NONBLOCK | O_NDELAY);
3458 if (fd < 0)
3459 goto next;
3460
3461 ptr = mmap(NULL, args->page_size, PROT_WRITE, MAP_PRIVATE, fd, 0);
3462 if (ptr != MAP_FAILED)
3463 (void)munmap(ptr, args->page_size);
3464 ptr = mmap(NULL, args->page_size, PROT_WRITE, MAP_SHARED, fd, 0);
3465 if (ptr != MAP_FAILED)
3466 (void)munmap(ptr, args->page_size);
3467
3468 ret = shim_fsync(fd);
3469 (void)ret;
3470
3471 for (i = 0; i < SIZEOF_ARRAY(dev_funcs); i++) {
3472 if (!strncmp(path, dev_funcs[i].devpath, dev_funcs[i].devpath_len))
3473 dev_funcs[i].func(args, fd, path);
3474 }
3475 stress_dev_close_unlock(path, fd);
3476 if (stress_time_now() - t_start > threshold) {
3477 timeout = true;
3478 goto next;
3479 }
3480 /*
3481 * O_RDONLY | O_WRONLY allows one to
3482 * use the fd for ioctl() only operations
3483 */
3484 fd = stress_dev_open_lock(args, dev_hash_info, O_RDONLY | O_WRONLY);
3485 if (fd < 0) {
3486 if (errno == EINTR)
3487 dev_hash_info->open_fail = true;
3488 } else {
3489 stress_dev_close_unlock(path, fd);
3490 }
3491
3492 next:
3493 if (loops > 0) {
3494 if (timeout)
3495 break;
3496 loops--;
3497 }
3498 }
3499 }
3500
3501 /*
3502 * stress_dev_thread
3503 * keep exercising a /dev entry until
3504 * controlling thread triggers an exit
3505 */
stress_dev_thread(void * arg)3506 static void *stress_dev_thread(void *arg)
3507 {
3508 static void *nowt = NULL;
3509 const stress_pthread_args_t *pa = (stress_pthread_args_t *)arg;
3510 const stress_args_t *args = pa->args;
3511
3512 /*
3513 * Block all signals, let controlling thread
3514 * handle these
3515 */
3516 (void)sigprocmask(SIG_BLOCK, &set, NULL);
3517
3518 while (keep_stressing_flag())
3519 stress_dev_rw(args, -1);
3520
3521 return &nowt;
3522 }
3523
3524 /*
3525 * stress_dev_file()
3526 * stress a specific device file
3527 */
stress_dev_file(const stress_args_t * args,char * path)3528 static void stress_dev_file(const stress_args_t *args, char *path)
3529 {
3530 int ret;
3531 int32_t loops = args->instance < 8 ? (int32_t)args->instance + 1 : 8;
3532 stress_dev_hash_info_t dev_hash_info;
3533
3534 dev_hash_info.dev_path = path;
3535
3536 ret = shim_pthread_spin_lock(&lock);
3537 if (!ret) {
3538 stress_dev_hash_info = &dev_hash_info;
3539 (void)shim_pthread_spin_unlock(&lock);
3540 stress_dev_rw(args, loops);
3541 inc_counter(args);
3542 }
3543 }
3544
3545 /*
3546 * stress_dev_dir()
3547 * stress all device files
3548 */
stress_dev_files(const stress_args_t * args)3549 static void stress_dev_files(const stress_args_t *args)
3550 {
3551 int32_t loops = args->instance < 8 ? (int32_t)args->instance + 1 : 8;
3552 static int try_failed;
3553 size_t i;
3554
3555 if (!keep_stressing_flag())
3556 return;
3557
3558 for (i = 0; keep_stressing(args) && (i < STRESS_DEV_HASH_SIZE); i++) {
3559 stress_dev_hash_info_t *dev_hash_info;
3560
3561 for (dev_hash_info = stress_dev_hash[i];
3562 keep_stressing(args) && dev_hash_info;
3563 dev_hash_info = dev_hash_info->next) {
3564 int ret;
3565
3566 if (dev_hash_info->open_fail)
3567 continue;
3568 /* Limit the number of locked up try failures */
3569 if (try_failed > STRESS_DEV_OPEN_TRIES_MAX)
3570 continue;
3571 stress_dev_procname(dev_hash_info->dev_path);
3572
3573 /* If it was opened OK before, no need for try_open check */
3574 if (!dev_hash_info->open_ok) {
3575 ret = stress_try_open(args, dev_hash_info->dev_path, O_RDONLY | O_NONBLOCK | O_NDELAY, 1500000000);
3576 if (ret == STRESS_TRY_OPEN_FAIL) {
3577 dev_hash_info->open_fail = true;
3578 try_failed++;
3579 continue;
3580 }
3581 if (ret == STRESS_TRY_AGAIN)
3582 continue;
3583 }
3584 ret = shim_pthread_spin_lock(&lock);
3585 if (!ret) {
3586 stress_dev_hash_info = dev_hash_info;
3587 (void)shim_pthread_spin_unlock(&lock);
3588 stress_dev_rw(args, loops);
3589 inc_counter(args);
3590 }
3591 dev_hash_info->open_ok = true;
3592 }
3593 }
3594 }
3595
3596 /*
3597 * stress_dev
3598 * stress reading all of /dev
3599 */
stress_dev(const stress_args_t * args)3600 static int stress_dev(const stress_args_t *args)
3601 {
3602 pthread_t pthreads[STRESS_DEV_THREADS_MAX];
3603 int ret[STRESS_DEV_THREADS_MAX], rc = EXIT_SUCCESS;
3604 stress_pthread_args_t pa;
3605 char *dev_file = NULL;
3606 const int stdout_fd = fileno(stdout);
3607 const char *tty_name = (stdout_fd >= 0) ? ttyname(stdout_fd) : NULL;
3608 stress_dev_hash_info_t dev_null = { "/dev/null", NULL, false, false, false };
3609
3610 stress_dev_hash_info = &dev_null;
3611 pa.args = args;
3612 pa.data = NULL;
3613
3614 (void)memset(ret, 0, sizeof(ret));
3615
3616 (void)stress_get_setting("dev-file", &dev_file);
3617 if (dev_file) {
3618 mode_t mode;
3619 struct stat statbuf;
3620
3621 if (stat(dev_file, &statbuf) < 0) {
3622 pr_fail("%s: cannot access file %s\n",
3623 args->name, dev_file);
3624 return EXIT_FAILURE;
3625 }
3626 mode = statbuf.st_mode & S_IFMT;
3627 if ((mode != S_IFBLK) && (mode != S_IFCHR)) {
3628 pr_fail("%s: file %s is not a character or block device\n",
3629 args->name, dev_file);
3630 return EXIT_FAILURE;
3631 }
3632 }
3633
3634 if (!dev_file)
3635 stress_dev_dir(args, "/dev", 0, tty_name);
3636
3637 stress_set_proc_state(args->name, STRESS_STATE_RUN);
3638
3639 do {
3640 pid_t pid;
3641
3642 again:
3643 pid = fork();
3644 if (pid < 0) {
3645 if (stress_redo_fork(errno))
3646 goto again;
3647 } else if (pid > 0) {
3648 int status, wret;
3649
3650 (void)setpgid(pid, g_pgrp);
3651 /* Parent, wait for child */
3652 wret = waitpid(pid, &status, 0);
3653 if (wret < 0) {
3654 if (errno != EINTR)
3655 pr_dbg("%s: waitpid(): errno=%d (%s)\n",
3656 args->name, errno, strerror(errno));
3657 /* Ring ring, time to die */
3658 (void)kill(pid, SIGALRM);
3659 wret = shim_waitpid(pid, &status, 0);
3660 (void)wret;
3661 } else {
3662 if (WIFEXITED(status) &&
3663 WEXITSTATUS(status) != 0) {
3664 rc = EXIT_FAILURE;
3665 break;
3666 }
3667 }
3668 } else {
3669 size_t i;
3670 int r;
3671
3672 (void)setpgid(0, g_pgrp);
3673 stress_parent_died_alarm();
3674 (void)sched_settings_apply(true);
3675 rc = shim_pthread_spin_init(&lock, SHIM_PTHREAD_PROCESS_SHARED);
3676 if (rc) {
3677 pr_inf("%s: pthread_spin_init failed, errno=%d (%s)\n",
3678 args->name, rc, strerror(rc));
3679 _exit(EXIT_NO_RESOURCE);
3680 }
3681 rc = shim_pthread_spin_init(&parport_lock, SHIM_PTHREAD_PROCESS_SHARED);
3682 if (rc) {
3683 pr_inf("%s: pthread_spin_init failed, errno=%d (%s)\n",
3684 args->name, rc, strerror(rc));
3685 _exit(EXIT_NO_RESOURCE);
3686 }
3687
3688 /* Make sure this is killable by OOM killer */
3689 stress_set_oom_adjustment(args->name, true);
3690
3691 for (i = 0; i < STRESS_DEV_THREADS_MAX; i++) {
3692 ret[i] = pthread_create(&pthreads[i], NULL,
3693 stress_dev_thread, (void *)&pa);
3694 }
3695
3696 do {
3697 if (dev_file)
3698 stress_dev_file(args, dev_file);
3699 else
3700 stress_dev_files(args);
3701 } while (keep_stressing(args));
3702
3703 r = shim_pthread_spin_lock(&lock);
3704 if (r) {
3705 pr_dbg("%s: failed to lock spin lock for dev_path\n", args->name);
3706 } else {
3707 stress_dev_hash_info = NULL;
3708 r = shim_pthread_spin_unlock(&lock);
3709 (void)r;
3710 }
3711
3712 for (i = 0; i < STRESS_DEV_THREADS_MAX; i++) {
3713 if (ret[i] == 0)
3714 (void)pthread_join(pthreads[i], NULL);
3715 }
3716 _exit(EXIT_SUCCESS);
3717 }
3718 } while (keep_stressing(args));
3719
3720 stress_set_proc_state(args->name, STRESS_STATE_DEINIT);
3721 (void)shim_pthread_spin_destroy(&lock);
3722
3723 /*
3724 * Ensure we don't get build warnings if these are not
3725 * referenced.
3726 */
3727 (void)ioctl_set_timeout;
3728 (void)ioctl_clr_timeout;
3729
3730 if (!dev_file)
3731 stress_dev_free();
3732
3733 return rc;
3734 }
3735 stressor_info_t stress_dev_info = {
3736 .stressor = stress_dev,
3737 .class = CLASS_DEV | CLASS_OS,
3738 .opt_set_funcs = opt_set_funcs,
3739 .help = help
3740 };
3741 #else
3742 stressor_info_t stress_dev_info = {
3743 .stressor = stress_not_implemented,
3744 .class = CLASS_DEV | CLASS_OS,
3745 .opt_set_funcs = opt_set_funcs,
3746 .help = help
3747 };
3748 #endif
3749