1a8c879a7SAndy Grover /* 2a8c879a7SAndy Grover * Copyright (c) 2006 Oracle. All rights reserved. 3a8c879a7SAndy Grover * 4a8c879a7SAndy Grover * This software is available to you under a choice of one of two 5a8c879a7SAndy Grover * licenses. You may choose to be licensed under the terms of the GNU 6a8c879a7SAndy Grover * General Public License (GPL) Version 2, available from the file 7a8c879a7SAndy Grover * COPYING in the main directory of this source tree, or the 8a8c879a7SAndy Grover * OpenIB.org BSD license below: 9a8c879a7SAndy Grover * 10a8c879a7SAndy Grover * Redistribution and use in source and binary forms, with or 11a8c879a7SAndy Grover * without modification, are permitted provided that the following 12a8c879a7SAndy Grover * conditions are met: 13a8c879a7SAndy Grover * 14a8c879a7SAndy Grover * - Redistributions of source code must retain the above 15a8c879a7SAndy Grover * copyright notice, this list of conditions and the following 16a8c879a7SAndy Grover * disclaimer. 17a8c879a7SAndy Grover * 18a8c879a7SAndy Grover * - Redistributions in binary form must reproduce the above 19a8c879a7SAndy Grover * copyright notice, this list of conditions and the following 20a8c879a7SAndy Grover * disclaimer in the documentation and/or other materials 21a8c879a7SAndy Grover * provided with the distribution. 22a8c879a7SAndy Grover * 23a8c879a7SAndy Grover * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24a8c879a7SAndy Grover * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25a8c879a7SAndy Grover * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26a8c879a7SAndy Grover * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27a8c879a7SAndy Grover * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28a8c879a7SAndy Grover * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29a8c879a7SAndy Grover * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30a8c879a7SAndy Grover * SOFTWARE. 31a8c879a7SAndy Grover * 32a8c879a7SAndy Grover */ 33a8c879a7SAndy Grover #include <linux/percpu.h> 34a8c879a7SAndy Grover #include <linux/seq_file.h> 35a8c879a7SAndy Grover #include <linux/proc_fs.h> 36a8c879a7SAndy Grover 37a8c879a7SAndy Grover #include "rds.h" 38a8c879a7SAndy Grover 39a8c879a7SAndy Grover DEFINE_PER_CPU_SHARED_ALIGNED(struct rds_statistics, rds_stats); 40616b757aSAndy Grover EXPORT_PER_CPU_SYMBOL_GPL(rds_stats); 41a8c879a7SAndy Grover 42a8c879a7SAndy Grover /* :.,$s/unsigned long\>.*\<s_\(.*\);/"\1",/g */ 43a8c879a7SAndy Grover 4436cbd3dcSJan Engelhardt static const char *const rds_stat_names[] = { 45a8c879a7SAndy Grover "conn_reset", 46a8c879a7SAndy Grover "recv_drop_bad_checksum", 47a8c879a7SAndy Grover "recv_drop_old_seq", 48a8c879a7SAndy Grover "recv_drop_no_sock", 49a8c879a7SAndy Grover "recv_drop_dead_sock", 50a8c879a7SAndy Grover "recv_deliver_raced", 51a8c879a7SAndy Grover "recv_delivered", 52a8c879a7SAndy Grover "recv_queued", 53a8c879a7SAndy Grover "recv_immediate_retry", 54a8c879a7SAndy Grover "recv_delayed_retry", 55a8c879a7SAndy Grover "recv_ack_required", 56a8c879a7SAndy Grover "recv_rdma_bytes", 57a8c879a7SAndy Grover "recv_ping", 58a8c879a7SAndy Grover "send_queue_empty", 59a8c879a7SAndy Grover "send_queue_full", 60049ee3f5SAndy Grover "send_lock_contention", 61049ee3f5SAndy Grover "send_lock_queue_raced", 62a8c879a7SAndy Grover "send_immediate_retry", 63a8c879a7SAndy Grover "send_delayed_retry", 64a8c879a7SAndy Grover "send_drop_acked", 65a8c879a7SAndy Grover "send_ack_required", 66a8c879a7SAndy Grover "send_queued", 67a8c879a7SAndy Grover "send_rdma", 68a8c879a7SAndy Grover "send_rdma_bytes", 69a8c879a7SAndy Grover "send_pong", 70a8c879a7SAndy Grover "page_remainder_hit", 71a8c879a7SAndy Grover "page_remainder_miss", 72a8c879a7SAndy Grover "copy_to_user", 73a8c879a7SAndy Grover "copy_from_user", 74a8c879a7SAndy Grover "cong_update_queued", 75a8c879a7SAndy Grover "cong_update_received", 76a8c879a7SAndy Grover "cong_send_error", 77a8c879a7SAndy Grover "cong_send_blocked", 78a8c879a7SAndy Grover }; 79a8c879a7SAndy Grover 80a8c879a7SAndy Grover void rds_stats_info_copy(struct rds_info_iterator *iter, 8136cbd3dcSJan Engelhardt uint64_t *values, const char *const *names, size_t nr) 82a8c879a7SAndy Grover { 83a8c879a7SAndy Grover struct rds_info_counter ctr; 84a8c879a7SAndy Grover size_t i; 85a8c879a7SAndy Grover 86a8c879a7SAndy Grover for (i = 0; i < nr; i++) { 87a8c879a7SAndy Grover BUG_ON(strlen(names[i]) >= sizeof(ctr.name)); 88a8c879a7SAndy Grover strncpy(ctr.name, names[i], sizeof(ctr.name) - 1); 89a8c879a7SAndy Grover ctr.value = values[i]; 90a8c879a7SAndy Grover 91a8c879a7SAndy Grover rds_info_copy(iter, &ctr, sizeof(ctr)); 92a8c879a7SAndy Grover } 93a8c879a7SAndy Grover } 94616b757aSAndy Grover EXPORT_SYMBOL_GPL(rds_stats_info_copy); 95a8c879a7SAndy Grover 96a8c879a7SAndy Grover /* 97a8c879a7SAndy Grover * This gives global counters across all the transports. The strings 98a8c879a7SAndy Grover * are copied in so that the tool doesn't need knowledge of the specific 99a8c879a7SAndy Grover * stats that we're exporting. Some are pretty implementation dependent 100a8c879a7SAndy Grover * and may change over time. That doesn't stop them from being useful. 101a8c879a7SAndy Grover * 102a8c879a7SAndy Grover * This is the only function in the chain that knows about the byte granular 103a8c879a7SAndy Grover * length in userspace. It converts it to number of stat entries that the 104a8c879a7SAndy Grover * rest of the functions operate in. 105a8c879a7SAndy Grover */ 106a8c879a7SAndy Grover static void rds_stats_info(struct socket *sock, unsigned int len, 107a8c879a7SAndy Grover struct rds_info_iterator *iter, 108a8c879a7SAndy Grover struct rds_info_lengths *lens) 109a8c879a7SAndy Grover { 110a8c879a7SAndy Grover struct rds_statistics stats = {0, }; 111a8c879a7SAndy Grover uint64_t *src; 112a8c879a7SAndy Grover uint64_t *sum; 113a8c879a7SAndy Grover size_t i; 114a8c879a7SAndy Grover int cpu; 115a8c879a7SAndy Grover unsigned int avail; 116a8c879a7SAndy Grover 117a8c879a7SAndy Grover avail = len / sizeof(struct rds_info_counter); 118a8c879a7SAndy Grover 119a8c879a7SAndy Grover if (avail < ARRAY_SIZE(rds_stat_names)) { 120a8c879a7SAndy Grover avail = 0; 121a8c879a7SAndy Grover goto trans; 122a8c879a7SAndy Grover } 123a8c879a7SAndy Grover 124a8c879a7SAndy Grover for_each_online_cpu(cpu) { 125a8c879a7SAndy Grover src = (uint64_t *)&(per_cpu(rds_stats, cpu)); 126a8c879a7SAndy Grover sum = (uint64_t *)&stats; 127a8c879a7SAndy Grover for (i = 0; i < sizeof(stats) / sizeof(uint64_t); i++) 128a8c879a7SAndy Grover *(sum++) += *(src++); 129a8c879a7SAndy Grover } 130a8c879a7SAndy Grover 131a8c879a7SAndy Grover rds_stats_info_copy(iter, (uint64_t *)&stats, rds_stat_names, 132a8c879a7SAndy Grover ARRAY_SIZE(rds_stat_names)); 133a8c879a7SAndy Grover avail -= ARRAY_SIZE(rds_stat_names); 134a8c879a7SAndy Grover 135a8c879a7SAndy Grover trans: 136a8c879a7SAndy Grover lens->each = sizeof(struct rds_info_counter); 137a8c879a7SAndy Grover lens->nr = rds_trans_stats_info_copy(iter, avail) + 138a8c879a7SAndy Grover ARRAY_SIZE(rds_stat_names); 139a8c879a7SAndy Grover } 140a8c879a7SAndy Grover 141a8c879a7SAndy Grover void rds_stats_exit(void) 142a8c879a7SAndy Grover { 143a8c879a7SAndy Grover rds_info_deregister_func(RDS_INFO_COUNTERS, rds_stats_info); 144a8c879a7SAndy Grover } 145a8c879a7SAndy Grover 146*ef87b7eaSZach Brown int rds_stats_init(void) 147a8c879a7SAndy Grover { 148a8c879a7SAndy Grover rds_info_register_func(RDS_INFO_COUNTERS, rds_stats_info); 149a8c879a7SAndy Grover return 0; 150a8c879a7SAndy Grover } 151