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