This commit was manufactured by cvs2svn to create branch 'vserver'.
[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/vinline.h>
17
18 #include <asm/errno.h>
19 #include <asm/uaccess.h>
20
21
22 static int is_valid_rlimit(int id)
23 {
24         int valid = 0;
25
26         switch (id) {
27                 case RLIMIT_NPROC:
28                 case RLIMIT_AS:
29                 case RLIMIT_RSS:
30                 case RLIMIT_MEMLOCK:
31                 case RLIMIT_NOFILE:
32                         valid = 1;
33                         break;
34         }
35         return valid;
36 }
37
38 static inline uint64_t vc_get_rlim(struct vx_info *vxi, int id)
39 {
40         unsigned long limit;
41
42         limit = vxi->limit.rlim[id];
43         if (limit == RLIM_INFINITY)
44                 return CRLIM_INFINITY;
45         return limit;   
46 }
47
48 int vc_get_rlimit(uint32_t id, void __user *data)
49 {
50         struct vx_info *vxi;
51         struct vcmd_ctx_rlimit_v0 vc_data;
52
53         if (copy_from_user (&vc_data, data, sizeof(vc_data)))
54                 return -EFAULT;
55         if (!is_valid_rlimit(vc_data.id))
56                 return -ENOTSUPP;
57                 
58         vxi = find_vx_info(id);
59         if (!vxi)
60                 return -ESRCH;
61
62         vc_data.maximum = vc_get_rlim(vxi, vc_data.id);
63         vc_data.minimum = CRLIM_UNSET;
64         vc_data.softlimit = CRLIM_UNSET;
65         put_vx_info(vxi);
66
67         if (copy_to_user (data, &vc_data, sizeof(vc_data)))
68                 return -EFAULT;
69         return 0;
70 }
71
72 int vc_set_rlimit(uint32_t id, void __user *data)
73 {
74         struct vx_info *vxi;
75         struct vcmd_ctx_rlimit_v0 vc_data;
76
77         if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RESOURCE))
78                 return -EPERM;
79         if (copy_from_user (&vc_data, data, sizeof(vc_data)))
80                 return -EFAULT;
81         if (!is_valid_rlimit(vc_data.id))
82                 return -ENOTSUPP;
83
84         vxi = find_vx_info(id);
85         if (!vxi)
86                 return -ESRCH;
87
88         if (vc_data.maximum != CRLIM_KEEP)
89                 vxi->limit.rlim[vc_data.id] = vc_data.maximum;
90         printk("setting [%d] = %d\n", vc_data.id, (int)vc_data.maximum);
91         put_vx_info(vxi);
92
93         return 0;
94 }
95
96 int vc_get_rlimit_mask(uint32_t id, void __user *data)
97 {
98         static struct vcmd_ctx_rlimit_mask_v0 mask = {
99                         /* minimum */
100                 0
101                 ,       /* softlimit */
102                 0
103                 ,       /* maximum */
104                 (1 << RLIMIT_NPROC) |
105                 (1 << RLIMIT_NOFILE) |
106                 (1 << RLIMIT_MEMLOCK) |
107                 (1 << RLIMIT_AS) |
108                 (1 << RLIMIT_RSS)
109                 };
110
111         if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RESOURCE))
112                 return -EPERM;
113         if (copy_to_user(data, &mask, sizeof(mask)))
114                 return -EFAULT;
115         return 0;
116 }
117
118
119 void vx_vsi_meminfo(struct sysinfo *val)
120 {
121         struct vx_info *vxi = current->vx_info;
122         unsigned long v;
123
124         v = vxi->limit.rlim[RLIMIT_RSS];
125         if (v != RLIM_INFINITY)
126                 val->totalram = min(val->totalram, v);
127         v = atomic_read(&vxi->limit.res[RLIMIT_RSS]);
128         val->freeram = (v < val->totalram) ? val->totalram - v : 0;
129         val->bufferram = 0;
130         val->totalhigh = 0;
131         val->freehigh = 0;
132         return;
133 }
134
135 void vx_vsi_swapinfo(struct sysinfo *val)
136 {
137         struct vx_info *vxi = current->vx_info;
138         unsigned long w,v;
139
140         v = vxi->limit.rlim[RLIMIT_RSS];
141         w = vxi->limit.rlim[RLIMIT_AS];
142         if (w != RLIM_INFINITY)
143                 val->totalswap = min(val->totalswap, w -
144                 ((v != RLIM_INFINITY) ? v : 0));
145         w = atomic_read(&vxi->limit.res[RLIMIT_AS]);
146         val->freeswap = (w < val->totalswap) ? val->totalswap - w : 0;
147         return;
148 }
149