2 * linux/kernel/vserver/cvirt.c
4 * Virtual Server: Context Virtualization
6 * Copyright (C) 2004-2007 Herbert Pƶtzl
8 * V0.01 broken out from limit.c
9 * V0.02 added utsname stuff
10 * V0.03 changed vcmds to vxi arg
14 #include <linux/sched.h>
15 #include <linux/sysctl.h>
16 #include <linux/types.h>
17 #include <linux/vs_base.h>
18 #include <linux/vs_context.h>
19 #include <linux/vs_cvirt.h>
20 #include <linux/vserver/switch.h>
21 #include <linux/vserver/cvirt_cmd.h>
23 #include <asm/errno.h>
24 #include <asm/uaccess.h>
27 void vx_vsi_uptime(struct timespec *uptime, struct timespec *idle)
29 struct vx_info *vxi = current->vx_info;
31 set_normalized_timespec(uptime,
32 uptime->tv_sec - vxi->cvirt.bias_uptime.tv_sec,
33 uptime->tv_nsec - vxi->cvirt.bias_uptime.tv_nsec);
36 set_normalized_timespec(idle,
37 idle->tv_sec - vxi->cvirt.bias_idle.tv_sec,
38 idle->tv_nsec - vxi->cvirt.bias_idle.tv_nsec);
42 uint64_t vx_idle_jiffies(void)
44 return init_task.utime + init_task.stime;
49 static inline uint32_t __update_loadavg(uint32_t load,
50 int wsize, int delta, int n)
52 unsigned long long calc, prev;
54 /* just set it to n */
55 if (unlikely(delta >= wsize))
60 prev = (wsize - delta);
68 void vx_update_load(struct vx_info *vxi)
70 uint32_t now, last, delta;
71 unsigned int nr_running, nr_uninterruptible;
75 spin_lock_irqsave(&vxi->cvirt.load_lock, flags);
78 last = vxi->cvirt.load_last;
84 nr_running = atomic_read(&vxi->cvirt.nr_running);
85 nr_uninterruptible = atomic_read(&vxi->cvirt.nr_uninterruptible);
86 total = nr_running + nr_uninterruptible;
88 vxi->cvirt.load[0] = __update_loadavg(vxi->cvirt.load[0],
90 vxi->cvirt.load[1] = __update_loadavg(vxi->cvirt.load[1],
91 5*60*HZ, delta, total);
92 vxi->cvirt.load[2] = __update_loadavg(vxi->cvirt.load[2],
93 15*60*HZ, delta, total);
95 vxi->cvirt.load_last = now;
97 atomic_inc(&vxi->cvirt.load_updates);
98 spin_unlock_irqrestore(&vxi->cvirt.load_lock, flags);
103 * Commands to do_syslog:
105 * 0 -- Close the log. Currently a NOP.
106 * 1 -- Open the log. Currently a NOP.
107 * 2 -- Read from the log.
108 * 3 -- Read all messages remaining in the ring buffer.
109 * 4 -- Read and clear all messages remaining in the ring buffer
110 * 5 -- Clear ring buffer.
111 * 6 -- Disable printk's to console
112 * 7 -- Enable printk's to console
113 * 8 -- Set level of messages printed to console
114 * 9 -- Return number of unread characters in the log buffer
115 * 10 -- Return size of the log buffer
117 int vx_do_syslog(int type, char __user *buf, int len)
121 struct vx_info *vxi = current->vx_info;
122 struct _vx_syslog *log;
126 log = &vxi->cvirt.syslog;
129 case 0: /* Close log */
130 case 1: /* Open log */
132 case 2: /* Read from log */
133 error = wait_event_interruptible(log->log_wait,
134 (log->log_start - log->log_end));
137 spin_lock_irq(&log->logbuf_lock);
138 spin_unlock_irq(&log->logbuf_lock);
140 case 4: /* Read/clear last kernel messages */
143 case 3: /* Read last kernel messages */
146 case 5: /* Clear ring buffer */
149 case 6: /* Disable logging to console */
150 case 7: /* Enable logging to console */
151 case 8: /* Set level of messages printed to console */
154 case 9: /* Number of chars in the log buffer */
156 case 10: /* Size of the log buffer */
166 /* virtual host info names */
168 static char * vx_vhi_name(struct vx_info *vxi, int id)
170 struct nsproxy *nsproxy;
171 struct uts_namespace *uts;
174 if (id == VHIN_CONTEXT)
177 nsproxy = vxi->vx_nsproxy;
181 uts = nsproxy->uts_ns;
187 return uts->name.sysname;
189 return uts->name.nodename;
191 return uts->name.release;
193 return uts->name.version;
195 return uts->name.machine;
196 case VHIN_DOMAINNAME:
197 return uts->name.domainname;
204 int vc_set_vhi_name(struct vx_info *vxi, void __user *data)
206 struct vcmd_vhi_name_v0 vc_data;
209 if (copy_from_user (&vc_data, data, sizeof(vc_data)))
212 name = vx_vhi_name(vxi, vc_data.field);
216 memcpy(name, vc_data.name, 65);
220 int vc_get_vhi_name(struct vx_info *vxi, void __user *data)
222 struct vcmd_vhi_name_v0 vc_data;
225 if (copy_from_user (&vc_data, data, sizeof(vc_data)))
228 name = vx_vhi_name(vxi, vc_data.field);
232 memcpy(vc_data.name, name, 65);
233 if (copy_to_user (data, &vc_data, sizeof(vc_data)))
239 int vc_virt_stat(struct vx_info *vxi, void __user *data)
241 struct vcmd_virt_stat_v0 vc_data;
242 struct _vx_cvirt *cvirt = &vxi->cvirt;
243 struct timespec uptime;
245 do_posix_clock_monotonic_gettime(&uptime);
246 set_normalized_timespec(&uptime,
247 uptime.tv_sec - cvirt->bias_uptime.tv_sec,
248 uptime.tv_nsec - cvirt->bias_uptime.tv_nsec);
250 vc_data.offset = timeval_to_ns(&cvirt->bias_tv);
251 vc_data.uptime = timespec_to_ns(&uptime);
252 vc_data.nr_threads = atomic_read(&cvirt->nr_threads);
253 vc_data.nr_running = atomic_read(&cvirt->nr_running);
254 vc_data.nr_uninterruptible = atomic_read(&cvirt->nr_uninterruptible);
255 vc_data.nr_onhold = atomic_read(&cvirt->nr_onhold);
256 vc_data.nr_forks = atomic_read(&cvirt->total_forks);
257 vc_data.load[0] = cvirt->load[0];
258 vc_data.load[1] = cvirt->load[1];
259 vc_data.load[2] = cvirt->load[2];
261 if (copy_to_user (data, &vc_data, sizeof(vc_data)))
267 #ifdef CONFIG_VSERVER_VTIME
269 /* virtualized time base */
271 void vx_gettimeofday(struct timeval *tv)
274 if (!vx_flags(VXF_VIRT_TIME, 0))
277 tv->tv_sec += current->vx_info->cvirt.bias_tv.tv_sec;
278 tv->tv_usec += current->vx_info->cvirt.bias_tv.tv_usec;
280 if (tv->tv_usec >= USEC_PER_SEC) {
282 tv->tv_usec -= USEC_PER_SEC;
283 } else if (tv->tv_usec < 0) {
285 tv->tv_usec += USEC_PER_SEC;
289 int vx_settimeofday(struct timespec *ts)
293 if (!vx_flags(VXF_VIRT_TIME, 0))
294 return do_settimeofday(ts);
296 do_gettimeofday(&tv);
297 current->vx_info->cvirt.bias_tv.tv_sec =
298 ts->tv_sec - tv.tv_sec;
299 current->vx_info->cvirt.bias_tv.tv_usec =
300 (ts->tv_nsec/NSEC_PER_USEC) - tv.tv_usec;