* [PATCH 1/2] lockdep: Use for_each_process_thread() for debug_show_all_locks()
@ 2018-04-06 10:41 Tetsuo Handa
2018-04-06 10:41 ` [PATCH 2/2] lockdep: Move sanity check to inside lockdep_print_held_locks() Tetsuo Handa
2018-05-14 7:53 ` [tip:locking/core] locking/lockdep: Use for_each_process_thread() for debug_show_all_locks() tip-bot for Tetsuo Handa
0 siblings, 2 replies; 4+ messages in thread
From: Tetsuo Handa @ 2018-04-06 10:41 UTC (permalink / raw)
To: linux-kernel; +Cc: Tetsuo Handa, Ingo Molnar, Peter Zijlstra
debug_show_all_locks() tries to grab tasklist_lock for two seconds, but
calling while_each_thread() without tasklist_lock held is not safe.
See commit 4449a51a7c281602 ("vm_is_stack: use for_each_thread() rather
then buggy while_each_thread()") for more information.
Change debug_show_all_locks() from "do_each_thread()/while_each_thread()
with possibility of missing tasklist_lock" to "for_each_process_thread()
with RCU", and add a call to touch_all_softlockup_watchdogs() like
show_state_filter() does.
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ingo Molnar <mingo@redhat.com>
---
kernel/locking/lockdep.c | 43 ++++++++-----------------------------------
1 file changed, 8 insertions(+), 35 deletions(-)
diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c
index 0233863..94f4d21 100644
--- a/kernel/locking/lockdep.c
+++ b/kernel/locking/lockdep.c
@@ -4451,8 +4451,6 @@ void debug_check_no_locks_held(void)
void debug_show_all_locks(void)
{
struct task_struct *g, *p;
- int count = 10;
- int unlock = 1;
if (unlikely(!debug_locks)) {
pr_warn("INFO: lockdep is turned off.\n");
@@ -4460,30 +4458,8 @@ void debug_show_all_locks(void)
}
pr_warn("\nShowing all locks held in the system:\n");
- /*
- * Here we try to get the tasklist_lock as hard as possible,
- * if not successful after 2 seconds we ignore it (but keep
- * trying). This is to enable a debug printout even if a
- * tasklist_lock-holding task deadlocks or crashes.
- */
-retry:
- if (!read_trylock(&tasklist_lock)) {
- if (count == 10)
- pr_warn("hm, tasklist_lock locked, retrying... ");
- if (count) {
- count--;
- pr_cont(" #%d", 10-count);
- mdelay(200);
- goto retry;
- }
- pr_cont(" ignoring it.\n");
- unlock = 0;
- } else {
- if (count != 10)
- pr_cont(" locked it.\n");
- }
-
- do_each_thread(g, p) {
+ rcu_read_lock();
+ for_each_process_thread(g, p) {
/*
* It's not reliable to print a task's held locks
* if it's not sleeping (or if it's not the current
@@ -4491,19 +4467,16 @@ void debug_show_all_locks(void)
*/
if (p->state == TASK_RUNNING && p != current)
continue;
- if (p->lockdep_depth)
- lockdep_print_held_locks(p);
- if (!unlock)
- if (read_trylock(&tasklist_lock))
- unlock = 1;
+ if (!p->lockdep_depth)
+ continue;
+ lockdep_print_held_locks(p);
touch_nmi_watchdog();
- } while_each_thread(g, p);
+ touch_all_softlockup_watchdogs();
+ }
+ rcu_read_unlock();
pr_warn("\n");
pr_warn("=============================================\n\n");
-
- if (unlock)
- read_unlock(&tasklist_lock);
}
EXPORT_SYMBOL_GPL(debug_show_all_locks);
#endif
--
1.8.3.1
^ permalink raw reply related [flat|nested] 4+ messages in thread* [PATCH 2/2] lockdep: Move sanity check to inside lockdep_print_held_locks(). 2018-04-06 10:41 [PATCH 1/2] lockdep: Use for_each_process_thread() for debug_show_all_locks() Tetsuo Handa @ 2018-04-06 10:41 ` Tetsuo Handa 2018-05-14 7:54 ` [tip:locking/core] locking/lockdep: " tip-bot for Tetsuo Handa 2018-05-14 7:53 ` [tip:locking/core] locking/lockdep: Use for_each_process_thread() for debug_show_all_locks() tip-bot for Tetsuo Handa 1 sibling, 1 reply; 4+ messages in thread From: Tetsuo Handa @ 2018-04-06 10:41 UTC (permalink / raw) To: linux-kernel Cc: Tetsuo Handa, Dmitry Vyukov, Ingo Molnar, Matthew Wilcox, Peter Zijlstra It is considered that calling lockdep_print_held_locks() on a running thread is not safe. Since all callers should follow that rule and the sanity check is not heavy, this patch moves the sanity check to inside lockdep_print_held_locks(). As a side effect of this patch, number of locks held by running threads will be printed as well. This change will be preferable when we want to know which threads might be relevant to a problem but unable to print any clue because that thread is running. Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Ingo Molnar <mingo@redhat.com> Cc: Matthew Wilcox <willy@infradead.org> Cc: Dmitry Vyukov <dvyukov@google.com> --- kernel/locking/lockdep.c | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c index 94f4d21..edcac5d 100644 --- a/kernel/locking/lockdep.c +++ b/kernel/locking/lockdep.c @@ -561,20 +561,24 @@ static void print_lock(struct held_lock *hlock) printk(KERN_CONT ", at: %pS\n", (void *)hlock->acquire_ip); } -static void lockdep_print_held_locks(struct task_struct *curr) +static void lockdep_print_held_locks(struct task_struct *p) { - int i, depth = curr->lockdep_depth; + int i, depth = READ_ONCE(p->lockdep_depth); - if (!depth) { - printk("no locks held by %s/%d.\n", curr->comm, task_pid_nr(curr)); + if (!depth) + printk("no locks held by %s/%d.\n", p->comm, task_pid_nr(p)); + else + printk("%d lock%s held by %s/%d:\n", depth, + depth > 1 ? "s" : "", p->comm, task_pid_nr(p)); + /* + * It's not reliable to print a task's held locks if it's not sleeping + * and it's not the current task. + */ + if (p->state == TASK_RUNNING && p != current) return; - } - printk("%d lock%s held by %s/%d:\n", - depth, depth > 1 ? "s" : "", curr->comm, task_pid_nr(curr)); - for (i = 0; i < depth; i++) { printk(" #%d: ", i); - print_lock(curr->held_locks + i); + print_lock(p->held_locks + i); } } @@ -4460,13 +4464,6 @@ void debug_show_all_locks(void) rcu_read_lock(); for_each_process_thread(g, p) { - /* - * It's not reliable to print a task's held locks - * if it's not sleeping (or if it's not the current - * task): - */ - if (p->state == TASK_RUNNING && p != current) - continue; if (!p->lockdep_depth) continue; lockdep_print_held_locks(p); -- 1.8.3.1 ^ permalink raw reply related [flat|nested] 4+ messages in thread
* [tip:locking/core] locking/lockdep: Move sanity check to inside lockdep_print_held_locks() 2018-04-06 10:41 ` [PATCH 2/2] lockdep: Move sanity check to inside lockdep_print_held_locks() Tetsuo Handa @ 2018-05-14 7:54 ` tip-bot for Tetsuo Handa 0 siblings, 0 replies; 4+ messages in thread From: tip-bot for Tetsuo Handa @ 2018-05-14 7:54 UTC (permalink / raw) To: linux-tip-commits Cc: torvalds, peterz, penguin-kernel, mingo, tglx, willy, linux-kernel, dvyukov, hpa Commit-ID: 8cc05c71ba5f793690bb72aeb404dce65b5d4b52 Gitweb: https://git.kernel.org/tip/8cc05c71ba5f793690bb72aeb404dce65b5d4b52 Author: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> AuthorDate: Fri, 6 Apr 2018 19:41:19 +0900 Committer: Ingo Molnar <mingo@kernel.org> CommitDate: Mon, 14 May 2018 09:15:02 +0200 locking/lockdep: Move sanity check to inside lockdep_print_held_locks() Calling lockdep_print_held_locks() on a running thread is considered unsafe. Since all callers should follow that rule and the sanity check is not heavy, this patch moves the sanity check to inside lockdep_print_held_locks(). As a side effect of this patch, the number of locks held by running threads will be printed as well. This change will be preferable when we want to know which threads might be relevant to a problem but are unable to print any clues because that thread is running. Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Cc: Dmitry Vyukov <dvyukov@google.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Matthew Wilcox <willy@infradead.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Link: http://lkml.kernel.org/r/1523011279-8206-2-git-send-email-penguin-kernel@I-love.SAKURA.ne.jp Signed-off-by: Ingo Molnar <mingo@kernel.org> --- kernel/locking/lockdep.c | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c index 94f4d21ff66d..edcac5de7ebc 100644 --- a/kernel/locking/lockdep.c +++ b/kernel/locking/lockdep.c @@ -561,20 +561,24 @@ static void print_lock(struct held_lock *hlock) printk(KERN_CONT ", at: %pS\n", (void *)hlock->acquire_ip); } -static void lockdep_print_held_locks(struct task_struct *curr) +static void lockdep_print_held_locks(struct task_struct *p) { - int i, depth = curr->lockdep_depth; + int i, depth = READ_ONCE(p->lockdep_depth); - if (!depth) { - printk("no locks held by %s/%d.\n", curr->comm, task_pid_nr(curr)); + if (!depth) + printk("no locks held by %s/%d.\n", p->comm, task_pid_nr(p)); + else + printk("%d lock%s held by %s/%d:\n", depth, + depth > 1 ? "s" : "", p->comm, task_pid_nr(p)); + /* + * It's not reliable to print a task's held locks if it's not sleeping + * and it's not the current task. + */ + if (p->state == TASK_RUNNING && p != current) return; - } - printk("%d lock%s held by %s/%d:\n", - depth, depth > 1 ? "s" : "", curr->comm, task_pid_nr(curr)); - for (i = 0; i < depth; i++) { printk(" #%d: ", i); - print_lock(curr->held_locks + i); + print_lock(p->held_locks + i); } } @@ -4460,13 +4464,6 @@ void debug_show_all_locks(void) rcu_read_lock(); for_each_process_thread(g, p) { - /* - * It's not reliable to print a task's held locks - * if it's not sleeping (or if it's not the current - * task): - */ - if (p->state == TASK_RUNNING && p != current) - continue; if (!p->lockdep_depth) continue; lockdep_print_held_locks(p); ^ permalink raw reply related [flat|nested] 4+ messages in thread
* [tip:locking/core] locking/lockdep: Use for_each_process_thread() for debug_show_all_locks() 2018-04-06 10:41 [PATCH 1/2] lockdep: Use for_each_process_thread() for debug_show_all_locks() Tetsuo Handa 2018-04-06 10:41 ` [PATCH 2/2] lockdep: Move sanity check to inside lockdep_print_held_locks() Tetsuo Handa @ 2018-05-14 7:53 ` tip-bot for Tetsuo Handa 1 sibling, 0 replies; 4+ messages in thread From: tip-bot for Tetsuo Handa @ 2018-05-14 7:53 UTC (permalink / raw) To: linux-tip-commits Cc: penguin-kernel, mingo, tglx, hpa, torvalds, peterz, linux-kernel Commit-ID: 0f736a52e4be86476eec1d5adbcbd9c2809ac4b4 Gitweb: https://git.kernel.org/tip/0f736a52e4be86476eec1d5adbcbd9c2809ac4b4 Author: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> AuthorDate: Fri, 6 Apr 2018 19:41:18 +0900 Committer: Ingo Molnar <mingo@kernel.org> CommitDate: Mon, 14 May 2018 09:15:02 +0200 locking/lockdep: Use for_each_process_thread() for debug_show_all_locks() debug_show_all_locks() tries to grab the tasklist_lock for two seconds, but calling while_each_thread() without tasklist_lock held is not safe. See the following commit for more information: 4449a51a7c281602 ("vm_is_stack: use for_each_thread() rather then buggy while_each_thread()") Change debug_show_all_locks() from "do_each_thread()/while_each_thread() with possibility of missing tasklist_lock" to "for_each_process_thread() with RCU", and add a call to touch_all_softlockup_watchdogs() like show_state_filter() does. Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Link: http://lkml.kernel.org/r/1523011279-8206-1-git-send-email-penguin-kernel@I-love.SAKURA.ne.jp Signed-off-by: Ingo Molnar <mingo@kernel.org> --- kernel/locking/lockdep.c | 43 ++++++++----------------------------------- 1 file changed, 8 insertions(+), 35 deletions(-) diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c index 023386338269..94f4d21ff66d 100644 --- a/kernel/locking/lockdep.c +++ b/kernel/locking/lockdep.c @@ -4451,8 +4451,6 @@ EXPORT_SYMBOL_GPL(debug_check_no_locks_held); void debug_show_all_locks(void) { struct task_struct *g, *p; - int count = 10; - int unlock = 1; if (unlikely(!debug_locks)) { pr_warn("INFO: lockdep is turned off.\n"); @@ -4460,30 +4458,8 @@ void debug_show_all_locks(void) } pr_warn("\nShowing all locks held in the system:\n"); - /* - * Here we try to get the tasklist_lock as hard as possible, - * if not successful after 2 seconds we ignore it (but keep - * trying). This is to enable a debug printout even if a - * tasklist_lock-holding task deadlocks or crashes. - */ -retry: - if (!read_trylock(&tasklist_lock)) { - if (count == 10) - pr_warn("hm, tasklist_lock locked, retrying... "); - if (count) { - count--; - pr_cont(" #%d", 10-count); - mdelay(200); - goto retry; - } - pr_cont(" ignoring it.\n"); - unlock = 0; - } else { - if (count != 10) - pr_cont(" locked it.\n"); - } - - do_each_thread(g, p) { + rcu_read_lock(); + for_each_process_thread(g, p) { /* * It's not reliable to print a task's held locks * if it's not sleeping (or if it's not the current @@ -4491,19 +4467,16 @@ retry: */ if (p->state == TASK_RUNNING && p != current) continue; - if (p->lockdep_depth) - lockdep_print_held_locks(p); - if (!unlock) - if (read_trylock(&tasklist_lock)) - unlock = 1; + if (!p->lockdep_depth) + continue; + lockdep_print_held_locks(p); touch_nmi_watchdog(); - } while_each_thread(g, p); + touch_all_softlockup_watchdogs(); + } + rcu_read_unlock(); pr_warn("\n"); pr_warn("=============================================\n\n"); - - if (unlock) - read_unlock(&tasklist_lock); } EXPORT_SYMBOL_GPL(debug_show_all_locks); #endif ^ permalink raw reply related [flat|nested] 4+ messages in thread
end of thread, other threads:[~2018-05-14 7:54 UTC | newest] Thread overview: 4+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2018-04-06 10:41 [PATCH 1/2] lockdep: Use for_each_process_thread() for debug_show_all_locks() Tetsuo Handa 2018-04-06 10:41 ` [PATCH 2/2] lockdep: Move sanity check to inside lockdep_print_held_locks() Tetsuo Handa 2018-05-14 7:54 ` [tip:locking/core] locking/lockdep: " tip-bot for Tetsuo Handa 2018-05-14 7:53 ` [tip:locking/core] locking/lockdep: Use for_each_process_thread() for debug_show_all_locks() tip-bot for Tetsuo Handa
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.