48053039d2b9eb6fe47600a4440c0997ad386caa
[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/sched.h>
14 #include <linux/sysctl.h>
15 #include <linux/types.h>
16 #include <linux/vs_context.h>
17 #include <linux/vs_cvirt.h>
18 #include <linux/vserver/switch.h>
19 #include <linux/vserver/cvirt_cmd.h>
20
21 #include <asm/errno.h>
22 #include <asm/uaccess.h>
23
24
25 void vx_vsi_uptime(struct timespec *uptime, struct timespec *idle)
26 {
27         struct vx_info *vxi = current->vx_info;
28
29         set_normalized_timespec(uptime,
30                 uptime->tv_sec - vxi->cvirt.bias_uptime.tv_sec,
31                 uptime->tv_nsec - vxi->cvirt.bias_uptime.tv_nsec);
32         if (!idle)
33                 return;
34         set_normalized_timespec(idle,
35                 idle->tv_sec - vxi->cvirt.bias_idle.tv_sec,
36                 idle->tv_nsec - vxi->cvirt.bias_idle.tv_nsec);
37         return;
38 }
39
40 uint64_t vx_idle_jiffies(void)
41 {
42         return init_task.utime + init_task.stime;
43 }
44
45
46
47 static inline uint32_t __update_loadavg(uint32_t load,
48         int wsize, int delta, int n)
49 {
50         unsigned long long calc, prev;
51
52         /* just set it to n */
53         if (unlikely(delta >= wsize))
54                 return (n << FSHIFT);
55
56         calc = delta * n;
57         calc <<= FSHIFT;
58         prev = (wsize - delta);
59         prev *= load;
60         calc += prev;
61         do_div(calc, wsize);
62         return calc;
63 }
64
65
66 void vx_update_load(struct vx_info *vxi)
67 {
68         uint32_t now, last, delta;
69         unsigned int nr_running, nr_uninterruptible;
70         unsigned int total;
71
72         spin_lock(&vxi->cvirt.load_lock);
73
74         now = jiffies;
75         last = vxi->cvirt.load_last;
76         delta = now - last;
77
78         if (delta < 5*HZ)
79                 goto out;
80
81         nr_running = atomic_read(&vxi->cvirt.nr_running);
82         nr_uninterruptible = atomic_read(&vxi->cvirt.nr_uninterruptible);
83         total = nr_running + nr_uninterruptible;
84
85         vxi->cvirt.load[0] = __update_loadavg(vxi->cvirt.load[0],
86                 60*HZ, delta, total);
87         vxi->cvirt.load[1] = __update_loadavg(vxi->cvirt.load[1],
88                 5*60*HZ, delta, total);
89         vxi->cvirt.load[2] = __update_loadavg(vxi->cvirt.load[2],
90                 15*60*HZ, delta, total);
91
92         vxi->cvirt.load_last = now;
93 out:
94         atomic_inc(&vxi->cvirt.load_updates);
95         spin_unlock(&vxi->cvirt.load_lock);
96 }
97
98
99 int vx_uts_virt_handler(struct ctl_table *ctl, int write, xid_t xid,
100         void **datap, size_t *lenp)
101 {
102         switch (ctl->ctl_name) {
103         case KERN_OSTYPE:
104                 *datap = vx_new_uts(sysname);
105                 break;
106         case KERN_OSRELEASE:
107                 *datap = vx_new_uts(release);
108                 break;
109         case KERN_VERSION:
110                 *datap = vx_new_uts(version);
111                 break;
112         case KERN_NODENAME:
113                 *datap = vx_new_uts(nodename);
114                 break;
115         case KERN_DOMAINNAME:
116                 *datap = vx_new_uts(domainname);
117                 break;
118         }
119
120         return 0;
121 }
122
123
124
125 /*
126  * Commands to do_syslog:
127  *
128  *      0 -- Close the log.  Currently a NOP.
129  *      1 -- Open the log. Currently a NOP.
130  *      2 -- Read from the log.
131  *      3 -- Read all messages remaining in the ring buffer.
132  *      4 -- Read and clear all messages remaining in the ring buffer
133  *      5 -- Clear ring buffer.
134  *      6 -- Disable printk's to console
135  *      7 -- Enable printk's to console
136  *      8 -- Set level of messages printed to console
137  *      9 -- Return number of unread characters in the log buffer
138  *     10 -- Return size of the log buffer
139  */
140 int vx_do_syslog(int type, char __user *buf, int len)
141 {
142         int error = 0;
143         int do_clear = 0;
144         struct vx_info *vxi = current->vx_info;
145         struct _vx_syslog *log;
146
147         if (!vxi)
148                 return -EINVAL;
149         log = &vxi->cvirt.syslog;
150
151         switch (type) {
152         case 0:         /* Close log */
153         case 1:         /* Open log */
154                 break;
155         case 2:         /* Read from log */
156                 error = wait_event_interruptible(log->log_wait,
157                         (log->log_start - log->log_end));
158                 if (error)
159                         break;
160                 spin_lock_irq(&log->logbuf_lock);
161                 spin_unlock_irq(&log->logbuf_lock);
162                 break;
163         case 4:         /* Read/clear last kernel messages */
164                 do_clear = 1;
165                 /* fall through */
166         case 3:         /* Read last kernel messages */
167                 return 0;
168
169         case 5:         /* Clear ring buffer */
170                 return 0;
171
172         case 6:         /* Disable logging to console */
173         case 7:         /* Enable logging to console */
174         case 8:         /* Set level of messages printed to console */
175                 break;
176
177         case 9:         /* Number of chars in the log buffer */
178                 return 0;
179         case 10:        /* Size of the log buffer */
180                 return 0;
181         default:
182                 error = -EINVAL;
183                 break;
184         }
185         return error;
186 }
187
188
189 /* virtual host info names */
190
191 static char * vx_vhi_name(struct vx_info *vxi, int id)
192 {
193         switch (id) {
194         case VHIN_CONTEXT:
195                 return vxi->vx_name;
196         case VHIN_SYSNAME:
197                 return vxi->cvirt.utsname.sysname;
198         case VHIN_NODENAME:
199                 return vxi->cvirt.utsname.nodename;
200         case VHIN_RELEASE:
201                 return vxi->cvirt.utsname.release;
202         case VHIN_VERSION:
203                 return vxi->cvirt.utsname.version;
204         case VHIN_MACHINE:
205                 return vxi->cvirt.utsname.machine;
206         case VHIN_DOMAINNAME:
207                 return vxi->cvirt.utsname.domainname;
208         default:
209                 return NULL;
210         }
211         return NULL;
212 }
213
214 int vc_set_vhi_name(uint32_t id, void __user *data)
215 {
216         struct vx_info *vxi;
217         struct vcmd_vhi_name_v0 vc_data;
218         char *name;
219
220         if (!capable(CAP_SYS_ADMIN))
221                 return -EPERM;
222         if (copy_from_user (&vc_data, data, sizeof(vc_data)))
223                 return -EFAULT;
224
225         vxi = lookup_vx_info(id);
226         if (!vxi)
227                 return -ESRCH;
228
229         name = vx_vhi_name(vxi, vc_data.field);
230         if (name)
231                 memcpy(name, vc_data.name, 65);
232         put_vx_info(vxi);
233         return (name ? 0 : -EFAULT);
234 }
235
236 int vc_get_vhi_name(uint32_t id, void __user *data)
237 {
238         struct vx_info *vxi;
239         struct vcmd_vhi_name_v0 vc_data;
240         char *name;
241
242         if (copy_from_user (&vc_data, data, sizeof(vc_data)))
243                 return -EFAULT;
244
245         vxi = lookup_vx_info(id);
246         if (!vxi)
247                 return -ESRCH;
248
249         name = vx_vhi_name(vxi, vc_data.field);
250         if (!name)
251                 goto out_put;
252
253         memcpy(vc_data.name, name, 65);
254         if (copy_to_user (data, &vc_data, sizeof(vc_data)))
255                 return -EFAULT;
256 out_put:
257         put_vx_info(vxi);
258         return (name ? 0 : -EFAULT);
259 }