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