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

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

 



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.

>  
>  	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.

> -	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);

-- 
Regards,

Laurent Pinchart



[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