Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.13.7.
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 *   fs/cifs_debug.c
   4 *
   5 *   Copyright (C) International Business Machines  Corp., 2000,2005
   6 *
   7 *   Modified by Steve French (sfrench@us.ibm.com)
   8 */
   9#include <linux/fs.h>
  10#include <linux/string.h>
  11#include <linux/ctype.h>
  12#include <linux/module.h>
  13#include <linux/proc_fs.h>
  14#include <linux/uaccess.h>
  15#include "cifspdu.h"
  16#include "cifsglob.h"
  17#include "cifsproto.h"
  18#include "cifs_debug.h"
  19#include "cifsfs.h"
  20#include "fs_context.h"
  21#ifdef CONFIG_CIFS_DFS_UPCALL
  22#include "dfs_cache.h"
  23#endif
  24#ifdef CONFIG_CIFS_SMB_DIRECT
  25#include "smbdirect.h"
  26#endif
  27#include "cifs_swn.h"
  28
  29void
  30cifs_dump_mem(char *label, void *data, int length)
  31{
  32	pr_debug("%s: dump of %d bytes of data at 0x%p\n", label, length, data);
  33	print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 16, 4,
  34		       data, length, true);
  35}
  36
  37void cifs_dump_detail(void *buf, struct TCP_Server_Info *server)
  38{
  39#ifdef CONFIG_CIFS_DEBUG2
  40	struct smb_hdr *smb = (struct smb_hdr *)buf;
  41
  42	cifs_dbg(VFS, "Cmd: %d Err: 0x%x Flags: 0x%x Flgs2: 0x%x Mid: %d Pid: %d\n",
  43		 smb->Command, smb->Status.CifsError,
  44		 smb->Flags, smb->Flags2, smb->Mid, smb->Pid);
  45	cifs_dbg(VFS, "smb buf %p len %u\n", smb,
  46		 server->ops->calc_smb_size(smb, server));
  47#endif /* CONFIG_CIFS_DEBUG2 */
  48}
  49
  50void cifs_dump_mids(struct TCP_Server_Info *server)
  51{
  52#ifdef CONFIG_CIFS_DEBUG2
  53	struct mid_q_entry *mid_entry;
  54
  55	if (server == NULL)
  56		return;
  57
  58	cifs_dbg(VFS, "Dump pending requests:\n");
  59	spin_lock(&GlobalMid_Lock);
  60	list_for_each_entry(mid_entry, &server->pending_mid_q, qhead) {
  61		cifs_dbg(VFS, "State: %d Cmd: %d Pid: %d Cbdata: %p Mid %llu\n",
  62			 mid_entry->mid_state,
  63			 le16_to_cpu(mid_entry->command),
  64			 mid_entry->pid,
  65			 mid_entry->callback_data,
  66			 mid_entry->mid);
  67#ifdef CONFIG_CIFS_STATS2
  68		cifs_dbg(VFS, "IsLarge: %d buf: %p time rcv: %ld now: %ld\n",
  69			 mid_entry->large_buf,
  70			 mid_entry->resp_buf,
  71			 mid_entry->when_received,
  72			 jiffies);
  73#endif /* STATS2 */
  74		cifs_dbg(VFS, "IsMult: %d IsEnd: %d\n",
  75			 mid_entry->multiRsp, mid_entry->multiEnd);
  76		if (mid_entry->resp_buf) {
  77			cifs_dump_detail(mid_entry->resp_buf, server);
  78			cifs_dump_mem("existing buf: ",
  79				mid_entry->resp_buf, 62);
  80		}
  81	}
  82	spin_unlock(&GlobalMid_Lock);
  83#endif /* CONFIG_CIFS_DEBUG2 */
  84}
  85
  86#ifdef CONFIG_PROC_FS
  87static void cifs_debug_tcon(struct seq_file *m, struct cifs_tcon *tcon)
  88{
  89	__u32 dev_type = le32_to_cpu(tcon->fsDevInfo.DeviceType);
  90
  91	seq_printf(m, "%s Mounts: %d ", tcon->treeName, tcon->tc_count);
  92	if (tcon->nativeFileSystem)
  93		seq_printf(m, "Type: %s ", tcon->nativeFileSystem);
  94	seq_printf(m, "DevInfo: 0x%x Attributes: 0x%x\n\tPathComponentMax: %d Status: %d",
  95		   le32_to_cpu(tcon->fsDevInfo.DeviceCharacteristics),
  96		   le32_to_cpu(tcon->fsAttrInfo.Attributes),
  97		   le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength),
  98		   tcon->tidStatus);
  99	if (dev_type == FILE_DEVICE_DISK)
 100		seq_puts(m, " type: DISK ");
 101	else if (dev_type == FILE_DEVICE_CD_ROM)
 102		seq_puts(m, " type: CDROM ");
 103	else
 104		seq_printf(m, " type: %d ", dev_type);
 105
 106	seq_printf(m, "Serial Number: 0x%x", tcon->vol_serial_number);
 107
 108	if ((tcon->seal) ||
 109	    (tcon->ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA) ||
 110	    (tcon->share_flags & SHI1005_FLAGS_ENCRYPT_DATA))
 111		seq_printf(m, " Encrypted");
 112	if (tcon->nocase)
 113		seq_printf(m, " nocase");
 114	if (tcon->unix_ext)
 115		seq_printf(m, " POSIX Extensions");
 116	if (tcon->ses->server->ops->dump_share_caps)
 117		tcon->ses->server->ops->dump_share_caps(m, tcon);
 118	if (tcon->use_witness)
 119		seq_puts(m, " Witness");
 120
 121	if (tcon->need_reconnect)
 122		seq_puts(m, "\tDISCONNECTED ");
 123	seq_putc(m, '\n');
 124}
 125
 126static void
 127cifs_dump_channel(struct seq_file *m, int i, struct cifs_chan *chan)
 128{
 129	struct TCP_Server_Info *server = chan->server;
 130
 131	seq_printf(m, "\n\n\t\tChannel: %d ConnectionId: 0x%llx"
 132		   "\n\t\tNumber of credits: %d Dialect 0x%x"
 133		   "\n\t\tTCP status: %d Instance: %d"
 134		   "\n\t\tLocal Users To Server: %d SecMode: 0x%x Req On Wire: %d"
 135		   "\n\t\tIn Send: %d In MaxReq Wait: %d",
 136		   i+1, server->conn_id,
 137		   server->credits,
 138		   server->dialect,
 139		   server->tcpStatus,
 140		   server->reconnect_instance,
 141		   server->srv_count,
 142		   server->sec_mode,
 143		   in_flight(server),
 144		   atomic_read(&server->in_send),
 145		   atomic_read(&server->num_waiters));
 146}
 147
 148static void
 149cifs_dump_iface(struct seq_file *m, struct cifs_server_iface *iface)
 150{
 151	struct sockaddr_in *ipv4 = (struct sockaddr_in *)&iface->sockaddr;
 152	struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)&iface->sockaddr;
 153
 154	seq_printf(m, "\tSpeed: %zu bps\n", iface->speed);
 155	seq_puts(m, "\t\tCapabilities: ");
 156	if (iface->rdma_capable)
 157		seq_puts(m, "rdma ");
 158	if (iface->rss_capable)
 159		seq_puts(m, "rss ");
 160	seq_putc(m, '\n');
 161	if (iface->sockaddr.ss_family == AF_INET)
 162		seq_printf(m, "\t\tIPv4: %pI4\n", &ipv4->sin_addr);
 163	else if (iface->sockaddr.ss_family == AF_INET6)
 164		seq_printf(m, "\t\tIPv6: %pI6\n", &ipv6->sin6_addr);
 165}
 166
 167static int cifs_debug_files_proc_show(struct seq_file *m, void *v)
 168{
 169	struct list_head *tmp, *tmp1, *tmp2;
 170	struct TCP_Server_Info *server;
 171	struct cifs_ses *ses;
 172	struct cifs_tcon *tcon;
 173	struct cifsFileInfo *cfile;
 174
 175	seq_puts(m, "# Version:1\n");
 176	seq_puts(m, "# Format:\n");
 177	seq_puts(m, "# <tree id> <persistent fid> <flags> <count> <pid> <uid>");
 178#ifdef CONFIG_CIFS_DEBUG2
 179	seq_printf(m, " <filename> <mid>\n");
 180#else
 181	seq_printf(m, " <filename>\n");
 182#endif /* CIFS_DEBUG2 */
 183	spin_lock(&cifs_tcp_ses_lock);
 184	list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
 185		list_for_each(tmp, &server->smb_ses_list) {
 186			ses = list_entry(tmp, struct cifs_ses, smb_ses_list);
 187			list_for_each(tmp1, &ses->tcon_list) {
 188				tcon = list_entry(tmp1, struct cifs_tcon, tcon_list);
 189				spin_lock(&tcon->open_file_lock);
 190				list_for_each(tmp2, &tcon->openFileList) {
 191					cfile = list_entry(tmp2, struct cifsFileInfo,
 192						     tlist);
 193					seq_printf(m,
 194						"0x%x 0x%llx 0x%x %d %d %d %pd",
 195						tcon->tid,
 196						cfile->fid.persistent_fid,
 197						cfile->f_flags,
 198						cfile->count,
 199						cfile->pid,
 200						from_kuid(&init_user_ns, cfile->uid),
 201						cfile->dentry);
 202#ifdef CONFIG_CIFS_DEBUG2
 203					seq_printf(m, " %llu\n", cfile->fid.mid);
 204#else
 205					seq_printf(m, "\n");
 206#endif /* CIFS_DEBUG2 */
 207				}
 208				spin_unlock(&tcon->open_file_lock);
 209			}
 210		}
 211	}
 212	spin_unlock(&cifs_tcp_ses_lock);
 213	seq_putc(m, '\n');
 214	return 0;
 215}
 216
 217static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
 218{
 219	struct list_head *tmp2, *tmp3;
 220	struct mid_q_entry *mid_entry;
 221	struct TCP_Server_Info *server;
 222	struct cifs_ses *ses;
 223	struct cifs_tcon *tcon;
 224	int c, i, j;
 225
 226	seq_puts(m,
 227		    "Display Internal CIFS Data Structures for Debugging\n"
 228		    "---------------------------------------------------\n");
 229	seq_printf(m, "CIFS Version %s\n", CIFS_VERSION);
 230	seq_printf(m, "Features:");
 231#ifdef CONFIG_CIFS_DFS_UPCALL
 232	seq_printf(m, " DFS");
 233#endif
 234#ifdef CONFIG_CIFS_FSCACHE
 235	seq_printf(m, ",FSCACHE");
 236#endif
 237#ifdef CONFIG_CIFS_SMB_DIRECT
 238	seq_printf(m, ",SMB_DIRECT");
 239#endif
 240#ifdef CONFIG_CIFS_STATS2
 241	seq_printf(m, ",STATS2");
 242#else
 243	seq_printf(m, ",STATS");
 244#endif
 245#ifdef CONFIG_CIFS_DEBUG2
 246	seq_printf(m, ",DEBUG2");
 247#elif defined(CONFIG_CIFS_DEBUG)
 248	seq_printf(m, ",DEBUG");
 249#endif
 250#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
 251	seq_printf(m, ",ALLOW_INSECURE_LEGACY");
 252#endif
 253#ifdef CONFIG_CIFS_WEAK_PW_HASH
 254	seq_printf(m, ",WEAK_PW_HASH");
 255#endif
 256#ifdef CONFIG_CIFS_POSIX
 257	seq_printf(m, ",CIFS_POSIX");
 258#endif
 259#ifdef CONFIG_CIFS_UPCALL
 260	seq_printf(m, ",UPCALL(SPNEGO)");
 261#endif
 262#ifdef CONFIG_CIFS_XATTR
 263	seq_printf(m, ",XATTR");
 264#endif
 265	seq_printf(m, ",ACL");
 266#ifdef CONFIG_CIFS_SWN_UPCALL
 267	seq_puts(m, ",WITNESS");
 268#endif
 269	seq_putc(m, '\n');
 270	seq_printf(m, "CIFSMaxBufSize: %d\n", CIFSMaxBufSize);
 271	seq_printf(m, "Active VFS Requests: %d\n", GlobalTotalActiveXid);
 272
 273	seq_printf(m, "\nServers: ");
 274
 275	c = 0;
 276	spin_lock(&cifs_tcp_ses_lock);
 277	list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
 278		if (server->is_channel)
 279			continue;
 280
 281		c++;
 282		seq_printf(m, "\n%d) ConnectionId: 0x%llx ",
 283			c, server->conn_id);
 284
 285		if (server->hostname)
 286			seq_printf(m, "Hostname: %s ", server->hostname);
 287#ifdef CONFIG_CIFS_SMB_DIRECT
 288		if (!server->rdma)
 289			goto skip_rdma;
 290
 291		if (!server->smbd_conn) {
 292			seq_printf(m, "\nSMBDirect transport not available");
 293			goto skip_rdma;
 294		}
 295
 296		seq_printf(m, "\nSMBDirect (in hex) protocol version: %x "
 297			"transport status: %x",
 298			server->smbd_conn->protocol,
 299			server->smbd_conn->transport_status);
 300		seq_printf(m, "\nConn receive_credit_max: %x "
 301			"send_credit_target: %x max_send_size: %x",
 302			server->smbd_conn->receive_credit_max,
 303			server->smbd_conn->send_credit_target,
 304			server->smbd_conn->max_send_size);
 305		seq_printf(m, "\nConn max_fragmented_recv_size: %x "
 306			"max_fragmented_send_size: %x max_receive_size:%x",
 307			server->smbd_conn->max_fragmented_recv_size,
 308			server->smbd_conn->max_fragmented_send_size,
 309			server->smbd_conn->max_receive_size);
 310		seq_printf(m, "\nConn keep_alive_interval: %x "
 311			"max_readwrite_size: %x rdma_readwrite_threshold: %x",
 312			server->smbd_conn->keep_alive_interval,
 313			server->smbd_conn->max_readwrite_size,
 314			server->smbd_conn->rdma_readwrite_threshold);
 315		seq_printf(m, "\nDebug count_get_receive_buffer: %x "
 316			"count_put_receive_buffer: %x count_send_empty: %x",
 317			server->smbd_conn->count_get_receive_buffer,
 318			server->smbd_conn->count_put_receive_buffer,
 319			server->smbd_conn->count_send_empty);
 320		seq_printf(m, "\nRead Queue count_reassembly_queue: %x "
 321			"count_enqueue_reassembly_queue: %x "
 322			"count_dequeue_reassembly_queue: %x "
 323			"fragment_reassembly_remaining: %x "
 324			"reassembly_data_length: %x "
 325			"reassembly_queue_length: %x",
 326			server->smbd_conn->count_reassembly_queue,
 327			server->smbd_conn->count_enqueue_reassembly_queue,
 328			server->smbd_conn->count_dequeue_reassembly_queue,
 329			server->smbd_conn->fragment_reassembly_remaining,
 330			server->smbd_conn->reassembly_data_length,
 331			server->smbd_conn->reassembly_queue_length);
 332		seq_printf(m, "\nCurrent Credits send_credits: %x "
 333			"receive_credits: %x receive_credit_target: %x",
 334			atomic_read(&server->smbd_conn->send_credits),
 335			atomic_read(&server->smbd_conn->receive_credits),
 336			server->smbd_conn->receive_credit_target);
 337		seq_printf(m, "\nPending send_pending: %x ",
 338			atomic_read(&server->smbd_conn->send_pending));
 339		seq_printf(m, "\nReceive buffers count_receive_queue: %x "
 340			"count_empty_packet_queue: %x",
 341			server->smbd_conn->count_receive_queue,
 342			server->smbd_conn->count_empty_packet_queue);
 343		seq_printf(m, "\nMR responder_resources: %x "
 344			"max_frmr_depth: %x mr_type: %x",
 345			server->smbd_conn->responder_resources,
 346			server->smbd_conn->max_frmr_depth,
 347			server->smbd_conn->mr_type);
 348		seq_printf(m, "\nMR mr_ready_count: %x mr_used_count: %x",
 349			atomic_read(&server->smbd_conn->mr_ready_count),
 350			atomic_read(&server->smbd_conn->mr_used_count));
 351skip_rdma:
 352#endif
 353		seq_printf(m, "\nNumber of credits: %d Dialect 0x%x",
 354			server->credits,  server->dialect);
 355		if (server->compress_algorithm == SMB3_COMPRESS_LZNT1)
 356			seq_printf(m, " COMPRESS_LZNT1");
 357		else if (server->compress_algorithm == SMB3_COMPRESS_LZ77)
 358			seq_printf(m, " COMPRESS_LZ77");
 359		else if (server->compress_algorithm == SMB3_COMPRESS_LZ77_HUFF)
 360			seq_printf(m, " COMPRESS_LZ77_HUFF");
 361		if (server->sign)
 362			seq_printf(m, " signed");
 363		if (server->posix_ext_supported)
 364			seq_printf(m, " posix");
 365
 366		if (server->rdma)
 367			seq_printf(m, "\nRDMA ");
 368		seq_printf(m, "\nTCP status: %d Instance: %d"
 369				"\nLocal Users To Server: %d SecMode: 0x%x Req On Wire: %d",
 370				server->tcpStatus,
 371				server->reconnect_instance,
 372				server->srv_count,
 373				server->sec_mode, in_flight(server));
 374
 375		seq_printf(m, "\nIn Send: %d In MaxReq Wait: %d",
 376				atomic_read(&server->in_send),
 377				atomic_read(&server->num_waiters));
 378
 379		seq_printf(m, "\n\n\tSessions: ");
 380		i = 0;
 381		list_for_each(tmp2, &server->smb_ses_list) {
 382			ses = list_entry(tmp2, struct cifs_ses,
 383					 smb_ses_list);
 384			i++;
 385			if ((ses->serverDomain == NULL) ||
 386				(ses->serverOS == NULL) ||
 387				(ses->serverNOS == NULL)) {
 388				seq_printf(m, "\n\t%d) Address: %s Uses: %d Capability: 0x%x\tSession Status: %d ",
 389					i, ses->ip_addr, ses->ses_count,
 390					ses->capabilities, ses->status);
 391				if (ses->session_flags & SMB2_SESSION_FLAG_IS_GUEST)
 392					seq_printf(m, "Guest ");
 393				else if (ses->session_flags & SMB2_SESSION_FLAG_IS_NULL)
 394					seq_printf(m, "Anonymous ");
 395			} else {
 396				seq_printf(m,
 397				    "\n\t%d) Name: %s  Domain: %s Uses: %d OS: %s "
 398				    "\n\tNOS: %s\tCapability: 0x%x"
 399					"\n\tSMB session status: %d ",
 400				i, ses->ip_addr, ses->serverDomain,
 401				ses->ses_count, ses->serverOS, ses->serverNOS,
 402				ses->capabilities, ses->status);
 403			}
 404
 405			seq_printf(m, "\n\tSecurity type: %s ",
 406				get_security_type_str(server->ops->select_sectype(server, ses->sectype)));
 407
 408			/* dump session id helpful for use with network trace */
 409			seq_printf(m, " SessionId: 0x%llx", ses->Suid);
 410			if (ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA)
 411				seq_puts(m, " encrypted");
 412			if (ses->sign)
 413				seq_puts(m, " signed");
 414
 415			seq_printf(m, "\n\tUser: %d Cred User: %d",
 416				   from_kuid(&init_user_ns, ses->linux_uid),
 417				   from_kuid(&init_user_ns, ses->cred_uid));
 418
 419			if (ses->chan_count > 1) {
 420				seq_printf(m, "\n\n\tExtra Channels: %zu ",
 421					   ses->chan_count-1);
 422				for (j = 1; j < ses->chan_count; j++)
 423					cifs_dump_channel(m, j, &ses->chans[j]);
 424			}
 425
 426			seq_puts(m, "\n\n\tShares: ");
 427			j = 0;
 428
 429			seq_printf(m, "\n\t%d) IPC: ", j);
 430			if (ses->tcon_ipc)
 431				cifs_debug_tcon(m, ses->tcon_ipc);
 432			else
 433				seq_puts(m, "none\n");
 434
 435			list_for_each(tmp3, &ses->tcon_list) {
 436				tcon = list_entry(tmp3, struct cifs_tcon,
 437						  tcon_list);
 438				++j;
 439				seq_printf(m, "\n\t%d) ", j);
 440				cifs_debug_tcon(m, tcon);
 441			}
 442
 443			spin_lock(&ses->iface_lock);
 444			if (ses->iface_count)
 445				seq_printf(m, "\n\n\tServer interfaces: %zu",
 446					   ses->iface_count);
 447			for (j = 0; j < ses->iface_count; j++) {
 448				struct cifs_server_iface *iface;
 449
 450				iface = &ses->iface_list[j];
 451				seq_printf(m, "\n\t%d)", j+1);
 452				cifs_dump_iface(m, iface);
 453				if (is_ses_using_iface(ses, iface))
 454					seq_puts(m, "\t\t[CONNECTED]\n");
 455			}
 456			spin_unlock(&ses->iface_lock);
 457		}
 458		if (i == 0)
 459			seq_printf(m, "\n\t\t[NONE]");
 460
 461		seq_puts(m, "\n\n\tMIDs: ");
 462		spin_lock(&GlobalMid_Lock);
 463		list_for_each(tmp3, &server->pending_mid_q) {
 464			mid_entry = list_entry(tmp3, struct mid_q_entry,
 465					qhead);
 466			seq_printf(m, "\n\tState: %d com: %d pid:"
 467					" %d cbdata: %p mid %llu\n",
 468					mid_entry->mid_state,
 469					le16_to_cpu(mid_entry->command),
 470					mid_entry->pid,
 471					mid_entry->callback_data,
 472					mid_entry->mid);
 473		}
 474		spin_unlock(&GlobalMid_Lock);
 475		seq_printf(m, "\n--\n");
 476	}
 477	if (c == 0)
 478		seq_printf(m, "\n\t[NONE]");
 479
 480	spin_unlock(&cifs_tcp_ses_lock);
 481	seq_putc(m, '\n');
 482	cifs_swn_dump(m);
 483
 484	/* BB add code to dump additional info such as TCP session info now */
 485	return 0;
 486}
 487
 488static ssize_t cifs_stats_proc_write(struct file *file,
 489		const char __user *buffer, size_t count, loff_t *ppos)
 490{
 491	bool bv;
 492	int rc;
 493	struct list_head *tmp1, *tmp2, *tmp3;
 494	struct TCP_Server_Info *server;
 495	struct cifs_ses *ses;
 496	struct cifs_tcon *tcon;
 497
 498	rc = kstrtobool_from_user(buffer, count, &bv);
 499	if (rc == 0) {
 500#ifdef CONFIG_CIFS_STATS2
 501		int i;
 502
 503		atomic_set(&totBufAllocCount, 0);
 504		atomic_set(&totSmBufAllocCount, 0);
 505#endif /* CONFIG_CIFS_STATS2 */
 506		atomic_set(&tcpSesReconnectCount, 0);
 507		atomic_set(&tconInfoReconnectCount, 0);
 508
 509		spin_lock(&GlobalMid_Lock);
 510		GlobalMaxActiveXid = 0;
 511		GlobalCurrentXid = 0;
 512		spin_unlock(&GlobalMid_Lock);
 513		spin_lock(&cifs_tcp_ses_lock);
 514		list_for_each(tmp1, &cifs_tcp_ses_list) {
 515			server = list_entry(tmp1, struct TCP_Server_Info,
 516					    tcp_ses_list);
 517			server->max_in_flight = 0;
 518#ifdef CONFIG_CIFS_STATS2
 519			for (i = 0; i < NUMBER_OF_SMB2_COMMANDS; i++) {
 520				atomic_set(&server->num_cmds[i], 0);
 521				atomic_set(&server->smb2slowcmd[i], 0);
 522				server->time_per_cmd[i] = 0;
 523				server->slowest_cmd[i] = 0;
 524				server->fastest_cmd[0] = 0;
 525			}
 526#endif /* CONFIG_CIFS_STATS2 */
 527			list_for_each(tmp2, &server->smb_ses_list) {
 528				ses = list_entry(tmp2, struct cifs_ses,
 529						 smb_ses_list);
 530				list_for_each(tmp3, &ses->tcon_list) {
 531					tcon = list_entry(tmp3,
 532							  struct cifs_tcon,
 533							  tcon_list);
 534					atomic_set(&tcon->num_smbs_sent, 0);
 535					spin_lock(&tcon->stat_lock);
 536					tcon->bytes_read = 0;
 537					tcon->bytes_written = 0;
 538					spin_unlock(&tcon->stat_lock);
 539					if (server->ops->clear_stats)
 540						server->ops->clear_stats(tcon);
 541				}
 542			}
 543		}
 544		spin_unlock(&cifs_tcp_ses_lock);
 545	} else {
 546		return rc;
 547	}
 548
 549	return count;
 550}
 551
 552static int cifs_stats_proc_show(struct seq_file *m, void *v)
 553{
 554	int i;
 555#ifdef CONFIG_CIFS_STATS2
 556	int j;
 557#endif /* STATS2 */
 558	struct list_head *tmp2, *tmp3;
 559	struct TCP_Server_Info *server;
 560	struct cifs_ses *ses;
 561	struct cifs_tcon *tcon;
 562
 563	seq_printf(m, "Resources in use\nCIFS Session: %d\n",
 564			sesInfoAllocCount.counter);
 565	seq_printf(m, "Share (unique mount targets): %d\n",
 566			tconInfoAllocCount.counter);
 567	seq_printf(m, "SMB Request/Response Buffer: %d Pool size: %d\n",
 568			bufAllocCount.counter,
 569			cifs_min_rcv + tcpSesAllocCount.counter);
 570	seq_printf(m, "SMB Small Req/Resp Buffer: %d Pool size: %d\n",
 571			smBufAllocCount.counter, cifs_min_small);
 572#ifdef CONFIG_CIFS_STATS2
 573	seq_printf(m, "Total Large %d Small %d Allocations\n",
 574				atomic_read(&totBufAllocCount),
 575				atomic_read(&totSmBufAllocCount));
 576#endif /* CONFIG_CIFS_STATS2 */
 577
 578	seq_printf(m, "Operations (MIDs): %d\n", atomic_read(&midCount));
 579	seq_printf(m,
 580		"\n%d session %d share reconnects\n",
 581		tcpSesReconnectCount.counter, tconInfoReconnectCount.counter);
 582
 583	seq_printf(m,
 584		"Total vfs operations: %d maximum at one time: %d\n",
 585		GlobalCurrentXid, GlobalMaxActiveXid);
 586
 587	i = 0;
 588	spin_lock(&cifs_tcp_ses_lock);
 589	list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
 590		seq_printf(m, "\nMax requests in flight: %d", server->max_in_flight);
 591#ifdef CONFIG_CIFS_STATS2
 592		seq_puts(m, "\nTotal time spent processing by command. Time ");
 593		seq_printf(m, "units are jiffies (%d per second)\n", HZ);
 594		seq_puts(m, "  SMB3 CMD\tNumber\tTotal Time\tFastest\tSlowest\n");
 595		seq_puts(m, "  --------\t------\t----------\t-------\t-------\n");
 596		for (j = 0; j < NUMBER_OF_SMB2_COMMANDS; j++)
 597			seq_printf(m, "  %d\t\t%d\t%llu\t\t%u\t%u\n", j,
 598				atomic_read(&server->num_cmds[j]),
 599				server->time_per_cmd[j],
 600				server->fastest_cmd[j],
 601				server->slowest_cmd[j]);
 602		for (j = 0; j < NUMBER_OF_SMB2_COMMANDS; j++)
 603			if (atomic_read(&server->smb2slowcmd[j]))
 604				seq_printf(m, "  %d slow responses from %s for command %d\n",
 605					atomic_read(&server->smb2slowcmd[j]),
 606					server->hostname, j);
 607#endif /* STATS2 */
 608		list_for_each(tmp2, &server->smb_ses_list) {
 609			ses = list_entry(tmp2, struct cifs_ses,
 610					 smb_ses_list);
 611			list_for_each(tmp3, &ses->tcon_list) {
 612				tcon = list_entry(tmp3,
 613						  struct cifs_tcon,
 614						  tcon_list);
 615				i++;
 616				seq_printf(m, "\n%d) %s", i, tcon->treeName);
 617				if (tcon->need_reconnect)
 618					seq_puts(m, "\tDISCONNECTED ");
 619				seq_printf(m, "\nSMBs: %d",
 620					   atomic_read(&tcon->num_smbs_sent));
 621				if (server->ops->print_stats)
 622					server->ops->print_stats(m, tcon);
 623			}
 624		}
 625	}
 626	spin_unlock(&cifs_tcp_ses_lock);
 627
 628	seq_putc(m, '\n');
 629	return 0;
 630}
 631
 632static int cifs_stats_proc_open(struct inode *inode, struct file *file)
 633{
 634	return single_open(file, cifs_stats_proc_show, NULL);
 635}
 636
 637static const struct proc_ops cifs_stats_proc_ops = {
 638	.proc_open	= cifs_stats_proc_open,
 639	.proc_read	= seq_read,
 640	.proc_lseek	= seq_lseek,
 641	.proc_release	= single_release,
 642	.proc_write	= cifs_stats_proc_write,
 643};
 644
 645#ifdef CONFIG_CIFS_SMB_DIRECT
 646#define PROC_FILE_DEFINE(name) \
 647static ssize_t name##_write(struct file *file, const char __user *buffer, \
 648	size_t count, loff_t *ppos) \
 649{ \
 650	int rc; \
 651	rc = kstrtoint_from_user(buffer, count, 10, & name); \
 652	if (rc) \
 653		return rc; \
 654	return count; \
 655} \
 656static int name##_proc_show(struct seq_file *m, void *v) \
 657{ \
 658	seq_printf(m, "%d\n", name ); \
 659	return 0; \
 660} \
 661static int name##_open(struct inode *inode, struct file *file) \
 662{ \
 663	return single_open(file, name##_proc_show, NULL); \
 664} \
 665\
 666static const struct proc_ops cifs_##name##_proc_fops = { \
 667	.proc_open	= name##_open, \
 668	.proc_read	= seq_read, \
 669	.proc_lseek	= seq_lseek, \
 670	.proc_release	= single_release, \
 671	.proc_write	= name##_write, \
 672}
 673
 674PROC_FILE_DEFINE(rdma_readwrite_threshold);
 675PROC_FILE_DEFINE(smbd_max_frmr_depth);
 676PROC_FILE_DEFINE(smbd_keep_alive_interval);
 677PROC_FILE_DEFINE(smbd_max_receive_size);
 678PROC_FILE_DEFINE(smbd_max_fragmented_recv_size);
 679PROC_FILE_DEFINE(smbd_max_send_size);
 680PROC_FILE_DEFINE(smbd_send_credit_target);
 681PROC_FILE_DEFINE(smbd_receive_credit_max);
 682#endif
 683
 684static struct proc_dir_entry *proc_fs_cifs;
 685static const struct proc_ops cifsFYI_proc_ops;
 686static const struct proc_ops cifs_lookup_cache_proc_ops;
 687static const struct proc_ops traceSMB_proc_ops;
 688static const struct proc_ops cifs_security_flags_proc_ops;
 689static const struct proc_ops cifs_linux_ext_proc_ops;
 690static const struct proc_ops cifs_mount_params_proc_ops;
 691
 692void
 693cifs_proc_init(void)
 694{
 695	proc_fs_cifs = proc_mkdir("fs/cifs", NULL);
 696	if (proc_fs_cifs == NULL)
 697		return;
 698
 699	proc_create_single("DebugData", 0, proc_fs_cifs,
 700			cifs_debug_data_proc_show);
 701
 702	proc_create_single("open_files", 0400, proc_fs_cifs,
 703			cifs_debug_files_proc_show);
 704
 705	proc_create("Stats", 0644, proc_fs_cifs, &cifs_stats_proc_ops);
 706	proc_create("cifsFYI", 0644, proc_fs_cifs, &cifsFYI_proc_ops);
 707	proc_create("traceSMB", 0644, proc_fs_cifs, &traceSMB_proc_ops);
 708	proc_create("LinuxExtensionsEnabled", 0644, proc_fs_cifs,
 709		    &cifs_linux_ext_proc_ops);
 710	proc_create("SecurityFlags", 0644, proc_fs_cifs,
 711		    &cifs_security_flags_proc_ops);
 712	proc_create("LookupCacheEnabled", 0644, proc_fs_cifs,
 713		    &cifs_lookup_cache_proc_ops);
 714
 715	proc_create("mount_params", 0444, proc_fs_cifs, &cifs_mount_params_proc_ops);
 716
 717#ifdef CONFIG_CIFS_DFS_UPCALL
 718	proc_create("dfscache", 0644, proc_fs_cifs, &dfscache_proc_ops);
 719#endif
 720
 721#ifdef CONFIG_CIFS_SMB_DIRECT
 722	proc_create("rdma_readwrite_threshold", 0644, proc_fs_cifs,
 723		&cifs_rdma_readwrite_threshold_proc_fops);
 724	proc_create("smbd_max_frmr_depth", 0644, proc_fs_cifs,
 725		&cifs_smbd_max_frmr_depth_proc_fops);
 726	proc_create("smbd_keep_alive_interval", 0644, proc_fs_cifs,
 727		&cifs_smbd_keep_alive_interval_proc_fops);
 728	proc_create("smbd_max_receive_size", 0644, proc_fs_cifs,
 729		&cifs_smbd_max_receive_size_proc_fops);
 730	proc_create("smbd_max_fragmented_recv_size", 0644, proc_fs_cifs,
 731		&cifs_smbd_max_fragmented_recv_size_proc_fops);
 732	proc_create("smbd_max_send_size", 0644, proc_fs_cifs,
 733		&cifs_smbd_max_send_size_proc_fops);
 734	proc_create("smbd_send_credit_target", 0644, proc_fs_cifs,
 735		&cifs_smbd_send_credit_target_proc_fops);
 736	proc_create("smbd_receive_credit_max", 0644, proc_fs_cifs,
 737		&cifs_smbd_receive_credit_max_proc_fops);
 738#endif
 739}
 740
 741void
 742cifs_proc_clean(void)
 743{
 744	if (proc_fs_cifs == NULL)
 745		return;
 746
 747	remove_proc_entry("DebugData", proc_fs_cifs);
 748	remove_proc_entry("open_files", proc_fs_cifs);
 749	remove_proc_entry("cifsFYI", proc_fs_cifs);
 750	remove_proc_entry("traceSMB", proc_fs_cifs);
 751	remove_proc_entry("Stats", proc_fs_cifs);
 752	remove_proc_entry("SecurityFlags", proc_fs_cifs);
 753	remove_proc_entry("LinuxExtensionsEnabled", proc_fs_cifs);
 754	remove_proc_entry("LookupCacheEnabled", proc_fs_cifs);
 755	remove_proc_entry("mount_params", proc_fs_cifs);
 756
 757#ifdef CONFIG_CIFS_DFS_UPCALL
 758	remove_proc_entry("dfscache", proc_fs_cifs);
 759#endif
 760#ifdef CONFIG_CIFS_SMB_DIRECT
 761	remove_proc_entry("rdma_readwrite_threshold", proc_fs_cifs);
 762	remove_proc_entry("smbd_max_frmr_depth", proc_fs_cifs);
 763	remove_proc_entry("smbd_keep_alive_interval", proc_fs_cifs);
 764	remove_proc_entry("smbd_max_receive_size", proc_fs_cifs);
 765	remove_proc_entry("smbd_max_fragmented_recv_size", proc_fs_cifs);
 766	remove_proc_entry("smbd_max_send_size", proc_fs_cifs);
 767	remove_proc_entry("smbd_send_credit_target", proc_fs_cifs);
 768	remove_proc_entry("smbd_receive_credit_max", proc_fs_cifs);
 769#endif
 770	remove_proc_entry("fs/cifs", NULL);
 771}
 772
 773static int cifsFYI_proc_show(struct seq_file *m, void *v)
 774{
 775	seq_printf(m, "%d\n", cifsFYI);
 776	return 0;
 777}
 778
 779static int cifsFYI_proc_open(struct inode *inode, struct file *file)
 780{
 781	return single_open(file, cifsFYI_proc_show, NULL);
 782}
 783
 784static ssize_t cifsFYI_proc_write(struct file *file, const char __user *buffer,
 785		size_t count, loff_t *ppos)
 786{
 787	char c[2] = { '\0' };
 788	bool bv;
 789	int rc;
 790
 791	rc = get_user(c[0], buffer);
 792	if (rc)
 793		return rc;
 794	if (strtobool(c, &bv) == 0)
 795		cifsFYI = bv;
 796	else if ((c[0] > '1') && (c[0] <= '9'))
 797		cifsFYI = (int) (c[0] - '0'); /* see cifs_debug.h for meanings */
 798	else
 799		return -EINVAL;
 800
 801	return count;
 802}
 803
 804static const struct proc_ops cifsFYI_proc_ops = {
 805	.proc_open	= cifsFYI_proc_open,
 806	.proc_read	= seq_read,
 807	.proc_lseek	= seq_lseek,
 808	.proc_release	= single_release,
 809	.proc_write	= cifsFYI_proc_write,
 810};
 811
 812static int cifs_linux_ext_proc_show(struct seq_file *m, void *v)
 813{
 814	seq_printf(m, "%d\n", linuxExtEnabled);
 815	return 0;
 816}
 817
 818static int cifs_linux_ext_proc_open(struct inode *inode, struct file *file)
 819{
 820	return single_open(file, cifs_linux_ext_proc_show, NULL);
 821}
 822
 823static ssize_t cifs_linux_ext_proc_write(struct file *file,
 824		const char __user *buffer, size_t count, loff_t *ppos)
 825{
 826	int rc;
 827
 828	rc = kstrtobool_from_user(buffer, count, &linuxExtEnabled);
 829	if (rc)
 830		return rc;
 831
 832	return count;
 833}
 834
 835static const struct proc_ops cifs_linux_ext_proc_ops = {
 836	.proc_open	= cifs_linux_ext_proc_open,
 837	.proc_read	= seq_read,
 838	.proc_lseek	= seq_lseek,
 839	.proc_release	= single_release,
 840	.proc_write	= cifs_linux_ext_proc_write,
 841};
 842
 843static int cifs_lookup_cache_proc_show(struct seq_file *m, void *v)
 844{
 845	seq_printf(m, "%d\n", lookupCacheEnabled);
 846	return 0;
 847}
 848
 849static int cifs_lookup_cache_proc_open(struct inode *inode, struct file *file)
 850{
 851	return single_open(file, cifs_lookup_cache_proc_show, NULL);
 852}
 853
 854static ssize_t cifs_lookup_cache_proc_write(struct file *file,
 855		const char __user *buffer, size_t count, loff_t *ppos)
 856{
 857	int rc;
 858
 859	rc = kstrtobool_from_user(buffer, count, &lookupCacheEnabled);
 860	if (rc)
 861		return rc;
 862
 863	return count;
 864}
 865
 866static const struct proc_ops cifs_lookup_cache_proc_ops = {
 867	.proc_open	= cifs_lookup_cache_proc_open,
 868	.proc_read	= seq_read,
 869	.proc_lseek	= seq_lseek,
 870	.proc_release	= single_release,
 871	.proc_write	= cifs_lookup_cache_proc_write,
 872};
 873
 874static int traceSMB_proc_show(struct seq_file *m, void *v)
 875{
 876	seq_printf(m, "%d\n", traceSMB);
 877	return 0;
 878}
 879
 880static int traceSMB_proc_open(struct inode *inode, struct file *file)
 881{
 882	return single_open(file, traceSMB_proc_show, NULL);
 883}
 884
 885static ssize_t traceSMB_proc_write(struct file *file, const char __user *buffer,
 886		size_t count, loff_t *ppos)
 887{
 888	int rc;
 889
 890	rc = kstrtobool_from_user(buffer, count, &traceSMB);
 891	if (rc)
 892		return rc;
 893
 894	return count;
 895}
 896
 897static const struct proc_ops traceSMB_proc_ops = {
 898	.proc_open	= traceSMB_proc_open,
 899	.proc_read	= seq_read,
 900	.proc_lseek	= seq_lseek,
 901	.proc_release	= single_release,
 902	.proc_write	= traceSMB_proc_write,
 903};
 904
 905static int cifs_security_flags_proc_show(struct seq_file *m, void *v)
 906{
 907	seq_printf(m, "0x%x\n", global_secflags);
 908	return 0;
 909}
 910
 911static int cifs_security_flags_proc_open(struct inode *inode, struct file *file)
 912{
 913	return single_open(file, cifs_security_flags_proc_show, NULL);
 914}
 915
 916/*
 917 * Ensure that if someone sets a MUST flag, that we disable all other MAY
 918 * flags except for the ones corresponding to the given MUST flag. If there are
 919 * multiple MUST flags, then try to prefer more secure ones.
 920 */
 921static void
 922cifs_security_flags_handle_must_flags(unsigned int *flags)
 923{
 924	unsigned int signflags = *flags & CIFSSEC_MUST_SIGN;
 925
 926	if ((*flags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
 927		*flags = CIFSSEC_MUST_KRB5;
 928	else if ((*flags & CIFSSEC_MUST_NTLMSSP) == CIFSSEC_MUST_NTLMSSP)
 929		*flags = CIFSSEC_MUST_NTLMSSP;
 930	else if ((*flags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
 931		*flags = CIFSSEC_MUST_NTLMV2;
 932	else if ((*flags & CIFSSEC_MUST_NTLM) == CIFSSEC_MUST_NTLM)
 933		*flags = CIFSSEC_MUST_NTLM;
 934	else if (CIFSSEC_MUST_LANMAN &&
 935		 (*flags & CIFSSEC_MUST_LANMAN) == CIFSSEC_MUST_LANMAN)
 936		*flags = CIFSSEC_MUST_LANMAN;
 937	else if (CIFSSEC_MUST_PLNTXT &&
 938		 (*flags & CIFSSEC_MUST_PLNTXT) == CIFSSEC_MUST_PLNTXT)
 939		*flags = CIFSSEC_MUST_PLNTXT;
 940
 941	*flags |= signflags;
 942}
 943
 944static ssize_t cifs_security_flags_proc_write(struct file *file,
 945		const char __user *buffer, size_t count, loff_t *ppos)
 946{
 947	int rc;
 948	unsigned int flags;
 949	char flags_string[12];
 950	bool bv;
 951
 952	if ((count < 1) || (count > 11))
 953		return -EINVAL;
 954
 955	memset(flags_string, 0, 12);
 956
 957	if (copy_from_user(flags_string, buffer, count))
 958		return -EFAULT;
 959
 960	if (count < 3) {
 961		/* single char or single char followed by null */
 962		if (strtobool(flags_string, &bv) == 0) {
 963			global_secflags = bv ? CIFSSEC_MAX : CIFSSEC_DEF;
 964			return count;
 965		} else if (!isdigit(flags_string[0])) {
 966			cifs_dbg(VFS, "Invalid SecurityFlags: %s\n",
 967					flags_string);
 968			return -EINVAL;
 969		}
 970	}
 971
 972	/* else we have a number */
 973	rc = kstrtouint(flags_string, 0, &flags);
 974	if (rc) {
 975		cifs_dbg(VFS, "Invalid SecurityFlags: %s\n",
 976				flags_string);
 977		return rc;
 978	}
 979
 980	cifs_dbg(FYI, "sec flags 0x%x\n", flags);
 981
 982	if (flags == 0)  {
 983		cifs_dbg(VFS, "Invalid SecurityFlags: %s\n", flags_string);
 984		return -EINVAL;
 985	}
 986
 987	if (flags & ~CIFSSEC_MASK) {
 988		cifs_dbg(VFS, "Unsupported security flags: 0x%x\n",
 989			 flags & ~CIFSSEC_MASK);
 990		return -EINVAL;
 991	}
 992
 993	cifs_security_flags_handle_must_flags(&flags);
 994
 995	/* flags look ok - update the global security flags for cifs module */
 996	global_secflags = flags;
 997	if (global_secflags & CIFSSEC_MUST_SIGN) {
 998		/* requiring signing implies signing is allowed */
 999		global_secflags |= CIFSSEC_MAY_SIGN;
1000		cifs_dbg(FYI, "packet signing now required\n");
1001	} else if ((global_secflags & CIFSSEC_MAY_SIGN) == 0) {
1002		cifs_dbg(FYI, "packet signing disabled\n");
1003	}
1004	/* BB should we turn on MAY flags for other MUST options? */
1005	return count;
1006}
1007
1008static const struct proc_ops cifs_security_flags_proc_ops = {
1009	.proc_open	= cifs_security_flags_proc_open,
1010	.proc_read	= seq_read,
1011	.proc_lseek	= seq_lseek,
1012	.proc_release	= single_release,
1013	.proc_write	= cifs_security_flags_proc_write,
1014};
1015
1016/* To make it easier to debug, can help to show mount params */
1017static int cifs_mount_params_proc_show(struct seq_file *m, void *v)
1018{
1019	const struct fs_parameter_spec *p;
1020	const char *type;
1021
1022	for (p = smb3_fs_parameters; p->name; p++) {
1023		/* cannot use switch with pointers... */
1024		if (!p->type) {
1025			if (p->flags == fs_param_neg_with_no)
1026				type = "noflag";
1027			else
1028				type = "flag";
1029		} else if (p->type == fs_param_is_bool)
1030			type = "bool";
1031		else if (p->type == fs_param_is_u32)
1032			type = "u32";
1033		else if (p->type == fs_param_is_u64)
1034			type = "u64";
1035		else if (p->type == fs_param_is_string)
1036			type = "string";
1037		else
1038			type = "unknown";
1039
1040		seq_printf(m, "%s:%s\n", p->name, type);
1041	}
1042
1043	return 0;
1044}
1045
1046static int cifs_mount_params_proc_open(struct inode *inode, struct file *file)
1047{
1048	return single_open(file, cifs_mount_params_proc_show, NULL);
1049}
1050
1051static const struct proc_ops cifs_mount_params_proc_ops = {
1052	.proc_open	= cifs_mount_params_proc_open,
1053	.proc_read	= seq_read,
1054	.proc_lseek	= seq_lseek,
1055	.proc_release	= single_release,
1056	/* No need for write for now */
1057	/* .proc_write	= cifs_mount_params_proc_write, */
1058};
1059
1060#else
1061inline void cifs_proc_init(void)
1062{
1063}
1064
1065inline void cifs_proc_clean(void)
1066{
1067}
1068#endif /* PROC_FS */