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