Domain device is freed but the port dev list is not adjusted on some discovery errors. Module unload will Oops if this happens. Signed-off-by: Darrick J. Wong <djwong@xxxxxxxxxx> --- diff --git a/drivers/scsi/libsas/sas_discover.c b/drivers/scsi/libsas/sas_discover.c index 23461dc..dcd0461 100644 --- a/drivers/scsi/libsas/sas_discover.c +++ b/drivers/scsi/libsas/sas_discover.c @@ -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; } diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c index 4cc7457..a79e89c 100644 --- a/drivers/scsi/libsas/sas_expander.c +++ b/drivers/scsi/libsas/sas_expander.c @@ -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 ---------- */ --- 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 - To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html