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