aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLalit Chandivade <lalit.chandivade@qlogic.com>2013-11-22 05:28:18 -0500
committerJames Bottomley <JBottomley@Parallels.com>2013-12-19 23:56:25 -0500
commit6fa7c554386d391d1d0f46bc298e57d2eda76e78 (patch)
tree01d32a0e0c5bc5660bc0a48079f42b9c3aec02e1
parentdf86f771578209599acc871a03f02346c8d7885b (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>
-rw-r--r--drivers/scsi/scsi_transport_iscsi.c70
-rw-r--r--include/scsi/iscsi_if.h112
-rw-r--r--include/scsi/scsi_transport_iscsi.h1
3 files changed, 183 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:
3416} 3416}
3417 3417
3418static int 3418static int
3419iscsi_get_host_stats(struct iscsi_transport *transport, struct nlmsghdr *nlh)
3420{
3421 struct iscsi_uevent *ev = nlmsg_data(nlh);
3422 struct Scsi_Host *shost = NULL;
3423 struct iscsi_internal *priv;
3424 struct sk_buff *skbhost_stats;
3425 struct nlmsghdr *nlhhost_stats;
3426 struct iscsi_uevent *evhost_stats;
3427 int host_stats_size = 0;
3428 int len, err = 0;
3429 char *buf;
3430
3431 if (!transport->get_host_stats)
3432 return -EINVAL;
3433
3434 priv = iscsi_if_transport_lookup(transport);
3435 if (!priv)
3436 return -EINVAL;
3437
3438 host_stats_size = sizeof(struct iscsi_offload_host_stats);
3439 len = nlmsg_total_size(sizeof(*ev) + host_stats_size);
3440
3441 shost = scsi_host_lookup(ev->u.get_host_stats.host_no);
3442 if (!shost) {
3443 pr_err("%s: failed. Cound not find host no %u\n",
3444 __func__, ev->u.get_host_stats.host_no);
3445 return -ENODEV;
3446 }
3447
3448 do {
3449 int actual_size;
3450
3451 skbhost_stats = alloc_skb(len, GFP_KERNEL);
3452 if (!skbhost_stats) {
3453 pr_err("cannot deliver host stats: OOM\n");
3454 err = -ENOMEM;
3455 goto exit_host_stats;
3456 }
3457
3458 nlhhost_stats = __nlmsg_put(skbhost_stats, 0, 0, 0,
3459 (len - sizeof(*nlhhost_stats)), 0);
3460 evhost_stats = nlmsg_data(nlhhost_stats);
3461 memset(evhost_stats, 0, sizeof(*evhost_stats));
3462 evhost_stats->transport_handle = iscsi_handle(transport);
3463 evhost_stats->type = nlh->nlmsg_type;
3464 evhost_stats->u.get_host_stats.host_no =
3465 ev->u.get_host_stats.host_no;
3466 buf = (char *)((char *)evhost_stats + sizeof(*evhost_stats));
3467 memset(buf, 0, host_stats_size);
3468
3469 err = transport->get_host_stats(shost, buf, host_stats_size);
3470
3471 actual_size = nlmsg_total_size(sizeof(*ev) + host_stats_size);
3472 skb_trim(skbhost_stats, NLMSG_ALIGN(actual_size));
3473 nlhhost_stats->nlmsg_len = actual_size;
3474
3475 err = iscsi_multicast_skb(skbhost_stats, ISCSI_NL_GRP_ISCSID,
3476 GFP_KERNEL);
3477 } while (err < 0 && err != -ECONNREFUSED);
3478
3479exit_host_stats:
3480 scsi_host_put(shost);
3481 return err;
3482}
3483
3484
3485static int
3419iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group) 3486iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
3420{ 3487{
3421 int err = 0; 3488 int err = 0;
@@ -3594,6 +3661,9 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
3594 err = iscsi_set_chap(transport, ev, 3661 err = iscsi_set_chap(transport, ev,
3595 nlmsg_attrlen(nlh, sizeof(*ev))); 3662 nlmsg_attrlen(nlh, sizeof(*ev)));
3596 break; 3663 break;
3664 case ISCSI_UEVENT_GET_HOST_STATS:
3665 err = iscsi_get_host_stats(transport, nlh);
3666 break;
3597 default: 3667 default:
3598 err = -ENOSYS; 3668 err = -ENOSYS;
3599 break; 3669 break;
diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h
index a572083c77cb..3851a737c429 100644
--- a/include/scsi/iscsi_if.h
+++ b/include/scsi/iscsi_if.h
@@ -70,6 +70,7 @@ enum iscsi_uevent_e {
70 ISCSI_UEVENT_LOGOUT_FLASHNODE = UEVENT_BASE + 29, 70 ISCSI_UEVENT_LOGOUT_FLASHNODE = UEVENT_BASE + 29,
71 ISCSI_UEVENT_LOGOUT_FLASHNODE_SID = UEVENT_BASE + 30, 71 ISCSI_UEVENT_LOGOUT_FLASHNODE_SID = UEVENT_BASE + 30,
72 ISCSI_UEVENT_SET_CHAP = UEVENT_BASE + 31, 72 ISCSI_UEVENT_SET_CHAP = UEVENT_BASE + 31,
73 ISCSI_UEVENT_GET_HOST_STATS = UEVENT_BASE + 32,
73 74
74 /* up events */ 75 /* up events */
75 ISCSI_KEVENT_RECV_PDU = KEVENT_BASE + 1, 76 ISCSI_KEVENT_RECV_PDU = KEVENT_BASE + 1,
@@ -242,6 +243,9 @@ struct iscsi_uevent {
242 uint32_t host_no; 243 uint32_t host_no;
243 uint32_t sid; 244 uint32_t sid;
244 } logout_flashnode_sid; 245 } logout_flashnode_sid;
246 struct msg_get_host_stats {
247 uint32_t host_no;
248 } get_host_stats;
245 } u; 249 } u;
246 union { 250 union {
247 /* messages k -> u */ 251 /* messages k -> u */
@@ -845,4 +849,112 @@ struct iscsi_chap_rec {
845 uint8_t password_length; 849 uint8_t password_length;
846}; 850};
847 851
852#define ISCSI_HOST_STATS_CUSTOM_MAX 32
853#define ISCSI_HOST_STATS_CUSTOM_DESC_MAX 64
854struct iscsi_host_stats_custom {
855 char desc[ISCSI_HOST_STATS_CUSTOM_DESC_MAX];
856 uint64_t value;
857};
858
859/* struct iscsi_offload_host_stats: Host statistics,
860 * Include statistics for MAC, IP, TCP & iSCSI.
861 */
862struct iscsi_offload_host_stats {
863 /* MAC */
864 uint64_t mactx_frames;
865 uint64_t mactx_bytes;
866 uint64_t mactx_multicast_frames;
867 uint64_t mactx_broadcast_frames;
868 uint64_t mactx_pause_frames;
869 uint64_t mactx_control_frames;
870 uint64_t mactx_deferral;
871 uint64_t mactx_excess_deferral;
872 uint64_t mactx_late_collision;
873 uint64_t mactx_abort;
874 uint64_t mactx_single_collision;
875 uint64_t mactx_multiple_collision;
876 uint64_t mactx_collision;
877 uint64_t mactx_frames_dropped;
878 uint64_t mactx_jumbo_frames;
879 uint64_t macrx_frames;
880 uint64_t macrx_bytes;
881 uint64_t macrx_unknown_control_frames;
882 uint64_t macrx_pause_frames;
883 uint64_t macrx_control_frames;
884 uint64_t macrx_dribble;
885 uint64_t macrx_frame_length_error;
886 uint64_t macrx_jabber;
887 uint64_t macrx_carrier_sense_error;
888 uint64_t macrx_frame_discarded;
889 uint64_t macrx_frames_dropped;
890 uint64_t mac_crc_error;
891 uint64_t mac_encoding_error;
892 uint64_t macrx_length_error_large;
893 uint64_t macrx_length_error_small;
894 uint64_t macrx_multicast_frames;
895 uint64_t macrx_broadcast_frames;
896 /* IP */
897 uint64_t iptx_packets;
898 uint64_t iptx_bytes;
899 uint64_t iptx_fragments;
900 uint64_t iprx_packets;
901 uint64_t iprx_bytes;
902 uint64_t iprx_fragments;
903 uint64_t ip_datagram_reassembly;
904 uint64_t ip_invalid_address_error;
905 uint64_t ip_error_packets;
906 uint64_t ip_fragrx_overlap;
907 uint64_t ip_fragrx_outoforder;
908 uint64_t ip_datagram_reassembly_timeout;
909 uint64_t ipv6tx_packets;
910 uint64_t ipv6tx_bytes;
911 uint64_t ipv6tx_fragments;
912 uint64_t ipv6rx_packets;
913 uint64_t ipv6rx_bytes;
914 uint64_t ipv6rx_fragments;
915 uint64_t ipv6_datagram_reassembly;
916 uint64_t ipv6_invalid_address_error;
917 uint64_t ipv6_error_packets;
918 uint64_t ipv6_fragrx_overlap;
919 uint64_t ipv6_fragrx_outoforder;
920 uint64_t ipv6_datagram_reassembly_timeout;
921 /* TCP */
922 uint64_t tcptx_segments;
923 uint64_t tcptx_bytes;
924 uint64_t tcprx_segments;
925 uint64_t tcprx_byte;
926 uint64_t tcp_duplicate_ack_retx;
927 uint64_t tcp_retx_timer_expired;
928 uint64_t tcprx_duplicate_ack;
929 uint64_t tcprx_pure_ackr;
930 uint64_t tcptx_delayed_ack;
931 uint64_t tcptx_pure_ack;
932 uint64_t tcprx_segment_error;
933 uint64_t tcprx_segment_outoforder;
934 uint64_t tcprx_window_probe;
935 uint64_t tcprx_window_update;
936 uint64_t tcptx_window_probe_persist;
937 /* ECC */
938 uint64_t ecc_error_correction;
939 /* iSCSI */
940 uint64_t iscsi_pdu_tx;
941 uint64_t iscsi_data_bytes_tx;
942 uint64_t iscsi_pdu_rx;
943 uint64_t iscsi_data_bytes_rx;
944 uint64_t iscsi_io_completed;
945 uint64_t iscsi_unexpected_io_rx;
946 uint64_t iscsi_format_error;
947 uint64_t iscsi_hdr_digest_error;
948 uint64_t iscsi_data_digest_error;
949 uint64_t iscsi_sequence_error;
950 /*
951 * iSCSI Custom Host Statistics support, i.e. Transport could
952 * extend existing host statistics with its own specific statistics
953 * up to ISCSI_HOST_STATS_CUSTOM_MAX
954 */
955 uint32_t custom_length;
956 struct iscsi_host_stats_custom custom[0]
957 __aligned(sizeof(uint64_t));
958};
959
848#endif 960#endif
diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
index 2ac11feab6f3..88640a47216c 100644
--- a/include/scsi/scsi_transport_iscsi.h
+++ b/include/scsi/scsi_transport_iscsi.h
@@ -166,6 +166,7 @@ struct iscsi_transport {
166 int (*logout_flashnode) (struct iscsi_bus_flash_session *fnode_sess, 166 int (*logout_flashnode) (struct iscsi_bus_flash_session *fnode_sess,
167 struct iscsi_bus_flash_conn *fnode_conn); 167 struct iscsi_bus_flash_conn *fnode_conn);
168 int (*logout_flashnode_sid) (struct iscsi_cls_session *cls_sess); 168 int (*logout_flashnode_sid) (struct iscsi_cls_session *cls_sess);
169 int (*get_host_stats) (struct Scsi_Host *shost, char *buf, int len);
169}; 170};
170 171
171/* 172/*