• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *   fs/cifs_debug.c
3  *
4  *   Copyright (C) International Business Machines  Corp., 2000,2005
5  *
6  *   Modified by Steve French (sfrench@us.ibm.com)
7  *
8  *   This program is free software;  you can redistribute it and/or modify
9  *   it under the terms of the GNU General Public License as published by
10  *   the Free Software Foundation; either version 2 of the License, or
11  *   (at your option) any later version.
12  *
13  *   This program is distributed in the hope that it will be useful,
14  *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
15  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
16  *   the GNU General Public License for more details.
17  *
18  *   You should have received a copy of the GNU General Public License
19  *   along with this program;  if not, write to the Free Software
20  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21  */
22 #include <linux/fs.h>
23 #include <linux/string.h>
24 #include <linux/ctype.h>
25 #include <linux/module.h>
26 #include <linux/proc_fs.h>
27 #include <asm/uaccess.h>
28 #include "cifspdu.h"
29 #include "cifsglob.h"
30 #include "cifsproto.h"
31 #include "cifs_debug.h"
32 #include "cifsfs.h"
33 
34 void
cifs_dump_mem(char * label,void * data,int length)35 cifs_dump_mem(char *label, void *data, int length)
36 {
37 	int i, j;
38 	int *intptr = data;
39 	char *charptr = data;
40 	char buf[10], line[80];
41 
42 	printk(KERN_DEBUG "%s: dump of %d bytes of data at 0x%p\n",
43 		label, length, data);
44 	for (i = 0; i < length; i += 16) {
45 		line[0] = 0;
46 		for (j = 0; (j < 4) && (i + j * 4 < length); j++) {
47 			sprintf(buf, " %08x", intptr[i / 4 + j]);
48 			strcat(line, buf);
49 		}
50 		buf[0] = ' ';
51 		buf[2] = 0;
52 		for (j = 0; (j < 16) && (i + j < length); j++) {
53 			buf[1] = isprint(charptr[i + j]) ? charptr[i + j] : '.';
54 			strcat(line, buf);
55 		}
56 		printk(KERN_DEBUG "%s\n", line);
57 	}
58 }
59 
60 #ifdef CONFIG_CIFS_DEBUG2
cifs_dump_detail(struct smb_hdr * smb)61 void cifs_dump_detail(struct smb_hdr *smb)
62 {
63 	cERROR(1, ("Cmd: %d Err: 0x%x Flags: 0x%x Flgs2: 0x%x Mid: %d Pid: %d",
64 		  smb->Command, smb->Status.CifsError,
65 		  smb->Flags, smb->Flags2, smb->Mid, smb->Pid));
66 	cERROR(1, ("smb buf %p len %d", smb, smbCalcSize_LE(smb)));
67 }
68 
69 
cifs_dump_mids(struct TCP_Server_Info * server)70 void cifs_dump_mids(struct TCP_Server_Info *server)
71 {
72 	struct list_head *tmp;
73 	struct mid_q_entry *mid_entry;
74 
75 	if (server == NULL)
76 		return;
77 
78 	cERROR(1, ("Dump pending requests:"));
79 	spin_lock(&GlobalMid_Lock);
80 	list_for_each(tmp, &server->pending_mid_q) {
81 		mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
82 		cERROR(1, ("State: %d Cmd: %d Pid: %d Tsk: %p Mid %d",
83 			mid_entry->midState,
84 			(int)mid_entry->command,
85 			mid_entry->pid,
86 			mid_entry->tsk,
87 			mid_entry->mid));
88 #ifdef CONFIG_CIFS_STATS2
89 		cERROR(1, ("IsLarge: %d buf: %p time rcv: %ld now: %ld",
90 			mid_entry->largeBuf,
91 			mid_entry->resp_buf,
92 			mid_entry->when_received,
93 			jiffies));
94 #endif /* STATS2 */
95 		cERROR(1, ("IsMult: %d IsEnd: %d", mid_entry->multiRsp,
96 			  mid_entry->multiEnd));
97 		if (mid_entry->resp_buf) {
98 			cifs_dump_detail(mid_entry->resp_buf);
99 			cifs_dump_mem("existing buf: ",
100 				mid_entry->resp_buf, 62);
101 		}
102 	}
103 	spin_unlock(&GlobalMid_Lock);
104 }
105 #endif /* CONFIG_CIFS_DEBUG2 */
106 
107 #ifdef CONFIG_PROC_FS
cifs_debug_data_proc_show(struct seq_file * m,void * v)108 static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
109 {
110 	struct list_head *tmp1, *tmp2, *tmp3;
111 	struct mid_q_entry *mid_entry;
112 	struct TCP_Server_Info *server;
113 	struct cifsSesInfo *ses;
114 	struct cifsTconInfo *tcon;
115 	int i, j;
116 	__u32 dev_type;
117 
118 	seq_puts(m,
119 		    "Display Internal CIFS Data Structures for Debugging\n"
120 		    "---------------------------------------------------\n");
121 	seq_printf(m, "CIFS Version %s\n", CIFS_VERSION);
122 	seq_printf(m, "Active VFS Requests: %d\n", GlobalTotalActiveXid);
123 	seq_printf(m, "Servers:");
124 
125 	i = 0;
126 	read_lock(&cifs_tcp_ses_lock);
127 	list_for_each(tmp1, &cifs_tcp_ses_list) {
128 		server = list_entry(tmp1, struct TCP_Server_Info,
129 				    tcp_ses_list);
130 		i++;
131 		list_for_each(tmp2, &server->smb_ses_list) {
132 			ses = list_entry(tmp2, struct cifsSesInfo,
133 					 smb_ses_list);
134 			if ((ses->serverDomain == NULL) ||
135 				(ses->serverOS == NULL) ||
136 				(ses->serverNOS == NULL)) {
137 				seq_printf(m, "\n%d) entry for %s not fully "
138 					   "displayed\n\t", i, ses->serverName);
139 			} else {
140 				seq_printf(m,
141 				    "\n%d) Name: %s  Domain: %s Uses: %d OS:"
142 				    " %s\n\tNOS: %s\tCapability: 0x%x\n\tSMB"
143 				    " session status: %d\t",
144 				i, ses->serverName, ses->serverDomain,
145 				ses->ses_count, ses->serverOS, ses->serverNOS,
146 				ses->capabilities, ses->status);
147 			}
148 			seq_printf(m, "TCP status: %d\n\tLocal Users To "
149 				   "Server: %d SecMode: 0x%x Req On Wire: %d",
150 				   server->tcpStatus, server->srv_count,
151 				   server->secMode,
152 				   atomic_read(&server->inFlight));
153 
154 #ifdef CONFIG_CIFS_STATS2
155 			seq_printf(m, " In Send: %d In MaxReq Wait: %d",
156 				atomic_read(&server->inSend),
157 				atomic_read(&server->num_waiters));
158 #endif
159 
160 			seq_puts(m, "\n\tShares:");
161 			j = 0;
162 			list_for_each(tmp3, &ses->tcon_list) {
163 				tcon = list_entry(tmp3, struct cifsTconInfo,
164 						  tcon_list);
165 				++j;
166 				dev_type = le32_to_cpu(tcon->fsDevInfo.DeviceType);
167 				seq_printf(m, "\n\t%d) %s Mounts: %d ", j,
168 					   tcon->treeName, tcon->tc_count);
169 				if (tcon->nativeFileSystem) {
170 					seq_printf(m, "Type: %s ",
171 						   tcon->nativeFileSystem);
172 				}
173 				seq_printf(m, "DevInfo: 0x%x Attributes: 0x%x"
174 					"\nPathComponentMax: %d Status: 0x%d",
175 					le32_to_cpu(tcon->fsDevInfo.DeviceCharacteristics),
176 					le32_to_cpu(tcon->fsAttrInfo.Attributes),
177 					le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength),
178 					tcon->tidStatus);
179 				if (dev_type == FILE_DEVICE_DISK)
180 					seq_puts(m, " type: DISK ");
181 				else if (dev_type == FILE_DEVICE_CD_ROM)
182 					seq_puts(m, " type: CDROM ");
183 				else
184 					seq_printf(m, " type: %d ", dev_type);
185 
186 				if (tcon->need_reconnect)
187 					seq_puts(m, "\tDISCONNECTED ");
188 				seq_putc(m, '\n');
189 			}
190 
191 			seq_puts(m, "\n\tMIDs:\n");
192 
193 			spin_lock(&GlobalMid_Lock);
194 			list_for_each(tmp3, &server->pending_mid_q) {
195 				mid_entry = list_entry(tmp3, struct mid_q_entry,
196 					qhead);
197 				seq_printf(m, "\tState: %d com: %d pid:"
198 						" %d tsk: %p mid %d\n",
199 						mid_entry->midState,
200 						(int)mid_entry->command,
201 						mid_entry->pid,
202 						mid_entry->tsk,
203 						mid_entry->mid);
204 			}
205 			spin_unlock(&GlobalMid_Lock);
206 		}
207 	}
208 	read_unlock(&cifs_tcp_ses_lock);
209 	seq_putc(m, '\n');
210 
211 	/* BB add code to dump additional info such as TCP session info now */
212 	return 0;
213 }
214 
cifs_debug_data_proc_open(struct inode * inode,struct file * file)215 static int cifs_debug_data_proc_open(struct inode *inode, struct file *file)
216 {
217 	return single_open(file, cifs_debug_data_proc_show, NULL);
218 }
219 
220 static const struct file_operations cifs_debug_data_proc_fops = {
221 	.owner		= THIS_MODULE,
222 	.open		= cifs_debug_data_proc_open,
223 	.read		= seq_read,
224 	.llseek		= seq_lseek,
225 	.release	= single_release,
226 };
227 
228 #ifdef CONFIG_CIFS_STATS
cifs_stats_proc_write(struct file * file,const char __user * buffer,size_t count,loff_t * ppos)229 static ssize_t cifs_stats_proc_write(struct file *file,
230 		const char __user *buffer, size_t count, loff_t *ppos)
231 {
232 	char c;
233 	int rc;
234 	struct list_head *tmp1, *tmp2, *tmp3;
235 	struct TCP_Server_Info *server;
236 	struct cifsSesInfo *ses;
237 	struct cifsTconInfo *tcon;
238 
239 	rc = get_user(c, buffer);
240 	if (rc)
241 		return rc;
242 
243 	if (c == '1' || c == 'y' || c == 'Y' || c == '0') {
244 #ifdef CONFIG_CIFS_STATS2
245 		atomic_set(&totBufAllocCount, 0);
246 		atomic_set(&totSmBufAllocCount, 0);
247 #endif /* CONFIG_CIFS_STATS2 */
248 		read_lock(&cifs_tcp_ses_lock);
249 		list_for_each(tmp1, &cifs_tcp_ses_list) {
250 			server = list_entry(tmp1, struct TCP_Server_Info,
251 					    tcp_ses_list);
252 			list_for_each(tmp2, &server->smb_ses_list) {
253 				ses = list_entry(tmp2, struct cifsSesInfo,
254 						 smb_ses_list);
255 				list_for_each(tmp3, &ses->tcon_list) {
256 					tcon = list_entry(tmp3,
257 							  struct cifsTconInfo,
258 							  tcon_list);
259 					atomic_set(&tcon->num_smbs_sent, 0);
260 					atomic_set(&tcon->num_writes, 0);
261 					atomic_set(&tcon->num_reads, 0);
262 					atomic_set(&tcon->num_oplock_brks, 0);
263 					atomic_set(&tcon->num_opens, 0);
264 					atomic_set(&tcon->num_closes, 0);
265 					atomic_set(&tcon->num_deletes, 0);
266 					atomic_set(&tcon->num_mkdirs, 0);
267 					atomic_set(&tcon->num_rmdirs, 0);
268 					atomic_set(&tcon->num_renames, 0);
269 					atomic_set(&tcon->num_t2renames, 0);
270 					atomic_set(&tcon->num_ffirst, 0);
271 					atomic_set(&tcon->num_fnext, 0);
272 					atomic_set(&tcon->num_fclose, 0);
273 					atomic_set(&tcon->num_hardlinks, 0);
274 					atomic_set(&tcon->num_symlinks, 0);
275 					atomic_set(&tcon->num_locks, 0);
276 				}
277 			}
278 		}
279 		read_unlock(&cifs_tcp_ses_lock);
280 	}
281 
282 	return count;
283 }
284 
cifs_stats_proc_show(struct seq_file * m,void * v)285 static int cifs_stats_proc_show(struct seq_file *m, void *v)
286 {
287 	int i;
288 	struct list_head *tmp1, *tmp2, *tmp3;
289 	struct TCP_Server_Info *server;
290 	struct cifsSesInfo *ses;
291 	struct cifsTconInfo *tcon;
292 
293 	seq_printf(m,
294 			"Resources in use\nCIFS Session: %d\n",
295 			sesInfoAllocCount.counter);
296 	seq_printf(m, "Share (unique mount targets): %d\n",
297 			tconInfoAllocCount.counter);
298 	seq_printf(m, "SMB Request/Response Buffer: %d Pool size: %d\n",
299 			bufAllocCount.counter,
300 			cifs_min_rcv + tcpSesAllocCount.counter);
301 	seq_printf(m, "SMB Small Req/Resp Buffer: %d Pool size: %d\n",
302 			smBufAllocCount.counter, cifs_min_small);
303 #ifdef CONFIG_CIFS_STATS2
304 	seq_printf(m, "Total Large %d Small %d Allocations\n",
305 				atomic_read(&totBufAllocCount),
306 				atomic_read(&totSmBufAllocCount));
307 #endif /* CONFIG_CIFS_STATS2 */
308 
309 	seq_printf(m, "Operations (MIDs): %d\n", midCount.counter);
310 	seq_printf(m,
311 		"\n%d session %d share reconnects\n",
312 		tcpSesReconnectCount.counter, tconInfoReconnectCount.counter);
313 
314 	seq_printf(m,
315 		"Total vfs operations: %d maximum at one time: %d\n",
316 		GlobalCurrentXid, GlobalMaxActiveXid);
317 
318 	i = 0;
319 	read_lock(&cifs_tcp_ses_lock);
320 	list_for_each(tmp1, &cifs_tcp_ses_list) {
321 		server = list_entry(tmp1, struct TCP_Server_Info,
322 				    tcp_ses_list);
323 		list_for_each(tmp2, &server->smb_ses_list) {
324 			ses = list_entry(tmp2, struct cifsSesInfo,
325 					 smb_ses_list);
326 			list_for_each(tmp3, &ses->tcon_list) {
327 				tcon = list_entry(tmp3,
328 						  struct cifsTconInfo,
329 						  tcon_list);
330 				i++;
331 				seq_printf(m, "\n%d) %s", i, tcon->treeName);
332 				if (tcon->need_reconnect)
333 					seq_puts(m, "\tDISCONNECTED ");
334 				seq_printf(m, "\nSMBs: %d Oplock Breaks: %d",
335 					atomic_read(&tcon->num_smbs_sent),
336 					atomic_read(&tcon->num_oplock_brks));
337 				seq_printf(m, "\nReads:  %d Bytes: %lld",
338 					atomic_read(&tcon->num_reads),
339 					(long long)(tcon->bytes_read));
340 				seq_printf(m, "\nWrites: %d Bytes: %lld",
341 					atomic_read(&tcon->num_writes),
342 					(long long)(tcon->bytes_written));
343 				seq_printf(m, "\nLocks: %d HardLinks: %d "
344 					      "Symlinks: %d",
345 					atomic_read(&tcon->num_locks),
346 					atomic_read(&tcon->num_hardlinks),
347 					atomic_read(&tcon->num_symlinks));
348 				seq_printf(m, "\nOpens: %d Closes: %d"
349 					      "Deletes: %d",
350 					atomic_read(&tcon->num_opens),
351 					atomic_read(&tcon->num_closes),
352 					atomic_read(&tcon->num_deletes));
353 				seq_printf(m, "\nMkdirs: %d Rmdirs: %d",
354 					atomic_read(&tcon->num_mkdirs),
355 					atomic_read(&tcon->num_rmdirs));
356 				seq_printf(m, "\nRenames: %d T2 Renames %d",
357 					atomic_read(&tcon->num_renames),
358 					atomic_read(&tcon->num_t2renames));
359 				seq_printf(m, "\nFindFirst: %d FNext %d "
360 					      "FClose %d",
361 					atomic_read(&tcon->num_ffirst),
362 					atomic_read(&tcon->num_fnext),
363 					atomic_read(&tcon->num_fclose));
364 			}
365 		}
366 	}
367 	read_unlock(&cifs_tcp_ses_lock);
368 
369 	seq_putc(m, '\n');
370 	return 0;
371 }
372 
cifs_stats_proc_open(struct inode * inode,struct file * file)373 static int cifs_stats_proc_open(struct inode *inode, struct file *file)
374 {
375 	return single_open(file, cifs_stats_proc_show, NULL);
376 }
377 
378 static const struct file_operations cifs_stats_proc_fops = {
379 	.owner		= THIS_MODULE,
380 	.open		= cifs_stats_proc_open,
381 	.read		= seq_read,
382 	.llseek		= seq_lseek,
383 	.release	= single_release,
384 	.write		= cifs_stats_proc_write,
385 };
386 #endif /* STATS */
387 
388 static struct proc_dir_entry *proc_fs_cifs;
389 static const struct file_operations cifsFYI_proc_fops;
390 static const struct file_operations cifs_oplock_proc_fops;
391 static const struct file_operations cifs_lookup_cache_proc_fops;
392 static const struct file_operations traceSMB_proc_fops;
393 static const struct file_operations cifs_multiuser_mount_proc_fops;
394 static const struct file_operations cifs_security_flags_proc_fops;
395 static const struct file_operations cifs_experimental_proc_fops;
396 static const struct file_operations cifs_linux_ext_proc_fops;
397 
398 void
cifs_proc_init(void)399 cifs_proc_init(void)
400 {
401 	proc_fs_cifs = proc_mkdir("fs/cifs", NULL);
402 	if (proc_fs_cifs == NULL)
403 		return;
404 
405 	proc_fs_cifs->owner = THIS_MODULE;
406 	proc_create("DebugData", 0, proc_fs_cifs, &cifs_debug_data_proc_fops);
407 
408 #ifdef CONFIG_CIFS_STATS
409 	proc_create("Stats", 0, proc_fs_cifs, &cifs_stats_proc_fops);
410 #endif /* STATS */
411 	proc_create("cifsFYI", 0, proc_fs_cifs, &cifsFYI_proc_fops);
412 	proc_create("traceSMB", 0, proc_fs_cifs, &traceSMB_proc_fops);
413 	proc_create("OplockEnabled", 0, proc_fs_cifs, &cifs_oplock_proc_fops);
414 	proc_create("Experimental", 0, proc_fs_cifs,
415 		    &cifs_experimental_proc_fops);
416 	proc_create("LinuxExtensionsEnabled", 0, proc_fs_cifs,
417 		    &cifs_linux_ext_proc_fops);
418 	proc_create("MultiuserMount", 0, proc_fs_cifs,
419 		    &cifs_multiuser_mount_proc_fops);
420 	proc_create("SecurityFlags", 0, proc_fs_cifs,
421 		    &cifs_security_flags_proc_fops);
422 	proc_create("LookupCacheEnabled", 0, proc_fs_cifs,
423 		    &cifs_lookup_cache_proc_fops);
424 }
425 
426 void
cifs_proc_clean(void)427 cifs_proc_clean(void)
428 {
429 	if (proc_fs_cifs == NULL)
430 		return;
431 
432 	remove_proc_entry("DebugData", proc_fs_cifs);
433 	remove_proc_entry("cifsFYI", proc_fs_cifs);
434 	remove_proc_entry("traceSMB", proc_fs_cifs);
435 #ifdef CONFIG_CIFS_STATS
436 	remove_proc_entry("Stats", proc_fs_cifs);
437 #endif
438 	remove_proc_entry("MultiuserMount", proc_fs_cifs);
439 	remove_proc_entry("OplockEnabled", proc_fs_cifs);
440 	remove_proc_entry("SecurityFlags", proc_fs_cifs);
441 	remove_proc_entry("LinuxExtensionsEnabled", proc_fs_cifs);
442 	remove_proc_entry("Experimental", proc_fs_cifs);
443 	remove_proc_entry("LookupCacheEnabled", proc_fs_cifs);
444 	remove_proc_entry("fs/cifs", NULL);
445 }
446 
cifsFYI_proc_show(struct seq_file * m,void * v)447 static int cifsFYI_proc_show(struct seq_file *m, void *v)
448 {
449 	seq_printf(m, "%d\n", cifsFYI);
450 	return 0;
451 }
452 
cifsFYI_proc_open(struct inode * inode,struct file * file)453 static int cifsFYI_proc_open(struct inode *inode, struct file *file)
454 {
455 	return single_open(file, cifsFYI_proc_show, NULL);
456 }
457 
cifsFYI_proc_write(struct file * file,const char __user * buffer,size_t count,loff_t * ppos)458 static ssize_t cifsFYI_proc_write(struct file *file, const char __user *buffer,
459 		size_t count, loff_t *ppos)
460 {
461 	char c;
462 	int rc;
463 
464 	rc = get_user(c, buffer);
465 	if (rc)
466 		return rc;
467 	if (c == '0' || c == 'n' || c == 'N')
468 		cifsFYI = 0;
469 	else if (c == '1' || c == 'y' || c == 'Y')
470 		cifsFYI = 1;
471 	else if ((c > '1') && (c <= '9'))
472 		cifsFYI = (int) (c - '0'); /* see cifs_debug.h for meanings */
473 
474 	return count;
475 }
476 
477 static const struct file_operations cifsFYI_proc_fops = {
478 	.owner		= THIS_MODULE,
479 	.open		= cifsFYI_proc_open,
480 	.read		= seq_read,
481 	.llseek		= seq_lseek,
482 	.release	= single_release,
483 	.write		= cifsFYI_proc_write,
484 };
485 
cifs_oplock_proc_show(struct seq_file * m,void * v)486 static int cifs_oplock_proc_show(struct seq_file *m, void *v)
487 {
488 	seq_printf(m, "%d\n", oplockEnabled);
489 	return 0;
490 }
491 
cifs_oplock_proc_open(struct inode * inode,struct file * file)492 static int cifs_oplock_proc_open(struct inode *inode, struct file *file)
493 {
494 	return single_open(file, cifs_oplock_proc_show, NULL);
495 }
496 
cifs_oplock_proc_write(struct file * file,const char __user * buffer,size_t count,loff_t * ppos)497 static ssize_t cifs_oplock_proc_write(struct file *file,
498 		const char __user *buffer, size_t count, loff_t *ppos)
499 {
500 	char c;
501 	int rc;
502 
503 	rc = get_user(c, buffer);
504 	if (rc)
505 		return rc;
506 	if (c == '0' || c == 'n' || c == 'N')
507 		oplockEnabled = 0;
508 	else if (c == '1' || c == 'y' || c == 'Y')
509 		oplockEnabled = 1;
510 
511 	return count;
512 }
513 
514 static const struct file_operations cifs_oplock_proc_fops = {
515 	.owner		= THIS_MODULE,
516 	.open		= cifs_oplock_proc_open,
517 	.read		= seq_read,
518 	.llseek		= seq_lseek,
519 	.release	= single_release,
520 	.write		= cifs_oplock_proc_write,
521 };
522 
cifs_experimental_proc_show(struct seq_file * m,void * v)523 static int cifs_experimental_proc_show(struct seq_file *m, void *v)
524 {
525 	seq_printf(m, "%d\n", experimEnabled);
526 	return 0;
527 }
528 
cifs_experimental_proc_open(struct inode * inode,struct file * file)529 static int cifs_experimental_proc_open(struct inode *inode, struct file *file)
530 {
531 	return single_open(file, cifs_experimental_proc_show, NULL);
532 }
533 
cifs_experimental_proc_write(struct file * file,const char __user * buffer,size_t count,loff_t * ppos)534 static ssize_t cifs_experimental_proc_write(struct file *file,
535 		const char __user *buffer, size_t count, loff_t *ppos)
536 {
537 	char c;
538 	int rc;
539 
540 	rc = get_user(c, buffer);
541 	if (rc)
542 		return rc;
543 	if (c == '0' || c == 'n' || c == 'N')
544 		experimEnabled = 0;
545 	else if (c == '1' || c == 'y' || c == 'Y')
546 		experimEnabled = 1;
547 	else if (c == '2')
548 		experimEnabled = 2;
549 
550 	return count;
551 }
552 
553 static const struct file_operations cifs_experimental_proc_fops = {
554 	.owner		= THIS_MODULE,
555 	.open		= cifs_experimental_proc_open,
556 	.read		= seq_read,
557 	.llseek		= seq_lseek,
558 	.release	= single_release,
559 	.write		= cifs_experimental_proc_write,
560 };
561 
cifs_linux_ext_proc_show(struct seq_file * m,void * v)562 static int cifs_linux_ext_proc_show(struct seq_file *m, void *v)
563 {
564 	seq_printf(m, "%d\n", linuxExtEnabled);
565 	return 0;
566 }
567 
cifs_linux_ext_proc_open(struct inode * inode,struct file * file)568 static int cifs_linux_ext_proc_open(struct inode *inode, struct file *file)
569 {
570 	return single_open(file, cifs_linux_ext_proc_show, NULL);
571 }
572 
cifs_linux_ext_proc_write(struct file * file,const char __user * buffer,size_t count,loff_t * ppos)573 static ssize_t cifs_linux_ext_proc_write(struct file *file,
574 		const char __user *buffer, size_t count, loff_t *ppos)
575 {
576 	char c;
577 	int rc;
578 
579 	rc = get_user(c, buffer);
580 	if (rc)
581 		return rc;
582 	if (c == '0' || c == 'n' || c == 'N')
583 		linuxExtEnabled = 0;
584 	else if (c == '1' || c == 'y' || c == 'Y')
585 		linuxExtEnabled = 1;
586 
587 	return count;
588 }
589 
590 static const struct file_operations cifs_linux_ext_proc_fops = {
591 	.owner		= THIS_MODULE,
592 	.open		= cifs_linux_ext_proc_open,
593 	.read		= seq_read,
594 	.llseek		= seq_lseek,
595 	.release	= single_release,
596 	.write		= cifs_linux_ext_proc_write,
597 };
598 
cifs_lookup_cache_proc_show(struct seq_file * m,void * v)599 static int cifs_lookup_cache_proc_show(struct seq_file *m, void *v)
600 {
601 	seq_printf(m, "%d\n", lookupCacheEnabled);
602 	return 0;
603 }
604 
cifs_lookup_cache_proc_open(struct inode * inode,struct file * file)605 static int cifs_lookup_cache_proc_open(struct inode *inode, struct file *file)
606 {
607 	return single_open(file, cifs_lookup_cache_proc_show, NULL);
608 }
609 
cifs_lookup_cache_proc_write(struct file * file,const char __user * buffer,size_t count,loff_t * ppos)610 static ssize_t cifs_lookup_cache_proc_write(struct file *file,
611 		const char __user *buffer, size_t count, loff_t *ppos)
612 {
613 	char c;
614 	int rc;
615 
616 	rc = get_user(c, buffer);
617 	if (rc)
618 		return rc;
619 	if (c == '0' || c == 'n' || c == 'N')
620 		lookupCacheEnabled = 0;
621 	else if (c == '1' || c == 'y' || c == 'Y')
622 		lookupCacheEnabled = 1;
623 
624 	return count;
625 }
626 
627 static const struct file_operations cifs_lookup_cache_proc_fops = {
628 	.owner		= THIS_MODULE,
629 	.open		= cifs_lookup_cache_proc_open,
630 	.read		= seq_read,
631 	.llseek		= seq_lseek,
632 	.release	= single_release,
633 	.write		= cifs_lookup_cache_proc_write,
634 };
635 
traceSMB_proc_show(struct seq_file * m,void * v)636 static int traceSMB_proc_show(struct seq_file *m, void *v)
637 {
638 	seq_printf(m, "%d\n", traceSMB);
639 	return 0;
640 }
641 
traceSMB_proc_open(struct inode * inode,struct file * file)642 static int traceSMB_proc_open(struct inode *inode, struct file *file)
643 {
644 	return single_open(file, traceSMB_proc_show, NULL);
645 }
646 
traceSMB_proc_write(struct file * file,const char __user * buffer,size_t count,loff_t * ppos)647 static ssize_t traceSMB_proc_write(struct file *file, const char __user *buffer,
648 		size_t count, loff_t *ppos)
649 {
650 	char c;
651 	int rc;
652 
653 	rc = get_user(c, buffer);
654 	if (rc)
655 		return rc;
656 	if (c == '0' || c == 'n' || c == 'N')
657 		traceSMB = 0;
658 	else if (c == '1' || c == 'y' || c == 'Y')
659 		traceSMB = 1;
660 
661 	return count;
662 }
663 
664 static const struct file_operations traceSMB_proc_fops = {
665 	.owner		= THIS_MODULE,
666 	.open		= traceSMB_proc_open,
667 	.read		= seq_read,
668 	.llseek		= seq_lseek,
669 	.release	= single_release,
670 	.write		= traceSMB_proc_write,
671 };
672 
cifs_multiuser_mount_proc_show(struct seq_file * m,void * v)673 static int cifs_multiuser_mount_proc_show(struct seq_file *m, void *v)
674 {
675 	seq_printf(m, "%d\n", multiuser_mount);
676 	return 0;
677 }
678 
cifs_multiuser_mount_proc_open(struct inode * inode,struct file * fh)679 static int cifs_multiuser_mount_proc_open(struct inode *inode, struct file *fh)
680 {
681 	return single_open(fh, cifs_multiuser_mount_proc_show, NULL);
682 }
683 
cifs_multiuser_mount_proc_write(struct file * file,const char __user * buffer,size_t count,loff_t * ppos)684 static ssize_t cifs_multiuser_mount_proc_write(struct file *file,
685 		const char __user *buffer, size_t count, loff_t *ppos)
686 {
687 	char c;
688 	int rc;
689 
690 	rc = get_user(c, buffer);
691 	if (rc)
692 		return rc;
693 	if (c == '0' || c == 'n' || c == 'N')
694 		multiuser_mount = 0;
695 	else if (c == '1' || c == 'y' || c == 'Y')
696 		multiuser_mount = 1;
697 
698 	return count;
699 }
700 
701 static const struct file_operations cifs_multiuser_mount_proc_fops = {
702 	.owner		= THIS_MODULE,
703 	.open		= cifs_multiuser_mount_proc_open,
704 	.read		= seq_read,
705 	.llseek		= seq_lseek,
706 	.release	= single_release,
707 	.write		= cifs_multiuser_mount_proc_write,
708 };
709 
cifs_security_flags_proc_show(struct seq_file * m,void * v)710 static int cifs_security_flags_proc_show(struct seq_file *m, void *v)
711 {
712 	seq_printf(m, "0x%x\n", extended_security);
713 	return 0;
714 }
715 
cifs_security_flags_proc_open(struct inode * inode,struct file * file)716 static int cifs_security_flags_proc_open(struct inode *inode, struct file *file)
717 {
718 	return single_open(file, cifs_security_flags_proc_show, NULL);
719 }
720 
cifs_security_flags_proc_write(struct file * file,const char __user * buffer,size_t count,loff_t * ppos)721 static ssize_t cifs_security_flags_proc_write(struct file *file,
722 		const char __user *buffer, size_t count, loff_t *ppos)
723 {
724 	unsigned int flags;
725 	char flags_string[12];
726 	char c;
727 
728 	if ((count < 1) || (count > 11))
729 		return -EINVAL;
730 
731 	memset(flags_string, 0, 12);
732 
733 	if (copy_from_user(flags_string, buffer, count))
734 		return -EFAULT;
735 
736 	if (count < 3) {
737 		/* single char or single char followed by null */
738 		c = flags_string[0];
739 		if (c == '0' || c == 'n' || c == 'N') {
740 			extended_security = CIFSSEC_DEF; /* default */
741 			return count;
742 		} else if (c == '1' || c == 'y' || c == 'Y') {
743 			extended_security = CIFSSEC_MAX;
744 			return count;
745 		} else if (!isdigit(c)) {
746 			cERROR(1, ("invalid flag %c", c));
747 			return -EINVAL;
748 		}
749 	}
750 	/* else we have a number */
751 
752 	flags = simple_strtoul(flags_string, NULL, 0);
753 
754 	cFYI(1, ("sec flags 0x%x", flags));
755 
756 	if (flags <= 0)  {
757 		cERROR(1, ("invalid security flags %s", flags_string));
758 		return -EINVAL;
759 	}
760 
761 	if (flags & ~CIFSSEC_MASK) {
762 		cERROR(1, ("attempt to set unsupported security flags 0x%x",
763 			flags & ~CIFSSEC_MASK));
764 		return -EINVAL;
765 	}
766 	/* flags look ok - update the global security flags for cifs module */
767 	extended_security = flags;
768 	if (extended_security & CIFSSEC_MUST_SIGN) {
769 		/* requiring signing implies signing is allowed */
770 		extended_security |= CIFSSEC_MAY_SIGN;
771 		cFYI(1, ("packet signing now required"));
772 	} else if ((extended_security & CIFSSEC_MAY_SIGN) == 0) {
773 		cFYI(1, ("packet signing disabled"));
774 	}
775 	/* BB should we turn on MAY flags for other MUST options? */
776 	return count;
777 }
778 
779 static const struct file_operations cifs_security_flags_proc_fops = {
780 	.owner		= THIS_MODULE,
781 	.open		= cifs_security_flags_proc_open,
782 	.read		= seq_read,
783 	.llseek		= seq_lseek,
784 	.release	= single_release,
785 	.write		= cifs_security_flags_proc_write,
786 };
787 #else
cifs_proc_init(void)788 inline void cifs_proc_init(void)
789 {
790 }
791 
cifs_proc_clean(void)792 inline void cifs_proc_clean(void)
793 {
794 }
795 #endif /* PROC_FS */
796