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@suse.de --- 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); }
/**