Re: Crash on unplug with the uvc driver in linuxtv/staging/for_v3.1

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

 



Hi Hans,

On Monday 13 June 2011 13:10:57 Hans Verkuil wrote:
> On Monday, June 13, 2011 11:41:42 Laurent Pinchart wrote:
> > On Saturday 11 June 2011 11:16:10 Laurent Pinchart wrote:
> > > On Thursday 09 June 2011 13:22:03 Hans de Goede wrote:
> > > > Hi,
> > > > 
> > > > When I unplug a uvc camera *while streaming* I get:
> > > > 
> > > > [15824.809741] BUG: unable to handle kernel NULL pointer dereference
> > > > at (null)
> > > 
> > > [snip]
> > > 
> > > > I've not tested if this also impacts 3.0!!
> > > 
> > > It probably does. Thanks for the report. I'll fix it.
> > 
> > It does. Fixing the problem turns to be more complex than expected.
> > 
> > The crash is caused by media entities life time management issues.
> > 
> > Entities associated with video device nodes are unregistered in
> > video_unregister_device(). This removes the entity from its parent's
> > entities list, and sets the entity's parent to NULL.
> > 
> > Entities also get/put references to their parent's module through
> > media_entity_get() and media_entity_put(). Those functions are called in
> > the open and release handlers of video device nodes and subdev device
> > nodes. The reason behind this is to avoid a parent module from being
> > removed while a subdev is opened, as closing a subdev can call to the
> > parent's module through board code.
> > 
> > When a UVC device is unplugged while streaming, the uvcvideo driver will
> > call video_unregister_device() in the disconnect handler. This will in
> > turn call media_device_unregister_entity() which sets the entity's
> > parent to NULL. When the user then closes open video device nodes,
> > v4l2_release() calls media_entity_put() which tries to dereference
> > entity->parent, and oopses.
> > 
> > I've tried to move the media_device_unregister_entity() call from
> > video_unregister_device() to v4l2_device_release() (called when the last
> > reference to the video device is released). media_entity_put() is then
> > called before the entity is unregistered, but that results in a
> > different oops: as this happens after the USB disconnect callback is
> > called, entity->parent->dev-
> > 
> > >driver is now NULL, and trying to access
> > >entity->parent->dev->driver->owner
> > 
> > to decrement the module use count oopses.
> > 
> > One possible workaround is to remove
> > media_entity_get()/media_entity_put() calls from v4l2-dev.c. As the
> > original purpose of those functions was to avoid a parent module from
> > being removed while still accessible through board code, and all
> > existing MC-enabled drivers register video device nodes with the owner
> > equal to the entity's parent's module, we can safely do it.
> > 
> > I'd rather implement a proper solution though, but that's not
> > straightforward. We short-circuit the kernel reference management by
> > going through board code. There's something fundamentally wrong in the
> > way we manage subdevs and device/module reference counts. I'm not sure
> > where the proper fix should go to though.
> 
> Hmm. Tricky.
> 
> media_device_unregister_entity() is definitely called in the wrong place.
> It should move to v4l2_device_release().

Agreed.

> I wonder why media_entity_get/put are called in v4l2_open and v4l2_release.
> That should be in __video_register_device and v4l2_device_release as far as
> I can see.
> 
> Just closing a device node shouldn't be cause for changing the module's
> refcount, that device node registration and the release after
> unregistration.

If you moved media_entity_get/put in the registration and unregistration 
functions, removing the uvcvideo module would become completely impossible if 
a driver is plugged in. uvcvideo registers a video device node, which would 
then increase the refcount on the module and lock it in in memory until the 
device is unplugged.

> I also wonder whether instead of refcounting the module in
> media_entity_get/put you should refcount the device (entity->parent->dev).

Increasing the device parent won't prevent the module from being unloaded. You 
can unload a module even if devices are bound to it.

> I have to admit that I don't quite understand why the USB disconnect zeroes
> entity->parent->dev->driver.
> 
> I hope this gives some ideas...

The easiest workaround is still to remove the media_entity_get()/put() calls 
from v4l2-dev.c. Those function have been introduced to fix a subdev-specific 
problem and are used for video nodes as well, but they're not needed there for 
now. This isn't a long-term fix though.

-- 
Regards,

Laurent Pinchart
--
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