[alsa-devel] [PATCH 2/7] ALSA: core: Add managed card creation
Takashi Sakamoto
o-takashi at sakamocchi.jp
Thu Oct 4 07:33:44 CEST 2018
Hi,
On Oct 4 2018 00:37, Takashi Iwai wrote:
> On Wed, 03 Oct 2018 17:02:59 +0200,
> Takashi Sakamoto wrote:
>>
>> Hi,
>>
>> On Oct 3 2018 22:14, Takashi Sakamoto wrote:
>>> On Oct 3 2018 19:30, Takashi Iwai wrote:
>>>> On Wed, 03 Oct 2018 10:12:34 +0200,
>>>>> I've investigated to use the new function, 'snd_devm_card_new()', and
>>>>> have a concern about timing to release memory object for sound card
>>>>> instance (and tailing private data) in error path between calls of the
>>>>> function and 'snd_card_register()'.
>>>>>
>>>>> In the error path, 'snd_card_free()' is called to release instances
>>>>> associated to the sound card instance as expected, however memory object
>>>>> for the sound card instance is not released yet because in usual cases
>>>>> associated device structure does not lost its reference count in this
>>>>> timing. It's released when the associated device is removed. This means
>>>>> that the memory object remains against its practicality during lifetime
>>>>> of the device.
>>>>>
>>>>> This is not a bug itself, so I have no opposition to this patchset. But
>>>>> it's reasonable for us to have a bit time to consider about it, IMO.
>>>>
>>>> Well, it's exactly same as the usual devm_kzalloc() & co, which have
>>>> been already deployed at various places (even you posted a new patch
>>>> series for using them :) The card memory is tied with the device, and
>>>> it's natural to align with the lifetime of the device.
>>>
>>> I have this concern against the usage of devres for a long time.
>>>
>>> A device can be referred by several handlers; e.g. character device
>>> driver and kernel driver. An example is USB devices. Userspace
>>> applications can transfer message to the device via character device.
>>> At the same time, iface driver in kernel land can do the same work.
>>>
>>> The lifetime of device is apparently different from each of the handler.
>>> Even if kernel driver returns negative value in its .probe callback, the
>>> other handlers can refer to and use it.
>>>
>>> If the kernel driver leave the devm-allocated memory in error path, it
>>> remains till all of the handler release its reference to the device.
>>> Even it the memory objects are maintained by devres, several small parts
>>> of kernel logical space is unavailable. This is similar to memory leak,
>>> in my view.
>>
>> I wrote a patch to e06afb87065c (HEAD of 'topic/devres' branch) for this
>> purpose. I've not tested thoroughly but expect it solves the above issue.
>>
>> ======== 8< --------
>>
>> >From 2ef56174ea3c07eb5d6c2adb60573321c04a02af Mon Sep 17 00:00:00 2001
>> From: Takashi Sakamoto <o-takashi at sakamocchi.jp>
>> Date: Wed, 3 Oct 2018 23:44:43 +0900
>> Subject: [PATCH] ALSA: core: release memory object for sound card immediately
>> in error path for a case of devm usage
>>
>> Drivers can snd_card_free() in error path between calls of
>> snd_devm_card_new() and snd_card_register(), In this case,
>> memory object for sound card structure is not deallocated
>> immediately because it's associated to target device by
>> devres framework. The memory object remains till the target
>> device is released. This looks like memory leak.
>
> Not really, this is *intentional* and designed behavior.
>
> Imagine the case if you have a device-managed irq handler and a
> device-managed IO memory. They are not freed at snd_card_free() call
> time, but at a later stage of devres release. Hence the *all*
> devres-managed resources have to be released there.
Indeed. This patch includes no extra care to your patch 01/03/04/05
because I've already proposed a solution to use of reference
counting without associating sound card instance to target device.
I decide not to use 'snd_devm_card_new()' for all drivers in ALSA
firewire stack because of several issues I've addressed. Thanks for
your time to discuss about them.
>> This commit postpones association of the memory object to
>> target device till a call of snd_card_register(). In error
>> path, a call of snd_card_free() releases the memory object
>> in the last part of snd_card_do_free().
>> ---
>> sound/core/init.c | 20 ++++++++++----------
>> 1 file changed, 10 insertions(+), 10 deletions(-)
>>
>> diff --git a/sound/core/init.c b/sound/core/init.c
>> index 2eade57db4b4..49cb22a735c1 100644
>> --- a/sound/core/init.c
>> +++ b/sound/core/init.c
>> @@ -272,7 +272,6 @@ int snd_devm_card_new(struct device *parent, int idx, const char *xid,
>> return err;
>> }
>>
>> - devres_add(parent, card);
>> *card_ret = card;
>> return 0;
>> }
>> @@ -569,6 +568,8 @@ static int snd_card_do_free(struct snd_card *card)
>> complete(card->release_completion);
>> if (!card->managed)
>> kfree(card);
>> + else if (!devres_find(card->dev, __snd_card_release, NULL, NULL))
>> + devres_free(card);
>> return 0;
>> }
>>
>> @@ -849,15 +850,6 @@ int snd_card_register(struct snd_card *card)
>> if (err < 0)
>> return err;
>> card->registered = true;
>> - } else {
>> - if (card->managed)
>> - devm_remove_action(card->dev, trigger_card_free, card);
>> - }
>> -
>> - if (card->managed) {
>> - err = devm_add_action(card->dev, trigger_card_free, card);
>> - if (err < 0)
>> - return err;
>> }
>>
>> if ((err = snd_device_register_all(card)) < 0)
>> @@ -887,6 +879,14 @@ int snd_card_register(struct snd_card *card)
>> if (snd_mixer_oss_notify_callback)
>> snd_mixer_oss_notify_callback(card, SND_MIXER_OSS_NOTIFY_REGISTER);
>> #endif
>> + if (card->managed &&
>> + !devres_find(card->dev, __snd_card_release, NULL, NULL)) {
>> + err = devm_add_action(card->dev, trigger_card_free, card);
>> + if (err < 0)
>> + return err;
>> + devres_add(card->dev, card);
>> + }
>> +
>> return 0;
>> }
>> EXPORT_SYMBOL(snd_card_register);
>> --
>> 2.17.1
Regards
Takashi Sakamoto
More information about the Alsa-devel
mailing list