diff -NurpP --minimal linux-2.6.9-vs1.9.3-w02-c4/fs/proc/array.c linux-2.6.9-vs1.9.3-w03-h3-p2-x1/fs/proc/array.c --- linux-2.6.9-vs1.9.3-w02-c4/fs/proc/array.c 2005-01-13 13:19:12.000000000 +0100 +++ linux-2.6.9-vs1.9.3-w03-h3-p2-x1/fs/proc/array.c 2005-01-13 13:19:35.000000000 +0100 @@ -350,7 +350,6 @@ int proc_pid_stat(struct task_struct *ta { unsigned long vsize, eip, esp, wchan; long priority, nice; - unsigned long long bias_uptime = 0; int tty_pgrp = -1, tty_nr = 0; sigset_t sigign, sigcatch; char state; @@ -395,10 +394,6 @@ int proc_pid_stat(struct task_struct *ta cutime = task->signal->cutime; cstime = task->signal->cstime; } - if (task_vx_flags(task, VXF_VIRT_UPTIME, 0)) { - bias_uptime = task->vx_info->cvirt.bias_uptime.tv_sec * NSEC_PER_SEC - + task->vx_info->cvirt.bias_uptime.tv_nsec; - } read_unlock(&tasklist_lock); /* scale priority and nice values from timeslices to -20..20 */ @@ -417,8 +412,20 @@ int proc_pid_stat(struct task_struct *ta /* convert timespec -> nsec*/ start_time = (unsigned long long)task->start_time.tv_sec * NSEC_PER_SEC + task->start_time.tv_nsec; + /* convert nsec -> ticks */ - start_time = nsec_to_clock_t(start_time - bias_uptime); + start_time = nsec_to_clock_t(start_time); + + /* fixup start time for virt uptime */ + if (vx_flags(VXF_VIRT_UPTIME, 0)) { + unsigned long long bias = + current->vx_info->cvirt.bias_clock; + + if (start_time > bias) + start_time -= bias; + else + start_time = 0; + } res = sprintf(buffer,"%d (%s) %c %d %d %d %d %d %lu %lu \ %lu %lu %lu %lu %lu %ld %ld %ld %ld %d %ld %llu %lu %ld %lu %lu %lu %lu %lu \ diff -NurpP --minimal linux-2.6.9-vs1.9.3-w02-c4/include/linux/vserver/cvirt_def.h linux-2.6.9-vs1.9.3-w03-h3-p2-x1/include/linux/vserver/cvirt_def.h --- linux-2.6.9-vs1.9.3-w02-c4/include/linux/vserver/cvirt_def.h 2005-01-13 13:18:53.000000000 +0100 +++ linux-2.6.9-vs1.9.3-w03-h3-p2-x1/include/linux/vserver/cvirt_def.h 2005-01-13 13:19:35.000000000 +0100 @@ -31,6 +31,7 @@ struct _vx_cvirt { struct timespec bias_idle; struct timespec bias_uptime; /* context creation point */ + uint64_t bias_clock; /* offset in clock_t */ struct new_utsname utsname; diff -NurpP --minimal linux-2.6.9-vs1.9.3-w02-c4/kernel/vserver/cvirt.c linux-2.6.9-vs1.9.3-w03-h3-p2-x1/kernel/vserver/cvirt.c --- linux-2.6.9-vs1.9.3-w02-c4/kernel/vserver/cvirt.c 2005-01-13 13:18:53.000000000 +0100 +++ linux-2.6.9-vs1.9.3-w03-h3-p2-x1/kernel/vserver/cvirt.c 2005-01-13 13:19:35.000000000 +0100 @@ -35,7 +35,7 @@ void vx_vsi_uptime(struct timespec *upti return; } -uint64_t vx_idle_jiffies() +uint64_t vx_idle_jiffies(void) { return init_task.utime + init_task.stime; } @@ -45,14 +45,17 @@ uint64_t vx_idle_jiffies() static inline uint32_t __update_loadavg(uint32_t load, int wsize, int delta, int n) { - unsigned long long calc; + unsigned long long calc, prev; /* just set it to n */ if (unlikely(delta >= wsize)) return (n << FSHIFT); - calc = (delta * n) << FSHIFT; - calc += (wsize - delta) * load; + calc = delta * n; + calc <<= FSHIFT; + prev = (wsize - delta); + prev *= load; + calc += prev; do_div(calc, wsize); return calc; } @@ -61,6 +64,8 @@ static inline uint32_t __update_loadavg( void vx_update_load(struct vx_info *vxi) { uint32_t now, last, delta; + unsigned int nr_running, nr_uninterruptible; + unsigned int total; spin_lock(&vxi->cvirt.load_lock); @@ -68,14 +73,23 @@ void vx_update_load(struct vx_info *vxi) last = vxi->cvirt.load_last; delta = now - last; + if (delta < 5*HZ) + goto out; + + nr_running = atomic_read(&vxi->cvirt.nr_running); + nr_uninterruptible = atomic_read(&vxi->cvirt.nr_uninterruptible); + total = nr_running + nr_uninterruptible; + vxi->cvirt.load[0] = __update_loadavg(vxi->cvirt.load[0], - 60*HZ, delta, atomic_read(&vxi->cvirt.nr_running)); + 60*HZ, delta, total); vxi->cvirt.load[1] = __update_loadavg(vxi->cvirt.load[1], - 5*60*HZ, delta, atomic_read(&vxi->cvirt.nr_running)); + 5*60*HZ, delta, total); vxi->cvirt.load[2] = __update_loadavg(vxi->cvirt.load[2], - 15*60*HZ, delta, atomic_read(&vxi->cvirt.nr_running)); + 15*60*HZ, delta, total); vxi->cvirt.load_last = now; +out: + atomic_inc(&vxi->cvirt.load_updates); spin_unlock(&vxi->cvirt.load_lock); } diff -NurpP --minimal linux-2.6.9-vs1.9.3-w02-c4/kernel/vserver/cvirt_init.h linux-2.6.9-vs1.9.3-w03-h3-p2-x1/kernel/vserver/cvirt_init.h --- linux-2.6.9-vs1.9.3-w02-c4/kernel/vserver/cvirt_init.h 2005-01-13 14:19:58.000000000 +0100 +++ linux-2.6.9-vs1.9.3-w03-h3-p2-x1/kernel/vserver/cvirt_init.h 2005-01-13 13:19:35.000000000 +0100 @@ -4,8 +4,13 @@ extern uint64_t vx_idle_jiffies(void); static inline void vx_info_init_cvirt(struct _vx_cvirt *cvirt) { uint64_t idle_jiffies = vx_idle_jiffies(); + uint64_t nsuptime; do_posix_clock_monotonic_gettime(&cvirt->bias_uptime); + nsuptime = (unsigned long long)cvirt->bias_uptime.tv_sec + * NSEC_PER_SEC + cvirt->bias_uptime.tv_nsec; + cvirt->bias_clock = nsec_to_clock_t(nsuptime); + jiffies_to_timespec(idle_jiffies, &cvirt->bias_idle); atomic_set(&cvirt->nr_threads, 0); atomic_set(&cvirt->nr_running, 0); diff -NurpP --minimal linux-2.6.9-vs1.9.3-w02-c4/kernel/vserver/cvirt_proc.h linux-2.6.9-vs1.9.3-w03-h3-p2-x1/kernel/vserver/cvirt_proc.h --- linux-2.6.9-vs1.9.3-w02-c4/kernel/vserver/cvirt_proc.h 2005-01-13 14:19:58.000000000 +0100 +++ linux-2.6.9-vs1.9.3-w03-h3-p2-x1/kernel/vserver/cvirt_proc.h 2005-01-13 13:19:35.000000000 +0100 @@ -39,11 +39,13 @@ static inline int vx_info_proc_cvirt(str "nr_running:\t%d\n" "nr_unintr:\t%d\n" "nr_onhold:\t%d\n" + "load_updates:\t%d\n" "loadavg:\t%d.%02d %d.%02d %d.%02d\n" ,atomic_read(&cvirt->nr_threads) ,atomic_read(&cvirt->nr_running) ,atomic_read(&cvirt->nr_uninterruptible) ,atomic_read(&cvirt->nr_onhold) + ,atomic_read(&cvirt->load_updates) ,LOAD_INT(a), LOAD_FRAC(a) ,LOAD_INT(b), LOAD_FRAC(b) ,LOAD_INT(c), LOAD_FRAC(c)