fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / kernel / vserver / cvirt.c
1 /*
2  *  linux/kernel/vserver/cvirt.c
3  *
4  *  Virtual Server: Context Virtualization
5  *
6  *  Copyright (C) 2004-2007  Herbert Pƶtzl
7  *
8  *  V0.01  broken out from limit.c
9  *  V0.02  added utsname stuff
10  *  V0.03  changed vcmds to vxi arg
11  *
12  */
13
14 #include <linux/sched.h>
15 #include <linux/sysctl.h>
16 #include <linux/types.h>
17 #include <linux/vs_context.h>
18 #include <linux/vs_cvirt.h>
19 #include <linux/vserver/switch.h>
20 #include <linux/vserver/cvirt_cmd.h>
21
22 #include <asm/errno.h>
23 #include <asm/uaccess.h>
24
25
26 void vx_vsi_uptime(struct timespec *uptime, struct timespec *idle)
27 {
28         struct vx_info *vxi = current->vx_info;
29
30         set_normalized_timespec(uptime,
31                 uptime->tv_sec - vxi->cvirt.bias_uptime.tv_sec,
32                 uptime->tv_nsec - vxi->cvirt.bias_uptime.tv_nsec);
33         if (!idle)
34                 return;
35         set_normalized_timespec(idle,
36                 idle->tv_sec - vxi->cvirt.bias_idle.tv_sec,
37                 idle->tv_nsec - vxi->cvirt.bias_idle.tv_nsec);
38         return;
39 }
40
41 uint64_t vx_idle_jiffies(void)
42 {
43         return init_task.utime + init_task.stime;
44 }
45
46
47
48 static inline uint32_t __update_loadavg(uint32_t load,
49         int wsize, int delta, int n)
50 {
51         unsigned long long calc, prev;
52
53         /* just set it to n */
54         if (unlikely(delta >= wsize))
55                 return (n << FSHIFT);
56
57         calc = delta * n;
58         calc <<= FSHIFT;
59         prev = (wsize - delta);
60         prev *= load;
61         calc += prev;
62         do_div(calc, wsize);
63         return calc;
64 }
65
66
67 void vx_update_load(struct vx_info *vxi)
68 {
69         uint32_t now, last, delta;
70         unsigned int nr_running, nr_uninterruptible;
71         unsigned int total;
72         unsigned long flags;
73
74         spin_lock_irqsave(&vxi->cvirt.load_lock, flags);
75
76         now = jiffies;
77         last = vxi->cvirt.load_last;
78         delta = now - last;
79
80         if (delta < 5*HZ)
81                 goto out;
82
83         nr_running = atomic_read(&vxi->cvirt.nr_running);
84         nr_uninterruptible = atomic_read(&vxi->cvirt.nr_uninterruptible);
85         total = nr_running + nr_uninterruptible;
86
87         vxi->cvirt.load[0] = __update_loadavg(vxi->cvirt.load[0],
88                 60*HZ, delta, total);
89         vxi->cvirt.load[1] = __update_loadavg(vxi->cvirt.load[1],
90                 5*60*HZ, delta, total);
91         vxi->cvirt.load[2] = __update_loadavg(vxi->cvirt.load[2],
92                 15*60*HZ, delta, total);
93
94         vxi->cvirt.load_last = now;
95 out:
96         atomic_inc(&vxi->cvirt.load_updates);
97         spin_unlock_irqrestore(&vxi->cvirt.load_lock, flags);
98 }
99
100
101 /*
102  * Commands to do_syslog:
103  *
104  *      0 -- Close the log.  Currently a NOP.
105  *      1 -- Open the log. Currently a NOP.
106  *      2 -- Read from the log.
107  *      3 -- Read all messages remaining in the ring buffer.
108  *      4 -- Read and clear all messages remaining in the ring buffer
109  *      5 -- Clear ring buffer.
110  *      6 -- Disable printk's to console
111  *      7 -- Enable printk's to console
112  *      8 -- Set level of messages printed to console
113  *      9 -- Return number of unread characters in the log buffer
114  *     10 -- Return size of the log buffer
115  */
116 int vx_do_syslog(int type, char __user *buf, int len)
117 {
118         int error = 0;
119         int do_clear = 0;
120         struct vx_info *vxi = current->vx_info;
121         struct _vx_syslog *log;
122
123         if (!vxi)
124                 return -EINVAL;
125         log = &vxi->cvirt.syslog;
126
127         switch (type) {
128         case 0:         /* Close log */
129         case 1:         /* Open log */
130                 break;
131         case 2:         /* Read from log */
132                 error = wait_event_interruptible(log->log_wait,
133                         (log->log_start - log->log_end));
134                 if (error)
135                         break;
136                 spin_lock_irq(&log->logbuf_lock);
137                 spin_unlock_irq(&log->logbuf_lock);
138                 break;
139         case 4:         /* Read/clear last kernel messages */
140                 do_clear = 1;
141                 /* fall through */
142         case 3:         /* Read last kernel messages */
143                 return 0;
144
145         case 5:         /* Clear ring buffer */
146                 return 0;
147
148         case 6:         /* Disable logging to console */
149         case 7:         /* Enable logging to console */
150         case 8:         /* Set level of messages printed to console */
151                 break;
152
153         case 9:         /* Number of chars in the log buffer */
154                 return 0;
155         case 10:        /* Size of the log buffer */
156                 return 0;
157         default:
158                 error = -EINVAL;
159                 break;
160         }
161         return error;
162 }
163
164
165 /* virtual host info names */
166
167 static char * vx_vhi_name(struct vx_info *vxi, int id)
168 {
169         struct nsproxy *nsproxy;
170         struct uts_namespace *uts;
171
172
173         if (id == VHIN_CONTEXT)
174                 return vxi->vx_name;
175
176         nsproxy = vxi->vx_nsproxy;
177         if (!nsproxy)
178                 return NULL;
179
180         uts = nsproxy->uts_ns;
181         if (!uts)
182                 return NULL;
183
184         switch (id) {
185         case VHIN_SYSNAME:
186                 return uts->name.sysname;
187         case VHIN_NODENAME:
188                 return uts->name.nodename;
189         case VHIN_RELEASE:
190                 return uts->name.release;
191         case VHIN_VERSION:
192                 return uts->name.version;
193         case VHIN_MACHINE:
194                 return uts->name.machine;
195         case VHIN_DOMAINNAME:
196                 return uts->name.domainname;
197         default:
198                 return NULL;
199         }
200         return NULL;
201 }
202
203 int vc_set_vhi_name(struct vx_info *vxi, void __user *data)
204 {
205         struct vcmd_vhi_name_v0 vc_data;
206         char *name;
207
208         if (copy_from_user (&vc_data, data, sizeof(vc_data)))
209                 return -EFAULT;
210
211         name = vx_vhi_name(vxi, vc_data.field);
212         if (!name)
213                 return -EINVAL;
214
215         memcpy(name, vc_data.name, 65);
216         return 0;
217 }
218
219 int vc_get_vhi_name(struct vx_info *vxi, void __user *data)
220 {
221         struct vcmd_vhi_name_v0 vc_data;
222         char *name;
223
224         if (copy_from_user (&vc_data, data, sizeof(vc_data)))
225                 return -EFAULT;
226
227         name = vx_vhi_name(vxi, vc_data.field);
228         if (!name)
229                 return -EINVAL;
230
231         memcpy(vc_data.name, name, 65);
232         if (copy_to_user (data, &vc_data, sizeof(vc_data)))
233                 return -EFAULT;
234         return 0;
235 }
236
237
238 int vc_virt_stat(struct vx_info *vxi, void __user *data)
239 {
240         struct vcmd_virt_stat_v0 vc_data;
241         struct _vx_cvirt *cvirt = &vxi->cvirt;
242         struct timespec uptime;
243
244         do_posix_clock_monotonic_gettime(&uptime);
245         set_normalized_timespec(&uptime,
246                 uptime.tv_sec - cvirt->bias_uptime.tv_sec,
247                 uptime.tv_nsec - cvirt->bias_uptime.tv_nsec);
248
249         vc_data.offset = timeval_to_ns(&cvirt->bias_tv);
250         vc_data.uptime = timespec_to_ns(&uptime);
251         vc_data.nr_threads = atomic_read(&cvirt->nr_threads);
252         vc_data.nr_running = atomic_read(&cvirt->nr_running);
253         vc_data.nr_uninterruptible = atomic_read(&cvirt->nr_uninterruptible);
254         vc_data.nr_onhold = atomic_read(&cvirt->nr_onhold);
255         vc_data.nr_forks = atomic_read(&cvirt->total_forks);
256         vc_data.load[0] = cvirt->load[0];
257         vc_data.load[1] = cvirt->load[1];
258         vc_data.load[2] = cvirt->load[2];
259
260         if (copy_to_user (data, &vc_data, sizeof(vc_data)))
261                 return -EFAULT;
262         return 0;
263 }
264
265
266 #ifdef CONFIG_VSERVER_VTIME
267
268 /* virtualized time base */
269
270 void vx_gettimeofday(struct timeval *tv)
271 {
272         do_gettimeofday(tv);
273         if (!vx_flags(VXF_VIRT_TIME, 0))
274                 return;
275
276         tv->tv_sec += current->vx_info->cvirt.bias_tv.tv_sec;
277         tv->tv_usec += current->vx_info->cvirt.bias_tv.tv_usec;
278
279         if (tv->tv_usec >= USEC_PER_SEC) {
280                 tv->tv_sec++;
281                 tv->tv_usec -= USEC_PER_SEC;
282         } else if (tv->tv_usec < 0) {
283                 tv->tv_sec--;
284                 tv->tv_usec += USEC_PER_SEC;
285         }
286 }
287
288 int vx_settimeofday(struct timespec *ts)
289 {
290         struct timeval tv;
291
292         if (!vx_flags(VXF_VIRT_TIME, 0))
293                 return do_settimeofday(ts);
294
295         do_gettimeofday(&tv);
296         current->vx_info->cvirt.bias_tv.tv_sec =
297                 ts->tv_sec - tv.tv_sec;
298         current->vx_info->cvirt.bias_tv.tv_usec =
299                 (ts->tv_nsec/NSEC_PER_USEC) - tv.tv_usec;
300         return 0;
301 }
302
303 #endif
304