[SCSI] libsas: better error handling in sas_expander.c

With async scanning, we're now tripping the BUG_ON in
sas_ex_discover_end_dev(), so make the error handling here correct.

Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
This commit is contained in:
James Bottomley 2006-11-15 18:03:07 -06:00 committed by James Bottomley
parent ba8d55048a
commit 024879ead9

View File

@ -597,10 +597,15 @@ static struct domain_device *sas_ex_discover_end_dev(
child->iproto = phy->attached_iproto; child->iproto = phy->attached_iproto;
memcpy(child->sas_addr, phy->attached_sas_addr, SAS_ADDR_SIZE); memcpy(child->sas_addr, phy->attached_sas_addr, SAS_ADDR_SIZE);
sas_hash_addr(child->hashed_sas_addr, child->sas_addr); sas_hash_addr(child->hashed_sas_addr, child->sas_addr);
phy->port = sas_port_alloc(&parent->rphy->dev, phy_id); if (!phy->port) {
BUG_ON(!phy->port); phy->port = sas_port_alloc(&parent->rphy->dev, phy_id);
/* FIXME: better error handling*/ if (unlikely(!phy->port))
BUG_ON(sas_port_add(phy->port) != 0); goto out_err;
if (unlikely(sas_port_add(phy->port) != 0)) {
sas_port_free(phy->port);
goto out_err;
}
}
sas_ex_get_linkrate(parent, child, phy); sas_ex_get_linkrate(parent, child, phy);
if ((phy->attached_tproto & SAS_PROTO_STP) || phy->attached_sata_dev) { if ((phy->attached_tproto & SAS_PROTO_STP) || phy->attached_sata_dev) {
@ -615,8 +620,7 @@ static struct domain_device *sas_ex_discover_end_dev(
SAS_DPRINTK("report phy sata to %016llx:0x%x returned " SAS_DPRINTK("report phy sata to %016llx:0x%x returned "
"0x%x\n", SAS_ADDR(parent->sas_addr), "0x%x\n", SAS_ADDR(parent->sas_addr),
phy_id, res); phy_id, res);
kfree(child); goto out_free;
return NULL;
} }
memcpy(child->frame_rcvd, &child->sata_dev.rps_resp.rps.fis, memcpy(child->frame_rcvd, &child->sata_dev.rps_resp.rps.fis,
sizeof(struct dev_to_host_fis)); sizeof(struct dev_to_host_fis));
@ -627,14 +631,14 @@ static struct domain_device *sas_ex_discover_end_dev(
"%016llx:0x%x returned 0x%x\n", "%016llx:0x%x returned 0x%x\n",
SAS_ADDR(child->sas_addr), SAS_ADDR(child->sas_addr),
SAS_ADDR(parent->sas_addr), phy_id, res); SAS_ADDR(parent->sas_addr), phy_id, res);
kfree(child); goto out_free;
return NULL;
} }
} else if (phy->attached_tproto & SAS_PROTO_SSP) { } else if (phy->attached_tproto & SAS_PROTO_SSP) {
child->dev_type = SAS_END_DEV; child->dev_type = SAS_END_DEV;
rphy = sas_end_device_alloc(phy->port); rphy = sas_end_device_alloc(phy->port);
/* FIXME: error handling */ /* FIXME: error handling */
BUG_ON(!rphy); if (unlikely(!rphy))
goto out_free;
child->tproto = phy->attached_tproto; child->tproto = phy->attached_tproto;
sas_init_dev(child); sas_init_dev(child);
@ -651,9 +655,7 @@ static struct domain_device *sas_ex_discover_end_dev(
"at %016llx:0x%x returned 0x%x\n", "at %016llx:0x%x returned 0x%x\n",
SAS_ADDR(child->sas_addr), SAS_ADDR(child->sas_addr),
SAS_ADDR(parent->sas_addr), phy_id, res); SAS_ADDR(parent->sas_addr), phy_id, res);
/* FIXME: this kfrees list elements without removing them */ goto out_list_del;
//kfree(child);
return NULL;
} }
} else { } else {
SAS_DPRINTK("target proto 0x%x at %016llx:0x%x not handled\n", SAS_DPRINTK("target proto 0x%x at %016llx:0x%x not handled\n",
@ -663,6 +665,16 @@ static struct domain_device *sas_ex_discover_end_dev(
list_add_tail(&child->siblings, &parent_ex->children); list_add_tail(&child->siblings, &parent_ex->children);
return child; return child;
out_list_del:
list_del(&child->dev_list_node);
sas_rphy_free(rphy);
out_free:
sas_port_delete(phy->port);
out_err:
phy->port = NULL;
kfree(child);
return NULL;
} }
static struct domain_device *sas_ex_discover_expander( static struct domain_device *sas_ex_discover_expander(