blob: 9b4f43828854d8426db2c8323285b82b430d142e [file] [log] [blame]
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +01001/*
2 * Copyright (c) 2015-2016 Cyril Hrubis <chrubis@suse.cz>
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include <stdio.h>
19#include <stdarg.h>
20#include <unistd.h>
21#include <string.h>
22#include <stdlib.h>
23#include <errno.h>
Sandeep Patilc9a7def2017-09-19 12:49:58 -070024#include <sys/mount.h>
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +010025#include <sys/types.h>
26#include <sys/wait.h>
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +010027
28#define TST_NO_DEFAULT_MAIN
29#include "tst_test.h"
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +010030#include "tst_device.h"
31#include "lapi/futex.h"
Steve Mucklec20831d2017-09-20 13:23:06 -070032#include "lapi/syscalls.h"
Petr Vorel3a0ef862017-03-01 15:31:08 +010033#include "tst_ansi_color.h"
Jan Stancekb95b1992017-10-10 15:47:58 +020034#include "tst_safe_stdio.h"
Cyril Hrubisc4596542017-06-20 15:42:18 +020035#include "tst_timer_test.h"
Cyril Hrubis2f7c8e92018-01-22 15:19:31 +010036#include "tst_clocks.h"
37#include "tst_timer.h"
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +010038
39#include "old_resource.h"
40#include "old_device.h"
41#include "old_tmpdir.h"
42
43struct tst_test *tst_test;
44
Li Wangb5d620a2017-11-01 13:15:23 +080045static const char *tid;
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +010046static int iterations = 1;
47static float duration = -1;
Jan Stanceke0bfa7d2016-06-08 15:27:55 +020048static pid_t main_pid, lib_pid;
Sandeep Patilc9a7def2017-09-19 12:49:58 -070049static int mntpoint_mounted;
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +010050
51struct results {
Jan Stancekc54ca052016-04-13 12:31:13 +020052 int passed;
53 int skipped;
54 int failed;
55 int warnings;
Cyril Hrubis2ad59b72016-08-03 15:53:55 +020056 unsigned int timeout;
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +010057};
58
59static struct results *results;
60
61static int ipc_fd;
62
63extern void *tst_futexes;
64extern unsigned int tst_max_futexes;
65
66#define IPC_ENV_VAR "LTP_IPC_PATH"
67
68static char ipc_path[1024];
69const char *tst_ipc_path = ipc_path;
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +010070
71static char shm_path[1024];
72
Jan Stancek332540e2016-06-08 16:48:22 +020073static void do_cleanup(void);
Cyril Hrubisfa495172016-06-08 16:06:35 +020074static void do_exit(int ret) __attribute__ ((noreturn));
Jan Stanceke0bfa7d2016-06-08 15:27:55 +020075
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +010076static void setup_ipc(void)
77{
78 size_t size = getpagesize();
79
Steven Jackson9f41dcf2016-12-21 20:09:01 +000080 if (access("/dev/shm", F_OK) == 0) {
81 snprintf(shm_path, sizeof(shm_path), "/dev/shm/ltp_%s_%d",
Li Wangb5d620a2017-11-01 13:15:23 +080082 tid, getpid());
Steven Jackson9f41dcf2016-12-21 20:09:01 +000083 } else {
84 char *tmpdir;
85
86 if (!tst_tmpdir_created())
87 tst_tmpdir();
88
89 tmpdir = tst_get_tmpdir();
90 snprintf(shm_path, sizeof(shm_path), "%s/ltp_%s_%d",
Li Wangb5d620a2017-11-01 13:15:23 +080091 tmpdir, tid, getpid());
Steven Jackson9f41dcf2016-12-21 20:09:01 +000092 free(tmpdir);
93 }
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +010094
95 ipc_fd = open(shm_path, O_CREAT | O_EXCL | O_RDWR, 0600);
96 if (ipc_fd < 0)
97 tst_brk(TBROK | TERRNO, "open(%s)", shm_path);
Jan Stancek2113eef2017-10-04 12:25:42 +020098 SAFE_CHMOD(shm_path, 0666);
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +010099
100 SAFE_FTRUNCATE(ipc_fd, size);
101
102 results = SAFE_MMAP(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, ipc_fd, 0);
103
104 /* Checkpoints needs to be accessible from processes started by exec() */
Jan Stancek03fc5372017-10-10 13:36:59 +0200105 if (tst_test->needs_checkpoints) {
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100106 sprintf(ipc_path, IPC_ENV_VAR "=%s", shm_path);
Jan Stancek03fc5372017-10-10 13:36:59 +0200107 putenv(ipc_path);
108 } else {
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100109 SAFE_UNLINK(shm_path);
Jan Stancek03fc5372017-10-10 13:36:59 +0200110 }
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100111
112 SAFE_CLOSE(ipc_fd);
113
114 if (tst_test->needs_checkpoints) {
115 tst_futexes = (char*)results + sizeof(struct results);
116 tst_max_futexes = (size - sizeof(struct results))/sizeof(futex_t);
117 }
118}
119
120static void cleanup_ipc(void)
121{
122 size_t size = getpagesize();
123
124 if (ipc_fd > 0 && close(ipc_fd))
125 tst_res(TWARN | TERRNO, "close(ipc_fd) failed");
126
Cyril Hrubis9726b902017-07-27 11:28:50 +0200127 if (shm_path[0] && !access(shm_path, F_OK) && unlink(shm_path))
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100128 tst_res(TWARN | TERRNO, "unlink(%s) failed", shm_path);
129
Cyril Hrubis9726b902017-07-27 11:28:50 +0200130 if (results) {
131 msync((void*)results, size, MS_SYNC);
132 munmap((void*)results, size);
133 }
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100134}
135
136void tst_reinit(void)
137{
Jan Stancek03fc5372017-10-10 13:36:59 +0200138 const char *path = getenv(IPC_ENV_VAR);
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100139 size_t size = getpagesize();
140 int fd;
141 void *ptr;
142
143 if (!path)
Jan Stancek03fc5372017-10-10 13:36:59 +0200144 tst_brk(TBROK, IPC_ENV_VAR" is not defined");
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100145
146 if (access(path, F_OK))
147 tst_brk(TBROK, "File %s does not exist!", path);
148
149 fd = SAFE_OPEN(path, O_RDWR);
150
151 ptr = SAFE_MMAP(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
152 tst_futexes = (char*)ptr + sizeof(struct results);
153 tst_max_futexes = (size - sizeof(struct results))/sizeof(futex_t);
154
155 SAFE_CLOSE(fd);
156}
157
Cyril Hrubis160ffcc2017-02-14 10:21:08 +0100158static void update_results(int ttype)
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100159{
Cyril Hrubisd97debf2017-02-13 12:37:39 +0100160 if (!results)
161 return;
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100162
163 switch (ttype) {
164 case TCONF:
165 tst_atomic_inc(&results->skipped);
166 break;
167 case TPASS:
168 tst_atomic_inc(&results->passed);
169 break;
170 case TWARN:
171 tst_atomic_inc(&results->warnings);
172 break;
173 case TFAIL:
174 tst_atomic_inc(&results->failed);
175 break;
176 }
177}
178
179static void print_result(const char *file, const int lineno, int ttype,
180 const char *fmt, va_list va)
181{
182 char buf[1024];
183 char *str = buf;
Veronika Kabatovacecbd0c2017-11-07 17:10:42 +0100184 int ret, size = sizeof(buf), ssize;
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100185 const char *str_errno = NULL;
186 const char *res;
187
188 switch (TTYPE_RESULT(ttype)) {
189 case TPASS:
190 res = "PASS";
191 break;
192 case TFAIL:
193 res = "FAIL";
194 break;
195 case TBROK:
196 res = "BROK";
197 break;
198 case TCONF:
199 res = "CONF";
200 break;
201 case TWARN:
202 res = "WARN";
203 break;
204 case TINFO:
205 res = "INFO";
206 break;
207 default:
208 tst_brk(TBROK, "Invalid ttype value %i", ttype);
Cyril Hrubis6440c5d2017-02-09 15:41:24 +0100209 abort();
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100210 }
211
212 if (ttype & TERRNO)
213 str_errno = tst_strerrno(errno);
214
215 if (ttype & TTERRNO)
216 str_errno = tst_strerrno(TEST_ERRNO);
217
Petr Vorela7f61332017-01-24 20:47:30 +0100218 ret = snprintf(str, size, "%s:%i: ", file, lineno);
219 str += ret;
220 size -= ret;
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100221
Cyril Hrubis047c7272017-02-13 16:23:36 +0100222 if (tst_color_enabled(STDERR_FILENO))
Petr Vorela7f61332017-01-24 20:47:30 +0100223 ret = snprintf(str, size, "%s%s: %s", tst_ttype2color(ttype),
224 res, ANSI_COLOR_RESET);
225 else
226 ret = snprintf(str, size, "%s: ", res);
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100227 str += ret;
228 size -= ret;
229
Veronika Kabatovacecbd0c2017-11-07 17:10:42 +0100230 ssize = size - 2;
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100231 ret = vsnprintf(str, size, fmt, va);
Veronika Kabatovacecbd0c2017-11-07 17:10:42 +0100232 str += MIN(ret, ssize);
233 size -= MIN(ret, ssize);
234 if (ret >= ssize) {
235 tst_res_(file, lineno, TWARN,
236 "Next message is too long and truncated:");
237 } else if (str_errno) {
238 ssize = size - 2;
Petr Vorela7f61332017-01-24 20:47:30 +0100239 ret = snprintf(str, size, ": %s", str_errno);
Veronika Kabatovacecbd0c2017-11-07 17:10:42 +0100240 str += MIN(ret, ssize);
241 size -= MIN(ret, ssize);
242 if (ret >= ssize)
243 tst_res_(file, lineno, TWARN,
244 "Next message is too long and truncated:");
Petr Vorela7f61332017-01-24 20:47:30 +0100245 }
246
247 snprintf(str, size, "\n");
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100248
249 fputs(buf, stderr);
250}
251
252void tst_vres_(const char *file, const int lineno, int ttype,
253 const char *fmt, va_list va)
254{
255 print_result(file, lineno, ttype, fmt, va);
256
Cyril Hrubis160ffcc2017-02-14 10:21:08 +0100257 update_results(TTYPE_RESULT(ttype));
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100258}
259
260void tst_vbrk_(const char *file, const int lineno, int ttype,
Cyril Hrubis6440c5d2017-02-09 15:41:24 +0100261 const char *fmt, va_list va);
262
263static void (*tst_brk_handler)(const char *file, const int lineno, int ttype,
264 const char *fmt, va_list va) = tst_vbrk_;
265
266static void tst_cvres(const char *file, const int lineno, int ttype,
267 const char *fmt, va_list va)
268{
269 if (TTYPE_RESULT(ttype) == TBROK) {
270 ttype &= ~TTYPE_MASK;
271 ttype |= TWARN;
272 }
273
274 print_result(file, lineno, ttype, fmt, va);
275 update_results(TTYPE_RESULT(ttype));
276}
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100277
Cyril Hrubis4aebb6c2016-06-07 13:40:41 +0200278static void do_test_cleanup(void)
279{
Cyril Hrubis6440c5d2017-02-09 15:41:24 +0100280 tst_brk_handler = tst_cvres;
281
Cyril Hrubis4aebb6c2016-06-07 13:40:41 +0200282 if (tst_test->cleanup)
283 tst_test->cleanup();
Cyril Hrubis6440c5d2017-02-09 15:41:24 +0100284
285 tst_brk_handler = tst_vbrk_;
Cyril Hrubis4aebb6c2016-06-07 13:40:41 +0200286}
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100287
288void tst_vbrk_(const char *file, const int lineno, int ttype,
289 const char *fmt, va_list va)
290{
291 print_result(file, lineno, ttype, fmt, va);
292
Steve Mucklec20831d2017-09-20 13:23:06 -0700293 /*
294 * The getpid implementation in some C library versions may cause cloned
295 * test threads to show the same pid as their parent when CLONE_VM is
296 * specified but CLONE_THREAD is not. Use direct syscall to avoid
297 * cleanup running in the child.
298 */
299 if (syscall(SYS_getpid) == main_pid)
Cyril Hrubis4aebb6c2016-06-07 13:40:41 +0200300 do_test_cleanup();
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100301
Jan Stanceke0bfa7d2016-06-08 15:27:55 +0200302 if (getpid() == lib_pid)
Cyril Hrubisfa495172016-06-08 16:06:35 +0200303 do_exit(TTYPE_RESULT(ttype));
Jan Stanceke0bfa7d2016-06-08 15:27:55 +0200304
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100305 exit(TTYPE_RESULT(ttype));
306}
307
308void tst_res_(const char *file, const int lineno, int ttype,
309 const char *fmt, ...)
310{
311 va_list va;
312
313 va_start(va, fmt);
314 tst_vres_(file, lineno, ttype, fmt, va);
315 va_end(va);
316}
317
318void tst_brk_(const char *file, const int lineno, int ttype,
319 const char *fmt, ...)
320{
321 va_list va;
322
323 va_start(va, fmt);
Cyril Hrubis6440c5d2017-02-09 15:41:24 +0100324 tst_brk_handler(file, lineno, ttype, fmt, va);
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100325 va_end(va);
326}
327
328static void check_child_status(pid_t pid, int status)
329{
330 int ret;
331
332 if (WIFSIGNALED(status)) {
333 tst_brk(TBROK, "Child (%i) killed by signal %s",
334 pid, tst_strsig(WTERMSIG(status)));
335 }
336
337 if (!(WIFEXITED(status)))
Petr Vorelf8853482017-10-31 09:40:38 +0100338 tst_brk(TBROK, "Child (%i) exited abnormaly", pid);
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100339
340 ret = WEXITSTATUS(status);
341 switch (ret) {
342 case TPASS:
343 break;
344 case TBROK:
345 case TCONF:
346 tst_brk(ret, "Reported by child (%i)", pid);
347 default:
348 tst_brk(TBROK, "Invalid child (%i) exit value %i", pid, ret);
349 }
350}
351
Stanislav Kholmanskikh6b56aa72016-08-04 17:16:31 +0300352void tst_reap_children(void)
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100353{
354 int status;
355 pid_t pid;
356
357 for (;;) {
358 pid = wait(&status);
359
360 if (pid > 0) {
361 check_child_status(pid, status);
362 continue;
363 }
364
365 if (errno == ECHILD)
366 break;
367
368 if (errno == EINTR)
369 continue;
370
371 tst_brk(TBROK | TERRNO, "wait() failed");
372 }
373}
374
375
376pid_t safe_fork(const char *filename, unsigned int lineno)
377{
378 pid_t pid;
379
380 if (!tst_test->forks_child)
381 tst_brk(TBROK, "test.forks_child must be set!");
382
383 fflush(stdout);
384
385 pid = fork();
386 if (pid < 0)
387 tst_brk_(filename, lineno, TBROK | TERRNO, "fork() failed");
388
389 return pid;
390}
391
392static struct option {
393 char *optstr;
394 char *help;
395} options[] = {
Cyril Hrubisb819c222016-08-03 14:36:07 +0200396 {"h", "-h Prints this help"},
397 {"i:", "-i n Execute test n times"},
398 {"I:", "-I x Execute test for n seconds"},
399 {"C:", "-C ARG Run child process with ARG arguments (used internally)"},
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100400};
401
402static void print_help(void)
403{
404 unsigned int i;
405
406 for (i = 0; i < ARRAY_SIZE(options); i++)
407 fprintf(stderr, "%s\n", options[i].help);
408
409 if (!tst_test->options)
410 return;
411
412 for (i = 0; tst_test->options[i].optstr; i++)
Cyril Hrubisb819c222016-08-03 14:36:07 +0200413 fprintf(stderr, "%s\n", tst_test->options[i].help);
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100414}
415
416static void check_option_collision(void)
417{
418 unsigned int i, j;
419 struct tst_option *toptions = tst_test->options;
420
421 if (!toptions)
422 return;
423
424 for (i = 0; toptions[i].optstr; i++) {
425 for (j = 0; j < ARRAY_SIZE(options); j++) {
426 if (toptions[i].optstr[0] == options[j].optstr[0]) {
427 tst_brk(TBROK, "Option collision '%s'",
428 options[j].help);
429 }
430 }
431 }
432}
433
434static unsigned int count_options(void)
435{
436 unsigned int i;
437
438 if (!tst_test->options)
439 return 0;
440
441 for (i = 0; tst_test->options[i].optstr; i++);
442
443 return i;
444}
445
446static void parse_topt(unsigned int topts_len, int opt, char *optarg)
447{
448 unsigned int i;
449 struct tst_option *toptions = tst_test->options;
450
451 for (i = 0; i < topts_len; i++) {
452 if (toptions[i].optstr[0] == opt)
453 break;
454 }
455
456 if (i >= topts_len)
457 tst_brk(TBROK, "Invalid option '%c' (should not happen)", opt);
458
Jan Stancekc07d36c2016-08-01 11:44:55 +0200459 *(toptions[i].arg) = optarg ? optarg : "";
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100460}
461
462/* see self_exec.c */
463#ifdef UCLINUX
464extern char *child_args;
465#endif
466
467static void parse_opts(int argc, char *argv[])
468{
469 unsigned int i, topts_len = count_options();
470 char optstr[2 * ARRAY_SIZE(options) + 2 * topts_len];
471 int opt;
472
473 check_option_collision();
474
475 optstr[0] = 0;
476
477 for (i = 0; i < ARRAY_SIZE(options); i++)
478 strcat(optstr, options[i].optstr);
479
480 for (i = 0; i < topts_len; i++)
481 strcat(optstr, tst_test->options[i].optstr);
482
483 while ((opt = getopt(argc, argv, optstr)) > 0) {
484 switch (opt) {
485 case '?':
486 print_help();
487 tst_brk(TBROK, "Invalid option");
488 case 'h':
489 print_help();
490 exit(0);
491 case 'i':
492 iterations = atoi(optarg);
493 break;
494 case 'I':
495 duration = atof(optarg);
496 break;
497 case 'C':
498#ifdef UCLINUX
499 child_args = optarg;
500#endif
501 break;
502 default:
503 parse_topt(topts_len, opt, optarg);
504 }
505 }
Cyril Hrubis9dc07e02017-10-02 11:11:04 +0200506
507 if (optind < argc)
508 tst_brk(TBROK, "Unexpected argument(s) '%s'...", argv[optind]);
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100509}
510
Cyril Hrubis1e92d8a2016-08-03 16:31:46 +0200511int tst_parse_int(const char *str, int *val, int min, int max)
512{
513 long rval;
Alexey Kodanevdd90c002016-12-18 00:36:00 +0300514
515 if (!str)
516 return 0;
517
518 int ret = tst_parse_long(str, &rval, min, max);
519
520 if (ret)
521 return ret;
522
523 *val = (int)rval;
524 return 0;
525}
526
527int tst_parse_long(const char *str, long *val, long min, long max)
528{
529 long rval;
Cyril Hrubis1e92d8a2016-08-03 16:31:46 +0200530 char *end;
531
532 if (!str)
533 return 0;
534
535 errno = 0;
536 rval = strtol(str, &end, 10);
537
538 if (str == end || *end != '\0')
539 return EINVAL;
540
541 if (errno)
542 return errno;
543
Alexey Kodanevdd90c002016-12-18 00:36:00 +0300544 if (rval > max || rval < min)
Cyril Hrubis1e92d8a2016-08-03 16:31:46 +0200545 return ERANGE;
546
Alexey Kodanevdd90c002016-12-18 00:36:00 +0300547 *val = rval;
Cyril Hrubis1e92d8a2016-08-03 16:31:46 +0200548 return 0;
549}
550
551int tst_parse_float(const char *str, float *val, float min, float max)
552{
553 double rval;
554 char *end;
555
556 if (!str)
557 return 0;
558
559 errno = 0;
560 rval = strtod(str, &end);
561
562 if (str == end || *end != '\0')
563 return EINVAL;
564
565 if (errno)
566 return errno;
567
568 if (rval > (double)max || rval < (double)min)
569 return ERANGE;
570
571 *val = (float)rval;
572 return 0;
573}
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100574
Cyril Hrubisfa495172016-06-08 16:06:35 +0200575static void do_exit(int ret)
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100576{
Xiao Yang11dfc322016-06-16 15:52:04 +0800577 if (results) {
578 printf("\nSummary:\n");
579 printf("passed %d\n", results->passed);
580 printf("failed %d\n", results->failed);
581 printf("skipped %d\n", results->skipped);
582 printf("warnings %d\n", results->warnings);
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100583
Cyril Hrubisfecdd882018-01-17 14:51:30 +0100584 if (results->passed && ret == TCONF)
585 ret = 0;
586
Xiao Yang11dfc322016-06-16 15:52:04 +0800587 if (results->failed)
588 ret |= TFAIL;
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100589
Cyril Hrubis5390d6e2017-09-07 15:47:22 +0200590 if (results->skipped && !results->passed)
Xiao Yang11dfc322016-06-16 15:52:04 +0800591 ret |= TCONF;
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100592
Xiao Yang11dfc322016-06-16 15:52:04 +0800593 if (results->warnings)
594 ret |= TWARN;
595 }
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100596
Jan Stancek332540e2016-06-08 16:48:22 +0200597 do_cleanup();
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100598
599 exit(ret);
600}
601
602void check_kver(void)
603{
604 int v1, v2, v3;
605
Cyril Hrubis4dcfd282016-11-01 15:07:12 +0100606 if (tst_parse_kver(tst_test->min_kver, &v1, &v2, &v3)) {
607 tst_res(TWARN,
608 "Invalid kernel version %s, expected %%d.%%d.%%d",
609 tst_test->min_kver);
610 }
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100611
612 if (tst_kvercmp(v1, v2, v3) < 0) {
613 tst_brk(TCONF, "The test requires kernel %s or newer",
614 tst_test->min_kver);
615 }
616}
617
618static int results_equal(struct results *a, struct results *b)
619{
620 if (a->passed != b->passed)
621 return 0;
622
623 if (a->failed != b->failed)
624 return 0;
625
626 if (a->skipped != b->skipped)
627 return 0;
628
629 return 1;
630}
631
632static int needs_tmpdir(void)
633{
634 return tst_test->needs_tmpdir ||
635 tst_test->needs_device ||
636 tst_test->resource_files ||
637 tst_test->needs_checkpoints;
638}
639
640static void copy_resources(void)
641{
642 unsigned int i;
643
644 for (i = 0; tst_test->resource_files[i]; i++)
645 TST_RESOURCE_COPY(NULL, tst_test->resource_files[i], NULL);
646}
647
Cyril Hrubisa5bf5252017-03-14 15:25:29 +0800648static const char *get_tid(char *argv[])
649{
650 char *p;
651
652 if (!argv[0] || !argv[0][0]) {
653 tst_res(TINFO, "argv[0] is empty!");
654 return "ltp_empty_argv";
655 }
656
657 p = strrchr(argv[0], '/');
658 if (p)
659 return p+1;
660
661 return argv[0];
662}
663
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100664static struct tst_device tdev;
665struct tst_device *tst_device;
666
Cyril Hrubisc4596542017-06-20 15:42:18 +0200667static void assert_test_fn(void)
668{
669 int cnt = 0;
670
671 if (tst_test->test)
672 cnt++;
673
674 if (tst_test->test_all)
675 cnt++;
676
677 if (tst_test->sample)
678 cnt++;
679
680 if (!cnt)
681 tst_brk(TBROK, "No test function speficied");
682
683 if (cnt != 1)
684 tst_brk(TBROK, "You can define only one test function");
685
686 if (tst_test->test && !tst_test->tcnt)
687 tst_brk(TBROK, "Number of tests (tcnt) must not be > 0");
688
689 if (!tst_test->test && tst_test->tcnt)
690 tst_brk(TBROK, "You can define tcnt only for test()");
691}
692
Cyril Hrubis35b8a132017-09-01 10:45:26 +0200693static void prepare_device(void)
694{
695 if (tst_test->format_device) {
696 SAFE_MKFS(tdev.dev, tdev.fs_type, tst_test->dev_fs_opts,
697 tst_test->dev_extra_opt);
698 }
699
700 if (tst_test->mount_device) {
701 SAFE_MOUNT(tdev.dev, tst_test->mntpoint, tdev.fs_type,
702 tst_test->mnt_flags, tst_test->mnt_data);
703 mntpoint_mounted = 1;
704 }
705}
706
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100707static void do_setup(int argc, char *argv[])
708{
709 if (!tst_test)
710 tst_brk(TBROK, "No tests to run");
711
Cyril Hrubisf706a2f2017-08-01 17:31:30 +0200712 if (tst_test->tconf_msg)
713 tst_brk(TCONF, "%s", tst_test->tconf_msg);
714
Cyril Hrubisc4596542017-06-20 15:42:18 +0200715 assert_test_fn();
716
Li Wangb5d620a2017-11-01 13:15:23 +0800717 tid = get_tid(argv);
718
Cyril Hrubisc4596542017-06-20 15:42:18 +0200719 if (tst_test->sample)
720 tst_test = tst_timer_test_setup(tst_test);
721
Cyril Hrubis88c220d2017-07-27 11:16:39 +0200722 parse_opts(argc, argv);
723
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100724 if (tst_test->needs_root && geteuid() != 0)
725 tst_brk(TCONF, "Test needs to be run as root");
726
727 if (tst_test->min_kver)
728 check_kver();
729
Cyril Hrubis874326d2017-02-14 15:59:40 +0100730 if (tst_test->format_device)
731 tst_test->needs_device = 1;
732
733 if (tst_test->mount_device) {
734 tst_test->needs_device = 1;
735 tst_test->format_device = 1;
736 }
737
Cyril Hrubis35b8a132017-09-01 10:45:26 +0200738 if (tst_test->all_filesystems)
739 tst_test->needs_device = 1;
740
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100741 setup_ipc();
742
Steven Jackson9f41dcf2016-12-21 20:09:01 +0000743 if (needs_tmpdir() && !tst_tmpdir_created())
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100744 tst_tmpdir();
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100745
Sandeep Patilc9a7def2017-09-19 12:49:58 -0700746 if (tst_test->mntpoint)
747 SAFE_MKDIR(tst_test->mntpoint, 0777);
748
Cyril Hrubis35b8a132017-09-01 10:45:26 +0200749 if ((tst_test->needs_rofs || tst_test->mount_device ||
750 tst_test->all_filesystems) && !tst_test->mntpoint) {
Sandeep Patilc9a7def2017-09-19 12:49:58 -0700751 tst_brk(TBROK, "tst_test->mntpoint must be set!");
752 }
753
754 if (tst_test->needs_rofs) {
755 /* If we failed to mount read-only tmpfs. Fallback to
756 * using a device with empty read-only filesystem.
757 */
758 if (mount(NULL, tst_test->mntpoint, "tmpfs", MS_RDONLY, NULL)) {
759 tst_res(TINFO | TERRNO, "Can't mount tmpfs read-only"
760 " at %s, setting up a device instead\n",
761 tst_test->mntpoint);
762 tst_test->mount_device = 1;
763 tst_test->needs_device = 1;
764 tst_test->format_device = 1;
765 tst_test->mnt_flags = MS_RDONLY;
766 } else {
767 mntpoint_mounted = 1;
768 }
769 }
770
771 if (tst_test->needs_device && !mntpoint_mounted) {
Cyril Hrubis874326d2017-02-14 15:59:40 +0100772 tdev.dev = tst_acquire_device_(NULL, tst_test->dev_min_size);
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100773
774 if (!tdev.dev)
775 tst_brk(TCONF, "Failed to acquire device");
776
777 tst_device = &tdev;
Cyril Hrubis874326d2017-02-14 15:59:40 +0100778
779 if (tst_test->dev_fs_type)
780 tdev.fs_type = tst_test->dev_fs_type;
781 else
782 tdev.fs_type = tst_dev_fs_type();
783
Cyril Hrubis35b8a132017-09-01 10:45:26 +0200784 if (!tst_test->all_filesystems)
785 prepare_device();
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100786 }
787
788 if (tst_test->resource_files)
789 copy_resources();
Cyril Hrubis4aebb6c2016-06-07 13:40:41 +0200790}
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100791
Cyril Hrubis4aebb6c2016-06-07 13:40:41 +0200792static void do_test_setup(void)
793{
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100794 main_pid = getpid();
795
796 if (tst_test->setup)
797 tst_test->setup();
798
799 if (main_pid != getpid())
800 tst_brk(TBROK, "Runaway child in setup()!");
801}
802
803static void do_cleanup(void)
804{
Sandeep Patilc9a7def2017-09-19 12:49:58 -0700805 if (mntpoint_mounted)
Cyril Hrubis874326d2017-02-14 15:59:40 +0100806 tst_umount(tst_test->mntpoint);
807
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100808 if (tst_test->needs_device && tdev.dev)
809 tst_release_device(tdev.dev);
810
Steven Jackson9f41dcf2016-12-21 20:09:01 +0000811 if (tst_tmpdir_created()) {
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100812 /* avoid munmap() on wrong pointer in tst_rmdir() */
813 tst_futexes = NULL;
814 tst_rmdir();
815 }
Jan Stancek332540e2016-06-08 16:48:22 +0200816
817 cleanup_ipc();
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100818}
819
820static void run_tests(void)
821{
822 unsigned int i;
823 struct results saved_results;
824
825 if (!tst_test->test) {
826 saved_results = *results;
827 tst_test->test_all();
828
829 if (getpid() != main_pid) {
830 exit(0);
831 }
832
Stanislav Kholmanskikh6b56aa72016-08-04 17:16:31 +0300833 tst_reap_children();
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100834
835 if (results_equal(&saved_results, results))
836 tst_brk(TBROK, "Test haven't reported results!");
837 return;
838 }
839
840 for (i = 0; i < tst_test->tcnt; i++) {
841 saved_results = *results;
842 tst_test->test(i);
843
844 if (getpid() != main_pid) {
845 exit(0);
846 }
847
Stanislav Kholmanskikh6b56aa72016-08-04 17:16:31 +0300848 tst_reap_children();
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100849
850 if (results_equal(&saved_results, results))
851 tst_brk(TBROK, "Test %i haven't reported results!", i);
852 }
853}
854
855static unsigned long long get_time_ms(void)
856{
Cyril Hrubis2f7c8e92018-01-22 15:19:31 +0100857 struct timespec ts;
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100858
Cyril Hrubis2f7c8e92018-01-22 15:19:31 +0100859 if (tst_clock_gettime(CLOCK_MONOTONIC, &ts))
860 tst_brk(TBROK | TERRNO, "tst_clock_gettime()");
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100861
Cyril Hrubis2f7c8e92018-01-22 15:19:31 +0100862 return tst_timespec_to_ms(ts);
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100863}
864
Jan Stancekb95b1992017-10-10 15:47:58 +0200865static void add_paths(void)
866{
867 char *old_path = getenv("PATH");
868 const char *start_dir;
869 char *new_path;
870
871 start_dir = tst_get_startwd();
872
873 if (old_path)
874 SAFE_ASPRINTF(&new_path, "%s::%s", old_path, start_dir);
875 else
876 SAFE_ASPRINTF(&new_path, "::%s", start_dir);
877
878 SAFE_SETENV("PATH", new_path, 1);
879 free(new_path);
880}
881
Cyril Hrubis35b8a132017-09-01 10:45:26 +0200882static void heartbeat(void)
883{
884 kill(getppid(), SIGUSR1);
885}
886
Cyril Hrubis4aebb6c2016-06-07 13:40:41 +0200887static void testrun(void)
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100888{
889 unsigned int i = 0;
890 unsigned long long stop_time = 0;
891 int cont = 1;
892
Jan Stancekb95b1992017-10-10 15:47:58 +0200893 add_paths();
Cyril Hrubis4aebb6c2016-06-07 13:40:41 +0200894 do_test_setup();
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100895
896 if (duration > 0)
897 stop_time = get_time_ms() + (unsigned long long)(duration * 1000);
898
899 for (;;) {
900 cont = 0;
901
902 if (i < (unsigned int)iterations) {
903 i++;
904 cont = 1;
905 }
906
907 if (stop_time && get_time_ms() < stop_time)
908 cont = 1;
909
910 if (!cont)
911 break;
912
913 run_tests();
Cyril Hrubis35b8a132017-09-01 10:45:26 +0200914 heartbeat();
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100915 }
916
Cyril Hrubis4aebb6c2016-06-07 13:40:41 +0200917 do_test_cleanup();
918 exit(0);
919}
920
921static pid_t test_pid;
Cyril Hrubis4aebb6c2016-06-07 13:40:41 +0200922
Cyril Hrubis79163172017-05-18 10:57:07 +0200923
924static volatile sig_atomic_t sigkill_retries;
925
926#define WRITE_MSG(msg) do { \
927 if (write(2, msg, sizeof(msg) - 1)) { \
928 /* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66425 */ \
929 } \
930} while (0)
931
Cyril Hrubis4aebb6c2016-06-07 13:40:41 +0200932static void alarm_handler(int sig LTP_ATTRIBUTE_UNUSED)
933{
Cyril Hrubis79163172017-05-18 10:57:07 +0200934 WRITE_MSG("Test timeouted, sending SIGKILL!\n");
Cyril Hrubis0f053c82016-06-07 14:29:39 +0200935 kill(-test_pid, SIGKILL);
Cyril Hrubis79163172017-05-18 10:57:07 +0200936 alarm(5);
937
938 if (++sigkill_retries > 10) {
939 WRITE_MSG("Cannot kill test processes!\n");
940 WRITE_MSG("Congratulation, likely test hit a kernel bug.\n");
941 WRITE_MSG("Exitting uncleanly...\n");
942 _exit(TFAIL);
943 }
Cyril Hrubis4aebb6c2016-06-07 13:40:41 +0200944}
945
946static void heartbeat_handler(int sig LTP_ATTRIBUTE_UNUSED)
947{
Cyril Hrubis2ad59b72016-08-03 15:53:55 +0200948 alarm(results->timeout);
Cyril Hrubis79163172017-05-18 10:57:07 +0200949 sigkill_retries = 0;
Cyril Hrubis2ad59b72016-08-03 15:53:55 +0200950}
951
Cyril Hrubisa41e9942016-08-04 16:31:06 +0200952static void sigint_handler(int sig LTP_ATTRIBUTE_UNUSED)
953{
954 if (test_pid > 0) {
Cyril Hrubis79163172017-05-18 10:57:07 +0200955 WRITE_MSG("Sending SIGKILL to test process...\n");
Cyril Hrubisa41e9942016-08-04 16:31:06 +0200956 kill(-test_pid, SIGKILL);
957 }
958}
959
Li Wang94823cf2017-07-18 16:23:00 +0800960void tst_set_timeout(int timeout)
Cyril Hrubis2ad59b72016-08-03 15:53:55 +0200961{
962 char *mul = getenv("LTP_TIMEOUT_MUL");
963
Li Wang94823cf2017-07-18 16:23:00 +0800964 if (timeout == -1) {
965 tst_res(TINFO, "Timeout per run is disabled");
966 return;
967 }
968
Cyril Hrubis2ad59b72016-08-03 15:53:55 +0200969 results->timeout = timeout;
970
971 if (mul) {
972 float m = atof(mul);
973
974 if (m < 1)
975 tst_brk(TBROK, "Invalid timeout multiplier '%s'", mul);
976
977 results->timeout = results->timeout * m + 0.5;
978 }
979
980 tst_res(TINFO, "Timeout per run is %uh %02um %02us",
981 results->timeout/3600, (results->timeout%3600)/60,
982 results->timeout % 60);
983
984 if (getpid() == lib_pid)
985 alarm(results->timeout);
986 else
Cyril Hrubis35b8a132017-09-01 10:45:26 +0200987 heartbeat();
Cyril Hrubis4aebb6c2016-06-07 13:40:41 +0200988}
989
Cyril Hrubis35b8a132017-09-01 10:45:26 +0200990static int fork_testrun(void)
Cyril Hrubis4aebb6c2016-06-07 13:40:41 +0200991{
992 int status;
Cyril Hrubis4aebb6c2016-06-07 13:40:41 +0200993
Cyril Hrubis2ad59b72016-08-03 15:53:55 +0200994 if (tst_test->timeout)
995 tst_set_timeout(tst_test->timeout);
996 else
997 tst_set_timeout(300);
Cyril Hrubis4aebb6c2016-06-07 13:40:41 +0200998
Cyril Hrubisa41e9942016-08-04 16:31:06 +0200999 SAFE_SIGNAL(SIGINT, sigint_handler);
1000
Cyril Hrubis4aebb6c2016-06-07 13:40:41 +02001001 test_pid = fork();
1002 if (test_pid < 0)
1003 tst_brk(TBROK | TERRNO, "fork()");
1004
Cyril Hrubis0f053c82016-06-07 14:29:39 +02001005 if (!test_pid) {
Cyril Hrubisa41e9942016-08-04 16:31:06 +02001006 SAFE_SIGNAL(SIGALRM, SIG_DFL);
1007 SAFE_SIGNAL(SIGUSR1, SIG_DFL);
1008 SAFE_SIGNAL(SIGINT, SIG_DFL);
Cyril Hrubis0f053c82016-06-07 14:29:39 +02001009 SAFE_SETPGID(0, 0);
Cyril Hrubis4aebb6c2016-06-07 13:40:41 +02001010 testrun();
Cyril Hrubis0f053c82016-06-07 14:29:39 +02001011 }
Cyril Hrubis4aebb6c2016-06-07 13:40:41 +02001012
1013 SAFE_WAITPID(test_pid, &status, 0);
Cyril Hrubis4aebb6c2016-06-07 13:40:41 +02001014 alarm(0);
Cyril Hrubisa41e9942016-08-04 16:31:06 +02001015 SAFE_SIGNAL(SIGINT, SIG_DFL);
Cyril Hrubis4aebb6c2016-06-07 13:40:41 +02001016
Cyril Hrubis4aebb6c2016-06-07 13:40:41 +02001017 if (WIFEXITED(status) && WEXITSTATUS(status))
Cyril Hrubis35b8a132017-09-01 10:45:26 +02001018 return WEXITSTATUS(status);
Cyril Hrubis4aebb6c2016-06-07 13:40:41 +02001019
1020 if (WIFSIGNALED(status) && WTERMSIG(status) == SIGKILL) {
1021 tst_res(TINFO, "If you are running on slow machine, "
1022 "try exporting LTP_TIMEOUT_MUL > 1");
1023 tst_brk(TBROK, "Test killed! (timeout?)");
1024 }
1025
1026 if (WIFSIGNALED(status))
1027 tst_brk(TBROK, "Test killed by %s!", tst_strsig(WTERMSIG(status)));
1028
Cyril Hrubis35b8a132017-09-01 10:45:26 +02001029 return 0;
1030}
1031
1032static int run_tcases_per_fs(void)
1033{
1034 int ret = 0;
1035 unsigned int i;
1036 const char *const *filesystems = tst_get_supported_fs_types();
1037
1038 if (!filesystems[0])
1039 tst_brk(TCONF, "There are no supported filesystems");
1040
1041 for (i = 0; filesystems[i]; i++) {
1042 tdev.fs_type = filesystems[i];
1043
1044 prepare_device();
1045
1046 ret = fork_testrun();
1047
1048 if (mntpoint_mounted) {
1049 tst_umount(tst_test->mntpoint);
1050 mntpoint_mounted = 0;
1051 }
1052
1053 if (ret == TCONF) {
1054 update_results(ret);
1055 continue;
1056 }
1057
1058 if (ret == 0)
1059 continue;
1060
1061 do_exit(ret);
1062 }
1063
1064 return ret;
1065}
1066
1067void tst_run_tcases(int argc, char *argv[], struct tst_test *self)
1068{
1069 int ret;
1070
1071 lib_pid = getpid();
1072 tst_test = self;
1073
1074 do_setup(argc, argv);
1075
1076 TCID = tid;
1077
1078 SAFE_SIGNAL(SIGALRM, alarm_handler);
1079 SAFE_SIGNAL(SIGUSR1, heartbeat_handler);
1080
1081 if (tst_test->all_filesystems)
1082 ret = run_tcases_per_fs();
1083 else
1084 ret = fork_testrun();
1085
1086 do_exit(ret);
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +01001087}
Michael Moese1ab33ce2018-03-09 15:16:08 +01001088
1089
1090void tst_flush(void)
1091{
1092 int rval;
1093
1094 rval = fflush(stderr);
1095 if (rval != 0)
1096 tst_brk(TBROK | TERRNO, "fflush(stderr) failed");
1097
1098 rval = fflush(stderr);
1099 if (rval != 0)
1100 tst_brk(TBROK | TERRNO, "fflush(stdout) failed");
1101
1102}