diff options
author | Dan Williams <dan.j.williams@intel.com> | 2011-11-17 20:59:47 -0500 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2012-02-19 14:37:47 -0500 |
commit | 735f7d2fedf57380214221be7bed7f62d729e262 (patch) | |
tree | 067db49c22dcbdf695a6517a6c8664b6bb2c2d32 /drivers/scsi/libsas/sas_expander.c | |
parent | 6f4e75a49fd07d707995865493b9f452302ae36b (diff) |
[SCSI] libsas: fix domain_device leak
Arrange for the deallocation of a struct domain_device object when it no
longer has:
1/ any children
2/ references by any scsi_targets
3/ references by a lldd
The comment about domain_device lifetime in
Documentation/scsi/libsas.txt is stale as it appears mainline never had
a version of a struct domain_device that was registered as a kobject.
We now manage domain_device reference counts on behalf of external
agents.
Reviewed-by: Jack Wang <jack_wang@usish.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/libsas/sas_expander.c')
-rw-r--r-- | drivers/scsi/libsas/sas_expander.c | 10 |
1 files changed, 6 insertions, 4 deletions
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c index 1b831c55ec6e..15d2239a378b 100644 --- a/drivers/scsi/libsas/sas_expander.c +++ b/drivers/scsi/libsas/sas_expander.c | |||
@@ -657,10 +657,11 @@ static struct domain_device *sas_ex_discover_end_dev( | |||
657 | if (phy->attached_sata_host || phy->attached_sata_ps) | 657 | if (phy->attached_sata_host || phy->attached_sata_ps) |
658 | return NULL; | 658 | return NULL; |
659 | 659 | ||
660 | child = kzalloc(sizeof(*child), GFP_KERNEL); | 660 | child = sas_alloc_device(); |
661 | if (!child) | 661 | if (!child) |
662 | return NULL; | 662 | return NULL; |
663 | 663 | ||
664 | kref_get(&parent->kref); | ||
664 | child->parent = parent; | 665 | child->parent = parent; |
665 | child->port = parent->port; | 666 | child->port = parent->port; |
666 | child->iproto = phy->attached_iproto; | 667 | child->iproto = phy->attached_iproto; |
@@ -762,7 +763,7 @@ static struct domain_device *sas_ex_discover_end_dev( | |||
762 | sas_port_delete(phy->port); | 763 | sas_port_delete(phy->port); |
763 | out_err: | 764 | out_err: |
764 | phy->port = NULL; | 765 | phy->port = NULL; |
765 | kfree(child); | 766 | sas_put_device(child); |
766 | return NULL; | 767 | return NULL; |
767 | } | 768 | } |
768 | 769 | ||
@@ -809,7 +810,7 @@ static struct domain_device *sas_ex_discover_expander( | |||
809 | phy->attached_phy_id); | 810 | phy->attached_phy_id); |
810 | return NULL; | 811 | return NULL; |
811 | } | 812 | } |
812 | child = kzalloc(sizeof(*child), GFP_KERNEL); | 813 | child = sas_alloc_device(); |
813 | if (!child) | 814 | if (!child) |
814 | return NULL; | 815 | return NULL; |
815 | 816 | ||
@@ -835,6 +836,7 @@ static struct domain_device *sas_ex_discover_expander( | |||
835 | child->rphy = rphy; | 836 | child->rphy = rphy; |
836 | edev = rphy_to_expander_device(rphy); | 837 | edev = rphy_to_expander_device(rphy); |
837 | child->dev_type = phy->attached_dev_type; | 838 | child->dev_type = phy->attached_dev_type; |
839 | kref_get(&parent->kref); | ||
838 | child->parent = parent; | 840 | child->parent = parent; |
839 | child->port = port; | 841 | child->port = port; |
840 | child->iproto = phy->attached_iproto; | 842 | child->iproto = phy->attached_iproto; |
@@ -858,7 +860,7 @@ static struct domain_device *sas_ex_discover_expander( | |||
858 | spin_lock_irq(&parent->port->dev_list_lock); | 860 | spin_lock_irq(&parent->port->dev_list_lock); |
859 | list_del(&child->dev_list_node); | 861 | list_del(&child->dev_list_node); |
860 | spin_unlock_irq(&parent->port->dev_list_lock); | 862 | spin_unlock_irq(&parent->port->dev_list_lock); |
861 | kfree(child); | 863 | sas_put_device(child); |
862 | return NULL; | 864 | return NULL; |
863 | } | 865 | } |
864 | list_add_tail(&child->siblings, &parent->ex_dev.children); | 866 | list_add_tail(&child->siblings, &parent->ex_dev.children); |