Commit d022509d1c54be4918e7fc8f1195ee8c392e9a57

Authored by David Teigland
1 parent e3a84ad495

dlm: add new debugfs entry

The new debugfs entry dumps all rsb and lkb structures, and includes
a lot more information than has been available before.  This includes
the new timestamps added by a previous patch for debugging callback
issues.

Signed-off-by: David Teigland <teigland@redhat.com>

Showing 2 changed files with 247 additions and 50 deletions Side-by-side Diff

1 1 /******************************************************************************
2 2 *******************************************************************************
3 3 **
4   -** Copyright (C) 2005 Red Hat, Inc. All rights reserved.
  4 +** Copyright (C) 2005-2008 Red Hat, Inc. All rights reserved.
5 5 **
6 6 ** This copyrighted material is made available to anyone wishing to use,
7 7 ** modify, copy, or redistribute it subject to the terms and conditions
... ... @@ -27,7 +27,7 @@
27 27  
28 28 struct rsb_iter {
29 29 int entry;
30   - int locks;
  30 + int format;
31 31 int header;
32 32 struct dlm_ls *ls;
33 33 struct list_head *next;
... ... @@ -60,8 +60,8 @@
60 60 }
61 61 }
62 62  
63   -static void print_resource_lock(struct seq_file *s, struct dlm_lkb *lkb,
64   - struct dlm_rsb *res)
  63 +static void print_format1_lock(struct seq_file *s, struct dlm_lkb *lkb,
  64 + struct dlm_rsb *res)
65 65 {
66 66 seq_printf(s, "%08x %s", lkb->lkb_id, print_lockmode(lkb->lkb_grmode));
67 67  
... ... @@ -83,7 +83,7 @@
83 83 seq_printf(s, "\n");
84 84 }
85 85  
86   -static int print_resource(struct dlm_rsb *res, struct seq_file *s)
  86 +static int print_format1(struct dlm_rsb *res, struct seq_file *s)
87 87 {
88 88 struct dlm_lkb *lkb;
89 89 int i, lvblen = res->res_ls->ls_lvblen, recover_list, root_list;
90 90  
91 91  
... ... @@ -134,15 +134,15 @@
134 134 /* Print the locks attached to this resource */
135 135 seq_printf(s, "Granted Queue\n");
136 136 list_for_each_entry(lkb, &res->res_grantqueue, lkb_statequeue)
137   - print_resource_lock(s, lkb, res);
  137 + print_format1_lock(s, lkb, res);
138 138  
139 139 seq_printf(s, "Conversion Queue\n");
140 140 list_for_each_entry(lkb, &res->res_convertqueue, lkb_statequeue)
141   - print_resource_lock(s, lkb, res);
  141 + print_format1_lock(s, lkb, res);
142 142  
143 143 seq_printf(s, "Waiting Queue\n");
144 144 list_for_each_entry(lkb, &res->res_waitqueue, lkb_statequeue)
145   - print_resource_lock(s, lkb, res);
  145 + print_format1_lock(s, lkb, res);
146 146  
147 147 if (list_empty(&res->res_lookup))
148 148 goto out;
... ... @@ -160,7 +160,8 @@
160 160 return 0;
161 161 }
162 162  
163   -static void print_lock(struct seq_file *s, struct dlm_lkb *lkb, struct dlm_rsb *r)
  163 +static void print_format2_lock(struct seq_file *s, struct dlm_lkb *lkb,
  164 + struct dlm_rsb *r)
164 165 {
165 166 u64 xid = 0;
166 167 u64 us;
167 168  
168 169  
169 170  
170 171  
... ... @@ -193,25 +194,113 @@
193 194 r->res_name);
194 195 }
195 196  
196   -static int print_locks(struct dlm_rsb *r, struct seq_file *s)
  197 +static int print_format2(struct dlm_rsb *r, struct seq_file *s)
197 198 {
198 199 struct dlm_lkb *lkb;
199 200  
200 201 lock_rsb(r);
201 202  
202 203 list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue)
203   - print_lock(s, lkb, r);
  204 + print_format2_lock(s, lkb, r);
204 205  
205 206 list_for_each_entry(lkb, &r->res_convertqueue, lkb_statequeue)
206   - print_lock(s, lkb, r);
  207 + print_format2_lock(s, lkb, r);
207 208  
208 209 list_for_each_entry(lkb, &r->res_waitqueue, lkb_statequeue)
209   - print_lock(s, lkb, r);
  210 + print_format2_lock(s, lkb, r);
