Merge to Fedora kernel-2.6.18-1.2255_FC5 patched with stable patch-2.6.18.5-vs2.0...
[linux-2.6.git] / kernel / vserver / limit.c
index 0527afc..e2b15d3 100644 (file)
@@ -3,13 +3,13 @@
  *
  *  Virtual Server: Context Limits
  *
- *  Copyright (C) 2004-2005  Herbert Pötzl
+ *  Copyright (C) 2004-2006  Herbert Pötzl
  *
  *  V0.01  broken out from vcontext V0.05
+ *  V0.02  sync to valid limit check from 2.1.1
  *
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/vs_context.h>
 #include <linux/vs_limit.h>
@@ -41,25 +41,33 @@ const char *vlimit_name[NUM_LIMITS] = {
 EXPORT_SYMBOL_GPL(vlimit_name);
 
 
-static int is_valid_rlimit(int id)
+#define MASK_ENTRY(x)  (1 << (x))
+
+const struct vcmd_ctx_rlimit_mask_v0 vlimit_mask = {
+               /* minimum */
+       0
+       ,       /* softlimit */
+       0
+       ,       /* maximum */
+       MASK_ENTRY( RLIMIT_RSS          ) |
+       MASK_ENTRY( RLIMIT_NPROC        ) |
+       MASK_ENTRY( RLIMIT_NOFILE       ) |
+       MASK_ENTRY( RLIMIT_MEMLOCK      ) |
+       MASK_ENTRY( RLIMIT_AS           ) |
+       MASK_ENTRY( RLIMIT_LOCKS        ) |
+       MASK_ENTRY( RLIMIT_MSGQUEUE     ) |
+
+       MASK_ENTRY( VLIMIT_ANON         ) |
+       MASK_ENTRY( VLIMIT_SHMEM        ) |
+       0
+};
+
+
+static int is_valid_vlimit(int id)
 {
-       int valid = 0;
-
-       switch (id) {
-               case RLIMIT_RSS:
-               case RLIMIT_NPROC:
-               case RLIMIT_NOFILE:
-               case RLIMIT_MEMLOCK:
-               case RLIMIT_AS:
-
-               case VLIMIT_NSOCK:
-               case VLIMIT_OPENFD:
-               case VLIMIT_ANON:
-               case VLIMIT_SHMEM:
-                       valid = 1;
-                       break;
-       }
-       return valid;
+       uint32_t mask = vlimit_mask.minimum |
+               vlimit_mask.softlimit | vlimit_mask.maximum;
+       return mask & (1 << id);
 }
 
 static inline uint64_t vc_get_rlim(struct vx_info *vxi, int id)
@@ -72,74 +80,117 @@ static inline uint64_t vc_get_rlim(struct vx_info *vxi, int id)
        return limit;
 }
 
-int vc_get_rlimit(uint32_t id, void __user *data)
+static int do_get_rlimit(xid_t xid, uint32_t id,
+       uint64_t *minimum, uint64_t *softlimit, uint64_t *maximum)
 {
        struct vx_info *vxi;
-       struct vcmd_ctx_rlimit_v0 vc_data;
 
-       if (copy_from_user (&vc_data, data, sizeof(vc_data)))
-               return -EFAULT;
-       if (!is_valid_rlimit(vc_data.id))
-               return -ENOTSUPP;
+       if (!is_valid_vlimit(id))
+               return -EINVAL;
 
-       vxi = locate_vx_info(id);
+       vxi = lookup_vx_info(xid);
        if (!vxi)
                return -ESRCH;
 
-       vc_data.maximum = vc_get_rlim(vxi, vc_data.id);
-       vc_data.minimum = CRLIM_UNSET;
-       vc_data.softlimit = CRLIM_UNSET;
+       if (minimum)
+               *minimum = CRLIM_UNSET;
+       if (softlimit)
+               *softlimit = CRLIM_UNSET;
+       if (maximum)
+               *maximum = vc_get_rlim(vxi, id);
        put_vx_info(vxi);
+       return 0;
+}
+
+int vc_get_rlimit(uint32_t id, void __user *data)
+{
+       struct vcmd_ctx_rlimit_v0 vc_data;
+       int ret;
+
+       if (copy_from_user (&vc_data, data, sizeof(vc_data)))
+               return -EFAULT;
+
+       ret = do_get_rlimit(id, vc_data.id,
+               &vc_data.minimum, &vc_data.softlimit, &vc_data.maximum);
+       if (ret)
+               return ret;
 
        if (copy_to_user (data, &vc_data, sizeof(vc_data)))
                return -EFAULT;
        return 0;
 }
 
