diff options
author | Dan Williams <dan.j.williams@intel.com> | 2011-03-03 20:59:32 -0500 |
---|---|---|
committer | Dan Williams <dan.j.williams@intel.com> | 2011-07-03 06:55:29 -0400 |
commit | d9c37390c4f02153188a64a7a89fa6798dc3ffc2 (patch) | |
tree | 508f28b5b88348b2d989f479442cbd6813bd2b42 /drivers/scsi/isci/init.c | |
parent | 6ad31fec306d532031b2f778f8656385df1b9d8f (diff) |
isci: preallocate remote devices
Until we synchronize against device removal this limits the damage of
use after free bugs to the driver's own objects. Unless we implement
reference counting we need to ensure at least a subset of a remote
device is valid at all times. We follow the lead of other libsas
drivers that also preallocate devices.
This also enforces maximum remote device accounting at the lldd layer,
but the core may still run out of RNC's before we hit this limit.
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Diffstat (limited to 'drivers/scsi/isci/init.c')
-rw-r--r-- | drivers/scsi/isci/init.c | 27 |
1 files changed, 7 insertions, 20 deletions
diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c index f1b8a51dd49f..2838beff43b8 100644 --- a/drivers/scsi/isci/init.c +++ b/drivers/scsi/isci/init.c | |||
@@ -64,7 +64,6 @@ | |||
64 | #include "sci_environment.h" | 64 | #include "sci_environment.h" |
65 | 65 | ||
66 | static struct scsi_transport_template *isci_transport_template; | 66 | static struct scsi_transport_template *isci_transport_template; |
67 | struct kmem_cache *isci_kmem_cache; | ||
68 | 67 | ||
69 | static DEFINE_PCI_DEVICE_TABLE(isci_id_table) = { | 68 | static DEFINE_PCI_DEVICE_TABLE(isci_id_table) = { |
70 | { PCI_VDEVICE(INTEL, 0x1D61),}, | 69 | { PCI_VDEVICE(INTEL, 0x1D61),}, |
@@ -443,7 +442,10 @@ static struct isci_host *isci_host_alloc(struct pci_dev *pdev, int id) | |||
443 | struct Scsi_Host *shost; | 442 | struct Scsi_Host *shost; |
444 | int err; | 443 | int err; |
445 | 444 | ||
446 | isci_host = devm_kzalloc(&pdev->dev, sizeof(*isci_host), GFP_KERNEL); | 445 | isci_host = devm_kzalloc(&pdev->dev, sizeof(*isci_host) + |
446 | SCI_MAX_REMOTE_DEVICES * | ||
447 | (sizeof(struct isci_remote_device) + | ||
448 | scic_remote_device_get_object_size()), GFP_KERNEL); | ||
447 | if (!isci_host) | 449 | if (!isci_host) |
448 | return NULL; | 450 | return NULL; |
449 | 451 | ||
@@ -656,31 +658,17 @@ static void __devexit isci_pci_remove(struct pci_dev *pdev) | |||
656 | 658 | ||
657 | static __init int isci_init(void) | 659 | static __init int isci_init(void) |
658 | { | 660 | { |
659 | int err = -ENOMEM; | 661 | int err; |
660 | 662 | ||
661 | pr_info("%s: Intel(R) C600 SAS Controller Driver\n", DRV_NAME); | 663 | pr_info("%s: Intel(R) C600 SAS Controller Driver\n", DRV_NAME); |
662 | 664 | ||
663 | isci_kmem_cache = kmem_cache_create(DRV_NAME, | ||
664 | sizeof(struct isci_remote_device) + | ||
665 | scic_remote_device_get_object_size(), | ||
666 | 0, 0, NULL); | ||
667 | if (!isci_kmem_cache) | ||
668 | return err; | ||
669 | |||
670 | isci_transport_template = sas_domain_attach_transport(&isci_transport_ops); | 665 | isci_transport_template = sas_domain_attach_transport(&isci_transport_ops); |
671 | if (!isci_transport_template) | 666 | if (!isci_transport_template) |
672 | goto err_kmem; | 667 | return -ENOMEM; |
673 | 668 | ||
674 | err = pci_register_driver(&isci_pci_driver); | 669 | err = pci_register_driver(&isci_pci_driver); |
675 | if (err) | 670 | if (err) |
676 | goto err_sas; | 671 | sas_release_transport(isci_transport_template); |
677 | |||
678 | return 0; | ||
679 | |||
680 | err_sas: | ||
681 | sas_release_transport(isci_transport_template); | ||
682 | err_kmem: | ||
683 | kmem_cache_destroy(isci_kmem_cache); | ||
684 | 672 | ||
685 | return err; | 673 | return err; |
686 | } | 674 | } |
@@ -689,7 +677,6 @@ static __exit void isci_exit(void) | |||
689 | { | 677 | { |
690 | pci_unregister_driver(&isci_pci_driver); | 678 | pci_unregister_driver(&isci_pci_driver); |
691 | sas_release_transport(isci_transport_template); | 679 | sas_release_transport(isci_transport_template); |
692 | kmem_cache_destroy(isci_kmem_cache); | ||
693 | } | 680 | } |
694 | 681 | ||
695 | MODULE_LICENSE("Dual BSD/GPL"); | 682 | MODULE_LICENSE("Dual BSD/GPL"); |