From patchwork Fri Aug 21 15:41:55 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Douglas Gilbert X-Patchwork-Id: 257897 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id F258BC433DF for ; Fri, 21 Aug 2020 15:42:38 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id D14332063A for ; Fri, 21 Aug 2020 15:42:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728219AbgHUPmd (ORCPT ); Fri, 21 Aug 2020 11:42:33 -0400 Received: from smtp.infotech.no ([82.134.31.41]:48297 "EHLO smtp.infotech.no" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727849AbgHUPmP (ORCPT ); Fri, 21 Aug 2020 11:42:15 -0400 Received: from localhost (localhost [127.0.0.1]) by smtp.infotech.no (Postfix) with ESMTP id 53949204259; Fri, 21 Aug 2020 17:42:10 +0200 (CEST) X-Virus-Scanned: by amavisd-new-2.6.6 (20110518) (Debian) at infotech.no Received: from smtp.infotech.no ([127.0.0.1]) by localhost (smtp.infotech.no [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id fM8-XfoiIb8T; Fri, 21 Aug 2020 17:42:07 +0200 (CEST) Received: from xtwo70.bingwo.ca (host-45-78-251-166.dyn.295.ca [45.78.251.166]) by smtp.infotech.no (Postfix) with ESMTPA id EAAFB20415B; Fri, 21 Aug 2020 17:42:06 +0200 (CEST) From: Douglas Gilbert To: linux-scsi@vger.kernel.org Cc: martin.petersen@oracle.com, jejb@linux.vnet.ibm.com, hare@suse.de, john.garry@huawei.com Subject: [PATCH v6 01/10] scsi: convert target lookup to xarray Date: Fri, 21 Aug 2020 11:41:55 -0400 Message-Id: <20200821154204.9298-2-dgilbert@interlog.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200821154204.9298-1-dgilbert@interlog.com> References: <20200821154204.9298-1-dgilbert@interlog.com> MIME-Version: 1.0 Sender: linux-scsi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org From: Hannes Reinecke Use an xarray instead of lists for holding the scsi targets. I've also shortened the 'channel' and 'id' values to 16 bit as none of the drivers requires a full 32bit range for either of them, and by shortening them we can use them as the index into the xarray for storing the scsi_target pointer. Signed-off-by: Hannes Reinecke Signed-off-by: Douglas Gilbert --- drivers/scsi/hosts.c | 4 +++- drivers/scsi/scsi.c | 32 +++++++++++++++---------- drivers/scsi/scsi_scan.c | 49 ++++++++++++++++---------------------- drivers/scsi/scsi_sysfs.c | 16 +++++++++---- include/scsi/scsi_device.h | 15 ++++++++---- include/scsi/scsi_host.h | 2 +- 6 files changed, 65 insertions(+), 53 deletions(-) diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index 37d1c5565d90..bcf132320e8f 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c @@ -189,6 +189,8 @@ void scsi_remove_host(struct Scsi_Host *shost) transport_unregister_device(&shost->shost_gendev); device_unregister(&shost->shost_dev); device_del(&shost->shost_gendev); + WARN_ON(!xa_empty(&shost->__targets)); + xa_destroy(&shost->__targets); } EXPORT_SYMBOL(scsi_remove_host); @@ -385,7 +387,7 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize) spin_lock_init(shost->host_lock); shost->shost_state = SHOST_CREATED; INIT_LIST_HEAD(&shost->__devices); - INIT_LIST_HEAD(&shost->__targets); + xa_init_flags(&shost->__targets, XA_FLAGS_LOCK_IRQ); INIT_LIST_HEAD(&shost->eh_cmd_q); INIT_LIST_HEAD(&shost->starved_list); init_waitqueue_head(&shost->host_wait); diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index 24619c3bebd5..2cb31b41d8f8 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -575,6 +575,19 @@ struct scsi_device *__scsi_iterate_devices(struct Scsi_Host *shost, } EXPORT_SYMBOL(__scsi_iterate_devices); +/** + * __scsi_target_lookup - find a target based on channel and target id + * @shost: SCSI host pointer + * @channel: channel number of the target + * @id: ID of the target + * + */ +static struct scsi_target *__scsi_target_lookup(struct Scsi_Host *shost, + u16 channel, u16 id) +{ + return xa_load(&shost->__targets, (channel << 16) | id); +} + /** * starget_for_each_device - helper to walk all devices of a target * @starget: target whose devices we want to iterate over. @@ -701,19 +714,14 @@ EXPORT_SYMBOL(scsi_device_lookup_by_target); * really want to use scsi_device_lookup instead. **/ struct scsi_device *__scsi_device_lookup(struct Scsi_Host *shost, - uint channel, uint id, u64 lun) + u16 channel, u16 id, u64 lun) { - struct scsi_device *sdev; + struct scsi_target *starget; - list_for_each_entry(sdev, &shost->__devices, siblings) { - if (sdev->sdev_state == SDEV_DEL) - continue; - if (sdev->channel == channel && sdev->id == id && - sdev->lun ==lun) - return sdev; - } - - return NULL; + starget = __scsi_target_lookup(shost, channel, id); + if (!starget) + return NULL; + return __scsi_device_lookup_by_target(starget, lun); } EXPORT_SYMBOL(__scsi_device_lookup); @@ -729,7 +737,7 @@ EXPORT_SYMBOL(__scsi_device_lookup); * needs to be released with scsi_device_put once you're done with it. **/ struct scsi_device *scsi_device_lookup(struct Scsi_Host *shost, - uint channel, uint id, u64 lun) + u16 channel, u16 id, u64 lun) { struct scsi_device *sdev; unsigned long flags; diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index f2437a7570ce..9fc35b6cbc30 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -309,6 +309,7 @@ static void scsi_target_destroy(struct scsi_target *starget) struct device *dev = &starget->dev; struct Scsi_Host *shost = dev_to_shost(dev->parent); unsigned long flags; + unsigned long tid = scsi_target_index(starget); BUG_ON(starget->state == STARGET_DEL); starget->state = STARGET_DEL; @@ -316,7 +317,7 @@ static void scsi_target_destroy(struct scsi_target *starget) spin_lock_irqsave(shost->host_lock, flags); if (shost->hostt->target_destroy) shost->hostt->target_destroy(starget); - list_del_init(&starget->siblings); + xa_erase(&shost->__targets, tid); spin_unlock_irqrestore(shost->host_lock, flags); put_device(dev); } @@ -341,27 +342,6 @@ int scsi_is_target_device(const struct device *dev) } EXPORT_SYMBOL(scsi_is_target_device); -static struct scsi_target *__scsi_find_target(struct device *parent, - int channel, uint id) -{ - struct scsi_target *starget, *found_starget = NULL; - struct Scsi_Host *shost = dev_to_shost(parent); - /* - * Search for an existing target for this sdev. - */ - list_for_each_entry(starget, &shost->__targets, siblings) { - if (starget->id == id && - starget->channel == channel) { - found_starget = starget; - break; - } - } - if (found_starget) - get_device(&found_starget->dev); - - return found_starget; -} - /** * scsi_target_reap_ref_release - remove target from visibility * @kref: the reap_ref in the target being released @@ -417,6 +397,7 @@ static struct scsi_target *scsi_alloc_target(struct device *parent, struct scsi_target *starget; struct scsi_target *found_target; int error, ref_got; + unsigned long tid; starget = kzalloc(size, GFP_KERNEL); if (!starget) { @@ -433,27 +414,37 @@ static struct scsi_target *scsi_alloc_target(struct device *parent, starget->id = id; starget->channel = channel; starget->can_queue = 0; - INIT_LIST_HEAD(&starget->siblings); INIT_LIST_HEAD(&starget->devices); starget->state = STARGET_CREATED; starget->scsi_level = SCSI_2; starget->max_target_blocked = SCSI_DEFAULT_TARGET_BLOCKED; + tid = scsi_target_index(starget); retry: spin_lock_irqsave(shost->host_lock, flags); - - found_target = __scsi_find_target(parent, channel, id); - if (found_target) + found_target = xa_load(&shost->__targets, tid); + if (found_target) { + get_device(&found_target->dev); goto found; - - list_add_tail(&starget->siblings, &shost->__targets); + } + error = xa_insert(&shost->__targets, tid, starget, GFP_ATOMIC); spin_unlock_irqrestore(shost->host_lock, flags); + if (error) { + dev_printk(KERN_ERR, dev, + "target %u:%u index allocation failed, error %d\n", + channel, id, error); + put_device(dev); + kfree(starget); + return NULL; + } /* allocate and add */ transport_setup_device(dev); if (shost->hostt->target_alloc) { error = shost->hostt->target_alloc(starget); if(error) { - dev_printk(KERN_ERR, dev, "target allocation failed, error %d\n", error); + dev_printk(KERN_ERR, dev, + "target %u:%u allocation failed, error %d\n", + channel, id, error); /* don't want scsi_target_reap to do the final * put because it will be under the host lock */ scsi_target_destroy(starget); diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index 163dbcb741c1..83bdcb032853 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -1511,16 +1511,21 @@ static void __scsi_remove_target(struct scsi_target *starget) void scsi_remove_target(struct device *dev) { struct Scsi_Host *shost = dev_to_shost(dev->parent); - struct scsi_target *starget; + struct scsi_target *starget, *starget_next; + unsigned long tid = 0; unsigned long flags; -restart: spin_lock_irqsave(shost->host_lock, flags); - list_for_each_entry(starget, &shost->__targets, siblings) { + starget = xa_find(&shost->__targets, &tid, UINT_MAX, XA_PRESENT); + while (starget) { + starget_next = xa_find_after(&shost->__targets, &tid, + UINT_MAX, XA_PRESENT); if (starget->state == STARGET_DEL || starget->state == STARGET_REMOVE || - starget->state == STARGET_CREATED_REMOVE) + starget->state == STARGET_CREATED_REMOVE) { + starget = starget_next; continue; + } if (starget->dev.parent == dev || &starget->dev == dev) { kref_get(&starget->reap_ref); if (starget->state == STARGET_CREATED) @@ -1530,8 +1535,9 @@ void scsi_remove_target(struct device *dev) spin_unlock_irqrestore(shost->host_lock, flags); __scsi_remove_target(starget); scsi_target_reap(starget); - goto restart; + spin_lock_irqsave(shost->host_lock, flags); } + starget = starget_next; } spin_unlock_irqrestore(shost->host_lock, flags); } diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index bc5909033d13..867559eca33d 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -121,7 +121,7 @@ struct scsi_device { unsigned long last_queue_ramp_up; /* last queue ramp up time */ - unsigned int id, channel; + u16 id, channel; u64 lun; unsigned int manufacturer; /* Manufacturer of device, for using * vendor-specific cmd's */ @@ -291,8 +291,8 @@ struct scsi_target { struct list_head devices; struct device dev; struct kref reap_ref; /* last put renders target invisible */ - unsigned int channel; - unsigned int id; /* target id ... replace + u16 channel; + u16 id; /* target id ... replace * scsi_device.id eventually */ unsigned int create:1; /* signal that it needs to be added */ unsigned int single_lun:1; /* Indicates we should only @@ -324,6 +324,11 @@ struct scsi_target { /* starget_data must be the last element!!!! */ } __attribute__((aligned(sizeof(unsigned long)))); +static inline u32 scsi_target_index(struct scsi_target *starget) +{ + return (starget->channel << 16) | (starget->id); +} + #define to_scsi_target(d) container_of(d, struct scsi_target, dev) static inline struct scsi_target *scsi_target(struct scsi_device *sdev) { @@ -348,9 +353,9 @@ extern struct scsi_device *scsi_device_from_queue(struct request_queue *q); extern int __must_check scsi_device_get(struct scsi_device *); extern void scsi_device_put(struct scsi_device *); extern struct scsi_device *scsi_device_lookup(struct Scsi_Host *, - uint, uint, u64); + u16, u16, u64); extern struct scsi_device *__scsi_device_lookup(struct Scsi_Host *, - uint, uint, u64); + u16, u16, u64); extern struct scsi_device *scsi_device_lookup_by_target(struct scsi_target *, u64); extern struct scsi_device *__scsi_device_lookup_by_target(struct scsi_target *, diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index 46ef8cccc982..d0a765dd995a 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -528,7 +528,7 @@ struct Scsi_Host { * access this list directly from a driver. */ struct list_head __devices; - struct list_head __targets; + struct xarray __targets; struct list_head starved_list; From patchwork Fri Aug 21 15:41:59 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Douglas Gilbert X-Patchwork-Id: 257896 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0A2D7C433E1 for ; Fri, 21 Aug 2020 15:42:49 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id E4193207BB for ; Fri, 21 Aug 2020 15:42:48 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728174AbgHUPmk (ORCPT ); Fri, 21 Aug 2020 11:42:40 -0400 Received: from smtp.infotech.no ([82.134.31.41]:48328 "EHLO smtp.infotech.no" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725828AbgHUPmR (ORCPT ); Fri, 21 Aug 2020 11:42:17 -0400 Received: from localhost (localhost [127.0.0.1]) by smtp.infotech.no (Postfix) with ESMTP id B3E57204190; Fri, 21 Aug 2020 17:42:14 +0200 (CEST) X-Virus-Scanned: by amavisd-new-2.6.6 (20110518) (Debian) at infotech.no Received: from smtp.infotech.no ([127.0.0.1]) by localhost (smtp.infotech.no [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id NOuqMNtP-sXO; Fri, 21 Aug 2020 17:42:13 +0200 (CEST) Received: from xtwo70.bingwo.ca (host-45-78-251-166.dyn.295.ca [45.78.251.166]) by smtp.infotech.no (Postfix) with ESMTPA id 3687E204248; Fri, 21 Aug 2020 17:42:12 +0200 (CEST) From: Douglas Gilbert To: linux-scsi@vger.kernel.org Cc: martin.petersen@oracle.com, jejb@linux.vnet.ibm.com, hare@suse.de, john.garry@huawei.com Subject: [PATCH v6 05/10] scsi_error: use xarray lookup instead of wrappers Date: Fri, 21 Aug 2020 11:41:59 -0400 Message-Id: <20200821154204.9298-6-dgilbert@interlog.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200821154204.9298-1-dgilbert@interlog.com> References: <20200821154204.9298-1-dgilbert@interlog.com> MIME-Version: 1.0 Sender: linux-scsi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org From: Hannes Reinecke For SCSI EH most shost_for_each_sdev() calls are just to filter out devices for specific targets or channels. These calls can be made more efficient using direct xarray lookup and iterators. Signed-off-by: Hannes Reinecke Signed-off-by: Douglas Gilbert --- drivers/scsi/scsi.c | 2 +- drivers/scsi/scsi_error.c | 35 ++++++++++++++++++++++------------- drivers/scsi/scsi_priv.h | 2 ++ 3 files changed, 25 insertions(+), 14 deletions(-) diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index 294e9d4d8b46..0e22fff072ff 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -652,7 +652,7 @@ EXPORT_SYMBOL(__scsi_iterate_devices_unlocked); * @id: ID of the target * */ -static struct scsi_target *__scsi_target_lookup(struct Scsi_Host *shost, +struct scsi_target *__scsi_target_lookup(struct Scsi_Host *shost, u16 channel, u16 id) { return xa_load(&shost->__targets, (channel << 16) | id); diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 927b1e641842..02605c848365 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -643,7 +643,9 @@ EXPORT_SYMBOL_GPL(scsi_check_sense); static void scsi_handle_queue_ramp_up(struct scsi_device *sdev) { struct scsi_host_template *sht = sdev->host->hostt; + struct scsi_target *starget; struct scsi_device *tmp_sdev; + unsigned long lun_idx = 0; if (!sht->track_queue_depth || sdev->queue_depth >= sdev->max_queue_depth) @@ -661,10 +663,9 @@ static void scsi_handle_queue_ramp_up(struct scsi_device *sdev) * Walk all devices of a target and do * ramp up on them. */ - shost_for_each_device(tmp_sdev, sdev->host) { - if (tmp_sdev->channel != sdev->channel || - tmp_sdev->id != sdev->id || - tmp_sdev->queue_depth == sdev->max_queue_depth) + starget = __scsi_target_lookup(sdev->host, sdev->channel, sdev->id); + xa_for_each(&starget->__devices, lun_idx, tmp_sdev) { + if (tmp_sdev->queue_depth == sdev->max_queue_depth) continue; scsi_change_queue_depth(tmp_sdev, tmp_sdev->queue_depth + 1); @@ -675,14 +676,15 @@ static void scsi_handle_queue_ramp_up(struct scsi_device *sdev) static void scsi_handle_queue_full(struct scsi_device *sdev) { struct scsi_host_template *sht = sdev->host->hostt; + struct scsi_target *starget = sdev->sdev_target; struct scsi_device *tmp_sdev; + unsigned long lun_idx = 0; if (!sht->track_queue_depth) return; - shost_for_each_device(tmp_sdev, sdev->host) { - if (tmp_sdev->channel != sdev->channel || - tmp_sdev->id != sdev->id) + xa_for_each(&starget->__devices, lun_idx, tmp_sdev) { + if (tmp_sdev->sdev_state == SDEV_DEL) continue; /* * We do not know the number of commands that were at @@ -2273,10 +2275,16 @@ int scsi_error_handler(void *data) */ void scsi_report_bus_reset(struct Scsi_Host *shost, int channel) { + struct scsi_target *starget; struct scsi_device *sdev; + unsigned long tid = 0; - __shost_for_each_device(sdev, shost) { - if (channel == sdev_channel(sdev)) + xa_for_each(&shost->__targets, tid, starget) { + unsigned long lun_idx = 0; + + if (starget->channel != channel) + continue; + xa_for_each(&starget->__devices, lun_idx, sdev) __scsi_report_device_reset(sdev, NULL); } } @@ -2306,13 +2314,14 @@ EXPORT_SYMBOL(scsi_report_bus_reset); */ void scsi_report_device_reset(struct Scsi_Host *shost, int channel, int target) { + struct scsi_target *starget; struct scsi_device *sdev; + unsigned long lun_idx = 0; - __shost_for_each_device(sdev, shost) { - if (channel == sdev_channel(sdev) && - target == sdev_id(sdev)) + starget = __scsi_target_lookup(shost, channel, target); + if (starget) + xa_for_each(&starget->__devices, lun_idx, sdev) __scsi_report_device_reset(sdev, NULL); - } } EXPORT_SYMBOL(scsi_report_device_reset); diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h index d12ada035961..86da143ae06b 100644 --- a/drivers/scsi/scsi_priv.h +++ b/drivers/scsi/scsi_priv.h @@ -49,6 +49,8 @@ enum scsi_devinfo_key { SCSI_DEVINFO_SPI, }; +extern struct scsi_target *__scsi_target_lookup(struct Scsi_Host *shost, + u16 channel, u16 id); extern blist_flags_t scsi_get_device_flags(struct scsi_device *sdev, const unsigned char *vendor, const unsigned char *model); From patchwork Fri Aug 21 15:42:00 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Douglas Gilbert X-Patchwork-Id: 257895 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id AB6EBC433DF for ; Fri, 21 Aug 2020 15:42:54 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 891452063A for ; Fri, 21 Aug 2020 15:42:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728261AbgHUPmx (ORCPT ); Fri, 21 Aug 2020 11:42:53 -0400 Received: from smtp.infotech.no ([82.134.31.41]:48334 "EHLO smtp.infotech.no" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728008AbgHUPmX (ORCPT ); Fri, 21 Aug 2020 11:42:23 -0400 Received: from localhost (localhost [127.0.0.1]) by smtp.infotech.no (Postfix) with ESMTP id CD249204248; Fri, 21 Aug 2020 17:42:15 +0200 (CEST) X-Virus-Scanned: by amavisd-new-2.6.6 (20110518) (Debian) at infotech.no Received: from smtp.infotech.no ([127.0.0.1]) by localhost (smtp.infotech.no [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id F5TEOiLB0ChM; Fri, 21 Aug 2020 17:42:14 +0200 (CEST) Received: from xtwo70.bingwo.ca (host-45-78-251-166.dyn.295.ca [45.78.251.166]) by smtp.infotech.no (Postfix) with ESMTPA id 68A9A204155; Fri, 21 Aug 2020 17:42:13 +0200 (CEST) From: Douglas Gilbert To: linux-scsi@vger.kernel.org Cc: martin.petersen@oracle.com, jejb@linux.vnet.ibm.com, hare@suse.de, john.garry@huawei.com Subject: [PATCH v6 06/10] scsi: avoid pointless memory allocation in scsi_alloc_target() Date: Fri, 21 Aug 2020 11:42:00 -0400 Message-Id: <20200821154204.9298-7-dgilbert@interlog.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200821154204.9298-1-dgilbert@interlog.com> References: <20200821154204.9298-1-dgilbert@interlog.com> MIME-Version: 1.0 Sender: linux-scsi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org From: Hannes Reinecke As we already know the index of the requested target in scsi_alloc_target() we can try to fetch it first before trying to allocate a new one. This will save us a pointless memory allocation in case the target is already present and uncontended. Signed-off-by: Hannes Reinecke Signed-off-by: Douglas Gilbert --- drivers/scsi/scsi_scan.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 8afb71c036d5..41818111808e 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -387,7 +387,7 @@ static void scsi_target_reap_ref_put(struct scsi_target *starget) * is responsible for both reaping and doing a last put */ static struct scsi_target *scsi_alloc_target(struct device *parent, - int channel, uint id) + u16 channel, u16 id) { struct Scsi_Host *shost = dev_to_shost(parent); struct device *dev = NULL; @@ -397,7 +397,23 @@ static struct scsi_target *scsi_alloc_target(struct device *parent, struct scsi_target *starget; struct scsi_target *found_target; int error, ref_got; - unsigned long tid; + unsigned long tid = (channel << 16) | id; + + /* + * Try if the target is already present, and save us + * a pointless memory allocation if so. + */ + spin_lock_irqsave(shost->host_lock, flags); + found_target = xa_load(&shost->__targets, tid); + if (found_target) { + get_device(&found_target->dev); + if (kref_get_unless_zero(&found_target->reap_ref)) { + spin_unlock_irqrestore(shost->host_lock, flags); + return found_target; + } + put_device(&found_target->dev); + } + spin_unlock_irqrestore(shost->host_lock, flags); starget = kzalloc(size, GFP_KERNEL); if (!starget) { @@ -418,7 +434,6 @@ static struct scsi_target *scsi_alloc_target(struct device *parent, starget->state = STARGET_CREATED; starget->scsi_level = SCSI_2; starget->max_target_blocked = SCSI_DEFAULT_TARGET_BLOCKED; - tid = scsi_target_index(starget); retry: spin_lock_irqsave(shost->host_lock, flags); found_target = xa_load(&shost->__targets, tid); From patchwork Fri Aug 21 15:42:01 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Douglas Gilbert X-Patchwork-Id: 257894 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 89824C433E1 for ; Fri, 21 Aug 2020 15:43:06 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 712782078B for ; Fri, 21 Aug 2020 15:43:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728265AbgHUPmy (ORCPT ); Fri, 21 Aug 2020 11:42:54 -0400 Received: from smtp.infotech.no ([82.134.31.41]:48341 "EHLO smtp.infotech.no" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728153AbgHUPmZ (ORCPT ); Fri, 21 Aug 2020 11:42:25 -0400 Received: from localhost (localhost [127.0.0.1]) by smtp.infotech.no (Postfix) with ESMTP id 6961320426D; Fri, 21 Aug 2020 17:42:17 +0200 (CEST) X-Virus-Scanned: by amavisd-new-2.6.6 (20110518) (Debian) at infotech.no Received: from smtp.infotech.no ([127.0.0.1]) by localhost (smtp.infotech.no [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id Pkkv24HtEyr4; Fri, 21 Aug 2020 17:42:15 +0200 (CEST) Received: from xtwo70.bingwo.ca (host-45-78-251-166.dyn.295.ca [45.78.251.166]) by smtp.infotech.no (Postfix) with ESMTPA id 9A9F9204269; Fri, 21 Aug 2020 17:42:14 +0200 (CEST) From: Douglas Gilbert To: linux-scsi@vger.kernel.org Cc: martin.petersen@oracle.com, jejb@linux.vnet.ibm.com, hare@suse.de, john.garry@huawei.com Subject: [PATCH v6 07/10] scsi: add starget_to_shost() specialization Date: Fri, 21 Aug 2020 11:42:01 -0400 Message-Id: <20200821154204.9298-8-dgilbert@interlog.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200821154204.9298-1-dgilbert@interlog.com> References: <20200821154204.9298-1-dgilbert@interlog.com> MIME-Version: 1.0 Sender: linux-scsi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org 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 --- 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 --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; From patchwork Fri Aug 21 15:42:02 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Douglas Gilbert X-Patchwork-Id: 257893 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7E932C433DF for ; Fri, 21 Aug 2020 15:43:27 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 58866207DF for ; Fri, 21 Aug 2020 15:43:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727123AbgHUPnT (ORCPT ); Fri, 21 Aug 2020 11:43:19 -0400 Received: from smtp.infotech.no ([82.134.31.41]:48345 "EHLO smtp.infotech.no" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728177AbgHUPme (ORCPT ); Fri, 21 Aug 2020 11:42:34 -0400 Received: from localhost (localhost [127.0.0.1]) by smtp.infotech.no (Postfix) with ESMTP id 2D19620425A; Fri, 21 Aug 2020 17:42:18 +0200 (CEST) X-Virus-Scanned: by amavisd-new-2.6.6 (20110518) (Debian) at infotech.no Received: from smtp.infotech.no ([127.0.0.1]) by localhost (smtp.infotech.no [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id Q4tdIIRPFXZh; Fri, 21 Aug 2020 17:42:16 +0200 (CEST) Received: from xtwo70.bingwo.ca (host-45-78-251-166.dyn.295.ca [45.78.251.166]) by smtp.infotech.no (Postfix) with ESMTPA id D026420426C; Fri, 21 Aug 2020 17:42:15 +0200 (CEST) From: Douglas Gilbert To: linux-scsi@vger.kernel.org Cc: martin.petersen@oracle.com, jejb@linux.vnet.ibm.com, hare@suse.de, john.garry@huawei.com Subject: [PATCH v6 08/10] scsi: simplify scsi_target() inline Date: Fri, 21 Aug 2020 11:42:02 -0400 Message-Id: <20200821154204.9298-9-dgilbert@interlog.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200821154204.9298-1-dgilbert@interlog.com> References: <20200821154204.9298-1-dgilbert@interlog.com> MIME-Version: 1.0 Sender: linux-scsi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org A review of the code indicates this scsi_device.h comment for a struct scsi_device member is misleading: struct scsi_target *sdev_target; /* used only for single_lun */ sdev_target is set once in scsi_alloc_sdev() to the new sdev's parent and not altered thereafter. This in turn implies that the often-used scsi_target(struct scsi_device *sdev) inline function is going the long way around finding its parent. Simplify it and rework that comment. Signed-off-by: Douglas Gilbert --- include/scsi/scsi_device.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index 5292787246ca..b0ba534b6f06 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -141,7 +141,7 @@ struct scsi_device { struct scsi_vpd __rcu *vpd_pg80; struct scsi_vpd __rcu *vpd_pg89; unsigned char current_tag; /* current tag */ - struct scsi_target *sdev_target; /* used only for single_lun */ + struct scsi_target *sdev_target; /* parent of this object */ blist_flags_t sdev_bflags; /* black/white flags as also found in * scsi_devinfo.[hc]. For now used only to @@ -337,7 +337,7 @@ static inline struct Scsi_Host *starget_to_shost(struct scsi_target *starg) #define to_scsi_target(d) container_of(d, struct scsi_target, dev) static inline struct scsi_target *scsi_target(struct scsi_device *sdev) { - return to_scsi_target(sdev->sdev_gendev.parent); + return sdev->sdev_target; } #define transport_class_to_starget(class_dev) \ to_scsi_target(class_dev->parent)