From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755590AbZHMTrq (ORCPT ); Thu, 13 Aug 2009 15:47:46 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1755579AbZHMTro (ORCPT ); Thu, 13 Aug 2009 15:47:44 -0400 Received: from kroah.org ([198.145.64.141]:36698 "EHLO coco.kroah.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755562AbZHMTrn (ORCPT ); Thu, 13 Aug 2009 15:47:43 -0400 X-Mailbox-Line: From gregkh@mini.kroah.org Thu Aug 13 12:43:36 2009 Message-Id: <20090813194336.011177297@mini.kroah.org> User-Agent: quilt/0.48-1 Date: Thu, 13 Aug 2009 12:40:25 -0700 From: Greg KH To: linux-kernel@vger.kernel.org, stable@kernel.org Cc: stable-review@kernel.org, torvalds@linux-foundation.org, akpm@linux-foundation.org, alan@lxorguk.ukuu.org.uk, Tom Peng , Jack Wang , Lindar Liu , James Bottomley Subject: [patch 04/28] SCSI: libsas: reuse the original port when hotplugging phys in wide ports References: <20090813194021.446758568@mini.kroah.org> Content-Disposition: inline; filename=libsas-reuse-the-original-port-when-hotplugging-phys-in-wide-ports.patch In-Reply-To: <20090813194554.GA13947@kroah.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 2.6.27-stable review patch. If anyone has any objections, please let us know. ------------------ From: Tom Peng commit 5381837f125cc62ad703fbcdfcd7566fc81fd404 upstream. There's a hotplug problem in the way libsas allocates ports: it loops over the available ports first trying to add to an existing for a wide port and otherwise allocating the next free port. This scheme only works if the port array is packed from zero, which fails if a port gets hot unplugged and the array becomes sparse. In that case, a new port is formed even if there's a wide port it should be part of. Fix this by creating two loops over all the ports: the first to see if the phy should be part of a wide port and the second to form a new port in an empty port slot. Signed-off-by: Tom Peng Signed-off-by: Jack Wang Signed-off-by: Lindar Liu Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/libsas/sas_port.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) --- a/drivers/scsi/libsas/sas_port.c +++ b/drivers/scsi/libsas/sas_port.c @@ -56,7 +56,7 @@ static void sas_form_port(struct asd_sas } } - /* find a port */ + /* see if the phy should be part of a wide port */ spin_lock_irqsave(&sas_ha->phy_port_lock, flags); for (i = 0; i < sas_ha->num_phys; i++) { port = sas_ha->sas_port[i]; @@ -69,12 +69,23 @@ static void sas_form_port(struct asd_sas SAS_DPRINTK("phy%d matched wide port%d\n", phy->id, port->id); break; - } else if (*(u64 *) port->sas_addr == 0 && port->num_phys==0) { - memcpy(port->sas_addr, phy->sas_addr, SAS_ADDR_SIZE); - break; } spin_unlock(&port->phy_list_lock); } + /* The phy does not match any existing port, create a new one */ + if (i == sas_ha->num_phys) { + for (i = 0; i < sas_ha->num_phys; i++) { + port = sas_ha->sas_port[i]; + spin_lock(&port->phy_list_lock); + if (*(u64 *)port->sas_addr == 0 + && port->num_phys == 0) { + memcpy(port->sas_addr, phy->sas_addr, + SAS_ADDR_SIZE); + break; + } + spin_unlock(&port->phy_list_lock); + } + } if (i >= sas_ha->num_phys) { printk(KERN_NOTICE "%s: couldn't find a free port, bug?\n",