diff -NurpP --minimal linux-2.6.19.1-vs2.2.0-rc6.1/include/linux/vserver/sched_cmd.h linux-2.6.19.1-vs2.2.0-rc6.2/include/linux/vserver/sched_cmd.h --- linux-2.6.19.1-vs2.2.0-rc6.1/include/linux/vserver/sched_cmd.h 2006-11-08 04:57:49 +0100 +++ linux-2.6.19.1-vs2.2.0-rc6.2/include/linux/vserver/sched_cmd.h 2007-01-10 05:30:43 +0100 @@ -6,7 +6,7 @@ #define VCMD_set_sched_v2 VC_CMD(SCHED, 1, 2) #define VCMD_set_sched_v3 VC_CMD(SCHED, 1, 3) -#define VCMD_set_sched VC_CMD(SCHED, 1, 4) +#define VCMD_set_sched_v4 VC_CMD(SCHED, 1, 4) struct vcmd_set_sched_v2 { int32_t fill_rate; @@ -39,6 +39,20 @@ struct vcmd_set_sched_v4 { int32_t bucket_id; }; +#define VCMD_set_sched VC_CMD(SCHED, 1, 5) +#define VCMD_get_sched VC_CMD(SCHED, 2, 5) + +struct vcmd_sched_v5 { + uint32_t mask; + int32_t cpu_id; + int32_t bucket_id; + int32_t fill_rate[2]; + int32_t interval[2]; + int32_t tokens; + int32_t tokens_min; + int32_t tokens_max; + int32_t prio_bias; +}; #define VXSM_FILL_RATE 0x0001 #define VXSM_INTERVAL 0x0002 @@ -58,6 +72,8 @@ struct vcmd_set_sched_v4 { #define VXSM_CPU_ID 0x1000 #define VXSM_BUCKET_ID 0x2000 +#define VXSM_MSEC 0x4000 + #define SCHED_KEEP (-2) /* only for v2 */ #ifdef __KERNEL__ @@ -66,7 +82,27 @@ struct vcmd_set_sched_v4 { extern int vc_set_sched_v2(struct vx_info *, void __user *); extern int vc_set_sched_v3(struct vx_info *, void __user *); +extern int vc_set_sched_v4(struct vx_info *, void __user *); extern int vc_set_sched(struct vx_info *, void __user *); +extern int vc_get_sched(struct vx_info *, void __user *); + +#endif /* __KERNEL__ */ + +#define VCMD_sched_info VC_CMD(SCHED, 3, 0) + +struct vcmd_sched_info { + int32_t cpu_id; + int32_t bucket_id; + uint64_t user_msec; + uint64_t sys_msec; + uint64_t hold_msec; + uint32_t token_usec; + int32_t vavavoom; +}; + +#ifdef __KERNEL__ + +extern int vc_sched_info(struct vx_info *, void __user *); #endif /* __KERNEL__ */ #endif /* _VX_SCHED_CMD_H */ diff -NurpP --minimal linux-2.6.19.1-vs2.2.0-rc6.1/kernel/vserver/Kconfig linux-2.6.19.1-vs2.2.0-rc6.2/kernel/vserver/Kconfig --- linux-2.6.19.1-vs2.2.0-rc6.1/kernel/vserver/Kconfig 2006-12-19 18:42:14 +0100 +++ linux-2.6.19.1-vs2.2.0-rc6.2/kernel/vserver/Kconfig 2006-12-22 00:15:09 +0100 @@ -230,7 +230,7 @@ config VSERVER_MONITOR for detailed analysis. config VSERVER_MONITOR_SIZE - intxi "Per-CPU Monitor Queue Size (32-65536)" + int "Per-CPU Monitor Queue Size (32-65536)" depends on VSERVER_MONITOR range 32 65536 default 1024 diff -NurpP --minimal linux-2.6.19.1-vs2.2.0-rc6.1/kernel/vserver/sched.c linux-2.6.19.1-vs2.2.0-rc6.2/kernel/vserver/sched.c --- linux-2.6.19.1-vs2.2.0-rc6.1/kernel/vserver/sched.c 2007-01-10 13:36:37 +0100 +++ linux-2.6.19.1-vs2.2.0-rc6.2/kernel/vserver/sched.c 2007-01-10 05:27:14 +0100 @@ -194,21 +194,33 @@ on_hold: #endif /* CONFIG_VSERVER_HARDCPU */ } +static inline unsigned long msec_to_ticks(unsigned long msec) +{ + return msecs_to_jiffies(msec); +} -static int do_set_sched(struct vx_info *vxi, struct vcmd_set_sched_v4 *data) +static inline unsigned long ticks_to_msec(unsigned long ticks) { - unsigned int set_mask = data->set_mask; + return jiffies_to_msecs(ticks); +} + +static inline unsigned long ticks_to_usec(unsigned long ticks) +{ + return jiffies_to_usecs(ticks); +} + + +static int do_set_sched(struct vx_info *vxi, struct vcmd_sched_v5 *data) +{ + unsigned int set_mask = data->mask; unsigned int update_mask; + int i; /* Sanity check data values */ - if (data->fill_rate < 0) - data->fill_rate = 1; - if (data->interval <= 0) - data->interval = HZ; if (data->tokens_max <= 0) data->tokens_max = HZ; if (data->tokens_min < 0) - data->tokens_min = data->fill_rate*3; + data->tokens_min = HZ/3; if (data->tokens_min >= data->tokens_max) data->tokens_min = data->tokens_max; @@ -220,13 +232,15 @@ static int do_set_sched(struct vx_info * spin_lock(&vxi->sched.tokens_lock); if (set_mask & VXSM_FILL_RATE) - vxi->sched.fill_rate[0] = data->fill_rate; - if (set_mask & VXSM_INTERVAL) - vxi->sched.interval[0] = data->interval; + vxi->sched.fill_rate[0] = data->fill_rate[0]; if (set_mask & VXSM_FILL_RATE2) - vxi->sched.fill_rate[1] = data->fill_rate; + vxi->sched.fill_rate[1] = data->fill_rate[1]; + if (set_mask & VXSM_INTERVAL) + vxi->sched.interval[0] = (set_mask & VXSM_MSEC) ? + msec_to_ticks(data->interval[0]) : data->interval[0]; if (set_mask & VXSM_INTERVAL2) - vxi->sched.interval[1] = data->interval; + vxi->sched.interval[1] = (set_mask & VXSM_MSEC) ? + msec_to_ticks(data->interval[1]) : data->interval[1]; if (set_mask & VXSM_TOKENS) vxi->sched.tokens = data->tokens; if (set_mask & VXSM_TOKENS_MIN) @@ -236,6 +250,14 @@ static int do_set_sched(struct vx_info * if (set_mask & VXSM_PRIO_BIAS) vxi->sched.prio_bias = data->prio_bias; + /* Sanity check rate/interval */ + for (i=0; i<2; i++) { + if (data->fill_rate[i] < 0) + data->fill_rate[i] = 0; + if (data->interval[i] <= 0) + data->interval[i] = HZ; + } + update_mask = vxi->sched.update_mask & VXSM_SET_MASK; update_mask |= (set_mask & (VXSM_SET_MASK|VXSM_IDLE_TIME)); vxi->sched.update_mask = update_mask; @@ -263,6 +285,24 @@ static int do_set_sched(struct vx_info * return 0; } +#define COPY_IDS(C) C(cpu_id); C(bucket_id) +#define COPY_TOK(C) C(tokens); C(tokens_min); C(tokens_max); C(prio_bias) +#define COPY_FRI(C) C(fill_rate[0]); C(interval[0]); \ + C(fill_rate[1]); C(interval[1]); + +#define COPY_VALUE(name) vc_data.name = data->name + +static int do_set_sched_v4(struct vx_info *vxi, struct vcmd_set_sched_v4 *data) +{ + struct vcmd_sched_v5 vc_data; + + vc_data.mask = data->set_mask; + COPY_IDS(COPY_VALUE); + COPY_TOK(COPY_VALUE); + vc_data.fill_rate[0] = vc_data.fill_rate[1] = data->fill_rate; + vc_data.interval[0] = vc_data.interval[1] = data->interval; + return do_set_sched(vxi, &vc_data); +} #ifdef CONFIG_VSERVER_LEGACY @@ -280,14 +320,14 @@ int vc_set_sched_v2(struct vx_info *vxi, if (copy_from_user (&vc_data, data, sizeof(vc_data))) return -EFAULT; - COPY_MASK_V2(fill_rate, VXSM_FILL_RATE); + COPY_MASK_V2(fill_rate, VXSM_FILL_RATE); COPY_MASK_V2(interval, VXSM_INTERVAL); COPY_MASK_V2(tokens, VXSM_TOKENS); COPY_MASK_V2(tokens_min, VXSM_TOKENS_MIN); COPY_MASK_V2(tokens_max, VXSM_TOKENS_MAX); vc_data_v4.bucket_id = 0; - do_set_sched(vxi, &vc_data_v4); + do_set_sched_v4(vxi, &vc_data_v4); return 0; } #endif @@ -305,16 +345,86 @@ int vc_set_sched_v3(struct vx_info *vxi, vc_data_v4.set_mask &= VXSM_V3_MASK; vc_data_v4.bucket_id = 0; - return do_set_sched(vxi, &vc_data_v4); + return do_set_sched_v4(vxi, &vc_data_v4); } -int vc_set_sched(struct vx_info *vxi, void __user *data) +int vc_set_sched_v4(struct vx_info *vxi, void __user *data) { struct vcmd_set_sched_v4 vc_data; if (copy_from_user (&vc_data, data, sizeof(vc_data))) return -EFAULT; + return do_set_sched_v4(vxi, &vc_data); +} + + /* latest interface is v5 */ + +int vc_set_sched(struct vx_info *vxi, void __user *data) +{ + struct vcmd_sched_v5 vc_data; + + if (copy_from_user (&vc_data, data, sizeof(vc_data))) + return -EFAULT; + return do_set_sched(vxi, &vc_data); } + +int vc_get_sched(struct vx_info *vxi, void __user *data) +{ + struct vcmd_sched_v5 vc_data; + + if (copy_from_user (&vc_data, data, sizeof(vc_data))) + return -EFAULT; + + if (vc_data.mask & VXSM_CPU_ID) { + int cpu = vc_data.cpu_id; + struct _vx_sched_pc *data; + + if (!cpu_possible(cpu)) + return -EINVAL; + + data = &vx_per_cpu(vxi, sched_pc, cpu); + COPY_TOK(COPY_VALUE); + COPY_FRI(COPY_VALUE); + } else { + struct _vx_sched *data = &vxi->sched; + + COPY_TOK(COPY_VALUE); + COPY_FRI(COPY_VALUE); + } + vc_data.prio_bias = vxi->sched.prio_bias; + + if (copy_to_user (data, &vc_data, sizeof(vc_data))) + return -EFAULT; + return 0; +} + + +int vc_sched_info(struct vx_info *vxi, void __user *data) +{ + struct vcmd_sched_info vc_data; + struct _vx_sched_pc *sched_pc; + int cpu; + + if (copy_from_user (&vc_data, data, sizeof(vc_data))) + return -EFAULT; + + cpu = vc_data.cpu_id; + if (!cpu_possible(cpu)) + return -EINVAL; + + sched_pc = &vx_per_cpu(vxi, sched_pc, cpu); + + vc_data.user_msec = ticks_to_msec(sched_pc->user_ticks); + vc_data.sys_msec = ticks_to_msec(sched_pc->sys_ticks); + vc_data.hold_msec = ticks_to_msec(sched_pc->hold_ticks); + vc_data.token_usec = ticks_to_usec(1); + vc_data.vavavoom = sched_pc->vavavoom; + + if (copy_to_user (data, &vc_data, sizeof(vc_data))) + return -EFAULT; + return 0; +} + diff -NurpP --minimal linux-2.6.19.1-vs2.2.0-rc6.1/kernel/vserver/switch.c linux-2.6.19.1-vs2.2.0-rc6.2/kernel/vserver/switch.c --- linux-2.6.19.1-vs2.2.0-rc6.1/kernel/vserver/switch.c 2006-12-05 18:15:48 +0100 +++ linux-2.6.19.1-vs2.2.0-rc6.2/kernel/vserver/switch.c 2007-01-10 05:29:41 +0100 @@ -165,9 +165,15 @@ long do_vcmd(uint32_t cmd, uint32_t id, #endif case VCMD_set_sched_v3: return vc_set_sched_v3(vxi, data); - /* this is version 4 */ + case VCMD_set_sched_v4: + return vc_set_sched_v4(vxi, data); + /* this is version 5 */ case VCMD_set_sched: return vc_set_sched(vxi, data); + case VCMD_get_sched: + return vc_get_sched(vxi, data); + case VCMD_sched_info: + return vc_sched_info(vxi, data); case VCMD_add_dlimit: return __COMPAT(vc_add_dlimit, id, data, compat); @@ -301,6 +307,8 @@ long do_vserver(uint32_t cmd, uint32_t i __VCMD(get_iattr, 2, VCA_NONE, 0); __VCMD(get_dlimit, 3, VCA_NONE, VCF_INFO); + __VCMD(get_sched, 3, VCA_VXI, VCF_INFO); + __VCMD(sched_info, 3, VCA_VXI, VCF_INFO); /* lower admin commands */ __VCMD(wait_exit, 4, VCA_VXI, VCF_INFO); @@ -330,6 +338,7 @@ long do_vserver(uint32_t cmd, uint32_t i __VCMD(set_sched, 7, VCA_VXI, VCF_ARES|VCF_SETUP); __VCMD(set_sched_v2, 7, VCA_VXI, VCF_ARES|VCF_SETUP); __VCMD(set_sched_v3, 7, VCA_VXI, VCF_ARES|VCF_SETUP); + __VCMD(set_sched_v4, 7, VCA_VXI, VCF_ARES|VCF_SETUP); __VCMD(set_ncaps, 7, VCA_NXI, VCF_ARES|VCF_SETUP); __VCMD(set_nflags, 7, VCA_NXI, VCF_ARES|VCF_SETUP);