--- /dev/null
+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);
+ }
+