vserver 2.0-pre4
[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  *
10  */
11
12 #include <linux/config.h>
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
20 #include <asm/errno.h>
21 #include <asm/uaccess.h>
22
23
24 void vx_vsi_uptime(struct timespec *uptime, struct timespec *idle)
25 {
26         struct vx_info *vxi = current->vx_info;
27
28         set_normalized_timespec(uptime,
29                 uptime->tv_sec - vxi->cvirt.bias_uptime.tv_sec,
30                 uptime->tv_nsec - vxi->cvirt.bias_uptime.tv_nsec);
31         if (!idle)
32                 return;
33         set_normalized_timespec(idle,
34                 idle->tv_sec - vxi->cvirt.bias_idle.tv_sec,
35                 idle->tv_nsec - vxi->cvirt.bias_idle.tv_nsec);
36         return;
37 }
38
39 uint64_t vx_idle_jiffies(void)
40 {
41         return init_task.utime + init_task.stime;
42 }
43
44
45
46 static inline uint32_t __update_loadavg(uint32_t load,
47         int wsize, int delta, int n)
48 {
49         unsigned long long calc, prev;
50
51         /* just set it to n */
52         if (unlikely(delta >= wsize))
53                 return (n << FSHIFT);
54
55         calc = delta * n;
56         calc <<= FSHIFT;
57         prev = (wsize - delta);
58         prev *= load;
59         calc += prev;
60         do_div(calc, wsize);
61         return calc;
62 }
63
64
65 void vx_update_load(struct vx_info *vxi)
66 {
67         uint32_t now, last, delta;
68         unsigned int nr_running, nr_uninterruptible;
69         unsigned int total;
70
71         spin_lock(&vxi->cvirt.load_lock);
72
73         now = jiffies;
74         last = vxi->cvirt.load_last;
75         delta = now - last;
76
77         if (delta < 5*HZ)
78                 goto out;
79
80         nr_running = atomic_read(&vxi->cvirt.nr_running);
81         nr_uninterruptible = atomic_read(&vxi->cvirt.nr_uninterruptible);
82         total = nr_running + nr_uninterruptible;
83
84         vxi->cvirt.load[0] = __update_loadavg(vxi->cvirt.load[0],
85                 60*HZ, delta, total);
86         vxi->cvirt.load[1] = __update_loadavg(vxi->cvirt.load[1],
87                 5*60*HZ, delta, total);
88         vxi->cvirt.load[2] = __update_loadavg(vxi->cvirt.load[2],
89                 15*60*HZ, delta, total);
90
91         vxi->cvirt.load_last = now;
92 out:
93         atomic_inc(&vxi->cvirt.load_updates);
94         spin_unlock(&vxi->cvirt.load_lock);
95 }
96
97
98 int vx_uts_virt_handler(struct ctl_table *ctl, int write, xid_t xid,
99         void **datap, size_t *lenp)
100 {
101         switch (ctl->ctl_name) {
102         case KERN_OSTYPE:
103                 *datap = vx_new_uts(sysname);
104                 break;
105         case KERN_OSRELEASE:
106                 *datap = vx_new_uts(release);
107                 break;
108         case KERN_VERSION:
109                 *datap = vx_new_uts(version);
110                 break;
111         case KERN_NODENAME:
112                 *datap = vx_new_uts(nodename);
113                 break;
114         case KERN_DOMAINNAME:
115                 *datap = vx_new_uts(domainname);
116                 break;
117         }
118
119         return 0;
120 }
121
122
123
124 /*
125  * Commands to do_syslog:
126  *
127  *      0 -- Close the log.  Currently a NOP.
128  *      1 -- Open the log. Currently a NOP.
129  *      2 -- Read from the log.
130  *      3 -- Read all messages remaining in the ring buffer.
131  *      4 -- Read and clear all messages remaining in the ring buffer
132  *      5 -- Clear ring buffer.
133  *      6 -- Disable printk's to console
134  *      7 -- Enable printk's to console
135  *      8 -- Set level of messages printed to console
136  *      9 -- Return number of unread characters in the log buffer
137  *     10 -- Return size of the log buffer
138  */
139 int vx_do_syslog(int type, char __user *buf, int len)
140 {
141         int error = 0;
142         int do_clear = 0;
143         struct vx_info *vxi = current->vx_info;
144         struct _vx_syslog *log;
145
146         if (!vxi)
147                 return -EINVAL;
148         log = &vxi->cvirt.syslog;
149
150         switch (type) {
151         case 0:         /* Close log */
152         case 1:         /* Open log */
153                 break;
154         case 2:         /* Read from log */
155                 error = wait_event_interruptible(log->log_wait,
156                         (log->log_start - log->log_end));
157                 if (error)
158                         break;
159                 spin_lock_irq(&log->logbuf_lock);
160                 spin_unlock_irq(&log->logbuf_lock);
161                 break;
162         case 4:         /* Read/clear last kernel messages */
163                 do_clear = 1;
164                 /* FALL THRU */
165         case 3:         /* Read last kernel messages */
166                 // if (count > log_buf_len)
167                 //      count = log_buf_len;
168                 spin_lock_irq(&log->logbuf_lock);
169                 // if (count > logged_chars)
170                 //      count = logged_chars;
171                 // if (do_clear)
172                 //      logged_chars = 0;
173                 spin_unlock_irq(&log->logbuf_lock);
174                 if (error)
175                         break;
176                 return 0;
177
178         case 5:         /* Clear ring buffer */
179                 // logged_chars = 0;
180                 return 0;
181
182         case 6:         /* Disable logging to console */
183         case 7:         /* Enable logging to console */
184         case 8:         /* Set level of messages printed to console */
185                 break;
186
187         case 9:         /* Number of chars in the log buffer */
188                 return 0;
189         case 10:        /* Size of the log buffer */
190                 return 0;
191         default:
192                 error = -EINVAL;
193                 break;
194         }
195         return error;
196 }
197