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