aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorMike Christie <michaelc@cs.wisc.edu>2011-02-16 16:04:33 -0500
committerJames Bottomley <James.Bottomley@suse.de>2011-02-24 12:41:05 -0500
commit22a39fbbfecfea703b686a4626a631d706ccb3ee (patch)
treed3d13184d9412310a6db0f9ae4423fd881a302cf /drivers/scsi
parentfdafd4dfc7bbdd40a4692192b77299b28c8a948f (diff)
[SCSI] iscsi: fix iscsi_endpoint leak
When iscsid restarts it does not know the connection's endpoint, so it is getting leaked. This fixes the problem by having the iscsi class force a disconnect before a new connection is bound. Signed-off-by: Mike Christie <michaelc@cs.wisc.edu> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/scsi_transport_iscsi.c63
1 files changed, 50 insertions, 13 deletions
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index f905ecb5704d..4e09b68a0789 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;
@@ -1430,6 +1431,29 @@ release_host:
1430 return err; 1431 return err;
1431} 1432}
1432 1433
1434static int iscsi_if_ep_disconnect(struct iscsi_transport *transport,
1435 u64 ep_handle)
1436{
1437 struct iscsi_cls_conn *conn;
1438 struct iscsi_endpoint *ep;
1439
1440 if (!transport->ep_disconnect)
1441 return -EINVAL;
1442
1443 ep = iscsi_lookup_endpoint(ep_handle);
1444 if (!ep)
1445 return -EINVAL;
1446 conn = ep->conn;
1447 if (conn) {
1448 mutex_lock(&conn->ep_mutex);
1449 conn->ep = NULL;
1450 mutex_unlock(&conn->ep_mutex);
1451 }
1452
1453 transport->ep_disconnect(ep);
1454 return 0;
1455}
1456
1433static int 1457static int
1434iscsi_if_transport_ep(struct iscsi_transport *transport, 1458iscsi_if_transport_ep(struct iscsi_transport *transport,
1435 struct iscsi_uevent *ev, int msg_type) 1459 struct iscsi_uevent *ev, int msg_type)
@@ -1454,14 +1478,8 @@ iscsi_if_transport_ep(struct iscsi_transport *transport,
1454 ev->u.ep_poll.timeout_ms); 1478 ev->u.ep_poll.timeout_ms);
1455 break; 1479 break;
1456 case ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT: 1480 case ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT:
1457 if (!transport->ep_disconnect) 1481 rc = iscsi_if_ep_disconnect(transport,
1458 return -EINVAL; 1482 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; 1483 break;
1466 } 1484 }
1467 return rc; 1485 return rc;
@@ -1609,12 +1627,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); 1627 session = iscsi_session_lookup(ev->u.b_conn.sid);
1610 conn = iscsi_conn_lookup(ev->u.b_conn.sid, ev->u.b_conn.cid); 1628 conn = iscsi_conn_lookup(ev->u.b_conn.sid, ev->u.b_conn.cid);
1611 1629
1612 if (session && conn) 1630 if (conn && conn->ep)
1613 ev->r.retcode = transport->bind_conn(session, conn, 1631 iscsi_if_ep_disconnect(transport, conn->ep->id);
1614 ev->u.b_conn.transport_eph, 1632
1615 ev->u.b_conn.is_leading); 1633 if (!session || !conn) {
1616 else
1617 err = -EINVAL; 1634 err = -EINVAL;
1635 break;
1636 }
1637
1638 ev->r.retcode = transport->bind_conn(session, conn,
1639 ev->u.b_conn.transport_eph,
1640 ev->u.b_conn.is_leading);
1641 if (ev->r.retcode || !transport->ep_connect)
1642 break;
1643
1644 ep = iscsi_lookup_endpoint(ev->u.b_conn.transport_eph);
1645 if (ep) {
1646 ep->conn = conn;
1647
1648 mutex_lock(&conn->ep_mutex);
1649 conn->ep = ep;
1650 mutex_unlock(&conn->ep_mutex);
1651 } else
1652 iscsi_cls_conn_printk(KERN_ERR, conn,
1653 "Could not set ep conn "
1654 "binding\n");
1618 break; 1655 break;
1619 case ISCSI_UEVENT_SET_PARAM: 1656 case ISCSI_UEVENT_SET_PARAM:
1620 err = iscsi_set_param(transport, ev); 1657 err = iscsi_set_param(transport, ev);