210 211  
211 212 unlock_rsb(r);
212 213 return 0;
213 214 }
214 215  
  216 +static void print_format3_lock(struct seq_file *s, struct dlm_lkb *lkb,
  217 + int rsb_lookup)
  218 +{
  219 + u64 xid = 0;
  220 +
  221 + if (lkb->lkb_flags & DLM_IFL_USER) {
  222 + if (lkb->lkb_ua)
  223 + xid = lkb->lkb_ua->xid;
  224 + }
  225 +
  226 + seq_printf(s, "lkb %x %d %x %u %llu %x %x %d %d %d %d %d %d %u %llu %llu\n",
  227 + lkb->lkb_id,
  228 + lkb->lkb_nodeid,
  229 + lkb->lkb_remid,
  230 + lkb->lkb_ownpid,
  231 + (unsigned long long)xid,
  232 + lkb->lkb_exflags,
  233 + lkb->lkb_flags,
  234 + lkb->lkb_status,
  235 + lkb->lkb_grmode,
  236 + lkb->lkb_rqmode,
  237 + lkb->lkb_highbast,
  238 + rsb_lookup,
  239 + lkb->lkb_wait_type,
  240 + lkb->lkb_lvbseq,
  241 + (unsigned long long)ktime_to_ns(lkb->lkb_timestamp),
  242 + (unsigned long long)ktime_to_ns(lkb->lkb_time_bast));
  243 +}
  244 +
  245 +static int print_format3(struct dlm_rsb *r, struct seq_file *s)
  246 +{
  247 + struct dlm_lkb *lkb;
  248 + int i, lvblen = r->res_ls->ls_lvblen;
  249 + int print_name = 1;
  250 +
  251 + lock_rsb(r);
  252 +
  253 + seq_printf(s, "rsb %p %d %x %lx %d %d %u %d ",
  254 + r,
  255 + r->res_nodeid,
  256 + r->res_first_lkid,
  257 + r->res_flags,
  258 + !list_empty(&r->res_root_list),
  259 + !list_empty(&r->res_recover_list),
  260 + r->res_recover_locks_count,
  261 + r->res_length);
  262 +
  263 + for (i = 0; i < r->res_length; i++) {
  264 + if (!isascii(r->res_name[i]) || !isprint(r->res_name[i]))
  265 + print_name = 0;
  266 + }
  267 +
  268 + seq_printf(s, "%s", print_name ? "str " : "hex");
  269 +
  270 + for (i = 0; i < r->res_length; i++) {
  271 + if (print_name)
  272 + seq_printf(s, "%c", r->res_name[i]);
  273 + else
  274 + seq_printf(s, " %02x", (unsigned char)r->res_name[i]);
  275 + }
  276 + seq_printf(s, "\n");
  277 +
  278 + if (!r->res_lvbptr)
  279 + goto do_locks;
  280 +
  281 + seq_printf(s, "lvb %u %d", r->res_lvbseq, lvblen);
  282 +
  283 + for (i = 0; i < lvblen; i++)
  284 + seq_printf(s, " %02x", (unsigned char)r->res_lvbptr[i]);
  285 + seq_printf(s, "\n");
  286 +
  287 + do_locks:
  288 + list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue)
  289 + print_format3_lock(s, lkb, 0);
  290 +
  291 + list_for_each_entry(lkb, &r->res_convertqueue, lkb_statequeue)
  292 + print_format3_lock(s, lkb, 0);
  293 +
  294 + list_for_each_entry(lkb, &r->res_waitqueue, lkb_statequeue)
  295 + print_format3_lock(s, lkb, 0);
  296 +
  297 + list_for_each_entry(lkb, &r->res_lookup, lkb_rsb_lookup)
  298 + print_format3_lock(s, lkb, 1);
  299 +
  300 + unlock_rsb(r);
  301 + return 0;
  302 +}
  303 +
215 304 static int rsb_iter_next(struct rsb_iter *ri)
216 305 {
217 306 struct dlm_ls *ls = ri->ls;
... ... @@ -231,7 +320,7 @@
231 320 break;
232 321 }
233 322 read_unlock(&ls->ls_rsbtbl[i].lock);
234   - }
  323 + }
235 324 ri->entry = i;
236 325  
237 326 if (ri->entry >= ls->ls_rsbtbl_size)
... ... @@ -248,7 +337,7 @@
248 337 read_unlock(&ls->ls_rsbtbl[i].lock);
249 338 dlm_put_rsb(old);
250 339 goto top;
251   - }
  340 + }
252 341 ri->rsb = list_entry(ri->next, struct dlm_rsb, res_hashchain);
253 342 dlm_hold_rsb(ri->rsb);
254 343 read_unlock(&ls->ls_rsbtbl[i].lock);
... ... @@ -274,6 +363,7 @@
274 363 ri->ls = ls;
275 364 ri->entry = 0;
276 365 ri->next = NULL;
  366 + ri->format = 1;
