0001
0002
0003
0004
0005
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
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
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
0179 us = ktime_to_us(ktime_sub(ktime_get(), lkb->lkb_timestamp));
0180
0181
0182
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
0377
0378
0379
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
0471
0472
0473
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
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
0536
0537
0538
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;
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;
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;
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;
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
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
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
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
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
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