fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / kernel / vserver / limit.c
1 /*
2  *  linux/kernel/vserver/limit.c
3  *
4  *  Virtual Server: Context Limits
5  *
6  *  Copyright (C) 2004-2007  Herbert Pƶtzl
7  *
8  *  V0.01  broken out from vcontext V0.05
9  *  V0.02  changed vcmds to vxi arg
10  *
11  */
12
13 #include <linux/module.h>
14 #include <linux/vs_context.h>
15 #include <linux/vs_limit.h>
16 #include <linux/vserver/limit.h>
17 #include <linux/vserver/switch.h>
18 #include <linux/vserver/limit_cmd.h>
19
20 #include <asm/errno.h>
21 #include <asm/uaccess.h>
22
23
24 const char *vlimit_name[NUM_LIMITS] = {
25         [RLIMIT_CPU]            = "CPU",
26         [RLIMIT_RSS]            = "RSS",
27         [RLIMIT_NPROC]          = "NPROC",
28         [RLIMIT_NOFILE]         = "NOFILE",
29         [RLIMIT_MEMLOCK]        = "VML",
30         [RLIMIT_AS]             = "VM",
31         [RLIMIT_LOCKS]          = "LOCKS",
32         [RLIMIT_SIGPENDING]     = "SIGP",
33         [RLIMIT_MSGQUEUE]       = "MSGQ",
34
35         [VLIMIT_NSOCK]          = "NSOCK",
36         [VLIMIT_OPENFD]         = "OPENFD",
37         [VLIMIT_ANON]           = "ANON",
38         [VLIMIT_SHMEM]          = "SHMEM",
39         [VLIMIT_DENTRY]         = "DENTRY",
40 };
41
42 EXPORT_SYMBOL_GPL(vlimit_name);
43
44 #define MASK_ENTRY(x)   (1 << (x))
45
46 const struct vcmd_ctx_rlimit_mask_v0 vlimit_mask = {
47                 /* minimum */
48         0
49         ,       /* softlimit */
50         MASK_ENTRY( RLIMIT_RSS          ) |
51         MASK_ENTRY( VLIMIT_ANON         ) |
52         0
53         ,       /* maximum */
54         MASK_ENTRY( RLIMIT_RSS          ) |
55         MASK_ENTRY( RLIMIT_NPROC        ) |
56         MASK_ENTRY( RLIMIT_NOFILE       ) |
57         MASK_ENTRY( RLIMIT_MEMLOCK      ) |
58         MASK_ENTRY( RLIMIT_AS           ) |
59         MASK_ENTRY( RLIMIT_LOCKS        ) |
60         MASK_ENTRY( RLIMIT_MSGQUEUE     ) |
61
62         MASK_ENTRY( VLIMIT_NSOCK        ) |
63         MASK_ENTRY( VLIMIT_OPENFD       ) |
64         MASK_ENTRY( VLIMIT_ANON         ) |
65         MASK_ENTRY( VLIMIT_SHMEM        ) |
66         MASK_ENTRY( VLIMIT_DENTRY       ) |
67         0
68 };
69                 /* accounting only */
70 uint32_t account_mask =
71         MASK_ENTRY( VLIMIT_SEMARY       ) |
72         MASK_ENTRY( VLIMIT_NSEMS        ) |
73         MASK_ENTRY( VLIMIT_MAPPED       ) |
74         0;
75
76
77 static int is_valid_vlimit(int id)
78 {
79         uint32_t mask = vlimit_mask.minimum |
80                 vlimit_mask.softlimit | vlimit_mask.maximum;
81         return mask & (1 << id);
82 }
83
84 static int is_accounted_vlimit(int id)
85 {
86         if (is_valid_vlimit(id))
87                 return 1;
88         return account_mask & (1 << id);
89 }
90
91
92 static inline uint64_t vc_get_soft(struct vx_info *vxi, int id)
93 {
94         rlim_t limit = __rlim_soft(&vxi->limit, id);
95         return VX_VLIM(limit);
96 }
97
98 static inline uint64_t vc_get_hard(struct vx_info *vxi, int id)
99 {
100         rlim_t limit = __rlim_hard(&vxi->limit, id);
101         return VX_VLIM(limit);
102 }
103
104 static int do_get_rlimit(struct vx_info *vxi, uint32_t id,
105         uint64_t *minimum, uint64_t *softlimit, uint64_t *maximum)
106 {
107         if (!is_valid_vlimit(id))
108                 return -EINVAL;
109
110         if (minimum)
111                 *minimum = CRLIM_UNSET;
112         if (softlimit)
113                 *softlimit = vc_get_soft(vxi, id);
114         if (maximum)
115                 *maximum = vc_get_hard(vxi, id);
116         return 0;
117 }
118
119 int vc_get_rlimit(struct vx_info *vxi, void __user *data)
120 {
121         struct vcmd_ctx_rlimit_v0 vc_data;
122         int ret;
123
124         if (copy_from_user (&vc_data, data, sizeof(vc_data)))
125                 return -EFAULT;
126
127         ret = do_get_rlimit(vxi, vc_data.id,
128                 &vc_data.minimum, &vc_data.softlimit, &vc_data.maximum);
129         if (ret)
130                 return ret;
131
132         if (copy_to_user (data, &vc_data, sizeof(vc_data)))
133                 return -EFAULT;
134         return 0;
135 }
136
137 static int do_set_rlimit(struct vx_info *vxi, uint32_t id,
138         uint64_t minimum, uint64_t softlimit, uint64_t maximum)
139 {
140         if (!is_valid_vlimit(id))
141                 return -EINVAL;
142
143         if (maximum != CRLIM_KEEP)
144                 __rlim_hard(&vxi->limit, id) = VX_RLIM(maximum);
145         if (softlimit != CRLIM_KEEP)
146                 __rlim_soft(&vxi->limit, id) = VX_RLIM(softlimit);
147
148         /* clamp soft limit */
149         if (__rlim_soft(&vxi->limit, id) > __rlim_hard(&vxi->limit, id))
150                 __rlim_soft(&vxi->limit, id) = __rlim_hard(&vxi->limit, id);
151
152         return 0;
153 }
154
155 int vc_set_rlimit(struct vx_info *vxi, void __user *data)
156 {
157         struct vcmd_ctx_rlimit_v0 vc_data;
158
159         if (copy_from_user (&vc_data, data, sizeof(vc_data)))
160                 return -EFAULT;
161
162         return do_set_rlimit(vxi, vc_data.id,
163                 vc_data.minimum, vc_data.softlimit, vc_data.maximum);
164 }
165
166 #ifdef  CONFIG_IA32_EMULATION
167
168 int vc_set_rlimit_x32(struct vx_info *vxi, void __user *data)
169 {
170         struct vcmd_ctx_rlimit_v0_x32 vc_data;
171
172         if (copy_from_user (&vc_data, data, sizeof(vc_data)))
173                 return -EFAULT;
174
175         return do_set_rlimit(vxi, vc_data.id,
176                 vc_data.minimum, vc_data.softlimit, vc_data.maximum);
177 }
178
179 int vc_get_rlimit_x32(struct vx_info *vxi, void __user *data)
180 {
181         struct vcmd_ctx_rlimit_v0_x32 vc_data;
182         int ret;
183
184         if (copy_from_user (&vc_data, data, sizeof(vc_data)))
185                 return -EFAULT;
186
187         ret = do_get_rlimit(vxi, vc_data.id,
188                 &vc_data.minimum, &vc_data.softlimit, &vc_data.maximum);
189         if (ret)
190                 return ret;
191
192         if (copy_to_user (data, &vc_data, sizeof(vc_data)))
193                 return -EFAULT;
194         return 0;
195 }
196
197 #endif  /* CONFIG_IA32_EMULATION */
198
199
200 int vc_get_rlimit_mask(uint32_t id, void __user *data)
201 {
202         if (copy_to_user(data, &vlimit_mask, sizeof(vlimit_mask)))
203                 return -EFAULT;
204         return 0;
205 }
206
207
208 static inline void vx_reset_minmax(struct _vx_limit *limit)
209 {
210         rlim_t value;
211         int lim;
212
213         for (lim=0; lim<NUM_LIMITS; lim++) {
214                 value = __rlim_get(limit, lim);
215                 __rlim_rmax(limit, lim) = value;
216                 __rlim_rmin(limit, lim) = value;
217         }
218 }
219
220
221 int vc_reset_minmax(struct vx_info *vxi, void __user *data)
222 {
223         vx_reset_minmax(&vxi->limit);
224         return 0;
225 }
226
227
228 int vc_rlimit_stat(struct vx_info *vxi, void __user *data)
229 {
230         struct vcmd_rlimit_stat_v0 vc_data;
231         struct _vx_limit *limit = &vxi->limit;
232         int id;
233
234         if (copy_from_user (&vc_data, data, sizeof(vc_data)))
235                 return -EFAULT;
236
237         id = vc_data.id;
238         if (!is_accounted_vlimit(id))
239                 return -EINVAL;
240
241         vx_limit_fixup(limit, id);
242         vc_data.hits = atomic_read(&__rlim_lhit(limit, id));
243         vc_data.value = __rlim_get(limit, id);
244         vc_data.minimum = __rlim_rmin(limit, id);
245         vc_data.maximum = __rlim_rmax(limit, id);
246
247         if (copy_to_user (data, &vc_data, sizeof(vc_data)))
248                 return -EFAULT;
249         return 0;
250 }
251
252
253 void vx_vsi_meminfo(struct sysinfo *val)
254 {
255         struct vx_info *vxi = current->vx_info;
256         unsigned long totalram, freeram;
257         rlim_t v;
258
259         /* we blindly accept the max */
260         v = __rlim_soft(&vxi->limit, RLIMIT_RSS);
261         totalram = (v != RLIM_INFINITY) ? v : val->totalram;
262
263         /* total minus used equals free */
264         v = __vx_cres_array_fixup(&vxi->limit, VLA_RSS);
265         freeram = (v < totalram) ? totalram - v : 0;
266
267         val->totalram = totalram;
268         val->freeram = freeram;
269         val->bufferram = 0;
270         val->totalhigh = 0;
271         val->freehigh = 0;
272         return;
273 }
274
275 void vx_vsi_swapinfo(struct sysinfo *val)
276 {
277         struct vx_info *vxi = current->vx_info;
278         unsigned long totalswap, freeswap;
279         rlim_t v, w;
280
281         v = __rlim_soft(&vxi->limit, RLIMIT_RSS);
282         if (v == RLIM_INFINITY) {
283                 val->freeswap = val->totalswap;
284                 return;
285         }
286
287         /* we blindly accept the max */
288         w = __rlim_hard(&vxi->limit, RLIMIT_RSS);
289         totalswap = (w != RLIM_INFINITY) ? (w - v) : val->totalswap;
290
291         /* currently 'used' swap */
292         w = __vx_cres_array_fixup(&vxi->limit, VLA_RSS);
293         w -= (w > v) ? v : w;
294
295         /* total minus used equals free */
296         freeswap = (w < totalswap) ? totalswap - w : 0;
297
298         val->totalswap = totalswap;
299         val->freeswap = freeswap;
300         return;
301 }
302
303
304 unsigned long vx_badness(struct task_struct *task, struct mm_struct *mm)
305 {
306         struct vx_info *vxi = mm->mm_vx_info;
307         unsigned long points;
308         rlim_t v, w;
309
310         if (!vxi)
311                 return 0;
312
313         v = __vx_cres_array_fixup(&vxi->limit, VLA_RSS);
314         w = __rlim_soft(&vxi->limit, RLIMIT_RSS);
315         points = (v > w) ? (v - w) : 0;
316
317         return points;
318 }
319