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