112 lines · c
1/* SPDX-License-Identifier: GPL-2.0 */2#ifndef __TIMENS_H__3#define __TIMENS_H__4 5#include <fcntl.h>6#include <unistd.h>7#include <stdlib.h>8#include <stdbool.h>9 10#include "../kselftest.h"11 12#ifndef CLONE_NEWTIME13# define CLONE_NEWTIME 0x0000008014#endif15 16static int config_posix_timers = true;17static int config_alarm_timers = true;18 19static inline void check_supported_timers(void)20{21 struct timespec ts;22 23 if (timer_create(-1, 0, 0) == -1 && errno == ENOSYS)24 config_posix_timers = false;25 26 if (clock_gettime(CLOCK_BOOTTIME_ALARM, &ts) == -1 && errno == EINVAL)27 config_alarm_timers = false;28}29 30static inline bool check_skip(int clockid)31{32 if (!config_alarm_timers && clockid == CLOCK_BOOTTIME_ALARM) {33 ksft_test_result_skip("CLOCK_BOOTTIME_ALARM isn't supported\n");34 return true;35 }36 37 if (config_posix_timers)38 return false;39 40 switch (clockid) {41 /* Only these clocks are supported without CONFIG_POSIX_TIMERS. */42 case CLOCK_BOOTTIME:43 case CLOCK_MONOTONIC:44 case CLOCK_REALTIME:45 return false;46 default:47 ksft_test_result_skip("Posix Clocks & timers are not supported\n");48 return true;49 }50 51 return false;52}53 54static inline int unshare_timens(void)55{56 if (unshare(CLONE_NEWTIME)) {57 if (errno == EPERM)58 ksft_exit_skip("need to run as root\n");59 return pr_perror("Can't unshare() timens");60 }61 return 0;62}63 64static inline int _settime(clockid_t clk_id, time_t offset)65{66 int fd, len;67 char buf[4096];68 69 if (clk_id == CLOCK_MONOTONIC_COARSE || clk_id == CLOCK_MONOTONIC_RAW)70 clk_id = CLOCK_MONOTONIC;71 72 len = snprintf(buf, sizeof(buf), "%d %ld 0", clk_id, offset);73 74 fd = open("/proc/self/timens_offsets", O_WRONLY);75 if (fd < 0)76 return pr_perror("/proc/self/timens_offsets");77 78 if (write(fd, buf, len) != len)79 return pr_perror("/proc/self/timens_offsets");80 81 close(fd);82 83 return 0;84}85 86static inline int _gettime(clockid_t clk_id, struct timespec *res, bool raw_syscall)87{88 int err;89 90 if (!raw_syscall) {91 if (clock_gettime(clk_id, res)) {92 pr_perror("clock_gettime(%d)", (int)clk_id);93 return -1;94 }95 return 0;96 }97 98 err = syscall(SYS_clock_gettime, clk_id, res);99 if (err)100 pr_perror("syscall(SYS_clock_gettime(%d))", (int)clk_id);101 102 return err;103}104 105static inline void nscheck(void)106{107 if (access("/proc/self/ns/time", F_OK) < 0)108 ksft_exit_skip("Time namespaces are not supported\n");109}110 111#endif112