linux/fs/dlm/debug_fs.c
<<
>>
Prefs
   1/******************************************************************************
   2*******************************************************************************
   3**
   4**  Copyright (C) 2005-2009 Red Hat, Inc.  All rights reserved.
   5**
   6**  This copyrighted material is made available to anyone wishing to use,
   7**  modify, copy, or redistribute it subject to the terms and conditions
   8**  of the GNU General Public License v.2.
   9**
  10*******************************************************************************
  11******************************************************************************/
  12
  13#include <linux/pagemap.h>
  14#include <linux/seq_file.h>
  15#include <linux/init.h>
  16#include <linux/ctype.h>
  17#include <linux/debugfs.h>
  18#include <linux/slab.h>
  19
  20#include "dlm_internal.h"
  21#include "lock.h"
  22
  23#define DLM_DEBUG_BUF_LEN 4096
  24static char debug_buf[DLM_DEBUG_BUF_LEN];
  25static struct mutex debug_buf_lock;
  26
  27static struct dentry *dlm_root;
  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                        return NULL;
 548                }
 549                tree = toss ? &ls->ls_rsbtbl[bucket].toss : &ls->ls_rsbtbl[bucket].keep;
 550
 551                spin_lock(&ls->ls_rsbtbl[bucket].lock);
 552                if (!RB_EMPTY_ROOT(tree)) {
 553                        next = rb_first(tree);
 554                        r = rb_entry(next, struct dlm_rsb, res_hashnode);
 555                        dlm_hold_rsb(r);
 556                        ri->rsb = r;
 557                        ri->bucket = bucket;
 558                        spin_unlock(&ls->ls_rsbtbl[bucket].lock);
 559                        *pos = n;
 560                        return ri;
 561                }
 562                spin_unlock(&ls->ls_rsbtbl[bucket].lock);
 563        }
 564}
 565
 566static void table_seq_stop(struct seq_file *seq, void *iter_ptr)
 567{
 568        struct rsbtbl_iter *ri = iter_ptr;
 569
 570        if (ri) {
 571                dlm_put_rsb(ri->rsb);
 572                kfree(ri);
 573        }
 574}
 575
 576static const struct seq_operations format1_seq_ops = {
 577        .start = table_seq_start,
 578        .next  = table_seq_next,
 579        .stop  = table_seq_stop,
 580        .show  = table_seq_show,
 581};
 582
 583static const struct seq_operations format2_seq_ops = {
 584        .start = table_seq_start,
 585        .next  = table_seq_next,
 586        .stop  = table_seq_stop,
 587        .show  = table_seq_show,
 588};
 589
 590static const struct seq_operations format3_seq_ops = {
 591        .start = table_seq_start,
 592        .next  = table_seq_next,
 593        .stop  = table_seq_stop,
 594        .show  = table_seq_show,
 595};
 596
 597static const struct seq_operations format4_seq_ops = {
 598        .start = table_seq_start,
 599        .next  = table_seq_next,
 600        .stop  = table_seq_stop,
 601        .show  = table_seq_show,
 602};
 603
 604static const struct file_operations format1_fops;
 605static const struct file_operations format2_fops;
 606static const struct file_operations format3_fops;
 607static const struct file_operations format4_fops;
 608
 609static int table_open1(struct inode *inode, struct file *file)
 610{
 611        struct seq_file *seq;
 612        int ret;
 613
 614        ret = seq_open(file, &format1_seq_ops);
 615        if (ret)
 616                return ret;
 617
 618        seq = file->private_data;
 619        seq->private = inode->i_private; /* the dlm_ls */
 620        return 0;
 621}
 622
 623static int table_open2(struct inode *inode, struct file *file)
 624{
 625        struct seq_file *seq;
 626        int ret;
 627
 628        ret = seq_open(file, &format2_seq_ops);
 629        if (ret)
 630                return ret;
 631
 632        seq = file->private_data;
 633        seq->private = inode->i_private; /* the dlm_ls */
 634        return 0;
 635}
 636
 637static int table_open3(struct inode *inode, struct file *file)
 638{
 639        struct seq_file *seq;
 640        int ret;
 641
 642        ret = seq_open(file, &format3_seq_ops);
 643        if (ret)
 644                return ret;
 645
 646        seq = file->private_data;
 647        seq->private = inode->i_private; /* the dlm_ls */
 648        return 0;
 649}
 650
 651static int table_open4(struct inode *inode, struct file *file)
 652{
 653        struct seq_file *seq;
 654        int ret;
 655
 656        ret = seq_open(file, &format4_seq_ops);
 657        if (ret)
 658                return ret;
 659
 660        seq = file->private_data;
 661        seq->private = inode->i_private; /* the dlm_ls */
 662        return 0;
 663}
 664
 665static const struct file_operations format1_fops = {
 666        .owner   = THIS_MODULE,
 667        .open    = table_open1,
 668        .read    = seq_read,
 669        .llseek  = seq_lseek,
 670        .release = seq_release
 671};
 672
 673static const struct file_operations format2_fops = {
 674        .owner   = THIS_MODULE,
 675        .open    = table_open2,
 676        .read    = seq_read,
 677        .llseek  = seq_lseek,
 678        .release = seq_release
 679};
 680
 681static const struct file_operations format3_fops = {
 682        .owner   = THIS_MODULE,
 683        .open    = table_open3,
 684        .read    = seq_read,
 685        .llseek  = seq_lseek,
 686        .release = seq_release
 687};
 688
 689static const struct file_operations format4_fops = {
 690        .owner   = THIS_MODULE,
 691        .open    = table_open4,
 692        .read    = seq_read,
 693        .llseek  = seq_lseek,
 694        .release = seq_release
 695};
 696
 697/*
 698 * dump lkb's on the ls_waiters list
 699 */
 700static ssize_t waiters_read(struct file *file, char __user *userbuf,
 701                            size_t count, loff_t *ppos)
 702{
 703        struct dlm_ls *ls = file->private_data;
 704        struct dlm_lkb *lkb;
 705        size_t len = DLM_DEBUG_BUF_LEN, pos = 0, ret, rv;
 706
 707        mutex_lock(&debug_buf_lock);
 708        mutex_lock(&ls->ls_waiters_mutex);
 709        memset(debug_buf, 0, sizeof(debug_buf));
 710
 711        list_for_each_entry(lkb, &ls->ls_waiters, lkb_wait_reply) {
 712                ret = snprintf(debug_buf + pos, len - pos, "%x %d %d %s\n",
 713                               lkb->lkb_id, lkb->lkb_wait_type,
 714                               lkb->lkb_nodeid, lkb->lkb_resource->res_name);
 715                if (ret >= len - pos)
 716                        break;
 717                pos += ret;
 718        }
 719        mutex_unlock(&ls->ls_waiters_mutex);
 720
 721        rv = simple_read_from_buffer(userbuf, count, ppos, debug_buf, pos);
 722        mutex_unlock(&debug_buf_lock);
 723        return rv;
 724}
 725
 726static const struct file_operations waiters_fops = {
 727        .owner   = THIS_MODULE,
 728        .open    = simple_open,
 729        .read    = waiters_read,
 730        .llseek  = default_llseek,
 731};
 732
 733void dlm_delete_debug_file(struct dlm_ls *ls)
 734{
 735        debugfs_remove(ls->ls_debug_rsb_dentry);
 736        debugfs_remove(ls->ls_debug_waiters_dentry);
 737        debugfs_remove(ls->ls_debug_locks_dentry);
 738        debugfs_remove(ls->ls_debug_all_dentry);
 739        debugfs_remove(ls->ls_debug_toss_dentry);
 740}
 741
 742int dlm_create_debug_file(struct dlm_ls *ls)
 743{
 744        char name[DLM_LOCKSPACE_LEN + 8];
 745
 746        /* format 1 */
 747
 748        ls->ls_debug_rsb_dentry = debugfs_create_file(ls->ls_name,
 749                                                      S_IFREG | S_IRUGO,
 750                                                      dlm_root,
 751                                                      ls,
 752                                                      &format1_fops);
 753        if (!ls->ls_debug_rsb_dentry)
 754                goto fail;
 755
 756        /* format 2 */
 757
 758        memset(name, 0, sizeof(name));
 759        snprintf(name, DLM_LOCKSPACE_LEN + 8, "%s_locks", ls->ls_name);
 760
 761        ls->ls_debug_locks_dentry = debugfs_create_file(name,
 762                                                        S_IFREG | S_IRUGO,
 763                                                        dlm_root,
 764                                                        ls,
 765                                                        &format2_fops);
 766        if (!ls->ls_debug_locks_dentry)
 767                goto fail;
 768
 769        /* format 3 */
 770
 771        memset(name, 0, sizeof(name));
 772        snprintf(name, DLM_LOCKSPACE_LEN + 8, "%s_all", ls->ls_name);
 773
 774        ls->ls_debug_all_dentry = debugfs_create_file(name,
 775                                                      S_IFREG | S_IRUGO,
 776                                                      dlm_root,
 777                                                      ls,
 778                                                      &format3_fops);
 779        if (!ls->ls_debug_all_dentry)
 780                goto fail;
 781
 782        /* format 4 */
 783
 784        memset(name, 0, sizeof(name));
 785        snprintf(name, DLM_LOCKSPACE_LEN + 8, "%s_toss", ls->ls_name);
 786
 787        ls->ls_debug_toss_dentry = debugfs_create_file(name,
 788                                                       S_IFREG | S_IRUGO,
 789                                                       dlm_root,
 790                                                       ls,
 791                                                       &format4_fops);
 792        if (!ls->ls_debug_toss_dentry)
 793                goto fail;
 794
 795        memset(name, 0, sizeof(name));
 796        snprintf(name, DLM_LOCKSPACE_LEN + 8, "%s_waiters", ls->ls_name);
 797
 798        ls->ls_debug_waiters_dentry = debugfs_create_file(name,
 799                                                          S_IFREG | S_IRUGO,
 800                                                          dlm_root,
 801                                                          ls,
 802                                                          &waiters_fops);
 803        if (!ls->ls_debug_waiters_dentry)
 804                goto fail;
 805
 806        return 0;
 807
 808 fail:
 809        dlm_delete_debug_file(ls);
 810        return -ENOMEM;
 811}
 812
 813int __init dlm_register_debugfs(void)
 814{
 815        mutex_init(&debug_buf_lock);
 816        dlm_root = debugfs_create_dir("dlm", NULL);
 817        return dlm_root ? 0 : -ENOMEM;
 818}
 819
 820void dlm_unregister_debugfs(void)
 821{
 822        debugfs_remove(dlm_root);
 823}
 824
 825