2019-05-24 13:04:05 +03:00
// SPDX-License-Identifier: GPL-2.0-or-later
2005-12-16 01:31:23 +03:00
/* -*- mode: c; c-basic-offset: 8; -*-
* vim : noexpandtab sw = 8 ts = 8 sts = 0 :
*
* dlmdebug . c
*
* debug functionality for the dlm
*
2008-03-11 01:16:29 +03:00
* Copyright ( C ) 2004 , 2008 Oracle . All rights reserved .
2005-12-16 01:31:23 +03:00
*/
# include <linux/types.h>
# include <linux/slab.h>
# include <linux/highmem.h>
# include <linux/sysctl.h>
# include <linux/spinlock.h>
2008-03-11 01:16:22 +03:00
# include <linux/debugfs.h>
2011-05-27 00:00:52 +04:00
# include <linux/export.h>
2005-12-16 01:31:23 +03:00
# include "cluster/heartbeat.h"
# include "cluster/nodemanager.h"
# include "cluster/tcp.h"
# include "dlmapi.h"
# include "dlmcommon.h"
# include "dlmdomain.h"
2008-03-11 01:16:22 +03:00
# include "dlmdebug.h"
2005-12-16 01:31:23 +03:00
# define MLOG_MASK_PREFIX ML_DLM
# include "cluster/masklog.h"
2008-04-21 12:49:37 +04:00
static int stringify_lockname ( const char * lockname , int locklen , char * buf ,
int len ) ;
2008-03-11 01:16:29 +03:00
2005-12-16 01:31:23 +03:00
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 ) ;
}
2006-12-02 01:47:20 +03:00
static void dlm_print_lockres_refmap ( struct dlm_lock_resource * res )
{
int bit ;
assert_spin_locked ( & res - > spinlock ) ;
2008-03-14 21:18:24 +03:00
printk ( " refmap nodes: [ " ) ;
2006-12-02 01:47:20 +03:00
bit = 0 ;
while ( 1 ) {
bit = find_next_bit ( res - > refmap , O2NM_MAX_NODES , bit ) ;
if ( bit > = O2NM_MAX_NODES )
break ;
2008-03-14 21:18:24 +03:00
printk ( " %u " , bit ) ;
2006-12-02 01:47:20 +03:00
bit + + ;
}
2008-03-14 21:18:24 +03:00
printk ( " ], inflight=%u \n " , res - > inflight_locks ) ;
2008-03-11 01:16:29 +03:00
}
static void __dlm_print_lock ( struct dlm_lock * lock )
{
spin_lock ( & lock - > spinlock ) ;
2008-03-14 21:18:24 +03:00
printk ( " type=%d, conv=%d, node=%u, cookie=%u:%llu, "
2008-03-11 01:16:29 +03:00
" 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 ) ) ,
2016-11-14 19:29:48 +03:00
kref_read ( & lock - > lock_refs ) ,
2008-03-11 01:16:29 +03:00
( 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 ) ;
2006-12-02 01:47:20 +03:00
}
2005-12-16 01:31:23 +03:00
void __dlm_print_one_lock_resource ( struct dlm_lock_resource * res )
{
struct dlm_lock * lock ;
2008-03-11 01:16:29 +03:00
char buf [ DLM_LOCKID_NAME_MAX ] ;
2005-12-16 01:31:23 +03:00
assert_spin_locked ( & res - > spinlock ) ;
2008-03-11 01:16:29 +03:00
stringify_lockname ( res - > lockname . name , res - > lockname . len ,
2010-02-06 04:55:56 +03:00
buf , sizeof ( buf ) ) ;
2008-03-14 21:18:24 +03:00
printk ( " lockres: %s, owner=%u, state=%u \n " ,
2008-03-11 01:16:29 +03:00
buf , res - > owner , res - > state ) ;
2008-03-14 21:18:24 +03:00
printk ( " last used: %lu, refcnt: %u, on purge list: %s \n " ,
2016-11-14 19:29:48 +03:00
res - > last_used , kref_read ( & res - > refs ) ,
2008-03-11 01:16:29 +03:00
list_empty ( & res - > purge ) ? " no " : " yes " ) ;
2008-03-14 21:18:24 +03:00
printk ( " on dirty list: %s, on reco list: %s, "
2008-03-11 01:16:29 +03:00
" migrating pending: %s \n " ,
list_empty ( & res - > dirty ) ? " no " : " yes " ,
list_empty ( & res - > recovering ) ? " no " : " yes " ,
res - > migration_pending ? " yes " : " no " ) ;
2008-03-14 21:18:24 +03:00
printk ( " inflight locks: %d, asts reserved: %d \n " ,
2008-03-11 01:16:29 +03:00
res - > inflight_locks , atomic_read ( & res - > asts_reserved ) ) ;
2006-12-02 01:47:20 +03:00
dlm_print_lockres_refmap ( res ) ;
2008-03-14 21:18:24 +03:00
printk ( " granted queue: \n " ) ;
2013-09-12 01:19:50 +04:00
list_for_each_entry ( lock , & res - > granted , list ) {
2008-03-11 01:16:29 +03:00
__dlm_print_lock ( lock ) ;
2005-12-16 01:31:23 +03:00
}
2008-03-14 21:18:24 +03:00
printk ( " converting queue: \n " ) ;
2013-09-12 01:19:50 +04:00
list_for_each_entry ( lock , & res - > converting , list ) {
2008-03-11 01:16:29 +03:00
__dlm_print_lock ( lock ) ;
2005-12-16 01:31:23 +03:00
}
2008-03-14 21:18:24 +03:00
printk ( " blocked queue: \n " ) ;
2013-09-12 01:19:50 +04:00
list_for_each_entry ( lock , & res - > blocked , list ) {
2008-03-11 01:16:29 +03:00
__dlm_print_lock ( lock ) ;
2005-12-16 01:31:23 +03:00
}
}
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 ] = " DLM_NOPURGED " ,
[ DLM_BADARGS ] = " DLM_BADARGS " ,
[ DLM_VOID ] = " DLM_VOID " ,
[ DLM_NOTQUEUED ] = " DLM_NOTQUEUED " ,
[ DLM_IVBUFLEN ] = " DLM_IVBUFLEN " ,
[ DLM_CVTUNGRANT ] = " DLM_CVTUNGRANT " ,
[ DLM_BADPARAM ] = " DLM_BADPARAM " ,
[ DLM_VALNOTVALID ] = " DLM_VALNOTVALID " ,
[ DLM_REJECTED ] = " DLM_REJECTED " ,
[ DLM_ABORT ] = " DLM_ABORT " ,
[ DLM_CANCEL ] = " DLM_CANCEL " ,
[ DLM_IVRESHANDLE ] = " DLM_IVRESHANDLE " ,
[ DLM_DEADLOCK ] = " DLM_DEADLOCK " ,
[ DLM_DENIED_NOASTS ] = " DLM_DENIED_NOASTS " ,
[ DLM_FORWARD ] = " DLM_FORWARD " ,
[ DLM_TIMEOUT ] = " DLM_TIMEOUT " ,
[ DLM_IVGROUPID ] = " DLM_IVGROUPID " ,
[ DLM_VERS_CONFLICT ] = " DLM_VERS_CONFLICT " ,
[ DLM_BAD_DEVICE_PATH ] = " DLM_BAD_DEVICE_PATH " ,
[ DLM_NO_DEVICE_PERMISSION ] = " DLM_NO_DEVICE_PERMISSION " ,
[ DLM_NO_CONTROL_DEVICE ] = " DLM_NO_CONTROL_DEVICE " ,
[ DLM_RECOVERING ] = " DLM_RECOVERING " ,
[ DLM_MIGRATING ] = " DLM_MIGRATING " ,
[ DLM_MAXSTATS ] = " DLM_MAXSTATS " ,
} ;
static const char * dlm_errmsgs [ ] = {
[ DLM_NORMAL ] = " request in progress " ,
[ DLM_GRANTED ] = " request granted " ,
[ DLM_DENIED ] = " request denied " ,
[ DLM_DENIED_NOLOCKS ] = " request denied, out of system resources " ,
[ DLM_WORKING ] = " async request in progress " ,
[ DLM_BLOCKED ] = " lock request blocked " ,
[ DLM_BLOCKED_ORPHAN ] = " lock request blocked by a orphan lock " ,
[ DLM_DENIED_GRACE_PERIOD ] = " topological change in progress " ,
[ DLM_SYSERR ] = " system error " ,
[ DLM_NOSUPPORT ] = " unsupported " ,
[ DLM_CANCELGRANT ] = " can't cancel convert: already granted " ,
[ DLM_IVLOCKID ] = " bad lockid " ,
[ DLM_SYNC ] = " synchronous request granted " ,
[ DLM_BADTYPE ] = " bad resource type " ,
[ DLM_BADRESOURCE ] = " bad resource handle " ,
[ DLM_MAXHANDLES ] = " no more resource handles " ,
[ DLM_NOCLINFO ] = " can't contact cluster manager " ,
[ DLM_NOLOCKMGR ] = " can't contact lock manager " ,
[ DLM_NOPURGED ] = " can't contact purge daemon " ,
[ DLM_BADARGS ] = " bad api args " ,
[ DLM_VOID ] = " no status " ,
[ DLM_NOTQUEUED ] = " NOQUEUE was specified and request failed " ,
[ DLM_IVBUFLEN ] = " invalid resource name length " ,
[ DLM_CVTUNGRANT ] = " attempted to convert ungranted lock " ,
[ DLM_BADPARAM ] = " invalid lock mode specified " ,
[ DLM_VALNOTVALID ] = " value block has been invalidated " ,
[ DLM_REJECTED ] = " request rejected, unrecognized client " ,
[ DLM_ABORT ] = " blocked lock request cancelled " ,
[ DLM_CANCEL ] = " conversion request cancelled " ,
[ DLM_IVRESHANDLE ] = " invalid resource handle " ,
[ DLM_DEADLOCK ] = " deadlock recovery refused this request " ,
[ DLM_DENIED_NOASTS ] = " failed to allocate AST " ,
[ DLM_FORWARD ] = " request must wait for primary's response " ,
[ DLM_TIMEOUT ] = " timeout value for lock has expired " ,
[ DLM_IVGROUPID ] = " invalid group specification " ,
[ DLM_VERS_CONFLICT ] = " version conflicts prevent request handling " ,
[ DLM_BAD_DEVICE_PATH ] = " Locks device does not exist or path wrong " ,
[ DLM_NO_DEVICE_PERMISSION ] = " Client has insufficient perms for device " ,
[ DLM_NO_CONTROL_DEVICE ] = " Cannot set options on opened device " ,
[ DLM_RECOVERING ] = " lock resource being recovered " ,
[ DLM_MIGRATING ] = " lock resource being migrated " ,
[ DLM_MAXSTATS ] = " invalid error number " ,
} ;
const char * dlm_errmsg ( enum dlm_status err )
{
if ( err > = DLM_MAXSTATS | | err < 0 )
return dlm_errmsgs [ DLM_MAXSTATS ] ;
return dlm_errmsgs [ err ] ;
}
EXPORT_SYMBOL_GPL ( dlm_errmsg ) ;
const char * dlm_errname ( enum dlm_status err )
{
if ( err > = DLM_MAXSTATS | | err < 0 )
return dlm_errnames [ DLM_MAXSTATS ] ;
return dlm_errnames [ err ] ;
}
EXPORT_SYMBOL_GPL ( dlm_errname ) ;
2008-03-11 01:16:22 +03:00
2008-03-11 01:16:24 +03:00
/* NOTE: This function converts a lockname into a string. It uses knowledge
* of the format of the lockname that should be outside the purview of the dlm .
* We are adding only to make dlm debugging slightly easier .
*
* For more on lockname formats , please refer to dlmglue . c and ocfs2_lockid . h .
*/
2008-04-21 12:49:37 +04:00
static int stringify_lockname ( const char * lockname , int locklen , char * buf ,
int len )
2008-03-11 01:16:24 +03:00
{
int out = 0 ;
__be64 inode_blkno_be ;
# define OCFS2_DENTRY_LOCK_INO_START 18
if ( * lockname = = ' N ' ) {
memcpy ( ( __be64 * ) & inode_blkno_be ,
( char * ) & lockname [ OCFS2_DENTRY_LOCK_INO_START ] ,
sizeof ( __be64 ) ) ;
out + = snprintf ( buf + out , len - out , " %.*s%08x " ,
OCFS2_DENTRY_LOCK_INO_START - 1 , lockname ,
( unsigned int ) be64_to_cpu ( inode_blkno_be ) ) ;
} else
out + = snprintf ( buf + out , len - out , " %.*s " ,
locklen , lockname ) ;
return out ;
}
2008-03-11 01:16:28 +03:00
static int stringify_nodemap ( unsigned long * nodemap , int maxnodes ,
char * buf , int len )
{
int out = 0 ;
int i = - 1 ;
while ( ( i = find_next_bit ( nodemap , maxnodes , i + 1 ) ) < maxnodes )
out + = snprintf ( buf + out , len - out , " %d " , i ) ;
return out ;
}
static int dump_mle ( struct dlm_master_list_entry * mle , char * buf , int len )
{
int out = 0 ;
char * mle_type ;
if ( mle - > type = = DLM_MLE_BLOCK )
mle_type = " BLK " ;
else if ( mle - > type = = DLM_MLE_MASTER )
mle_type = " MAS " ;
else
mle_type = " MIG " ;
2009-02-27 02:00:47 +03:00
out + = stringify_lockname ( mle - > mname , mle - > mnamelen , buf + out , len - out ) ;
2008-03-11 01:16:28 +03:00
out + = snprintf ( buf + out , len - out ,
" \t %3s \t mas=%3u \t new=%3u \t evt=%1d \t use=%1d \t ref=%3d \n " ,
mle_type , mle - > master , mle - > new_master ,
! list_empty ( & mle - > hb_events ) ,
! ! mle - > inuse ,
2016-11-14 19:29:48 +03:00
kref_read ( & mle - > mle_refs ) ) ;
2008-03-11 01:16:28 +03:00
out + = snprintf ( buf + out , len - out , " Maybe= " ) ;
out + = stringify_nodemap ( mle - > maybe_map , O2NM_MAX_NODES ,
buf + out , len - out ) ;
out + = snprintf ( buf + out , len - out , " \n " ) ;
out + = snprintf ( buf + out , len - out , " Vote= " ) ;
out + = stringify_nodemap ( mle - > vote_map , O2NM_MAX_NODES ,
buf + out , len - out ) ;
out + = snprintf ( buf + out , len - out , " \n " ) ;
out + = snprintf ( buf + out , len - out , " Response= " ) ;
out + = stringify_nodemap ( mle - > response_map , O2NM_MAX_NODES ,
buf + out , len - out ) ;
out + = snprintf ( buf + out , len - out , " \n " ) ;
out + = snprintf ( buf + out , len - out , " Node= " ) ;
out + = stringify_nodemap ( mle - > node_map , O2NM_MAX_NODES ,
buf + out , len - out ) ;
out + = snprintf ( buf + out , len - out , " \n " ) ;
out + = snprintf ( buf + out , len - out , " \n " ) ;
return out ;
}
void dlm_print_one_mle ( struct dlm_master_list_entry * mle )
{
char * buf ;
2018-10-27 01:02:52 +03:00
buf = ( char * ) get_zeroed_page ( GFP_ATOMIC ) ;
2008-03-11 01:16:28 +03:00
if ( buf ) {
dump_mle ( mle , buf , PAGE_SIZE - 1 ) ;
free_page ( ( unsigned long ) buf ) ;
}
}
# ifdef CONFIG_DEBUG_FS
2014-06-05 03:06:06 +04:00
static struct dentry * dlm_debugfs_root ;
2008-03-11 01:16:28 +03:00
2008-03-11 01:16:22 +03:00
# define DLM_DEBUGFS_DIR "o2dlm"
2008-03-11 01:16:23 +03:00
# define DLM_DEBUGFS_DLM_STATE "dlm_state"
2008-03-11 01:16:24 +03:00
# define DLM_DEBUGFS_LOCKING_STATE "locking_state"
2008-03-11 01:16:26 +03:00
# define DLM_DEBUGFS_MLE_STATE "mle_state"
2008-03-11 01:16:27 +03:00
# define DLM_DEBUGFS_PURGE_LIST "purge_list"
2008-03-11 01:16:23 +03:00
/* begin - utils funcs */
2010-12-21 03:34:59 +03:00
static int debug_release ( struct inode * inode , struct file * file )
2008-03-11 01:16:23 +03:00
{
2010-12-21 03:34:59 +03:00
free_page ( ( unsigned long ) file - > private_data ) ;
return 0 ;
2008-03-11 01:16:23 +03:00
}
2010-12-21 03:34:59 +03:00
static ssize_t debug_read ( struct file * file , char __user * buf ,
size_t nbytes , loff_t * ppos )
2008-03-11 01:16:23 +03:00
{
2010-12-21 03:34:59 +03:00
return simple_read_from_buffer ( buf , nbytes , ppos , file - > private_data ,
i_size_read ( file - > f_mapping - > host ) ) ;
2008-03-11 01:16:23 +03:00
}
/* end - util funcs */
2008-03-11 01:16:27 +03:00
/* begin - purge list funcs */
2010-12-21 03:34:59 +03:00
static int debug_purgelist_print ( struct dlm_ctxt * dlm , char * buf , int len )
2008-03-11 01:16:27 +03:00
{
struct dlm_lock_resource * res ;
int out = 0 ;
unsigned long total = 0 ;
2010-12-21 03:34:59 +03:00
out + = snprintf ( buf + out , len - out ,
2008-03-11 01:16:27 +03:00
" Dumping Purgelist for Domain: %s \n " , dlm - > name ) ;
spin_lock ( & dlm - > spinlock ) ;
list_for_each_entry ( res , & dlm - > purge_list , purge ) {
+ + total ;
2010-12-21 03:34:59 +03:00
if ( len - out < 100 )
2008-03-11 01:16:27 +03:00
continue ;
spin_lock ( & res - > spinlock ) ;
out + = stringify_lockname ( res - > lockname . name ,
res - > lockname . len ,
2010-12-21 03:34:59 +03:00
buf + out , len - out ) ;
out + = snprintf ( buf + out , len - out , " \t %ld \n " ,
2008-03-11 01:16:27 +03:00
( jiffies - res - > last_used ) / HZ ) ;
spin_unlock ( & res - > spinlock ) ;
}
spin_unlock ( & dlm - > spinlock ) ;
2015-02-11 01:08:51 +03:00
out + = snprintf ( buf + out , len - out , " Total on list: %lu \n " , total ) ;
2008-03-11 01:16:27 +03:00
return out ;
}
static int debug_purgelist_open ( struct inode * inode , struct file * file )
{
struct dlm_ctxt * dlm = inode - > i_private ;
2010-12-21 03:34:59 +03:00
char * buf = NULL ;
2008-03-11 01:16:27 +03:00
2010-12-21 03:34:59 +03:00
buf = ( char * ) get_zeroed_page ( GFP_NOFS ) ;
if ( ! buf )
2008-03-11 01:16:27 +03:00
goto bail ;
2010-12-21 03:34:59 +03:00
i_size_write ( inode , debug_purgelist_print ( dlm , buf , PAGE_SIZE - 1 ) ) ;
2008-03-11 01:16:27 +03:00
2010-12-21 03:34:59 +03:00
file - > private_data = buf ;
2008-03-11 01:16:27 +03:00
return 0 ;
bail :
return - ENOMEM ;
}
2009-10-02 02:43:56 +04:00
static const struct file_operations debug_purgelist_fops = {
2008-03-11 01:16:27 +03:00
. open = debug_purgelist_open ,
2010-12-21 03:34:59 +03:00
. release = debug_release ,
. read = debug_read ,
. llseek = generic_file_llseek ,
2008-03-11 01:16:27 +03:00
} ;
/* end - purge list funcs */
2008-03-11 01:16:26 +03:00
/* begin - debug mle funcs */
2010-12-21 03:34:59 +03:00
static int debug_mle_print ( struct dlm_ctxt * dlm , char * buf , int len )
2008-03-11 01:16:26 +03:00
{
struct dlm_master_list_entry * mle ;
2009-02-27 02:00:41 +03:00
struct hlist_head * bucket ;
int i , out = 0 ;
2010-09-16 04:00:58 +04:00
unsigned long total = 0 , longest = 0 , bucket_count = 0 ;
2008-03-11 01:16:26 +03:00
2010-12-21 03:34:59 +03:00
out + = snprintf ( buf + out , len - out ,
2008-03-11 01:16:26 +03:00
" Dumping MLEs for Domain: %s \n " , dlm - > name ) ;
spin_lock ( & dlm - > master_lock ) ;
2009-02-27 02:00:41 +03:00
for ( i = 0 ; i < DLM_HASH_BUCKETS ; i + + ) {
bucket = dlm_master_hash ( dlm , i ) ;
2013-09-12 01:19:50 +04:00
hlist_for_each_entry ( mle , bucket , master_hash_node ) {
2009-02-27 02:00:41 +03:00
+ + total ;
2010-09-16 04:00:58 +04:00
+ + bucket_count ;
2010-12-21 03:34:59 +03:00
if ( len - out < 200 )
2009-02-27 02:00:41 +03:00
continue ;
2010-12-21 03:34:59 +03:00
out + = dump_mle ( mle , buf + out , len - out ) ;
2009-02-27 02:00:41 +03:00
}
2010-09-16 04:00:58 +04:00
longest = max ( longest , bucket_count ) ;
bucket_count = 0 ;
2008-03-11 01:16:26 +03:00
}
spin_unlock ( & dlm - > master_lock ) ;
2010-12-21 03:34:59 +03:00
out + = snprintf ( buf + out , len - out ,
2015-02-11 01:08:51 +03:00
" Total: %lu, Longest: %lu \n " , total , longest ) ;
2008-03-11 01:16:26 +03:00
return out ;
}
static int debug_mle_open ( struct inode * inode , struct file * file )
{
struct dlm_ctxt * dlm = inode - > i_private ;
2010-12-21 03:34:59 +03:00
char * buf = NULL ;
2008-03-11 01:16:26 +03:00
2010-12-21 03:34:59 +03:00
buf = ( char * ) get_zeroed_page ( GFP_NOFS ) ;
if ( ! buf )
2008-03-11 01:16:26 +03:00
goto bail ;
2010-12-21 03:34:59 +03:00
i_size_write ( inode , debug_mle_print ( dlm , buf , PAGE_SIZE - 1 ) ) ;
2008-03-11 01:16:26 +03:00
2010-12-21 03:34:59 +03:00
file - > private_data = buf ;
2008-03-11 01:16:26 +03:00
return 0 ;
bail :
return - ENOMEM ;
}
2009-10-02 02:43:56 +04:00
static const struct file_operations debug_mle_fops = {
2008-03-11 01:16:26 +03:00
. open = debug_mle_open ,
2010-12-21 03:34:59 +03:00
. release = debug_release ,
. read = debug_read ,
. llseek = generic_file_llseek ,
2008-03-11 01:16:26 +03:00
} ;
/* end - debug mle funcs */
2008-03-11 01:16:24 +03:00
/* begin - debug lockres funcs */
static int dump_lock ( struct dlm_lock * lock , int list_type , char * buf , int len )
{
int out ;
# define DEBUG_LOCK_VERSION 1
spin_lock ( & lock - > spinlock ) ;
out = snprintf ( buf , len , " LOCK:%d,%d,%d,%d,%d,%d:%lld,%d,%d,%d,%d,%d, "
" %d,%d,%d,%d \n " ,
DEBUG_LOCK_VERSION ,
list_type , 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 ) ) ,
! list_empty ( & lock - > ast_list ) ,
! list_empty ( & lock - > bast_list ) ,
lock - > ast_pending , lock - > bast_pending ,
lock - > convert_pending , lock - > lock_pending ,
lock - > cancel_pending , lock - > unlock_pending ,
2016-11-14 19:29:48 +03:00
kref_read ( & lock - > lock_refs ) ) ;
2008-03-11 01:16:24 +03:00
spin_unlock ( & lock - > spinlock ) ;
return out ;
}
static int dump_lockres ( struct dlm_lock_resource * res , char * buf , int len )
{
struct dlm_lock * lock ;
int i ;
int out = 0 ;
out + = snprintf ( buf + out , len - out , " NAME: " ) ;
out + = stringify_lockname ( res - > lockname . name , res - > lockname . len ,
buf + out , len - out ) ;
out + = snprintf ( buf + out , len - out , " \n " ) ;
# define DEBUG_LRES_VERSION 1
out + = snprintf ( buf + out , len - out ,
" LRES:%d,%d,%d,%ld,%d,%d,%d,%d,%d,%d,%d \n " ,
DEBUG_LRES_VERSION ,
res - > owner , res - > state , res - > last_used ,
! list_empty ( & res - > purge ) ,
! list_empty ( & res - > dirty ) ,
! list_empty ( & res - > recovering ) ,
res - > inflight_locks , res - > migration_pending ,
atomic_read ( & res - > asts_reserved ) ,
2016-11-14 19:29:48 +03:00
kref_read ( & res - > refs ) ) ;
2008-03-11 01:16:24 +03:00
/* refmap */
out + = snprintf ( buf + out , len - out , " RMAP: " ) ;
out + = stringify_nodemap ( res - > refmap , O2NM_MAX_NODES ,
buf + out , len - out ) ;
out + = snprintf ( buf + out , len - out , " \n " ) ;
/* lvb */
out + = snprintf ( buf + out , len - out , " LVBX: " ) ;
for ( i = 0 ; i < DLM_LVB_LEN ; i + + )
out + = snprintf ( buf + out , len - out ,
" %02x " , ( unsigned char ) res - > lvb [ i ] ) ;
out + = snprintf ( buf + out , len - out , " \n " ) ;
/* granted */
list_for_each_entry ( lock , & res - > granted , list )
out + = dump_lock ( lock , 0 , buf + out , len - out ) ;
/* converting */
list_for_each_entry ( lock , & res - > converting , list )
out + = dump_lock ( lock , 1 , buf + out , len - out ) ;
/* blocked */
list_for_each_entry ( lock , & res - > blocked , list )
out + = dump_lock ( lock , 2 , buf + out , len - out ) ;
out + = snprintf ( buf + out , len - out , " \n " ) ;
return out ;
}
static void * lockres_seq_start ( struct seq_file * m , loff_t * pos )
{
struct debug_lockres * dl = m - > private ;
struct dlm_ctxt * dlm = dl - > dl_ctxt ;
2008-12-17 02:49:22 +03:00
struct dlm_lock_resource * oldres = dl - > dl_res ;
2008-03-11 01:16:24 +03:00
struct dlm_lock_resource * res = NULL ;
2008-12-17 02:49:22 +03:00
struct list_head * track_list ;
2008-03-11 01:16:24 +03:00
2008-12-17 02:49:22 +03:00
spin_lock ( & dlm - > track_lock ) ;
if ( oldres )
track_list = & oldres - > tracking ;
2010-09-10 06:16:33 +04:00
else {
2008-12-17 02:49:22 +03:00
track_list = & dlm - > tracking_list ;
2010-09-10 06:16:33 +04:00
if ( list_empty ( track_list ) ) {
dl = NULL ;
spin_unlock ( & dlm - > track_lock ) ;
goto bail ;
}
}
2008-03-11 01:16:24 +03:00
2008-12-17 02:49:22 +03:00
list_for_each_entry ( res , track_list , tracking ) {
if ( & res - > tracking = = & dlm - > tracking_list )
res = NULL ;
else
2008-03-11 01:16:24 +03:00
dlm_lockres_get ( res ) ;
2008-12-17 02:49:22 +03:00
break ;
2008-03-11 01:16:24 +03:00
}
2008-12-17 02:49:22 +03:00
spin_unlock ( & dlm - > track_lock ) ;
2008-03-11 01:16:24 +03:00
2008-12-17 02:49:22 +03:00
if ( oldres )
dlm_lockres_put ( oldres ) ;
2008-03-11 01:16:24 +03:00
2008-12-17 02:49:22 +03:00
dl - > dl_res = res ;
if ( res ) {
spin_lock ( & res - > spinlock ) ;
dump_lockres ( res , dl - > dl_buf , dl - > dl_len - 1 ) ;
spin_unlock ( & res - > spinlock ) ;
} else
dl = NULL ;
2008-03-11 01:16:24 +03:00
2010-09-10 06:16:33 +04:00
bail :
2008-12-17 02:49:22 +03:00
/* passed to seq_show */
2008-03-11 01:16:24 +03:00
return dl ;
}
static void lockres_seq_stop ( struct seq_file * m , void * v )
{
}
static void * lockres_seq_next ( struct seq_file * m , void * v , loff_t * pos )
{
return NULL ;
}
static int lockres_seq_show ( struct seq_file * s , void * v )
{
struct debug_lockres * dl = ( struct debug_lockres * ) v ;
seq_printf ( s , " %s " , dl - > dl_buf ) ;
return 0 ;
}
2009-09-23 03:43:43 +04:00
static const struct seq_operations debug_lockres_ops = {
2008-03-11 01:16:24 +03:00
. start = lockres_seq_start ,
. stop = lockres_seq_stop ,
. next = lockres_seq_next ,
. show = lockres_seq_show ,
} ;
static int debug_lockres_open ( struct inode * inode , struct file * file )
{
struct dlm_ctxt * dlm = inode - > i_private ;
2014-10-10 02:25:05 +04:00
struct debug_lockres * dl ;
void * buf ;
2008-03-11 01:16:24 +03:00
2014-10-10 02:25:05 +04:00
buf = kmalloc ( PAGE_SIZE , GFP_KERNEL ) ;
if ( ! buf )
2008-03-11 01:16:24 +03:00
goto bail ;
2014-10-10 02:25:05 +04:00
dl = __seq_open_private ( file , & debug_lockres_ops , sizeof ( * dl ) ) ;
if ( ! dl )
goto bailfree ;
2008-03-11 01:16:24 +03:00
2014-10-10 02:25:05 +04:00
dl - > dl_len = PAGE_SIZE ;
dl - > dl_buf = buf ;
2008-03-11 01:16:24 +03:00
dlm_grab ( dlm ) ;
dl - > dl_ctxt = dlm ;
return 0 ;
2014-10-10 02:25:05 +04:00
bailfree :
kfree ( buf ) ;
2008-03-11 01:16:24 +03:00
bail :
2014-10-10 02:25:05 +04:00
mlog_errno ( - ENOMEM ) ;
return - ENOMEM ;
2008-03-11 01:16:24 +03:00
}
static int debug_lockres_release ( struct inode * inode , struct file * file )
{
2010-07-13 00:50:19 +04:00
struct seq_file * seq = file - > private_data ;
2008-03-11 01:16:24 +03:00
struct debug_lockres * dl = ( struct debug_lockres * ) seq - > private ;
if ( dl - > dl_res )
dlm_lockres_put ( dl - > dl_res ) ;
dlm_put ( dl - > dl_ctxt ) ;
kfree ( dl - > dl_buf ) ;
return seq_release_private ( inode , file ) ;
}
2009-10-02 02:43:56 +04:00
static const struct file_operations debug_lockres_fops = {
2008-03-11 01:16:24 +03:00
. open = debug_lockres_open ,
. release = debug_lockres_release ,
. read = seq_read ,
. llseek = seq_lseek ,
} ;
/* end - debug lockres funcs */
2008-03-11 01:16:23 +03:00
/* begin - debug state funcs */
2010-12-21 03:34:59 +03:00
static int debug_state_print ( struct dlm_ctxt * dlm , char * buf , int len )
2008-03-11 01:16:23 +03:00
{
int out = 0 ;
struct dlm_reco_node_data * node ;
char * state ;
2009-02-27 02:00:46 +03:00
int cur_mles = 0 , tot_mles = 0 ;
int i ;
2008-03-11 01:16:23 +03:00
spin_lock ( & dlm - > spinlock ) ;
switch ( dlm - > dlm_state ) {
case DLM_CTXT_NEW :
state = " NEW " ; break ;
case DLM_CTXT_JOINED :
state = " JOINED " ; break ;
case DLM_CTXT_IN_SHUTDOWN :
state = " SHUTDOWN " ; break ;
case DLM_CTXT_LEAVING :
state = " LEAVING " ; break ;
default :
state = " UNKNOWN " ; break ;
}
/* Domain: xxxxxxxxxx Key: 0xdfbac769 */
2010-12-21 03:34:59 +03:00
out + = snprintf ( buf + out , len - out ,
2010-10-07 04:55:34 +04:00
" Domain: %s Key: 0x%08x Protocol: %d.%d \n " ,
dlm - > name , dlm - > key , dlm - > dlm_locking_proto . pv_major ,
dlm - > dlm_locking_proto . pv_minor ) ;
2008-03-11 01:16:23 +03:00
/* Thread Pid: xxx Node: xxx State: xxxxx */
2010-12-21 03:34:59 +03:00
out + = snprintf ( buf + out , len - out ,
2008-03-11 01:16:23 +03:00
" Thread Pid: %d Node: %d State: %s \n " ,
2010-12-21 03:35:00 +03:00
task_pid_nr ( dlm - > dlm_thread_task ) , dlm - > node_num , state ) ;
2008-03-11 01:16:23 +03:00
/* Number of Joins: xxx Joining Node: xxx */
2010-12-21 03:34:59 +03:00
out + = snprintf ( buf + out , len - out ,
2008-03-11 01:16:23 +03:00
" Number of Joins: %d Joining Node: %d \n " ,
dlm - > num_joins , dlm - > joining_node ) ;
/* Domain Map: xx xx xx */
2010-12-21 03:34:59 +03:00
out + = snprintf ( buf + out , len - out , " Domain Map: " ) ;
2008-03-11 01:16:23 +03:00
out + = stringify_nodemap ( dlm - > domain_map , O2NM_MAX_NODES ,
2010-12-21 03:34:59 +03:00
buf + out , len - out ) ;
out + = snprintf ( buf + out , len - out , " \n " ) ;
2008-03-11 01:16:23 +03:00
2011-05-20 01:34:11 +04:00
/* Exit Domain Map: xx xx xx */
out + = snprintf ( buf + out , len - out , " Exit Domain Map: " ) ;
out + = stringify_nodemap ( dlm - > exit_domain_map , O2NM_MAX_NODES ,
buf + out , len - out ) ;
out + = snprintf ( buf + out , len - out , " \n " ) ;
2008-03-11 01:16:23 +03:00
/* Live Map: xx xx xx */
2010-12-21 03:34:59 +03:00
out + = snprintf ( buf + out , len - out , " Live Map: " ) ;
2008-03-11 01:16:23 +03:00
out + = stringify_nodemap ( dlm - > live_nodes_map , O2NM_MAX_NODES ,
2010-12-21 03:34:59 +03:00
buf + out , len - out ) ;
out + = snprintf ( buf + out , len - out , " \n " ) ;
2008-03-11 01:16:23 +03:00
2009-02-27 02:00:46 +03:00
/* Lock Resources: xxx (xxx) */
2010-12-21 03:34:59 +03:00
out + = snprintf ( buf + out , len - out ,
2009-02-27 02:00:46 +03:00
" Lock Resources: %d (%d) \n " ,
atomic_read ( & dlm - > res_cur_count ) ,
atomic_read ( & dlm - > res_tot_count ) ) ;
for ( i = 0 ; i < DLM_MLE_NUM_TYPES ; + + i )
tot_mles + = atomic_read ( & dlm - > mle_tot_count [ i ] ) ;
for ( i = 0 ; i < DLM_MLE_NUM_TYPES ; + + i )
cur_mles + = atomic_read ( & dlm - > mle_cur_count [ i ] ) ;
/* MLEs: xxx (xxx) */
2010-12-21 03:34:59 +03:00
out + = snprintf ( buf + out , len - out ,
2009-02-27 02:00:46 +03:00
" MLEs: %d (%d) \n " , cur_mles , tot_mles ) ;
/* Blocking: xxx (xxx) */
2010-12-21 03:34:59 +03:00
out + = snprintf ( buf + out , len - out ,
2009-02-27 02:00:46 +03:00
" Blocking: %d (%d) \n " ,
atomic_read ( & dlm - > mle_cur_count [ DLM_MLE_BLOCK ] ) ,
atomic_read ( & dlm - > mle_tot_count [ DLM_MLE_BLOCK ] ) ) ;
/* Mastery: xxx (xxx) */
2010-12-21 03:34:59 +03:00
out + = snprintf ( buf + out , len - out ,
2009-02-27 02:00:46 +03:00
" Mastery: %d (%d) \n " ,
atomic_read ( & dlm - > mle_cur_count [ DLM_MLE_MASTER ] ) ,
atomic_read ( & dlm - > mle_tot_count [ DLM_MLE_MASTER ] ) ) ;
/* Migration: xxx (xxx) */
2010-12-21 03:34:59 +03:00
out + = snprintf ( buf + out , len - out ,
2009-02-27 02:00:46 +03:00
" Migration: %d (%d) \n " ,
atomic_read ( & dlm - > mle_cur_count [ DLM_MLE_MIGRATION ] ) ,
atomic_read ( & dlm - > mle_tot_count [ DLM_MLE_MIGRATION ] ) ) ;
2008-03-11 01:16:23 +03:00
/* Lists: Dirty=Empty Purge=InUse PendingASTs=Empty ... */
2010-12-21 03:34:59 +03:00
out + = snprintf ( buf + out , len - out ,
2008-03-11 01:16:23 +03:00
" Lists: Dirty=%s Purge=%s PendingASTs=%s "
2009-02-27 02:00:41 +03:00
" PendingBASTs=%s \n " ,
2008-03-11 01:16:23 +03:00
( list_empty ( & dlm - > dirty_list ) ? " Empty " : " InUse " ) ,
( list_empty ( & dlm - > purge_list ) ? " Empty " : " InUse " ) ,
( list_empty ( & dlm - > pending_asts ) ? " Empty " : " InUse " ) ,
2009-02-27 02:00:41 +03:00
( list_empty ( & dlm - > pending_basts ) ? " Empty " : " InUse " ) ) ;
2008-03-11 01:16:23 +03:00
/* Purge Count: xxx Refs: xxx */
2010-12-21 03:34:59 +03:00
out + = snprintf ( buf + out , len - out ,
2008-03-11 01:16:23 +03:00
" Purge Count: %d Refs: %d \n " , dlm - > purge_count ,
2016-11-14 19:29:48 +03:00
kref_read ( & dlm - > dlm_refs ) ) ;
2008-03-11 01:16:23 +03:00
/* Dead Node: xxx */
2010-12-21 03:34:59 +03:00
out + = snprintf ( buf + out , len - out ,
2008-03-11 01:16:23 +03:00
" Dead Node: %d \n " , dlm - > reco . dead_node ) ;
/* What about DLM_RECO_STATE_FINALIZE? */
if ( dlm - > reco . state = = DLM_RECO_STATE_ACTIVE )
state = " ACTIVE " ;
else
state = " INACTIVE " ;
/* Recovery Pid: xxxx Master: xxx State: xxxx */
2010-12-21 03:34:59 +03:00
out + = snprintf ( buf + out , len - out ,
2008-03-11 01:16:23 +03:00
" Recovery Pid: %d Master: %d State: %s \n " ,
2010-12-21 03:35:00 +03:00
task_pid_nr ( dlm - > dlm_reco_thread_task ) ,
2008-03-11 01:16:23 +03:00
dlm - > reco . new_master , state ) ;
/* Recovery Map: xx xx */
2010-12-21 03:34:59 +03:00
out + = snprintf ( buf + out , len - out , " Recovery Map: " ) ;
2008-03-11 01:16:23 +03:00
out + = stringify_nodemap ( dlm - > recovery_map , O2NM_MAX_NODES ,
2010-12-21 03:34:59 +03:00
buf + out , len - out ) ;
out + = snprintf ( buf + out , len - out , " \n " ) ;
2008-03-11 01:16:23 +03:00
/* Recovery Node State: */
2010-12-21 03:34:59 +03:00
out + = snprintf ( buf + out , len - out , " Recovery Node State: \n " ) ;
2008-03-11 01:16:23 +03:00
list_for_each_entry ( node , & dlm - > reco . node_data , list ) {
switch ( node - > state ) {
case DLM_RECO_NODE_DATA_INIT :
state = " INIT " ;
break ;
case DLM_RECO_NODE_DATA_REQUESTING :
state = " REQUESTING " ;
break ;
case DLM_RECO_NODE_DATA_DEAD :
state = " DEAD " ;
break ;
case DLM_RECO_NODE_DATA_RECEIVING :
state = " RECEIVING " ;
break ;
case DLM_RECO_NODE_DATA_REQUESTED :
state = " REQUESTED " ;
break ;
case DLM_RECO_NODE_DATA_DONE :
state = " DONE " ;
break ;
case DLM_RECO_NODE_DATA_FINALIZE_SENT :
state = " FINALIZE-SENT " ;
break ;
default :
state = " BAD " ;
break ;
}
2010-12-21 03:34:59 +03:00
out + = snprintf ( buf + out , len - out , " \t %u - %s \n " ,
2008-03-11 01:16:23 +03:00
node - > node_num , state ) ;
}
spin_unlock ( & dlm - > spinlock ) ;
return out ;
}
static int debug_state_open ( struct inode * inode , struct file * file )
{
struct dlm_ctxt * dlm = inode - > i_private ;
2010-12-21 03:34:59 +03:00
char * buf = NULL ;
2008-03-11 01:16:23 +03:00
2010-12-21 03:34:59 +03:00
buf = ( char * ) get_zeroed_page ( GFP_NOFS ) ;
if ( ! buf )
2008-03-11 01:16:23 +03:00
goto bail ;
2010-12-21 03:34:59 +03:00
i_size_write ( inode , debug_state_print ( dlm , buf , PAGE_SIZE - 1 ) ) ;
2008-03-11 01:16:23 +03:00
2010-12-21 03:34:59 +03:00
file - > private_data = buf ;
2008-03-11 01:16:23 +03:00
return 0 ;
bail :
return - ENOMEM ;
}
2009-10-02 02:43:56 +04:00
static const struct file_operations debug_state_fops = {
2008-03-11 01:16:23 +03:00
. open = debug_state_open ,
2010-12-21 03:34:59 +03:00
. release = debug_release ,
. read = debug_read ,
. llseek = generic_file_llseek ,
2008-03-11 01:16:23 +03:00
} ;
/* end - debug state funcs */
/* files in subroot */
2019-07-12 06:53:12 +03:00
void dlm_debug_init ( struct dlm_ctxt * dlm )
2008-03-11 01:16:23 +03:00
{
struct dlm_debug_ctxt * dc = dlm - > dlm_debug_ctxt ;
/* for dumping dlm_ctxt */
dc - > debug_state_dentry = debugfs_create_file ( DLM_DEBUGFS_DLM_STATE ,
S_IFREG | S_IRUSR ,
dlm - > dlm_debugfs_subroot ,
dlm , & debug_state_fops ) ;
2008-03-11 01:16:24 +03:00
/* for dumping lockres */
dc - > debug_lockres_dentry =
debugfs_create_file ( DLM_DEBUGFS_LOCKING_STATE ,
S_IFREG | S_IRUSR ,
dlm - > dlm_debugfs_subroot ,
dlm , & debug_lockres_fops ) ;
2008-03-11 01:16:26 +03:00
/* for dumping mles */
dc - > debug_mle_dentry = debugfs_create_file ( DLM_DEBUGFS_MLE_STATE ,
S_IFREG | S_IRUSR ,
dlm - > dlm_debugfs_subroot ,
dlm , & debug_mle_fops ) ;
2008-03-11 01:16:27 +03:00
/* for dumping lockres on the purge list */
dc - > debug_purgelist_dentry =
debugfs_create_file ( DLM_DEBUGFS_PURGE_LIST ,
S_IFREG | S_IRUSR ,
dlm - > dlm_debugfs_subroot ,
dlm , & debug_purgelist_fops ) ;
2008-03-11 01:16:23 +03:00
}
void dlm_debug_shutdown ( struct dlm_ctxt * dlm )
{
struct dlm_debug_ctxt * dc = dlm - > dlm_debug_ctxt ;
if ( dc ) {
2010-12-21 03:35:00 +03:00
debugfs_remove ( dc - > debug_purgelist_dentry ) ;
debugfs_remove ( dc - > debug_mle_dentry ) ;
debugfs_remove ( dc - > debug_lockres_dentry ) ;
debugfs_remove ( dc - > debug_state_dentry ) ;
2016-07-27 01:21:38 +03:00
kfree ( dc ) ;
dc = NULL ;
2008-03-11 01:16:23 +03:00
}
}
2008-03-11 01:16:22 +03:00
/* subroot - domain dir */
int dlm_create_debugfs_subroot ( struct dlm_ctxt * dlm )
{
2008-03-11 01:16:23 +03:00
dlm - > dlm_debug_ctxt = kzalloc ( sizeof ( struct dlm_debug_ctxt ) ,
GFP_KERNEL ) ;
if ( ! dlm - > dlm_debug_ctxt ) {
mlog_errno ( - ENOMEM ) ;
2019-07-12 06:53:12 +03:00
return - ENOMEM ;
2008-03-11 01:16:23 +03:00
}
2019-07-12 06:53:12 +03:00
dlm - > dlm_debugfs_subroot = debugfs_create_dir ( dlm - > name ,
dlm_debugfs_root ) ;
2008-03-11 01:16:22 +03:00
return 0 ;
}
void dlm_destroy_debugfs_subroot ( struct dlm_ctxt * dlm )
{
2010-12-21 03:35:00 +03:00
debugfs_remove ( dlm - > dlm_debugfs_subroot ) ;
2008-03-11 01:16:22 +03:00
}
/* debugfs root */
2019-07-12 06:53:12 +03:00
void dlm_create_debugfs_root ( void )
2008-03-11 01:16:22 +03:00
{
dlm_debugfs_root = debugfs_create_dir ( DLM_DEBUGFS_DIR , NULL ) ;
}
void dlm_destroy_debugfs_root ( void )
{
2010-12-21 03:35:00 +03:00
debugfs_remove ( dlm_debugfs_root ) ;
2008-03-11 01:16:22 +03:00
}
# endif /* CONFIG_DEBUG_FS */