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