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