V4L/DVB (9690): gspca: Lock the subdrivers via module_get/put.
authorJean-Francois Moine <moinejf@free.fr>
Tue, 18 Nov 2008 18:52:31 +0000 (15:52 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Mon, 24 Nov 2008 14:01:23 +0000 (12:01 -0200)
The previous subdriver protection against rmmod was done via the
file operations table in the device descriptor. On device disconnection
while streaming, the device structure was freed at close time, and the
module_put still used the module name in the freed area.
Now, explicit module get/put are done on open and close.

Signed-off-by: Jean-Francois Moine <moinejf@free.fr>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/video/gspca/gspca.c
drivers/media/video/gspca/gspca.h

index f28d2f4aceac5f22a710c8c09d9f56139f3ecc7e..a565f37648378df80b107a7c62bf9a7df9137e94 100644 (file)
@@ -874,6 +874,13 @@ static int dev_open(struct inode *inode, struct file *file)
                ret = -EBUSY;
                goto out;
        }
+
+       /* protect the subdriver against rmmod */
+       if (!try_module_get(gspca_dev->module)) {
+               ret = -ENODEV;
+               goto out;
+       }
+
        gspca_dev->users++;
 
        /* one more user */
@@ -920,6 +927,7 @@ static int dev_close(struct inode *inode, struct file *file)
                gspca_dev->memory = GSPCA_MEMORY_NO;
        }
        file->private_data = NULL;
+       module_put(gspca_dev->module);
        mutex_unlock(&gspca_dev->queue_lock);
 
        PDEBUG(D_STREAM, "close done");
@@ -1870,9 +1878,8 @@ int gspca_dev_probe(struct usb_interface *intf,
        /* init video stuff */
        memcpy(&gspca_dev->vdev, &gspca_template, sizeof gspca_template);
        gspca_dev->vdev.parent = &dev->dev;
-       memcpy(&gspca_dev->fops, &dev_fops, sizeof gspca_dev->fops);
-       gspca_dev->vdev.fops = &gspca_dev->fops;
-       gspca_dev->fops.owner = module;         /* module protection */
+       gspca_dev->vdev.fops = &dev_fops;
+       gspca_dev->module = module;
        gspca_dev->present = 1;
        ret = video_register_device(&gspca_dev->vdev,
                                  VFL_TYPE_GRABBER,
index c35d7b97112fc4f52b0b43da2d78dff99e216f5c..2ae1ad7c1483ea8d235f0c9396cbb4f75c3ea632 100644 (file)
@@ -121,7 +121,7 @@ struct gspca_frame {
 
 struct gspca_dev {
        struct video_device vdev;       /* !! must be the first item */
-       struct file_operations fops;
+       struct module *module;          /* subdriver handling the device */
        struct usb_device *dev;
        struct kref kref;
        struct file *capt_file;         /* file doing video capture */