]> nv-tegra.nvidia Code Review - linux-4.9.git/commitdiff
Revert "media: v4l: event: Prevent freeing event subscriptions while accessed"
authorKetan Patil <ketanp@nvidia.com>
Mon, 29 Oct 2018 07:59:59 +0000 (13:29 +0530)
committerKetan Patil <ketanp@nvidia.com>
Mon, 29 Oct 2018 07:59:59 +0000 (13:29 +0530)
This reverts commit ec964c3c00457e7ce6b633a33d1c6b61e0091557.

drivers/media/v4l2-core/v4l2-event.c
drivers/media/v4l2-core/v4l2-fh.c
include/media/v4l2-fh.h

index 567d86835f0011fda388c721af84c7a44d6ac193..8d3171c6bee8e5be0d5f06d1e104151b4ee06485 100644 (file)
@@ -119,6 +119,14 @@ static void __v4l2_event_queue_fh(struct v4l2_fh *fh, const struct v4l2_event *e
        if (sev == NULL)
                return;
 
+       /*
+        * If the event has been added to the fh->subscribed list, but its
+        * add op has not completed yet elems will be 0, treat this as
+        * not being subscribed.
+        */
+       if (!sev->elems)
+               return;
+
        /* Increase event sequence number on fh. */
        fh->sequence++;
 
@@ -204,7 +212,6 @@ int v4l2_event_subscribe(struct v4l2_fh *fh,
        struct v4l2_subscribed_event *sev, *found_ev;
        unsigned long flags;
        unsigned i;
-       int ret = 0;
 
        if (sub->type == V4L2_EVENT_ALL)
                return -EINVAL;
@@ -222,36 +229,31 @@ int v4l2_event_subscribe(struct v4l2_fh *fh,
        sev->flags = sub->flags;
        sev->fh = fh;
        sev->ops = ops;
-       sev->elems = elems;
-
-       mutex_lock(&fh->subscribe_lock);
 
        spin_lock_irqsave(&fh->vdev->fh_lock, flags);
        found_ev = v4l2_event_subscribed(fh, sub->type, sub->id);
+       if (!found_ev)
+               list_add(&sev->list, &fh->subscribed);
        spin_unlock_irqrestore(&fh->vdev->fh_lock, flags);
 
        if (found_ev) {
-               /* Already listening */
                kfree(sev);
-               goto out_unlock;
+               return 0; /* Already listening */
        }
 
        if (sev->ops && sev->ops->add) {
-               ret = sev->ops->add(sev, elems);
+               int ret = sev->ops->add(sev, elems);
                if (ret) {
-                       kfree(sev);
-                       goto out_unlock;
+                       sev->ops = NULL;
+                       v4l2_event_unsubscribe(fh, sub);
+                       return ret;
                }
        }
 
-       spin_lock_irqsave(&fh->vdev->fh_lock, flags);
-       list_add(&sev->list, &fh->subscribed);
-       spin_unlock_irqrestore(&fh->vdev->fh_lock, flags);
-
-out_unlock:
-       mutex_unlock(&fh->subscribe_lock);
+       /* Mark as ready for use */
+       sev->elems = elems;
 
-       return ret;
+       return 0;
 }
 EXPORT_SYMBOL_GPL(v4l2_event_subscribe);
 
@@ -290,8 +292,6 @@ int v4l2_event_unsubscribe(struct v4l2_fh *fh,
                return 0;
        }
 
-       mutex_lock(&fh->subscribe_lock);
-
        spin_lock_irqsave(&fh->vdev->fh_lock, flags);
 
        sev = v4l2_event_subscribed(fh, sub->type, sub->id);
@@ -309,8 +309,6 @@ int v4l2_event_unsubscribe(struct v4l2_fh *fh,
        if (sev && sev->ops && sev->ops->del)
                sev->ops->del(sev);
 
-       mutex_unlock(&fh->subscribe_lock);
-
        kfree(sev);
 
        return 0;
index 0c5e690705861381dd9afdf71649dcc7199de73a..c183f0996fa1ce3b394b4bd2cb700574842e7e80 100644 (file)
@@ -50,7 +50,6 @@ void v4l2_fh_init(struct v4l2_fh *fh, struct video_device *vdev)
        INIT_LIST_HEAD(&fh->available);
        INIT_LIST_HEAD(&fh->subscribed);
        fh->sequence = -1;
-       mutex_init(&fh->subscribe_lock);
 }
 EXPORT_SYMBOL_GPL(v4l2_fh_init);
 
@@ -96,7 +95,6 @@ void v4l2_fh_exit(struct v4l2_fh *fh)
                return;
        v4l_disable_media_source(fh->vdev);
        v4l2_event_unsubscribe_all(fh);
-       mutex_destroy(&fh->subscribe_lock);
        fh->vdev = NULL;
 }
 EXPORT_SYMBOL_GPL(v4l2_fh_exit);
index d2671606cb5d918758b88f00e8cbcba8c9ecc575..e19e6246e21c85dc78fa545b95e0f62b011026bb 100644 (file)
@@ -42,13 +42,10 @@ struct v4l2_ctrl_handler;
  * @prio: priority of the file handler, as defined by &enum v4l2_priority
  *
  * @wait: event' s wait queue
- * @subscribe_lock: serialise changes to the subscribed list; guarantee that
- *                 the add and del event callbacks are orderly called
  * @subscribed: list of subscribed events
  * @available: list of events waiting to be dequeued
  * @navailable: number of available events at @available list
  * @sequence: event sequence number
- *
  * @m2m_ctx: pointer to &struct v4l2_m2m_ctx
  */
 struct v4l2_fh {
@@ -59,7 +56,6 @@ struct v4l2_fh {
 
        /* Events */
        wait_queue_head_t       wait;
-       struct mutex            subscribe_lock;
        struct list_head        subscribed;
        struct list_head        available;
        unsigned int            navailable;