]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
procfs: do not overflow get_{idle,iowait}_time for nohz
authorMichal Hocko <mhocko@suse.cz>
Thu, 8 Dec 2011 04:32:05 +0000 (15:32 +1100)
committerStephen Rothwell <sfr@canb.auug.org.au>
Fri, 9 Dec 2011 04:52:20 +0000 (15:52 +1100)
Since a25cac51 ("proc: Consider NO_HZ when printing idle and iowait
times") we are reporting idle/io_wait time also while a CPU is tickless.
We rely on get_{idle,iowait}_time functions to retrieve proper data.

These functions, however, use usecs_to_cputime to translate micro seconds
time to cputime64_t.  This is just an alias to usecs_to_jiffies which
reduces the data type from u64 to unsigned int and also checks whether the
given parameter overflows jiffies_to_usecs(MAX_JIFFY_OFFSET) and returns
MAX_JIFFY_OFFSET in that case.

When do we overflow depends on CONFIG_HZ but especially for CONFIG_HZ_300
it is quite low (1431649781) so we are getting MAX_JIFFY_OFFSET for
>3000s!  until we overflow unsigned int.  Just for reference CONFIG_HZ_100
has an overflow window around 20s, CONFIG_HZ_250 ~8s and CONFIG_HZ_1000
~2s.

This results in a bug when people saw [h]top going mad reporting 100% CPU
usage even though there was basically no CPU load.  The reason was simply
that /proc/stat stopped reporting idle/io_wait changes (and reported
MAX_JIFFY_OFFSET) and so the only change happening was for user system
time.

Let's use nsecs_to_jiffies64 instead which doesn't reduce the precision to
32b type and it is much more appropriate for cumulative time values
(unlike usecs_to_jiffies which intended for timeout calculations).

Signed-off-by: Michal Hocko <mhocko@suse.cz>
Tested-by: Artem S. Tashkinov <t.artem@mailcity.com>
Cc: Dave Jones <davej@redhat.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Alexey Dobriyan <adobriyan@gmail.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
fs/proc/stat.c

index 8a6ab666e9f8bc27ffd64b1371a33e8c355fe6c5..2527a68057fcd7ccda132ba7c0b408e64e074baa 100644 (file)
@@ -31,7 +31,7 @@ static u64 get_idle_time(int cpu)
                idle = kcpustat_cpu(cpu).cpustat[CPUTIME_IDLE];
                idle += arch_idle_time(cpu);
        } else
-               idle = usecs_to_cputime(idle_time);
+               idle = nsecs_to_jiffies64(1000 * idle_time);
 
        return idle;
 }
@@ -44,7 +44,7 @@ static u64 get_iowait_time(int cpu)
                /* !NO_HZ so we can rely on cpustat.iowait */
                iowait = kcpustat_cpu(cpu).cpustat[CPUTIME_IOWAIT];
        else
-               iowait = usecs_to_cputime(iowait_time);
+               iowait = nsecs_to_jiffies64(1000 * iowait_time);
 
        return iowait;
 }