[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>
This commit is contained in:
Родитель
df86f77157
Коммит
6fa7c55438
|
@ -3415,6 +3415,73 @@ exit_logout_sid:
|
|||
return err;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -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;
|
||||
|
|
|
@ -70,6 +70,7 @@ enum iscsi_uevent_e {
|
|||
ISCSI_UEVENT_LOGOUT_FLASHNODE = UEVENT_BASE + 29,
|
||||
ISCSI_UEVENT_LOGOUT_FLASHNODE_SID = UEVENT_BASE + 30,
|
||||
ISCSI_UEVENT_SET_CHAP = UEVENT_BASE + 31,
|
||||
ISCSI_UEVENT_GET_HOST_STATS = UEVENT_BASE + 32,
|
||||
|
||||
/* up events */
|
||||
ISCSI_KEVENT_RECV_PDU = KEVENT_BASE + 1,
|
||||
|
@ -242,6 +243,9 @@ struct iscsi_uevent {
|
|||
uint32_t host_no;
|
||||
uint32_t sid;
|
||||
} logout_flashnode_sid;
|
||||
struct msg_get_host_stats {
|
||||
uint32_t host_no;
|
||||
} get_host_stats;
|
||||
} u;
|
||||
union {
|
||||
/* messages k -> u */
|
||||
|
@ -845,4 +849,112 @@ struct iscsi_chap_rec {
|
|||
uint8_t password_length;
|
||||
};
|
||||
|
||||
#define ISCSI_HOST_STATS_CUSTOM_MAX 32
|
||||
#define ISCSI_HOST_STATS_CUSTOM_DESC_MAX 64
|
||||
struct iscsi_host_stats_custom {
|
||||
char desc[ISCSI_HOST_STATS_CUSTOM_DESC_MAX];
|
||||
uint64_t value;
|
||||
};
|
||||
|
||||
/* struct iscsi_offload_host_stats: Host statistics,
|
||||
* Include statistics for MAC, IP, TCP & iSCSI.
|
||||
*/
|
||||
struct iscsi_offload_host_stats {
|
||||
/* MAC */
|
||||
uint64_t mactx_frames;
|
||||
uint64_t mactx_bytes;
|
||||
uint64_t mactx_multicast_frames;
|
||||
uint64_t mactx_broadcast_frames;
|
||||
uint64_t mactx_pause_frames;
|
||||
uint64_t mactx_control_frames;
|
||||
uint64_t mactx_deferral;
|
||||
uint64_t mactx_excess_deferral;
|
||||
uint64_t mactx_late_collision;
|
||||
uint64_t mactx_abort;
|
||||
uint64_t mactx_single_collision;
|
||||
uint64_t mactx_multiple_collision;
|
||||
uint64_t mactx_collision;
|
||||
uint64_t mactx_frames_dropped;
|
||||
uint64_t mactx_jumbo_frames;
|
||||
uint64_t macrx_frames;
|
||||
uint64_t macrx_bytes;
|
||||
uint64_t macrx_unknown_control_frames;
|
||||
uint64_t macrx_pause_frames;
|
||||
uint64_t macrx_control_frames;
|
||||
uint64_t macrx_dribble;
|
||||
uint64_t macrx_frame_length_error;
|
||||
uint64_t macrx_jabber;
|
||||
uint64_t macrx_carrier_sense_error;
|
||||
uint64_t macrx_frame_discarded;
|
||||
uint64_t macrx_frames_dropped;
|
||||
uint64_t mac_crc_error;
|
||||
uint64_t mac_encoding_error;
|
||||
uint64_t macrx_length_error_large;
|
||||
uint64_t macrx_length_error_small;
|
||||
uint64_t macrx_multicast_frames;
|
||||
uint64_t macrx_broadcast_frames;
|
||||
/* IP */
|
||||
uint64_t iptx_packets;
|
||||
uint64_t iptx_bytes;
|
||||
uint64_t iptx_fragments;
|
||||
uint64_t iprx_packets;
|
||||
uint64_t iprx_bytes;
|
||||
uint64_t iprx_fragments;
|
||||
uint64_t ip_datagram_reassembly;
|
||||
uint64_t ip_invalid_address_error;
|
||||
uint64_t ip_error_packets;
|
||||
uint64_t ip_fragrx_overlap;
|
||||
uint64_t ip_fragrx_outoforder;
|
||||
uint64_t ip_datagram_reassembly_timeout;
|
||||
uint64_t ipv6tx_packets;
|
||||
uint64_t ipv6tx_bytes;
|
||||
uint64_t ipv6tx_fragments;
|
||||
uint64_t ipv6rx_packets;
|
||||
uint64_t ipv6rx_bytes;
|
||||
uint64_t ipv6rx_fragments;
|
||||
uint64_t ipv6_datagram_reassembly;
|
||||
uint64_t ipv6_invalid_address_error;
|
||||
uint64_t ipv6_error_packets;
|
||||
uint64_t ipv6_fragrx_overlap;
|
||||
uint64_t ipv6_fragrx_outoforder;
|
||||
uint64_t ipv6_datagram_reassembly_timeout;
|
||||
/* TCP */
|
||||
uint64_t tcptx_segments;
|
||||
uint64_t tcptx_bytes;
|
||||
uint64_t tcprx_segments;
|
||||
uint64_t tcprx_byte;
|
||||
uint64_t tcp_duplicate_ack_retx;
|
||||
uint64_t tcp_retx_timer_expired;
|
||||
uint64_t tcprx_duplicate_ack;
|
||||
uint64_t tcprx_pure_ackr;
|
||||
uint64_t tcptx_delayed_ack;
|
||||
uint64_t tcptx_pure_ack;
|
||||
uint64_t tcprx_segment_error;
|
||||
uint64_t tcprx_segment_outoforder;
|
||||
uint64_t tcprx_window_probe;
|
||||
uint64_t tcprx_window_update;
|
||||
uint64_t tcptx_window_probe_persist;
|
||||
/* ECC */
|
||||
uint64_t ecc_error_correction;
|
||||
/* iSCSI */
|
||||
uint64_t iscsi_pdu_tx;
|
||||
uint64_t iscsi_data_bytes_tx;
|
||||
uint64_t iscsi_pdu_rx;
|
||||
uint64_t iscsi_data_bytes_rx;
|
||||
uint64_t iscsi_io_completed;
|
||||
uint64_t iscsi_unexpected_io_rx;
|
||||
uint64_t iscsi_format_error;
|
||||
uint64_t iscsi_hdr_digest_error;
|
||||
uint64_t iscsi_data_digest_error;
|
||||
uint64_t iscsi_sequence_error;
|
||||
/*
|
||||
* iSCSI Custom Host Statistics support, i.e. Transport could
|
||||
* extend existing host statistics with its own specific statistics
|
||||
* up to ISCSI_HOST_STATS_CUSTOM_MAX
|
||||
*/
|
||||
uint32_t custom_length;
|
||||
struct iscsi_host_stats_custom custom[0]
|
||||
__aligned(sizeof(uint64_t));
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -166,6 +166,7 @@ struct iscsi_transport {
|
|||
int (*logout_flashnode) (struct iscsi_bus_flash_session *fnode_sess,
|
||||
struct iscsi_bus_flash_conn *fnode_conn);
|
||||
int (*logout_flashnode_sid) (struct iscsi_cls_session *cls_sess);
|
||||
int (*get_host_stats) (struct Scsi_Host *shost, char *buf, int len);
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
Загрузка…
Ссылка в новой задаче