|
@@ -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)
|
|
@@ -1945,6 +1974,33 @@ iscsi_set_iface_params(struct iscsi_transport *transport,
|
|
|
return err;
|
|
|
}
|
|
|
|
|
|
+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)
|
|
|
{
|
|
@@ -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;
|