Home | History | Annotate | Download | only in lib
      1 /*
      2  * Copyright (c) 2015-2016 Cyril Hrubis <chrubis (at) suse.cz>
      3  *
      4  * This program is free software: you can redistribute it and/or modify
      5  * it under the terms of the GNU General Public License as published by
      6  * the Free Software Foundation, either version 2 of the License, or
      7  * (at your option) any later version.
      8  *
      9  * This program is distributed in the hope that it will be useful,
     10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12  * GNU General Public License for more details.
     13  *
     14  * You should have received a copy of the GNU General Public License
     15  * along with this program. If not, see <http://www.gnu.org/licenses/>.
     16  */
     17 
     18 #include <stdio.h>
     19 #include <stdarg.h>
     20 #include <unistd.h>
     21 #include <string.h>
     22 #include <stdlib.h>
     23 #include <errno.h>
     24 #include <sys/mount.h>
     25 #include <sys/types.h>
     26 #include <sys/wait.h>
     27 #include <sys/time.h>
     28 
     29 #define TST_NO_DEFAULT_MAIN
     30 #include "tst_test.h"
     31 #include "tst_device.h"
     32 #include "lapi/futex.h"
     33 #include "lapi/syscalls.h"
     34 #include "tst_ansi_color.h"
     35 #include "tst_safe_stdio.h"
     36 #include "tst_timer_test.h"
     37 
     38 #include "old_resource.h"
     39 #include "old_device.h"
     40 #include "old_tmpdir.h"
     41 
     42 struct tst_test *tst_test;
     43 
     44 static const char *tid;
     45 static int iterations = 1;
     46 static float duration = -1;
     47 static pid_t main_pid, lib_pid;
     48 static int mntpoint_mounted;
     49 
     50 struct results {
     51 	int passed;
     52 	int skipped;
     53 	int failed;
     54 	int warnings;
     55 	unsigned int timeout;
     56 };
     57 
     58 static struct results *results;
     59 
     60 static int ipc_fd;
     61 
     62 extern void *tst_futexes;
     63 extern unsigned int tst_max_futexes;
     64 
     65 #define IPC_ENV_VAR "LTP_IPC_PATH"
     66 
     67 static char ipc_path[1024];
     68 const char *tst_ipc_path = ipc_path;
     69 
     70 static char shm_path[1024];
     71 
     72 static void do_cleanup(void);
     73 static void do_exit(int ret) __attribute__ ((noreturn));
     74 
     75 static void setup_ipc(void)
     76 {
     77 	size_t size = getpagesize();
     78 
     79 	if (access("/dev/shm", F_OK) == 0) {
     80 		snprintf(shm_path, sizeof(shm_path), "/dev/shm/ltp_%s_%d",
     81 		         tid, getpid());
     82 	} else {
     83 		char *tmpdir;
     84 
     85 		if (!tst_tmpdir_created())
     86 			tst_tmpdir();
     87 
     88 		tmpdir = tst_get_tmpdir();
     89 		snprintf(shm_path, sizeof(shm_path), "%s/ltp_%s_%d",
     90 		         tmpdir, tid, getpid());
     91 		free(tmpdir);
     92 	}
     93 
     94 	ipc_fd = open(shm_path, O_CREAT | O_EXCL | O_RDWR, 0600);
     95 	if (ipc_fd < 0)
     96 		tst_brk(TBROK | TERRNO, "open(%s)", shm_path);
     97 	SAFE_CHMOD(shm_path, 0666);
     98 
     99 	SAFE_FTRUNCATE(ipc_fd, size);
    100 
    101 	results = SAFE_MMAP(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, ipc_fd, 0);
    102 
    103 	/* Checkpoints needs to be accessible from processes started by exec() */
    104 	if (tst_test->needs_checkpoints) {
    105 		sprintf(ipc_path, IPC_ENV_VAR "=%s", shm_path);
    106 		putenv(ipc_path);
    107 	} else {
    108 		SAFE_UNLINK(shm_path);
    109 	}
    110 
    111 	SAFE_CLOSE(ipc_fd);
    112 
    113 	if (tst_test->needs_checkpoints) {
    114 		tst_futexes = (char*)results + sizeof(struct results);
    115 		tst_max_futexes = (size - sizeof(struct results))/sizeof(futex_t);
    116 	}
    117 }
    118 
    119 static void cleanup_ipc(void)
    120 {
    121 	size_t size = getpagesize();
    122 
    123 	if (ipc_fd > 0 && close(ipc_fd))
    124 		tst_res(TWARN | TERRNO, "close(ipc_fd) failed");
    125 
    126 	if (shm_path[0] && !access(shm_path, F_OK) && unlink(shm_path))
    127 		tst_res(TWARN | TERRNO, "unlink(%s) failed", shm_path);
    128 
    129 	if (results) {
    130 		msync((void*)results, size, MS_SYNC);
    131 		munmap((void*)results, size);
    132 	}
    133 }
    134 
    135 void tst_reinit(void)
    136 {
    137 	const char *path = getenv(IPC_ENV_VAR);
    138 	size_t size = getpagesize();
    139 	int fd;
    140 	void *ptr;
    141 
    142 	if (!path)
    143 		tst_brk(TBROK, IPC_ENV_VAR" is not defined");
    144 
    145 	if (access(path, F_OK))
    146 		tst_brk(TBROK, "File %s does not exist!", path);
    147 
    148 	fd = SAFE_OPEN(path, O_RDWR);
    149 
    150 	ptr = SAFE_MMAP(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    151 	tst_futexes = (char*)ptr + sizeof(struct results);
    152 	tst_max_futexes = (size - sizeof(struct results))/sizeof(futex_t);
    153 
    154 	SAFE_CLOSE(fd);
    155 }
    156 
    157 static void update_results(int ttype)
    158 {
    159 	if (!results)
    160 		return;
    161 
    162 	switch (ttype) {
    163 	case TCONF:
    164 		tst_atomic_inc(&results->skipped);
    165 	break;
    166 	case TPASS:
    167 		tst_atomic_inc(&results->passed);
    168 	break;
    169 	case TWARN:
    170 		tst_atomic_inc(&results->warnings);
    171 	break;
    172 	case TFAIL:
    173 		tst_atomic_inc(&results->failed);
    174 	break;
    175 	}
    176 }
    177 
    178 static void print_result(const char *file, const int lineno, int ttype,
    179                          const char *fmt, va_list va)
    180 {
    181 	char buf[1024];
    182 	char *str = buf;
    183 	int ret, size = sizeof(buf), ssize;
    184 	const char *str_errno = NULL;
    185 	const char *res;
    186 
    187 	switch (TTYPE_RESULT(ttype)) {
    188 	case TPASS:
    189 		res = "PASS";
    190 	break;
    191 	case TFAIL:
    192 		res = "FAIL";
    193 	break;
    194 	case TBROK:
    195 		res = "BROK";
    196 	break;
    197 	case TCONF:
    198 		res = "CONF";
    199 	break;
    200 	case TWARN:
    201 		res = "WARN";
    202 	break;
    203 	case TINFO:
    204 		res = "INFO";
    205 	break;
    206 	default:
    207 		tst_brk(TBROK, "Invalid ttype value %i", ttype);
    208 		abort();
    209 	}
    210 
    211 	if (ttype & TERRNO)
    212 		str_errno = tst_strerrno(errno);
    213 
    214 	if (ttype & TTERRNO)
    215 		str_errno = tst_strerrno(TEST_ERRNO);
    216 
    217 	ret = snprintf(str, size, "%s:%i: ", file, lineno);
    218 	str += ret;
    219 	size -= ret;
    220 
    221 	if (tst_color_enabled(STDERR_FILENO))
    222 		ret = snprintf(str, size, "%s%s: %s", tst_ttype2color(ttype),
    223 			       res, ANSI_COLOR_RESET);
    224 	else
    225 		ret = snprintf(str, size, "%s: ", res);
    226 	str += ret;
    227 	size -= ret;
    228 
    229 	ssize = size - 2;
    230 	ret = vsnprintf(str, size, fmt, va);
    231 	str += MIN(ret, ssize);
    232 	size -= MIN(ret, ssize);
    233 	if (ret >= ssize) {
    234 		tst_res_(file, lineno, TWARN,
    235 				"Next message is too long and truncated:");
    236 	} else if (str_errno) {
    237 		ssize = size - 2;
    238 		ret = snprintf(str, size, ": %s", str_errno);
    239 		str += MIN(ret, ssize);
    240 		size -= MIN(ret, ssize);
    241 		if (ret >= ssize)
    242 			tst_res_(file, lineno, TWARN,
    243 				"Next message is too long and truncated:");
    244 	}
    245 
    246 	snprintf(str, size, "\n");
    247 
    248 	fputs(buf, stderr);
    249 }
    250 
    251 void tst_vres_(const char *file, const int lineno, int ttype,
    252                const char *fmt, va_list va)
    253 {
    254 	print_result(file, lineno, ttype, fmt, va);
    255 
    256 	update_results(TTYPE_RESULT(ttype));
    257 }
    258 
    259 void tst_vbrk_(const char *file, const int lineno, int ttype,
    260                const char *fmt, va_list va);
    261 
    262 static void (*tst_brk_handler)(const char *file, const int lineno, int ttype,
    263 			       const char *fmt, va_list va) = tst_vbrk_;
    264 
    265 static void tst_cvres(const char *file, const int lineno, int ttype,
    266 		      const char *fmt, va_list va)
    267 {
    268 	if (TTYPE_RESULT(ttype) == TBROK) {
    269 		ttype &= ~TTYPE_MASK;
    270 		ttype |= TWARN;
    271 	}
    272 
    273 	print_result(file, lineno, ttype, fmt, va);
    274 	update_results(TTYPE_RESULT(ttype));
    275 }
    276 
    277 static void do_test_cleanup(void)
    278 {
    279 	tst_brk_handler = tst_cvres;
    280 
    281 	if (tst_test->cleanup)
    282 		tst_test->cleanup();
    283 
    284 	tst_brk_handler = tst_vbrk_;
    285 }
    286 
    287 void tst_vbrk_(const char *file, const int lineno, int ttype,
    288                const char *fmt, va_list va)
    289 {
    290 	print_result(file, lineno, ttype, fmt, va);
    291 
    292 	/*
    293 	 * The getpid implementation in some C library versions may cause cloned
    294 	 * test threads to show the same pid as their parent when CLONE_VM is
    295 	 * specified but CLONE_THREAD is not. Use direct syscall to avoid
    296 	 * cleanup running in the child.
    297 	 */
    298 	if (syscall(SYS_getpid) == main_pid)
    299 		do_test_cleanup();
    300 
    301 	if (getpid() == lib_pid)
    302 		do_exit(TTYPE_RESULT(ttype));
    303 
    304 	exit(TTYPE_RESULT(ttype));
    305 }
    306 
    307 void tst_res_(const char *file, const int lineno, int ttype,
    308               const char *fmt, ...)
    309 {
    310 	va_list va;
    311 
    312 	va_start(va, fmt);
    313 	tst_vres_(file, lineno, ttype, fmt, va);
    314 	va_end(va);
    315 }
    316 
    317 void tst_brk_(const char *file, const int lineno, int ttype,
    318               const char *fmt, ...)
    319 {
    320 	va_list va;
    321 
    322 	va_start(va, fmt);
    323 	tst_brk_handler(file, lineno, ttype, fmt, va);
    324 	va_end(va);
    325 }
    326 
    327 static void check_child_status(pid_t pid, int status)
    328 {
    329 	int ret;
    330 
    331 	if (WIFSIGNALED(status)) {
    332 		tst_brk(TBROK, "Child (%i) killed by signal %s",
    333 		        pid, tst_strsig(WTERMSIG(status)));
    334 	}
    335 
    336 	if (!(WIFEXITED(status)))
    337 		tst_brk(TBROK, "Child (%i) exited abnormaly", pid);
    338 
    339 	ret = WEXITSTATUS(status);
    340 	switch (ret) {
    341 	case TPASS:
    342 	break;
    343 	case TBROK:
    344 	case TCONF:
    345 		tst_brk(ret, "Reported by child (%i)", pid);
    346 	default:
    347 		tst_brk(TBROK, "Invalid child (%i) exit value %i", pid, ret);
    348 	}
    349 }
    350 
    351 void tst_reap_children(void)
    352 {
    353 	int status;
    354 	pid_t pid;
    355 
    356 	for (;;) {
    357 		pid = wait(&status);
    358 
    359 		if (pid > 0) {
    360 			check_child_status(pid, status);
    361 			continue;
    362 		}
    363 
    364 		if (errno == ECHILD)
    365 			break;
    366 
    367 		if (errno == EINTR)
    368 			continue;
    369 
    370 		tst_brk(TBROK | TERRNO, "wait() failed");
    371 	}
    372 }
    373 
    374 
    375 pid_t safe_fork(const char *filename, unsigned int lineno)
    376 {
    377 	pid_t pid;
    378 
    379 	if (!tst_test->forks_child)
    380 		tst_brk(TBROK, "test.forks_child must be set!");
    381 
    382 	fflush(stdout);
    383 
    384 	pid = fork();
    385 	if (pid < 0)
    386 		tst_brk_(filename, lineno, TBROK | TERRNO, "fork() failed");
    387 
    388 	return pid;
    389 }
    390 
    391 static struct option {
    392 	char *optstr;
    393 	char *help;
    394 } options[] = {
    395 	{"h",  "-h       Prints this help"},
    396 	{"i:", "-i n     Execute test n times"},
    397 	{"I:", "-I x     Execute test for n seconds"},
    398 	{"C:", "-C ARG   Run child process with ARG arguments (used internally)"},
    399 };
    400 
    401 static void print_help(void)
    402 {
    403 	unsigned int i;
    404 
    405 	for (i = 0; i < ARRAY_SIZE(options); i++)
    406 		fprintf(stderr, "%s\n", options[i].help);
    407 
    408 	if (!tst_test->options)
    409 		return;
    410 
    411 	for (i = 0; tst_test->options[i].optstr; i++)
    412 		fprintf(stderr, "%s\n", tst_test->options[i].help);
    413 }
    414 
    415 static void check_option_collision(void)
    416 {
    417 	unsigned int i, j;
    418 	struct tst_option *toptions = tst_test->options;
    419 
    420 	if (!toptions)
    421 		return;
    422 
    423 	for (i = 0; toptions[i].optstr; i++) {
    424 		for (j = 0; j < ARRAY_SIZE(options); j++) {
    425 			if (toptions[i].optstr[0] == options[j].optstr[0]) {
    426 				tst_brk(TBROK, "Option collision '%s'",
    427 				        options[j].help);
    428 			}
    429 		}
    430 	}
    431 }
    432 
    433 static unsigned int count_options(void)
    434 {
    435 	unsigned int i;
    436 
    437 	if (!tst_test->options)
    438 		return 0;
    439 
    440 	for (i = 0; tst_test->options[i].optstr; i++);
    441 
    442 	return i;
    443 }
    444 
    445 static void parse_topt(unsigned int topts_len, int opt, char *optarg)
    446 {
    447 	unsigned int i;
    448 	struct tst_option *toptions = tst_test->options;
    449 
    450 	for (i = 0; i < topts_len; i++) {
    451 		if (toptions[i].optstr[0] == opt)
    452 			break;
    453 	}
    454 
    455 	if (i >= topts_len)
    456 		tst_brk(TBROK, "Invalid option '%c' (should not happen)", opt);
    457 
    458 	*(toptions[i].arg) = optarg ? optarg : "";
    459 }
    460 
    461 /* see self_exec.c */
    462 #ifdef UCLINUX
    463 extern char *child_args;
    464 #endif
    465 
    466 static void parse_opts(int argc, char *argv[])
    467 {
    468 	unsigned int i, topts_len = count_options();
    469 	char optstr[2 * ARRAY_SIZE(options) + 2 * topts_len];
    470 	int opt;
    471 
    472 	check_option_collision();
    473 
    474 	optstr[0] = 0;
    475 
    476 	for (i = 0; i < ARRAY_SIZE(options); i++)
    477 		strcat(optstr, options[i].optstr);
    478 
    479 	for (i = 0; i < topts_len; i++)
    480 		strcat(optstr, tst_test->options[i].optstr);
    481 
    482 	while ((opt = getopt(argc, argv, optstr)) > 0) {
    483 		switch (opt) {
    484 		case '?':
    485 			print_help();
    486 			tst_brk(TBROK, "Invalid option");
    487 		case 'h':
    488 			print_help();
    489 			exit(0);
    490 		case 'i':
    491 			iterations = atoi(optarg);
    492 		break;
    493 		case 'I':
    494 			duration = atof(optarg);
    495 		break;
    496 		case 'C':
    497 #ifdef UCLINUX
    498 			child_args = optarg;
    499 #endif
    500 		break;
    501 		default:
    502 			parse_topt(topts_len, opt, optarg);
    503 		}
    504 	}
    505 
    506 	if (optind < argc)
    507 		tst_brk(TBROK, "Unexpected argument(s) '%s'...", argv[optind]);
    508 }
    509 
    510 int tst_parse_int(const char *str, int *val, int min, int max)
    511 {
    512 	long rval;
    513 
    514 	if (!str)
    515 		return 0;
    516 
    517 	int ret = tst_parse_long(str, &rval, min, max);
    518 
    519 	if (ret)
    520 		return ret;
    521 
    522 	*val = (int)rval;
    523 	return 0;
    524 }
    525 
    526 int tst_parse_long(const char *str, long *val, long min, long max)
    527 {
    528 	long rval;
    529 	char *end;
    530 
    531 	if (!str)
    532 		return 0;
    533 
    534 	errno = 0;
    535 	rval = strtol(str, &end, 10);
    536 
    537 	if (str == end || *end != '\0')
    538 		return EINVAL;
    539 
    540 	if (errno)
    541 		return errno;
    542 
    543 	if (rval > max || rval < min)
    544 		return ERANGE;
    545 
    546 	*val = rval;
    547 	return 0;
    548 }
    549 
    550 int tst_parse_float(const char *str, float *val, float min, float max)
    551 {
    552 	double rval;
    553 	char *end;
    554 
    555 	if (!str)
    556 		return 0;
    557 
    558 	errno = 0;
    559 	rval = strtod(str, &end);
    560 
    561 	if (str == end || *end != '\0')
    562 		return EINVAL;
    563 
    564 	if (errno)
    565 		return errno;
    566 
    567 	if (rval > (double)max || rval < (double)min)
    568 		return ERANGE;
    569 
    570 	*val = (float)rval;
    571 	return 0;
    572 }
    573 
    574 static void do_exit(int ret)
    575 {
    576 	if (results) {
    577 		printf("\nSummary:\n");
    578 		printf("passed   %d\n", results->passed);
    579 		printf("failed   %d\n", results->failed);
    580 		printf("skipped  %d\n", results->skipped);
    581 		printf("warnings %d\n", results->warnings);
    582 
    583 		if (results->passed && ret == TCONF)
    584 			ret = 0;
    585 
    586 		if (results->failed)
    587 			ret |= TFAIL;
    588 
    589 		if (results->skipped && !results->passed)
    590 			ret |= TCONF;
    591 
    592 		if (results->warnings)
    593 			ret |= TWARN;
    594 	}
    595 
    596 	do_cleanup();
    597 
    598 	exit(ret);
    599 }
    600 
    601 void check_kver(void)
    602 {
    603 	int v1, v2, v3;
    604 
    605 	if (tst_parse_kver(tst_test->min_kver, &v1, &v2, &v3)) {
    606 		tst_res(TWARN,
    607 		        "Invalid kernel version %s, expected %%d.%%d.%%d",
    608 		        tst_test->min_kver);
    609 	}
    610 
    611 	if (tst_kvercmp(v1, v2, v3) < 0) {
    612 		tst_brk(TCONF, "The test requires kernel %s or newer",
    613 		        tst_test->min_kver);
    614 	}
    615 }
    616 
    617 static int results_equal(struct results *a, struct results *b)
    618 {
    619 	if (a->passed != b->passed)
    620 		return 0;
    621 
    622 	if (a->failed != b->failed)
    623 		return 0;
    624 
    625 	if (a->skipped != b->skipped)
    626 		return 0;
    627 
    628 	return 1;
    629 }
    630 
    631 static int needs_tmpdir(void)
    632 {
    633 	return tst_test->needs_tmpdir ||
    634 	       tst_test->needs_device ||
    635 	       tst_test->resource_files ||
    636 	       tst_test->needs_checkpoints;
    637 }
    638 
    639 static void copy_resources(void)
    640 {
    641 	unsigned int i;
    642 
    643 	for (i = 0; tst_test->resource_files[i]; i++)
    644 		TST_RESOURCE_COPY(NULL, tst_test->resource_files[i], NULL);
    645 }
    646 
    647 static const char *get_tid(char *argv[])
    648 {
    649 	char *p;
    650 
    651 	if (!argv[0] || !argv[0][0]) {
    652 		tst_res(TINFO, "argv[0] is empty!");
    653 		return "ltp_empty_argv";
    654 	}
    655 
    656 	p = strrchr(argv[0], '/');
    657 	if (p)
    658 		return p+1;
    659 
    660 	return argv[0];
    661 }
    662 
    663 static struct tst_device tdev;
    664 struct tst_device *tst_device;
    665 
    666 static void assert_test_fn(void)
    667 {
    668 	int cnt = 0;
    669 
    670 	if (tst_test->test)
    671 		cnt++;
    672 
    673 	if (tst_test->test_all)
    674 		cnt++;
    675 
    676 	if (tst_test->sample)
    677 		cnt++;
    678 
    679 	if (!cnt)
    680 		tst_brk(TBROK, "No test function speficied");
    681 
    682 	if (cnt != 1)
    683 		tst_brk(TBROK, "You can define only one test function");
    684 
    685 	if (tst_test->test && !tst_test->tcnt)
    686 		tst_brk(TBROK, "Number of tests (tcnt) must not be > 0");
    687 
    688 	if (!tst_test->test && tst_test->tcnt)
    689 		tst_brk(TBROK, "You can define tcnt only for test()");
    690 }
    691 
    692 static void prepare_device(void)
    693 {
    694 	if (tst_test->format_device) {
    695 		SAFE_MKFS(tdev.dev, tdev.fs_type, tst_test->dev_fs_opts,
    696 			  tst_test->dev_extra_opt);
    697 	}
    698 
    699 	if (tst_test->mount_device) {
    700 		SAFE_MOUNT(tdev.dev, tst_test->mntpoint, tdev.fs_type,
    701 			   tst_test->mnt_flags, tst_test->mnt_data);
    702 		mntpoint_mounted = 1;
    703 	}
    704 }
    705 
    706 static void do_setup(int argc, char *argv[])
    707 {
    708 	if (!tst_test)
    709 		tst_brk(TBROK, "No tests to run");
    710 
    711 	if (tst_test->tconf_msg)
    712 		tst_brk(TCONF, "%s", tst_test->tconf_msg);
    713 
    714 	assert_test_fn();
    715 
    716 	tid = get_tid(argv);
    717 
    718 	if (tst_test->sample)
    719 		tst_test = tst_timer_test_setup(tst_test);
    720 
    721 	parse_opts(argc, argv);
    722 
    723 	if (tst_test->needs_root && geteuid() != 0)
    724 		tst_brk(TCONF, "Test needs to be run as root");
    725 
    726 	if (tst_test->min_kver)
    727 		check_kver();
    728 
    729 	if (tst_test->format_device)
    730 		tst_test->needs_device = 1;
    731 
    732 	if (tst_test->mount_device) {
    733 		tst_test->needs_device = 1;
    734 		tst_test->format_device = 1;
    735 	}
    736 
    737 	if (tst_test->all_filesystems)
    738 		tst_test->needs_device = 1;
    739 
    740 	setup_ipc();
    741 
    742 	if (needs_tmpdir() && !tst_tmpdir_created())
    743 		tst_tmpdir();
    744 
    745 	if (tst_test->mntpoint)
    746 		SAFE_MKDIR(tst_test->mntpoint, 0777);
    747 
    748 	if ((tst_test->needs_rofs || tst_test->mount_device ||
    749 	     tst_test->all_filesystems) && !tst_test->mntpoint) {
    750 		tst_brk(TBROK, "tst_test->mntpoint must be set!");
    751 	}
    752 
    753 	if (tst_test->needs_rofs) {
    754 		/* If we failed to mount read-only tmpfs. Fallback to
    755 		 * using a device with empty read-only filesystem.
    756 		 */
    757 		if (mount(NULL, tst_test->mntpoint, "tmpfs", MS_RDONLY, NULL)) {
    758 			tst_res(TINFO | TERRNO, "Can't mount tmpfs read-only"
    759 				" at %s, setting up a device instead\n",
    760 				tst_test->mntpoint);
    761 			tst_test->mount_device = 1;
    762 			tst_test->needs_device = 1;
    763 			tst_test->format_device = 1;
    764 			tst_test->mnt_flags = MS_RDONLY;
    765 		} else {
    766 			mntpoint_mounted = 1;
    767 		}
    768 	}
    769 
    770 	if (tst_test->needs_device && !mntpoint_mounted) {
    771 		tdev.dev = tst_acquire_device_(NULL, tst_test->dev_min_size);
    772 
    773 		if (!tdev.dev)
    774 			tst_brk(TCONF, "Failed to acquire device");
    775 
    776 		tst_device = &tdev;
    777 
    778 		if (tst_test->dev_fs_type)
    779 			tdev.fs_type = tst_test->dev_fs_type;
    780 		else
    781 			tdev.fs_type = tst_dev_fs_type();
    782 
    783 		if (!tst_test->all_filesystems)
    784 			prepare_device();
    785 	}
    786 
    787 	if (tst_test->resource_files)
    788 		copy_resources();
    789 }
    790 
    791 static void do_test_setup(void)
    792 {
    793 	main_pid = getpid();
    794 
    795 	if (tst_test->setup)
    796 		tst_test->setup();
    797 
    798 	if (main_pid != getpid())
    799 		tst_brk(TBROK, "Runaway child in setup()!");
    800 }
    801 
    802 static void do_cleanup(void)
    803 {
    804 	if (mntpoint_mounted)
    805 		tst_umount(tst_test->mntpoint);
    806 
    807 	if (tst_test->needs_device && tdev.dev)
    808 		tst_release_device(tdev.dev);
    809 
    810 	if (tst_tmpdir_created()) {
    811 		/* avoid munmap() on wrong pointer in tst_rmdir() */
    812 		tst_futexes = NULL;
    813 		tst_rmdir();
    814 	}
    815 
    816 	cleanup_ipc();
    817 }
    818 
    819 static void run_tests(void)
    820 {
    821 	unsigned int i;
    822 	struct results saved_results;
    823 
    824 	if (!tst_test->test) {
    825 		saved_results = *results;
    826 		tst_test->test_all();
    827 
    828 		if (getpid() != main_pid) {
    829 			exit(0);
    830 		}
    831 
    832 		tst_reap_children();
    833 
    834 		if (results_equal(&saved_results, results))
    835 			tst_brk(TBROK, "Test haven't reported results!");
    836 		return;
    837 	}
    838 
    839 	for (i = 0; i < tst_test->tcnt; i++) {
    840 		saved_results = *results;
    841 		tst_test->test(i);
    842 
    843 		if (getpid() != main_pid) {
    844 			exit(0);
    845 		}
    846 
    847 		tst_reap_children();
    848 
    849 		if (results_equal(&saved_results, results))
    850 			tst_brk(TBROK, "Test %i haven't reported results!", i);
    851 	}
    852 }
    853 
    854 static unsigned long long get_time_ms(void)
    855 {
    856 	struct timeval tv;
    857 
    858 	gettimeofday(&tv, NULL);
    859 
    860 	return tv.tv_sec * 1000 + tv.tv_usec / 1000;
    861 }
    862 
    863 static void add_paths(void)
    864 {
    865 	char *old_path = getenv("PATH");
    866 	const char *start_dir;
    867 	char *new_path;
    868 
    869 	start_dir = tst_get_startwd();
    870 
    871 	if (old_path)
    872 		SAFE_ASPRINTF(&new_path, "%s::%s", old_path, start_dir);
    873 	else
    874 		SAFE_ASPRINTF(&new_path, "::%s", start_dir);
    875 
    876 	SAFE_SETENV("PATH", new_path, 1);
    877 	free(new_path);
    878 }
    879 
    880 static void heartbeat(void)
    881 {
    882 	kill(getppid(), SIGUSR1);
    883 }
    884 
    885 static void testrun(void)
    886 {
    887 	unsigned int i = 0;
    888 	unsigned long long stop_time = 0;
    889 	int cont = 1;
    890 
    891 	add_paths();
    892 	do_test_setup();
    893 
    894 	if (duration > 0)
    895 		stop_time = get_time_ms() + (unsigned long long)(duration * 1000);
    896 
    897 	for (;;) {
    898 		cont = 0;
    899 
    900 		if (i < (unsigned int)iterations) {
    901 			i++;
    902 			cont = 1;
    903 		}
    904 
    905 		if (stop_time && get_time_ms() < stop_time)
    906 			cont = 1;
    907 
    908 		if (!cont)
    909 			break;
    910 
    911 		run_tests();
    912 		heartbeat();
    913 	}
    914 
    915 	do_test_cleanup();
    916 	exit(0);
    917 }
    918 
    919 static pid_t test_pid;
    920 
    921 
    922 static volatile sig_atomic_t sigkill_retries;
    923 
    924 #define WRITE_MSG(msg) do { \
    925 	if (write(2, msg, sizeof(msg) - 1)) { \
    926 		/* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66425 */ \
    927 	} \
    928 } while (0)
    929 
    930 static void alarm_handler(int sig LTP_ATTRIBUTE_UNUSED)
    931 {
    932 	WRITE_MSG("Test timeouted, sending SIGKILL!\n");
    933 	kill(-test_pid, SIGKILL);
    934 	alarm(5);
    935 
    936 	if (++sigkill_retries > 10) {
    937 		WRITE_MSG("Cannot kill test processes!\n");
    938 		WRITE_MSG("Congratulation, likely test hit a kernel bug.\n");
    939 		WRITE_MSG("Exitting uncleanly...\n");
    940 		_exit(TFAIL);
    941 	}
    942 }
    943 
    944 static void heartbeat_handler(int sig LTP_ATTRIBUTE_UNUSED)
    945 {
    946 	alarm(results->timeout);
    947 	sigkill_retries = 0;
    948 }
    949 
    950 static void sigint_handler(int sig LTP_ATTRIBUTE_UNUSED)
    951 {
    952 	if (test_pid > 0) {
    953 		WRITE_MSG("Sending SIGKILL to test process...\n");
    954 		kill(-test_pid, SIGKILL);
    955 	}
    956 }
    957 
    958 void tst_set_timeout(int timeout)
    959 {
    960 	char *mul = getenv("LTP_TIMEOUT_MUL");
    961 
    962 	if (timeout == -1) {
    963 		tst_res(TINFO, "Timeout per run is disabled");
    964 		return;
    965 	}
    966 
    967 	results->timeout = timeout;
    968 
    969 	if (mul) {
    970 		float m = atof(mul);
    971 
    972 		if (m < 1)
    973 			tst_brk(TBROK, "Invalid timeout multiplier '%s'", mul);
    974 
    975 		results->timeout = results->timeout * m + 0.5;
    976 	}
    977 
    978 	tst_res(TINFO, "Timeout per run is %uh %02um %02us",
    979 		results->timeout/3600, (results->timeout%3600)/60,
    980 		results->timeout % 60);
    981 
    982 	if (getpid() == lib_pid)
    983 		alarm(results->timeout);
    984 	else
    985 		heartbeat();
    986 }
    987 
    988 static int fork_testrun(void)
    989 {
    990 	int status;
    991 
    992 	if (tst_test->timeout)
    993 		tst_set_timeout(tst_test->timeout);
    994 	else
    995 		tst_set_timeout(300);
    996 
    997 	SAFE_SIGNAL(SIGINT, sigint_handler);
    998 
    999 	test_pid = fork();
   1000 	if (test_pid < 0)
   1001 		tst_brk(TBROK | TERRNO, "fork()");
   1002 
   1003 	if (!test_pid) {
   1004 		SAFE_SIGNAL(SIGALRM, SIG_DFL);
   1005 		SAFE_SIGNAL(SIGUSR1, SIG_DFL);
   1006 		SAFE_SIGNAL(SIGINT, SIG_DFL);
   1007 		SAFE_SETPGID(0, 0);
   1008 		testrun();
   1009 	}
   1010 
   1011 	SAFE_WAITPID(test_pid, &status, 0);
   1012 	alarm(0);
   1013 	SAFE_SIGNAL(SIGINT, SIG_DFL);
   1014 
   1015 	if (WIFEXITED(status) && WEXITSTATUS(status))
   1016 		return WEXITSTATUS(status);
   1017 
   1018 	if (WIFSIGNALED(status) && WTERMSIG(status) == SIGKILL) {
   1019 		tst_res(TINFO, "If you are running on slow machine, "
   1020 			       "try exporting LTP_TIMEOUT_MUL > 1");
   1021 		tst_brk(TBROK, "Test killed! (timeout?)");
   1022 	}
   1023 
   1024 	if (WIFSIGNALED(status))
   1025 		tst_brk(TBROK, "Test killed by %s!", tst_strsig(WTERMSIG(status)));
   1026 
   1027 	return 0;
   1028 }
   1029 
   1030 static int run_tcases_per_fs(void)
   1031 {
   1032 	int ret = 0;
   1033 	unsigned int i;
   1034 	const char *const *filesystems = tst_get_supported_fs_types();
   1035 
   1036 	if (!filesystems[0])
   1037 		tst_brk(TCONF, "There are no supported filesystems");
   1038 
   1039 	for (i = 0; filesystems[i]; i++) {
   1040 		tdev.fs_type = filesystems[i];
   1041 
   1042 		prepare_device();
   1043 
   1044 		ret = fork_testrun();
   1045 
   1046 		if (mntpoint_mounted) {
   1047 			tst_umount(tst_test->mntpoint);
   1048 			mntpoint_mounted = 0;
   1049 		}
   1050 
   1051 		if (ret == TCONF) {
   1052 			update_results(ret);
   1053 			continue;
   1054 		}
   1055 
   1056 		if (ret == 0)
   1057 			continue;
   1058 
   1059 		do_exit(ret);
   1060 	}
   1061 
   1062 	return ret;
   1063 }
   1064 
   1065 void tst_run_tcases(int argc, char *argv[], struct tst_test *self)
   1066 {
   1067 	int ret;
   1068 
   1069 	lib_pid = getpid();
   1070 	tst_test = self;
   1071 
   1072 	do_setup(argc, argv);
   1073 
   1074 	TCID = tid;
   1075 
   1076 	SAFE_SIGNAL(SIGALRM, alarm_handler);
   1077 	SAFE_SIGNAL(SIGUSR1, heartbeat_handler);
   1078 
   1079 	if (tst_test->all_filesystems)
   1080 		ret = run_tcases_per_fs();
   1081 	else
   1082 		ret = fork_testrun();
   1083 
   1084 	do_exit(ret);
   1085 }
   1086