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