* [PATCH] tty: tty_mutex: fix lockdep warning in tty_lock_pair(v1) @ 2012-05-22 1:58 Ming Lei 2012-05-23 6:01 ` Ming Lei 0 siblings, 1 reply; 8+ messages in thread From: Ming Lei @ 2012-05-22 1:58 UTC (permalink / raw) To: Greg Kroah-Hartman Cc: linux-kernel, Ming Lei, Alan Cox, Arnd Bergmann, Peter Zijlstra Commit d29f3ef39be4eec0362b985305fc526d9be318cf(tty_lock: Localise the lock) introduces tty_lock_pair, in which may cause lockdep warning because two locks with same lock class are to be acquired one after another. This patch uses mutex_lock_nested annotation to avoid the warning as suggested by Peter. Cc: Alan Cox <alan@linux.intel.com> Cc: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Peter Zijlstra <peterz@infradead.org> Signed-off-by: Ming Lei <ming.lei@canonical.com> --- drivers/tty/tty_mutex.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/drivers/tty/tty_mutex.c b/drivers/tty/tty_mutex.c index 69adc80..fecf592 100644 --- a/drivers/tty/tty_mutex.c +++ b/drivers/tty/tty_mutex.c @@ -10,7 +10,8 @@ * Getting the big tty mutex. */ -void __lockfunc tty_lock(struct tty_struct *tty) +static void __lockfunc tty_lock_nested(struct tty_struct *tty, + int subclass) { if (tty->magic != TTY_MAGIC) { printk(KERN_ERR "L Bad %p\n", tty); @@ -18,7 +19,12 @@ void __lockfunc tty_lock(struct tty_struct *tty) return; } tty_kref_get(tty); - mutex_lock(&tty->legacy_mutex); + mutex_lock_nested(&tty->legacy_mutex, subclass); +} + +void __lockfunc tty_lock(struct tty_struct *tty) +{ + tty_lock_nested(tty, 0); } EXPORT_SYMBOL(tty_lock); @@ -43,11 +49,14 @@ void __lockfunc tty_lock_pair(struct tty_struct *tty, { if (tty < tty2) { tty_lock(tty); - tty_lock(tty2); + tty_lock_nested(tty2, SINGLE_DEPTH_NESTING); } else { - if (tty2 && tty2 != tty) + int nested = 0; + if (tty2 && tty2 != tty) { tty_lock(tty2); - tty_lock(tty); + nested = SINGLE_DEPTH_NESTING; + } + tty_lock_nested(tty, nested); } } EXPORT_SYMBOL(tty_lock_pair); -- 1.7.9.5 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH] tty: tty_mutex: fix lockdep warning in tty_lock_pair(v1) 2012-05-22 1:58 [PATCH] tty: tty_mutex: fix lockdep warning in tty_lock_pair(v1) Ming Lei @ 2012-05-23 6:01 ` Ming Lei 2012-05-25 13:28 ` Peter Zijlstra 0 siblings, 1 reply; 8+ messages in thread From: Ming Lei @ 2012-05-23 6:01 UTC (permalink / raw) To: Greg Kroah-Hartman Cc: linux-kernel, Ming Lei, Alan Cox, Arnd Bergmann, Peter Zijlstra Hi, On Tue, May 22, 2012 at 9:58 AM, Ming Lei <ming.lei@canonical.com> wrote: > Commit d29f3ef39be4eec0362b985305fc526d9be318cf(tty_lock: > Localise the lock) introduces tty_lock_pair, in which > may cause lockdep warning because two locks with same lock > class are to be acquired one after another. > > This patch uses mutex_lock_nested annotation to avoid > the warning as suggested by Peter. Sorry, please ignore the patch because it misses the change on tty_unlock_pair, and the correct one should be [1]. Even though the patch is applied, there is still one related problem about mixing tty_lock_pair with tty_unlock and tty_lock. If tty locks are held by calling tty_lock_pair, then deadlock warning between legacy_mutex/1 and legacy_mutex may be triggered if tty_unlock(tty) and tty_lock(tty) are called later when tty < tty2, see tty_ldisc_release() in tty_release(). Thanks, -- Ming Lei [1], --- drivers/tty/tty_mutex.c | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/drivers/tty/tty_mutex.c b/drivers/tty/tty_mutex.c index 69adc80..c7f4523 100644 --- a/drivers/tty/tty_mutex.c +++ b/drivers/tty/tty_mutex.c @@ -10,7 +10,8 @@ * Getting the big tty mutex. */ -void __lockfunc tty_lock(struct tty_struct *tty) +static void __lockfunc tty_lock_nested(struct tty_struct *tty, + int subclass) { if (tty->magic != TTY_MAGIC) { printk(KERN_ERR "L Bad %p\n", tty); @@ -18,7 +19,12 @@ void __lockfunc tty_lock(struct tty_struct *tty) return; } tty_kref_get(tty); - mutex_lock(&tty->legacy_mutex); + mutex_lock_nested(&tty->legacy_mutex, subclass); +} + +void __lockfunc tty_lock(struct tty_struct *tty) +{ + tty_lock_nested(tty, 0); } EXPORT_SYMBOL(tty_lock); @@ -43,11 +49,14 @@ void __lockfunc tty_lock_pair(struct tty_struct *tty, { if (tty < tty2) { tty_lock(tty); - tty_lock(tty2); + tty_lock_nested(tty2, SINGLE_DEPTH_NESTING); } else { - if (tty2 && tty2 != tty) + int nested = 0; + if (tty2 && tty2 != tty) { tty_lock(tty2); - tty_lock(tty); + nested = SINGLE_DEPTH_NESTING; + } + tty_lock_nested(tty, nested); } } EXPORT_SYMBOL(tty_lock_pair); @@ -55,8 +64,13 @@ EXPORT_SYMBOL(tty_lock_pair); void __lockfunc tty_unlock_pair(struct tty_struct *tty, struct tty_struct *tty2) { - tty_unlock(tty); - if (tty2 && tty2 != tty) + if (tty < tty2) { tty_unlock(tty2); + tty_unlock(tty); + } else { + tty_unlock(tty); + if (tty2 && tty2 != tty) + tty_unlock(tty2); + } } EXPORT_SYMBOL(tty_unlock_pair); -- 1.7.9.5 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH] tty: tty_mutex: fix lockdep warning in tty_lock_pair(v1) 2012-05-23 6:01 ` Ming Lei @ 2012-05-25 13:28 ` Peter Zijlstra 2012-05-25 13:39 ` Peter Zijlstra 2012-05-25 13:47 ` Alan Cox 0 siblings, 2 replies; 8+ messages in thread From: Peter Zijlstra @ 2012-05-25 13:28 UTC (permalink / raw) To: Ming Lei; +Cc: Greg Kroah-Hartman, linux-kernel, Alan Cox, Arnd Bergmann On Wed, 2012-05-23 at 14:01 +0800, Ming Lei wrote: > Even though the patch is applied, there is still one related problem about > mixing tty_lock_pair with tty_unlock and tty_lock. If tty locks are > held by calling > tty_lock_pair, then deadlock warning between legacy_mutex/1 and legacy_mutex > may be triggered if tty_unlock(tty) and tty_lock(tty) are called later > when tty < tty2, > see tty_ldisc_release() in tty_release(). This just gives me a head-ache instead of explaining anything. Having looked at the source I still don't see how it could possibly work,.. So the problem with tty_release() -> tty_ldisc_release() is that tty_ldisc_release() does an unlock/lock of tty. However your tty_lock_pair() can still result in tty being subclass 1, see your else branch, nested case. That said, how is this not a real deadlock? If you rely on tty pointer ordering to avoid deadlocks, you always need to lock them in the same order. The unlock+lock in ldisc_release violates that. If we don't rely on the order, then why bother with the _pair() primitive? ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] tty: tty_mutex: fix lockdep warning in tty_lock_pair(v1) 2012-05-25 13:28 ` Peter Zijlstra @ 2012-05-25 13:39 ` Peter Zijlstra 2012-05-25 13:47 ` Alan Cox 1 sibling, 0 replies; 8+ messages in thread From: Peter Zijlstra @ 2012-05-25 13:39 UTC (permalink / raw) To: Ming Lei; +Cc: Greg Kroah-Hartman, linux-kernel, Alan Cox, Arnd Bergmann On Fri, 2012-05-25 at 15:28 +0200, Peter Zijlstra wrote: > On Wed, 2012-05-23 at 14:01 +0800, Ming Lei wrote: > > > Even though the patch is applied, there is still one related problem about > > mixing tty_lock_pair with tty_unlock and tty_lock. If tty locks are > > held by calling > > tty_lock_pair, then deadlock warning between legacy_mutex/1 and legacy_mutex > > may be triggered if tty_unlock(tty) and tty_lock(tty) are called later > > when tty < tty2, > > see tty_ldisc_release() in tty_release(). > > This just gives me a head-ache instead of explaining anything. > > Having looked at the source I still don't see how it could possibly > work,.. So the problem with tty_release() -> tty_ldisc_release() is that > tty_ldisc_release() does an unlock/lock of tty. > > However your tty_lock_pair() can still result in tty being subclass 1, > see your else branch, nested case. > > That said, how is this not a real deadlock? If you rely on tty pointer > ordering to avoid deadlocks, you always need to lock them in the same > order. The unlock+lock in ldisc_release violates that. > > If we don't rely on the order, then why bother with the _pair() > primitive? A git grep reveals tty_release() is the only user of tty_lock_pair() and while we hold tty_mutex over the tty_lock_pair() its not held over ldisc_release(). Thus afaict we can create the following deadlock: cpu-A cpu-B lock tty_mutex lock tty lock o_tty unlock tty_mutex unlock tty lock tty_mutex lock tty lock o_tty -> block on A lock tty -> block on B Also, what is that plain call to schedule() doing in tty_release()?! ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] tty: tty_mutex: fix lockdep warning in tty_lock_pair(v1) 2012-05-25 13:28 ` Peter Zijlstra 2012-05-25 13:39 ` Peter Zijlstra @ 2012-05-25 13:47 ` Alan Cox 2012-05-25 13:52 ` Peter Zijlstra 1 sibling, 1 reply; 8+ messages in thread From: Alan Cox @ 2012-05-25 13:47 UTC (permalink / raw) To: Peter Zijlstra; +Cc: Ming Lei, Greg Kroah-Hartman, linux-kernel, Arnd Bergmann > Having looked at the source I still don't see how it could possibly > work,.. So the problem with tty_release() -> tty_ldisc_release() is > that tty_ldisc_release() does an unlock/lock of tty. Yes it should do the pair, see the patch I posted restructing it, and the second one restructing it right. > However your tty_lock_pair() can still result in tty being subclass 1, > see your else branch, nested case. > > That said, how is this not a real deadlock? If you rely on tty pointer > ordering to avoid deadlocks, you always need to lock them in the same > order. The unlock+lock in ldisc_release violates that. Which was a bug. Alan ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] tty: tty_mutex: fix lockdep warning in tty_lock_pair(v1) 2012-05-25 13:47 ` Alan Cox @ 2012-05-25 13:52 ` Peter Zijlstra 2012-05-25 14:01 ` Alan Cox 0 siblings, 1 reply; 8+ messages in thread From: Peter Zijlstra @ 2012-05-25 13:52 UTC (permalink / raw) To: Alan Cox; +Cc: Ming Lei, Greg Kroah-Hartman, linux-kernel, Arnd Bergmann On Fri, 2012-05-25 at 14:47 +0100, Alan Cox wrote: > > Having looked at the source I still don't see how it could possibly > > work,.. So the problem with tty_release() -> tty_ldisc_release() is > > that tty_ldisc_release() does an unlock/lock of tty. > > Yes it should do the pair, see the patch I posted restructing it, and > the second one restructing it right. http://marc.info/?l=linux-kernel&m=133794355529930 That one? To what tree does one apply that? Because the tty_lock_pair() in Linus is still missing a lockdep annotation afaict. ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] tty: tty_mutex: fix lockdep warning in tty_lock_pair(v1) 2012-05-25 13:52 ` Peter Zijlstra @ 2012-05-25 14:01 ` Alan Cox 2012-05-25 14:08 ` Peter Zijlstra 0 siblings, 1 reply; 8+ messages in thread From: Alan Cox @ 2012-05-25 14:01 UTC (permalink / raw) To: Peter Zijlstra Cc: Alan Cox, Ming Lei, Greg Kroah-Hartman, linux-kernel, Arnd Bergmann On Fri, 25 May 2012 15:52:02 +0200 Peter Zijlstra <peterz@infradead.org> wrote: > On Fri, 2012-05-25 at 14:47 +0100, Alan Cox wrote: > > > Having looked at the source I still don't see how it could possibly > > > work,.. So the problem with tty_release() -> tty_ldisc_release() is > > > that tty_ldisc_release() does an unlock/lock of tty. > > > > Yes it should do the pair, see the patch I posted restructing it, and > > the second one restructing it right. > > http://marc.info/?l=linux-kernel&m=133794355529930 > > That one? To what tree does one apply that? Because the tty_lock_pair() > in Linus is still missing a lockdep annotation afaict. It applies on top of the other patches being tested in the thread on the lockdep warning. Alan ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] tty: tty_mutex: fix lockdep warning in tty_lock_pair(v1) 2012-05-25 14:01 ` Alan Cox @ 2012-05-25 14:08 ` Peter Zijlstra 0 siblings, 0 replies; 8+ messages in thread From: Peter Zijlstra @ 2012-05-25 14:08 UTC (permalink / raw) To: Alan Cox Cc: Alan Cox, Ming Lei, Greg Kroah-Hartman, linux-kernel, Arnd Bergmann On Fri, 2012-05-25 at 15:01 +0100, Alan Cox wrote: > > It applies on top of the other patches being tested in the thread on the > lockdep warning. You're really going to make me hunt and peck patches from lkml? /me looses interest and gets on with reducing his inbox. ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2012-05-25 14:08 UTC | newest] Thread overview: 8+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2012-05-22 1:58 [PATCH] tty: tty_mutex: fix lockdep warning in tty_lock_pair(v1) Ming Lei 2012-05-23 6:01 ` Ming Lei 2012-05-25 13:28 ` Peter Zijlstra 2012-05-25 13:39 ` Peter Zijlstra 2012-05-25 13:47 ` Alan Cox 2012-05-25 13:52 ` Peter Zijlstra 2012-05-25 14:01 ` Alan Cox 2012-05-25 14:08 ` Peter Zijlstra
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox