diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c
index bb30c6b44fde9744439e62a92312499b26243896..45503e6ed4853dd33cd4f14abff6c1de32092e18 100644
--- a/drivers/scsi/osst.c
+++ b/drivers/scsi/osst.c
@@ -4234,14 +4234,14 @@ static int os_scsi_tape_open(struct inode * inode, struct file * filp)
 #endif
 		return (-EBUSY);
 	}
-	if (!try_module_get(STp->device->host->hostt->module)) {
+
+	if (!scsi_device_get(STp->device)) {
 		write_unlock(&os_scsi_tapes_lock);
 #if DEBUG
-                printk(OSST_DEB_MSG "%s:D: Failed try_module_get.\n", name);
+                printk(OSST_DEB_MSG "%s:D: Failed scsi_device_get.\n", name);
 #endif
 		return (-ENXIO);
 	}
-	STp->device->access_count++;
 	filp->private_data = STp;
 	STp->in_use = 1;
 	write_unlock(&os_scsi_tapes_lock);
@@ -4589,9 +4589,7 @@ static int os_scsi_tape_open(struct inode * inode, struct file * filp)
 	normalize_buffer(STp->buffer);
 	STp->header_ok = 0;
 	STp->in_use = 0;
-	STp->device->access_count--;
-
-	module_put(STp->device->host->hostt->module);
+	scsi_device_put(STp->device);
 
 	return retval;
 }
@@ -4719,9 +4717,8 @@ static int os_scsi_tape_close(struct inode * inode, struct file * filp)
 	write_lock(&os_scsi_tapes_lock);
 	STp->in_use = 0;
 	write_unlock(&os_scsi_tapes_lock);
-	STp->device->access_count--;
 
-	module_put(STp->device->host->hostt->module);
+	scsi_device_put(STp->device);
 
 	return result;
 }
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index d0d3bcd43a453c51d7cb7231e8e7949a349117c4..f9c56ce1108b219f7de11f9d2938691216a89300 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -1877,20 +1877,12 @@ int scsi_attach_device(struct scsi_device *sdev)
 	struct Scsi_Device_Template *sdt;
 
 	down_read(&scsi_devicelist_mutex);
-	list_for_each_entry(sdt, &scsi_devicelist, list)
-		if (sdt->attach) {
-			/*
-			 * XXX check result when the upper level attach
-			 * return values are fixed, and on failure goto
-			 * fail.
-			 */
-			if(try_module_get(sdt->module)) {
-				(*sdt->attach)(sdev);
-				module_put(sdt->module);
-			} else {
-				printk(KERN_WARNING "SCSI module %s not ready, skipping attach.\n", sdt->name);
-			}
-		}
+	list_for_each_entry(sdt, &scsi_devicelist, list) {
+		if (!try_module_get(sdt->module))
+			continue;
+		(*sdt->attach)(sdev);
+		module_put(sdt->module);
+	}
 	up_read(&scsi_devicelist_mutex);
 	return 0;
 }
@@ -1900,18 +1892,30 @@ void scsi_detach_device(struct scsi_device *sdev)
 	struct Scsi_Device_Template *sdt;
 
 	down_read(&scsi_devicelist_mutex);
-	list_for_each_entry(sdt, &scsi_devicelist, list)
-		if (sdt->detach) {
-			if(try_module_get(sdt->module)) {
-				(*sdt->detach)(sdev);
-				module_put(sdt->module);
-			} else {
-				printk(KERN_WARNING "SCSI module %s not ready, skipping detach.\n", sdt->name);
-			}
-		}
+	list_for_each_entry(sdt, &scsi_devicelist, list) {
+		if (!try_module_get(sdt->module))
+			continue;
+		(*sdt->detach)(sdev);
+		module_put(sdt->module);
+	}
 	up_read(&scsi_devicelist_mutex);
 }
 
