Skip to contentSkip to conversation

cleanup after a discovery error

PATCH In review [email protected] 3 participants 4 messages Oct 19, 2006 – Nov 7, 2006

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 cleanup after a discovery error

Domain device is freed but the port dev list is not adjusted on some discovery errors. Module unload will Oops if this happens.

drivers/scsi/libsas/sas_discover.c +17 -1
diff -r 4e1720b3c71b drivers/scsi/libsas/sas_discover.c
@@ -684,7 +684,23 @@ static void sas_discover_domain(void *da
 	}
 
 	if (error) {
-		kfree(port->port_dev); /* not kobject_register-ed yet */
+		struct domain_device *dev = port->port_dev;
+		
+		if (dev->rphy) {
+			sas_remove_children(&dev->rphy->dev);
+			sas_rphy_delete(dev->rphy);
+			dev->rphy = NULL;
+		}
+		if (dev->dev_type == EDGE_DEV || dev->dev_type == FANOUT_DEV) {
+			if (dev->ex_dev.ex_phy) {
+				kfree(dev->ex_dev.ex_phy);
+				dev->ex_dev.ex_phy = NULL;
+			}
+		}
+		spin_lock(&port->dev_list_lock);
+		list_del_init(&dev->dev_list_node);
+		spin_unlock(&port->dev_list_lock);
+		kfree(dev); /* not kobject_register-ed yet */
 		port->port_dev = NULL;
 	}
 
#1 lore raw
Quoted 20 lines · On Wed, 2006-10-18 at 20:19 -0700, [email protected] wrote:

Domain device is freed but the port dev list is not adjusted on some discovery errors. Module unload will Oops if this happens.

diff -r 4e1720b3c71b drivers/scsi/libsas/sas_discover.c

drivers/scsi/libsas/sas_discover.c +7 -1
@@ -684,7 +684,23 @@ static void sas_discover_domain(void *da
 	}
 
 	if (error) {
-		kfree(port->port_dev); /* not kobject_register-ed yet */
+		struct domain_device *dev = port->port_dev;
+		
+		if (dev->rphy) {
+			sas_remove_children(&dev->rphy->dev);
+			sas_rphy_delete(dev->rphy);
+			dev->rphy = NULL;
+		}

drivers/scsi/libsas/sas_discover.c static void sas_discover_domain(void *da · line 703

Quoted 10 lines
drivers/scsi/libsas/sas_discover.c +10 -0
+		if (dev->dev_type == EDGE_DEV || dev->dev_type == FANOUT_DEV) {
+			if (dev->ex_dev.ex_phy) {
+				kfree(dev->ex_dev.ex_phy);
+				dev->ex_dev.ex_phy = NULL;
+			}
+		}
+		spin_lock(&port->dev_list_lock);
+		list_del_init(&dev->dev_list_node);
+		spin_unlock(&port->dev_list_lock);
+		kfree(dev); /* not kobject_register-ed yet */

This is a bit of a layering violation

if the various discover functions are going to return an error, I think it's their job to clean up whatever they did before returning.

James

#2 lore raw
Quoted 7 lines · James Bottomley [[email protected]] wrote:

This is a bit of a layering violation

if the various discover functions are going to return an error, I think it's their job to clean up whatever they did before returning.

James

Hope this works better.

drivers/scsi/libsas/sas_discover.c +5 -0
diff -r 80de69a94159 drivers/scsi/libsas/sas_discover.c
@@ -684,6 +684,11 @@ static void sas_discover_domain(void *da
 	}
 
 	if (error) {
+		sas_rphy_delete(port->port_dev->rphy);
+		port->port_dev->rphy = NULL;
+		spin_lock(&port->dev_list_lock);
+		list_del_init(&port->port_dev->dev_list_node);
+		spin_unlock(&port->dev_list_lock);
 		kfree(port->port_dev); /* not kobject_register-ed yet */
 		port->port_dev = NULL;
 	}
#3 lore raw
Quoted 5 lines
Quoted 4 lines · James Bottomley [[email protected]] wrote:

This is a bit of a layering violation

if the various discover functions are going to return an error, I think it's their job to clean up whatever they did before returning.

Here's a reworked version of Malahal's patch that pushes the sas_rphy cleanups into the sas_discover_{sas,sata,expander}.* functions. It also checks the return value of sas_notify_lldd_dev_found(). This patch (since it includes discovery error cleanup for SATA) is against 2.6.19-rc4 + scsi-misc + scsi-rc-fixes + aic94xx-sas, though I can respin it without the SATA bits if desired.

--

drivers/scsi/libsas/sas_discover.c +30 -5
index 23461dc..0f790ea 100644
@@ -564,12 +564,25 @@ int sas_discover_sata(struct domain_devi
 	default:
 		break;
 	}
+	if (res)
+		goto out_err;
 
 	sas_notify_lldd_dev_gone(dev);
-	if (!res) {
-		sas_notify_lldd_dev_found(dev);
-		res = sas_rphy_add(dev->rphy);
-	}
+	res = sas_notify_lldd_dev_found(dev);
+	if (res)
+		goto out_err2;
+
+	res = sas_rphy_add(dev->rphy);
+	if (res)
+		goto out_err;
+
+	return res;
+
+out_err:
+	sas_notify_lldd_dev_gone(dev);
+out_err2:
+	sas_rphy_free(dev->rphy);
+	dev->rphy = NULL;
 	return res;
 }
 
@@ -594,12 +607,20 @@ int sas_discover_end_dev(struct domain_d
 	/* do this to get the end device port attributes which will have
 	 * been scanned in sas_rphy_add */
 	sas_notify_lldd_dev_gone(dev);
-	sas_notify_lldd_dev_found(dev);
+	res = sas_notify_lldd_dev_found(dev);
+	if (res)
+		goto out_err2;
 
 	return 0;
 
 out_err:
 	sas_notify_lldd_dev_gone(dev);
+	sas_rphy_free(dev->rphy);
+	dev->rphy = NULL;
+	return res;
+out_err2:
+	sas_rphy_delete(dev->rphy);
+	dev->rphy = NULL;
 	return res;
 }
 
@@ -689,6 +710,10 @@ static void sas_discover_domain(void *da
 	}
 
 	if (error) {
+		spin_lock(&port->dev_list_lock);
+		list_del_init(&port->port_dev->dev_list_node);
+		spin_unlock(&port->dev_list_lock);
+
 		kfree(port->port_dev); /* not kobject_register-ed yet */
 		port->port_dev = NULL;
 	}
drivers/scsi/libsas/sas_expander.c +16 -3
index 4cc7457..a79e89c 100644
@@ -1474,14 +1474,27 @@ int sas_discover_root_expander(struct do
 	int res;
 	struct sas_expander_device *ex = rphy_to_expander_device(dev->rphy);
 
-	sas_rphy_add(dev->rphy);
+	res = sas_rphy_add(dev->rphy);
+	if (res)
+		goto out_err;
 
 	ex->level = dev->port->disc.max_level; /* 0 */
 	res = sas_discover_expander(dev);
-	if (!res)
-		sas_ex_bfs_disc(dev->port);
+	if (res)
+		goto out_err2;
+
+	sas_ex_bfs_disc(dev->port);
 
 	return res;
+
+out_err2:
+	sas_rphy_delete(dev->rphy);
+	dev->rphy = NULL;
+	return res;
+out_err:
+	sas_rphy_free(dev->rphy);
+	dev->rphy = NULL;
+	return res;
 }
 
 /* ---------- Domain revalidation ---------- */