Re: [PATCH for v5.18] v4l2-ctrls: unlink all subscribed events

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

 



On 21/03/2022 13:09, Laurent Pinchart wrote:
> Hi Hans,
> 
> Thank you for the patch.
> 
> On Thu, Mar 17, 2022 at 01:56:08PM +0100, Hans Verkuil wrote:
>> The v4l2_ctrl_handler_free() function must unlink all subscribed events
>> of the control handler that is being freed, but it only did so for the
>> controls owned by that control handler and not for the controls referred
>> to by that control handler. This leaves stale data in the ev_subs list
>> of those controls.
>>
>> The node list header is also properly initialized and list_del_init is
>> called instead of list_del to ensure that list_empty() can be used
>> to detect whether a v4l2_subscribed_event is part of a list or not.
>>
>> This makes v4l2_ctrl_del_event() more robust since it will not attempt
>> to find the control if the v4l2_subscribed_event has already been unlinked
>> from the control.
>>
>> Signed-off-by: Hans Verkuil <hverkuil-cisco@xxxxxxxxx>
>> ---
>>  drivers/media/v4l2-core/v4l2-ctrls-api.c  | 7 +++++--
>>  drivers/media/v4l2-core/v4l2-ctrls-core.c | 6 +++++-
>>  drivers/media/v4l2-core/v4l2-event.c      | 1 +
>>  3 files changed, 11 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/media/v4l2-core/v4l2-ctrls-api.c b/drivers/media/v4l2-core/v4l2-ctrls-api.c
>> index db9baa0bd05f..d64b22cb182c 100644
>> --- a/drivers/media/v4l2-core/v4l2-ctrls-api.c
>> +++ b/drivers/media/v4l2-core/v4l2-ctrls-api.c
>> @@ -1159,13 +1159,16 @@ static int v4l2_ctrl_add_event(struct v4l2_subscribed_event *sev,
>>  
>>  static void v4l2_ctrl_del_event(struct v4l2_subscribed_event *sev)
>>  {
>> -	struct v4l2_ctrl *ctrl = v4l2_ctrl_find(sev->fh->ctrl_handler, sev->id);
>> +	struct v4l2_ctrl *ctrl = NULL;
>> +
>> +	if (!list_empty(&sev->node))
>> +		ctrl = v4l2_ctrl_find(sev->fh->ctrl_handler, sev->id);
>>  
>>  	if (!ctrl)
>>  		return;
> 
> I'd go for
> 
> 	if (list_empty(&sdev->node))
> 		return;
> 
> 	ctrl = v4l2_ctrl_find(sev->fh->ctrl_handler, sev->id);
> 	if (!ctrl)
> 		return;
> 
> and drop the initialization of ctrl to NULL, it's easier to read.

Good point, that's much better.

> 
>>  
>>  	v4l2_ctrl_lock(ctrl);
> 
> v4l2_ctrl_lock() simply calls
> 
> 	mutex_lock(ctrl->handler->lock);
> 
> Is there any case where ctrl->handler != sev->fh->ctrl_handler ? If not
> this could be simplified to drop the v4l2_ctrl_find() call.

Yes, ctrl->handler might be different from sev->fh->ctrl_handler. Specifically
for inherited controls, in fact.

Regards,

	Hans

> 
>> -	list_del(&sev->node);
>> +	list_del_init(&sev->node);
>>  	v4l2_ctrl_unlock(ctrl);
>>  }
>>  
>> diff --git a/drivers/media/v4l2-core/v4l2-ctrls-core.c b/drivers/media/v4l2-core/v4l2-ctrls-core.c
>> index 8968cec8454e..1a9d60cb119c 100644
>> --- a/drivers/media/v4l2-core/v4l2-ctrls-core.c
>> +++ b/drivers/media/v4l2-core/v4l2-ctrls-core.c
>> @@ -10,6 +10,7 @@
>>  #include <linux/slab.h>
>>  #include <media/v4l2-ctrls.h>
>>  #include <media/v4l2-event.h>
>> +#include <media/v4l2-fh.h>
>>  #include <media/v4l2-fwnode.h>
>>  
>>  #include "v4l2-ctrls-priv.h"
>> @@ -1165,13 +1166,16 @@ void v4l2_ctrl_handler_free(struct v4l2_ctrl_handler *hdl)
>>  	/* Free all nodes */
>>  	list_for_each_entry_safe(ref, next_ref, &hdl->ctrl_refs, node) {
>>  		list_del(&ref->node);
>> +		list_for_each_entry_safe(sev, next_sev, &ref->ctrl->ev_subs, node)
>> +			if (sev->fh->ctrl_handler == hdl)
>> +				list_del_init(&sev->node);
> 
> I have no idea how control reference works or what they're used for, so
> I can't tell if this is safe without locking ref->ctrl.
> 
>>  		kfree(ref);
>>  	}
>>  	/* Free all controls owned by the handler */
>>  	list_for_each_entry_safe(ctrl, next_ctrl, &hdl->ctrls, node) {
>>  		list_del(&ctrl->node);
>>  		list_for_each_entry_safe(sev, next_sev, &ctrl->ev_subs, node)
>> -			list_del(&sev->node);
>> +			list_del_init(&sev->node);
>>  		kvfree(ctrl);
>>  	}
>>  	kvfree(hdl->buckets);
>> diff --git a/drivers/media/v4l2-core/v4l2-event.c b/drivers/media/v4l2-core/v4l2-event.c
>> index c5ce9f11ad7b..2fd9f7187c04 100644
>> --- a/drivers/media/v4l2-core/v4l2-event.c
>> +++ b/drivers/media/v4l2-core/v4l2-event.c
>> @@ -246,6 +246,7 @@ int v4l2_event_subscribe(struct v4l2_fh *fh,
>>  	sev->fh = fh;
>>  	sev->ops = ops;
>>  	sev->elems = elems;
>> +	INIT_LIST_HEAD(&sev->node);
>>  
>>  	mutex_lock(&fh->subscribe_lock);
> 




[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