1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (c) 2015-2016 Cyril Hrubis <chrubis@suse.cz>
4 * Copyright (c) Linux Test Project, 2016-2024
5 */
6
7 #define _GNU_SOURCE
8
9 #include <limits.h>
10 #include <stdio.h>
11 #include <stdarg.h>
12 #include <unistd.h>
13 #include <string.h>
14 #include <stdlib.h>
15 #include <errno.h>
16 #include <sys/mount.h>
17 #include <sys/types.h>
18 #include <sys/utsname.h>
19 #include <sys/wait.h>
20 #include <math.h>
21
22 #define TST_NO_DEFAULT_MAIN
23 #include "tst_test.h"
24 #include "tst_device.h"
25 #include "lapi/abisize.h"
26 #include "lapi/futex.h"
27 #include "lapi/syscalls.h"
28 #include "tst_ansi_color.h"
29 #include "tst_safe_stdio.h"
30 #include "tst_timer_test.h"
31 #include "tst_clocks.h"
32 #include "tst_timer.h"
33 #include "tst_wallclock.h"
34 #include "tst_sys_conf.h"
35 #include "tst_kconfig.h"
36 #include "tst_private.h"
37 #include "old_resource.h"
38 #include "old_device.h"
39 #include "old_tmpdir.h"
40 #include "ltp-version.h"
41
42 /*
43 * Hack to get TCID defined in newlib tests
44 */
45 const char *TCID __attribute__((weak));
46
47 /* update also docparse/testinfo.pl */
48 #define LINUX_GIT_URL "https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id="
49 #define LINUX_STABLE_GIT_URL "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id="
50 #define GLIBC_GIT_URL "https://sourceware.org/git/?p=glibc.git;a=commit;h="
51 #define MUSL_GIT_URL "https://git.musl-libc.org/cgit/musl/commit/src/linux/clone.c?id="
52 #define CVE_DB_URL "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-"
53
54 #define DEFAULT_TIMEOUT 30
55
56 struct tst_test *tst_test;
57
58 static const char *tid;
59 static int iterations = 1;
60 static float duration = -1;
61 static float timeout_mul = -1;
62 static pid_t main_pid, lib_pid;
63 static int mntpoint_mounted;
64 static int ovl_mounted;
65 static struct timespec tst_start_time; /* valid only for test pid */
66 static int tdebug;
67
68 struct results {
69 int passed;
70 int skipped;
71 int failed;
72 int warnings;
73 int broken;
74 unsigned int runtime;
75 unsigned int overall_time;
76 };
77
78 static struct results *results;
79
80 static int ipc_fd;
81
82 extern void *tst_futexes;
83 extern unsigned int tst_max_futexes;
84
85 static char ipc_path[1064];
86 const char *tst_ipc_path = ipc_path;
87
88 static char shm_path[1024];
89
90 int TST_ERR;
91 int TST_PASS;
92 long TST_RET;
93
94 static void do_cleanup(void);
95 static void do_exit(int ret) __attribute__ ((noreturn));
96
setup_ipc(void)97 static void setup_ipc(void)
98 {
99 size_t size = getpagesize();
100
101 if (access("/dev/shm", F_OK) == 0) {
102 snprintf(shm_path, sizeof(shm_path), "/dev/shm/ltp_%s_%d",
103 tid, getpid());
104 } else {
105 char *tmpdir;
106
107 if (!tst_tmpdir_created())
108 tst_tmpdir();
109
110 tmpdir = tst_get_tmpdir();
111 snprintf(shm_path, sizeof(shm_path), "%s/ltp_%s_%d",
112 tmpdir, tid, getpid());
113 free(tmpdir);
114 }
115
116 ipc_fd = open(shm_path, O_CREAT | O_EXCL | O_RDWR, 0600);
117 if (ipc_fd < 0)
118 tst_brk(TBROK | TERRNO, "open(%s)", shm_path);
119 SAFE_CHMOD(shm_path, 0666);
120
121 SAFE_FTRUNCATE(ipc_fd, size);
122
123 results = SAFE_MMAP(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, ipc_fd, 0);
124
125 /* Checkpoints needs to be accessible from processes started by exec() */
126 if (tst_test->needs_checkpoints || tst_test->child_needs_reinit) {
127 sprintf(ipc_path, IPC_ENV_VAR "=%s", shm_path);
128 putenv(ipc_path);
129 } else {
130 SAFE_UNLINK(shm_path);
131 }
132
133 SAFE_CLOSE(ipc_fd);
134
135 if (tst_test->needs_checkpoints) {
136 tst_futexes = (char *)results + sizeof(struct results);
137 tst_max_futexes = (size - sizeof(struct results))/sizeof(futex_t);
138 }
139 }
140
cleanup_ipc(void)141 static void cleanup_ipc(void)
142 {
143 size_t size = getpagesize();
144
145 if (ipc_fd > 0 && close(ipc_fd))
146 tst_res(TWARN | TERRNO, "close(ipc_fd) failed");
147
148 if (shm_path[0] && !access(shm_path, F_OK) && unlink(shm_path))
149 tst_res(TWARN | TERRNO, "unlink(%s) failed", shm_path);
150
151 if (results) {
152 msync((void *)results, size, MS_SYNC);
153 munmap((void *)results, size);
154 results = NULL;
155 }
156 }
157
tst_reinit(void)158 void tst_reinit(void)
159 {
160 const char *path = getenv(IPC_ENV_VAR);
161 size_t size = getpagesize();
162 int fd;
163
164 if (!path)
165 tst_brk(TBROK, IPC_ENV_VAR" is not defined");
166
167 if (access(path, F_OK))
168 tst_brk(TBROK, "File %s does not exist!", path);
169
170 fd = SAFE_OPEN(path, O_RDWR);
171
172 results = SAFE_MMAP(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
173 tst_futexes = (char *)results + sizeof(struct results);
174 tst_max_futexes = (size - sizeof(struct results))/sizeof(futex_t);
175
176 SAFE_CLOSE(fd);
177 }
178
179 extern char **environ;
180
params_array_len(char * const array[])181 static unsigned int params_array_len(char *const array[])
182 {
183 unsigned int ret = 0;
184
185 if (!array)
186 return 0;
187
188 while (*(array++))
189 ret++;
190
191 return ret;
192 }
193
tst_run_script(const char * script_name,char * const params[])194 int tst_run_script(const char *script_name, char *const params[])
195 {
196 int pid;
197 unsigned int i, params_len = params_array_len(params);
198 char *argv[params_len + 2];
199
200 if (!tst_test->runs_script)
201 tst_brk(TBROK, "runs_script flag must be set!");
202
203 argv[0] = (char*)script_name;
204
205 if (params) {
206 for (i = 0; i < params_len; i++)
207 argv[i+1] = params[i];
208 }
209
210 argv[params_len+1] = NULL;
211
212 pid = SAFE_FORK();
213 if (pid)
214 return pid;
215
216 execvpe(script_name, argv, environ);
217
218 tst_brk(TBROK | TERRNO, "execvpe(%s, ...) failed!", script_name);
219
220 return -1;
221 }
222
update_results(int ttype)223 static void update_results(int ttype)
224 {
225 if (!results)
226 return;
227
228 switch (ttype) {
229 case TCONF:
230 tst_atomic_inc(&results->skipped);
231 break;
232 case TPASS:
233 tst_atomic_inc(&results->passed);
234 break;
235 case TWARN:
236 tst_atomic_inc(&results->warnings);
237 break;
238 case TFAIL:
239 tst_atomic_inc(&results->failed);
240 break;
241 case TBROK:
242 tst_atomic_inc(&results->broken);
243 break;
244 }
245 }
246
print_result(const char * file,const int lineno,int ttype,const char * fmt,va_list va)247 static void print_result(const char *file, const int lineno, int ttype,
248 const char *fmt, va_list va)
249 {
250 char buf[1024];
251 char *str = buf;
252 int ret, size = sizeof(buf), ssize, int_errno, buflen;
253 const char *str_errno = NULL;
254 const char *res;
255
256 switch (TTYPE_RESULT(ttype)) {
257 case TPASS:
258 res = "TPASS";
259 break;
260 case TFAIL:
261 res = "TFAIL";
262 break;
263 case TBROK:
264 res = "TBROK";
265 break;
266 case TCONF:
267 res = "TCONF";
268 break;
269 case TWARN:
270 res = "TWARN";
271 break;
272 case TINFO:
273 res = "TINFO";
274 break;
275 case TDEBUG:
276 res = "TDEBUG";
277 break;
278 default:
279 tst_brk(TBROK, "Invalid ttype value %i", ttype);
280 abort();
281 }
282
283 if (ttype & TERRNO) {
284 str_errno = tst_strerrno(errno);
285 int_errno = errno;
286 }
287
288 if (ttype & TTERRNO) {
289 str_errno = tst_strerrno(TST_ERR);
290 int_errno = TST_ERR;
291 }
292
293 if (ttype & TRERRNO) {
294 int_errno = TST_RET < 0 ? -(int)TST_RET : (int)TST_RET;
295 str_errno = tst_strerrno(int_errno);
296 }
297
298 ret = snprintf(str, size, "%s:%i: ", file, lineno);
299 str += ret;
300 size -= ret;
301
302 if (tst_color_enabled(STDERR_FILENO))
303 ret = snprintf(str, size, "%s%s: %s", tst_ttype2color(ttype),
304 res, ANSI_COLOR_RESET);
305 else
306 ret = snprintf(str, size, "%s: ", res);
307 str += ret;
308 size -= ret;
309
310 ssize = size - 2;
311 ret = vsnprintf(str, size, fmt, va);
312 str += MIN(ret, ssize);
313 size -= MIN(ret, ssize);
314 if (ret >= ssize) {
315 tst_res_(file, lineno, TWARN,
316 "Next message is too long and truncated:");
317 } else if (str_errno) {
318 ssize = size - 2;
319 ret = snprintf(str, size, ": %s (%d)", str_errno, int_errno);
320 str += MIN(ret, ssize);
321 size -= MIN(ret, ssize);
322 if (ret >= ssize)
323 tst_res_(file, lineno, TWARN,
324 "Next message is too long and truncated:");
325 }
326
327 snprintf(str, size, "\n");
328
329 /* we might be called from signal handler, so use write() */
330 buflen = str - buf + 1;
331 str = buf;
332 while (buflen) {
333 ret = write(STDERR_FILENO, str, buflen);
334 if (ret <= 0)
335 break;
336
337 str += ret;
338 buflen -= ret;
339 }
340 }
341
tst_vres_(const char * file,const int lineno,int ttype,const char * fmt,va_list va)342 void tst_vres_(const char *file, const int lineno, int ttype, const char *fmt,
343 va_list va)
344 {
345 print_result(file, lineno, ttype, fmt, va);
346
347 update_results(TTYPE_RESULT(ttype));
348 }
349
350 void tst_vbrk_(const char *file, const int lineno, int ttype, const char *fmt,
351 va_list va);
352
353 static void (*tst_brk_handler)(const char *file, const int lineno, int ttype,
354 const char *fmt, va_list va) = tst_vbrk_;
355
tst_cvres(const char * file,const int lineno,int ttype,const char * fmt,va_list va)356 static void tst_cvres(const char *file, const int lineno, int ttype,
357 const char *fmt, va_list va)
358 {
359 if (TTYPE_RESULT(ttype) == TBROK) {
360 ttype &= ~TTYPE_MASK;
361 ttype |= TWARN;
362 }
363
364 print_result(file, lineno, ttype, fmt, va);
365 update_results(TTYPE_RESULT(ttype));
366 }
367
do_test_cleanup(void)368 static void do_test_cleanup(void)
369 {
370 tst_brk_handler = tst_cvres;
371
372 if (tst_test->cleanup)
373 tst_test->cleanup();
374
375 tst_free_all();
376
377 tst_brk_handler = tst_vbrk_;
378 }
379
tst_vbrk_(const char * file,const int lineno,int ttype,const char * fmt,va_list va)380 void tst_vbrk_(const char *file, const int lineno, int ttype, const char *fmt,
381 va_list va)
382 {
383 print_result(file, lineno, ttype, fmt, va);
384 update_results(TTYPE_RESULT(ttype));
385
386 /*
387 * The getpid implementation in some C library versions may cause cloned
388 * test threads to show the same pid as their parent when CLONE_VM is
389 * specified but CLONE_THREAD is not. Use direct syscall to avoid
390 * cleanup running in the child.
391 */
392 if (tst_getpid() == main_pid)
393 do_test_cleanup();
394
395 if (getpid() == lib_pid)
396 do_exit(TTYPE_RESULT(ttype));
397
398 exit(TTYPE_RESULT(ttype));
399 }
400
tst_res_(const char * file,const int lineno,int ttype,const char * fmt,...)401 void tst_res_(const char *file, const int lineno, int ttype,
402 const char *fmt, ...)
403 {
404 va_list va;
405
406 if (ttype == TDEBUG && !tdebug)
407 return;
408
409 va_start(va, fmt);
410 tst_vres_(file, lineno, ttype, fmt, va);
411 va_end(va);
412 }
413
tst_brk_(const char * file,const int lineno,int ttype,const char * fmt,...)414 void tst_brk_(const char *file, const int lineno, int ttype,
415 const char *fmt, ...)
416 {
417 va_list va;
418
419 va_start(va, fmt);
420 tst_brk_handler(file, lineno, ttype, fmt, va);
421 va_end(va);
422 }
423
tst_printf(const char * const fmt,...)424 void tst_printf(const char *const fmt, ...)
425 {
426 va_list va;
427
428 va_start(va, fmt);
429 vdprintf(STDERR_FILENO, fmt, va);
430 va_end(va);
431 }
432
check_child_status(pid_t pid,int status)433 static void check_child_status(pid_t pid, int status)
434 {
435 int ret;
436
437 if (WIFSIGNALED(status)) {
438 tst_brk(TBROK, "Child (%i) killed by signal %s", pid,
439 tst_strsig(WTERMSIG(status)));
440 }
441
442 if (!(WIFEXITED(status)))
443 tst_brk(TBROK, "Child (%i) exited abnormally", pid);
444
445 ret = WEXITSTATUS(status);
446 switch (ret) {
447 case TPASS:
448 case TBROK:
449 case TCONF:
450 break;
451 default:
452 tst_brk(TBROK, "Invalid child (%i) exit value %i", pid, ret);
453 }
454 }
455
tst_reap_children(void)456 void tst_reap_children(void)
457 {
458 int status;
459 pid_t pid;
460
461 for (;;) {
462 pid = wait(&status);
463
464 if (pid > 0) {
465 check_child_status(pid, status);
466 continue;
467 }
468
469 if (errno == ECHILD)
470 break;
471
472 if (errno == EINTR)
473 continue;
474
475 tst_brk(TBROK | TERRNO, "wait() failed");
476 }
477 }
478
479
safe_fork(const char * filename,unsigned int lineno)480 pid_t safe_fork(const char *filename, unsigned int lineno)
481 {
482 pid_t pid;
483
484 if (!tst_test->forks_child)
485 tst_brk(TBROK, "test.forks_child must be set!");
486
487 tst_flush();
488
489 pid = fork();
490 if (pid < 0)
491 tst_brk_(filename, lineno, TBROK | TERRNO, "fork() failed");
492
493 if (!pid)
494 atexit(tst_free_all);
495
496 return pid;
497 }
498
499 /* too fast creating namespaces => retrying */
500 #define TST_CHECK_ENOSPC(x) ((x) >= 0 || !(errno == ENOSPC))
501
safe_clone(const char * file,const int lineno,const struct tst_clone_args * args)502 pid_t safe_clone(const char *file, const int lineno,
503 const struct tst_clone_args *args)
504 {
505 pid_t pid;
506
507 if (!tst_test->forks_child)
508 tst_brk(TBROK, "test.forks_child must be set!");
509
510 pid = TST_RETRY_FUNC(tst_clone(args), TST_CHECK_ENOSPC);
511
512 switch (pid) {
513 case -1:
514 tst_brk_(file, lineno, TBROK | TERRNO, "clone3 failed");
515 break;
516 case -2:
517 tst_brk_(file, lineno, TBROK | TERRNO, "clone failed");
518 return -1;
519 }
520
521 if (!pid)
522 atexit(tst_free_all);
523
524 return pid;
525 }
526
parse_mul(float * mul,const char * env_name,float min,float max)527 static void parse_mul(float *mul, const char *env_name, float min, float max)
528 {
529 char *str_mul;
530 int ret;
531
532 if (*mul > 0)
533 return;
534
535 str_mul = getenv(env_name);
536
537 if (!str_mul) {
538 *mul = 1;
539 return;
540 }
541
542 ret = tst_parse_float(str_mul, mul, min, max);
543 if (ret) {
544 tst_brk(TBROK, "Failed to parse %s: %s",
545 env_name, tst_strerrno(ret));
546 }
547 }
548
multiply_runtime(unsigned int runtime)549 static int multiply_runtime(unsigned int runtime)
550 {
551 static float runtime_mul = -1;
552
553 parse_mul(&runtime_mul, "LTP_RUNTIME_MUL", 0.0099, 100);
554
555 return runtime * runtime_mul;
556 }
557
558 static struct option {
559 char *optstr;
560 char *help;
561 } options[] = {
562 {"h", "-h Prints this help"},
563 {"i:", "-i n Execute test n times"},
564 {"I:", "-I x Execute test for n seconds"},
565 {"D", "-D Prints debug information"},
566 {"V", "-V Prints LTP version"},
567 };
568
print_help(void)569 static void print_help(void)
570 {
571 unsigned int i;
572 int timeout, runtime;
573
574 /* see doc/User-Guidelines.asciidoc, which lists also shell API variables */
575 fprintf(stderr, "Environment Variables\n");
576 fprintf(stderr, "---------------------\n");
577 fprintf(stderr, "KCONFIG_PATH Specify kernel config file\n");
578 fprintf(stderr, "KCONFIG_SKIP_CHECK Skip kernel config check if variable set (not set by default)\n");
579 fprintf(stderr, "LTPROOT Prefix for installed LTP (default: /opt/ltp)\n");
580 fprintf(stderr, "LTP_COLORIZE_OUTPUT Force colorized output behaviour (y/1 always, n/0: never)\n");
581 fprintf(stderr, "LTP_DEV Path to the block device to be used (for .needs_device)\n");
582 fprintf(stderr, "LTP_DEV_FS_TYPE Filesystem used for testing (default: %s)\n", DEFAULT_FS_TYPE);
583 fprintf(stderr, "LTP_SINGLE_FS_TYPE Testing only - specifies filesystem instead all supported (for .all_filesystems)\n");
584 fprintf(stderr, "LTP_TIMEOUT_MUL Timeout multiplier (must be a number >=1)\n");
585 fprintf(stderr, "LTP_RUNTIME_MUL Runtime multiplier (must be a number >=1)\n");
586 fprintf(stderr, "LTP_VIRT_OVERRIDE Overrides virtual machine detection (values: \"\"|kvm|microsoft|xen|zvm)\n");
587 fprintf(stderr, "TMPDIR Base directory for template directory (for .needs_tmpdir, default: %s)\n", TEMPDIR);
588 fprintf(stderr, "\n");
589
590 fprintf(stderr, "Timeout and runtime\n");
591 fprintf(stderr, "-------------------\n");
592
593 if (tst_test->timeout == TST_UNLIMITED_TIMEOUT) {
594 fprintf(stderr, "Test timeout is not limited\n");
595 } else {
596 timeout = tst_multiply_timeout(DEFAULT_TIMEOUT + tst_test->timeout);
597
598 fprintf(stderr, "Test timeout (not including runtime) %ih %im %is\n",
599 timeout/3600, (timeout%3600)/60, timeout % 60);
600 }
601
602 if (tst_test->runtime) {
603 runtime = multiply_runtime(tst_test->runtime);
604
605 fprintf(stderr, "Test iteration runtime cap %ih %im %is\n",
606 runtime/3600, (runtime%3600)/60, runtime % 60);
607 }
608
609 fprintf(stderr, "\n");
610
611 fprintf(stderr, "Options\n");
612 fprintf(stderr, "-------\n");
613
614 for (i = 0; i < ARRAY_SIZE(options); i++)
615 fprintf(stderr, "%s\n", options[i].help);
616
617 if (!tst_test->options)
618 return;
619
620 for (i = 0; tst_test->options[i].optstr; i++) {
621 fprintf(stderr, "-%c\t %s\n",
622 tst_test->options[i].optstr[0],
623 tst_test->options[i].help);
624 }
625 }
626
print_test_tags(void)627 static void print_test_tags(void)
628 {
629 unsigned int i;
630 const struct tst_tag *tags = tst_test->tags;
631
632 if (!tags)
633 return;
634
635 fprintf(stderr, "\nTags\n");
636 fprintf(stderr, "----\n");
637
638 for (i = 0; tags[i].name; i++) {
639 if (!strcmp(tags[i].name, "CVE"))
640 fprintf(stderr, CVE_DB_URL "%s\n", tags[i].value);
641 else if (!strcmp(tags[i].name, "linux-git"))
642 fprintf(stderr, LINUX_GIT_URL "%s\n", tags[i].value);
643 else if (!strcmp(tags[i].name, "linux-stable-git"))
644 fprintf(stderr, LINUX_STABLE_GIT_URL "%s\n", tags[i].value);
645 else if (!strcmp(tags[i].name, "glibc-git"))
646 fprintf(stderr, GLIBC_GIT_URL "%s\n", tags[i].value);
647 else if (!strcmp(tags[i].name, "musl-git"))
648 fprintf(stderr, MUSL_GIT_URL "%s\n", tags[i].value);
649 else
650 fprintf(stderr, "%s: %s\n", tags[i].name, tags[i].value);
651 }
652
653 fprintf(stderr, "\n");
654 }
655
check_option_collision(void)656 static void check_option_collision(void)
657 {
658 unsigned int i, j;
659 struct tst_option *toptions = tst_test->options;
660
661 if (!toptions)
662 return;
663
664 for (i = 0; toptions[i].optstr; i++) {
665 for (j = 0; j < ARRAY_SIZE(options); j++) {
666 if (toptions[i].optstr[0] == options[j].optstr[0]) {
667 tst_brk(TBROK, "Option collision '%s'",
668 options[j].help);
669 }
670 }
671 }
672 }
673
count_options(void)674 static unsigned int count_options(void)
675 {
676 unsigned int i;
677
678 if (!tst_test->options)
679 return 0;
680
681 for (i = 0; tst_test->options[i].optstr; i++)
682 ;
683
684 return i;
685 }
686
parse_topt(unsigned int topts_len,int opt,char * optarg)687 static void parse_topt(unsigned int topts_len, int opt, char *optarg)
688 {
689 unsigned int i;
690 struct tst_option *toptions = tst_test->options;
691
692 for (i = 0; i < topts_len; i++) {
693 if (toptions[i].optstr[0] == opt)
694 break;
695 }
696
697 if (i >= topts_len)
698 tst_brk(TBROK, "Invalid option '%c' (should not happen)", opt);
699
700 if (*toptions[i].arg)
701 tst_res(TWARN, "Option -%c passed multiple times", opt);
702
703 *(toptions[i].arg) = optarg ? optarg : "";
704 }
705
parse_opts(int argc,char * argv[])706 static void parse_opts(int argc, char *argv[])
707 {
708 unsigned int i, topts_len = count_options();
709 char optstr[2 * ARRAY_SIZE(options) + 2 * topts_len];
710 int opt;
711
712 check_option_collision();
713
714 optstr[0] = 0;
715
716 for (i = 0; i < ARRAY_SIZE(options); i++)
717 strcat(optstr, options[i].optstr);
718
719 for (i = 0; i < topts_len; i++)
720 strcat(optstr, tst_test->options[i].optstr);
721
722 while ((opt = getopt(argc, argv, optstr)) > 0) {
723 switch (opt) {
724 case '?':
725 print_help();
726 tst_brk(TBROK, "Invalid option");
727 break;
728 case 'D':
729 tst_res(TINFO, "Enabling debug info");
730 tdebug = 1;
731 break;
732 case 'h':
733 print_help();
734 print_test_tags();
735 exit(0);
736 case 'i':
737 iterations = SAFE_STRTOL(optarg, 0, INT_MAX);
738 break;
739 case 'I':
740 if (tst_test->runtime > 0)
741 tst_test->runtime = SAFE_STRTOL(optarg, 1, INT_MAX);
742 else
743 duration = SAFE_STRTOF(optarg, 0.1, HUGE_VALF);
744 break;
745 case 'V':
746 fprintf(stderr, "LTP version: " LTP_VERSION "\n");
747 exit(0);
748 break;
749 default:
750 parse_topt(topts_len, opt, optarg);
751 }
752 }
753
754 if (optind < argc)
755 tst_brk(TBROK, "Unexpected argument(s) '%s'...", argv[optind]);
756 }
757
tst_parse_int(const char * str,int * val,int min,int max)758 int tst_parse_int(const char *str, int *val, int min, int max)
759 {
760 long rval;
761
762 if (!str)
763 return 0;
764
765 int ret = tst_parse_long(str, &rval, min, max);
766
767 if (ret)
768 return ret;
769
770 *val = (int)rval;
771 return 0;
772 }
773
tst_parse_long(const char * str,long * val,long min,long max)774 int tst_parse_long(const char *str, long *val, long min, long max)
775 {
776 long rval;
777 char *end;
778
779 if (!str)
780 return 0;
781
782 errno = 0;
783 rval = strtol(str, &end, 10);
784
785 if (str == end || *end != '\0')
786 return EINVAL;
787
788 if (errno)
789 return errno;
790
791 if (rval > max || rval < min)
792 return ERANGE;
793
794 *val = rval;
795 return 0;
796 }
797
tst_parse_float(const char * str,float * val,float min,float max)798 int tst_parse_float(const char *str, float *val, float min, float max)
799 {
800 double rval;
801 char *end;
802
803 if (!str)
804 return 0;
805
806 errno = 0;
807 rval = strtod(str, &end);
808
809 if (str == end || *end != '\0')
810 return EINVAL;
811
812 if (errno)
813 return errno;
814
815 if (rval > (double)max || rval < (double)min)
816 return ERANGE;
817
818 *val = (float)rval;
819 return 0;
820 }
821
tst_parse_filesize(const char * str,long long * val,long long min,long long max)822 int tst_parse_filesize(const char *str, long long *val, long long min, long long max)
823 {
824 long long rval;
825 char *end;
826
827 if (!str)
828 return 0;
829
830 errno = 0;
831 rval = strtoll(str, &end, 0);
832
833 if (str == end || (end[0] && end[1]))
834 return EINVAL;
835
836 if (errno)
837 return errno;
838
839 switch (*end) {
840 case 'g':
841 case 'G':
842 rval *= (1024 * 1024 * 1024);
843 break;
844 case 'm':
845 case 'M':
846 rval *= (1024 * 1024);
847 break;
848 case 'k':
849 case 'K':
850 rval *= 1024;
851 break;
852 default:
853 break;
854 }
855
856 if (rval > max || rval < min)
857 return ERANGE;
858
859 *val = rval;
860 return 0;
861 }
862
print_colored(const char * str)863 static void print_colored(const char *str)
864 {
865 if (tst_color_enabled(STDOUT_FILENO))
866 fprintf(stderr, "%s%s%s", ANSI_COLOR_YELLOW, str, ANSI_COLOR_RESET);
867 else
868 fprintf(stderr, "%s", str);
869 }
870
print_failure_hint(const char * tag,const char * hint,const char * url)871 static void print_failure_hint(const char *tag, const char *hint,
872 const char *url)
873 {
874 const struct tst_tag *tags = tst_test->tags;
875
876 if (!tags)
877 return;
878
879 unsigned int i;
880 int hint_printed = 0;
881
882 for (i = 0; tags[i].name; i++) {
883 if (!strcmp(tags[i].name, tag)) {
884 if (!hint_printed) {
885 hint_printed = 1;
886 fprintf(stderr, "\n");
887 print_colored("HINT: ");
888 fprintf(stderr, "You _MAY_ be %s:\n\n", hint);
889 }
890
891 if (url)
892 fprintf(stderr, "%s%s\n", url, tags[i].value);
893 else
894 fprintf(stderr, "%s\n", tags[i].value);
895 }
896 }
897 }
898
899 static int show_failure_hints;
900
901 /* update also docparse/testinfo.pl */
print_failure_hints(void)902 static void print_failure_hints(void)
903 {
904 print_failure_hint("linux-git", "missing kernel fixes", LINUX_GIT_URL);
905 print_failure_hint("linux-stable-git", "missing stable kernel fixes",
906 LINUX_STABLE_GIT_URL);
907 print_failure_hint("glibc-git", "missing glibc fixes", GLIBC_GIT_URL);
908 print_failure_hint("musl-git", "missing musl fixes", MUSL_GIT_URL);
909 print_failure_hint("CVE", "vulnerable to CVE(s)", CVE_DB_URL);
910 print_failure_hint("known-fail", "hit by known kernel failures", NULL);
911
912 show_failure_hints = 0;
913 }
914
do_exit(int ret)915 static void do_exit(int ret)
916 {
917 if (results) {
918 if (results->passed && ret == TCONF)
919 ret = 0;
920
921 if (results->failed) {
922 ret |= TFAIL;
923 if (show_failure_hints)
924 print_failure_hints();
925 }
926
927 if (results->skipped && !results->passed)
928 ret |= TCONF;
929
930 if (results->warnings)
931 ret |= TWARN;
932
933 if (results->broken) {
934 ret |= TBROK;
935 if (show_failure_hints)
936 print_failure_hints();
937 }
938
939 fprintf(stderr, "\nSummary:\n");
940 fprintf(stderr, "passed %d\n", results->passed);
941 fprintf(stderr, "failed %d\n", results->failed);
942 fprintf(stderr, "broken %d\n", results->broken);
943 fprintf(stderr, "skipped %d\n", results->skipped);
944 fprintf(stderr, "warnings %d\n", results->warnings);
945 }
946
947 do_cleanup();
948
949 exit(ret);
950 }
951
check_kver(const char * min_kver,const int brk_nosupp)952 int check_kver(const char *min_kver, const int brk_nosupp)
953 {
954 char *msg;
955 int v1, v2, v3;
956
957 if (tst_parse_kver(min_kver, &v1, &v2, &v3)) {
958 tst_res(TWARN,
959 "Invalid kernel version %s, expected %%d.%%d.%%d",
960 min_kver);
961 }
962
963 if (tst_kvercmp(v1, v2, v3) < 0) {
964 msg = "The test requires kernel %s or newer";
965
966 if (brk_nosupp)
967 tst_brk(TCONF, msg, min_kver);
968 else
969 tst_res(TCONF, msg, min_kver);
970
971 return 1;
972 }
973
974 return 0;
975 }
976
results_equal(struct results * a,struct results * b)977 static int results_equal(struct results *a, struct results *b)
978 {
979 if (a->passed != b->passed)
980 return 0;
981
982 if (a->failed != b->failed)
983 return 0;
984
985 if (a->skipped != b->skipped)
986 return 0;
987
988 if (a->broken != b->broken)
989 return 0;
990
991 return 1;
992 }
993
needs_tmpdir(void)994 static int needs_tmpdir(void)
995 {
996 return tst_test->needs_tmpdir ||
997 tst_test->needs_device ||
998 tst_test->mntpoint ||
999 tst_test->resource_files ||
1000 tst_test->needs_checkpoints;
1001 }
1002
copy_resources(void)1003 static void copy_resources(void)
1004 {
1005 unsigned int i;
1006
1007 for (i = 0; tst_test->resource_files[i]; i++)
1008 TST_RESOURCE_COPY(NULL, tst_test->resource_files[i], NULL);
1009 }
1010
get_tid(char * argv[])1011 static const char *get_tid(char *argv[])
1012 {
1013 char *p;
1014
1015 if (!argv[0] || !argv[0][0]) {
1016 tst_res(TINFO, "argv[0] is empty!");
1017 return "ltp_empty_argv";
1018 }
1019
1020 p = strrchr(argv[0], '/');
1021 if (p)
1022 return p+1;
1023
1024 return argv[0];
1025 }
1026
1027 static struct tst_device tdev;
1028 struct tst_device *tst_device;
1029
assert_test_fn(void)1030 static void assert_test_fn(void)
1031 {
1032 int cnt = 0;
1033
1034 if (tst_test->test)
1035 cnt++;
1036
1037 if (tst_test->test_all)
1038 cnt++;
1039
1040 if (tst_test->sample)
1041 cnt++;
1042
1043 if (!cnt)
1044 tst_brk(TBROK, "No test function specified");
1045
1046 if (cnt != 1)
1047 tst_brk(TBROK, "You can define only one test function");
1048
1049 if (tst_test->test && !tst_test->tcnt)
1050 tst_brk(TBROK, "Number of tests (tcnt) must be > 0");
1051
1052 if (!tst_test->test && tst_test->tcnt)
1053 tst_brk(TBROK, "You can define tcnt only for test()");
1054 }
1055
prepare_and_mount_ro_fs(const char * dev,const char * mntpoint,const char * fs_type)1056 static int prepare_and_mount_ro_fs(const char *dev, const char *mntpoint,
1057 const char *fs_type)
1058 {
1059 char buf[PATH_MAX];
1060
1061 if (mount(dev, mntpoint, fs_type, 0, NULL)) {
1062 tst_res(TINFO | TERRNO, "Can't mount %s at %s (%s)",
1063 dev, mntpoint, fs_type);
1064 return 1;
1065 }
1066
1067 mntpoint_mounted = 1;
1068
1069 snprintf(buf, sizeof(buf), "%s/dir/", mntpoint);
1070 SAFE_MKDIR(buf, 0777);
1071
1072 snprintf(buf, sizeof(buf), "%s/file", mntpoint);
1073 SAFE_FILE_PRINTF(buf, "file content");
1074 SAFE_CHMOD(buf, 0777);
1075
1076 SAFE_MOUNT(dev, mntpoint, fs_type, MS_REMOUNT | MS_RDONLY, NULL);
1077
1078 return 0;
1079 }
1080
prepare_and_mount_dev_fs(const char * mntpoint)1081 static void prepare_and_mount_dev_fs(const char *mntpoint)
1082 {
1083 const char *flags[] = {"nodev", NULL};
1084 int mounted_nodev;
1085
1086 mounted_nodev = tst_path_has_mnt_flags(NULL, flags);
1087 if (mounted_nodev) {
1088 tst_res(TINFO, "tmpdir isn't suitable for creating devices, "
1089 "mounting tmpfs without nodev on %s", mntpoint);
1090 SAFE_MOUNT(NULL, mntpoint, "tmpfs", 0, NULL);
1091 mntpoint_mounted = 1;
1092 }
1093 }
1094
prepare_and_mount_hugetlb_fs(void)1095 static void prepare_and_mount_hugetlb_fs(void)
1096 {
1097 SAFE_MOUNT("none", tst_test->mntpoint, "hugetlbfs", 0, NULL);
1098 mntpoint_mounted = 1;
1099 }
1100
tst_creat_unlinked(const char * path,int flags,mode_t mode)1101 int tst_creat_unlinked(const char *path, int flags, mode_t mode)
1102 {
1103 char template[PATH_MAX];
1104 int len, c, range;
1105 int fd;
1106 int start[3] = {'0', 'a', 'A'};
1107
1108 snprintf(template, PATH_MAX, "%s/ltp_%.3sXXXXXX",
1109 path, tid);
1110
1111 len = strlen(template) - 1;
1112 while (template[len] == 'X') {
1113 c = rand() % 3;
1114 range = start[c] == '0' ? 10 : 26;
1115 c = start[c] + (rand() % range);
1116 template[len--] = (char)c;
1117 }
1118
1119 flags |= O_CREAT|O_EXCL|O_RDWR;
1120 fd = SAFE_OPEN(template, flags, mode);
1121 SAFE_UNLINK(template);
1122 return fd;
1123 }
1124
limit_tmpfs_mount_size(const char * mnt_data,char * buf,size_t buf_size,const char * fs_type)1125 static const char *limit_tmpfs_mount_size(const char *mnt_data,
1126 char *buf, size_t buf_size, const char *fs_type)
1127 {
1128 unsigned int tmpfs_size;
1129
1130 if (strcmp(fs_type, "tmpfs"))
1131 return mnt_data;
1132
1133 if (!tst_test->dev_min_size)
1134 tmpfs_size = 32;
1135 else
1136 tmpfs_size = tdev.size;
1137
1138 if ((tst_available_mem() / 1024) < (tmpfs_size * 2))
1139 tst_brk(TCONF, "No enough memory for tmpfs use");
1140
1141 if (mnt_data)
1142 snprintf(buf, buf_size, "%s,size=%uM", mnt_data, tmpfs_size);
1143 else
1144 snprintf(buf, buf_size, "size=%uM", tmpfs_size);
1145
1146 tst_res(TINFO, "Limiting tmpfs size to %uMB", tmpfs_size);
1147
1148 return buf;
1149 }
1150
get_device_name(const char * fs_type)1151 static const char *get_device_name(const char *fs_type)
1152 {
1153 if (!strcmp(fs_type, "tmpfs"))
1154 return "ltp-tmpfs";
1155 else
1156 return tdev.dev;
1157 }
1158
prepare_device(struct tst_fs * fs)1159 static void prepare_device(struct tst_fs *fs)
1160 {
1161 const char *mnt_data;
1162 char buf[1024];
1163 struct tst_fs dummy = {};
1164
1165 fs = fs ?: &dummy;
1166
1167 const char *const extra[] = {fs->mkfs_size_opt, NULL};
1168
1169 if (tst_test->format_device)
1170 SAFE_MKFS(tdev.dev, tdev.fs_type, fs->mkfs_opts, extra);
1171
1172 if (tst_test->needs_rofs) {
1173 prepare_and_mount_ro_fs(tdev.dev, tst_test->mntpoint,
1174 tdev.fs_type);
1175 return;
1176 }
1177
1178 if (tst_test->mount_device) {
1179 mnt_data = limit_tmpfs_mount_size(fs->mnt_data,
1180 buf, sizeof(buf), tdev.fs_type);
1181
1182 SAFE_MOUNT(get_device_name(tdev.fs_type), tst_test->mntpoint,
1183 tdev.fs_type, fs->mnt_flags, mnt_data);
1184 mntpoint_mounted = 1;
1185 }
1186 }
1187
do_cgroup_requires(void)1188 static void do_cgroup_requires(void)
1189 {
1190 const struct tst_cg_opts cg_opts = {
1191 .needs_ver = tst_test->needs_cgroup_ver,
1192 .needs_nsdelegate = tst_test->needs_cgroup_nsdelegate,
1193 };
1194 const char *const *ctrl_names = tst_test->needs_cgroup_ctrls;
1195
1196 for (; *ctrl_names; ctrl_names++)
1197 tst_cg_require(*ctrl_names, &cg_opts);
1198
1199 tst_cg_init();
1200 }
1201
1202 #define tst_set_ulimit(conf) \
1203 set_ulimit_(__FILE__, __LINE__, (conf))
1204
1205 /*
1206 * Set resource limits.
1207 */
set_ulimit_(const char * file,const int lineno,const struct tst_ulimit_val * conf)1208 static void set_ulimit_(const char *file, const int lineno, const struct tst_ulimit_val *conf)
1209 {
1210 struct rlimit rlim;
1211
1212 safe_getrlimit(file, lineno, conf->resource, &rlim);
1213
1214 rlim.rlim_cur = conf->rlim_cur;
1215
1216 if (conf->rlim_cur > rlim.rlim_max)
1217 rlim.rlim_max = conf->rlim_cur;
1218
1219 tst_res_(file, lineno, TINFO, "Set ulimit resource: %d rlim_cur: %llu rlim_max: %llu",
1220 conf->resource, (long long unsigned int)rlim.rlim_cur,
1221 (long long unsigned int)rlim.rlim_max);
1222
1223 safe_setrlimit(file, lineno, conf->resource, &rlim);
1224 }
1225
count_fs_descs(void)1226 static unsigned int count_fs_descs(void)
1227 {
1228 unsigned int ret = 0;
1229
1230 if (!tst_test->filesystems)
1231 return 0;
1232
1233 /*
1234 * First entry is special, if it has zero type it's the default entry
1235 * and is either followed by a terminating entry or by filesystem
1236 * description(s) plus terminating entry.
1237 */
1238 if (!tst_test->filesystems[0].type)
1239 ret = 1;
1240
1241 while (tst_test->filesystems[ret].type)
1242 ret++;
1243
1244 return ret;
1245 }
1246
default_fs_type(void)1247 static const char *default_fs_type(void)
1248 {
1249 if (!tst_test->filesystems)
1250 return tst_dev_fs_type();
1251
1252 if (tst_test->filesystems[0].type)
1253 return tst_test->filesystems[0].type;
1254
1255 return tst_dev_fs_type();
1256 }
1257
do_setup(int argc,char * argv[])1258 static void do_setup(int argc, char *argv[])
1259 {
1260 char *tdebug_env = getenv("LTP_ENABLE_DEBUG");
1261
1262 if (!tst_test)
1263 tst_brk(TBROK, "No tests to run");
1264
1265 if (tst_test->timeout < -1) {
1266 tst_brk(TBROK, "Invalid timeout value %i",
1267 tst_test->timeout);
1268 }
1269
1270 if (tst_test->runtime < 0) {
1271 tst_brk(TBROK, "Invalid runtime value %i",
1272 results->runtime);
1273 }
1274
1275 if (tst_test->tconf_msg)
1276 tst_brk(TCONF, "%s", tst_test->tconf_msg);
1277
1278 assert_test_fn();
1279
1280 TCID = tid = get_tid(argv);
1281
1282 if (tst_test->sample)
1283 tst_test = tst_timer_test_setup(tst_test);
1284
1285 parse_opts(argc, argv);
1286
1287 if (tdebug_env && (!strcmp(tdebug_env, "1") || !strcmp(tdebug_env, "y"))) {
1288 tst_res(TINFO, "Enabling debug info");
1289 tdebug = 1;
1290 }
1291
1292 if (tst_test->runs_script) {
1293 tst_test->child_needs_reinit = 1;
1294 tst_test->forks_child = 1;
1295 }
1296
1297 if (tst_test->needs_kconfigs && tst_kconfig_check(tst_test->needs_kconfigs))
1298 tst_brk(TCONF, "Aborting due to unsuitable kernel config, see above!");
1299
1300 if (tst_test->needs_root && geteuid() != 0)
1301 tst_brk(TCONF, "Test needs to be run as root");
1302
1303 if (tst_test->min_kver)
1304 check_kver(tst_test->min_kver, 1);
1305
1306 if (tst_test->supported_archs && !tst_is_on_arch(tst_test->supported_archs))
1307 tst_brk(TCONF, "This arch '%s' is not supported for test!", tst_arch.name);
1308
1309 if (tst_test->skip_in_lockdown && tst_lockdown_enabled() > 0)
1310 tst_brk(TCONF, "Kernel is locked down, skipping test");
1311
1312 if (tst_test->skip_in_secureboot && tst_secureboot_enabled() > 0)
1313 tst_brk(TCONF, "SecureBoot enabled, skipping test");
1314
1315 if (tst_test->skip_in_compat && tst_is_compat_mode())
1316 tst_brk(TCONF, "Not supported in 32-bit compat mode");
1317
1318 if (tst_test->needs_abi_bits && !tst_abi_bits(tst_test->needs_abi_bits))
1319 tst_brk(TCONF, "%dbit ABI is not supported", tst_test->needs_abi_bits);
1320
1321 if (tst_test->needs_cmds) {
1322 const char *cmd;
1323 int i;
1324
1325 for (i = 0; (cmd = tst_test->needs_cmds[i]); ++i)
1326 tst_check_cmd(cmd, 1);
1327 }
1328
1329 if (tst_test->needs_drivers) {
1330 const char *name;
1331 int i;
1332
1333 for (i = 0; (name = tst_test->needs_drivers[i]); ++i)
1334 if (tst_check_driver(name))
1335 tst_brk(TCONF, "%s driver not available", name);
1336 }
1337
1338 if (tst_test->mount_device)
1339 tst_test->format_device = 1;
1340
1341 if (tst_test->format_device)
1342 tst_test->needs_device = 1;
1343
1344 if (tst_test->all_filesystems)
1345 tst_test->needs_device = 1;
1346
1347 if (tst_test->min_cpus > (unsigned long)tst_ncpus())
1348 tst_brk(TCONF, "Test needs at least %lu CPUs online", tst_test->min_cpus);
1349
1350 if (tst_test->min_mem_avail > (unsigned long)(tst_available_mem() / 1024))
1351 tst_brk(TCONF, "Test needs at least %luMB MemAvailable", tst_test->min_mem_avail);
1352
1353 if (tst_test->min_swap_avail > (unsigned long)(tst_available_swap() / 1024))
1354 tst_brk(TCONF, "Test needs at least %luMB SwapFree", tst_test->min_swap_avail);
1355
1356 if (tst_test->hugepages.number)
1357 tst_reserve_hugepages(&tst_test->hugepages);
1358
1359 setup_ipc();
1360
1361 if (tst_test->bufs)
1362 tst_buffers_alloc(tst_test->bufs);
1363
1364 if (needs_tmpdir() && !tst_tmpdir_created())
1365 tst_tmpdir();
1366
1367 if (tst_test->save_restore) {
1368 const struct tst_path_val *pvl = tst_test->save_restore;
1369
1370 while (pvl->path) {
1371 tst_sys_conf_save(pvl);
1372 pvl++;
1373 }
1374 }
1375
1376 if (tst_test->ulimit) {
1377 const struct tst_ulimit_val *pvl = tst_test->ulimit;
1378
1379 while (pvl->resource) {
1380 tst_set_ulimit(pvl);
1381 pvl++;
1382 }
1383 }
1384
1385 if (tst_test->mntpoint)
1386 SAFE_MKDIR(tst_test->mntpoint, 0777);
1387
1388 if ((tst_test->needs_devfs || tst_test->needs_rofs ||
1389 tst_test->mount_device || tst_test->all_filesystems ||
1390 tst_test->needs_hugetlbfs) &&
1391 !tst_test->mntpoint) {
1392 tst_brk(TBROK, "tst_test->mntpoint must be set!");
1393 }
1394
1395 if (!!tst_test->needs_rofs + !!tst_test->needs_devfs +
1396 !!tst_test->needs_device + !!tst_test->needs_hugetlbfs > 1) {
1397 tst_brk(TBROK,
1398 "Two or more of needs_{rofs, devfs, device, hugetlbfs} are set");
1399 }
1400
1401 if (tst_test->needs_devfs)
1402 prepare_and_mount_dev_fs(tst_test->mntpoint);
1403
1404 if (tst_test->needs_rofs) {
1405 /* If we failed to mount read-only tmpfs. Fallback to
1406 * using a device with read-only filesystem.
1407 */
1408 if (prepare_and_mount_ro_fs(NULL, tst_test->mntpoint, "tmpfs")) {
1409 tst_res(TINFO, "Can't mount tmpfs read-only, "
1410 "falling back to block device...");
1411 tst_test->needs_device = 1;
1412 tst_test->format_device = 1;
1413 }
1414 }
1415
1416 if (tst_test->needs_hugetlbfs)
1417 prepare_and_mount_hugetlb_fs();
1418
1419 if (tst_test->needs_device && !mntpoint_mounted) {
1420 tdev.dev = tst_acquire_device_(NULL, tst_test->dev_min_size);
1421
1422 if (!tdev.dev)
1423 tst_brk(TCONF, "Failed to acquire device");
1424
1425 tdev.size = tst_get_device_size(tdev.dev);
1426
1427 tst_device = &tdev;
1428
1429 tdev.fs_type = default_fs_type();
1430
1431 if (!tst_test->all_filesystems && count_fs_descs() <= 1) {
1432 if (tst_test->filesystems && tst_test->filesystems->mkfs_ver)
1433 tst_check_cmd(tst_test->filesystems->mkfs_ver, 1);
1434
1435 if (tst_test->filesystems && tst_test->filesystems->min_kver)
1436 check_kver(tst_test->filesystems->min_kver, 1);
1437
1438 prepare_device(tst_test->filesystems);
1439 }
1440 }
1441
1442 if (tst_test->needs_overlay && !tst_test->mount_device)
1443 tst_brk(TBROK, "tst_test->mount_device must be set");
1444
1445 if (tst_test->needs_overlay && !mntpoint_mounted)
1446 tst_brk(TBROK, "tst_test->mntpoint must be mounted");
1447
1448 if (tst_test->needs_overlay && !ovl_mounted) {
1449 SAFE_MOUNT_OVERLAY();
1450 ovl_mounted = 1;
1451 }
1452
1453 if (tst_test->resource_files)
1454 copy_resources();
1455
1456 if (tst_test->restore_wallclock)
1457 tst_wallclock_save();
1458
1459 if (tst_test->taint_check)
1460 tst_taint_init(tst_test->taint_check);
1461
1462 if (tst_test->needs_cgroup_ctrls)
1463 do_cgroup_requires();
1464 else if (tst_test->needs_cgroup_ver)
1465 tst_brk(TBROK, "tst_test->needs_cgroup_ctrls must be set");
1466 }
1467
do_test_setup(void)1468 static void do_test_setup(void)
1469 {
1470 main_pid = getpid();
1471
1472 if (!tst_test->all_filesystems && tst_test->skip_filesystems) {
1473 long fs_type = tst_fs_type(".");
1474 const char *fs_name = tst_fs_type_name(fs_type);
1475
1476 if (tst_fs_in_skiplist(fs_name, tst_test->skip_filesystems)) {
1477 tst_brk(TCONF, "%s is not supported by the test",
1478 fs_name);
1479 }
1480
1481 tst_res(TINFO, "%s is supported by the test", fs_name);
1482 }
1483
1484 if (tst_test->caps)
1485 tst_cap_setup(tst_test->caps, TST_CAP_REQ);
1486
1487 if (tst_test->setup)
1488 tst_test->setup();
1489
1490 if (main_pid != tst_getpid())
1491 tst_brk(TBROK, "Runaway child in setup()!");
1492
1493 if (tst_test->caps)
1494 tst_cap_setup(tst_test->caps, TST_CAP_DROP);
1495 }
1496
do_cleanup(void)1497 static void do_cleanup(void)
1498 {
1499 if (tst_test->needs_cgroup_ctrls)
1500 tst_cg_cleanup();
1501
1502 if (ovl_mounted)
1503 SAFE_UMOUNT(OVL_MNT);
1504
1505 if (mntpoint_mounted)
1506 tst_umount(tst_test->mntpoint);
1507
1508 if (tst_test->needs_device && tdev.dev)
1509 tst_release_device(tdev.dev);
1510
1511 if (tst_tmpdir_created()) {
1512 /* avoid munmap() on wrong pointer in tst_rmdir() */
1513 tst_futexes = NULL;
1514 tst_rmdir();
1515 }
1516
1517 tst_sys_conf_restore(0);
1518
1519 if (tst_test->restore_wallclock)
1520 tst_wallclock_restore();
1521
1522 cleanup_ipc();
1523 }
1524
heartbeat(void)1525 static void heartbeat(void)
1526 {
1527 if (tst_clock_gettime(CLOCK_MONOTONIC, &tst_start_time))
1528 tst_res(TWARN | TERRNO, "tst_clock_gettime() failed");
1529
1530 if (getppid() == 1) {
1531 tst_res(TFAIL, "Main test process might have exit!");
1532 /*
1533 * We need kill the task group immediately since the
1534 * main process has exit.
1535 */
1536 kill(0, SIGKILL);
1537 exit(TBROK);
1538 }
1539
1540 kill(getppid(), SIGUSR1);
1541 }
1542
run_tests(void)1543 static void run_tests(void)
1544 {
1545 unsigned int i;
1546 struct results saved_results;
1547
1548 if (!tst_test->test) {
1549 saved_results = *results;
1550 heartbeat();
1551 tst_test->test_all();
1552
1553 if (tst_getpid() != main_pid)
1554 exit(0);
1555
1556 tst_reap_children();
1557
1558 if (results_equal(&saved_results, results))
1559 tst_brk(TBROK, "Test haven't reported results!");
1560 return;
1561 }
1562
1563 for (i = 0; i < tst_test->tcnt; i++) {
1564 saved_results = *results;
1565 heartbeat();
1566 tst_test->test(i);
1567
1568 if (tst_getpid() != main_pid)
1569 exit(0);
1570
1571 tst_reap_children();
1572
1573 if (results_equal(&saved_results, results))
1574 tst_brk(TBROK, "Test %i haven't reported results!", i);
1575 }
1576 }
1577
get_time_ms(void)1578 static unsigned long long get_time_ms(void)
1579 {
1580 struct timespec ts;
1581
1582 if (tst_clock_gettime(CLOCK_MONOTONIC, &ts))
1583 tst_brk(TBROK | TERRNO, "tst_clock_gettime()");
1584
1585 return tst_timespec_to_ms(ts);
1586 }
1587
add_paths(void)1588 static void add_paths(void)
1589 {
1590 char *old_path = getenv("PATH");
1591 const char *start_dir;
1592 char *new_path;
1593
1594 start_dir = tst_get_startwd();
1595
1596 if (old_path)
1597 SAFE_ASPRINTF(&new_path, "%s::%s", old_path, start_dir);
1598 else
1599 SAFE_ASPRINTF(&new_path, "::%s", start_dir);
1600
1601 SAFE_SETENV("PATH", new_path, 1);
1602 free(new_path);
1603 }
1604
testrun(void)1605 static void testrun(void)
1606 {
1607 unsigned int i = 0;
1608 unsigned long long stop_time = 0;
1609 int cont = 1;
1610
1611 heartbeat();
1612 add_paths();
1613 do_test_setup();
1614
1615 if (duration > 0)
1616 stop_time = get_time_ms() + (unsigned long long)(duration * 1000);
1617
1618 for (;;) {
1619 cont = 0;
1620
1621 if (i < (unsigned int)iterations) {
1622 i++;
1623 cont = 1;
1624 }
1625
1626 if (stop_time && get_time_ms() < stop_time)
1627 cont = 1;
1628
1629 if (!cont)
1630 break;
1631
1632 run_tests();
1633 heartbeat();
1634 }
1635
1636 do_test_cleanup();
1637 exit(0);
1638 }
1639
1640 static pid_t test_pid;
1641
1642
1643 static volatile sig_atomic_t sigkill_retries;
1644
1645 #define WRITE_MSG(msg) do { \
1646 if (write(2, msg, sizeof(msg) - 1)) { \
1647 /* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66425 */ \
1648 } \
1649 } while (0)
1650
alarm_handler(int sig LTP_ATTRIBUTE_UNUSED)1651 static void alarm_handler(int sig LTP_ATTRIBUTE_UNUSED)
1652 {
1653 WRITE_MSG("Test timeouted, sending SIGKILL!\n");
1654 kill(-test_pid, SIGKILL);
1655 alarm(5);
1656
1657 if (++sigkill_retries > 10) {
1658 WRITE_MSG("Cannot kill test processes!\n");
1659 WRITE_MSG("Congratulation, likely test hit a kernel bug.\n");
1660 WRITE_MSG("Exiting uncleanly...\n");
1661 _exit(TFAIL);
1662 }
1663 }
1664
heartbeat_handler(int sig LTP_ATTRIBUTE_UNUSED)1665 static void heartbeat_handler(int sig LTP_ATTRIBUTE_UNUSED)
1666 {
1667 alarm(results->overall_time);
1668 sigkill_retries = 0;
1669 }
1670
sigint_handler(int sig LTP_ATTRIBUTE_UNUSED)1671 static void sigint_handler(int sig LTP_ATTRIBUTE_UNUSED)
1672 {
1673 if (test_pid > 0) {
1674 WRITE_MSG("Sending SIGKILL to test process...\n");
1675 kill(-test_pid, SIGKILL);
1676 }
1677 }
1678
tst_remaining_runtime(void)1679 unsigned int tst_remaining_runtime(void)
1680 {
1681 static struct timespec now;
1682 int elapsed;
1683
1684 if (results->runtime == 0)
1685 tst_brk(TBROK, "Runtime not set!");
1686
1687 if (tst_clock_gettime(CLOCK_MONOTONIC, &now))
1688 tst_res(TWARN | TERRNO, "tst_clock_gettime() failed");
1689
1690 elapsed = tst_timespec_diff_ms(now, tst_start_time) / 1000;
1691 if (results->runtime > (unsigned int) elapsed)
1692 return results->runtime - elapsed;
1693
1694 return 0;
1695 }
1696
1697
tst_multiply_timeout(unsigned int timeout)1698 unsigned int tst_multiply_timeout(unsigned int timeout)
1699 {
1700 parse_mul(&timeout_mul, "LTP_TIMEOUT_MUL", 0.099, 10000);
1701
1702 if (timeout < 1)
1703 tst_brk(TBROK, "timeout must to be >= 1! (%d)", timeout);
1704
1705 if (tst_has_slow_kconfig())
1706 timeout *= 4;
1707
1708 return timeout * timeout_mul;
1709 }
1710
set_overall_timeout(void)1711 static void set_overall_timeout(void)
1712 {
1713 unsigned int timeout = DEFAULT_TIMEOUT + tst_test->timeout;
1714
1715 if (tst_test->timeout == TST_UNLIMITED_TIMEOUT) {
1716 tst_res(TINFO, "Test timeout is not limited");
1717 return;
1718 }
1719
1720 results->overall_time = tst_multiply_timeout(timeout) + results->runtime;
1721
1722 tst_res(TINFO, "Overall timeout per run is %uh %02um %02us",
1723 results->overall_time/3600, (results->overall_time%3600)/60,
1724 results->overall_time % 60);
1725 }
1726
tst_set_timeout(int timeout)1727 void tst_set_timeout(int timeout)
1728 {
1729 int timeout_adj = DEFAULT_TIMEOUT + timeout;
1730
1731 results->overall_time = tst_multiply_timeout(timeout_adj) + results->runtime;
1732
1733 tst_res(TINFO, "Overall timeout per run is %uh %02um %02us",
1734 results->overall_time/3600, (results->overall_time%3600)/60,
1735 results->overall_time % 60);
1736
1737 heartbeat();
1738 }
1739
tst_set_runtime(int runtime)1740 void tst_set_runtime(int runtime)
1741 {
1742 results->runtime = multiply_runtime(runtime);
1743 tst_res(TINFO, "Updating runtime to %uh %02um %02us",
1744 runtime/3600, (runtime%3600)/60, runtime % 60);
1745 set_overall_timeout();
1746 heartbeat();
1747 }
1748
fork_testrun(void)1749 static int fork_testrun(void)
1750 {
1751 int status;
1752
1753 SAFE_SIGNAL(SIGINT, sigint_handler);
1754 SAFE_SIGNAL(SIGTERM, sigint_handler);
1755
1756 alarm(results->overall_time);
1757
1758 show_failure_hints = 1;
1759
1760 test_pid = fork();
1761 if (test_pid < 0)
1762 tst_brk(TBROK | TERRNO, "fork()");
1763
1764 if (!test_pid) {
1765 tst_disable_oom_protection(0);
1766 SAFE_SIGNAL(SIGALRM, SIG_DFL);
1767 SAFE_SIGNAL(SIGUSR1, SIG_DFL);
1768 SAFE_SIGNAL(SIGTERM, SIG_DFL);
1769 SAFE_SIGNAL(SIGINT, SIG_DFL);
1770 SAFE_SETPGID(0, 0);
1771 testrun();
1772 }
1773
1774 SAFE_WAITPID(test_pid, &status, 0);
1775 alarm(0);
1776 SAFE_SIGNAL(SIGTERM, SIG_DFL);
1777 SAFE_SIGNAL(SIGINT, SIG_DFL);
1778
1779 if (tst_test->taint_check && tst_taint_check()) {
1780 tst_res(TFAIL, "Kernel is now tainted.");
1781 return TFAIL;
1782 }
1783
1784 if (tst_test->forks_child && kill(-test_pid, SIGKILL) == 0)
1785 tst_res(TINFO, "Killed the leftover descendant processes");
1786
1787 if (WIFEXITED(status) && WEXITSTATUS(status))
1788 return WEXITSTATUS(status);
1789
1790 if (WIFSIGNALED(status) && WTERMSIG(status) == SIGKILL) {
1791 tst_res(TINFO, "If you are running on slow machine, "
1792 "try exporting LTP_TIMEOUT_MUL > 1");
1793 tst_brk(TBROK, "Test killed! (timeout?)");
1794 }
1795
1796 if (WIFSIGNALED(status))
1797 tst_brk(TBROK, "Test killed by %s!", tst_strsig(WTERMSIG(status)));
1798
1799 return 0;
1800 }
1801
lookup_fs_desc(const char * fs_type,int all_filesystems)1802 static struct tst_fs *lookup_fs_desc(const char *fs_type, int all_filesystems)
1803 {
1804 struct tst_fs *fs = tst_test->filesystems;
1805 static struct tst_fs empty;
1806
1807 if (!fs)
1808 goto ret;
1809
1810 for (; fs->type; fs++) {
1811
1812 if (!fs->type)
1813 continue;
1814
1815 if (!strcmp(fs_type, fs->type))
1816 return fs;
1817 }
1818
1819 ret:
1820 if (!all_filesystems)
1821 return NULL;
1822
1823 if (!tst_test->filesystems || tst_test->filesystems[0].type)
1824 return ∅
1825
1826 return &tst_test->filesystems[0];
1827 }
1828
run_tcase_on_fs(struct tst_fs * fs,const char * fs_type)1829 static int run_tcase_on_fs(struct tst_fs *fs, const char *fs_type)
1830 {
1831 int ret;
1832
1833 tst_res(TINFO, "=== Testing on %s ===", fs_type);
1834 tdev.fs_type = fs_type;
1835
1836 if (fs->mkfs_ver && tst_check_cmd(fs->mkfs_ver, 0))
1837 return TCONF;
1838
1839 if (fs->min_kver && check_kver(fs->min_kver, 0))
1840 return TCONF;
1841
1842 prepare_device(fs);
1843
1844 ret = fork_testrun();
1845
1846 if (mntpoint_mounted) {
1847 tst_umount(tst_test->mntpoint);
1848 mntpoint_mounted = 0;
1849 }
1850
1851 return ret;
1852 }
1853
run_tcases_per_fs(void)1854 static int run_tcases_per_fs(void)
1855 {
1856 int ret = 0;
1857 unsigned int i;
1858 const char *const *filesystems = tst_get_supported_fs_types(tst_test->skip_filesystems);
1859
1860 if (!filesystems[0])
1861 tst_brk(TCONF, "There are no supported filesystems");
1862
1863 for (i = 0; filesystems[i]; i++) {
1864 struct tst_fs *fs = lookup_fs_desc(filesystems[i], tst_test->all_filesystems);
1865
1866 if (!fs)
1867 continue;
1868
1869 ret = run_tcase_on_fs(fs, filesystems[i]);
1870
1871 if (ret == TCONF)
1872 continue;
1873
1874 if (ret == 0)
1875 continue;
1876
1877 do_exit(ret);
1878 }
1879
1880 return ret;
1881 }
1882
1883 unsigned int tst_variant;
1884
tst_run_tcases(int argc,char * argv[],struct tst_test * self)1885 void tst_run_tcases(int argc, char *argv[], struct tst_test *self)
1886 {
1887 int ret = 0;
1888 unsigned int test_variants = 1;
1889 struct utsname uval;
1890
1891 lib_pid = getpid();
1892 tst_test = self;
1893
1894 do_setup(argc, argv);
1895 tst_enable_oom_protection(lib_pid);
1896
1897 SAFE_SIGNAL(SIGALRM, alarm_handler);
1898 SAFE_SIGNAL(SIGUSR1, heartbeat_handler);
1899
1900 tst_res(TINFO, "LTP version: "LTP_VERSION);
1901
1902
1903 uname(&uval);
1904 tst_res(TINFO, "Tested kernel: %s %s %s", uval.release, uval.version, uval.machine);
1905
1906 if (tst_test->runtime)
1907 results->runtime = multiply_runtime(tst_test->runtime);
1908
1909 set_overall_timeout();
1910
1911 if (tst_test->test_variants)
1912 test_variants = tst_test->test_variants;
1913
1914 for (tst_variant = 0; tst_variant < test_variants; tst_variant++) {
1915 if (tst_test->all_filesystems || count_fs_descs() > 1)
1916 ret |= run_tcases_per_fs();
1917 else
1918 ret |= fork_testrun();
1919
1920 if (ret & ~(TCONF))
1921 goto exit;
1922 }
1923
1924 exit:
1925 do_exit(ret);
1926 }
1927
1928
tst_flush(void)1929 void tst_flush(void)
1930 {
1931 int rval;
1932
1933 rval = fflush(stderr);
1934 if (rval != 0)
1935 tst_brk(TBROK | TERRNO, "fflush(stderr) failed");
1936
1937 rval = fflush(stdout);
1938 if (rval != 0)
1939 tst_brk(TBROK | TERRNO, "fflush(stdout) failed");
1940
1941 }
1942