+int scsi_device_get(struct scsi_device *sdev)
+{
+	if (!try_module_get(sdev->host->hostt->module))
+		return -ENXIO;
+
+	sdev->access_count++;
+	return 0;
+}
+
+void scsi_device_put(struct scsi_device *sdev)
+{
+	sdev->access_count--;
+	module_put(sdev->host->hostt->module);
+}
+
 /*
  * Function:	scsi_slave_attach()
  *
@@ -1935,7 +1939,7 @@ int scsi_slave_attach(struct scsi_device *sdev)
 			printk(KERN_ERR "scsi: Allocation failure during"
 			       " attach, some SCSI devices might not be"
 			       " configured\n");
-			return 1;
+			return -ENOMEM;
 		}
 		if (sdev->host->hostt->slave_configure != NULL) {
 			if (sdev->host->hostt->slave_configure(sdev) != 0) {
@@ -1943,7 +1947,7 @@ int scsi_slave_attach(struct scsi_device *sdev)
 				       " attach, some SCSI device might not be"
 				       " configured\n");
 				scsi_release_commandblocks(sdev);
-				return 1;
+				return -ENOMEM;
 			}
 		} else if (sdev->host->cmd_per_lun != 0)
 			scsi_adjust_queue_depth(sdev, 0,
diff --git a/drivers/scsi/scsi.h b/drivers/scsi/scsi.h
index 2cbccf4271e19a3391cd80bc764cf13cff9d410e..9070c70c1913d4535aa2cda1f9b55c13e556b160 100644
--- a/drivers/scsi/scsi.h
+++ b/drivers/scsi/scsi.h
@@ -448,8 +448,10 @@ extern void scsi_release_commandblocks(Scsi_Device * SDpnt);
 extern void scsi_build_commandblocks(Scsi_Device * SDpnt);
 extern void scsi_adjust_queue_depth(Scsi_Device *, int, int);
 extern int scsi_track_queue_full(Scsi_Device *, int);
-extern int scsi_slave_attach(struct scsi_device *sdev);
-extern void scsi_slave_detach(struct scsi_device *sdev);
+extern int scsi_slave_attach(struct scsi_device *);
+extern void scsi_slave_detach(struct scsi_device *);
+extern int scsi_device_get(struct scsi_device *);
+extern void scsi_device_put(struct scsi_device *);
 extern void scsi_done(Scsi_Cmnd * SCpnt);
 extern void scsi_finish_command(Scsi_Cmnd *);
 extern int scsi_retry_command(Scsi_Cmnd *);
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 95949bff71d9b73766371ff3b94fc7736395f707..c6c49a2710bd125665c617f33e0af621174aac37 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -1340,7 +1340,7 @@ static int scsi_add_lun(Scsi_Device *sdevscan, Scsi_Device **sdevnew,
 	return SCSI_SCAN_LUN_PRESENT;
 }
 
-static int scsi_remove_lun(struct scsi_device *sdev)
+static void scsi_remove_lun(struct scsi_device *sdev)
 {
 	devfs_unregister(sdev->de);
 	scsi_device_unregister(sdev);
diff --git a/drivers/scsi/scsi_syms.c b/drivers/scsi/scsi_syms.c
index 325912fee6e9200420dc99b914a0172748af07f1..85de9b673e3329a8f76aaaefab43874db8e5587d 100644
--- a/drivers/scsi/scsi_syms.c
+++ b/drivers/scsi/scsi_syms.c
@@ -81,6 +81,8 @@ EXPORT_SYMBOL(scsi_register_blocked_host);
 EXPORT_SYMBOL(scsi_deregister_blocked_host);
 EXPORT_SYMBOL(scsi_slave_attach);
 EXPORT_SYMBOL(scsi_slave_detach);
+EXPORT_SYMBOL(scsi_device_get);
+EXPORT_SYMBOL(scsi_device_put);
 
 /*
  * This symbol is for the highlevel drivers (e.g. sg) only.
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 8a6b5ed7ee0e96d9e30ce6462fe365a25c1d3852..6445396e187f8cac5a1973c806a558f8d143b84c 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -261,9 +261,9 @@ sg_open(struct inode *inode, struct file *filp)
 
 	/* This driver's module count bumped by fops_get in <linux/fs.h> */
 	/* Prevent the device driver from vanishing while we sleep */
-	if (!try_module_get(sdp->device->host->hostt->module))
-		return -ENXIO;
-	sdp->device->access_count++;
+	retval = scsi_device_get(sdp->device);
+	if (retval)
+		return retval;
 
 	if (!((flags & O_NONBLOCK) ||
 	      scsi_block_when_processing_errors(sdp->device))) {
@@ -316,8 +316,7 @@ sg_open(struct inode *inode, struct file *filp)
 	return 0;
 
       error_out:
-	sdp->device->access_count--;
-	module_put(sdp->device->host->hostt->module);
+	scsi_device_put(sdp->device);
 	return retval;
 }
 
@@ -334,8 +333,7 @@ sg_release(struct inode *inode, struct file *filp)
 	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) {
-			sdp->device->access_count--;
-			module_put(sdp->device->host->hostt->module);
+			scsi_device_put(sdp->device);
 		}
 		sdp->exclude = 0;
 		wake_up_interruptible(&sdp->o_excl_wait);
