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;