diff options
author | Lalit Chandivade <lalit.chandivade@qlogic.com> | 2013-11-22 05:28:18 -0500 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2013-12-19 20:56:25 -0800 |
commit | 6fa7c554386d391d1d0f46bc298e57d2eda76e78 (patch) | |
tree | 01d32a0e0c5bc5660bc0a48079f42b9c3aec02e1 /drivers/scsi | |
parent | df86f771578209599acc871a03f02346c8d7885b (diff) |
[SCSI] scsi_transport_iscsi: Add host statistics support
Add transport_iscsi hooks to get aggregate host statistics.
The statistics include MAC, TCP/IP & iSCSI statistics.
Signed-off-by: Lalit Chandivade <lalit.chandivade@qlogic.com>
Signed-off-by: Vikas Chaudhary <vikas.chaudhary@qlogic.com>
Reviewed-by: Mike Christie <michaelc@cs.wisc.edu>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/scsi_transport_iscsi.c | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 9477f84c83a6..4cf918a9fc6f 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -3416,6 +3416,73 @@ exit_logout_sid: } static int +iscsi_get_host_stats(struct iscsi_transport *transport, struct nlmsghdr *nlh) +{ + struct iscsi_uevent *ev = nlmsg_data(nlh); + struct Scsi_Host *shost = NULL; + struct iscsi_internal *priv; + struct sk_buff *skbhost_stats; + struct nlmsghdr *nlhhost_stats; + struct iscsi_uevent *evhost_stats; + int host_stats_size = 0; + int len, err = 0; + char *buf; + + if (!transport->get_host_stats) + return -EINVAL; + + priv = iscsi_if_transport_lookup(transport); + if (!priv) + return -EINVAL; + + host_stats_size = sizeof(struct iscsi_offload_host_stats); + len = nlmsg_total_size(sizeof(*ev) + host_stats_size); + + shost = scsi_host_lookup(ev->u.get_host_stats.host_no); + if (!shost) { + pr_err("%s: failed. Cound not find host no %u\n", + __func__, ev->u.get_host_stats.host_no); + return -ENODEV; + } + + do { + int actual_size; + + skbhost_stats = alloc_skb(len, GFP_KERNEL); + if (!skbhost_stats) { + pr_err("cannot deliver host stats: OOM\n"); + err = -ENOMEM; + goto exit_host_stats; + } + + nlhhost_stats = __nlmsg_put(skbhost_stats, 0, 0, 0, + (len - sizeof(*nlhhost_stats)), 0); + evhost_stats = nlmsg_data(nlhhost_stats); + memset(evhost_stats, 0, sizeof(*evhost_stats)); + evhost_stats->transport_handle = iscsi_handle(transport); + evhost_stats->type = nlh->nlmsg_type; + evhost_stats->u.get_host_stats.host_no = + ev->u.get_host_stats.host_no; + buf = (char *)((char *)evhost_stats + sizeof(*evhost_stats)); + memset(buf, 0, host_stats_size); + + err = transport->get_host_stats(shost, buf, host_stats_size); + + actual_size = nlmsg_total_size(sizeof(*ev) + host_stats_size); + 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); + } while (err < 0 && err != -ECONNREFUSED); + +exit_host_stats: + 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; @@ -3594,6 +3661,9 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group) err = iscsi_set_chap(transport, ev, nlmsg_attrlen(nlh, sizeof(*ev))); break; + case ISCSI_UEVENT_GET_HOST_STATS: + err = iscsi_get_host_stats(transport, nlh); + break; default: err = -ENOSYS; break; |