VServer 1.9.2 (patch-2.6.8.1-vs1.9.2.diff)
[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  Herbert Pƶtzl
7  *
8  *  V0.01  broken out from vcontext V0.05
9  *
10  */
11
12 #include <linux/config.h>
13 #include <linux/vserver/limit.h>
14 #include <linux/vserver/context.h>
15 #include <linux/vserver/switch.h>
16 #include <linux/vs_base.h>
17 #include <linux/vs_context.h>
18 #include <linux/vs_limit.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_MSGQUEUE]       = "MSGQ",
33         [VLIMIT_NSOCK]          = "NSOCK",
34 };
35
36
37 static int is_valid_rlimit(int id)
38 {
39         int valid = 0;
40
41         switch (id) {
42                 case RLIMIT_NPROC:
43                 case RLIMIT_AS:
44                 case RLIMIT_RSS:
45                 case RLIMIT_MEMLOCK:
46                 case RLIMIT_NOFILE:
47                         valid = 1;
48                         break;
49         }
50         return valid;
51 }
52
53 static inline uint64_t vc_get_rlim(struct vx_info *vxi, int id)
54 {
55         unsigned long limit;
56
57         limit = vxi->limit.rlim[id];
58         if (limit == RLIM_INFINITY)
59                 return CRLIM_INFINITY;
60         return limit;   
61 }
62
63 int vc_get_rlimit(uint32_t id, void __user *data)
64 {
65         struct vx_info *vxi;
66         struct vcmd_ctx_rlimit_v0 vc_data;
67
68         if (copy_from_user (&vc_data, data, sizeof(vc_data)))
69                 return -EFAULT;
70         if (!is_valid_rlimit(vc_data.id))
71                 return -ENOTSUPP;
72                 
73         vxi = locate_vx_info(id);
74         if (!vxi)
75                 return -ESRCH;
76
77         vc_data.maximum = vc_get_rlim(vxi, vc_data.id);
78         vc_data.minimum = CRLIM_UNSET;
79         vc_data.softlimit = CRLIM_UNSET;
80         put_vx_info(vxi);
81
82         if (copy_to_user (data, &vc_data, sizeof(vc_data)))
83                 return -EFAULT;
84         return 0;
85 }
86
87 int vc_set_rlimit(uint32_t id, void __user *data)
88 {
89         struct vx_info *vxi;
90         struct vcmd_ctx_rlimit_v0 vc_data;
91
92         if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RESOURCE))
93                 return -EPERM;
94         if (copy_from_user (&vc_data, data, sizeof(vc_data)))
95                 return -EFAULT;
96         if (!is_valid_rlimit(vc_data.id))
97                 return -ENOTSUPP;
98
99         vxi = locate_vx_info(id);
100         if (!vxi)
101                 return -ESRCH;
102
103         if (vc_data.maximum != CRLIM_KEEP)
104                 vxi->limit.rlim[vc_data.id] = vc_data.maximum;
105         printk("setting [%d] = %d\n", vc_data.id, (int)vc_data.maximum);
106         put_vx_info(vxi);
107
108         return 0;
109 }
110
111 int vc_get_rlimit_mask(uint32_t id, void __user *data)
112 {
113         static struct vcmd_ctx_rlimit_mask_v0 mask = {
114                         /* minimum */
115                 0
116                 ,       /* softlimit */
117                 0
118                 ,       /* maximum */
119                 (1 << RLIMIT_NPROC) |
120                 (1 << RLIMIT_NOFILE) |
121                 (1 << RLIMIT_MEMLOCK) |
122                 (1 << RLIMIT_AS) |
123                 (1 << RLIMIT_RSS)
124                 };
125
126         if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RESOURCE))
127                 return -EPERM;
128         if (copy_to_user(data, &mask, sizeof(mask)))
129                 return -EFAULT;
130         return 0;
131 }
132
133
134 void vx_vsi_meminfo(struct sysinfo *val)
135 {
136         struct vx_info *vxi = current->vx_info;
137         unsigned long v;
138
139         v = vxi->limit.rlim[RLIMIT_RSS];
140         if (v != RLIM_INFINITY)
141                 val->totalram = min(val->totalram, v);
142         v = atomic_read(&vxi->limit.rcur[RLIMIT_RSS]);
143         val->freeram = (v < val->totalram) ? val->totalram - v : 0;
144         val->bufferram = 0;
145         val->totalhigh = 0;
146         val->freehigh = 0;
147         return;
148 }
149
150 void vx_vsi_swapinfo(struct sysinfo *val)
151 {
152         struct vx_info *vxi = current->vx_info;
153         unsigned long w,v;
154
155         v = vxi->limit.rlim[RLIMIT_RSS];
156         w = vxi->limit.rlim[RLIMIT_AS];
157         if (w != RLIM_INFINITY)
158                 val->totalswap = min(val->totalswap, w -
159                 ((v != RLIM_INFINITY) ? v : 0));
160         w = atomic_read(&vxi->limit.rcur[RLIMIT_AS]);
161         val->freeswap = (w < val->totalswap) ? val->totalswap - w : 0;
162         return;
163 }
164