0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033 #include <linux/percpu.h>
0034 #include <linux/seq_file.h>
0035 #include <linux/proc_fs.h>
0036 #include <linux/export.h>
0037
0038 #include "rds.h"
0039
0040 DEFINE_PER_CPU_SHARED_ALIGNED(struct rds_statistics, rds_stats);
0041 EXPORT_PER_CPU_SYMBOL_GPL(rds_stats);
0042
0043
0044
0045 static const char *const rds_stat_names[] = {
0046 "conn_reset",
0047 "recv_drop_bad_checksum",
0048 "recv_drop_old_seq",
0049 "recv_drop_no_sock",
0050 "recv_drop_dead_sock",
0051 "recv_deliver_raced",
0052 "recv_delivered",
0053 "recv_queued",
0054 "recv_immediate_retry",
0055 "recv_delayed_retry",
0056 "recv_ack_required",
0057 "recv_rdma_bytes",
0058 "recv_ping",
0059 "send_queue_empty",
0060 "send_queue_full",
0061 "send_lock_contention",
0062 "send_lock_queue_raced",
0063 "send_immediate_retry",
0064 "send_delayed_retry",
0065 "send_drop_acked",
0066 "send_ack_required",
0067 "send_queued",
0068 "send_rdma",
0069 "send_rdma_bytes",
0070 "send_pong",
0071 "page_remainder_hit",
0072 "page_remainder_miss",
0073 "copy_to_user",
0074 "copy_from_user",
0075 "cong_update_queued",
0076 "cong_update_received",
0077 "cong_send_error",
0078 "cong_send_blocked",
0079 "recv_bytes_added_to_sock",
0080 "recv_bytes_freed_fromsock",
0081 "send_stuck_rm",
0082 };
0083
0084 void rds_stats_info_copy(struct rds_info_iterator *iter,
0085 uint64_t *values, const char *const *names, size_t nr)
0086 {
0087 struct rds_info_counter ctr;
0088 size_t i;
0089
0090 for (i = 0; i < nr; i++) {
0091 BUG_ON(strlen(names[i]) >= sizeof(ctr.name));
0092 strncpy(ctr.name, names[i], sizeof(ctr.name) - 1);
0093 ctr.name[sizeof(ctr.name) - 1] = '\0';
0094 ctr.value = values[i];
0095
0096 rds_info_copy(iter, &ctr, sizeof(ctr));
0097 }
0098 }
0099 EXPORT_SYMBOL_GPL(rds_stats_info_copy);
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111 static void rds_stats_info(struct socket *sock, unsigned int len,
0112 struct rds_info_iterator *iter,
0113 struct rds_info_lengths *lens)
0114 {
0115 struct rds_statistics stats = {0, };
0116 uint64_t *src;
0117 uint64_t *sum;
0118 size_t i;
0119 int cpu;
0120 unsigned int avail;
0121
0122 avail = len / sizeof(struct rds_info_counter);
0123
0124 if (avail < ARRAY_SIZE(rds_stat_names)) {
0125 avail = 0;
0126 goto trans;
0127 }
0128
0129 for_each_online_cpu(cpu) {
0130 src = (uint64_t *)&(per_cpu(rds_stats, cpu));
0131 sum = (uint64_t *)&stats;
0132 for (i = 0; i < sizeof(stats) / sizeof(uint64_t); i++)
0133 *(sum++) += *(src++);
0134 }
0135
0136 rds_stats_info_copy(iter, (uint64_t *)&stats, rds_stat_names,
0137 ARRAY_SIZE(rds_stat_names));
0138 avail -= ARRAY_SIZE(rds_stat_names);
0139
0140 trans:
0141 lens->each = sizeof(struct rds_info_counter);
0142 lens->nr = rds_trans_stats_info_copy(iter, avail) +
0143 ARRAY_SIZE(rds_stat_names);
0144 }
0145
0146 void rds_stats_exit(void)
0147 {
0148 rds_info_deregister_func(RDS_INFO_COUNTERS, rds_stats_info);
0149 }
0150
0151 int rds_stats_init(void)
0152 {
0153 rds_info_register_func(RDS_INFO_COUNTERS, rds_stats_info);
0154 return 0;
0155 }