[Devel] [PATCH RHEL7 COMMIT] ve/printk: fix __vprintk_emit after rebase to RHEL7.3 beta
Konstantin Khorenko
khorenko at virtuozzo.com
Wed Nov 9 06:21:38 PST 2016
The commit is pushed to "branch-rh7-3.10.0-493.vz7.25.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-493.el7
------>
commit d3c72648bd62dc0c2e002389a1d92179d4ce3d7b
Author: Pavel Tikhomirov <ptikhomirov at virtuozzo.com>
Date: Wed Nov 9 18:21:38 2016 +0400
ve/printk: fix __vprintk_emit after rebase to RHEL7.3 beta
1. In case of ENOMEM from log_state_init do:
a) reset logbuf_cpu as we are just about to unlock logbuf_lock
b) unlock logbuf_lock
c) enable lockdep back
d) restore irqs
same as in the end before if (!in_sched) but we don't want to enter
these if-block with log variable uninitialized, so goto does not fit
well.
2. Take logbuf_lock and disable interrupts before operating
with log
3. Also move our log wake up into if (!in_sched) if-block as when
called from printk_deferred, __vprintk_emit should not call up(),
that can lead to deadlock on scheduler rq locks.
Those changes are needed after commit 458df9fd4815 ("printk: remove
separate printk_sched buffers and use printk buf instead")
Note: now we do not use ve_printk from scheduler but in future
we might need some kind of ve_printk_deferred for it.
https://jira.sw.ru/browse/PSBM-54820
Signed-off-by: Pavel Tikhomirov <ptikhomirov at virtuozzo.com>
Reviewed-by: Dmitry Safonov <dsafonov at virtuozzo.com>
---
kernel/printk.c | 18 ++++++++++++------
1 file changed, 12 insertions(+), 6 deletions(-)
diff --git a/kernel/printk.c b/kernel/printk.c
index ae835e3..a332be1 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -1676,10 +1676,11 @@ static int __vprintk_emit(struct log_state *log,
err = log_state_init(log);
if (err) {
+ logbuf_cpu = UINT_MAX;
raw_spin_unlock(&logbuf_lock);
- printed_len = err;
lockdep_on();
- goto out;
+ local_irq_restore(flags);
+ return err;
}
if (recursion_bug) {
@@ -1789,20 +1790,21 @@ static int __vprintk_emit(struct log_state *log,
* /dev/kmsg and syslog() users.
*/
if (log != &init_log_state) {
+ raw_spin_lock_irqsave(&logbuf_lock, flags);
if (log->seen_seq != log->next_seq && !oops_in_progress) {
log->seen_seq = log->next_seq;
need_wake = true;
}
logbuf_cpu = UINT_MAX;
- raw_spin_unlock(&logbuf_lock);
+ raw_spin_unlock_irqrestore(&logbuf_lock, flags);
} else if (console_trylock_for_printk())
console_unlock();
preempt_enable();
lockdep_on();
+
+ if (need_wake)
+ wake_up_interruptible(&log->wait);
}
-out:
- if (need_wake)
- wake_up_interruptible(&log->wait);
return printed_len;
}
@@ -1881,6 +1883,10 @@ asmlinkage int ve_vprintk(int dst, const char *fmt, va_list args)
return r;
}
+/*
+ * Do not use it from scheduler code - can lead to deadlocks.
+ */
+
asmlinkage int ve_printk(int dst, const char *fmt, ...)
{
va_list args;
More information about the Devel
mailing list