277 367  
278 368 if (rsb_iter_next(ri)) {
279 369 rsb_iter_free(ri);
280 370  
281 371  
... ... @@ -325,16 +415,26 @@
325 415 {
326 416 struct rsb_iter *ri = iter_ptr;
327 417  
328   - if (ri->locks) {
  418 + switch (ri->format) {
  419 + case 1:
  420 + print_format1(ri->rsb, file);
  421 + break;
  422 + case 2:
329 423 if (ri->header) {
330   - seq_printf(file, "id nodeid remid pid xid exflags flags "
331   - "sts grmode rqmode time_ms r_nodeid "
332   - "r_len r_name\n");
  424 + seq_printf(file, "id nodeid remid pid xid exflags "
  425 + "flags sts grmode rqmode time_ms "
  426 + "r_nodeid r_len r_name\n");
333 427 ri->header = 0;
334 428 }
335   - print_locks(ri->rsb, file);
336   - } else {
337   - print_resource(ri->rsb, file);
  429 + print_format2(ri->rsb, file);
  430 + break;
  431 + case 3:
  432 + if (ri->header) {
  433 + seq_printf(file, "version rsb 1.1 lvb 1.1 lkb 1.1\n");
  434 + ri->header = 0;
  435 + }
  436 + print_format3(ri->rsb, file);
  437 + break;
338 438 }
339 439  
340 440 return 0;
... ... @@ -385,7 +485,7 @@
385 485 ri->ls = ls;
386 486 ri->entry = 0;
387 487 ri->next = NULL;
388   - ri->locks = 1;
  488 + ri->format = 2;
389 489  
390 490 if (*pos == 0)
391 491 ri->header = 1;
... ... @@ -448,6 +548,84 @@
448 548 };
449 549  
450 550 /*
  551 + * Dump all rsb/lvb/lkb state in compact listing, more complete than _locks
  552 + * This can replace both formats 1 and 2 eventually.
  553 + */
  554 +
  555 +static struct rsb_iter *all_iter_init(struct dlm_ls *ls, loff_t *pos)
  556 +{
  557 + struct rsb_iter *ri;
  558 +
  559 + ri = kzalloc(sizeof *ri, GFP_KERNEL);
  560 + if (!ri)
  561 + return NULL;
  562 +
  563 + ri->ls = ls;
  564 + ri->entry = 0;
  565 + ri->next = NULL;
  566 + ri->format = 3;
  567 +
  568 + if (*pos == 0)
  569 + ri->header = 1;
  570 +
  571 + if (rsb_iter_next(ri)) {
  572 + rsb_iter_free(ri);
  573 + return NULL;
  574 + }
  575 +
  576 + return ri;
  577 +}
  578 +
  579 +static void *all_seq_start(struct seq_file *file, loff_t *pos)
  580 +{
  581 + struct rsb_iter *ri;
  582 + loff_t n = *pos;
  583 +
  584 + ri = all_iter_init(file->private, pos);
  585 + if (!ri)
  586 + return NULL;
  587 +
  588 + while (n--) {
  589 + if (rsb_iter_next(ri)) {
  590 + rsb_iter_free(ri);
  591 + return NULL;
  592 + }
  593 + }
  594 +
  595 + return ri;
  596 +}
  597 +
  598 +static struct seq_operations all_seq_ops = {
  599 + .start = all_seq_start,
  600 + .next = rsb_seq_next,
  601 + .stop = rsb_seq_stop,
  602 + .show = rsb_seq_show,
  603 +};
  604 +
  605 +static int all_open(struct inode *inode, struct file *file)
  606 +{
  607 + struct seq_file *seq;
  608 + int ret;
  609 +
  610 + ret = seq_open(file, &all_seq_ops);
  611 + if (ret)
  612 + return ret;
  613 +
  614 + seq = file->private_data;
  615 + seq->private = inode->i_private;
  616 +
  617 + return 0;
  618 +}
  619 +
  620 +static const struct file_operations all_fops = {
  621 + .owner = THIS_MODULE,
  622 + .open = all_open,
  623 + .read = seq_read,
  624 + .llseek = seq_lseek,
  625 + .release = seq_release
  626 +};
  627 +
  628 +/*
451 629 * dump lkb's on the ls_waiters list
452 630 */
453 631  
454 632  
455 633  
456 634  
457 635  
... ... @@ -489,31 +667,34 @@
489 667 .read = waiters_read
490 668 };
491 669  
  670 +void dlm_delete_debug_file(struct dlm_ls *ls)
  671 +{
  672 + if (ls->ls_debug_rsb_dentry)
  673 + debugfs_remove(ls->ls_debug_rsb_dentry);
  674 + if (ls->ls_debug_waiters_dentry)
  675 + debugfs_remove(ls->ls_debug_waiters_dentry);
  676 + if (ls->ls_debug_locks_dentry)
  677 + debugfs_remove(ls->ls_debug_locks_dentry);
  678 + if (ls->ls_debug_all_dentry)
  679 + debugfs_remove(ls->ls_debug_all_dentry);
  680 +}
  681 +
492 682 int dlm_create_debug_file(struct dlm_ls *ls)
493 683 {
494 684 char name[DLM_LOCKSPACE_LEN+8];
495 685  
  686 + /* format 1 */
  687 +
496 688 ls->ls_debug_rsb_dentry = debugfs_create_file(ls->ls_name,
497 689 S_IFREG | S_IRUGO,
498 690 dlm_root,
499 691 ls,
500 692 &rsb_fops);
501 693 if (!ls->ls_debug_rsb_dentry)
502   - return -ENOMEM;
  694 + goto fail;
503 695  
504   - memset(name, 0, sizeof(name));
505   - snprintf(name, DLM_LOCKSPACE_LEN+8, "%s_waiters", ls->ls_name);
  696 + /* format 2 */
506 697  
507   - ls->ls_debug_waiters_dentry = debugfs_create_file(name,
508   - S_IFREG | S_IRUGO,
509   - dlm_root,
510   - ls,
511   - &waiters_fops);
512   - if (!ls->ls_debug_waiters_dentry) {
513   - debugfs_remove(ls->ls_debug_rsb_dentry);
514   - return -ENOMEM;
515   - }
516   -
517 698 memset(name, 0, sizeof(name));
518 699 snprintf(name, DLM_LOCKSPACE_LEN+8, "%s_locks", ls->ls_name);
519 700  
520 701  
521 702  
522 703  
... ... @@ -522,23 +703,38 @@
522 703 dlm_root,
523 704 ls,
524 705 &locks_fops);
525   - if (!ls->ls_debug_locks_dentry) {
526   - debugfs_remove(ls->ls_debug_waiters_dentry);
527   - debugfs_remove(ls->ls_debug_rsb_dentry);
528   - return -ENOMEM;
529   - }
  706 + if (!ls->ls_debug_locks_dentry)
  707 + goto fail;
530 708  
  709 + /* format 3 */
  710 +
  711 + memset(name, 0, sizeof(name));
  712 + snprintf(name, DLM_LOCKSPACE_LEN+8, "%s_all", ls->ls_name);
  713 +
  714 + ls->ls_debug_all_dentry = debugfs_create_file(name,
  715 + S_IFREG | S_IRUGO,
  716 + dlm_root,
  717 + ls,
  718 + &all_fops);
  719 + if (!ls->ls_debug_all_dentry)
  720 + goto fail;
  721 +
  722 + memset(name, 0, sizeof(name));
  723 + snprintf(name, DLM_LOCKSPACE_LEN+8, "%s_waiters", ls->ls_name);
  724 +
  725 + ls->ls_debug_waiters_dentry = debugfs_create_file(name,
  726 + S_IFREG | S_IRUGO,
  727 + dlm_root,
  728 + ls,
  729 + &waiters_fops);
  730 + if (!ls->ls_debug_waiters_dentry)
  731 + goto fail;
  732 +
531 733 return 0;
532   -}
533 734  
534   -void dlm_delete_debug_file(struct dlm_ls *ls)
535   -{
536   - if (ls->ls_debug_rsb_dentry)
537   - debugfs_remove(ls->ls_debug_rsb_dentry);
538   - if (ls->ls_debug_waiters_dentry)
539   - debugfs_remove(ls->ls_debug_waiters_dentry);
540   - if (ls->ls_debug_locks_dentry)
541   - debugfs_remove(ls->ls_debug_locks_dentry);
  735 + fail:
  736 + dlm_delete_debug_file(ls);
  737 + return -ENOMEM;
542 738 }
543 739  
544 740 int __init dlm_register_debugfs(void)
fs/dlm/dlm_internal.h
... ... @@ -482,6 +482,7 @@
482 482 struct dentry *ls_debug_rsb_dentry; /* debugfs */
483 483 struct dentry *ls_debug_waiters_dentry; /* debugfs */
484 484 struct dentry *ls_debug_locks_dentry; /* debugfs */
  485 + struct dentry *ls_debug_all_dentry; /* debugfs */
485 486  
486 487 wait_queue_head_t ls_uevent_wait; /* user part of join/leave */
487 488 int ls_uevent_result;