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/module.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_puts(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_puts(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_puts(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_puts(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_puts(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_puts(s, "\n");
 365
 366        unlock_rsb(r);
 367}
 368
 369struct rsbtbl_iter {
 370        struct dlm_rsb *rsb;
 371        unsigned bucket;
 372        int format;
 373        int header;
 374};
 375
 376/*
 377 * If the buffer is full, seq_printf can be called again, but it
 378 * does nothing.  So, the these printing routines periodically check
 379 * seq_has_overflowed to avoid wasting too much time trying to print to
 380 * a full buffer.
 381 */
 382
 383static int table_seq_show(struct seq_file *seq, void *iter_ptr)
 384{
 385        struct rsbtbl_iter *ri = iter_ptr;
 386
 387        switch (ri->format) {
 388        case 1:
 389                print_format1(ri->rsb, seq);
 390                break;
 391        case 2:
 392                if (ri->header) {
 393                        seq_puts(seq, "id nodeid remid pid xid exflags flags sts grmode rqmode time_ms r_nodeid r_len r_name\n");
 394                        ri->header = 0;
 395                }
 396                print_format2(ri->rsb, seq);
 397                break;
 398        case 3:
 399                if (ri->header) {
 400                        seq_puts(seq, "version rsb 1.1 lvb 1.1 lkb 1.1\n");
 401                        ri->header = 0;
 402                }
 403                print_format3(ri->rsb, seq);
 404                break;
 405        case 4:
 406                if (ri->header) {
 407                        seq_puts(seq, "version 4 rsb 2\n");
 408                        ri->header = 0;
 409                }
 410                print_format4(ri->rsb, seq);
 411                break;
 412        }
 413
 414        return 0;
 415}
 416
 417static const struct seq_operations format1_seq_ops;
 418static const struct seq_operations format2_seq_ops;
 419static const struct seq_operations format3_seq_ops;
 420static const struct seq_operations format4_seq_ops;
 421
 422static void *table_seq_start(struct seq_file *seq, loff_t *pos)
 423{
 424        struct rb_root *tree;
 425        struct rb_node *node;
 426        struct dlm_ls *ls = seq->private;
 427        struct rsbtbl_iter *ri;
 428        struct dlm_rsb *r;
 429        loff_t n = *pos;
 430        unsigned bucket, entry;
 431        int toss = (seq->op == &format4_seq_ops);
 432
 433        bucket = n >> 32;
 434        entry = n & ((1LL << 32) - 1);
 435
 436        if (bucket >= ls->ls_rsbtbl_size)
 437                return NULL;
 438
 439        ri = kzalloc(sizeof(struct rsbtbl_iter), GFP_NOFS);
 440        if (!ri)
 441                return NULL;
 442        if (n == 0)
 443                ri->header = 1;
 444        if (seq->op == &format1_seq_ops)
 445                ri->format = 1;
 446        if (seq->op == &format2_seq_ops)
 447                ri->format = 2;
 448        if (seq->op == &format3_seq_ops)
 449                ri->format = 3;
 450        if (seq->op == &format4_seq_ops)
 451                ri->format = 4;
 452
 453        tree = toss ? &ls->ls_rsbtbl[bucket].toss : &ls->ls_rsbtbl[bucket].keep;
 454
 455        spin_lock(&ls->ls_rsbtbl[bucket].lock);
 456        if (!RB_EMPTY_ROOT(tree)) {
 457                for (node = rb_first(tree); node; node = rb_next(node)) {
 458                        r = rb_entry(node, struct dlm_rsb, res_hashnode);
 459                        if (!entry--) {
 460                                dlm_hold_rsb(r);
 461                                ri->rsb = r;
 462                                ri->bucket = bucket;
 463                                spin_unlock(&ls->ls_rsbtbl[bucket].lock);
 464                                return ri;
 465                        }
 466                }
 467        }
 468        spin_unlock(&ls->ls_rsbtbl[bucket].lock);
 469
 470        /*
 471         * move to the first rsb in the next non-empty bucket
 472         */
 473
 474        /* zero the entry */
 475        n &= ~((1LL << 32) - 1);
 476
 477        while (1) {
 478                bucket++;
 479                n += 1LL << 32;
 480
 481                if (bucket >= ls->ls_rsbtbl_size) {
 482                        kfree(ri);
 483                        return NULL;
 484                }
 485                tree = toss ? &ls->ls_rsbtbl[bucket].toss : &ls->ls_rsbtbl[bucket].keep;
 486
 487                spin_lock(&ls->ls_rsbtbl[bucket].lock);
 488                if (!RB_EMPTY_ROOT(tree)) {
 489                        node = rb_first(tree);
 490                        r = rb_entry(node, struct dlm_rsb, res_hashnode);
 491                        dlm_hold_rsb(r);
 492                        ri->rsb = r;
 493                        ri->bucket = bucket;
 494                        spin_unlock(&ls->ls_rsbtbl[bucket].lock);
 495                        *pos = n;
 496                        return ri;
 497                }
 498                spin_unlock(&ls->ls_rsbtbl[bucket].lock);
 499        }
 500}
 501
 502static void *table_seq_next(struct seq_file *seq, void *iter_ptr, loff_t *pos)
 503{
 504        struct dlm_ls *ls = seq->private;
 505        struct rsbtbl_iter *ri = iter_ptr;
 506        struct rb_root *tree;
 507        struct rb_node *next;
 508        struct dlm_rsb *r, *rp;
 509        loff_t n = *pos;
 510        unsigned bucket;
 511        int toss = (seq->op == &format4_seq_ops);
 512
 513        bucket = n >> 32;
 514
 515        /*
 516         * move to the next rsb in the same bucket
 517         */
 518
 519        spin_lock(&ls->ls_rsbtbl[bucket].lock);
 520        rp = ri->rsb;
 521        next = rb_next(&rp->res_hashnode);
 522
 523        if (next) {
 524                r = rb_entry(next, struct dlm_rsb, res_hashnode);
 525                dlm_hold_rsb(r);
 526                ri->rsb = r;
 527                spin_unlock(&ls->ls_rsbtbl[bucket].lock);
 528                dlm_put_rsb(rp);
 529                ++*pos;
 530                return ri;
 531        }
 532        spin_unlock(&ls->ls_rsbtbl[bucket].lock);
 533        dlm_put_rsb(rp);
 534
 535        /*
 536         * move to the first rsb in the next non-empty bucket
 537         */
 538
 539        /* zero the entry */
 540        n &= ~((1LL << 32) - 1);
 541
 542        while (1) {
 543                bucket++;
 544                n += 1LL << 32;
 545
 546                if (bucket >= ls->ls_rsbtbl_size) {
 547                        kfree(ri);
 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
 743int dlm_create_debug_file(struct dlm_ls *ls)
 744{
 745        char name[DLM_LOCKSPACE_LEN+8];
 746
 747        /* format 1 */
 748
 749        ls->ls_debug_rsb_dentry = debugfs_create_file(ls->ls_name,
 750                                                      S_IFREG | S_IRUGO,
 751                                                      dlm_root,
 752                                                      ls,
 753                                                      &format1_fops);
 754        if (!ls->ls_debug_rsb_dentry)
 755                goto fail;
 756
 757        /* format 2 */
 758
 759        memset(name, 0, sizeof(name));
 760        snprintf(name, DLM_LOCKSPACE_LEN+8, "%s_locks", ls->ls_name);
 761
 762        ls->ls_debug_locks_dentry = debugfs_create_file(name,
 763                                                        S_IFREG | S_IRUGO,
 764                                                        dlm_root,
 765                                                        ls,
 766                                                        &format2_fops);
 767        if (!ls->ls_debug_locks_dentry)
 768                goto fail;
 769
 770        /* format 3 */
 771
 772        memset(name, 0, sizeof(name));
 773        snprintf(name, DLM_LOCKSPACE_LEN+8, "%s_all", ls->ls_name);
 774
 775        ls->ls_debug_all_dentry = debugfs_create_file(name,
 776                                                      S_IFREG | S_IRUGO,
 777                                                      dlm_root,
 778                                                      ls,
 779                                                      &format3_fops);
 780        if (!ls->ls_debug_all_dentry)
 781                goto fail;
 782
 783        /* format 4 */
 784
 785        memset(name, 0, sizeof(name));
 786        snprintf(name, DLM_LOCKSPACE_LEN+8, "%s_toss", ls->ls_name);
 787
 788        ls->ls_debug_toss_dentry = debugfs_create_file(name,
 789                                                       S_IFREG | S_IRUGO,
 790                                                       dlm_root,
 791                                                       ls,
 792                                                       &format4_fops);
 793        if (!ls->ls_debug_toss_dentry)
 794                goto fail;
 795
 796        memset(name, 0, sizeof(name));
 797        snprintf(name, DLM_LOCKSPACE_LEN+8, "%s_waiters", ls->ls_name);
 798
 799        ls->ls_debug_waiters_dentry = debugfs_create_file(name,
 800                                                          S_IFREG | S_IRUGO,
 801                                                          dlm_root,
 802                                                          ls,
 803                                                          &waiters_fops);
 804        if (!ls->ls_debug_waiters_dentry)
 805                goto fail;
 806
 807        return 0;
 808
 809 fail:
 810        dlm_delete_debug_file(ls);
 811        return -ENOMEM;
 812}
 813
 814int __init dlm_register_debugfs(void)
 815{
 816        mutex_init(&debug_buf_lock);
 817        dlm_root = debugfs_create_dir("dlm", NULL);
 818        return dlm_root ? 0 : -ENOMEM;
 819}
 820
 821void dlm_unregister_debugfs(void)
 822{
 823        debugfs_remove(dlm_root);
 824}
 825
 826