xref: /openbmc/linux/fs/ocfs2/dlm/dlmdebug.c (revision 828c0950)
16714d8e8SKurt Hackel /* -*- mode: c; c-basic-offset: 8; -*-
26714d8e8SKurt Hackel  * vim: noexpandtab sw=8 ts=8 sts=0:
36714d8e8SKurt Hackel  *
46714d8e8SKurt Hackel  * dlmdebug.c
56714d8e8SKurt Hackel  *
66714d8e8SKurt Hackel  * debug functionality for the dlm
76714d8e8SKurt Hackel  *
8c834cdb1SSunil Mushran  * Copyright (C) 2004, 2008 Oracle.  All rights reserved.
96714d8e8SKurt Hackel  *
106714d8e8SKurt Hackel  * This program is free software; you can redistribute it and/or
116714d8e8SKurt Hackel  * modify it under the terms of the GNU General Public
126714d8e8SKurt Hackel  * License as published by the Free Software Foundation; either
136714d8e8SKurt Hackel  * version 2 of the License, or (at your option) any later version.
146714d8e8SKurt Hackel  *
156714d8e8SKurt Hackel  * This program is distributed in the hope that it will be useful,
166714d8e8SKurt Hackel  * but WITHOUT ANY WARRANTY; without even the implied warranty of
176714d8e8SKurt Hackel  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
186714d8e8SKurt Hackel  * General Public License for more details.
196714d8e8SKurt Hackel  *
206714d8e8SKurt Hackel  * You should have received a copy of the GNU General Public
216714d8e8SKurt Hackel  * License along with this program; if not, write to the
226714d8e8SKurt Hackel  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
236714d8e8SKurt Hackel  * Boston, MA 021110-1307, USA.
246714d8e8SKurt Hackel  *
256714d8e8SKurt Hackel  */
266714d8e8SKurt Hackel 
276714d8e8SKurt Hackel #include <linux/types.h>
286714d8e8SKurt Hackel #include <linux/slab.h>
296714d8e8SKurt Hackel #include <linux/highmem.h>
306714d8e8SKurt Hackel #include <linux/sysctl.h>
316714d8e8SKurt Hackel #include <linux/spinlock.h>
326325b4a2SSunil Mushran #include <linux/debugfs.h>
336714d8e8SKurt Hackel 
346714d8e8SKurt Hackel #include "cluster/heartbeat.h"
356714d8e8SKurt Hackel #include "cluster/nodemanager.h"
366714d8e8SKurt Hackel #include "cluster/tcp.h"
376714d8e8SKurt Hackel 
386714d8e8SKurt Hackel #include "dlmapi.h"
396714d8e8SKurt Hackel #include "dlmcommon.h"
406714d8e8SKurt Hackel #include "dlmdomain.h"
416325b4a2SSunil Mushran #include "dlmdebug.h"
426714d8e8SKurt Hackel 
436714d8e8SKurt Hackel #define MLOG_MASK_PREFIX ML_DLM
446714d8e8SKurt Hackel #include "cluster/masklog.h"
456714d8e8SKurt Hackel 
4695642e56SAdrian Bunk static int stringify_lockname(const char *lockname, int locklen, char *buf,
4795642e56SAdrian Bunk 			      int len);
48c834cdb1SSunil Mushran 
496714d8e8SKurt Hackel void dlm_print_one_lock_resource(struct dlm_lock_resource *res)
506714d8e8SKurt Hackel {
516714d8e8SKurt Hackel 	spin_lock(&res->spinlock);
526714d8e8SKurt Hackel 	__dlm_print_one_lock_resource(res);
536714d8e8SKurt Hackel 	spin_unlock(&res->spinlock);
546714d8e8SKurt Hackel }
556714d8e8SKurt Hackel 
56ba2bf218SKurt Hackel static void dlm_print_lockres_refmap(struct dlm_lock_resource *res)
57ba2bf218SKurt Hackel {
58ba2bf218SKurt Hackel 	int bit;
59ba2bf218SKurt Hackel 	assert_spin_locked(&res->spinlock);
60ba2bf218SKurt Hackel 
618f50eb97SSunil Mushran 	printk("  refmap nodes: [ ");
62ba2bf218SKurt Hackel 	bit = 0;
63ba2bf218SKurt Hackel 	while (1) {
64ba2bf218SKurt Hackel 		bit = find_next_bit(res->refmap, O2NM_MAX_NODES, bit);
65ba2bf218SKurt Hackel 		if (bit >= O2NM_MAX_NODES)
66ba2bf218SKurt Hackel 			break;
678f50eb97SSunil Mushran 		printk("%u ", bit);
68ba2bf218SKurt Hackel 		bit++;
69ba2bf218SKurt Hackel 	}
708f50eb97SSunil Mushran 	printk("], inflight=%u\n", res->inflight_locks);
71c834cdb1SSunil Mushran }
72c834cdb1SSunil Mushran 
73c834cdb1SSunil Mushran static void __dlm_print_lock(struct dlm_lock *lock)
74c834cdb1SSunil Mushran {
75c834cdb1SSunil Mushran 	spin_lock(&lock->spinlock);
76c834cdb1SSunil Mushran 
778f50eb97SSunil Mushran 	printk("    type=%d, conv=%d, node=%u, cookie=%u:%llu, "
78c834cdb1SSunil Mushran 	       "ref=%u, ast=(empty=%c,pend=%c), bast=(empty=%c,pend=%c), "
79c834cdb1SSunil Mushran 	       "pending=(conv=%c,lock=%c,cancel=%c,unlock=%c)\n",
80c834cdb1SSunil Mushran 	       lock->ml.type, lock->ml.convert_type, lock->ml.node,
81c834cdb1SSunil Mushran 	       dlm_get_lock_cookie_node(be64_to_cpu(lock->ml.cookie)),
82c834cdb1SSunil Mushran 	       dlm_get_lock_cookie_seq(be64_to_cpu(lock->ml.cookie)),
83c834cdb1SSunil Mushran 	       atomic_read(&lock->lock_refs.refcount),
84c834cdb1SSunil Mushran 	       (list_empty(&lock->ast_list) ? 'y' : 'n'),
85c834cdb1SSunil Mushran 	       (lock->ast_pending ? 'y' : 'n'),
86c834cdb1SSunil Mushran 	       (list_empty(&lock->bast_list) ? 'y' : 'n'),
87c834cdb1SSunil Mushran 	       (lock->bast_pending ? 'y' : 'n'),
88c834cdb1SSunil Mushran 	       (lock->convert_pending ? 'y' : 'n'),
89c834cdb1SSunil Mushran 	       (lock->lock_pending ? 'y' : 'n'),
90c834cdb1SSunil Mushran 	       (lock->cancel_pending ? 'y' : 'n'),
91c834cdb1SSunil Mushran 	       (lock->unlock_pending ? 'y' : 'n'));
92c834cdb1SSunil Mushran 
93c834cdb1SSunil Mushran 	spin_unlock(&lock->spinlock);
94ba2bf218SKurt Hackel }
95ba2bf218SKurt Hackel 
966714d8e8SKurt Hackel void __dlm_print_one_lock_resource(struct dlm_lock_resource *res)
976714d8e8SKurt Hackel {
986714d8e8SKurt Hackel 	struct list_head *iter2;
996714d8e8SKurt Hackel 	struct dlm_lock *lock;
100c834cdb1SSunil Mushran 	char buf[DLM_LOCKID_NAME_MAX];
1016714d8e8SKurt Hackel 
1026714d8e8SKurt Hackel 	assert_spin_locked(&res->spinlock);
1036714d8e8SKurt Hackel 
104c834cdb1SSunil Mushran 	stringify_lockname(res->lockname.name, res->lockname.len,
105c834cdb1SSunil Mushran 			   buf, sizeof(buf) - 1);
1068f50eb97SSunil Mushran 	printk("lockres: %s, owner=%u, state=%u\n",
107c834cdb1SSunil Mushran 	       buf, res->owner, res->state);
1088f50eb97SSunil Mushran 	printk("  last used: %lu, refcnt: %u, on purge list: %s\n",
109c834cdb1SSunil Mushran 	       res->last_used, atomic_read(&res->refs.refcount),
110c834cdb1SSunil Mushran 	       list_empty(&res->purge) ? "no" : "yes");
1118f50eb97SSunil Mushran 	printk("  on dirty list: %s, on reco list: %s, "
112c834cdb1SSunil Mushran 	       "migrating pending: %s\n",
113c834cdb1SSunil Mushran 	       list_empty(&res->dirty) ? "no" : "yes",
114c834cdb1SSunil Mushran 	       list_empty(&res->recovering) ? "no" : "yes",
115c834cdb1SSunil Mushran 	       res->migration_pending ? "yes" : "no");
1168f50eb97SSunil Mushran 	printk("  inflight locks: %d, asts reserved: %d\n",
117c834cdb1SSunil Mushran 	       res->inflight_locks, atomic_read(&res->asts_reserved));
118ba2bf218SKurt Hackel 	dlm_print_lockres_refmap(res);
1198f50eb97SSunil Mushran 	printk("  granted queue:\n");
1206714d8e8SKurt Hackel 	list_for_each(iter2, &res->granted) {
1216714d8e8SKurt Hackel 		lock = list_entry(iter2, struct dlm_lock, list);
122c834cdb1SSunil Mushran 		__dlm_print_lock(lock);
1236714d8e8SKurt Hackel 	}
1248f50eb97SSunil Mushran 	printk("  converting queue:\n");
1256714d8e8SKurt Hackel 	list_for_each(iter2, &res->converting) {
1266714d8e8SKurt Hackel 		lock = list_entry(iter2, struct dlm_lock, list);
127c834cdb1SSunil Mushran 		__dlm_print_lock(lock);
1286714d8e8SKurt Hackel 	}
1298f50eb97SSunil Mushran 	printk("  blocked queue:\n");
1306714d8e8SKurt Hackel 	list_for_each(iter2, &res->blocked) {
1316714d8e8SKurt Hackel 		lock = list_entry(iter2, struct dlm_lock, list);
132c834cdb1SSunil Mushran 		__dlm_print_lock(lock);
1336714d8e8SKurt Hackel 	}
1346714d8e8SKurt Hackel }
1356714d8e8SKurt Hackel 
1366714d8e8SKurt Hackel void dlm_print_one_lock(struct dlm_lock *lockid)
1376714d8e8SKurt Hackel {
1386714d8e8SKurt Hackel 	dlm_print_one_lock_resource(lockid->lockres);
1396714d8e8SKurt Hackel }
1406714d8e8SKurt Hackel EXPORT_SYMBOL_GPL(dlm_print_one_lock);
1416714d8e8SKurt Hackel 
1426714d8e8SKurt Hackel static const char *dlm_errnames[] = {
1436714d8e8SKurt Hackel 	[DLM_NORMAL] =			"DLM_NORMAL",
1446714d8e8SKurt Hackel 	[DLM_GRANTED] =			"DLM_GRANTED",
1456714d8e8SKurt Hackel 	[DLM_DENIED] =			"DLM_DENIED",
1466714d8e8SKurt Hackel 	[DLM_DENIED_NOLOCKS] =		"DLM_DENIED_NOLOCKS",
1476714d8e8SKurt Hackel 	[DLM_WORKING] =			"DLM_WORKING",
1486714d8e8SKurt Hackel 	[DLM_BLOCKED] =			"DLM_BLOCKED",
1496714d8e8SKurt Hackel 	[DLM_BLOCKED_ORPHAN] =		"DLM_BLOCKED_ORPHAN",
1506714d8e8SKurt Hackel 	[DLM_DENIED_GRACE_PERIOD] =	"DLM_DENIED_GRACE_PERIOD",
1516714d8e8SKurt Hackel 	[DLM_SYSERR] =			"DLM_SYSERR",
1526714d8e8SKurt Hackel 	[DLM_NOSUPPORT] =		"DLM_NOSUPPORT",
1536714d8e8SKurt Hackel 	[DLM_CANCELGRANT] =		"DLM_CANCELGRANT",
1546714d8e8SKurt Hackel 	[DLM_IVLOCKID] =		"DLM_IVLOCKID",
1556714d8e8SKurt Hackel 	[DLM_SYNC] =			"DLM_SYNC",
1566714d8e8SKurt Hackel 	[DLM_BADTYPE] =			"DLM_BADTYPE",
1576714d8e8SKurt Hackel 	[DLM_BADRESOURCE] =		"DLM_BADRESOURCE",
1586714d8e8SKurt Hackel 	[DLM_MAXHANDLES] =		"DLM_MAXHANDLES",
1596714d8e8SKurt Hackel 	[DLM_NOCLINFO] =		"DLM_NOCLINFO",
1606714d8e8SKurt Hackel 	[DLM_NOLOCKMGR] =		"DLM_NOLOCKMGR",
1616714d8e8SKurt Hackel 	[DLM_NOPURGED] =		"DLM_NOPURGED",
1626714d8e8SKurt Hackel 	[DLM_BADARGS] =			"DLM_BADARGS",
1636714d8e8SKurt Hackel 	[DLM_VOID] =			"DLM_VOID",
1646714d8e8SKurt Hackel 	[DLM_NOTQUEUED] =		"DLM_NOTQUEUED",
1656714d8e8SKurt Hackel 	[DLM_IVBUFLEN] =		"DLM_IVBUFLEN",
1666714d8e8SKurt Hackel 	[DLM_CVTUNGRANT] =		"DLM_CVTUNGRANT",
1676714d8e8SKurt Hackel 	[DLM_BADPARAM] =		"DLM_BADPARAM",
1686714d8e8SKurt Hackel 	[DLM_VALNOTVALID] =		"DLM_VALNOTVALID",
1696714d8e8SKurt Hackel 	[DLM_REJECTED] =		"DLM_REJECTED",
1706714d8e8SKurt Hackel 	[DLM_ABORT] =			"DLM_ABORT",
1716714d8e8SKurt Hackel 	[DLM_CANCEL] =			"DLM_CANCEL",
1726714d8e8SKurt Hackel 	[DLM_IVRESHANDLE] =		"DLM_IVRESHANDLE",
1736714d8e8SKurt Hackel 	[DLM_DEADLOCK] =		"DLM_DEADLOCK",
1746714d8e8SKurt Hackel 	[DLM_DENIED_NOASTS] =		"DLM_DENIED_NOASTS",
1756714d8e8SKurt Hackel 	[DLM_FORWARD] =			"DLM_FORWARD",
1766714d8e8SKurt Hackel 	[DLM_TIMEOUT] =			"DLM_TIMEOUT",
1776714d8e8SKurt Hackel 	[DLM_IVGROUPID] =		"DLM_IVGROUPID",
1786714d8e8SKurt Hackel 	[DLM_VERS_CONFLICT] =		"DLM_VERS_CONFLICT",
1796714d8e8SKurt Hackel 	[DLM_BAD_DEVICE_PATH] =		"DLM_BAD_DEVICE_PATH",
1806714d8e8SKurt Hackel 	[DLM_NO_DEVICE_PERMISSION] =	"DLM_NO_DEVICE_PERMISSION",
1816714d8e8SKurt Hackel 	[DLM_NO_CONTROL_DEVICE ] =	"DLM_NO_CONTROL_DEVICE ",
1826714d8e8SKurt Hackel 	[DLM_RECOVERING] =		"DLM_RECOVERING",
1836714d8e8SKurt Hackel 	[DLM_MIGRATING] =		"DLM_MIGRATING",
1846714d8e8SKurt Hackel 	[DLM_MAXSTATS] =		"DLM_MAXSTATS",
1856714d8e8SKurt Hackel };
1866714d8e8SKurt Hackel 
1876714d8e8SKurt Hackel static const char *dlm_errmsgs[] = {
1886714d8e8SKurt Hackel 	[DLM_NORMAL] = 			"request in progress",
1896714d8e8SKurt Hackel 	[DLM_GRANTED] = 		"request granted",
1906714d8e8SKurt Hackel 	[DLM_DENIED] = 			"request denied",
1916714d8e8SKurt Hackel 	[DLM_DENIED_NOLOCKS] = 		"request denied, out of system resources",
1926714d8e8SKurt Hackel 	[DLM_WORKING] = 		"async request in progress",
1936714d8e8SKurt Hackel 	[DLM_BLOCKED] = 		"lock request blocked",
1946714d8e8SKurt Hackel 	[DLM_BLOCKED_ORPHAN] = 		"lock request blocked by a orphan lock",
1956714d8e8SKurt Hackel 	[DLM_DENIED_GRACE_PERIOD] = 	"topological change in progress",
1966714d8e8SKurt Hackel 	[DLM_SYSERR] = 			"system error",
1976714d8e8SKurt Hackel 	[DLM_NOSUPPORT] = 		"unsupported",
1986714d8e8SKurt Hackel 	[DLM_CANCELGRANT] = 		"can't cancel convert: already granted",
1996714d8e8SKurt Hackel 	[DLM_IVLOCKID] = 		"bad lockid",
2006714d8e8SKurt Hackel 	[DLM_SYNC] = 			"synchronous request granted",
2016714d8e8SKurt Hackel 	[DLM_BADTYPE] = 		"bad resource type",
2026714d8e8SKurt Hackel 	[DLM_BADRESOURCE] = 		"bad resource handle",
2036714d8e8SKurt Hackel 	[DLM_MAXHANDLES] = 		"no more resource handles",
2046714d8e8SKurt Hackel 	[DLM_NOCLINFO] = 		"can't contact cluster manager",
2056714d8e8SKurt Hackel 	[DLM_NOLOCKMGR] = 		"can't contact lock manager",
2066714d8e8SKurt Hackel 	[DLM_NOPURGED] = 		"can't contact purge daemon",
2076714d8e8SKurt Hackel 	[DLM_BADARGS] = 		"bad api args",
2086714d8e8SKurt Hackel 	[DLM_VOID] = 			"no status",
2096714d8e8SKurt Hackel 	[DLM_NOTQUEUED] = 		"NOQUEUE was specified and request failed",
2106714d8e8SKurt Hackel 	[DLM_IVBUFLEN] = 		"invalid resource name length",
2116714d8e8SKurt Hackel 	[DLM_CVTUNGRANT] = 		"attempted to convert ungranted lock",
2126714d8e8SKurt Hackel 	[DLM_BADPARAM] = 		"invalid lock mode specified",
2136714d8e8SKurt Hackel 	[DLM_VALNOTVALID] = 		"value block has been invalidated",
2146714d8e8SKurt Hackel 	[DLM_REJECTED] = 		"request rejected, unrecognized client",
2156714d8e8SKurt Hackel 	[DLM_ABORT] = 			"blocked lock request cancelled",
2166714d8e8SKurt Hackel 	[DLM_CANCEL] = 			"conversion request cancelled",
2176714d8e8SKurt Hackel 	[DLM_IVRESHANDLE] = 		"invalid resource handle",
2186714d8e8SKurt Hackel 	[DLM_DEADLOCK] = 		"deadlock recovery refused this request",
2196714d8e8SKurt Hackel 	[DLM_DENIED_NOASTS] = 		"failed to allocate AST",
2206714d8e8SKurt Hackel 	[DLM_FORWARD] = 		"request must wait for primary's response",
2216714d8e8SKurt Hackel 	[DLM_TIMEOUT] = 		"timeout value for lock has expired",
2226714d8e8SKurt Hackel 	[DLM_IVGROUPID] = 		"invalid group specification",
2236714d8e8SKurt Hackel 	[DLM_VERS_CONFLICT] = 		"version conflicts prevent request handling",
2246714d8e8SKurt Hackel 	[DLM_BAD_DEVICE_PATH] = 	"Locks device does not exist or path wrong",
2256714d8e8SKurt Hackel 	[DLM_NO_DEVICE_PERMISSION] = 	"Client has insufficient perms for device",
2266714d8e8SKurt Hackel 	[DLM_NO_CONTROL_DEVICE] = 	"Cannot set options on opened device ",
2276714d8e8SKurt Hackel 	[DLM_RECOVERING] = 		"lock resource being recovered",
2286714d8e8SKurt Hackel 	[DLM_MIGRATING] = 		"lock resource being migrated",
2296714d8e8SKurt Hackel 	[DLM_MAXSTATS] = 		"invalid error number",
2306714d8e8SKurt Hackel };
2316714d8e8SKurt Hackel 
2326714d8e8SKurt Hackel const char *dlm_errmsg(enum dlm_status err)
2336714d8e8SKurt Hackel {
2346714d8e8SKurt Hackel 	if (err >= DLM_MAXSTATS || err < 0)
2356714d8e8SKurt Hackel 		return dlm_errmsgs[DLM_MAXSTATS];
2366714d8e8SKurt Hackel 	return dlm_errmsgs[err];
2376714d8e8SKurt Hackel }
2386714d8e8SKurt Hackel EXPORT_SYMBOL_GPL(dlm_errmsg);
2396714d8e8SKurt Hackel 
2406714d8e8SKurt Hackel const char *dlm_errname(enum dlm_status err)
2416714d8e8SKurt Hackel {
2426714d8e8SKurt Hackel 	if (err >= DLM_MAXSTATS || err < 0)
2436714d8e8SKurt Hackel 		return dlm_errnames[DLM_MAXSTATS];
2446714d8e8SKurt Hackel 	return dlm_errnames[err];
2456714d8e8SKurt Hackel }
2466714d8e8SKurt Hackel EXPORT_SYMBOL_GPL(dlm_errname);
2476325b4a2SSunil Mushran 
2484e3d24edSSunil Mushran /* NOTE: This function converts a lockname into a string. It uses knowledge
2494e3d24edSSunil Mushran  * of the format of the lockname that should be outside the purview of the dlm.
2504e3d24edSSunil Mushran  * We are adding only to make dlm debugging slightly easier.
2514e3d24edSSunil Mushran  *
2524e3d24edSSunil Mushran  * For more on lockname formats, please refer to dlmglue.c and ocfs2_lockid.h.
2534e3d24edSSunil Mushran  */
25495642e56SAdrian Bunk static int stringify_lockname(const char *lockname, int locklen, char *buf,
25595642e56SAdrian Bunk 			      int len)
2564e3d24edSSunil Mushran {
2574e3d24edSSunil Mushran 	int out = 0;
2584e3d24edSSunil Mushran 	__be64 inode_blkno_be;
2594e3d24edSSunil Mushran 
2604e3d24edSSunil Mushran #define OCFS2_DENTRY_LOCK_INO_START	18
2614e3d24edSSunil Mushran 	if (*lockname == 'N') {
2624e3d24edSSunil Mushran 		memcpy((__be64 *)&inode_blkno_be,
2634e3d24edSSunil Mushran 		       (char *)&lockname[OCFS2_DENTRY_LOCK_INO_START],
2644e3d24edSSunil Mushran 		       sizeof(__be64));
2654e3d24edSSunil Mushran 		out += snprintf(buf + out, len - out, "%.*s%08x",
2664e3d24edSSunil Mushran 				OCFS2_DENTRY_LOCK_INO_START - 1, lockname,
2674e3d24edSSunil Mushran 				(unsigned int)be64_to_cpu(inode_blkno_be));
2684e3d24edSSunil Mushran 	} else
2694e3d24edSSunil Mushran 		out += snprintf(buf + out, len - out, "%.*s",
2704e3d24edSSunil Mushran 				locklen, lockname);
2714e3d24edSSunil Mushran 	return out;
2724e3d24edSSunil Mushran }
2734e3d24edSSunil Mushran 
274e5a0334cSSunil Mushran static int stringify_nodemap(unsigned long *nodemap, int maxnodes,
275e5a0334cSSunil Mushran 			     char *buf, int len)
276e5a0334cSSunil Mushran {
277e5a0334cSSunil Mushran 	int out = 0;
278e5a0334cSSunil Mushran 	int i = -1;
279e5a0334cSSunil Mushran 
280e5a0334cSSunil Mushran 	while ((i = find_next_bit(nodemap, maxnodes, i + 1)) < maxnodes)
281e5a0334cSSunil Mushran 		out += snprintf(buf + out, len - out, "%d ", i);
282e5a0334cSSunil Mushran 
283e5a0334cSSunil Mushran 	return out;
284e5a0334cSSunil Mushran }
285e5a0334cSSunil Mushran 
286e5a0334cSSunil Mushran static int dump_mle(struct dlm_master_list_entry *mle, char *buf, int len)
287e5a0334cSSunil Mushran {
288e5a0334cSSunil Mushran 	int out = 0;
289e5a0334cSSunil Mushran 	char *mle_type;
290e5a0334cSSunil Mushran 
291e5a0334cSSunil Mushran 	if (mle->type == DLM_MLE_BLOCK)
292e5a0334cSSunil Mushran 		mle_type = "BLK";
293e5a0334cSSunil Mushran 	else if (mle->type == DLM_MLE_MASTER)
294e5a0334cSSunil Mushran 		mle_type = "MAS";
295e5a0334cSSunil Mushran 	else
296e5a0334cSSunil Mushran 		mle_type = "MIG";
297e5a0334cSSunil Mushran 
2987141514bSSunil Mushran 	out += stringify_lockname(mle->mname, mle->mnamelen, buf + out, len - out);
299e5a0334cSSunil Mushran 	out += snprintf(buf + out, len - out,
300e5a0334cSSunil Mushran 			"\t%3s\tmas=%3u\tnew=%3u\tevt=%1d\tuse=%1d\tref=%3d\n",
301e5a0334cSSunil Mushran 			mle_type, mle->master, mle->new_master,
302e5a0334cSSunil Mushran 			!list_empty(&mle->hb_events),
303e5a0334cSSunil Mushran 			!!mle->inuse,
304e5a0334cSSunil Mushran 			atomic_read(&mle->mle_refs.refcount));
305e5a0334cSSunil Mushran 
306e5a0334cSSunil Mushran 	out += snprintf(buf + out, len - out, "Maybe=");
307e5a0334cSSunil Mushran 	out += stringify_nodemap(mle->maybe_map, O2NM_MAX_NODES,
308e5a0334cSSunil Mushran 				 buf + out, len - out);
309e5a0334cSSunil Mushran 	out += snprintf(buf + out, len - out, "\n");
310e5a0334cSSunil Mushran 
311e5a0334cSSunil Mushran 	out += snprintf(buf + out, len - out, "Vote=");
312e5a0334cSSunil Mushran 	out += stringify_nodemap(mle->vote_map, O2NM_MAX_NODES,
313e5a0334cSSunil Mushran 				 buf + out, len - out);
314e5a0334cSSunil Mushran 	out += snprintf(buf + out, len - out, "\n");
315e5a0334cSSunil Mushran 
316e5a0334cSSunil Mushran 	out += snprintf(buf + out, len - out, "Response=");
317e5a0334cSSunil Mushran 	out += stringify_nodemap(mle->response_map, O2NM_MAX_NODES,
318e5a0334cSSunil Mushran 				 buf + out, len - out);
319e5a0334cSSunil Mushran 	out += snprintf(buf + out, len - out, "\n");
320e5a0334cSSunil Mushran 
321e5a0334cSSunil Mushran 	out += snprintf(buf + out, len - out, "Node=");
322e5a0334cSSunil Mushran 	out += stringify_nodemap(mle->node_map, O2NM_MAX_NODES,
323e5a0334cSSunil Mushran 				 buf + out, len - out);
324e5a0334cSSunil Mushran 	out += snprintf(buf + out, len - out, "\n");
325e5a0334cSSunil Mushran 
326e5a0334cSSunil Mushran 	out += snprintf(buf + out, len - out, "\n");
327e5a0334cSSunil Mushran 
328e5a0334cSSunil Mushran 	return out;
329e5a0334cSSunil Mushran }
330e5a0334cSSunil Mushran 
331e5a0334cSSunil Mushran void dlm_print_one_mle(struct dlm_master_list_entry *mle)
332e5a0334cSSunil Mushran {
333e5a0334cSSunil Mushran 	char *buf;
334e5a0334cSSunil Mushran 
335e5a0334cSSunil Mushran 	buf = (char *) get_zeroed_page(GFP_NOFS);
336e5a0334cSSunil Mushran 	if (buf) {
337e5a0334cSSunil Mushran 		dump_mle(mle, buf, PAGE_SIZE - 1);
338e5a0334cSSunil Mushran 		free_page((unsigned long)buf);
339e5a0334cSSunil Mushran 	}
340e5a0334cSSunil Mushran }
341e5a0334cSSunil Mushran 
342e5a0334cSSunil Mushran #ifdef CONFIG_DEBUG_FS
343e5a0334cSSunil Mushran 
344e5a0334cSSunil Mushran static struct dentry *dlm_debugfs_root = NULL;
345e5a0334cSSunil Mushran 
3466325b4a2SSunil Mushran #define DLM_DEBUGFS_DIR				"o2dlm"
347007dce53SSunil Mushran #define DLM_DEBUGFS_DLM_STATE			"dlm_state"
3484e3d24edSSunil Mushran #define DLM_DEBUGFS_LOCKING_STATE		"locking_state"
349d0129aceSSunil Mushran #define DLM_DEBUGFS_MLE_STATE			"mle_state"
3507209300aSSunil Mushran #define DLM_DEBUGFS_PURGE_LIST			"purge_list"
351007dce53SSunil Mushran 
352007dce53SSunil Mushran /* begin - utils funcs */
353007dce53SSunil Mushran static void dlm_debug_free(struct kref *kref)
354007dce53SSunil Mushran {
355007dce53SSunil Mushran 	struct dlm_debug_ctxt *dc;
356007dce53SSunil Mushran 
357007dce53SSunil Mushran 	dc = container_of(kref, struct dlm_debug_ctxt, debug_refcnt);
358007dce53SSunil Mushran 
359007dce53SSunil Mushran 	kfree(dc);
360007dce53SSunil Mushran }
361007dce53SSunil Mushran 
36295642e56SAdrian Bunk static void dlm_debug_put(struct dlm_debug_ctxt *dc)
363007dce53SSunil Mushran {
364007dce53SSunil Mushran 	if (dc)
365007dce53SSunil Mushran 		kref_put(&dc->debug_refcnt, dlm_debug_free);
366007dce53SSunil Mushran }
367007dce53SSunil Mushran 
368007dce53SSunil Mushran static void dlm_debug_get(struct dlm_debug_ctxt *dc)
369007dce53SSunil Mushran {
370007dce53SSunil Mushran 	kref_get(&dc->debug_refcnt);
371007dce53SSunil Mushran }
372007dce53SSunil Mushran 
373007dce53SSunil Mushran static struct debug_buffer *debug_buffer_allocate(void)
374007dce53SSunil Mushran {
375007dce53SSunil Mushran 	struct debug_buffer *db = NULL;
376007dce53SSunil Mushran 
377007dce53SSunil Mushran 	db = kzalloc(sizeof(struct debug_buffer), GFP_KERNEL);
378007dce53SSunil Mushran 	if (!db)
379007dce53SSunil Mushran 		goto bail;
380007dce53SSunil Mushran 
381007dce53SSunil Mushran 	db->len = PAGE_SIZE;
382007dce53SSunil Mushran 	db->buf = kmalloc(db->len, GFP_KERNEL);
383007dce53SSunil Mushran 	if (!db->buf)
384007dce53SSunil Mushran 		goto bail;
385007dce53SSunil Mushran 
386007dce53SSunil Mushran 	return db;
387007dce53SSunil Mushran bail:
388007dce53SSunil Mushran 	kfree(db);
389007dce53SSunil Mushran 	return NULL;
390007dce53SSunil Mushran }
391007dce53SSunil Mushran 
392007dce53SSunil Mushran static ssize_t debug_buffer_read(struct file *file, char __user *buf,
393007dce53SSunil Mushran 				 size_t nbytes, loff_t *ppos)
394007dce53SSunil Mushran {
395007dce53SSunil Mushran 	struct debug_buffer *db = file->private_data;
396007dce53SSunil Mushran 
397007dce53SSunil Mushran 	return simple_read_from_buffer(buf, nbytes, ppos, db->buf, db->len);
398007dce53SSunil Mushran }
399007dce53SSunil Mushran 
400007dce53SSunil Mushran static loff_t debug_buffer_llseek(struct file *file, loff_t off, int whence)
401007dce53SSunil Mushran {
402007dce53SSunil Mushran 	struct debug_buffer *db = file->private_data;
403007dce53SSunil Mushran 	loff_t new = -1;
404007dce53SSunil Mushran 
405007dce53SSunil Mushran 	switch (whence) {
406007dce53SSunil Mushran 	case 0:
407007dce53SSunil Mushran 		new = off;
408007dce53SSunil Mushran 		break;
409007dce53SSunil Mushran 	case 1:
410007dce53SSunil Mushran 		new = file->f_pos + off;
411007dce53SSunil Mushran 		break;
412007dce53SSunil Mushran 	}
413007dce53SSunil Mushran 
414007dce53SSunil Mushran 	if (new < 0 || new > db->len)
415007dce53SSunil Mushran 		return -EINVAL;
416007dce53SSunil Mushran 
417007dce53SSunil Mushran 	return (file->f_pos = new);
418007dce53SSunil Mushran }
419007dce53SSunil Mushran 
420007dce53SSunil Mushran static int debug_buffer_release(struct inode *inode, struct file *file)
421007dce53SSunil Mushran {
422007dce53SSunil Mushran 	struct debug_buffer *db = (struct debug_buffer *)file->private_data;
423007dce53SSunil Mushran 
424007dce53SSunil Mushran 	if (db)
425007dce53SSunil Mushran 		kfree(db->buf);
426007dce53SSunil Mushran 	kfree(db);
427007dce53SSunil Mushran 
428007dce53SSunil Mushran 	return 0;
429007dce53SSunil Mushran }
430007dce53SSunil Mushran /* end - util funcs */
431007dce53SSunil Mushran 
4327209300aSSunil Mushran /* begin - purge list funcs */
4337209300aSSunil Mushran static int debug_purgelist_print(struct dlm_ctxt *dlm, struct debug_buffer *db)
4347209300aSSunil Mushran {
4357209300aSSunil Mushran 	struct dlm_lock_resource *res;
4367209300aSSunil Mushran 	int out = 0;
4377209300aSSunil Mushran 	unsigned long total = 0;
4387209300aSSunil Mushran 
4397209300aSSunil Mushran 	out += snprintf(db->buf + out, db->len - out,
4407209300aSSunil Mushran 			"Dumping Purgelist for Domain: %s\n", dlm->name);
4417209300aSSunil Mushran 
4427209300aSSunil Mushran 	spin_lock(&dlm->spinlock);
4437209300aSSunil Mushran 	list_for_each_entry(res, &dlm->purge_list, purge) {
4447209300aSSunil Mushran 		++total;
4457209300aSSunil Mushran 		if (db->len - out < 100)
4467209300aSSunil Mushran 			continue;
4477209300aSSunil Mushran 		spin_lock(&res->spinlock);
4487209300aSSunil Mushran 		out += stringify_lockname(res->lockname.name,
4497209300aSSunil Mushran 					  res->lockname.len,
4507209300aSSunil Mushran 					  db->buf + out, db->len - out);
4517209300aSSunil Mushran 		out += snprintf(db->buf + out, db->len - out, "\t%ld\n",
4527209300aSSunil Mushran 				(jiffies - res->last_used)/HZ);
4537209300aSSunil Mushran 		spin_unlock(&res->spinlock);
4547209300aSSunil Mushran 	}
4557209300aSSunil Mushran 	spin_unlock(&dlm->spinlock);
4567209300aSSunil Mushran 
4577209300aSSunil Mushran 	out += snprintf(db->buf + out, db->len - out,
4587209300aSSunil Mushran 			"Total on list: %ld\n", total);
4597209300aSSunil Mushran 
4607209300aSSunil Mushran 	return out;
4617209300aSSunil Mushran }
4627209300aSSunil Mushran 
4637209300aSSunil Mushran static int debug_purgelist_open(struct inode *inode, struct file *file)
4647209300aSSunil Mushran {
4657209300aSSunil Mushran 	struct dlm_ctxt *dlm = inode->i_private;
4667209300aSSunil Mushran 	struct debug_buffer *db;
4677209300aSSunil Mushran 
4687209300aSSunil Mushran 	db = debug_buffer_allocate();
4697209300aSSunil Mushran 	if (!db)
4707209300aSSunil Mushran 		goto bail;
4717209300aSSunil Mushran 
4727209300aSSunil Mushran 	db->len = debug_purgelist_print(dlm, db);
4737209300aSSunil Mushran 
4747209300aSSunil Mushran 	file->private_data = db;
4757209300aSSunil Mushran 
4767209300aSSunil Mushran 	return 0;
4777209300aSSunil Mushran bail:
4787209300aSSunil Mushran 	return -ENOMEM;
4797209300aSSunil Mushran }
4807209300aSSunil Mushran 
481828c0950SAlexey Dobriyan static const struct file_operations debug_purgelist_fops = {
4827209300aSSunil Mushran 	.open =		debug_purgelist_open,
4837209300aSSunil Mushran 	.release =	debug_buffer_release,
4847209300aSSunil Mushran 	.read =		debug_buffer_read,
4857209300aSSunil Mushran 	.llseek =	debug_buffer_llseek,
4867209300aSSunil Mushran };
4877209300aSSunil Mushran /* end - purge list funcs */
4887209300aSSunil Mushran 
489d0129aceSSunil Mushran /* begin - debug mle funcs */
490d0129aceSSunil Mushran static int debug_mle_print(struct dlm_ctxt *dlm, struct debug_buffer *db)
491d0129aceSSunil Mushran {
492d0129aceSSunil Mushran 	struct dlm_master_list_entry *mle;
4932ed6c750SSunil Mushran 	struct hlist_head *bucket;
4942ed6c750SSunil Mushran 	struct hlist_node *list;
4952ed6c750SSunil Mushran 	int i, out = 0;
4969405dccfSSunil Mushran 	unsigned long total = 0, longest = 0, bktcnt;
497d0129aceSSunil Mushran 
498d0129aceSSunil Mushran 	out += snprintf(db->buf + out, db->len - out,
499d0129aceSSunil Mushran 			"Dumping MLEs for Domain: %s\n", dlm->name);
500d0129aceSSunil Mushran 
501d0129aceSSunil Mushran 	spin_lock(&dlm->master_lock);
5022ed6c750SSunil Mushran 	for (i = 0; i < DLM_HASH_BUCKETS; i++) {
5032ed6c750SSunil Mushran 		bucket = dlm_master_hash(dlm, i);
5042ed6c750SSunil Mushran 		hlist_for_each(list, bucket) {
5052ed6c750SSunil Mushran 			mle = hlist_entry(list, struct dlm_master_list_entry,
5062ed6c750SSunil Mushran 					  master_hash_node);
507d0129aceSSunil Mushran 			++total;
5089405dccfSSunil Mushran 			++bktcnt;
509d0129aceSSunil Mushran 			if (db->len - out < 200)
510d0129aceSSunil Mushran 				continue;
511d0129aceSSunil Mushran 			out += dump_mle(mle, db->buf + out, db->len - out);
512d0129aceSSunil Mushran 		}
5139405dccfSSunil Mushran 		longest = max(longest, bktcnt);
5149405dccfSSunil Mushran 		bktcnt = 0;
5152ed6c750SSunil Mushran 	}
516d0129aceSSunil Mushran 	spin_unlock(&dlm->master_lock);
517d0129aceSSunil Mushran 
518d0129aceSSunil Mushran 	out += snprintf(db->buf + out, db->len - out,
5199405dccfSSunil Mushran 			"Total: %ld, Longest: %ld\n", total, longest);
520d0129aceSSunil Mushran 	return out;
521d0129aceSSunil Mushran }
522d0129aceSSunil Mushran 
523d0129aceSSunil Mushran static int debug_mle_open(struct inode *inode, struct file *file)
524d0129aceSSunil Mushran {
525d0129aceSSunil Mushran 	struct dlm_ctxt *dlm = inode->i_private;
526d0129aceSSunil Mushran 	struct debug_buffer *db;
527d0129aceSSunil Mushran 
528d0129aceSSunil Mushran 	db = debug_buffer_allocate();
529d0129aceSSunil Mushran 	if (!db)
530d0129aceSSunil Mushran 		goto bail;
531d0129aceSSunil Mushran 
532d0129aceSSunil Mushran 	db->len = debug_mle_print(dlm, db);
533d0129aceSSunil Mushran 
534d0129aceSSunil Mushran 	file->private_data = db;
535d0129aceSSunil Mushran 
536d0129aceSSunil Mushran 	return 0;
537d0129aceSSunil Mushran bail:
538d0129aceSSunil Mushran 	return -ENOMEM;
539d0129aceSSunil Mushran }
540d0129aceSSunil Mushran 
541828c0950SAlexey Dobriyan static const struct file_operations debug_mle_fops = {
542d0129aceSSunil Mushran 	.open =		debug_mle_open,
543d0129aceSSunil Mushran 	.release =	debug_buffer_release,
544d0129aceSSunil Mushran 	.read =		debug_buffer_read,
545d0129aceSSunil Mushran 	.llseek =	debug_buffer_llseek,
546d0129aceSSunil Mushran };
547d0129aceSSunil Mushran 
548d0129aceSSunil Mushran /* end - debug mle funcs */
549d0129aceSSunil Mushran 
5504e3d24edSSunil Mushran /* begin - debug lockres funcs */
5514e3d24edSSunil Mushran static int dump_lock(struct dlm_lock *lock, int list_type, char *buf, int len)
5524e3d24edSSunil Mushran {
5534e3d24edSSunil Mushran 	int out;
5544e3d24edSSunil Mushran 
5554e3d24edSSunil Mushran #define DEBUG_LOCK_VERSION	1
5564e3d24edSSunil Mushran 	spin_lock(&lock->spinlock);
5574e3d24edSSunil Mushran 	out = snprintf(buf, len, "LOCK:%d,%d,%d,%d,%d,%d:%lld,%d,%d,%d,%d,%d,"
5584e3d24edSSunil Mushran 		       "%d,%d,%d,%d\n",
5594e3d24edSSunil Mushran 		       DEBUG_LOCK_VERSION,
5604e3d24edSSunil Mushran 		       list_type, lock->ml.type, lock->ml.convert_type,
5614e3d24edSSunil Mushran 		       lock->ml.node,
5624e3d24edSSunil Mushran 		       dlm_get_lock_cookie_node(be64_to_cpu(lock->ml.cookie)),
5634e3d24edSSunil Mushran 		       dlm_get_lock_cookie_seq(be64_to_cpu(lock->ml.cookie)),
5644e3d24edSSunil Mushran 		       !list_empty(&lock->ast_list),
5654e3d24edSSunil Mushran 		       !list_empty(&lock->bast_list),
5664e3d24edSSunil Mushran 		       lock->ast_pending, lock->bast_pending,
5674e3d24edSSunil Mushran 		       lock->convert_pending, lock->lock_pending,
5684e3d24edSSunil Mushran 		       lock->cancel_pending, lock->unlock_pending,
5694e3d24edSSunil Mushran 		       atomic_read(&lock->lock_refs.refcount));
5704e3d24edSSunil Mushran 	spin_unlock(&lock->spinlock);
5714e3d24edSSunil Mushran 
5724e3d24edSSunil Mushran 	return out;
5734e3d24edSSunil Mushran }
5744e3d24edSSunil Mushran 
5754e3d24edSSunil Mushran static int dump_lockres(struct dlm_lock_resource *res, char *buf, int len)
5764e3d24edSSunil Mushran {
5774e3d24edSSunil Mushran 	struct dlm_lock *lock;
5784e3d24edSSunil Mushran 	int i;
5794e3d24edSSunil Mushran 	int out = 0;
5804e3d24edSSunil Mushran 
5814e3d24edSSunil Mushran 	out += snprintf(buf + out, len - out, "NAME:");
5824e3d24edSSunil Mushran 	out += stringify_lockname(res->lockname.name, res->lockname.len,
5834e3d24edSSunil Mushran 				  buf + out, len - out);
5844e3d24edSSunil Mushran 	out += snprintf(buf + out, len - out, "\n");
5854e3d24edSSunil Mushran 
5864e3d24edSSunil Mushran #define DEBUG_LRES_VERSION	1
5874e3d24edSSunil Mushran 	out += snprintf(buf + out, len - out,
5884e3d24edSSunil Mushran 			"LRES:%d,%d,%d,%ld,%d,%d,%d,%d,%d,%d,%d\n",
5894e3d24edSSunil Mushran 			DEBUG_LRES_VERSION,
5904e3d24edSSunil Mushran 			res->owner, res->state, res->last_used,
5914e3d24edSSunil Mushran 			!list_empty(&res->purge),
5924e3d24edSSunil Mushran 			!list_empty(&res->dirty),
5934e3d24edSSunil Mushran 			!list_empty(&res->recovering),
5944e3d24edSSunil Mushran 			res->inflight_locks, res->migration_pending,
5954e3d24edSSunil Mushran 			atomic_read(&res->asts_reserved),
5964e3d24edSSunil Mushran 			atomic_read(&res->refs.refcount));
5974e3d24edSSunil Mushran 
5984e3d24edSSunil Mushran 	/* refmap */
5994e3d24edSSunil Mushran 	out += snprintf(buf + out, len - out, "RMAP:");
6004e3d24edSSunil Mushran 	out += stringify_nodemap(res->refmap, O2NM_MAX_NODES,
6014e3d24edSSunil Mushran 				 buf + out, len - out);
6024e3d24edSSunil Mushran 	out += snprintf(buf + out, len - out, "\n");
6034e3d24edSSunil Mushran 
6044e3d24edSSunil Mushran 	/* lvb */
6054e3d24edSSunil Mushran 	out += snprintf(buf + out, len - out, "LVBX:");
6064e3d24edSSunil Mushran 	for (i = 0; i < DLM_LVB_LEN; i++)
6074e3d24edSSunil Mushran 		out += snprintf(buf + out, len - out,
6084e3d24edSSunil Mushran 					"%02x", (unsigned char)res->lvb[i]);
6094e3d24edSSunil Mushran 	out += snprintf(buf + out, len - out, "\n");
6104e3d24edSSunil Mushran 
6114e3d24edSSunil Mushran 	/* granted */
6124e3d24edSSunil Mushran 	list_for_each_entry(lock, &res->granted, list)
6134e3d24edSSunil Mushran 		out += dump_lock(lock, 0, buf + out, len - out);
6144e3d24edSSunil Mushran 
6154e3d24edSSunil Mushran 	/* converting */
6164e3d24edSSunil Mushran 	list_for_each_entry(lock, &res->converting, list)
6174e3d24edSSunil Mushran 		out += dump_lock(lock, 1, buf + out, len - out);
6184e3d24edSSunil Mushran 
6194e3d24edSSunil Mushran 	/* blocked */
6204e3d24edSSunil Mushran 	list_for_each_entry(lock, &res->blocked, list)
6214e3d24edSSunil Mushran 		out += dump_lock(lock, 2, buf + out, len - out);
6224e3d24edSSunil Mushran 
6234e3d24edSSunil Mushran 	out += snprintf(buf + out, len - out, "\n");
6244e3d24edSSunil Mushran 
6254e3d24edSSunil Mushran 	return out;
6264e3d24edSSunil Mushran }
6274e3d24edSSunil Mushran 
6284e3d24edSSunil Mushran static void *lockres_seq_start(struct seq_file *m, loff_t *pos)
6294e3d24edSSunil Mushran {
6304e3d24edSSunil Mushran 	struct debug_lockres *dl = m->private;
6314e3d24edSSunil Mushran 	struct dlm_ctxt *dlm = dl->dl_ctxt;
632b0d4f817SSunil Mushran 	struct dlm_lock_resource *oldres = dl->dl_res;
6334e3d24edSSunil Mushran 	struct dlm_lock_resource *res = NULL;
634b0d4f817SSunil Mushran 	struct list_head *track_list;
6354e3d24edSSunil Mushran 
636b0d4f817SSunil Mushran 	spin_lock(&dlm->track_lock);
637b0d4f817SSunil Mushran 	if (oldres)
638b0d4f817SSunil Mushran 		track_list = &oldres->tracking;
639b0d4f817SSunil Mushran 	else
640b0d4f817SSunil Mushran 		track_list = &dlm->tracking_list;
6414e3d24edSSunil Mushran 
642b0d4f817SSunil Mushran 	list_for_each_entry(res, track_list, tracking) {
643b0d4f817SSunil Mushran 		if (&res->tracking == &dlm->tracking_list)
644b0d4f817SSunil Mushran 			res = NULL;
645b0d4f817SSunil Mushran 		else
6464e3d24edSSunil Mushran 			dlm_lockres_get(res);
6474e3d24edSSunil Mushran 		break;
6484e3d24edSSunil Mushran 	}
649b0d4f817SSunil Mushran 	spin_unlock(&dlm->track_lock);
650b0d4f817SSunil Mushran 
651b0d4f817SSunil Mushran 	if (oldres)
652b0d4f817SSunil Mushran 		dlm_lockres_put(oldres);
653b0d4f817SSunil Mushran 
6544e3d24edSSunil Mushran 	dl->dl_res = res;
655b0d4f817SSunil Mushran 
656b0d4f817SSunil Mushran 	if (res) {
657b0d4f817SSunil Mushran 		spin_lock(&res->spinlock);
658b0d4f817SSunil Mushran 		dump_lockres(res, dl->dl_buf, dl->dl_len - 1);
659b0d4f817SSunil Mushran 		spin_unlock(&res->spinlock);
6604e3d24edSSunil Mushran 	} else
6614e3d24edSSunil Mushran 		dl = NULL;
6624e3d24edSSunil Mushran 
663b0d4f817SSunil Mushran 	/* passed to seq_show */
6644e3d24edSSunil Mushran 	return dl;
6654e3d24edSSunil Mushran }
6664e3d24edSSunil Mushran 
6674e3d24edSSunil Mushran static void lockres_seq_stop(struct seq_file *m, void *v)
6684e3d24edSSunil Mushran {
6694e3d24edSSunil Mushran }
6704e3d24edSSunil Mushran 
6714e3d24edSSunil Mushran static void *lockres_seq_next(struct seq_file *m, void *v, loff_t *pos)
6724e3d24edSSunil Mushran {
6734e3d24edSSunil Mushran 	return NULL;
6744e3d24edSSunil Mushran }
6754e3d24edSSunil Mushran 
6764e3d24edSSunil Mushran static int lockres_seq_show(struct seq_file *s, void *v)
6774e3d24edSSunil Mushran {
6784e3d24edSSunil Mushran 	struct debug_lockres *dl = (struct debug_lockres *)v;
6794e3d24edSSunil Mushran 
6804e3d24edSSunil Mushran 	seq_printf(s, "%s", dl->dl_buf);
6814e3d24edSSunil Mushran 
6824e3d24edSSunil Mushran 	return 0;
6834e3d24edSSunil Mushran }
6844e3d24edSSunil Mushran 
68588e9d34cSJames Morris static const struct seq_operations debug_lockres_ops = {
6864e3d24edSSunil Mushran 	.start =	lockres_seq_start,
6874e3d24edSSunil Mushran 	.stop =		lockres_seq_stop,
6884e3d24edSSunil Mushran 	.next =		lockres_seq_next,
6894e3d24edSSunil Mushran 	.show =		lockres_seq_show,
6904e3d24edSSunil Mushran };
6914e3d24edSSunil Mushran 
6924e3d24edSSunil Mushran static int debug_lockres_open(struct inode *inode, struct file *file)
6934e3d24edSSunil Mushran {
6944e3d24edSSunil Mushran 	struct dlm_ctxt *dlm = inode->i_private;
6954e3d24edSSunil Mushran 	int ret = -ENOMEM;
6964e3d24edSSunil Mushran 	struct seq_file *seq;
6974e3d24edSSunil Mushran 	struct debug_lockres *dl = NULL;
6984e3d24edSSunil Mushran 
6994e3d24edSSunil Mushran 	dl = kzalloc(sizeof(struct debug_lockres), GFP_KERNEL);
7004e3d24edSSunil Mushran 	if (!dl) {
7014e3d24edSSunil Mushran 		mlog_errno(ret);
7024e3d24edSSunil Mushran 		goto bail;
7034e3d24edSSunil Mushran 	}
7044e3d24edSSunil Mushran 
7054e3d24edSSunil Mushran 	dl->dl_len = PAGE_SIZE;
7064e3d24edSSunil Mushran 	dl->dl_buf = kmalloc(dl->dl_len, GFP_KERNEL);
7074e3d24edSSunil Mushran 	if (!dl->dl_buf) {
7084e3d24edSSunil Mushran 		mlog_errno(ret);
7094e3d24edSSunil Mushran 		goto bail;
7104e3d24edSSunil Mushran 	}
7114e3d24edSSunil Mushran 
7124e3d24edSSunil Mushran 	ret = seq_open(file, &debug_lockres_ops);
7134e3d24edSSunil Mushran 	if (ret) {
7144e3d24edSSunil Mushran 		mlog_errno(ret);
7154e3d24edSSunil Mushran 		goto bail;
7164e3d24edSSunil Mushran 	}
7174e3d24edSSunil Mushran 
7184e3d24edSSunil Mushran 	seq = (struct seq_file *) file->private_data;
7194e3d24edSSunil Mushran 	seq->private = dl;
7204e3d24edSSunil Mushran 
7214e3d24edSSunil Mushran 	dlm_grab(dlm);
7224e3d24edSSunil Mushran 	dl->dl_ctxt = dlm;
7234e3d24edSSunil Mushran 
7244e3d24edSSunil Mushran 	return 0;
7254e3d24edSSunil Mushran bail:
7264e3d24edSSunil Mushran 	if (dl)
7274e3d24edSSunil Mushran 		kfree(dl->dl_buf);
7284e3d24edSSunil Mushran 	kfree(dl);
7294e3d24edSSunil Mushran 	return ret;
7304e3d24edSSunil Mushran }
7314e3d24edSSunil Mushran 
7324e3d24edSSunil Mushran static int debug_lockres_release(struct inode *inode, struct file *file)
7334e3d24edSSunil Mushran {
7344e3d24edSSunil Mushran 	struct seq_file *seq = (struct seq_file *)file->private_data;
7354e3d24edSSunil Mushran 	struct debug_lockres *dl = (struct debug_lockres *)seq->private;
7364e3d24edSSunil Mushran 
7374e3d24edSSunil Mushran 	if (dl->dl_res)
7384e3d24edSSunil Mushran 		dlm_lockres_put(dl->dl_res);
7394e3d24edSSunil Mushran 	dlm_put(dl->dl_ctxt);
7404e3d24edSSunil Mushran 	kfree(dl->dl_buf);
7414e3d24edSSunil Mushran 	return seq_release_private(inode, file);
7424e3d24edSSunil Mushran }
7434e3d24edSSunil Mushran 
744828c0950SAlexey Dobriyan static const struct file_operations debug_lockres_fops = {
7454e3d24edSSunil Mushran 	.open =		debug_lockres_open,
7464e3d24edSSunil Mushran 	.release =	debug_lockres_release,
7474e3d24edSSunil Mushran 	.read =		seq_read,
7484e3d24edSSunil Mushran 	.llseek =	seq_lseek,
7494e3d24edSSunil Mushran };
7504e3d24edSSunil Mushran /* end - debug lockres funcs */
7514e3d24edSSunil Mushran 
752007dce53SSunil Mushran /* begin - debug state funcs */
753007dce53SSunil Mushran static int debug_state_print(struct dlm_ctxt *dlm, struct debug_buffer *db)
754007dce53SSunil Mushran {
755007dce53SSunil Mushran 	int out = 0;
756007dce53SSunil Mushran 	struct dlm_reco_node_data *node;
757007dce53SSunil Mushran 	char *state;
758e64ff146SSunil Mushran 	int cur_mles = 0, tot_mles = 0;
759e64ff146SSunil Mushran 	int i;
760007dce53SSunil Mushran 
761007dce53SSunil Mushran 	spin_lock(&dlm->spinlock);
762007dce53SSunil Mushran 
763007dce53SSunil Mushran 	switch (dlm->dlm_state) {
764007dce53SSunil Mushran 	case DLM_CTXT_NEW:
765007dce53SSunil Mushran 		state = "NEW"; break;
766007dce53SSunil Mushran 	case DLM_CTXT_JOINED:
767007dce53SSunil Mushran 		state = "JOINED"; break;
768007dce53SSunil Mushran 	case DLM_CTXT_IN_SHUTDOWN:
769007dce53SSunil Mushran 		state = "SHUTDOWN"; break;
770007dce53SSunil Mushran 	case DLM_CTXT_LEAVING:
771007dce53SSunil Mushran 		state = "LEAVING"; break;
772007dce53SSunil Mushran 	default:
773007dce53SSunil Mushran 		state = "UNKNOWN"; break;
774007dce53SSunil Mushran 	}
775007dce53SSunil Mushran 
776007dce53SSunil Mushran 	/* Domain: xxxxxxxxxx  Key: 0xdfbac769 */
777007dce53SSunil Mushran 	out += snprintf(db->buf + out, db->len - out,
778007dce53SSunil Mushran 			"Domain: %s  Key: 0x%08x\n", dlm->name, dlm->key);
779007dce53SSunil Mushran 
780007dce53SSunil Mushran 	/* Thread Pid: xxx  Node: xxx  State: xxxxx */
781007dce53SSunil Mushran 	out += snprintf(db->buf + out, db->len - out,
782007dce53SSunil Mushran 			"Thread Pid: %d  Node: %d  State: %s\n",
783007dce53SSunil Mushran 			dlm->dlm_thread_task->pid, dlm->node_num, state);
784007dce53SSunil Mushran 
785007dce53SSunil Mushran 	/* Number of Joins: xxx  Joining Node: xxx */
786007dce53SSunil Mushran 	out += snprintf(db->buf + out, db->len - out,
787007dce53SSunil Mushran 			"Number of Joins: %d  Joining Node: %d\n",
788007dce53SSunil Mushran 			dlm->num_joins, dlm->joining_node);
789007dce53SSunil Mushran 
790007dce53SSunil Mushran 	/* Domain Map: xx xx xx */
791007dce53SSunil Mushran 	out += snprintf(db->buf + out, db->len - out, "Domain Map: ");
792007dce53SSunil Mushran 	out += stringify_nodemap(dlm->domain_map, O2NM_MAX_NODES,
793007dce53SSunil Mushran 				 db->buf + out, db->len - out);
794007dce53SSunil Mushran 	out += snprintf(db->buf + out, db->len - out, "\n");
795007dce53SSunil Mushran 
796007dce53SSunil Mushran 	/* Live Map: xx xx xx */
797007dce53SSunil Mushran 	out += snprintf(db->buf + out, db->len - out, "Live Map: ");
798007dce53SSunil Mushran 	out += stringify_nodemap(dlm->live_nodes_map, O2NM_MAX_NODES,
799007dce53SSunil Mushran 				 db->buf + out, db->len - out);
800007dce53SSunil Mushran 	out += snprintf(db->buf + out, db->len - out, "\n");
801007dce53SSunil Mushran 
802e64ff146SSunil Mushran 	/* Lock Resources: xxx (xxx) */
803e64ff146SSunil Mushran 	out += snprintf(db->buf + out, db->len - out,
804e64ff146SSunil Mushran 			"Lock Resources: %d (%d)\n",
805e64ff146SSunil Mushran 			atomic_read(&dlm->res_cur_count),
806e64ff146SSunil Mushran 			atomic_read(&dlm->res_tot_count));
807e64ff146SSunil Mushran 
808e64ff146SSunil Mushran 	for (i = 0; i < DLM_MLE_NUM_TYPES; ++i)
809e64ff146SSunil Mushran 		tot_mles += atomic_read(&dlm->mle_tot_count[i]);
810e64ff146SSunil Mushran 
811e64ff146SSunil Mushran 	for (i = 0; i < DLM_MLE_NUM_TYPES; ++i)
812e64ff146SSunil Mushran 		cur_mles += atomic_read(&dlm->mle_cur_count[i]);
813e64ff146SSunil Mushran 
814e64ff146SSunil Mushran 	/* MLEs: xxx (xxx) */
815e64ff146SSunil Mushran 	out += snprintf(db->buf + out, db->len - out,
816e64ff146SSunil Mushran 			"MLEs: %d (%d)\n", cur_mles, tot_mles);
817e64ff146SSunil Mushran 
818e64ff146SSunil Mushran 	/*  Blocking: xxx (xxx) */
819e64ff146SSunil Mushran 	out += snprintf(db->buf + out, db->len - out,
820e64ff146SSunil Mushran 			"  Blocking: %d (%d)\n",
821e64ff146SSunil Mushran 			atomic_read(&dlm->mle_cur_count[DLM_MLE_BLOCK]),
822e64ff146SSunil Mushran 			atomic_read(&dlm->mle_tot_count[DLM_MLE_BLOCK]));
823e64ff146SSunil Mushran 
824e64ff146SSunil Mushran 	/*  Mastery: xxx (xxx) */
825e64ff146SSunil Mushran 	out += snprintf(db->buf + out, db->len - out,
826e64ff146SSunil Mushran 			"  Mastery: %d (%d)\n",
827e64ff146SSunil Mushran 			atomic_read(&dlm->mle_cur_count[DLM_MLE_MASTER]),
828e64ff146SSunil Mushran 			atomic_read(&dlm->mle_tot_count[DLM_MLE_MASTER]));
829e64ff146SSunil Mushran 
830e64ff146SSunil Mushran 	/*  Migration: xxx (xxx) */
831e64ff146SSunil Mushran 	out += snprintf(db->buf + out, db->len - out,
832e64ff146SSunil Mushran 			"  Migration: %d (%d)\n",
833e64ff146SSunil Mushran 			atomic_read(&dlm->mle_cur_count[DLM_MLE_MIGRATION]),
834e64ff146SSunil Mushran 			atomic_read(&dlm->mle_tot_count[DLM_MLE_MIGRATION]));
835e64ff146SSunil Mushran 
836007dce53SSunil Mushran 	/* Lists: Dirty=Empty  Purge=InUse  PendingASTs=Empty  ... */
837007dce53SSunil Mushran 	out += snprintf(db->buf + out, db->len - out,
838007dce53SSunil Mushran 			"Lists: Dirty=%s  Purge=%s  PendingASTs=%s  "
8392ed6c750SSunil Mushran 			"PendingBASTs=%s\n",
840007dce53SSunil Mushran 			(list_empty(&dlm->dirty_list) ? "Empty" : "InUse"),
841007dce53SSunil Mushran 			(list_empty(&dlm->purge_list) ? "Empty" : "InUse"),
842007dce53SSunil Mushran 			(list_empty(&dlm->pending_asts) ? "Empty" : "InUse"),
8432ed6c750SSunil Mushran 			(list_empty(&dlm->pending_basts) ? "Empty" : "InUse"));
844007dce53SSunil Mushran 
845007dce53SSunil Mushran 	/* Purge Count: xxx  Refs: xxx */
846007dce53SSunil Mushran 	out += snprintf(db->buf + out, db->len - out,
847007dce53SSunil Mushran 			"Purge Count: %d  Refs: %d\n", dlm->purge_count,
848007dce53SSunil Mushran 			atomic_read(&dlm->dlm_refs.refcount));
849007dce53SSunil Mushran 
850007dce53SSunil Mushran 	/* Dead Node: xxx */
851007dce53SSunil Mushran 	out += snprintf(db->buf + out, db->len - out,
852007dce53SSunil Mushran 			"Dead Node: %d\n", dlm->reco.dead_node);
853007dce53SSunil Mushran 
854007dce53SSunil Mushran 	/* What about DLM_RECO_STATE_FINALIZE? */
855007dce53SSunil Mushran 	if (dlm->reco.state == DLM_RECO_STATE_ACTIVE)
856007dce53SSunil Mushran 		state = "ACTIVE";
857007dce53SSunil Mushran 	else
858007dce53SSunil Mushran 		state = "INACTIVE";
859007dce53SSunil Mushran 
860007dce53SSunil Mushran 	/* Recovery Pid: xxxx  Master: xxx  State: xxxx */
861007dce53SSunil Mushran 	out += snprintf(db->buf + out, db->len - out,
862007dce53SSunil Mushran 			"Recovery Pid: %d  Master: %d  State: %s\n",
863007dce53SSunil Mushran 			dlm->dlm_reco_thread_task->pid,
864007dce53SSunil Mushran 			dlm->reco.new_master, state);
865007dce53SSunil Mushran 
866007dce53SSunil Mushran 	/* Recovery Map: xx xx */
867007dce53SSunil Mushran 	out += snprintf(db->buf + out, db->len - out, "Recovery Map: ");
868007dce53SSunil Mushran 	out += stringify_nodemap(dlm->recovery_map, O2NM_MAX_NODES,
869007dce53SSunil Mushran 				 db->buf + out, db->len - out);
870007dce53SSunil Mushran 	out += snprintf(db->buf + out, db->len - out, "\n");
871007dce53SSunil Mushran 
872007dce53SSunil Mushran 	/* Recovery Node State: */
873007dce53SSunil Mushran 	out += snprintf(db->buf + out, db->len - out, "Recovery Node State:\n");
874007dce53SSunil Mushran 	list_for_each_entry(node, &dlm->reco.node_data, list) {
875007dce53SSunil Mushran 		switch (node->state) {
876007dce53SSunil Mushran 		case DLM_RECO_NODE_DATA_INIT:
877007dce53SSunil Mushran 			state = "INIT";
878007dce53SSunil Mushran 			break;
879007dce53SSunil Mushran 		case DLM_RECO_NODE_DATA_REQUESTING:
880007dce53SSunil Mushran 			state = "REQUESTING";
881007dce53SSunil Mushran 			break;
882007dce53SSunil Mushran 		case DLM_RECO_NODE_DATA_DEAD:
883007dce53SSunil Mushran 			state = "DEAD";
884007dce53SSunil Mushran 			break;
885007dce53SSunil Mushran 		case DLM_RECO_NODE_DATA_RECEIVING:
886007dce53SSunil Mushran 			state = "RECEIVING";
887007dce53SSunil Mushran 			break;
888007dce53SSunil Mushran 		case DLM_RECO_NODE_DATA_REQUESTED:
889007dce53SSunil Mushran 			state = "REQUESTED";
890007dce53SSunil Mushran 			break;
891007dce53SSunil Mushran 		case DLM_RECO_NODE_DATA_DONE:
892007dce53SSunil Mushran 			state = "DONE";
893007dce53SSunil Mushran 			break;
894007dce53SSunil Mushran 		case DLM_RECO_NODE_DATA_FINALIZE_SENT:
895007dce53SSunil Mushran 			state = "FINALIZE-SENT";
896007dce53SSunil Mushran 			break;
897007dce53SSunil Mushran 		default:
898007dce53SSunil Mushran 			state = "BAD";
899007dce53SSunil Mushran 			break;
900007dce53SSunil Mushran 		}
901007dce53SSunil Mushran 		out += snprintf(db->buf + out, db->len - out, "\t%u - %s\n",
902007dce53SSunil Mushran 				node->node_num, state);
903007dce53SSunil Mushran 	}
904007dce53SSunil Mushran 
905007dce53SSunil Mushran 	spin_unlock(&dlm->spinlock);
906007dce53SSunil Mushran 
907007dce53SSunil Mushran 	return out;
908007dce53SSunil Mushran }
909007dce53SSunil Mushran 
910007dce53SSunil Mushran static int debug_state_open(struct inode *inode, struct file *file)
911007dce53SSunil Mushran {
912007dce53SSunil Mushran 	struct dlm_ctxt *dlm = inode->i_private;
913007dce53SSunil Mushran 	struct debug_buffer *db = NULL;
914007dce53SSunil Mushran 
915007dce53SSunil Mushran 	db = debug_buffer_allocate();
916007dce53SSunil Mushran 	if (!db)
917007dce53SSunil Mushran 		goto bail;
918007dce53SSunil Mushran 
919007dce53SSunil Mushran 	db->len = debug_state_print(dlm, db);
920007dce53SSunil Mushran 
921007dce53SSunil Mushran 	file->private_data = db;
922007dce53SSunil Mushran 
923007dce53SSunil Mushran 	return 0;
924007dce53SSunil Mushran bail:
925007dce53SSunil Mushran 	return -ENOMEM;
926007dce53SSunil Mushran }
927007dce53SSunil Mushran 
928828c0950SAlexey Dobriyan static const struct file_operations debug_state_fops = {
929007dce53SSunil Mushran 	.open =		debug_state_open,
930007dce53SSunil Mushran 	.release =	debug_buffer_release,
931007dce53SSunil Mushran 	.read =		debug_buffer_read,
932007dce53SSunil Mushran 	.llseek =	debug_buffer_llseek,
933007dce53SSunil Mushran };
934007dce53SSunil Mushran /* end  - debug state funcs */
935007dce53SSunil Mushran 
936007dce53SSunil Mushran /* files in subroot */
937007dce53SSunil Mushran int dlm_debug_init(struct dlm_ctxt *dlm)
938007dce53SSunil Mushran {
939007dce53SSunil Mushran 	struct dlm_debug_ctxt *dc = dlm->dlm_debug_ctxt;
940007dce53SSunil Mushran 
941007dce53SSunil Mushran 	/* for dumping dlm_ctxt */
942007dce53SSunil Mushran 	dc->debug_state_dentry = debugfs_create_file(DLM_DEBUGFS_DLM_STATE,
943007dce53SSunil Mushran 						     S_IFREG|S_IRUSR,
944007dce53SSunil Mushran 						     dlm->dlm_debugfs_subroot,
945007dce53SSunil Mushran 						     dlm, &debug_state_fops);
946007dce53SSunil Mushran 	if (!dc->debug_state_dentry) {
947007dce53SSunil Mushran 		mlog_errno(-ENOMEM);
948007dce53SSunil Mushran 		goto bail;
949007dce53SSunil Mushran 	}
950007dce53SSunil Mushran 
9514e3d24edSSunil Mushran 	/* for dumping lockres */
9524e3d24edSSunil Mushran 	dc->debug_lockres_dentry =
9534e3d24edSSunil Mushran 			debugfs_create_file(DLM_DEBUGFS_LOCKING_STATE,
9544e3d24edSSunil Mushran 					    S_IFREG|S_IRUSR,
9554e3d24edSSunil Mushran 					    dlm->dlm_debugfs_subroot,
9564e3d24edSSunil Mushran 					    dlm, &debug_lockres_fops);
9574e3d24edSSunil Mushran 	if (!dc->debug_lockres_dentry) {
9584e3d24edSSunil Mushran 		mlog_errno(-ENOMEM);
9594e3d24edSSunil Mushran 		goto bail;
9604e3d24edSSunil Mushran 	}
9614e3d24edSSunil Mushran 
962d0129aceSSunil Mushran 	/* for dumping mles */
963d0129aceSSunil Mushran 	dc->debug_mle_dentry = debugfs_create_file(DLM_DEBUGFS_MLE_STATE,
964d0129aceSSunil Mushran 						   S_IFREG|S_IRUSR,
965d0129aceSSunil Mushran 						   dlm->dlm_debugfs_subroot,
966d0129aceSSunil Mushran 						   dlm, &debug_mle_fops);
967d0129aceSSunil Mushran 	if (!dc->debug_mle_dentry) {
968d0129aceSSunil Mushran 		mlog_errno(-ENOMEM);
969d0129aceSSunil Mushran 		goto bail;
970d0129aceSSunil Mushran 	}
971d0129aceSSunil Mushran 
9727209300aSSunil Mushran 	/* for dumping lockres on the purge list */
9737209300aSSunil Mushran 	dc->debug_purgelist_dentry =
9747209300aSSunil Mushran 			debugfs_create_file(DLM_DEBUGFS_PURGE_LIST,
9757209300aSSunil Mushran 					    S_IFREG|S_IRUSR,
9767209300aSSunil Mushran 					    dlm->dlm_debugfs_subroot,
9777209300aSSunil Mushran 					    dlm, &debug_purgelist_fops);
9787209300aSSunil Mushran 	if (!dc->debug_purgelist_dentry) {
9797209300aSSunil Mushran 		mlog_errno(-ENOMEM);
9807209300aSSunil Mushran 		goto bail;
9817209300aSSunil Mushran 	}
9827209300aSSunil Mushran 
983007dce53SSunil Mushran 	dlm_debug_get(dc);
984007dce53SSunil Mushran 	return 0;
985007dce53SSunil Mushran 
986007dce53SSunil Mushran bail:
987007dce53SSunil Mushran 	dlm_debug_shutdown(dlm);
988007dce53SSunil Mushran 	return -ENOMEM;
989007dce53SSunil Mushran }
990007dce53SSunil Mushran 
991007dce53SSunil Mushran void dlm_debug_shutdown(struct dlm_ctxt *dlm)
992007dce53SSunil Mushran {
993007dce53SSunil Mushran 	struct dlm_debug_ctxt *dc = dlm->dlm_debug_ctxt;
994007dce53SSunil Mushran 
995007dce53SSunil Mushran 	if (dc) {
9967209300aSSunil Mushran 		if (dc->debug_purgelist_dentry)
9977209300aSSunil Mushran 			debugfs_remove(dc->debug_purgelist_dentry);
998d0129aceSSunil Mushran 		if (dc->debug_mle_dentry)
999d0129aceSSunil Mushran 			debugfs_remove(dc->debug_mle_dentry);
10004e3d24edSSunil Mushran 		if (dc->debug_lockres_dentry)
10014e3d24edSSunil Mushran 			debugfs_remove(dc->debug_lockres_dentry);
1002007dce53SSunil Mushran 		if (dc->debug_state_dentry)
1003007dce53SSunil Mushran 			debugfs_remove(dc->debug_state_dentry);
1004007dce53SSunil Mushran 		dlm_debug_put(dc);
1005007dce53SSunil Mushran 	}
1006007dce53SSunil Mushran }
10076325b4a2SSunil Mushran 
10086325b4a2SSunil Mushran /* subroot - domain dir */
10096325b4a2SSunil Mushran int dlm_create_debugfs_subroot(struct dlm_ctxt *dlm)
10106325b4a2SSunil Mushran {
10116325b4a2SSunil Mushran 	dlm->dlm_debugfs_subroot = debugfs_create_dir(dlm->name,
10126325b4a2SSunil Mushran 						      dlm_debugfs_root);
10136325b4a2SSunil Mushran 	if (!dlm->dlm_debugfs_subroot) {
10146325b4a2SSunil Mushran 		mlog_errno(-ENOMEM);
10156325b4a2SSunil Mushran 		goto bail;
10166325b4a2SSunil Mushran 	}
10176325b4a2SSunil Mushran 
1018007dce53SSunil Mushran 	dlm->dlm_debug_ctxt = kzalloc(sizeof(struct dlm_debug_ctxt),
1019007dce53SSunil Mushran 				      GFP_KERNEL);
1020007dce53SSunil Mushran 	if (!dlm->dlm_debug_ctxt) {
1021007dce53SSunil Mushran 		mlog_errno(-ENOMEM);
1022007dce53SSunil Mushran 		goto bail;
1023007dce53SSunil Mushran 	}
1024007dce53SSunil Mushran 	kref_init(&dlm->dlm_debug_ctxt->debug_refcnt);
1025007dce53SSunil Mushran 
10266325b4a2SSunil Mushran 	return 0;
10276325b4a2SSunil Mushran bail:
10286325b4a2SSunil Mushran 	dlm_destroy_debugfs_subroot(dlm);
10296325b4a2SSunil Mushran 	return -ENOMEM;
10306325b4a2SSunil Mushran }
10316325b4a2SSunil Mushran 
10326325b4a2SSunil Mushran void dlm_destroy_debugfs_subroot(struct dlm_ctxt *dlm)
10336325b4a2SSunil Mushran {
10346325b4a2SSunil Mushran 	if (dlm->dlm_debugfs_subroot)
10356325b4a2SSunil Mushran 		debugfs_remove(dlm->dlm_debugfs_subroot);
10366325b4a2SSunil Mushran }
10376325b4a2SSunil Mushran 
10386325b4a2SSunil Mushran /* debugfs root */
10396325b4a2SSunil Mushran int dlm_create_debugfs_root(void)
10406325b4a2SSunil Mushran {
10416325b4a2SSunil Mushran 	dlm_debugfs_root = debugfs_create_dir(DLM_DEBUGFS_DIR, NULL);
10426325b4a2SSunil Mushran 	if (!dlm_debugfs_root) {
10436325b4a2SSunil Mushran 		mlog_errno(-ENOMEM);
10446325b4a2SSunil Mushran 		return -ENOMEM;
10456325b4a2SSunil Mushran 	}
10466325b4a2SSunil Mushran 	return 0;
10476325b4a2SSunil Mushran }
10486325b4a2SSunil Mushran 
10496325b4a2SSunil Mushran void dlm_destroy_debugfs_root(void)
10506325b4a2SSunil Mushran {
10516325b4a2SSunil Mushran 	if (dlm_debugfs_root)
10526325b4a2SSunil Mushran 		debugfs_remove(dlm_debugfs_root);
10536325b4a2SSunil Mushran }
10546325b4a2SSunil Mushran #endif	/* CONFIG_DEBUG_FS */
1055