Commit 673242c1 authored by Andi Kleen's avatar Andi Kleen Committed by Linus Torvalds

[PATCH] x86-64: Make lockless machine check record passing a bit more robust.

One machine is constantly throwing NMI watchdog timeouts in mce_log

This was one attempt to fix it.

(AK: this doesn't actually fix the bug I'm seeing unfortunately, probably
drop.  I don't like it that the reader can spin forever now waiting
for a writer)
Signed-off-by: default avatarAndi Kleen <ak@suse.de>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent a54e678b
...@@ -56,6 +56,7 @@ void mce_log(struct mce *mce) ...@@ -56,6 +56,7 @@ void mce_log(struct mce *mce)
smp_wmb(); smp_wmb();
for (;;) { for (;;) {
entry = rcu_dereference(mcelog.next); entry = rcu_dereference(mcelog.next);
for (;;) {
/* When the buffer fills up discard new entries. Assume /* When the buffer fills up discard new entries. Assume
that the earlier errors are the more interesting. */ that the earlier errors are the more interesting. */
if (entry >= MCE_LOG_LEN) { if (entry >= MCE_LOG_LEN) {
...@@ -63,8 +64,11 @@ void mce_log(struct mce *mce) ...@@ -63,8 +64,11 @@ void mce_log(struct mce *mce)
return; return;
} }
/* Old left over entry. Skip. */ /* Old left over entry. Skip. */
if (mcelog.entry[entry].finished) if (mcelog.entry[entry].finished) {
entry++;
continue; continue;
}
}
smp_rmb(); smp_rmb();
next = entry + 1; next = entry + 1;
if (cmpxchg(&mcelog.next, entry, next) == entry) if (cmpxchg(&mcelog.next, entry, next) == entry)
...@@ -405,8 +409,14 @@ static ssize_t mce_read(struct file *filp, char __user *ubuf, size_t usize, loff ...@@ -405,8 +409,14 @@ static ssize_t mce_read(struct file *filp, char __user *ubuf, size_t usize, loff
err = 0; err = 0;
for (i = 0; i < next; i++) { for (i = 0; i < next; i++) {
if (!mcelog.entry[i].finished) unsigned long start = jiffies;
while (!mcelog.entry[i].finished) {
if (!time_before(jiffies, start + 2)) {
memset(mcelog.entry + i,0, sizeof(struct mce));
continue; continue;
}
cpu_relax();
}
smp_rmb(); smp_rmb();
err |= copy_to_user(buf, mcelog.entry + i, sizeof(struct mce)); err |= copy_to_user(buf, mcelog.entry + i, sizeof(struct mce));
buf += sizeof(struct mce); buf += sizeof(struct mce);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment