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