PATCH to videodev.c

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



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    <luca_ing@xxxxxxxxx>

 
******************* 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 <claudio@xxxxxxxxxxxxx>
  *		- Added procfs support
- */
+ *		20021109  Luca Risolia <luca_ing@xxxxxxxxx>
+ *		- 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 <claudio@xxxxxxxxxxxxx>
  *		- Added procfs support
+ *		20021109  Luca Risolia <luca_ing@xxxxxxxxx>
+ *		- 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;







[Index of Archives]     [Linux DVB]     [Video Disk Recorder]     [Asterisk]     [Photo]     [DCCP]     [Netdev]     [Xorg]     [Util Linux NG]     [Xfree86]     [Free Photo Albums]     [Fedora Users]     [Fedora Women]     [ALSA Users]     [ALSA Devel]     [Linux USB]

Powered by Linux