aic94xx: cleanup after a discovery error
Subsystems (2)
PATCH 3/4 aic94xx: 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 +15 -2
@@ -585,7 +598,7 @@ int sas_discover_end_dev(struct domain_d res =sas_notify_lldd_dev_found (dev);if (res) -return res; + goto out_err2; res =sas_rphy_add (dev->rphy);if (res)
@@ -594,12 +607,21 @@ 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_err3;return 0 ; out_err:sas_notify_lldd_dev_gone (dev); +out_err2: +sas_rphy_free (dev->rphy); + dev->rphy =NULL ; +return res; +out_err3: +sas_rphy_delete (dev->rphy); + dev->rphy =NULL ;return res; }
@@ -689,6 +711,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
@@ -1474,14 +1474,27 @@ int sas_discover_root_expander(struct doint 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 ---------- */
---
One question that remains with this patch is whether or not sas_get_port_device should be moved into sas_discover_{sas,expander} to ensure that the rphy struct is allocated and freed-in-error in the same function
Quoted 4 lines · Alexis Bruemmer
One question that remains with this patch is whether or not
sas_get_port_deviceshould be moved into sas_discover_{sas,expander} to ensure that the rphy struct is allocated and freed-in-error in the same function
It looks as though we could move the parts of sas_get_port_device() that deal with rphy allocation/initialization into the sas_discover_{sata,sas,expander} functions? I don't know for sure; I could be missing some subtlety that requires the sas_rphy creation to be in sas_get_port_device.
--D
Quoted 2 lines · Alexis Bruemmer
Domain device is freed but the port dev list is not adjusted on some discovery errors. Module unload will Oops if this happens.
It'll still oops; sas_ex_discover_end_dev needs to be updated to know that it needn't call sas_rphy_free if the device-specific discovery functions fail. This patch should fix that case too.
--
drivers/scsi/libsas/sas_expander.c +0 -1
@@ -711,7 +711,6 @@ static struct domain_device *sas_ex_disc out_list_del:list_del (&child->dev_list_node); -sas_rphy_free (rphy); out_free:sas_port_delete (phy->port); out_err:
Quoted 3 lines · Darrick J. Wong
It'll still oops;
sas_ex_discover_end_devneeds to be updated to know that it needn't callsas_rphy_freeif the device-specific discovery functions fail. This patch should fix that case too.
Erm... this patch is only necessary if one has jejb's "better error handling in sas_ex_discover_end_dev()" patch applied.
(My queue of pending patches is getting a bit too long, methinks.)
--D
This patch applies the same cleanups to sas_discover_sata. Note that this is against aic94xx-sas, not scsi-misc.
--
drivers/scsi/libsas/sas_discover.c +18 -5
@@ -552,7 +552,7 @@ int sas_discover_sata(struct domain_devi res =sas_notify_lldd_dev_found (dev);if (res) -return res; + goto out_err2;switch (dev->dev_type) {case SATA_DEV :
@@ -564,12 +564,25 @@ int sas_discover_sata(struct domain_devidefault :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; }