target code updates to support scanned targets
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, ¤t_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 );