patch-2_6_7-vs1_9_1_12
[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 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 Server: %d SecMode: 0x%x Req Active: %d",
93                                 atomic_read(&ses->server->socketUseCount),
94                                 ses->server->secMode,
95                                 atomic_read(&ses->server->inFlight));
96                         
97                         /* length = sprintf(buf, "\nMIDs: \n");
98                         buf += length;
99
100                         spin_lock(&GlobalMid_Lock);
101                         list_for_each(tmp1, &ses->server->pending_mid_q) {
102                                 mid_entry = list_entry(tmp1, struct
103                                         mid_q_entry,
104                                         qhead);
105                                 if(mid_entry) {
106                                         length = sprintf(buf,"State: %d com: %d pid: %d tsk: %p\n",mid_entry->midState,mid_entry->command,mid_entry->pid,mid_entry->tsk);
107                                         buf += length;
108                                 }
109                         }
110                         spin_unlock(&GlobalMid_Lock); */
111                 }
112
113         }
114         read_unlock(&GlobalSMBSeslock);
115         sprintf(buf, "\n");
116         buf++;
117
118         length = sprintf(buf, "\nShares:\n");
119         buf += length;
120
121         i = 0;
122         read_lock(&GlobalSMBSeslock);
123         list_for_each(tmp, &GlobalTreeConnectionList) {
124                 i++;
125                 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
126                 length =
127                     sprintf(buf,
128                             "\n%d) %s Uses: %d Type: %s Characteristics: 0x%x Attributes: 0x%x\nPathComponentMax: %d Status: %d",
129                             i, tcon->treeName,
130                             atomic_read(&tcon->useCount),
131                             tcon->nativeFileSystem,
132                             tcon->fsDevInfo.DeviceCharacteristics,
133                             tcon->fsAttrInfo.Attributes,
134                             tcon->fsAttrInfo.MaxPathNameComponentLength,tcon->tidStatus);
135                 buf += length;        
136                 if (tcon->fsDevInfo.DeviceType == FILE_DEVICE_DISK)
137                         length = sprintf(buf, " type: DISK ");
138                 else if (tcon->fsDevInfo.DeviceType == FILE_DEVICE_CD_ROM)
139                         length = sprintf(buf, " type: CDROM ");
140                 else
141                         length =
142                             sprintf(buf, " type: %d ",
143                                     tcon->fsDevInfo.DeviceType);
144                 buf += length;
145                 if(tcon->tidStatus == CifsNeedReconnect) {
146                         buf += sprintf(buf, "\tDISCONNECTED ");
147                         length += 14;
148                 }
149         }
150         read_unlock(&GlobalSMBSeslock);
151
152         length = sprintf(buf, "\n");
153         buf += length;
154
155         *eof = 1;
156         /* BB add code to dump additional info such as TCP session info now */
157         /*
158            if (offset >= (buf - buf_start)) 
159            {
160            *beginBuffer = buf;
161            return 0;
162            }
163            *beginBuffer = buf + offset;
164            if ((buf - buf_start - offset) > count)
165            return count;
166    else */
167         return (buf - buf_start - offset);
168 }
169
170 int
171 cifs_total_xid_read(char *buf, char **beginBuffer, off_t offset,
172                     int length, int *eof, void *data)
173 {
174
175         length =
176             sprintf(buf,
177                     "Total vfs operations: %d and maximum simultaneous serviced by this filesystem: %d\n",
178                     GlobalCurrentXid,GlobalMaxActiveXid);
179
180         return length;
181 }
182
183 #ifdef CONFIG_CIFS_STATS
184 int
185 cifs_stats_read(char *buf, char **beginBuffer, off_t offset,
186                   int length, int *eof, void *data)
187 {
188         int item_length,i;
189         struct list_head *tmp;
190         struct cifsTconInfo *tcon;
191
192         length = sprintf(buf,
193                         "Resources in use\nCIFS Session: %d\n",
194                         sesInfoAllocCount.counter);
195         buf += length;
196         item_length = 
197                 sprintf(buf,"Share (unique mount targets): %d\n",
198                         tconInfoAllocCount.counter);
199         length += item_length;
200         buf += item_length;      
201         item_length = 
202                 sprintf(buf,"SMB Request/Response Buffer: %d\n",
203                         bufAllocCount.counter);
204         length += item_length;
205         buf += item_length;      
206         item_length = 
207                 sprintf(buf,"Operations (MIDs): %d\n",
208                         midCount.counter);
209         length += item_length;
210         buf += item_length;
211         item_length = sprintf(buf,
212                 "\n%d session %d share reconnects\n",
213                 tcpSesReconnectCount.counter,tconInfoReconnectCount.counter);
214         length += item_length;
215         buf += item_length;
216
217         i = 0;
218         read_lock(&GlobalSMBSeslock);
219         list_for_each(tmp, &GlobalTreeConnectionList) {
220                 i++;
221                 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
222                 item_length = sprintf(buf,"\n%d) %s",i, tcon->treeName);
223                 buf += item_length;
224                 length += item_length;
225                 if(tcon->tidStatus == CifsNeedReconnect) {
226                         buf += sprintf(buf, "\tDISCONNECTED ");
227                         length += 14;
228                 }
229                 item_length = sprintf(buf,"\nSMBs: %d Oplock Breaks: %d",
230                         atomic_read(&tcon->num_smbs_sent),
231                         atomic_read(&tcon->num_oplock_brks));
232                 buf += item_length;
233                 length += item_length;
234                 item_length = sprintf(buf,"\nReads: %d Bytes %lld",
235                         atomic_read(&tcon->num_reads),
236                         (long long)(tcon->bytes_read));
237                 buf += item_length;
238                 item_length = sprintf(buf,"\nWrites: %d Bytes: %lld",
239                         atomic_read(&tcon->num_writes),
240                         (long long)(tcon->bytes_written));
241                 buf += item_length;
242                 item_length = sprintf(buf,
243                         "\nOpens: %d Deletes: %d\nMkdirs: %d Rmdirs: %d",
244                         atomic_read(&tcon->num_opens),
245                         atomic_read(&tcon->num_deletes),
246                         atomic_read(&tcon->num_mkdirs),
247                         atomic_read(&tcon->num_rmdirs));
248                 buf += item_length;
249                 length += item_length;
250         }
251         read_unlock(&GlobalSMBSeslock);
252
253
254         return length;
255 }
256 #endif
257
258 struct proc_dir_entry *proc_fs_cifs;
259 read_proc_t cifs_txanchor_read;
260 static read_proc_t cifsFYI_read;
261 static write_proc_t cifsFYI_write;
262 static read_proc_t oplockEnabled_read;
263 static write_proc_t oplockEnabled_write;
264 static read_proc_t lookupFlag_read;
265 static write_proc_t lookupFlag_write;
266 static read_proc_t traceSMB_read;
267 static write_proc_t traceSMB_write;
268 static read_proc_t multiuser_mount_read;
269 static write_proc_t multiuser_mount_write;
270 static read_proc_t extended_security_read;
271 static write_proc_t extended_security_write;
272 static read_proc_t ntlmv2_enabled_read;
273 static write_proc_t ntlmv2_enabled_write;
274 static read_proc_t packet_signing_enabled_read;
275 static write_proc_t packet_signing_enabled_write;
276 static read_proc_t quotaEnabled_read;
277 static write_proc_t quotaEnabled_write;
278 static read_proc_t linuxExtensionsEnabled_read;
279 static write_proc_t linuxExtensionsEnabled_write;
280
281 void
282 cifs_proc_init(void)
283 {
284         struct proc_dir_entry *pde;
285
286         proc_fs_cifs = proc_mkdir("cifs", proc_root_fs);
287         if (proc_fs_cifs == NULL)
288                 return;
289
290         proc_fs_cifs->owner = THIS_MODULE;
291         create_proc_read_entry("DebugData", 0, proc_fs_cifs,
292                                 cifs_debug_data_read, 0);
293
294         create_proc_read_entry("SimultaneousOps", 0, proc_fs_cifs,
295                                 cifs_total_xid_read, 0);
296 #ifdef CONFIG_CIFS_STATS
297         create_proc_read_entry("Stats", 0, proc_fs_cifs,
298                                 cifs_stats_read, 0);
299 #endif
300         pde = create_proc_read_entry("cifsFYI", 0, proc_fs_cifs,
301                                 cifsFYI_read, 0);
302         if (pde)
303                 pde->write_proc = cifsFYI_write;
304
305         pde =
306             create_proc_read_entry("traceSMB", 0, proc_fs_cifs,
307                                 traceSMB_read, 0);
308         if (pde)
309                 pde->write_proc = traceSMB_write;
310
311         pde = create_proc_read_entry("OplockEnabled", 0, proc_fs_cifs,
312                                 oplockEnabled_read, 0);
313         if (pde)
314                 pde->write_proc = oplockEnabled_write;
315
316         pde = create_proc_read_entry("QuotaEnabled", 0, proc_fs_cifs,
317                                 quotaEnabled_read, 0);
318         if (pde)
319                 pde->write_proc = quotaEnabled_write;
320
321         pde = create_proc_read_entry("LinuxExtensionsEnabled", 0, proc_fs_cifs,
322                                 linuxExtensionsEnabled_read, 0);
323         if (pde)
324                 pde->write_proc = linuxExtensionsEnabled_write;
325
326         pde =
327             create_proc_read_entry("MultiuserMount", 0, proc_fs_cifs,
328                                 multiuser_mount_read, 0);
329         if (pde)
330                 pde->write_proc = multiuser_mount_write;
331
332         pde =
333             create_proc_read_entry("ExtendedSecurity", 0, proc_fs_cifs,
334                                 extended_security_read, 0);
335         if (pde)
336                 pde->write_proc = extended_security_write;
337
338         pde =
339         create_proc_read_entry("LookupCacheEnabled", 0, proc_fs_cifs,
340                                 lookupFlag_read, 0);
341         if (pde)
342                 pde->write_proc = lookupFlag_write;
343
344         pde =
345             create_proc_read_entry("NTLMV2Enabled", 0, proc_fs_cifs,
346                                 ntlmv2_enabled_read, 0);
347         if (pde)
348                 pde->write_proc = ntlmv2_enabled_write;
349
350         pde =
351             create_proc_read_entry("PacketSigningEnabled", 0, proc_fs_cifs,
352                                 packet_signing_enabled_read, 0);
353         if (pde)
354                 pde->write_proc = packet_signing_enabled_write;
355 }
356
357 void
358 cifs_proc_clean(void)
359 {
360         if (proc_fs_cifs == NULL)
361                 return;
362
363         remove_proc_entry("DebugData", proc_fs_cifs);
364         remove_proc_entry("cifsFYI", proc_fs_cifs);
365         remove_proc_entry("traceSMB", proc_fs_cifs);
366         remove_proc_entry("SimultaneousOps", proc_fs_cifs);
367 #ifdef CONFIG_CIFS_STATS
368         remove_proc_entry("Stats", proc_fs_cifs);
369 #endif
370         remove_proc_entry("MultiuserMount", proc_fs_cifs);
371         remove_proc_entry("OplockEnabled", proc_fs_cifs);
372         remove_proc_entry("NTLMV2Enabled",proc_fs_cifs);
373         remove_proc_entry("ExtendedSecurity",proc_fs_cifs);
374         remove_proc_entry("PacketSigningEnabled",proc_fs_cifs);
375         remove_proc_entry("LinuxExtensionsEnabled",proc_fs_cifs);
376         remove_proc_entry("QuotaEnabled",proc_fs_cifs);
377         remove_proc_entry("LookupCacheEnabled",proc_fs_cifs);
378         remove_proc_entry("cifs", proc_root_fs);
379 }
380
381 static int
382 cifsFYI_read(char *page, char **start, off_t off, int count,
383              int *eof, void *data)
384 {
385         int len;
386
387         len = sprintf(page, "%d\n", cifsFYI);
388
389         len -= off;
390         *start = page + off;
391
392         if (len > count)
393                 len = count;
394         else
395                 *eof = 1;
396
397         if (len < 0)
398                 len = 0;
399
400         return len;
401 }
402 static int
403 cifsFYI_write(struct file *file, const char __user *buffer,
404               unsigned long count, void *data)
405 {
406         char c;
407         int rc;
408
409         rc = get_user(c, buffer);
410         if (rc)
411                 return rc;
412         if (c == '0' || c == 'n' || c == 'N')
413                 cifsFYI = 0;
414         else if (c == '1' || c == 'y' || c == 'Y')
415                 cifsFYI = 1;
416
417         return count;
418 }
419
420 static int
421 oplockEnabled_read(char *page, char **start, off_t off,
422                    int count, int *eof, void *data)
423 {
424         int len;
425
426         len = sprintf(page, "%d\n", oplockEnabled);
427
428         len -= off;
429         *start = page + off;
430
431         if (len > count)
432                 len = count;
433         else
434                 *eof = 1;
435
436         if (len < 0)
437                 len = 0;
438
439         return len;
440 }
441 static int
442 oplockEnabled_write(struct file *file, const char __user *buffer,
443                     unsigned long count, void *data)
444 {
445         char c;
446         int rc;
447
448         rc = get_user(c, buffer);
449         if (rc)
450                 return rc;
451         if (c == '0' || c == 'n' || c == 'N')
452                 oplockEnabled = 0;
453         else if (c == '1' || c == 'y' || c == 'Y')
454                 oplockEnabled = 1;
455
456         return count;
457 }
458
459 static int
460 quotaEnabled_read(char *page, char **start, off_t off,
461                    int count, int *eof, void *data)
462 {
463         int len;
464
465         len = sprintf(page, "%d\n", quotaEnabled);
466 /* could also check if quotas are enabled in kernel
467         as a whole first */
468         len -= off;
469         *start = page + off;
470
471         if (len > count)
472                 len = count;
473         else
474                 *eof = 1;
475
476         if (len < 0)
477                 len = 0;
478
479         return len;
480 }
481 static int
482 quotaEnabled_write(struct file *file, const char __user *buffer,
483                     unsigned long count, void *data)
484 {
485         char c;
486         int rc;
487
488         rc = get_user(c, buffer);
489         if (rc)
490                 return rc;
491         if (c == '0' || c == 'n' || c == 'N')
492                 quotaEnabled = 0;
493         else if (c == '1' || c == 'y' || c == 'Y')
494                 quotaEnabled = 1;
495
496         return count;
497 }
498
499 static int
500 linuxExtensionsEnabled_read(char *page, char **start, off_t off,
501                    int count, int *eof, void *data)
502 {
503         int len;
504
505         len = sprintf(page, "%d\n", linuxExtEnabled);
506 /* could also check if quotas are enabled in kernel
507         as a whole first */
508         len -= off;
509         *start = page + off;
510
511         if (len > count)
512                 len = count;
513         else
514                 *eof = 1;
515
516         if (len < 0)
517                 len = 0;
518
519         return len;
520 }
521 static int
522 linuxExtensionsEnabled_write(struct file *file, const char __user *buffer,
523                     unsigned long count, void *data)
524 {
525         char c;
526         int rc;
527
528         rc = get_user(c, buffer);
529         if (rc)
530                 return rc;
531         if (c == '0' || c == 'n' || c == 'N')
532                 linuxExtEnabled = 0;
533         else if (c == '1' || c == 'y' || c == 'Y')
534                 linuxExtEnabled = 1;
535
536         return count;
537 }
538
539
540 static int
541 lookupFlag_read(char *page, char **start, off_t off,
542                    int count, int *eof, void *data)
543 {
544         int len;
545
546         len = sprintf(page, "%d\n", lookupCacheEnabled);
547
548         len -= off;
549         *start = page + off;
550
551         if (len > count)
552                 len = count;
553         else
554                 *eof = 1;
555
556         if (len < 0)
557                 len = 0;
558
559         return len;
560 }
561 static int
562 lookupFlag_write(struct file *file, const char __user *buffer,
563                     unsigned long count, void *data)
564 {
565         char c;
566         int rc;
567
568         rc = get_user(c, buffer);
569         if (rc)
570                 return rc;
571         if (c == '0' || c == 'n' || c == 'N')
572                 lookupCacheEnabled = 0;
573         else if (c == '1' || c == 'y' || c == 'Y')
574                 lookupCacheEnabled = 1;
575
576         return count;
577 }
578 static int
579 traceSMB_read(char *page, char **start, off_t off, int count,
580               int *eof, void *data)
581 {
582         int len;
583
584         len = sprintf(page, "%d\n", traceSMB);
585
586         len -= off;
587         *start = page + off;
588
589         if (len > count)
590                 len = count;
591         else
592                 *eof = 1;
593
594         if (len < 0)
595                 len = 0;
596
597         return len;
598 }
599 static int
600 traceSMB_write(struct file *file, const char __user *buffer,
601                unsigned long count, void *data)
602 {
603         char c;
604         int rc;
605
606         rc = get_user(c, buffer);
607         if (rc)
608                 return rc;
609         if (c == '0' || c == 'n' || c == 'N')
610                 traceSMB = 0;
611         else if (c == '1' || c == 'y' || c == 'Y')
612                 traceSMB = 1;
613
614         return count;
615 }
616
617 static int
618 multiuser_mount_read(char *page, char **start, off_t off,
619                      int count, int *eof, void *data)
620 {
621         int len;
622
623         len = sprintf(page, "%d\n", multiuser_mount);
624
625         len -= off;
626         *start = page + off;
627
628         if (len > count)
629                 len = count;
630         else
631                 *eof = 1;
632
633         if (len < 0)
634                 len = 0;
635
636         return len;
637 }
638 static int
639 multiuser_mount_write(struct file *file, const char __user *buffer,
640                       unsigned long count, void *data)
641 {
642         char c;
643         int rc;
644
645         rc = get_user(c, buffer);
646         if (rc)
647                 return rc;
648         if (c == '0' || c == 'n' || c == 'N')
649                 multiuser_mount = 0;
650         else if (c == '1' || c == 'y' || c == 'Y')
651                 multiuser_mount = 1;
652
653         return count;
654 }
655
656 static int
657 extended_security_read(char *page, char **start, off_t off,
658                        int count, int *eof, void *data)
659 {
660         int len;
661
662         len = sprintf(page, "%d\n", extended_security);
663
664         len -= off;
665         *start = page + off;
666
667         if (len > count)
668                 len = count;
669         else
670                 *eof = 1;
671
672         if (len < 0)
673                 len = 0;
674
675         return len;
676 }
677 static int
678 extended_security_write(struct file *file, const char __user *buffer,
679                         unsigned long count, void *data)
680 {
681         char c;
682         int rc;
683
684         rc = get_user(c, buffer);
685         if (rc)
686                 return rc;
687         if (c == '0' || c == 'n' || c == 'N')
688                 extended_security = 0;
689         else if (c == '1' || c == 'y' || c == 'Y')
690                 extended_security = 1;
691
692         return count;
693 }
694
695 static int
696 ntlmv2_enabled_read(char *page, char **start, off_t off,
697                        int count, int *eof, void *data)
698 {
699         int len;
700
701         len = sprintf(page, "%d\n", ntlmv2_support);
702
703         len -= off;
704         *start = page + off;
705
706         if (len > count)
707                 len = count;
708         else
709                 *eof = 1;
710
711         if (len < 0)
712                 len = 0;
713
714         return len;
715 }
716 static int
717 ntlmv2_enabled_write(struct file *file, const char __user *buffer,
718                         unsigned long count, void *data)
719 {
720         char c;
721         int rc;
722
723         rc = get_user(c, buffer);
724         if (rc)
725                 return rc;
726         if (c == '0' || c == 'n' || c == 'N')
727                 ntlmv2_support = 0;
728         else if (c == '1' || c == 'y' || c == 'Y')
729                 ntlmv2_support = 1;
730
731         return count;
732 }
733
734 static int
735 packet_signing_enabled_read(char *page, char **start, off_t off,
736                        int count, int *eof, void *data)
737 {
738         int len;
739
740         len = sprintf(page, "%d\n", sign_CIFS_PDUs);
741
742         len -= off;
743         *start = page + off;
744
745         if (len > count)
746                 len = count;
747         else
748                 *eof = 1;
749
750         if (len < 0)
751                 len = 0;
752
753         return len;
754 }
755 static int
756 packet_signing_enabled_write(struct file *file, const char __user *buffer,
757                         unsigned long count, void *data)
758 {
759         char c;
760         int rc;
761
762         rc = get_user(c, buffer);
763         if (rc)
764                 return rc;
765         if (c == '0' || c == 'n' || c == 'N')
766                 sign_CIFS_PDUs = 0;
767         else if (c == '1' || c == 'y' || c == 'Y')
768                 sign_CIFS_PDUs = 1;
769         else if (c == '2')
770                 sign_CIFS_PDUs = 2;
771
772         return count;
773 }
774
775
776 #endif