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