Re: [RFC PATCH] radio-mr800: locking fixes

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

 



On Mon, Oct 18, 2010 at 9:38 AM, Hans Verkuil <hverkuil@xxxxxxxxx> wrote:
>
>> On Sun, Oct 17, 2010 at 8:26 AM, Hans Verkuil <hverkuil@xxxxxxxxx> wrote:
>>> - serialize the suspend and resume functions using the global lock.
>>> - do not call usb_autopm_put_interface after a disconnect.
>>> - fix a race when disconnecting the device.
>>>
>>> Reported-by: David Ellingsworth <david@xxxxxxxxxxxxxxxxx>
>>> Signed-off-by: Hans Verkuil <hverkuil@xxxxxxxxx>
>>> ---
>>>  drivers/media/radio/radio-mr800.c |   17 ++++++++++++++---
>>>  1 files changed, 14 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/drivers/media/radio/radio-mr800.c
>>> b/drivers/media/radio/radio-mr800.c
>>> index 2f56b26..b540e80 100644
>>> --- a/drivers/media/radio/radio-mr800.c
>>> +++ b/drivers/media/radio/radio-mr800.c
>>> @@ -284,9 +284,13 @@ static void usb_amradio_disconnect(struct
>>> usb_interface *intf)
>>>        struct amradio_device *radio =
>>> to_amradio_dev(usb_get_intfdata(intf));
>>>
>>>        mutex_lock(&radio->lock);
>>> +       /* increase the device node's refcount */
>>> +       get_device(&radio->videodev.dev);
>>>        v4l2_device_disconnect(&radio->v4l2_dev);
>>> -       mutex_unlock(&radio->lock);
>>>        video_unregister_device(&radio->videodev);
>>> +       mutex_unlock(&radio->lock);
>>> +       /* decrease the device node's refcount, allowing it to be
>>> released */
>>> +       put_device(&radio->videodev.dev);
>>>  }
>>
>> Hans, I understand the use of get/put_device here.. but can you
>> explain to me what issue you are trying to solve?
>> video_unregister_device does not have to be synchronized with anything
>> else. Thus, it is perfectly safe to call video_unregister_device while
>> not holding the device lock. Your prior implementation here was
>> correct.
>
> This the original sequence:
>
>       mutex_lock(&radio->lock);
>       v4l2_device_disconnect(&radio->v4l2_dev);
>       mutex_unlock(&radio->lock);
>       video_unregister_device(&radio->videodev);
>
> The problem with this is that userspace can call open or ioctl after the
> unlock and before the device node is marked unregistered by
> video_unregister_device.
>
> Once you disconnect you want to block all access (except the release call).
> What my patch does is to move the video_unregister_device call inside the
> lock, but then I have to guard against the release being called before the
> unlock by increasing the refcount.
>
> I have ideas to improve on this as this gets hairy when you have multiple
> device nodes, but I wait with that until the next kernel cycle.
>
> Regards,
>
>         Hans
>

I think you're trying to solve a problem that doesn't exist.
To be a little more specific we have the following:

1. video_register_device - increments device refcount
2. video_unregister_device - decrements device refcount
3. v4l2_open - increments device refcount
4. v4l2_release - decrements device refcount

Keeping this in mind, the release callback of video_device is called
only when the device count reaches 0.

So under normal operation we have:

1. video_register_device -> device refcount incremented to 1
2. v4l2_open -> device refcount incremented to 2
3. v4l2_release -> device refcount decremented to 1
4. disconnect callback: video_unregister_device -> device refcount
decremented to 0 & release callback called.

If the user disconnects the device while it's open we have the following:

1. video_register_device -> device refcount incremented to 1
2. v4l2_open -> device refcount incremented to 2
3. disconnect callback: video_unregister_device -> device refcount
decremented to 1
4. v4l2_release -> device refcount decremented to 0 & release callback called.

In the above case, once video_unregister_device has been called, calls
to open no longer will work. However, the user holding the currently
open file handle can still call ioctl and other callbacks, but those
should be met with an -EIO, forcing them to close the open handle. The
original code did this by using the usb device as an indicator to see
if the device was still connected, as this functionality was not in
v4l2_core. On the other hand, v4l2_core could do this for us, just by
checking if the device is still registered.

As you can see from the above, there are no race conditions here.

Regards,

David Ellingsworth
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux