blob: a627242a68f2df514f283c56c2a9ed020941ceaa [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>
27#include <sys/time.h>
28
29#define TST_NO_DEFAULT_MAIN
30#include "tst_test.h"
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +010031#include "tst_device.h"
32#include "lapi/futex.h"
Steve Mucklec20831d2017-09-20 13:23:06 -070033#include "lapi/syscalls.h"
Petr Vorel3a0ef862017-03-01 15:31:08 +010034#include "tst_ansi_color.h"
Cyril Hrubisc4596542017-06-20 15:42:18 +020035#include "tst_timer_test.h"
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +010036
37#include "old_resource.h"
38#include "old_device.h"
39#include "old_tmpdir.h"
40
41struct tst_test *tst_test;
42
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +010043static int iterations = 1;
44static float duration = -1;
Jan Stanceke0bfa7d2016-06-08 15:27:55 +020045static pid_t main_pid, lib_pid;
Sandeep Patilc9a7def2017-09-19 12:49:58 -070046static int mntpoint_mounted;
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +010047
48struct results {
Jan Stancekc54ca052016-04-13 12:31:13 +020049 int passed;
50 int skipped;
51 int failed;
52 int warnings;
Cyril Hrubis2ad59b72016-08-03 15:53:55 +020053 unsigned int timeout;
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +010054};
55
56static struct results *results;
57
58static int ipc_fd;
59
60extern void *tst_futexes;
61extern unsigned int tst_max_futexes;
62
63#define IPC_ENV_VAR "LTP_IPC_PATH"
64
65static char ipc_path[1024];
66const char *tst_ipc_path = ipc_path;
67char *const tst_ipc_envp[] = {ipc_path, NULL};
68
69static char shm_path[1024];
70
Jan Stancek332540e2016-06-08 16:48:22 +020071static void do_cleanup(void);
Cyril Hrubisfa495172016-06-08 16:06:35 +020072static void do_exit(int ret) __attribute__ ((noreturn));
Jan Stanceke0bfa7d2016-06-08 15:27:55 +020073
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +010074static void setup_ipc(void)
75{
76 size_t size = getpagesize();
77
Steven Jackson9f41dcf2016-12-21 20:09:01 +000078 if (access("/dev/shm", F_OK) == 0) {
79 snprintf(shm_path, sizeof(shm_path), "/dev/shm/ltp_%s_%d",
80 tst_test->tid, getpid());
81 } else {
82 char *tmpdir;
83
84 if (!tst_tmpdir_created())
85 tst_tmpdir();
86
87 tmpdir = tst_get_tmpdir();
88 snprintf(shm_path, sizeof(shm_path), "%s/ltp_%s_%d",
89 tmpdir, tst_test->tid, getpid());
90 free(tmpdir);
91 }
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +010092
93 ipc_fd = open(shm_path, O_CREAT | O_EXCL | O_RDWR, 0600);
94 if (ipc_fd < 0)
95 tst_brk(TBROK | TERRNO, "open(%s)", shm_path);
96
97 SAFE_FTRUNCATE(ipc_fd, size);
98
99 results = SAFE_MMAP(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, ipc_fd, 0);
100
101 /* Checkpoints needs to be accessible from processes started by exec() */
102 if (tst_test->needs_checkpoints)
103 sprintf(ipc_path, IPC_ENV_VAR "=%s", shm_path);
104 else
105 SAFE_UNLINK(shm_path);
106
107 SAFE_CLOSE(ipc_fd);
108
109 if (tst_test->needs_checkpoints) {
110 tst_futexes = (char*)results + sizeof(struct results);
111 tst_max_futexes = (size - sizeof(struct results))/sizeof(futex_t);
112 }
113}
114
115static void cleanup_ipc(void)
116{
117 size_t size = getpagesize();
118
119 if (ipc_fd > 0 && close(ipc_fd))
120 tst_res(TWARN | TERRNO, "close(ipc_fd) failed");
121
Cyril Hrubis9726b902017-07-27 11:28:50 +0200122 if (shm_path[0] && !access(shm_path, F_OK) && unlink(shm_path))
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100123 tst_res(TWARN | TERRNO, "unlink(%s) failed", shm_path);
124
Cyril Hrubis9726b902017-07-27 11:28:50 +0200125 if (results) {
126 msync((void*)results, size, MS_SYNC);
127 munmap((void*)results, size);
128 }
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100129}
130
131void tst_reinit(void)
132{
133 const char *path = getenv("LTP_IPC_PATH");
134 size_t size = getpagesize();
135 int fd;
136 void *ptr;
137
138 if (!path)
139 tst_brk(TBROK, "LTP_IPC_PATH is not defined");
140
141 if (access(path, F_OK))
142 tst_brk(TBROK, "File %s does not exist!", path);
143
144 fd = SAFE_OPEN(path, O_RDWR);
145
146 ptr = SAFE_MMAP(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
147 tst_futexes = (char*)ptr + sizeof(struct results);
148 tst_max_futexes = (size - sizeof(struct results))/sizeof(futex_t);
149
150 SAFE_CLOSE(fd);
151}
152
Cyril Hrubis160ffcc2017-02-14 10:21:08 +0100153static void update_results(int ttype)
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100154{
Cyril Hrubisd97debf2017-02-13 12:37:39 +0100155 if (!results)
156 return;
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100157
158 switch (ttype) {
159 case TCONF:
160 tst_atomic_inc(&results->skipped);
161 break;
162 case TPASS:
163 tst_atomic_inc(&results->passed);
164 break;
165 case TWARN:
166 tst_atomic_inc(&results->warnings);
167 break;
168 case TFAIL:
169 tst_atomic_inc(&results->failed);
170 break;
171 }
172}
173
174static void print_result(const char *file, const int lineno, int ttype,
175 const char *fmt, va_list va)
176{
177 char buf[1024];
178 char *str = buf;
179 int ret, size = sizeof(buf);
180 const char *str_errno = NULL;
181 const char *res;
182
183 switch (TTYPE_RESULT(ttype)) {
184 case TPASS:
185 res = "PASS";
186 break;
187 case TFAIL:
188 res = "FAIL";
189 break;
190 case TBROK:
191 res = "BROK";
192 break;
193 case TCONF:
194 res = "CONF";
195 break;
196 case TWARN:
197 res = "WARN";
198 break;
199 case TINFO:
200 res = "INFO";
201 break;
202 default:
203 tst_brk(TBROK, "Invalid ttype value %i", ttype);
Cyril Hrubis6440c5d2017-02-09 15:41:24 +0100204 abort();
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100205 }
206
207 if (ttype & TERRNO)
208 str_errno = tst_strerrno(errno);
209
210 if (ttype & TTERRNO)
211 str_errno = tst_strerrno(TEST_ERRNO);
212
Petr Vorela7f61332017-01-24 20:47:30 +0100213 ret = snprintf(str, size, "%s:%i: ", file, lineno);
214 str += ret;
215 size -= ret;
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100216
Cyril Hrubis047c7272017-02-13 16:23:36 +0100217 if (tst_color_enabled(STDERR_FILENO))
Petr Vorela7f61332017-01-24 20:47:30 +0100218 ret = snprintf(str, size, "%s%s: %s", tst_ttype2color(ttype),
219 res, ANSI_COLOR_RESET);
220 else
221 ret = snprintf(str, size, "%s: ", res);
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100222 str += ret;
223 size -= ret;
224
225 ret = vsnprintf(str, size, fmt, va);
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100226 str += ret;
227 size -= ret;
228
Petr Vorela7f61332017-01-24 20:47:30 +0100229 if (str_errno) {
230 ret = snprintf(str, size, ": %s", str_errno);
231 str += ret;
232 size -= ret;
233 }
234
235 snprintf(str, size, "\n");
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100236
237 fputs(buf, stderr);
238}
239
240void tst_vres_(const char *file, const int lineno, int ttype,
241 const char *fmt, va_list va)
242{
243 print_result(file, lineno, ttype, fmt, va);
244
Cyril Hrubis160ffcc2017-02-14 10:21:08 +0100245 update_results(TTYPE_RESULT(ttype));
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100246}
247
248void tst_vbrk_(const char *file, const int lineno, int ttype,
Cyril Hrubis6440c5d2017-02-09 15:41:24 +0100249 const char *fmt, va_list va);
250
251static void (*tst_brk_handler)(const char *file, const int lineno, int ttype,
252 const char *fmt, va_list va) = tst_vbrk_;
253
254static void tst_cvres(const char *file, const int lineno, int ttype,
255 const char *fmt, va_list va)
256{
257 if (TTYPE_RESULT(ttype) == TBROK) {
258 ttype &= ~TTYPE_MASK;
259 ttype |= TWARN;
260 }
261
262 print_result(file, lineno, ttype, fmt, va);
263 update_results(TTYPE_RESULT(ttype));
264}
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100265
Cyril Hrubis4aebb6c2016-06-07 13:40:41 +0200266static void do_test_cleanup(void)
267{
Cyril Hrubis6440c5d2017-02-09 15:41:24 +0100268 tst_brk_handler = tst_cvres;
269
Cyril Hrubis4aebb6c2016-06-07 13:40:41 +0200270 if (tst_test->cleanup)
271 tst_test->cleanup();
Cyril Hrubis6440c5d2017-02-09 15:41:24 +0100272
273 tst_brk_handler = tst_vbrk_;
Cyril Hrubis4aebb6c2016-06-07 13:40:41 +0200274}
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100275
276void tst_vbrk_(const char *file, const int lineno, int ttype,
277 const char *fmt, va_list va)
278{
279 print_result(file, lineno, ttype, fmt, va);
280
Steve Mucklec20831d2017-09-20 13:23:06 -0700281 /*
282 * The getpid implementation in some C library versions may cause cloned
283 * test threads to show the same pid as their parent when CLONE_VM is
284 * specified but CLONE_THREAD is not. Use direct syscall to avoid
285 * cleanup running in the child.
286 */
287 if (syscall(SYS_getpid) == main_pid)
Cyril Hrubis4aebb6c2016-06-07 13:40:41 +0200288 do_test_cleanup();
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100289
Jan Stanceke0bfa7d2016-06-08 15:27:55 +0200290 if (getpid() == lib_pid)
Cyril Hrubisfa495172016-06-08 16:06:35 +0200291 do_exit(TTYPE_RESULT(ttype));
Jan Stanceke0bfa7d2016-06-08 15:27:55 +0200292
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100293 exit(TTYPE_RESULT(ttype));
294}
295
296void tst_res_(const char *file, const int lineno, int ttype,
297 const char *fmt, ...)
298{
299 va_list va;
300
301 va_start(va, fmt);
302 tst_vres_(file, lineno, ttype, fmt, va);
303 va_end(va);
304}
305
306void tst_brk_(const char *file, const int lineno, int ttype,
307 const char *fmt, ...)
308{
309 va_list va;
310
311 va_start(va, fmt);
Cyril Hrubis6440c5d2017-02-09 15:41:24 +0100312 tst_brk_handler(file, lineno, ttype, fmt, va);
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100313 va_end(va);
314}
315
316static void check_child_status(pid_t pid, int status)
317{
318 int ret;
319
320 if (WIFSIGNALED(status)) {
321 tst_brk(TBROK, "Child (%i) killed by signal %s",
322 pid, tst_strsig(WTERMSIG(status)));
323 }
324
325 if (!(WIFEXITED(status)))
326 tst_brk(TBROK, "Child (%i) exitted abnormaly", pid);
327
328 ret = WEXITSTATUS(status);
329 switch (ret) {
330 case TPASS:
331 break;
332 case TBROK:
333 case TCONF:
334 tst_brk(ret, "Reported by child (%i)", pid);
335 default:
336 tst_brk(TBROK, "Invalid child (%i) exit value %i", pid, ret);
337 }
338}
339
Stanislav Kholmanskikh6b56aa72016-08-04 17:16:31 +0300340void tst_reap_children(void)
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100341{
342 int status;
343 pid_t pid;
344
345 for (;;) {
346 pid = wait(&status);
347
348 if (pid > 0) {
349 check_child_status(pid, status);
350 continue;
351 }
352
353 if (errno == ECHILD)
354 break;
355
356 if (errno == EINTR)
357 continue;
358
359 tst_brk(TBROK | TERRNO, "wait() failed");
360 }
361}
362
363
364pid_t safe_fork(const char *filename, unsigned int lineno)
365{
366 pid_t pid;
367
368 if (!tst_test->forks_child)
369 tst_brk(TBROK, "test.forks_child must be set!");
370
371 fflush(stdout);
372
373 pid = fork();
374 if (pid < 0)
375 tst_brk_(filename, lineno, TBROK | TERRNO, "fork() failed");
376
377 return pid;
378}
379
380static struct option {
381 char *optstr;
382 char *help;
383} options[] = {
Cyril Hrubisb819c222016-08-03 14:36:07 +0200384 {"h", "-h Prints this help"},
385 {"i:", "-i n Execute test n times"},
386 {"I:", "-I x Execute test for n seconds"},
387 {"C:", "-C ARG Run child process with ARG arguments (used internally)"},
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100388};
389
390static void print_help(void)
391{
392 unsigned int i;
393
394 for (i = 0; i < ARRAY_SIZE(options); i++)
395 fprintf(stderr, "%s\n", options[i].help);
396
397 if (!tst_test->options)
398 return;
399
400 for (i = 0; tst_test->options[i].optstr; i++)
Cyril Hrubisb819c222016-08-03 14:36:07 +0200401 fprintf(stderr, "%s\n", tst_test->options[i].help);
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100402}
403
404static void check_option_collision(void)
405{
406 unsigned int i, j;
407 struct tst_option *toptions = tst_test->options;
408
409 if (!toptions)
410 return;
411
412 for (i = 0; toptions[i].optstr; i++) {
413 for (j = 0; j < ARRAY_SIZE(options); j++) {
414 if (toptions[i].optstr[0] == options[j].optstr[0]) {
415 tst_brk(TBROK, "Option collision '%s'",
416 options[j].help);
417 }
418 }
419 }
420}
421
422static unsigned int count_options(void)
423{
424 unsigned int i;
425
426 if (!tst_test->options)
427 return 0;
428
429 for (i = 0; tst_test->options[i].optstr; i++);
430
431 return i;
432}
433
434static void parse_topt(unsigned int topts_len, int opt, char *optarg)
435{
436 unsigned int i;
437 struct tst_option *toptions = tst_test->options;
438
439 for (i = 0; i < topts_len; i++) {
440 if (toptions[i].optstr[0] == opt)
441 break;
442 }
443
444 if (i >= topts_len)
445 tst_brk(TBROK, "Invalid option '%c' (should not happen)", opt);
446
Jan Stancekc07d36c2016-08-01 11:44:55 +0200447 *(toptions[i].arg) = optarg ? optarg : "";
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100448}
449
450/* see self_exec.c */
451#ifdef UCLINUX
452extern char *child_args;
453#endif
454
455static void parse_opts(int argc, char *argv[])
456{
457 unsigned int i, topts_len = count_options();
458 char optstr[2 * ARRAY_SIZE(options) + 2 * topts_len];
459 int opt;
460
461 check_option_collision();
462
463 optstr[0] = 0;
464
465 for (i = 0; i < ARRAY_SIZE(options); i++)
466 strcat(optstr, options[i].optstr);
467
468 for (i = 0; i < topts_len; i++)
469 strcat(optstr, tst_test->options[i].optstr);
470
471 while ((opt = getopt(argc, argv, optstr)) > 0) {
472 switch (opt) {
473 case '?':
474 print_help();
475 tst_brk(TBROK, "Invalid option");
476 case 'h':
477 print_help();
478 exit(0);
479 case 'i':
480 iterations = atoi(optarg);
481 break;
482 case 'I':
483 duration = atof(optarg);
484 break;
485 case 'C':
486#ifdef UCLINUX
487 child_args = optarg;
488#endif
489 break;
490 default:
491 parse_topt(topts_len, opt, optarg);
492 }
493 }
494}
495
Cyril Hrubis1e92d8a2016-08-03 16:31:46 +0200496int tst_parse_int(const char *str, int *val, int min, int max)
497{
498 long rval;
Alexey Kodanevdd90c002016-12-18 00:36:00 +0300499
500 if (!str)
501 return 0;
502
503 int ret = tst_parse_long(str, &rval, min, max);
504
505 if (ret)
506 return ret;
507
508 *val = (int)rval;
509 return 0;
510}
511
512int tst_parse_long(const char *str, long *val, long min, long max)
513{
514 long rval;
Cyril Hrubis1e92d8a2016-08-03 16:31:46 +0200515 char *end;
516
517 if (!str)
518 return 0;
519
520 errno = 0;
521 rval = strtol(str, &end, 10);
522
523 if (str == end || *end != '\0')
524 return EINVAL;
525
526 if (errno)
527 return errno;
528
Alexey Kodanevdd90c002016-12-18 00:36:00 +0300529 if (rval > max || rval < min)
Cyril Hrubis1e92d8a2016-08-03 16:31:46 +0200530 return ERANGE;
531
Alexey Kodanevdd90c002016-12-18 00:36:00 +0300532 *val = rval;
Cyril Hrubis1e92d8a2016-08-03 16:31:46 +0200533 return 0;
534}
535
536int tst_parse_float(const char *str, float *val, float min, float max)
537{
538 double rval;
539 char *end;
540
541 if (!str)
542 return 0;
543
544 errno = 0;
545 rval = strtod(str, &end);
546
547 if (str == end || *end != '\0')
548 return EINVAL;
549
550 if (errno)
551 return errno;
552
553 if (rval > (double)max || rval < (double)min)
554 return ERANGE;
555
556 *val = (float)rval;
557 return 0;
558}
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100559
Cyril Hrubisfa495172016-06-08 16:06:35 +0200560static void do_exit(int ret)
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100561{
Xiao Yang11dfc322016-06-16 15:52:04 +0800562 if (results) {
563 printf("\nSummary:\n");
564 printf("passed %d\n", results->passed);
565 printf("failed %d\n", results->failed);
566 printf("skipped %d\n", results->skipped);
567 printf("warnings %d\n", results->warnings);
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100568
Xiao Yang11dfc322016-06-16 15:52:04 +0800569 if (results->failed)
570 ret |= TFAIL;
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100571
Cyril Hrubis5390d6e2017-09-07 15:47:22 +0200572 if (results->skipped && !results->passed)
Xiao Yang11dfc322016-06-16 15:52:04 +0800573 ret |= TCONF;
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100574
Xiao Yang11dfc322016-06-16 15:52:04 +0800575 if (results->warnings)
576 ret |= TWARN;
577 }
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100578
Jan Stancek332540e2016-06-08 16:48:22 +0200579 do_cleanup();
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100580
581 exit(ret);
582}
583
584void check_kver(void)
585{
586 int v1, v2, v3;
587
Cyril Hrubis4dcfd282016-11-01 15:07:12 +0100588 if (tst_parse_kver(tst_test->min_kver, &v1, &v2, &v3)) {
589 tst_res(TWARN,
590 "Invalid kernel version %s, expected %%d.%%d.%%d",
591 tst_test->min_kver);
592 }
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100593
594 if (tst_kvercmp(v1, v2, v3) < 0) {
595 tst_brk(TCONF, "The test requires kernel %s or newer",
596 tst_test->min_kver);
597 }
598}
599
600static int results_equal(struct results *a, struct results *b)
601{
602 if (a->passed != b->passed)
603 return 0;
604
605 if (a->failed != b->failed)
606 return 0;
607
608 if (a->skipped != b->skipped)
609 return 0;
610
611 return 1;
612}
613
614static int needs_tmpdir(void)
615{
616 return tst_test->needs_tmpdir ||
617 tst_test->needs_device ||
618 tst_test->resource_files ||
619 tst_test->needs_checkpoints;
620}
621
622static void copy_resources(void)
623{
624 unsigned int i;
625
626 for (i = 0; tst_test->resource_files[i]; i++)
627 TST_RESOURCE_COPY(NULL, tst_test->resource_files[i], NULL);
628}
629
Cyril Hrubisa5bf5252017-03-14 15:25:29 +0800630static const char *get_tid(char *argv[])
631{
632 char *p;
633
634 if (!argv[0] || !argv[0][0]) {
635 tst_res(TINFO, "argv[0] is empty!");
636 return "ltp_empty_argv";
637 }
638
639 p = strrchr(argv[0], '/');
640 if (p)
641 return p+1;
642
643 return argv[0];
644}
645
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100646static struct tst_device tdev;
647struct tst_device *tst_device;
648
Cyril Hrubisc4596542017-06-20 15:42:18 +0200649static void assert_test_fn(void)
650{
651 int cnt = 0;
652
653 if (tst_test->test)
654 cnt++;
655
656 if (tst_test->test_all)
657 cnt++;
658
659 if (tst_test->sample)
660 cnt++;
661
662 if (!cnt)
663 tst_brk(TBROK, "No test function speficied");
664
665 if (cnt != 1)
666 tst_brk(TBROK, "You can define only one test function");
667
668 if (tst_test->test && !tst_test->tcnt)
669 tst_brk(TBROK, "Number of tests (tcnt) must not be > 0");
670
671 if (!tst_test->test && tst_test->tcnt)
672 tst_brk(TBROK, "You can define tcnt only for test()");
673}
674
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100675static void do_setup(int argc, char *argv[])
676{
677 if (!tst_test)
678 tst_brk(TBROK, "No tests to run");
679
Cyril Hrubisf706a2f2017-08-01 17:31:30 +0200680 if (tst_test->tconf_msg)
681 tst_brk(TCONF, "%s", tst_test->tconf_msg);
682
Cyril Hrubisc4596542017-06-20 15:42:18 +0200683 assert_test_fn();
684
685 if (tst_test->sample)
686 tst_test = tst_timer_test_setup(tst_test);
687
Cyril Hrubisf5f208b2016-08-04 16:10:21 +0200688 if (!tst_test->tid)
Cyril Hrubisa5bf5252017-03-14 15:25:29 +0800689 tst_test->tid = get_tid(argv);
Cyril Hrubisf5f208b2016-08-04 16:10:21 +0200690
Cyril Hrubis88c220d2017-07-27 11:16:39 +0200691 parse_opts(argc, argv);
692
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100693 if (tst_test->needs_root && geteuid() != 0)
694 tst_brk(TCONF, "Test needs to be run as root");
695
696 if (tst_test->min_kver)
697 check_kver();
698
Cyril Hrubis874326d2017-02-14 15:59:40 +0100699 if (tst_test->format_device)
700 tst_test->needs_device = 1;
701
702 if (tst_test->mount_device) {
703 tst_test->needs_device = 1;
704 tst_test->format_device = 1;
705 }
706
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100707 setup_ipc();
708
Steven Jackson9f41dcf2016-12-21 20:09:01 +0000709 if (needs_tmpdir() && !tst_tmpdir_created())
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100710 tst_tmpdir();
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100711
Sandeep Patilc9a7def2017-09-19 12:49:58 -0700712 if (tst_test->mntpoint)
713 SAFE_MKDIR(tst_test->mntpoint, 0777);
714
715 if ((tst_test->needs_rofs || tst_test->mount_device) &&
716 !tst_test->mntpoint) {
717 tst_brk(TBROK, "tst_test->mntpoint must be set!");
718 }
719
720 if (tst_test->needs_rofs) {
721 /* If we failed to mount read-only tmpfs. Fallback to
722 * using a device with empty read-only filesystem.
723 */
724 if (mount(NULL, tst_test->mntpoint, "tmpfs", MS_RDONLY, NULL)) {
725 tst_res(TINFO | TERRNO, "Can't mount tmpfs read-only"
726 " at %s, setting up a device instead\n",
727 tst_test->mntpoint);
728 tst_test->mount_device = 1;
729 tst_test->needs_device = 1;
730 tst_test->format_device = 1;
731 tst_test->mnt_flags = MS_RDONLY;
732 } else {
733 mntpoint_mounted = 1;
734 }
735 }
736
737 if (tst_test->needs_device && !mntpoint_mounted) {
Cyril Hrubis874326d2017-02-14 15:59:40 +0100738 tdev.dev = tst_acquire_device_(NULL, tst_test->dev_min_size);
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100739
740 if (!tdev.dev)
741 tst_brk(TCONF, "Failed to acquire device");
742
743 tst_device = &tdev;
Cyril Hrubis874326d2017-02-14 15:59:40 +0100744
745 if (tst_test->dev_fs_type)
746 tdev.fs_type = tst_test->dev_fs_type;
747 else
748 tdev.fs_type = tst_dev_fs_type();
749
750 if (tst_test->format_device) {
751 SAFE_MKFS(tdev.dev, tdev.fs_type,
752 tst_test->dev_fs_opts,
753 tst_test->dev_extra_opt);
754 }
755
756 if (tst_test->mount_device) {
Cyril Hrubis874326d2017-02-14 15:59:40 +0100757 SAFE_MOUNT(tdev.dev, tst_test->mntpoint, tdev.fs_type,
758 tst_test->mnt_flags, tst_test->mnt_data);
Sandeep Patilc9a7def2017-09-19 12:49:58 -0700759 mntpoint_mounted = 1;
Cyril Hrubis874326d2017-02-14 15:59:40 +0100760 }
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100761 }
762
763 if (tst_test->resource_files)
764 copy_resources();
Cyril Hrubis4aebb6c2016-06-07 13:40:41 +0200765}
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100766
Cyril Hrubis4aebb6c2016-06-07 13:40:41 +0200767static void do_test_setup(void)
768{
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100769 main_pid = getpid();
770
771 if (tst_test->setup)
772 tst_test->setup();
773
774 if (main_pid != getpid())
775 tst_brk(TBROK, "Runaway child in setup()!");
776}
777
778static void do_cleanup(void)
779{
Sandeep Patilc9a7def2017-09-19 12:49:58 -0700780 if (mntpoint_mounted)
Cyril Hrubis874326d2017-02-14 15:59:40 +0100781 tst_umount(tst_test->mntpoint);
782
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100783 if (tst_test->needs_device && tdev.dev)
784 tst_release_device(tdev.dev);
785
Steven Jackson9f41dcf2016-12-21 20:09:01 +0000786 if (tst_tmpdir_created()) {
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100787 /* avoid munmap() on wrong pointer in tst_rmdir() */
788 tst_futexes = NULL;
789 tst_rmdir();
790 }
Jan Stancek332540e2016-06-08 16:48:22 +0200791
792 cleanup_ipc();
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100793}
794
795static void run_tests(void)
796{
797 unsigned int i;
798 struct results saved_results;
799
800 if (!tst_test->test) {
801 saved_results = *results;
802 tst_test->test_all();
803
804 if (getpid() != main_pid) {
805 exit(0);
806 }
807
Stanislav Kholmanskikh6b56aa72016-08-04 17:16:31 +0300808 tst_reap_children();
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100809
810 if (results_equal(&saved_results, results))
811 tst_brk(TBROK, "Test haven't reported results!");
812 return;
813 }
814
815 for (i = 0; i < tst_test->tcnt; i++) {
816 saved_results = *results;
817 tst_test->test(i);
818
819 if (getpid() != main_pid) {
820 exit(0);
821 }
822
Stanislav Kholmanskikh6b56aa72016-08-04 17:16:31 +0300823 tst_reap_children();
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100824
825 if (results_equal(&saved_results, results))
826 tst_brk(TBROK, "Test %i haven't reported results!", i);
827 }
828}
829
830static unsigned long long get_time_ms(void)
831{
832 struct timeval tv;
833
834 gettimeofday(&tv, NULL);
835
836 return tv.tv_sec * 1000 + tv.tv_usec / 1000;
837}
838
Cyril Hrubis4aebb6c2016-06-07 13:40:41 +0200839static void testrun(void)
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100840{
841 unsigned int i = 0;
842 unsigned long long stop_time = 0;
843 int cont = 1;
844
Cyril Hrubis4aebb6c2016-06-07 13:40:41 +0200845 do_test_setup();
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100846
847 if (duration > 0)
848 stop_time = get_time_ms() + (unsigned long long)(duration * 1000);
849
850 for (;;) {
851 cont = 0;
852
853 if (i < (unsigned int)iterations) {
854 i++;
855 cont = 1;
856 }
857
858 if (stop_time && get_time_ms() < stop_time)
859 cont = 1;
860
861 if (!cont)
862 break;
863
864 run_tests();
Cyril Hrubis4aebb6c2016-06-07 13:40:41 +0200865
866 kill(getppid(), SIGUSR1);
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100867 }
868
Cyril Hrubis4aebb6c2016-06-07 13:40:41 +0200869 do_test_cleanup();
870 exit(0);
871}
872
873static pid_t test_pid;
Cyril Hrubis4aebb6c2016-06-07 13:40:41 +0200874
Cyril Hrubis79163172017-05-18 10:57:07 +0200875
876static volatile sig_atomic_t sigkill_retries;
877
878#define WRITE_MSG(msg) do { \
879 if (write(2, msg, sizeof(msg) - 1)) { \
880 /* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66425 */ \
881 } \
882} while (0)
883
Cyril Hrubis4aebb6c2016-06-07 13:40:41 +0200884static void alarm_handler(int sig LTP_ATTRIBUTE_UNUSED)
885{
Cyril Hrubis79163172017-05-18 10:57:07 +0200886 WRITE_MSG("Test timeouted, sending SIGKILL!\n");
Cyril Hrubis0f053c82016-06-07 14:29:39 +0200887 kill(-test_pid, SIGKILL);
Cyril Hrubis79163172017-05-18 10:57:07 +0200888 alarm(5);
889
890 if (++sigkill_retries > 10) {
891 WRITE_MSG("Cannot kill test processes!\n");
892 WRITE_MSG("Congratulation, likely test hit a kernel bug.\n");
893 WRITE_MSG("Exitting uncleanly...\n");
894 _exit(TFAIL);
895 }
Cyril Hrubis4aebb6c2016-06-07 13:40:41 +0200896}
897
898static void heartbeat_handler(int sig LTP_ATTRIBUTE_UNUSED)
899{
Cyril Hrubis2ad59b72016-08-03 15:53:55 +0200900 alarm(results->timeout);
Cyril Hrubis79163172017-05-18 10:57:07 +0200901 sigkill_retries = 0;
Cyril Hrubis2ad59b72016-08-03 15:53:55 +0200902}
903
Cyril Hrubisa41e9942016-08-04 16:31:06 +0200904static void sigint_handler(int sig LTP_ATTRIBUTE_UNUSED)
905{
906 if (test_pid > 0) {
Cyril Hrubis79163172017-05-18 10:57:07 +0200907 WRITE_MSG("Sending SIGKILL to test process...\n");
Cyril Hrubisa41e9942016-08-04 16:31:06 +0200908 kill(-test_pid, SIGKILL);
909 }
910}
911
Li Wang94823cf2017-07-18 16:23:00 +0800912void tst_set_timeout(int timeout)
Cyril Hrubis2ad59b72016-08-03 15:53:55 +0200913{
914 char *mul = getenv("LTP_TIMEOUT_MUL");
915
Li Wang94823cf2017-07-18 16:23:00 +0800916 if (timeout == -1) {
917 tst_res(TINFO, "Timeout per run is disabled");
918 return;
919 }
920
Cyril Hrubis2ad59b72016-08-03 15:53:55 +0200921 results->timeout = timeout;
922
923 if (mul) {
924 float m = atof(mul);
925
926 if (m < 1)
927 tst_brk(TBROK, "Invalid timeout multiplier '%s'", mul);
928
929 results->timeout = results->timeout * m + 0.5;
930 }
931
932 tst_res(TINFO, "Timeout per run is %uh %02um %02us",
933 results->timeout/3600, (results->timeout%3600)/60,
934 results->timeout % 60);
935
936 if (getpid() == lib_pid)
937 alarm(results->timeout);
938 else
939 kill(getppid(), SIGUSR1);
Cyril Hrubis4aebb6c2016-06-07 13:40:41 +0200940}
941
942void tst_run_tcases(int argc, char *argv[], struct tst_test *self)
943{
944 int status;
Cyril Hrubis4aebb6c2016-06-07 13:40:41 +0200945
Jan Stanceke0bfa7d2016-06-08 15:27:55 +0200946 lib_pid = getpid();
Cyril Hrubis4aebb6c2016-06-07 13:40:41 +0200947 tst_test = self;
Cyril Hrubis4aebb6c2016-06-07 13:40:41 +0200948
949 do_setup(argc, argv);
950
Cyril Hrubisa5bf5252017-03-14 15:25:29 +0800951 TCID = tst_test->tid;
952
Cyril Hrubis4aebb6c2016-06-07 13:40:41 +0200953 SAFE_SIGNAL(SIGALRM, alarm_handler);
954 SAFE_SIGNAL(SIGUSR1, heartbeat_handler);
955
Cyril Hrubis2ad59b72016-08-03 15:53:55 +0200956 if (tst_test->timeout)
957 tst_set_timeout(tst_test->timeout);
958 else
959 tst_set_timeout(300);
Cyril Hrubis4aebb6c2016-06-07 13:40:41 +0200960
Cyril Hrubisa41e9942016-08-04 16:31:06 +0200961 SAFE_SIGNAL(SIGINT, sigint_handler);
962
Cyril Hrubis4aebb6c2016-06-07 13:40:41 +0200963 test_pid = fork();
964 if (test_pid < 0)
965 tst_brk(TBROK | TERRNO, "fork()");
966
Cyril Hrubis0f053c82016-06-07 14:29:39 +0200967 if (!test_pid) {
Cyril Hrubisa41e9942016-08-04 16:31:06 +0200968 SAFE_SIGNAL(SIGALRM, SIG_DFL);
969 SAFE_SIGNAL(SIGUSR1, SIG_DFL);
970 SAFE_SIGNAL(SIGINT, SIG_DFL);
Cyril Hrubis0f053c82016-06-07 14:29:39 +0200971 SAFE_SETPGID(0, 0);
Cyril Hrubis4aebb6c2016-06-07 13:40:41 +0200972 testrun();
Cyril Hrubis0f053c82016-06-07 14:29:39 +0200973 }
Cyril Hrubis4aebb6c2016-06-07 13:40:41 +0200974
975 SAFE_WAITPID(test_pid, &status, 0);
Cyril Hrubis4aebb6c2016-06-07 13:40:41 +0200976 alarm(0);
Cyril Hrubisa41e9942016-08-04 16:31:06 +0200977 SAFE_SIGNAL(SIGINT, SIG_DFL);
Cyril Hrubis4aebb6c2016-06-07 13:40:41 +0200978
Cyril Hrubis4aebb6c2016-06-07 13:40:41 +0200979 if (WIFEXITED(status) && WEXITSTATUS(status))
Cyril Hrubisfa495172016-06-08 16:06:35 +0200980 do_exit(WEXITSTATUS(status));
Cyril Hrubis4aebb6c2016-06-07 13:40:41 +0200981
982 if (WIFSIGNALED(status) && WTERMSIG(status) == SIGKILL) {
983 tst_res(TINFO, "If you are running on slow machine, "
984 "try exporting LTP_TIMEOUT_MUL > 1");
985 tst_brk(TBROK, "Test killed! (timeout?)");
986 }
987
988 if (WIFSIGNALED(status))
989 tst_brk(TBROK, "Test killed by %s!", tst_strsig(WTERMSIG(status)));
990
Cyril Hrubisfa495172016-06-08 16:06:35 +0200991 do_exit(0);
Cyril Hrubisbbdb9f72016-03-16 15:53:57 +0100992}