2 * linux/kernel/vserver/limit.c
4 * Virtual Server: Context Limits
6 * Copyright (C) 2004-2006 Herbert Pƶtzl
8 * V0.01 broken out from vcontext V0.05
9 * V0.02 sync to valid limit check from 2.1.1
13 #include <linux/module.h>
14 #include <linux/vs_base.h>
15 #include <linux/vs_context.h>
16 #include <linux/vs_limit.h>
17 #include <linux/vserver/switch.h>
18 #include <linux/vserver/limit_cmd.h>
20 #include <asm/errno.h>
21 #include <asm/uaccess.h>
24 const char *vlimit_name[NUM_LIMITS] = {
27 [RLIMIT_NPROC] = "NPROC",
28 [RLIMIT_NOFILE] = "NOFILE",
29 [RLIMIT_MEMLOCK] = "VML",
31 [RLIMIT_LOCKS] = "LOCKS",
32 [RLIMIT_SIGPENDING] = "SIGP",
33 [RLIMIT_MSGQUEUE] = "MSGQ",
35 [VLIMIT_NSOCK] = "NSOCK",
36 [VLIMIT_OPENFD] = "OPENFD",
37 [VLIMIT_ANON] = "ANON",
38 [VLIMIT_SHMEM] = "SHMEM",
41 EXPORT_SYMBOL_GPL(vlimit_name);
44 #define MASK_ENTRY(x) (1 << (x))
46 const struct vcmd_ctx_rlimit_mask_v0 vlimit_mask = {
50 MASK_ENTRY( RLIMIT_RSS ) |
51 MASK_ENTRY( VLIMIT_ANON ) |
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 ) |
62 MASK_ENTRY( VLIMIT_NSOCK ) |
63 MASK_ENTRY( VLIMIT_OPENFD ) |
64 MASK_ENTRY( VLIMIT_ANON ) |
65 MASK_ENTRY( VLIMIT_SHMEM ) |
70 static int is_valid_vlimit(int id)
72 uint32_t mask = vlimit_mask.minimum |
73 vlimit_mask.softlimit | vlimit_mask.maximum;
74 return mask & (1 << id);
77 static inline uint64_t vc_get_rlim(struct vx_info *vxi, int id)
81 limit = vxi->limit.rlim[id];
82 if (limit == RLIM_INFINITY)
83 return CRLIM_INFINITY;
87 static int do_get_rlimit(xid_t xid, uint32_t id,
88 uint64_t *minimum, uint64_t *softlimit, uint64_t *maximum)
92 if (!is_valid_vlimit(id))
95 vxi = lookup_vx_info(xid);
100 *minimum = CRLIM_UNSET;
102 *softlimit = CRLIM_UNSET;
104 *maximum = vc_get_rlim(vxi, id);
109 int vc_get_rlimit(uint32_t id, void __user *data)
111 struct vcmd_ctx_rlimit_v0 vc_data;
114 if (copy_from_user (&vc_data, data, sizeof(vc_data)))
117 ret = do_get_rlimit(id, vc_data.id,
118 &vc_data.minimum, &vc_data.softlimit, &vc_data.maximum);
122 if (copy_to_user (data, &vc_data, sizeof(vc_data)))
127 static int do_set_rlimit(xid_t xid, uint32_t id,
128 uint64_t minimum, uint64_t softlimit, uint64_t maximum)
132 if (!is_valid_vlimit(id))
135 vxi = lookup_vx_info(xid);
139 if (maximum != CRLIM_KEEP)
140 vxi->limit.rlim[id] = maximum;
146 int vc_set_rlimit(uint32_t id, void __user *data)
148 struct vcmd_ctx_rlimit_v0 vc_data;
150 if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RESOURCE))
152 if (copy_from_user (&vc_data, data, sizeof(vc_data)))
155 return do_set_rlimit(id, vc_data.id,
156 vc_data.minimum, vc_data.softlimit, vc_data.maximum);
159 #ifdef CONFIG_IA32_EMULATION
161 int vc_set_rlimit_x32(uint32_t id, void __user *data)
163 struct vcmd_ctx_rlimit_v0_x32 vc_data;
165 if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RESOURCE))
167 if (copy_from_user (&vc_data, data, sizeof(vc_data)))
170 return do_set_rlimit(id, vc_data.id,
171 vc_data.minimum, vc_data.softlimit, vc_data.maximum);
174 int vc_get_rlimit_x32(uint32_t id, void __user *data)
176 struct vcmd_ctx_rlimit_v0_x32 vc_data;
179 if (copy_from_user (&vc_data, data, sizeof(vc_data)))
182 ret = do_get_rlimit(id, vc_data.id,
183 &vc_data.minimum, &vc_data.softlimit, &vc_data.maximum);
187 if (copy_to_user (data, &vc_data, sizeof(vc_data)))
192 #endif /* CONFIG_IA32_EMULATION */
195 int vc_get_rlimit_mask(uint32_t id, void __user *data)
197 if (copy_to_user(data, &vlimit_mask, sizeof(vlimit_mask)))
203 void vx_vsi_meminfo(struct sysinfo *val)
205 struct vx_info *vxi = current->vx_info;
208 v = vxi->limit.rlim[RLIMIT_RSS];
209 if (v != RLIM_INFINITY)
210 val->totalram = min(val->totalram, v);
211 v = atomic_read(&vxi->limit.rcur[RLIMIT_RSS]);
212 val->freeram = (v < val->totalram) ? val->totalram - v : 0;
219 void vx_vsi_swapinfo(struct sysinfo *val)
221 struct vx_info *vxi = current->vx_info;
224 v = vxi->limit.rlim[RLIMIT_RSS];
225 w = vxi->limit.rlim[RLIMIT_AS];
226 if (w != RLIM_INFINITY)
227 val->totalswap = min(val->totalswap, w -
228 ((v != RLIM_INFINITY) ? v : 0));
229 w = atomic_read(&vxi->limit.rcur[RLIMIT_AS]);
230 val->freeswap = (w < val->totalswap) ? val->totalswap - w : 0;