The patch pertains to the source code of the video_open() function
in drivers/media/video/videodev.c in the linux 2.4.19 stable source.
In the original code of video_open() there are two small bugs:
(1) the counter of the module is not incremented _before_ the
file->f_op->open(inode,file) function call, but only before
the vfl->open() one.
(2) the increment of the variable vfl->users is incoherent with the
decrement of the same variable in the function video_release().
A brief analysis of the source code and of the patch reveals
that it is so, but i will not enter into details.
Since the bug was such that the author's intentions were
incomprehensible, here are two alternative patches: either one or
the other!
Infact, the bug (1) is fixed in the same way both in patch1 and
in patch2, but there are two solutions of the bug (2):
a) patch1.diff: multiple video_open() of the same device are not
allowed.
b) patch2.diff: multiple opens are allowed when the new interface
(struct file_operation*) is used; and multiple opens aren't
allowed when the old interface is used. See the comments.
The patches are given below (plain text, diff -u output).
Luca Risolia <[EMAIL PROTECTED]>
******************* PATCH1.diff ***************************
--- drivers/media/video/videodev.c.orig Sat Nov 9 05:34:24 2002
+++ drivers/media/video/videodev.c Sun Nov 10 12:52:30 2002
@@ -13,7 +13,9 @@
*
* Fixes: 20000516 Claudio Matsuoka <[EMAIL PROTECTED]>
* - Added procfs support
- */
+ * 20021109 Luca Risolia <[EMAIL PROTECTED]>
+ * - Bug fix in video_open()
+*/
#include <linux/config.h>
#include <linux/version.h>
@@ -140,29 +142,38 @@
goto unlock_out;
}
}
+
+ /* Multiple opens are not allowed */
+ if(vfl->users) {
+ err = -EBUSY;
+ goto unlock_out;
+ }
+
+ if(vfl->owner)
+ __MOD_INC_USE_COUNT(vfl->owner);
+
+ /* In case every open call below sleep */
+ vfl->users++;
+
if (vfl->fops) {
struct file_
s = file->f_op;
file->f_op = fops_get(vfl->fops);
- if(file->f_op->open)
+ if(file->f_op->open) {
err = file->f_op->open(inode,file);
- if (err) {
- fops_put(file->f_op);
- file->f_op = fops_get(old_fops);
- }
+ if (err) {
+ vfl->users--;
+ if(vfl->owner)
+ __MOD_DEC_USE_COUNT(vfl->owner);
+ fops_put(file->f_op);
+ file->f_op = fops_get(old_fops);
+ }
+ }
fops_put(old_fops);
goto unlock_out;
}
- if(vfl->users) {
- err = -EBUSY;
- goto unlock_out;
- }
- vfl->users++; /* In case vfl->open sleeps */
-
- if(vfl->owner)
- __MOD_INC_USE_COUNT(vfl->owner);
-
+
if (vfl->open) {
err=vfl->open(vfl,0); /* Tell the device it is open */
if (err) {
********************* PATCH2.diff ***************************
--- drivers/media/video/videodev.c.orig Sat Nov 9 05:34:24 2002
+++ drivers/media/video/videodev.c Sun Nov 10 12:52:56 2002
@@ -13,6 +13,8 @@
*
* Fixes: 20000516 Claudio Matsuoka <[EMAIL PROTECTED]>
* - Added procfs support
+ * 20021109 Luca Risolia <[EMAIL PROTECTED]>
+ * - Bug fix in video_open()
*/
#include <linux/config.h>
@@ -140,30 +142,39 @@
goto unlock_out;
}
}
+
+ if(vfl->owner)
+ __MOD_INC_USE_COUNT(vfl->owner);
+
+ /* New interface: multiple opens allowed */
if (vfl->fops) {
struct file_operations *old_fops;
old_fops = file->f_op;
file->f_op = fops_get(vfl->fops);
- if(file->f_op->open)
+ if(file->f_op->open) {
+ vfl->users++;
err = file->f_op->open(inode,file);
- if (err) {
- fops_put(file->f_op);
- file->f_op = fops_get(old_fops);
- }
+ if (err) {
+ vfl->users-
OUNT(vfl->owner);
+ fops_put(file->f_op);
+ file->f_op = fops_get(old_fops);
+ }
+ }
fops_put(old_fops);
goto unlock_out;
}
+
+ /* Old interface: just one open allowed */
if(vfl->users) {
err = -EBUSY;
goto unlock_out;
}
- vfl->users++; /* In case vfl->open sleeps */
-
- if(vfl->owner)
- __MOD_INC_USE_COUNT(vfl->owner);
-
+
if (vfl->open) {
+ vfl->users++; /* In case vfl->open sleeps */
err=vfl->open(vfl,0); /* Tell the device it is open */
if (err) {
vfl->users--;
@@ -173,7 +184,7 @@
}
}
err = 0;
-
+
unlock_out:
up(&videodev_lock);
return err;
--
video4linux-list mailing list
Unsubscribe mailto:video4linux-list-request@;redhat.com?subject=unsubscribe
https://listman.redhat.com/mailman/listinfo/video4linux-list