Hi,

On Thu, Dec 19, 2002 at 04:52:55PM -0800, Greg KH wrote:
> On Fri, Dec 20, 2002 at 01:45:16AM +0100, Oliver Neukum wrote:
> > This patch is wrong. Please do not apply.
> 
> I agree.  It tries to do several different things, and doesn't really
> seem to make much sense as to why it is trying to do them :(

Sorry for that. I only head a quick look at it before forwarding it.
I'll check other peoples patches more thoroughly in future.

> Henning, you might want to just split the logic of the reference
> counting logic out into a single patch, and work from there.

As I didn't really understand what Sergey wanted to do I started from
scratch using ideas from usb-skeleton.c. There are still some locking
issues in ioctl_scanner and read_scanner keeps trying to read until
timeout, if the device was disconnected in the middle of a read. But
as the issues are not directly realted, I'll check the later. The
patch works for me, that means: the module usage count is 0 even if an
opened device is disconnected and there is no kerenel crash any more
if someone writes to/reads from a disconnected device.

So what about this (on top of the interface and altsetting patches
from today):

[PATCH 2.4.21-pre1] scanner.c: fix for disconnect while open

Decrease module usage count even if device was disconnected while
open. Check if disconnected before read, write, and ioctl.


--- linux-2.4.21-pre1.altsetting/drivers/usb/scanner.c  2002-12-22 12:06:52.000000000 
+0100
+++ linux-2.4.21-pre1.present/drivers/usb/scanner.c     2002-12-22 19:34:13.000000000 
++0100
@@ -327,6 +327,8 @@
  *    - Accept devices with more than one interface. Only use interfaces that
  *      look like belonging to scanners.
  *    - Use altsetting[0], not altsetting[ifnum].
+ *    - Decrease module usage count even if device was disconnected while open.
+ *      Check if disconnected before read, write, and ioctl.
  *
  * TODO
  *    - Remove the 2/3 endpoint limitation
@@ -366,6 +368,17 @@
  */ 
 #include "scanner.h"
 
+static inline void 
+delete_scanner (struct scn_usb_data *scn)
+{
+       p_scn_table[scn->scn_minor] = NULL;
+       if (scn->ibuf != NULL)
+               kfree(scn->ibuf);
+       if (scn->obuf != NULL)
+               kfree(scn->obuf);
+       kfree (scn);
+}
+
 static void
 irq_scanner(struct urb *urb)
 {
@@ -470,21 +483,27 @@
 
        dbg("close_scanner: scn_minor:%d", scn_minor);
 
+       down(&scn_mutex);
        if (!p_scn_table[scn_minor]) {
                err("close_scanner(%d): invalid scn_minor", scn_minor);
+               up(&scn_mutex);
                return -ENODEV;
        }
 
-       down(&scn_mutex);
-
        scn = p_scn_table[scn_minor];
        down(&(scn->sem));
        scn->isopen = 0;
 
        file->private_data = NULL;
 
+       if (!scn->present) {
+               up(&(scn->sem));
+               delete_scanner (scn);
+       } else {
+               up(&(scn->sem));
+       }
+
        up(&scn_mutex);
-       up(&(scn->sem));
 
        MOD_DEC_USE_COUNT;
 
@@ -513,14 +532,20 @@
 
        down(&(scn->sem));
 
+       scn_minor = scn->scn_minor;
+
+       if (!scn->present) {
+               err("write_scanner(%d): Scanner is not present", scn_minor);
+               up(&(scn->sem));
+               return -ENODEV;
+       }
+
        if (!scn->bulk_out_ep) {
                /* This scanner does not have a bulk-out endpoint */
                up(&(scn->sem));
                return -EINVAL;
        }
 
-       scn_minor = scn->scn_minor;
-
        obuf = scn->obuf;
 
        dev = scn->scn_dev;
@@ -609,6 +634,12 @@
 
        scn_minor = scn->scn_minor;
 
+       if (!scn->present) {
+               err("read_scanner(%d): Scanner is not present", scn_minor);
+               up(&(scn->sem));
+               return -ENODEV;
+       }
+
        ibuf = scn->ibuf;
 
        dev = scn->scn_dev;
@@ -718,6 +749,11 @@
                return -ENODEV;
        }
 
+       if (!p_scn_table[scn_minor]->present) {
+               err("ioctl_scanner(%d): Scanner is not present", scn_minor);
+               return -ENODEV;
+       }
+
        dev = p_scn_table[scn_minor]->scn_dev;
 
        switch (cmd)
@@ -1121,14 +1157,16 @@
         usb_driver_release_interface(&scanner_driver,
                 &scn->scn_dev->actconfig->interface[scn->ifnum]);
 
-       kfree(scn->ibuf);
-       kfree(scn->obuf);
-
        dbg("disconnect_scanner: De-allocating minor:%d", scn->scn_minor);
        devfs_unregister(scn->devfs);
-       p_scn_table[scn->scn_minor] = NULL;
-       up (&(scn->sem));
-       kfree (scn);
+
+       if (scn->isopen) {
+               scn->present = 0;
+               up (&(scn->sem));
+       } else {
+               up (&(scn->sem));
+               delete_scanner (scn);
+       }
        up (&scn_mutex);
 }
 


-------------------------------------------------------
This sf.net email is sponsored by:ThinkGeek
Welcome to geek heaven.
http://thinkgeek.com/sf
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to