162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * Copyright (c) 2006 Oracle. All rights reserved. 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * This software is available to you under a choice of one of two 562306a36Sopenharmony_ci * licenses. You may choose to be licensed under the terms of the GNU 662306a36Sopenharmony_ci * General Public License (GPL) Version 2, available from the file 762306a36Sopenharmony_ci * COPYING in the main directory of this source tree, or the 862306a36Sopenharmony_ci * OpenIB.org BSD license below: 962306a36Sopenharmony_ci * 1062306a36Sopenharmony_ci * Redistribution and use in source and binary forms, with or 1162306a36Sopenharmony_ci * without modification, are permitted provided that the following 1262306a36Sopenharmony_ci * conditions are met: 1362306a36Sopenharmony_ci * 1462306a36Sopenharmony_ci * - Redistributions of source code must retain the above 1562306a36Sopenharmony_ci * copyright notice, this list of conditions and the following 1662306a36Sopenharmony_ci * disclaimer. 1762306a36Sopenharmony_ci * 1862306a36Sopenharmony_ci * - Redistributions in binary form must reproduce the above 1962306a36Sopenharmony_ci * copyright notice, this list of conditions and the following 2062306a36Sopenharmony_ci * disclaimer in the documentation and/or other materials 2162306a36Sopenharmony_ci * provided with the distribution. 2262306a36Sopenharmony_ci * 2362306a36Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 2462306a36Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 2562306a36Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 2662306a36Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 2762306a36Sopenharmony_ci * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 2862306a36Sopenharmony_ci * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 2962306a36Sopenharmony_ci * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 3062306a36Sopenharmony_ci * SOFTWARE. 3162306a36Sopenharmony_ci * 3262306a36Sopenharmony_ci */ 3362306a36Sopenharmony_ci#include <linux/percpu.h> 3462306a36Sopenharmony_ci#include <linux/seq_file.h> 3562306a36Sopenharmony_ci#include <linux/proc_fs.h> 3662306a36Sopenharmony_ci#include <linux/export.h> 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci#include "rds.h" 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ciDEFINE_PER_CPU_SHARED_ALIGNED(struct rds_statistics, rds_stats); 4162306a36Sopenharmony_ciEXPORT_PER_CPU_SYMBOL_GPL(rds_stats); 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci/* :.,$s/unsigned long\>.*\<s_\(.*\);/"\1",/g */ 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_cistatic const char *const rds_stat_names[] = { 4662306a36Sopenharmony_ci "conn_reset", 4762306a36Sopenharmony_ci "recv_drop_bad_checksum", 4862306a36Sopenharmony_ci "recv_drop_old_seq", 4962306a36Sopenharmony_ci "recv_drop_no_sock", 5062306a36Sopenharmony_ci "recv_drop_dead_sock", 5162306a36Sopenharmony_ci "recv_deliver_raced", 5262306a36Sopenharmony_ci "recv_delivered", 5362306a36Sopenharmony_ci "recv_queued", 5462306a36Sopenharmony_ci "recv_immediate_retry", 5562306a36Sopenharmony_ci "recv_delayed_retry", 5662306a36Sopenharmony_ci "recv_ack_required", 5762306a36Sopenharmony_ci "recv_rdma_bytes", 5862306a36Sopenharmony_ci "recv_ping", 5962306a36Sopenharmony_ci "send_queue_empty", 6062306a36Sopenharmony_ci "send_queue_full", 6162306a36Sopenharmony_ci "send_lock_contention", 6262306a36Sopenharmony_ci "send_lock_queue_raced", 6362306a36Sopenharmony_ci "send_immediate_retry", 6462306a36Sopenharmony_ci "send_delayed_retry", 6562306a36Sopenharmony_ci "send_drop_acked", 6662306a36Sopenharmony_ci "send_ack_required", 6762306a36Sopenharmony_ci "send_queued", 6862306a36Sopenharmony_ci "send_rdma", 6962306a36Sopenharmony_ci "send_rdma_bytes", 7062306a36Sopenharmony_ci "send_pong", 7162306a36Sopenharmony_ci "page_remainder_hit", 7262306a36Sopenharmony_ci "page_remainder_miss", 7362306a36Sopenharmony_ci "copy_to_user", 7462306a36Sopenharmony_ci "copy_from_user", 7562306a36Sopenharmony_ci "cong_update_queued", 7662306a36Sopenharmony_ci "cong_update_received", 7762306a36Sopenharmony_ci "cong_send_error", 7862306a36Sopenharmony_ci "cong_send_blocked", 7962306a36Sopenharmony_ci "recv_bytes_added_to_sock", 8062306a36Sopenharmony_ci "recv_bytes_freed_fromsock", 8162306a36Sopenharmony_ci "send_stuck_rm", 8262306a36Sopenharmony_ci}; 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_civoid rds_stats_info_copy(struct rds_info_iterator *iter, 8562306a36Sopenharmony_ci uint64_t *values, const char *const *names, size_t nr) 8662306a36Sopenharmony_ci{ 8762306a36Sopenharmony_ci struct rds_info_counter ctr; 8862306a36Sopenharmony_ci size_t i; 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci for (i = 0; i < nr; i++) { 9162306a36Sopenharmony_ci BUG_ON(strlen(names[i]) >= sizeof(ctr.name)); 9262306a36Sopenharmony_ci strncpy(ctr.name, names[i], sizeof(ctr.name) - 1); 9362306a36Sopenharmony_ci ctr.name[sizeof(ctr.name) - 1] = '\0'; 9462306a36Sopenharmony_ci ctr.value = values[i]; 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci rds_info_copy(iter, &ctr, sizeof(ctr)); 9762306a36Sopenharmony_ci } 9862306a36Sopenharmony_ci} 9962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(rds_stats_info_copy); 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci/* 10262306a36Sopenharmony_ci * This gives global counters across all the transports. The strings 10362306a36Sopenharmony_ci * are copied in so that the tool doesn't need knowledge of the specific 10462306a36Sopenharmony_ci * stats that we're exporting. Some are pretty implementation dependent 10562306a36Sopenharmony_ci * and may change over time. That doesn't stop them from being useful. 10662306a36Sopenharmony_ci * 10762306a36Sopenharmony_ci * This is the only function in the chain that knows about the byte granular 10862306a36Sopenharmony_ci * length in userspace. It converts it to number of stat entries that the 10962306a36Sopenharmony_ci * rest of the functions operate in. 11062306a36Sopenharmony_ci */ 11162306a36Sopenharmony_cistatic void rds_stats_info(struct socket *sock, unsigned int len, 11262306a36Sopenharmony_ci struct rds_info_iterator *iter, 11362306a36Sopenharmony_ci struct rds_info_lengths *lens) 11462306a36Sopenharmony_ci{ 11562306a36Sopenharmony_ci struct rds_statistics stats = {0, }; 11662306a36Sopenharmony_ci uint64_t *src; 11762306a36Sopenharmony_ci uint64_t *sum; 11862306a36Sopenharmony_ci size_t i; 11962306a36Sopenharmony_ci int cpu; 12062306a36Sopenharmony_ci unsigned int avail; 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci avail = len / sizeof(struct rds_info_counter); 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci if (avail < ARRAY_SIZE(rds_stat_names)) { 12562306a36Sopenharmony_ci avail = 0; 12662306a36Sopenharmony_ci goto trans; 12762306a36Sopenharmony_ci } 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci for_each_online_cpu(cpu) { 13062306a36Sopenharmony_ci src = (uint64_t *)&(per_cpu(rds_stats, cpu)); 13162306a36Sopenharmony_ci sum = (uint64_t *)&stats; 13262306a36Sopenharmony_ci for (i = 0; i < sizeof(stats) / sizeof(uint64_t); i++) 13362306a36Sopenharmony_ci *(sum++) += *(src++); 13462306a36Sopenharmony_ci } 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci rds_stats_info_copy(iter, (uint64_t *)&stats, rds_stat_names, 13762306a36Sopenharmony_ci ARRAY_SIZE(rds_stat_names)); 13862306a36Sopenharmony_ci avail -= ARRAY_SIZE(rds_stat_names); 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_citrans: 14162306a36Sopenharmony_ci lens->each = sizeof(struct rds_info_counter); 14262306a36Sopenharmony_ci lens->nr = rds_trans_stats_info_copy(iter, avail) + 14362306a36Sopenharmony_ci ARRAY_SIZE(rds_stat_names); 14462306a36Sopenharmony_ci} 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_civoid rds_stats_exit(void) 14762306a36Sopenharmony_ci{ 14862306a36Sopenharmony_ci rds_info_deregister_func(RDS_INFO_COUNTERS, rds_stats_info); 14962306a36Sopenharmony_ci} 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ciint rds_stats_init(void) 15262306a36Sopenharmony_ci{ 15362306a36Sopenharmony_ci rds_info_register_func(RDS_INFO_COUNTERS, rds_stats_info); 15462306a36Sopenharmony_ci return 0; 15562306a36Sopenharmony_ci} 156