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