| From 4adef816984aaa39d5c862e686a2a000675de679 Mon Sep 17 00:00:00 2001 |
| From: =?UTF-8?q?Micha=C5=82=20Miros=C5=82aw?= <mirq-linux@rere.qmqm.pl> |
| Date: Mon, 8 Jun 2020 12:06:32 +0200 |
| Subject: [PATCH] ALSA: pcm: fix snd_pcm_link() lockdep splat |
| MIME-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| commit e18035cf5cb3d2bf8e4f4d350a23608bd208b934 upstream. |
| |
| Add and use snd_pcm_stream_lock_nested() in snd_pcm_link/unlink |
| implementation. The code is fine, but generates a lockdep complaint: |
| |
| ============================================ |
| WARNING: possible recursive locking detected |
| 5.7.1mq+ #381 Tainted: G O |
| -------------------------------------------- |
| pulseaudio/4180 is trying to acquire lock: |
| ffff888402d6f508 (&group->lock){-...}-{2:2}, at: snd_pcm_common_ioctl+0xda8/0xee0 [snd_pcm] |
| |
| but task is already holding lock: |
| ffff8883f7a8cf18 (&group->lock){-...}-{2:2}, at: snd_pcm_common_ioctl+0xe4e/0xee0 [snd_pcm] |
| |
| other info that might help us debug this: |
| Possible unsafe locking scenario: |
| |
| CPU0 |
| ---- |
| lock(&group->lock); |
| lock(&group->lock); |
| |
| *** DEADLOCK *** |
| |
| May be due to missing lock nesting notation |
| |
| 2 locks held by pulseaudio/4180: |
| #0: ffffffffa1a05190 (snd_pcm_link_rwsem){++++}-{3:3}, at: snd_pcm_common_ioctl+0xca0/0xee0 [snd_pcm] |
| #1: ffff8883f7a8cf18 (&group->lock){-...}-{2:2}, at: snd_pcm_common_ioctl+0xe4e/0xee0 [snd_pcm] |
| [...] |
| |
| Cc: stable@vger.kernel.org |
| Fixes: f57f3df03a8e ("ALSA: pcm: More fine-grained PCM link locking") |
| Signed-off-by: Michał Mirosław <mirq-linux@rere.qmqm.pl> |
| Link: https://lore.kernel.org/r/37252c65941e58473b1219ca9fab03d48f47e3e3.1591610330.git.mirq-linux@rere.qmqm.pl |
| |
| Signed-off-by: Takashi Iwai <tiwai@suse.de> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c |
| index cca448f62e29..f37cb1ebd728 100644 |
| --- a/sound/core/pcm_native.c |
| +++ b/sound/core/pcm_native.c |
| @@ -136,6 +136,16 @@ void snd_pcm_stream_lock_irq(struct snd_pcm_substream *substream) |
| } |
| EXPORT_SYMBOL_GPL(snd_pcm_stream_lock_irq); |
| |
| +static void snd_pcm_stream_lock_nested(struct snd_pcm_substream *substream) |
| +{ |
| + struct snd_pcm_group *group = &substream->self_group; |
| + |
| + if (substream->pcm->nonatomic) |
| + mutex_lock_nested(&group->mutex, SINGLE_DEPTH_NESTING); |
| + else |
| + spin_lock_nested(&group->lock, SINGLE_DEPTH_NESTING); |
| +} |
| + |
| /** |
| * snd_pcm_stream_unlock_irq - Unlock the PCM stream |
| * @substream: PCM substream |
| @@ -2028,7 +2038,7 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd) |
| snd_pcm_stream_unlock_irq(substream); |
| |
| snd_pcm_group_lock_irq(target_group, nonatomic); |
| - snd_pcm_stream_lock(substream1); |
| + snd_pcm_stream_lock_nested(substream1); |
| snd_pcm_group_assign(substream1, target_group); |
| refcount_inc(&target_group->refs); |
| snd_pcm_stream_unlock(substream1); |
| @@ -2044,7 +2054,7 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd) |
| |
| static void relink_to_local(struct snd_pcm_substream *substream) |
| { |
| - snd_pcm_stream_lock(substream); |
| + snd_pcm_stream_lock_nested(substream); |
| snd_pcm_group_assign(substream, &substream->self_group); |
| snd_pcm_stream_unlock(substream); |
| } |
| -- |
| 2.27.0 |
| |