projects
/
openwrt
/
staging
/
blogic.git
/ commitdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
| commitdiff |
tree
raw
|
patch
| inline |
side by side
(parent:
c3b46c7
)
locking/pvqspinlock: Fix division by zero in qstat_read()
author
Davidlohr Bueso
<
[email protected]
>
Mon, 18 Apr 2016 06:31:41 +0000
(23:31 -0700)
committer
Ingo Molnar
<
[email protected]
>
Tue, 19 Apr 2016 08:49:19 +0000
(10:49 +0200)
While playing with the qstat statistics (in <debugfs>/qlockstat/) I ran into
the following splat on a VM when opening pv_hash_hops:
divide error: 0000 [#1] SMP
...
RIP: 0010:[<
ffffffff810b61fe
>] [<
ffffffff810b61fe
>] qstat_read+0x12e/0x1e0
...
Call Trace:
[<
ffffffff811cad7c
>] ? mem_cgroup_commit_charge+0x6c/0xd0
[<
ffffffff8119750c
>] ? page_add_new_anon_rmap+0x8c/0xd0
[<
ffffffff8118d3b9
>] ? handle_mm_fault+0x1439/0x1b40
[<
ffffffff811937a9
>] ? do_mmap+0x449/0x550
[<
ffffffff811d3de3
>] ? __vfs_read+0x23/0xd0
[<
ffffffff811d4ab2
>] ? rw_verify_area+0x52/0xd0
[<
ffffffff811d4bb1
>] ? vfs_read+0x81/0x120
[<
ffffffff811d5f12
>] ? SyS_read+0x42/0xa0
[<
ffffffff815720f6
>] ? entry_SYSCALL_64_fastpath+0x1e/0xa8
Fix this by verifying that qstat_pv_kick_unlock is in fact non-zero,
similarly to what the qstat_pv_latency_wake case does, as if nothing
else, this can come from resetting the statistics, thus having 0 kicks
should be quite valid in this context.
Signed-off-by: Davidlohr Bueso <
[email protected]
>
Reviewed-by: Waiman Long <
[email protected]
>
Cc: Andrew Morton <
[email protected]
>
Cc: Linus Torvalds <
[email protected]
>
Cc: Paul E. McKenney <
[email protected]
>
Cc: Peter Zijlstra <
[email protected]
>
Cc: Thomas Gleixner <
[email protected]
>
Cc:
[email protected]
Cc:
[email protected]
Link:
http://lkml.kernel.org/r/
[email protected]
Signed-off-by: Ingo Molnar <
[email protected]
>
kernel/locking/qspinlock_stat.h
patch
|
blob
|
history
diff --git
a/kernel/locking/qspinlock_stat.h
b/kernel/locking/qspinlock_stat.h
index eb2a2c9bc3fc15d181c9e5981648974dc7aec65c..d734b750200180afc91d9f5d2015f1cb27aa6032 100644
(file)
--- a/
kernel/locking/qspinlock_stat.h
+++ b/
kernel/locking/qspinlock_stat.h
@@
-136,10
+136,12
@@
static ssize_t qstat_read(struct file *file, char __user *user_buf,
}
if (counter == qstat_pv_hash_hops) {
- u64 frac;
+ u64 frac
= 0
;
- frac = 100ULL * do_div(stat, kicks);
- frac = DIV_ROUND_CLOSEST_ULL(frac, kicks);
+ if (kicks) {
+ frac = 100ULL * do_div(stat, kicks);
+ frac = DIV_ROUND_CLOSEST_ULL(frac, kicks);
+ }
/*
* Return a X.XX decimal number