18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/* -*- mode: c; c-basic-offset: 8; -*-
38c2ecf20Sopenharmony_ci * vim: noexpandtab sw=8 ts=8 sts=0:
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * dlmdebug.c
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * debug functionality for the dlm
88c2ecf20Sopenharmony_ci *
98c2ecf20Sopenharmony_ci * Copyright (C) 2004, 2008 Oracle.  All rights reserved.
108c2ecf20Sopenharmony_ci */
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci#include <linux/types.h>
138c2ecf20Sopenharmony_ci#include <linux/slab.h>
148c2ecf20Sopenharmony_ci#include <linux/highmem.h>
158c2ecf20Sopenharmony_ci#include <linux/sysctl.h>
168c2ecf20Sopenharmony_ci#include <linux/spinlock.h>
178c2ecf20Sopenharmony_ci#include <linux/debugfs.h>
188c2ecf20Sopenharmony_ci#include <linux/export.h>
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_ci#include "../cluster/heartbeat.h"
218c2ecf20Sopenharmony_ci#include "../cluster/nodemanager.h"
228c2ecf20Sopenharmony_ci#include "../cluster/tcp.h"
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_ci#include "dlmapi.h"
258c2ecf20Sopenharmony_ci#include "dlmcommon.h"
268c2ecf20Sopenharmony_ci#include "dlmdomain.h"
278c2ecf20Sopenharmony_ci#include "dlmdebug.h"
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ci#define MLOG_MASK_PREFIX ML_DLM
308c2ecf20Sopenharmony_ci#include "../cluster/masklog.h"
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_cistatic int stringify_lockname(const char *lockname, int locklen, char *buf,
338c2ecf20Sopenharmony_ci			      int len);
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_civoid dlm_print_one_lock_resource(struct dlm_lock_resource *res)
368c2ecf20Sopenharmony_ci{
378c2ecf20Sopenharmony_ci	spin_lock(&res->spinlock);
388c2ecf20Sopenharmony_ci	__dlm_print_one_lock_resource(res);
398c2ecf20Sopenharmony_ci	spin_unlock(&res->spinlock);
408c2ecf20Sopenharmony_ci}
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_cistatic void dlm_print_lockres_refmap(struct dlm_lock_resource *res)
438c2ecf20Sopenharmony_ci{
448c2ecf20Sopenharmony_ci	int bit;
458c2ecf20Sopenharmony_ci	assert_spin_locked(&res->spinlock);
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ci	printk("  refmap nodes: [ ");
488c2ecf20Sopenharmony_ci	bit = 0;
498c2ecf20Sopenharmony_ci	while (1) {
508c2ecf20Sopenharmony_ci		bit = find_next_bit(res->refmap, O2NM_MAX_NODES, bit);
518c2ecf20Sopenharmony_ci		if (bit >= O2NM_MAX_NODES)
528c2ecf20Sopenharmony_ci			break;
538c2ecf20Sopenharmony_ci		printk("%u ", bit);
548c2ecf20Sopenharmony_ci		bit++;
558c2ecf20Sopenharmony_ci	}
568c2ecf20Sopenharmony_ci	printk("], inflight=%u\n", res->inflight_locks);
578c2ecf20Sopenharmony_ci}
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_cistatic void __dlm_print_lock(struct dlm_lock *lock)
608c2ecf20Sopenharmony_ci{
618c2ecf20Sopenharmony_ci	spin_lock(&lock->spinlock);
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_ci	printk("    type=%d, conv=%d, node=%u, cookie=%u:%llu, "
648c2ecf20Sopenharmony_ci	       "ref=%u, ast=(empty=%c,pend=%c), bast=(empty=%c,pend=%c), "
658c2ecf20Sopenharmony_ci	       "pending=(conv=%c,lock=%c,cancel=%c,unlock=%c)\n",
668c2ecf20Sopenharmony_ci	       lock->ml.type, lock->ml.convert_type, lock->ml.node,
678c2ecf20Sopenharmony_ci	       dlm_get_lock_cookie_node(be64_to_cpu(lock->ml.cookie)),
688c2ecf20Sopenharmony_ci	       dlm_get_lock_cookie_seq(be64_to_cpu(lock->ml.cookie)),
698c2ecf20Sopenharmony_ci	       kref_read(&lock->lock_refs),
708c2ecf20Sopenharmony_ci	       (list_empty(&lock->ast_list) ? 'y' : 'n'),
718c2ecf20Sopenharmony_ci	       (lock->ast_pending ? 'y' : 'n'),
728c2ecf20Sopenharmony_ci	       (list_empty(&lock->bast_list) ? 'y' : 'n'),
738c2ecf20Sopenharmony_ci	       (lock->bast_pending ? 'y' : 'n'),
748c2ecf20Sopenharmony_ci	       (lock->convert_pending ? 'y' : 'n'),
758c2ecf20Sopenharmony_ci	       (lock->lock_pending ? 'y' : 'n'),
768c2ecf20Sopenharmony_ci	       (lock->cancel_pending ? 'y' : 'n'),
778c2ecf20Sopenharmony_ci	       (lock->unlock_pending ? 'y' : 'n'));
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_ci	spin_unlock(&lock->spinlock);
808c2ecf20Sopenharmony_ci}
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_civoid __dlm_print_one_lock_resource(struct dlm_lock_resource *res)
838c2ecf20Sopenharmony_ci{
848c2ecf20Sopenharmony_ci	struct dlm_lock *lock;
858c2ecf20Sopenharmony_ci	char buf[DLM_LOCKID_NAME_MAX];
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci	assert_spin_locked(&res->spinlock);
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_ci	stringify_lockname(res->lockname.name, res->lockname.len,
908c2ecf20Sopenharmony_ci			   buf, sizeof(buf));
918c2ecf20Sopenharmony_ci	printk("lockres: %s, owner=%u, state=%u\n",
928c2ecf20Sopenharmony_ci	       buf, res->owner, res->state);
938c2ecf20Sopenharmony_ci	printk("  last used: %lu, refcnt: %u, on purge list: %s\n",
948c2ecf20Sopenharmony_ci	       res->last_used, kref_read(&res->refs),
958c2ecf20Sopenharmony_ci	       list_empty(&res->purge) ? "no" : "yes");
968c2ecf20Sopenharmony_ci	printk("  on dirty list: %s, on reco list: %s, "
978c2ecf20Sopenharmony_ci	       "migrating pending: %s\n",
988c2ecf20Sopenharmony_ci	       list_empty(&res->dirty) ? "no" : "yes",
998c2ecf20Sopenharmony_ci	       list_empty(&res->recovering) ? "no" : "yes",
1008c2ecf20Sopenharmony_ci	       res->migration_pending ? "yes" : "no");
1018c2ecf20Sopenharmony_ci	printk("  inflight locks: %d, asts reserved: %d\n",
1028c2ecf20Sopenharmony_ci	       res->inflight_locks, atomic_read(&res->asts_reserved));
1038c2ecf20Sopenharmony_ci	dlm_print_lockres_refmap(res);
1048c2ecf20Sopenharmony_ci	printk("  granted queue:\n");
1058c2ecf20Sopenharmony_ci	list_for_each_entry(lock, &res->granted, list) {
1068c2ecf20Sopenharmony_ci		__dlm_print_lock(lock);
1078c2ecf20Sopenharmony_ci	}
1088c2ecf20Sopenharmony_ci	printk("  converting queue:\n");
1098c2ecf20Sopenharmony_ci	list_for_each_entry(lock, &res->converting, list) {
1108c2ecf20Sopenharmony_ci		__dlm_print_lock(lock);
1118c2ecf20Sopenharmony_ci	}
1128c2ecf20Sopenharmony_ci	printk("  blocked queue:\n");
1138c2ecf20Sopenharmony_ci	list_for_each_entry(lock, &res->blocked, list) {
1148c2ecf20Sopenharmony_ci		__dlm_print_lock(lock);
1158c2ecf20Sopenharmony_ci	}
1168c2ecf20Sopenharmony_ci}
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_civoid dlm_print_one_lock(struct dlm_lock *lockid)
1198c2ecf20Sopenharmony_ci{
1208c2ecf20Sopenharmony_ci	dlm_print_one_lock_resource(lockid->lockres);
1218c2ecf20Sopenharmony_ci}
1228c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(dlm_print_one_lock);
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_cistatic const char *dlm_errnames[] = {
1258c2ecf20Sopenharmony_ci	[DLM_NORMAL] =			"DLM_NORMAL",
1268c2ecf20Sopenharmony_ci	[DLM_GRANTED] =			"DLM_GRANTED",
1278c2ecf20Sopenharmony_ci	[DLM_DENIED] =			"DLM_DENIED",
1288c2ecf20Sopenharmony_ci	[DLM_DENIED_NOLOCKS] =		"DLM_DENIED_NOLOCKS",
1298c2ecf20Sopenharmony_ci	[DLM_WORKING] =			"DLM_WORKING",
1308c2ecf20Sopenharmony_ci	[DLM_BLOCKED] =			"DLM_BLOCKED",
1318c2ecf20Sopenharmony_ci	[DLM_BLOCKED_ORPHAN] =		"DLM_BLOCKED_ORPHAN",
1328c2ecf20Sopenharmony_ci	[DLM_DENIED_GRACE_PERIOD] =	"DLM_DENIED_GRACE_PERIOD",
1338c2ecf20Sopenharmony_ci	[DLM_SYSERR] =			"DLM_SYSERR",
1348c2ecf20Sopenharmony_ci	[DLM_NOSUPPORT] =		"DLM_NOSUPPORT",
1358c2ecf20Sopenharmony_ci	[DLM_CANCELGRANT] =		"DLM_CANCELGRANT",
1368c2ecf20Sopenharmony_ci	[DLM_IVLOCKID] =		"DLM_IVLOCKID",
1378c2ecf20Sopenharmony_ci	[DLM_SYNC] =			"DLM_SYNC",
1388c2ecf20Sopenharmony_ci	[DLM_BADTYPE] =			"DLM_BADTYPE",
1398c2ecf20Sopenharmony_ci	[DLM_BADRESOURCE] =		"DLM_BADRESOURCE",
1408c2ecf20Sopenharmony_ci	[DLM_MAXHANDLES] =		"DLM_MAXHANDLES",
1418c2ecf20Sopenharmony_ci	[DLM_NOCLINFO] =		"DLM_NOCLINFO",
1428c2ecf20Sopenharmony_ci	[DLM_NOLOCKMGR] =		"DLM_NOLOCKMGR",
1438c2ecf20Sopenharmony_ci	[DLM_NOPURGED] =		"DLM_NOPURGED",
1448c2ecf20Sopenharmony_ci	[DLM_BADARGS] =			"DLM_BADARGS",
1458c2ecf20Sopenharmony_ci	[DLM_VOID] =			"DLM_VOID",
1468c2ecf20Sopenharmony_ci	[DLM_NOTQUEUED] =		"DLM_NOTQUEUED",
1478c2ecf20Sopenharmony_ci	[DLM_IVBUFLEN] =		"DLM_IVBUFLEN",
1488c2ecf20Sopenharmony_ci	[DLM_CVTUNGRANT] =		"DLM_CVTUNGRANT",
1498c2ecf20Sopenharmony_ci	[DLM_BADPARAM] =		"DLM_BADPARAM",
1508c2ecf20Sopenharmony_ci	[DLM_VALNOTVALID] =		"DLM_VALNOTVALID",
1518c2ecf20Sopenharmony_ci	[DLM_REJECTED] =		"DLM_REJECTED",
1528c2ecf20Sopenharmony_ci	[DLM_ABORT] =			"DLM_ABORT",
1538c2ecf20Sopenharmony_ci	[DLM_CANCEL] =			"DLM_CANCEL",
1548c2ecf20Sopenharmony_ci	[DLM_IVRESHANDLE] =		"DLM_IVRESHANDLE",
1558c2ecf20Sopenharmony_ci	[DLM_DEADLOCK] =		"DLM_DEADLOCK",
1568c2ecf20Sopenharmony_ci	[DLM_DENIED_NOASTS] =		"DLM_DENIED_NOASTS",
1578c2ecf20Sopenharmony_ci	[DLM_FORWARD] =			"DLM_FORWARD",
1588c2ecf20Sopenharmony_ci	[DLM_TIMEOUT] =			"DLM_TIMEOUT",
1598c2ecf20Sopenharmony_ci	[DLM_IVGROUPID] =		"DLM_IVGROUPID",
1608c2ecf20Sopenharmony_ci	[DLM_VERS_CONFLICT] =		"DLM_VERS_CONFLICT",
1618c2ecf20Sopenharmony_ci	[DLM_BAD_DEVICE_PATH] =		"DLM_BAD_DEVICE_PATH",
1628c2ecf20Sopenharmony_ci	[DLM_NO_DEVICE_PERMISSION] =	"DLM_NO_DEVICE_PERMISSION",
1638c2ecf20Sopenharmony_ci	[DLM_NO_CONTROL_DEVICE ] =	"DLM_NO_CONTROL_DEVICE ",
1648c2ecf20Sopenharmony_ci	[DLM_RECOVERING] =		"DLM_RECOVERING",
1658c2ecf20Sopenharmony_ci	[DLM_MIGRATING] =		"DLM_MIGRATING",
1668c2ecf20Sopenharmony_ci	[DLM_MAXSTATS] =		"DLM_MAXSTATS",
1678c2ecf20Sopenharmony_ci};
1688c2ecf20Sopenharmony_ci
1698c2ecf20Sopenharmony_cistatic const char *dlm_errmsgs[] = {
1708c2ecf20Sopenharmony_ci	[DLM_NORMAL] = 			"request in progress",
1718c2ecf20Sopenharmony_ci	[DLM_GRANTED] = 		"request granted",
1728c2ecf20Sopenharmony_ci	[DLM_DENIED] = 			"request denied",
1738c2ecf20Sopenharmony_ci	[DLM_DENIED_NOLOCKS] = 		"request denied, out of system resources",
1748c2ecf20Sopenharmony_ci	[DLM_WORKING] = 		"async request in progress",
1758c2ecf20Sopenharmony_ci	[DLM_BLOCKED] = 		"lock request blocked",
1768c2ecf20Sopenharmony_ci	[DLM_BLOCKED_ORPHAN] = 		"lock request blocked by a orphan lock",
1778c2ecf20Sopenharmony_ci	[DLM_DENIED_GRACE_PERIOD] = 	"topological change in progress",
1788c2ecf20Sopenharmony_ci	[DLM_SYSERR] = 			"system error",
1798c2ecf20Sopenharmony_ci	[DLM_NOSUPPORT] = 		"unsupported",
1808c2ecf20Sopenharmony_ci	[DLM_CANCELGRANT] = 		"can't cancel convert: already granted",
1818c2ecf20Sopenharmony_ci	[DLM_IVLOCKID] = 		"bad lockid",
1828c2ecf20Sopenharmony_ci	[DLM_SYNC] = 			"synchronous request granted",
1838c2ecf20Sopenharmony_ci	[DLM_BADTYPE] = 		"bad resource type",
1848c2ecf20Sopenharmony_ci	[DLM_BADRESOURCE] = 		"bad resource handle",
1858c2ecf20Sopenharmony_ci	[DLM_MAXHANDLES] = 		"no more resource handles",
1868c2ecf20Sopenharmony_ci	[DLM_NOCLINFO] = 		"can't contact cluster manager",
1878c2ecf20Sopenharmony_ci	[DLM_NOLOCKMGR] = 		"can't contact lock manager",
1888c2ecf20Sopenharmony_ci	[DLM_NOPURGED] = 		"can't contact purge daemon",
1898c2ecf20Sopenharmony_ci	[DLM_BADARGS] = 		"bad api args",
1908c2ecf20Sopenharmony_ci	[DLM_VOID] = 			"no status",
1918c2ecf20Sopenharmony_ci	[DLM_NOTQUEUED] = 		"NOQUEUE was specified and request failed",
1928c2ecf20Sopenharmony_ci	[DLM_IVBUFLEN] = 		"invalid resource name length",
1938c2ecf20Sopenharmony_ci	[DLM_CVTUNGRANT] = 		"attempted to convert ungranted lock",
1948c2ecf20Sopenharmony_ci	[DLM_BADPARAM] = 		"invalid lock mode specified",
1958c2ecf20Sopenharmony_ci	[DLM_VALNOTVALID] = 		"value block has been invalidated",
1968c2ecf20Sopenharmony_ci	[DLM_REJECTED] = 		"request rejected, unrecognized client",
1978c2ecf20Sopenharmony_ci	[DLM_ABORT] = 			"blocked lock request cancelled",
1988c2ecf20Sopenharmony_ci	[DLM_CANCEL] = 			"conversion request cancelled",
1998c2ecf20Sopenharmony_ci	[DLM_IVRESHANDLE] = 		"invalid resource handle",
2008c2ecf20Sopenharmony_ci	[DLM_DEADLOCK] = 		"deadlock recovery refused this request",
2018c2ecf20Sopenharmony_ci	[DLM_DENIED_NOASTS] = 		"failed to allocate AST",
2028c2ecf20Sopenharmony_ci	[DLM_FORWARD] = 		"request must wait for primary's response",
2038c2ecf20Sopenharmony_ci	[DLM_TIMEOUT] = 		"timeout value for lock has expired",
2048c2ecf20Sopenharmony_ci	[DLM_IVGROUPID] = 		"invalid group specification",
2058c2ecf20Sopenharmony_ci	[DLM_VERS_CONFLICT] = 		"version conflicts prevent request handling",
2068c2ecf20Sopenharmony_ci	[DLM_BAD_DEVICE_PATH] = 	"Locks device does not exist or path wrong",
2078c2ecf20Sopenharmony_ci	[DLM_NO_DEVICE_PERMISSION] = 	"Client has insufficient perms for device",
2088c2ecf20Sopenharmony_ci	[DLM_NO_CONTROL_DEVICE] = 	"Cannot set options on opened device ",
2098c2ecf20Sopenharmony_ci	[DLM_RECOVERING] = 		"lock resource being recovered",
2108c2ecf20Sopenharmony_ci	[DLM_MIGRATING] = 		"lock resource being migrated",
2118c2ecf20Sopenharmony_ci	[DLM_MAXSTATS] = 		"invalid error number",
2128c2ecf20Sopenharmony_ci};
2138c2ecf20Sopenharmony_ci
2148c2ecf20Sopenharmony_ciconst char *dlm_errmsg(enum dlm_status err)
2158c2ecf20Sopenharmony_ci{
2168c2ecf20Sopenharmony_ci	if (err >= DLM_MAXSTATS || err < 0)
2178c2ecf20Sopenharmony_ci		return dlm_errmsgs[DLM_MAXSTATS];
2188c2ecf20Sopenharmony_ci	return dlm_errmsgs[err];
2198c2ecf20Sopenharmony_ci}
2208c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(dlm_errmsg);
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_ciconst char *dlm_errname(enum dlm_status err)
2238c2ecf20Sopenharmony_ci{
2248c2ecf20Sopenharmony_ci	if (err >= DLM_MAXSTATS || err < 0)
2258c2ecf20Sopenharmony_ci		return dlm_errnames[DLM_MAXSTATS];
2268c2ecf20Sopenharmony_ci	return dlm_errnames[err];
2278c2ecf20Sopenharmony_ci}
2288c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(dlm_errname);
2298c2ecf20Sopenharmony_ci
2308c2ecf20Sopenharmony_ci/* NOTE: This function converts a lockname into a string. It uses knowledge
2318c2ecf20Sopenharmony_ci * of the format of the lockname that should be outside the purview of the dlm.
2328c2ecf20Sopenharmony_ci * We are adding only to make dlm debugging slightly easier.
2338c2ecf20Sopenharmony_ci *
2348c2ecf20Sopenharmony_ci * For more on lockname formats, please refer to dlmglue.c and ocfs2_lockid.h.
2358c2ecf20Sopenharmony_ci */
2368c2ecf20Sopenharmony_cistatic int stringify_lockname(const char *lockname, int locklen, char *buf,
2378c2ecf20Sopenharmony_ci			      int len)
2388c2ecf20Sopenharmony_ci{
2398c2ecf20Sopenharmony_ci	int out = 0;
2408c2ecf20Sopenharmony_ci	__be64 inode_blkno_be;
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_ci#define OCFS2_DENTRY_LOCK_INO_START	18
2438c2ecf20Sopenharmony_ci	if (*lockname == 'N') {
2448c2ecf20Sopenharmony_ci		memcpy((__be64 *)&inode_blkno_be,
2458c2ecf20Sopenharmony_ci		       (char *)&lockname[OCFS2_DENTRY_LOCK_INO_START],
2468c2ecf20Sopenharmony_ci		       sizeof(__be64));
2478c2ecf20Sopenharmony_ci		out += scnprintf(buf + out, len - out, "%.*s%08x",
2488c2ecf20Sopenharmony_ci				OCFS2_DENTRY_LOCK_INO_START - 1, lockname,
2498c2ecf20Sopenharmony_ci				(unsigned int)be64_to_cpu(inode_blkno_be));
2508c2ecf20Sopenharmony_ci	} else
2518c2ecf20Sopenharmony_ci		out += scnprintf(buf + out, len - out, "%.*s",
2528c2ecf20Sopenharmony_ci				locklen, lockname);
2538c2ecf20Sopenharmony_ci	return out;
2548c2ecf20Sopenharmony_ci}
2558c2ecf20Sopenharmony_ci
2568c2ecf20Sopenharmony_cistatic int stringify_nodemap(unsigned long *nodemap, int maxnodes,
2578c2ecf20Sopenharmony_ci			     char *buf, int len)
2588c2ecf20Sopenharmony_ci{
2598c2ecf20Sopenharmony_ci	int out = 0;
2608c2ecf20Sopenharmony_ci	int i = -1;
2618c2ecf20Sopenharmony_ci
2628c2ecf20Sopenharmony_ci	while ((i = find_next_bit(nodemap, maxnodes, i + 1)) < maxnodes)
2638c2ecf20Sopenharmony_ci		out += scnprintf(buf + out, len - out, "%d ", i);
2648c2ecf20Sopenharmony_ci
2658c2ecf20Sopenharmony_ci	return out;
2668c2ecf20Sopenharmony_ci}
2678c2ecf20Sopenharmony_ci
2688c2ecf20Sopenharmony_cistatic int dump_mle(struct dlm_master_list_entry *mle, char *buf, int len)
2698c2ecf20Sopenharmony_ci{
2708c2ecf20Sopenharmony_ci	int out = 0;
2718c2ecf20Sopenharmony_ci	char *mle_type;
2728c2ecf20Sopenharmony_ci
2738c2ecf20Sopenharmony_ci	if (mle->type == DLM_MLE_BLOCK)
2748c2ecf20Sopenharmony_ci		mle_type = "BLK";
2758c2ecf20Sopenharmony_ci	else if (mle->type == DLM_MLE_MASTER)
2768c2ecf20Sopenharmony_ci		mle_type = "MAS";
2778c2ecf20Sopenharmony_ci	else
2788c2ecf20Sopenharmony_ci		mle_type = "MIG";
2798c2ecf20Sopenharmony_ci
2808c2ecf20Sopenharmony_ci	out += stringify_lockname(mle->mname, mle->mnamelen, buf + out, len - out);
2818c2ecf20Sopenharmony_ci	out += scnprintf(buf + out, len - out,
2828c2ecf20Sopenharmony_ci			"\t%3s\tmas=%3u\tnew=%3u\tevt=%1d\tuse=%1d\tref=%3d\n",
2838c2ecf20Sopenharmony_ci			mle_type, mle->master, mle->new_master,
2848c2ecf20Sopenharmony_ci			!list_empty(&mle->hb_events),
2858c2ecf20Sopenharmony_ci			!!mle->inuse,
2868c2ecf20Sopenharmony_ci			kref_read(&mle->mle_refs));
2878c2ecf20Sopenharmony_ci
2888c2ecf20Sopenharmony_ci	out += scnprintf(buf + out, len - out, "Maybe=");
2898c2ecf20Sopenharmony_ci	out += stringify_nodemap(mle->maybe_map, O2NM_MAX_NODES,
2908c2ecf20Sopenharmony_ci				 buf + out, len - out);
2918c2ecf20Sopenharmony_ci	out += scnprintf(buf + out, len - out, "\n");
2928c2ecf20Sopenharmony_ci
2938c2ecf20Sopenharmony_ci	out += scnprintf(buf + out, len - out, "Vote=");
2948c2ecf20Sopenharmony_ci	out += stringify_nodemap(mle->vote_map, O2NM_MAX_NODES,
2958c2ecf20Sopenharmony_ci				 buf + out, len - out);
2968c2ecf20Sopenharmony_ci	out += scnprintf(buf + out, len - out, "\n");
2978c2ecf20Sopenharmony_ci
2988c2ecf20Sopenharmony_ci	out += scnprintf(buf + out, len - out, "Response=");
2998c2ecf20Sopenharmony_ci	out += stringify_nodemap(mle->response_map, O2NM_MAX_NODES,
3008c2ecf20Sopenharmony_ci				 buf + out, len - out);
3018c2ecf20Sopenharmony_ci	out += scnprintf(buf + out, len - out, "\n");
3028c2ecf20Sopenharmony_ci
3038c2ecf20Sopenharmony_ci	out += scnprintf(buf + out, len - out, "Node=");
3048c2ecf20Sopenharmony_ci	out += stringify_nodemap(mle->node_map, O2NM_MAX_NODES,
3058c2ecf20Sopenharmony_ci				 buf + out, len - out);
3068c2ecf20Sopenharmony_ci	out += scnprintf(buf + out, len - out, "\n");
3078c2ecf20Sopenharmony_ci
3088c2ecf20Sopenharmony_ci	out += scnprintf(buf + out, len - out, "\n");
3098c2ecf20Sopenharmony_ci
3108c2ecf20Sopenharmony_ci	return out;
3118c2ecf20Sopenharmony_ci}
3128c2ecf20Sopenharmony_ci
3138c2ecf20Sopenharmony_civoid dlm_print_one_mle(struct dlm_master_list_entry *mle)
3148c2ecf20Sopenharmony_ci{
3158c2ecf20Sopenharmony_ci	char *buf;
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_ci	buf = (char *) get_zeroed_page(GFP_ATOMIC);
3188c2ecf20Sopenharmony_ci	if (buf) {
3198c2ecf20Sopenharmony_ci		dump_mle(mle, buf, PAGE_SIZE - 1);
3208c2ecf20Sopenharmony_ci		free_page((unsigned long)buf);
3218c2ecf20Sopenharmony_ci	}
3228c2ecf20Sopenharmony_ci}
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_ci#ifdef CONFIG_DEBUG_FS
3258c2ecf20Sopenharmony_ci
3268c2ecf20Sopenharmony_cistatic struct dentry *dlm_debugfs_root;
3278c2ecf20Sopenharmony_ci
3288c2ecf20Sopenharmony_ci#define DLM_DEBUGFS_DIR				"o2dlm"
3298c2ecf20Sopenharmony_ci#define DLM_DEBUGFS_DLM_STATE			"dlm_state"
3308c2ecf20Sopenharmony_ci#define DLM_DEBUGFS_LOCKING_STATE		"locking_state"
3318c2ecf20Sopenharmony_ci#define DLM_DEBUGFS_MLE_STATE			"mle_state"
3328c2ecf20Sopenharmony_ci#define DLM_DEBUGFS_PURGE_LIST			"purge_list"
3338c2ecf20Sopenharmony_ci
3348c2ecf20Sopenharmony_ci/* begin - utils funcs */
3358c2ecf20Sopenharmony_cistatic int debug_release(struct inode *inode, struct file *file)
3368c2ecf20Sopenharmony_ci{
3378c2ecf20Sopenharmony_ci	free_page((unsigned long)file->private_data);
3388c2ecf20Sopenharmony_ci	return 0;
3398c2ecf20Sopenharmony_ci}
3408c2ecf20Sopenharmony_ci
3418c2ecf20Sopenharmony_cistatic ssize_t debug_read(struct file *file, char __user *buf,
3428c2ecf20Sopenharmony_ci			  size_t nbytes, loff_t *ppos)
3438c2ecf20Sopenharmony_ci{
3448c2ecf20Sopenharmony_ci	return simple_read_from_buffer(buf, nbytes, ppos, file->private_data,
3458c2ecf20Sopenharmony_ci				       i_size_read(file->f_mapping->host));
3468c2ecf20Sopenharmony_ci}
3478c2ecf20Sopenharmony_ci/* end - util funcs */
3488c2ecf20Sopenharmony_ci
3498c2ecf20Sopenharmony_ci/* begin - purge list funcs */
3508c2ecf20Sopenharmony_cistatic int debug_purgelist_print(struct dlm_ctxt *dlm, char *buf, int len)
3518c2ecf20Sopenharmony_ci{
3528c2ecf20Sopenharmony_ci	struct dlm_lock_resource *res;
3538c2ecf20Sopenharmony_ci	int out = 0;
3548c2ecf20Sopenharmony_ci	unsigned long total = 0;
3558c2ecf20Sopenharmony_ci
3568c2ecf20Sopenharmony_ci	out += scnprintf(buf + out, len - out,
3578c2ecf20Sopenharmony_ci			"Dumping Purgelist for Domain: %s\n", dlm->name);
3588c2ecf20Sopenharmony_ci
3598c2ecf20Sopenharmony_ci	spin_lock(&dlm->spinlock);
3608c2ecf20Sopenharmony_ci	list_for_each_entry(res, &dlm->purge_list, purge) {
3618c2ecf20Sopenharmony_ci		++total;
3628c2ecf20Sopenharmony_ci		if (len - out < 100)
3638c2ecf20Sopenharmony_ci			continue;
3648c2ecf20Sopenharmony_ci		spin_lock(&res->spinlock);
3658c2ecf20Sopenharmony_ci		out += stringify_lockname(res->lockname.name,
3668c2ecf20Sopenharmony_ci					  res->lockname.len,
3678c2ecf20Sopenharmony_ci					  buf + out, len - out);
3688c2ecf20Sopenharmony_ci		out += scnprintf(buf + out, len - out, "\t%ld\n",
3698c2ecf20Sopenharmony_ci				(jiffies - res->last_used)/HZ);
3708c2ecf20Sopenharmony_ci		spin_unlock(&res->spinlock);
3718c2ecf20Sopenharmony_ci	}
3728c2ecf20Sopenharmony_ci	spin_unlock(&dlm->spinlock);
3738c2ecf20Sopenharmony_ci
3748c2ecf20Sopenharmony_ci	out += scnprintf(buf + out, len - out, "Total on list: %lu\n", total);
3758c2ecf20Sopenharmony_ci
3768c2ecf20Sopenharmony_ci	return out;
3778c2ecf20Sopenharmony_ci}
3788c2ecf20Sopenharmony_ci
3798c2ecf20Sopenharmony_cistatic int debug_purgelist_open(struct inode *inode, struct file *file)
3808c2ecf20Sopenharmony_ci{
3818c2ecf20Sopenharmony_ci	struct dlm_ctxt *dlm = inode->i_private;
3828c2ecf20Sopenharmony_ci	char *buf = NULL;
3838c2ecf20Sopenharmony_ci
3848c2ecf20Sopenharmony_ci	buf = (char *) get_zeroed_page(GFP_NOFS);
3858c2ecf20Sopenharmony_ci	if (!buf)
3868c2ecf20Sopenharmony_ci		goto bail;
3878c2ecf20Sopenharmony_ci
3888c2ecf20Sopenharmony_ci	i_size_write(inode, debug_purgelist_print(dlm, buf, PAGE_SIZE - 1));
3898c2ecf20Sopenharmony_ci
3908c2ecf20Sopenharmony_ci	file->private_data = buf;
3918c2ecf20Sopenharmony_ci
3928c2ecf20Sopenharmony_ci	return 0;
3938c2ecf20Sopenharmony_cibail:
3948c2ecf20Sopenharmony_ci	return -ENOMEM;
3958c2ecf20Sopenharmony_ci}
3968c2ecf20Sopenharmony_ci
3978c2ecf20Sopenharmony_cistatic const struct file_operations debug_purgelist_fops = {
3988c2ecf20Sopenharmony_ci	.open =		debug_purgelist_open,
3998c2ecf20Sopenharmony_ci	.release =	debug_release,
4008c2ecf20Sopenharmony_ci	.read =		debug_read,
4018c2ecf20Sopenharmony_ci	.llseek =	generic_file_llseek,
4028c2ecf20Sopenharmony_ci};
4038c2ecf20Sopenharmony_ci/* end - purge list funcs */
4048c2ecf20Sopenharmony_ci
4058c2ecf20Sopenharmony_ci/* begin - debug mle funcs */
4068c2ecf20Sopenharmony_cistatic int debug_mle_print(struct dlm_ctxt *dlm, char *buf, int len)
4078c2ecf20Sopenharmony_ci{
4088c2ecf20Sopenharmony_ci	struct dlm_master_list_entry *mle;
4098c2ecf20Sopenharmony_ci	struct hlist_head *bucket;
4108c2ecf20Sopenharmony_ci	int i, out = 0;
4118c2ecf20Sopenharmony_ci	unsigned long total = 0, longest = 0, bucket_count = 0;
4128c2ecf20Sopenharmony_ci
4138c2ecf20Sopenharmony_ci	out += scnprintf(buf + out, len - out,
4148c2ecf20Sopenharmony_ci			"Dumping MLEs for Domain: %s\n", dlm->name);
4158c2ecf20Sopenharmony_ci
4168c2ecf20Sopenharmony_ci	spin_lock(&dlm->master_lock);
4178c2ecf20Sopenharmony_ci	for (i = 0; i < DLM_HASH_BUCKETS; i++) {
4188c2ecf20Sopenharmony_ci		bucket = dlm_master_hash(dlm, i);
4198c2ecf20Sopenharmony_ci		hlist_for_each_entry(mle, bucket, master_hash_node) {
4208c2ecf20Sopenharmony_ci			++total;
4218c2ecf20Sopenharmony_ci			++bucket_count;
4228c2ecf20Sopenharmony_ci			if (len - out < 200)
4238c2ecf20Sopenharmony_ci				continue;
4248c2ecf20Sopenharmony_ci			out += dump_mle(mle, buf + out, len - out);
4258c2ecf20Sopenharmony_ci		}
4268c2ecf20Sopenharmony_ci		longest = max(longest, bucket_count);
4278c2ecf20Sopenharmony_ci		bucket_count = 0;
4288c2ecf20Sopenharmony_ci	}
4298c2ecf20Sopenharmony_ci	spin_unlock(&dlm->master_lock);
4308c2ecf20Sopenharmony_ci
4318c2ecf20Sopenharmony_ci	out += scnprintf(buf + out, len - out,
4328c2ecf20Sopenharmony_ci			"Total: %lu, Longest: %lu\n", total, longest);
4338c2ecf20Sopenharmony_ci	return out;
4348c2ecf20Sopenharmony_ci}
4358c2ecf20Sopenharmony_ci
4368c2ecf20Sopenharmony_cistatic int debug_mle_open(struct inode *inode, struct file *file)
4378c2ecf20Sopenharmony_ci{
4388c2ecf20Sopenharmony_ci	struct dlm_ctxt *dlm = inode->i_private;
4398c2ecf20Sopenharmony_ci	char *buf = NULL;
4408c2ecf20Sopenharmony_ci
4418c2ecf20Sopenharmony_ci	buf = (char *) get_zeroed_page(GFP_NOFS);
4428c2ecf20Sopenharmony_ci	if (!buf)
4438c2ecf20Sopenharmony_ci		goto bail;
4448c2ecf20Sopenharmony_ci
4458c2ecf20Sopenharmony_ci	i_size_write(inode, debug_mle_print(dlm, buf, PAGE_SIZE - 1));
4468c2ecf20Sopenharmony_ci
4478c2ecf20Sopenharmony_ci	file->private_data = buf;
4488c2ecf20Sopenharmony_ci
4498c2ecf20Sopenharmony_ci	return 0;
4508c2ecf20Sopenharmony_cibail:
4518c2ecf20Sopenharmony_ci	return -ENOMEM;
4528c2ecf20Sopenharmony_ci}
4538c2ecf20Sopenharmony_ci
4548c2ecf20Sopenharmony_cistatic const struct file_operations debug_mle_fops = {
4558c2ecf20Sopenharmony_ci	.open =		debug_mle_open,
4568c2ecf20Sopenharmony_ci	.release =	debug_release,
4578c2ecf20Sopenharmony_ci	.read =		debug_read,
4588c2ecf20Sopenharmony_ci	.llseek =	generic_file_llseek,
4598c2ecf20Sopenharmony_ci};
4608c2ecf20Sopenharmony_ci
4618c2ecf20Sopenharmony_ci/* end - debug mle funcs */
4628c2ecf20Sopenharmony_ci
4638c2ecf20Sopenharmony_ci/* begin - debug lockres funcs */
4648c2ecf20Sopenharmony_cistatic int dump_lock(struct dlm_lock *lock, int list_type, char *buf, int len)
4658c2ecf20Sopenharmony_ci{
4668c2ecf20Sopenharmony_ci	int out;
4678c2ecf20Sopenharmony_ci
4688c2ecf20Sopenharmony_ci#define DEBUG_LOCK_VERSION	1
4698c2ecf20Sopenharmony_ci	spin_lock(&lock->spinlock);
4708c2ecf20Sopenharmony_ci	out = scnprintf(buf, len, "LOCK:%d,%d,%d,%d,%d,%d:%lld,%d,%d,%d,%d,%d,"
4718c2ecf20Sopenharmony_ci		       "%d,%d,%d,%d\n",
4728c2ecf20Sopenharmony_ci		       DEBUG_LOCK_VERSION,
4738c2ecf20Sopenharmony_ci		       list_type, lock->ml.type, lock->ml.convert_type,
4748c2ecf20Sopenharmony_ci		       lock->ml.node,
4758c2ecf20Sopenharmony_ci		       dlm_get_lock_cookie_node(be64_to_cpu(lock->ml.cookie)),
4768c2ecf20Sopenharmony_ci		       dlm_get_lock_cookie_seq(be64_to_cpu(lock->ml.cookie)),
4778c2ecf20Sopenharmony_ci		       !list_empty(&lock->ast_list),
4788c2ecf20Sopenharmony_ci		       !list_empty(&lock->bast_list),
4798c2ecf20Sopenharmony_ci		       lock->ast_pending, lock->bast_pending,
4808c2ecf20Sopenharmony_ci		       lock->convert_pending, lock->lock_pending,
4818c2ecf20Sopenharmony_ci		       lock->cancel_pending, lock->unlock_pending,
4828c2ecf20Sopenharmony_ci		       kref_read(&lock->lock_refs));
4838c2ecf20Sopenharmony_ci	spin_unlock(&lock->spinlock);
4848c2ecf20Sopenharmony_ci
4858c2ecf20Sopenharmony_ci	return out;
4868c2ecf20Sopenharmony_ci}
4878c2ecf20Sopenharmony_ci
4888c2ecf20Sopenharmony_cistatic int dump_lockres(struct dlm_lock_resource *res, char *buf, int len)
4898c2ecf20Sopenharmony_ci{
4908c2ecf20Sopenharmony_ci	struct dlm_lock *lock;
4918c2ecf20Sopenharmony_ci	int i;
4928c2ecf20Sopenharmony_ci	int out = 0;
4938c2ecf20Sopenharmony_ci
4948c2ecf20Sopenharmony_ci	out += scnprintf(buf + out, len - out, "NAME:");
4958c2ecf20Sopenharmony_ci	out += stringify_lockname(res->lockname.name, res->lockname.len,
4968c2ecf20Sopenharmony_ci				  buf + out, len - out);
4978c2ecf20Sopenharmony_ci	out += scnprintf(buf + out, len - out, "\n");
4988c2ecf20Sopenharmony_ci
4998c2ecf20Sopenharmony_ci#define DEBUG_LRES_VERSION	1
5008c2ecf20Sopenharmony_ci	out += scnprintf(buf + out, len - out,
5018c2ecf20Sopenharmony_ci			"LRES:%d,%d,%d,%ld,%d,%d,%d,%d,%d,%d,%d\n",
5028c2ecf20Sopenharmony_ci			DEBUG_LRES_VERSION,
5038c2ecf20Sopenharmony_ci			res->owner, res->state, res->last_used,
5048c2ecf20Sopenharmony_ci			!list_empty(&res->purge),
5058c2ecf20Sopenharmony_ci			!list_empty(&res->dirty),
5068c2ecf20Sopenharmony_ci			!list_empty(&res->recovering),
5078c2ecf20Sopenharmony_ci			res->inflight_locks, res->migration_pending,
5088c2ecf20Sopenharmony_ci			atomic_read(&res->asts_reserved),
5098c2ecf20Sopenharmony_ci			kref_read(&res->refs));
5108c2ecf20Sopenharmony_ci
5118c2ecf20Sopenharmony_ci	/* refmap */
5128c2ecf20Sopenharmony_ci	out += scnprintf(buf + out, len - out, "RMAP:");
5138c2ecf20Sopenharmony_ci	out += stringify_nodemap(res->refmap, O2NM_MAX_NODES,
5148c2ecf20Sopenharmony_ci				 buf + out, len - out);
5158c2ecf20Sopenharmony_ci	out += scnprintf(buf + out, len - out, "\n");
5168c2ecf20Sopenharmony_ci
5178c2ecf20Sopenharmony_ci	/* lvb */
5188c2ecf20Sopenharmony_ci	out += scnprintf(buf + out, len - out, "LVBX:");
5198c2ecf20Sopenharmony_ci	for (i = 0; i < DLM_LVB_LEN; i++)
5208c2ecf20Sopenharmony_ci		out += scnprintf(buf + out, len - out,
5218c2ecf20Sopenharmony_ci					"%02x", (unsigned char)res->lvb[i]);
5228c2ecf20Sopenharmony_ci	out += scnprintf(buf + out, len - out, "\n");
5238c2ecf20Sopenharmony_ci
5248c2ecf20Sopenharmony_ci	/* granted */
5258c2ecf20Sopenharmony_ci	list_for_each_entry(lock, &res->granted, list)
5268c2ecf20Sopenharmony_ci		out += dump_lock(lock, 0, buf + out, len - out);
5278c2ecf20Sopenharmony_ci
5288c2ecf20Sopenharmony_ci	/* converting */
5298c2ecf20Sopenharmony_ci	list_for_each_entry(lock, &res->converting, list)
5308c2ecf20Sopenharmony_ci		out += dump_lock(lock, 1, buf + out, len - out);
5318c2ecf20Sopenharmony_ci
5328c2ecf20Sopenharmony_ci	/* blocked */
5338c2ecf20Sopenharmony_ci	list_for_each_entry(lock, &res->blocked, list)
5348c2ecf20Sopenharmony_ci		out += dump_lock(lock, 2, buf + out, len - out);
5358c2ecf20Sopenharmony_ci
5368c2ecf20Sopenharmony_ci	out += scnprintf(buf + out, len - out, "\n");
5378c2ecf20Sopenharmony_ci
5388c2ecf20Sopenharmony_ci	return out;
5398c2ecf20Sopenharmony_ci}
5408c2ecf20Sopenharmony_ci
5418c2ecf20Sopenharmony_cistatic void *lockres_seq_start(struct seq_file *m, loff_t *pos)
5428c2ecf20Sopenharmony_ci{
5438c2ecf20Sopenharmony_ci	struct debug_lockres *dl = m->private;
5448c2ecf20Sopenharmony_ci	struct dlm_ctxt *dlm = dl->dl_ctxt;
5458c2ecf20Sopenharmony_ci	struct dlm_lock_resource *oldres = dl->dl_res;
5468c2ecf20Sopenharmony_ci	struct dlm_lock_resource *res = NULL;
5478c2ecf20Sopenharmony_ci	struct list_head *track_list;
5488c2ecf20Sopenharmony_ci
5498c2ecf20Sopenharmony_ci	spin_lock(&dlm->track_lock);
5508c2ecf20Sopenharmony_ci	if (oldres)
5518c2ecf20Sopenharmony_ci		track_list = &oldres->tracking;
5528c2ecf20Sopenharmony_ci	else {
5538c2ecf20Sopenharmony_ci		track_list = &dlm->tracking_list;
5548c2ecf20Sopenharmony_ci		if (list_empty(track_list)) {
5558c2ecf20Sopenharmony_ci			dl = NULL;
5568c2ecf20Sopenharmony_ci			spin_unlock(&dlm->track_lock);
5578c2ecf20Sopenharmony_ci			goto bail;
5588c2ecf20Sopenharmony_ci		}
5598c2ecf20Sopenharmony_ci	}
5608c2ecf20Sopenharmony_ci
5618c2ecf20Sopenharmony_ci	list_for_each_entry(res, track_list, tracking) {
5628c2ecf20Sopenharmony_ci		if (&res->tracking == &dlm->tracking_list)
5638c2ecf20Sopenharmony_ci			res = NULL;
5648c2ecf20Sopenharmony_ci		else
5658c2ecf20Sopenharmony_ci			dlm_lockres_get(res);
5668c2ecf20Sopenharmony_ci		break;
5678c2ecf20Sopenharmony_ci	}
5688c2ecf20Sopenharmony_ci	spin_unlock(&dlm->track_lock);
5698c2ecf20Sopenharmony_ci
5708c2ecf20Sopenharmony_ci	if (oldres)
5718c2ecf20Sopenharmony_ci		dlm_lockres_put(oldres);
5728c2ecf20Sopenharmony_ci
5738c2ecf20Sopenharmony_ci	dl->dl_res = res;
5748c2ecf20Sopenharmony_ci
5758c2ecf20Sopenharmony_ci	if (res) {
5768c2ecf20Sopenharmony_ci		spin_lock(&res->spinlock);
5778c2ecf20Sopenharmony_ci		dump_lockres(res, dl->dl_buf, dl->dl_len - 1);
5788c2ecf20Sopenharmony_ci		spin_unlock(&res->spinlock);
5798c2ecf20Sopenharmony_ci	} else
5808c2ecf20Sopenharmony_ci		dl = NULL;
5818c2ecf20Sopenharmony_ci
5828c2ecf20Sopenharmony_cibail:
5838c2ecf20Sopenharmony_ci	/* passed to seq_show */
5848c2ecf20Sopenharmony_ci	return dl;
5858c2ecf20Sopenharmony_ci}
5868c2ecf20Sopenharmony_ci
5878c2ecf20Sopenharmony_cistatic void lockres_seq_stop(struct seq_file *m, void *v)
5888c2ecf20Sopenharmony_ci{
5898c2ecf20Sopenharmony_ci}
5908c2ecf20Sopenharmony_ci
5918c2ecf20Sopenharmony_cistatic void *lockres_seq_next(struct seq_file *m, void *v, loff_t *pos)
5928c2ecf20Sopenharmony_ci{
5938c2ecf20Sopenharmony_ci	return NULL;
5948c2ecf20Sopenharmony_ci}
5958c2ecf20Sopenharmony_ci
5968c2ecf20Sopenharmony_cistatic int lockres_seq_show(struct seq_file *s, void *v)
5978c2ecf20Sopenharmony_ci{
5988c2ecf20Sopenharmony_ci	struct debug_lockres *dl = (struct debug_lockres *)v;
5998c2ecf20Sopenharmony_ci
6008c2ecf20Sopenharmony_ci	seq_printf(s, "%s", dl->dl_buf);
6018c2ecf20Sopenharmony_ci
6028c2ecf20Sopenharmony_ci	return 0;
6038c2ecf20Sopenharmony_ci}
6048c2ecf20Sopenharmony_ci
6058c2ecf20Sopenharmony_cistatic const struct seq_operations debug_lockres_ops = {
6068c2ecf20Sopenharmony_ci	.start =	lockres_seq_start,
6078c2ecf20Sopenharmony_ci	.stop =		lockres_seq_stop,
6088c2ecf20Sopenharmony_ci	.next =		lockres_seq_next,
6098c2ecf20Sopenharmony_ci	.show =		lockres_seq_show,
6108c2ecf20Sopenharmony_ci};
6118c2ecf20Sopenharmony_ci
6128c2ecf20Sopenharmony_cistatic int debug_lockres_open(struct inode *inode, struct file *file)
6138c2ecf20Sopenharmony_ci{
6148c2ecf20Sopenharmony_ci	struct dlm_ctxt *dlm = inode->i_private;
6158c2ecf20Sopenharmony_ci	struct debug_lockres *dl;
6168c2ecf20Sopenharmony_ci	void *buf;
6178c2ecf20Sopenharmony_ci
6188c2ecf20Sopenharmony_ci	buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
6198c2ecf20Sopenharmony_ci	if (!buf)
6208c2ecf20Sopenharmony_ci		goto bail;
6218c2ecf20Sopenharmony_ci
6228c2ecf20Sopenharmony_ci	dl = __seq_open_private(file, &debug_lockres_ops, sizeof(*dl));
6238c2ecf20Sopenharmony_ci	if (!dl)
6248c2ecf20Sopenharmony_ci		goto bailfree;
6258c2ecf20Sopenharmony_ci
6268c2ecf20Sopenharmony_ci	dl->dl_len = PAGE_SIZE;
6278c2ecf20Sopenharmony_ci	dl->dl_buf = buf;
6288c2ecf20Sopenharmony_ci
6298c2ecf20Sopenharmony_ci	dlm_grab(dlm);
6308c2ecf20Sopenharmony_ci	dl->dl_ctxt = dlm;
6318c2ecf20Sopenharmony_ci
6328c2ecf20Sopenharmony_ci	return 0;
6338c2ecf20Sopenharmony_ci
6348c2ecf20Sopenharmony_cibailfree:
6358c2ecf20Sopenharmony_ci	kfree(buf);
6368c2ecf20Sopenharmony_cibail:
6378c2ecf20Sopenharmony_ci	mlog_errno(-ENOMEM);
6388c2ecf20Sopenharmony_ci	return -ENOMEM;
6398c2ecf20Sopenharmony_ci}
6408c2ecf20Sopenharmony_ci
6418c2ecf20Sopenharmony_cistatic int debug_lockres_release(struct inode *inode, struct file *file)
6428c2ecf20Sopenharmony_ci{
6438c2ecf20Sopenharmony_ci	struct seq_file *seq = file->private_data;
6448c2ecf20Sopenharmony_ci	struct debug_lockres *dl = (struct debug_lockres *)seq->private;
6458c2ecf20Sopenharmony_ci
6468c2ecf20Sopenharmony_ci	if (dl->dl_res)
6478c2ecf20Sopenharmony_ci		dlm_lockres_put(dl->dl_res);
6488c2ecf20Sopenharmony_ci	dlm_put(dl->dl_ctxt);
6498c2ecf20Sopenharmony_ci	kfree(dl->dl_buf);
6508c2ecf20Sopenharmony_ci	return seq_release_private(inode, file);
6518c2ecf20Sopenharmony_ci}
6528c2ecf20Sopenharmony_ci
6538c2ecf20Sopenharmony_cistatic const struct file_operations debug_lockres_fops = {
6548c2ecf20Sopenharmony_ci	.open =		debug_lockres_open,
6558c2ecf20Sopenharmony_ci	.release =	debug_lockres_release,
6568c2ecf20Sopenharmony_ci	.read =		seq_read,
6578c2ecf20Sopenharmony_ci	.llseek =	seq_lseek,
6588c2ecf20Sopenharmony_ci};
6598c2ecf20Sopenharmony_ci/* end - debug lockres funcs */
6608c2ecf20Sopenharmony_ci
6618c2ecf20Sopenharmony_ci/* begin - debug state funcs */
6628c2ecf20Sopenharmony_cistatic int debug_state_print(struct dlm_ctxt *dlm, char *buf, int len)
6638c2ecf20Sopenharmony_ci{
6648c2ecf20Sopenharmony_ci	int out = 0;
6658c2ecf20Sopenharmony_ci	struct dlm_reco_node_data *node;
6668c2ecf20Sopenharmony_ci	char *state;
6678c2ecf20Sopenharmony_ci	int cur_mles = 0, tot_mles = 0;
6688c2ecf20Sopenharmony_ci	int i;
6698c2ecf20Sopenharmony_ci
6708c2ecf20Sopenharmony_ci	spin_lock(&dlm->spinlock);
6718c2ecf20Sopenharmony_ci
6728c2ecf20Sopenharmony_ci	switch (dlm->dlm_state) {
6738c2ecf20Sopenharmony_ci	case DLM_CTXT_NEW:
6748c2ecf20Sopenharmony_ci		state = "NEW"; break;
6758c2ecf20Sopenharmony_ci	case DLM_CTXT_JOINED:
6768c2ecf20Sopenharmony_ci		state = "JOINED"; break;
6778c2ecf20Sopenharmony_ci	case DLM_CTXT_IN_SHUTDOWN:
6788c2ecf20Sopenharmony_ci		state = "SHUTDOWN"; break;
6798c2ecf20Sopenharmony_ci	case DLM_CTXT_LEAVING:
6808c2ecf20Sopenharmony_ci		state = "LEAVING"; break;
6818c2ecf20Sopenharmony_ci	default:
6828c2ecf20Sopenharmony_ci		state = "UNKNOWN"; break;
6838c2ecf20Sopenharmony_ci	}
6848c2ecf20Sopenharmony_ci
6858c2ecf20Sopenharmony_ci	/* Domain: xxxxxxxxxx  Key: 0xdfbac769 */
6868c2ecf20Sopenharmony_ci	out += scnprintf(buf + out, len - out,
6878c2ecf20Sopenharmony_ci			"Domain: %s  Key: 0x%08x  Protocol: %d.%d\n",
6888c2ecf20Sopenharmony_ci			dlm->name, dlm->key, dlm->dlm_locking_proto.pv_major,
6898c2ecf20Sopenharmony_ci			dlm->dlm_locking_proto.pv_minor);
6908c2ecf20Sopenharmony_ci
6918c2ecf20Sopenharmony_ci	/* Thread Pid: xxx  Node: xxx  State: xxxxx */
6928c2ecf20Sopenharmony_ci	out += scnprintf(buf + out, len - out,
6938c2ecf20Sopenharmony_ci			"Thread Pid: %d  Node: %d  State: %s\n",
6948c2ecf20Sopenharmony_ci			task_pid_nr(dlm->dlm_thread_task), dlm->node_num, state);
6958c2ecf20Sopenharmony_ci
6968c2ecf20Sopenharmony_ci	/* Number of Joins: xxx  Joining Node: xxx */
6978c2ecf20Sopenharmony_ci	out += scnprintf(buf + out, len - out,
6988c2ecf20Sopenharmony_ci			"Number of Joins: %d  Joining Node: %d\n",
6998c2ecf20Sopenharmony_ci			dlm->num_joins, dlm->joining_node);
7008c2ecf20Sopenharmony_ci
7018c2ecf20Sopenharmony_ci	/* Domain Map: xx xx xx */
7028c2ecf20Sopenharmony_ci	out += scnprintf(buf + out, len - out, "Domain Map: ");
7038c2ecf20Sopenharmony_ci	out += stringify_nodemap(dlm->domain_map, O2NM_MAX_NODES,
7048c2ecf20Sopenharmony_ci				 buf + out, len - out);
7058c2ecf20Sopenharmony_ci	out += scnprintf(buf + out, len - out, "\n");
7068c2ecf20Sopenharmony_ci
7078c2ecf20Sopenharmony_ci	/* Exit Domain Map: xx xx xx */
7088c2ecf20Sopenharmony_ci	out += scnprintf(buf + out, len - out, "Exit Domain Map: ");
7098c2ecf20Sopenharmony_ci	out += stringify_nodemap(dlm->exit_domain_map, O2NM_MAX_NODES,
7108c2ecf20Sopenharmony_ci				 buf + out, len - out);
7118c2ecf20Sopenharmony_ci	out += scnprintf(buf + out, len - out, "\n");
7128c2ecf20Sopenharmony_ci
7138c2ecf20Sopenharmony_ci	/* Live Map: xx xx xx */
7148c2ecf20Sopenharmony_ci	out += scnprintf(buf + out, len - out, "Live Map: ");
7158c2ecf20Sopenharmony_ci	out += stringify_nodemap(dlm->live_nodes_map, O2NM_MAX_NODES,
7168c2ecf20Sopenharmony_ci				 buf + out, len - out);
7178c2ecf20Sopenharmony_ci	out += scnprintf(buf + out, len - out, "\n");
7188c2ecf20Sopenharmony_ci
7198c2ecf20Sopenharmony_ci	/* Lock Resources: xxx (xxx) */
7208c2ecf20Sopenharmony_ci	out += scnprintf(buf + out, len - out,
7218c2ecf20Sopenharmony_ci			"Lock Resources: %d (%d)\n",
7228c2ecf20Sopenharmony_ci			atomic_read(&dlm->res_cur_count),
7238c2ecf20Sopenharmony_ci			atomic_read(&dlm->res_tot_count));
7248c2ecf20Sopenharmony_ci
7258c2ecf20Sopenharmony_ci	for (i = 0; i < DLM_MLE_NUM_TYPES; ++i)
7268c2ecf20Sopenharmony_ci		tot_mles += atomic_read(&dlm->mle_tot_count[i]);
7278c2ecf20Sopenharmony_ci
7288c2ecf20Sopenharmony_ci	for (i = 0; i < DLM_MLE_NUM_TYPES; ++i)
7298c2ecf20Sopenharmony_ci		cur_mles += atomic_read(&dlm->mle_cur_count[i]);
7308c2ecf20Sopenharmony_ci
7318c2ecf20Sopenharmony_ci	/* MLEs: xxx (xxx) */
7328c2ecf20Sopenharmony_ci	out += scnprintf(buf + out, len - out,
7338c2ecf20Sopenharmony_ci			"MLEs: %d (%d)\n", cur_mles, tot_mles);
7348c2ecf20Sopenharmony_ci
7358c2ecf20Sopenharmony_ci	/*  Blocking: xxx (xxx) */
7368c2ecf20Sopenharmony_ci	out += scnprintf(buf + out, len - out,
7378c2ecf20Sopenharmony_ci			"  Blocking: %d (%d)\n",
7388c2ecf20Sopenharmony_ci			atomic_read(&dlm->mle_cur_count[DLM_MLE_BLOCK]),
7398c2ecf20Sopenharmony_ci			atomic_read(&dlm->mle_tot_count[DLM_MLE_BLOCK]));
7408c2ecf20Sopenharmony_ci
7418c2ecf20Sopenharmony_ci	/*  Mastery: xxx (xxx) */
7428c2ecf20Sopenharmony_ci	out += scnprintf(buf + out, len - out,
7438c2ecf20Sopenharmony_ci			"  Mastery: %d (%d)\n",
7448c2ecf20Sopenharmony_ci			atomic_read(&dlm->mle_cur_count[DLM_MLE_MASTER]),
7458c2ecf20Sopenharmony_ci			atomic_read(&dlm->mle_tot_count[DLM_MLE_MASTER]));
7468c2ecf20Sopenharmony_ci
7478c2ecf20Sopenharmony_ci	/*  Migration: xxx (xxx) */
7488c2ecf20Sopenharmony_ci	out += scnprintf(buf + out, len - out,
7498c2ecf20Sopenharmony_ci			"  Migration: %d (%d)\n",
7508c2ecf20Sopenharmony_ci			atomic_read(&dlm->mle_cur_count[DLM_MLE_MIGRATION]),
7518c2ecf20Sopenharmony_ci			atomic_read(&dlm->mle_tot_count[DLM_MLE_MIGRATION]));
7528c2ecf20Sopenharmony_ci
7538c2ecf20Sopenharmony_ci	/* Lists: Dirty=Empty  Purge=InUse  PendingASTs=Empty  ... */
7548c2ecf20Sopenharmony_ci	out += scnprintf(buf + out, len - out,
7558c2ecf20Sopenharmony_ci			"Lists: Dirty=%s  Purge=%s  PendingASTs=%s  "
7568c2ecf20Sopenharmony_ci			"PendingBASTs=%s\n",
7578c2ecf20Sopenharmony_ci			(list_empty(&dlm->dirty_list) ? "Empty" : "InUse"),
7588c2ecf20Sopenharmony_ci			(list_empty(&dlm->purge_list) ? "Empty" : "InUse"),
7598c2ecf20Sopenharmony_ci			(list_empty(&dlm->pending_asts) ? "Empty" : "InUse"),
7608c2ecf20Sopenharmony_ci			(list_empty(&dlm->pending_basts) ? "Empty" : "InUse"));
7618c2ecf20Sopenharmony_ci
7628c2ecf20Sopenharmony_ci	/* Purge Count: xxx  Refs: xxx */
7638c2ecf20Sopenharmony_ci	out += scnprintf(buf + out, len - out,
7648c2ecf20Sopenharmony_ci			"Purge Count: %d  Refs: %d\n", dlm->purge_count,
7658c2ecf20Sopenharmony_ci			kref_read(&dlm->dlm_refs));
7668c2ecf20Sopenharmony_ci
7678c2ecf20Sopenharmony_ci	/* Dead Node: xxx */
7688c2ecf20Sopenharmony_ci	out += scnprintf(buf + out, len - out,
7698c2ecf20Sopenharmony_ci			"Dead Node: %d\n", dlm->reco.dead_node);
7708c2ecf20Sopenharmony_ci
7718c2ecf20Sopenharmony_ci	/* What about DLM_RECO_STATE_FINALIZE? */
7728c2ecf20Sopenharmony_ci	if (dlm->reco.state == DLM_RECO_STATE_ACTIVE)
7738c2ecf20Sopenharmony_ci		state = "ACTIVE";
7748c2ecf20Sopenharmony_ci	else
7758c2ecf20Sopenharmony_ci		state = "INACTIVE";
7768c2ecf20Sopenharmony_ci
7778c2ecf20Sopenharmony_ci	/* Recovery Pid: xxxx  Master: xxx  State: xxxx */
7788c2ecf20Sopenharmony_ci	out += scnprintf(buf + out, len - out,
7798c2ecf20Sopenharmony_ci			"Recovery Pid: %d  Master: %d  State: %s\n",
7808c2ecf20Sopenharmony_ci			task_pid_nr(dlm->dlm_reco_thread_task),
7818c2ecf20Sopenharmony_ci			dlm->reco.new_master, state);
7828c2ecf20Sopenharmony_ci
7838c2ecf20Sopenharmony_ci	/* Recovery Map: xx xx */
7848c2ecf20Sopenharmony_ci	out += scnprintf(buf + out, len - out, "Recovery Map: ");
7858c2ecf20Sopenharmony_ci	out += stringify_nodemap(dlm->recovery_map, O2NM_MAX_NODES,
7868c2ecf20Sopenharmony_ci				 buf + out, len - out);
7878c2ecf20Sopenharmony_ci	out += scnprintf(buf + out, len - out, "\n");
7888c2ecf20Sopenharmony_ci
7898c2ecf20Sopenharmony_ci	/* Recovery Node State: */
7908c2ecf20Sopenharmony_ci	out += scnprintf(buf + out, len - out, "Recovery Node State:\n");
7918c2ecf20Sopenharmony_ci	list_for_each_entry(node, &dlm->reco.node_data, list) {
7928c2ecf20Sopenharmony_ci		switch (node->state) {
7938c2ecf20Sopenharmony_ci		case DLM_RECO_NODE_DATA_INIT:
7948c2ecf20Sopenharmony_ci			state = "INIT";
7958c2ecf20Sopenharmony_ci			break;
7968c2ecf20Sopenharmony_ci		case DLM_RECO_NODE_DATA_REQUESTING:
7978c2ecf20Sopenharmony_ci			state = "REQUESTING";
7988c2ecf20Sopenharmony_ci			break;
7998c2ecf20Sopenharmony_ci		case DLM_RECO_NODE_DATA_DEAD:
8008c2ecf20Sopenharmony_ci			state = "DEAD";
8018c2ecf20Sopenharmony_ci			break;
8028c2ecf20Sopenharmony_ci		case DLM_RECO_NODE_DATA_RECEIVING:
8038c2ecf20Sopenharmony_ci			state = "RECEIVING";
8048c2ecf20Sopenharmony_ci			break;
8058c2ecf20Sopenharmony_ci		case DLM_RECO_NODE_DATA_REQUESTED:
8068c2ecf20Sopenharmony_ci			state = "REQUESTED";
8078c2ecf20Sopenharmony_ci			break;
8088c2ecf20Sopenharmony_ci		case DLM_RECO_NODE_DATA_DONE:
8098c2ecf20Sopenharmony_ci			state = "DONE";
8108c2ecf20Sopenharmony_ci			break;
8118c2ecf20Sopenharmony_ci		case DLM_RECO_NODE_DATA_FINALIZE_SENT:
8128c2ecf20Sopenharmony_ci			state = "FINALIZE-SENT";
8138c2ecf20Sopenharmony_ci			break;
8148c2ecf20Sopenharmony_ci		default:
8158c2ecf20Sopenharmony_ci			state = "BAD";
8168c2ecf20Sopenharmony_ci			break;
8178c2ecf20Sopenharmony_ci		}
8188c2ecf20Sopenharmony_ci		out += scnprintf(buf + out, len - out, "\t%u - %s\n",
8198c2ecf20Sopenharmony_ci				node->node_num, state);
8208c2ecf20Sopenharmony_ci	}
8218c2ecf20Sopenharmony_ci
8228c2ecf20Sopenharmony_ci	spin_unlock(&dlm->spinlock);
8238c2ecf20Sopenharmony_ci
8248c2ecf20Sopenharmony_ci	return out;
8258c2ecf20Sopenharmony_ci}
8268c2ecf20Sopenharmony_ci
8278c2ecf20Sopenharmony_cistatic int debug_state_open(struct inode *inode, struct file *file)
8288c2ecf20Sopenharmony_ci{
8298c2ecf20Sopenharmony_ci	struct dlm_ctxt *dlm = inode->i_private;
8308c2ecf20Sopenharmony_ci	char *buf = NULL;
8318c2ecf20Sopenharmony_ci
8328c2ecf20Sopenharmony_ci	buf = (char *) get_zeroed_page(GFP_NOFS);
8338c2ecf20Sopenharmony_ci	if (!buf)
8348c2ecf20Sopenharmony_ci		goto bail;
8358c2ecf20Sopenharmony_ci
8368c2ecf20Sopenharmony_ci	i_size_write(inode, debug_state_print(dlm, buf, PAGE_SIZE - 1));
8378c2ecf20Sopenharmony_ci
8388c2ecf20Sopenharmony_ci	file->private_data = buf;
8398c2ecf20Sopenharmony_ci
8408c2ecf20Sopenharmony_ci	return 0;
8418c2ecf20Sopenharmony_cibail:
8428c2ecf20Sopenharmony_ci	return -ENOMEM;
8438c2ecf20Sopenharmony_ci}
8448c2ecf20Sopenharmony_ci
8458c2ecf20Sopenharmony_cistatic const struct file_operations debug_state_fops = {
8468c2ecf20Sopenharmony_ci	.open =		debug_state_open,
8478c2ecf20Sopenharmony_ci	.release =	debug_release,
8488c2ecf20Sopenharmony_ci	.read =		debug_read,
8498c2ecf20Sopenharmony_ci	.llseek =	generic_file_llseek,
8508c2ecf20Sopenharmony_ci};
8518c2ecf20Sopenharmony_ci/* end  - debug state funcs */
8528c2ecf20Sopenharmony_ci
8538c2ecf20Sopenharmony_ci/* files in subroot */
8548c2ecf20Sopenharmony_civoid dlm_debug_init(struct dlm_ctxt *dlm)
8558c2ecf20Sopenharmony_ci{
8568c2ecf20Sopenharmony_ci	/* for dumping dlm_ctxt */
8578c2ecf20Sopenharmony_ci	debugfs_create_file(DLM_DEBUGFS_DLM_STATE, S_IFREG|S_IRUSR,
8588c2ecf20Sopenharmony_ci			    dlm->dlm_debugfs_subroot, dlm, &debug_state_fops);
8598c2ecf20Sopenharmony_ci
8608c2ecf20Sopenharmony_ci	/* for dumping lockres */
8618c2ecf20Sopenharmony_ci	debugfs_create_file(DLM_DEBUGFS_LOCKING_STATE, S_IFREG|S_IRUSR,
8628c2ecf20Sopenharmony_ci			    dlm->dlm_debugfs_subroot, dlm, &debug_lockres_fops);
8638c2ecf20Sopenharmony_ci
8648c2ecf20Sopenharmony_ci	/* for dumping mles */
8658c2ecf20Sopenharmony_ci	debugfs_create_file(DLM_DEBUGFS_MLE_STATE, S_IFREG|S_IRUSR,
8668c2ecf20Sopenharmony_ci			    dlm->dlm_debugfs_subroot, dlm, &debug_mle_fops);
8678c2ecf20Sopenharmony_ci
8688c2ecf20Sopenharmony_ci	/* for dumping lockres on the purge list */
8698c2ecf20Sopenharmony_ci	debugfs_create_file(DLM_DEBUGFS_PURGE_LIST, S_IFREG|S_IRUSR,
8708c2ecf20Sopenharmony_ci			    dlm->dlm_debugfs_subroot, dlm,
8718c2ecf20Sopenharmony_ci			    &debug_purgelist_fops);
8728c2ecf20Sopenharmony_ci}
8738c2ecf20Sopenharmony_ci
8748c2ecf20Sopenharmony_ci/* subroot - domain dir */
8758c2ecf20Sopenharmony_civoid dlm_create_debugfs_subroot(struct dlm_ctxt *dlm)
8768c2ecf20Sopenharmony_ci{
8778c2ecf20Sopenharmony_ci	dlm->dlm_debugfs_subroot = debugfs_create_dir(dlm->name,
8788c2ecf20Sopenharmony_ci						      dlm_debugfs_root);
8798c2ecf20Sopenharmony_ci}
8808c2ecf20Sopenharmony_ci
8818c2ecf20Sopenharmony_civoid dlm_destroy_debugfs_subroot(struct dlm_ctxt *dlm)
8828c2ecf20Sopenharmony_ci{
8838c2ecf20Sopenharmony_ci	debugfs_remove_recursive(dlm->dlm_debugfs_subroot);
8848c2ecf20Sopenharmony_ci}
8858c2ecf20Sopenharmony_ci
8868c2ecf20Sopenharmony_ci/* debugfs root */
8878c2ecf20Sopenharmony_civoid dlm_create_debugfs_root(void)
8888c2ecf20Sopenharmony_ci{
8898c2ecf20Sopenharmony_ci	dlm_debugfs_root = debugfs_create_dir(DLM_DEBUGFS_DIR, NULL);
8908c2ecf20Sopenharmony_ci}
8918c2ecf20Sopenharmony_ci
8928c2ecf20Sopenharmony_civoid dlm_destroy_debugfs_root(void)
8938c2ecf20Sopenharmony_ci{
8948c2ecf20Sopenharmony_ci	debugfs_remove(dlm_debugfs_root);
8958c2ecf20Sopenharmony_ci}
8968c2ecf20Sopenharmony_ci#endif	/* CONFIG_DEBUG_FS */
897