@@ -813,7 +813,7 @@ static int iscsi_iser_get_ep_param(struct iscsi_endpoint *ep,
* Return: iscsi_endpoint created by iscsi layer or ERR_PTR(error)
* if fails.
*/
-static struct iscsi_endpoint *iscsi_iser_ep_connect(struct Scsi_Host *shost,
+static struct iscsi_endpoint *iscsi_iser_ep_connect(struct net *net,
struct sockaddr *dst_addr,
int non_blocking)
{
@@ -821,7 +821,7 @@ static struct iscsi_endpoint *iscsi_iser_ep_connect(struct Scsi_Host *shost,
struct iser_conn *iser_conn;
struct iscsi_endpoint *ep;
- ep = iscsi_create_endpoint(shost, 0);
+ ep = iscsi_create_endpoint_net(net, 0);
if (!ep)
return ERR_PTR(-ENOMEM);
@@ -1027,7 +1027,7 @@ static struct iscsi_transport iscsi_iser_transport = {
/* recovery */
.session_recovery_timedout = iscsi_session_recovery_timedout,
- .ep_connect = iscsi_iser_ep_connect,
+ .ep_connect_net = iscsi_iser_ep_connect,
.ep_poll = iscsi_iser_ep_poll,
.ep_disconnect = iscsi_iser_ep_disconnect
};
@@ -190,6 +190,9 @@ static struct net *iscsi_endpoint_net(struct iscsi_endpoint *ep)
{
struct Scsi_Host *shost = iscsi_endpoint_to_shost(ep);
struct iscsi_cls_host *ihost;
+
+ if (ep->netns)
+ return ep->netns;
if (!shost)
return &init_net;
ihost = shost->shost_data;
@@ -228,7 +231,7 @@ static struct attribute_group iscsi_endpoint_group = {
};
struct iscsi_endpoint *
-iscsi_create_endpoint(struct Scsi_Host *shost, int dd_size)
+__iscsi_create_endpoint(struct Scsi_Host *shost, int dd_size, struct net *net)
{
struct iscsi_endpoint *ep;
int err, id;
@@ -256,6 +259,8 @@ iscsi_create_endpoint(struct Scsi_Host *shost, int dd_size)
ep->dev.class = &iscsi_endpoint_class;
if (shost)
ep->dev.parent = &shost->shost_gendev;
+ if (net)
+ ep->netns = net;
dev_set_name(&ep->dev, "ep-%d", id);
err = device_register(&ep->dev);
if (err)
@@ -283,8 +288,21 @@ iscsi_create_endpoint(struct Scsi_Host *shost, int dd_size)
kfree(ep);
return NULL;
}
+
+struct iscsi_endpoint *
+iscsi_create_endpoint(struct Scsi_Host *shost, int dd_size) {
+ return __iscsi_create_endpoint(shost, dd_size, NULL);
+}
+
EXPORT_SYMBOL_GPL(iscsi_create_endpoint);
+struct iscsi_endpoint *
+iscsi_create_endpoint_net(struct net *net, int dd_size) {
+ return __iscsi_create_endpoint(NULL, dd_size, net);
+}
+
+EXPORT_SYMBOL_GPL(iscsi_create_endpoint_net);
+
void iscsi_destroy_endpoint(struct iscsi_endpoint *ep)
{
sysfs_remove_group(&ep->dev.kobj, &iscsi_endpoint_group);
@@ -3279,10 +3297,10 @@ static int iscsi_if_ep_connect(struct net *net,
struct Scsi_Host *shost = NULL;
int non_blocking, err = 0;
- if (!transport->ep_connect)
- return -EINVAL;
-
if (msg_type == ISCSI_UEVENT_TRANSPORT_EP_CONNECT_THROUGH_HOST) {
+ if (!transport->ep_connect)
+ return -EINVAL;
+
shost = iscsi_host_lookup(net,
ev->u.ep_connect_through_host.host_no);
if (!shost) {
@@ -3292,11 +3310,17 @@ static int iscsi_if_ep_connect(struct net *net,
return -ENODEV;
}
non_blocking = ev->u.ep_connect_through_host.non_blocking;
- } else
+ dst_addr = (struct sockaddr *)((char*)ev + sizeof(*ev));
+ ep = transport->ep_connect(shost, dst_addr, non_blocking);
+ } else {
+ if (!transport->ep_connect_net)
+ return -EINVAL;
+
non_blocking = ev->u.ep_connect.non_blocking;
+ dst_addr = (struct sockaddr *)((char*)ev + sizeof(*ev));
+ ep = transport->ep_connect_net(net, dst_addr, non_blocking);
+ }
- dst_addr = (struct sockaddr *)((char*)ev + sizeof(*ev));
- ep = transport->ep_connect(shost, dst_addr, non_blocking);
if (IS_ERR(ep)) {
err = PTR_ERR(ep);
goto release_host;
@@ -127,6 +127,9 @@ struct iscsi_transport {
struct iscsi_endpoint *(*ep_connect) (struct Scsi_Host *shost,
struct sockaddr *dst_addr,
int non_blocking);
+ struct iscsi_endpoint *(*ep_connect_net) (struct net *net,
+ struct sockaddr *dst_addr,
+ int non_blocking);
int (*ep_poll) (struct iscsi_endpoint *ep, int timeout_ms);
void (*ep_disconnect) (struct iscsi_endpoint *ep);
int (*tgt_dscvr) (struct Scsi_Host *shost, enum iscsi_tgt_dscvr type,
@@ -321,6 +324,7 @@ struct iscsi_endpoint {
struct device dev;
int id;
struct iscsi_cls_conn *conn;
+ struct net *netns; /* used if there's no parent shost */
};
struct iscsi_iface {
@@ -477,6 +481,8 @@ extern void iscsi_unblock_session(struct iscsi_cls_session *session);
extern void iscsi_block_session(struct iscsi_cls_session *session);
extern struct iscsi_endpoint *iscsi_create_endpoint(struct Scsi_Host *shost,
int dd_size);
+extern struct iscsi_endpoint *iscsi_create_endpoint_net(struct net *net,
+ int dd_size);
extern void iscsi_destroy_endpoint(struct iscsi_endpoint *ep);
extern struct iscsi_endpoint *iscsi_lookup_endpoint(struct net *net,
u64 handle);
Split endpoint creation into host-bound and with a specified namespace, for iSER's unique use of enpoint objects + virtual host-per-session. This is much like was done with sessions already for iscsi_tcp. Signed-off-by: Chris Leech <cleech@redhat.com> --- drivers/infiniband/ulp/iser/iscsi_iser.c | 6 ++-- drivers/scsi/scsi_transport_iscsi.c | 38 +++++++++++++++++++----- include/scsi/scsi_transport_iscsi.h | 6 ++++ 3 files changed, 40 insertions(+), 10 deletions(-)