root/fs/ocfs2/cluster/netdebug.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. o2net_debug_add_nst
  2. o2net_debug_del_nst
  3. next_nst
  4. nst_seq_start
  5. nst_seq_next
  6. nst_seq_show
  7. nst_seq_stop
  8. nst_fop_open
  9. nst_fop_release
  10. o2net_debug_add_sc
  11. o2net_debug_del_sc
  12. next_sc
  13. sc_seq_start
  14. sc_seq_next
  15. sc_show_sock_stats
  16. sc_show_sock_container
  17. sc_seq_show
  18. sc_seq_stop
  19. sc_common_open
  20. sc_fop_release
  21. stats_fop_open
  22. sc_fop_open
  23. o2net_fill_bitmap
  24. nodes_fop_open
  25. o2net_debug_release
  26. o2net_debug_read
  27. o2net_debugfs_exit
  28. o2net_debugfs_init

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /* -*- mode: c; c-basic-offset: 8; -*-
   3  * vim: noexpandtab sw=8 ts=8 sts=0:
   4  *
   5  * netdebug.c
   6  *
   7  * debug functionality for o2net
   8  *
   9  * Copyright (C) 2005, 2008 Oracle.  All rights reserved.
  10  */
  11 
  12 #ifdef CONFIG_DEBUG_FS
  13 
  14 #include <linux/module.h>
  15 #include <linux/types.h>
  16 #include <linux/slab.h>
  17 #include <linux/idr.h>
  18 #include <linux/kref.h>
  19 #include <linux/seq_file.h>
  20 #include <linux/debugfs.h>
  21 
  22 #include <linux/uaccess.h>
  23 
  24 #include "tcp.h"
  25 #include "nodemanager.h"
  26 #define MLOG_MASK_PREFIX ML_TCP
  27 #include "masklog.h"
  28 
  29 #include "tcp_internal.h"
  30 
  31 #define O2NET_DEBUG_DIR         "o2net"
  32 #define SC_DEBUG_NAME           "sock_containers"
  33 #define NST_DEBUG_NAME          "send_tracking"
  34 #define STATS_DEBUG_NAME        "stats"
  35 #define NODES_DEBUG_NAME        "connected_nodes"
  36 
  37 #define SHOW_SOCK_CONTAINERS    0
  38 #define SHOW_SOCK_STATS         1
  39 
  40 static struct dentry *o2net_dentry;
  41 
  42 static DEFINE_SPINLOCK(o2net_debug_lock);
  43 
  44 static LIST_HEAD(sock_containers);
  45 static LIST_HEAD(send_tracking);
  46 
  47 void o2net_debug_add_nst(struct o2net_send_tracking *nst)
  48 {
  49         spin_lock(&o2net_debug_lock);
  50         list_add(&nst->st_net_debug_item, &send_tracking);
  51         spin_unlock(&o2net_debug_lock);
  52 }
  53 
  54 void o2net_debug_del_nst(struct o2net_send_tracking *nst)
  55 {
  56         spin_lock(&o2net_debug_lock);
  57         if (!list_empty(&nst->st_net_debug_item))
  58                 list_del_init(&nst->st_net_debug_item);
  59         spin_unlock(&o2net_debug_lock);
  60 }
  61 
  62 static struct o2net_send_tracking
  63                         *next_nst(struct o2net_send_tracking *nst_start)
  64 {
  65         struct o2net_send_tracking *nst, *ret = NULL;
  66 
  67         assert_spin_locked(&o2net_debug_lock);
  68 
  69         list_for_each_entry(nst, &nst_start->st_net_debug_item,
  70                             st_net_debug_item) {
  71                 /* discover the head of the list */
  72                 if (&nst->st_net_debug_item == &send_tracking)
  73                         break;
  74 
  75                 /* use st_task to detect real nsts in the list */
  76                 if (nst->st_task != NULL) {
  77                         ret = nst;
  78                         break;
  79                 }
  80         }
  81 
  82         return ret;
  83 }
  84 
  85 static void *nst_seq_start(struct seq_file *seq, loff_t *pos)
  86 {
  87         struct o2net_send_tracking *nst, *dummy_nst = seq->private;
  88 
  89         spin_lock(&o2net_debug_lock);
  90         nst = next_nst(dummy_nst);
  91         spin_unlock(&o2net_debug_lock);
  92 
  93         return nst;
  94 }
  95 
  96 static void *nst_seq_next(struct seq_file *seq, void *v, loff_t *pos)
  97 {
  98         struct o2net_send_tracking *nst, *dummy_nst = seq->private;
  99 
 100         spin_lock(&o2net_debug_lock);
 101         nst = next_nst(dummy_nst);
 102         list_del_init(&dummy_nst->st_net_debug_item);
 103         if (nst)
 104                 list_add(&dummy_nst->st_net_debug_item,
 105                          &nst->st_net_debug_item);
 106         spin_unlock(&o2net_debug_lock);
 107 
 108         return nst; /* unused, just needs to be null when done */
 109 }
 110 
 111 static int nst_seq_show(struct seq_file *seq, void *v)
 112 {
 113         struct o2net_send_tracking *nst, *dummy_nst = seq->private;
 114         ktime_t now;
 115         s64 sock, send, status;
 116 
 117         spin_lock(&o2net_debug_lock);
 118         nst = next_nst(dummy_nst);
 119         if (!nst)
 120                 goto out;
 121 
 122         now = ktime_get();
 123         sock = ktime_to_us(ktime_sub(now, nst->st_sock_time));
 124         send = ktime_to_us(ktime_sub(now, nst->st_send_time));
 125         status = ktime_to_us(ktime_sub(now, nst->st_status_time));
 126 
 127         /* get_task_comm isn't exported.  oh well. */
 128         seq_printf(seq, "%p:\n"
 129                    "  pid:          %lu\n"
 130                    "  tgid:         %lu\n"
 131                    "  process name: %s\n"
 132                    "  node:         %u\n"
 133                    "  sc:           %p\n"
 134                    "  message id:   %d\n"
 135                    "  message type: %u\n"
 136                    "  message key:  0x%08x\n"
 137                    "  sock acquiry: %lld usecs ago\n"
 138                    "  send start:   %lld usecs ago\n"
 139                    "  wait start:   %lld usecs ago\n",
 140                    nst, (unsigned long)task_pid_nr(nst->st_task),
 141                    (unsigned long)nst->st_task->tgid,
 142                    nst->st_task->comm, nst->st_node,
 143                    nst->st_sc, nst->st_id, nst->st_msg_type,
 144                    nst->st_msg_key,
 145                    (long long)sock,
 146                    (long long)send,
 147                    (long long)status);
 148 
 149 out:
 150         spin_unlock(&o2net_debug_lock);
 151 
 152         return 0;
 153 }
 154 
 155 static void nst_seq_stop(struct seq_file *seq, void *v)
 156 {
 157 }
 158 
 159 static const struct seq_operations nst_seq_ops = {
 160         .start = nst_seq_start,
 161         .next = nst_seq_next,
 162         .stop = nst_seq_stop,
 163         .show = nst_seq_show,
 164 };
 165 
 166 static int nst_fop_open(struct inode *inode, struct file *file)
 167 {
 168         struct o2net_send_tracking *dummy_nst;
 169 
 170         dummy_nst = __seq_open_private(file, &nst_seq_ops, sizeof(*dummy_nst));
 171         if (!dummy_nst)
 172                 return -ENOMEM;
 173         o2net_debug_add_nst(dummy_nst);
 174 
 175         return 0;
 176 }
 177 
 178 static int nst_fop_release(struct inode *inode, struct file *file)
 179 {
 180         struct seq_file *seq = file->private_data;
 181         struct o2net_send_tracking *dummy_nst = seq->private;
 182 
 183         o2net_debug_del_nst(dummy_nst);
 184         return seq_release_private(inode, file);
 185 }
 186 
 187 static const struct file_operations nst_seq_fops = {
 188         .open = nst_fop_open,
 189         .read = seq_read,
 190         .llseek = seq_lseek,
 191         .release = nst_fop_release,
 192 };
 193 
 194 void o2net_debug_add_sc(struct o2net_sock_container *sc)
 195 {
 196         spin_lock(&o2net_debug_lock);
 197         list_add(&sc->sc_net_debug_item, &sock_containers);
 198         spin_unlock(&o2net_debug_lock);
 199 }
 200 
 201 void o2net_debug_del_sc(struct o2net_sock_container *sc)
 202 {
 203         spin_lock(&o2net_debug_lock);
 204         list_del_init(&sc->sc_net_debug_item);
 205         spin_unlock(&o2net_debug_lock);
 206 }
 207 
 208 struct o2net_sock_debug {
 209         int dbg_ctxt;
 210         struct o2net_sock_container *dbg_sock;
 211 };
 212 
 213 static struct o2net_sock_container
 214                         *next_sc(struct o2net_sock_container *sc_start)
 215 {
 216         struct o2net_sock_container *sc, *ret = NULL;
 217 
 218         assert_spin_locked(&o2net_debug_lock);
 219 
 220         list_for_each_entry(sc, &sc_start->sc_net_debug_item,
 221                             sc_net_debug_item) {
 222                 /* discover the head of the list miscast as a sc */
 223                 if (&sc->sc_net_debug_item == &sock_containers)
 224                         break;
 225 
 226                 /* use sc_page to detect real scs in the list */
 227                 if (sc->sc_page != NULL) {
 228                         ret = sc;
 229                         break;
 230                 }
 231         }
 232 
 233         return ret;
 234 }
 235 
 236 static void *sc_seq_start(struct seq_file *seq, loff_t *pos)
 237 {
 238         struct o2net_sock_debug *sd = seq->private;
 239         struct o2net_sock_container *sc, *dummy_sc = sd->dbg_sock;
 240 
 241         spin_lock(&o2net_debug_lock);
 242         sc = next_sc(dummy_sc);
 243         spin_unlock(&o2net_debug_lock);
 244 
 245         return sc;
 246 }
 247 
 248 static void *sc_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 249 {
 250         struct o2net_sock_debug *sd = seq->private;
 251         struct o2net_sock_container *sc, *dummy_sc = sd->dbg_sock;
 252 
 253         spin_lock(&o2net_debug_lock);
 254         sc = next_sc(dummy_sc);
 255         list_del_init(&dummy_sc->sc_net_debug_item);
 256         if (sc)
 257                 list_add(&dummy_sc->sc_net_debug_item, &sc->sc_net_debug_item);
 258         spin_unlock(&o2net_debug_lock);
 259 
 260         return sc; /* unused, just needs to be null when done */
 261 }
 262 
 263 #ifdef CONFIG_OCFS2_FS_STATS
 264 # define sc_send_count(_s)              ((_s)->sc_send_count)
 265 # define sc_recv_count(_s)              ((_s)->sc_recv_count)
 266 # define sc_tv_acquiry_total_ns(_s)     (ktime_to_ns((_s)->sc_tv_acquiry_total))
 267 # define sc_tv_send_total_ns(_s)        (ktime_to_ns((_s)->sc_tv_send_total))
 268 # define sc_tv_status_total_ns(_s)      (ktime_to_ns((_s)->sc_tv_status_total))
 269 # define sc_tv_process_total_ns(_s)     (ktime_to_ns((_s)->sc_tv_process_total))
 270 #else
 271 # define sc_send_count(_s)              (0U)
 272 # define sc_recv_count(_s)              (0U)
 273 # define sc_tv_acquiry_total_ns(_s)     (0LL)
 274 # define sc_tv_send_total_ns(_s)        (0LL)
 275 # define sc_tv_status_total_ns(_s)      (0LL)
 276 # define sc_tv_process_total_ns(_s)     (0LL)
 277 #endif
 278 
 279 /* So that debugfs.ocfs2 can determine which format is being used */
 280 #define O2NET_STATS_STR_VERSION         1
 281 static void sc_show_sock_stats(struct seq_file *seq,
 282                                struct o2net_sock_container *sc)
 283 {
 284         if (!sc)
 285                 return;
 286 
 287         seq_printf(seq, "%d,%u,%lu,%lld,%lld,%lld,%lu,%lld\n", O2NET_STATS_STR_VERSION,
 288                    sc->sc_node->nd_num, (unsigned long)sc_send_count(sc),
 289                    (long long)sc_tv_acquiry_total_ns(sc),
 290                    (long long)sc_tv_send_total_ns(sc),
 291                    (long long)sc_tv_status_total_ns(sc),
 292                    (unsigned long)sc_recv_count(sc),
 293                    (long long)sc_tv_process_total_ns(sc));
 294 }
 295 
 296 static void sc_show_sock_container(struct seq_file *seq,
 297                                    struct o2net_sock_container *sc)
 298 {
 299         struct inet_sock *inet = NULL;
 300         __be32 saddr = 0, daddr = 0;
 301         __be16 sport = 0, dport = 0;
 302 
 303         if (!sc)
 304                 return;
 305 
 306         if (sc->sc_sock) {
 307                 inet = inet_sk(sc->sc_sock->sk);
 308                 /* the stack's structs aren't sparse endian clean */
 309                 saddr = (__force __be32)inet->inet_saddr;
 310                 daddr = (__force __be32)inet->inet_daddr;
 311                 sport = (__force __be16)inet->inet_sport;
 312                 dport = (__force __be16)inet->inet_dport;
 313         }
 314 
 315         /* XXX sigh, inet-> doesn't have sparse annotation so any
 316          * use of it here generates a warning with -Wbitwise */
 317         seq_printf(seq, "%p:\n"
 318                    "  krefs:           %d\n"
 319                    "  sock:            %pI4:%u -> "
 320                                       "%pI4:%u\n"
 321                    "  remote node:     %s\n"
 322                    "  page off:        %zu\n"
 323                    "  handshake ok:    %u\n"
 324                    "  timer:           %lld usecs\n"
 325                    "  data ready:      %lld usecs\n"
 326                    "  advance start:   %lld usecs\n"
 327                    "  advance stop:    %lld usecs\n"
 328                    "  func start:      %lld usecs\n"
 329                    "  func stop:       %lld usecs\n"
 330                    "  func key:        0x%08x\n"
 331                    "  func type:       %u\n",
 332                    sc,
 333                    kref_read(&sc->sc_kref),
 334                    &saddr, inet ? ntohs(sport) : 0,
 335                    &daddr, inet ? ntohs(dport) : 0,
 336                    sc->sc_node->nd_name,
 337                    sc->sc_page_off,
 338                    sc->sc_handshake_ok,
 339                    (long long)ktime_to_us(sc->sc_tv_timer),
 340                    (long long)ktime_to_us(sc->sc_tv_data_ready),
 341                    (long long)ktime_to_us(sc->sc_tv_advance_start),
 342                    (long long)ktime_to_us(sc->sc_tv_advance_stop),
 343                    (long long)ktime_to_us(sc->sc_tv_func_start),
 344                    (long long)ktime_to_us(sc->sc_tv_func_stop),
 345                    sc->sc_msg_key,
 346                    sc->sc_msg_type);
 347 }
 348 
 349 static int sc_seq_show(struct seq_file *seq, void *v)
 350 {
 351         struct o2net_sock_debug *sd = seq->private;
 352         struct o2net_sock_container *sc, *dummy_sc = sd->dbg_sock;
 353 
 354         spin_lock(&o2net_debug_lock);
 355         sc = next_sc(dummy_sc);
 356 
 357         if (sc) {
 358                 if (sd->dbg_ctxt == SHOW_SOCK_CONTAINERS)
 359                         sc_show_sock_container(seq, sc);
 360                 else
 361                         sc_show_sock_stats(seq, sc);
 362         }
 363 
 364         spin_unlock(&o2net_debug_lock);
 365 
 366         return 0;
 367 }
 368 
 369 static void sc_seq_stop(struct seq_file *seq, void *v)
 370 {
 371 }
 372 
 373 static const struct seq_operations sc_seq_ops = {
 374         .start = sc_seq_start,
 375         .next = sc_seq_next,
 376         .stop = sc_seq_stop,
 377         .show = sc_seq_show,
 378 };
 379 
 380 static int sc_common_open(struct file *file, int ctxt)
 381 {
 382         struct o2net_sock_debug *sd;
 383         struct o2net_sock_container *dummy_sc;
 384 
 385         dummy_sc = kzalloc(sizeof(*dummy_sc), GFP_KERNEL);
 386         if (!dummy_sc)
 387                 return -ENOMEM;
 388 
 389         sd = __seq_open_private(file, &sc_seq_ops, sizeof(*sd));
 390         if (!sd) {
 391                 kfree(dummy_sc);
 392                 return -ENOMEM;
 393         }
 394 
 395         sd->dbg_ctxt = ctxt;
 396         sd->dbg_sock = dummy_sc;
 397 
 398         o2net_debug_add_sc(dummy_sc);
 399 
 400         return 0;
 401 }
 402 
 403 static int sc_fop_release(struct inode *inode, struct file *file)
 404 {
 405         struct seq_file *seq = file->private_data;
 406         struct o2net_sock_debug *sd = seq->private;
 407         struct o2net_sock_container *dummy_sc = sd->dbg_sock;
 408 
 409         o2net_debug_del_sc(dummy_sc);
 410         kfree(dummy_sc);
 411         return seq_release_private(inode, file);
 412 }
 413 
 414 static int stats_fop_open(struct inode *inode, struct file *file)
 415 {
 416         return sc_common_open(file, SHOW_SOCK_STATS);
 417 }
 418 
 419 static const struct file_operations stats_seq_fops = {
 420         .open = stats_fop_open,
 421         .read = seq_read,
 422         .llseek = seq_lseek,
 423         .release = sc_fop_release,
 424 };
 425 
 426 static int sc_fop_open(struct inode *inode, struct file *file)
 427 {
 428         return sc_common_open(file, SHOW_SOCK_CONTAINERS);
 429 }
 430 
 431 static const struct file_operations sc_seq_fops = {
 432         .open = sc_fop_open,
 433         .read = seq_read,
 434         .llseek = seq_lseek,
 435         .release = sc_fop_release,
 436 };
 437 
 438 static int o2net_fill_bitmap(char *buf, int len)
 439 {
 440         unsigned long map[BITS_TO_LONGS(O2NM_MAX_NODES)];
 441         int i = -1, out = 0;
 442 
 443         o2net_fill_node_map(map, sizeof(map));
 444 
 445         while ((i = find_next_bit(map, O2NM_MAX_NODES, i + 1)) < O2NM_MAX_NODES)
 446                 out += snprintf(buf + out, PAGE_SIZE - out, "%d ", i);
 447         out += snprintf(buf + out, PAGE_SIZE - out, "\n");
 448 
 449         return out;
 450 }
 451 
 452 static int nodes_fop_open(struct inode *inode, struct file *file)
 453 {
 454         char *buf;
 455 
 456         buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
 457         if (!buf)
 458                 return -ENOMEM;
 459 
 460         i_size_write(inode, o2net_fill_bitmap(buf, PAGE_SIZE));
 461 
 462         file->private_data = buf;
 463 
 464         return 0;
 465 }
 466 
 467 static int o2net_debug_release(struct inode *inode, struct file *file)
 468 {
 469         kfree(file->private_data);
 470         return 0;
 471 }
 472 
 473 static ssize_t o2net_debug_read(struct file *file, char __user *buf,
 474                                 size_t nbytes, loff_t *ppos)
 475 {
 476         return simple_read_from_buffer(buf, nbytes, ppos, file->private_data,
 477                                        i_size_read(file->f_mapping->host));
 478 }
 479 
 480 static const struct file_operations nodes_fops = {
 481         .open           = nodes_fop_open,
 482         .release        = o2net_debug_release,
 483         .read           = o2net_debug_read,
 484         .llseek         = generic_file_llseek,
 485 };
 486 
 487 void o2net_debugfs_exit(void)
 488 {
 489         debugfs_remove_recursive(o2net_dentry);
 490 }
 491 
 492 void o2net_debugfs_init(void)
 493 {
 494         umode_t mode = S_IFREG|S_IRUSR;
 495 
 496         o2net_dentry = debugfs_create_dir(O2NET_DEBUG_DIR, NULL);
 497 
 498         debugfs_create_file(NST_DEBUG_NAME, mode, o2net_dentry, NULL,
 499                             &nst_seq_fops);
 500         debugfs_create_file(SC_DEBUG_NAME, mode, o2net_dentry, NULL,
 501                             &sc_seq_fops);
 502         debugfs_create_file(STATS_DEBUG_NAME, mode, o2net_dentry, NULL,
 503                             &stats_seq_fops);
 504         debugfs_create_file(NODES_DEBUG_NAME, mode, o2net_dentry, NULL,
 505                             &nodes_fops);
 506 }
 507 
 508 #endif  /* CONFIG_DEBUG_FS */

/* [<][>][^][v][top][bottom][index][help] */