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