27 #include <linux/types.h>
28 #include <linux/slab.h>
30 #include <linux/sysctl.h>
33 #include <linux/export.h>
44 #define MLOG_MASK_PREFIX ML_DLM
47 static int stringify_lockname(
const char *lockname,
int locklen,
char *
buf,
62 printk(
" refmap nodes: [ ");
74 static void __dlm_print_lock(
struct dlm_lock *lock)
78 printk(
" type=%d, conv=%d, node=%u, cookie=%u:%llu, "
79 "ref=%u, ast=(empty=%c,pend=%c), bast=(empty=%c,pend=%c), "
80 "pending=(conv=%c,lock=%c,cancel=%c,unlock=%c)\n",
81 lock->
ml.type, lock->
ml.convert_type, lock->
ml.node,
85 (list_empty(&lock->
ast_list) ?
'y' :
'n'),
87 (list_empty(&lock->
bast_list) ?
'y' :
'n'),
107 printk(
"lockres: %s, owner=%u, state=%u\n",
109 printk(
" last used: %lu, refcnt: %u, on purge list: %s\n",
111 list_empty(&res->
purge) ?
"no" :
"yes");
112 printk(
" on dirty list: %s, on reco list: %s, "
113 "migrating pending: %s\n",
114 list_empty(&res->
dirty) ?
"no" :
"yes",
117 printk(
" inflight locks: %d, asts reserved: %d\n",
119 dlm_print_lockres_refmap(res);
120 printk(
" granted queue:\n");
123 __dlm_print_lock(lock);
125 printk(
" converting queue:\n");
128 __dlm_print_lock(lock);
130 printk(
" blocked queue:\n");
133 __dlm_print_lock(lock);
143 static const char *dlm_errnames[] = {
188 static const char *dlm_errmsgs[] = {
201 [
DLM_SYNC] =
"synchronous request granted",
210 [
DLM_NOTQUEUED] =
"NOQUEUE was specified and request failed",
215 [
DLM_REJECTED] =
"request rejected, unrecognized client",
216 [
DLM_ABORT] =
"blocked lock request cancelled",
217 [
DLM_CANCEL] =
"conversion request cancelled",
219 [
DLM_DEADLOCK] =
"deadlock recovery refused this request",
221 [
DLM_FORWARD] =
"request must wait for primary's response",
222 [
DLM_TIMEOUT] =
"timeout value for lock has expired",
237 return dlm_errmsgs[
err];
245 return dlm_errnames[
err];
255 static int stringify_lockname(
const char *lockname,
int locklen,
char *
buf,
261 #define OCFS2_DENTRY_LOCK_INO_START 18
262 if (*lockname ==
'N') {
264 (
char *)&lockname[OCFS2_DENTRY_LOCK_INO_START],
266 out +=
snprintf(buf + out, len - out,
"%.*s%08x",
267 OCFS2_DENTRY_LOCK_INO_START - 1, lockname,
270 out +=
snprintf(buf + out, len - out,
"%.*s",
275 static int stringify_nodemap(
unsigned long *nodemap,
int maxnodes,
281 while ((i =
find_next_bit(nodemap, maxnodes, i + 1)) < maxnodes)
282 out +=
snprintf(buf + out, len - out,
"%d ", i);
299 out += stringify_lockname(mle->
mname, mle->
mnamelen, buf + out, len - out);
300 out +=
snprintf(buf + out, len - out,
301 "\t%3s\tmas=%3u\tnew=%3u\tevt=%1d\tuse=%1d\tref=%3d\n",
307 out +=
snprintf(buf + out, len - out,
"Maybe=");
309 buf + out, len - out);
310 out +=
snprintf(buf + out, len - out,
"\n");
312 out +=
snprintf(buf + out, len - out,
"Vote=");
314 buf + out, len - out);
315 out +=
snprintf(buf + out, len - out,
"\n");
317 out +=
snprintf(buf + out, len - out,
"Response=");
319 buf + out, len - out);
320 out +=
snprintf(buf + out, len - out,
"\n");
322 out +=
snprintf(buf + out, len - out,
"Node=");
324 buf + out, len - out);
325 out +=
snprintf(buf + out, len - out,
"\n");
327 out +=
snprintf(buf + out, len - out,
"\n");
343 #ifdef CONFIG_DEBUG_FS
345 static struct dentry *dlm_debugfs_root =
NULL;
347 #define DLM_DEBUGFS_DIR "o2dlm"
348 #define DLM_DEBUGFS_DLM_STATE "dlm_state"
349 #define DLM_DEBUGFS_LOCKING_STATE "locking_state"
350 #define DLM_DEBUGFS_MLE_STATE "mle_state"
351 #define DLM_DEBUGFS_PURGE_LIST "purge_list"
354 static void dlm_debug_free(
struct kref *
kref)
356 struct dlm_debug_ctxt *
dc;
358 dc =
container_of(kref,
struct dlm_debug_ctxt, debug_refcnt);
363 static void dlm_debug_put(
struct dlm_debug_ctxt *
dc)
366 kref_put(&dc->debug_refcnt, dlm_debug_free);
369 static void dlm_debug_get(
struct dlm_debug_ctxt *dc)
371 kref_get(&dc->debug_refcnt);
380 static ssize_t debug_read(
struct file *file,
char __user *buf,
381 size_t nbytes, loff_t *ppos)
389 static int debug_purgelist_print(
struct dlm_ctxt *
dlm,
char *buf,
int len)
393 unsigned long total = 0;
395 out +=
snprintf(buf + out, len - out,
396 "Dumping Purgelist for Domain: %s\n", dlm->
name);
404 out += stringify_lockname(res->
lockname.name,
406 buf + out, len - out);
407 out +=
snprintf(buf + out, len - out,
"\t%ld\n",
413 out +=
snprintf(buf + out, len - out,
"Total on list: %ld\n", total);
418 static int debug_purgelist_open(
struct inode *inode,
struct file *file)
427 i_size_write(inode, debug_purgelist_print(dlm, buf,
PAGE_SIZE - 1));
437 .
open = debug_purgelist_open,
438 .release = debug_release,
445 static int debug_mle_print(
struct dlm_ctxt *dlm,
char *buf,
int len)
451 unsigned long total = 0, longest = 0, bucket_count = 0;
453 out +=
snprintf(buf + out, len - out,
454 "Dumping MLEs for Domain: %s\n", dlm->
name);
458 bucket = dlm_master_hash(dlm, i);
466 out += dump_mle(mle, buf + out, len - out);
468 longest =
max(longest, bucket_count);
473 out +=
snprintf(buf + out, len - out,
474 "Total: %ld, Longest: %ld\n", total, longest);
478 static int debug_mle_open(
struct inode *inode,
struct file *file)
487 i_size_write(inode, debug_mle_print(dlm, buf,
PAGE_SIZE - 1));
497 .
open = debug_mle_open,
498 .release = debug_release,
506 static int dump_lock(
struct dlm_lock *lock,
int list_type,
char *buf,
int len)
510 #define DEBUG_LOCK_VERSION 1
512 out =
snprintf(buf, len,
"LOCK:%d,%d,%d,%d,%d,%d:%lld,%d,%d,%d,%d,%d,"
515 list_type, lock->
ml.type, lock->
ml.convert_type,
536 out +=
snprintf(buf + out, len - out,
"NAME:");
538 buf + out, len - out);
539 out +=
snprintf(buf + out, len - out,
"\n");
541 #define DEBUG_LRES_VERSION 1
542 out +=
snprintf(buf + out, len - out,
543 "LRES:%d,%d,%d,%ld,%d,%d,%d,%d,%d,%d,%d\n",
546 !list_empty(&res->
purge),
547 !list_empty(&res->
dirty),
554 out +=
snprintf(buf + out, len - out,
"RMAP:");
556 buf + out, len - out);
557 out +=
snprintf(buf + out, len - out,
"\n");
560 out +=
snprintf(buf + out, len - out,
"LVBX:");
562 out +=
snprintf(buf + out, len - out,
563 "%02x", (
unsigned char)res->
lvb[i]);
564 out +=
snprintf(buf + out, len - out,
"\n");
568 out += dump_lock(lock, 0, buf + out, len - out);
572 out += dump_lock(lock, 1, buf + out, len - out);
576 out += dump_lock(lock, 2, buf + out, len - out);
578 out +=
snprintf(buf + out, len - out, "\
n");
585 struct debug_lockres *
dl = m->private;
596 if (list_empty(track_list)) {
607 dlm_lockres_get(res);
619 dump_lockres(res, dl->dl_buf, dl->dl_len - 1);
629 static void lockres_seq_stop(
struct seq_file *m,
void *
v)
633 static void *lockres_seq_next(
struct seq_file *m,
void *
v, loff_t *pos)
638 static int lockres_seq_show(
struct seq_file *
s,
void *
v)
640 struct debug_lockres *dl = (
struct debug_lockres *)v;
648 .
start = lockres_seq_start,
649 .stop = lockres_seq_stop,
650 .next = lockres_seq_next,
651 .show = lockres_seq_show,
654 static int debug_lockres_open(
struct inode *inode,
struct file *file)
659 struct debug_lockres *dl =
NULL;
661 dl = kzalloc(
sizeof(
struct debug_lockres),
GFP_KERNEL);
674 ret =
seq_open(file, &debug_lockres_ops);
694 static int debug_lockres_release(
struct inode *inode,
struct file *file)
697 struct debug_lockres *dl = (
struct debug_lockres *)seq->
private;
707 .
open = debug_lockres_open,
708 .release = debug_lockres_release,
715 static int debug_state_print(
struct dlm_ctxt *dlm,
char *buf,
int len)
720 int cur_mles = 0, tot_mles = 0;
727 state =
"NEW";
break;
729 state =
"JOINED";
break;
731 state =
"SHUTDOWN";
break;
733 state =
"LEAVING";
break;
735 state =
"UNKNOWN";
break;
739 out +=
snprintf(buf + out, len - out,
740 "Domain: %s Key: 0x%08x Protocol: %d.%d\n",
745 out +=
snprintf(buf + out, len - out,
746 "Thread Pid: %d Node: %d State: %s\n",
750 out +=
snprintf(buf + out, len - out,
751 "Number of Joins: %d Joining Node: %d\n",
755 out +=
snprintf(buf + out, len - out,
"Domain Map: ");
757 buf + out, len - out);
758 out +=
snprintf(buf + out, len - out,
"\n");
761 out +=
snprintf(buf + out, len - out,
"Exit Domain Map: ");
763 buf + out, len - out);
764 out +=
snprintf(buf + out, len - out,
"\n");
767 out +=
snprintf(buf + out, len - out,
"Live Map: ");
769 buf + out, len - out);
770 out +=
snprintf(buf + out, len - out,
"\n");
773 out +=
snprintf(buf + out, len - out,
774 "Lock Resources: %d (%d)\n",
785 out +=
snprintf(buf + out, len - out,
786 "MLEs: %d (%d)\n", cur_mles, tot_mles);
789 out +=
snprintf(buf + out, len - out,
790 " Blocking: %d (%d)\n",
795 out +=
snprintf(buf + out, len - out,
796 " Mastery: %d (%d)\n",
801 out +=
snprintf(buf + out, len - out,
802 " Migration: %d (%d)\n",
807 out +=
snprintf(buf + out, len - out,
808 "Lists: Dirty=%s Purge=%s PendingASTs=%s "
810 (list_empty(&dlm->
dirty_list) ?
"Empty" :
"InUse"),
811 (list_empty(&dlm->
purge_list) ?
"Empty" :
"InUse"),
816 out +=
snprintf(buf + out, len - out,
821 out +=
snprintf(buf + out, len - out,
822 "Dead Node: %d\n", dlm->
reco.dead_node);
831 out +=
snprintf(buf + out, len - out,
832 "Recovery Pid: %d Master: %d State: %s\n",
834 dlm->
reco.new_master, state);
837 out +=
snprintf(buf + out, len - out,
"Recovery Map: ");
839 buf + out, len - out);
840 out +=
snprintf(buf + out, len - out,
"\n");
843 out +=
snprintf(buf + out, len - out,
"Recovery Node State:\n");
845 switch (node->
state) {
850 state =
"REQUESTING";
865 state =
"FINALIZE-SENT";
871 out +=
snprintf(buf + out, len - out,
"\t%u - %s\n",
880 static int debug_state_open(
struct inode *inode,
struct file *file)
889 i_size_write(inode, debug_state_print(dlm, buf,
PAGE_SIZE - 1));
899 .
open = debug_state_open,
900 .release = debug_release,
907 int dlm_debug_init(
struct dlm_ctxt *dlm)
915 dlm, &debug_state_fops);
916 if (!dc->debug_state_dentry) {
922 dc->debug_lockres_dentry =
926 dlm, &debug_lockres_fops);
927 if (!dc->debug_lockres_dentry) {
936 dlm, &debug_mle_fops);
937 if (!dc->debug_mle_dentry) {
943 dc->debug_purgelist_dentry =
947 dlm, &debug_purgelist_fops);
948 if (!dc->debug_purgelist_dentry) {
957 dlm_debug_shutdown(dlm);
961 void dlm_debug_shutdown(
struct dlm_ctxt *dlm)
975 int dlm_create_debugfs_subroot(
struct dlm_ctxt *dlm)
994 dlm_destroy_debugfs_subroot(dlm);
998 void dlm_destroy_debugfs_subroot(
struct dlm_ctxt *dlm)
1004 int dlm_create_debugfs_root(
void)
1007 if (!dlm_debugfs_root) {
1014 void dlm_destroy_debugfs_root(
void)