// SPDX-License-Identifier: GPL-2.0-or-later
/* -*- mode: c; c-basic-offset: 8; -*-
* vim: noexpandtab sw=8 ts=8 sts=0:
*
* dlmdebug.c
*
* debug functionality for the dlm
*
* Copyright (C) 2004, 2008 Oracle. All rights reserved.
*/
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/highmem.h>
#include <linux/sysctl.h>
#include <linux/spinlock.h>
#include <linux/debugfs.h>
#include <linux/export.h>
#include "../cluster/heartbeat.h"
#include "../cluster/nodemanager.h"
#include "../cluster/tcp.h"
#include "dlmapi.h"
#include "dlmcommon.h"
#include "dlmdomain.h"
#include "dlmdebug.h"
#define MLOG_MASK_PREFIX ML_DLM
#include "../cluster/masklog.h"
static int stringify_lockname(const char *lockname, int locklen, char *buf,
int len);
void dlm_print_one_lock_resource(struct dlm_lock_resource *res)
{
spin_lock(&res->spinlock);
__dlm_print_one_lock_resource(res);
spin_unlock(&res->spinlock);
}
static void dlm_print_lockres_refmap(struct dlm_lock_resource *res)
{
int bit;
assert_spin_locked(&res->spinlock);
printk(" refmap nodes: [ ");
bit = 0;
while (1) {
bit = find_next_bit(res->refmap, O2NM_MAX_NODES, bit);
if (bit >= O2NM_MAX_NODES)
break;
printk("%u ", bit);
bit++;
}
printk("], inflight=%u\n", res->inflight_locks);
}
static void __dlm_print_lock(struct dlm_lock *lock)
{
spin_lock(&lock->spinlock);
printk(" type=%d, conv=%d, node=%u, cookie=%u:%llu, "
"ref=%u, ast=(empty=%c,pend=%c), bast=(empty=%c,pend=%c), "
"pending=(conv=%c,lock=%c,cancel=%c,unlock=%c)\n",
lock->ml.type, lock->ml.convert_type, lock->ml.node,
dlm_get_lock_cookie_node(be64_to_cpu(lock->ml.cookie)),
dlm_get_lock_cookie_seq(be64_to_cpu(lock->ml.cookie)),
kref_read(&lock->lock_refs),
(list_empty(&lock->ast_list) ? 'y' : 'n'),
(lock->ast_pending ? 'y' : 'n'),
(list_empty(&lock->bast_list) ? 'y' : 'n'),
(lock->bast_pending ? 'y' : 'n'),
(lock->convert_pending ? 'y' : 'n'),
(lock->lock_pending ? 'y' : 'n'),
(lock->cancel_pending ? 'y' : 'n'),
(lock->unlock_pending ? 'y' : 'n'));
spin_unlock(&lock->spinlock);
}
void __dlm_print_one_lock_resource(struct dlm_lock_resource *res)
{
struct dlm_lock *lock;
char buf[DLM_LOCKID_NAME_MAX];
assert_spin_locked(&res->spinlock);
stringify_lockname(res->lockname.name, res->lockname.len,
buf, sizeof(buf));
printk("lockres: %s, owner=%u, state=%u\n",
buf, res->owner, res->state);
printk(" last used: %lu, refcnt: %u, on purge list: %s\n",
res->last_used, kref_read(&res->refs),
list_empty(&res->purge) ? "no" : "yes");
printk(" on dirty list: %s, on reco list: %s, "
"migrating pending: %s\n",
list_empty(&res->dirty) ? "no" : "yes",
list_empty(&res->recovering) ? "no" : "yes",
res->migration_pending ? "yes" : "no");
printk(" inflight locks: %d, asts reserved: %d\n",
res->inflight_locks, atomic_read(&res->asts_reserved));
dlm_print_lockres_refmap(res);
printk(" granted queue:\n");
list_for_each_entry(lock, &res->granted, list) {
__dlm_print_lock(lock);
}
printk(" converting queue:\n");
list_for_each_entry(lock, &res->converting, list) {
__dlm_print_lock(lock);
}
printk(" blocked queue:\n");
list_for_each_entry(lock, &res->blocked, list) {
__dlm_print_lock(lock);
}
}
void dlm_print_one_lock(struct dlm_lock *lockid)
{
dlm_print_one_lock_resource(lockid->lockres);
}
EXPORT_SYMBOL_GPL(dlm_print_one_lock);
static const char *dlm_errnames[] = {
[DLM_NORMAL] = "DLM_NORMAL",
[DLM_GRANTED] = "DLM_GRANTED",
[DLM_DENIED] = "DLM_DENIED",
[DLM_DENIED_NOLOCKS] = "DLM_DENIED_NOLOCKS",
[DLM_WORKING] = "DLM_WORKING",
[DLM_BLOCKED] = "DLM_BLOCKED",
[DLM_BLOCKED_ORPHAN] = "DLM_BLOCKED_ORPHAN",
[DLM_DENIED_GRACE_PERIOD] = "DLM_DENIED_GRACE_PERIOD",
[DLM_SYSERR] = "DLM_SYSERR",
[DLM_NOSUPPORT] = "DLM_NOSUPPORT",
[DLM_CANCELGRANT] = "DLM_CANCELGRANT",
[DLM_IVLOCKID] = "DLM_IVLOCKID",
[DLM_SYNC] = "DLM_SYNC",
[DLM_BADTYPE] = "DLM_BADTYPE",
[DLM_BADRESOURCE] = "DLM_BADRESOURCE",
[DLM_MAXHANDLES] = "DLM_MAXHANDLES",
[DLM_NOCLINFO] = "DLM_NOCLINFO",
[DLM_NOLOCKMGR] = "DLM_NOLOCKMGR",
[DLM_NOPURGED]