vserver 2.0 rc7
[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-2005  Herbert Pƶtzl
7  *
8  *  V0.01  broken out from limit.c
9  *  V0.02  added utsname stuff
10  *
11  */
12
13 #include <linux/config.h>
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
73         spin_lock(&vxi->cvirt.load_lock);
74
75         now = jiffies;
76         last = vxi->cvirt.load_last;
77         delta = now - last;
78
79         if (delta < 5*HZ)
80                 goto out;
81
82         nr_running = atomic_read(&vxi->cvirt.nr_running);
83         nr_uninterruptible = atomic_read(&vxi->cvirt.nr_uninterruptible);
84         total = nr_running + nr_uninterruptible;
85
86         vxi->cvirt.load[0] = __update_loadavg(vxi->cvirt.load[0],
87                 60*HZ, delta, total);
88         vxi->cvirt.load[1] = __update_loadavg(vxi->cvirt.load[1],
89                 5*60*HZ, delta, total);
90         vxi->cvirt.load[2] = __update_loadavg(vxi->cvirt.load[2],
91                 15*60*HZ, delta, total);
92
93         vxi->cvirt.load_last = now;
94 out:
95         atomic_inc(&vxi->cvirt.load_updates);
96         spin_unlock(&vxi->cvirt.load_lock);
97 }
98
99
100 int vx_uts_virt_handler(struct ctl_table *ctl, int write, xid_t xid,
101         void **datap, size_t *lenp)
102 {
103         switch (ctl->ctl_name) {
104         case KERN_OSTYPE:
105                 *datap = vx_new_uts(sysname);
106                 break;
107         case KERN_OSRELEASE:
108                 *datap = vx_new_uts(release);
109                 break;
110         case KERN_VERSION:
111                 *datap = vx_new_uts(version);
112                 break;
113         case KERN_NODENAME:
114                 *datap = vx_new_uts(nodename);
115                 break;
116         case KERN_DOMAINNAME:
117                 *datap = vx_new_uts(domainname);
118                 break;
119         }
120
121         return 0;
122 }
123
124
125
126 /*
127  * Commands to do_syslog:
128  *
129  *      0 -- Close the log.  Currently a NOP.
130  *      1 -- Open the log. Currently a NOP.
131  *      2 -- Read from the log.
132  *      3 -- Read all messages remaining in the ring buffer.
133  *      4 -- Read and clear all messages remaining in the ring buffer
134  *      5 -- Clear ring buffer.
135  *      6 -- Disable printk's to console
136  *      7 -- Enable printk's to console
137  *      8 -- Set level of messages printed to console
138  *      9 -- Return number of unread characters in the log buffer
139  *     10 -- Return size of the log buffer
140  */
141 int vx_do_syslog(int type, char __user *buf, int len)
142 {
143         int error = 0;
144         int do_clear = 0;
145         struct vx_info *vxi = current->vx_info;
146         struct _vx_syslog *log;
147
148         if (!vxi)
149                 return -EINVAL;
150         log = &vxi->cvirt.syslog;
151
152         switch (type) {
153         case 0:         /* Close log */
154         case 1:         /* Open log */
155                 break;
156         case 2:         /* Read from log */
157                 error = wait_event_interruptible(log->log_wait,
158                         (log->log_start - log->log_end));
159                 if (error)
160                         break;
161                 spin_lock_irq(&log->logbuf_lock);
162                 spin_unlock_irq(&log->logbuf_lock);
163                 break;
164         case 4:         /* Read/clear last kernel messages */
165                 do_clear = 1;
166                 /* fall through */
167         case 3:         /* Read last kernel messages */
168                 return 0;
169
170         case 5:         /* Clear ring buffer */
171                 return 0;
172
173         case 6:         /* Disable logging to console */
174         case 7:         /* Enable logging to console */
175         case 8:         /* Set level of messages printed to console */
176                 break;
177
178         case 9:         /* Number of chars in the log buffer */
179                 return 0;
180         case 10:        /* Size of the log buffer */
181                 return 0;
182         default:
183                 error = -EINVAL;
184                 break;
185         }
186         return error;
187 }
188
189
190 /* virtual host info names */
191
192 static char * vx_vhi_name(struct vx_info *vxi, int id)
193 {
194         switch (id) {
195                 case VHIN_CONTEXT:
196                         return vxi->vx_name;
197                 case VHIN_SYSNAME:
198                         return vxi->cvirt.utsname.sysname;
199                 case VHIN_NODENAME:
200                         return vxi->cvirt.utsname.nodename;
201                 case VHIN_RELEASE:
202                         return vxi->cvirt.utsname.release;
203                 case VHIN_VERSION:
204                         return vxi->cvirt.utsname.version;
205                 case VHIN_MACHINE:
206                         return vxi->cvirt.utsname.machine;
207                 case VHIN_DOMAINNAME:
208                         return vxi->cvirt.utsname.domainname;
209                 default:
210                         return NULL;
211         }
212         return NULL;
213 }
214
215 int vc_set_vhi_name(uint32_t id, void __user *data)
216 {
217         struct vx_info *vxi;
218         struct vcmd_vhi_name_v0 vc_data;
219         char *name;
220
221         if (!capable(CAP_SYS_ADMIN))
222                 return -EPERM;
223         if (copy_from_user (&vc_data, data, sizeof(vc_data)))
224                 return -EFAULT;
225
226         vxi = locate_vx_info(id);
227         if (!vxi)
228                 return -ESRCH;
229
230         name = vx_vhi_name(vxi, vc_data.field);
231         if (name)
232                 memcpy(name, vc_data.name, 65);
233         put_vx_info(vxi);
234         return (name ? 0 : -EFAULT);
235 }
236
237 int vc_get_vhi_name(uint32_t id, void __user *data)
238 {
239         struct vx_info *vxi;
240         struct vcmd_vhi_name_v0 vc_data;
241         char *name;
242
243         if (copy_from_user (&vc_data, data, sizeof(vc_data)))
244                 return -EFAULT;
245
246         vxi = locate_vx_info(id);
247         if (!vxi)
248                 return -ESRCH;
249
250         name = vx_vhi_name(vxi, vc_data.field);
251         if (!name)
252                 goto out_put;
253
254         memcpy(vc_data.name, name, 65);
255         if (copy_to_user (data, &vc_data, sizeof(vc_data)))
256                 return -EFAULT;
257 out_put:
258         put_vx_info(vxi);
259         return (name ? 0 : -EFAULT);
260 }