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>

+247 -50
+246 -50
fs/dlm/debug_fs.c
··· 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 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 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 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; ··· 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 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; ··· 194 193 r->res_name); 195 194 } 196 195 197 - static int print_locks(struct dlm_rsb *r, struct seq_file *s) 196 + static int print_format2(struct dlm_rsb *r, struct seq_file *s) 198 197 { 199 198 struct dlm_lkb *lkb; 200 199 201 200 lock_rsb(r); 202 201 203 202 list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue) 204 - print_lock(s, lkb, r); 203 + print_format2_lock(s, lkb, r); 205 204 206 205 list_for_each_entry(lkb, &r->res_convertqueue, lkb_statequeue) 207 - print_lock(s, lkb, r); 206 + print_format2_lock(s, lkb, r); 208 207 209 208 list_for_each_entry(lkb, &r->res_waitqueue, lkb_statequeue) 210 - print_lock(s, lkb, r); 209 + print_format2_lock(s, lkb, r); 210 + 211 + unlock_rsb(r); 212 + return 0; 213 + } 214 + 215 + static void print_format3_lock(struct seq_file *s, struct dlm_lkb *lkb, 216 + int rsb_lookup) 217 + { 218 + u64 xid = 0; 219 + 220 + if (lkb->lkb_flags & DLM_IFL_USER) { 221 + if (lkb->lkb_ua) 222 + xid = lkb->lkb_ua->xid; 223 + } 224 + 225 + seq_printf(s, "lkb %x %d %x %u %llu %x %x %d %d %d %d %d %d %u %llu %llu\n", 226 + lkb->lkb_id, 227 + lkb->lkb_nodeid, 228 + lkb->lkb_remid, 229 + lkb->lkb_ownpid, 230 + (unsigned long long)xid, 231 + lkb->lkb_exflags, 232 + lkb->lkb_flags, 233 + lkb->lkb_status, 234 + lkb->lkb_grmode, 235 + lkb->lkb_rqmode, 236 + lkb->lkb_highbast, 237 + rsb_lookup, 238 + lkb->lkb_wait_type, 239 + lkb->lkb_lvbseq, 240 + (unsigned long long)ktime_to_ns(lkb->lkb_timestamp), 241 + (unsigned long long)ktime_to_ns(lkb->lkb_time_bast)); 242 + } 243 + 244 + static int print_format3(struct dlm_rsb *r, struct seq_file *s) 245 + { 246 + struct dlm_lkb *lkb; 247 + int i, lvblen = r->res_ls->ls_lvblen; 248 + int print_name = 1; 249 + 250 + lock_rsb(r); 251 + 252 + seq_printf(s, "rsb %p %d %x %lx %d %d %u %d ", 253 + r, 254 + r->res_nodeid, 255 + r->res_first_lkid, 256 + r->res_flags, 257 + !list_empty(&r->res_root_list), 258 + !list_empty(&r->res_recover_list), 259 + r->res_recover_locks_count, 260 + r->res_length); 261 + 262 + for (i = 0; i < r->res_length; i++) { 263 + if (!isascii(r->res_name[i]) || !isprint(r->res_name[i])) 264 + print_name = 0; 265 + } 266 + 267 + seq_printf(s, "%s", print_name ? "str " : "hex"); 268 + 269 + for (i = 0; i < r->res_length; i++) { 270 + if (print_name) 271 + seq_printf(s, "%c", r->res_name[i]); 272 + else 273 + seq_printf(s, " %02x", (unsigned char)r->res_name[i]); 274 + } 275 + seq_printf(s, "\n"); 276 + 277 + if (!r->res_lvbptr) 278 + goto do_locks; 279 + 280 + seq_printf(s, "lvb %u %d", r->res_lvbseq, lvblen); 281 + 282 + for (i = 0; i < lvblen; i++) 283 + seq_printf(s, " %02x", (unsigned char)r->res_lvbptr[i]); 284 + seq_printf(s, "\n"); 285 + 286 + do_locks: 287 + list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue) 288 + print_format3_lock(s, lkb, 0); 289 + 290 + list_for_each_entry(lkb, &r->res_convertqueue, lkb_statequeue) 291 + print_format3_lock(s, lkb, 0); 292 + 293 + list_for_each_entry(lkb, &r->res_waitqueue, lkb_statequeue) 294 + print_format3_lock(s, lkb, 0); 295 + 296 + list_for_each_entry(lkb, &r->res_lookup, lkb_rsb_lookup) 297 + print_format3_lock(s, lkb, 1); 211 298 212 299 unlock_rsb(r); 213 300 return 0; ··· 320 231 break; 321 232 } 322 233 read_unlock(&ls->ls_rsbtbl[i].lock); 323 - } 234 + } 324 235 ri->entry = i; 325 236 326 237 if (ri->entry >= ls->ls_rsbtbl_size) ··· 337 248 read_unlock(&ls->ls_rsbtbl[i].lock); 338 249 dlm_put_rsb(old); 339 250 goto top; 340 - } 251 + } 341 252 ri->rsb = list_entry(ri->next, struct dlm_rsb, res_hashchain); 342 253 dlm_hold_rsb(ri->rsb); 343 254 read_unlock(&ls->ls_rsbtbl[i].lock); ··· 363 274 ri->ls = ls; 364 275 ri->entry = 0; 365 276 ri->next = NULL; 277 + ri->format = 1; 366 278 367 279 if (rsb_iter_next(ri)) { 368 280 rsb_iter_free(ri); ··· 415 325 { 416 326 struct rsb_iter *ri = iter_ptr; 417 327 418 - if (ri->locks) { 328 + switch (ri->format) { 329 + case 1: 330 + print_format1(ri->rsb, file); 331 + break; 332 + case 2: 419 333 if (ri->header) { 420 - seq_printf(file, "id nodeid remid pid xid exflags flags " 421 - "sts grmode rqmode time_ms r_nodeid " 422 - "r_len r_name\n"); 334 + seq_printf(file, "id nodeid remid pid xid exflags " 335 + "flags sts grmode rqmode time_ms " 336 + "r_nodeid r_len r_name\n"); 423 337 ri->header = 0; 424 338 } 425 - print_locks(ri->rsb, file); 426 - } else { 427 - print_resource(ri->rsb, file); 339 + print_format2(ri->rsb, file); 340 + break; 341 + case 3: 342 + if (ri->header) { 343 + seq_printf(file, "version rsb 1.1 lvb 1.1 lkb 1.1\n"); 344 + ri->header = 0; 345 + } 346 + print_format3(ri->rsb, file); 347 + break; 428 348 } 429 349 430 350 return 0; ··· 485 385 ri->ls = ls; 486 386 ri->entry = 0; 487 387 ri->next = NULL; 488 - ri->locks = 1; 388 + ri->format = 2; 489 389 490 390 if (*pos == 0) 491 391 ri->header = 1; ··· 548 448 }; 549 449 550 450 /* 451 + * Dump all rsb/lvb/lkb state in compact listing, more complete than _locks 452 + * This can replace both formats 1 and 2 eventually. 453 + */ 454 + 455 + static struct rsb_iter *all_iter_init(struct dlm_ls *ls, loff_t *pos) 456 + { 457 + struct rsb_iter *ri; 458 + 459 + ri = kzalloc(sizeof *ri, GFP_KERNEL); 460 + if (!ri) 461 + return NULL; 462 + 463 + ri->ls = ls; 464 + ri->entry = 0; 465 + ri->next = NULL; 466 + ri->format = 3; 467 + 468 + if (*pos == 0) 469 + ri->header = 1; 470 + 471 + if (rsb_iter_next(ri)) { 472 + rsb_iter_free(ri); 473 + return NULL; 474 + } 475 + 476 + return ri; 477 + } 478 + 479 + static void *all_seq_start(struct seq_file *file, loff_t *pos) 480 + { 481 + struct rsb_iter *ri; 482 + loff_t n = *pos; 483 + 484 + ri = all_iter_init(file->private, pos); 485 + if (!ri) 486 + return NULL; 487 + 488 + while (n--) { 489 + if (rsb_iter_next(ri)) { 490 + rsb_iter_free(ri); 491 + return NULL; 492 + } 493 + } 494 + 495 + return ri; 496 + } 497 + 498 + static struct seq_operations all_seq_ops = { 499 + .start = all_seq_start, 500 + .next = rsb_seq_next, 501 + .stop = rsb_seq_stop, 502 + .show = rsb_seq_show, 503 + }; 504 + 505 + static int all_open(struct inode *inode, struct file *file) 506 + { 507 + struct seq_file *seq; 508 + int ret; 509 + 510 + ret = seq_open(file, &all_seq_ops); 511 + if (ret) 512 + return ret; 513 + 514 + seq = file->private_data; 515 + seq->private = inode->i_private; 516 + 517 + return 0; 518 + } 519 + 520 + static const struct file_operations all_fops = { 521 + .owner = THIS_MODULE, 522 + .open = all_open, 523 + .read = seq_read, 524 + .llseek = seq_lseek, 525 + .release = seq_release 526 + }; 527 + 528 + /* 551 529 * dump lkb's on the ls_waiters list 552 530 */ 553 531 ··· 667 489 .read = waiters_read 668 490 }; 669 491 492 + void dlm_delete_debug_file(struct dlm_ls *ls) 493 + { 494 + if (ls->ls_debug_rsb_dentry) 495 + debugfs_remove(ls->ls_debug_rsb_dentry); 496 + if (ls->ls_debug_waiters_dentry) 497 + debugfs_remove(ls->ls_debug_waiters_dentry); 498 + if (ls->ls_debug_locks_dentry) 499 + debugfs_remove(ls->ls_debug_locks_dentry); 500 + if (ls->ls_debug_all_dentry) 501 + debugfs_remove(ls->ls_debug_all_dentry); 502 + } 503 + 670 504 int dlm_create_debug_file(struct dlm_ls *ls) 671 505 { 672 506 char name[DLM_LOCKSPACE_LEN+8]; 507 + 508 + /* format 1 */ 673 509 674 510 ls->ls_debug_rsb_dentry = debugfs_create_file(ls->ls_name, 675 511 S_IFREG | S_IRUGO, ··· 691 499 ls, 692 500 &rsb_fops); 693 501 if (!ls->ls_debug_rsb_dentry) 694 - return -ENOMEM; 502 + goto fail; 695 503 696 - memset(name, 0, sizeof(name)); 697 - snprintf(name, DLM_LOCKSPACE_LEN+8, "%s_waiters", ls->ls_name); 698 - 699 - ls->ls_debug_waiters_dentry = debugfs_create_file(name, 700 - S_IFREG | S_IRUGO, 701 - dlm_root, 702 - ls, 703 - &waiters_fops); 704 - if (!ls->ls_debug_waiters_dentry) { 705 - debugfs_remove(ls->ls_debug_rsb_dentry); 706 - return -ENOMEM; 707 - } 504 + /* format 2 */ 708 505 709 506 memset(name, 0, sizeof(name)); 710 507 snprintf(name, DLM_LOCKSPACE_LEN+8, "%s_locks", ls->ls_name); ··· 703 522 dlm_root, 704 523 ls, 705 524 &locks_fops); 706 - if (!ls->ls_debug_locks_dentry) { 707 - debugfs_remove(ls->ls_debug_waiters_dentry); 708 - debugfs_remove(ls->ls_debug_rsb_dentry); 709 - return -ENOMEM; 710 - } 525 + if (!ls->ls_debug_locks_dentry) 526 + goto fail; 527 + 528 + /* format 3 */ 529 + 530 + memset(name, 0, sizeof(name)); 531 + snprintf(name, DLM_LOCKSPACE_LEN+8, "%s_all", ls->ls_name); 532 + 533 + ls->ls_debug_all_dentry = debugfs_create_file(name, 534 + S_IFREG | S_IRUGO, 535 + dlm_root, 536 + ls, 537 + &all_fops); 538 + if (!ls->ls_debug_all_dentry) 539 + goto fail; 540 + 541 + memset(name, 0, sizeof(name)); 542 + snprintf(name, DLM_LOCKSPACE_LEN+8, "%s_waiters", ls->ls_name); 543 + 544 + ls->ls_debug_waiters_dentry = debugfs_create_file(name, 545 + S_IFREG | S_IRUGO, 546 + dlm_root, 547 + ls, 548 + &waiters_fops); 549 + if (!ls->ls_debug_waiters_dentry) 550 + goto fail; 711 551 712 552 return 0; 713 - } 714 553 715 - void dlm_delete_debug_file(struct dlm_ls *ls) 716 - { 717 - if (ls->ls_debug_rsb_dentry) 718 - debugfs_remove(ls->ls_debug_rsb_dentry); 719 - if (ls->ls_debug_waiters_dentry) 720 - debugfs_remove(ls->ls_debug_waiters_dentry); 721 - if (ls->ls_debug_locks_dentry) 722 - debugfs_remove(ls->ls_debug_locks_dentry); 554 + fail: 555 + dlm_delete_debug_file(ls); 556 + return -ENOMEM; 723 557 } 724 558 725 559 int __init dlm_register_debugfs(void)
+1
fs/dlm/dlm_internal.h
··· 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;