The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/ofed/drivers/infiniband/ulp/sdp/sdp_proc.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause OR GPL-2.0
    3  *
    4  * Copyright (c) 2008 Mellanox Technologies Ltd.  All rights reserved.
    5  *
    6  * This software is available to you under a choice of one of two
    7  * licenses.  You may choose to be licensed under the terms of the GNU
    8  * General Public License (GPL) Version 2, available from the file
    9  * COPYING in the main directory of this source tree, or the
   10  * OpenIB.org BSD license below:
   11  *
   12  *     Redistribution and use in source and binary forms, with or
   13  *     without modification, are permitted provided that the following
   14  *     conditions are met:
   15  *
   16  *      - Redistributions of source code must retain the above
   17  *        copyright notice, this list of conditions and the following
   18  *        disclaimer.
   19  *
   20  *      - Redistributions in binary form must reproduce the above
   21  *        copyright notice, this list of conditions and the following
   22  *        disclaimer in the documentation and/or other materials
   23  *        provided with the distribution.
   24  *
   25  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
   26  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
   27  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
   28  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
   29  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
   30  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
   31  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
   32  * SOFTWARE.
   33  */
   34 
   35 #include <linux/proc_fs.h>
   36 #include "sdp.h"
   37 
   38 #ifdef CONFIG_PROC_FS
   39 
   40 #define PROC_SDP_STATS "sdpstats"
   41 #define PROC_SDP_PERF "sdpprf"
   42 
   43 /* just like TCP fs */
   44 struct sdp_seq_afinfo {
   45         struct module           *owner;
   46         char                    *name;
   47         sa_family_t             family;
   48         int                     (*seq_show) (struct seq_file *m, void *v);
   49         struct file_operations  *seq_fops;
   50 };
   51 
   52 struct sdp_iter_state {
   53         sa_family_t             family;
   54         int                     num;
   55         struct seq_operations   seq_ops;
   56 };
   57 
   58 static void *sdp_get_idx(struct seq_file *seq, loff_t pos)
   59 {
   60         int i = 0;
   61         struct sdp_sock *ssk;
   62 
   63         if (!list_empty(&sock_list))
   64                 list_for_each_entry(ssk, &sock_list, sock_list) {
   65                         if (i == pos)
   66                                 return ssk;
   67                         i++;
   68                 }
   69 
   70         return NULL;
   71 }
   72 
   73 static void *sdp_seq_start(struct seq_file *seq, loff_t *pos)
   74 {
   75         void *start = NULL;
   76         struct sdp_iter_state *st = seq->private;
   77 
   78         st->num = 0;
   79 
   80         if (!*pos)
   81                 return SEQ_START_TOKEN;
   82 
   83         spin_lock_irq(&sock_list_lock);
   84         start = sdp_get_idx(seq, *pos - 1);
   85         if (start)
   86                 sock_hold((struct socket *)start, SOCK_REF_SEQ);
   87         spin_unlock_irq(&sock_list_lock);
   88 
   89         return start;
   90 }
   91 
   92 static void *sdp_seq_next(struct seq_file *seq, void *v, loff_t *pos)
   93 {
   94         struct sdp_iter_state *st = seq->private;
   95         void *next = NULL;
   96 
   97         spin_lock_irq(&sock_list_lock);
   98         if (v == SEQ_START_TOKEN)
   99                 next = sdp_get_idx(seq, 0);
  100         else
  101                 next = sdp_get_idx(seq, *pos);
  102         if (next)
  103                 sock_hold((struct socket *)next, SOCK_REF_SEQ);
  104         spin_unlock_irq(&sock_list_lock);
  105 
  106         *pos += 1;
  107         st->num++;
  108 
  109         return next;
  110 }
  111 
  112 static void sdp_seq_stop(struct seq_file *seq, void *v)
  113 {
  114 }
  115 
  116 #define TMPSZ 150
  117 
  118 static int sdp_seq_show(struct seq_file *seq, void *v)
  119 {
  120         struct sdp_iter_state *st;
  121         struct socket *sk = v;
  122         char tmpbuf[TMPSZ + 1];
  123         unsigned int dest;
  124         unsigned int src;
  125         int uid;
  126         unsigned long inode;
  127         __u16 destp;
  128         __u16 srcp;
  129         __u32 rx_queue, tx_queue;
  130 
  131         if (v == SEQ_START_TOKEN) {
  132                 seq_printf(seq, "%-*s\n", TMPSZ - 1,
  133                                 "  sl  local_address rem_address        "
  134                                 "uid inode   rx_queue tx_queue state");
  135                 goto out;
  136         }
  137 
  138         st = seq->private;
  139 
  140         dest = inet_sk(sk)->daddr;
  141         src = inet_sk(sk)->rcv_saddr;
  142         destp = ntohs(inet_sk(sk)->dport);
  143         srcp = ntohs(inet_sk(sk)->sport);
  144         uid = sock_i_uid(sk);
  145         inode = sock_i_ino(sk);
  146         rx_queue = rcv_nxt(sdp_sk(sk)) - sdp_sk(sk)->copied_seq;
  147         tx_queue = sdp_sk(sk)->write_seq - sdp_sk(sk)->tx_ring.una_seq;
  148 
  149         sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X %5d %lu       %08X:%08X %X",
  150                 st->num, src, srcp, dest, destp, uid, inode,
  151                 rx_queue, tx_queue, sk->sk_state);
  152 
  153         seq_printf(seq, "%-*s\n", TMPSZ - 1, tmpbuf);
  154 
  155         sock_put(sk, SOCK_REF_SEQ);
  156 out:
  157         return 0;
  158 }
  159 
  160 static int sdp_seq_open(struct inode *inode, struct file *file)
  161 {
  162         struct sdp_seq_afinfo *afinfo = PDE(inode)->data;
  163         struct seq_file *seq;
  164         struct sdp_iter_state *s;
  165         int rc;
  166 
  167         if (unlikely(afinfo == NULL))
  168                 return -EINVAL;
  169 
  170 /* Workaround bogus warning by memtrack */
  171 #define _kzalloc(size,flags) kzalloc(size,flags)
  172 #undef kzalloc
  173         s = kzalloc(sizeof(*s), GFP_KERNEL);
  174 #define kzalloc(s,f) _kzalloc(s,f)      
  175         if (!s)
  176                 return -ENOMEM;
  177         s->family               = afinfo->family;
  178         s->seq_ops.start        = sdp_seq_start;
  179         s->seq_ops.next         = sdp_seq_next;
  180         s->seq_ops.show         = afinfo->seq_show;
  181         s->seq_ops.stop         = sdp_seq_stop;
  182 
  183         rc = seq_open(file, &s->seq_ops);
  184         if (rc)
  185                 goto out_kfree;
  186         seq          = file->private_data;
  187         seq->private = s;
  188 out:
  189         return rc;
  190 out_kfree:
  191         kfree(s);
  192         goto out;
  193 }
  194 
  195 
  196 static struct file_operations sdp_seq_fops;
  197 static struct sdp_seq_afinfo sdp_seq_afinfo = {
  198         .owner          = THIS_MODULE,
  199         .name           = "sdp",
  200         .family         = AF_INET_SDP,
  201         .seq_show       = sdp_seq_show,
  202         .seq_fops       = &sdp_seq_fops,
  203 };
  204 
  205 #ifdef SDPSTATS_ON
  206 DEFINE_PER_CPU(struct sdpstats, sdpstats);
  207 
  208 static void sdpstats_seq_hist(struct seq_file *seq, char *str, u32 *h, int n,
  209                 int is_log)
  210 {
  211         int i;
  212         u32 max = 0;
  213 
  214         seq_printf(seq, "%s:\n", str);
  215 
  216         for (i = 0; i < n; i++) {
  217                 if (h[i] > max)
  218                         max = h[i];
  219         }
  220 
  221         if (max == 0) {
  222                 seq_printf(seq, " - all values are 0\n");
  223                 return;
  224         }
  225 
  226         for (i = 0; i < n; i++) {
  227                 char s[51];
  228                 int j = 50 * h[i] / max;
  229                 int val = is_log ? (i == n-1 ? 0 : 1<<i) : i;
  230                 memset(s, '*', j);
  231                 s[j] = '\0';
  232 
  233                 seq_printf(seq, "%10d | %-50s - %d\n", val, s, h[i]);
  234         }
  235 }
  236 
  237 #define SDPSTATS_COUNTER_GET(var) ({ \
  238         u32 __val = 0;                                          \
  239         unsigned int __i;                                       \
  240         for_each_possible_cpu(__i)                              \
  241                 __val += per_cpu(sdpstats, __i).var;            \
  242         __val;                                                  \
  243 })      
  244 
  245 #define SDPSTATS_HIST_GET(hist, hist_len, sum) ({ \
  246         unsigned int __i;                                       \
  247         for_each_possible_cpu(__i) {                            \
  248                 unsigned int __j;                               \
  249                 u32 *h = per_cpu(sdpstats, __i).hist;           \
  250                 for (__j = 0; __j < hist_len; __j++) {          \
  251                         sum[__j] += h[__j];                     \
  252                 } \
  253         }                                                       \
  254 })
  255 
  256 #define __sdpstats_seq_hist(seq, msg, hist, is_log) ({          \
  257         u32 tmp_hist[SDPSTATS_MAX_HIST_SIZE];                   \
  258         int hist_len = ARRAY_SIZE(__get_cpu_var(sdpstats).hist);\
  259         memset(tmp_hist, 0, sizeof(tmp_hist));                  \
  260         SDPSTATS_HIST_GET(hist, hist_len, tmp_hist);    \
  261         sdpstats_seq_hist(seq, msg, tmp_hist, hist_len, is_log);\
  262 })
  263 
  264 static int sdpstats_seq_show(struct seq_file *seq, void *v)
  265 {
  266         int i;
  267 
  268         seq_printf(seq, "SDP statistics:\n");
  269 
  270         __sdpstats_seq_hist(seq, "sendmsg_seglen", sendmsg_seglen, 1);
  271         __sdpstats_seq_hist(seq, "send_size", send_size, 1);
  272         __sdpstats_seq_hist(seq, "credits_before_update",
  273                 credits_before_update, 0);
  274 
  275         seq_printf(seq, "sdp_sendmsg() calls\t\t: %d\n",
  276                 SDPSTATS_COUNTER_GET(sendmsg));
  277         seq_printf(seq, "bcopy segments     \t\t: %d\n",
  278                 SDPSTATS_COUNTER_GET(sendmsg_bcopy_segment));
  279         seq_printf(seq, "bzcopy segments    \t\t: %d\n",
  280                 SDPSTATS_COUNTER_GET(sendmsg_bzcopy_segment));
  281         seq_printf(seq, "zcopy segments    \t\t: %d\n",
  282                 SDPSTATS_COUNTER_GET(sendmsg_zcopy_segment));
  283         seq_printf(seq, "post_send_credits  \t\t: %d\n",
  284                 SDPSTATS_COUNTER_GET(post_send_credits));
  285         seq_printf(seq, "memcpy_count       \t\t: %u\n",
  286                 SDPSTATS_COUNTER_GET(memcpy_count));
  287 
  288         for (i = 0; i < ARRAY_SIZE(__get_cpu_var(sdpstats).post_send); i++) {
  289                 if (mid2str(i)) {
  290                         seq_printf(seq, "post_send %-20s\t: %d\n",
  291                                         mid2str(i),
  292                                         SDPSTATS_COUNTER_GET(post_send[i]));
  293                 }
  294         }
  295 
  296         seq_printf(seq, "\n");
  297         seq_printf(seq, "post_recv         \t\t: %d\n",
  298                 SDPSTATS_COUNTER_GET(post_recv));
  299         seq_printf(seq, "BZCopy poll miss  \t\t: %d\n",
  300                 SDPSTATS_COUNTER_GET(bzcopy_poll_miss));
  301         seq_printf(seq, "send_wait_for_mem \t\t: %d\n",
  302                 SDPSTATS_COUNTER_GET(send_wait_for_mem));
  303         seq_printf(seq, "send_miss_no_credits\t\t: %d\n",
  304                 SDPSTATS_COUNTER_GET(send_miss_no_credits));
  305 
  306         seq_printf(seq, "rx_poll_miss      \t\t: %d\n", SDPSTATS_COUNTER_GET(rx_poll_miss));
  307         seq_printf(seq, "tx_poll_miss      \t\t: %d\n", SDPSTATS_COUNTER_GET(tx_poll_miss));
  308         seq_printf(seq, "tx_poll_busy      \t\t: %d\n", SDPSTATS_COUNTER_GET(tx_poll_busy));
  309         seq_printf(seq, "tx_poll_hit       \t\t: %d\n", SDPSTATS_COUNTER_GET(tx_poll_hit));
  310 
  311         seq_printf(seq, "CQ stats:\n");
  312         seq_printf(seq, "- RX interrupts\t\t: %d\n", SDPSTATS_COUNTER_GET(rx_int_count));
  313         seq_printf(seq, "- TX interrupts\t\t: %d\n", SDPSTATS_COUNTER_GET(tx_int_count));
  314 
  315         seq_printf(seq, "ZCopy stats:\n");
  316         seq_printf(seq, "- TX timeout\t\t: %d\n", SDPSTATS_COUNTER_GET(zcopy_tx_timeout));
  317         seq_printf(seq, "- TX cross send\t\t: %d\n", SDPSTATS_COUNTER_GET(zcopy_cross_send));
  318         seq_printf(seq, "- TX aborted by peer\t: %d\n", SDPSTATS_COUNTER_GET(zcopy_tx_aborted));
  319         seq_printf(seq, "- TX error\t\t: %d\n", SDPSTATS_COUNTER_GET(zcopy_tx_error));
  320         return 0;
  321 }
  322 
  323 static ssize_t sdpstats_write(struct file *file, const char __user *buf,
  324                             size_t count, loff_t *offs)
  325 {
  326         int i;
  327 
  328         for_each_possible_cpu(i)
  329                 memset(&per_cpu(sdpstats, i), 0, sizeof(struct sdpstats));
  330         printk(KERN_WARNING "Cleared sdp statistics\n");
  331 
  332         return count;
  333 }
  334 
  335 static int sdpstats_seq_open(struct inode *inode, struct file *file)
  336 {
  337         return single_open(file, sdpstats_seq_show, NULL);
  338 }
  339 
  340 static struct file_operations sdpstats_fops = {
  341         .owner          = THIS_MODULE,
  342         .open           = sdpstats_seq_open,
  343         .read           = seq_read,
  344         .write          = sdpstats_write,
  345         .llseek         = seq_lseek,
  346         .release        = single_release,
  347 };
  348 
  349 #endif
  350 
  351 #ifdef SDP_PROFILING
  352 struct sdpprf_log sdpprf_log[SDPPRF_LOG_SIZE];
  353 int sdpprf_log_count;
  354 
  355 static unsigned long long start_t;
  356 
  357 static int sdpprf_show(struct seq_file *m, void *v)
  358 {
  359         struct sdpprf_log *l = v;
  360         unsigned long nsec_rem, t;
  361 
  362         if (!sdpprf_log_count) {
  363                 seq_printf(m, "No performance logs\n");
  364                 goto out;
  365         }
  366 
  367         t = l->time - start_t;
  368         nsec_rem = do_div(t, 1000000000);
  369 
  370         seq_printf(m, "%-6d: [%5lu.%06lu] %-50s - [%d{%d} %d:%d] "
  371                         "mb: %p %s:%d\n",
  372                         l->idx, (unsigned long)t, nsec_rem/1000,
  373                         l->msg, l->pid, l->cpu, l->sk_num, l->sk_dport,
  374                         l->mb, l->func, l->line);
  375 out:
  376         return 0;
  377 }
  378 
  379 static void *sdpprf_start(struct seq_file *p, loff_t *pos)
  380 {
  381         int idx = *pos;
  382 
  383         if (!*pos) {
  384                 if (!sdpprf_log_count)
  385                         return SEQ_START_TOKEN;
  386         }
  387 
  388         if (*pos >= MIN(sdpprf_log_count, SDPPRF_LOG_SIZE - 1))
  389                 return NULL;
  390 
  391         if (sdpprf_log_count >= SDPPRF_LOG_SIZE - 1) {
  392                 int off = sdpprf_log_count & (SDPPRF_LOG_SIZE - 1);
  393                 idx = (idx + off) & (SDPPRF_LOG_SIZE - 1);
  394 
  395         }
  396 
  397         if (!start_t)
  398                 start_t = sdpprf_log[idx].time;
  399         return &sdpprf_log[idx];
  400 }
  401 
  402 static void *sdpprf_next(struct seq_file *p, void *v, loff_t *pos)
  403 {
  404         struct sdpprf_log *l = v;
  405 
  406         if (++*pos >= MIN(sdpprf_log_count, SDPPRF_LOG_SIZE - 1))
  407                 return NULL;
  408 
  409         ++l;
  410         if (l - &sdpprf_log[0] >= SDPPRF_LOG_SIZE - 1)
  411                 return &sdpprf_log[0];
  412 
  413         return l;
  414 }
  415 
  416 static void sdpprf_stop(struct seq_file *p, void *v)
  417 {
  418 }
  419 
  420 static struct seq_operations sdpprf_ops = {
  421         .start = sdpprf_start,
  422         .stop = sdpprf_stop,
  423         .next = sdpprf_next,
  424         .show = sdpprf_show,
  425 };
  426 
  427 static int sdpprf_open(struct inode *inode, struct file *file)
  428 {
  429         int res;
  430 
  431         res = seq_open(file, &sdpprf_ops);
  432 
  433         return res;
  434 }
  435 
  436 static ssize_t sdpprf_write(struct file *file, const char __user *buf,
  437                             size_t count, loff_t *offs)
  438 {
  439         sdpprf_log_count = 0;
  440         printk(KERN_INFO "Cleared sdpprf statistics\n");
  441 
  442         return count;
  443 }
  444 
  445 static struct file_operations sdpprf_fops = {
  446         .open           = sdpprf_open,
  447         .read           = seq_read,
  448         .llseek         = seq_lseek,
  449         .release        = seq_release,
  450         .write          = sdpprf_write,
  451 };
  452 #endif /* SDP_PROFILING */
  453 
  454 int __init sdp_proc_init(void)
  455 {
  456         struct proc_dir_entry *p = NULL;
  457 #ifdef SDPSTATS_ON
  458         struct proc_dir_entry *stats = NULL;
  459 #endif
  460 #ifdef SDP_PROFILING
  461         struct proc_dir_entry *prof = NULL;
  462 #endif
  463 
  464         sdp_seq_afinfo.seq_fops->owner         = sdp_seq_afinfo.owner;
  465         sdp_seq_afinfo.seq_fops->open          = sdp_seq_open;
  466         sdp_seq_afinfo.seq_fops->read          = seq_read;
  467         sdp_seq_afinfo.seq_fops->llseek        = seq_lseek;
  468         sdp_seq_afinfo.seq_fops->release       = seq_release_private;
  469 
  470         p = proc_net_fops_create(&init_net, sdp_seq_afinfo.name, S_IRUGO,
  471                                  sdp_seq_afinfo.seq_fops);
  472         if (p)
  473                 p->data = &sdp_seq_afinfo;
  474         else
  475                 goto no_mem;
  476 
  477 #ifdef SDPSTATS_ON
  478 
  479         stats = proc_net_fops_create(&init_net, PROC_SDP_STATS,
  480                         S_IRUGO | S_IWUGO, &sdpstats_fops);
  481         if (!stats)
  482                 goto no_mem_stats;
  483 
  484 #endif
  485 
  486 #ifdef SDP_PROFILING
  487         prof = proc_net_fops_create(&init_net, PROC_SDP_PERF,
  488                         S_IRUGO | S_IWUGO, &sdpprf_fops);
  489         if (!prof)
  490                 goto no_mem_prof;
  491 #endif
  492 
  493         return 0;
  494 
  495 #ifdef SDP_PROFILING
  496 no_mem_prof:
  497 #endif
  498 
  499 #ifdef SDPSTATS_ON
  500         proc_net_remove(&init_net, PROC_SDP_STATS);
  501 
  502 no_mem_stats:
  503 #endif
  504         proc_net_remove(&init_net, sdp_seq_afinfo.name);
  505 
  506 no_mem: 
  507         return -ENOMEM;
  508 }
  509 
  510 void sdp_proc_unregister(void)
  511 {
  512         proc_net_remove(&init_net, sdp_seq_afinfo.name);
  513         memset(sdp_seq_afinfo.seq_fops, 0, sizeof(*sdp_seq_afinfo.seq_fops));
  514 
  515 #ifdef SDPSTATS_ON
  516         proc_net_remove(&init_net, PROC_SDP_STATS);
  517 #endif
  518 #ifdef SDP_PROFILING
  519         proc_net_remove(&init_net, PROC_SDP_PERF);
  520 #endif
  521 }
  522 
  523 #else /* CONFIG_PROC_FS */
  524 
  525 int __init sdp_proc_init(void)
  526 {
  527         return 0;
  528 }
  529 
  530 void sdp_proc_unregister(void)
  531 {
  532 
  533 }
  534 #endif /* CONFIG_PROC_FS */

Cache object: 74a876d4a6232fdfabb8b3c1c4c73241


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.