diff -NurpP --minimal linux-2.6.16-vs2.0.2-rc14.1/include/linux/vserver/limit_cmd.h linux-2.6.16-vs2.0.2-rc14.2/include/linux/vserver/limit_cmd.h --- linux-2.6.16-vs2.0.2-rc14.1/include/linux/vserver/limit_cmd.h 2006-03-20 17:34:50 +0100 +++ linux-2.6.16-vs2.0.2-rc14.2/include/linux/vserver/limit_cmd.h 2006-04-03 02:37:59 +0200 @@ -27,11 +27,29 @@ struct vcmd_ctx_rlimit_mask_v0 { #ifdef __KERNEL__ +#ifdef CONFIG_IA32_EMULATION + +struct vcmd_ctx_rlimit_v0_x32 { + uint32_t id; + uint64_t minimum; + uint64_t softlimit; + uint64_t maximum; +} __attribute__ ((aligned (4))); + +#endif /* CONFIG_IA32_EMULATION */ + #include extern int vc_get_rlimit(uint32_t, void __user *); extern int vc_set_rlimit(uint32_t, void __user *); extern int vc_get_rlimit_mask(uint32_t, void __user *); +#ifdef CONFIG_IA32_EMULATION + +extern int vc_get_rlimit_x32(uint32_t, void __user *); +extern int vc_set_rlimit_x32(uint32_t, void __user *); + +#endif /* CONFIG_IA32_EMULATION */ + #endif /* __KERNEL__ */ #endif /* _VX_LIMIT_CMD_H */ diff -NurpP --minimal linux-2.6.16-vs2.0.2-rc14.1/kernel/vserver/limit.c linux-2.6.16-vs2.0.2-rc14.2/kernel/vserver/limit.c --- linux-2.6.16-vs2.0.2-rc14.1/kernel/vserver/limit.c 2006-03-20 17:34:50 +0100 +++ linux-2.6.16-vs2.0.2-rc14.2/kernel/vserver/limit.c 2006-04-03 01:43:40 +0200 @@ -71,53 +71,114 @@ static inline uint64_t vc_get_rlim(struc return limit; } -int vc_get_rlimit(uint32_t id, void __user *data) +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)) + if (!is_valid_rlimit(id)) return -EINVAL; - vxi = lookup_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) +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_rlimit(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 -EINVAL; - vxi = lookup_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 = { diff -NurpP --minimal linux-2.6.16-vs2.0.2-rc14.1/kernel/vserver/switch.c linux-2.6.16-vs2.0.2-rc14.2/kernel/vserver/switch.c --- linux-2.6.16-vs2.0.2-rc14.1/kernel/vserver/switch.c 2006-03-24 16:50:48 +0100 +++ linux-2.6.16-vs2.0.2-rc14.2/kernel/vserver/switch.c 2006-04-03 02:38:01 +0200 @@ -130,10 +130,17 @@ long do_vserver(uint32_t cmd, uint32_t i #endif switch (cmd) { +#ifdef CONFIG_IA32_EMULATION + case VCMD_get_rlimit: + return __COMPAT(vc_get_rlimit, id, data, compat); + case VCMD_set_rlimit: + return __COMPAT(vc_set_rlimit, id, data, compat); +#else case VCMD_get_rlimit: return vc_get_rlimit(id, data); case VCMD_set_rlimit: return vc_set_rlimit(id, data); +#endif case VCMD_get_rlimit_mask: return vc_get_rlimit_mask(id, data);