@@ -1298,8 +1296,7 @@ sg_cmd_done(Scsi_Cmnd * SCpnt)
 		if (NULL == sfp->headrp) {
 			SCSI_LOG_TIMEOUT(1, printk("sg...bh: already closed, final cleanup\n"));
 			if (0 == sg_remove_sfp(sdp, sfp)) {	/* device still present */
-				sdp->device->access_count--;
-				module_put(sdp->device->host->hostt->module);
+				scsi_device_put(sdp->device);
 			}
 			sfp = NULL;
 		}
@@ -1374,15 +1371,19 @@ static DEVICE_ATTR(type,S_IRUGO,sg_device_type_read,NULL);
 static int
 sg_attach(Scsi_Device * scsidp)
 {
-	struct gendisk *disk = alloc_disk(1);
+	struct gendisk *disk;
 	Sg_device *sdp = NULL;
 	unsigned long iflags;
-	int k;
+	int k, error;
 
+	disk = alloc_disk(1);
 	if (!disk)
-		return 1;
-	if (scsi_slave_attach(scsidp))
-		return 1;
+		return -ENOMEM;
+
+	error = scsi_slave_attach(scsidp);
+	if (error)
+		goto out_put;
+		
 	write_lock_irqsave(&sg_dev_arr_lock, iflags);
 	if (sg_nr_dev >= sg_dev_max) {	/* try to resize */
 		Sg_device **tmp_da;
@@ -1394,9 +1395,8 @@ sg_attach(Scsi_Device * scsidp)
 		if (NULL == tmp_da) {
 			printk(KERN_ERR
 			       "sg_attach: device array cannot be resized\n");
-			put_disk(disk);
-			scsi_slave_detach(scsidp);
-			return 1;
+			error = -ENOMEM;
+			goto out_detach;
 		}
 		write_lock_irqsave(&sg_dev_arr_lock, iflags);
 		memset(tmp_da, 0, tmp_dev_max * sizeof (Sg_device *));
@@ -1420,9 +1420,8 @@ sg_attach(Scsi_Device * scsidp)
 		       scsidp->lun, scsidp->type, SG_MAX_DEVS_MASK);
 		if (NULL != sdp)
 			vfree((char *) sdp);
-		put_disk(disk);
-		scsi_slave_detach(scsidp);
-		return 1;
+		error = -ENODEV;
+		goto out_detach;
 	}
 	if (k < sg_dev_max) {
 		if (NULL == sdp) {
@@ -1437,9 +1436,8 @@ sg_attach(Scsi_Device * scsidp)
 	if (NULL == sdp) {
 		write_unlock_irqrestore(&sg_dev_arr_lock, iflags);
 		printk(KERN_ERR "sg_attach: Sg_device cannot be allocated\n");
-		put_disk(disk);
-		scsi_slave_detach(scsidp);
-		return 1;
+		error = -ENOMEM;
+		goto out_detach;
 	}
 
 	SCSI_LOG_TIMEOUT(3, printk("sg_attach: dev=%d \n", k));
@@ -1492,6 +1490,12 @@ sg_attach(Scsi_Device * scsidp)
 		       scsidp->lun, scsidp->type);
 	}
 	return 0;
+
+out_detach:
+	scsi_slave_detach(scsidp);
+out_put:
+	put_disk(disk);
+	return error;
 }
 
 static void
@@ -1523,8 +1527,7 @@ sg_detach(Scsi_Device * scsidp)
 						sg_finish_rem_req(srp);
 				}
 				if (sfp->closed) {
-					sdp->device->access_count--;
-					module_put(sdp->device->host->hostt->module);
+					scsi_device_put(sdp->device);
 					__sg_remove_sfp(sdp, sfp);
 				} else {
 					delay = 1;
@@ -2512,8 +2515,7 @@ sg_remove_sfp(Sg_device * sdp, Sg_fd * sfp)
 		/* MOD_INC's to inhibit unloading sg and associated adapter driver */
 		/* only bump the access_count if we actually succeeded in
 		 * throwing another counter on the host module */
-		if(try_module_get(sdp->device->host->hostt->module))
-			sdp->device->access_count++;
+		scsi_device_get(sdp->device);	/* XXX: retval ignored? */	
 		sfp->closed = 1;	/* flag dirty state on this fd */
 		SCSI_LOG_TIMEOUT(1, printk("sg_remove_sfp: worrisome, %d writes pending\n",
 				  dirty));
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index 2e915f79ed595a56ff38b2f96ddaf745f51ff626..286f79955d1ffacf83893777ac1bab38aa7c0e6e 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -87,6 +87,8 @@ static LIST_HEAD(sr_devlist);
 static spinlock_t sr_devlist_lock = SPIN_LOCK_UNLOCKED;
 
 static int sr_open(struct cdrom_device_info *, int);
+static void sr_release(struct cdrom_device_info *);
+
 static void get_sectorsize(struct scsi_cd *);
 static void get_capabilities(struct scsi_cd *);
 
@@ -124,16 +126,6 @@ static inline void sr_devlist_remove(Scsi_CD *cd)
 	spin_unlock(&sr_devlist_lock);
 }
 
