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