162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci *   Copyright (C) International Business Machines  Corp., 2000,2005
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci *   Modified by Steve French (sfrench@us.ibm.com)
762306a36Sopenharmony_ci */
862306a36Sopenharmony_ci#include <linux/fs.h>
962306a36Sopenharmony_ci#include <linux/string.h>
1062306a36Sopenharmony_ci#include <linux/ctype.h>
1162306a36Sopenharmony_ci#include <linux/kstrtox.h>
1262306a36Sopenharmony_ci#include <linux/module.h>
1362306a36Sopenharmony_ci#include <linux/proc_fs.h>
1462306a36Sopenharmony_ci#include <linux/uaccess.h>
1562306a36Sopenharmony_ci#include <uapi/linux/ethtool.h>
1662306a36Sopenharmony_ci#include "cifspdu.h"
1762306a36Sopenharmony_ci#include "cifsglob.h"
1862306a36Sopenharmony_ci#include "cifsproto.h"
1962306a36Sopenharmony_ci#include "cifs_debug.h"
2062306a36Sopenharmony_ci#include "cifsfs.h"
2162306a36Sopenharmony_ci#include "fs_context.h"
2262306a36Sopenharmony_ci#ifdef CONFIG_CIFS_DFS_UPCALL
2362306a36Sopenharmony_ci#include "dfs_cache.h"
2462306a36Sopenharmony_ci#endif
2562306a36Sopenharmony_ci#ifdef CONFIG_CIFS_SMB_DIRECT
2662306a36Sopenharmony_ci#include "smbdirect.h"
2762306a36Sopenharmony_ci#endif
2862306a36Sopenharmony_ci#include "cifs_swn.h"
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_civoid
3162306a36Sopenharmony_cicifs_dump_mem(char *label, void *data, int length)
3262306a36Sopenharmony_ci{
3362306a36Sopenharmony_ci	pr_debug("%s: dump of %d bytes of data at 0x%p\n", label, length, data);
3462306a36Sopenharmony_ci	print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 16, 4,
3562306a36Sopenharmony_ci		       data, length, true);
3662306a36Sopenharmony_ci}
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_civoid cifs_dump_detail(void *buf, struct TCP_Server_Info *server)
3962306a36Sopenharmony_ci{
4062306a36Sopenharmony_ci#ifdef CONFIG_CIFS_DEBUG2
4162306a36Sopenharmony_ci	struct smb_hdr *smb = buf;
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci	cifs_dbg(VFS, "Cmd: %d Err: 0x%x Flags: 0x%x Flgs2: 0x%x Mid: %d Pid: %d Wct: %d\n",
4462306a36Sopenharmony_ci		 smb->Command, smb->Status.CifsError, smb->Flags,
4562306a36Sopenharmony_ci		 smb->Flags2, smb->Mid, smb->Pid, smb->WordCount);
4662306a36Sopenharmony_ci	if (!server->ops->check_message(buf, server->total_read, server)) {
4762306a36Sopenharmony_ci		cifs_dbg(VFS, "smb buf %p len %u\n", smb,
4862306a36Sopenharmony_ci			 server->ops->calc_smb_size(smb));
4962306a36Sopenharmony_ci	}
5062306a36Sopenharmony_ci#endif /* CONFIG_CIFS_DEBUG2 */
5162306a36Sopenharmony_ci}
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_civoid cifs_dump_mids(struct TCP_Server_Info *server)
5462306a36Sopenharmony_ci{
5562306a36Sopenharmony_ci#ifdef CONFIG_CIFS_DEBUG2
5662306a36Sopenharmony_ci	struct mid_q_entry *mid_entry;
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci	if (server == NULL)
5962306a36Sopenharmony_ci		return;
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci	cifs_dbg(VFS, "Dump pending requests:\n");
6262306a36Sopenharmony_ci	spin_lock(&server->mid_lock);
6362306a36Sopenharmony_ci	list_for_each_entry(mid_entry, &server->pending_mid_q, qhead) {
6462306a36Sopenharmony_ci		cifs_dbg(VFS, "State: %d Cmd: %d Pid: %d Cbdata: %p Mid %llu\n",
6562306a36Sopenharmony_ci			 mid_entry->mid_state,
6662306a36Sopenharmony_ci			 le16_to_cpu(mid_entry->command),
6762306a36Sopenharmony_ci			 mid_entry->pid,
6862306a36Sopenharmony_ci			 mid_entry->callback_data,
6962306a36Sopenharmony_ci			 mid_entry->mid);
7062306a36Sopenharmony_ci#ifdef CONFIG_CIFS_STATS2
7162306a36Sopenharmony_ci		cifs_dbg(VFS, "IsLarge: %d buf: %p time rcv: %ld now: %ld\n",
7262306a36Sopenharmony_ci			 mid_entry->large_buf,
7362306a36Sopenharmony_ci			 mid_entry->resp_buf,
7462306a36Sopenharmony_ci			 mid_entry->when_received,
7562306a36Sopenharmony_ci			 jiffies);
7662306a36Sopenharmony_ci#endif /* STATS2 */
7762306a36Sopenharmony_ci		cifs_dbg(VFS, "IsMult: %d IsEnd: %d\n",
7862306a36Sopenharmony_ci			 mid_entry->multiRsp, mid_entry->multiEnd);
7962306a36Sopenharmony_ci		if (mid_entry->resp_buf) {
8062306a36Sopenharmony_ci			cifs_dump_detail(mid_entry->resp_buf, server);
8162306a36Sopenharmony_ci			cifs_dump_mem("existing buf: ",
8262306a36Sopenharmony_ci				mid_entry->resp_buf, 62);
8362306a36Sopenharmony_ci		}
8462306a36Sopenharmony_ci	}
8562306a36Sopenharmony_ci	spin_unlock(&server->mid_lock);
8662306a36Sopenharmony_ci#endif /* CONFIG_CIFS_DEBUG2 */
8762306a36Sopenharmony_ci}
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci#ifdef CONFIG_PROC_FS
9062306a36Sopenharmony_cistatic void cifs_debug_tcon(struct seq_file *m, struct cifs_tcon *tcon)
9162306a36Sopenharmony_ci{
9262306a36Sopenharmony_ci	__u32 dev_type = le32_to_cpu(tcon->fsDevInfo.DeviceType);
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ci	seq_printf(m, "%s Mounts: %d ", tcon->tree_name, tcon->tc_count);
9562306a36Sopenharmony_ci	if (tcon->nativeFileSystem)
9662306a36Sopenharmony_ci		seq_printf(m, "Type: %s ", tcon->nativeFileSystem);
9762306a36Sopenharmony_ci	seq_printf(m, "DevInfo: 0x%x Attributes: 0x%x\n\tPathComponentMax: %d Status: %d",
9862306a36Sopenharmony_ci		   le32_to_cpu(tcon->fsDevInfo.DeviceCharacteristics),
9962306a36Sopenharmony_ci		   le32_to_cpu(tcon->fsAttrInfo.Attributes),
10062306a36Sopenharmony_ci		   le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength),
10162306a36Sopenharmony_ci		   tcon->status);
10262306a36Sopenharmony_ci	if (dev_type == FILE_DEVICE_DISK)
10362306a36Sopenharmony_ci		seq_puts(m, " type: DISK ");
10462306a36Sopenharmony_ci	else if (dev_type == FILE_DEVICE_CD_ROM)
10562306a36Sopenharmony_ci		seq_puts(m, " type: CDROM ");
10662306a36Sopenharmony_ci	else
10762306a36Sopenharmony_ci		seq_printf(m, " type: %d ", dev_type);
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci	seq_printf(m, "Serial Number: 0x%x", tcon->vol_serial_number);
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci	if ((tcon->seal) ||
11262306a36Sopenharmony_ci	    (tcon->ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA) ||
11362306a36Sopenharmony_ci	    (tcon->share_flags & SHI1005_FLAGS_ENCRYPT_DATA))
11462306a36Sopenharmony_ci		seq_puts(m, " encrypted");
11562306a36Sopenharmony_ci	if (tcon->nocase)
11662306a36Sopenharmony_ci		seq_printf(m, " nocase");
11762306a36Sopenharmony_ci	if (tcon->unix_ext)
11862306a36Sopenharmony_ci		seq_printf(m, " POSIX Extensions");
11962306a36Sopenharmony_ci	if (tcon->ses->server->ops->dump_share_caps)
12062306a36Sopenharmony_ci		tcon->ses->server->ops->dump_share_caps(m, tcon);
12162306a36Sopenharmony_ci	if (tcon->use_witness)
12262306a36Sopenharmony_ci		seq_puts(m, " Witness");
12362306a36Sopenharmony_ci	if (tcon->broken_sparse_sup)
12462306a36Sopenharmony_ci		seq_puts(m, " nosparse");
12562306a36Sopenharmony_ci	if (tcon->need_reconnect)
12662306a36Sopenharmony_ci		seq_puts(m, "\tDISCONNECTED ");
12762306a36Sopenharmony_ci	spin_lock(&tcon->tc_lock);
12862306a36Sopenharmony_ci	if (tcon->origin_fullpath) {
12962306a36Sopenharmony_ci		seq_printf(m, "\n\tDFS origin fullpath: %s",
13062306a36Sopenharmony_ci			   tcon->origin_fullpath);
13162306a36Sopenharmony_ci	}
13262306a36Sopenharmony_ci	spin_unlock(&tcon->tc_lock);
13362306a36Sopenharmony_ci	seq_putc(m, '\n');
13462306a36Sopenharmony_ci}
13562306a36Sopenharmony_ci
13662306a36Sopenharmony_cistatic void
13762306a36Sopenharmony_cicifs_dump_channel(struct seq_file *m, int i, struct cifs_chan *chan)
13862306a36Sopenharmony_ci{
13962306a36Sopenharmony_ci	struct TCP_Server_Info *server = chan->server;
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_ci	if (!server) {
14262306a36Sopenharmony_ci		seq_printf(m, "\n\n\t\tChannel: %d DISABLED", i+1);
14362306a36Sopenharmony_ci		return;
14462306a36Sopenharmony_ci	}
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_ci	seq_printf(m, "\n\n\t\tChannel: %d ConnectionId: 0x%llx"
14762306a36Sopenharmony_ci		   "\n\t\tNumber of credits: %d,%d,%d Dialect 0x%x"
14862306a36Sopenharmony_ci		   "\n\t\tTCP status: %d Instance: %d"
14962306a36Sopenharmony_ci		   "\n\t\tLocal Users To Server: %d SecMode: 0x%x Req On Wire: %d"
15062306a36Sopenharmony_ci		   "\n\t\tIn Send: %d In MaxReq Wait: %d",
15162306a36Sopenharmony_ci		   i+1, server->conn_id,
15262306a36Sopenharmony_ci		   server->credits,
15362306a36Sopenharmony_ci		   server->echo_credits,
15462306a36Sopenharmony_ci		   server->oplock_credits,
15562306a36Sopenharmony_ci		   server->dialect,
15662306a36Sopenharmony_ci		   server->tcpStatus,
15762306a36Sopenharmony_ci		   server->reconnect_instance,
15862306a36Sopenharmony_ci		   server->srv_count,
15962306a36Sopenharmony_ci		   server->sec_mode,
16062306a36Sopenharmony_ci		   in_flight(server),
16162306a36Sopenharmony_ci		   atomic_read(&server->in_send),
16262306a36Sopenharmony_ci		   atomic_read(&server->num_waiters));
16362306a36Sopenharmony_ci#ifdef CONFIG_NET_NS
16462306a36Sopenharmony_ci	if (server->net)
16562306a36Sopenharmony_ci		seq_printf(m, " Net namespace: %u ", server->net->ns.inum);
16662306a36Sopenharmony_ci#endif /* NET_NS */
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_ci}
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_cistatic inline const char *smb_speed_to_str(size_t bps)
17162306a36Sopenharmony_ci{
17262306a36Sopenharmony_ci	size_t mbps = bps / 1000 / 1000;
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_ci	switch (mbps) {
17562306a36Sopenharmony_ci	case SPEED_10:
17662306a36Sopenharmony_ci		return "10Mbps";
17762306a36Sopenharmony_ci	case SPEED_100:
17862306a36Sopenharmony_ci		return "100Mbps";
17962306a36Sopenharmony_ci	case SPEED_1000:
18062306a36Sopenharmony_ci		return "1Gbps";
18162306a36Sopenharmony_ci	case SPEED_2500:
18262306a36Sopenharmony_ci		return "2.5Gbps";
18362306a36Sopenharmony_ci	case SPEED_5000:
18462306a36Sopenharmony_ci		return "5Gbps";
18562306a36Sopenharmony_ci	case SPEED_10000:
18662306a36Sopenharmony_ci		return "10Gbps";
18762306a36Sopenharmony_ci	case SPEED_14000:
18862306a36Sopenharmony_ci		return "14Gbps";
18962306a36Sopenharmony_ci	case SPEED_20000:
19062306a36Sopenharmony_ci		return "20Gbps";
19162306a36Sopenharmony_ci	case SPEED_25000:
19262306a36Sopenharmony_ci		return "25Gbps";
19362306a36Sopenharmony_ci	case SPEED_40000:
19462306a36Sopenharmony_ci		return "40Gbps";
19562306a36Sopenharmony_ci	case SPEED_50000:
19662306a36Sopenharmony_ci		return "50Gbps";
19762306a36Sopenharmony_ci	case SPEED_56000:
19862306a36Sopenharmony_ci		return "56Gbps";
19962306a36Sopenharmony_ci	case SPEED_100000:
20062306a36Sopenharmony_ci		return "100Gbps";
20162306a36Sopenharmony_ci	case SPEED_200000:
20262306a36Sopenharmony_ci		return "200Gbps";
20362306a36Sopenharmony_ci	case SPEED_400000:
20462306a36Sopenharmony_ci		return "400Gbps";
20562306a36Sopenharmony_ci	case SPEED_800000:
20662306a36Sopenharmony_ci		return "800Gbps";
20762306a36Sopenharmony_ci	default:
20862306a36Sopenharmony_ci		return "Unknown";
20962306a36Sopenharmony_ci	}
21062306a36Sopenharmony_ci}
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_cistatic void
21362306a36Sopenharmony_cicifs_dump_iface(struct seq_file *m, struct cifs_server_iface *iface)
21462306a36Sopenharmony_ci{
21562306a36Sopenharmony_ci	struct sockaddr_in *ipv4 = (struct sockaddr_in *)&iface->sockaddr;
21662306a36Sopenharmony_ci	struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)&iface->sockaddr;
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ci	seq_printf(m, "\tSpeed: %s\n", smb_speed_to_str(iface->speed));
21962306a36Sopenharmony_ci	seq_puts(m, "\t\tCapabilities: ");
22062306a36Sopenharmony_ci	if (iface->rdma_capable)
22162306a36Sopenharmony_ci		seq_puts(m, "rdma ");
22262306a36Sopenharmony_ci	if (iface->rss_capable)
22362306a36Sopenharmony_ci		seq_puts(m, "rss ");
22462306a36Sopenharmony_ci	if (!iface->rdma_capable && !iface->rss_capable)
22562306a36Sopenharmony_ci		seq_puts(m, "None");
22662306a36Sopenharmony_ci	seq_putc(m, '\n');
22762306a36Sopenharmony_ci	if (iface->sockaddr.ss_family == AF_INET)
22862306a36Sopenharmony_ci		seq_printf(m, "\t\tIPv4: %pI4\n", &ipv4->sin_addr);
22962306a36Sopenharmony_ci	else if (iface->sockaddr.ss_family == AF_INET6)
23062306a36Sopenharmony_ci		seq_printf(m, "\t\tIPv6: %pI6\n", &ipv6->sin6_addr);
23162306a36Sopenharmony_ci	if (!iface->is_active)
23262306a36Sopenharmony_ci		seq_puts(m, "\t\t[for-cleanup]\n");
23362306a36Sopenharmony_ci}
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_cistatic int cifs_debug_files_proc_show(struct seq_file *m, void *v)
23662306a36Sopenharmony_ci{
23762306a36Sopenharmony_ci	struct TCP_Server_Info *server;
23862306a36Sopenharmony_ci	struct cifs_ses *ses;
23962306a36Sopenharmony_ci	struct cifs_tcon *tcon;
24062306a36Sopenharmony_ci	struct cifsFileInfo *cfile;
24162306a36Sopenharmony_ci
24262306a36Sopenharmony_ci	seq_puts(m, "# Version:1\n");
24362306a36Sopenharmony_ci	seq_puts(m, "# Format:\n");
24462306a36Sopenharmony_ci	seq_puts(m, "# <tree id> <ses id> <persistent fid> <flags> <count> <pid> <uid>");
24562306a36Sopenharmony_ci#ifdef CONFIG_CIFS_DEBUG2
24662306a36Sopenharmony_ci	seq_printf(m, " <filename> <mid>\n");
24762306a36Sopenharmony_ci#else
24862306a36Sopenharmony_ci	seq_printf(m, " <filename>\n");
24962306a36Sopenharmony_ci#endif /* CIFS_DEBUG2 */
25062306a36Sopenharmony_ci	spin_lock(&cifs_tcp_ses_lock);
25162306a36Sopenharmony_ci	list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
25262306a36Sopenharmony_ci		list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
25362306a36Sopenharmony_ci			list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
25462306a36Sopenharmony_ci				spin_lock(&tcon->open_file_lock);
25562306a36Sopenharmony_ci				list_for_each_entry(cfile, &tcon->openFileList, tlist) {
25662306a36Sopenharmony_ci					seq_printf(m,
25762306a36Sopenharmony_ci						"0x%x 0x%llx 0x%llx 0x%x %d %d %d %pd",
25862306a36Sopenharmony_ci						tcon->tid,
25962306a36Sopenharmony_ci						ses->Suid,
26062306a36Sopenharmony_ci						cfile->fid.persistent_fid,
26162306a36Sopenharmony_ci						cfile->f_flags,
26262306a36Sopenharmony_ci						cfile->count,
26362306a36Sopenharmony_ci						cfile->pid,
26462306a36Sopenharmony_ci						from_kuid(&init_user_ns, cfile->uid),
26562306a36Sopenharmony_ci						cfile->dentry);
26662306a36Sopenharmony_ci#ifdef CONFIG_CIFS_DEBUG2
26762306a36Sopenharmony_ci					seq_printf(m, " %llu\n", cfile->fid.mid);
26862306a36Sopenharmony_ci#else
26962306a36Sopenharmony_ci					seq_printf(m, "\n");
27062306a36Sopenharmony_ci#endif /* CIFS_DEBUG2 */
27162306a36Sopenharmony_ci				}
27262306a36Sopenharmony_ci				spin_unlock(&tcon->open_file_lock);
27362306a36Sopenharmony_ci			}
27462306a36Sopenharmony_ci		}
27562306a36Sopenharmony_ci	}
27662306a36Sopenharmony_ci	spin_unlock(&cifs_tcp_ses_lock);
27762306a36Sopenharmony_ci	seq_putc(m, '\n');
27862306a36Sopenharmony_ci	return 0;
27962306a36Sopenharmony_ci}
28062306a36Sopenharmony_ci
28162306a36Sopenharmony_cistatic int cifs_debug_data_proc_show(struct seq_file *m, void *v)
28262306a36Sopenharmony_ci{
28362306a36Sopenharmony_ci	struct mid_q_entry *mid_entry;
28462306a36Sopenharmony_ci	struct TCP_Server_Info *server;
28562306a36Sopenharmony_ci	struct TCP_Server_Info *chan_server;
28662306a36Sopenharmony_ci	struct cifs_ses *ses;
28762306a36Sopenharmony_ci	struct cifs_tcon *tcon;
28862306a36Sopenharmony_ci	struct cifs_server_iface *iface;
28962306a36Sopenharmony_ci	size_t iface_weight = 0, iface_min_speed = 0;
29062306a36Sopenharmony_ci	struct cifs_server_iface *last_iface = NULL;
29162306a36Sopenharmony_ci	int c, i, j;
29262306a36Sopenharmony_ci
29362306a36Sopenharmony_ci	seq_puts(m,
29462306a36Sopenharmony_ci		    "Display Internal CIFS Data Structures for Debugging\n"
29562306a36Sopenharmony_ci		    "---------------------------------------------------\n");
29662306a36Sopenharmony_ci	seq_printf(m, "CIFS Version %s\n", CIFS_VERSION);
29762306a36Sopenharmony_ci	seq_printf(m, "Features:");
29862306a36Sopenharmony_ci#ifdef CONFIG_CIFS_DFS_UPCALL
29962306a36Sopenharmony_ci	seq_printf(m, " DFS");
30062306a36Sopenharmony_ci#endif
30162306a36Sopenharmony_ci#ifdef CONFIG_CIFS_FSCACHE
30262306a36Sopenharmony_ci	seq_printf(m, ",FSCACHE");
30362306a36Sopenharmony_ci#endif
30462306a36Sopenharmony_ci#ifdef CONFIG_CIFS_SMB_DIRECT
30562306a36Sopenharmony_ci	seq_printf(m, ",SMB_DIRECT");
30662306a36Sopenharmony_ci#endif
30762306a36Sopenharmony_ci#ifdef CONFIG_CIFS_STATS2
30862306a36Sopenharmony_ci	seq_printf(m, ",STATS2");
30962306a36Sopenharmony_ci#else
31062306a36Sopenharmony_ci	seq_printf(m, ",STATS");
31162306a36Sopenharmony_ci#endif
31262306a36Sopenharmony_ci#ifdef CONFIG_CIFS_DEBUG2
31362306a36Sopenharmony_ci	seq_printf(m, ",DEBUG2");
31462306a36Sopenharmony_ci#elif defined(CONFIG_CIFS_DEBUG)
31562306a36Sopenharmony_ci	seq_printf(m, ",DEBUG");
31662306a36Sopenharmony_ci#endif
31762306a36Sopenharmony_ci#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
31862306a36Sopenharmony_ci	seq_printf(m, ",ALLOW_INSECURE_LEGACY");
31962306a36Sopenharmony_ci#endif
32062306a36Sopenharmony_ci#ifdef CONFIG_CIFS_POSIX
32162306a36Sopenharmony_ci	seq_printf(m, ",CIFS_POSIX");
32262306a36Sopenharmony_ci#endif
32362306a36Sopenharmony_ci#ifdef CONFIG_CIFS_UPCALL
32462306a36Sopenharmony_ci	seq_printf(m, ",UPCALL(SPNEGO)");
32562306a36Sopenharmony_ci#endif
32662306a36Sopenharmony_ci#ifdef CONFIG_CIFS_XATTR
32762306a36Sopenharmony_ci	seq_printf(m, ",XATTR");
32862306a36Sopenharmony_ci#endif
32962306a36Sopenharmony_ci	seq_printf(m, ",ACL");
33062306a36Sopenharmony_ci#ifdef CONFIG_CIFS_SWN_UPCALL
33162306a36Sopenharmony_ci	seq_puts(m, ",WITNESS");
33262306a36Sopenharmony_ci#endif
33362306a36Sopenharmony_ci	seq_putc(m, '\n');
33462306a36Sopenharmony_ci	seq_printf(m, "CIFSMaxBufSize: %d\n", CIFSMaxBufSize);
33562306a36Sopenharmony_ci	seq_printf(m, "Active VFS Requests: %d\n", GlobalTotalActiveXid);
33662306a36Sopenharmony_ci
33762306a36Sopenharmony_ci	seq_printf(m, "\nServers: ");
33862306a36Sopenharmony_ci
33962306a36Sopenharmony_ci	c = 0;
34062306a36Sopenharmony_ci	spin_lock(&cifs_tcp_ses_lock);
34162306a36Sopenharmony_ci	list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
34262306a36Sopenharmony_ci		/* channel info will be printed as a part of sessions below */
34362306a36Sopenharmony_ci		if (SERVER_IS_CHAN(server))
34462306a36Sopenharmony_ci			continue;
34562306a36Sopenharmony_ci
34662306a36Sopenharmony_ci		c++;
34762306a36Sopenharmony_ci		seq_printf(m, "\n%d) ConnectionId: 0x%llx ",
34862306a36Sopenharmony_ci			c, server->conn_id);
34962306a36Sopenharmony_ci
35062306a36Sopenharmony_ci		spin_lock(&server->srv_lock);
35162306a36Sopenharmony_ci		if (server->hostname)
35262306a36Sopenharmony_ci			seq_printf(m, "Hostname: %s ", server->hostname);
35362306a36Sopenharmony_ci		seq_printf(m, "\nClientGUID: %pUL", server->client_guid);
35462306a36Sopenharmony_ci		spin_unlock(&server->srv_lock);
35562306a36Sopenharmony_ci#ifdef CONFIG_CIFS_SMB_DIRECT
35662306a36Sopenharmony_ci		if (!server->rdma)
35762306a36Sopenharmony_ci			goto skip_rdma;
35862306a36Sopenharmony_ci
35962306a36Sopenharmony_ci		if (!server->smbd_conn) {
36062306a36Sopenharmony_ci			seq_printf(m, "\nSMBDirect transport not available");
36162306a36Sopenharmony_ci			goto skip_rdma;
36262306a36Sopenharmony_ci		}
36362306a36Sopenharmony_ci
36462306a36Sopenharmony_ci		seq_printf(m, "\nSMBDirect (in hex) protocol version: %x "
36562306a36Sopenharmony_ci			"transport status: %x",
36662306a36Sopenharmony_ci			server->smbd_conn->protocol,
36762306a36Sopenharmony_ci			server->smbd_conn->transport_status);
36862306a36Sopenharmony_ci		seq_printf(m, "\nConn receive_credit_max: %x "
36962306a36Sopenharmony_ci			"send_credit_target: %x max_send_size: %x",
37062306a36Sopenharmony_ci			server->smbd_conn->receive_credit_max,
37162306a36Sopenharmony_ci			server->smbd_conn->send_credit_target,
37262306a36Sopenharmony_ci			server->smbd_conn->max_send_size);
37362306a36Sopenharmony_ci		seq_printf(m, "\nConn max_fragmented_recv_size: %x "
37462306a36Sopenharmony_ci			"max_fragmented_send_size: %x max_receive_size:%x",
37562306a36Sopenharmony_ci			server->smbd_conn->max_fragmented_recv_size,
37662306a36Sopenharmony_ci			server->smbd_conn->max_fragmented_send_size,
37762306a36Sopenharmony_ci			server->smbd_conn->max_receive_size);
37862306a36Sopenharmony_ci		seq_printf(m, "\nConn keep_alive_interval: %x "
37962306a36Sopenharmony_ci			"max_readwrite_size: %x rdma_readwrite_threshold: %x",
38062306a36Sopenharmony_ci			server->smbd_conn->keep_alive_interval,
38162306a36Sopenharmony_ci			server->smbd_conn->max_readwrite_size,
38262306a36Sopenharmony_ci			server->smbd_conn->rdma_readwrite_threshold);
38362306a36Sopenharmony_ci		seq_printf(m, "\nDebug count_get_receive_buffer: %x "
38462306a36Sopenharmony_ci			"count_put_receive_buffer: %x count_send_empty: %x",
38562306a36Sopenharmony_ci			server->smbd_conn->count_get_receive_buffer,
38662306a36Sopenharmony_ci			server->smbd_conn->count_put_receive_buffer,
38762306a36Sopenharmony_ci			server->smbd_conn->count_send_empty);
38862306a36Sopenharmony_ci		seq_printf(m, "\nRead Queue count_reassembly_queue: %x "
38962306a36Sopenharmony_ci			"count_enqueue_reassembly_queue: %x "
39062306a36Sopenharmony_ci			"count_dequeue_reassembly_queue: %x "
39162306a36Sopenharmony_ci			"fragment_reassembly_remaining: %x "
39262306a36Sopenharmony_ci			"reassembly_data_length: %x "
39362306a36Sopenharmony_ci			"reassembly_queue_length: %x",
39462306a36Sopenharmony_ci			server->smbd_conn->count_reassembly_queue,
39562306a36Sopenharmony_ci			server->smbd_conn->count_enqueue_reassembly_queue,
39662306a36Sopenharmony_ci			server->smbd_conn->count_dequeue_reassembly_queue,
39762306a36Sopenharmony_ci			server->smbd_conn->fragment_reassembly_remaining,
39862306a36Sopenharmony_ci			server->smbd_conn->reassembly_data_length,
39962306a36Sopenharmony_ci			server->smbd_conn->reassembly_queue_length);
40062306a36Sopenharmony_ci		seq_printf(m, "\nCurrent Credits send_credits: %x "
40162306a36Sopenharmony_ci			"receive_credits: %x receive_credit_target: %x",
40262306a36Sopenharmony_ci			atomic_read(&server->smbd_conn->send_credits),
40362306a36Sopenharmony_ci			atomic_read(&server->smbd_conn->receive_credits),
40462306a36Sopenharmony_ci			server->smbd_conn->receive_credit_target);
40562306a36Sopenharmony_ci		seq_printf(m, "\nPending send_pending: %x ",
40662306a36Sopenharmony_ci			atomic_read(&server->smbd_conn->send_pending));
40762306a36Sopenharmony_ci		seq_printf(m, "\nReceive buffers count_receive_queue: %x "
40862306a36Sopenharmony_ci			"count_empty_packet_queue: %x",
40962306a36Sopenharmony_ci			server->smbd_conn->count_receive_queue,
41062306a36Sopenharmony_ci			server->smbd_conn->count_empty_packet_queue);
41162306a36Sopenharmony_ci		seq_printf(m, "\nMR responder_resources: %x "
41262306a36Sopenharmony_ci			"max_frmr_depth: %x mr_type: %x",
41362306a36Sopenharmony_ci			server->smbd_conn->responder_resources,
41462306a36Sopenharmony_ci			server->smbd_conn->max_frmr_depth,
41562306a36Sopenharmony_ci			server->smbd_conn->mr_type);
41662306a36Sopenharmony_ci		seq_printf(m, "\nMR mr_ready_count: %x mr_used_count: %x",
41762306a36Sopenharmony_ci			atomic_read(&server->smbd_conn->mr_ready_count),
41862306a36Sopenharmony_ci			atomic_read(&server->smbd_conn->mr_used_count));
41962306a36Sopenharmony_ciskip_rdma:
42062306a36Sopenharmony_ci#endif
42162306a36Sopenharmony_ci		seq_printf(m, "\nNumber of credits: %d,%d,%d Dialect 0x%x",
42262306a36Sopenharmony_ci			server->credits,
42362306a36Sopenharmony_ci			server->echo_credits,
42462306a36Sopenharmony_ci			server->oplock_credits,
42562306a36Sopenharmony_ci			server->dialect);
42662306a36Sopenharmony_ci		if (server->compress_algorithm == SMB3_COMPRESS_LZNT1)
42762306a36Sopenharmony_ci			seq_printf(m, " COMPRESS_LZNT1");
42862306a36Sopenharmony_ci		else if (server->compress_algorithm == SMB3_COMPRESS_LZ77)
42962306a36Sopenharmony_ci			seq_printf(m, " COMPRESS_LZ77");
43062306a36Sopenharmony_ci		else if (server->compress_algorithm == SMB3_COMPRESS_LZ77_HUFF)
43162306a36Sopenharmony_ci			seq_printf(m, " COMPRESS_LZ77_HUFF");
43262306a36Sopenharmony_ci		if (server->sign)
43362306a36Sopenharmony_ci			seq_printf(m, " signed");
43462306a36Sopenharmony_ci		if (server->posix_ext_supported)
43562306a36Sopenharmony_ci			seq_printf(m, " posix");
43662306a36Sopenharmony_ci		if (server->nosharesock)
43762306a36Sopenharmony_ci			seq_printf(m, " nosharesock");
43862306a36Sopenharmony_ci
43962306a36Sopenharmony_ci		if (server->rdma)
44062306a36Sopenharmony_ci			seq_printf(m, "\nRDMA ");
44162306a36Sopenharmony_ci		seq_printf(m, "\nTCP status: %d Instance: %d"
44262306a36Sopenharmony_ci				"\nLocal Users To Server: %d SecMode: 0x%x Req On Wire: %d",
44362306a36Sopenharmony_ci				server->tcpStatus,
44462306a36Sopenharmony_ci				server->reconnect_instance,
44562306a36Sopenharmony_ci				server->srv_count,
44662306a36Sopenharmony_ci				server->sec_mode, in_flight(server));
44762306a36Sopenharmony_ci#ifdef CONFIG_NET_NS
44862306a36Sopenharmony_ci		if (server->net)
44962306a36Sopenharmony_ci			seq_printf(m, " Net namespace: %u ", server->net->ns.inum);
45062306a36Sopenharmony_ci#endif /* NET_NS */
45162306a36Sopenharmony_ci
45262306a36Sopenharmony_ci		seq_printf(m, "\nIn Send: %d In MaxReq Wait: %d",
45362306a36Sopenharmony_ci				atomic_read(&server->in_send),
45462306a36Sopenharmony_ci				atomic_read(&server->num_waiters));
45562306a36Sopenharmony_ci
45662306a36Sopenharmony_ci		if (server->leaf_fullpath) {
45762306a36Sopenharmony_ci			seq_printf(m, "\nDFS leaf full path: %s",
45862306a36Sopenharmony_ci				   server->leaf_fullpath);
45962306a36Sopenharmony_ci		}
46062306a36Sopenharmony_ci
46162306a36Sopenharmony_ci		seq_printf(m, "\n\n\tSessions: ");
46262306a36Sopenharmony_ci		i = 0;
46362306a36Sopenharmony_ci		list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
46462306a36Sopenharmony_ci			spin_lock(&ses->ses_lock);
46562306a36Sopenharmony_ci			if (ses->ses_status == SES_EXITING) {
46662306a36Sopenharmony_ci				spin_unlock(&ses->ses_lock);
46762306a36Sopenharmony_ci				continue;
46862306a36Sopenharmony_ci			}
46962306a36Sopenharmony_ci			i++;
47062306a36Sopenharmony_ci			if ((ses->serverDomain == NULL) ||
47162306a36Sopenharmony_ci				(ses->serverOS == NULL) ||
47262306a36Sopenharmony_ci				(ses->serverNOS == NULL)) {
47362306a36Sopenharmony_ci				seq_printf(m, "\n\t%d) Address: %s Uses: %d Capability: 0x%x\tSession Status: %d ",
47462306a36Sopenharmony_ci					i, ses->ip_addr, ses->ses_count,
47562306a36Sopenharmony_ci					ses->capabilities, ses->ses_status);
47662306a36Sopenharmony_ci				if (ses->session_flags & SMB2_SESSION_FLAG_IS_GUEST)
47762306a36Sopenharmony_ci					seq_printf(m, "Guest ");
47862306a36Sopenharmony_ci				else if (ses->session_flags & SMB2_SESSION_FLAG_IS_NULL)
47962306a36Sopenharmony_ci					seq_printf(m, "Anonymous ");
48062306a36Sopenharmony_ci			} else {
48162306a36Sopenharmony_ci				seq_printf(m,
48262306a36Sopenharmony_ci				    "\n\t%d) Name: %s  Domain: %s Uses: %d OS: %s "
48362306a36Sopenharmony_ci				    "\n\tNOS: %s\tCapability: 0x%x"
48462306a36Sopenharmony_ci					"\n\tSMB session status: %d ",
48562306a36Sopenharmony_ci				i, ses->ip_addr, ses->serverDomain,
48662306a36Sopenharmony_ci				ses->ses_count, ses->serverOS, ses->serverNOS,
48762306a36Sopenharmony_ci				ses->capabilities, ses->ses_status);
48862306a36Sopenharmony_ci			}
48962306a36Sopenharmony_ci			if (ses->expired_pwd)
49062306a36Sopenharmony_ci				seq_puts(m, "password no longer valid ");
49162306a36Sopenharmony_ci			spin_unlock(&ses->ses_lock);
49262306a36Sopenharmony_ci
49362306a36Sopenharmony_ci			seq_printf(m, "\n\tSecurity type: %s ",
49462306a36Sopenharmony_ci				get_security_type_str(server->ops->select_sectype(server, ses->sectype)));
49562306a36Sopenharmony_ci
49662306a36Sopenharmony_ci			/* dump session id helpful for use with network trace */
49762306a36Sopenharmony_ci			seq_printf(m, " SessionId: 0x%llx", ses->Suid);
49862306a36Sopenharmony_ci			if (ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA) {
49962306a36Sopenharmony_ci				seq_puts(m, " encrypted");
50062306a36Sopenharmony_ci				/* can help in debugging to show encryption type */
50162306a36Sopenharmony_ci				if (server->cipher_type == SMB2_ENCRYPTION_AES256_GCM)
50262306a36Sopenharmony_ci					seq_puts(m, "(gcm256)");
50362306a36Sopenharmony_ci			}
50462306a36Sopenharmony_ci			if (ses->sign)
50562306a36Sopenharmony_ci				seq_puts(m, " signed");
50662306a36Sopenharmony_ci
50762306a36Sopenharmony_ci			seq_printf(m, "\n\tUser: %d Cred User: %d",
50862306a36Sopenharmony_ci				   from_kuid(&init_user_ns, ses->linux_uid),
50962306a36Sopenharmony_ci				   from_kuid(&init_user_ns, ses->cred_uid));
51062306a36Sopenharmony_ci
51162306a36Sopenharmony_ci			if (ses->dfs_root_ses) {
51262306a36Sopenharmony_ci				seq_printf(m, "\n\tDFS root session id: 0x%llx",
51362306a36Sopenharmony_ci					   ses->dfs_root_ses->Suid);
51462306a36Sopenharmony_ci			}
51562306a36Sopenharmony_ci
51662306a36Sopenharmony_ci			spin_lock(&ses->chan_lock);
51762306a36Sopenharmony_ci			if (CIFS_CHAN_NEEDS_RECONNECT(ses, 0))
51862306a36Sopenharmony_ci				seq_puts(m, "\tPrimary channel: DISCONNECTED ");
51962306a36Sopenharmony_ci			if (CIFS_CHAN_IN_RECONNECT(ses, 0))
52062306a36Sopenharmony_ci				seq_puts(m, "\t[RECONNECTING] ");
52162306a36Sopenharmony_ci
52262306a36Sopenharmony_ci			if (ses->chan_count > 1) {
52362306a36Sopenharmony_ci				seq_printf(m, "\n\n\tExtra Channels: %zu ",
52462306a36Sopenharmony_ci					   ses->chan_count-1);
52562306a36Sopenharmony_ci				for (j = 1; j < ses->chan_count; j++) {
52662306a36Sopenharmony_ci					cifs_dump_channel(m, j, &ses->chans[j]);
52762306a36Sopenharmony_ci					if (CIFS_CHAN_NEEDS_RECONNECT(ses, j))
52862306a36Sopenharmony_ci						seq_puts(m, "\tDISCONNECTED ");
52962306a36Sopenharmony_ci					if (CIFS_CHAN_IN_RECONNECT(ses, j))
53062306a36Sopenharmony_ci						seq_puts(m, "\t[RECONNECTING] ");
53162306a36Sopenharmony_ci				}
53262306a36Sopenharmony_ci			}
53362306a36Sopenharmony_ci			spin_unlock(&ses->chan_lock);
53462306a36Sopenharmony_ci
53562306a36Sopenharmony_ci			seq_puts(m, "\n\n\tShares: ");
53662306a36Sopenharmony_ci			j = 0;
53762306a36Sopenharmony_ci
53862306a36Sopenharmony_ci			seq_printf(m, "\n\t%d) IPC: ", j);
53962306a36Sopenharmony_ci			if (ses->tcon_ipc)
54062306a36Sopenharmony_ci				cifs_debug_tcon(m, ses->tcon_ipc);
54162306a36Sopenharmony_ci			else
54262306a36Sopenharmony_ci				seq_puts(m, "none\n");
54362306a36Sopenharmony_ci
54462306a36Sopenharmony_ci			list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
54562306a36Sopenharmony_ci				++j;
54662306a36Sopenharmony_ci				seq_printf(m, "\n\t%d) ", j);
54762306a36Sopenharmony_ci				cifs_debug_tcon(m, tcon);
54862306a36Sopenharmony_ci			}
54962306a36Sopenharmony_ci
55062306a36Sopenharmony_ci			spin_lock(&ses->iface_lock);
55162306a36Sopenharmony_ci			if (ses->iface_count)
55262306a36Sopenharmony_ci				seq_printf(m, "\n\n\tServer interfaces: %zu"
55362306a36Sopenharmony_ci					   "\tLast updated: %lu seconds ago",
55462306a36Sopenharmony_ci					   ses->iface_count,
55562306a36Sopenharmony_ci					   (jiffies - ses->iface_last_update) / HZ);
55662306a36Sopenharmony_ci
55762306a36Sopenharmony_ci			last_iface = list_last_entry(&ses->iface_list,
55862306a36Sopenharmony_ci						     struct cifs_server_iface,
55962306a36Sopenharmony_ci						     iface_head);
56062306a36Sopenharmony_ci			iface_min_speed = last_iface->speed;
56162306a36Sopenharmony_ci
56262306a36Sopenharmony_ci			j = 0;
56362306a36Sopenharmony_ci			list_for_each_entry(iface, &ses->iface_list,
56462306a36Sopenharmony_ci						 iface_head) {
56562306a36Sopenharmony_ci				seq_printf(m, "\n\t%d)", ++j);
56662306a36Sopenharmony_ci				cifs_dump_iface(m, iface);
56762306a36Sopenharmony_ci
56862306a36Sopenharmony_ci				iface_weight = iface->speed / iface_min_speed;
56962306a36Sopenharmony_ci				seq_printf(m, "\t\tWeight (cur,total): (%zu,%zu)"
57062306a36Sopenharmony_ci					   "\n\t\tAllocated channels: %u\n",
57162306a36Sopenharmony_ci					   iface->weight_fulfilled,
57262306a36Sopenharmony_ci					   iface_weight,
57362306a36Sopenharmony_ci					   iface->num_channels);
57462306a36Sopenharmony_ci
57562306a36Sopenharmony_ci				if (is_ses_using_iface(ses, iface))
57662306a36Sopenharmony_ci					seq_puts(m, "\t\t[CONNECTED]\n");
57762306a36Sopenharmony_ci			}
57862306a36Sopenharmony_ci			spin_unlock(&ses->iface_lock);
57962306a36Sopenharmony_ci
58062306a36Sopenharmony_ci			seq_puts(m, "\n\n\tMIDs: ");
58162306a36Sopenharmony_ci			spin_lock(&ses->chan_lock);
58262306a36Sopenharmony_ci			for (j = 0; j < ses->chan_count; j++) {
58362306a36Sopenharmony_ci				chan_server = ses->chans[j].server;
58462306a36Sopenharmony_ci				if (!chan_server)
58562306a36Sopenharmony_ci					continue;
58662306a36Sopenharmony_ci
58762306a36Sopenharmony_ci				if (list_empty(&chan_server->pending_mid_q))
58862306a36Sopenharmony_ci					continue;
58962306a36Sopenharmony_ci
59062306a36Sopenharmony_ci				seq_printf(m, "\n\tServer ConnectionId: 0x%llx",
59162306a36Sopenharmony_ci					   chan_server->conn_id);
59262306a36Sopenharmony_ci				spin_lock(&chan_server->mid_lock);
59362306a36Sopenharmony_ci				list_for_each_entry(mid_entry, &chan_server->pending_mid_q, qhead) {
59462306a36Sopenharmony_ci					seq_printf(m, "\n\t\tState: %d com: %d pid: %d cbdata: %p mid %llu",
59562306a36Sopenharmony_ci						   mid_entry->mid_state,
59662306a36Sopenharmony_ci						   le16_to_cpu(mid_entry->command),
59762306a36Sopenharmony_ci						   mid_entry->pid,
59862306a36Sopenharmony_ci						   mid_entry->callback_data,
59962306a36Sopenharmony_ci						   mid_entry->mid);
60062306a36Sopenharmony_ci				}
60162306a36Sopenharmony_ci				spin_unlock(&chan_server->mid_lock);
60262306a36Sopenharmony_ci			}
60362306a36Sopenharmony_ci			spin_unlock(&ses->chan_lock);
60462306a36Sopenharmony_ci			seq_puts(m, "\n--\n");
60562306a36Sopenharmony_ci		}
60662306a36Sopenharmony_ci		if (i == 0)
60762306a36Sopenharmony_ci			seq_printf(m, "\n\t\t[NONE]");
60862306a36Sopenharmony_ci	}
60962306a36Sopenharmony_ci	if (c == 0)
61062306a36Sopenharmony_ci		seq_printf(m, "\n\t[NONE]");
61162306a36Sopenharmony_ci
61262306a36Sopenharmony_ci	spin_unlock(&cifs_tcp_ses_lock);
61362306a36Sopenharmony_ci	seq_putc(m, '\n');
61462306a36Sopenharmony_ci	cifs_swn_dump(m);
61562306a36Sopenharmony_ci
61662306a36Sopenharmony_ci	/* BB add code to dump additional info such as TCP session info now */
61762306a36Sopenharmony_ci	return 0;
61862306a36Sopenharmony_ci}
61962306a36Sopenharmony_ci
62062306a36Sopenharmony_cistatic ssize_t cifs_stats_proc_write(struct file *file,
62162306a36Sopenharmony_ci		const char __user *buffer, size_t count, loff_t *ppos)
62262306a36Sopenharmony_ci{
62362306a36Sopenharmony_ci	bool bv;
62462306a36Sopenharmony_ci	int rc;
62562306a36Sopenharmony_ci	struct TCP_Server_Info *server;
62662306a36Sopenharmony_ci	struct cifs_ses *ses;
62762306a36Sopenharmony_ci	struct cifs_tcon *tcon;
62862306a36Sopenharmony_ci
62962306a36Sopenharmony_ci	rc = kstrtobool_from_user(buffer, count, &bv);
63062306a36Sopenharmony_ci	if (rc == 0) {
63162306a36Sopenharmony_ci#ifdef CONFIG_CIFS_STATS2
63262306a36Sopenharmony_ci		int i;
63362306a36Sopenharmony_ci
63462306a36Sopenharmony_ci		atomic_set(&total_buf_alloc_count, 0);
63562306a36Sopenharmony_ci		atomic_set(&total_small_buf_alloc_count, 0);
63662306a36Sopenharmony_ci#endif /* CONFIG_CIFS_STATS2 */
63762306a36Sopenharmony_ci		atomic_set(&tcpSesReconnectCount, 0);
63862306a36Sopenharmony_ci		atomic_set(&tconInfoReconnectCount, 0);
63962306a36Sopenharmony_ci
64062306a36Sopenharmony_ci		spin_lock(&GlobalMid_Lock);
64162306a36Sopenharmony_ci		GlobalMaxActiveXid = 0;
64262306a36Sopenharmony_ci		GlobalCurrentXid = 0;
64362306a36Sopenharmony_ci		spin_unlock(&GlobalMid_Lock);
64462306a36Sopenharmony_ci		spin_lock(&cifs_tcp_ses_lock);
64562306a36Sopenharmony_ci		list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
64662306a36Sopenharmony_ci			server->max_in_flight = 0;
64762306a36Sopenharmony_ci#ifdef CONFIG_CIFS_STATS2
64862306a36Sopenharmony_ci			for (i = 0; i < NUMBER_OF_SMB2_COMMANDS; i++) {
64962306a36Sopenharmony_ci				atomic_set(&server->num_cmds[i], 0);
65062306a36Sopenharmony_ci				atomic_set(&server->smb2slowcmd[i], 0);
65162306a36Sopenharmony_ci				server->time_per_cmd[i] = 0;
65262306a36Sopenharmony_ci				server->slowest_cmd[i] = 0;
65362306a36Sopenharmony_ci				server->fastest_cmd[0] = 0;
65462306a36Sopenharmony_ci			}
65562306a36Sopenharmony_ci#endif /* CONFIG_CIFS_STATS2 */
65662306a36Sopenharmony_ci			list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
65762306a36Sopenharmony_ci				list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
65862306a36Sopenharmony_ci					atomic_set(&tcon->num_smbs_sent, 0);
65962306a36Sopenharmony_ci					spin_lock(&tcon->stat_lock);
66062306a36Sopenharmony_ci					tcon->bytes_read = 0;
66162306a36Sopenharmony_ci					tcon->bytes_written = 0;
66262306a36Sopenharmony_ci					spin_unlock(&tcon->stat_lock);
66362306a36Sopenharmony_ci					if (server->ops->clear_stats)
66462306a36Sopenharmony_ci						server->ops->clear_stats(tcon);
66562306a36Sopenharmony_ci				}
66662306a36Sopenharmony_ci			}
66762306a36Sopenharmony_ci		}
66862306a36Sopenharmony_ci		spin_unlock(&cifs_tcp_ses_lock);
66962306a36Sopenharmony_ci	} else {
67062306a36Sopenharmony_ci		return rc;
67162306a36Sopenharmony_ci	}
67262306a36Sopenharmony_ci
67362306a36Sopenharmony_ci	return count;
67462306a36Sopenharmony_ci}
67562306a36Sopenharmony_ci
67662306a36Sopenharmony_cistatic int cifs_stats_proc_show(struct seq_file *m, void *v)
67762306a36Sopenharmony_ci{
67862306a36Sopenharmony_ci	int i;
67962306a36Sopenharmony_ci#ifdef CONFIG_CIFS_STATS2
68062306a36Sopenharmony_ci	int j;
68162306a36Sopenharmony_ci#endif /* STATS2 */
68262306a36Sopenharmony_ci	struct TCP_Server_Info *server;
68362306a36Sopenharmony_ci	struct cifs_ses *ses;
68462306a36Sopenharmony_ci	struct cifs_tcon *tcon;
68562306a36Sopenharmony_ci
68662306a36Sopenharmony_ci	seq_printf(m, "Resources in use\nCIFS Session: %d\n",
68762306a36Sopenharmony_ci			sesInfoAllocCount.counter);
68862306a36Sopenharmony_ci	seq_printf(m, "Share (unique mount targets): %d\n",
68962306a36Sopenharmony_ci			tconInfoAllocCount.counter);
69062306a36Sopenharmony_ci	seq_printf(m, "SMB Request/Response Buffer: %d Pool size: %d\n",
69162306a36Sopenharmony_ci			buf_alloc_count.counter,
69262306a36Sopenharmony_ci			cifs_min_rcv + tcpSesAllocCount.counter);
69362306a36Sopenharmony_ci	seq_printf(m, "SMB Small Req/Resp Buffer: %d Pool size: %d\n",
69462306a36Sopenharmony_ci			small_buf_alloc_count.counter, cifs_min_small);
69562306a36Sopenharmony_ci#ifdef CONFIG_CIFS_STATS2
69662306a36Sopenharmony_ci	seq_printf(m, "Total Large %d Small %d Allocations\n",
69762306a36Sopenharmony_ci				atomic_read(&total_buf_alloc_count),
69862306a36Sopenharmony_ci				atomic_read(&total_small_buf_alloc_count));
69962306a36Sopenharmony_ci#endif /* CONFIG_CIFS_STATS2 */
70062306a36Sopenharmony_ci
70162306a36Sopenharmony_ci	seq_printf(m, "Operations (MIDs): %d\n", atomic_read(&mid_count));
70262306a36Sopenharmony_ci	seq_printf(m,
70362306a36Sopenharmony_ci		"\n%d session %d share reconnects\n",
70462306a36Sopenharmony_ci		tcpSesReconnectCount.counter, tconInfoReconnectCount.counter);
70562306a36Sopenharmony_ci
70662306a36Sopenharmony_ci	seq_printf(m,
70762306a36Sopenharmony_ci		"Total vfs operations: %d maximum at one time: %d\n",
70862306a36Sopenharmony_ci		GlobalCurrentXid, GlobalMaxActiveXid);
70962306a36Sopenharmony_ci
71062306a36Sopenharmony_ci	i = 0;
71162306a36Sopenharmony_ci	spin_lock(&cifs_tcp_ses_lock);
71262306a36Sopenharmony_ci	list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
71362306a36Sopenharmony_ci		seq_printf(m, "\nMax requests in flight: %d", server->max_in_flight);
71462306a36Sopenharmony_ci#ifdef CONFIG_CIFS_STATS2
71562306a36Sopenharmony_ci		seq_puts(m, "\nTotal time spent processing by command. Time ");
71662306a36Sopenharmony_ci		seq_printf(m, "units are jiffies (%d per second)\n", HZ);
71762306a36Sopenharmony_ci		seq_puts(m, "  SMB3 CMD\tNumber\tTotal Time\tFastest\tSlowest\n");
71862306a36Sopenharmony_ci		seq_puts(m, "  --------\t------\t----------\t-------\t-------\n");
71962306a36Sopenharmony_ci		for (j = 0; j < NUMBER_OF_SMB2_COMMANDS; j++)
72062306a36Sopenharmony_ci			seq_printf(m, "  %d\t\t%d\t%llu\t\t%u\t%u\n", j,
72162306a36Sopenharmony_ci				atomic_read(&server->num_cmds[j]),
72262306a36Sopenharmony_ci				server->time_per_cmd[j],
72362306a36Sopenharmony_ci				server->fastest_cmd[j],
72462306a36Sopenharmony_ci				server->slowest_cmd[j]);
72562306a36Sopenharmony_ci		for (j = 0; j < NUMBER_OF_SMB2_COMMANDS; j++)
72662306a36Sopenharmony_ci			if (atomic_read(&server->smb2slowcmd[j])) {
72762306a36Sopenharmony_ci				spin_lock(&server->srv_lock);
72862306a36Sopenharmony_ci				seq_printf(m, "  %d slow responses from %s for command %d\n",
72962306a36Sopenharmony_ci					atomic_read(&server->smb2slowcmd[j]),
73062306a36Sopenharmony_ci					server->hostname, j);
73162306a36Sopenharmony_ci				spin_unlock(&server->srv_lock);
73262306a36Sopenharmony_ci			}
73362306a36Sopenharmony_ci#endif /* STATS2 */
73462306a36Sopenharmony_ci		list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
73562306a36Sopenharmony_ci			list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
73662306a36Sopenharmony_ci				i++;
73762306a36Sopenharmony_ci				seq_printf(m, "\n%d) %s", i, tcon->tree_name);
73862306a36Sopenharmony_ci				if (tcon->need_reconnect)
73962306a36Sopenharmony_ci					seq_puts(m, "\tDISCONNECTED ");
74062306a36Sopenharmony_ci				seq_printf(m, "\nSMBs: %d",
74162306a36Sopenharmony_ci					   atomic_read(&tcon->num_smbs_sent));
74262306a36Sopenharmony_ci				if (server->ops->print_stats)
74362306a36Sopenharmony_ci					server->ops->print_stats(m, tcon);
74462306a36Sopenharmony_ci			}
74562306a36Sopenharmony_ci		}
74662306a36Sopenharmony_ci	}
74762306a36Sopenharmony_ci	spin_unlock(&cifs_tcp_ses_lock);
74862306a36Sopenharmony_ci
74962306a36Sopenharmony_ci	seq_putc(m, '\n');
75062306a36Sopenharmony_ci	return 0;
75162306a36Sopenharmony_ci}
75262306a36Sopenharmony_ci
75362306a36Sopenharmony_cistatic int cifs_stats_proc_open(struct inode *inode, struct file *file)
75462306a36Sopenharmony_ci{
75562306a36Sopenharmony_ci	return single_open(file, cifs_stats_proc_show, NULL);
75662306a36Sopenharmony_ci}
75762306a36Sopenharmony_ci
75862306a36Sopenharmony_cistatic const struct proc_ops cifs_stats_proc_ops = {
75962306a36Sopenharmony_ci	.proc_open	= cifs_stats_proc_open,
76062306a36Sopenharmony_ci	.proc_read	= seq_read,
76162306a36Sopenharmony_ci	.proc_lseek	= seq_lseek,
76262306a36Sopenharmony_ci	.proc_release	= single_release,
76362306a36Sopenharmony_ci	.proc_write	= cifs_stats_proc_write,
76462306a36Sopenharmony_ci};
76562306a36Sopenharmony_ci
76662306a36Sopenharmony_ci#ifdef CONFIG_CIFS_SMB_DIRECT
76762306a36Sopenharmony_ci#define PROC_FILE_DEFINE(name) \
76862306a36Sopenharmony_cistatic ssize_t name##_write(struct file *file, const char __user *buffer, \
76962306a36Sopenharmony_ci	size_t count, loff_t *ppos) \
77062306a36Sopenharmony_ci{ \
77162306a36Sopenharmony_ci	int rc; \
77262306a36Sopenharmony_ci	rc = kstrtoint_from_user(buffer, count, 10, & name); \
77362306a36Sopenharmony_ci	if (rc) \
77462306a36Sopenharmony_ci		return rc; \
77562306a36Sopenharmony_ci	return count; \
77662306a36Sopenharmony_ci} \
77762306a36Sopenharmony_cistatic int name##_proc_show(struct seq_file *m, void *v) \
77862306a36Sopenharmony_ci{ \
77962306a36Sopenharmony_ci	seq_printf(m, "%d\n", name ); \
78062306a36Sopenharmony_ci	return 0; \
78162306a36Sopenharmony_ci} \
78262306a36Sopenharmony_cistatic int name##_open(struct inode *inode, struct file *file) \
78362306a36Sopenharmony_ci{ \
78462306a36Sopenharmony_ci	return single_open(file, name##_proc_show, NULL); \
78562306a36Sopenharmony_ci} \
78662306a36Sopenharmony_ci\
78762306a36Sopenharmony_cistatic const struct proc_ops cifs_##name##_proc_fops = { \
78862306a36Sopenharmony_ci	.proc_open	= name##_open, \
78962306a36Sopenharmony_ci	.proc_read	= seq_read, \
79062306a36Sopenharmony_ci	.proc_lseek	= seq_lseek, \
79162306a36Sopenharmony_ci	.proc_release	= single_release, \
79262306a36Sopenharmony_ci	.proc_write	= name##_write, \
79362306a36Sopenharmony_ci}
79462306a36Sopenharmony_ci
79562306a36Sopenharmony_ciPROC_FILE_DEFINE(rdma_readwrite_threshold);
79662306a36Sopenharmony_ciPROC_FILE_DEFINE(smbd_max_frmr_depth);
79762306a36Sopenharmony_ciPROC_FILE_DEFINE(smbd_keep_alive_interval);
79862306a36Sopenharmony_ciPROC_FILE_DEFINE(smbd_max_receive_size);
79962306a36Sopenharmony_ciPROC_FILE_DEFINE(smbd_max_fragmented_recv_size);
80062306a36Sopenharmony_ciPROC_FILE_DEFINE(smbd_max_send_size);
80162306a36Sopenharmony_ciPROC_FILE_DEFINE(smbd_send_credit_target);
80262306a36Sopenharmony_ciPROC_FILE_DEFINE(smbd_receive_credit_max);
80362306a36Sopenharmony_ci#endif
80462306a36Sopenharmony_ci
80562306a36Sopenharmony_cistatic struct proc_dir_entry *proc_fs_cifs;
80662306a36Sopenharmony_cistatic const struct proc_ops cifsFYI_proc_ops;
80762306a36Sopenharmony_cistatic const struct proc_ops cifs_lookup_cache_proc_ops;
80862306a36Sopenharmony_cistatic const struct proc_ops traceSMB_proc_ops;
80962306a36Sopenharmony_cistatic const struct proc_ops cifs_security_flags_proc_ops;
81062306a36Sopenharmony_cistatic const struct proc_ops cifs_linux_ext_proc_ops;
81162306a36Sopenharmony_cistatic const struct proc_ops cifs_mount_params_proc_ops;
81262306a36Sopenharmony_ci
81362306a36Sopenharmony_civoid
81462306a36Sopenharmony_cicifs_proc_init(void)
81562306a36Sopenharmony_ci{
81662306a36Sopenharmony_ci	proc_fs_cifs = proc_mkdir("fs/cifs", NULL);
81762306a36Sopenharmony_ci	if (proc_fs_cifs == NULL)
81862306a36Sopenharmony_ci		return;
81962306a36Sopenharmony_ci
82062306a36Sopenharmony_ci	proc_create_single("DebugData", 0, proc_fs_cifs,
82162306a36Sopenharmony_ci			cifs_debug_data_proc_show);
82262306a36Sopenharmony_ci
82362306a36Sopenharmony_ci	proc_create_single("open_files", 0400, proc_fs_cifs,
82462306a36Sopenharmony_ci			cifs_debug_files_proc_show);
82562306a36Sopenharmony_ci
82662306a36Sopenharmony_ci	proc_create("Stats", 0644, proc_fs_cifs, &cifs_stats_proc_ops);
82762306a36Sopenharmony_ci	proc_create("cifsFYI", 0644, proc_fs_cifs, &cifsFYI_proc_ops);
82862306a36Sopenharmony_ci	proc_create("traceSMB", 0644, proc_fs_cifs, &traceSMB_proc_ops);
82962306a36Sopenharmony_ci	proc_create("LinuxExtensionsEnabled", 0644, proc_fs_cifs,
83062306a36Sopenharmony_ci		    &cifs_linux_ext_proc_ops);
83162306a36Sopenharmony_ci	proc_create("SecurityFlags", 0644, proc_fs_cifs,
83262306a36Sopenharmony_ci		    &cifs_security_flags_proc_ops);
83362306a36Sopenharmony_ci	proc_create("LookupCacheEnabled", 0644, proc_fs_cifs,
83462306a36Sopenharmony_ci		    &cifs_lookup_cache_proc_ops);
83562306a36Sopenharmony_ci
83662306a36Sopenharmony_ci	proc_create("mount_params", 0444, proc_fs_cifs, &cifs_mount_params_proc_ops);
83762306a36Sopenharmony_ci
83862306a36Sopenharmony_ci#ifdef CONFIG_CIFS_DFS_UPCALL
83962306a36Sopenharmony_ci	proc_create("dfscache", 0644, proc_fs_cifs, &dfscache_proc_ops);
84062306a36Sopenharmony_ci#endif
84162306a36Sopenharmony_ci
84262306a36Sopenharmony_ci#ifdef CONFIG_CIFS_SMB_DIRECT
84362306a36Sopenharmony_ci	proc_create("rdma_readwrite_threshold", 0644, proc_fs_cifs,
84462306a36Sopenharmony_ci		&cifs_rdma_readwrite_threshold_proc_fops);
84562306a36Sopenharmony_ci	proc_create("smbd_max_frmr_depth", 0644, proc_fs_cifs,
84662306a36Sopenharmony_ci		&cifs_smbd_max_frmr_depth_proc_fops);
84762306a36Sopenharmony_ci	proc_create("smbd_keep_alive_interval", 0644, proc_fs_cifs,
84862306a36Sopenharmony_ci		&cifs_smbd_keep_alive_interval_proc_fops);
84962306a36Sopenharmony_ci	proc_create("smbd_max_receive_size", 0644, proc_fs_cifs,
85062306a36Sopenharmony_ci		&cifs_smbd_max_receive_size_proc_fops);
85162306a36Sopenharmony_ci	proc_create("smbd_max_fragmented_recv_size", 0644, proc_fs_cifs,
85262306a36Sopenharmony_ci		&cifs_smbd_max_fragmented_recv_size_proc_fops);
85362306a36Sopenharmony_ci	proc_create("smbd_max_send_size", 0644, proc_fs_cifs,
85462306a36Sopenharmony_ci		&cifs_smbd_max_send_size_proc_fops);
85562306a36Sopenharmony_ci	proc_create("smbd_send_credit_target", 0644, proc_fs_cifs,
85662306a36Sopenharmony_ci		&cifs_smbd_send_credit_target_proc_fops);
85762306a36Sopenharmony_ci	proc_create("smbd_receive_credit_max", 0644, proc_fs_cifs,
85862306a36Sopenharmony_ci		&cifs_smbd_receive_credit_max_proc_fops);
85962306a36Sopenharmony_ci#endif
86062306a36Sopenharmony_ci}
86162306a36Sopenharmony_ci
86262306a36Sopenharmony_civoid
86362306a36Sopenharmony_cicifs_proc_clean(void)
86462306a36Sopenharmony_ci{
86562306a36Sopenharmony_ci	if (proc_fs_cifs == NULL)
86662306a36Sopenharmony_ci		return;
86762306a36Sopenharmony_ci
86862306a36Sopenharmony_ci	remove_proc_entry("DebugData", proc_fs_cifs);
86962306a36Sopenharmony_ci	remove_proc_entry("open_files", proc_fs_cifs);
87062306a36Sopenharmony_ci	remove_proc_entry("cifsFYI", proc_fs_cifs);
87162306a36Sopenharmony_ci	remove_proc_entry("traceSMB", proc_fs_cifs);
87262306a36Sopenharmony_ci	remove_proc_entry("Stats", proc_fs_cifs);
87362306a36Sopenharmony_ci	remove_proc_entry("SecurityFlags", proc_fs_cifs);
87462306a36Sopenharmony_ci	remove_proc_entry("LinuxExtensionsEnabled", proc_fs_cifs);
87562306a36Sopenharmony_ci	remove_proc_entry("LookupCacheEnabled", proc_fs_cifs);
87662306a36Sopenharmony_ci	remove_proc_entry("mount_params", proc_fs_cifs);
87762306a36Sopenharmony_ci
87862306a36Sopenharmony_ci#ifdef CONFIG_CIFS_DFS_UPCALL
87962306a36Sopenharmony_ci	remove_proc_entry("dfscache", proc_fs_cifs);
88062306a36Sopenharmony_ci#endif
88162306a36Sopenharmony_ci#ifdef CONFIG_CIFS_SMB_DIRECT
88262306a36Sopenharmony_ci	remove_proc_entry("rdma_readwrite_threshold", proc_fs_cifs);
88362306a36Sopenharmony_ci	remove_proc_entry("smbd_max_frmr_depth", proc_fs_cifs);
88462306a36Sopenharmony_ci	remove_proc_entry("smbd_keep_alive_interval", proc_fs_cifs);
88562306a36Sopenharmony_ci	remove_proc_entry("smbd_max_receive_size", proc_fs_cifs);
88662306a36Sopenharmony_ci	remove_proc_entry("smbd_max_fragmented_recv_size", proc_fs_cifs);
88762306a36Sopenharmony_ci	remove_proc_entry("smbd_max_send_size", proc_fs_cifs);
88862306a36Sopenharmony_ci	remove_proc_entry("smbd_send_credit_target", proc_fs_cifs);
88962306a36Sopenharmony_ci	remove_proc_entry("smbd_receive_credit_max", proc_fs_cifs);
89062306a36Sopenharmony_ci#endif
89162306a36Sopenharmony_ci	remove_proc_entry("fs/cifs", NULL);
89262306a36Sopenharmony_ci}
89362306a36Sopenharmony_ci
89462306a36Sopenharmony_cistatic int cifsFYI_proc_show(struct seq_file *m, void *v)
89562306a36Sopenharmony_ci{
89662306a36Sopenharmony_ci	seq_printf(m, "%d\n", cifsFYI);
89762306a36Sopenharmony_ci	return 0;
89862306a36Sopenharmony_ci}
89962306a36Sopenharmony_ci
90062306a36Sopenharmony_cistatic int cifsFYI_proc_open(struct inode *inode, struct file *file)
90162306a36Sopenharmony_ci{
90262306a36Sopenharmony_ci	return single_open(file, cifsFYI_proc_show, NULL);
90362306a36Sopenharmony_ci}
90462306a36Sopenharmony_ci
90562306a36Sopenharmony_cistatic ssize_t cifsFYI_proc_write(struct file *file, const char __user *buffer,
90662306a36Sopenharmony_ci		size_t count, loff_t *ppos)
90762306a36Sopenharmony_ci{
90862306a36Sopenharmony_ci	char c[2] = { '\0' };
90962306a36Sopenharmony_ci	bool bv;
91062306a36Sopenharmony_ci	int rc;
91162306a36Sopenharmony_ci
91262306a36Sopenharmony_ci	rc = get_user(c[0], buffer);
91362306a36Sopenharmony_ci	if (rc)
91462306a36Sopenharmony_ci		return rc;
91562306a36Sopenharmony_ci	if (kstrtobool(c, &bv) == 0)
91662306a36Sopenharmony_ci		cifsFYI = bv;
91762306a36Sopenharmony_ci	else if ((c[0] > '1') && (c[0] <= '9'))
91862306a36Sopenharmony_ci		cifsFYI = (int) (c[0] - '0'); /* see cifs_debug.h for meanings */
91962306a36Sopenharmony_ci	else
92062306a36Sopenharmony_ci		return -EINVAL;
92162306a36Sopenharmony_ci
92262306a36Sopenharmony_ci	return count;
92362306a36Sopenharmony_ci}
92462306a36Sopenharmony_ci
92562306a36Sopenharmony_cistatic const struct proc_ops cifsFYI_proc_ops = {
92662306a36Sopenharmony_ci	.proc_open	= cifsFYI_proc_open,
92762306a36Sopenharmony_ci	.proc_read	= seq_read,
92862306a36Sopenharmony_ci	.proc_lseek	= seq_lseek,
92962306a36Sopenharmony_ci	.proc_release	= single_release,
93062306a36Sopenharmony_ci	.proc_write	= cifsFYI_proc_write,
93162306a36Sopenharmony_ci};
93262306a36Sopenharmony_ci
93362306a36Sopenharmony_cistatic int cifs_linux_ext_proc_show(struct seq_file *m, void *v)
93462306a36Sopenharmony_ci{
93562306a36Sopenharmony_ci	seq_printf(m, "%d\n", linuxExtEnabled);
93662306a36Sopenharmony_ci	return 0;
93762306a36Sopenharmony_ci}
93862306a36Sopenharmony_ci
93962306a36Sopenharmony_cistatic int cifs_linux_ext_proc_open(struct inode *inode, struct file *file)
94062306a36Sopenharmony_ci{
94162306a36Sopenharmony_ci	return single_open(file, cifs_linux_ext_proc_show, NULL);
94262306a36Sopenharmony_ci}
94362306a36Sopenharmony_ci
94462306a36Sopenharmony_cistatic ssize_t cifs_linux_ext_proc_write(struct file *file,
94562306a36Sopenharmony_ci		const char __user *buffer, size_t count, loff_t *ppos)
94662306a36Sopenharmony_ci{
94762306a36Sopenharmony_ci	int rc;
94862306a36Sopenharmony_ci
94962306a36Sopenharmony_ci	rc = kstrtobool_from_user(buffer, count, &linuxExtEnabled);
95062306a36Sopenharmony_ci	if (rc)
95162306a36Sopenharmony_ci		return rc;
95262306a36Sopenharmony_ci
95362306a36Sopenharmony_ci	return count;
95462306a36Sopenharmony_ci}
95562306a36Sopenharmony_ci
95662306a36Sopenharmony_cistatic const struct proc_ops cifs_linux_ext_proc_ops = {
95762306a36Sopenharmony_ci	.proc_open	= cifs_linux_ext_proc_open,
95862306a36Sopenharmony_ci	.proc_read	= seq_read,
95962306a36Sopenharmony_ci	.proc_lseek	= seq_lseek,
96062306a36Sopenharmony_ci	.proc_release	= single_release,
96162306a36Sopenharmony_ci	.proc_write	= cifs_linux_ext_proc_write,
96262306a36Sopenharmony_ci};
96362306a36Sopenharmony_ci
96462306a36Sopenharmony_cistatic int cifs_lookup_cache_proc_show(struct seq_file *m, void *v)
96562306a36Sopenharmony_ci{
96662306a36Sopenharmony_ci	seq_printf(m, "%d\n", lookupCacheEnabled);
96762306a36Sopenharmony_ci	return 0;
96862306a36Sopenharmony_ci}
96962306a36Sopenharmony_ci
97062306a36Sopenharmony_cistatic int cifs_lookup_cache_proc_open(struct inode *inode, struct file *file)
97162306a36Sopenharmony_ci{
97262306a36Sopenharmony_ci	return single_open(file, cifs_lookup_cache_proc_show, NULL);
97362306a36Sopenharmony_ci}
97462306a36Sopenharmony_ci
97562306a36Sopenharmony_cistatic ssize_t cifs_lookup_cache_proc_write(struct file *file,
97662306a36Sopenharmony_ci		const char __user *buffer, size_t count, loff_t *ppos)
97762306a36Sopenharmony_ci{
97862306a36Sopenharmony_ci	int rc;
97962306a36Sopenharmony_ci
98062306a36Sopenharmony_ci	rc = kstrtobool_from_user(buffer, count, &lookupCacheEnabled);
98162306a36Sopenharmony_ci	if (rc)
98262306a36Sopenharmony_ci		return rc;
98362306a36Sopenharmony_ci
98462306a36Sopenharmony_ci	return count;
98562306a36Sopenharmony_ci}
98662306a36Sopenharmony_ci
98762306a36Sopenharmony_cistatic const struct proc_ops cifs_lookup_cache_proc_ops = {
98862306a36Sopenharmony_ci	.proc_open	= cifs_lookup_cache_proc_open,
98962306a36Sopenharmony_ci	.proc_read	= seq_read,
99062306a36Sopenharmony_ci	.proc_lseek	= seq_lseek,
99162306a36Sopenharmony_ci	.proc_release	= single_release,
99262306a36Sopenharmony_ci	.proc_write	= cifs_lookup_cache_proc_write,
99362306a36Sopenharmony_ci};
99462306a36Sopenharmony_ci
99562306a36Sopenharmony_cistatic int traceSMB_proc_show(struct seq_file *m, void *v)
99662306a36Sopenharmony_ci{
99762306a36Sopenharmony_ci	seq_printf(m, "%d\n", traceSMB);
99862306a36Sopenharmony_ci	return 0;
99962306a36Sopenharmony_ci}
100062306a36Sopenharmony_ci
100162306a36Sopenharmony_cistatic int traceSMB_proc_open(struct inode *inode, struct file *file)
100262306a36Sopenharmony_ci{
100362306a36Sopenharmony_ci	return single_open(file, traceSMB_proc_show, NULL);
100462306a36Sopenharmony_ci}
100562306a36Sopenharmony_ci
100662306a36Sopenharmony_cistatic ssize_t traceSMB_proc_write(struct file *file, const char __user *buffer,
100762306a36Sopenharmony_ci		size_t count, loff_t *ppos)
100862306a36Sopenharmony_ci{
100962306a36Sopenharmony_ci	int rc;
101062306a36Sopenharmony_ci
101162306a36Sopenharmony_ci	rc = kstrtobool_from_user(buffer, count, &traceSMB);
101262306a36Sopenharmony_ci	if (rc)
101362306a36Sopenharmony_ci		return rc;
101462306a36Sopenharmony_ci
101562306a36Sopenharmony_ci	return count;
101662306a36Sopenharmony_ci}
101762306a36Sopenharmony_ci
101862306a36Sopenharmony_cistatic const struct proc_ops traceSMB_proc_ops = {
101962306a36Sopenharmony_ci	.proc_open	= traceSMB_proc_open,
102062306a36Sopenharmony_ci	.proc_read	= seq_read,
102162306a36Sopenharmony_ci	.proc_lseek	= seq_lseek,
102262306a36Sopenharmony_ci	.proc_release	= single_release,
102362306a36Sopenharmony_ci	.proc_write	= traceSMB_proc_write,
102462306a36Sopenharmony_ci};
102562306a36Sopenharmony_ci
102662306a36Sopenharmony_cistatic int cifs_security_flags_proc_show(struct seq_file *m, void *v)
102762306a36Sopenharmony_ci{
102862306a36Sopenharmony_ci	seq_printf(m, "0x%x\n", global_secflags);
102962306a36Sopenharmony_ci	return 0;
103062306a36Sopenharmony_ci}
103162306a36Sopenharmony_ci
103262306a36Sopenharmony_cistatic int cifs_security_flags_proc_open(struct inode *inode, struct file *file)
103362306a36Sopenharmony_ci{
103462306a36Sopenharmony_ci	return single_open(file, cifs_security_flags_proc_show, NULL);
103562306a36Sopenharmony_ci}
103662306a36Sopenharmony_ci
103762306a36Sopenharmony_ci/*
103862306a36Sopenharmony_ci * Ensure that if someone sets a MUST flag, that we disable all other MAY
103962306a36Sopenharmony_ci * flags except for the ones corresponding to the given MUST flag. If there are
104062306a36Sopenharmony_ci * multiple MUST flags, then try to prefer more secure ones.
104162306a36Sopenharmony_ci */
104262306a36Sopenharmony_cistatic void
104362306a36Sopenharmony_cicifs_security_flags_handle_must_flags(unsigned int *flags)
104462306a36Sopenharmony_ci{
104562306a36Sopenharmony_ci	unsigned int signflags = *flags & CIFSSEC_MUST_SIGN;
104662306a36Sopenharmony_ci
104762306a36Sopenharmony_ci	if ((*flags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
104862306a36Sopenharmony_ci		*flags = CIFSSEC_MUST_KRB5;
104962306a36Sopenharmony_ci	else if ((*flags & CIFSSEC_MUST_NTLMSSP) == CIFSSEC_MUST_NTLMSSP)
105062306a36Sopenharmony_ci		*flags = CIFSSEC_MUST_NTLMSSP;
105162306a36Sopenharmony_ci	else if ((*flags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
105262306a36Sopenharmony_ci		*flags = CIFSSEC_MUST_NTLMV2;
105362306a36Sopenharmony_ci
105462306a36Sopenharmony_ci	*flags |= signflags;
105562306a36Sopenharmony_ci}
105662306a36Sopenharmony_ci
105762306a36Sopenharmony_cistatic ssize_t cifs_security_flags_proc_write(struct file *file,
105862306a36Sopenharmony_ci		const char __user *buffer, size_t count, loff_t *ppos)
105962306a36Sopenharmony_ci{
106062306a36Sopenharmony_ci	int rc;
106162306a36Sopenharmony_ci	unsigned int flags;
106262306a36Sopenharmony_ci	char flags_string[12];
106362306a36Sopenharmony_ci	bool bv;
106462306a36Sopenharmony_ci
106562306a36Sopenharmony_ci	if ((count < 1) || (count > 11))
106662306a36Sopenharmony_ci		return -EINVAL;
106762306a36Sopenharmony_ci
106862306a36Sopenharmony_ci	memset(flags_string, 0, 12);
106962306a36Sopenharmony_ci
107062306a36Sopenharmony_ci	if (copy_from_user(flags_string, buffer, count))
107162306a36Sopenharmony_ci		return -EFAULT;
107262306a36Sopenharmony_ci
107362306a36Sopenharmony_ci	if (count < 3) {
107462306a36Sopenharmony_ci		/* single char or single char followed by null */
107562306a36Sopenharmony_ci		if (kstrtobool(flags_string, &bv) == 0) {
107662306a36Sopenharmony_ci			global_secflags = bv ? CIFSSEC_MAX : CIFSSEC_DEF;
107762306a36Sopenharmony_ci			return count;
107862306a36Sopenharmony_ci		} else if (!isdigit(flags_string[0])) {
107962306a36Sopenharmony_ci			cifs_dbg(VFS, "Invalid SecurityFlags: %s\n",
108062306a36Sopenharmony_ci					flags_string);
108162306a36Sopenharmony_ci			return -EINVAL;
108262306a36Sopenharmony_ci		}
108362306a36Sopenharmony_ci	}
108462306a36Sopenharmony_ci
108562306a36Sopenharmony_ci	/* else we have a number */
108662306a36Sopenharmony_ci	rc = kstrtouint(flags_string, 0, &flags);
108762306a36Sopenharmony_ci	if (rc) {
108862306a36Sopenharmony_ci		cifs_dbg(VFS, "Invalid SecurityFlags: %s\n",
108962306a36Sopenharmony_ci				flags_string);
109062306a36Sopenharmony_ci		return rc;
109162306a36Sopenharmony_ci	}
109262306a36Sopenharmony_ci
109362306a36Sopenharmony_ci	cifs_dbg(FYI, "sec flags 0x%x\n", flags);
109462306a36Sopenharmony_ci
109562306a36Sopenharmony_ci	if (flags == 0)  {
109662306a36Sopenharmony_ci		cifs_dbg(VFS, "Invalid SecurityFlags: %s\n", flags_string);
109762306a36Sopenharmony_ci		return -EINVAL;
109862306a36Sopenharmony_ci	}
109962306a36Sopenharmony_ci
110062306a36Sopenharmony_ci	if (flags & ~CIFSSEC_MASK) {
110162306a36Sopenharmony_ci		cifs_dbg(VFS, "Unsupported security flags: 0x%x\n",
110262306a36Sopenharmony_ci			 flags & ~CIFSSEC_MASK);
110362306a36Sopenharmony_ci		return -EINVAL;
110462306a36Sopenharmony_ci	}
110562306a36Sopenharmony_ci
110662306a36Sopenharmony_ci	cifs_security_flags_handle_must_flags(&flags);
110762306a36Sopenharmony_ci
110862306a36Sopenharmony_ci	/* flags look ok - update the global security flags for cifs module */
110962306a36Sopenharmony_ci	global_secflags = flags;
111062306a36Sopenharmony_ci	if (global_secflags & CIFSSEC_MUST_SIGN) {
111162306a36Sopenharmony_ci		/* requiring signing implies signing is allowed */
111262306a36Sopenharmony_ci		global_secflags |= CIFSSEC_MAY_SIGN;
111362306a36Sopenharmony_ci		cifs_dbg(FYI, "packet signing now required\n");
111462306a36Sopenharmony_ci	} else if ((global_secflags & CIFSSEC_MAY_SIGN) == 0) {
111562306a36Sopenharmony_ci		cifs_dbg(FYI, "packet signing disabled\n");
111662306a36Sopenharmony_ci	}
111762306a36Sopenharmony_ci	/* BB should we turn on MAY flags for other MUST options? */
111862306a36Sopenharmony_ci	return count;
111962306a36Sopenharmony_ci}
112062306a36Sopenharmony_ci
112162306a36Sopenharmony_cistatic const struct proc_ops cifs_security_flags_proc_ops = {
112262306a36Sopenharmony_ci	.proc_open	= cifs_security_flags_proc_open,
112362306a36Sopenharmony_ci	.proc_read	= seq_read,
112462306a36Sopenharmony_ci	.proc_lseek	= seq_lseek,
112562306a36Sopenharmony_ci	.proc_release	= single_release,
112662306a36Sopenharmony_ci	.proc_write	= cifs_security_flags_proc_write,
112762306a36Sopenharmony_ci};
112862306a36Sopenharmony_ci
112962306a36Sopenharmony_ci/* To make it easier to debug, can help to show mount params */
113062306a36Sopenharmony_cistatic int cifs_mount_params_proc_show(struct seq_file *m, void *v)
113162306a36Sopenharmony_ci{
113262306a36Sopenharmony_ci	const struct fs_parameter_spec *p;
113362306a36Sopenharmony_ci	const char *type;
113462306a36Sopenharmony_ci
113562306a36Sopenharmony_ci	for (p = smb3_fs_parameters; p->name; p++) {
113662306a36Sopenharmony_ci		/* cannot use switch with pointers... */
113762306a36Sopenharmony_ci		if (!p->type) {
113862306a36Sopenharmony_ci			if (p->flags == fs_param_neg_with_no)
113962306a36Sopenharmony_ci				type = "noflag";
114062306a36Sopenharmony_ci			else
114162306a36Sopenharmony_ci				type = "flag";
114262306a36Sopenharmony_ci		} else if (p->type == fs_param_is_bool)
114362306a36Sopenharmony_ci			type = "bool";
114462306a36Sopenharmony_ci		else if (p->type == fs_param_is_u32)
114562306a36Sopenharmony_ci			type = "u32";
114662306a36Sopenharmony_ci		else if (p->type == fs_param_is_u64)
114762306a36Sopenharmony_ci			type = "u64";
114862306a36Sopenharmony_ci		else if (p->type == fs_param_is_string)
114962306a36Sopenharmony_ci			type = "string";
115062306a36Sopenharmony_ci		else
115162306a36Sopenharmony_ci			type = "unknown";
115262306a36Sopenharmony_ci
115362306a36Sopenharmony_ci		seq_printf(m, "%s:%s\n", p->name, type);
115462306a36Sopenharmony_ci	}
115562306a36Sopenharmony_ci
115662306a36Sopenharmony_ci	return 0;
115762306a36Sopenharmony_ci}
115862306a36Sopenharmony_ci
115962306a36Sopenharmony_cistatic int cifs_mount_params_proc_open(struct inode *inode, struct file *file)
116062306a36Sopenharmony_ci{
116162306a36Sopenharmony_ci	return single_open(file, cifs_mount_params_proc_show, NULL);
116262306a36Sopenharmony_ci}
116362306a36Sopenharmony_ci
116462306a36Sopenharmony_cistatic const struct proc_ops cifs_mount_params_proc_ops = {
116562306a36Sopenharmony_ci	.proc_open	= cifs_mount_params_proc_open,
116662306a36Sopenharmony_ci	.proc_read	= seq_read,
116762306a36Sopenharmony_ci	.proc_lseek	= seq_lseek,
116862306a36Sopenharmony_ci	.proc_release	= single_release,
116962306a36Sopenharmony_ci	/* No need for write for now */
117062306a36Sopenharmony_ci	/* .proc_write	= cifs_mount_params_proc_write, */
117162306a36Sopenharmony_ci};
117262306a36Sopenharmony_ci
117362306a36Sopenharmony_ci#else
117462306a36Sopenharmony_ciinline void cifs_proc_init(void)
117562306a36Sopenharmony_ci{
117662306a36Sopenharmony_ci}
117762306a36Sopenharmony_ci
117862306a36Sopenharmony_ciinline void cifs_proc_clean(void)
117962306a36Sopenharmony_ci{
118062306a36Sopenharmony_ci}
118162306a36Sopenharmony_ci#endif /* PROC_FS */
1182