-static void sr_release(struct cdrom_device_info *cdi)
-{
-	struct scsi_cd *cd = cdi->handle;
-
-	if (cd->device->sector_size > 2048)
-		sr_set_blocklength(cd, 2048);
-	cd->device->access_count--;
-	module_put(cd->device->host->hostt->module);
-}
-
 static struct cdrom_device_ops sr_dops = {
 	.open			= sr_open,
 	.release	 	= sr_release,
@@ -460,43 +452,59 @@ struct block_device_operations sr_bdops =
 static int sr_open(struct cdrom_device_info *cdi, int purpose)
 {
 	struct scsi_cd *cd = cdi->handle;
+	struct scsi_device *sdev = cd->device;
+	int retval;
 
-	if (!cd->device)
-		return -ENXIO;	/* No such device */
+	retval = scsi_device_get(sdev);
+	if (retval)
+		return retval;
+	
 	/*
 	 * If the device is in error recovery, wait until it is done.
 	 * If the device is offline, then disallow any access to it.
 	 */
-	if (!scsi_block_when_processing_errors(cd->device)) {
-		return -ENXIO;
-	}
-	if(!try_module_get(cd->device->host->hostt->module))
-		return -ENXIO;
-	cd->device->access_count++;
+	retval = -ENXIO;
+	if (!scsi_block_when_processing_errors(sdev))
+		goto error_out;
 
-	/* If this device did not have media in the drive at boot time, then
+	/*
+	 * If this device did not have media in the drive at boot time, then
 	 * we would have been unable to get the sector size.  Check to see if
 	 * this is the case, and try again.
 	 */
-
 	if (cd->needs_sector_size)
 		get_sectorsize(cd);
-
 	return 0;
+
+error_out:
+	scsi_device_put(sdev);
+	return retval;	
+}
+
+static void sr_release(struct cdrom_device_info *cdi)
+{
+	struct scsi_cd *cd = cdi->handle;
+
+	if (cd->device->sector_size > 2048)
+		sr_set_blocklength(cd, 2048);
+
+	scsi_device_put(cd->device);
 }
 
 static int sr_attach(struct scsi_device *sdev)
 {
 	struct gendisk *disk;
 	struct scsi_cd *cd;
-	int minor;
+	int minor, error;
 
 	if (sdev->type != TYPE_ROM && sdev->type != TYPE_WORM)
 		return 1;
 
-	if (scsi_slave_attach(sdev))
-		return 1;
+	error = scsi_slave_attach(sdev);
+	if (error)
+		return error;
 
+	error = -ENOMEM;
 	cd = kmalloc(sizeof(*cd), GFP_KERNEL);
 	if (!cd)
 		goto fail;
@@ -566,7 +574,7 @@ static int sr_attach(struct scsi_device *sdev)
 	kfree(cd);
 fail:
 	scsi_slave_detach(sdev);
-	return 1;
+	return error;
 }
 
 
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index 4e8fe52b240e42e39c07252f87c98c2f254e48f6..a00fe03306980a75c238bb0f1e9c2a1ba1c9363e 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -993,9 +993,9 @@ static int st_open(struct inode *inode, struct file *filp)
 		DEB( printk(ST_DEB_MSG "%s: Device already in use.\n", name); )
 		return (-EBUSY);
 	}
-	if(!try_module_get(STp->device->host->hostt->module))
+
+	if(!scsi_device_get(STp->device))
 		return (-ENXIO);
-	STp->device->access_count++;
 	STp->in_use = 1;
 	write_unlock(&st_dev_arr_lock);
 	STp->rew_at_close = STp->autorew_dev = (minor(inode->i_rdev) & 0x80) == 0;
@@ -1040,8 +1040,7 @@ static int st_open(struct inode *inode, struct file *filp)
  err_out:
 	normalize_buffer(STp->buffer);
 	STp->in_use = 0;
-	STp->device->access_count--;
-	module_put(STp->device->host->hostt->module);
+	scsi_device_put(STp->device);
 	return retval;
 
 }
@@ -1174,8 +1173,7 @@ static int st_release(struct inode *inode, struct file *filp)
 	write_lock(&st_dev_arr_lock);
 	STp->in_use = 0;
 	write_unlock(&st_dev_arr_lock);
-	STp->device->access_count--;
-	module_put(STp->device->host->hostt->module);
+	scsi_device_put(STp->device);
 
 	return result;
 }