ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / fs / cifs / cifs_debug.c
1 /*
2  *   fs/cifs_debug.c
3  *
4  *   Copyright (C) International Business Machines  Corp., 2000,2003
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
33 void
34 cifs_dump_mem(char *label, void *data, int length)
35 {
36         int i, j;
37         int *intptr = data;
38         char *charptr = data;
39         char buf[10], line[80];
40
41         printk(KERN_DEBUG "%s: dump of %d bytes of data at 0x%p\n\n", 
42                 label, length, data);
43         for (i = 0; i < length; i += 16) {
44                 line[0] = 0;
45                 for (j = 0; (j < 4) && (i + j * 4 < length); j++) {
46                         sprintf(buf, " %08x", intptr[i / 4 + j]);
47                         strcat(line, buf);
48                 }
49                 buf[0] = ' ';
50                 buf[2] = 0;
51                 for (j = 0; (j < 16) && (i + j < length); j++) {
52                         buf[1] = isprint(charptr[i + j]) ? charptr[i + j] : '.';
53                         strcat(line, buf);
54                 }
55                 printk(KERN_DEBUG "%s\n", line);
56         }
57 }
58
59 #ifdef CONFIG_PROC_FS
60 int
61 cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
62                      int count, int *eof, void *data)
63 {
64         struct list_head *tmp;
65         struct cifsSesInfo *ses;
66         struct cifsTconInfo *tcon;
67         int i;
68         int length = 0;
69         char *buf_start = buf;
70
71         length =
72             sprintf(buf,
73                     "Display Internal CIFS Data Structures for Debugging\n"
74                     "---------------------------------------------------\n");
75         buf += length;
76
77         length = sprintf(buf, "Servers: \n");
78         buf += length;
79
80         i = 0;
81         read_lock(&GlobalSMBSeslock);
82         list_for_each(tmp, &GlobalSMBSessionList) {
83                 i++;
84                 ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
85                 length =
86                     sprintf(buf,
87                             "\n%d) Name: %s  Domain: %s Mounts: %d ServerOS: %s  \n\tServerNOS: %s\tCapabilities: 0x%x\n\tSMB session status: %d\tTCP session status: %d",
88                                 i, ses->serverName, ses->serverDomain, atomic_read(&ses->inUse),
89                                 ses->serverOS, ses->serverNOS, ses->capabilities,ses->status,ses->server->tcpStatus);
90                 buf += length;
91                 if(ses->server) {
92                         buf += sprintf(buf, "\n\tLocal Users To Same Server: %d SecMode: 0x%x",
93                                 atomic_read(&ses->server->socketUseCount),ses->server->secMode);
94                         
95                         /* length = sprintf(buf, "\nMIDs: \n");
96                         buf += length;
97
98                         spin_lock(&GlobalMid_Lock);
99                         list_for_each(tmp1, &ses->server->pending_mid_q) {
100                                 mid_entry = list_entry(tmp1, struct
101                                         mid_q_entry,
102                                         qhead);
103                                 if(mid_entry) {
104                                         length = sprintf(buf,"State: %d com: %d pid: %d tsk: %p\n",mid_entry->midState,mid_entry->command,mid_entry->pid,mid_entry->tsk);
105                                         buf += length;
106                                 }
107                         }
108                         spin_unlock(&GlobalMid_Lock); */
109                 }
110
111         }
112         read_unlock(&GlobalSMBSeslock);
113         sprintf(buf, "\n");
114         buf++;
115
116         length = sprintf(buf, "\nShares: \n");
117         buf += length;
118
119         i = 0;
120         read_lock(&GlobalSMBSeslock);
121         list_for_each(tmp, &GlobalTreeConnectionList) {
122                 i++;
123                 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
124                 length =
125                     sprintf(buf,
126                             "\n%d) %s Uses: %d on FS: %s with characteristics: 0x%x Attributes: 0x%x\n\tPathComponentMax: %d Status: %d",
127                             i, tcon->treeName,
128                             atomic_read(&tcon->useCount),
129                             tcon->nativeFileSystem,
130                             tcon->fsDevInfo.DeviceCharacteristics,
131                             tcon->fsAttrInfo.Attributes,
132                             tcon->fsAttrInfo.MaxPathNameComponentLength,tcon->tidStatus);
133                 buf += length;        
134                 if (tcon->fsDevInfo.DeviceType == FILE_DEVICE_DISK)
135                         length = sprintf(buf, " type: DISK ");
136                 else if (tcon->fsDevInfo.DeviceType == FILE_DEVICE_CD_ROM)
137                         length = sprintf(buf, " type: CDROM ");
138                 else
139                         length =
140                             sprintf(buf, " type: %d ",
141                                     tcon->fsDevInfo.DeviceType);
142                 buf += length;
143                 if(tcon->tidStatus == CifsNeedReconnect)
144                         buf += sprintf(buf, "\tDISCONNECTED ");
145         }
146         read_unlock(&GlobalSMBSeslock);
147
148         length = sprintf(buf, "\n");
149         buf += length;
150
151         *eof = 1;
152         /* BB add code to dump additional info such as TCP session info now */
153         /*
154            if (offset >= (buf - buf_start)) 
155            {
156            *beginBuffer = buf;
157            return 0;
158            }
159            *beginBuffer = buf + offset;
160            if ((buf - buf_start - offset) > count)
161            return count;
162    else */
163         return (buf - buf_start - offset);
164 }
165
166 int
167 cifs_total_xid_read(char *buf, char **beginBuffer, off_t offset,
168                     int length, int *eof, void *data)
169 {
170
171         length =
172             sprintf(buf,
173                     "Total vfs operations: %d and maximum simultaneous serviced by this filesystem: %d\n",
174                     GlobalCurrentXid,GlobalMaxActiveXid);
175
176         return length;
177 }
178
179 int
180 cifs_stats_read(char *buf, char **beginBuffer, off_t offset,
181                   int length, int *eof, void *data)
182 {
183         int item_length;
184         length =
185             sprintf(buf,
186                     "Currently Allocated structures\nCIFS Sessions: %d\n",sesInfoAllocCount.counter);
187         buf += length;
188         item_length = 
189                 sprintf(buf,"Shares (unique mount targets): %d\n",tconInfoAllocCount.counter);
190         length += item_length;
191         buf += item_length;      
192         item_length = 
193                         sprintf(buf,"Allocated SMB Request and Response Buffers: %d\n",bufAllocCount.counter);
194         length += item_length;
195         buf += item_length;      
196         item_length = 
197                 sprintf(buf,"Active Operations (MIDs in use): %d\n",midCount.counter);
198         length += item_length;
199         buf += item_length;
200         item_length = sprintf(buf,"%d sessions and %d shares reconnected after failure\n",tcpSesReconnectCount.counter,tconInfoReconnectCount.counter);
201         length += item_length;
202
203         return length;
204 }
205
206 struct proc_dir_entry *proc_fs_cifs;
207 read_proc_t cifs_txanchor_read;
208 static read_proc_t cifsFYI_read;
209 static write_proc_t cifsFYI_write;
210 static read_proc_t oplockEnabled_read;
211 static write_proc_t oplockEnabled_write;
212 static read_proc_t lookupFlag_read;
213 static write_proc_t lookupFlag_write;
214 static read_proc_t traceSMB_read;
215 static write_proc_t traceSMB_write;
216 static read_proc_t multiuser_mount_read;
217 static write_proc_t multiuser_mount_write;
218 static read_proc_t extended_security_read;
219 static write_proc_t extended_security_write;
220 static read_proc_t ntlmv2_enabled_read;
221 static write_proc_t ntlmv2_enabled_write;
222 static read_proc_t packet_signing_enabled_read;
223 static write_proc_t packet_signing_enabled_write;
224 static read_proc_t quotaEnabled_read;
225 static write_proc_t quotaEnabled_write;
226 static read_proc_t linuxExtensionsEnabled_read;
227 static write_proc_t linuxExtensionsEnabled_write;
228
229 void
230 cifs_proc_init(void)
231 {
232         struct proc_dir_entry *pde;
233
234         proc_fs_cifs = proc_mkdir("cifs", proc_root_fs);
235         if (proc_fs_cifs == NULL)
236                 return;
237
238         proc_fs_cifs->owner = THIS_MODULE;
239         create_proc_read_entry("DebugData", 0, proc_fs_cifs,
240                                 cifs_debug_data_read, 0);
241
242         create_proc_read_entry("SimultaneousOps", 0, proc_fs_cifs,
243                                 cifs_total_xid_read, 0);
244
245         create_proc_read_entry("Stats", 0, proc_fs_cifs,
246                                 cifs_stats_read, 0);
247
248         pde = create_proc_read_entry("cifsFYI", 0, proc_fs_cifs,
249                                 cifsFYI_read, 0);
250         if (pde)
251                 pde->write_proc = cifsFYI_write;
252
253         pde =
254             create_proc_read_entry("traceSMB", 0, proc_fs_cifs,
255                                 traceSMB_read, 0);
256         if (pde)
257                 pde->write_proc = traceSMB_write;
258
259         pde = create_proc_read_entry("OplockEnabled", 0, proc_fs_cifs,
260                                 oplockEnabled_read, 0);
261         if (pde)
262                 pde->write_proc = oplockEnabled_write;
263
264         pde = create_proc_read_entry("QuotaEnabled", 0, proc_fs_cifs,
265                                 quotaEnabled_read, 0);
266         if (pde)
267                 pde->write_proc = quotaEnabled_write;
268
269         pde = create_proc_read_entry("LinuxExtensionsEnabled", 0, proc_fs_cifs,
270                                 linuxExtensionsEnabled_read, 0);
271         if (pde)
272                 pde->write_proc = linuxExtensionsEnabled_write;
273
274         pde =
275             create_proc_read_entry("MultiuserMount", 0, proc_fs_cifs,
276                                 multiuser_mount_read, 0);
277         if (pde)
278                 pde->write_proc = multiuser_mount_write;
279
280         pde =
281             create_proc_read_entry("ExtendedSecurity", 0, proc_fs_cifs,
282                                 extended_security_read, 0);
283         if (pde)
284                 pde->write_proc = extended_security_write;
285
286         pde =
287         create_proc_read_entry("LookupCacheEnabled", 0, proc_fs_cifs,
288                                 lookupFlag_read, 0);
289         if (pde)
290                 pde->write_proc = lookupFlag_write;
291
292         pde =
293             create_proc_read_entry("NTLMV2Enabled", 0, proc_fs_cifs,
294                                 ntlmv2_enabled_read, 0);
295         if (pde)
296                 pde->write_proc = ntlmv2_enabled_write;
297
298         pde =
299             create_proc_read_entry("PacketSigningEnabled", 0, proc_fs_cifs,
300                                 packet_signing_enabled_read, 0);
301         if (pde)
302                 pde->write_proc = packet_signing_enabled_write;
303 }
304
305 void
306 cifs_proc_clean(void)
307 {
308         if (proc_fs_cifs == NULL)
309                 return;
310
311         remove_proc_entry("DebugData", proc_fs_cifs);
312         remove_proc_entry("cifsFYI", proc_fs_cifs);
313         remove_proc_entry("traceSMB", proc_fs_cifs);
314         remove_proc_entry("SimultaneousOps", proc_fs_cifs);
315         remove_proc_entry("Stats", proc_fs_cifs);
316         remove_proc_entry("MultiuserMount", proc_fs_cifs);
317         remove_proc_entry("OplockEnabled", proc_fs_cifs);
318         remove_proc_entry("NTLMV2Enabled",proc_fs_cifs);
319         remove_proc_entry("ExtendedSecurity",proc_fs_cifs);
320         remove_proc_entry("PacketSigningEnabled",proc_fs_cifs);
321         remove_proc_entry("LinuxExtensionsEnabled",proc_fs_cifs);
322         remove_proc_entry("QuotaEnabled",proc_fs_cifs);
323         remove_proc_entry("LookupCacheEnabled",proc_fs_cifs);
324         remove_proc_entry("cifs", proc_root_fs);
325 }
326
327 static int
328 cifsFYI_read(char *page, char **start, off_t off, int count,
329              int *eof, void *data)
330 {
331         int len;
332
333         len = sprintf(page, "%d\n", cifsFYI);
334
335         len -= off;
336         *start = page + off;
337
338         if (len > count)
339                 len = count;
340         else
341                 *eof = 1;
342
343         if (len < 0)
344                 len = 0;
345
346         return len;
347 }
348 static int
349 cifsFYI_write(struct file *file, const char *buffer,
350               unsigned long count, void *data)
351 {
352         char c;
353         int rc;
354
355         rc = get_user(c, buffer);
356         if (rc)
357                 return rc;
358         if (c == '0' || c == 'n' || c == 'N')
359                 cifsFYI = 0;
360         else if (c == '1' || c == 'y' || c == 'Y')
361                 cifsFYI = 1;
362
363         return count;
364 }
365
366 static int
367 oplockEnabled_read(char *page, char **start, off_t off,
368                    int count, int *eof, void *data)
369 {
370         int len;
371
372         len = sprintf(page, "%d\n", oplockEnabled);
373
374         len -= off;
375         *start = page + off;
376
377         if (len > count)
378                 len = count;
379         else
380                 *eof = 1;
381
382         if (len < 0)
383                 len = 0;
384
385         return len;
386 }
387 static int
388 oplockEnabled_write(struct file *file, const char *buffer,
389                     unsigned long count, void *data)
390 {
391         char c;
392         int rc;
393
394         rc = get_user(c, buffer);
395         if (rc)
396                 return rc;
397         if (c == '0' || c == 'n' || c == 'N')
398                 oplockEnabled = 0;
399         else if (c == '1' || c == 'y' || c == 'Y')
400                 oplockEnabled = 1;
401
402         return count;
403 }
404
405 static int
406 quotaEnabled_read(char *page, char **start, off_t off,
407                    int count, int *eof, void *data)
408 {
409         int len;
410
411         len = sprintf(page, "%d\n", quotaEnabled);
412 /* could also check if quotas are enabled in kernel
413         as a whole first */
414         len -= off;
415         *start = page + off;
416
417         if (len > count)
418                 len = count;
419         else
420                 *eof = 1;
421
422         if (len < 0)
423                 len = 0;
424
425         return len;
426 }
427 static int
428 quotaEnabled_write(struct file *file, const char *buffer,
429                     unsigned long count, void *data)
430 {
431         char c;
432         int rc;
433
434         rc = get_user(c, buffer);
435         if (rc)
436                 return rc;
437         if (c == '0' || c == 'n' || c == 'N')
438                 quotaEnabled = 0;
439         else if (c == '1' || c == 'y' || c == 'Y')
440                 quotaEnabled = 1;
441
442         return count;
443 }
444
445 static int
446 linuxExtensionsEnabled_read(char *page, char **start, off_t off,
447                    int count, int *eof, void *data)
448 {
449         int len;
450
451         len = sprintf(page, "%d\n", linuxExtEnabled);
452 /* could also check if quotas are enabled in kernel
453         as a whole first */
454         len -= off;
455         *start = page + off;
456
457         if (len > count)
458                 len = count;
459         else
460                 *eof = 1;
461
462         if (len < 0)
463                 len = 0;
464
465         return len;
466 }
467 static int
468 linuxExtensionsEnabled_write(struct file *file, const char *buffer,
469                     unsigned long count, void *data)
470 {
471         char c;
472         int rc;
473
474         rc = get_user(c, buffer);
475         if (rc)
476                 return rc;
477         if (c == '0' || c == 'n' || c == 'N')
478                 linuxExtEnabled = 0;
479         else if (c == '1' || c == 'y' || c == 'Y')
480                 linuxExtEnabled = 1;
481
482         return count;
483 }
484
485
486 static int
487 lookupFlag_read(char *page, char **start, off_t off,
488                    int count, int *eof, void *data)
489 {
490         int len;
491
492         len = sprintf(page, "%d\n", lookupCacheEnabled);
493
494         len -= off;
495         *start = page + off;
496
497         if (len > count)
498                 len = count;
499         else
500                 *eof = 1;
501
502         if (len < 0)
503                 len = 0;
504
505         return len;
506 }
507 static int
508 lookupFlag_write(struct file *file, const char *buffer,
509                     unsigned long count, void *data)
510 {
511         char c;
512         int rc;
513
514         rc = get_user(c, buffer);
515         if (rc)
516                 return rc;
517         if (c == '0' || c == 'n' || c == 'N')
518                 lookupCacheEnabled = 0;
519         else if (c == '1' || c == 'y' || c == 'Y')
520                 lookupCacheEnabled = 1;
521
522         return count;
523 }
524 static int
525 traceSMB_read(char *page, char **start, off_t off, int count,
526               int *eof, void *data)
527 {
528         int len;
529
530         len = sprintf(page, "%d\n", traceSMB);
531
532         len -= off;
533         *start = page + off;
534
535         if (len > count)
536                 len = count;
537         else
538                 *eof = 1;
539
540         if (len < 0)
541                 len = 0;
542
543         return len;
544 }
545 static int
546 traceSMB_write(struct file *file, const char *buffer,
547                unsigned long count, void *data)
548 {
549         char c;
550         int rc;
551
552         rc = get_user(c, buffer);
553         if (rc)
554                 return rc;
555         if (c == '0' || c == 'n' || c == 'N')
556                 traceSMB = 0;
557         else if (c == '1' || c == 'y' || c == 'Y')
558                 traceSMB = 1;
559
560         return count;
561 }
562
563 static int
564 multiuser_mount_read(char *page, char **start, off_t off,
565                      int count, int *eof, void *data)
566 {
567         int len;
568
569         len = sprintf(page, "%d\n", multiuser_mount);
570
571         len -= off;
572         *start = page + off;
573
574         if (len > count)
575                 len = count;
576         else
577                 *eof = 1;
578
579         if (len < 0)
580                 len = 0;
581
582         return len;
583 }
584 static int
585 multiuser_mount_write(struct file *file, const char *buffer,
586                       unsigned long count, void *data)
587 {
588         char c;
589         int rc;
590
591         rc = get_user(c, buffer);
592         if (rc)
593                 return rc;
594         if (c == '0' || c == 'n' || c == 'N')
595                 multiuser_mount = 0;
596         else if (c == '1' || c == 'y' || c == 'Y')
597                 multiuser_mount = 1;
598
599         return count;
600 }
601
602 static int
603 extended_security_read(char *page, char **start, off_t off,
604                        int count, int *eof, void *data)
605 {
606         int len;
607
608         len = sprintf(page, "%d\n", extended_security);
609
610         len -= off;
611         *start = page + off;
612
613         if (len > count)
614                 len = count;
615         else
616                 *eof = 1;
617
618         if (len < 0)
619                 len = 0;
620
621         return len;
622 }
623 static int
624 extended_security_write(struct file *file, const char *buffer,
625                         unsigned long count, void *data)
626 {
627         char c;
628         int rc;
629
630         rc = get_user(c, buffer);
631         if (rc)
632                 return rc;
633         if (c == '0' || c == 'n' || c == 'N')
634                 extended_security = 0;
635         else if (c == '1' || c == 'y' || c == 'Y')
636                 extended_security = 1;
637
638         return count;
639 }
640
641 static int
642 ntlmv2_enabled_read(char *page, char **start, off_t off,
643                        int count, int *eof, void *data)
644 {
645         int len;
646
647         len = sprintf(page, "%d\n", ntlmv2_support);
648
649         len -= off;
650         *start = page + off;
651
652         if (len > count)
653                 len = count;
654         else
655                 *eof = 1;
656
657         if (len < 0)
658                 len = 0;
659
660         return len;
661 }
662 static int
663 ntlmv2_enabled_write(struct file *file, const char *buffer,
664                         unsigned long count, void *data)
665 {
666         char c;
667         int rc;
668
669         rc = get_user(c, buffer);
670         if (rc)
671                 return rc;
672         if (c == '0' || c == 'n' || c == 'N')
673                 ntlmv2_support = 0;
674         else if (c == '1' || c == 'y' || c == 'Y')
675                 ntlmv2_support = 1;
676
677         return count;
678 }
679
680 static int
681 packet_signing_enabled_read(char *page, char **start, off_t off,
682                        int count, int *eof, void *data)
683 {
684         int len;
685
686         len = sprintf(page, "%d\n", sign_CIFS_PDUs);
687
688         len -= off;
689         *start = page + off;
690
691         if (len > count)
692                 len = count;
693         else
694                 *eof = 1;
695
696         if (len < 0)
697                 len = 0;
698
699         return len;
700 }
701 static int
702 packet_signing_enabled_write(struct file *file, const char *buffer,
703                         unsigned long count, void *data)
704 {
705         char c;
706         int rc;
707
708         rc = get_user(c, buffer);
709         if (rc)
710                 return rc;
711         if (c == '0' || c == 'n' || c == 'N')
712                 sign_CIFS_PDUs = 0;
713         else if (c == '1' || c == 'y' || c == 'Y')
714                 sign_CIFS_PDUs = 1;
715         else if (c == '2')
716                 sign_CIFS_PDUs = 2;
717
718         return count;
719 }
720
721
722 #endif