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_NEWTIME 13 # define CLONE_NEWTIME 0x00000080 14 #endif 15 16 static int config_posix_timers = true; 17 18 static inline void check_config_posix_timers(void) 19 { 20 if (timer_create(-1, 0, 0) == -1 && errno == ENOSYS) 21 config_posix_timers = false; 22 } 23 24 static inline bool check_skip(int clockid) 25 { 26 if (config_posix_timers) 27 return false; 28 29 switch (clockid) { 30 /* Only these clocks are supported without CONFIG_POSIX_TIMERS. */ 31 case CLOCK_BOOTTIME: 32 case CLOCK_MONOTONIC: 33 case CLOCK_REALTIME: 34 return false; 35 default: 36 ksft_test_result_skip("Posix Clocks & timers are not supported\n"); 37 return true; 38 } 39 40 return false; 41 } 42 43 static inline int unshare_timens(void) 44 { 45 if (unshare(CLONE_NEWTIME)) { 46 if (errno == EPERM) 47 ksft_exit_skip("need to run as root\n"); 48 return pr_perror("Can't unshare() timens"); 49 } 50 return 0; 51 } 52 53 static inline int _settime(clockid_t clk_id, time_t offset) 54 { 55 int fd, len; 56 char buf[4096]; 57 58 if (clk_id == CLOCK_MONOTONIC_COARSE || clk_id == CLOCK_MONOTONIC_RAW) 59 clk_id = CLOCK_MONOTONIC; 60 61 len = snprintf(buf, sizeof(buf), "%d %ld 0", clk_id, offset); 62 63 fd = open("/proc/self/timens_offsets", O_WRONLY); 64 if (fd < 0) 65 return pr_perror("/proc/self/timens_offsets"); 66 67 if (write(fd, buf, len) != len) 68 return pr_perror("/proc/self/timens_offsets"); 69 70 close(fd); 71 72 return 0; 73 } 74 75 static inline int _gettime(clockid_t clk_id, struct timespec *res, bool raw_syscall) 76 { 77 int err; 78 79 if (!raw_syscall) { 80 if (clock_gettime(clk_id, res)) { 81 pr_perror("clock_gettime(%d)", (int)clk_id); 82 return -1; 83 } 84 return 0; 85 } 86 87 err = syscall(SYS_clock_gettime, clk_id, res); 88 if (err) 89 pr_perror("syscall(SYS_clock_gettime(%d))", (int)clk_id); 90 91 return err; 92 } 93 94 static inline void nscheck(void) 95 { 96 if (access("/proc/self/ns/time", F_OK) < 0) 97 ksft_exit_skip("Time namespaces are not supported\n"); 98 } 99 100 #endif 101