diff options
Diffstat (limited to 'drivers/scsi/scsi_transport_iscsi.c')
-rw-r--r-- | drivers/scsi/scsi_transport_iscsi.c | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 38f0bf8ea91a..a20f1813cb51 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -1507,6 +1507,35 @@ void iscsi_post_host_event(uint32_t host_no, struct iscsi_transport *transport, } EXPORT_SYMBOL_GPL(iscsi_post_host_event); +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 nlmsghdr *nlh; + struct sk_buff *skb; + struct iscsi_uevent *ev; + int len = NLMSG_SPACE(sizeof(*ev) + data_size); + + skb = alloc_skb(len, GFP_KERNEL); + if (!skb) { + printk(KERN_ERR "gracefully ignored ping comp: OOM\n"); + return; + } + + nlh = __nlmsg_put(skb, 0, 0, 0, (len - sizeof(*nlh)), 0); + ev = NLMSG_DATA(nlh); + ev->transport_handle = iscsi_handle(transport); + ev->type = ISCSI_KEVENT_PING_COMP; + ev->r.ping_comp.host_no = host_no; + ev->r.ping_comp.status = status; + ev->r.ping_comp.pid = pid; + 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_KERNEL); +} +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) @@ -1946,6 +1975,33 @@ iscsi_set_iface_params(struct iscsi_transport *transport, } static int +iscsi_send_ping(struct iscsi_transport *transport, struct iscsi_uevent *ev) +{ + struct Scsi_Host *shost; + struct sockaddr *dst_addr; + int err; + + if (!transport->send_ping) + return -ENOSYS; + + shost = scsi_host_lookup(ev->u.iscsi_ping.host_no); + if (!shost) { + printk(KERN_ERR "iscsi_ping could not find host no %u\n", + ev->u.iscsi_ping.host_no); + return -ENODEV; + } + + dst_addr = (struct sockaddr *)((char *)ev + sizeof(*ev)); + err = transport->send_ping(shost, ev->u.iscsi_ping.iface_num, + ev->u.iscsi_ping.iface_type, + ev->u.iscsi_ping.payload_size, + ev->u.iscsi_ping.pid, + dst_addr); + scsi_host_put(shost); + return err; +} + +static int iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group) { int err = 0; @@ -2090,6 +2146,9 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group) err = iscsi_set_iface_params(transport, ev, nlmsg_attrlen(nlh, sizeof(*ev))); break; + case ISCSI_UEVENT_PING: + err = iscsi_send_ping(transport, ev); + break; default: err = -ENOSYS; break; |