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