Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /******************************************************************************
0003 *******************************************************************************
0004 **
0005 **  Copyright (C) 2005-2009 Red Hat, Inc.  All rights reserved.
0006 **
0007 **
0008 *******************************************************************************
0009 ******************************************************************************/
0010 
0011 #include <linux/pagemap.h>
0012 #include <linux/seq_file.h>
0013 #include <linux/init.h>
0014 #include <linux/ctype.h>
0015 #include <linux/debugfs.h>
0016 #include <linux/slab.h>
0017 
0018 #include "dlm_internal.h"
0019 #include "midcomms.h"
0020 #include "lock.h"
0021 
0022 #define DLM_DEBUG_BUF_LEN 4096
0023 static char debug_buf[DLM_DEBUG_BUF_LEN];
0024 static struct mutex debug_buf_lock;
0025 
0026 static struct dentry *dlm_root;
0027 static struct dentry *dlm_comms;
0028 
0029 static char *print_lockmode(int mode)
0030 {
0031     switch (mode) {
0032     case DLM_LOCK_IV:
0033         return "--";
0034     case DLM_LOCK_NL:
0035         return "NL";
0036     case DLM_LOCK_CR:
0037         return "CR";
0038     case DLM_LOCK_CW:
0039         return "CW";
0040     case DLM_LOCK_PR:
0041         return "PR";
0042     case DLM_LOCK_PW:
0043         return "PW";
0044     case DLM_LOCK_EX:
0045         return "EX";
0046     default:
0047         return "??";
0048     }
0049 }
0050 
0051 static void print_format1_lock(struct seq_file *s, struct dlm_lkb *lkb,
0052                    struct dlm_rsb *res)
0053 {
0054     seq_printf(s, "%08x %s", lkb->lkb_id, print_lockmode(lkb->lkb_grmode));
0055 
0056     if (lkb->lkb_status == DLM_LKSTS_CONVERT ||
0057         lkb->lkb_status == DLM_LKSTS_WAITING)
0058         seq_printf(s, " (%s)", print_lockmode(lkb->lkb_rqmode));
0059 
0060     if (lkb->lkb_nodeid) {
0061         if (lkb->lkb_nodeid != res->res_nodeid)
0062             seq_printf(s, " Remote: %3d %08x", lkb->lkb_nodeid,
0063                    lkb->lkb_remid);
0064         else
0065             seq_printf(s, " Master:     %08x", lkb->lkb_remid);
0066     }
0067 
0068     if (lkb->lkb_wait_type)
0069         seq_printf(s, " wait_type: %d", lkb->lkb_wait_type);
0070 
0071     seq_putc(s, '\n');
0072 }
0073 
0074 static void print_format1(struct dlm_rsb *res, struct seq_file *s)
0075 {
0076     struct dlm_lkb *lkb;
0077     int i, lvblen = res->res_ls->ls_lvblen, recover_list, root_list;
0078 
0079     lock_rsb(res);
0080 
0081     seq_printf(s, "\nResource %p Name (len=%d) \"", res, res->res_length);
0082 
0083     for (i = 0; i < res->res_length; i++) {
0084         if (isprint(res->res_name[i]))
0085             seq_printf(s, "%c", res->res_name[i]);
0086         else
0087             seq_printf(s, "%c", '.');
0088     }
0089 
0090     if (res->res_nodeid > 0)
0091         seq_printf(s, "\"\nLocal Copy, Master is node %d\n",
0092                res->res_nodeid);
0093     else if (res->res_nodeid == 0)
0094         seq_puts(s, "\"\nMaster Copy\n");
0095     else if (res->res_nodeid == -1)
0096         seq_printf(s, "\"\nLooking up master (lkid %x)\n",
0097                res->res_first_lkid);
0098     else
0099         seq_printf(s, "\"\nInvalid master %d\n", res->res_nodeid);
0100     if (seq_has_overflowed(s))
0101         goto out;
0102 
0103     /* Print the LVB: */
0104     if (res->res_lvbptr) {
0105         seq_puts(s, "LVB: ");
0106         for (i = 0; i < lvblen; i++) {
0107             if (i == lvblen / 2)
0108                 seq_puts(s, "\n     ");
0109             seq_printf(s, "%02x ",
0110                    (unsigned char) res->res_lvbptr[i]);
0111         }
0112         if (rsb_flag(res, RSB_VALNOTVALID))
0113             seq_puts(s, " (INVALID)");
0114         seq_putc(s, '\n');
0115         if (seq_has_overflowed(s))
0116             goto out;
0117     }
0118 
0119     root_list = !list_empty(&res->res_root_list);
0120     recover_list = !list_empty(&res->res_recover_list);
0121 
0122     if (root_list || recover_list) {
0123         seq_printf(s, "Recovery: root %d recover %d flags %lx count %d\n",
0124                root_list, recover_list,
0125                res->res_flags, res->res_recover_locks_count);
0126     }
0127 
0128     /* Print the locks attached to this resource */
0129     seq_puts(s, "Granted Queue\n");
0130     list_for_each_entry(lkb, &res->res_grantqueue, lkb_statequeue) {
0131         print_format1_lock(s, lkb, res);
0132         if (seq_has_overflowed(s))
0133             goto out;
0134     }
0135 
0136     seq_puts(s, "Conversion Queue\n");
0137     list_for_each_entry(lkb, &res->res_convertqueue, lkb_statequeue) {
0138         print_format1_lock(s, lkb, res);
0139         if (seq_has_overflowed(s))
0140             goto out;
0141     }
0142 
0143     seq_puts(s, "Waiting Queue\n");
0144     list_for_each_entry(lkb, &res->res_waitqueue, lkb_statequeue) {
0145         print_format1_lock(s, lkb, res);
0146         if (seq_has_overflowed(s))
0147             goto out;
0148     }
0149 
0150     if (list_empty(&res->res_lookup))
0151         goto out;
0152 
0153     seq_puts(s, "Lookup Queue\n");
0154     list_for_each_entry(lkb, &res->res_lookup, lkb_rsb_lookup) {
0155         seq_printf(s, "%08x %s",
0156                lkb->lkb_id, print_lockmode(lkb->lkb_rqmode));
0157         if (lkb->lkb_wait_type)
0158             seq_printf(s, " wait_type: %d", lkb->lkb_wait_type);
0159         seq_putc(s, '\n');
0160         if (seq_has_overflowed(s))
0161             goto out;
0162     }
0163  out:
0164     unlock_rsb(res);
0165 }
0166 
0167 static void print_format2_lock(struct seq_file *s, struct dlm_lkb *lkb,
0168                    struct dlm_rsb *r)
0169 {
0170     u64 xid = 0;
0171     u64 us;
0172 
0173     if (lkb->lkb_flags & DLM_IFL_USER) {
0174         if (lkb->lkb_ua)
0175             xid = lkb->lkb_ua->xid;
0176     }
0177 
0178     /* microseconds since lkb was added to current queue */
0179     us = ktime_to_us(ktime_sub(ktime_get(), lkb->lkb_timestamp));
0180 
0181     /* id nodeid remid pid xid exflags flags sts grmode rqmode time_us
0182        r_nodeid r_len r_name */
0183 
0184     seq_printf(s, "%x %d %x %u %llu %x %x %d %d %d %llu %u %d \"%s\"\n",
0185            lkb->lkb_id,
0186            lkb->lkb_nodeid,
0187            lkb->lkb_remid,
0188            lkb->lkb_ownpid,
0189            (unsigned long long)xid,
0190            lkb->lkb_exflags,
0191            lkb->lkb_flags,
0192            lkb->lkb_status,
0193            lkb->lkb_grmode,
0194            lkb->lkb_rqmode,
0195            (unsigned long long)us,
0196            r->res_nodeid,
0197            r->res_length,
0198            r->res_name);
0199 }
0200 
0201 static void print_format2(struct dlm_rsb *r, struct seq_file *s)
0202 {
0203     struct dlm_lkb *lkb;
0204 
0205     lock_rsb(r);
0206 
0207     list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue) {
0208         print_format2_lock(s, lkb, r);
0209         if (seq_has_overflowed(s))
0210             goto out;
0211     }
0212 
0213     list_for_each_entry(lkb, &r->res_convertqueue, lkb_statequeue) {
0214         print_format2_lock(s, lkb, r);
0215         if (seq_has_overflowed(s))
0216             goto out;
0217     }
0218 
0219     list_for_each_entry(lkb, &r->res_waitqueue, lkb_statequeue) {
0220         print_format2_lock(s, lkb, r);
0221         if (seq_has_overflowed(s))
0222             goto out;
0223     }
0224  out:
0225     unlock_rsb(r);
0226 }
0227 
0228 static void print_format3_lock(struct seq_file *s, struct dlm_lkb *lkb,
0229                   int rsb_lookup)
0230 {
0231     u64 xid = 0;
0232 
0233     if (lkb->lkb_flags & DLM_IFL_USER) {
0234         if (lkb->lkb_ua)
0235             xid = lkb->lkb_ua->xid;
0236     }
0237 
0238     seq_printf(s, "lkb %x %d %x %u %llu %x %x %d %d %d %d %d %d %u %llu %llu\n",
0239            lkb->lkb_id,
0240            lkb->lkb_nodeid,
0241            lkb->lkb_remid,
0242            lkb->lkb_ownpid,
0243            (unsigned long long)xid,
0244            lkb->lkb_exflags,
0245            lkb->lkb_flags,
0246            lkb->lkb_status,
0247            lkb->lkb_grmode,
0248            lkb->lkb_rqmode,
0249            lkb->lkb_last_bast.mode,
0250            rsb_lookup,
0251            lkb->lkb_wait_type,
0252            lkb->lkb_lvbseq,
0253            (unsigned long long)ktime_to_ns(lkb->lkb_timestamp),
0254            (unsigned long long)ktime_to_ns(lkb->lkb_last_bast_time));
0255 }
0256 
0257 static void print_format3(struct dlm_rsb *r, struct seq_file *s)
0258 {
0259     struct dlm_lkb *lkb;
0260     int i, lvblen = r->res_ls->ls_lvblen;
0261     int print_name = 1;
0262 
0263     lock_rsb(r);
0264 
0265     seq_printf(s, "rsb %p %d %x %lx %d %d %u %d ",
0266            r,
0267            r->res_nodeid,
0268            r->res_first_lkid,
0269            r->res_flags,
0270            !list_empty(&r->res_root_list),
0271            !list_empty(&r->res_recover_list),
0272            r->res_recover_locks_count,
0273            r->res_length);
0274     if (seq_has_overflowed(s))
0275         goto out;
0276 
0277     for (i = 0; i < r->res_length; i++) {
0278         if (!isascii(r->res_name[i]) || !isprint(r->res_name[i]))
0279             print_name = 0;
0280     }
0281 
0282     seq_puts(s, print_name ? "str " : "hex");
0283 
0284     for (i = 0; i < r->res_length; i++) {
0285         if (print_name)
0286             seq_printf(s, "%c", r->res_name[i]);
0287         else
0288             seq_printf(s, " %02x", (unsigned char)r->res_name[i]);
0289     }
0290     seq_putc(s, '\n');
0291     if (seq_has_overflowed(s))
0292         goto out;
0293 
0294     if (!r->res_lvbptr)
0295         goto do_locks;
0296 
0297     seq_printf(s, "lvb %u %d", r->res_lvbseq, lvblen);
0298 
0299     for (i = 0; i < lvblen; i++)
0300         seq_printf(s, " %02x", (unsigned char)r->res_lvbptr[i]);
0301     seq_putc(s, '\n');
0302     if (seq_has_overflowed(s))
0303         goto out;
0304 
0305  do_locks:
0306     list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue) {
0307         print_format3_lock(s, lkb, 0);
0308         if (seq_has_overflowed(s))
0309             goto out;
0310     }
0311 
0312     list_for_each_entry(lkb, &r->res_convertqueue, lkb_statequeue) {
0313         print_format3_lock(s, lkb, 0);
0314         if (seq_has_overflowed(s))
0315             goto out;
0316     }
0317 
0318     list_for_each_entry(lkb, &r->res_waitqueue, lkb_statequeue) {
0319         print_format3_lock(s, lkb, 0);
0320         if (seq_has_overflowed(s))
0321             goto out;
0322     }
0323 
0324     list_for_each_entry(lkb, &r->res_lookup, lkb_rsb_lookup) {
0325         print_format3_lock(s, lkb, 1);
0326         if (seq_has_overflowed(s))
0327             goto out;
0328     }
0329  out:
0330     unlock_rsb(r);
0331 }
0332 
0333 static void print_format4(struct dlm_rsb *r, struct seq_file *s)
0334 {
0335     int our_nodeid = dlm_our_nodeid();
0336     int print_name = 1;
0337     int i;
0338 
0339     lock_rsb(r);
0340 
0341     seq_printf(s, "rsb %p %d %d %d %d %lu %lx %d ",
0342            r,
0343            r->res_nodeid,
0344            r->res_master_nodeid,
0345            r->res_dir_nodeid,
0346            our_nodeid,
0347            r->res_toss_time,
0348            r->res_flags,
0349            r->res_length);
0350 
0351     for (i = 0; i < r->res_length; i++) {
0352         if (!isascii(r->res_name[i]) || !isprint(r->res_name[i]))
0353             print_name = 0;
0354     }
0355 
0356     seq_puts(s, print_name ? "str " : "hex");
0357 
0358     for (i = 0; i < r->res_length; i++) {
0359         if (print_name)
0360             seq_printf(s, "%c", r->res_name[i]);
0361         else
0362             seq_printf(s, " %02x", (unsigned char)r->res_name[i]);
0363     }
0364     seq_putc(s, '\n');
0365     unlock_rsb(r);
0366 }
0367 
0368 struct rsbtbl_iter {
0369     struct dlm_rsb *rsb;
0370     unsigned bucket;
0371     int format;
0372     int header;
0373 };
0374 
0375 /*
0376  * If the buffer is full, seq_printf can be called again, but it
0377  * does nothing.  So, the these printing routines periodically check
0378  * seq_has_overflowed to avoid wasting too much time trying to print to
0379  * a full buffer.
0380  */
0381 
0382 static int table_seq_show(struct seq_file *seq, void *iter_ptr)
0383 {
0384     struct rsbtbl_iter *ri = iter_ptr;
0385 
0386     switch (ri->format) {
0387     case 1:
0388         print_format1(ri->rsb, seq);
0389         break;
0390     case 2:
0391         if (ri->header) {
0392             seq_puts(seq, "id nodeid remid pid xid exflags flags sts grmode rqmode time_ms r_nodeid r_len r_name\n");
0393             ri->header = 0;
0394         }
0395         print_format2(ri->rsb, seq);
0396         break;
0397     case 3:
0398         if (ri->header) {
0399             seq_puts(seq, "version rsb 1.1 lvb 1.1 lkb 1.1\n");
0400             ri->header = 0;
0401         }
0402         print_format3(ri->rsb, seq);
0403         break;
0404     case 4:
0405         if (ri->header) {
0406             seq_puts(seq, "version 4 rsb 2\n");
0407             ri->header = 0;
0408         }
0409         print_format4(ri->rsb, seq);
0410         break;
0411     }
0412 
0413     return 0;
0414 }
0415 
0416 static const struct seq_operations format1_seq_ops;
0417 static const struct seq_operations format2_seq_ops;
0418 static const struct seq_operations format3_seq_ops;
0419 static const struct seq_operations format4_seq_ops;
0420 
0421 static void *table_seq_start(struct seq_file *seq, loff_t *pos)
0422 {
0423     struct rb_root *tree;
0424     struct rb_node *node;
0425     struct dlm_ls *ls = seq->private;
0426     struct rsbtbl_iter *ri;
0427     struct dlm_rsb *r;
0428     loff_t n = *pos;
0429     unsigned bucket, entry;
0430     int toss = (seq->op == &format4_seq_ops);
0431 
0432     bucket = n >> 32;
0433     entry = n & ((1LL << 32) - 1);
0434 
0435     if (bucket >= ls->ls_rsbtbl_size)
0436         return NULL;
0437 
0438     ri = kzalloc(sizeof(*ri), GFP_NOFS);
0439     if (!ri)
0440         return NULL;
0441     if (n == 0)
0442         ri->header = 1;
0443     if (seq->op == &format1_seq_ops)
0444         ri->format = 1;
0445     if (seq->op == &format2_seq_ops)
0446         ri->format = 2;
0447     if (seq->op == &format3_seq_ops)
0448         ri->format = 3;
0449     if (seq->op == &format4_seq_ops)
0450         ri->format = 4;
0451 
0452     tree = toss ? &ls->ls_rsbtbl[bucket].toss : &ls->ls_rsbtbl[bucket].keep;
0453 
0454     spin_lock(&ls->ls_rsbtbl[bucket].lock);
0455     if (!RB_EMPTY_ROOT(tree)) {
0456         for (node = rb_first(tree); node; node = rb_next(node)) {
0457             r = rb_entry(node, struct dlm_rsb, res_hashnode);
0458             if (!entry--) {
0459                 dlm_hold_rsb(r);
0460                 ri->rsb = r;
0461                 ri->bucket = bucket;
0462                 spin_unlock(&ls->ls_rsbtbl[bucket].lock);
0463                 return ri;
0464             }
0465         }
0466     }
0467     spin_unlock(&ls->ls_rsbtbl[bucket].lock);
0468 
0469     /*
0470      * move to the first rsb in the next non-empty bucket
0471      */
0472 
0473     /* zero the entry */
0474     n &= ~((1LL << 32) - 1);
0475 
0476     while (1) {
0477         bucket++;
0478         n += 1LL << 32;
0479 
0480         if (bucket >= ls->ls_rsbtbl_size) {
0481             kfree(ri);
0482             return NULL;
0483         }
0484         tree = toss ? &ls->ls_rsbtbl[bucket].toss : &ls->ls_rsbtbl[bucket].keep;
0485 
0486         spin_lock(&ls->ls_rsbtbl[bucket].lock);
0487         if (!RB_EMPTY_ROOT(tree)) {
0488             node = rb_first(tree);
0489             r = rb_entry(node, struct dlm_rsb, res_hashnode);
0490             dlm_hold_rsb(r);
0491             ri->rsb = r;
0492             ri->bucket = bucket;
0493             spin_unlock(&ls->ls_rsbtbl[bucket].lock);
0494             *pos = n;
0495             return ri;
0496         }
0497         spin_unlock(&ls->ls_rsbtbl[bucket].lock);
0498     }
0499 }
0500 
0501 static void *table_seq_next(struct seq_file *seq, void *iter_ptr, loff_t *pos)
0502 {
0503     struct dlm_ls *ls = seq->private;
0504     struct rsbtbl_iter *ri = iter_ptr;
0505     struct rb_root *tree;
0506     struct rb_node *next;
0507     struct dlm_rsb *r, *rp;
0508     loff_t n = *pos;
0509     unsigned bucket;
0510     int toss = (seq->op == &format4_seq_ops);
0511 
0512     bucket = n >> 32;
0513 
0514     /*
0515      * move to the next rsb in the same bucket
0516      */
0517 
0518     spin_lock(&ls->ls_rsbtbl[bucket].lock);
0519     rp = ri->rsb;
0520     next = rb_next(&rp->res_hashnode);
0521 
0522     if (next) {
0523         r = rb_entry(next, struct dlm_rsb, res_hashnode);
0524         dlm_hold_rsb(r);
0525         ri->rsb = r;
0526         spin_unlock(&ls->ls_rsbtbl[bucket].lock);
0527         dlm_put_rsb(rp);
0528         ++*pos;
0529         return ri;
0530     }
0531     spin_unlock(&ls->ls_rsbtbl[bucket].lock);
0532     dlm_put_rsb(rp);
0533 
0534     /*
0535      * move to the first rsb in the next non-empty bucket
0536      */
0537 
0538     /* zero the entry */
0539     n &= ~((1LL << 32) - 1);
0540 
0541     while (1) {
0542         bucket++;
0543         n += 1LL << 32;
0544 
0545         if (bucket >= ls->ls_rsbtbl_size) {
0546             kfree(ri);
0547             ++*pos;
0548             return NULL;
0549         }
0550         tree = toss ? &ls->ls_rsbtbl[bucket].toss : &ls->ls_rsbtbl[bucket].keep;
0551 
0552         spin_lock(&ls->ls_rsbtbl[bucket].lock);
0553         if (!RB_EMPTY_ROOT(tree)) {
0554             next = rb_first(tree);
0555             r = rb_entry(next, struct dlm_rsb, res_hashnode);
0556             dlm_hold_rsb(r);
0557             ri->rsb = r;
0558             ri->bucket = bucket;
0559             spin_unlock(&ls->ls_rsbtbl[bucket].lock);
0560             *pos = n;
0561             return ri;
0562         }
0563         spin_unlock(&ls->ls_rsbtbl[bucket].lock);
0564     }
0565 }
0566 
0567 static void table_seq_stop(struct seq_file *seq, void *iter_ptr)
0568 {
0569     struct rsbtbl_iter *ri = iter_ptr;
0570 
0571     if (ri) {
0572         dlm_put_rsb(ri->rsb);
0573         kfree(ri);
0574     }
0575 }
0576 
0577 static const struct seq_operations format1_seq_ops = {
0578     .start = table_seq_start,
0579     .next  = table_seq_next,
0580     .stop  = table_seq_stop,
0581     .show  = table_seq_show,
0582 };
0583 
0584 static const struct seq_operations format2_seq_ops = {
0585     .start = table_seq_start,
0586     .next  = table_seq_next,
0587     .stop  = table_seq_stop,
0588     .show  = table_seq_show,
0589 };
0590 
0591 static const struct seq_operations format3_seq_ops = {
0592     .start = table_seq_start,
0593     .next  = table_seq_next,
0594     .stop  = table_seq_stop,
0595     .show  = table_seq_show,
0596 };
0597 
0598 static const struct seq_operations format4_seq_ops = {
0599     .start = table_seq_start,
0600     .next  = table_seq_next,
0601     .stop  = table_seq_stop,
0602     .show  = table_seq_show,
0603 };
0604 
0605 static const struct file_operations format1_fops;
0606 static const struct file_operations format2_fops;
0607 static const struct file_operations format3_fops;
0608 static const struct file_operations format4_fops;
0609 
0610 static int table_open1(struct inode *inode, struct file *file)
0611 {
0612     struct seq_file *seq;
0613     int ret;
0614 
0615     ret = seq_open(file, &format1_seq_ops);
0616     if (ret)
0617         return ret;
0618 
0619     seq = file->private_data;
0620     seq->private = inode->i_private; /* the dlm_ls */
0621     return 0;
0622 }
0623 
0624 static int table_open2(struct inode *inode, struct file *file)
0625 {
0626     struct seq_file *seq;
0627     int ret;
0628 
0629     ret = seq_open(file, &format2_seq_ops);
0630     if (ret)
0631         return ret;
0632 
0633     seq = file->private_data;
0634     seq->private = inode->i_private; /* the dlm_ls */
0635     return 0;
0636 }
0637 
0638 static ssize_t table_write2(struct file *file, const char __user *user_buf,
0639                 size_t count, loff_t *ppos)
0640 {
0641     struct seq_file *seq = file->private_data;
0642     int n, len, lkb_nodeid, lkb_status, error;
0643     char name[DLM_RESNAME_MAXLEN + 1] = {};
0644     struct dlm_ls *ls = seq->private;
0645     unsigned int lkb_flags;
0646     char buf[256] = {};
0647     uint32_t lkb_id;
0648 
0649     if (copy_from_user(buf, user_buf,
0650                min_t(size_t, sizeof(buf) - 1, count)))
0651         return -EFAULT;
0652 
0653     n = sscanf(buf, "%x %" __stringify(DLM_RESNAME_MAXLEN) "s %x %d %d",
0654            &lkb_id, name, &lkb_flags, &lkb_nodeid, &lkb_status);
0655     if (n != 5)
0656         return -EINVAL;
0657 
0658     len = strnlen(name, DLM_RESNAME_MAXLEN);
0659     error = dlm_debug_add_lkb(ls, lkb_id, name, len, lkb_flags,
0660                   lkb_nodeid, lkb_status);
0661     if (error)
0662         return error;
0663 
0664     return count;
0665 }
0666 
0667 static int table_open3(struct inode *inode, struct file *file)
0668 {
0669     struct seq_file *seq;
0670     int ret;
0671 
0672     ret = seq_open(file, &format3_seq_ops);
0673     if (ret)
0674         return ret;
0675 
0676     seq = file->private_data;
0677     seq->private = inode->i_private; /* the dlm_ls */
0678     return 0;
0679 }
0680 
0681 static int table_open4(struct inode *inode, struct file *file)
0682 {
0683     struct seq_file *seq;
0684     int ret;
0685 
0686     ret = seq_open(file, &format4_seq_ops);
0687     if (ret)
0688         return ret;
0689 
0690     seq = file->private_data;
0691     seq->private = inode->i_private; /* the dlm_ls */
0692     return 0;
0693 }
0694 
0695 static const struct file_operations format1_fops = {
0696     .owner   = THIS_MODULE,
0697     .open    = table_open1,
0698     .read    = seq_read,
0699     .llseek  = seq_lseek,
0700     .release = seq_release
0701 };
0702 
0703 static const struct file_operations format2_fops = {
0704     .owner   = THIS_MODULE,
0705     .open    = table_open2,
0706     .read    = seq_read,
0707     .write   = table_write2,
0708     .llseek  = seq_lseek,
0709     .release = seq_release
0710 };
0711 
0712 static const struct file_operations format3_fops = {
0713     .owner   = THIS_MODULE,
0714     .open    = table_open3,
0715     .read    = seq_read,
0716     .llseek  = seq_lseek,
0717     .release = seq_release
0718 };
0719 
0720 static const struct file_operations format4_fops = {
0721     .owner   = THIS_MODULE,
0722     .open    = table_open4,
0723     .read    = seq_read,
0724     .llseek  = seq_lseek,
0725     .release = seq_release
0726 };
0727 
0728 /*
0729  * dump lkb's on the ls_waiters list
0730  */
0731 static ssize_t waiters_read(struct file *file, char __user *userbuf,
0732                 size_t count, loff_t *ppos)
0733 {
0734     struct dlm_ls *ls = file->private_data;
0735     struct dlm_lkb *lkb;
0736     size_t len = DLM_DEBUG_BUF_LEN, pos = 0, ret, rv;
0737 
0738     mutex_lock(&debug_buf_lock);
0739     mutex_lock(&ls->ls_waiters_mutex);
0740     memset(debug_buf, 0, sizeof(debug_buf));
0741 
0742     list_for_each_entry(lkb, &ls->ls_waiters, lkb_wait_reply) {
0743         ret = snprintf(debug_buf + pos, len - pos, "%x %d %d %s\n",
0744                    lkb->lkb_id, lkb->lkb_wait_type,
0745                    lkb->lkb_nodeid, lkb->lkb_resource->res_name);
0746         if (ret >= len - pos)
0747             break;
0748         pos += ret;
0749     }
0750     mutex_unlock(&ls->ls_waiters_mutex);
0751 
0752     rv = simple_read_from_buffer(userbuf, count, ppos, debug_buf, pos);
0753     mutex_unlock(&debug_buf_lock);
0754     return rv;
0755 }
0756 
0757 static ssize_t waiters_write(struct file *file, const char __user *user_buf,
0758                  size_t count, loff_t *ppos)
0759 {
0760     struct dlm_ls *ls = file->private_data;
0761     int mstype, to_nodeid;
0762     char buf[128] = {};
0763     uint32_t lkb_id;
0764     int n, error;
0765 
0766     if (copy_from_user(buf, user_buf,
0767                min_t(size_t, sizeof(buf) - 1, count)))
0768         return -EFAULT;
0769 
0770     n = sscanf(buf, "%x %d %d", &lkb_id, &mstype, &to_nodeid);
0771     if (n != 3)
0772         return -EINVAL;
0773 
0774     error = dlm_debug_add_lkb_to_waiters(ls, lkb_id, mstype, to_nodeid);
0775     if (error)
0776         return error;
0777 
0778     return count;
0779 }
0780 
0781 static const struct file_operations waiters_fops = {
0782     .owner   = THIS_MODULE,
0783     .open    = simple_open,
0784     .read    = waiters_read,
0785     .write   = waiters_write,
0786     .llseek  = default_llseek,
0787 };
0788 
0789 void dlm_delete_debug_file(struct dlm_ls *ls)
0790 {
0791     debugfs_remove(ls->ls_debug_rsb_dentry);
0792     debugfs_remove(ls->ls_debug_waiters_dentry);
0793     debugfs_remove(ls->ls_debug_locks_dentry);
0794     debugfs_remove(ls->ls_debug_all_dentry);
0795     debugfs_remove(ls->ls_debug_toss_dentry);
0796 }
0797 
0798 static int dlm_state_show(struct seq_file *file, void *offset)
0799 {
0800     seq_printf(file, "%s\n", dlm_midcomms_state(file->private));
0801     return 0;
0802 }
0803 DEFINE_SHOW_ATTRIBUTE(dlm_state);
0804 
0805 static int dlm_flags_show(struct seq_file *file, void *offset)
0806 {
0807     seq_printf(file, "%lu\n", dlm_midcomms_flags(file->private));
0808     return 0;
0809 }
0810 DEFINE_SHOW_ATTRIBUTE(dlm_flags);
0811 
0812 static int dlm_send_queue_cnt_show(struct seq_file *file, void *offset)
0813 {
0814     seq_printf(file, "%d\n", dlm_midcomms_send_queue_cnt(file->private));
0815     return 0;
0816 }
0817 DEFINE_SHOW_ATTRIBUTE(dlm_send_queue_cnt);
0818 
0819 static int dlm_version_show(struct seq_file *file, void *offset)
0820 {
0821     seq_printf(file, "0x%08x\n", dlm_midcomms_version(file->private));
0822     return 0;
0823 }
0824 DEFINE_SHOW_ATTRIBUTE(dlm_version);
0825 
0826 static ssize_t dlm_rawmsg_write(struct file *fp, const char __user *user_buf,
0827                 size_t count, loff_t *ppos)
0828 {
0829     void *buf;
0830     int ret;
0831 
0832     if (count > PAGE_SIZE || count < sizeof(struct dlm_header))
0833         return -EINVAL;
0834 
0835     buf = kmalloc(PAGE_SIZE, GFP_NOFS);
0836     if (!buf)
0837         return -ENOMEM;
0838 
0839     if (copy_from_user(buf, user_buf, count)) {
0840         ret = -EFAULT;
0841         goto out;
0842     }
0843 
0844     ret = dlm_midcomms_rawmsg_send(fp->private_data, buf, count);
0845     if (ret)
0846         goto out;
0847 
0848     kfree(buf);
0849     return count;
0850 
0851 out:
0852     kfree(buf);
0853     return ret;
0854 }
0855 
0856 static const struct file_operations dlm_rawmsg_fops = {
0857     .open   = simple_open,
0858     .write  = dlm_rawmsg_write,
0859     .llseek = no_llseek,
0860 };
0861 
0862 void *dlm_create_debug_comms_file(int nodeid, void *data)
0863 {
0864     struct dentry *d_node;
0865     char name[256];
0866 
0867     memset(name, 0, sizeof(name));
0868     snprintf(name, 256, "%d", nodeid);
0869 
0870     d_node = debugfs_create_dir(name, dlm_comms);
0871     debugfs_create_file("state", 0444, d_node, data, &dlm_state_fops);
0872     debugfs_create_file("flags", 0444, d_node, data, &dlm_flags_fops);
0873     debugfs_create_file("send_queue_count", 0444, d_node, data,
0874                 &dlm_send_queue_cnt_fops);
0875     debugfs_create_file("version", 0444, d_node, data, &dlm_version_fops);
0876     debugfs_create_file("rawmsg", 0200, d_node, data, &dlm_rawmsg_fops);
0877 
0878     return d_node;
0879 }
0880 
0881 void dlm_delete_debug_comms_file(void *ctx)
0882 {
0883     debugfs_remove(ctx);
0884 }
0885 
0886 void dlm_create_debug_file(struct dlm_ls *ls)
0887 {
0888     char name[DLM_LOCKSPACE_LEN + 8];
0889 
0890     /* format 1 */
0891 
0892     ls->ls_debug_rsb_dentry = debugfs_create_file(ls->ls_name,
0893                               S_IFREG | S_IRUGO,
0894                               dlm_root,
0895                               ls,
0896                               &format1_fops);
0897 
0898     /* format 2 */
0899 
0900     memset(name, 0, sizeof(name));
0901     snprintf(name, DLM_LOCKSPACE_LEN + 8, "%s_locks", ls->ls_name);
0902 
0903     ls->ls_debug_locks_dentry = debugfs_create_file(name,
0904                             0644,
0905                             dlm_root,
0906                             ls,
0907                             &format2_fops);
0908 
0909     /* format 3 */
0910 
0911     memset(name, 0, sizeof(name));
0912     snprintf(name, DLM_LOCKSPACE_LEN + 8, "%s_all", ls->ls_name);
0913 
0914     ls->ls_debug_all_dentry = debugfs_create_file(name,
0915                               S_IFREG | S_IRUGO,
0916                               dlm_root,
0917                               ls,
0918                               &format3_fops);
0919 
0920     /* format 4 */
0921 
0922     memset(name, 0, sizeof(name));
0923     snprintf(name, DLM_LOCKSPACE_LEN + 8, "%s_toss", ls->ls_name);
0924 
0925     ls->ls_debug_toss_dentry = debugfs_create_file(name,
0926                                S_IFREG | S_IRUGO,
0927                                dlm_root,
0928                                ls,
0929                                &format4_fops);
0930 
0931     memset(name, 0, sizeof(name));
0932     snprintf(name, DLM_LOCKSPACE_LEN + 8, "%s_waiters", ls->ls_name);
0933 
0934     ls->ls_debug_waiters_dentry = debugfs_create_file(name,
0935                               0644,
0936                               dlm_root,
0937                               ls,
0938                               &waiters_fops);
0939 }
0940 
0941 void __init dlm_register_debugfs(void)
0942 {
0943     mutex_init(&debug_buf_lock);
0944     dlm_root = debugfs_create_dir("dlm", NULL);
0945     dlm_comms = debugfs_create_dir("comms", dlm_root);
0946 }
0947 
0948 void dlm_unregister_debugfs(void)
0949 {
0950     debugfs_remove(dlm_root);
0951 }
0952