-int vc_set_rlimit(uint32_t id, void __user *data)
+static int do_set_rlimit(xid_t xid, uint32_t id,
+       uint64_t minimum, uint64_t softlimit, uint64_t maximum)
 {
        struct vx_info *vxi;
+
+       if (!is_valid_vlimit(id))
+               return -EINVAL;
+
+       vxi = lookup_vx_info(xid);
+       if (!vxi)
+               return -ESRCH;
+
+       if (maximum != CRLIM_KEEP)
+               vxi->limit.rlim[id] = maximum;
+
+       put_vx_info(vxi);
+       return 0;
+}
+
+int vc_set_rlimit(uint32_t id, void __user *data)
+{
        struct vcmd_ctx_rlimit_v0 vc_data;
 
        if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RESOURCE))
                return -EPERM;
        if (copy_from_user (&vc_data, data, sizeof(vc_data)))
                return -EFAULT;
-       if (!is_valid_rlimit(vc_data.id))
-               return -ENOTSUPP;
 
-       vxi = locate_vx_info(id);
-       if (!vxi)
-               return -ESRCH;
+       return do_set_rlimit(id, vc_data.id,
+               vc_data.minimum, vc_data.softlimit, vc_data.maximum);
+}
 
-       if (vc_data.maximum != CRLIM_KEEP)
-               vxi->limit.rlim[vc_data.id] = vc_data.maximum;
-       put_vx_info(vxi);
+#ifdef CONFIG_IA32_EMULATION
+
+int vc_set_rlimit_x32(uint32_t id, void __user *data)
+{
+       struct vcmd_ctx_rlimit_v0_x32 vc_data;
+
+       if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RESOURCE))
+               return -EPERM;
+       if (copy_from_user (&vc_data, data, sizeof(vc_data)))
+               return -EFAULT;
+
+       return do_set_rlimit(id, vc_data.id,
+               vc_data.minimum, vc_data.softlimit, vc_data.maximum);
+}
+
+int vc_get_rlimit_x32(uint32_t id, void __user *data)
+{
+       struct vcmd_ctx_rlimit_v0_x32 vc_data;
+       int ret;
+
+       if (copy_from_user (&vc_data, data, sizeof(vc_data)))
+               return -EFAULT;
+
+       ret = do_get_rlimit(id, vc_data.id,
+               &vc_data.minimum, &vc_data.softlimit, &vc_data.maximum);
+       if (ret)
+               return ret;
 
+       if (copy_to_user (data, &vc_data, sizeof(vc_data)))
+               return -EFAULT;
        return 0;
 }
 
+#endif /* CONFIG_IA32_EMULATION */
+
+
 int vc_get_rlimit_mask(uint32_t id, void __user *data)
 {
-       static struct vcmd_ctx_rlimit_mask_v0 mask = {
-                       /* minimum */
-               0
-               ,       /* softlimit */
-               0
-               ,       /* maximum */
-               (1 << RLIMIT_RSS) |
-               (1 << RLIMIT_NPROC) |
-               (1 << RLIMIT_NOFILE) |
-               (1 << RLIMIT_MEMLOCK) |
-               (1 << RLIMIT_LOCKS) |
-               (1 << RLIMIT_AS) |
-               (1 << VLIMIT_ANON) |
-               0
-               };
-
-       if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RESOURCE))
-               return -EPERM;
-       if (copy_to_user(data, &mask, sizeof(mask)))
+       if (copy_to_user(data, &vlimit_mask, sizeof(vlimit_mask)))
                return -EFAULT;
        return 0;
 }