linux/fs/dlm/debug_fs.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/******************************************************************************
   3*******************************************************************************
   4**
   5**  Copyright (C) 2005-2009 Red Hat, Inc.  All rights reserved.
   6**
   7**
   8*******************************************************************************
   9******************************************************************************/
  10
  11#include <linux/pagemap.h>
  12#include <linux/seq_file.h>
  13#include <linux/init.h>
  14#include <linux/ctype.h>
  15#include <linux/debugfs.h>
  16#include <linux/slab.h>
  17
  18#include "dlm_internal.h"
  19#include "midcomms.h"
  20#include "lock.h"
  21
  22#define DLM_DEBUG_BUF_LEN 4096
  23static char debug_buf[DLM_DEBUG_BUF_LEN];
  24static struct mutex debug_buf_lock;
  25
  26static struct dentry *dlm_root;
  27static struct dentry *dlm_comms;
  28
  29static char *print_lockmode(int mode)
  30{
  31        switch (mode) {
  32        case DLM_LOCK_IV:
  33                return "--";
  34        case DLM_LOCK_NL:
  35                return "NL";
  36        case DLM_LOCK_CR:
  37                return "CR";
  38        case DLM_LOCK_CW:
  39                return "CW";
  40        case DLM_LOCK_PR:
  41                return "PR";
  42        case DLM_LOCK_PW:
  43                return "PW";
  44        case DLM_LOCK_EX:
  45                return "EX";
  46        default:
  47                return "??";
  48        }
  49}
  50
  51static void print_format1_lock(struct seq_file *s, struct dlm_lkb *lkb,
  52                               struct dlm_rsb *res)
  53{
  54        seq_printf(s, "%08x %s", lkb->lkb_id, print_lockmode(lkb->lkb_grmode));
  55
  56        if (lkb->lkb_status == DLM_LKSTS_CONVERT ||
  57            lkb->lkb_status == DLM_LKSTS_WAITING)
  58                seq_printf(s, " (%s)", print_lockmode(lkb->lkb_rqmode));
  59
  60        if (lkb->lkb_nodeid) {
  61                if (lkb->lkb_nodeid != res->res_nodeid)
  62                        seq_printf(s, " Remote: %3d %08x", lkb->lkb_nodeid,
  63                                   lkb->lkb_remid);
  64                else
  65                        seq_printf(s, " Master:     %08x", lkb->lkb_remid);
  66        }
  67
  68        if (lkb->lkb_wait_type)
  69                seq_printf(s, " wait_type: %d", lkb->lkb_wait_type);
  70
  71        seq_putc(s, '\n');
  72}
  73
  74static void print_format1(struct dlm_rsb *res, struct seq_file *s)
  75{
  76        struct dlm_lkb *lkb;
  77        int i, lvblen = res->res_ls->ls_lvblen, recover_list, root_list;
  78
  79        lock_rsb(res);
  80
  81        seq_printf(s, "\nResource %p Name (len=%d) \"", res, res->res_length);
  82
  83        for (i = 0; i < res->res_length; i++) {
  84                if (isprint(res->res_name[i]))
  85                        seq_printf(s, "%c", res->res_name[i]);
  86                else
  87                        seq_printf(s, "%c", '.');
  88        }
  89
  90        if (res->res_nodeid > 0)
  91                seq_printf(s, "\"\nLocal Copy, Master is node %d\n",
  92                           res->res_nodeid);
  93        else if (res->res_nodeid == 0)
  94                seq_puts(s, "\"\nMaster Copy\n");
  95        else if (res->res_nodeid == -1)
  96                seq_printf(s, "\"\nLooking up master (lkid %x)\n",
  97                           res->res_first_lkid);
  98        else
  99                seq_printf(s, "\"\nInvalid master %d\n", res->res_nodeid);
 100        if (seq_has_overflowed(s))
 101                goto out;
 102
 103        /* Print the LVB: */
 104        if (res->res_lvbptr) {
 105                seq_puts(s, "LVB: ");
 106                for (i = 0; i < lvblen; i++) {
 107                        if (i == lvblen / 2)
 108                                seq_puts(s, "\n     ");
 109                        seq_printf(s, "%02x ",
 110                                   (unsigned char) res->res_lvbptr[i]);
 111                }
 112                if (rsb_flag(res, RSB_VALNOTVALID))
 113                        seq_puts(s, " (INVALID)");
 114                seq_putc(s, '\n');
 115                if (seq_has_overflowed(s))
 116                        goto out;
 117        }
 118
 119        root_list = !list_empty(&res->res_root_list);
 120        recover_list = !list_empty(&res->res_recover_list);
 121
 122        if (root_list || recover_list) {
 123                seq_printf(s, "Recovery: root %d recover %d flags %lx count %d\n",
 124                           root_list, recover_list,
 125                           res->res_flags, res->res_recover_locks_count);
 126        }
 127
 128        /* Print the locks attached to this resource */
 129        seq_puts(s, "Granted Queue\n");
 130        list_for_each_entry(lkb, &res->res_grantqueue, lkb_statequeue) {
 131                print_format1_lock(s, lkb, res);
 132                if (seq_has_overflowed(s))
 133                        goto out;
 134        }
 135
 136        seq_puts(s, "Conversion Queue\n");
 137        list_for_each_entry(lkb, &res->res_convertqueue, lkb_statequeue) {
 138                print_format1_lock(s, lkb, res);
 139                if (seq_has_overflowed(s))
 140                        goto out;
 141        }
 142
 143        seq_puts(s, "Waiting Queue\n");
 144        list_for_each_entry(lkb, &res->res_waitqueue, lkb_statequeue) {
 145                print_format1_lock(s, lkb, res);
 146                if (seq_has_overflowed(s))
 147                        goto out;
 148        }
 149
 150        if (list_empty(&res->res_lookup))
 151                goto out;
 152
 153        seq_puts(s, "Lookup Queue\n");
 154        list_for_each_entry(lkb, &res->res_lookup, lkb_rsb_lookup) {
 155                seq_printf(s, "%08x %s",
 156                           lkb->lkb_id, print_lockmode(lkb->lkb_rqmode));
 157                if (lkb->lkb_wait_type)
 158                        seq_printf(s, " wait_type: %d", lkb->lkb_wait_type);
 159                seq_putc(s, '\n');
 160                if (seq_has_overflowed(s))
 161                        goto out;
 162        }
 163 out:
 164        unlock_rsb(res);
 165}
 166
 167static void print_format2_lock(struct seq_file *s, struct dlm_lkb *lkb,
 168                               struct dlm_rsb *r)
 169{
 170        u64 xid = 0;
 171        u64 us;
 172
 173        if (lkb->lkb_flags & DLM_IFL_USER) {
 174                if (lkb->lkb_ua)
 175                        xid = lkb->lkb_ua->xid;
 176        }
 177
 178        /* microseconds since lkb was added to current queue */
 179        us = ktime_to_us(ktime_sub(ktime_get(), lkb->lkb_timestamp));
 180
 181        /* id nodeid remid pid xid exflags flags sts grmode rqmode time_us
 182           r_nodeid r_len r_name */
 183
 184        seq_printf(s, "%x %d %x %u %llu %x %x %d %d %d %llu %u %d \"%s\"\n",
 185                   lkb->lkb_id,
 186                   lkb->lkb_nodeid,
 187                   lkb->lkb_remid,
 188                   lkb->lkb_ownpid,
 189                   (unsigned long long)xid,
 190                   lkb->lkb_exflags,
 191                   lkb->lkb_flags,
 192                   lkb->lkb_status,
 193                   lkb->lkb_grmode,
 194                   lkb->lkb_rqmode,
 195                   (unsigned long long)us,
 196                   r->res_nodeid,
 197                   r->res_length,
 198                   r->res_name);
 199}
 200
 201static void print_format2(struct dlm_rsb *r, struct seq_file *s)
 202{
 203        struct dlm_lkb *lkb;
 204
 205        lock_rsb(r);
 206
 207        list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue) {
 208                print_format2_lock(s, lkb, r);
 209                if (seq_has_overflowed(s))
 210                        goto out;
 211        }
 212
 213        list_for_each_entry(lkb, &r->res_convertqueue, lkb_statequeue) {
 214                print_format2_lock(s, lkb, r);
 215                if (seq_has_overflowed(s))
 216                        goto out;
 217        }
 218
 219        list_for_each_entry(lkb, &r->res_waitqueue, lkb_statequeue) {
 220                print_format2_lock(s, lkb, r);
 221                if (seq_has_overflowed(s))
 222                        goto out;
 223        }
 224 out:
 225        unlock_rsb(r);
 226}
 227
 228static void print_format3_lock(struct seq_file *s, struct dlm_lkb *lkb,
 229                              int rsb_lookup)
 230{
 231        u64 xid = 0;
 232
 233        if (lkb->lkb_flags & DLM_IFL_USER) {
 234                if (lkb->lkb_ua)
 235                        xid = lkb->lkb_ua->xid;
 236        }
 237
 238        seq_printf(s, "lkb %x %d %x %u %llu %x %x %d %d %d %d %d %d %u %llu %llu\n",
 239                   lkb->lkb_id,
 240                   lkb->lkb_nodeid,
 241                   lkb->lkb_remid,
 242                   lkb->lkb_ownpid,
 243                   (unsigned long long)xid,
 244                   lkb->lkb_exflags,
 245                   lkb->lkb_flags,
 246                   lkb->lkb_status,
 247                   lkb->lkb_grmode,
 248                   lkb->lkb_rqmode,
 249                   lkb->lkb_last_bast.mode,
 250                   rsb_lookup,
 251                   lkb->lkb_wait_type,
 252                   lkb->lkb_lvbseq,
 253                   (unsigned long long)ktime_to_ns(lkb->lkb_timestamp),
 254                   (unsigned long long)ktime_to_ns(lkb->lkb_last_bast_time));
 255}
 256
 257static void print_format3(struct dlm_rsb *r, struct seq_file *s)
 258{
 259        struct dlm_lkb *lkb;
 260        int i, lvblen = r->res_ls->ls_lvblen;
 261        int print_name = 1;
 262
 263        lock_rsb(r);
 264
 265        seq_printf(s, "rsb %p %d %x %lx %d %d %u %d ",
 266                   r,
 267                   r->res_nodeid,
 268                   r->res_first_lkid,
 269                   r->res_flags,
 270                   !list_empty(&r->res_root_list),
 271                   !list_empty(&r->res_recover_list),
 272                   r->res_recover_locks_count,
 273                   r->res_length);
 274        if (seq_has_overflowed(s))
 275                goto out;
 276
 277        for (i = 0; i < r->res_length; i++) {
 278                if (!isascii(r->res_name[i]) || !isprint(r->res_name[i]))
 279                        print_name = 0;
 280        }
 281
 282        seq_puts(s, print_name ? "str " : "hex");
 283
 284        for (i = 0; i < r->res_length; i++) {
 285                if (print_name)
 286                        seq_printf(s, "%c", r->res_name[i]);
 287                else
 288                        seq_printf(s, " %02x", (unsigned char)r->res_name[i]);
 289        }
 290        seq_putc(s, '\n');
 291        if (seq_has_overflowed(s))
 292                goto out;
 293
 294        if (!r->res_lvbptr)
 295                goto do_locks;
 296
 297        seq_printf(s, "lvb %u %d", r->res_lvbseq, lvblen);
 298
 299        for (i = 0; i < lvblen; i++)
 300                seq_printf(s, " %02x", (unsigned char)r->res_lvbptr[i]);
 301        seq_putc(s, '\n');
 302        if (seq_has_overflowed(s))
 303                goto out;
 304
 305 do_locks:
 306        list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue) {
 307                print_format3_lock(s, lkb, 0);
 308                if (seq_has_overflowed(s))
 309                        goto out;
 310        }
 311
 312        list_for_each_entry(lkb, &r->res_convertqueue, lkb_statequeue) {
 313                print_format3_lock(s, lkb, 0);
 314                if (seq_has_overflowed(s))
 315                        goto out;
 316        }
 317
 318        list_for_each_entry(lkb, &r->res_waitqueue, lkb_statequeue) {
 319                print_format3_lock(s, lkb, 0);
 320                if (seq_has_overflowed(s))
 321                        goto out;
 322        }
 323
 324        list_for_each_entry(lkb, &r->res_lookup, lkb_rsb_lookup) {
 325                print_format3_lock(s, lkb, 1);
 326                if (seq_has_overflowed(s))
 327                        goto out;
 328        }
 329 out:
 330        unlock_rsb(r);
 331}
 332
 333static void print_format4(struct dlm_rsb *r, struct seq_file *s)
 334{
 335        int our_nodeid = dlm_our_nodeid();
 336        int print_name = 1;
 337        int i;
 338
 339        lock_rsb(r);
 340
 341        seq_printf(s, "rsb %p %d %d %d %d %lu %lx %d ",
 342                   r,
 343                   r->res_nodeid,
 344                   r->res_master_nodeid,
 345                   r->res_dir_nodeid,
 346                   our_nodeid,
 347                   r->res_toss_time,
 348                   r->res_flags,
 349                   r->res_length);
 350
 351        for (i = 0; i < r->res_length; i++) {
 352                if (!isascii(r->res_name[i]) || !isprint(r->res_name[i]))
 353                        print_name = 0;
 354        }
 355
 356        seq_puts(s, print_name ? "str " : "hex");
 357
 358        for (i = 0; i < r->res_length; i++) {
 359                if (print_name)
 360                        seq_printf(s, "%c", r->res_name[i]);
 361                else
 362                        seq_printf(s, " %02x", (unsigned char)r->res_name[i]);
 363        }
 364        seq_putc(s, '\n');
 365        unlock_rsb(r);
 366}
 367
 368struct rsbtbl_iter {
 369        struct dlm_rsb *rsb;
 370        unsigned bucket;
 371        int format;
 372        int header;
 373};
 374
 375/*
 376 * If the buffer is full, seq_printf can be called again, but it
 377 * does nothing.  So, the these printing routines periodically check
 378 * seq_has_overflowed to avoid wasting too much time trying to print to
 379 * a full buffer.
 380 */
 381
 382static int table_seq_show(struct seq_file *seq, void *iter_ptr)
 383{
 384        struct rsbtbl_iter *ri = iter_ptr;
 385
 386        switch (ri->format) {
 387        case 1:
 388                print_format1(ri->rsb, seq);
 389                break;
 390        case 2:
 391                if (ri->header) {
 392                        seq_puts(seq, "id nodeid remid pid xid exflags flags sts grmode rqmode time_ms r_nodeid r_len r_name\n");
 393                        ri->header = 0;
 394                }
 395                print_format2(ri->rsb, seq);
 396                break;
 397        case 3:
 398                if (ri->header) {
 399                        seq_puts(seq, "version rsb 1.1 lvb 1.1 lkb 1.1\n");
 400                        ri->header = 0;
 401                }
 402                print_format3(ri->rsb, seq);
 403                break;
 404        case 4:
 405                if (ri->header) {
 406                        seq_puts(seq, "version 4 rsb 2\n");
 407                        ri->header = 0;
 408                }
 409                print_format4(ri->rsb, seq);
 410                break;
 411        }
 412
 413        return 0;
 414}
 415
 416static const struct seq_operations format1_seq_ops;
 417static const struct seq_operations format2_seq_ops;
 418static const struct seq_operations format3_seq_ops;
 419static const struct seq_operations format4_seq_ops;
 420
 421static void *table_seq_start(struct seq_file *seq, loff_t *pos)
 422{
 423        struct rb_root *tree;
 424        struct rb_node *node;
 425        struct dlm_ls *ls = seq->private;
 426        struct rsbtbl_iter *ri;
 427        struct dlm_rsb *r;
 428        loff_t n = *pos;
 429        unsigned bucket, entry;
 430        int toss = (seq->op == &format4_seq_ops);
 431
 432        bucket = n >> 32;
 433        entry = n & ((1LL << 32) - 1);
 434
 435        if (bucket >= ls->ls_rsbtbl_size)
 436                return NULL;
 437
 438        ri = kzalloc(sizeof(*ri), GFP_NOFS);
 439        if (!ri)
 440                return NULL;
 441        if (n == 0)
 442                ri->header = 1;
 443        if (seq->op == &format1_seq_ops)
 444                ri->format = 1;
 445        if (seq->op == &format2_seq_ops)
 446                ri->format = 2;
 447        if (seq->op == &format3_seq_ops)
 448                ri->format = 3;
 449        if (seq->op == &format4_seq_ops)
 450                ri->format = 4;
 451
 452        tree = toss ? &ls->ls_rsbtbl[bucket].toss : &ls->ls_rsbtbl[bucket].keep;
 453
 454        spin_lock(&ls->ls_rsbtbl[bucket].lock);
 455        if (!RB_EMPTY_ROOT(tree)) {
 456                for (node = rb_first(tree); node; node = rb_next(node)) {
 457                        r = rb_entry(node, struct dlm_rsb, res_hashnode);
 458                        if (!entry--) {
 459                                dlm_hold_rsb(r);
 460                                ri->rsb = r;
 461                                ri->bucket = bucket;
 462                                spin_unlock(&ls->ls_rsbtbl[bucket].lock);
 463                                return ri;
 464                        }
 465                }
 466        }
 467        spin_unlock(&ls->ls_rsbtbl[bucket].lock);
 468
 469        /*
 470         * move to the first rsb in the next non-empty bucket
 471         */
 472
 473        /* zero the entry */
 474        n &= ~((1LL << 32) - 1);
 475
 476        while (1) {
 477                bucket++;
 478                n += 1LL << 32;
 479
 480                if (bucket >= ls->ls_rsbtbl_size) {
 481                        kfree(ri);
 482                        return NULL;
 483                }
 484                tree = toss ? &ls->ls_rsbtbl[bucket].toss : &ls->ls_rsbtbl[bucket].keep;
 485
 486                spin_lock(&ls->ls_rsbtbl[bucket].lock);
 487                if (!RB_EMPTY_ROOT(tree)) {
 488                        node = rb_first(tree);
 489                        r = rb_entry(node, struct dlm_rsb, res_hashnode);
 490                        dlm_hold_rsb(r);
 491                        ri->rsb = r;
 492                        ri->bucket = bucket;
 493                        spin_unlock(&ls->ls_rsbtbl[bucket].lock);
 494                        *pos = n;
 495                        return ri;
 496                }
 497                spin_unlock(&ls->ls_rsbtbl[bucket].lock);
 498        }
 499}
 500
 501static void *table_seq_next(struct seq_file *seq, void *iter_ptr, loff_t *pos)
 502{
 503        struct dlm_ls *ls = seq->private;
 504        struct rsbtbl_iter *ri = iter_ptr;
 505        struct rb_root *tree;
 506        struct rb_node *next;
 507        struct dlm_rsb *r, *rp;
 508        loff_t n = *pos;
 509        unsigned bucket;
 510        int toss = (seq->op == &format4_seq_ops);
 511
 512        bucket = n >> 32;
 513
 514        /*
 515         * move to the next rsb in the same bucket
 516         */
 517
 518        spin_lock(&ls->ls_rsbtbl[bucket].lock);
 519        rp = ri->rsb;
 520        next = rb_next(&rp->res_hashnode);
 521
 522        if (next) {
 523                r = rb_entry(next, struct dlm_rsb, res_hashnode);
 524                dlm_hold_rsb(r);
 525                ri->rsb = r;
 526                spin_unlock(&ls->ls_rsbtbl[bucket].lock);
 527                dlm_put_rsb(rp);
 528                ++*pos;
 529                return ri;
 530        }
 531        spin_unlock(&ls->ls_rsbtbl[bucket].lock);
 532        dlm_put_rsb(rp);
 533
 534        /*
 535         * move to the first rsb in the next non-empty bucket
 536         */
 537
 538        /* zero the entry */
 539        n &= ~((1LL << 32) - 1);
 540
 541        while (1) {
 542                bucket++;
 543                n += 1LL << 32;
 544
 545                if (bucket >= ls->ls_rsbtbl_size) {
 546                        kfree(ri);
 547                        ++*pos;
 548                        return NULL;
 549                }
 550                tree = toss ? &ls->ls_rsbtbl[bucket].toss : &ls->ls_rsbtbl[bucket].keep;
 551
 552                spin_lock(&ls->ls_rsbtbl[bucket].lock);
 553                if (!RB_EMPTY_ROOT(tree)) {
 554                        next = rb_first(tree);
 555                        r = rb_entry(next, struct dlm_rsb, res_hashnode);
 556                        dlm_hold_rsb(r);
 557                        ri->rsb = r;
 558                        ri->bucket = bucket;
 559                        spin_unlock(&ls->ls_rsbtbl[bucket].lock);
 560                        *pos = n;
 561                        return ri;
 562                }
 563                spin_unlock(&ls->ls_rsbtbl[bucket].lock);
 564        }
 565}
 566
 567static void table_seq_stop(struct seq_file *seq, void *iter_ptr)
 568{
 569        struct rsbtbl_iter *ri = iter_ptr;
 570
 571        if (ri) {
 572                dlm_put_rsb(ri->rsb);
 573                kfree(ri);
 574        }
 575}
 576
 577static const struct seq_operations format1_seq_ops = {
 578        .start = table_seq_start,
 579        .next  = table_seq_next,
 580        .stop  = table_seq_stop,
 581        .show  = table_seq_show,
 582};
 583
 584static const struct seq_operations format2_seq_ops = {
 585        .start = table_seq_start,
 586        .next  = table_seq_next,
 587        .stop  = table_seq_stop,
 588        .show  = table_seq_show,
 589};
 590
 591static const struct seq_operations format3_seq_ops = {
 592        .start = table_seq_start,
 593        .next  = table_seq_next,
 594        .stop  = table_seq_stop,
 595        .show  = table_seq_show,
 596};
 597
 598static const struct seq_operations format4_seq_ops = {
 599        .start = table_seq_start,
 600        .next  = table_seq_next,
 601        .stop  = table_seq_stop,
 602        .show  = table_seq_show,
 603};
 604
 605static const struct file_operations format1_fops;
 606static const struct file_operations format2_fops;
 607static const struct file_operations format3_fops;
 608static const struct file_operations format4_fops;
 609
 610static int table_open1(struct inode *inode, struct file *file)
 611{
 612        struct seq_file *seq;
 613        int ret;
 614
 615        ret = seq_open(file, &format1_seq_ops);
 616        if (ret)
 617                return ret;
 618
 619        seq = file->private_data;
 620        seq->private = inode->i_private; /* the dlm_ls */
 621        return 0;
 622}
 623
 624static int table_open2(struct inode *inode, struct file *file)
 625{
 626        struct seq_file *seq;
 627        int ret;
 628
 629        ret = seq_open(file, &format2_seq_ops);
 630        if (ret)
 631                return ret;
 632
 633        seq = file->private_data;
 634        seq->private = inode->i_private; /* the dlm_ls */
 635        return 0;
 636}
 637
 638static int table_open3(struct inode *inode, struct file *file)
 639{
 640        struct seq_file *seq;
 641        int ret;
 642
 643        ret = seq_open(file, &format3_seq_ops);
 644        if (ret)
 645                return ret;
 646
 647        seq = file->private_data;
 648        seq->private = inode->i_private; /* the dlm_ls */
 649        return 0;
 650}
 651
 652static int table_open4(struct inode *inode, struct file *file)
 653{
 654        struct seq_file *seq;
 655        int ret;
 656
 657        ret = seq_open(file, &format4_seq_ops);
 658        if (ret)
 659                return ret;
 660
 661        seq = file->private_data;
 662        seq->private = inode->i_private; /* the dlm_ls */
 663        return 0;
 664}
 665
 666static const struct file_operations format1_fops = {
 667        .owner   = THIS_MODULE,
 668        .open    = table_open1,
 669        .read    = seq_read,
 670        .llseek  = seq_lseek,
 671        .release = seq_release
 672};
 673
 674static const struct file_operations format2_fops = {
 675        .owner   = THIS_MODULE,
 676        .open    = table_open2,
 677        .read    = seq_read,
 678        .llseek  = seq_lseek,
 679        .release = seq_release
 680};
 681
 682static const struct file_operations format3_fops = {
 683        .owner   = THIS_MODULE,
 684        .open    = table_open3,
 685        .read    = seq_read,
 686        .llseek  = seq_lseek,
 687        .release = seq_release
 688};
 689
 690static const struct file_operations format4_fops = {
 691        .owner   = THIS_MODULE,
 692        .open    = table_open4,
 693        .read    = seq_read,
 694        .llseek  = seq_lseek,
 695        .release = seq_release
 696};
 697
 698/*
 699 * dump lkb's on the ls_waiters list
 700 */
 701static ssize_t waiters_read(struct file *file, char __user *userbuf,
 702                            size_t count, loff_t *ppos)
 703{
 704        struct dlm_ls *ls = file->private_data;
 705        struct dlm_lkb *lkb;
 706        size_t len = DLM_DEBUG_BUF_LEN, pos = 0, ret, rv;
 707
 708        mutex_lock(&debug_buf_lock);
 709        mutex_lock(&ls->ls_waiters_mutex);
 710        memset(debug_buf, 0, sizeof(debug_buf));
 711
 712        list_for_each_entry(lkb, &ls->ls_waiters, lkb_wait_reply) {
 713                ret = snprintf(debug_buf + pos, len - pos, "%x %d %d %s\n",
 714                               lkb->lkb_id, lkb->lkb_wait_type,
 715                               lkb->lkb_nodeid, lkb->lkb_resource->res_name);
 716                if (ret >= len - pos)
 717                        break;
 718                pos += ret;
 719        }
 720        mutex_unlock(&ls->ls_waiters_mutex);
 721
 722        rv = simple_read_from_buffer(userbuf, count, ppos, debug_buf, pos);
 723        mutex_unlock(&debug_buf_lock);
 724        return rv;
 725}
 726
 727static const struct file_operations waiters_fops = {
 728        .owner   = THIS_MODULE,
 729        .open    = simple_open,
 730        .read    = waiters_read,
 731        .llseek  = default_llseek,
 732};
 733
 734void dlm_delete_debug_file(struct dlm_ls *ls)
 735{
 736        debugfs_remove(ls->ls_debug_rsb_dentry);
 737        debugfs_remove(ls->ls_debug_waiters_dentry);
 738        debugfs_remove(ls->ls_debug_locks_dentry);
 739        debugfs_remove(ls->ls_debug_all_dentry);
 740        debugfs_remove(ls->ls_debug_toss_dentry);
 741}
 742
 743static int dlm_state_show(struct seq_file *file, void *offset)
 744{
 745        seq_printf(file, "%s\n", dlm_midcomms_state(file->private));
 746        return 0;
 747}
 748DEFINE_SHOW_ATTRIBUTE(dlm_state);
 749
 750static int dlm_flags_show(struct seq_file *file, void *offset)
 751{
 752        seq_printf(file, "%lu\n", dlm_midcomms_flags(file->private));
 753        return 0;
 754}
 755DEFINE_SHOW_ATTRIBUTE(dlm_flags);
 756
 757static int dlm_send_queue_cnt_show(struct seq_file *file, void *offset)
 758{
 759        seq_printf(file, "%d\n", dlm_midcomms_send_queue_cnt(file->private));
 760        return 0;
 761}
 762DEFINE_SHOW_ATTRIBUTE(dlm_send_queue_cnt);
 763
 764static int dlm_version_show(struct seq_file *file, void *offset)
 765{
 766        seq_printf(file, "0x%08x\n", dlm_midcomms_version(file->private));
 767        return 0;
 768}
 769DEFINE_SHOW_ATTRIBUTE(dlm_version);
 770
 771void *dlm_create_debug_comms_file(int nodeid, void *data)
 772{
 773        struct dentry *d_node;
 774        char name[256];
 775
 776        memset(name, 0, sizeof(name));
 777        snprintf(name, 256, "%d", nodeid);
 778
 779        d_node = debugfs_create_dir(name, dlm_comms);
 780        debugfs_create_file("state", 0444, d_node, data, &dlm_state_fops);
 781        debugfs_create_file("flags", 0444, d_node, data, &dlm_flags_fops);
 782        debugfs_create_file("send_queue_count", 0444, d_node, data,
 783                            &dlm_send_queue_cnt_fops);
 784        debugfs_create_file("version", 0444, d_node, data, &dlm_version_fops);
 785
 786        return d_node;
 787}
 788
 789void dlm_delete_debug_comms_file(void *ctx)
 790{
 791        debugfs_remove(ctx);
 792}
 793
 794void dlm_create_debug_file(struct dlm_ls *ls)
 795{
 796        char name[DLM_LOCKSPACE_LEN + 8];
 797
 798        /* format 1 */
 799
 800        ls->ls_debug_rsb_dentry = debugfs_create_file(ls->ls_name,
 801                                                      S_IFREG | S_IRUGO,
 802                                                      dlm_root,
 803                                                      ls,
 804                                                      &format1_fops);
 805
 806        /* format 2 */
 807
 808        memset(name, 0, sizeof(name));
 809        snprintf(name, DLM_LOCKSPACE_LEN + 8, "%s_locks", ls->ls_name);
 810
 811        ls->ls_debug_locks_dentry = debugfs_create_file(name,
 812                                                        S_IFREG | S_IRUGO,
 813                                                        dlm_root,
 814                                                        ls,
 815                                                        &format2_fops);
 816
 817        /* format 3 */
 818
 819        memset(name, 0, sizeof(name));
 820        snprintf(name, DLM_LOCKSPACE_LEN + 8, "%s_all", ls->ls_name);
 821
 822        ls->ls_debug_all_dentry = debugfs_create_file(name,
 823                                                      S_IFREG | S_IRUGO,
 824                                                      dlm_root,
 825                                                      ls,
 826                                                      &format3_fops);
 827
 828        /* format 4 */
 829
 830        memset(name, 0, sizeof(name));
 831        snprintf(name, DLM_LOCKSPACE_LEN + 8, "%s_toss", ls->ls_name);
 832
 833        ls->ls_debug_toss_dentry = debugfs_create_file(name,
 834                                                       S_IFREG | S_IRUGO,
 835                                                       dlm_root,
 836                                                       ls,
 837                                                       &format4_fops);
 838
 839        memset(name, 0, sizeof(name));
 840        snprintf(name, DLM_LOCKSPACE_LEN + 8, "%s_waiters", ls->ls_name);
 841
 842        ls->ls_debug_waiters_dentry = debugfs_create_file(name,
 843                                                          S_IFREG | S_IRUGO,
 844                                                          dlm_root,
 845                                                          ls,
 846                                                          &waiters_fops);
 847}
 848
 849void __init dlm_register_debugfs(void)
 850{
 851        mutex_init(&debug_buf_lock);
 852        dlm_root = debugfs_create_dir("dlm", NULL);
 853        dlm_comms = debugfs_create_dir("comms", dlm_root);
 854}
 855
 856void dlm_unregister_debugfs(void)
 857{
 858        debugfs_remove(dlm_root);
 859}
 860
 861