summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJean-Francois Moine <moinejf@free.fr>2008-11-18 19:52:31 +0100
committerJean-Francois Moine <moinejf@free.fr>2008-11-18 19:52:31 +0100
commitffa812c1a2fa46e3b894155e598c0e6e0d51b2f1 (patch)
tree2a2e73ff75bf2889a677c10ba2f65f532206ddef
parent7830a441c0d4f9753dea8a72466091346ded739b (diff)
downloadmediapointer-dvb-s2-ffa812c1a2fa46e3b894155e598c0e6e0d51b2f1.tar.gz
mediapointer-dvb-s2-ffa812c1a2fa46e3b894155e598c0e6e0d51b2f1.tar.bz2
gspca: Lock the subdrivers via module_get/put.
From: Jean-Francois Moine <moinejf@free.fr> 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. Priority: high Signed-off-by: Jean-Francois Moine <moinejf@free.fr>
-rw-r--r--linux/drivers/media/video/gspca/gspca.c13
-rw-r--r--linux/drivers/media/video/gspca/gspca.h2
2 files changed, 11 insertions, 4 deletions
diff --git a/linux/drivers/media/video/gspca/gspca.c b/linux/drivers/media/video/gspca/gspca.c
index d78835584..4e3833a00 100644
--- a/linux/drivers/media/video/gspca/gspca.c
+++ b/linux/drivers/media/video/gspca/gspca.c
@@ -909,6 +909,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 */
@@ -955,6 +962,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");
@@ -1906,9 +1914,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,
diff --git a/linux/drivers/media/video/gspca/gspca.h b/linux/drivers/media/video/gspca/gspca.h
index 35f463c95..4ff9b8105 100644
--- a/linux/drivers/media/video/gspca/gspca.h
+++ b/linux/drivers/media/video/gspca/gspca.h
@@ -125,7 +125,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 */