Commit af170928 authored by Chris Leech's avatar Chris Leech Committed by Martin K. Petersen

scsi: iscsi: respond to netlink with unicast when appropriate

Instead of always multicasting responses, send a unicast netlink message
directed at the correct pid.  This will be needed if we ever want to
support multiple userspace processes interacting with the kernel over
iSCSI netlink simultaneously.  Limitations can currently be seen if you
attempt to run multiple iscsistart commands in parallel.

We've fixed up the userspace issues in iscsistart that prevented
multiple instances from running, so now attempts to speed up booting by
bringing up multiple iscsi sessions at once in the initramfs are just
running into misrouted responses that this fixes.
Signed-off-by: default avatarChris Leech <cleech@redhat.com>
Reviewed-by: default avatarLee Duncan <lduncan@suse.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 60cc43fc
...@@ -2322,6 +2322,12 @@ iscsi_multicast_skb(struct sk_buff *skb, uint32_t group, gfp_t gfp) ...@@ -2322,6 +2322,12 @@ iscsi_multicast_skb(struct sk_buff *skb, uint32_t group, gfp_t gfp)
return nlmsg_multicast(nls, skb, 0, group, gfp); return nlmsg_multicast(nls, skb, 0, group, gfp);
} }
static int
iscsi_unicast_skb(struct sk_buff *skb, u32 portid)
{
return nlmsg_unicast(nls, skb, portid);
}
int iscsi_recv_pdu(struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr, int iscsi_recv_pdu(struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr,
char *data, uint32_t data_size) char *data, uint32_t data_size)
{ {
...@@ -2524,14 +2530,11 @@ void iscsi_ping_comp_event(uint32_t host_no, struct iscsi_transport *transport, ...@@ -2524,14 +2530,11 @@ void iscsi_ping_comp_event(uint32_t host_no, struct iscsi_transport *transport,
EXPORT_SYMBOL_GPL(iscsi_ping_comp_event); EXPORT_SYMBOL_GPL(iscsi_ping_comp_event);
static int static int
iscsi_if_send_reply(uint32_t group, int seq, int type, int done, int multi, iscsi_if_send_reply(u32 portid, int type, void *payload, int size)
void *payload, int size)
{ {
struct sk_buff *skb; struct sk_buff *skb;
struct nlmsghdr *nlh; struct nlmsghdr *nlh;
int len = nlmsg_total_size(size); int len = nlmsg_total_size(size);
int flags = multi ? NLM_F_MULTI : 0;
int t = done ? NLMSG_DONE : type;
skb = alloc_skb(len, GFP_ATOMIC); skb = alloc_skb(len, GFP_ATOMIC);
if (!skb) { if (!skb) {
...@@ -2539,10 +2542,9 @@ iscsi_if_send_reply(uint32_t group, int seq, int type, int done, int multi, ...@@ -2539,10 +2542,9 @@ iscsi_if_send_reply(uint32_t group, int seq, int type, int done, int multi,
return -ENOMEM; return -ENOMEM;
} }
nlh = __nlmsg_put(skb, 0, 0, t, (len - sizeof(*nlh)), 0); nlh = __nlmsg_put(skb, 0, 0, type, (len - sizeof(*nlh)), 0);
nlh->nlmsg_flags = flags;
memcpy(nlmsg_data(nlh), payload, size); memcpy(nlmsg_data(nlh), payload, size);
return iscsi_multicast_skb(skb, group, GFP_ATOMIC); return iscsi_unicast_skb(skb, portid);
} }
static int static int
...@@ -3470,6 +3472,7 @@ static int ...@@ -3470,6 +3472,7 @@ static int
iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group) iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
{ {
int err = 0; int err = 0;
u32 portid;
struct iscsi_uevent *ev = nlmsg_data(nlh); struct iscsi_uevent *ev = nlmsg_data(nlh);
struct iscsi_transport *transport = NULL; struct iscsi_transport *transport = NULL;
struct iscsi_internal *priv; struct iscsi_internal *priv;
...@@ -3490,10 +3493,12 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group) ...@@ -3490,10 +3493,12 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
if (!try_module_get(transport->owner)) if (!try_module_get(transport->owner))
return -EINVAL; return -EINVAL;
portid = NETLINK_CB(skb).portid;
switch (nlh->nlmsg_type) { switch (nlh->nlmsg_type) {
case ISCSI_UEVENT_CREATE_SESSION: case ISCSI_UEVENT_CREATE_SESSION:
err = iscsi_if_create_session(priv, ep, ev, err = iscsi_if_create_session(priv, ep, ev,
NETLINK_CB(skb).portid, portid,
ev->u.c_session.initial_cmdsn, ev->u.c_session.initial_cmdsn,
ev->u.c_session.cmds_max, ev->u.c_session.cmds_max,
ev->u.c_session.queue_depth); ev->u.c_session.queue_depth);
...@@ -3506,7 +3511,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group) ...@@ -3506,7 +3511,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
} }
err = iscsi_if_create_session(priv, ep, ev, err = iscsi_if_create_session(priv, ep, ev,
NETLINK_CB(skb).portid, portid,
ev->u.c_bound_session.initial_cmdsn, ev->u.c_bound_session.initial_cmdsn,
ev->u.c_bound_session.cmds_max, ev->u.c_bound_session.cmds_max,
ev->u.c_bound_session.queue_depth); ev->u.c_bound_session.queue_depth);
...@@ -3664,6 +3669,8 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group) ...@@ -3664,6 +3669,8 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
static void static void
iscsi_if_rx(struct sk_buff *skb) iscsi_if_rx(struct sk_buff *skb)
{ {
u32 portid = NETLINK_CB(skb).portid;
mutex_lock(&rx_queue_mutex); mutex_lock(&rx_queue_mutex);
while (skb->len >= NLMSG_HDRLEN) { while (skb->len >= NLMSG_HDRLEN) {
int err; int err;
...@@ -3699,8 +3706,8 @@ iscsi_if_rx(struct sk_buff *skb) ...@@ -3699,8 +3706,8 @@ iscsi_if_rx(struct sk_buff *skb)
break; break;
if (ev->type == ISCSI_UEVENT_GET_CHAP && !err) if (ev->type == ISCSI_UEVENT_GET_CHAP && !err)
break; break;
err = iscsi_if_send_reply(group, nlh->nlmsg_seq, err = iscsi_if_send_reply(portid, nlh->nlmsg_type,
nlh->nlmsg_type, 0, 0, ev, sizeof(*ev)); ev, sizeof(*ev));
} while (err < 0 && err != -ECONNREFUSED && err != -ESRCH); } while (err < 0 && err != -ECONNREFUSED && err != -ESRCH);
skb_pull(skb, rlen); skb_pull(skb, rlen);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment