2005-04-17 02:20:36 +04:00
/*
* fs / cifs_debug . c
*
2005-04-29 09:41:07 +04:00
* Copyright ( C ) International Business Machines Corp . , 2000 , 2005
2005-04-17 02:20:36 +04:00
*
* Modified by Steve French ( sfrench @ us . ibm . com )
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
2007-06-06 00:35:06 +04:00
* the Free Software Foundation ; either version 2 of the License , or
2005-04-17 02:20:36 +04:00
* ( at your option ) any later version .
2007-06-06 00:35:06 +04:00
*
2005-04-17 02:20:36 +04:00
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See
* the GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
2007-06-06 00:35:06 +04:00
* along with this program ; if not , write to the Free Software
2005-04-17 02:20:36 +04:00
* Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
*/
# include <linux/fs.h>
# include <linux/string.h>
# include <linux/ctype.h>
# include <linux/module.h>
# include <linux/proc_fs.h>
2016-12-24 22:46:01 +03:00
# include <linux/uaccess.h>
2005-04-17 02:20:36 +04:00
# include "cifspdu.h"
# include "cifsglob.h"
# include "cifsproto.h"
# include "cifs_debug.h"
2005-04-29 09:41:06 +04:00
# include "cifsfs.h"
2017-11-07 11:54:58 +03:00
# ifdef CONFIG_CIFS_SMB_DIRECT
# include "smbdirect.h"
# endif
2005-04-17 02:20:36 +04:00
void
cifs_dump_mem ( char * label , void * data , int length )
{
2014-08-27 17:49:44 +04:00
pr_debug ( " %s: dump of %d bytes of data at 0x%p \n " , label , length , data ) ;
2014-08-27 17:49:43 +04:00
print_hex_dump ( KERN_DEBUG , " " , DUMP_PREFIX_OFFSET , 16 , 4 ,
data , length , true ) ;
2005-04-17 02:20:36 +04:00
}
2012-03-23 22:28:02 +04:00
void cifs_dump_detail ( void * buf )
2006-06-01 02:40:51 +04:00
{
2012-05-17 13:25:35 +04:00
# ifdef CONFIG_CIFS_DEBUG2
2012-03-23 22:28:02 +04:00
struct smb_hdr * smb = ( struct smb_hdr * ) buf ;
2013-05-05 07:12:25 +04:00
cifs_dbg ( VFS , " Cmd: %d Err: 0x%x Flags: 0x%x Flgs2: 0x%x Mid: %d Pid: %d \n " ,
smb - > Command , smb - > Status . CifsError ,
smb - > Flags , smb - > Flags2 , smb - > Mid , smb - > Pid ) ;
cifs_dbg ( VFS , " smb buf %p len %u \n " , smb , smbCalcSize ( smb ) ) ;
2012-05-17 13:25:35 +04:00
# endif /* CONFIG_CIFS_DEBUG2 */
2006-06-01 02:40:51 +04:00
}
2007-06-25 01:15:44 +04:00
void cifs_dump_mids ( struct TCP_Server_Info * server )
2006-06-01 02:40:51 +04:00
{
2012-05-17 13:25:35 +04:00
# ifdef CONFIG_CIFS_DEBUG2
2006-06-01 02:40:51 +04:00
struct list_head * tmp ;
2007-06-25 01:15:44 +04:00
struct mid_q_entry * mid_entry ;
2006-06-01 02:40:51 +04:00
2007-06-06 00:35:06 +04:00
if ( server = = NULL )
2006-06-01 02:40:51 +04:00
return ;
2013-05-05 07:12:25 +04:00
cifs_dbg ( VFS , " Dump pending requests: \n " ) ;
2006-06-01 02:40:51 +04:00
spin_lock ( & GlobalMid_Lock ) ;
list_for_each ( tmp , & server - > pending_mid_q ) {
mid_entry = list_entry ( tmp , struct mid_q_entry , qhead ) ;
2013-05-05 07:12:25 +04:00
cifs_dbg ( VFS , " State: %d Cmd: %d Pid: %d Cbdata: %p Mid %llu \n " ,
mid_entry - > mid_state ,
le16_to_cpu ( mid_entry - > command ) ,
mid_entry - > pid ,
mid_entry - > callback_data ,
mid_entry - > mid ) ;
2006-06-01 02:40:51 +04:00
# ifdef CONFIG_CIFS_STATS2
2013-05-05 07:12:25 +04:00
cifs_dbg ( VFS , " IsLarge: %d buf: %p time rcv: %ld now: %ld \n " ,
mid_entry - > large_buf ,
mid_entry - > resp_buf ,
mid_entry - > when_received ,
jiffies ) ;
2006-06-01 02:40:51 +04:00
# endif /* STATS2 */
2013-05-05 07:12:25 +04:00
cifs_dbg ( VFS , " IsMult: %d IsEnd: %d \n " ,
mid_entry - > multiRsp , mid_entry - > multiEnd ) ;
2008-08-09 01:10:16 +04:00
if ( mid_entry - > resp_buf ) {
cifs_dump_detail ( mid_entry - > resp_buf ) ;
cifs_dump_mem ( " existing buf: " ,
mid_entry - > resp_buf , 62 ) ;
2006-06-01 02:40:51 +04:00
}
}
spin_unlock ( & GlobalMid_Lock ) ;
# endif /* CONFIG_CIFS_DEBUG2 */
2012-05-17 13:25:35 +04:00
}
2006-06-01 02:40:51 +04:00
2005-04-17 02:20:36 +04:00
# ifdef CONFIG_PROC_FS
2018-01-24 15:46:12 +03:00
static void cifs_debug_tcon ( struct seq_file * m , struct cifs_tcon * tcon )
{
__u32 dev_type = le32_to_cpu ( tcon - > fsDevInfo . DeviceType ) ;
seq_printf ( m , " %s Mounts: %d " , tcon - > treeName , tcon - > tc_count ) ;
if ( tcon - > nativeFileSystem )
seq_printf ( m , " Type: %s " , tcon - > nativeFileSystem ) ;
seq_printf ( m , " DevInfo: 0x%x Attributes: 0x%x \n \t PathComponentMax: %d Status: %d " ,
le32_to_cpu ( tcon - > fsDevInfo . DeviceCharacteristics ) ,
le32_to_cpu ( tcon - > fsAttrInfo . Attributes ) ,
le32_to_cpu ( tcon - > fsAttrInfo . MaxPathNameComponentLength ) ,
tcon - > tidStatus ) ;
if ( dev_type = = FILE_DEVICE_DISK )
seq_puts ( m , " type: DISK " ) ;
else if ( dev_type = = FILE_DEVICE_CD_ROM )
seq_puts ( m , " type: CDROM " ) ;
else
seq_printf ( m , " type: %d " , dev_type ) ;
2018-01-31 23:34:37 +03:00
if ( tcon - > seal )
seq_printf ( m , " Encrypted " ) ;
if ( tcon - > unix_ext )
seq_printf ( m , " POSIX Extensions " ) ;
2018-01-24 15:46:12 +03:00
if ( tcon - > ses - > server - > ops - > dump_share_caps )
tcon - > ses - > server - > ops - > dump_share_caps ( m , tcon ) ;
if ( tcon - > need_reconnect )
seq_puts ( m , " \t DISCONNECTED " ) ;
seq_putc ( m , ' \n ' ) ;
}
2008-07-24 06:34:24 +04:00
static int cifs_debug_data_proc_show ( struct seq_file * m , void * v )
2005-04-17 02:20:36 +04:00
{
2008-11-15 19:12:47 +03:00
struct list_head * tmp1 , * tmp2 , * tmp3 ;
2007-06-25 01:15:44 +04:00
struct mid_q_entry * mid_entry ;
2008-11-14 21:53:46 +03:00
struct TCP_Server_Info * server ;
2011-05-27 08:34:02 +04:00
struct cifs_ses * ses ;
struct cifs_tcon * tcon ;
2008-11-15 19:12:47 +03:00
int i , j ;
2005-04-17 02:20:36 +04:00
2008-07-24 06:34:24 +04:00
seq_puts ( m ,
2005-04-17 02:20:36 +04:00
" Display Internal CIFS Data Structures for Debugging \n "
" --------------------------------------------------- \n " ) ;
2008-07-24 06:34:24 +04:00
seq_printf ( m , " CIFS Version %s \n " , CIFS_VERSION ) ;
2011-01-07 19:30:29 +03:00
seq_printf ( m , " Features: " ) ;
2010-07-30 16:55:56 +04:00
# ifdef CONFIG_CIFS_DFS_UPCALL
2011-01-07 19:30:29 +03:00
seq_printf ( m , " dfs " ) ;
2010-07-30 16:55:56 +04:00
# endif
# ifdef CONFIG_CIFS_FSCACHE
2011-01-07 19:30:29 +03:00
seq_printf ( m , " fscache " ) ;
2010-07-30 16:55:56 +04:00
# endif
# ifdef CONFIG_CIFS_WEAK_PW_HASH
2011-01-07 19:30:29 +03:00
seq_printf ( m , " lanman " ) ;
2010-07-30 16:55:56 +04:00
# endif
# ifdef CONFIG_CIFS_POSIX
2011-01-07 19:30:29 +03:00
seq_printf ( m , " posix " ) ;
2010-07-30 16:55:56 +04:00
# endif
# ifdef CONFIG_CIFS_UPCALL
2011-01-07 19:30:29 +03:00
seq_printf ( m , " spnego " ) ;
2010-07-30 16:55:56 +04:00
# endif
# ifdef CONFIG_CIFS_XATTR
2011-01-07 19:30:29 +03:00
seq_printf ( m , " xattr " ) ;
# endif
# ifdef CONFIG_CIFS_ACL
seq_printf ( m , " acl " ) ;
2010-07-30 16:55:56 +04:00
# endif
seq_putc ( m , ' \n ' ) ;
2008-07-24 06:34:24 +04:00
seq_printf ( m , " Active VFS Requests: %d \n " , GlobalTotalActiveXid ) ;
seq_printf ( m , " Servers: " ) ;
2005-04-17 02:20:36 +04:00
i = 0 ;
2010-10-18 21:59:37 +04:00
spin_lock ( & cifs_tcp_ses_lock ) ;
2008-11-15 19:12:47 +03:00
list_for_each ( tmp1 , & cifs_tcp_ses_list ) {
server = list_entry ( tmp1 , struct TCP_Server_Info ,
2008-11-14 21:53:46 +03:00
tcp_ses_list ) ;
2017-11-23 03:38:48 +03:00
# ifdef CONFIG_CIFS_SMB_DIRECT
if ( ! server - > rdma )
goto skip_rdma ;
seq_printf ( m , " \n SMBDirect (in hex) protocol version: %x "
" transport status: %x " ,
server - > smbd_conn - > protocol ,
server - > smbd_conn - > transport_status ) ;
seq_printf ( m , " \n Conn receive_credit_max: %x "
" send_credit_target: %x max_send_size: %x " ,
server - > smbd_conn - > receive_credit_max ,
server - > smbd_conn - > send_credit_target ,
server - > smbd_conn - > max_send_size ) ;
seq_printf ( m , " \n Conn max_fragmented_recv_size: %x "
" max_fragmented_send_size: %x max_receive_size:%x " ,
server - > smbd_conn - > max_fragmented_recv_size ,
server - > smbd_conn - > max_fragmented_send_size ,
server - > smbd_conn - > max_receive_size ) ;
seq_printf ( m , " \n Conn keep_alive_interval: %x "
" max_readwrite_size: %x rdma_readwrite_threshold: %x " ,
server - > smbd_conn - > keep_alive_interval ,
server - > smbd_conn - > max_readwrite_size ,
server - > smbd_conn - > rdma_readwrite_threshold ) ;
seq_printf ( m , " \n Debug count_get_receive_buffer: %x "
" count_put_receive_buffer: %x count_send_empty: %x " ,
server - > smbd_conn - > count_get_receive_buffer ,
server - > smbd_conn - > count_put_receive_buffer ,
server - > smbd_conn - > count_send_empty ) ;
seq_printf ( m , " \n Read Queue count_reassembly_queue: %x "
" count_enqueue_reassembly_queue: %x "
" count_dequeue_reassembly_queue: %x "
" fragment_reassembly_remaining: %x "
" reassembly_data_length: %x "
" reassembly_queue_length: %x " ,
server - > smbd_conn - > count_reassembly_queue ,
server - > smbd_conn - > count_enqueue_reassembly_queue ,
server - > smbd_conn - > count_dequeue_reassembly_queue ,
server - > smbd_conn - > fragment_reassembly_remaining ,
server - > smbd_conn - > reassembly_data_length ,
server - > smbd_conn - > reassembly_queue_length ) ;
seq_printf ( m , " \n Current Credits send_credits: %x "
" receive_credits: %x receive_credit_target: %x " ,
atomic_read ( & server - > smbd_conn - > send_credits ) ,
atomic_read ( & server - > smbd_conn - > receive_credits ) ,
server - > smbd_conn - > receive_credit_target ) ;
seq_printf ( m , " \n Pending send_pending: %x send_payload_pending: "
" %x smbd_send_pending: %x smbd_recv_pending: %x " ,
atomic_read ( & server - > smbd_conn - > send_pending ) ,
atomic_read ( & server - > smbd_conn - > send_payload_pending ) ,
server - > smbd_conn - > smbd_send_pending ,
server - > smbd_conn - > smbd_recv_pending ) ;
seq_printf ( m , " \n Receive buffers count_receive_queue: %x "
" count_empty_packet_queue: %x " ,
server - > smbd_conn - > count_receive_queue ,
server - > smbd_conn - > count_empty_packet_queue ) ;
seq_printf ( m , " \n MR responder_resources: %x "
" max_frmr_depth: %x mr_type: %x " ,
server - > smbd_conn - > responder_resources ,
server - > smbd_conn - > max_frmr_depth ,
server - > smbd_conn - > mr_type ) ;
seq_printf ( m , " \n MR mr_ready_count: %x mr_used_count: %x " ,
atomic_read ( & server - > smbd_conn - > mr_ready_count ) ,
atomic_read ( & server - > smbd_conn - > mr_used_count ) ) ;
skip_rdma :
# endif
2018-01-31 23:34:37 +03:00
seq_printf ( m , " \n Number of credits: %d Dialect 0x%x " ,
server - > credits , server - > dialect ) ;
if ( server - > sign )
seq_printf ( m , " signed " ) ;
2005-04-17 02:20:36 +04:00
i + + ;
2008-11-14 21:53:46 +03:00
list_for_each ( tmp2 , & server - > smb_ses_list ) {
2011-05-27 08:34:02 +04:00
ses = list_entry ( tmp2 , struct cifs_ses ,
2008-11-14 21:53:46 +03:00
smb_ses_list ) ;
if ( ( ses - > serverDomain = = NULL ) | |
( ses - > serverOS = = NULL ) | |
( ses - > serverNOS = = NULL ) ) {
2017-09-21 00:46:49 +03:00
seq_printf ( m , " \n %d) Name: %s Uses: %d Capability: 0x%x \t Session Status: %d \t " ,
i , ses - > serverName , ses - > ses_count ,
ses - > capabilities , ses - > status ) ;
if ( ses - > session_flags & SMB2_SESSION_FLAG_IS_GUEST )
seq_printf ( m , " Guest \t " ) ;
else if ( ses - > session_flags & SMB2_SESSION_FLAG_IS_NULL )
seq_printf ( m , " Anonymous \t " ) ;
2008-11-14 21:53:46 +03:00
} else {
seq_printf ( m ,
2008-11-15 19:12:47 +03:00
" \n %d) Name: %s Domain: %s Uses: %d OS: "
" %s \n \t NOS: %s \t Capability: 0x%x \n \t SMB "
2007-06-06 00:35:06 +04:00
" session status: %d \t " ,
2005-04-29 09:41:07 +04:00
i , ses - > serverName , ses - > serverDomain ,
2008-11-14 21:53:46 +03:00
ses - > ses_count , ses - > serverOS , ses - > serverNOS ,
2007-06-06 00:35:06 +04:00
ses - > capabilities , ses - > status ) ;
2008-11-14 21:53:46 +03:00
}
2017-11-07 11:54:55 +03:00
if ( server - > rdma )
seq_printf ( m , " RDMA \n \t " ) ;
2008-07-24 06:34:24 +04:00
seq_printf ( m , " TCP status: %d \n \t Local Users To "
2008-11-14 21:53:46 +03:00
" Server: %d SecMode: 0x%x Req On Wire: %d " ,
server - > tcpStatus , server - > srv_count ,
2012-02-17 18:09:12 +04:00
server - > sec_mode , in_flight ( server ) ) ;
2005-10-07 20:51:05 +04:00
# ifdef CONFIG_CIFS_STATS2
2008-07-24 06:34:24 +04:00
seq_printf ( m , " In Send: %d In MaxReq Wait: %d " ,
2011-08-09 22:44:44 +04:00
atomic_read ( & server - > in_send ) ,
2008-11-14 21:53:46 +03:00
atomic_read ( & server - > num_waiters ) ) ;
2005-10-07 20:51:05 +04:00
# endif
2008-11-15 19:12:47 +03:00
seq_puts ( m , " \n \t Shares: " ) ;
j = 0 ;
2018-01-24 15:46:12 +03:00
seq_printf ( m , " \n \t %d) IPC: " , j ) ;
if ( ses - > tcon_ipc )
cifs_debug_tcon ( m , ses - > tcon_ipc ) ;
else
seq_puts ( m , " none \n " ) ;
2008-11-15 19:12:47 +03:00
list_for_each ( tmp3 , & ses - > tcon_list ) {
2011-05-27 08:34:02 +04:00
tcon = list_entry ( tmp3 , struct cifs_tcon ,
2008-11-15 19:12:47 +03:00
tcon_list ) ;
+ + j ;
2018-01-24 15:46:12 +03:00
seq_printf ( m , " \n \t %d) " , j ) ;
cifs_debug_tcon ( m , tcon ) ;
2008-11-15 19:12:47 +03:00
}
seq_puts ( m , " \n \t MIDs: \n " ) ;
2005-04-17 02:20:36 +04:00
spin_lock ( & GlobalMid_Lock ) ;
2008-11-14 21:53:46 +03:00
list_for_each ( tmp3 , & server - > pending_mid_q ) {
2008-11-15 19:12:47 +03:00
mid_entry = list_entry ( tmp3 , struct mid_q_entry ,
2005-04-17 02:20:36 +04:00
qhead ) ;
2008-11-15 19:12:47 +03:00
seq_printf ( m , " \t State: %d com: %d pid: "
2012-03-23 22:28:03 +04:00
" %d cbdata: %p mid %llu \n " ,
mid_entry - > mid_state ,
le16_to_cpu ( mid_entry - > command ) ,
mid_entry - > pid ,
mid_entry - > callback_data ,
mid_entry - > mid ) ;
2005-04-17 02:20:36 +04:00
}
2007-06-06 00:35:06 +04:00
spin_unlock ( & GlobalMid_Lock ) ;
2005-04-17 02:20:36 +04:00
}
}
2010-10-18 21:59:37 +04:00
spin_unlock ( & cifs_tcp_ses_lock ) ;
2008-07-24 06:34:24 +04:00
seq_putc ( m , ' \n ' ) ;
2005-04-17 02:20:36 +04:00
/* BB add code to dump additional info such as TCP session info now */
2008-07-24 06:34:24 +04:00
return 0 ;
}
2005-04-17 02:20:36 +04:00
2008-07-24 06:34:24 +04:00
static int cifs_debug_data_proc_open ( struct inode * inode , struct file * file )
{
return single_open ( file , cifs_debug_data_proc_show , NULL ) ;
2005-04-17 02:20:36 +04:00
}
2008-07-24 06:34:24 +04:00
static const struct file_operations cifs_debug_data_proc_fops = {
. open = cifs_debug_data_proc_open ,
. read = seq_read ,
. llseek = seq_lseek ,
. release = single_release ,
} ;
2005-10-12 06:58:06 +04:00
2008-07-24 06:34:24 +04:00
# ifdef CONFIG_CIFS_STATS
static ssize_t cifs_stats_proc_write ( struct file * file ,
const char __user * buffer , size_t count , loff_t * ppos )
2005-10-12 06:58:06 +04:00
{
2014-08-27 17:49:42 +04:00
bool bv ;
2007-06-06 00:35:06 +04:00
int rc ;
2008-11-15 19:12:47 +03:00
struct list_head * tmp1 , * tmp2 , * tmp3 ;
struct TCP_Server_Info * server ;
2011-05-27 08:34:02 +04:00
struct cifs_ses * ses ;
struct cifs_tcon * tcon ;
2005-10-12 06:58:06 +04:00
2016-03-18 00:22:54 +03:00
rc = kstrtobool_from_user ( buffer , count , & bv ) ;
if ( rc = = 0 ) {
2005-12-04 00:58:57 +03:00
# ifdef CONFIG_CIFS_STATS2
atomic_set ( & totBufAllocCount , 0 ) ;
atomic_set ( & totSmBufAllocCount , 0 ) ;
# endif /* CONFIG_CIFS_STATS2 */
2010-10-18 21:59:37 +04:00
spin_lock ( & cifs_tcp_ses_lock ) ;
2008-11-15 19:12:47 +03:00
list_for_each ( tmp1 , & cifs_tcp_ses_list ) {
server = list_entry ( tmp1 , struct TCP_Server_Info ,
tcp_ses_list ) ;
2008-11-17 06:57:13 +03:00
list_for_each ( tmp2 , & server - > smb_ses_list ) {
2011-05-27 08:34:02 +04:00
ses = list_entry ( tmp2 , struct cifs_ses ,
2008-11-17 06:57:13 +03:00
smb_ses_list ) ;
2008-11-15 19:12:47 +03:00
list_for_each ( tmp3 , & ses - > tcon_list ) {
tcon = list_entry ( tmp3 ,
2011-05-27 08:34:02 +04:00
struct cifs_tcon ,
2008-11-15 19:12:47 +03:00
tcon_list ) ;
atomic_set ( & tcon - > num_smbs_sent , 0 ) ;
2012-05-28 14:16:31 +04:00
if ( server - > ops - > clear_stats )
server - > ops - > clear_stats ( tcon ) ;
2008-11-15 19:12:47 +03:00
}
}
2005-10-12 06:58:06 +04:00
}
2010-10-18 21:59:37 +04:00
spin_unlock ( & cifs_tcp_ses_lock ) ;
2016-03-18 00:22:54 +03:00
} else {
return rc ;
2005-10-12 06:58:06 +04:00
}
2007-06-06 00:35:06 +04:00
return count ;
2005-10-12 06:58:06 +04:00
}
2008-07-24 06:34:24 +04:00
static int cifs_stats_proc_show ( struct seq_file * m , void * v )
2005-04-17 02:20:36 +04:00
{
2008-07-24 06:34:24 +04:00
int i ;
2008-11-15 19:12:47 +03:00
struct list_head * tmp1 , * tmp2 , * tmp3 ;
struct TCP_Server_Info * server ;
2011-05-27 08:34:02 +04:00
struct cifs_ses * ses ;
struct cifs_tcon * tcon ;
2005-04-17 02:20:36 +04:00
2008-07-24 06:34:24 +04:00
seq_printf ( m ,
2005-04-17 02:20:36 +04:00
" Resources in use \n CIFS Session: %d \n " ,
sesInfoAllocCount . counter ) ;
2008-07-24 06:34:24 +04:00
seq_printf ( m , " Share (unique mount targets): %d \n " ,
2005-04-17 02:20:36 +04:00
tconInfoAllocCount . counter ) ;
2008-07-24 06:34:24 +04:00
seq_printf ( m , " SMB Request/Response Buffer: %d Pool size: %d \n " ,
2005-04-29 09:41:07 +04:00
bufAllocCount . counter ,
cifs_min_rcv + tcpSesAllocCount . counter ) ;
2008-07-24 06:34:24 +04:00
seq_printf ( m , " SMB Small Req/Resp Buffer: %d Pool size: %d \n " ,
2007-06-06 00:35:06 +04:00
smBufAllocCount . counter , cifs_min_small ) ;
2005-12-04 01:11:37 +03:00
# ifdef CONFIG_CIFS_STATS2
2008-07-24 06:34:24 +04:00
seq_printf ( m , " Total Large %d Small %d Allocations \n " ,
2005-12-04 01:11:37 +03:00
atomic_read ( & totBufAllocCount ) ,
2007-06-06 00:35:06 +04:00
atomic_read ( & totSmBufAllocCount ) ) ;
2005-12-04 01:11:37 +03:00
# endif /* CONFIG_CIFS_STATS2 */
2011-01-11 15:24:02 +03:00
seq_printf ( m , " Operations (MIDs): %d \n " , atomic_read ( & midCount ) ) ;
2008-07-24 06:34:24 +04:00
seq_printf ( m ,
2005-04-17 02:20:36 +04:00
" \n %d session %d share reconnects \n " ,
2007-06-06 00:35:06 +04:00
tcpSesReconnectCount . counter , tconInfoReconnectCount . counter ) ;
2005-04-17 02:20:36 +04:00
2008-07-24 06:34:24 +04:00
seq_printf ( m ,
2005-04-17 02:20:36 +04:00
" Total vfs operations: %d maximum at one time: %d \n " ,
2007-06-06 00:35:06 +04:00
GlobalCurrentXid , GlobalMaxActiveXid ) ;
2005-04-17 02:20:36 +04:00
i = 0 ;
2010-10-18 21:59:37 +04:00
spin_lock ( & cifs_tcp_ses_lock ) ;
2008-11-15 19:12:47 +03:00
list_for_each ( tmp1 , & cifs_tcp_ses_list ) {
server = list_entry ( tmp1 , struct TCP_Server_Info ,
tcp_ses_list ) ;
list_for_each ( tmp2 , & server - > smb_ses_list ) {
2011-05-27 08:34:02 +04:00
ses = list_entry ( tmp2 , struct cifs_ses ,
2008-11-15 19:12:47 +03:00
smb_ses_list ) ;
list_for_each ( tmp3 , & ses - > tcon_list ) {
tcon = list_entry ( tmp3 ,
2011-05-27 08:34:02 +04:00
struct cifs_tcon ,
2008-11-15 19:12:47 +03:00
tcon_list ) ;
i + + ;
seq_printf ( m , " \n %d) %s " , i , tcon - > treeName ) ;
if ( tcon - > need_reconnect )
seq_puts ( m , " \t DISCONNECTED " ) ;
2012-05-28 14:16:31 +04:00
seq_printf ( m , " \n SMBs: %d " ,
atomic_read ( & tcon - > num_smbs_sent ) ) ;
if ( server - > ops - > print_stats )
server - > ops - > print_stats ( m , tcon ) ;
2008-11-15 19:12:47 +03:00
}
}
2005-04-17 02:20:36 +04:00
}
2010-10-18 21:59:37 +04:00
spin_unlock ( & cifs_tcp_ses_lock ) ;
2005-04-17 02:20:36 +04:00
2008-07-24 06:34:24 +04:00
seq_putc ( m , ' \n ' ) ;
return 0 ;
}
2007-06-06 00:35:06 +04:00
2008-07-24 06:34:24 +04:00
static int cifs_stats_proc_open ( struct inode * inode , struct file * file )
{
return single_open ( file , cifs_stats_proc_show , NULL ) ;
2005-04-17 02:20:36 +04:00
}
2008-07-24 06:34:24 +04:00
static const struct file_operations cifs_stats_proc_fops = {
. open = cifs_stats_proc_open ,
. read = seq_read ,
. llseek = seq_lseek ,
. release = single_release ,
. write = cifs_stats_proc_write ,
} ;
2008-02-12 23:32:36 +03:00
# endif /* STATS */
2005-04-17 02:20:36 +04:00
2017-11-07 11:54:58 +03:00
# ifdef CONFIG_CIFS_SMB_DIRECT
# define PROC_FILE_DEFINE(name) \
static ssize_t name # # _write ( struct file * file , const char __user * buffer , \
size_t count , loff_t * ppos ) \
{ \
int rc ; \
rc = kstrtoint_from_user ( buffer , count , 10 , & name ) ; \
if ( rc ) \
return rc ; \
return count ; \
} \
static int name # # _proc_show ( struct seq_file * m , void * v ) \
{ \
seq_printf ( m , " %d \n " , name ) ; \
return 0 ; \
} \
static int name # # _open ( struct inode * inode , struct file * file ) \
{ \
return single_open ( file , name # # _proc_show , NULL ) ; \
} \
\
static const struct file_operations cifs_ # # name # # _proc_fops = { \
. open = name # # _open , \
. read = seq_read , \
. llseek = seq_lseek , \
. release = single_release , \
. write = name # # _write , \
}
PROC_FILE_DEFINE ( rdma_readwrite_threshold ) ;
PROC_FILE_DEFINE ( smbd_max_frmr_depth ) ;
PROC_FILE_DEFINE ( smbd_keep_alive_interval ) ;
PROC_FILE_DEFINE ( smbd_max_receive_size ) ;
PROC_FILE_DEFINE ( smbd_max_fragmented_recv_size ) ;
PROC_FILE_DEFINE ( smbd_max_send_size ) ;
PROC_FILE_DEFINE ( smbd_send_credit_target ) ;
PROC_FILE_DEFINE ( smbd_receive_credit_max ) ;
# endif
2005-04-17 02:20:36 +04:00
static struct proc_dir_entry * proc_fs_cifs ;
2008-07-24 06:34:24 +04:00
static const struct file_operations cifsFYI_proc_fops ;
static const struct file_operations cifs_lookup_cache_proc_fops ;
static const struct file_operations traceSMB_proc_fops ;
static const struct file_operations cifs_security_flags_proc_fops ;
static const struct file_operations cifs_linux_ext_proc_fops ;
2005-04-17 02:20:36 +04:00
void
cifs_proc_init ( void )
{
2008-04-29 12:01:42 +04:00
proc_fs_cifs = proc_mkdir ( " fs/cifs " , NULL ) ;
2005-04-17 02:20:36 +04:00
if ( proc_fs_cifs = = NULL )
return ;
2008-07-24 06:34:24 +04:00
proc_create ( " DebugData " , 0 , proc_fs_cifs , & cifs_debug_data_proc_fops ) ;
2005-04-17 02:20:36 +04:00
# ifdef CONFIG_CIFS_STATS
2008-07-24 06:34:24 +04:00
proc_create ( " Stats " , 0 , proc_fs_cifs , & cifs_stats_proc_fops ) ;
2008-02-12 23:32:36 +03:00
# endif /* STATS */
2008-07-24 06:34:24 +04:00
proc_create ( " cifsFYI " , 0 , proc_fs_cifs , & cifsFYI_proc_fops ) ;
proc_create ( " traceSMB " , 0 , proc_fs_cifs , & traceSMB_proc_fops ) ;
2008-07-24 06:37:45 +04:00
proc_create ( " LinuxExtensionsEnabled " , 0 , proc_fs_cifs ,
& cifs_linux_ext_proc_fops ) ;
proc_create ( " SecurityFlags " , 0 , proc_fs_cifs ,
& cifs_security_flags_proc_fops ) ;
proc_create ( " LookupCacheEnabled " , 0 , proc_fs_cifs ,
& cifs_lookup_cache_proc_fops ) ;
2017-11-07 11:54:58 +03:00
# ifdef CONFIG_CIFS_SMB_DIRECT
proc_create ( " rdma_readwrite_threshold " , 0 , proc_fs_cifs ,
& cifs_rdma_readwrite_threshold_proc_fops ) ;
proc_create ( " smbd_max_frmr_depth " , 0 , proc_fs_cifs ,
& cifs_smbd_max_frmr_depth_proc_fops ) ;
proc_create ( " smbd_keep_alive_interval " , 0 , proc_fs_cifs ,
& cifs_smbd_keep_alive_interval_proc_fops ) ;
proc_create ( " smbd_max_receive_size " , 0 , proc_fs_cifs ,
& cifs_smbd_max_receive_size_proc_fops ) ;
proc_create ( " smbd_max_fragmented_recv_size " , 0 , proc_fs_cifs ,
& cifs_smbd_max_fragmented_recv_size_proc_fops ) ;
proc_create ( " smbd_max_send_size " , 0 , proc_fs_cifs ,
& cifs_smbd_max_send_size_proc_fops ) ;
proc_create ( " smbd_send_credit_target " , 0 , proc_fs_cifs ,
& cifs_smbd_send_credit_target_proc_fops ) ;
proc_create ( " smbd_receive_credit_max " , 0 , proc_fs_cifs ,
& cifs_smbd_receive_credit_max_proc_fops ) ;
# endif
2005-04-17 02:20:36 +04:00
}
void
cifs_proc_clean ( void )
{
if ( proc_fs_cifs = = NULL )
return ;
remove_proc_entry ( " DebugData " , proc_fs_cifs ) ;
remove_proc_entry ( " cifsFYI " , proc_fs_cifs ) ;
remove_proc_entry ( " traceSMB " , proc_fs_cifs ) ;
# ifdef CONFIG_CIFS_STATS
remove_proc_entry ( " Stats " , proc_fs_cifs ) ;
# endif
2007-06-06 00:35:06 +04:00
remove_proc_entry ( " SecurityFlags " , proc_fs_cifs ) ;
remove_proc_entry ( " LinuxExtensionsEnabled " , proc_fs_cifs ) ;
remove_proc_entry ( " LookupCacheEnabled " , proc_fs_cifs ) ;
2017-11-07 11:54:58 +03:00
# ifdef CONFIG_CIFS_SMB_DIRECT
remove_proc_entry ( " rdma_readwrite_threshold " , proc_fs_cifs ) ;
remove_proc_entry ( " smbd_max_frmr_depth " , proc_fs_cifs ) ;
remove_proc_entry ( " smbd_keep_alive_interval " , proc_fs_cifs ) ;
remove_proc_entry ( " smbd_max_receive_size " , proc_fs_cifs ) ;
remove_proc_entry ( " smbd_max_fragmented_recv_size " , proc_fs_cifs ) ;
remove_proc_entry ( " smbd_max_send_size " , proc_fs_cifs ) ;
remove_proc_entry ( " smbd_send_credit_target " , proc_fs_cifs ) ;
remove_proc_entry ( " smbd_receive_credit_max " , proc_fs_cifs ) ;
# endif
2008-04-29 12:01:42 +04:00
remove_proc_entry ( " fs/cifs " , NULL ) ;
2005-04-17 02:20:36 +04:00
}
2008-07-24 06:34:24 +04:00
static int cifsFYI_proc_show ( struct seq_file * m , void * v )
2005-04-17 02:20:36 +04:00
{
2008-07-24 06:34:24 +04:00
seq_printf ( m , " %d \n " , cifsFYI ) ;
return 0 ;
}
2005-04-17 02:20:36 +04:00
2008-07-24 06:34:24 +04:00
static int cifsFYI_proc_open ( struct inode * inode , struct file * file )
{
return single_open ( file , cifsFYI_proc_show , NULL ) ;
2005-04-17 02:20:36 +04:00
}
2008-07-24 06:34:24 +04:00
static ssize_t cifsFYI_proc_write ( struct file * file , const char __user * buffer ,
size_t count , loff_t * ppos )
2005-04-17 02:20:36 +04:00
{
2016-03-18 00:22:54 +03:00
char c [ 2 ] = { ' \0 ' } ;
2014-08-27 17:49:42 +04:00
bool bv ;
2005-04-17 02:20:36 +04:00
int rc ;
2016-03-18 00:22:54 +03:00
rc = get_user ( c [ 0 ] , buffer ) ;
2005-04-17 02:20:36 +04:00
if ( rc )
return rc ;
2016-03-18 00:22:54 +03:00
if ( strtobool ( c , & bv ) = = 0 )
2014-08-27 17:49:42 +04:00
cifsFYI = bv ;
2016-03-18 00:22:54 +03:00
else if ( ( c [ 0 ] > ' 1 ' ) & & ( c [ 0 ] < = ' 9 ' ) )
cifsFYI = ( int ) ( c [ 0 ] - ' 0 ' ) ; /* see cifs_debug.h for meanings */
2005-04-17 02:20:36 +04:00
return count ;
}
2008-07-24 06:34:24 +04:00
static const struct file_operations cifsFYI_proc_fops = {
. open = cifsFYI_proc_open ,
. read = seq_read ,
. llseek = seq_lseek ,
. release = single_release ,
. write = cifsFYI_proc_write ,
} ;
2005-04-17 02:20:36 +04:00
2008-07-24 06:34:24 +04:00
static int cifs_linux_ext_proc_show ( struct seq_file * m , void * v )
{
seq_printf ( m , " %d \n " , linuxExtEnabled ) ;
return 0 ;
}
2005-04-17 02:20:36 +04:00
2008-07-24 06:34:24 +04:00
static int cifs_linux_ext_proc_open ( struct inode * inode , struct file * file )
{
return single_open ( file , cifs_linux_ext_proc_show , NULL ) ;
2005-04-17 02:20:36 +04:00
}
2008-07-24 06:34:24 +04:00
static ssize_t cifs_linux_ext_proc_write ( struct file * file ,
const char __user * buffer , size_t count , loff_t * ppos )
2005-04-17 02:20:36 +04:00
{
2007-06-06 00:35:06 +04:00
int rc ;
2016-03-18 00:22:54 +03:00
rc = kstrtobool_from_user ( buffer , count , & linuxExtEnabled ) ;
2007-06-06 00:35:06 +04:00
if ( rc )
return rc ;
2014-08-27 17:49:42 +04:00
2007-06-06 00:35:06 +04:00
return count ;
2005-04-17 02:20:36 +04:00
}
2008-07-24 06:34:24 +04:00
static const struct file_operations cifs_linux_ext_proc_fops = {
. open = cifs_linux_ext_proc_open ,
. read = seq_read ,
. llseek = seq_lseek ,
. release = single_release ,
. write = cifs_linux_ext_proc_write ,
} ;
2005-04-17 02:20:36 +04:00
2008-07-24 06:34:24 +04:00
static int cifs_lookup_cache_proc_show ( struct seq_file * m , void * v )
2005-04-17 02:20:36 +04:00
{
2008-07-24 06:34:24 +04:00
seq_printf ( m , " %d \n " , lookupCacheEnabled ) ;
return 0 ;
}
2005-04-17 02:20:36 +04:00
2008-07-24 06:34:24 +04:00
static int cifs_lookup_cache_proc_open ( struct inode * inode , struct file * file )
{
return single_open ( file , cifs_lookup_cache_proc_show , NULL ) ;
2005-04-17 02:20:36 +04:00
}
2008-07-24 06:34:24 +04:00
static ssize_t cifs_lookup_cache_proc_write ( struct file * file ,
const char __user * buffer , size_t count , loff_t * ppos )
2005-04-17 02:20:36 +04:00
{
int rc ;
2016-03-18 00:22:54 +03:00
rc = kstrtobool_from_user ( buffer , count , & lookupCacheEnabled ) ;
2005-04-17 02:20:36 +04:00
if ( rc )
return rc ;
2014-08-27 17:49:42 +04:00
2005-04-17 02:20:36 +04:00
return count ;
}
2008-07-24 06:34:24 +04:00
static const struct file_operations cifs_lookup_cache_proc_fops = {
. open = cifs_lookup_cache_proc_open ,
. read = seq_read ,
. llseek = seq_lseek ,
. release = single_release ,
. write = cifs_lookup_cache_proc_write ,
} ;
2005-04-17 02:20:36 +04:00
2008-07-24 06:34:24 +04:00
static int traceSMB_proc_show ( struct seq_file * m , void * v )
{
seq_printf ( m , " %d \n " , traceSMB ) ;
return 0 ;
}
2005-04-17 02:20:36 +04:00
2008-07-24 06:34:24 +04:00
static int traceSMB_proc_open ( struct inode * inode , struct file * file )
{
return single_open ( file , traceSMB_proc_show , NULL ) ;
2005-04-17 02:20:36 +04:00
}
2008-07-24 06:34:24 +04:00
static ssize_t traceSMB_proc_write ( struct file * file , const char __user * buffer ,
size_t count , loff_t * ppos )
2005-04-17 02:20:36 +04:00
{
int rc ;
2016-03-18 00:22:54 +03:00
rc = kstrtobool_from_user ( buffer , count , & traceSMB ) ;
2005-04-17 02:20:36 +04:00
if ( rc )
return rc ;
2014-08-27 17:49:42 +04:00
2005-04-17 02:20:36 +04:00
return count ;
}
2008-07-24 06:34:24 +04:00
static const struct file_operations traceSMB_proc_fops = {
. open = traceSMB_proc_open ,
. read = seq_read ,
. llseek = seq_lseek ,
. release = single_release ,
. write = traceSMB_proc_write ,
} ;
2005-04-17 02:20:36 +04:00
2008-07-24 06:34:24 +04:00
static int cifs_security_flags_proc_show ( struct seq_file * m , void * v )
{
2010-04-24 15:57:45 +04:00
seq_printf ( m , " 0x%x \n " , global_secflags ) ;
2008-07-24 06:34:24 +04:00
return 0 ;
}
2005-04-17 02:20:36 +04:00
2008-07-24 06:34:24 +04:00
static int cifs_security_flags_proc_open ( struct inode * inode , struct file * file )
{
return single_open ( file , cifs_security_flags_proc_show , NULL ) ;
2005-04-17 02:20:36 +04:00
}
2008-07-24 06:34:24 +04:00
2013-05-26 15:01:02 +04:00
/*
* Ensure that if someone sets a MUST flag , that we disable all other MAY
* flags except for the ones corresponding to the given MUST flag . If there are
* multiple MUST flags , then try to prefer more secure ones .
*/
static void
cifs_security_flags_handle_must_flags ( unsigned int * flags )
{
unsigned int signflags = * flags & CIFSSEC_MUST_SIGN ;
if ( ( * flags & CIFSSEC_MUST_KRB5 ) = = CIFSSEC_MUST_KRB5 )
* flags = CIFSSEC_MUST_KRB5 ;
else if ( ( * flags & CIFSSEC_MUST_NTLMSSP ) = = CIFSSEC_MUST_NTLMSSP )
* flags = CIFSSEC_MUST_NTLMSSP ;
else if ( ( * flags & CIFSSEC_MUST_NTLMV2 ) = = CIFSSEC_MUST_NTLMV2 )
* flags = CIFSSEC_MUST_NTLMV2 ;
else if ( ( * flags & CIFSSEC_MUST_NTLM ) = = CIFSSEC_MUST_NTLM )
* flags = CIFSSEC_MUST_NTLM ;
2015-01-22 16:16:34 +03:00
else if ( CIFSSEC_MUST_LANMAN & &
( * flags & CIFSSEC_MUST_LANMAN ) = = CIFSSEC_MUST_LANMAN )
2013-05-26 15:01:02 +04:00
* flags = CIFSSEC_MUST_LANMAN ;
2015-01-22 16:16:34 +03:00
else if ( CIFSSEC_MUST_PLNTXT & &
( * flags & CIFSSEC_MUST_PLNTXT ) = = CIFSSEC_MUST_PLNTXT )
2013-05-26 15:01:02 +04:00
* flags = CIFSSEC_MUST_PLNTXT ;
* flags | = signflags ;
}
2008-07-24 06:34:24 +04:00
static ssize_t cifs_security_flags_proc_write ( struct file * file ,
const char __user * buffer , size_t count , loff_t * ppos )
2005-04-17 02:20:36 +04:00
{
2013-05-26 15:01:01 +04:00
int rc ;
2006-06-03 02:57:13 +04:00
unsigned int flags ;
char flags_string [ 12 ] ;
2014-08-27 17:49:42 +04:00
bool bv ;
2006-06-03 02:57:13 +04:00
2007-06-06 00:35:06 +04:00
if ( ( count < 1 ) | | ( count > 11 ) )
2006-06-01 02:40:51 +04:00
return - EINVAL ;
2005-04-17 02:20:36 +04:00
2006-06-03 02:57:13 +04:00
memset ( flags_string , 0 , 12 ) ;
2006-06-01 02:40:51 +04:00
2007-06-06 00:35:06 +04:00
if ( copy_from_user ( flags_string , buffer , count ) )
2006-06-03 02:57:13 +04:00
return - EFAULT ;
2006-06-01 02:40:51 +04:00
2007-06-06 00:35:06 +04:00
if ( count < 3 ) {
2006-06-03 02:57:13 +04:00
/* single char or single char followed by null */
2016-03-18 00:22:54 +03:00
if ( strtobool ( flags_string , & bv ) = = 0 ) {
2014-08-27 17:49:42 +04:00
global_secflags = bv ? CIFSSEC_MAX : CIFSSEC_DEF ;
2007-10-05 00:05:09 +04:00
return count ;
2016-03-18 00:22:54 +03:00
} else if ( ! isdigit ( flags_string [ 0 ] ) ) {
2013-05-26 15:01:01 +04:00
cifs_dbg ( VFS , " Invalid SecurityFlags: %s \n " ,
flags_string ) ;
2007-10-05 00:05:09 +04:00
return - EINVAL ;
}
2006-06-03 02:57:13 +04:00
}
2013-05-26 15:01:01 +04:00
/* else we have a number */
rc = kstrtouint ( flags_string , 0 , & flags ) ;
if ( rc ) {
cifs_dbg ( VFS , " Invalid SecurityFlags: %s \n " ,
flags_string ) ;
return rc ;
}
2006-06-03 02:57:13 +04:00
2013-05-05 07:12:25 +04:00
cifs_dbg ( FYI , " sec flags 0x%x \n " , flags ) ;
2006-06-03 02:57:13 +04:00
2013-05-26 15:01:01 +04:00
if ( flags = = 0 ) {
cifs_dbg ( VFS , " Invalid SecurityFlags: %s \n " , flags_string ) ;
2006-06-03 02:57:13 +04:00
return - EINVAL ;
}
2005-04-17 02:20:36 +04:00
2007-06-06 00:35:06 +04:00
if ( flags & ~ CIFSSEC_MASK ) {
2013-05-26 15:01:01 +04:00
cifs_dbg ( VFS , " Unsupported security flags: 0x%x \n " ,
2013-05-05 07:12:25 +04:00
flags & ~ CIFSSEC_MASK ) ;
2006-06-03 02:57:13 +04:00
return - EINVAL ;
}
2013-05-26 15:01:01 +04:00
2013-05-26 15:01:02 +04:00
cifs_security_flags_handle_must_flags ( & flags ) ;
2006-06-03 02:57:13 +04:00
/* flags look ok - update the global security flags for cifs module */
2010-04-24 15:57:45 +04:00
global_secflags = flags ;
if ( global_secflags & CIFSSEC_MUST_SIGN ) {
2007-06-28 22:41:42 +04:00
/* requiring signing implies signing is allowed */
2010-04-24 15:57:45 +04:00
global_secflags | = CIFSSEC_MAY_SIGN ;
2013-05-05 07:12:25 +04:00
cifs_dbg ( FYI , " packet signing now required \n " ) ;
2010-04-24 15:57:45 +04:00
} else if ( ( global_secflags & CIFSSEC_MAY_SIGN ) = = 0 ) {
2013-05-05 07:12:25 +04:00
cifs_dbg ( FYI , " packet signing disabled \n " ) ;
2007-06-28 22:41:42 +04:00
}
/* BB should we turn on MAY flags for other MUST options? */
2005-04-17 02:20:36 +04:00
return count ;
}
2008-07-24 06:34:24 +04:00
static const struct file_operations cifs_security_flags_proc_fops = {
. open = cifs_security_flags_proc_open ,
. read = seq_read ,
. llseek = seq_lseek ,
. release = single_release ,
. write = cifs_security_flags_proc_write ,
} ;
2008-02-12 23:32:36 +03:00
# else
2008-02-18 07:03:58 +03:00
inline void cifs_proc_init ( void )
2008-02-12 23:32:36 +03:00
{
}
2008-02-18 07:03:58 +03:00
inline void cifs_proc_clean ( void )
2008-02-12 23:32:36 +03:00
{
}
# endif /* PROC_FS */