Skip to contentSkip to conversation

target code updates to support scanned targets

RFC New James Bottomley 1 participant 1 message Feb 15, 2005 SCSI

lore
Share & tools
lore
#0 lore raw

RFC 1/1 target code updates to support scanned targets

Since everyone's been asking for the ability to do target scanning, I took a look at how this might be done in our current infrastructure. The attached patch does three things:

1. Pulls target allocation forward so it's now allocated and destroyed as a separate entity instead of being bound into device (LUN) allocation
2. rejig the scanning code to do target scanning via a parent generic device rather than the HCTL numbers.
3. Exported the modified scsi_scan_target and scsi_remove_target.
4. moved our sibling lists into the target.

Immediately for iscsi and fc, this should give the ability to parent a scanned target to something not necessarily a scsi host (needed for the rport work) and also both of you should now be able to remove scsi_scan_host() from your drivers.

Anyway, give it the once over and tell me what you think.

James

===== drivers/scsi/hosts.c 1.107 vs edited =====

drivers/scsi/hosts.c +1 -0
@@ -216,6 +216,7 @@
 	spin_lock_init(&shost->default_lock);
 	scsi_assign_lock(shost, &shost->default_lock);
 	INIT_LIST_HEAD(&shost->__devices);
+	INIT_LIST_HEAD(&shost->__targets);
 	INIT_LIST_HEAD(&shost->eh_cmd_q);
 	INIT_LIST_HEAD(&shost->starved_list);
 	init_waitqueue_head(&shost->host_wait);

===== drivers/scsi/scsi_lib.c 1.148 vs edited =====

drivers/scsi/scsi_lib.c +6 -3
@@ -365,10 +365,11 @@
 {
 	struct Scsi_Host *shost = current_sdev->host;
 	struct scsi_device *sdev, *tmp;
+	struct scsi_target *starget = scsi_target(current_sdev);
 	unsigned long flags;
 
 	spin_lock_irqsave(shost->host_lock, flags);
-	scsi_target(current_sdev)->starget_sdev_user = NULL;
+	starget->starget_sdev_user = NULL;
 	spin_unlock_irqrestore(shost->host_lock, flags);
 
 	/*
@@ -380,10 +381,12 @@
 	blk_run_queue(current_sdev->request_queue);
 
 	spin_lock_irqsave(shost->host_lock, flags);
-	if (scsi_target(current_sdev)->starget_sdev_user)
+	if (starget->starget_sdev_user)
 		goto out;
-	list_for_each_entry_safe(sdev, tmp, &current_sdev->same_target_siblings,
+	list_for_each_entry_safe(sdev, tmp, &starget->devices,
 			same_target_siblings) {
+		if (sdev == current_sdev)
+			continue;
 		if (scsi_device_get(sdev))
 			continue;
 

===== drivers/scsi/scsi_scan.c 1.140 vs edited =====

drivers/scsi/scsi_scan.c +190 -60

450 lines not on this page · raw message

===== drivers/scsi/scsi_sysfs.c 1.67 vs edited =====

drivers/scsi/scsi_sysfs.c +52 -109

236 lines not on this page · raw message

===== include/scsi/scsi_device.h 1.30 vs edited =====

include/scsi/scsi_device.h +6 -0
@@ -112,6 +112,7 @@
 	unsigned no_uld_attach:1; /* disable connecting to upper level drivers */
 	unsigned select_no_atn:1;
 	unsigned fix_capacity:1;	/* READ_CAPACITY is too high by 1 */
+	unsigned reap:1;	/* whether release reaps the target */
 
 	unsigned int device_blocked;	/* Device returned QUEUE_FULL. */
 
@@ -144,7 +145,10 @@
  */
 struct scsi_target {
 	struct scsi_device	*starget_sdev_user;
+	struct list_head	siblings;
+	struct list_head	devices;
 	struct device		dev;
+	unsigned int		reap_ref; /* protected by the host lock */
 	unsigned int		channel;
 	unsigned int		id; /* target id ... replace
 				     * scsi_device.id eventually */
@@ -226,6 +230,8 @@
 extern void scsi_device_resume(struct scsi_device *sdev);
 extern void scsi_target_quiesce(struct scsi_target *);
 extern void scsi_target_resume(struct scsi_target *);
+extern void scsi_target_reap(struct scsi_target *);
+extern void scsi_remove_target(struct scsi_target *);
 extern const char *scsi_device_state_name(enum scsi_device_state);
 extern int scsi_is_sdev_device(const struct device *);
 extern int scsi_is_target_device(const struct device *);

===== include/scsi/scsi_host.h 1.26 vs edited =====

include/scsi/scsi_host.h +13 -4
@@ -416,6 +416,7 @@
 	 * access this list directly from a driver.
 	 */
 	struct list_head	__devices;
+	struct list_head	__targets;
 	
 	struct scsi_host_cmd_pool *cmd_pool;
 	spinlock_t		free_list_lock;
@@ -548,11 +549,21 @@
 	unsigned long hostdata[0]  /* Used for storage of host specific stuff */
 		__attribute__ ((aligned (sizeof(unsigned long))));
 };
-#define		dev_to_shost(d)		\
-	container_of(d, struct Scsi_Host, shost_gendev)
+
 #define		class_to_shost(d)	\
 	container_of(d, struct Scsi_Host, shost_classdev)
 
+int scsi_is_host_device(const struct device *);
+
+static inline struct Scsi_Host *dev_to_shost(struct device *dev)
+{
+	while (!scsi_is_host_device(dev)) {
+		if (!dev->parent)
+			return NULL;
+		dev = dev->parent;
+	}
+	return container_of(dev, struct Scsi_Host, shost_gendev);
+}
 
 extern struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *, int);
 extern int __must_check scsi_add_host(struct Scsi_Host *, struct device *);
@@ -596,8 +607,6 @@
  */
 extern void scsi_free_host_dev(struct scsi_device *);
 extern struct scsi_device *scsi_get_host_dev(struct Scsi_Host *);
-int scsi_is_host_device(const struct device *);
-
 
 /* legacy interfaces */
 extern struct Scsi_Host *scsi_register(struct scsi_host_template *, int);