Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 10eb0f01 authored by Mike Christie's avatar Mike Christie Committed by James Bottomley
Browse files

[SCSI] iscsi: pass ep connect shost



When we create the tcp/ip connection by calling ep_connect, we currently
just go by the routing table info.

I think there are two problems with this.

1. Some drivers do not have access to a routing table. Some drivers like
qla4xxx do not even know about other ports.

2. If you have two initiator ports on the same subnet, the user may have
set things up so that session1 was supposed to be run through port1. and
session2 was supposed to be run through port2. It looks like we could
end with both sessions going through one of the ports.

Fixes for cxgb3i from Karen Xie.

Signed-off-by: default avatarMike Christie <michaelc@cs.wisc.edu>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@HansenPartnership.com>
parent 5a253795
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -517,7 +517,8 @@ iscsi_iser_conn_get_stats(struct iscsi_cls_conn *cls_conn, struct iscsi_stats *s
}

static struct iscsi_endpoint *
iscsi_iser_ep_connect(struct sockaddr *dst_addr, int non_blocking)
iscsi_iser_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr,
		      int non_blocking)
{
	int err;
	struct iser_conn *ib_conn;
+0 −1
Original line number Diff line number Diff line
@@ -144,7 +144,6 @@ struct cxgb3i_adapter *cxgb3i_adapter_find_by_tdev(struct t3cdev *);
void cxgb3i_adapter_open(struct t3cdev *);
void cxgb3i_adapter_close(struct t3cdev *);

struct cxgb3i_hba *cxgb3i_hba_find_by_netdev(struct net_device *);
struct cxgb3i_hba *cxgb3i_hba_host_add(struct cxgb3i_adapter *,
				       struct net_device *);
void cxgb3i_hba_host_remove(struct cxgb3i_hba *);
+21 −4
Original line number Diff line number Diff line
@@ -178,7 +178,7 @@ void cxgb3i_adapter_close(struct t3cdev *t3dev)
 * cxgb3i_hba_find_by_netdev - find the cxgb3i_hba structure via net_device
 * @t3dev: t3cdev adapter
 */
struct cxgb3i_hba *cxgb3i_hba_find_by_netdev(struct net_device *ndev)
static struct cxgb3i_hba *cxgb3i_hba_find_by_netdev(struct net_device *ndev)
{
	struct cxgb3i_adapter *snic;
	int i;
@@ -261,20 +261,27 @@ void cxgb3i_hba_host_remove(struct cxgb3i_hba *hba)

/**
 * cxgb3i_ep_connect - establish TCP connection to target portal
 * @shost:		scsi host to use
 * @dst_addr:		target IP address
 * @non_blocking:	blocking or non-blocking call
 *
 * Initiates a TCP/IP connection to the dst_addr
 */
static struct iscsi_endpoint *cxgb3i_ep_connect(struct sockaddr *dst_addr,
static struct iscsi_endpoint *cxgb3i_ep_connect(struct Scsi_Host *shost,
						struct sockaddr *dst_addr,
						int non_blocking)
{
	struct iscsi_endpoint *ep;
	struct cxgb3i_endpoint *cep;
	struct cxgb3i_hba *hba;
	struct cxgb3i_hba *hba = NULL;
	struct s3_conn *c3cn = NULL;
	int err = 0;

	if (shost)
		hba = iscsi_host_priv(shost);

	cxgb3i_api_debug("shost 0x%p, hba 0x%p.\n", shost, hba);

	c3cn = cxgb3i_c3cn_create();
	if (!c3cn) {
		cxgb3i_log_info("ep connect OOM.\n");
@@ -282,17 +289,27 @@ static struct iscsi_endpoint *cxgb3i_ep_connect(struct sockaddr *dst_addr,
		goto release_conn;
	}

	err = cxgb3i_c3cn_connect(c3cn, (struct sockaddr_in *)dst_addr);
	err = cxgb3i_c3cn_connect(hba ? hba->ndev : NULL, c3cn,
				 (struct sockaddr_in *)dst_addr);
	if (err < 0) {
		cxgb3i_log_info("ep connect failed.\n");
		goto release_conn;
	}

	hba = cxgb3i_hba_find_by_netdev(c3cn->dst_cache->dev);
	if (!hba) {
		err = -ENOSPC;
		cxgb3i_log_info("NOT going through cxgbi device.\n");
		goto release_conn;
	}

	if (shost && hba != iscsi_host_priv(shost)) {
		err = -ENOSPC;
		cxgb3i_log_info("Could not connect through request host%u\n",
				shost->host_no);
		goto release_conn;
	}

	if (c3cn_is_closing(c3cn)) {
		err = -ENOSPC;
		cxgb3i_log_info("ep connect unable to connect.\n");
+14 −9
Original line number Diff line number Diff line
@@ -1479,12 +1479,13 @@ static struct net_device *cxgb3_egress_dev(struct net_device *root_dev,
	return NULL;
}

static struct rtable *find_route(__be32 saddr, __be32 daddr,
static struct rtable *find_route(struct net_device *dev,
				 __be32 saddr, __be32 daddr,
				 __be16 sport, __be16 dport)
{
	struct rtable *rt;
	struct flowi fl = {
		.oif = 0,
		.oif = dev ? dev->ifindex : 0,
		.nl_u = {
			 .ip4_u = {
				   .daddr = daddr,
@@ -1573,36 +1574,40 @@ static int initiate_act_open(struct s3_conn *c3cn, struct net_device *dev)
 *
 * return 0 if active open request is sent, < 0 otherwise.
 */
int cxgb3i_c3cn_connect(struct s3_conn *c3cn, struct sockaddr_in *usin)
int cxgb3i_c3cn_connect(struct net_device *dev, struct s3_conn *c3cn,
			struct sockaddr_in *usin)
{
	struct rtable *rt;
	struct net_device *dev;
	struct cxgb3i_sdev_data *cdata;
	struct t3cdev *cdev;
	__be32 sipv4;
	int err;

	c3cn_conn_debug("c3cn 0x%p, dev 0x%p.\n", c3cn, dev);

	if (usin->sin_family != AF_INET)
		return -EAFNOSUPPORT;

	c3cn->daddr.sin_port = usin->sin_port;
	c3cn->daddr.sin_addr.s_addr = usin->sin_addr.s_addr;

	rt = find_route(c3cn->saddr.sin_addr.s_addr,
	rt = find_route(dev, c3cn->saddr.sin_addr.s_addr,
			c3cn->daddr.sin_addr.s_addr,
			c3cn->saddr.sin_port,
			c3cn->daddr.sin_port);
	if (rt == NULL) {
		c3cn_conn_debug("NO route to 0x%x, port %u.\n",
		c3cn_conn_debug("NO route to 0x%x, port %u, dev %s.\n",
				c3cn->daddr.sin_addr.s_addr,
				ntohs(c3cn->daddr.sin_port));
				ntohs(c3cn->daddr.sin_port),
				dev ? dev->name : "any");
		return -ENETUNREACH;
	}

	if (rt->rt_flags & (RTCF_MULTICAST | RTCF_BROADCAST)) {
		c3cn_conn_debug("multi-cast route to 0x%x, port %u.\n",
		c3cn_conn_debug("multi-cast route to 0x%x, port %u, dev %s.\n",
				c3cn->daddr.sin_addr.s_addr,
				ntohs(c3cn->daddr.sin_port));
				ntohs(c3cn->daddr.sin_port),
				dev ? dev->name : "any");
		ip_rt_put(rt);
		return -ENETUNREACH;
	}
+2 −1
Original line number Diff line number Diff line
@@ -169,7 +169,8 @@ void cxgb3i_sdev_add(struct t3cdev *, struct cxgb3_client *);
void cxgb3i_sdev_remove(struct t3cdev *);

struct s3_conn *cxgb3i_c3cn_create(void);
int cxgb3i_c3cn_connect(struct s3_conn *, struct sockaddr_in *);
int cxgb3i_c3cn_connect(struct net_device *, struct s3_conn *,
			struct sockaddr_in *);
void cxgb3i_c3cn_rx_credits(struct s3_conn *, int);
int cxgb3i_c3cn_send_pdus(struct s3_conn *, struct sk_buff *);
void cxgb3i_c3cn_release(struct s3_conn *);
Loading