2010-04-07 02:14:15 +04:00
# include <linux/ceph/ceph_debug.h>
# include <linux/device.h>
# include <linux/slab.h>
# include <linux/module.h>
# include <linux/ctype.h>
# include <linux/debugfs.h>
# include <linux/seq_file.h>
# include <linux/ceph/libceph.h>
# include <linux/ceph/mon_client.h>
# include <linux/ceph/auth.h>
# include <linux/ceph/debugfs.h>
# ifdef CONFIG_DEBUG_FS
/*
* Implement / sys / kernel / debug / ceph fun
*
* / sys / kernel / debug / ceph / client * - an instance of the ceph client
* . . . / osdmap - current osdmap
* . . . / monmap - current monmap
* . . . / osdc - active osd requests
* . . . / monc - mon client state
2015-03-25 21:07:41 +03:00
* . . . / client_options - libceph - only ( i . e . not rbd or cephfs ) options
2010-04-07 02:14:15 +04:00
* . . . / dentry_lru - dump contents of dentry lru
* . . . / caps - expose cap ( reservation ) stats
* . . . / bdi - symlink to . . / . . / bdi / something
*/
static struct dentry * ceph_debugfs_dir ;
static int monmap_show ( struct seq_file * s , void * p )
{
int i ;
struct ceph_client * client = s - > private ;
if ( client - > monc . monmap = = NULL )
return 0 ;
seq_printf ( s , " epoch %d \n " , client - > monc . monmap - > epoch ) ;
for ( i = 0 ; i < client - > monc . monmap - > num_mon ; i + + ) {
struct ceph_entity_inst * inst =
& client - > monc . monmap - > mon_inst [ i ] ;
seq_printf ( s , " \t %s%lld \t %s \n " ,
ENTITY_NAME ( inst - > name ) ,
ceph_pr_addr ( & inst - > addr . in_addr ) ) ;
}
return 0 ;
}
static int osdmap_show ( struct seq_file * s , void * p )
{
int i ;
struct ceph_client * client = s - > private ;
2016-04-28 17:07:27 +03:00
struct ceph_osd_client * osdc = & client - > osdc ;
struct ceph_osdmap * map = osdc - > osdmap ;
2010-04-07 02:14:15 +04:00
struct rb_node * n ;
2014-03-13 18:36:12 +04:00
if ( map = = NULL )
2010-04-07 02:14:15 +04:00
return 0 ;
2014-03-13 18:36:12 +04:00
2016-04-28 17:07:27 +03:00
down_read ( & osdc - > lock ) ;
2017-04-18 16:21:16 +03:00
seq_printf ( s , " epoch %u barrier %u flags 0x%x \n " , map - > epoch ,
osdc - > epoch_barrier , map - > flags ) ;
2014-03-13 18:36:12 +04:00
for ( n = rb_first ( & map - > pg_pools ) ; n ; n = rb_next ( n ) ) {
2016-04-28 17:07:23 +03:00
struct ceph_pg_pool_info * pi =
2010-04-07 02:14:15 +04:00
rb_entry ( n , struct ceph_pg_pool_info , node ) ;
2014-03-13 18:36:12 +04:00
2016-04-28 17:07:23 +03:00
seq_printf ( s , " pool %lld '%s' type %d size %d min_size %d pg_num %u pg_num_mask %d flags 0x%llx lfor %u read_tier %lld write_tier %lld \n " ,
pi - > id , pi - > name , pi - > type , pi - > size , pi - > min_size ,
pi - > pg_num , pi - > pg_num_mask , pi - > flags ,
pi - > last_force_request_resend , pi - > read_tier ,
pi - > write_tier ) ;
2010-04-07 02:14:15 +04:00
}
2014-03-13 18:36:12 +04:00
for ( i = 0 ; i < map - > max_osd ; i + + ) {
struct ceph_entity_addr * addr = & map - > osd_addr [ i ] ;
int state = map - > osd_state [ i ] ;
2010-04-07 02:14:15 +04:00
char sb [ 64 ] ;
2014-03-21 21:05:30 +04:00
seq_printf ( s , " osd%d \t %s \t %3d%% \t (%s) \t %3d%% \n " ,
2010-04-07 02:14:15 +04:00
i , ceph_pr_addr ( & addr - > in_addr ) ,
2014-03-13 18:36:12 +04:00
( ( map - > osd_weight [ i ] * 100 ) > > 16 ) ,
2014-03-21 21:05:30 +04:00
ceph_osdmap_state_str ( sb , sizeof ( sb ) , state ) ,
( ( ceph_get_primary_affinity ( map , i ) * 100 ) > > 16 ) ) ;
2010-04-07 02:14:15 +04:00
}
2014-03-13 18:36:13 +04:00
for ( n = rb_first ( & map - > pg_temp ) ; n ; n = rb_next ( n ) ) {
struct ceph_pg_mapping * pg =
rb_entry ( n , struct ceph_pg_mapping , node ) ;
seq_printf ( s , " pg_temp %llu.%x [ " , pg - > pgid . pool ,
pg - > pgid . seed ) ;
2014-03-21 21:05:29 +04:00
for ( i = 0 ; i < pg - > pg_temp . len ; i + + )
2014-03-13 18:36:13 +04:00
seq_printf ( s , " %s%d " , ( i = = 0 ? " " : " , " ) ,
2014-03-21 21:05:29 +04:00
pg - > pg_temp . osds [ i ] ) ;
2014-03-13 18:36:13 +04:00
seq_printf ( s , " ] \n " ) ;
}
2014-03-21 21:05:29 +04:00
for ( n = rb_first ( & map - > primary_temp ) ; n ; n = rb_next ( n ) ) {
struct ceph_pg_mapping * pg =
rb_entry ( n , struct ceph_pg_mapping , node ) ;
seq_printf ( s , " primary_temp %llu.%x %d \n " , pg - > pgid . pool ,
pg - > pgid . seed , pg - > primary_temp . osd ) ;
}
2014-03-13 18:36:12 +04:00
2016-04-28 17:07:27 +03:00
up_read ( & osdc - > lock ) ;
2010-04-07 02:14:15 +04:00
return 0 ;
}
static int monc_show ( struct seq_file * s , void * p )
{
struct ceph_client * client = s - > private ;
struct ceph_mon_generic_request * req ;
struct ceph_mon_client * monc = & client - > monc ;
struct rb_node * rp ;
2016-01-19 18:19:06 +03:00
int i ;
2010-04-07 02:14:15 +04:00
mutex_lock ( & monc - > mutex ) ;
2016-01-19 18:19:06 +03:00
for ( i = 0 ; i < ARRAY_SIZE ( monc - > subs ) ; i + + ) {
seq_printf ( s , " have %s %u " , ceph_sub_str [ i ] ,
monc - > subs [ i ] . have ) ;
if ( monc - > subs [ i ] . want )
seq_printf ( s , " want %llu%s " ,
le64_to_cpu ( monc - > subs [ i ] . item . start ) ,
( monc - > subs [ i ] . item . flags &
CEPH_SUBSCRIBE_ONETIME ? " " : " + " ) ) ;
seq_putc ( s , ' \n ' ) ;
}
2016-05-26 01:05:01 +03:00
seq_printf ( s , " fs_cluster_id %d \n " , monc - > fs_cluster_id ) ;
2010-04-07 02:14:15 +04:00
for ( rp = rb_first ( & monc - > generic_request_tree ) ; rp ; rp = rb_next ( rp ) ) {
__u16 op ;
req = rb_entry ( rp , struct ceph_mon_generic_request , node ) ;
op = le16_to_cpu ( req - > request - > hdr . type ) ;
if ( op = = CEPH_MSG_STATFS )
2014-05-12 13:05:47 +04:00
seq_printf ( s , " %llu statfs \n " , req - > tid ) ;
2014-05-13 11:19:26 +04:00
else if ( op = = CEPH_MSG_MON_GET_VERSION )
seq_printf ( s , " %llu mon_get_version " , req - > tid ) ;
2010-04-07 02:14:15 +04:00
else
2014-05-12 13:05:47 +04:00
seq_printf ( s , " %llu unknown \n " , req - > tid ) ;
2010-04-07 02:14:15 +04:00
}
mutex_unlock ( & monc - > mutex ) ;
return 0 ;
}
2017-06-15 17:30:53 +03:00
static void dump_spgid ( struct seq_file * s , const struct ceph_spg * spgid )
{
seq_printf ( s , " %llu.%x " , spgid - > pgid . pool , spgid - > pgid . seed ) ;
if ( spgid - > shard ! = CEPH_SPG_NOSHARD )
seq_printf ( s , " s%d " , spgid - > shard ) ;
}
2016-05-26 01:29:52 +03:00
static void dump_target ( struct seq_file * s , struct ceph_osd_request_target * t )
{
int i ;
2017-06-15 17:30:53 +03:00
seq_printf ( s , " osd%d \t %llu.%x \t " , t - > osd , t - > pgid . pool , t - > pgid . seed ) ;
dump_spgid ( s , & t - > spgid ) ;
seq_puts ( s , " \t [ " ) ;
2016-05-26 01:29:52 +03:00
for ( i = 0 ; i < t - > up . size ; i + + )
seq_printf ( s , " %s%d " , ( ! i ? " " : " , " ) , t - > up . osds [ i ] ) ;
seq_printf ( s , " ]/%d \t [ " , t - > up . primary ) ;
for ( i = 0 ; i < t - > acting . size ; i + + )
seq_printf ( s , " %s%d " , ( ! i ? " " : " , " ) , t - > acting . osds [ i ] ) ;
2017-06-15 17:30:55 +03:00
seq_printf ( s , " ]/%d \t e%u \t " , t - > acting . primary , t - > epoch ) ;
2016-02-14 06:24:31 +03:00
if ( t - > target_oloc . pool_ns ) {
seq_printf ( s , " %*pE/%*pE \t 0x%x " ,
( int ) t - > target_oloc . pool_ns - > len ,
t - > target_oloc . pool_ns - > str ,
t - > target_oid . name_len , t - > target_oid . name , t - > flags ) ;
} else {
seq_printf ( s , " %*pE \t 0x%x " , t - > target_oid . name_len ,
t - > target_oid . name , t - > flags ) ;
}
2016-05-26 01:29:52 +03:00
if ( t - > paused )
seq_puts ( s , " \t P " ) ;
}
static void dump_request ( struct seq_file * s , struct ceph_osd_request * req )
{
int i ;
seq_printf ( s , " %llu \t " , req - > r_tid ) ;
dump_target ( s , & req - > r_t ) ;
2017-04-04 15:39:36 +03:00
seq_printf ( s , " \t %d " , req - > r_attempts ) ;
2016-05-26 01:29:52 +03:00
for ( i = 0 ; i < req - > r_num_ops ; i + + ) {
struct ceph_osd_req_op * op = & req - > r_ops [ i ] ;
seq_printf ( s , " %s%s " , ( i = = 0 ? " \t " : " , " ) ,
ceph_osd_op_name ( op - > op ) ) ;
2016-05-26 02:15:02 +03:00
if ( op - > op = = CEPH_OSD_OP_WATCH )
seq_printf ( s , " -%s " ,
ceph_osd_watch_op_name ( op - > watch . op ) ) ;
2016-05-26 01:29:52 +03:00
}
seq_putc ( s , ' \n ' ) ;
}
2016-04-28 17:07:26 +03:00
static void dump_requests ( struct seq_file * s , struct ceph_osd * osd )
{
struct rb_node * n ;
mutex_lock ( & osd - > lock ) ;
for ( n = rb_first ( & osd - > o_requests ) ; n ; n = rb_next ( n ) ) {
struct ceph_osd_request * req =
rb_entry ( n , struct ceph_osd_request , r_node ) ;
dump_request ( s , req ) ;
}
mutex_unlock ( & osd - > lock ) ;
}
2016-05-26 02:15:02 +03:00
static void dump_linger_request ( struct seq_file * s ,
struct ceph_osd_linger_request * lreq )
{
seq_printf ( s , " %llu \t " , lreq - > linger_id ) ;
dump_target ( s , & lreq - > t ) ;
2016-04-28 17:07:27 +03:00
seq_printf ( s , " \t %u \t %s%s/%d \n " , lreq - > register_gen ,
lreq - > is_watch ? " W " : " N " , lreq - > committed ? " C " : " " ,
lreq - > last_error ) ;
2016-05-26 02:15:02 +03:00
}
static void dump_linger_requests ( struct seq_file * s , struct ceph_osd * osd )
{
struct rb_node * n ;
mutex_lock ( & osd - > lock ) ;
for ( n = rb_first ( & osd - > o_linger_requests ) ; n ; n = rb_next ( n ) ) {
struct ceph_osd_linger_request * lreq =
rb_entry ( n , struct ceph_osd_linger_request , node ) ;
dump_linger_request ( s , lreq ) ;
}
mutex_unlock ( & osd - > lock ) ;
}
2010-04-07 02:14:15 +04:00
static int osdc_show ( struct seq_file * s , void * pp )
{
struct ceph_client * client = s - > private ;
struct ceph_osd_client * osdc = & client - > osdc ;
2016-04-28 17:07:26 +03:00
struct rb_node * n ;
2010-04-07 02:14:15 +04:00
2016-04-28 17:07:26 +03:00
down_read ( & osdc - > lock ) ;
seq_printf ( s , " REQUESTS %d homeless %d \n " ,
atomic_read ( & osdc - > num_requests ) ,
atomic_read ( & osdc - > num_homeless ) ) ;
for ( n = rb_first ( & osdc - > osds ) ; n ; n = rb_next ( n ) ) {
struct ceph_osd * osd = rb_entry ( n , struct ceph_osd , o_node ) ;
2010-04-07 02:14:15 +04:00
2016-04-28 17:07:26 +03:00
dump_requests ( s , osd ) ;
2010-04-07 02:14:15 +04:00
}
2016-04-28 17:07:26 +03:00
dump_requests ( s , & osdc - > homeless_osd ) ;
2016-05-26 02:15:02 +03:00
seq_puts ( s , " LINGER REQUESTS \n " ) ;
for ( n = rb_first ( & osdc - > osds ) ; n ; n = rb_next ( n ) ) {
struct ceph_osd * osd = rb_entry ( n , struct ceph_osd , o_node ) ;
dump_linger_requests ( s , osd ) ;
}
dump_linger_requests ( s , & osdc - > homeless_osd ) ;
2016-04-28 17:07:26 +03:00
up_read ( & osdc - > lock ) ;
2010-04-07 02:14:15 +04:00
return 0 ;
}
2015-03-25 21:07:41 +03:00
static int client_options_show ( struct seq_file * s , void * p )
{
struct ceph_client * client = s - > private ;
int ret ;
ret = ceph_print_client_options ( s , client ) ;
if ( ret )
return ret ;
seq_putc ( s , ' \n ' ) ;
return 0 ;
}
2010-04-07 02:14:15 +04:00
CEPH_DEFINE_SHOW_FUNC ( monmap_show )
CEPH_DEFINE_SHOW_FUNC ( osdmap_show )
CEPH_DEFINE_SHOW_FUNC ( monc_show )
CEPH_DEFINE_SHOW_FUNC ( osdc_show )
2015-03-25 21:07:41 +03:00
CEPH_DEFINE_SHOW_FUNC ( client_options_show )
2010-04-07 02:14:15 +04:00
int ceph_debugfs_init ( void )
{
ceph_debugfs_dir = debugfs_create_dir ( " ceph " , NULL ) ;
if ( ! ceph_debugfs_dir )
return - ENOMEM ;
return 0 ;
}
void ceph_debugfs_cleanup ( void )
{
debugfs_remove ( ceph_debugfs_dir ) ;
}
int ceph_debugfs_client_init ( struct ceph_client * client )
{
int ret = - ENOMEM ;
char name [ 80 ] ;
snprintf ( name , sizeof ( name ) , " %pU.client%lld " , & client - > fsid ,
client - > monc . auth - > global_id ) ;
2012-08-19 23:29:16 +04:00
dout ( " ceph_debugfs_client_init %p %s \n " , client , name ) ;
BUG_ON ( client - > debugfs_dir ) ;
2010-04-07 02:14:15 +04:00
client - > debugfs_dir = debugfs_create_dir ( name , ceph_debugfs_dir ) ;
if ( ! client - > debugfs_dir )
goto out ;
client - > monc . debugfs_file = debugfs_create_file ( " monc " ,
0600 ,
client - > debugfs_dir ,
client ,
& monc_show_fops ) ;
if ( ! client - > monc . debugfs_file )
goto out ;
client - > osdc . debugfs_file = debugfs_create_file ( " osdc " ,
0600 ,
client - > debugfs_dir ,
client ,
& osdc_show_fops ) ;
if ( ! client - > osdc . debugfs_file )
goto out ;
client - > debugfs_monmap = debugfs_create_file ( " monmap " ,
0600 ,
client - > debugfs_dir ,
client ,
& monmap_show_fops ) ;
if ( ! client - > debugfs_monmap )
goto out ;
client - > debugfs_osdmap = debugfs_create_file ( " osdmap " ,
0600 ,
client - > debugfs_dir ,
client ,
& osdmap_show_fops ) ;
if ( ! client - > debugfs_osdmap )
goto out ;
2015-03-25 21:07:41 +03:00
client - > debugfs_options = debugfs_create_file ( " client_options " ,
0600 ,
client - > debugfs_dir ,
client ,
& client_options_show_fops ) ;
if ( ! client - > debugfs_options )
goto out ;
2010-04-07 02:14:15 +04:00
return 0 ;
out :
ceph_debugfs_client_cleanup ( client ) ;
return ret ;
}
void ceph_debugfs_client_cleanup ( struct ceph_client * client )
{
2012-08-19 23:29:16 +04:00
dout ( " ceph_debugfs_client_cleanup %p \n " , client ) ;
2015-03-25 21:07:41 +03:00
debugfs_remove ( client - > debugfs_options ) ;
2010-04-07 02:14:15 +04:00
debugfs_remove ( client - > debugfs_osdmap ) ;
debugfs_remove ( client - > debugfs_monmap ) ;
debugfs_remove ( client - > osdc . debugfs_file ) ;
debugfs_remove ( client - > monc . debugfs_file ) ;
debugfs_remove ( client - > debugfs_dir ) ;
}
# else /* CONFIG_DEBUG_FS */
int ceph_debugfs_init ( void )
{
return 0 ;
}
void ceph_debugfs_cleanup ( void )
{
}
2010-08-13 03:11:25 +04:00
int ceph_debugfs_client_init ( struct ceph_client * client )
2010-04-07 02:14:15 +04:00
{
return 0 ;
}
void ceph_debugfs_client_cleanup ( struct ceph_client * client )
{
}
# endif /* CONFIG_DEBUG_FS */
EXPORT_SYMBOL ( ceph_debugfs_init ) ;
EXPORT_SYMBOL ( ceph_debugfs_cleanup ) ;