diff options
Diffstat (limited to 'drivers/scsi/scsi_transport_iscsi.c')
-rw-r--r-- | drivers/scsi/scsi_transport_iscsi.c | 104 |
1 files changed, 87 insertions, 17 deletions
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index f905ecb5704..b4218390941 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c | |||
@@ -954,6 +954,7 @@ iscsi_create_conn(struct iscsi_cls_session *session, int dd_size, uint32_t cid) | |||
954 | if (dd_size) | 954 | if (dd_size) |
955 | conn->dd_data = &conn[1]; | 955 | conn->dd_data = &conn[1]; |
956 | 956 | ||
957 | mutex_init(&conn->ep_mutex); | ||
957 | INIT_LIST_HEAD(&conn->conn_list); | 958 | INIT_LIST_HEAD(&conn->conn_list); |
958 | conn->transport = transport; | 959 | conn->transport = transport; |
959 | conn->cid = cid; | 960 | conn->cid = cid; |
@@ -975,7 +976,6 @@ iscsi_create_conn(struct iscsi_cls_session *session, int dd_size, uint32_t cid) | |||
975 | 976 | ||
976 | spin_lock_irqsave(&connlock, flags); | 977 | spin_lock_irqsave(&connlock, flags); |
977 | list_add(&conn->conn_list, &connlist); | 978 | list_add(&conn->conn_list, &connlist); |
978 | conn->active = 1; | ||
979 | spin_unlock_irqrestore(&connlock, flags); | 979 | spin_unlock_irqrestore(&connlock, flags); |
980 | 980 | ||
981 | ISCSI_DBG_TRANS_CONN(conn, "Completed conn creation\n"); | 981 | ISCSI_DBG_TRANS_CONN(conn, "Completed conn creation\n"); |
@@ -1001,7 +1001,6 @@ int iscsi_destroy_conn(struct iscsi_cls_conn *conn) | |||
1001 | unsigned long flags; | 1001 | unsigned long flags; |
1002 | 1002 | ||
1003 | spin_lock_irqsave(&connlock, flags); | 1003 | spin_lock_irqsave(&connlock, flags); |
1004 | conn->active = 0; | ||
1005 | list_del(&conn->conn_list); | 1004 | list_del(&conn->conn_list); |
1006 | spin_unlock_irqrestore(&connlock, flags); | 1005 | spin_unlock_irqrestore(&connlock, flags); |
1007 | 1006 | ||
@@ -1430,6 +1429,29 @@ release_host: | |||
1430 | return err; | 1429 | return err; |
1431 | } | 1430 | } |
1432 | 1431 | ||
1432 | static int iscsi_if_ep_disconnect(struct iscsi_transport *transport, | ||
1433 | u64 ep_handle) | ||
1434 | { | ||
1435 | struct iscsi_cls_conn *conn; | ||
1436 | struct iscsi_endpoint *ep; | ||
1437 | |||
1438 | if (!transport->ep_disconnect) | ||
1439 | return -EINVAL; | ||
1440 | |||
1441 | ep = iscsi_lookup_endpoint(ep_handle); | ||
1442 | if (!ep) | ||
1443 | return -EINVAL; | ||
1444 | conn = ep->conn; | ||
1445 | if (conn) { | ||
1446 | mutex_lock(&conn->ep_mutex); | ||
1447 | conn->ep = NULL; | ||
1448 | mutex_unlock(&conn->ep_mutex); | ||
1449 | } | ||
1450 | |||
1451 | transport->ep_disconnect(ep); | ||
1452 | return 0; | ||
1453 | } | ||
1454 | |||
1433 | static int | 1455 | static int |
1434 | iscsi_if_transport_ep(struct iscsi_transport *transport, | 1456 | iscsi_if_transport_ep(struct iscsi_transport *transport, |
1435 | struct iscsi_uevent *ev, int msg_type) | 1457 | struct iscsi_uevent *ev, int msg_type) |
@@ -1454,14 +1476,8 @@ iscsi_if_transport_ep(struct iscsi_transport *transport, | |||
1454 | ev->u.ep_poll.timeout_ms); | 1476 | ev->u.ep_poll.timeout_ms); |
1455 | break; | 1477 | break; |
1456 | case ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT: | 1478 | case ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT: |
1457 | if (!transport->ep_disconnect) | 1479 | rc = iscsi_if_ep_disconnect(transport, |
1458 | return -EINVAL; | 1480 | ev->u.ep_disconnect.ep_handle); |
1459 | |||
1460 | ep = iscsi_lookup_endpoint(ev->u.ep_disconnect.ep_handle); | ||
1461 | if (!ep) | ||
1462 | return -EINVAL; | ||
1463 | |||
1464 | transport->ep_disconnect(ep); | ||
1465 | break; | 1481 | break; |
1466 | } | 1482 | } |
1467 | return rc; | 1483 | return rc; |
@@ -1609,12 +1625,31 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group) | |||
1609 | session = iscsi_session_lookup(ev->u.b_conn.sid); | 1625 | session = iscsi_session_lookup(ev->u.b_conn.sid); |
1610 | conn = iscsi_conn_lookup(ev->u.b_conn.sid, ev->u.b_conn.cid); | 1626 | conn = iscsi_conn_lookup(ev->u.b_conn.sid, ev->u.b_conn.cid); |
1611 | 1627 | ||
1612 | if (session && conn) | 1628 | if (conn && conn->ep) |
1613 | ev->r.retcode = transport->bind_conn(session, conn, | 1629 | iscsi_if_ep_disconnect(transport, conn->ep->id); |
1614 | ev->u.b_conn.transport_eph, | 1630 | |
1615 | ev->u.b_conn.is_leading); | 1631 | if (!session || !conn) { |
1616 | else | ||
1617 | err = -EINVAL; | 1632 | err = -EINVAL; |
1633 | break; | ||
1634 | } | ||
1635 | |||
1636 | ev->r.retcode = transport->bind_conn(session, conn, | ||
1637 | ev->u.b_conn.transport_eph, | ||
1638 | ev->u.b_conn.is_leading); | ||
1639 | if (ev->r.retcode || !transport->ep_connect) | ||
1640 | break; | ||
1641 | |||
1642 | ep = iscsi_lookup_endpoint(ev->u.b_conn.transport_eph); | ||
1643 | if (ep) { | ||
1644 | ep->conn = conn; | ||
1645 | |||
1646 | mutex_lock(&conn->ep_mutex); | ||
1647 | conn->ep = ep; | ||
1648 | mutex_unlock(&conn->ep_mutex); | ||
1649 | } else | ||
1650 | iscsi_cls_conn_printk(KERN_ERR, conn, | ||
1651 | "Could not set ep conn " | ||
1652 | "binding\n"); | ||
1618 | break; | 1653 | break; |
1619 | case ISCSI_UEVENT_SET_PARAM: | 1654 | case ISCSI_UEVENT_SET_PARAM: |
1620 | err = iscsi_set_param(transport, ev); | 1655 | err = iscsi_set_param(transport, ev); |
@@ -1747,13 +1782,48 @@ iscsi_conn_attr(data_digest, ISCSI_PARAM_DATADGST_EN); | |||
1747 | iscsi_conn_attr(ifmarker, ISCSI_PARAM_IFMARKER_EN); | 1782 | iscsi_conn_attr(ifmarker, ISCSI_PARAM_IFMARKER_EN); |
1748 | iscsi_conn_attr(ofmarker, ISCSI_PARAM_OFMARKER_EN); | 1783 | iscsi_conn_attr(ofmarker, ISCSI_PARAM_OFMARKER_EN); |
1749 | iscsi_conn_attr(persistent_port, ISCSI_PARAM_PERSISTENT_PORT); | 1784 | iscsi_conn_attr(persistent_port, ISCSI_PARAM_PERSISTENT_PORT); |
1750 | iscsi_conn_attr(port, ISCSI_PARAM_CONN_PORT); | ||
1751 | iscsi_conn_attr(exp_statsn, ISCSI_PARAM_EXP_STATSN); | 1785 | iscsi_conn_attr(exp_statsn, ISCSI_PARAM_EXP_STATSN); |
1752 | iscsi_conn_attr(persistent_address, ISCSI_PARAM_PERSISTENT_ADDRESS); | 1786 | iscsi_conn_attr(persistent_address, ISCSI_PARAM_PERSISTENT_ADDRESS); |
1753 | iscsi_conn_attr(address, ISCSI_PARAM_CONN_ADDRESS); | ||
1754 | iscsi_conn_attr(ping_tmo, ISCSI_PARAM_PING_TMO); | 1787 | iscsi_conn_attr(ping_tmo, ISCSI_PARAM_PING_TMO); |
1755 | iscsi_conn_attr(recv_tmo, ISCSI_PARAM_RECV_TMO); | 1788 | iscsi_conn_attr(recv_tmo, ISCSI_PARAM_RECV_TMO); |
1756 | 1789 | ||
1790 | #define iscsi_conn_ep_attr_show(param) \ | ||
1791 | static ssize_t show_conn_ep_param_##param(struct device *dev, \ | ||
1792 | struct device_attribute *attr,\ | ||
1793 | char *buf) \ | ||
1794 | { \ | ||
1795 | struct iscsi_cls_conn *conn = iscsi_dev_to_conn(dev->parent); \ | ||
1796 | struct iscsi_transport *t = conn->transport; \ | ||
1797 | struct iscsi_endpoint *ep; \ | ||
1798 | ssize_t rc; \ | ||
1799 | \ | ||
1800 | /* \ | ||
1801 | * Need to make sure ep_disconnect does not free the LLD's \ | ||
1802 | * interconnect resources while we are trying to read them. \ | ||
1803 | */ \ | ||
1804 | mutex_lock(&conn->ep_mutex); \ | ||
1805 | ep = conn->ep; \ | ||
1806 | if (!ep && t->ep_connect) { \ | ||
1807 | mutex_unlock(&conn->ep_mutex); \ | ||
1808 | return -ENOTCONN; \ | ||
1809 | } \ | ||
1810 | \ | ||
1811 | if (ep) \ | ||
1812 | rc = t->get_ep_param(ep, param, buf); \ | ||
1813 | else \ | ||
1814 | rc = t->get_conn_param(conn, param, buf); \ | ||
1815 | mutex_unlock(&conn->ep_mutex); \ | ||
1816 | return rc; \ | ||
1817 | } | ||
1818 | |||
1819 | #define iscsi_conn_ep_attr(field, param) \ | ||
1820 | iscsi_conn_ep_attr_show(param) \ | ||
1821 | static ISCSI_CLASS_ATTR(conn, field, S_IRUGO, \ | ||
1822 | show_conn_ep_param_##param, NULL); | ||
1823 | |||
1824 | iscsi_conn_ep_attr(address, ISCSI_PARAM_CONN_ADDRESS); | ||
1825 | iscsi_conn_ep_attr(port, ISCSI_PARAM_CONN_PORT); | ||
1826 | |||
1757 | /* | 1827 | /* |
1758 | * iSCSI session attrs | 1828 | * iSCSI session attrs |
1759 | */ | 1829 | */ |