[PATCH 4/9] Free sdev class device from release function

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



For a clean teardown of a sdev the class device should
really be freed from the sdev's release function.
This way we don't have to worry about refcounting the
class device structures itself.
And the functions are now better aligned with the sdev
state model; _scsi_remove_device() transitions the sdev
from RUNNING to CANCEL, and scsi_destroy_device() from
CANCEL to DEL.

Signed-off-by: Hannes Reinecke <hare@xxxxxxx>
---
 drivers/scsi/scsi_scan.c  |   13 ++++++-------
 drivers/scsi/scsi_sysfs.c |   34 ++++++++++++++++------------------
 2 files changed, 22 insertions(+), 25 deletions(-)

diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 4874bdd..e967705 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -298,8 +298,7 @@ static struct scsi_device *scsi_alloc_sd
 	return sdev;
 
 out_device_destroy:
-	transport_destroy_device(&sdev->sdev_gendev);
-	put_device(&sdev->sdev_gendev);
+	scsi_destroy_device(sdev);
 out:
 	if (display_failure_msg)
 		printk(ALLOC_FAILURE_MSG, __FUNCTION__);
@@ -1095,11 +1094,12 @@ static int scsi_probe_and_add_lun(struct
 				*sdevp = sdev;
 			} else {
 				__scsi_remove_device(sdev);
+				scsi_destroy_device(sdev);
 				res = SCSI_SCAN_NO_RESPONSE;
 			}
 		}
 	} else
-		scsi_destroy_sdev(sdev);
+		scsi_destroy_device(sdev);
  out:
 	return res;
 }
@@ -1453,7 +1453,7 @@ static int scsi_report_lun_scan(struct s
 		/*
 		 * the sdev we used didn't appear in the report luns scan
 		 */
-		scsi_destroy_sdev(sdev);
+		scsi_destroy_device(sdev);
 	return ret;
 }
 
@@ -1662,8 +1662,7 @@ static void scsi_sysfs_add_devices(struc
 {
 	struct scsi_device *sdev;
 	shost_for_each_device(sdev, shost) {
-		if (scsi_sysfs_add_sdev(sdev) != 0)
-			scsi_destroy_sdev(sdev);
+		scsi_sysfs_add_sdev(sdev);
 	}
 }
 
@@ -1877,7 +1876,7 @@ void scsi_free_host_dev(struct scsi_devi
 {
 	BUG_ON(sdev->id != sdev->host->this_id);
 
-	scsi_destroy_sdev(sdev);
+	scsi_destroy_device(sdev);
 }
 EXPORT_SYMBOL(scsi_free_host_dev);
 
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index c81c326..65b46e0 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -215,7 +215,6 @@ static void scsi_device_cls_release(stru
 	struct scsi_device *sdev;
 
 	sdev = class_to_sdev(class_dev);
-	put_device(&sdev->sdev_gendev);
 }
 
 static void scsi_device_dev_release_usercontext(struct work_struct *work)
@@ -230,6 +229,11 @@ static void scsi_device_dev_release_user
 	parent = sdev->sdev_gendev.parent;
 	starget = to_scsi_target(parent);
 
+	if (sdev->host->hostt->slave_destroy)
+		sdev->host->hostt->slave_destroy(sdev);
+	transport_destroy_device(&sdev->sdev_gendev);
+	class_device_put(&sdev->sdev_classdev);
+
 	spin_lock_irqsave(sdev->host->host_lock, flags);
 	starget->reap_ref++;
 	list_del(&sdev->siblings);
@@ -741,17 +745,20 @@ int scsi_sysfs_add_sdev(struct scsi_devi
 	if (error) {
 		sdev_printk(KERN_INFO, sdev,
 			    "failed to add device (error %d)\n", error);
+		scsi_device_set_state(sdev, SDEV_DEL);
 		return error;
 	}
 	error = class_device_add(&sdev->sdev_classdev);
 	if (error) {
 		sdev_printk(KERN_INFO, sdev,
 			    "failed to add class device (error %d)\n", error);
-		goto clean_device;
+		scsi_device_set_state(sdev, SDEV_DEL);
+		device_del(&sdev->sdev_gendev);
+		return error;
 	}
 
 	/* take a reference for the sdev_classdev; this is
-	 * released by the sdev_class .release */
+	 * released in scsi_remove_device() */
 	get_device(&sdev->sdev_gendev);
 	if (sdev->host->hostt->sdev_attrs) {
 		for (i = 0; sdev->host->hostt->sdev_attrs[i]; i++) {
@@ -759,6 +766,7 @@ int scsi_sysfs_add_sdev(struct scsi_devi
 					sdev->host->hostt->sdev_attrs[i]);
 			if (error) {
 				__scsi_remove_device(sdev);
+				scsi_destroy_device(sdev);
 				goto out;
 			}
 		}
@@ -773,6 +781,7 @@ int scsi_sysfs_add_sdev(struct scsi_devi
 			error = device_create_file(&sdev->sdev_gendev, attr);
 			if (error) {
 				__scsi_remove_device(sdev);
+				scsi_destroy_device(sdev);
 				goto out;
 			}
 		}
@@ -781,15 +790,6 @@ int scsi_sysfs_add_sdev(struct scsi_devi
 	transport_add_device(&sdev->sdev_gendev);
  out:
 	return error;
-
- clean_device:
-	scsi_device_set_state(sdev, SDEV_CANCEL);
-
-	device_del(&sdev->sdev_gendev);
-	transport_destroy_device(&sdev->sdev_gendev);
-	put_device(&sdev->sdev_gendev);
-
-	return error;
 }
 
 void __scsi_remove_device(struct scsi_device *sdev)
@@ -799,14 +799,11 @@ void __scsi_remove_device(struct scsi_de
 	if (scsi_device_set_state(sdev, SDEV_CANCEL) != 0)
 		return;
 
-	class_device_unregister(&sdev->sdev_classdev);
+	class_device_del(&sdev->sdev_classdev);
+	/* Release the refcount hold for the classdev */
+	put_device(&sdev->sdev_gendev);
 	transport_remove_device(dev);
 	device_del(dev);
-	scsi_device_set_state(sdev, SDEV_DEL);
-	if (sdev->host->hostt->slave_destroy)
-		sdev->host->hostt->slave_destroy(sdev);
-	transport_destroy_device(dev);
-	put_device(dev);
 }
 
 /**
@@ -819,6 +816,7 @@ void scsi_remove_device(struct scsi_devi
 
 	mutex_lock(&shost->scan_mutex);
 	__scsi_remove_device(sdev);
+	scsi_destroy_device(sdev);
 	mutex_unlock(&shost->scan_mutex);
 }
 EXPORT_SYMBOL(scsi_remove_device);
-- 
1.4.3.4

-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [SCSI Target Devel]     [Linux SCSI Target Infrastructure]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Samba]     [Device Mapper]
  Powered by Linux