Merge tag 'docs-4.16' of git://git.lwn.net/linux
[sfrench/cifs-2.6.git] / fs / cifs / cifs_debug.c
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 <linux/uaccess.h>
28 #include "cifspdu.h"
29 #include "cifsglob.h"
30 #include "cifsproto.h"
31 #include "cifs_debug.h"
32 #include "cifsfs.h"
33 #ifdef CONFIG_CIFS_SMB_DIRECT
34 #include "smbdirect.h"
35 #endif
36
37 void
38 cifs_dump_mem(char *label, void *data, int length)
39 {
40         pr_debug("%s: dump of %d bytes of data at 0x%p\n", label, length, data);
41         print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 16, 4,
42                        data, length, true);
43 }
44
45 #ifdef CONFIG_CIFS_DEBUG
46 void cifs_vfs_err(const char *fmt, ...)
47 {
48         struct va_format vaf;
49         va_list args;
50
51         va_start(args, fmt);
52
53         vaf.fmt = fmt;
54         vaf.va = &args;
55
56         pr_err_ratelimited("CIFS VFS: %pV", &vaf);
57
58         va_end(args);
59 }
60 #endif
61
62 void cifs_dump_detail(void *buf)
63 {
64 #ifdef CONFIG_CIFS_DEBUG2
65         struct smb_hdr *smb = (struct smb_hdr *)buf;
66
67         cifs_dbg(VFS, "Cmd: %d Err: 0x%x Flags: 0x%x Flgs2: 0x%x Mid: %d Pid: %d\n",
68                  smb->Command, smb->Status.CifsError,
69                  smb->Flags, smb->Flags2, smb->Mid, smb->Pid);
70         cifs_dbg(VFS, "smb buf %p len %u\n", smb, smbCalcSize(smb));
71 #endif /* CONFIG_CIFS_DEBUG2 */
72 }
73
74 void cifs_dump_mids(struct TCP_Server_Info *server)
75 {
76 #ifdef CONFIG_CIFS_DEBUG2
77         struct list_head *tmp;
78         struct mid_q_entry *mid_entry;
79
80         if (server == NULL)
81                 return;
82
83         cifs_dbg(VFS, "Dump pending requests:\n");
84         spin_lock(&GlobalMid_Lock);
85         list_for_each(tmp, &server->pending_mid_q) {
86                 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
87                 cifs_dbg(VFS, "State: %d Cmd: %d Pid: %d Cbdata: %p Mid %llu\n",
88                          mid_entry->mid_state,
89                          le16_to_cpu(mid_entry->command),
90                          mid_entry->pid,
91                          mid_entry->callback_data,
92                          mid_entry->mid);
93 #ifdef CONFIG_CIFS_STATS2
94                 cifs_dbg(VFS, "IsLarge: %d buf: %p time rcv: %ld now: %ld\n",
95                          mid_entry->large_buf,
96                          mid_entry->resp_buf,
97                          mid_entry->when_received,
98                          jiffies);
99 #endif /* STATS2 */
100                 cifs_dbg(VFS, "IsMult: %d IsEnd: %d\n",
101                          mid_entry->multiRsp, mid_entry->multiEnd);
102                 if (mid_entry->resp_buf) {
103                         cifs_dump_detail(mid_entry->resp_buf);
104                         cifs_dump_mem("existing buf: ",
105                                 mid_entry->resp_buf, 62);
106                 }
107         }
108         spin_unlock(&GlobalMid_Lock);
109 #endif /* CONFIG_CIFS_DEBUG2 */
110 }
111
112 #ifdef CONFIG_PROC_FS
113 static void cifs_debug_tcon(struct seq_file *m, struct cifs_tcon *tcon)
114 {
115         __u32 dev_type = le32_to_cpu(tcon->fsDevInfo.DeviceType);
116
117         seq_printf(m, "%s Mounts: %d ", tcon->treeName, tcon->tc_count);
118         if (tcon->nativeFileSystem)
119                 seq_printf(m, "Type: %s ", tcon->nativeFileSystem);
120         seq_printf(m, "DevInfo: 0x%x Attributes: 0x%x\n\tPathComponentMax: %d Status: %d",
121                    le32_to_cpu(tcon->fsDevInfo.DeviceCharacteristics),
122                    le32_to_cpu(tcon->fsAttrInfo.Attributes),
123                    le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength),
124                    tcon->tidStatus);
125         if (dev_type == FILE_DEVICE_DISK)
126                 seq_puts(m, " type: DISK ");
127         else if (dev_type == FILE_DEVICE_CD_ROM)
128                 seq_puts(m, " type: CDROM ");
129         else
130                 seq_printf(m, " type: %d ", dev_type);
131         if (tcon->ses->server->ops->dump_share_caps)
132                 tcon->ses->server->ops->dump_share_caps(m, tcon);
133
134         if (tcon->need_reconnect)
135                 seq_puts(m, "\tDISCONNECTED ");
136         seq_putc(m, '\n');
137 }
138
139 static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
140 {
141         struct list_head *tmp1, *tmp2, *tmp3;
142         struct mid_q_entry *mid_entry;
143         struct TCP_Server_Info *server;
144         struct cifs_ses *ses;
145         struct cifs_tcon *tcon;
146         int i, j;
147
148         seq_puts(m,
149                     "Display Internal CIFS Data Structures for Debugging\n"
150                     "---------------------------------------------------\n");
151         seq_printf(m, "CIFS Version %s\n", CIFS_VERSION);
152         seq_printf(m, "Features:");
153 #ifdef CONFIG_CIFS_DFS_UPCALL
154         seq_printf(m, " dfs");
155 #endif
156 #ifdef CONFIG_CIFS_FSCACHE
157         seq_printf(m, " fscache");
158 #endif
159 #ifdef CONFIG_CIFS_WEAK_PW_HASH
160         seq_printf(m, " lanman");
161 #endif
162 #ifdef CONFIG_CIFS_POSIX
163         seq_printf(m, " posix");
164 #endif
165 #ifdef CONFIG_CIFS_UPCALL
166         seq_printf(m, " spnego");
167 #endif
168 #ifdef CONFIG_CIFS_XATTR
169         seq_printf(m, " xattr");
170 #endif
171 #ifdef CONFIG_CIFS_ACL
172         seq_printf(m, " acl");
173 #endif
174         seq_putc(m, '\n');
175         seq_printf(m, "Active VFS Requests: %d\n", GlobalTotalActiveXid);
176         seq_printf(m, "Servers:");
177
178         i = 0;
179         spin_lock(&cifs_tcp_ses_lock);
180         list_for_each(tmp1, &cifs_tcp_ses_list) {
181                 server = list_entry(tmp1, struct TCP_Server_Info,
182                                     tcp_ses_list);
183
184 #ifdef CONFIG_CIFS_SMB_DIRECT
185                 if (!server->rdma)
186                         goto skip_rdma;
187
188                 seq_printf(m, "\nSMBDirect (in hex) protocol version: %x "
189                         "transport status: %x",
190                         server->smbd_conn->protocol,
191                         server->smbd_conn->transport_status);
192                 seq_printf(m, "\nConn receive_credit_max: %x "
193                         "send_credit_target: %x max_send_size: %x",
194                         server->smbd_conn->receive_credit_max,
195                         server->smbd_conn->send_credit_target,
196                         server->smbd_conn->max_send_size);
197                 seq_printf(m, "\nConn max_fragmented_recv_size: %x "
198                         "max_fragmented_send_size: %x max_receive_size:%x",
199                         server->smbd_conn->max_fragmented_recv_size,
200                         server->smbd_conn->max_fragmented_send_size,
201                         server->smbd_conn->max_receive_size);
202                 seq_printf(m, "\nConn keep_alive_interval: %x "
203                         "max_readwrite_size: %x rdma_readwrite_threshold: %x",
204                         server->smbd_conn->keep_alive_interval,
205                         server->smbd_conn->max_readwrite_size,
206                         server->smbd_conn->rdma_readwrite_threshold);
207                 seq_printf(m, "\nDebug count_get_receive_buffer: %x "
208                         "count_put_receive_buffer: %x count_send_empty: %x",
209                         server->smbd_conn->count_get_receive_buffer,
210                         server->smbd_conn->count_put_receive_buffer,
211                         server->smbd_conn->count_send_empty);
212                 seq_printf(m, "\nRead Queue count_reassembly_queue: %x "
213                         "count_enqueue_reassembly_queue: %x "
214                         "count_dequeue_reassembly_queue: %x "
215                         "fragment_reassembly_remaining: %x "
216                         "reassembly_data_length: %x "
217                         "reassembly_queue_length: %x",
218                         server->smbd_conn->count_reassembly_queue,
219                         server->smbd_conn->count_enqueue_reassembly_queue,
220                         server->smbd_conn->count_dequeue_reassembly_queue,
221                         server->smbd_conn->fragment_reassembly_remaining,
222                         server->smbd_conn->reassembly_data_length,
223                         server->smbd_conn->reassembly_queue_length);
224                 seq_printf(m, "\nCurrent Credits send_credits: %x "
225                         "receive_credits: %x receive_credit_target: %x",
226                         atomic_read(&server->smbd_conn->send_credits),
227                         atomic_read(&server->smbd_conn->receive_credits),
228                         server->smbd_conn->receive_credit_target);
229                 seq_printf(m, "\nPending send_pending: %x send_payload_pending:"
230                         " %x smbd_send_pending: %x smbd_recv_pending: %x",
231                         atomic_read(&server->smbd_conn->send_pending),
232                         atomic_read(&server->smbd_conn->send_payload_pending),
233                         server->smbd_conn->smbd_send_pending,
234                         server->smbd_conn->smbd_recv_pending);
235                 seq_printf(m, "\nReceive buffers count_receive_queue: %x "
236                         "count_empty_packet_queue: %x",
237                         server->smbd_conn->count_receive_queue,
238                         server->smbd_conn->count_empty_packet_queue);
239                 seq_printf(m, "\nMR responder_resources: %x "
240                         "max_frmr_depth: %x mr_type: %x",
241                         server->smbd_conn->responder_resources,
242                         server->smbd_conn->max_frmr_depth,
243                         server->smbd_conn->mr_type);
244                 seq_printf(m, "\nMR mr_ready_count: %x mr_used_count: %x",
245                         atomic_read(&server->smbd_conn->mr_ready_count),
246                         atomic_read(&server->smbd_conn->mr_used_count));
247 skip_rdma:
248 #endif
249                 seq_printf(m, "\nNumber of credits: %d", server->credits);
250                 i++;
251                 list_for_each(tmp2, &server->smb_ses_list) {
252                         ses = list_entry(tmp2, struct cifs_ses,
253                                          smb_ses_list);
254                         if ((ses->serverDomain == NULL) ||
255                                 (ses->serverOS == NULL) ||
256                                 (ses->serverNOS == NULL)) {
257                                 seq_printf(m, "\n%d) Name: %s Uses: %d Capability: 0x%x\tSession Status: %d\t",
258                                         i, ses->serverName, ses->ses_count,
259                                         ses->capabilities, ses->status);
260                                 if (ses->session_flags & SMB2_SESSION_FLAG_IS_GUEST)
261                                         seq_printf(m, "Guest\t");
262                                 else if (ses->session_flags & SMB2_SESSION_FLAG_IS_NULL)
263                                         seq_printf(m, "Anonymous\t");
264                         } else {
265                                 seq_printf(m,
266                                     "\n%d) Name: %s  Domain: %s Uses: %d OS:"
267                                     " %s\n\tNOS: %s\tCapability: 0x%x\n\tSMB"
268                                     " session status: %d\t",
269                                 i, ses->serverName, ses->serverDomain,
270                                 ses->ses_count, ses->serverOS, ses->serverNOS,
271                                 ses->capabilities, ses->status);
272                         }
273                         if (server->rdma)
274                                 seq_printf(m, "RDMA\n\t");
275                         seq_printf(m, "TCP status: %d\n\tLocal Users To "
276                                    "Server: %d SecMode: 0x%x Req On Wire: %d",
277                                    server->tcpStatus, server->srv_count,
278                                    server->sec_mode, in_flight(server));
279
280 #ifdef CONFIG_CIFS_STATS2
281                         seq_printf(m, " In Send: %d In MaxReq Wait: %d",
282                                 atomic_read(&server->in_send),
283                                 atomic_read(&server->num_waiters));
284 #endif
285
286                         seq_puts(m, "\n\tShares:");
287                         j = 0;
288
289                         seq_printf(m, "\n\t%d) IPC: ", j);
290                         if (ses->tcon_ipc)
291                                 cifs_debug_tcon(m, ses->tcon_ipc);
292                         else
293                                 seq_puts(m, "none\n");
294
295                         list_for_each(tmp3, &ses->tcon_list) {
296                                 tcon = list_entry(tmp3, struct cifs_tcon,
297                                                   tcon_list);
298                                 ++j;
299                                 seq_printf(m, "\n\t%d) ", j);
300                                 cifs_debug_tcon(m, tcon);
301                         }
302
303                         seq_puts(m, "\n\tMIDs:\n");
304
305                         spin_lock(&GlobalMid_Lock);
306                         list_for_each(tmp3, &server->pending_mid_q) {
307                                 mid_entry = list_entry(tmp3, struct mid_q_entry,
308                                         qhead);
309                                 seq_printf(m, "\tState: %d com: %d pid:"
310                                               " %d cbdata: %p mid %llu\n",
311                                               mid_entry->mid_state,
312                                               le16_to_cpu(mid_entry->command),
313                                               mid_entry->pid,
314                                               mid_entry->callback_data,
315                                               mid_entry->mid);
316                         }
317                         spin_unlock(&GlobalMid_Lock);
318                 }
319         }
320         spin_unlock(&cifs_tcp_ses_lock);
321         seq_putc(m, '\n');
322
323         /* BB add code to dump additional info such as TCP session info now */
324         return 0;
325 }
326
327 static int cifs_debug_data_proc_open(struct inode *inode, struct file *file)
328 {
329         return single_open(file, cifs_debug_data_proc_show, NULL);
330 }
331
332 static const struct file_operations cifs_debug_data_proc_fops = {
333         .open           = cifs_debug_data_proc_open,
334         .read           = seq_read,
335         .llseek         = seq_lseek,
336         .release        = single_release,
337 };
338
339 #ifdef CONFIG_CIFS_STATS
340 static ssize_t cifs_stats_proc_write(struct file *file,
341                 const char __user *buffer, size_t count, loff_t *ppos)
342 {
343         bool bv;
344         int rc;
345         struct list_head *tmp1, *tmp2, *tmp3;
346         struct TCP_Server_Info *server;
347         struct cifs_ses *ses;
348         struct cifs_tcon *tcon;
349
350         rc = kstrtobool_from_user(buffer, count, &bv);
351         if (rc == 0) {
352 #ifdef CONFIG_CIFS_STATS2
353                 atomic_set(&totBufAllocCount, 0);
354                 atomic_set(&totSmBufAllocCount, 0);
355 #endif /* CONFIG_CIFS_STATS2 */
356                 spin_lock(&cifs_tcp_ses_lock);
357                 list_for_each(tmp1, &cifs_tcp_ses_list) {
358                         server = list_entry(tmp1, struct TCP_Server_Info,
359                                             tcp_ses_list);
360                         list_for_each(tmp2, &server->smb_ses_list) {
361                                 ses = list_entry(tmp2, struct cifs_ses,
362                                                  smb_ses_list);
363                                 list_for_each(tmp3, &ses->tcon_list) {
364                                         tcon = list_entry(tmp3,
365                                                           struct cifs_tcon,
366                                                           tcon_list);
367                                         atomic_set(&tcon->num_smbs_sent, 0);
368                                         if (server->ops->clear_stats)
369                                                 server->ops->clear_stats(tcon);
370                                 }
371                         }
372                 }
373                 spin_unlock(&cifs_tcp_ses_lock);
374         } else {
375                 return rc;
376         }
377
378         return count;
379 }
380
381 static int cifs_stats_proc_show(struct seq_file *m, void *v)
382 {
383         int i;
384         struct list_head *tmp1, *tmp2, *tmp3;
385         struct TCP_Server_Info *server;
386         struct cifs_ses *ses;
387         struct cifs_tcon *tcon;
388
389         seq_printf(m,
390                         "Resources in use\nCIFS Session: %d\n",
391                         sesInfoAllocCount.counter);
392         seq_printf(m, "Share (unique mount targets): %d\n",
393                         tconInfoAllocCount.counter);
394         seq_printf(m, "SMB Request/Response Buffer: %d Pool size: %d\n",
395                         bufAllocCount.counter,
396                         cifs_min_rcv + tcpSesAllocCount.counter);
397         seq_printf(m, "SMB Small Req/Resp Buffer: %d Pool size: %d\n",
398                         smBufAllocCount.counter, cifs_min_small);
399 #ifdef CONFIG_CIFS_STATS2
400         seq_printf(m, "Total Large %d Small %d Allocations\n",
401                                 atomic_read(&totBufAllocCount),
402                                 atomic_read(&totSmBufAllocCount));
403 #endif /* CONFIG_CIFS_STATS2 */
404
405         seq_printf(m, "Operations (MIDs): %d\n", atomic_read(&midCount));
406         seq_printf(m,
407                 "\n%d session %d share reconnects\n",
408                 tcpSesReconnectCount.counter, tconInfoReconnectCount.counter);
409
410         seq_printf(m,
411                 "Total vfs operations: %d maximum at one time: %d\n",
412                 GlobalCurrentXid, GlobalMaxActiveXid);
413
414         i = 0;
415         spin_lock(&cifs_tcp_ses_lock);
416         list_for_each(tmp1, &cifs_tcp_ses_list) {
417                 server = list_entry(tmp1, struct TCP_Server_Info,
418                                     tcp_ses_list);
419                 list_for_each(tmp2, &server->smb_ses_list) {
420                         ses = list_entry(tmp2, struct cifs_ses,
421                                          smb_ses_list);
422                         list_for_each(tmp3, &ses->tcon_list) {
423                                 tcon = list_entry(tmp3,
424                                                   struct cifs_tcon,
425                                                   tcon_list);
426                                 i++;
427                                 seq_printf(m, "\n%d) %s", i, tcon->treeName);
428                                 if (tcon->need_reconnect)
429                                         seq_puts(m, "\tDISCONNECTED ");
430                                 seq_printf(m, "\nSMBs: %d",
431                                            atomic_read(&tcon->num_smbs_sent));
432                                 if (server->ops->print_stats)
433                                         server->ops->print_stats(m, tcon);
434                         }
435                 }
436         }
437         spin_unlock(&cifs_tcp_ses_lock);
438
439         seq_putc(m, '\n');
440         return 0;
441 }
442
443 static int cifs_stats_proc_open(struct inode *inode, struct file *file)
444 {
445         return single_open(file, cifs_stats_proc_show, NULL);
446 }
447
448 static const struct file_operations cifs_stats_proc_fops = {
449         .open           = cifs_stats_proc_open,
450         .read           = seq_read,
451         .llseek         = seq_lseek,
452         .release        = single_release,
453         .write          = cifs_stats_proc_write,
454 };
455 #endif /* STATS */
456
457 #ifdef CONFIG_CIFS_SMB_DIRECT
458 #define PROC_FILE_DEFINE(name) \
459 static ssize_t name##_write(struct file *file, const char __user *buffer, \
460         size_t count, loff_t *ppos) \
461 { \
462         int rc; \
463         rc = kstrtoint_from_user(buffer, count, 10, & name); \
464         if (rc) \
465                 return rc; \
466         return count; \
467 } \
468 static int name##_proc_show(struct seq_file *m, void *v) \
469 { \
470         seq_printf(m, "%d\n", name ); \
471         return 0; \
472 } \
473 static int name##_open(struct inode *inode, struct file *file) \
474 { \
475         return single_open(file, name##_proc_show, NULL); \
476 } \
477 \
478 static const struct file_operations cifs_##name##_proc_fops = { \
479         .open           = name##_open, \
480         .read           = seq_read, \
481         .llseek         = seq_lseek, \
482         .release        = single_release, \
483         .write          = name##_write, \
484 }
485
486 PROC_FILE_DEFINE(rdma_readwrite_threshold);
487 PROC_FILE_DEFINE(smbd_max_frmr_depth);
488 PROC_FILE_DEFINE(smbd_keep_alive_interval);
489 PROC_FILE_DEFINE(smbd_max_receive_size);
490 PROC_FILE_DEFINE(smbd_max_fragmented_recv_size);
491 PROC_FILE_DEFINE(smbd_max_send_size);
492 PROC_FILE_DEFINE(smbd_send_credit_target);
493 PROC_FILE_DEFINE(smbd_receive_credit_max);
494 #endif
495
496 static struct proc_dir_entry *proc_fs_cifs;
497 static const struct file_operations cifsFYI_proc_fops;
498 static const struct file_operations cifs_lookup_cache_proc_fops;
499 static const struct file_operations traceSMB_proc_fops;
500 static const struct file_operations cifs_security_flags_proc_fops;
501 static const struct file_operations cifs_linux_ext_proc_fops;
502
503 void
504 cifs_proc_init(void)
505 {
506         proc_fs_cifs = proc_mkdir("fs/cifs", NULL);
507         if (proc_fs_cifs == NULL)
508                 return;
509
510         proc_create("DebugData", 0, proc_fs_cifs, &cifs_debug_data_proc_fops);
511
512 #ifdef CONFIG_CIFS_STATS
513         proc_create("Stats", 0, proc_fs_cifs, &cifs_stats_proc_fops);
514 #endif /* STATS */
515         proc_create("cifsFYI", 0, proc_fs_cifs, &cifsFYI_proc_fops);
516         proc_create("traceSMB", 0, proc_fs_cifs, &traceSMB_proc_fops);
517         proc_create("LinuxExtensionsEnabled", 0, proc_fs_cifs,
518                     &cifs_linux_ext_proc_fops);
519         proc_create("SecurityFlags", 0, proc_fs_cifs,
520                     &cifs_security_flags_proc_fops);
521         proc_create("LookupCacheEnabled", 0, proc_fs_cifs,
522                     &cifs_lookup_cache_proc_fops);
523 #ifdef CONFIG_CIFS_SMB_DIRECT
524         proc_create("rdma_readwrite_threshold", 0, proc_fs_cifs,
525                 &cifs_rdma_readwrite_threshold_proc_fops);
526         proc_create("smbd_max_frmr_depth", 0, proc_fs_cifs,
527                 &cifs_smbd_max_frmr_depth_proc_fops);
528         proc_create("smbd_keep_alive_interval", 0, proc_fs_cifs,
529                 &cifs_smbd_keep_alive_interval_proc_fops);
530         proc_create("smbd_max_receive_size", 0, proc_fs_cifs,
531                 &cifs_smbd_max_receive_size_proc_fops);
532         proc_create("smbd_max_fragmented_recv_size", 0, proc_fs_cifs,
533                 &cifs_smbd_max_fragmented_recv_size_proc_fops);
534         proc_create("smbd_max_send_size", 0, proc_fs_cifs,
535                 &cifs_smbd_max_send_size_proc_fops);
536         proc_create("smbd_send_credit_target", 0, proc_fs_cifs,
537                 &cifs_smbd_send_credit_target_proc_fops);
538         proc_create("smbd_receive_credit_max", 0, proc_fs_cifs,
539                 &cifs_smbd_receive_credit_max_proc_fops);
540 #endif
541 }
542
543 void
544 cifs_proc_clean(void)
545 {
546         if (proc_fs_cifs == NULL)
547                 return;
548
549         remove_proc_entry("DebugData", proc_fs_cifs);
550         remove_proc_entry("cifsFYI", proc_fs_cifs);
551         remove_proc_entry("traceSMB", proc_fs_cifs);
552 #ifdef CONFIG_CIFS_STATS
553         remove_proc_entry("Stats", proc_fs_cifs);
554 #endif
555         remove_proc_entry("SecurityFlags", proc_fs_cifs);
556         remove_proc_entry("LinuxExtensionsEnabled", proc_fs_cifs);
557         remove_proc_entry("LookupCacheEnabled", proc_fs_cifs);
558 #ifdef CONFIG_CIFS_SMB_DIRECT
559         remove_proc_entry("rdma_readwrite_threshold", proc_fs_cifs);
560         remove_proc_entry("smbd_max_frmr_depth", proc_fs_cifs);
561         remove_proc_entry("smbd_keep_alive_interval", proc_fs_cifs);
562         remove_proc_entry("smbd_max_receive_size", proc_fs_cifs);
563         remove_proc_entry("smbd_max_fragmented_recv_size", proc_fs_cifs);
564         remove_proc_entry("smbd_max_send_size", proc_fs_cifs);
565         remove_proc_entry("smbd_send_credit_target", proc_fs_cifs);
566         remove_proc_entry("smbd_receive_credit_max", proc_fs_cifs);
567 #endif
568         remove_proc_entry("fs/cifs", NULL);
569 }
570
571 static int cifsFYI_proc_show(struct seq_file *m, void *v)
572 {
573         seq_printf(m, "%d\n", cifsFYI);
574         return 0;
575 }
576
577 static int cifsFYI_proc_open(struct inode *inode, struct file *file)
578 {
579         return single_open(file, cifsFYI_proc_show, NULL);
580 }
581
582 static ssize_t cifsFYI_proc_write(struct file *file, const char __user *buffer,
583                 size_t count, loff_t *ppos)
584 {
585         char c[2] = { '\0' };
586         bool bv;
587         int rc;
588
589         rc = get_user(c[0], buffer);
590         if (rc)
591                 return rc;
592         if (strtobool(c, &bv) == 0)
593                 cifsFYI = bv;
594         else if ((c[0] > '1') && (c[0] <= '9'))
595                 cifsFYI = (int) (c[0] - '0'); /* see cifs_debug.h for meanings */
596
597         return count;
598 }
599
600 static const struct file_operations cifsFYI_proc_fops = {
601         .open           = cifsFYI_proc_open,
602         .read           = seq_read,
603         .llseek         = seq_lseek,
604         .release        = single_release,
605         .write          = cifsFYI_proc_write,
606 };
607
608 static int cifs_linux_ext_proc_show(struct seq_file *m, void *v)
609 {
610         seq_printf(m, "%d\n", linuxExtEnabled);
611         return 0;
612 }
613
614 static int cifs_linux_ext_proc_open(struct inode *inode, struct file *file)
615 {
616         return single_open(file, cifs_linux_ext_proc_show, NULL);
617 }
618
619 static ssize_t cifs_linux_ext_proc_write(struct file *file,
620                 const char __user *buffer, size_t count, loff_t *ppos)
621 {
622         int rc;
623
624         rc = kstrtobool_from_user(buffer, count, &linuxExtEnabled);
625         if (rc)
626                 return rc;
627
628         return count;
629 }
630
631 static const struct file_operations cifs_linux_ext_proc_fops = {
632         .open           = cifs_linux_ext_proc_open,
633         .read           = seq_read,
634         .llseek         = seq_lseek,
635         .release        = single_release,
636         .write          = cifs_linux_ext_proc_write,
637 };
638
639 static int cifs_lookup_cache_proc_show(struct seq_file *m, void *v)
640 {
641         seq_printf(m, "%d\n", lookupCacheEnabled);
642         return 0;
643 }
644
645 static int cifs_lookup_cache_proc_open(struct inode *inode, struct file *file)
646 {
647         return single_open(file, cifs_lookup_cache_proc_show, NULL);
648 }
649
650 static ssize_t cifs_lookup_cache_proc_write(struct file *file,
651                 const char __user *buffer, size_t count, loff_t *ppos)
652 {
653         int rc;
654
655         rc = kstrtobool_from_user(buffer, count, &lookupCacheEnabled);
656         if (rc)
657                 return rc;
658
659         return count;
660 }
661
662 static const struct file_operations cifs_lookup_cache_proc_fops = {
663         .open           = cifs_lookup_cache_proc_open,
664         .read           = seq_read,
665         .llseek         = seq_lseek,
666         .release        = single_release,
667         .write          = cifs_lookup_cache_proc_write,
668 };
669
670 static int traceSMB_proc_show(struct seq_file *m, void *v)
671 {
672         seq_printf(m, "%d\n", traceSMB);
673         return 0;
674 }
675
676 static int traceSMB_proc_open(struct inode *inode, struct file *file)
677 {
678         return single_open(file, traceSMB_proc_show, NULL);
679 }
680
681 static ssize_t traceSMB_proc_write(struct file *file, const char __user *buffer,
682                 size_t count, loff_t *ppos)
683 {
684         int rc;
685
686         rc = kstrtobool_from_user(buffer, count, &traceSMB);
687         if (rc)
688                 return rc;
689
690         return count;
691 }
692
693 static const struct file_operations traceSMB_proc_fops = {
694         .open           = traceSMB_proc_open,
695         .read           = seq_read,
696         .llseek         = seq_lseek,
697         .release        = single_release,
698         .write          = traceSMB_proc_write,
699 };
700
701 static int cifs_security_flags_proc_show(struct seq_file *m, void *v)
702 {
703         seq_printf(m, "0x%x\n", global_secflags);
704         return 0;
705 }
706
707 static int cifs_security_flags_proc_open(struct inode *inode, struct file *file)
708 {
709         return single_open(file, cifs_security_flags_proc_show, NULL);
710 }
711
712 /*
713  * Ensure that if someone sets a MUST flag, that we disable all other MAY
714  * flags except for the ones corresponding to the given MUST flag. If there are
715  * multiple MUST flags, then try to prefer more secure ones.
716  */
717 static void
718 cifs_security_flags_handle_must_flags(unsigned int *flags)
719 {
720         unsigned int signflags = *flags & CIFSSEC_MUST_SIGN;
721
722         if ((*flags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
723                 *flags = CIFSSEC_MUST_KRB5;
724         else if ((*flags & CIFSSEC_MUST_NTLMSSP) == CIFSSEC_MUST_NTLMSSP)
725                 *flags = CIFSSEC_MUST_NTLMSSP;
726         else if ((*flags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
727                 *flags = CIFSSEC_MUST_NTLMV2;
728         else if ((*flags & CIFSSEC_MUST_NTLM) == CIFSSEC_MUST_NTLM)
729                 *flags = CIFSSEC_MUST_NTLM;
730         else if (CIFSSEC_MUST_LANMAN &&
731                  (*flags & CIFSSEC_MUST_LANMAN) == CIFSSEC_MUST_LANMAN)
732                 *flags = CIFSSEC_MUST_LANMAN;
733         else if (CIFSSEC_MUST_PLNTXT &&
734                  (*flags & CIFSSEC_MUST_PLNTXT) == CIFSSEC_MUST_PLNTXT)
735                 *flags = CIFSSEC_MUST_PLNTXT;
736
737         *flags |= signflags;
738 }
739
740 static ssize_t cifs_security_flags_proc_write(struct file *file,
741                 const char __user *buffer, size_t count, loff_t *ppos)
742 {
743         int rc;
744         unsigned int flags;
745         char flags_string[12];
746         bool bv;
747
748         if ((count < 1) || (count > 11))
749                 return -EINVAL;
750
751         memset(flags_string, 0, 12);
752
753         if (copy_from_user(flags_string, buffer, count))
754                 return -EFAULT;
755
756         if (count < 3) {
757                 /* single char or single char followed by null */
758                 if (strtobool(flags_string, &bv) == 0) {
759                         global_secflags = bv ? CIFSSEC_MAX : CIFSSEC_DEF;
760                         return count;
761                 } else if (!isdigit(flags_string[0])) {
762                         cifs_dbg(VFS, "Invalid SecurityFlags: %s\n",
763                                         flags_string);
764                         return -EINVAL;
765                 }
766         }
767
768         /* else we have a number */
769         rc = kstrtouint(flags_string, 0, &flags);
770         if (rc) {
771                 cifs_dbg(VFS, "Invalid SecurityFlags: %s\n",
772                                 flags_string);
773                 return rc;
774         }
775
776         cifs_dbg(FYI, "sec flags 0x%x\n", flags);
777
778         if (flags == 0)  {
779                 cifs_dbg(VFS, "Invalid SecurityFlags: %s\n", flags_string);
780                 return -EINVAL;
781         }
782
783         if (flags & ~CIFSSEC_MASK) {
784                 cifs_dbg(VFS, "Unsupported security flags: 0x%x\n",
785                          flags & ~CIFSSEC_MASK);
786                 return -EINVAL;
787         }
788
789         cifs_security_flags_handle_must_flags(&flags);
790
791         /* flags look ok - update the global security flags for cifs module */
792         global_secflags = flags;
793         if (global_secflags & CIFSSEC_MUST_SIGN) {
794                 /* requiring signing implies signing is allowed */
795                 global_secflags |= CIFSSEC_MAY_SIGN;
796                 cifs_dbg(FYI, "packet signing now required\n");
797         } else if ((global_secflags & CIFSSEC_MAY_SIGN) == 0) {
798                 cifs_dbg(FYI, "packet signing disabled\n");
799         }
800         /* BB should we turn on MAY flags for other MUST options? */
801         return count;
802 }
803
804 static const struct file_operations cifs_security_flags_proc_fops = {
805         .open           = cifs_security_flags_proc_open,
806         .read           = seq_read,
807         .llseek         = seq_lseek,
808         .release        = single_release,
809         .write          = cifs_security_flags_proc_write,
810 };
811 #else
812 inline void cifs_proc_init(void)
813 {
814 }
815
816 inline void cifs_proc_clean(void)
817 {
818 }
819 #endif /* PROC_FS */