* [RFC][PATCH 0/3] Convert timekeeping core to use printk_deferred
@ 2014-04-23 3:36 John Stultz
2014-04-23 3:36 ` [RFC][PATCH 1/3] printk: Rename printk_sched to printk_deferred John Stultz
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: John Stultz @ 2014-04-23 3:36 UTC (permalink / raw)
To: LKML
Cc: John Stultz, Jan Kara, Peter Zijlstra, Jiri Bohac,
Thomas Gleixner, Ingo Molnar, Andrew Morton
Jiri pointed out a potential deadlock when calling printk while holding
the timekeeping seqlock.
Annoyingly, the seqlock lockdep enablement doesn't catch this, as
printk disables lockdep.
When looking for possible solutions, one idea was to use a local buffer
and defer the printk to later. Ends up there is already similar
functionality in printk_sched() to avoid similar style deadlocks w/
the scheduler.
Thus this patchset renames printk_sched to printk_deferred and then
moves the affected timekeeping printks to make use of it.
There were some points in the discussion between Jan and Peter that
made it seem that there may still be problems lurking in the console
layer, and I'm not sure I fully understand their point, so this solution
may be incomplete.
Additionally, the same issue likely affects any WARN_ONs as well, but
I wanted to get some thoughts on this approach before trying to remove
or convert affected WARN_ONS.
Your thoughts and feedback are greatly appreciated!
thanks
-john
Cc: Jan Kara <jack@suse.cz>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Jiri Bohac <jbohac@suse.cz>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
John Stultz (3):
printk: Rename printk_sched to printk_deferred
printk: Add printk_once_deferred
timekeeping: Use printk_deferred when holding timekeeping seqlock
include/linux/printk.h | 17 ++++++++++++++---
kernel/printk/printk.c | 8 ++++----
kernel/sched/core.c | 2 +-
kernel/sched/deadline.c | 7 +------
kernel/sched/rt.c | 8 +-------
kernel/time/ntp.c | 15 +++++++++------
kernel/time/timekeeping.c | 7 ++++---
7 files changed, 34 insertions(+), 30 deletions(-)
--
1.8.3.2
^ permalink raw reply [flat|nested] 4+ messages in thread
* [RFC][PATCH 1/3] printk: Rename printk_sched to printk_deferred
2014-04-23 3:36 [RFC][PATCH 0/3] Convert timekeeping core to use printk_deferred John Stultz
@ 2014-04-23 3:36 ` John Stultz
2014-04-23 3:36 ` [RFC][PATCH 2/3] printk: Add printk_once_deferred John Stultz
2014-04-23 3:36 ` [RFC][PATCH 3/3] timekeeping: Use printk_deferred when holding timekeeping seqlock John Stultz
2 siblings, 0 replies; 4+ messages in thread
From: John Stultz @ 2014-04-23 3:36 UTC (permalink / raw)
To: LKML
Cc: John Stultz, Jan Kara, Peter Zijlstra, Jiri Bohac,
Thomas Gleixner, Ingo Molnar, Andrew Morton
After learning we'll need some sort of deferred printk functionality
in the timekeeping core, Peter suggested we rename the printk_sched
function so it can be reused by needed subsystems.
This only changes the function name and name of the associated buffer.
No logic changes.
Cc: Jan Kara <jack@suse.cz>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Jiri Bohac <jbohac@suse.cz>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: John Stultz <john.stultz@linaro.org>
---
include/linux/printk.h | 6 +++---
kernel/printk/printk.c | 8 ++++----
kernel/sched/core.c | 2 +-
kernel/sched/deadline.c | 2 +-
kernel/sched/rt.c | 2 +-
5 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/include/linux/printk.h b/include/linux/printk.h
index 8752f75..7847301 100644
--- a/include/linux/printk.h
+++ b/include/linux/printk.h
@@ -128,9 +128,9 @@ asmlinkage __printf(1, 2) __cold
int printk(const char *fmt, ...);
/*
- * Special printk facility for scheduler use only, _DO_NOT_USE_ !
+ * Special printk facility for scheduler/timekeeping use only, _DO_NOT_USE_ !
*/
-__printf(1, 2) __cold int printk_sched(const char *fmt, ...);
+__printf(1, 2) __cold int printk_deferred(const char *fmt, ...);
/*
* Please don't use printk_ratelimit(), because it shares ratelimiting state
@@ -165,7 +165,7 @@ int printk(const char *s, ...)
return 0;
}
static inline __printf(1, 2) __cold
-int printk_sched(const char *s, ...)
+int printk_deferred(const char *s, ...)
{
return 0;
}
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index a45b509..a9763e4 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -2443,14 +2443,14 @@ late_initcall(printk_late_init);
#define PRINTK_PENDING_SCHED 0x02
static DEFINE_PER_CPU(int, printk_pending);
-static DEFINE_PER_CPU(char [PRINTK_BUF_SIZE], printk_sched_buf);
+static DEFINE_PER_CPU(char [PRINTK_BUF_SIZE], printk_deferred_buf);
static void wake_up_klogd_work_func(struct irq_work *irq_work)
{
int pending = __this_cpu_xchg(printk_pending, 0);
if (pending & PRINTK_PENDING_SCHED) {
- char *buf = __get_cpu_var(printk_sched_buf);
+ char *buf = __get_cpu_var(printk_deferred_buf);
pr_warn("[sched_delayed] %s", buf);
}
@@ -2473,7 +2473,7 @@ void wake_up_klogd(void)
preempt_enable();
}
-int printk_sched(const char *fmt, ...)
+int printk_deferred(const char *fmt, ...)
{
unsigned long flags;
va_list args;
@@ -2481,7 +2481,7 @@ int printk_sched(const char *fmt, ...)
int r;
local_irq_save(flags);
- buf = __get_cpu_var(printk_sched_buf);
+ buf = __get_cpu_var(printk_deferred_buf);
va_start(args, fmt);
r = vsnprintf(buf, PRINTK_BUF_SIZE, fmt, args);
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 268a45e..423704c 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -1320,7 +1320,7 @@ out:
* leave kernel.
*/
if (p->mm && printk_ratelimit()) {
- printk_sched("process %d (%s) no longer affine to cpu%d\n",
+ printk_deferred("process %d (%s) no longer affine to cpu%d\n",
task_pid_nr(p), p->comm, cpu);
}
}
diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c
index b080957..657ed68 100644
--- a/kernel/sched/deadline.c
+++ b/kernel/sched/deadline.c
@@ -352,7 +352,7 @@ static void replenish_dl_entity(struct sched_dl_entity *dl_se,
if (!lag_once) {
lag_once = true;
- printk_sched("sched: DL replenish lagged to much\n");
+ printk_deferred("sched: DL replenish lagged to much\n");
}
dl_se->deadline = rq_clock(rq) + pi_se->dl_deadline;
dl_se->runtime = pi_se->dl_runtime;
diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c
index bd2267a..c19b3cc 100644
--- a/kernel/sched/rt.c
+++ b/kernel/sched/rt.c
@@ -857,7 +857,7 @@ static int sched_rt_runtime_exceeded(struct rt_rq *rt_rq)
if (!once) {
once = true;
- printk_sched("sched: RT throttling activated\n");
+ printk_deferred("sched: RT throttling activated\n");
}
} else {
/*
--
1.8.3.2
^ permalink raw reply [flat|nested] 4+ messages in thread
* [RFC][PATCH 2/3] printk: Add printk_once_deferred
2014-04-23 3:36 [RFC][PATCH 0/3] Convert timekeeping core to use printk_deferred John Stultz
2014-04-23 3:36 ` [RFC][PATCH 1/3] printk: Rename printk_sched to printk_deferred John Stultz
@ 2014-04-23 3:36 ` John Stultz
2014-04-23 3:36 ` [RFC][PATCH 3/3] timekeeping: Use printk_deferred when holding timekeeping seqlock John Stultz
2 siblings, 0 replies; 4+ messages in thread
From: John Stultz @ 2014-04-23 3:36 UTC (permalink / raw)
To: LKML
Cc: John Stultz, Jan Kara, Peter Zijlstra, Jiri Bohac,
Thomas Gleixner, Ingo Molnar, Andrew Morton
Two of the three prink_deferred uses are really printk_once style
uses, so add a printk_once_deferred macro to simplify those call
sites.
Cc: Jan Kara <jack@suse.cz>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Jiri Bohac <jbohac@suse.cz>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: John Stultz <john.stultz@linaro.org>
---
include/linux/printk.h | 11 +++++++++++
kernel/sched/deadline.c | 7 +------
kernel/sched/rt.c | 8 +-------
3 files changed, 13 insertions(+), 13 deletions(-)
diff --git a/include/linux/printk.h b/include/linux/printk.h
index 7847301..bd21234 100644
--- a/include/linux/printk.h
+++ b/include/linux/printk.h
@@ -266,9 +266,20 @@ extern asmlinkage void dump_stack(void) __cold;
printk(fmt, ##__VA_ARGS__); \
} \
})
+#define printk_once_deferred(fmt, ...) \
+({ \
+ static bool __print_once __read_mostly; \
+ \
+ if (!__print_once) { \
+ __print_once = true; \
+ printk_deferred(fmt, ##__VA_ARGS__); \
+ } \
+})
#else
#define printk_once(fmt, ...) \
no_printk(fmt, ##__VA_ARGS__)
+#define printk_once_deferred(fmt, ...) \
+ no_printk(fmt, ##__VA_ARGS__)
#endif
#define pr_emerg_once(fmt, ...) \
diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c
index 657ed68..3ec96bd 100644
--- a/kernel/sched/deadline.c
+++ b/kernel/sched/deadline.c
@@ -348,12 +348,7 @@ static void replenish_dl_entity(struct sched_dl_entity *dl_se,
* entity.
*/
if (dl_time_before(dl_se->deadline, rq_clock(rq))) {
- static bool lag_once = false;
-
- if (!lag_once) {
- lag_once = true;
- printk_deferred("sched: DL replenish lagged to much\n");
- }
+ printk_once_deferred("sched: DL replenish lagged to much\n");
dl_se->deadline = rq_clock(rq) + pi_se->dl_deadline;
dl_se->runtime = pi_se->dl_runtime;
}
diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c
index c19b3cc..722e9a3 100644
--- a/kernel/sched/rt.c
+++ b/kernel/sched/rt.c
@@ -851,14 +851,8 @@ static int sched_rt_runtime_exceeded(struct rt_rq *rt_rq)
* but accrue some time due to boosting.
*/
if (likely(rt_b->rt_runtime)) {
- static bool once = false;
-
rt_rq->rt_throttled = 1;
-
- if (!once) {
- once = true;
- printk_deferred("sched: RT throttling activated\n");
- }
+ printk_once_deferred("sched: RT throttling activated\n");
} else {
/*
* In case we did anyway, make it go away,
--
1.8.3.2
^ permalink raw reply [flat|nested] 4+ messages in thread
* [RFC][PATCH 3/3] timekeeping: Use printk_deferred when holding timekeeping seqlock
2014-04-23 3:36 [RFC][PATCH 0/3] Convert timekeeping core to use printk_deferred John Stultz
2014-04-23 3:36 ` [RFC][PATCH 1/3] printk: Rename printk_sched to printk_deferred John Stultz
2014-04-23 3:36 ` [RFC][PATCH 2/3] printk: Add printk_once_deferred John Stultz
@ 2014-04-23 3:36 ` John Stultz
2 siblings, 0 replies; 4+ messages in thread
From: John Stultz @ 2014-04-23 3:36 UTC (permalink / raw)
To: LKML
Cc: John Stultz, Jan Kara, Peter Zijlstra, Jiri Bohac,
Thomas Gleixner, Ingo Molnar, Andrew Morton
Jiri Bohac pointed out that there are rare but potential deadlock
possibilities when calling printk while holding the timekeeping
seqlock.
This is due to printk() triggering console sem wakeup, which can
cause scheduling code to trigger hrtimers which may try to read
the time.
Specifically, as Jiri pointed out, that path is:
printk
vprintk_emit
console_unlock
up(&console_sem)
__up
wake_up_process
try_to_wake_up
ttwu_do_activate
ttwu_activate
activate_task
enqueue_task
enqueue_task_fair
hrtick_update
hrtick_start_fair
hrtick_start_fair
get_time
ktime_get
--> endless loop on
read_seqcount_retry(&timekeeper_seq, ...)
This patch tries to avoid this issue by using printk_deferred (previously
named printk_sched) which should defer printing via a irq_work_queue.
Cc: Jan Kara <jack@suse.cz>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Jiri Bohac <jbohac@suse.cz>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Reported-by: Jiri Bohac <jbohac@suse.cz>
Signed-off-by: John Stultz <john.stultz@linaro.org>
---
kernel/time/ntp.c | 15 +++++++++------
kernel/time/timekeeping.c | 7 ++++---
2 files changed, 13 insertions(+), 9 deletions(-)
diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c
index 419a52c..5b0ac4d 100644
--- a/kernel/time/ntp.c
+++ b/kernel/time/ntp.c
@@ -786,8 +786,9 @@ static long hardpps_update_freq(struct pps_normtime freq_norm)
time_status |= STA_PPSERROR;
pps_errcnt++;
pps_dec_freq_interval();
- pr_err("hardpps: PPSERROR: interval too long - %ld s\n",
- freq_norm.sec);
+ printk_deferred(KERN_ERR
+ "hardpps: PPSERROR: interval too long - %ld s\n",
+ freq_norm.sec);
return 0;
}
@@ -800,7 +801,8 @@ static long hardpps_update_freq(struct pps_normtime freq_norm)
delta = shift_right(ftemp - pps_freq, NTP_SCALE_SHIFT);
pps_freq = ftemp;
if (delta > PPS_MAXWANDER || delta < -PPS_MAXWANDER) {
- pr_warning("hardpps: PPSWANDER: change=%ld\n", delta);
+ printk_deferred(KERN_WARNING
+ "hardpps: PPSWANDER: change=%ld\n", delta);
time_status |= STA_PPSWANDER;
pps_stbcnt++;
pps_dec_freq_interval();
@@ -844,8 +846,9 @@ static void hardpps_update_phase(long error)
* the time offset is updated.
*/
if (jitter > (pps_jitter << PPS_POPCORN)) {
- pr_warning("hardpps: PPSJITTER: jitter=%ld, limit=%ld\n",
- jitter, (pps_jitter << PPS_POPCORN));
+ printk_deferred(KERN_WARNING
+ "hardpps: PPSJITTER: jitter=%ld, limit=%ld\n",
+ jitter, (pps_jitter << PPS_POPCORN));
time_status |= STA_PPSJITTER;
pps_jitcnt++;
} else if (time_status & STA_PPSTIME) {
@@ -902,7 +905,7 @@ void __hardpps(const struct timespec *phase_ts, const struct timespec *raw_ts)
time_status |= STA_PPSJITTER;
/* restart the frequency calibration interval */
pps_fbase = *raw_ts;
- pr_err("hardpps: PPSJITTER: bad pulse\n");
+ printk_deferred(KERN_ERR "hardpps: PPSJITTER: bad pulse\n");
return;
}
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index f7df8ea..ffd3113 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -852,8 +852,9 @@ static void __timekeeping_inject_sleeptime(struct timekeeper *tk,
struct timespec *delta)
{
if (!timespec_valid_strict(delta)) {
- printk(KERN_WARNING "__timekeeping_inject_sleeptime: Invalid "
- "sleep delta value!\n");
+ printk_deferred(KERN_WARNING
+ "__timekeeping_inject_sleeptime: Invalid "
+ "sleep delta value!\n");
return;
}
tk_xtime_add(tk, delta);
@@ -1157,7 +1158,7 @@ static void timekeeping_adjust(struct timekeeper *tk, s64 offset)
if (unlikely(tk->clock->maxadj &&
(tk->mult + adj > tk->clock->mult + tk->clock->maxadj))) {
- printk_once(KERN_WARNING
+ printk_once_deferred(KERN_WARNING
"Adjusting %s more than 11%% (%ld vs %ld)\n",
tk->clock->name, (long)tk->mult + adj,
(long)tk->clock->mult + tk->clock->maxadj);
--
1.8.3.2
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2014-04-23 3:37 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-04-23 3:36 [RFC][PATCH 0/3] Convert timekeeping core to use printk_deferred John Stultz
2014-04-23 3:36 ` [RFC][PATCH 1/3] printk: Rename printk_sched to printk_deferred John Stultz
2014-04-23 3:36 ` [RFC][PATCH 2/3] printk: Add printk_once_deferred John Stultz
2014-04-23 3:36 ` [RFC][PATCH 3/3] timekeeping: Use printk_deferred when holding timekeeping seqlock John Stultz
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®