xref: /openbmc/linux/fs/ocfs2/dlm/dlmdebug.c (revision b02da32b)
1328970deSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2fa60ce2cSMasahiro Yamada /*
36714d8e8SKurt Hackel  * dlmdebug.c
46714d8e8SKurt Hackel  *
56714d8e8SKurt Hackel  * debug functionality for the dlm
66714d8e8SKurt Hackel  *
7c834cdb1SSunil Mushran  * Copyright (C) 2004, 2008 Oracle.  All rights reserved.
86714d8e8SKurt Hackel  */
96714d8e8SKurt Hackel 
106714d8e8SKurt Hackel #include <linux/types.h>
116714d8e8SKurt Hackel #include <linux/slab.h>
126714d8e8SKurt Hackel #include <linux/highmem.h>
136714d8e8SKurt Hackel #include <linux/sysctl.h>
146714d8e8SKurt Hackel #include <linux/spinlock.h>
156325b4a2SSunil Mushran #include <linux/debugfs.h>
16afeacc8cSPaul Gortmaker #include <linux/export.h>
176714d8e8SKurt Hackel 
18ca322fb6SMasahiro Yamada #include "../cluster/heartbeat.h"
19ca322fb6SMasahiro Yamada #include "../cluster/nodemanager.h"
20ca322fb6SMasahiro Yamada #include "../cluster/tcp.h"
216714d8e8SKurt Hackel 
226714d8e8SKurt Hackel #include "dlmapi.h"
236714d8e8SKurt Hackel #include "dlmcommon.h"
246714d8e8SKurt Hackel #include "dlmdomain.h"
256325b4a2SSunil Mushran #include "dlmdebug.h"
266714d8e8SKurt Hackel 
276714d8e8SKurt Hackel #define MLOG_MASK_PREFIX ML_DLM
28ca322fb6SMasahiro Yamada #include "../cluster/masklog.h"
296714d8e8SKurt Hackel 
3095642e56SAdrian Bunk static int stringify_lockname(const char *lockname, int locklen, char *buf,
3195642e56SAdrian Bunk 			      int len);
32c834cdb1SSunil Mushran 
dlm_print_one_lock_resource(struct dlm_lock_resource * res)336714d8e8SKurt Hackel void dlm_print_one_lock_resource(struct dlm_lock_resource *res)
346714d8e8SKurt Hackel {
356714d8e8SKurt Hackel 	spin_lock(&res->spinlock);
366714d8e8SKurt Hackel 	__dlm_print_one_lock_resource(res);
376714d8e8SKurt Hackel 	spin_unlock(&res->spinlock);
386714d8e8SKurt Hackel }
396714d8e8SKurt Hackel 
dlm_print_lockres_refmap(struct dlm_lock_resource * res)40ba2bf218SKurt Hackel static void dlm_print_lockres_refmap(struct dlm_lock_resource *res)
41ba2bf218SKurt Hackel {
42ba2bf218SKurt Hackel 	int bit;
43ba2bf218SKurt Hackel 	assert_spin_locked(&res->spinlock);
44ba2bf218SKurt Hackel 
458f50eb97SSunil Mushran 	printk("  refmap nodes: [ ");
46ba2bf218SKurt Hackel 	bit = 0;
47ba2bf218SKurt Hackel 	while (1) {
48ba2bf218SKurt Hackel 		bit = find_next_bit(res->refmap, O2NM_MAX_NODES, bit);
49ba2bf218SKurt Hackel 		if (bit >= O2NM_MAX_NODES)
50ba2bf218SKurt Hackel 			break;
518f50eb97SSunil Mushran 		printk("%u ", bit);
52ba2bf218SKurt Hackel 		bit++;
53ba2bf218SKurt Hackel 	}
548f50eb97SSunil Mushran 	printk("], inflight=%u\n", res->inflight_locks);
55c834cdb1SSunil Mushran }
56c834cdb1SSunil Mushran 
__dlm_print_lock(struct dlm_lock * lock)57c834cdb1SSunil Mushran static void __dlm_print_lock(struct dlm_lock *lock)
58c834cdb1SSunil Mushran {
59c834cdb1SSunil Mushran 	spin_lock(&lock->spinlock);
60c834cdb1SSunil Mushran 
618f50eb97SSunil Mushran 	printk("    type=%d, conv=%d, node=%u, cookie=%u:%llu, "
62c834cdb1SSunil Mushran 	       "ref=%u, ast=(empty=%c,pend=%c), bast=(empty=%c,pend=%c), "
63c834cdb1SSunil Mushran 	       "pending=(conv=%c,lock=%c,cancel=%c,unlock=%c)\n",
64c834cdb1SSunil Mushran 	       lock->ml.type, lock->ml.convert_type, lock->ml.node,
65c834cdb1SSunil Mushran 	       dlm_get_lock_cookie_node(be64_to_cpu(lock->ml.cookie)),
66c834cdb1SSunil Mushran 	       dlm_get_lock_cookie_seq(be64_to_cpu(lock->ml.cookie)),
672c935bc5SPeter Zijlstra 	       kref_read(&lock->lock_refs),
68c834cdb1SSunil Mushran 	       (list_empty(&lock->ast_list) ? 'y' : 'n'),
69c834cdb1SSunil Mushran 	       (lock->ast_pending ? 'y' : 'n'),
70c834cdb1SSunil Mushran 	       (list_empty(&lock->bast_list) ? 'y' : 'n'),
71c834cdb1SSunil Mushran 	       (lock->bast_pending ? 'y' : 'n'),
72c834cdb1SSunil Mushran 	       (lock->convert_pending ? 'y' : 'n'),
73c834cdb1SSunil Mushran 	       (lock->lock_pending ? 'y' : 'n'),
74c834cdb1SSunil Mushran 	       (lock->cancel_pending ? 'y' : 'n'),
75c834cdb1SSunil Mushran 	       (lock->unlock_pending ? 'y' : 'n'));
76c834cdb1SSunil Mushran 
77c834cdb1SSunil Mushran 	spin_unlock(&lock->spinlock);
78ba2bf218SKurt Hackel }
79ba2bf218SKurt Hackel 
__dlm_print_one_lock_resource(struct dlm_lock_resource * res)806714d8e8SKurt Hackel void __dlm_print_one_lock_resource(struct dlm_lock_resource *res)
816714d8e8SKurt Hackel {
826714d8e8SKurt Hackel 	struct dlm_lock *lock;
83c834cdb1SSunil Mushran 	char buf[DLM_LOCKID_NAME_MAX];
846714d8e8SKurt Hackel 
856714d8e8SKurt Hackel 	assert_spin_locked(&res->spinlock);
866714d8e8SKurt Hackel 
87c834cdb1SSunil Mushran 	stringify_lockname(res->lockname.name, res->lockname.len,
8886a06abaSSunil Mushran 			   buf, sizeof(buf));
898f50eb97SSunil Mushran 	printk("lockres: %s, owner=%u, state=%u\n",
90c834cdb1SSunil Mushran 	       buf, res->owner, res->state);
918f50eb97SSunil Mushran 	printk("  last used: %lu, refcnt: %u, on purge list: %s\n",
922c935bc5SPeter Zijlstra 	       res->last_used, kref_read(&res->refs),
93c834cdb1SSunil Mushran 	       list_empty(&res->purge) ? "no" : "yes");
948f50eb97SSunil Mushran 	printk("  on dirty list: %s, on reco list: %s, "
95c834cdb1SSunil Mushran 	       "migrating pending: %s\n",
96c834cdb1SSunil Mushran 	       list_empty(&res->dirty) ? "no" : "yes",
97c834cdb1SSunil Mushran 	       list_empty(&res->recovering) ? "no" : "yes",
98c834cdb1SSunil Mushran 	       res->migration_pending ? "yes" : "no");
998f50eb97SSunil Mushran 	printk("  inflight locks: %d, asts reserved: %d\n",
100c834cdb1SSunil Mushran 	       res->inflight_locks, atomic_read(&res->asts_reserved));
101ba2bf218SKurt Hackel 	dlm_print_lockres_refmap(res);
1028f50eb97SSunil Mushran 	printk("  granted queue:\n");
103df53cd3bSDong Fang 	list_for_each_entry(lock, &res->granted, list) {
104c834cdb1SSunil Mushran 		__dlm_print_lock(lock);
1056714d8e8SKurt Hackel 	}
1068f50eb97SSunil Mushran 	printk("  converting queue:\n");
107df53cd3bSDong Fang 	list_for_each_entry(lock, &res->converting, list) {
108c834cdb1SSunil Mushran 		__dlm_print_lock(lock);
1096714d8e8SKurt Hackel 	}
1108f50eb97SSunil Mushran 	printk("  blocked queue:\n");
111df53cd3bSDong Fang 	list_for_each_entry(lock, &res->blocked, list) {
112c834cdb1SSunil Mushran 		__dlm_print_lock(lock);
1136714d8e8SKurt Hackel 	}
1146714d8e8SKurt Hackel }
1156714d8e8SKurt Hackel 
dlm_print_one_lock(struct dlm_lock * lockid)1166714d8e8SKurt Hackel void dlm_print_one_lock(struct dlm_lock *lockid)
1176714d8e8SKurt Hackel {
1186714d8e8SKurt Hackel 	dlm_print_one_lock_resource(lockid->lockres);
1196714d8e8SKurt Hackel }
1206714d8e8SKurt Hackel EXPORT_SYMBOL_GPL(dlm_print_one_lock);
1216714d8e8SKurt Hackel 
1226714d8e8SKurt Hackel static const char *dlm_errnames[] = {
1236714d8e8SKurt Hackel 	[DLM_NORMAL] =			"DLM_NORMAL",
1246714d8e8SKurt Hackel 	[DLM_GRANTED] =			"DLM_GRANTED",
1256714d8e8SKurt Hackel 	[DLM_DENIED] =			"DLM_DENIED",
1266714d8e8SKurt Hackel 	[DLM_DENIED_NOLOCKS] =		"DLM_DENIED_NOLOCKS",
1276714d8e8SKurt Hackel 	[DLM_WORKING] =			"DLM_WORKING",
1286714d8e8SKurt Hackel 	[DLM_BLOCKED] =			"DLM_BLOCKED",
1296714d8e8SKurt Hackel 	[DLM_BLOCKED_ORPHAN] =		"DLM_BLOCKED_ORPHAN",
1306714d8e8SKurt Hackel 	[DLM_DENIED_GRACE_PERIOD] =	"DLM_DENIED_GRACE_PERIOD",
1316714d8e8SKurt Hackel 	[DLM_SYSERR] =			"DLM_SYSERR",
1326714d8e8SKurt Hackel 	[DLM_NOSUPPORT] =		"DLM_NOSUPPORT",
1336714d8e8SKurt Hackel 	[DLM_CANCELGRANT] =		"DLM_CANCELGRANT",
1346714d8e8SKurt Hackel 	[DLM_IVLOCKID] =		"DLM_IVLOCKID",
1356714d8e8SKurt Hackel 	[DLM_SYNC] =			"DLM_SYNC",
1366714d8e8SKurt Hackel 	[DLM_BADTYPE] =			"DLM_BADTYPE",
1376714d8e8SKurt Hackel 	[DLM_BADRESOURCE] =		"DLM_BADRESOURCE",
1386714d8e8SKurt Hackel 	[DLM_MAXHANDLES] =		"DLM_MAXHANDLES",
1396714d8e8SKurt Hackel 	[DLM_NOCLINFO] =		"DLM_NOCLINFO",
1406714d8e8SKurt Hackel 	[DLM_NOLOCKMGR] =		"DLM_NOLOCKMGR",
1416714d8e8SKurt Hackel 	[DLM_NOPURGED] =		"DLM_NOPURGED",
1426714d8e8SKurt Hackel 	[DLM_BADARGS] =			"DLM_BADARGS",
1436714d8e8SKurt Hackel 	[DLM_VOID] =			"DLM_VOID",
1446714d8e8SKurt Hackel 	[DLM_NOTQUEUED] =		"DLM_NOTQUEUED",
1456714d8e8SKurt Hackel 	[DLM_IVBUFLEN] =		"DLM_IVBUFLEN",
1466714d8e8SKurt Hackel 	[DLM_CVTUNGRANT] =		"DLM_CVTUNGRANT",
1476714d8e8SKurt Hackel 	[DLM_BADPARAM] =		"DLM_BADPARAM",
1486714d8e8SKurt Hackel 	[DLM_VALNOTVALID] =		"DLM_VALNOTVALID",
1496714d8e8SKurt Hackel 	[DLM_REJECTED] =		"DLM_REJECTED",
1506714d8e8SKurt Hackel 	[DLM_ABORT] =			"DLM_ABORT",
1516714d8e8SKurt Hackel 	[DLM_CANCEL] =			"DLM_CANCEL",
1526714d8e8SKurt Hackel 	[DLM_IVRESHANDLE] =		"DLM_IVRESHANDLE",
1536714d8e8SKurt Hackel 	[DLM_DEADLOCK] =		"DLM_DEADLOCK",
1546714d8e8SKurt Hackel 	[DLM_DENIED_NOASTS] =		"DLM_DENIED_NOASTS",
1556714d8e8SKurt Hackel 	[DLM_FORWARD] =			"DLM_FORWARD",
1566714d8e8SKurt Hackel 	[DLM_TIMEOUT] =			"DLM_TIMEOUT",
1576714d8e8SKurt Hackel 	[DLM_IVGROUPID] =		"DLM_IVGROUPID",
1586714d8e8SKurt Hackel 	[DLM_VERS_CONFLICT] =		"DLM_VERS_CONFLICT",
1596714d8e8SKurt Hackel 	[DLM_BAD_DEVICE_PATH] =		"DLM_BAD_DEVICE_PATH",
1606714d8e8SKurt Hackel 	[DLM_NO_DEVICE_PERMISSION] =	"DLM_NO_DEVICE_PERMISSION",
1616714d8e8SKurt Hackel 	[DLM_NO_CONTROL_DEVICE ] =	"DLM_NO_CONTROL_DEVICE ",
1626714d8e8SKurt Hackel 	[DLM_RECOVERING] =		"DLM_RECOVERING",
1636714d8e8SKurt Hackel 	[DLM_MIGRATING] =		"DLM_MIGRATING",
1646714d8e8SKurt Hackel 	[DLM_MAXSTATS] =		"DLM_MAXSTATS",
1656714d8e8SKurt Hackel };
1666714d8e8SKurt Hackel 
1676714d8e8SKurt Hackel static const char *dlm_errmsgs[] = {
1686714d8e8SKurt Hackel 	[DLM_NORMAL] = 			"request in progress",
1696714d8e8SKurt Hackel 	[DLM_GRANTED] = 		"request granted",
1706714d8e8SKurt Hackel 	[DLM_DENIED] = 			"request denied",
1716714d8e8SKurt Hackel 	[DLM_DENIED_NOLOCKS] = 		"request denied, out of system resources",
1726714d8e8SKurt Hackel 	[DLM_WORKING] = 		"async request in progress",
1736714d8e8SKurt Hackel 	[DLM_BLOCKED] = 		"lock request blocked",
1746714d8e8SKurt Hackel 	[DLM_BLOCKED_ORPHAN] = 		"lock request blocked by a orphan lock",
1756714d8e8SKurt Hackel 	[DLM_DENIED_GRACE_PERIOD] = 	"topological change in progress",
1766714d8e8SKurt Hackel 	[DLM_SYSERR] = 			"system error",
1776714d8e8SKurt Hackel 	[DLM_NOSUPPORT] = 		"unsupported",
1786714d8e8SKurt Hackel 	[DLM_CANCELGRANT] = 		"can't cancel convert: already granted",
1796714d8e8SKurt Hackel 	[DLM_IVLOCKID] = 		"bad lockid",
1806714d8e8SKurt Hackel 	[DLM_SYNC] = 			"synchronous request granted",
1816714d8e8SKurt Hackel 	[DLM_BADTYPE] = 		"bad resource type",
1826714d8e8SKurt Hackel 	[DLM_BADRESOURCE] = 		"bad resource handle",
1836714d8e8SKurt Hackel 	[DLM_MAXHANDLES] = 		"no more resource handles",
1846714d8e8SKurt Hackel 	[DLM_NOCLINFO] = 		"can't contact cluster manager",
1856714d8e8SKurt Hackel 	[DLM_NOLOCKMGR] = 		"can't contact lock manager",
1866714d8e8SKurt Hackel 	[DLM_NOPURGED] = 		"can't contact purge daemon",
1876714d8e8SKurt Hackel 	[DLM_BADARGS] = 		"bad api args",
1886714d8e8SKurt Hackel 	[DLM_VOID] = 			"no status",
1896714d8e8SKurt Hackel 	[DLM_NOTQUEUED] = 		"NOQUEUE was specified and request failed",
1906714d8e8SKurt Hackel 	[DLM_IVBUFLEN] = 		"invalid resource name length",
1916714d8e8SKurt Hackel 	[DLM_CVTUNGRANT] = 		"attempted to convert ungranted lock",
1926714d8e8SKurt Hackel 	[DLM_BADPARAM] = 		"invalid lock mode specified",
1936714d8e8SKurt Hackel 	[DLM_VALNOTVALID] = 		"value block has been invalidated",
1946714d8e8SKurt Hackel 	[DLM_REJECTED] = 		"request rejected, unrecognized client",
1956714d8e8SKurt Hackel 	[DLM_ABORT] = 			"blocked lock request cancelled",
1966714d8e8SKurt Hackel 	[DLM_CANCEL] = 			"conversion request cancelled",
1976714d8e8SKurt Hackel 	[DLM_IVRESHANDLE] = 		"invalid resource handle",
1986714d8e8SKurt Hackel 	[DLM_DEADLOCK] = 		"deadlock recovery refused this request",
1996714d8e8SKurt Hackel 	[DLM_DENIED_NOASTS] = 		"failed to allocate AST",
2006714d8e8SKurt Hackel 	[DLM_FORWARD] = 		"request must wait for primary's response",
2016714d8e8SKurt Hackel 	[DLM_TIMEOUT] = 		"timeout value for lock has expired",
2026714d8e8SKurt Hackel 	[DLM_IVGROUPID] = 		"invalid group specification",
2036714d8e8SKurt Hackel 	[DLM_VERS_CONFLICT] = 		"version conflicts prevent request handling",
2046714d8e8SKurt Hackel 	[DLM_BAD_DEVICE_PATH] = 	"Locks device does not exist or path wrong",
2056714d8e8SKurt Hackel 	[DLM_NO_DEVICE_PERMISSION] = 	"Client has insufficient perms for device",
2066714d8e8SKurt Hackel 	[DLM_NO_CONTROL_DEVICE] = 	"Cannot set options on opened device ",
2076714d8e8SKurt Hackel 	[DLM_RECOVERING] = 		"lock resource being recovered",
2086714d8e8SKurt Hackel 	[DLM_MIGRATING] = 		"lock resource being migrated",
2096714d8e8SKurt Hackel 	[DLM_MAXSTATS] = 		"invalid error number",
2106714d8e8SKurt Hackel };
2116714d8e8SKurt Hackel 
dlm_errmsg(enum dlm_status err)2126714d8e8SKurt Hackel const char *dlm_errmsg(enum dlm_status err)
2136714d8e8SKurt Hackel {
2146714d8e8SKurt Hackel 	if (err >= DLM_MAXSTATS || err < 0)
2156714d8e8SKurt Hackel 		return dlm_errmsgs[DLM_MAXSTATS];
2166714d8e8SKurt Hackel 	return dlm_errmsgs[err];
2176714d8e8SKurt Hackel }
2186714d8e8SKurt Hackel EXPORT_SYMBOL_GPL(dlm_errmsg);
2196714d8e8SKurt Hackel 
dlm_errname(enum dlm_status err)2206714d8e8SKurt Hackel const char *dlm_errname(enum dlm_status err)
2216714d8e8SKurt Hackel {
2226714d8e8SKurt Hackel 	if (err >= DLM_MAXSTATS || err < 0)
2236714d8e8SKurt Hackel 		return dlm_errnames[DLM_MAXSTATS];
2246714d8e8SKurt Hackel 	return dlm_errnames[err];
2256714d8e8SKurt Hackel }
2266714d8e8SKurt Hackel EXPORT_SYMBOL_GPL(dlm_errname);
2276325b4a2SSunil Mushran 
2284e3d24edSSunil Mushran /* NOTE: This function converts a lockname into a string. It uses knowledge
2294e3d24edSSunil Mushran  * of the format of the lockname that should be outside the purview of the dlm.
2304e3d24edSSunil Mushran  * We are adding only to make dlm debugging slightly easier.
2314e3d24edSSunil Mushran  *
2324e3d24edSSunil Mushran  * For more on lockname formats, please refer to dlmglue.c and ocfs2_lockid.h.
2334e3d24edSSunil Mushran  */
stringify_lockname(const char * lockname,int locklen,char * buf,int len)23495642e56SAdrian Bunk static int stringify_lockname(const char *lockname, int locklen, char *buf,
23595642e56SAdrian Bunk 			      int len)
2364e3d24edSSunil Mushran {
2374e3d24edSSunil Mushran 	int out = 0;
2384e3d24edSSunil Mushran 	__be64 inode_blkno_be;
2394e3d24edSSunil Mushran 
2404e3d24edSSunil Mushran #define OCFS2_DENTRY_LOCK_INO_START	18
2414e3d24edSSunil Mushran 	if (*lockname == 'N') {
2424e3d24edSSunil Mushran 		memcpy((__be64 *)&inode_blkno_be,
2434e3d24edSSunil Mushran 		       (char *)&lockname[OCFS2_DENTRY_LOCK_INO_START],
2444e3d24edSSunil Mushran 		       sizeof(__be64));
245d293d3afSTakashi Iwai 		out += scnprintf(buf + out, len - out, "%.*s%08x",
2464e3d24edSSunil Mushran 				OCFS2_DENTRY_LOCK_INO_START - 1, lockname,
2474e3d24edSSunil Mushran 				(unsigned int)be64_to_cpu(inode_blkno_be));
2484e3d24edSSunil Mushran 	} else
249d293d3afSTakashi Iwai 		out += scnprintf(buf + out, len - out, "%.*s",
2504e3d24edSSunil Mushran 				locklen, lockname);
2514e3d24edSSunil Mushran 	return out;
2524e3d24edSSunil Mushran }
2534e3d24edSSunil Mushran 
stringify_nodemap(unsigned long * nodemap,int maxnodes,char * buf,int len)254e5a0334cSSunil Mushran static int stringify_nodemap(unsigned long *nodemap, int maxnodes,
255e5a0334cSSunil Mushran 			     char *buf, int len)
256e5a0334cSSunil Mushran {
257e5a0334cSSunil Mushran 	int out = 0;
258e5a0334cSSunil Mushran 	int i = -1;
259e5a0334cSSunil Mushran 
260e5a0334cSSunil Mushran 	while ((i = find_next_bit(nodemap, maxnodes, i + 1)) < maxnodes)
261d293d3afSTakashi Iwai 		out += scnprintf(buf + out, len - out, "%d ", i);
262e5a0334cSSunil Mushran 
263e5a0334cSSunil Mushran 	return out;
264e5a0334cSSunil Mushran }
265e5a0334cSSunil Mushran 
dump_mle(struct dlm_master_list_entry * mle,char * buf,int len)266e5a0334cSSunil Mushran static int dump_mle(struct dlm_master_list_entry *mle, char *buf, int len)
267e5a0334cSSunil Mushran {
268e5a0334cSSunil Mushran 	int out = 0;
269e5a0334cSSunil Mushran 	char *mle_type;
270e5a0334cSSunil Mushran 
271e5a0334cSSunil Mushran 	if (mle->type == DLM_MLE_BLOCK)
272e5a0334cSSunil Mushran 		mle_type = "BLK";
273e5a0334cSSunil Mushran 	else if (mle->type == DLM_MLE_MASTER)
274e5a0334cSSunil Mushran 		mle_type = "MAS";
275e5a0334cSSunil Mushran 	else
276e5a0334cSSunil Mushran 		mle_type = "MIG";
277e5a0334cSSunil Mushran 
2787141514bSSunil Mushran 	out += stringify_lockname(mle->mname, mle->mnamelen, buf + out, len - out);
279d293d3afSTakashi Iwai 	out += scnprintf(buf + out, len - out,
280e5a0334cSSunil Mushran 			"\t%3s\tmas=%3u\tnew=%3u\tevt=%1d\tuse=%1d\tref=%3d\n",
281e5a0334cSSunil Mushran 			mle_type, mle->master, mle->new_master,
282e5a0334cSSunil Mushran 			!list_empty(&mle->hb_events),
283e5a0334cSSunil Mushran 			!!mle->inuse,
2842c935bc5SPeter Zijlstra 			kref_read(&mle->mle_refs));
285e5a0334cSSunil Mushran 
286d293d3afSTakashi Iwai 	out += scnprintf(buf + out, len - out, "Maybe=");
287e5a0334cSSunil Mushran 	out += stringify_nodemap(mle->maybe_map, O2NM_MAX_NODES,
288e5a0334cSSunil Mushran 				 buf + out, len - out);
289d293d3afSTakashi Iwai 	out += scnprintf(buf + out, len - out, "\n");
290e5a0334cSSunil Mushran 
291d293d3afSTakashi Iwai 	out += scnprintf(buf + out, len - out, "Vote=");
292e5a0334cSSunil Mushran 	out += stringify_nodemap(mle->vote_map, O2NM_MAX_NODES,
293e5a0334cSSunil Mushran 				 buf + out, len - out);
294d293d3afSTakashi Iwai 	out += scnprintf(buf + out, len - out, "\n");
295e5a0334cSSunil Mushran 
296d293d3afSTakashi Iwai 	out += scnprintf(buf + out, len - out, "Response=");
297e5a0334cSSunil Mushran 	out += stringify_nodemap(mle->response_map, O2NM_MAX_NODES,
298e5a0334cSSunil Mushran 				 buf + out, len - out);
299d293d3afSTakashi Iwai 	out += scnprintf(buf + out, len - out, "\n");
300e5a0334cSSunil Mushran 
301d293d3afSTakashi Iwai 	out += scnprintf(buf + out, len - out, "Node=");
302e5a0334cSSunil Mushran 	out += stringify_nodemap(mle->node_map, O2NM_MAX_NODES,
303e5a0334cSSunil Mushran 				 buf + out, len - out);
304d293d3afSTakashi Iwai 	out += scnprintf(buf + out, len - out, "\n");
305e5a0334cSSunil Mushran 
306d293d3afSTakashi Iwai 	out += scnprintf(buf + out, len - out, "\n");
307e5a0334cSSunil Mushran 
308e5a0334cSSunil Mushran 	return out;
309e5a0334cSSunil Mushran }
310e5a0334cSSunil Mushran 
dlm_print_one_mle(struct dlm_master_list_entry * mle)311e5a0334cSSunil Mushran void dlm_print_one_mle(struct dlm_master_list_entry *mle)
312e5a0334cSSunil Mushran {
313e5a0334cSSunil Mushran 	char *buf;
314e5a0334cSSunil Mushran 
31599986576SJia-Ju Bai 	buf = (char *) get_zeroed_page(GFP_ATOMIC);
316e5a0334cSSunil Mushran 	if (buf) {
317e5a0334cSSunil Mushran 		dump_mle(mle, buf, PAGE_SIZE - 1);
318e5a0334cSSunil Mushran 		free_page((unsigned long)buf);
319e5a0334cSSunil Mushran 	}
320e5a0334cSSunil Mushran }
321e5a0334cSSunil Mushran 
322e5a0334cSSunil Mushran #ifdef CONFIG_DEBUG_FS
323e5a0334cSSunil Mushran 
3241a5c4e2aSFabian Frederick static struct dentry *dlm_debugfs_root;
325e5a0334cSSunil Mushran 
3266325b4a2SSunil Mushran #define DLM_DEBUGFS_DIR				"o2dlm"
327007dce53SSunil Mushran #define DLM_DEBUGFS_DLM_STATE			"dlm_state"
3284e3d24edSSunil Mushran #define DLM_DEBUGFS_LOCKING_STATE		"locking_state"
329d0129aceSSunil Mushran #define DLM_DEBUGFS_MLE_STATE			"mle_state"
3307209300aSSunil Mushran #define DLM_DEBUGFS_PURGE_LIST			"purge_list"
331007dce53SSunil Mushran 
332007dce53SSunil Mushran /* begin - utils funcs */
debug_release(struct inode * inode,struct file * file)33302bd9c39SSunil Mushran static int debug_release(struct inode *inode, struct file *file)
334007dce53SSunil Mushran {
33502bd9c39SSunil Mushran 	free_page((unsigned long)file->private_data);
33602bd9c39SSunil Mushran 	return 0;
337007dce53SSunil Mushran }
338007dce53SSunil Mushran 
debug_read(struct file * file,char __user * buf,size_t nbytes,loff_t * ppos)33902bd9c39SSunil Mushran static ssize_t debug_read(struct file *file, char __user *buf,
340007dce53SSunil Mushran 			  size_t nbytes, loff_t *ppos)
341007dce53SSunil Mushran {
34202bd9c39SSunil Mushran 	return simple_read_from_buffer(buf, nbytes, ppos, file->private_data,
34302bd9c39SSunil Mushran 				       i_size_read(file->f_mapping->host));
344007dce53SSunil Mushran }
345007dce53SSunil Mushran /* end - util funcs */
346007dce53SSunil Mushran 
3477209300aSSunil Mushran /* begin - purge list funcs */
debug_purgelist_print(struct dlm_ctxt * dlm,char * buf,int len)34802bd9c39SSunil Mushran static int debug_purgelist_print(struct dlm_ctxt *dlm, char *buf, int len)
3497209300aSSunil Mushran {
3507209300aSSunil Mushran 	struct dlm_lock_resource *res;
3517209300aSSunil Mushran 	int out = 0;
3527209300aSSunil Mushran 	unsigned long total = 0;
3537209300aSSunil Mushran 
354d293d3afSTakashi Iwai 	out += scnprintf(buf + out, len - out,
3557209300aSSunil Mushran 			"Dumping Purgelist for Domain: %s\n", dlm->name);
3567209300aSSunil Mushran 
3577209300aSSunil Mushran 	spin_lock(&dlm->spinlock);
3587209300aSSunil Mushran 	list_for_each_entry(res, &dlm->purge_list, purge) {
3597209300aSSunil Mushran 		++total;
36002bd9c39SSunil Mushran 		if (len - out < 100)
3617209300aSSunil Mushran 			continue;
3627209300aSSunil Mushran 		spin_lock(&res->spinlock);
3637209300aSSunil Mushran 		out += stringify_lockname(res->lockname.name,
3647209300aSSunil Mushran 					  res->lockname.len,
36502bd9c39SSunil Mushran 					  buf + out, len - out);
366d293d3afSTakashi Iwai 		out += scnprintf(buf + out, len - out, "\t%ld\n",
3677209300aSSunil Mushran 				(jiffies - res->last_used)/HZ);
3687209300aSSunil Mushran 		spin_unlock(&res->spinlock);
3697209300aSSunil Mushran 	}
3707209300aSSunil Mushran 	spin_unlock(&dlm->spinlock);
3717209300aSSunil Mushran 
372d293d3afSTakashi Iwai 	out += scnprintf(buf + out, len - out, "Total on list: %lu\n", total);
3737209300aSSunil Mushran 
3747209300aSSunil Mushran 	return out;
3757209300aSSunil Mushran }
3767209300aSSunil Mushran 
debug_purgelist_open(struct inode * inode,struct file * file)3777209300aSSunil Mushran static int debug_purgelist_open(struct inode *inode, struct file *file)
3787209300aSSunil Mushran {
3797209300aSSunil Mushran 	struct dlm_ctxt *dlm = inode->i_private;
38002bd9c39SSunil Mushran 	char *buf = NULL;
3817209300aSSunil Mushran 
38202bd9c39SSunil Mushran 	buf = (char *) get_zeroed_page(GFP_NOFS);
38302bd9c39SSunil Mushran 	if (!buf)
3847209300aSSunil Mushran 		goto bail;
3857209300aSSunil Mushran 
38602bd9c39SSunil Mushran 	i_size_write(inode, debug_purgelist_print(dlm, buf, PAGE_SIZE - 1));
3877209300aSSunil Mushran 
38802bd9c39SSunil Mushran 	file->private_data = buf;
3897209300aSSunil Mushran 
3907209300aSSunil Mushran 	return 0;
3917209300aSSunil Mushran bail:
3927209300aSSunil Mushran 	return -ENOMEM;
3937209300aSSunil Mushran }
3947209300aSSunil Mushran 
395828c0950SAlexey Dobriyan static const struct file_operations debug_purgelist_fops = {
3967209300aSSunil Mushran 	.open =		debug_purgelist_open,
39702bd9c39SSunil Mushran 	.release =	debug_release,
39802bd9c39SSunil Mushran 	.read =		debug_read,
39902bd9c39SSunil Mushran 	.llseek =	generic_file_llseek,
4007209300aSSunil Mushran };
4017209300aSSunil Mushran /* end - purge list funcs */
4027209300aSSunil Mushran 
403d0129aceSSunil Mushran /* begin - debug mle funcs */
debug_mle_print(struct dlm_ctxt * dlm,char * buf,int len)40402bd9c39SSunil Mushran static int debug_mle_print(struct dlm_ctxt *dlm, char *buf, int len)
405d0129aceSSunil Mushran {
406d0129aceSSunil Mushran 	struct dlm_master_list_entry *mle;
4072ed6c750SSunil Mushran 	struct hlist_head *bucket;
4082ed6c750SSunil Mushran 	int i, out = 0;
40993f3b86fSJoel Becker 	unsigned long total = 0, longest = 0, bucket_count = 0;
410d0129aceSSunil Mushran 
411d293d3afSTakashi Iwai 	out += scnprintf(buf + out, len - out,
412d0129aceSSunil Mushran 			"Dumping MLEs for Domain: %s\n", dlm->name);
413d0129aceSSunil Mushran 
414d0129aceSSunil Mushran 	spin_lock(&dlm->master_lock);
4152ed6c750SSunil Mushran 	for (i = 0; i < DLM_HASH_BUCKETS; i++) {
4162ed6c750SSunil Mushran 		bucket = dlm_master_hash(dlm, i);
417df53cd3bSDong Fang 		hlist_for_each_entry(mle, bucket, master_hash_node) {
418d0129aceSSunil Mushran 			++total;
41993f3b86fSJoel Becker 			++bucket_count;
42002bd9c39SSunil Mushran 			if (len - out < 200)
421d0129aceSSunil Mushran 				continue;
42202bd9c39SSunil Mushran 			out += dump_mle(mle, buf + out, len - out);
423d0129aceSSunil Mushran 		}
42493f3b86fSJoel Becker 		longest = max(longest, bucket_count);
42593f3b86fSJoel Becker 		bucket_count = 0;
4262ed6c750SSunil Mushran 	}
427d0129aceSSunil Mushran 	spin_unlock(&dlm->master_lock);
428d0129aceSSunil Mushran 
429d293d3afSTakashi Iwai 	out += scnprintf(buf + out, len - out,
43079c83ea1Salex chen 			"Total: %lu, Longest: %lu\n", total, longest);
431d0129aceSSunil Mushran 	return out;
432d0129aceSSunil Mushran }
433d0129aceSSunil Mushran 
debug_mle_open(struct inode * inode,struct file * file)434d0129aceSSunil Mushran static int debug_mle_open(struct inode *inode, struct file *file)
435d0129aceSSunil Mushran {
436d0129aceSSunil Mushran 	struct dlm_ctxt *dlm = inode->i_private;
43702bd9c39SSunil Mushran 	char *buf = NULL;
438d0129aceSSunil Mushran 
43902bd9c39SSunil Mushran 	buf = (char *) get_zeroed_page(GFP_NOFS);
44002bd9c39SSunil Mushran 	if (!buf)
441d0129aceSSunil Mushran 		goto bail;
442d0129aceSSunil Mushran 
44302bd9c39SSunil Mushran 	i_size_write(inode, debug_mle_print(dlm, buf, PAGE_SIZE - 1));
444d0129aceSSunil Mushran 
44502bd9c39SSunil Mushran 	file->private_data = buf;
446d0129aceSSunil Mushran 
447d0129aceSSunil Mushran 	return 0;
448d0129aceSSunil Mushran bail:
449d0129aceSSunil Mushran 	return -ENOMEM;
450d0129aceSSunil Mushran }
451d0129aceSSunil Mushran 
452828c0950SAlexey Dobriyan static const struct file_operations debug_mle_fops = {
453d0129aceSSunil Mushran 	.open =		debug_mle_open,
45402bd9c39SSunil Mushran 	.release =	debug_release,
45502bd9c39SSunil Mushran 	.read =		debug_read,
45602bd9c39SSunil Mushran 	.llseek =	generic_file_llseek,
457d0129aceSSunil Mushran };
458d0129aceSSunil Mushran 
459d0129aceSSunil Mushran /* end - debug mle funcs */
460d0129aceSSunil Mushran 
4614e3d24edSSunil Mushran /* begin - debug lockres funcs */
dump_lock(struct dlm_lock * lock,int list_type,char * buf,int len)4624e3d24edSSunil Mushran static int dump_lock(struct dlm_lock *lock, int list_type, char *buf, int len)
4634e3d24edSSunil Mushran {
4644e3d24edSSunil Mushran 	int out;
4654e3d24edSSunil Mushran 
4664e3d24edSSunil Mushran #define DEBUG_LOCK_VERSION	1
4674e3d24edSSunil Mushran 	spin_lock(&lock->spinlock);
468d293d3afSTakashi Iwai 	out = scnprintf(buf, len, "LOCK:%d,%d,%d,%d,%d,%d:%lld,%d,%d,%d,%d,%d,"
4694e3d24edSSunil Mushran 		       "%d,%d,%d,%d\n",
4704e3d24edSSunil Mushran 		       DEBUG_LOCK_VERSION,
4714e3d24edSSunil Mushran 		       list_type, lock->ml.type, lock->ml.convert_type,
4724e3d24edSSunil Mushran 		       lock->ml.node,
4734e3d24edSSunil Mushran 		       dlm_get_lock_cookie_node(be64_to_cpu(lock->ml.cookie)),
4744e3d24edSSunil Mushran 		       dlm_get_lock_cookie_seq(be64_to_cpu(lock->ml.cookie)),
4754e3d24edSSunil Mushran 		       !list_empty(&lock->ast_list),
4764e3d24edSSunil Mushran 		       !list_empty(&lock->bast_list),
4774e3d24edSSunil Mushran 		       lock->ast_pending, lock->bast_pending,
4784e3d24edSSunil Mushran 		       lock->convert_pending, lock->lock_pending,
4794e3d24edSSunil Mushran 		       lock->cancel_pending, lock->unlock_pending,
4802c935bc5SPeter Zijlstra 		       kref_read(&lock->lock_refs));
4814e3d24edSSunil Mushran 	spin_unlock(&lock->spinlock);
4824e3d24edSSunil Mushran 
4834e3d24edSSunil Mushran 	return out;
4844e3d24edSSunil Mushran }
4854e3d24edSSunil Mushran 
dump_lockres(struct dlm_lock_resource * res,char * buf,int len)4864e3d24edSSunil Mushran static int dump_lockres(struct dlm_lock_resource *res, char *buf, int len)
4874e3d24edSSunil Mushran {
4884e3d24edSSunil Mushran 	struct dlm_lock *lock;
4894e3d24edSSunil Mushran 	int i;
4904e3d24edSSunil Mushran 	int out = 0;
4914e3d24edSSunil Mushran 
492d293d3afSTakashi Iwai 	out += scnprintf(buf + out, len - out, "NAME:");
4934e3d24edSSunil Mushran 	out += stringify_lockname(res->lockname.name, res->lockname.len,
4944e3d24edSSunil Mushran 				  buf + out, len - out);
495d293d3afSTakashi Iwai 	out += scnprintf(buf + out, len - out, "\n");
4964e3d24edSSunil Mushran 
4974e3d24edSSunil Mushran #define DEBUG_LRES_VERSION	1
498d293d3afSTakashi Iwai 	out += scnprintf(buf + out, len - out,
4994e3d24edSSunil Mushran 			"LRES:%d,%d,%d,%ld,%d,%d,%d,%d,%d,%d,%d\n",
5004e3d24edSSunil Mushran 			DEBUG_LRES_VERSION,
5014e3d24edSSunil Mushran 			res->owner, res->state, res->last_used,
5024e3d24edSSunil Mushran 			!list_empty(&res->purge),
5034e3d24edSSunil Mushran 			!list_empty(&res->dirty),
5044e3d24edSSunil Mushran 			!list_empty(&res->recovering),
5054e3d24edSSunil Mushran 			res->inflight_locks, res->migration_pending,
5064e3d24edSSunil Mushran 			atomic_read(&res->asts_reserved),
5072c935bc5SPeter Zijlstra 			kref_read(&res->refs));
5084e3d24edSSunil Mushran 
5094e3d24edSSunil Mushran 	/* refmap */
510d293d3afSTakashi Iwai 	out += scnprintf(buf + out, len - out, "RMAP:");
5114e3d24edSSunil Mushran 	out += stringify_nodemap(res->refmap, O2NM_MAX_NODES,
5124e3d24edSSunil Mushran 				 buf + out, len - out);
513d293d3afSTakashi Iwai 	out += scnprintf(buf + out, len - out, "\n");
5144e3d24edSSunil Mushran 
5154e3d24edSSunil Mushran 	/* lvb */
516d293d3afSTakashi Iwai 	out += scnprintf(buf + out, len - out, "LVBX:");
5174e3d24edSSunil Mushran 	for (i = 0; i < DLM_LVB_LEN; i++)
518d293d3afSTakashi Iwai 		out += scnprintf(buf + out, len - out,
5194e3d24edSSunil Mushran 					"%02x", (unsigned char)res->lvb[i]);
520d293d3afSTakashi Iwai 	out += scnprintf(buf + out, len - out, "\n");
5214e3d24edSSunil Mushran 
5224e3d24edSSunil Mushran 	/* granted */
5234e3d24edSSunil Mushran 	list_for_each_entry(lock, &res->granted, list)
5244e3d24edSSunil Mushran 		out += dump_lock(lock, 0, buf + out, len - out);
5254e3d24edSSunil Mushran 
5264e3d24edSSunil Mushran 	/* converting */
5274e3d24edSSunil Mushran 	list_for_each_entry(lock, &res->converting, list)
5284e3d24edSSunil Mushran 		out += dump_lock(lock, 1, buf + out, len - out);
5294e3d24edSSunil Mushran 
5304e3d24edSSunil Mushran 	/* blocked */
5314e3d24edSSunil Mushran 	list_for_each_entry(lock, &res->blocked, list)
5324e3d24edSSunil Mushran 		out += dump_lock(lock, 2, buf + out, len - out);
5334e3d24edSSunil Mushran 
534d293d3afSTakashi Iwai 	out += scnprintf(buf + out, len - out, "\n");
5354e3d24edSSunil Mushran 
5364e3d24edSSunil Mushran 	return out;
5374e3d24edSSunil Mushran }
5384e3d24edSSunil Mushran 
lockres_seq_start(struct seq_file * m,loff_t * pos)5394e3d24edSSunil Mushran static void *lockres_seq_start(struct seq_file *m, loff_t *pos)
5404e3d24edSSunil Mushran {
5414e3d24edSSunil Mushran 	struct debug_lockres *dl = m->private;
5424e3d24edSSunil Mushran 	struct dlm_ctxt *dlm = dl->dl_ctxt;
543b0d4f817SSunil Mushran 	struct dlm_lock_resource *oldres = dl->dl_res;
544*b02da32bSJakob Koschel 	struct dlm_lock_resource *res = NULL, *iter;
545b0d4f817SSunil Mushran 	struct list_head *track_list;
5464e3d24edSSunil Mushran 
547b0d4f817SSunil Mushran 	spin_lock(&dlm->track_lock);
548b0d4f817SSunil Mushran 	if (oldres)
549b0d4f817SSunil Mushran 		track_list = &oldres->tracking;
550228ac635STristan Ye 	else {
551b0d4f817SSunil Mushran 		track_list = &dlm->tracking_list;
552228ac635STristan Ye 		if (list_empty(track_list)) {
553228ac635STristan Ye 			dl = NULL;
554228ac635STristan Ye 			spin_unlock(&dlm->track_lock);
555228ac635STristan Ye 			goto bail;
556228ac635STristan Ye 		}
557228ac635STristan Ye 	}
5584e3d24edSSunil Mushran 
559*b02da32bSJakob Koschel 	list_for_each_entry(iter, track_list, tracking) {
560*b02da32bSJakob Koschel 		if (&iter->tracking != &dlm->tracking_list) {
561*b02da32bSJakob Koschel 			dlm_lockres_get(iter);
562*b02da32bSJakob Koschel 			res = iter;
563*b02da32bSJakob Koschel 		}
5644e3d24edSSunil Mushran 		break;
5654e3d24edSSunil Mushran 	}
566b0d4f817SSunil Mushran 	spin_unlock(&dlm->track_lock);
567b0d4f817SSunil Mushran 
568b0d4f817SSunil Mushran 	if (oldres)
569b0d4f817SSunil Mushran 		dlm_lockres_put(oldres);
570b0d4f817SSunil Mushran 
5714e3d24edSSunil Mushran 	dl->dl_res = res;
572b0d4f817SSunil Mushran 
573b0d4f817SSunil Mushran 	if (res) {
574b0d4f817SSunil Mushran 		spin_lock(&res->spinlock);
575b0d4f817SSunil Mushran 		dump_lockres(res, dl->dl_buf, dl->dl_len - 1);
576b0d4f817SSunil Mushran 		spin_unlock(&res->spinlock);
5774e3d24edSSunil Mushran 	} else
5784e3d24edSSunil Mushran 		dl = NULL;
5794e3d24edSSunil Mushran 
580228ac635STristan Ye bail:
581b0d4f817SSunil Mushran 	/* passed to seq_show */
5824e3d24edSSunil Mushran 	return dl;
5834e3d24edSSunil Mushran }
5844e3d24edSSunil Mushran 
lockres_seq_stop(struct seq_file * m,void * v)5854e3d24edSSunil Mushran static void lockres_seq_stop(struct seq_file *m, void *v)
5864e3d24edSSunil Mushran {
5874e3d24edSSunil Mushran }
5884e3d24edSSunil Mushran 
lockres_seq_next(struct seq_file * m,void * v,loff_t * pos)5894e3d24edSSunil Mushran static void *lockres_seq_next(struct seq_file *m, void *v, loff_t *pos)
5904e3d24edSSunil Mushran {
5914e3d24edSSunil Mushran 	return NULL;
5924e3d24edSSunil Mushran }
5934e3d24edSSunil Mushran 
lockres_seq_show(struct seq_file * s,void * v)5944e3d24edSSunil Mushran static int lockres_seq_show(struct seq_file *s, void *v)
5954e3d24edSSunil Mushran {
5964e3d24edSSunil Mushran 	struct debug_lockres *dl = (struct debug_lockres *)v;
5974e3d24edSSunil Mushran 
5984e3d24edSSunil Mushran 	seq_printf(s, "%s", dl->dl_buf);
5994e3d24edSSunil Mushran 
6004e3d24edSSunil Mushran 	return 0;
6014e3d24edSSunil Mushran }
6024e3d24edSSunil Mushran 
60388e9d34cSJames Morris static const struct seq_operations debug_lockres_ops = {
6044e3d24edSSunil Mushran 	.start =	lockres_seq_start,
6054e3d24edSSunil Mushran 	.stop =		lockres_seq_stop,
6064e3d24edSSunil Mushran 	.next =		lockres_seq_next,
6074e3d24edSSunil Mushran 	.show =		lockres_seq_show,
6084e3d24edSSunil Mushran };
6094e3d24edSSunil Mushran 
debug_lockres_open(struct inode * inode,struct file * file)6104e3d24edSSunil Mushran static int debug_lockres_open(struct inode *inode, struct file *file)
6114e3d24edSSunil Mushran {
6124e3d24edSSunil Mushran 	struct dlm_ctxt *dlm = inode->i_private;
6138f9ac032SRob Jones 	struct debug_lockres *dl;
6148f9ac032SRob Jones 	void *buf;
6154e3d24edSSunil Mushran 
6168f9ac032SRob Jones 	buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
6178f9ac032SRob Jones 	if (!buf)
6184e3d24edSSunil Mushran 		goto bail;
6198f9ac032SRob Jones 
6208f9ac032SRob Jones 	dl = __seq_open_private(file, &debug_lockres_ops, sizeof(*dl));
6218f9ac032SRob Jones 	if (!dl)
6228f9ac032SRob Jones 		goto bailfree;
6234e3d24edSSunil Mushran 
6244e3d24edSSunil Mushran 	dl->dl_len = PAGE_SIZE;
6258f9ac032SRob Jones 	dl->dl_buf = buf;
6264e3d24edSSunil Mushran 
6274e3d24edSSunil Mushran 	dlm_grab(dlm);
6284e3d24edSSunil Mushran 	dl->dl_ctxt = dlm;
6294e3d24edSSunil Mushran 
6304e3d24edSSunil Mushran 	return 0;
6318f9ac032SRob Jones 
6328f9ac032SRob Jones bailfree:
6338f9ac032SRob Jones 	kfree(buf);
6344e3d24edSSunil Mushran bail:
6358f9ac032SRob Jones 	mlog_errno(-ENOMEM);
6368f9ac032SRob Jones 	return -ENOMEM;
6374e3d24edSSunil Mushran }
6384e3d24edSSunil Mushran 
debug_lockres_release(struct inode * inode,struct file * file)6394e3d24edSSunil Mushran static int debug_lockres_release(struct inode *inode, struct file *file)
6404e3d24edSSunil Mushran {
64133fa1d90SJoe Perches 	struct seq_file *seq = file->private_data;
6424e3d24edSSunil Mushran 	struct debug_lockres *dl = (struct debug_lockres *)seq->private;
6434e3d24edSSunil Mushran 
6444e3d24edSSunil Mushran 	if (dl->dl_res)
6454e3d24edSSunil Mushran 		dlm_lockres_put(dl->dl_res);
6464e3d24edSSunil Mushran 	dlm_put(dl->dl_ctxt);
6474e3d24edSSunil Mushran 	kfree(dl->dl_buf);
6484e3d24edSSunil Mushran 	return seq_release_private(inode, file);
6494e3d24edSSunil Mushran }
6504e3d24edSSunil Mushran 
651828c0950SAlexey Dobriyan static const struct file_operations debug_lockres_fops = {
6524e3d24edSSunil Mushran 	.open =		debug_lockres_open,
6534e3d24edSSunil Mushran 	.release =	debug_lockres_release,
6544e3d24edSSunil Mushran 	.read =		seq_read,
6554e3d24edSSunil Mushran 	.llseek =	seq_lseek,
6564e3d24edSSunil Mushran };
6574e3d24edSSunil Mushran /* end - debug lockres funcs */
6584e3d24edSSunil Mushran 
659007dce53SSunil Mushran /* begin - debug state funcs */
debug_state_print(struct dlm_ctxt * dlm,char * buf,int len)66002bd9c39SSunil Mushran static int debug_state_print(struct dlm_ctxt *dlm, char *buf, int len)
661007dce53SSunil Mushran {
662007dce53SSunil Mushran 	int out = 0;
663007dce53SSunil Mushran 	struct dlm_reco_node_data *node;
664007dce53SSunil Mushran 	char *state;
665e64ff146SSunil Mushran 	int cur_mles = 0, tot_mles = 0;
666e64ff146SSunil Mushran 	int i;
667007dce53SSunil Mushran 
668007dce53SSunil Mushran 	spin_lock(&dlm->spinlock);
669007dce53SSunil Mushran 
670007dce53SSunil Mushran 	switch (dlm->dlm_state) {
671007dce53SSunil Mushran 	case DLM_CTXT_NEW:
672007dce53SSunil Mushran 		state = "NEW"; break;
673007dce53SSunil Mushran 	case DLM_CTXT_JOINED:
674007dce53SSunil Mushran 		state = "JOINED"; break;
675007dce53SSunil Mushran 	case DLM_CTXT_IN_SHUTDOWN:
676007dce53SSunil Mushran 		state = "SHUTDOWN"; break;
677007dce53SSunil Mushran 	case DLM_CTXT_LEAVING:
678007dce53SSunil Mushran 		state = "LEAVING"; break;
679007dce53SSunil Mushran 	default:
680007dce53SSunil Mushran 		state = "UNKNOWN"; break;
681007dce53SSunil Mushran 	}
682007dce53SSunil Mushran 
683007dce53SSunil Mushran 	/* Domain: xxxxxxxxxx  Key: 0xdfbac769 */
684d293d3afSTakashi Iwai 	out += scnprintf(buf + out, len - out,
685b1365d0bSSunil Mushran 			"Domain: %s  Key: 0x%08x  Protocol: %d.%d\n",
686b1365d0bSSunil Mushran 			dlm->name, dlm->key, dlm->dlm_locking_proto.pv_major,
687b1365d0bSSunil Mushran 			dlm->dlm_locking_proto.pv_minor);
688007dce53SSunil Mushran 
689007dce53SSunil Mushran 	/* Thread Pid: xxx  Node: xxx  State: xxxxx */
690d293d3afSTakashi Iwai 	out += scnprintf(buf + out, len - out,
691007dce53SSunil Mushran 			"Thread Pid: %d  Node: %d  State: %s\n",
69237096a79SSunil Mushran 			task_pid_nr(dlm->dlm_thread_task), dlm->node_num, state);
693007dce53SSunil Mushran 
694007dce53SSunil Mushran 	/* Number of Joins: xxx  Joining Node: xxx */
695d293d3afSTakashi Iwai 	out += scnprintf(buf + out, len - out,
696007dce53SSunil Mushran 			"Number of Joins: %d  Joining Node: %d\n",
697007dce53SSunil Mushran 			dlm->num_joins, dlm->joining_node);
698007dce53SSunil Mushran 
699007dce53SSunil Mushran 	/* Domain Map: xx xx xx */
700d293d3afSTakashi Iwai 	out += scnprintf(buf + out, len - out, "Domain Map: ");
701007dce53SSunil Mushran 	out += stringify_nodemap(dlm->domain_map, O2NM_MAX_NODES,
70202bd9c39SSunil Mushran 				 buf + out, len - out);
703d293d3afSTakashi Iwai 	out += scnprintf(buf + out, len - out, "\n");
704007dce53SSunil Mushran 
705bddefdeeSSunil Mushran 	/* Exit Domain Map: xx xx xx */
706d293d3afSTakashi Iwai 	out += scnprintf(buf + out, len - out, "Exit Domain Map: ");
707bddefdeeSSunil Mushran 	out += stringify_nodemap(dlm->exit_domain_map, O2NM_MAX_NODES,
708bddefdeeSSunil Mushran 				 buf + out, len - out);
709d293d3afSTakashi Iwai 	out += scnprintf(buf + out, len - out, "\n");
710bddefdeeSSunil Mushran 
711007dce53SSunil Mushran 	/* Live Map: xx xx xx */
712d293d3afSTakashi Iwai 	out += scnprintf(buf + out, len - out, "Live Map: ");
713007dce53SSunil Mushran 	out += stringify_nodemap(dlm->live_nodes_map, O2NM_MAX_NODES,
71402bd9c39SSunil Mushran 				 buf + out, len - out);
715d293d3afSTakashi Iwai 	out += scnprintf(buf + out, len - out, "\n");
716007dce53SSunil Mushran 
717e64ff146SSunil Mushran 	/* Lock Resources: xxx (xxx) */
718d293d3afSTakashi Iwai 	out += scnprintf(buf + out, len - out,
719e64ff146SSunil Mushran 			"Lock Resources: %d (%d)\n",
720e64ff146SSunil Mushran 			atomic_read(&dlm->res_cur_count),
721e64ff146SSunil Mushran 			atomic_read(&dlm->res_tot_count));
722e64ff146SSunil Mushran 
723e64ff146SSunil Mushran 	for (i = 0; i < DLM_MLE_NUM_TYPES; ++i)
724e64ff146SSunil Mushran 		tot_mles += atomic_read(&dlm->mle_tot_count[i]);
725e64ff146SSunil Mushran 
726e64ff146SSunil Mushran 	for (i = 0; i < DLM_MLE_NUM_TYPES; ++i)
727e64ff146SSunil Mushran 		cur_mles += atomic_read(&dlm->mle_cur_count[i]);
728e64ff146SSunil Mushran 
729e64ff146SSunil Mushran 	/* MLEs: xxx (xxx) */
730d293d3afSTakashi Iwai 	out += scnprintf(buf + out, len - out,
731e64ff146SSunil Mushran 			"MLEs: %d (%d)\n", cur_mles, tot_mles);
732e64ff146SSunil Mushran 
733e64ff146SSunil Mushran 	/*  Blocking: xxx (xxx) */
734d293d3afSTakashi Iwai 	out += scnprintf(buf + out, len - out,
735e64ff146SSunil Mushran 			"  Blocking: %d (%d)\n",
736e64ff146SSunil Mushran 			atomic_read(&dlm->mle_cur_count[DLM_MLE_BLOCK]),
737e64ff146SSunil Mushran 			atomic_read(&dlm->mle_tot_count[DLM_MLE_BLOCK]));
738e64ff146SSunil Mushran 
739e64ff146SSunil Mushran 	/*  Mastery: xxx (xxx) */
740d293d3afSTakashi Iwai 	out += scnprintf(buf + out, len - out,
741e64ff146SSunil Mushran 			"  Mastery: %d (%d)\n",
742e64ff146SSunil Mushran 			atomic_read(&dlm->mle_cur_count[DLM_MLE_MASTER]),
743e64ff146SSunil Mushran 			atomic_read(&dlm->mle_tot_count[DLM_MLE_MASTER]));
744e64ff146SSunil Mushran 
745e64ff146SSunil Mushran 	/*  Migration: xxx (xxx) */
746d293d3afSTakashi Iwai 	out += scnprintf(buf + out, len - out,
747e64ff146SSunil Mushran 			"  Migration: %d (%d)\n",
748e64ff146SSunil Mushran 			atomic_read(&dlm->mle_cur_count[DLM_MLE_MIGRATION]),
749e64ff146SSunil Mushran 			atomic_read(&dlm->mle_tot_count[DLM_MLE_MIGRATION]));
750e64ff146SSunil Mushran 
751007dce53SSunil Mushran 	/* Lists: Dirty=Empty  Purge=InUse  PendingASTs=Empty  ... */
752d293d3afSTakashi Iwai 	out += scnprintf(buf + out, len - out,
753007dce53SSunil Mushran 			"Lists: Dirty=%s  Purge=%s  PendingASTs=%s  "
7542ed6c750SSunil Mushran 			"PendingBASTs=%s\n",
755007dce53SSunil Mushran 			(list_empty(&dlm->dirty_list) ? "Empty" : "InUse"),
756007dce53SSunil Mushran 			(list_empty(&dlm->purge_list) ? "Empty" : "InUse"),
757007dce53SSunil Mushran 			(list_empty(&dlm->pending_asts) ? "Empty" : "InUse"),
7582ed6c750SSunil Mushran 			(list_empty(&dlm->pending_basts) ? "Empty" : "InUse"));
759007dce53SSunil Mushran 
760007dce53SSunil Mushran 	/* Purge Count: xxx  Refs: xxx */
761d293d3afSTakashi Iwai 	out += scnprintf(buf + out, len - out,
762007dce53SSunil Mushran 			"Purge Count: %d  Refs: %d\n", dlm->purge_count,
7632c935bc5SPeter Zijlstra 			kref_read(&dlm->dlm_refs));
764007dce53SSunil Mushran 
765007dce53SSunil Mushran 	/* Dead Node: xxx */
766d293d3afSTakashi Iwai 	out += scnprintf(buf + out, len - out,
767007dce53SSunil Mushran 			"Dead Node: %d\n", dlm->reco.dead_node);
768007dce53SSunil Mushran 
769007dce53SSunil Mushran 	/* What about DLM_RECO_STATE_FINALIZE? */
770007dce53SSunil Mushran 	if (dlm->reco.state == DLM_RECO_STATE_ACTIVE)
771007dce53SSunil Mushran 		state = "ACTIVE";
772007dce53SSunil Mushran 	else
773007dce53SSunil Mushran 		state = "INACTIVE";
774007dce53SSunil Mushran 
775007dce53SSunil Mushran 	/* Recovery Pid: xxxx  Master: xxx  State: xxxx */
776d293d3afSTakashi Iwai 	out += scnprintf(buf + out, len - out,
777007dce53SSunil Mushran 			"Recovery Pid: %d  Master: %d  State: %s\n",
77837096a79SSunil Mushran 			task_pid_nr(dlm->dlm_reco_thread_task),
779007dce53SSunil Mushran 			dlm->reco.new_master, state);
780007dce53SSunil Mushran 
781007dce53SSunil Mushran 	/* Recovery Map: xx xx */
782d293d3afSTakashi Iwai 	out += scnprintf(buf + out, len - out, "Recovery Map: ");
783007dce53SSunil Mushran 	out += stringify_nodemap(dlm->recovery_map, O2NM_MAX_NODES,
78402bd9c39SSunil Mushran 				 buf + out, len - out);
785d293d3afSTakashi Iwai 	out += scnprintf(buf + out, len - out, "\n");
786007dce53SSunil Mushran 
787007dce53SSunil Mushran 	/* Recovery Node State: */
788d293d3afSTakashi Iwai 	out += scnprintf(buf + out, len - out, "Recovery Node State:\n");
789007dce53SSunil Mushran 	list_for_each_entry(node, &dlm->reco.node_data, list) {
790007dce53SSunil Mushran 		switch (node->state) {
791007dce53SSunil Mushran 		case DLM_RECO_NODE_DATA_INIT:
792007dce53SSunil Mushran 			state = "INIT";
793007dce53SSunil Mushran 			break;
794007dce53SSunil Mushran 		case DLM_RECO_NODE_DATA_REQUESTING:
795007dce53SSunil Mushran 			state = "REQUESTING";
796007dce53SSunil Mushran 			break;
797007dce53SSunil Mushran 		case DLM_RECO_NODE_DATA_DEAD:
798007dce53SSunil Mushran 			state = "DEAD";
799007dce53SSunil Mushran 			break;
800007dce53SSunil Mushran 		case DLM_RECO_NODE_DATA_RECEIVING:
801007dce53SSunil Mushran 			state = "RECEIVING";
802007dce53SSunil Mushran 			break;
803007dce53SSunil Mushran 		case DLM_RECO_NODE_DATA_REQUESTED:
804007dce53SSunil Mushran 			state = "REQUESTED";
805007dce53SSunil Mushran 			break;
806007dce53SSunil Mushran 		case DLM_RECO_NODE_DATA_DONE:
807007dce53SSunil Mushran 			state = "DONE";
808007dce53SSunil Mushran 			break;
809007dce53SSunil Mushran 		case DLM_RECO_NODE_DATA_FINALIZE_SENT:
810007dce53SSunil Mushran 			state = "FINALIZE-SENT";
811007dce53SSunil Mushran 			break;
812007dce53SSunil Mushran 		default:
813007dce53SSunil Mushran 			state = "BAD";
814007dce53SSunil Mushran 			break;
815007dce53SSunil Mushran 		}
816d293d3afSTakashi Iwai 		out += scnprintf(buf + out, len - out, "\t%u - %s\n",
817007dce53SSunil Mushran 				node->node_num, state);
818007dce53SSunil Mushran 	}
819007dce53SSunil Mushran 
820007dce53SSunil Mushran 	spin_unlock(&dlm->spinlock);
821007dce53SSunil Mushran 
822007dce53SSunil Mushran 	return out;
823007dce53SSunil Mushran }
824007dce53SSunil Mushran 
debug_state_open(struct inode * inode,struct file * file)825007dce53SSunil Mushran static int debug_state_open(struct inode *inode, struct file *file)
826007dce53SSunil Mushran {
827007dce53SSunil Mushran 	struct dlm_ctxt *dlm = inode->i_private;
82802bd9c39SSunil Mushran 	char *buf = NULL;
829007dce53SSunil Mushran 
83002bd9c39SSunil Mushran 	buf = (char *) get_zeroed_page(GFP_NOFS);
83102bd9c39SSunil Mushran 	if (!buf)
832007dce53SSunil Mushran 		goto bail;
833007dce53SSunil Mushran 
83402bd9c39SSunil Mushran 	i_size_write(inode, debug_state_print(dlm, buf, PAGE_SIZE - 1));
835007dce53SSunil Mushran 
83602bd9c39SSunil Mushran 	file->private_data = buf;
837007dce53SSunil Mushran 
838007dce53SSunil Mushran 	return 0;
839007dce53SSunil Mushran bail:
840007dce53SSunil Mushran 	return -ENOMEM;
841007dce53SSunil Mushran }
842007dce53SSunil Mushran 
843828c0950SAlexey Dobriyan static const struct file_operations debug_state_fops = {
844007dce53SSunil Mushran 	.open =		debug_state_open,
84502bd9c39SSunil Mushran 	.release =	debug_release,
84602bd9c39SSunil Mushran 	.read =		debug_read,
84702bd9c39SSunil Mushran 	.llseek =	generic_file_llseek,
848007dce53SSunil Mushran };
849007dce53SSunil Mushran /* end  - debug state funcs */
850007dce53SSunil Mushran 
851007dce53SSunil Mushran /* files in subroot */
dlm_debug_init(struct dlm_ctxt * dlm)852e581595eSGreg Kroah-Hartman void dlm_debug_init(struct dlm_ctxt *dlm)
853007dce53SSunil Mushran {
854007dce53SSunil Mushran 	/* for dumping dlm_ctxt */
8555e7a3ed9SGreg Kroah-Hartman 	debugfs_create_file(DLM_DEBUGFS_DLM_STATE, S_IFREG|S_IRUSR,
8565e7a3ed9SGreg Kroah-Hartman 			    dlm->dlm_debugfs_subroot, dlm, &debug_state_fops);
857007dce53SSunil Mushran 
8584e3d24edSSunil Mushran 	/* for dumping lockres */
8595e7a3ed9SGreg Kroah-Hartman 	debugfs_create_file(DLM_DEBUGFS_LOCKING_STATE, S_IFREG|S_IRUSR,
8605e7a3ed9SGreg Kroah-Hartman 			    dlm->dlm_debugfs_subroot, dlm, &debug_lockres_fops);
8614e3d24edSSunil Mushran 
862d0129aceSSunil Mushran 	/* for dumping mles */
8635e7a3ed9SGreg Kroah-Hartman 	debugfs_create_file(DLM_DEBUGFS_MLE_STATE, S_IFREG|S_IRUSR,
8645e7a3ed9SGreg Kroah-Hartman 			    dlm->dlm_debugfs_subroot, dlm, &debug_mle_fops);
865d0129aceSSunil Mushran 
8667209300aSSunil Mushran 	/* for dumping lockres on the purge list */
8675e7a3ed9SGreg Kroah-Hartman 	debugfs_create_file(DLM_DEBUGFS_PURGE_LIST, S_IFREG|S_IRUSR,
8685e7a3ed9SGreg Kroah-Hartman 			    dlm->dlm_debugfs_subroot, dlm,
8695e7a3ed9SGreg Kroah-Hartman 			    &debug_purgelist_fops);
870007dce53SSunil Mushran }
8716325b4a2SSunil Mushran 
8726325b4a2SSunil Mushran /* subroot - domain dir */
dlm_create_debugfs_subroot(struct dlm_ctxt * dlm)8735e7a3ed9SGreg Kroah-Hartman void dlm_create_debugfs_subroot(struct dlm_ctxt *dlm)
8746325b4a2SSunil Mushran {
875e581595eSGreg Kroah-Hartman 	dlm->dlm_debugfs_subroot = debugfs_create_dir(dlm->name,
876e581595eSGreg Kroah-Hartman 						      dlm_debugfs_root);
8776325b4a2SSunil Mushran }
8786325b4a2SSunil Mushran 
dlm_destroy_debugfs_subroot(struct dlm_ctxt * dlm)8796325b4a2SSunil Mushran void dlm_destroy_debugfs_subroot(struct dlm_ctxt *dlm)
8806325b4a2SSunil Mushran {
8815e7a3ed9SGreg Kroah-Hartman 	debugfs_remove_recursive(dlm->dlm_debugfs_subroot);
8826325b4a2SSunil Mushran }
8836325b4a2SSunil Mushran 
8846325b4a2SSunil Mushran /* debugfs root */
dlm_create_debugfs_root(void)885e581595eSGreg Kroah-Hartman void dlm_create_debugfs_root(void)
8866325b4a2SSunil Mushran {
8876325b4a2SSunil Mushran 	dlm_debugfs_root = debugfs_create_dir(DLM_DEBUGFS_DIR, NULL);
8886325b4a2SSunil Mushran }
8896325b4a2SSunil Mushran 
dlm_destroy_debugfs_root(void)8906325b4a2SSunil Mushran void dlm_destroy_debugfs_root(void)
8916325b4a2SSunil Mushran {
8926325b4a2SSunil Mushran 	debugfs_remove(dlm_debugfs_root);
8936325b4a2SSunil Mushran }
8946325b4a2SSunil Mushran #endif	/* CONFIG_DEBUG_FS */
895