Make use of the per-net netlink sockets. Responses are sent back on the
same socket/namespace the request was received on.  Async events are
reported on the socket/namespace stored in the iscsi_cls_host associated
with the event.

Signed-off-by: Chris Leech <cle...@redhat.com>
---
 drivers/scsi/scsi_transport_iscsi.c | 92 ++++++++++++++++++++++++-------------
 1 file changed, 61 insertions(+), 31 deletions(-)

diff --git a/drivers/scsi/scsi_transport_iscsi.c 
b/drivers/scsi/scsi_transport_iscsi.c
index d29c095ccc7d..1fc5878b1a8c 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -2418,8 +2418,8 @@ iscsi_if_transport_lookup(struct iscsi_transport *tt)
 }
 
 static int
-iscsi_multicast_netns(struct net *net, struct sk_buff *skb,
-                     uint32_t group, gfp_t gfp)
+iscsi_multicast_skb(struct net *net, struct sk_buff *skb,
+                   uint32_t group, gfp_t gfp)
 {
        struct sock *nls;
        struct iscsi_net *isn;
@@ -2429,12 +2429,6 @@ iscsi_multicast_netns(struct net *net, struct sk_buff 
*skb,
        return nlmsg_multicast(nls, skb, 0, group, gfp);
 }
 
-static int
-iscsi_multicast_skb(struct sk_buff *skb, uint32_t group, gfp_t gfp)
-{
-       return iscsi_multicast_netns(&init_net, skb, group, gfp);
-}
-
 int iscsi_recv_pdu(struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr,
                   char *data, uint32_t data_size)
 {
@@ -2443,6 +2437,7 @@ int iscsi_recv_pdu(struct iscsi_cls_conn *conn, struct 
iscsi_hdr *hdr,
        struct iscsi_uevent *ev;
        char *pdu;
        struct iscsi_internal *priv;
+       struct net *net;
        int len = nlmsg_total_size(sizeof(*ev) + sizeof(struct iscsi_hdr) +
                                   data_size);
 
@@ -2469,7 +2464,8 @@ int iscsi_recv_pdu(struct iscsi_cls_conn *conn, struct 
iscsi_hdr *hdr,
        memcpy(pdu, hdr, sizeof(struct iscsi_hdr));
        memcpy(pdu + sizeof(struct iscsi_hdr), data, data_size);
 
-       return iscsi_multicast_skb(skb, ISCSI_NL_GRP_ISCSID, GFP_ATOMIC);
+       net = iscsi_conn_net(conn);
+       return iscsi_multicast_skb(net, skb, ISCSI_NL_GRP_ISCSID, GFP_ATOMIC);
 }
 EXPORT_SYMBOL_GPL(iscsi_recv_pdu);
 
@@ -2480,6 +2476,7 @@ int iscsi_offload_mesg(struct Scsi_Host *shost,
        struct nlmsghdr *nlh;
        struct sk_buff *skb;
        struct iscsi_uevent *ev;
+       struct net *net;
        int len = nlmsg_total_size(sizeof(*ev) + data_size);
 
        skb = alloc_skb(len, GFP_ATOMIC);
@@ -2504,7 +2501,8 @@ int iscsi_offload_mesg(struct Scsi_Host *shost,
 
        memcpy((char *)ev + sizeof(*ev), data, data_size);
 
-       return iscsi_multicast_skb(skb, ISCSI_NL_GRP_UIP, GFP_ATOMIC);
+       net = iscsi_host_net(shost->shost_data);
+       return iscsi_multicast_skb(net, skb, ISCSI_NL_GRP_UIP, GFP_ATOMIC);
 }
 EXPORT_SYMBOL_GPL(iscsi_offload_mesg);
 
@@ -2514,6 +2512,7 @@ void iscsi_conn_error_event(struct iscsi_cls_conn *conn, 
enum iscsi_err error)
        struct sk_buff  *skb;
        struct iscsi_uevent *ev;
        struct iscsi_internal *priv;
+       struct net *net;
        int len = nlmsg_total_size(sizeof(*ev));
 
        priv = iscsi_if_transport_lookup(conn->transport);
@@ -2535,7 +2534,8 @@ void iscsi_conn_error_event(struct iscsi_cls_conn *conn, 
enum iscsi_err error)
        ev->r.connerror.cid = conn->cid;
        ev->r.connerror.sid = iscsi_conn_get_sid(conn);
 
-       iscsi_multicast_skb(skb, ISCSI_NL_GRP_ISCSID, GFP_ATOMIC);
+       net = iscsi_conn_net(conn);
+       iscsi_multicast_skb(net, skb, ISCSI_NL_GRP_ISCSID, GFP_ATOMIC);
 
        iscsi_cls_conn_printk(KERN_INFO, conn, "detected conn error (%d)\n",
                              error);
@@ -2549,6 +2549,7 @@ void iscsi_conn_login_event(struct iscsi_cls_conn *conn,
        struct sk_buff  *skb;
        struct iscsi_uevent *ev;
        struct iscsi_internal *priv;
+       struct net *net;
        int len = nlmsg_total_size(sizeof(*ev));
 
        priv = iscsi_if_transport_lookup(conn->transport);
@@ -2569,7 +2570,9 @@ void iscsi_conn_login_event(struct iscsi_cls_conn *conn,
        ev->r.conn_login.state = state;
        ev->r.conn_login.cid = conn->cid;
        ev->r.conn_login.sid = iscsi_conn_get_sid(conn);
-       iscsi_multicast_skb(skb, ISCSI_NL_GRP_ISCSID, GFP_ATOMIC);
+
+       net = iscsi_conn_net(conn);
+       iscsi_multicast_skb(net, skb, ISCSI_NL_GRP_ISCSID, GFP_ATOMIC);
 
        iscsi_cls_conn_printk(KERN_INFO, conn, "detected conn login (%d)\n",
                              state);
@@ -2580,11 +2583,17 @@ void iscsi_post_host_event(uint32_t host_no, struct 
iscsi_transport *transport,
                           enum iscsi_host_event_code code, uint32_t data_size,
                           uint8_t *data)
 {
+       struct Scsi_Host *shost;
+       struct net *net;
        struct nlmsghdr *nlh;
        struct sk_buff *skb;
        struct iscsi_uevent *ev;
        int len = nlmsg_total_size(sizeof(*ev) + data_size);
 
+       shost = scsi_host_lookup(host_no);
+       if (!shost)
+               return;
+
        skb = alloc_skb(len, GFP_NOIO);
        if (!skb) {
                printk(KERN_ERR "gracefully ignored host event (%d):%d OOM\n",
@@ -2603,7 +2612,9 @@ void iscsi_post_host_event(uint32_t host_no, struct 
iscsi_transport *transport,
        if (data_size)
                memcpy((char *)ev + sizeof(*ev), data, data_size);
 
-       iscsi_multicast_skb(skb, ISCSI_NL_GRP_ISCSID, GFP_NOIO);
+       net = iscsi_host_net(shost->shost_data);
+       scsi_host_put(shost);
+       iscsi_multicast_skb(net, skb, ISCSI_NL_GRP_ISCSID, GFP_NOIO);
 }
 EXPORT_SYMBOL_GPL(iscsi_post_host_event);
 
@@ -2611,11 +2622,17 @@ void iscsi_ping_comp_event(uint32_t host_no, struct 
iscsi_transport *transport,
                           uint32_t status, uint32_t pid, uint32_t data_size,
                           uint8_t *data)
 {
+       struct Scsi_Host *shost;
+       struct net *net;
        struct nlmsghdr *nlh;
        struct sk_buff *skb;
        struct iscsi_uevent *ev;
        int len = nlmsg_total_size(sizeof(*ev) + data_size);
 
+       shost = scsi_host_lookup(host_no);
+       if (!shost)
+               return;
+
        skb = alloc_skb(len, GFP_NOIO);
        if (!skb) {
                printk(KERN_ERR "gracefully ignored ping comp: OOM\n");
@@ -2632,13 +2649,15 @@ void iscsi_ping_comp_event(uint32_t host_no, struct 
iscsi_transport *transport,
        ev->r.ping_comp.data_size = data_size;
        memcpy((char *)ev + sizeof(*ev), data, data_size);
 
-       iscsi_multicast_skb(skb, ISCSI_NL_GRP_ISCSID, GFP_NOIO);
+       net = iscsi_host_net(shost->shost_data);
+       scsi_host_put(shost);
+       iscsi_multicast_skb(net, skb, ISCSI_NL_GRP_ISCSID, GFP_NOIO);
 }
 EXPORT_SYMBOL_GPL(iscsi_ping_comp_event);
 
 static int
-iscsi_if_send_reply(uint32_t group, int seq, int type, int done, int multi,
-                   void *payload, int size)
+iscsi_if_send_reply(struct net *net, uint32_t group, int seq, int type,
+                   int done, int multi, void *payload, int size)
 {
        struct sk_buff  *skb;
        struct nlmsghdr *nlh;
@@ -2655,11 +2674,12 @@ iscsi_if_send_reply(uint32_t group, int seq, int type, 
int done, int multi,
        nlh = __nlmsg_put(skb, 0, 0, t, (len - sizeof(*nlh)), 0);
        nlh->nlmsg_flags = flags;
        memcpy(nlmsg_data(nlh), payload, size);
-       return iscsi_multicast_skb(skb, group, GFP_ATOMIC);
+       return iscsi_multicast_skb(net, skb, group, GFP_ATOMIC);
 }
 
 static int
-iscsi_if_get_stats(struct iscsi_transport *transport, struct nlmsghdr *nlh)
+iscsi_if_get_stats(struct net *net, struct iscsi_transport *transport,
+                  struct nlmsghdr *nlh)
 {
        struct iscsi_uevent *ev = nlmsg_data(nlh);
        struct iscsi_stats *stats;
@@ -2716,7 +2736,7 @@ iscsi_if_get_stats(struct iscsi_transport *transport, 
struct nlmsghdr *nlh)
                skb_trim(skbstat, NLMSG_ALIGN(actual_size));
                nlhstat->nlmsg_len = actual_size;
 
-               err = iscsi_multicast_skb(skbstat, ISCSI_NL_GRP_ISCSID,
+               err = iscsi_multicast_skb(net, skbstat, ISCSI_NL_GRP_ISCSID,
                                          GFP_ATOMIC);
        } while (err < 0 && err != -ECONNREFUSED);
 
@@ -2736,6 +2756,7 @@ int iscsi_session_event(struct iscsi_cls_session *session,
        struct iscsi_uevent *ev;
        struct sk_buff  *skb;
        struct nlmsghdr *nlh;
+       struct net *net;
        int rc, len = nlmsg_total_size(sizeof(*ev));
 
        priv = iscsi_if_transport_lookup(session->transport);
@@ -2780,7 +2801,8 @@ int iscsi_session_event(struct iscsi_cls_session *session,
         * this will occur if the daemon is not up, so we just warn
         * the user and when the daemon is restarted it will handle it
         */
-       rc = iscsi_multicast_skb(skb, ISCSI_NL_GRP_ISCSID, GFP_KERNEL);
+       net = iscsi_sess_net(session);
+       rc = iscsi_multicast_skb(net, skb, ISCSI_NL_GRP_ISCSID, GFP_KERNEL);
        if (rc == -ESRCH)
                iscsi_cls_session_printk(KERN_ERR, session,
                                         "Cannot notify userspace of session "
@@ -3103,7 +3125,8 @@ iscsi_send_ping(struct iscsi_transport *transport, struct 
iscsi_uevent *ev)
 }
 
 static int
-iscsi_get_chap(struct iscsi_transport *transport, struct nlmsghdr *nlh)
+iscsi_get_chap(struct net *net, struct iscsi_transport *transport,
+              struct nlmsghdr *nlh)
 {
        struct iscsi_uevent *ev = nlmsg_data(nlh);
        struct Scsi_Host *shost = NULL;
@@ -3162,7 +3185,7 @@ iscsi_get_chap(struct iscsi_transport *transport, struct 
nlmsghdr *nlh)
                skb_trim(skbchap, NLMSG_ALIGN(actual_size));
                nlhchap->nlmsg_len = actual_size;
 
-               err = iscsi_multicast_skb(skbchap, ISCSI_NL_GRP_ISCSID,
+               err = iscsi_multicast_skb(net, skbchap, ISCSI_NL_GRP_ISCSID,
                                          GFP_KERNEL);
        } while (err < 0 && err != -ECONNREFUSED);
 
@@ -3509,7 +3532,8 @@ static int iscsi_logout_flashnode_sid(struct 
iscsi_transport *transport,
 }
 
 static int
-iscsi_get_host_stats(struct iscsi_transport *transport, struct nlmsghdr *nlh)
+iscsi_get_host_stats(struct net *net, struct iscsi_transport *transport,
+                    struct nlmsghdr *nlh)
 {
        struct iscsi_uevent *ev = nlmsg_data(nlh);
        struct Scsi_Host *shost = NULL;
@@ -3569,8 +3593,8 @@ iscsi_get_host_stats(struct iscsi_transport *transport, 
struct nlmsghdr *nlh)
                skb_trim(skbhost_stats, NLMSG_ALIGN(actual_size));
                nlhhost_stats->nlmsg_len = actual_size;
 
-               err = iscsi_multicast_skb(skbhost_stats, ISCSI_NL_GRP_ISCSID,
-                                         GFP_KERNEL);
+               err = iscsi_multicast_skb(net, skbhost_stats,
+                                         ISCSI_NL_GRP_ISCSID, GFP_KERNEL);
        } while (err < 0 && err != -ECONNREFUSED);
 
 exit_host_stats:
@@ -3580,7 +3604,8 @@ iscsi_get_host_stats(struct iscsi_transport *transport, 
struct nlmsghdr *nlh)
 
 
 static int
-iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
+iscsi_if_recv_msg(struct net *net, struct sk_buff *skb,
+                 struct nlmsghdr *nlh, uint32_t *group)
 {
        int err = 0;
        struct iscsi_uevent *ev = nlmsg_data(nlh);
@@ -3703,7 +3728,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr 
*nlh, uint32_t *group)
                        err = -EINVAL;
                break;
        case ISCSI_UEVENT_GET_STATS:
-               err = iscsi_if_get_stats(transport, nlh);
+               err = iscsi_if_get_stats(net, transport, nlh);
                break;
        case ISCSI_UEVENT_TRANSPORT_EP_CONNECT:
        case ISCSI_UEVENT_TRANSPORT_EP_POLL:
@@ -3728,7 +3753,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr 
*nlh, uint32_t *group)
                err = iscsi_send_ping(transport, ev);
                break;
        case ISCSI_UEVENT_GET_CHAP:
-               err = iscsi_get_chap(transport, nlh);
+               err = iscsi_get_chap(net, transport, nlh);
                break;
        case ISCSI_UEVENT_DELETE_CHAP:
                err = iscsi_delete_chap(transport, ev);
@@ -3759,7 +3784,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr 
*nlh, uint32_t *group)
                                     nlmsg_attrlen(nlh, sizeof(*ev)));
                break;
        case ISCSI_UEVENT_GET_HOST_STATS:
-               err = iscsi_get_host_stats(transport, nlh);
+               err = iscsi_get_host_stats(net, transport, nlh);
                break;
        default:
                err = -ENOSYS;
@@ -3777,6 +3802,9 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr 
*nlh, uint32_t *group)
 static void
 iscsi_if_rx(struct sk_buff *skb)
 {
+       struct sock *sk = skb->sk;
+       struct net *net = sock_net(sk);
+
        mutex_lock(&rx_queue_mutex);
        while (skb->len >= NLMSG_HDRLEN) {
                int err;
@@ -3796,7 +3824,7 @@ iscsi_if_rx(struct sk_buff *skb)
                if (rlen > skb->len)
                        rlen = skb->len;
 
-               err = iscsi_if_recv_msg(skb, nlh, &group);
+               err = iscsi_if_recv_msg(net, skb, nlh, &group);
                if (err) {
                        ev->type = ISCSI_KEVENT_IF_ERROR;
                        ev->iferror = err;
@@ -3812,7 +3840,9 @@ iscsi_if_rx(struct sk_buff *skb)
                                break;
                        if (ev->type == ISCSI_UEVENT_GET_CHAP && !err)
                                break;
-                       err = iscsi_if_send_reply(group, nlh->nlmsg_seq,
+                       if (ev->type == ISCSI_UEVENT_GET_HOST_STATS && !err)
+                               break;
+                       err = iscsi_if_send_reply(net, group, nlh->nlmsg_seq,
                                nlh->nlmsg_type, 0, 0, ev, sizeof(*ev));
                } while (err < 0 && err != -ECONNREFUSED && err != -ESRCH);
                skb_pull(skb, rlen);
-- 
2.9.5

-- 
You received this message because you are subscribed to the Google Groups 
"open-iscsi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to open-iscsi+unsubscr...@googlegroups.com.
To post to this group, send email to open-iscsi@googlegroups.com.
Visit this group at https://groups.google.com/group/open-iscsi.
For more options, visit https://groups.google.com/d/optout.

Reply via email to