1 // SPDX-License-Identifier: GPL-2.0
11 #include <sys/syscall.h>
12 #include <sys/types.h>
20 * Test shouldn't be run for a day, so add 10 days to child
21 * time and check parent's time to be in the same day.
23 #define MAX_TEST_TIME_SEC (60*5)
24 #define DAY_IN_SEC (60*60*24)
25 #define TEN_DAYS_IN_SEC (10*DAY_IN_SEC)
27 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
29 static int child_ns
, parent_ns
;
31 static int switch_ns(int fd
)
33 if (setns(fd
, CLONE_NEWTIME
))
34 return pr_perror("setns()");
39 static int init_namespaces(void)
41 char path
[] = "/proc/self/ns/time_for_children";
44 parent_ns
= open(path
, O_RDONLY
);
46 return pr_perror("Unable to open %s", path
);
48 if (fstat(parent_ns
, &st1
))
49 return pr_perror("Unable to stat the parent timens");
54 child_ns
= open(path
, O_RDONLY
);
56 return pr_perror("Unable to open %s", path
);
58 if (fstat(child_ns
, &st2
))
59 return pr_perror("Unable to stat the timens");
61 if (st1
.st_ino
== st2
.st_ino
)
62 return pr_err("The same child_ns after CLONE_NEWTIME");
64 if (_settime(CLOCK_BOOTTIME
, TEN_DAYS_IN_SEC
))
70 static int read_proc_uptime(struct timespec
*uptime
)
72 unsigned long up_sec
, up_nsec
;
75 proc
= fopen("/proc/uptime", "r");
77 pr_perror("Unable to open /proc/uptime");
81 if (fscanf(proc
, "%lu.%02lu", &up_sec
, &up_nsec
) != 2) {
86 pr_err("failed to parse /proc/uptime");
91 uptime
->tv_sec
= up_sec
;
92 uptime
->tv_nsec
= up_nsec
;
96 static int check_uptime(void)
98 struct timespec uptime_new
, uptime_old
;
99 time_t uptime_expected
;
100 double prec
= MAX_TEST_TIME_SEC
;
102 if (switch_ns(parent_ns
))
103 return pr_err("switch_ns(%d)", parent_ns
);
105 if (read_proc_uptime(&uptime_old
))
108 if (switch_ns(child_ns
))
109 return pr_err("switch_ns(%d)", child_ns
);
111 if (read_proc_uptime(&uptime_new
))
114 uptime_expected
= uptime_old
.tv_sec
+ TEN_DAYS_IN_SEC
;
115 if (fabs(difftime(uptime_new
.tv_sec
, uptime_expected
)) > prec
) {
116 pr_fail("uptime in /proc/uptime: old %ld, new %ld [%ld]",
117 uptime_old
.tv_sec
, uptime_new
.tv_sec
,
118 uptime_old
.tv_sec
+ TEN_DAYS_IN_SEC
);
122 ksft_test_result_pass("Passed for /proc/uptime\n");
126 int main(int argc
, char *argv
[])
134 if (init_namespaces())
137 ret
|= check_uptime();