From patchwork Mon Oct 5 23:01:11 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lee Duncan X-Patchwork-Id: 7332181 Return-Path: X-Original-To: patchwork-linux-scsi@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 2DA34BEEA4 for ; Mon, 5 Oct 2015 23:01:54 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 3586A206AD for ; Mon, 5 Oct 2015 23:01:52 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 28B21206A5 for ; Mon, 5 Oct 2015 23:01:51 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752293AbbJEXBX (ORCPT ); Mon, 5 Oct 2015 19:01:23 -0400 Received: from mx2.suse.de ([195.135.220.15]:36100 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752032AbbJEXBW (ORCPT ); Mon, 5 Oct 2015 19:01:22 -0400 X-Virus-Scanned: by amavisd-new at test-mx.suse.de X-Amavis-Alert: BAD HEADER SECTION, Duplicate header field: "References" Received: from relay2.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 15FCCAABB; Mon, 5 Oct 2015 23:01:18 +0000 (UTC) Received: by worklaptop.gonzoleeman.net (Postfix, from userid 1000) id 2F8CC4046A; Mon, 5 Oct 2015 16:01:13 -0700 (PDT) From: Lee Duncan To: linux-scsi@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Lee Duncan , James Bottomley , Tejun Heo , Hannes Reinecke , Johannes Thumshirn , Christoph Hellwig Subject: [PATCHv2 1/1] SCSI: update hosts module to use idr index management Date: Mon, 5 Oct 2015 16:01:11 -0700 Message-Id: <1a69690d615610c1dee725db7e6d81cf2db28266.1444085255.git.lduncan@suse.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: References: In-Reply-To: References: Sender: linux-scsi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Update the SCSI hosts module to use idr to manage its host_no index instead of an ATOMIC integer. This also allows using idr_find() to look up the SCSI host structure given the host number. This means that the SCSI host number will now be reclaimable. Signed-off-by: Lee Duncan Reviewed-by: Hannes Reinecke --- drivers/scsi/hosts.c | 60 +++++++++++++++++++++++++--------------------------- 1 file changed, 29 insertions(+), 31 deletions(-) diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index 8bb173e01084..9dc8ff971f5a 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c @@ -33,7 +33,7 @@ #include #include #include - +#include #include #include #include @@ -41,8 +41,8 @@ #include "scsi_priv.h" #include "scsi_logging.h" - -static atomic_t scsi_host_next_hn = ATOMIC_INIT(0); /* host_no for next new host */ +static DEFINE_IDR(host_index_idr); +static DEFINE_SPINLOCK(host_index_lock); static void scsi_host_cls_release(struct device *dev) @@ -337,6 +337,10 @@ static void scsi_host_dev_release(struct device *dev) kfree(shost->shost_data); + spin_lock(&host_index_lock); + idr_remove(&host_index_idr, shost->host_no); + spin_unlock(&host_index_lock); + if (parent) put_device(parent); kfree(shost); @@ -370,6 +374,7 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize) { struct Scsi_Host *shost; gfp_t gfp_mask = GFP_KERNEL; + int index; if (sht->unchecked_isa_dma && privsize) gfp_mask |= __GFP_DMA; @@ -388,11 +393,15 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize) init_waitqueue_head(&shost->host_wait); mutex_init(&shost->scan_mutex); - /* - * subtract one because we increment first then return, but we need to - * know what the next host number was before increment - */ - shost->host_no = atomic_inc_return(&scsi_host_next_hn) - 1; + idr_preload(GFP_KERNEL); + spin_lock(&host_index_lock); + index = idr_alloc(&host_index_idr, shost, 0, 0, GFP_NOWAIT); + spin_unlock(&host_index_lock); + idr_preload_end(); + if (index < 0) + goto fail_kfree; + shost->host_no = index; + shost->dma_channel = 0xff; /* These three are default values which can be overridden */ @@ -477,7 +486,7 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize) shost_printk(KERN_WARNING, shost, "error handler thread failed to spawn, error = %ld\n", PTR_ERR(shost->ehandler)); - goto fail_kfree; + goto fail_idr_remove; } shost->tmf_work_q = alloc_workqueue("scsi_tmf_%d", @@ -493,6 +502,10 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize) fail_kthread: kthread_stop(shost->ehandler); + fail_idr_remove: + spin_lock(&host_index_lock); + idr_remove(&host_index_idr, shost->host_no); + spin_unlock(&host_index_lock); fail_kfree: kfree(shost); return NULL; @@ -522,37 +535,21 @@ void scsi_unregister(struct Scsi_Host *shost) } EXPORT_SYMBOL(scsi_unregister); -static int __scsi_host_match(struct device *dev, const void *data) -{ - struct Scsi_Host *p; - const unsigned short *hostnum = data; - - p = class_to_shost(dev); - return p->host_no == *hostnum; -} - /** * scsi_host_lookup - get a reference to a Scsi_Host by host no * @hostnum: host number to locate * * Return value: * A pointer to located Scsi_Host or NULL. - * - * The caller must do a scsi_host_put() to drop the reference - * that scsi_host_get() took. The put_device() below dropped - * the reference from class_find_device(). **/ struct Scsi_Host *scsi_host_lookup(unsigned short hostnum) { - struct device *cdev; - struct Scsi_Host *shost = NULL; - - cdev = class_find_device(&shost_class, NULL, &hostnum, - __scsi_host_match); - if (cdev) { - shost = scsi_host_get(class_to_shost(cdev)); - put_device(cdev); - } + struct Scsi_Host *shost; + + spin_lock(&host_index_lock); + shost = idr_find(&host_index_idr, hostnum); + spin_unlock(&host_index_lock); + return shost; } EXPORT_SYMBOL(scsi_host_lookup); @@ -588,6 +585,7 @@ int scsi_init_hosts(void) void scsi_exit_hosts(void) { class_unregister(&shost_class); + idr_destroy(&host_index_idr); } int scsi_is_host_device(const struct device *dev)