diff options
| author | Mike Christie <michaelc@cs.wisc.edu> | 2008-05-21 16:54:00 -0400 |
|---|---|---|
| committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-07-12 09:22:16 -0400 |
| commit | a4804cd6eb19318ae8d08ea967cfeaaf5c5b68a6 (patch) | |
| tree | a69acbfdf4e3646ebb7583f0627b7b7952d13b10 /drivers | |
| parent | 756135215ec743be6fdce2bdebe8cdb9f8a231f6 (diff) | |
[SCSI] iscsi: add iscsi host helpers
This finishes the host/session unbinding, by adding some helpers
to add and remove hosts and the session they manage.
Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/infiniband/ulp/iser/iscsi_iser.c | 17 | ||||
| -rw-r--r-- | drivers/scsi/iscsi_tcp.c | 18 | ||||
| -rw-r--r-- | drivers/scsi/libiscsi.c | 60 | ||||
| -rw-r--r-- | drivers/scsi/scsi_transport_iscsi.c | 20 |
4 files changed, 86 insertions, 29 deletions
diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c index 5a750042e2b2..62e35e503e49 100644 --- a/drivers/infiniband/ulp/iser/iscsi_iser.c +++ b/drivers/infiniband/ulp/iser/iscsi_iser.c | |||
| @@ -371,10 +371,8 @@ static void iscsi_iser_session_destroy(struct iscsi_cls_session *cls_session) | |||
| 371 | { | 371 | { |
| 372 | struct Scsi_Host *shost = iscsi_session_to_shost(cls_session); | 372 | struct Scsi_Host *shost = iscsi_session_to_shost(cls_session); |
| 373 | 373 | ||
| 374 | iscsi_session_teardown(cls_session); | 374 | iscsi_host_remove(shost); |
| 375 | scsi_remove_host(shost); | 375 | iscsi_host_free(shost); |
| 376 | iscsi_host_teardown(shost); | ||
| 377 | scsi_host_put(shost); | ||
| 378 | } | 376 | } |
| 379 | 377 | ||
| 380 | static struct iscsi_cls_session * | 378 | static struct iscsi_cls_session * |
| @@ -396,7 +394,7 @@ iscsi_iser_session_create(struct Scsi_Host *shost, | |||
| 396 | return NULL; | 394 | return NULL; |
| 397 | } | 395 | } |
| 398 | 396 | ||
| 399 | shost = scsi_host_alloc(&iscsi_iser_sht, 0); | 397 | shost = iscsi_host_alloc(&iscsi_iser_sht, 0, ISCSI_MAX_CMD_PER_LUN); |
| 400 | if (!shost) | 398 | if (!shost) |
| 401 | return NULL; | 399 | return NULL; |
| 402 | shost->transportt = iscsi_iser_scsi_transport; | 400 | shost->transportt = iscsi_iser_scsi_transport; |
| @@ -405,9 +403,7 @@ iscsi_iser_session_create(struct Scsi_Host *shost, | |||
| 405 | shost->max_channel = 0; | 403 | shost->max_channel = 0; |
| 406 | shost->max_cmd_len = 16; | 404 | shost->max_cmd_len = 16; |
| 407 | 405 | ||
| 408 | iscsi_host_setup(shost, qdepth); | 406 | if (iscsi_host_add(shost, NULL)) |
| 409 | |||
| 410 | if (scsi_add_host(shost, NULL)) | ||
| 411 | goto free_host; | 407 | goto free_host; |
| 412 | *hostno = shost->host_no; | 408 | *hostno = shost->host_no; |
| 413 | 409 | ||
| @@ -443,10 +439,9 @@ iscsi_iser_session_create(struct Scsi_Host *shost, | |||
| 443 | return cls_session; | 439 | return cls_session; |
| 444 | 440 | ||
| 445 | remove_host: | 441 | remove_host: |
| 446 | scsi_remove_host(shost); | 442 | iscsi_host_remove(shost); |
| 447 | free_host: | 443 | free_host: |
| 448 | iscsi_host_teardown(shost); | 444 | iscsi_host_free(shost); |
| 449 | scsi_host_put(shost); | ||
| 450 | return NULL; | 445 | return NULL; |
| 451 | } | 446 | } |
| 452 | 447 | ||
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 8cdcaf33fb4e..e19d92f2d753 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c | |||
| @@ -1866,7 +1866,7 @@ iscsi_tcp_session_create(struct Scsi_Host *shost, uint16_t cmds_max, | |||
| 1866 | return NULL; | 1866 | return NULL; |
| 1867 | } | 1867 | } |
| 1868 | 1868 | ||
| 1869 | shost = scsi_host_alloc(&iscsi_sht, sizeof(struct iscsi_host)); | 1869 | shost = iscsi_host_alloc(&iscsi_sht, 0, qdepth); |
| 1870 | if (!shost) | 1870 | if (!shost) |
| 1871 | return NULL; | 1871 | return NULL; |
| 1872 | shost->transportt = iscsi_tcp_scsi_transport; | 1872 | shost->transportt = iscsi_tcp_scsi_transport; |
| @@ -1874,10 +1874,9 @@ iscsi_tcp_session_create(struct Scsi_Host *shost, uint16_t cmds_max, | |||
| 1874 | shost->max_id = 0; | 1874 | shost->max_id = 0; |
| 1875 | shost->max_channel = 0; | 1875 | shost->max_channel = 0; |
| 1876 | shost->max_cmd_len = 16; | 1876 | shost->max_cmd_len = 16; |
| 1877 | shost->can_queue = cmds_max; | ||
| 1877 | 1878 | ||
| 1878 | iscsi_host_setup(shost, qdepth); | 1879 | if (iscsi_host_add(shost, NULL)) |
| 1879 | |||
| 1880 | if (scsi_add_host(shost, NULL)) | ||
| 1881 | goto free_host; | 1880 | goto free_host; |
| 1882 | *hostno = shost->host_no; | 1881 | *hostno = shost->host_no; |
| 1883 | 1882 | ||
| @@ -1912,10 +1911,9 @@ iscsi_tcp_session_create(struct Scsi_Host *shost, uint16_t cmds_max, | |||
| 1912 | remove_session: | 1911 | remove_session: |
| 1913 | iscsi_session_teardown(cls_session); | 1912 | iscsi_session_teardown(cls_session); |
| 1914 | remove_host: | 1913 | remove_host: |
| 1915 | scsi_remove_host(shost); | 1914 | iscsi_host_remove(shost); |
| 1916 | free_host: | 1915 | free_host: |
| 1917 | iscsi_host_teardown(shost); | 1916 | iscsi_host_free(shost); |
| 1918 | scsi_host_put(shost); | ||
| 1919 | return NULL; | 1917 | return NULL; |
| 1920 | } | 1918 | } |
| 1921 | 1919 | ||
| @@ -1924,11 +1922,9 @@ static void iscsi_tcp_session_destroy(struct iscsi_cls_session *cls_session) | |||
| 1924 | struct Scsi_Host *shost = iscsi_session_to_shost(cls_session); | 1922 | struct Scsi_Host *shost = iscsi_session_to_shost(cls_session); |
| 1925 | 1923 | ||
| 1926 | iscsi_r2tpool_free(cls_session->dd_data); | 1924 | iscsi_r2tpool_free(cls_session->dd_data); |
| 1927 | iscsi_session_teardown(cls_session); | ||
| 1928 | 1925 | ||
| 1929 | scsi_remove_host(shost); | 1926 | iscsi_host_remove(shost); |
| 1930 | iscsi_host_teardown(shost); | 1927 | iscsi_host_free(shost); |
| 1931 | scsi_host_put(shost); | ||
| 1932 | } | 1928 | } |
| 1933 | 1929 | ||
| 1934 | static int iscsi_tcp_slave_configure(struct scsi_device *sdev) | 1930 | static int iscsi_tcp_slave_configure(struct scsi_device *sdev) |
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 64b1dd827366..73c37c04ca66 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c | |||
| @@ -1764,8 +1764,39 @@ void iscsi_pool_free(struct iscsi_pool *q) | |||
| 1764 | } | 1764 | } |
| 1765 | EXPORT_SYMBOL_GPL(iscsi_pool_free); | 1765 | EXPORT_SYMBOL_GPL(iscsi_pool_free); |
| 1766 | 1766 | ||
| 1767 | void iscsi_host_setup(struct Scsi_Host *shost, uint16_t qdepth) | 1767 | /** |
| 1768 | * iscsi_host_add - add host to system | ||
| 1769 | * @shost: scsi host | ||
| 1770 | * @pdev: parent device | ||
| 1771 | * | ||
| 1772 | * This should be called by partial offload and software iscsi drivers | ||
| 1773 | * to add a host to the system. | ||
| 1774 | */ | ||
| 1775 | int iscsi_host_add(struct Scsi_Host *shost, struct device *pdev) | ||
| 1776 | { | ||
| 1777 | return scsi_add_host(shost, pdev); | ||
| 1778 | } | ||
| 1779 | EXPORT_SYMBOL_GPL(iscsi_host_add); | ||
| 1780 | |||
| 1781 | /** | ||
| 1782 | * iscsi_host_alloc - allocate a host and driver data | ||
| 1783 | * @sht: scsi host template | ||
| 1784 | * @dd_data_size: driver host data size | ||
| 1785 | * @qdepth: default device queue depth | ||
| 1786 | * | ||
| 1787 | * This should be called by partial offload and software iscsi drivers. | ||
| 1788 | * To access the driver specific memory use the iscsi_host_priv() macro. | ||
| 1789 | */ | ||
| 1790 | struct Scsi_Host *iscsi_host_alloc(struct scsi_host_template *sht, | ||
| 1791 | int dd_data_size, uint16_t qdepth) | ||
| 1768 | { | 1792 | { |
| 1793 | struct Scsi_Host *shost; | ||
| 1794 | |||
| 1795 | shost = scsi_host_alloc(sht, sizeof(struct iscsi_host) + dd_data_size); | ||
| 1796 | if (!shost) | ||
| 1797 | return NULL; | ||
| 1798 | shost->transportt->eh_timed_out = iscsi_eh_cmd_timed_out; | ||
| 1799 | |||
| 1769 | if (qdepth > ISCSI_MAX_CMD_PER_LUN || qdepth < 1) { | 1800 | if (qdepth > ISCSI_MAX_CMD_PER_LUN || qdepth < 1) { |
| 1770 | if (qdepth != 0) | 1801 | if (qdepth != 0) |
| 1771 | printk(KERN_ERR "iscsi: invalid queue depth of %d. " | 1802 | printk(KERN_ERR "iscsi: invalid queue depth of %d. " |
| @@ -1773,22 +1804,37 @@ void iscsi_host_setup(struct Scsi_Host *shost, uint16_t qdepth) | |||
| 1773 | qdepth, ISCSI_MAX_CMD_PER_LUN); | 1804 | qdepth, ISCSI_MAX_CMD_PER_LUN); |
| 1774 | qdepth = ISCSI_DEF_CMD_PER_LUN; | 1805 | qdepth = ISCSI_DEF_CMD_PER_LUN; |
| 1775 | } | 1806 | } |
| 1776 | |||
| 1777 | shost->transportt->create_work_queue = 1; | ||
| 1778 | shost->transportt->eh_timed_out = iscsi_eh_cmd_timed_out; | ||
| 1779 | shost->cmd_per_lun = qdepth; | 1807 | shost->cmd_per_lun = qdepth; |
| 1808 | return shost; | ||
| 1809 | } | ||
| 1810 | EXPORT_SYMBOL_GPL(iscsi_host_alloc); | ||
| 1811 | |||
| 1812 | /** | ||
| 1813 | * iscsi_host_remove - remove host and sessions | ||
| 1814 | * @shost: scsi host | ||
| 1815 | * | ||
| 1816 | * This will also remove any sessions attached to the host, but if userspace | ||
| 1817 | * is managing the session at the same time this will break. TODO: add | ||
| 1818 | * refcounting to the netlink iscsi interface so a rmmod or host hot unplug | ||
| 1819 | * does not remove the memory from under us. | ||
| 1820 | */ | ||
| 1821 | void iscsi_host_remove(struct Scsi_Host *shost) | ||
| 1822 | { | ||
| 1823 | iscsi_host_for_each_session(shost, iscsi_session_teardown); | ||
| 1824 | scsi_remove_host(shost); | ||
| 1780 | } | 1825 | } |
| 1781 | EXPORT_SYMBOL_GPL(iscsi_host_setup); | 1826 | EXPORT_SYMBOL_GPL(iscsi_host_remove); |
| 1782 | 1827 | ||
| 1783 | void iscsi_host_teardown(struct Scsi_Host *shost) | 1828 | void iscsi_host_free(struct Scsi_Host *shost) |
| 1784 | { | 1829 | { |
| 1785 | struct iscsi_host *ihost = shost_priv(shost); | 1830 | struct iscsi_host *ihost = shost_priv(shost); |
| 1786 | 1831 | ||
| 1787 | kfree(ihost->netdev); | 1832 | kfree(ihost->netdev); |
| 1788 | kfree(ihost->hwaddress); | 1833 | kfree(ihost->hwaddress); |
| 1789 | kfree(ihost->initiatorname); | 1834 | kfree(ihost->initiatorname); |
| 1835 | scsi_host_put(shost); | ||
| 1790 | } | 1836 | } |
| 1791 | EXPORT_SYMBOL_GPL(iscsi_host_teardown); | 1837 | EXPORT_SYMBOL_GPL(iscsi_host_free); |
| 1792 | 1838 | ||
| 1793 | /** | 1839 | /** |
| 1794 | * iscsi_session_setup - create iscsi cls session and host and session | 1840 | * iscsi_session_setup - create iscsi cls session and host and session |
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 9c00a157b485..6fdaa2ee6632 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c | |||
| @@ -279,6 +279,24 @@ static int iscsi_is_session_dev(const struct device *dev) | |||
| 279 | return dev->release == iscsi_session_release; | 279 | return dev->release == iscsi_session_release; |
| 280 | } | 280 | } |
| 281 | 281 | ||
| 282 | static int iscsi_iter_session_fn(struct device *dev, void *data) | ||
| 283 | { | ||
| 284 | void (* fn) (struct iscsi_cls_session *) = data; | ||
| 285 | |||
| 286 | if (!iscsi_is_session_dev(dev)) | ||
| 287 | return 0; | ||
| 288 | fn(iscsi_dev_to_session(dev)); | ||
| 289 | return 0; | ||
| 290 | } | ||
| 291 | |||
| 292 | void iscsi_host_for_each_session(struct Scsi_Host *shost, | ||
| 293 | void (*fn)(struct iscsi_cls_session *)) | ||
| 294 | { | ||
| 295 | device_for_each_child(&shost->shost_gendev, fn, | ||
| 296 | iscsi_iter_session_fn); | ||
| 297 | } | ||
| 298 | EXPORT_SYMBOL_GPL(iscsi_host_for_each_session); | ||
| 299 | |||
| 282 | /** | 300 | /** |
| 283 | * iscsi_scan_finished - helper to report when running scans are done | 301 | * iscsi_scan_finished - helper to report when running scans are done |
| 284 | * @shost: scsi host | 302 | * @shost: scsi host |
| @@ -1599,6 +1617,8 @@ iscsi_register_transport(struct iscsi_transport *tt) | |||
| 1599 | priv->daemon_pid = -1; | 1617 | priv->daemon_pid = -1; |
| 1600 | priv->iscsi_transport = tt; | 1618 | priv->iscsi_transport = tt; |
| 1601 | priv->t.user_scan = iscsi_user_scan; | 1619 | priv->t.user_scan = iscsi_user_scan; |
| 1620 | if (!(tt->caps & CAP_DATA_PATH_OFFLOAD)) | ||
| 1621 | priv->t.create_work_queue = 1; | ||
| 1602 | 1622 | ||
| 1603 | priv->dev.class = &iscsi_transport_class; | 1623 | priv->dev.class = &iscsi_transport_class; |
| 1604 | snprintf(priv->dev.bus_id, BUS_ID_SIZE, "%s", tt->name); | 1624 | snprintf(priv->dev.bus_id, BUS_ID_SIZE, "%s", tt->name); |
