nohz: stat: Fix CPU idle time accounting
Bo Yan [Fri, 22 Mar 2013 21:03:26 +0000 (14:03 -0700)]
Since cpustat[CPUTIME_IDLE] is never connected to ts->idle_sleeptime,
never read from cpustat[CPUTIME_IDLE] when reporting stats in
/proc/stat.

Note this was rejected by Michal Hocko when it was initially proposed
by Martin Schwidefsky in LKML, so if you want to upstream it, better
find an alternative (either completely disable cpustat[CPUTIME_IDLE]
for CONFIG_NO_HZ or somehow connect them to keep them in sync.)

bug 1190321

Change-Id: Idc92488910b826aff850a010016d8326c7ab9e6c
Signed-off-by: Bo Yan <byan@nvidia.com>
Reviewed-on: http://git-master/r/212224
Reviewed-by: Liang Cheng (SW) <licheng@nvidia.com>
Tested-by: Liang Cheng (SW) <licheng@nvidia.com>
Reviewed-by: Peter Boonstoppel <pboonstoppel@nvidia.com>

fs/proc/stat.c
kernel/time/tick-sched.c

index 98bf0c2..ffcda1f 100644 (file)
@@ -47,11 +47,10 @@ static u64 get_idle_time(int cpu)
 {
        u64 idle, idle_time = -1ULL;
 
-       if (cpu_online(cpu))
-               idle_time = get_cpu_idle_time_us(cpu, NULL);
+       idle_time = get_cpu_idle_time_us(cpu, NULL);
 
        if (idle_time == -1ULL)
-               /* !NO_HZ or cpu offline so we can rely on cpustat.idle */
+               /* !NO_HZ so we can rely on cpustat.idle */
                idle = kcpustat_cpu(cpu).cpustat[CPUTIME_IDLE];
        else
                idle = usecs_to_cputime64(idle_time);
index e603477..cd0e5a7 100644 (file)
@@ -218,7 +218,7 @@ u64 get_cpu_idle_time_us(int cpu, u64 *last_update_time)
                update_ts_time_stats(cpu, ts, now, last_update_time);
                idle = ts->idle_sleeptime;
        } else {
-               if (ts->idle_active && !nr_iowait_cpu(cpu)) {
+               if (cpu_online(cpu) && ts->idle_active && !nr_iowait_cpu(cpu)) {
                        ktime_t delta = ktime_sub(now, ts->idle_entrytime);
 
                        idle = ktime_add(ts->idle_sleeptime, delta);
@@ -259,7 +259,8 @@ u64 get_cpu_iowait_time_us(int cpu, u64 *last_update_time)
                update_ts_time_stats(cpu, ts, now, last_update_time);
                iowait = ts->iowait_sleeptime;
        } else {
-               if (ts->idle_active && nr_iowait_cpu(cpu) > 0) {
+               if (cpu_online(cpu) && ts->idle_active &&
+                                               nr_iowait_cpu(cpu) > 0) {
                        ktime_t delta = ktime_sub(now, ts->idle_entrytime);
 
                        iowait = ktime_add(ts->iowait_sleeptime, delta);