1 // SPDX-License-Identifier: GPL-2.0-or-later
5 * debug functionality for the dlm
7 * Copyright (C) 2004, 2008 Oracle. All rights reserved.
10 #include <linux/types.h>
11 #include <linux/slab.h>
12 #include <linux/highmem.h>
13 #include <linux/sysctl.h>
14 #include <linux/spinlock.h>
15 #include <linux/debugfs.h>
16 #include <linux/export.h>
18 #include "../cluster/heartbeat.h"
19 #include "../cluster/nodemanager.h"
20 #include "../cluster/tcp.h"
23 #include "dlmcommon.h"
24 #include "dlmdomain.h"
27 #define MLOG_MASK_PREFIX ML_DLM
28 #include "../cluster/masklog.h"
30 static int stringify_lockname(const char *lockname
, int locklen
, char *buf
,
33 void dlm_print_one_lock_resource(struct dlm_lock_resource
*res
)
35 spin_lock(&res
->spinlock
);
36 __dlm_print_one_lock_resource(res
);
37 spin_unlock(&res
->spinlock
);
40 static void dlm_print_lockres_refmap(struct dlm_lock_resource
*res
)
43 assert_spin_locked(&res
->spinlock
);
45 printk(" refmap nodes: [ ");
48 bit
= find_next_bit(res
->refmap
, O2NM_MAX_NODES
, bit
);
49 if (bit
>= O2NM_MAX_NODES
)
54 printk("], inflight=%u\n", res
->inflight_locks
);
57 static void __dlm_print_lock(struct dlm_lock
*lock
)
59 spin_lock(&lock
->spinlock
);
61 printk(" type=%d, conv=%d, node=%u, cookie=%u:%llu, "
62 "ref=%u, ast=(empty=%c,pend=%c), bast=(empty=%c,pend=%c), "
63 "pending=(conv=%c,lock=%c,cancel=%c,unlock=%c)\n",
64 lock
->ml
.type
, lock
->ml
.convert_type
, lock
->ml
.node
,
65 dlm_get_lock_cookie_node(be64_to_cpu(lock
->ml
.cookie
)),
66 dlm_get_lock_cookie_seq(be64_to_cpu(lock
->ml
.cookie
)),
67 kref_read(&lock
->lock_refs
),
68 (list_empty(&lock
->ast_list
) ? 'y' : 'n'),
69 (lock
->ast_pending
? 'y' : 'n'),
70 (list_empty(&lock
->bast_list
) ? 'y' : 'n'),
71 (lock
->bast_pending
? 'y' : 'n'),
72 (lock
->convert_pending
? 'y' : 'n'),
73 (lock
->lock_pending
? 'y' : 'n'),
74 (lock
->cancel_pending
? 'y' : 'n'),
75 (lock
->unlock_pending
? 'y' : 'n'));
77 spin_unlock(&lock
->spinlock
);
80 void __dlm_print_one_lock_resource(struct dlm_lock_resource
*res
)
82 struct dlm_lock
*lock
;
83 char buf
[DLM_LOCKID_NAME_MAX
];
85 assert_spin_locked(&res
->spinlock
);
87 stringify_lockname(res
->lockname
.name
, res
->lockname
.len
,
89 printk("lockres: %s, owner=%u, state=%u\n",
90 buf
, res
->owner
, res
->state
);
91 printk(" last used: %lu, refcnt: %u, on purge list: %s\n",
92 res
->last_used
, kref_read(&res
->refs
),
93 list_empty(&res
->purge
) ? "no" : "yes");
94 printk(" on dirty list: %s, on reco list: %s, "
95 "migrating pending: %s\n",
96 list_empty(&res
->dirty
) ? "no" : "yes",
97 list_empty(&res
->recovering
) ? "no" : "yes",
98 res
->migration_pending
? "yes" : "no");
99 printk(" inflight locks: %d, asts reserved: %d\n",
100 res
->inflight_locks
, atomic_read(&res
->asts_reserved
));
101 dlm_print_lockres_refmap(res
);
102 printk(" granted queue:\n");
103 list_for_each_entry(lock
, &res
->granted
, list
) {
104 __dlm_print_lock(lock
);
106 printk(" converting queue:\n");
107 list_for_each_entry(lock
, &res
->converting
, list
) {
108 __dlm_print_lock(lock
);
110 printk(" blocked queue:\n");
111 list_for_each_entry(lock
, &res
->blocked
, list
) {
112 __dlm_print_lock(lock
);
116 void dlm_print_one_lock(struct dlm_lock
*lockid
)
118 dlm_print_one_lock_resource(lockid
->lockres
);
120 EXPORT_SYMBOL_GPL(dlm_print_one_lock
);
122 static const char *dlm_errnames
[] = {
123 [DLM_NORMAL
] = "DLM_NORMAL",
124 [DLM_GRANTED
] = "DLM_GRANTED",
125 [DLM_DENIED
] = "DLM_DENIED",
126 [DLM_DENIED_NOLOCKS
] = "DLM_DENIED_NOLOCKS",
127 [DLM_WORKING
] = "DLM_WORKING",
128 [DLM_BLOCKED
] = "DLM_BLOCKED",
129 [DLM_BLOCKED_ORPHAN
] = "DLM_BLOCKED_ORPHAN",
130 [DLM_DENIED_GRACE_PERIOD
] = "DLM_DENIED_GRACE_PERIOD",
131 [DLM_SYSERR
] = "DLM_SYSERR",
132 [DLM_NOSUPPORT
] = "DLM_NOSUPPORT",
133 [DLM_CANCELGRANT
] = "DLM_CANCELGRANT",
134 [DLM_IVLOCKID
] = "DLM_IVLOCKID",
135 [DLM_SYNC
] = "DLM_SYNC",
136 [DLM_BADTYPE
] = "DLM_BADTYPE",
137 [DLM_BADRESOURCE
] = "DLM_BADRESOURCE",
138 [DLM_MAXHANDLES
] = "DLM_MAXHANDLES",
139 [DLM_NOCLINFO
] = "DLM_NOCLINFO",
140 [DLM_NOLOCKMGR
] = "DLM_NOLOCKMGR",
141 [DLM_NOPURGED
] = "DLM_NOPURGED",
142 [DLM_BADARGS
] = "DLM_BADARGS",
143 [DLM_VOID
] = "DLM_VOID",
144 [DLM_NOTQUEUED
] = "DLM_NOTQUEUED",
145 [DLM_IVBUFLEN
] = "DLM_IVBUFLEN",
146 [DLM_CVTUNGRANT
] = "DLM_CVTUNGRANT",
147 [DLM_BADPARAM
] = "DLM_BADPARAM",
148 [DLM_VALNOTVALID
] = "DLM_VALNOTVALID",
149 [DLM_REJECTED
] = "DLM_REJECTED",
150 [DLM_ABORT
] = "DLM_ABORT",
151 [DLM_CANCEL
] = "DLM_CANCEL",
152 [DLM_IVRESHANDLE
] = "DLM_IVRESHANDLE",
153 [DLM_DEADLOCK
] = "DLM_DEADLOCK",
154 [DLM_DENIED_NOASTS
] = "DLM_DENIED_NOASTS",
155 [DLM_FORWARD
] = "DLM_FORWARD",
156 [DLM_TIMEOUT
] = "DLM_TIMEOUT",
157 [DLM_IVGROUPID
] = "DLM_IVGROUPID",
158 [DLM_VERS_CONFLICT
] = "DLM_VERS_CONFLICT",
159 [DLM_BAD_DEVICE_PATH
] = "DLM_BAD_DEVICE_PATH",
160 [DLM_NO_DEVICE_PERMISSION
] = "DLM_NO_DEVICE_PERMISSION",
161 [DLM_NO_CONTROL_DEVICE
] = "DLM_NO_CONTROL_DEVICE ",
162 [DLM_RECOVERING
] = "DLM_RECOVERING",
163 [DLM_MIGRATING
] = "DLM_MIGRATING",
164 [DLM_MAXSTATS
] = "DLM_MAXSTATS",
167 const char *dlm_errname(enum dlm_status err
)
169 if (err
>= DLM_MAXSTATS
|| err
< 0)
170 return dlm_errnames
[DLM_MAXSTATS
];
171 return dlm_errnames
[err
];
173 EXPORT_SYMBOL_GPL(dlm_errname
);
175 /* NOTE: This function converts a lockname into a string. It uses knowledge
176 * of the format of the lockname that should be outside the purview of the dlm.
177 * We are adding only to make dlm debugging slightly easier.
179 * For more on lockname formats, please refer to dlmglue.c and ocfs2_lockid.h.
181 static int stringify_lockname(const char *lockname
, int locklen
, char *buf
,
185 __be64 inode_blkno_be
;
187 #define OCFS2_DENTRY_LOCK_INO_START 18
188 if (*lockname
== 'N') {
189 memcpy((__be64
*)&inode_blkno_be
,
190 (char *)&lockname
[OCFS2_DENTRY_LOCK_INO_START
],
192 out
+= scnprintf(buf
+ out
, len
- out
, "%.*s%08x",
193 OCFS2_DENTRY_LOCK_INO_START
- 1, lockname
,
194 (unsigned int)be64_to_cpu(inode_blkno_be
));
196 out
+= scnprintf(buf
+ out
, len
- out
, "%.*s",
201 static int stringify_nodemap(unsigned long *nodemap
, int maxnodes
,
207 while ((i
= find_next_bit(nodemap
, maxnodes
, i
+ 1)) < maxnodes
)
208 out
+= scnprintf(buf
+ out
, len
- out
, "%d ", i
);
213 static int dump_mle(struct dlm_master_list_entry
*mle
, char *buf
, int len
)
218 if (mle
->type
== DLM_MLE_BLOCK
)
220 else if (mle
->type
== DLM_MLE_MASTER
)
225 out
+= stringify_lockname(mle
->mname
, mle
->mnamelen
, buf
+ out
, len
- out
);
226 out
+= scnprintf(buf
+ out
, len
- out
,
227 "\t%3s\tmas=%3u\tnew=%3u\tevt=%1d\tuse=%1d\tref=%3d\n",
228 mle_type
, mle
->master
, mle
->new_master
,
229 !list_empty(&mle
->hb_events
),
231 kref_read(&mle
->mle_refs
));
233 out
+= scnprintf(buf
+ out
, len
- out
, "Maybe=");
234 out
+= stringify_nodemap(mle
->maybe_map
, O2NM_MAX_NODES
,
235 buf
+ out
, len
- out
);
236 out
+= scnprintf(buf
+ out
, len
- out
, "\n");
238 out
+= scnprintf(buf
+ out
, len
- out
, "Vote=");
239 out
+= stringify_nodemap(mle
->vote_map
, O2NM_MAX_NODES
,
240 buf
+ out
, len
- out
);
241 out
+= scnprintf(buf
+ out
, len
- out
, "\n");
243 out
+= scnprintf(buf
+ out
, len
- out
, "Response=");
244 out
+= stringify_nodemap(mle
->response_map
, O2NM_MAX_NODES
,
245 buf
+ out
, len
- out
);
246 out
+= scnprintf(buf
+ out
, len
- out
, "\n");
248 out
+= scnprintf(buf
+ out
, len
- out
, "Node=");
249 out
+= stringify_nodemap(mle
->node_map
, O2NM_MAX_NODES
,
250 buf
+ out
, len
- out
);
251 out
+= scnprintf(buf
+ out
, len
- out
, "\n");
253 out
+= scnprintf(buf
+ out
, len
- out
, "\n");
258 void dlm_print_one_mle(struct dlm_master_list_entry
*mle
)
262 buf
= (char *) get_zeroed_page(GFP_ATOMIC
);
264 dump_mle(mle
, buf
, PAGE_SIZE
- 1);
265 free_page((unsigned long)buf
);
269 #ifdef CONFIG_DEBUG_FS
271 static struct dentry
*dlm_debugfs_root
;
273 #define DLM_DEBUGFS_DIR "o2dlm"
274 #define DLM_DEBUGFS_DLM_STATE "dlm_state"
275 #define DLM_DEBUGFS_LOCKING_STATE "locking_state"
276 #define DLM_DEBUGFS_MLE_STATE "mle_state"
277 #define DLM_DEBUGFS_PURGE_LIST "purge_list"
279 /* begin - utils funcs */
280 static int debug_release(struct inode
*inode
, struct file
*file
)
282 free_page((unsigned long)file
->private_data
);
286 static ssize_t
debug_read(struct file
*file
, char __user
*buf
,
287 size_t nbytes
, loff_t
*ppos
)
289 return simple_read_from_buffer(buf
, nbytes
, ppos
, file
->private_data
,
290 i_size_read(file
->f_mapping
->host
));
292 /* end - util funcs */
294 /* begin - purge list funcs */
295 static int debug_purgelist_print(struct dlm_ctxt
*dlm
, char *buf
, int len
)
297 struct dlm_lock_resource
*res
;
299 unsigned long total
= 0;
301 out
+= scnprintf(buf
+ out
, len
- out
,
302 "Dumping Purgelist for Domain: %s\n", dlm
->name
);
304 spin_lock(&dlm
->spinlock
);
305 list_for_each_entry(res
, &dlm
->purge_list
, purge
) {
309 spin_lock(&res
->spinlock
);
310 out
+= stringify_lockname(res
->lockname
.name
,
312 buf
+ out
, len
- out
);
313 out
+= scnprintf(buf
+ out
, len
- out
, "\t%ld\n",
314 (jiffies
- res
->last_used
)/HZ
);
315 spin_unlock(&res
->spinlock
);
317 spin_unlock(&dlm
->spinlock
);
319 out
+= scnprintf(buf
+ out
, len
- out
, "Total on list: %lu\n", total
);
324 static int debug_purgelist_open(struct inode
*inode
, struct file
*file
)
326 struct dlm_ctxt
*dlm
= inode
->i_private
;
329 buf
= (char *) get_zeroed_page(GFP_NOFS
);
333 i_size_write(inode
, debug_purgelist_print(dlm
, buf
, PAGE_SIZE
- 1));
335 file
->private_data
= buf
;
342 static const struct file_operations debug_purgelist_fops
= {
343 .open
= debug_purgelist_open
,
344 .release
= debug_release
,
346 .llseek
= generic_file_llseek
,
348 /* end - purge list funcs */
350 /* begin - debug mle funcs */
351 static int debug_mle_print(struct dlm_ctxt
*dlm
, char *buf
, int len
)
353 struct dlm_master_list_entry
*mle
;
354 struct hlist_head
*bucket
;
356 unsigned long total
= 0, longest
= 0, bucket_count
= 0;
358 out
+= scnprintf(buf
+ out
, len
- out
,
359 "Dumping MLEs for Domain: %s\n", dlm
->name
);
361 spin_lock(&dlm
->master_lock
);
362 for (i
= 0; i
< DLM_HASH_BUCKETS
; i
++) {
363 bucket
= dlm_master_hash(dlm
, i
);
364 hlist_for_each_entry(mle
, bucket
, master_hash_node
) {
369 out
+= dump_mle(mle
, buf
+ out
, len
- out
);
371 longest
= max(longest
, bucket_count
);
374 spin_unlock(&dlm
->master_lock
);
376 out
+= scnprintf(buf
+ out
, len
- out
,
377 "Total: %lu, Longest: %lu\n", total
, longest
);
381 static int debug_mle_open(struct inode
*inode
, struct file
*file
)
383 struct dlm_ctxt
*dlm
= inode
->i_private
;
386 buf
= (char *) get_zeroed_page(GFP_NOFS
);
390 i_size_write(inode
, debug_mle_print(dlm
, buf
, PAGE_SIZE
- 1));
392 file
->private_data
= buf
;
399 static const struct file_operations debug_mle_fops
= {
400 .open
= debug_mle_open
,
401 .release
= debug_release
,
403 .llseek
= generic_file_llseek
,
406 /* end - debug mle funcs */
408 /* begin - debug lockres funcs */
409 static int dump_lock(struct dlm_lock
*lock
, int list_type
, char *buf
, int len
)
413 #define DEBUG_LOCK_VERSION 1
414 spin_lock(&lock
->spinlock
);
415 out
= scnprintf(buf
, len
, "LOCK:%d,%d,%d,%d,%d,%d:%lld,%d,%d,%d,%d,%d,"
418 list_type
, lock
->ml
.type
, lock
->ml
.convert_type
,
420 dlm_get_lock_cookie_node(be64_to_cpu(lock
->ml
.cookie
)),
421 dlm_get_lock_cookie_seq(be64_to_cpu(lock
->ml
.cookie
)),
422 !list_empty(&lock
->ast_list
),
423 !list_empty(&lock
->bast_list
),
424 lock
->ast_pending
, lock
->bast_pending
,
425 lock
->convert_pending
, lock
->lock_pending
,
426 lock
->cancel_pending
, lock
->unlock_pending
,
427 kref_read(&lock
->lock_refs
));
428 spin_unlock(&lock
->spinlock
);
433 static int dump_lockres(struct dlm_lock_resource
*res
, char *buf
, int len
)
435 struct dlm_lock
*lock
;
439 out
+= scnprintf(buf
+ out
, len
- out
, "NAME:");
440 out
+= stringify_lockname(res
->lockname
.name
, res
->lockname
.len
,
441 buf
+ out
, len
- out
);
442 out
+= scnprintf(buf
+ out
, len
- out
, "\n");
444 #define DEBUG_LRES_VERSION 1
445 out
+= scnprintf(buf
+ out
, len
- out
,
446 "LRES:%d,%d,%d,%ld,%d,%d,%d,%d,%d,%d,%d\n",
448 res
->owner
, res
->state
, res
->last_used
,
449 !list_empty(&res
->purge
),
450 !list_empty(&res
->dirty
),
451 !list_empty(&res
->recovering
),
452 res
->inflight_locks
, res
->migration_pending
,
453 atomic_read(&res
->asts_reserved
),
454 kref_read(&res
->refs
));
457 out
+= scnprintf(buf
+ out
, len
- out
, "RMAP:");
458 out
+= stringify_nodemap(res
->refmap
, O2NM_MAX_NODES
,
459 buf
+ out
, len
- out
);
460 out
+= scnprintf(buf
+ out
, len
- out
, "\n");
463 out
+= scnprintf(buf
+ out
, len
- out
, "LVBX:");
464 for (i
= 0; i
< DLM_LVB_LEN
; i
++)
465 out
+= scnprintf(buf
+ out
, len
- out
,
466 "%02x", (unsigned char)res
->lvb
[i
]);
467 out
+= scnprintf(buf
+ out
, len
- out
, "\n");
470 list_for_each_entry(lock
, &res
->granted
, list
)
471 out
+= dump_lock(lock
, 0, buf
+ out
, len
- out
);
474 list_for_each_entry(lock
, &res
->converting
, list
)
475 out
+= dump_lock(lock
, 1, buf
+ out
, len
- out
);
478 list_for_each_entry(lock
, &res
->blocked
, list
)
479 out
+= dump_lock(lock
, 2, buf
+ out
, len
- out
);
481 out
+= scnprintf(buf
+ out
, len
- out
, "\n");
486 static void *lockres_seq_start(struct seq_file
*m
, loff_t
*pos
)
488 struct debug_lockres
*dl
= m
->private;
489 struct dlm_ctxt
*dlm
= dl
->dl_ctxt
;
490 struct dlm_lock_resource
*oldres
= dl
->dl_res
;
491 struct dlm_lock_resource
*res
= NULL
, *iter
;
492 struct list_head
*track_list
;
494 spin_lock(&dlm
->track_lock
);
496 track_list
= &oldres
->tracking
;
498 track_list
= &dlm
->tracking_list
;
499 if (list_empty(track_list
)) {
501 spin_unlock(&dlm
->track_lock
);
506 list_for_each_entry(iter
, track_list
, tracking
) {
507 if (&iter
->tracking
!= &dlm
->tracking_list
) {
508 dlm_lockres_get(iter
);
513 spin_unlock(&dlm
->track_lock
);
516 dlm_lockres_put(oldres
);
521 spin_lock(&res
->spinlock
);
522 dump_lockres(res
, dl
->dl_buf
, dl
->dl_len
- 1);
523 spin_unlock(&res
->spinlock
);
528 /* passed to seq_show */
532 static void lockres_seq_stop(struct seq_file
*m
, void *v
)
536 static void *lockres_seq_next(struct seq_file
*m
, void *v
, loff_t
*pos
)
541 static int lockres_seq_show(struct seq_file
*s
, void *v
)
543 struct debug_lockres
*dl
= (struct debug_lockres
*)v
;
545 seq_printf(s
, "%s", dl
->dl_buf
);
550 static const struct seq_operations debug_lockres_ops
= {
551 .start
= lockres_seq_start
,
552 .stop
= lockres_seq_stop
,
553 .next
= lockres_seq_next
,
554 .show
= lockres_seq_show
,
557 static int debug_lockres_open(struct inode
*inode
, struct file
*file
)
559 struct dlm_ctxt
*dlm
= inode
->i_private
;
560 struct debug_lockres
*dl
;
563 buf
= kmalloc(PAGE_SIZE
, GFP_KERNEL
);
567 dl
= __seq_open_private(file
, &debug_lockres_ops
, sizeof(*dl
));
571 dl
->dl_len
= PAGE_SIZE
;
586 static int debug_lockres_release(struct inode
*inode
, struct file
*file
)
588 struct seq_file
*seq
= file
->private_data
;
589 struct debug_lockres
*dl
= (struct debug_lockres
*)seq
->private;
592 dlm_lockres_put(dl
->dl_res
);
593 dlm_put(dl
->dl_ctxt
);
595 return seq_release_private(inode
, file
);
598 static const struct file_operations debug_lockres_fops
= {
599 .open
= debug_lockres_open
,
600 .release
= debug_lockres_release
,
604 /* end - debug lockres funcs */
606 /* begin - debug state funcs */
607 static int debug_state_print(struct dlm_ctxt
*dlm
, char *buf
, int len
)
610 struct dlm_reco_node_data
*node
;
612 int cur_mles
= 0, tot_mles
= 0;
615 spin_lock(&dlm
->spinlock
);
617 switch (dlm
->dlm_state
) {
619 state
= "NEW"; break;
620 case DLM_CTXT_JOINED
:
621 state
= "JOINED"; break;
622 case DLM_CTXT_IN_SHUTDOWN
:
623 state
= "SHUTDOWN"; break;
624 case DLM_CTXT_LEAVING
:
625 state
= "LEAVING"; break;
627 state
= "UNKNOWN"; break;
630 /* Domain: xxxxxxxxxx Key: 0xdfbac769 */
631 out
+= scnprintf(buf
+ out
, len
- out
,
632 "Domain: %s Key: 0x%08x Protocol: %d.%d\n",
633 dlm
->name
, dlm
->key
, dlm
->dlm_locking_proto
.pv_major
,
634 dlm
->dlm_locking_proto
.pv_minor
);
636 /* Thread Pid: xxx Node: xxx State: xxxxx */
637 out
+= scnprintf(buf
+ out
, len
- out
,
638 "Thread Pid: %d Node: %d State: %s\n",
639 task_pid_nr(dlm
->dlm_thread_task
), dlm
->node_num
, state
);
641 /* Number of Joins: xxx Joining Node: xxx */
642 out
+= scnprintf(buf
+ out
, len
- out
,
643 "Number of Joins: %d Joining Node: %d\n",
644 dlm
->num_joins
, dlm
->joining_node
);
646 /* Domain Map: xx xx xx */
647 out
+= scnprintf(buf
+ out
, len
- out
, "Domain Map: ");
648 out
+= stringify_nodemap(dlm
->domain_map
, O2NM_MAX_NODES
,
649 buf
+ out
, len
- out
);
650 out
+= scnprintf(buf
+ out
, len
- out
, "\n");
652 /* Exit Domain Map: xx xx xx */
653 out
+= scnprintf(buf
+ out
, len
- out
, "Exit Domain Map: ");
654 out
+= stringify_nodemap(dlm
->exit_domain_map
, O2NM_MAX_NODES
,
655 buf
+ out
, len
- out
);
656 out
+= scnprintf(buf
+ out
, len
- out
, "\n");
658 /* Live Map: xx xx xx */
659 out
+= scnprintf(buf
+ out
, len
- out
, "Live Map: ");
660 out
+= stringify_nodemap(dlm
->live_nodes_map
, O2NM_MAX_NODES
,
661 buf
+ out
, len
- out
);
662 out
+= scnprintf(buf
+ out
, len
- out
, "\n");
664 /* Lock Resources: xxx (xxx) */
665 out
+= scnprintf(buf
+ out
, len
- out
,
666 "Lock Resources: %d (%d)\n",
667 atomic_read(&dlm
->res_cur_count
),
668 atomic_read(&dlm
->res_tot_count
));
670 for (i
= 0; i
< DLM_MLE_NUM_TYPES
; ++i
)
671 tot_mles
+= atomic_read(&dlm
->mle_tot_count
[i
]);
673 for (i
= 0; i
< DLM_MLE_NUM_TYPES
; ++i
)
674 cur_mles
+= atomic_read(&dlm
->mle_cur_count
[i
]);
676 /* MLEs: xxx (xxx) */
677 out
+= scnprintf(buf
+ out
, len
- out
,
678 "MLEs: %d (%d)\n", cur_mles
, tot_mles
);
680 /* Blocking: xxx (xxx) */
681 out
+= scnprintf(buf
+ out
, len
- out
,
682 " Blocking: %d (%d)\n",
683 atomic_read(&dlm
->mle_cur_count
[DLM_MLE_BLOCK
]),
684 atomic_read(&dlm
->mle_tot_count
[DLM_MLE_BLOCK
]));
686 /* Mastery: xxx (xxx) */
687 out
+= scnprintf(buf
+ out
, len
- out
,
688 " Mastery: %d (%d)\n",
689 atomic_read(&dlm
->mle_cur_count
[DLM_MLE_MASTER
]),
690 atomic_read(&dlm
->mle_tot_count
[DLM_MLE_MASTER
]));
692 /* Migration: xxx (xxx) */
693 out
+= scnprintf(buf
+ out
, len
- out
,
694 " Migration: %d (%d)\n",
695 atomic_read(&dlm
->mle_cur_count
[DLM_MLE_MIGRATION
]),
696 atomic_read(&dlm
->mle_tot_count
[DLM_MLE_MIGRATION
]));
698 /* Lists: Dirty=Empty Purge=InUse PendingASTs=Empty ... */
699 out
+= scnprintf(buf
+ out
, len
- out
,
700 "Lists: Dirty=%s Purge=%s PendingASTs=%s "
702 (list_empty(&dlm
->dirty_list
) ? "Empty" : "InUse"),
703 (list_empty(&dlm
->purge_list
) ? "Empty" : "InUse"),
704 (list_empty(&dlm
->pending_asts
) ? "Empty" : "InUse"),
705 (list_empty(&dlm
->pending_basts
) ? "Empty" : "InUse"));
707 /* Purge Count: xxx Refs: xxx */
708 out
+= scnprintf(buf
+ out
, len
- out
,
709 "Purge Count: %d Refs: %d\n", dlm
->purge_count
,
710 kref_read(&dlm
->dlm_refs
));
713 out
+= scnprintf(buf
+ out
, len
- out
,
714 "Dead Node: %d\n", dlm
->reco
.dead_node
);
716 /* What about DLM_RECO_STATE_FINALIZE? */
717 if (dlm
->reco
.state
== DLM_RECO_STATE_ACTIVE
)
722 /* Recovery Pid: xxxx Master: xxx State: xxxx */
723 out
+= scnprintf(buf
+ out
, len
- out
,
724 "Recovery Pid: %d Master: %d State: %s\n",
725 task_pid_nr(dlm
->dlm_reco_thread_task
),
726 dlm
->reco
.new_master
, state
);
728 /* Recovery Map: xx xx */
729 out
+= scnprintf(buf
+ out
, len
- out
, "Recovery Map: ");
730 out
+= stringify_nodemap(dlm
->recovery_map
, O2NM_MAX_NODES
,
731 buf
+ out
, len
- out
);
732 out
+= scnprintf(buf
+ out
, len
- out
, "\n");
734 /* Recovery Node State: */
735 out
+= scnprintf(buf
+ out
, len
- out
, "Recovery Node State:\n");
736 list_for_each_entry(node
, &dlm
->reco
.node_data
, list
) {
737 switch (node
->state
) {
738 case DLM_RECO_NODE_DATA_INIT
:
741 case DLM_RECO_NODE_DATA_REQUESTING
:
742 state
= "REQUESTING";
744 case DLM_RECO_NODE_DATA_DEAD
:
747 case DLM_RECO_NODE_DATA_RECEIVING
:
750 case DLM_RECO_NODE_DATA_REQUESTED
:
753 case DLM_RECO_NODE_DATA_DONE
:
756 case DLM_RECO_NODE_DATA_FINALIZE_SENT
:
757 state
= "FINALIZE-SENT";
763 out
+= scnprintf(buf
+ out
, len
- out
, "\t%u - %s\n",
764 node
->node_num
, state
);
767 spin_unlock(&dlm
->spinlock
);
772 static int debug_state_open(struct inode
*inode
, struct file
*file
)
774 struct dlm_ctxt
*dlm
= inode
->i_private
;
777 buf
= (char *) get_zeroed_page(GFP_NOFS
);
781 i_size_write(inode
, debug_state_print(dlm
, buf
, PAGE_SIZE
- 1));
783 file
->private_data
= buf
;
790 static const struct file_operations debug_state_fops
= {
791 .open
= debug_state_open
,
792 .release
= debug_release
,
794 .llseek
= generic_file_llseek
,
796 /* end - debug state funcs */
798 /* files in subroot */
799 void dlm_debug_init(struct dlm_ctxt
*dlm
)
801 /* for dumping dlm_ctxt */
802 debugfs_create_file(DLM_DEBUGFS_DLM_STATE
, S_IFREG
|S_IRUSR
,
803 dlm
->dlm_debugfs_subroot
, dlm
, &debug_state_fops
);
805 /* for dumping lockres */
806 debugfs_create_file(DLM_DEBUGFS_LOCKING_STATE
, S_IFREG
|S_IRUSR
,
807 dlm
->dlm_debugfs_subroot
, dlm
, &debug_lockres_fops
);
809 /* for dumping mles */
810 debugfs_create_file(DLM_DEBUGFS_MLE_STATE
, S_IFREG
|S_IRUSR
,
811 dlm
->dlm_debugfs_subroot
, dlm
, &debug_mle_fops
);
813 /* for dumping lockres on the purge list */
814 debugfs_create_file(DLM_DEBUGFS_PURGE_LIST
, S_IFREG
|S_IRUSR
,
815 dlm
->dlm_debugfs_subroot
, dlm
,
816 &debug_purgelist_fops
);
819 /* subroot - domain dir */
820 void dlm_create_debugfs_subroot(struct dlm_ctxt
*dlm
)
822 dlm
->dlm_debugfs_subroot
= debugfs_create_dir(dlm
->name
,
826 void dlm_destroy_debugfs_subroot(struct dlm_ctxt
*dlm
)
828 debugfs_remove_recursive(dlm
->dlm_debugfs_subroot
);
832 void dlm_create_debugfs_root(void)
834 dlm_debugfs_root
= debugfs_create_dir(DLM_DEBUGFS_DIR
, NULL
);
837 void dlm_destroy_debugfs_root(void)
839 debugfs_remove(dlm_debugfs_root
);
841 #endif /* CONFIG_DEBUG_FS */