diff mbox series

[v6,07/10] scsi: add starget_to_shost() specialization

Message ID 20200821154204.9298-8-dgilbert@interlog.com
State New
Headers show
Series scsi: use xarray for devices and targets | expand

Commit Message

Douglas Gilbert Aug. 21, 2020, 3:42 p.m. UTC
In the SCSI mid-layer object tree the host level and the target
level under it can be separated by transport supplied objects.
For example the SCSI SAS transport inserts SAS port objects.
To cope with this is a generic way there is function called
dev_to_host() function that loops back up the 'device' object
hierarchy asking at each level: "Are you a shost object?".

It does the job but it is not particulary efficient in the case
where the given object is a SCSI target. This is because when
a SCSI target object is created it knows its SCSI host object
and can hold that pointer value. So as long as a SCSI target
cannot change its parent SCSI host object "midstream" then
following that pointer (which is what starget_to_shost() does)
is safe and faster.

Signed-off-by: Douglas Gilbert <dgilbert@interlog.com>
---
 drivers/scsi/scsi.c           |  2 +-
 drivers/scsi/scsi_scan.c      | 11 ++++++-----
 drivers/scsi/scsi_sysfs.c     |  2 +-
 include/scsi/scsi_device.h    |  8 ++++++++
 include/scsi/scsi_transport.h |  2 +-
 5 files changed, 17 insertions(+), 8 deletions(-)
diff mbox series

Patch

diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index 0e22fff072ff..1293ccb4e9fd 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -761,7 +761,7 @@  struct scsi_device *scsi_device_lookup_by_target(struct scsi_target *starget,
 						 u64 lun)
 {
 	struct scsi_device *sdev;
-	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+	struct Scsi_Host *shost = starget_to_shost(starget);
 	unsigned long flags;
 
 	spin_lock_irqsave(shost->host_lock, flags);
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 41818111808e..5f4b8ed31a76 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -217,7 +217,7 @@  static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget,
 {
 	struct scsi_device *sdev;
 	int display_failure_msg = 1, ret;
-	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+	struct Scsi_Host *shost = starget_to_shost(starget);
 
 	sdev = kzalloc(sizeof(*sdev) + shost->transportt->device_size,
 		       GFP_KERNEL);
@@ -305,7 +305,7 @@  static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget,
 static void scsi_target_destroy(struct scsi_target *starget)
 {
 	struct device *dev = &starget->dev;
-	struct Scsi_Host *shost = dev_to_shost(dev->parent);
+	struct Scsi_Host *shost = starget_to_shost(starget);
 	unsigned long flags;
 	unsigned long tid = scsi_target_index(starget);
 
@@ -424,6 +424,7 @@  static struct scsi_target *scsi_alloc_target(struct device *parent,
 	device_initialize(dev);
 	kref_init(&starget->reap_ref);
 	dev->parent = get_device(parent);
+	starget->parent_shost = shost;		/* redundant but faster */
 	dev_set_name(dev, "target%d:%d:%d", shost->host_no, channel, id);
 	dev->bus = &scsi_bus_type;
 	dev->type = &scsi_target_type;
@@ -1055,7 +1056,7 @@  static int scsi_probe_and_add_lun(struct scsi_target *starget,
 	unsigned char *result;
 	blist_flags_t bflags;
 	int res = SCSI_SCAN_NO_RESPONSE, result_len = 256;
-	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+	struct Scsi_Host *shost = starget_to_shost(starget);
 
 	/*
 	 * The rescan flag is used as an optimization, the first scan of a
@@ -1205,7 +1206,7 @@  static void scsi_sequential_lun_scan(struct scsi_target *starget,
 {
 	uint max_dev_lun;
 	u64 sparse_lun, lun;
-	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+	struct Scsi_Host *shost = starget_to_shost(starget);
 
 	SCSI_LOG_SCAN_BUS(3, starget_printk(KERN_INFO, starget,
 		"scsi scan: Sequential scan\n"));
@@ -1303,7 +1304,7 @@  static int scsi_report_lun_scan(struct scsi_target *starget, blist_flags_t bflag
 	struct scsi_lun *lunp, *lun_data;
 	struct scsi_sense_hdr sshdr;
 	struct scsi_device *sdev;
-	struct Scsi_Host *shost = dev_to_shost(&starget->dev);
+	struct Scsi_Host *shost = starget_to_shost(starget);
 	int ret = 0;
 
 	/*
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index e30a058c6b33..0b5ede1b8ebe 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -1477,7 +1477,7 @@  EXPORT_SYMBOL(scsi_remove_device);
 
 static void __scsi_remove_target(struct scsi_target *starget)
 {
-	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+	struct Scsi_Host *shost = starget_to_shost(starget);
 	unsigned long flags;
 	struct scsi_device *sdev, *sdev_next;
 	unsigned long lun_idx = 0;
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
index 390a150cdaca..5292787246ca 100644
--- a/include/scsi/scsi_device.h
+++ b/include/scsi/scsi_device.h
@@ -281,12 +281,14 @@  enum scsi_target_state {
  * scsi_target: representation of a scsi target, for now, this is only
  * used for single_lun devices. If no one has active IO to the target,
  * starget_sdev_user is NULL, else it points to the active sdev.
+ * * Invariant: starg->parent_shost == dev_to_shost(starg->dev.parent)
  */
 struct scsi_target {
 	struct scsi_device	*starget_sdev_user;
 	struct list_head	siblings;
 	struct xarray		__devices;
 	struct device		dev;
+	struct Scsi_Host        *parent_shost;	/* redundant but faster */
 	struct kref		reap_ref; /* last put renders target invisible */
 	u16			channel;
 	u16			id; /* target id ... replace
@@ -326,6 +328,12 @@  static inline u32 scsi_target_index(struct scsi_target *starget)
 	return (starget->channel << 16) | (starget->id);
 }
 
+/* This is faster that doing dev_to_shost(starg->dev.parent) */
+static inline struct Scsi_Host *starget_to_shost(struct scsi_target *starg)
+{
+	return starg->parent_shost;
+}
+
 #define to_scsi_target(d)	container_of(d, struct scsi_target, dev)
 static inline struct scsi_target *scsi_target(struct scsi_device *sdev)
 {
diff --git a/include/scsi/scsi_transport.h b/include/scsi/scsi_transport.h
index a0458bda3148..5a2337ded7b0 100644
--- a/include/scsi/scsi_transport.h
+++ b/include/scsi/scsi_transport.h
@@ -70,7 +70,7 @@  scsi_transport_reserve_device(struct scsi_transport_template * t, int space)
 static inline void *
 scsi_transport_target_data(struct scsi_target *starget)
 {
-	struct Scsi_Host *shost = dev_to_shost(&starget->dev);
+	struct Scsi_Host *shost = starget_to_shost(starget);
 	return (u8 *)starget->starget_data
 		+ shost->transportt->target_private_offset;