This makes the iscsi_host, iscsi_session, iscsi_connection, iscsi_iface, and iscsi_endpoint transport class devices only visible in sysfs under a matching network namespace. The network namespace for all of these objects is tracked in the iscsi_cls_host structure. Signed-off-by: Lee Duncan <lduncan@xxxxxxxxx> Reviewed-by: Hannes Reinecke <hare@xxxxxxx> Signed-off-by: Chris Leech <cleech@xxxxxxxxxx> --- drivers/scsi/scsi_transport_iscsi.c | 127 ++++++++++++++++++++++++---- include/scsi/scsi_transport_iscsi.h | 1 + 2 files changed, 113 insertions(+), 15 deletions(-) diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 2f9348178450..814aef6da4a3 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -181,9 +181,34 @@ static void iscsi_endpoint_release(struct device *dev) kfree(ep); } +static struct net *iscsi_host_net(struct iscsi_cls_host *ihost) +{ + return ihost->netns; +} + +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 (!shost) + return &init_net; + ihost = shost->shost_data; + return iscsi_host_net(ihost); +} + +static const void *iscsi_endpoint_namespace(const struct device *dev) +{ + struct iscsi_endpoint *ep = iscsi_dev_to_endpoint(dev); + + return iscsi_endpoint_net(ep); +} + static struct class iscsi_endpoint_class = { .name = "iscsi_endpoint", .dev_release = iscsi_endpoint_release, + .ns_type = &net_ns_type_operations, + .namespace = iscsi_endpoint_namespace, }; static ssize_t @@ -309,10 +334,26 @@ static void iscsi_iface_release(struct device *dev) put_device(parent); } +static struct net *iscsi_iface_net(struct iscsi_iface *iface) +{ + struct Scsi_Host *shost = iscsi_iface_to_shost(iface); + struct iscsi_cls_host *ihost = shost->shost_data; + + return iscsi_host_net(ihost); +} + +static const void *iscsi_iface_namespace(const struct device *dev) +{ + struct iscsi_iface *iface = iscsi_dev_to_iface(dev); + + return iscsi_iface_net(iface); +} static struct class iscsi_iface_class = { .name = "iscsi_iface", .dev_release = iscsi_iface_release, + .ns_type = &net_ns_type_operations, + .namespace = iscsi_iface_namespace, }; #define ISCSI_IFACE_ATTR(_prefix, _name, _mode, _show, _store) \ @@ -1566,6 +1607,7 @@ static int iscsi_setup_host(struct transport_container *tc, struct device *dev, memset(ihost, 0, sizeof(*ihost)); mutex_init(&ihost->mutex); + ihost->netns = &init_net; iscsi_bsg_host_add(shost, ihost); /* ignore any bsg add error - we just can't do sgio */ @@ -1583,23 +1625,78 @@ static int iscsi_remove_host(struct transport_container *tc, return 0; } -static DECLARE_TRANSPORT_CLASS(iscsi_host_class, - "iscsi_host", - iscsi_setup_host, - iscsi_remove_host, - NULL); +#define DECLARE_TRANSPORT_CLASS_NS(cls, nm, su, rm, cfg, ns, nslookup) \ +struct transport_class cls = { \ + .class = { \ + .name = nm, \ + .ns_type = ns, \ + .namespace = nslookup, \ + }, \ + .setup = su, \ + .remove = rm, \ + .configure = cfg, \ +} -static DECLARE_TRANSPORT_CLASS(iscsi_session_class, - "iscsi_session", - NULL, - NULL, - NULL); +static const void *iscsi_host_namespace(const struct device *dev) +{ + struct Scsi_Host *shost = transport_class_to_shost(dev); + struct iscsi_cls_host *ihost = shost->shost_data; + + return iscsi_host_net(ihost); +} + +static DECLARE_TRANSPORT_CLASS_NS(iscsi_host_class, + "iscsi_host", + iscsi_setup_host, + iscsi_remove_host, + NULL, + &net_ns_type_operations, + iscsi_host_namespace); + +static struct net *iscsi_sess_net(struct iscsi_cls_session *cls_session) +{ + struct Scsi_Host *shost = iscsi_session_to_shost(cls_session); + struct iscsi_cls_host *ihost = shost->shost_data; + + return iscsi_host_net(ihost); +} + +static const void *iscsi_sess_namespace(const struct device *dev) +{ + struct iscsi_cls_session *cls_session = transport_class_to_session(dev); + + return iscsi_sess_net(cls_session); +} + +static DECLARE_TRANSPORT_CLASS_NS(iscsi_session_class, + "iscsi_session", + NULL, + NULL, + NULL, + &net_ns_type_operations, + iscsi_sess_namespace); + +static struct net *iscsi_conn_net(struct iscsi_cls_conn *cls_conn) +{ + struct iscsi_cls_session *cls_session = iscsi_conn_to_session(cls_conn); + + return iscsi_sess_net(cls_session); +} + +static const void *iscsi_conn_namespace(const struct device *dev) +{ + struct iscsi_cls_conn *cls_conn = transport_class_to_conn(dev); + + return iscsi_conn_net(cls_conn); +} -static DECLARE_TRANSPORT_CLASS(iscsi_connection_class, - "iscsi_connection", - NULL, - NULL, - NULL); +static DECLARE_TRANSPORT_CLASS_NS(iscsi_connection_class, + "iscsi_connection", + NULL, + NULL, + NULL, + &net_ns_type_operations, + iscsi_conn_namespace); struct iscsi_net { struct sock *nls; diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h index 8ade6a03f85a..d795e65a1f75 100644 --- a/include/scsi/scsi_transport_iscsi.h +++ b/include/scsi/scsi_transport_iscsi.h @@ -299,6 +299,7 @@ struct iscsi_cls_host { struct request_queue *bsg_q; uint32_t port_speed; uint32_t port_state; + struct net *netns; }; #define iscsi_job_to_shost(_job) \ -- 2.39.2