--- linux/drivers/scsi/sg.c 2005-03-19 11:38:32.000000000 +1000 +++ linux/drivers/scsi/sg.c2612rc2nd2 2005-04-12 20:52:40.000000000 +1000 @@ -318,9 +318,7 @@ SCSI_LOG_TIMEOUT(3, printk("sg_release: %s\n", sdp->disk->disk_name)); sg_fasync(-1, filp, 0); /* remove filp from async notification list */ if (0 == sg_remove_sfp(sdp, sfp)) { /* Returns 1 when sdp gone */ - if (!sdp->detached) { - scsi_device_put(sdp->device); - } + scsi_device_put(sdp->device); sdp->exclude = 0; wake_up_interruptible(&sdp->o_excl_wait); } @@ -1574,19 +1572,29 @@ sg_nr_dev--; break; } - write_unlock_irqrestore(&sg_dev_arr_lock, iflags); if (sdp) { - sysfs_remove_link(&scsidp->sdev_gendev.kobj, "generic"); - class_simple_device_remove(MKDEV(SCSI_GENERIC_MAJOR, k)); - cdev_del(sdp->cdev); + struct cdev *tmp_cdev; + struct gendisk *tmp_disk; + int free_sdp = 0; + + tmp_cdev = sdp->cdev; sdp->cdev = NULL; - devfs_remove("%s/generic", scsidp->devfs_name); - put_disk(sdp->disk); + tmp_disk = sdp->disk; sdp->disk = NULL; if (NULL == sdp->headfp) + free_sdp = 1; + write_unlock_irqrestore(&sg_dev_arr_lock, iflags); + + sysfs_remove_link(&scsidp->sdev_gendev.kobj, "generic"); + class_simple_device_remove(MKDEV(SCSI_GENERIC_MAJOR, k)); + cdev_del(tmp_cdev); + devfs_remove("%s/generic", scsidp->devfs_name); + put_disk(tmp_disk); + if (free_sdp) kfree((char *) sdp); - } + } else + write_unlock_irqrestore(&sg_dev_arr_lock, iflags); if (delay) msleep(10); /* dirty detach so delay device destruction */ @@ -2550,6 +2558,7 @@ } if (k < maxd) sg_dev_arr[k] = NULL; + scsi_device_put(sdp->device); kfree((char *) sdp); res = 1; }