]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
added usb patch to queue
authorGreg Kroah-Hartman <gregkh@suse.de>
Fri, 5 May 2006 00:01:23 +0000 (17:01 -0700)
committerGreg Kroah-Hartman <gregkh@suse.de>
Fri, 5 May 2006 00:01:23 +0000 (17:01 -0700)
queue-2.6.16/series
queue-2.6.16/usb-ub-oops-in-block_uevent.patch [new file with mode: 0644]

index 0684c1b31a2a635a21404f2c529a80460bb1c1e4..3122a84d229777ba8bf2023a6d7f41d33b1b6e8a 100644 (file)
@@ -1,2 +1,3 @@
 md-avoid-oops-when-attempting-to-fix-read-errors-on-raid10.patch
 via-rhine-zero-pad-short-packets-on-rhine-i-ethernet-cards.patch
+usb-ub-oops-in-block_uevent.patch
diff --git a/queue-2.6.16/usb-ub-oops-in-block_uevent.patch b/queue-2.6.16/usb-ub-oops-in-block_uevent.patch
new file mode 100644 (file)
index 0000000..59fe63b
--- /dev/null
@@ -0,0 +1,72 @@
+From zaitcev@redhat.com Wed May  3 00:16:11 2006
+Date: Wed, 3 May 2006 00:16:00 -0700
+From: Pete Zaitcev <zaitcev@redhat.com>
+To: greg@kroah.com
+Cc: zaitcev@redhat.com, linux-usb-devel@lists.sourceforge.net
+Subject: USB: ub oops in block_uevent
+Message-Id: <20060503001600.c9012512.zaitcev@redhat.com>
+
+In kernel 2.6.16, if a mounted storage device is removed, an oops happens
+because ub supplies an interface device (and kobject) to the block layer,
+but neglects to pin it. And apparently, the block layer expects its users
+to pin device structures.
+
+The code in ub was broken this way for years. But the bug was exposed only
+by 2.6.16 when it started to call block_uevent on close, which traverses
+device structures (kobjects actually).
+
+Signed-off-by: Pete Zaitcev <zaitcev@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/block/ub.c |   18 ++++++++++--------
+ 1 file changed, 10 insertions(+), 8 deletions(-)
+
+--- linux-2.6.16.13.orig/drivers/block/ub.c
++++ linux-2.6.16.13/drivers/block/ub.c
+@@ -704,6 +704,9 @@ static void ub_cleanup(struct ub_dev *sc
+               kfree(lun);
+       }
++      usb_set_intfdata(sc->intf, NULL);
++      usb_put_intf(sc->intf);
++      usb_put_dev(sc->dev);
+       kfree(sc);
+ }
+@@ -2428,7 +2431,12 @@ static int ub_probe(struct usb_interface
+       // sc->ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
+       usb_set_intfdata(intf, sc);
+       usb_get_dev(sc->dev);
+-      // usb_get_intf(sc->intf);      /* Do we need this? */
++      /*
++       * Since we give the interface struct to the block level through
++       * disk->driverfs_dev, we have to pin it. Otherwise, block_uevent
++       * oopses on close after a disconnect (kernels 2.6.16 and up).
++       */
++      usb_get_intf(sc->intf);
+       snprintf(sc->name, 12, DRV_NAME "(%d.%d)",
+           sc->dev->bus->busnum, sc->dev->devnum);
+@@ -2509,7 +2517,7 @@ static int ub_probe(struct usb_interface
+ err_diag:
+ err_dev_desc:
+       usb_set_intfdata(intf, NULL);
+-      // usb_put_intf(sc->intf);
++      usb_put_intf(sc->intf);
+       usb_put_dev(sc->dev);
+       kfree(sc);
+ err_core:
+@@ -2688,12 +2696,6 @@ static void ub_disconnect(struct usb_int
+        */
+       device_remove_file(&sc->intf->dev, &dev_attr_diag);
+-      usb_set_intfdata(intf, NULL);
+-      // usb_put_intf(sc->intf);
+-      sc->intf = NULL;
+-      usb_put_dev(sc->dev);
+-      sc->dev = NULL;
+-
+       ub_put(sc);
+ }