4 * Copyright (C) International Business Machines Corp., 2000,2005
6 * Modified by Steve French (sfrench@us.ibm.com)
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.
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.
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
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>
30 #include "cifsproto.h"
31 #include "cifs_debug.h"
35 cifs_dump_mem(char *label
, void *data
, int length
)
40 char buf
[10], line
[80];
42 printk(KERN_DEBUG
"%s: dump of %d bytes of data at 0x%p\n\n",
44 for (i
= 0; i
< length
; i
+= 16) {
46 for (j
= 0; (j
< 4) && (i
+ j
* 4 < length
); j
++) {
47 sprintf(buf
, " %08x", intptr
[i
/ 4 + j
]);
52 for (j
= 0; (j
< 16) && (i
+ j
< length
); j
++) {
53 buf
[1] = isprint(charptr
[i
+ j
]) ? charptr
[i
+ j
] : '.';
56 printk(KERN_DEBUG
"%s\n", line
);
62 cifs_debug_data_read(char *buf
, char **beginBuffer
, off_t offset
,
63 int count
, int *eof
, void *data
)
65 struct list_head
*tmp
;
66 struct list_head
*tmp1
;
67 struct mid_q_entry
* mid_entry
;
68 struct cifsSesInfo
*ses
;
69 struct cifsTconInfo
*tcon
;
72 char * original_buf
= buf
;
74 *beginBuffer
= buf
+ offset
;
79 "Display Internal CIFS Data Structures for Debugging\n"
80 "---------------------------------------------------\n");
82 length
= sprintf(buf
,"CIFS Version %s\n",CIFS_VERSION
);
84 length
= sprintf(buf
,"Active VFS Requests: %d\n", GlobalTotalActiveXid
);
86 length
= sprintf(buf
, "Servers:");
90 read_lock(&GlobalSMBSeslock
);
91 list_for_each(tmp
, &GlobalSMBSessionList
) {
93 ses
= list_entry(tmp
, struct cifsSesInfo
, cifsSessionList
);
94 if((ses
->serverDomain
== NULL
) || (ses
->serverOS
== NULL
) ||
95 (ses
->serverNOS
== NULL
)) {
96 buf
+= sprintf("\nentry for %s not fully displayed\n\t",
102 "\n%d) Name: %s Domain: %s Mounts: %d OS: %s \n\tNOS: %s\tCapability: 0x%x\n\tSMB session status: %d\t",
103 i
, ses
->serverName
, ses
->serverDomain
,
104 atomic_read(&ses
->inUse
),
105 ses
->serverOS
, ses
->serverNOS
,
106 ses
->capabilities
,ses
->status
);
110 buf
+= sprintf(buf
, "TCP status: %d\n\tLocal Users To Server: %d SecMode: 0x%x Req On Wire: %d",
111 ses
->server
->tcpStatus
,
112 atomic_read(&ses
->server
->socketUseCount
),
113 ses
->server
->secMode
,
114 atomic_read(&ses
->server
->inFlight
));
116 #ifdef CONFIG_CIFS_STATS2
117 buf
+= sprintf(buf
, " In Send: %d In MaxReq Wait: %d",
118 atomic_read(&ses
->server
->inSend
),
119 atomic_read(&ses
->server
->num_waiters
));
122 length
= sprintf(buf
, "\nMIDs:\n");
125 spin_lock(&GlobalMid_Lock
);
126 list_for_each(tmp1
, &ses
->server
->pending_mid_q
) {
127 mid_entry
= list_entry(tmp1
, struct
131 length
= sprintf(buf
,"State: %d com: %d pid: %d tsk: %p mid %d\n",
133 (int)mid_entry
->command
,
140 spin_unlock(&GlobalMid_Lock
);
144 read_unlock(&GlobalSMBSeslock
);
148 length
= sprintf(buf
, "Shares:");
152 read_lock(&GlobalSMBSeslock
);
153 list_for_each(tmp
, &GlobalTreeConnectionList
) {
156 tcon
= list_entry(tmp
, struct cifsTconInfo
, cifsConnectionList
);
157 dev_type
= le32_to_cpu(tcon
->fsDevInfo
.DeviceType
);
160 "\n%d) %s Uses: %d Type: %s DevInfo: 0x%x Attributes: 0x%x\nPathComponentMax: %d Status: %d",
162 atomic_read(&tcon
->useCount
),
163 tcon
->nativeFileSystem
,
164 le32_to_cpu(tcon
->fsDevInfo
.DeviceCharacteristics
),
165 le32_to_cpu(tcon
->fsAttrInfo
.Attributes
),
166 le32_to_cpu(tcon
->fsAttrInfo
.MaxPathNameComponentLength
),
169 if (dev_type
== FILE_DEVICE_DISK
)
170 length
= sprintf(buf
, " type: DISK ");
171 else if (dev_type
== FILE_DEVICE_CD_ROM
)
172 length
= sprintf(buf
, " type: CDROM ");
175 sprintf(buf
, " type: %d ", dev_type
);
177 if(tcon
->tidStatus
== CifsNeedReconnect
) {
178 buf
+= sprintf(buf
, "\tDISCONNECTED ");
182 read_unlock(&GlobalSMBSeslock
);
184 length
= sprintf(buf
, "\n");
187 /* BB add code to dump additional info such as TCP session info now */
188 /* Now calculate total size of returned data */
189 length
= buf
- original_buf
;
191 if(offset
+ count
>= length
)
193 if(length
< offset
) {
197 length
= length
- offset
;
205 #ifdef CONFIG_CIFS_STATS
208 cifs_stats_write(struct file
*file
, const char __user
*buffer
,
209 unsigned long count
, void *data
)
213 struct list_head
*tmp
;
214 struct cifsTconInfo
*tcon
;
216 rc
= get_user(c
, buffer
);
220 if (c
== '1' || c
== 'y' || c
== 'Y' || c
== '0') {
221 read_lock(&GlobalSMBSeslock
);
222 #ifdef CONFIG_CIFS_STATS2
223 atomic_set(&totBufAllocCount
, 0);
224 atomic_set(&totSmBufAllocCount
, 0);
225 #endif /* CONFIG_CIFS_STATS2 */
226 list_for_each(tmp
, &GlobalTreeConnectionList
) {
227 tcon
= list_entry(tmp
, struct cifsTconInfo
,
229 atomic_set(&tcon
->num_smbs_sent
, 0);
230 atomic_set(&tcon
->num_writes
, 0);
231 atomic_set(&tcon
->num_reads
, 0);
232 atomic_set(&tcon
->num_oplock_brks
, 0);
233 atomic_set(&tcon
->num_opens
, 0);
234 atomic_set(&tcon
->num_closes
, 0);
235 atomic_set(&tcon
->num_deletes
, 0);
236 atomic_set(&tcon
->num_mkdirs
, 0);
237 atomic_set(&tcon
->num_rmdirs
, 0);
238 atomic_set(&tcon
->num_renames
, 0);
239 atomic_set(&tcon
->num_t2renames
, 0);
240 atomic_set(&tcon
->num_ffirst
, 0);
241 atomic_set(&tcon
->num_fnext
, 0);
242 atomic_set(&tcon
->num_fclose
, 0);
243 atomic_set(&tcon
->num_hardlinks
, 0);
244 atomic_set(&tcon
->num_symlinks
, 0);
245 atomic_set(&tcon
->num_locks
, 0);
247 read_unlock(&GlobalSMBSeslock
);
254 cifs_stats_read(char *buf
, char **beginBuffer
, off_t offset
,
255 int count
, int *eof
, void *data
)
257 int item_length
,i
,length
;
258 struct list_head
*tmp
;
259 struct cifsTconInfo
*tcon
;
261 *beginBuffer
= buf
+ offset
;
263 length
= sprintf(buf
,
264 "Resources in use\nCIFS Session: %d\n",
265 sesInfoAllocCount
.counter
);
268 sprintf(buf
,"Share (unique mount targets): %d\n",
269 tconInfoAllocCount
.counter
);
270 length
+= item_length
;
273 sprintf(buf
,"SMB Request/Response Buffer: %d Pool size: %d\n",
274 bufAllocCount
.counter
,
275 cifs_min_rcv
+ tcpSesAllocCount
.counter
);
276 length
+= item_length
;
279 sprintf(buf
,"SMB Small Req/Resp Buffer: %d Pool size: %d\n",
280 smBufAllocCount
.counter
,cifs_min_small
);
281 length
+= item_length
;
283 #ifdef CONFIG_CIFS_STATS2
284 item_length
= sprintf(buf
, "Total Large %d Small %d Allocations\n",
285 atomic_read(&totBufAllocCount
),
286 atomic_read(&totSmBufAllocCount
));
287 length
+= item_length
;
289 #endif /* CONFIG_CIFS_STATS2 */
292 sprintf(buf
,"Operations (MIDs): %d\n",
294 length
+= item_length
;
296 item_length
= sprintf(buf
,
297 "\n%d session %d share reconnects\n",
298 tcpSesReconnectCount
.counter
,tconInfoReconnectCount
.counter
);
299 length
+= item_length
;
302 item_length
= sprintf(buf
,
303 "Total vfs operations: %d maximum at one time: %d\n",
304 GlobalCurrentXid
,GlobalMaxActiveXid
);
305 length
+= item_length
;
309 read_lock(&GlobalSMBSeslock
);
310 list_for_each(tmp
, &GlobalTreeConnectionList
) {
312 tcon
= list_entry(tmp
, struct cifsTconInfo
, cifsConnectionList
);
313 item_length
= sprintf(buf
,"\n%d) %s",i
, tcon
->treeName
);
315 length
+= item_length
;
316 if(tcon
->tidStatus
== CifsNeedReconnect
) {
317 buf
+= sprintf(buf
, "\tDISCONNECTED ");
320 item_length
= sprintf(buf
, "\nSMBs: %d Oplock Breaks: %d",
321 atomic_read(&tcon
->num_smbs_sent
),
322 atomic_read(&tcon
->num_oplock_brks
));
324 length
+= item_length
;
325 item_length
= sprintf(buf
, "\nReads: %d Bytes: %lld",
326 atomic_read(&tcon
->num_reads
),
327 (long long)(tcon
->bytes_read
));
329 length
+= item_length
;
330 item_length
= sprintf(buf
, "\nWrites: %d Bytes: %lld",
331 atomic_read(&tcon
->num_writes
),
332 (long long)(tcon
->bytes_written
));
334 length
+= item_length
;
335 item_length
= sprintf(buf
,
336 "\nLocks: %d HardLinks: %d Symlinks: %d",
337 atomic_read(&tcon
->num_locks
),
338 atomic_read(&tcon
->num_hardlinks
),
339 atomic_read(&tcon
->num_symlinks
));
341 length
+= item_length
;
343 item_length
= sprintf(buf
, "\nOpens: %d Closes: %d Deletes: %d",
344 atomic_read(&tcon
->num_opens
),
345 atomic_read(&tcon
->num_closes
),
346 atomic_read(&tcon
->num_deletes
));
348 length
+= item_length
;
349 item_length
= sprintf(buf
, "\nMkdirs: %d Rmdirs: %d",
350 atomic_read(&tcon
->num_mkdirs
),
351 atomic_read(&tcon
->num_rmdirs
));
353 length
+= item_length
;
354 item_length
= sprintf(buf
, "\nRenames: %d T2 Renames %d",
355 atomic_read(&tcon
->num_renames
),
356 atomic_read(&tcon
->num_t2renames
));
358 length
+= item_length
;
359 item_length
= sprintf(buf
, "\nFindFirst: %d FNext %d FClose %d",
360 atomic_read(&tcon
->num_ffirst
),
361 atomic_read(&tcon
->num_fnext
),
362 atomic_read(&tcon
->num_fclose
));
364 length
+= item_length
;
366 read_unlock(&GlobalSMBSeslock
);
368 buf
+= sprintf(buf
,"\n");
371 if(offset
+ count
>= length
)
373 if(length
< offset
) {
377 length
= length
- offset
;
386 static struct proc_dir_entry
*proc_fs_cifs
;
387 read_proc_t cifs_txanchor_read
;
388 static read_proc_t cifsFYI_read
;
389 static write_proc_t cifsFYI_write
;
390 static read_proc_t oplockEnabled_read
;
391 static write_proc_t oplockEnabled_write
;
392 static read_proc_t lookupFlag_read
;
393 static write_proc_t lookupFlag_write
;
394 static read_proc_t traceSMB_read
;
395 static write_proc_t traceSMB_write
;
396 static read_proc_t multiuser_mount_read
;
397 static write_proc_t multiuser_mount_write
;
398 static read_proc_t extended_security_read
;
399 static write_proc_t extended_security_write
;
400 static read_proc_t ntlmv2_enabled_read
;
401 static write_proc_t ntlmv2_enabled_write
;
402 static read_proc_t packet_signing_enabled_read
;
403 static write_proc_t packet_signing_enabled_write
;
404 static read_proc_t experimEnabled_read
;
405 static write_proc_t experimEnabled_write
;
406 static read_proc_t linuxExtensionsEnabled_read
;
407 static write_proc_t linuxExtensionsEnabled_write
;
412 struct proc_dir_entry
*pde
;
414 proc_fs_cifs
= proc_mkdir("cifs", proc_root_fs
);
415 if (proc_fs_cifs
== NULL
)
418 proc_fs_cifs
->owner
= THIS_MODULE
;
419 create_proc_read_entry("DebugData", 0, proc_fs_cifs
,
420 cifs_debug_data_read
, NULL
);
422 #ifdef CONFIG_CIFS_STATS
423 pde
= create_proc_read_entry("Stats", 0, proc_fs_cifs
,
424 cifs_stats_read
, NULL
);
426 pde
->write_proc
= cifs_stats_write
;
428 pde
= create_proc_read_entry("cifsFYI", 0, proc_fs_cifs
,
431 pde
->write_proc
= cifsFYI_write
;
434 create_proc_read_entry("traceSMB", 0, proc_fs_cifs
,
435 traceSMB_read
, NULL
);
437 pde
->write_proc
= traceSMB_write
;
439 pde
= create_proc_read_entry("OplockEnabled", 0, proc_fs_cifs
,
440 oplockEnabled_read
, NULL
);
442 pde
->write_proc
= oplockEnabled_write
;
444 pde
= create_proc_read_entry("Experimental", 0, proc_fs_cifs
,
445 experimEnabled_read
, NULL
);
447 pde
->write_proc
= experimEnabled_write
;
449 pde
= create_proc_read_entry("LinuxExtensionsEnabled", 0, proc_fs_cifs
,
450 linuxExtensionsEnabled_read
, NULL
);
452 pde
->write_proc
= linuxExtensionsEnabled_write
;
455 create_proc_read_entry("MultiuserMount", 0, proc_fs_cifs
,
456 multiuser_mount_read
, NULL
);
458 pde
->write_proc
= multiuser_mount_write
;
461 create_proc_read_entry("ExtendedSecurity", 0, proc_fs_cifs
,
462 extended_security_read
, NULL
);
464 pde
->write_proc
= extended_security_write
;
467 create_proc_read_entry("LookupCacheEnabled", 0, proc_fs_cifs
,
468 lookupFlag_read
, NULL
);
470 pde
->write_proc
= lookupFlag_write
;
473 create_proc_read_entry("NTLMV2Enabled", 0, proc_fs_cifs
,
474 ntlmv2_enabled_read
, NULL
);
476 pde
->write_proc
= ntlmv2_enabled_write
;
479 create_proc_read_entry("PacketSigningEnabled", 0, proc_fs_cifs
,
480 packet_signing_enabled_read
, NULL
);
482 pde
->write_proc
= packet_signing_enabled_write
;
486 cifs_proc_clean(void)
488 if (proc_fs_cifs
== NULL
)
491 remove_proc_entry("DebugData", proc_fs_cifs
);
492 remove_proc_entry("cifsFYI", proc_fs_cifs
);
493 remove_proc_entry("traceSMB", proc_fs_cifs
);
494 #ifdef CONFIG_CIFS_STATS
495 remove_proc_entry("Stats", proc_fs_cifs
);
497 remove_proc_entry("MultiuserMount", proc_fs_cifs
);
498 remove_proc_entry("OplockEnabled", proc_fs_cifs
);
499 remove_proc_entry("NTLMV2Enabled",proc_fs_cifs
);
500 remove_proc_entry("ExtendedSecurity",proc_fs_cifs
);
501 remove_proc_entry("PacketSigningEnabled",proc_fs_cifs
);
502 remove_proc_entry("LinuxExtensionsEnabled",proc_fs_cifs
);
503 remove_proc_entry("Experimental",proc_fs_cifs
);
504 remove_proc_entry("LookupCacheEnabled",proc_fs_cifs
);
505 remove_proc_entry("cifs", proc_root_fs
);
509 cifsFYI_read(char *page
, char **start
, off_t off
, int count
,
510 int *eof
, void *data
)
514 len
= sprintf(page
, "%d\n", cifsFYI
);
530 cifsFYI_write(struct file
*file
, const char __user
*buffer
,
531 unsigned long count
, void *data
)
536 rc
= get_user(c
, buffer
);
539 if (c
== '0' || c
== 'n' || c
== 'N')
541 else if (c
== '1' || c
== 'y' || c
== 'Y')
543 else if((c
> '1') && (c
<= '9'))
544 cifsFYI
= (int) (c
- '0'); /* see cifs_debug.h for meanings */
550 oplockEnabled_read(char *page
, char **start
, off_t off
,
551 int count
, int *eof
, void *data
)
555 len
= sprintf(page
, "%d\n", oplockEnabled
);
571 oplockEnabled_write(struct file
*file
, const char __user
*buffer
,
572 unsigned long count
, void *data
)
577 rc
= get_user(c
, buffer
);
580 if (c
== '0' || c
== 'n' || c
== 'N')
582 else if (c
== '1' || c
== 'y' || c
== 'Y')
589 experimEnabled_read(char *page
, char **start
, off_t off
,
590 int count
, int *eof
, void *data
)
594 len
= sprintf(page
, "%d\n", experimEnabled
);
610 experimEnabled_write(struct file
*file
, const char __user
*buffer
,
611 unsigned long count
, void *data
)
616 rc
= get_user(c
, buffer
);
619 if (c
== '0' || c
== 'n' || c
== 'N')
621 else if (c
== '1' || c
== 'y' || c
== 'Y')
630 linuxExtensionsEnabled_read(char *page
, char **start
, off_t off
,
631 int count
, int *eof
, void *data
)
635 len
= sprintf(page
, "%d\n", linuxExtEnabled
);
650 linuxExtensionsEnabled_write(struct file
*file
, const char __user
*buffer
,
651 unsigned long count
, void *data
)
656 rc
= get_user(c
, buffer
);
659 if (c
== '0' || c
== 'n' || c
== 'N')
661 else if (c
== '1' || c
== 'y' || c
== 'Y')
669 lookupFlag_read(char *page
, char **start
, off_t off
,
670 int count
, int *eof
, void *data
)
674 len
= sprintf(page
, "%d\n", lookupCacheEnabled
);
690 lookupFlag_write(struct file
*file
, const char __user
*buffer
,
691 unsigned long count
, void *data
)
696 rc
= get_user(c
, buffer
);
699 if (c
== '0' || c
== 'n' || c
== 'N')
700 lookupCacheEnabled
= 0;
701 else if (c
== '1' || c
== 'y' || c
== 'Y')
702 lookupCacheEnabled
= 1;
707 traceSMB_read(char *page
, char **start
, off_t off
, int count
,
708 int *eof
, void *data
)
712 len
= sprintf(page
, "%d\n", traceSMB
);
728 traceSMB_write(struct file
*file
, const char __user
*buffer
,
729 unsigned long count
, void *data
)
734 rc
= get_user(c
, buffer
);
737 if (c
== '0' || c
== 'n' || c
== 'N')
739 else if (c
== '1' || c
== 'y' || c
== 'Y')
746 multiuser_mount_read(char *page
, char **start
, off_t off
,
747 int count
, int *eof
, void *data
)
751 len
= sprintf(page
, "%d\n", multiuser_mount
);
767 multiuser_mount_write(struct file
*file
, const char __user
*buffer
,
768 unsigned long count
, void *data
)
773 rc
= get_user(c
, buffer
);
776 if (c
== '0' || c
== 'n' || c
== 'N')
778 else if (c
== '1' || c
== 'y' || c
== 'Y')
785 extended_security_read(char *page
, char **start
, off_t off
,
786 int count
, int *eof
, void *data
)
790 len
= sprintf(page
, "%d\n", extended_security
);
806 extended_security_write(struct file
*file
, const char __user
*buffer
,
807 unsigned long count
, void *data
)
812 rc
= get_user(c
, buffer
);
815 if (c
== '0' || c
== 'n' || c
== 'N')
816 extended_security
= 0;
817 else if (c
== '1' || c
== 'y' || c
== 'Y')
818 extended_security
= 1;
824 ntlmv2_enabled_read(char *page
, char **start
, off_t off
,
825 int count
, int *eof
, void *data
)
829 len
= sprintf(page
, "%d\n", ntlmv2_support
);
845 ntlmv2_enabled_write(struct file
*file
, const char __user
*buffer
,
846 unsigned long count
, void *data
)
851 rc
= get_user(c
, buffer
);
854 if (c
== '0' || c
== 'n' || c
== 'N')
856 else if (c
== '1' || c
== 'y' || c
== 'Y')
863 packet_signing_enabled_read(char *page
, char **start
, off_t off
,
864 int count
, int *eof
, void *data
)
868 len
= sprintf(page
, "%d\n", sign_CIFS_PDUs
);
884 packet_signing_enabled_write(struct file
*file
, const char __user
*buffer
,
885 unsigned long count
, void *data
)
890 rc
= get_user(c
, buffer
);
893 if (c
== '0' || c
== 'n' || c
== 'N')
895 else if (c
== '1' || c
== 'y' || c
== 'Y')