[PATCH] ALSA: core: Fix double calls of snd_card_free() via devres

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



At the transition to the devres-managed card release, we've put the
check of double-free at trigger_card_release().  But this wasn't
enough, as the code path calls snd_card_free() again, and it would
lead to the doubly snd_card_free() calls.

Actually the v1 patch was correct to handle this, but I forgot that
corner case and moved the check to the more obvious place as I thought
it's clearer.  But, as usual, devils live in details.

This patch corrects the check of the double-free to the right place,
with a bit more comments.

Fixes: e8ad415b7a55 ("ALSA: core: Add managed card creation")
Signed-off-by: Takashi Iwai <tiwai@xxxxxxx>
---
 sound/core/init.c | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/sound/core/init.c b/sound/core/init.c
index e985185ebc91..ac335f5906c6 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -605,6 +605,15 @@ int snd_card_free(struct snd_card *card)
 	DECLARE_COMPLETION_ONSTACK(released);
 	int ret;
 
+	/* The call of snd_card_free() is allowed from various code paths;
+	 * a manual call from the driver and the call via devres_free, and
+	 * we need to avoid double-free. Moreover, the release via devres
+	 * may call snd_card_free() twice due to its nature, we need to have
+	 * the check here at the beginning.
+	 */
+	if (card->releasing)
+		return 0;
+
 	card->release_completion = &released;
 	ret = snd_card_free_when_closed(card);
 	if (ret)
@@ -813,10 +822,7 @@ EXPORT_SYMBOL_GPL(snd_card_add_dev_attr);
 
 static void trigger_card_free(void *data)
 {
-	struct snd_card *card = data;
-
-	if (!card->releasing)
-		snd_card_free(data);
+	snd_card_free(data);
 }
 
 /**
-- 
2.26.2




[Index of Archives]     [ALSA User]     [Linux Audio Users]     [Pulse Audio]     [Kernel Archive]     [Asterisk PBX]     [Photo Sharing]     [Linux Sound]     [Video 4 Linux]     [Gimp]     [Yosemite News]

  Powered by Linux