Linux Audio

Check our new training course

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