Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright (c) 2006 Oracle.  All rights reserved.
0003  *
0004  * This software is available to you under a choice of one of two
0005  * licenses.  You may choose to be licensed under the terms of the GNU
0006  * General Public License (GPL) Version 2, available from the file
0007  * COPYING in the main directory of this source tree, or the
0008  * OpenIB.org BSD license below:
0009  *
0010  *     Redistribution and use in source and binary forms, with or
0011  *     without modification, are permitted provided that the following
0012  *     conditions are met:
0013  *
0014  *      - Redistributions of source code must retain the above
0015  *        copyright notice, this list of conditions and the following
0016  *        disclaimer.
0017  *
0018  *      - Redistributions in binary form must reproduce the above
0019  *        copyright notice, this list of conditions and the following
0020  *        disclaimer in the documentation and/or other materials
0021  *        provided with the distribution.
0022  *
0023  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
0024  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
0025  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
0026  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
0027  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
0028  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
0029  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
0030  * SOFTWARE.
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 /* :.,$s/unsigned long\>.*\<s_\(.*\);/"\1",/g */
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  * This gives global counters across all the transports.  The strings
0103  * are copied in so that the tool doesn't need knowledge of the specific
0104  * stats that we're exporting.  Some are pretty implementation dependent
0105  * and may change over time.  That doesn't stop them from being useful.
0106  *
0107  * This is the only function in the chain that knows about the byte granular
0108  * length in userspace.  It converts it to number of stat entries that the
0109  * rest of the functions operate in.
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 }