GNU Linux-libre 6.9.1-gnu
[releases.git] / include / linux / time_namespace.h
1 /* SPDX-License-Identifier: GPL-2.0 */
2 #ifndef _LINUX_TIMENS_H
3 #define _LINUX_TIMENS_H
4
5
6 #include <linux/sched.h>
7 #include <linux/nsproxy.h>
8 #include <linux/ns_common.h>
9 #include <linux/err.h>
10 #include <linux/time64.h>
11
12 struct user_namespace;
13 extern struct user_namespace init_user_ns;
14
15 struct vm_area_struct;
16
17 struct timens_offsets {
18         struct timespec64 monotonic;
19         struct timespec64 boottime;
20 };
21
22 struct time_namespace {
23         struct user_namespace   *user_ns;
24         struct ucounts          *ucounts;
25         struct ns_common        ns;
26         struct timens_offsets   offsets;
27         struct page             *vvar_page;
28         /* If set prevents changing offsets after any task joined namespace. */
29         bool                    frozen_offsets;
30 } __randomize_layout;
31
32 extern struct time_namespace init_time_ns;
33
34 #ifdef CONFIG_TIME_NS
35 extern int vdso_join_timens(struct task_struct *task,
36                             struct time_namespace *ns);
37 extern void timens_commit(struct task_struct *tsk, struct time_namespace *ns);
38
39 static inline struct time_namespace *get_time_ns(struct time_namespace *ns)
40 {
41         refcount_inc(&ns->ns.count);
42         return ns;
43 }
44
45 struct time_namespace *copy_time_ns(unsigned long flags,
46                                     struct user_namespace *user_ns,
47                                     struct time_namespace *old_ns);
48 void free_time_ns(struct time_namespace *ns);
49 void timens_on_fork(struct nsproxy *nsproxy, struct task_struct *tsk);
50 struct page *find_timens_vvar_page(struct vm_area_struct *vma);
51
52 static inline void put_time_ns(struct time_namespace *ns)
53 {
54         if (refcount_dec_and_test(&ns->ns.count))
55                 free_time_ns(ns);
56 }
57
58 void proc_timens_show_offsets(struct task_struct *p, struct seq_file *m);
59
60 struct proc_timens_offset {
61         int                     clockid;
62         struct timespec64       val;
63 };
64
65 int proc_timens_set_offset(struct file *file, struct task_struct *p,
66                            struct proc_timens_offset *offsets, int n);
67
68 static inline void timens_add_monotonic(struct timespec64 *ts)
69 {
70         struct timens_offsets *ns_offsets = &current->nsproxy->time_ns->offsets;
71
72         *ts = timespec64_add(*ts, ns_offsets->monotonic);
73 }
74
75 static inline void timens_add_boottime(struct timespec64 *ts)
76 {
77         struct timens_offsets *ns_offsets = &current->nsproxy->time_ns->offsets;
78
79         *ts = timespec64_add(*ts, ns_offsets->boottime);
80 }
81
82 static inline u64 timens_add_boottime_ns(u64 nsec)
83 {
84         struct timens_offsets *ns_offsets = &current->nsproxy->time_ns->offsets;
85
86         return nsec + timespec64_to_ns(&ns_offsets->boottime);
87 }
88
89 static inline void timens_sub_boottime(struct timespec64 *ts)
90 {
91         struct timens_offsets *ns_offsets = &current->nsproxy->time_ns->offsets;
92
93         *ts = timespec64_sub(*ts, ns_offsets->boottime);
94 }
95
96 ktime_t do_timens_ktime_to_host(clockid_t clockid, ktime_t tim,
97                                 struct timens_offsets *offsets);
98
99 static inline ktime_t timens_ktime_to_host(clockid_t clockid, ktime_t tim)
100 {
101         struct time_namespace *ns = current->nsproxy->time_ns;
102
103         if (likely(ns == &init_time_ns))
104                 return tim;
105
106         return do_timens_ktime_to_host(clockid, tim, &ns->offsets);
107 }
108
109 #else
110 static inline int vdso_join_timens(struct task_struct *task,
111                                    struct time_namespace *ns)
112 {
113         return 0;
114 }
115
116 static inline void timens_commit(struct task_struct *tsk,
117                                  struct time_namespace *ns)
118 {
119 }
120
121 static inline struct time_namespace *get_time_ns(struct time_namespace *ns)
122 {
123         return NULL;
124 }
125
126 static inline void put_time_ns(struct time_namespace *ns)
127 {
128 }
129
130 static inline
131 struct time_namespace *copy_time_ns(unsigned long flags,
132                                     struct user_namespace *user_ns,
133                                     struct time_namespace *old_ns)
134 {
135         if (flags & CLONE_NEWTIME)
136                 return ERR_PTR(-EINVAL);
137
138         return old_ns;
139 }
140
141 static inline void timens_on_fork(struct nsproxy *nsproxy,
142                                  struct task_struct *tsk)
143 {
144         return;
145 }
146
147 static inline struct page *find_timens_vvar_page(struct vm_area_struct *vma)
148 {
149         return NULL;
150 }
151
152 static inline void timens_add_monotonic(struct timespec64 *ts) { }
153 static inline void timens_add_boottime(struct timespec64 *ts) { }
154
155 static inline u64 timens_add_boottime_ns(u64 nsec)
156 {
157         return nsec;
158 }
159
160 static inline void timens_sub_boottime(struct timespec64 *ts) { }
161
162 static inline ktime_t timens_ktime_to_host(clockid_t clockid, ktime_t tim)
163 {
164         return tim;
165 }
166 #endif
167
168 struct vdso_data *arch_get_vdso_data(void *vvar_page);
169
170 #endif /* _LINUX_TIMENS_H */