/*
* fs/cifs_debug.c
*
* Copyright (C) International Business Machines Corp., 2000,2005
*
* Modified by Steve French (sfrench@us.ibm.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
* the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/fs.h>
#include <linux/string.h>
#include <linux/ctype.h>
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <asm/uaccess.h>
#include "cifspdu.h"
#include "cifsglob.h"
#include "cifsproto.h"
#include "cifs_debug.h"
#include "cifsfs.h"
void
cifs_dump_mem(char *label, void *data, int length)
{
int i, j;
int *intptr = data;
char *charptr = data;
char buf[10], line[80];
printk(KERN_DEBUG "%s: dump of %d bytes of data at 0x%p\n",
label, length, data);
for (i = 0; i < length; i += 16) {
line[0] = 0;
for (j = 0; (j < 4) && (i + j * 4 < length); j++) {
sprintf(buf, " %08x", intptr[i / 4 + j]);
strcat(line, buf);
}
buf[0] = ' ';
buf[2] = 0;
for (j = 0; (j < 16) && (i + j < length); j++) {
buf[1] = isprint(charptr[i + j]) ? charptr[i + j] : '.';
strcat(line, buf);
}
printk(KERN_DEBUG "%s\n", line);
}
}
#ifdef CONFIG_CIFS_DEBUG2
void cifs_dump_detail(struct smb_hdr *smb)
{
cERROR(1, ("Cmd: %d Err: 0x%x Flags: 0x%x Flgs2: 0x%x Mid: %d Pid: %d",
smb->Command, smb->Status.CifsError,
smb->Flags, smb->Flags2, smb->Mid, smb->Pid));
cERROR(1, ("smb buf %p len %d", smb, smbCalcSize_LE(smb)));
}
void cifs_dump_mids(struct TCP_Server_Info *server)
{
struct list_head *tmp;
struct mid_q_entry *mid_entry;
if (server == NULL)
return;
cERROR(1, ("Dump pending requests:"));
spin_lock(&GlobalMid_Lock);
list_for_each(tmp, &server->pending_mid_q) {
mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
if (mid_entry) {
cERROR(1, ("State: %d Cmd: %d Pid: %d Tsk: %p Mid %d",
mid_entry->midState,
(int)mid_entry->command,
mid_entry->pid,
mid_entry->tsk,
mid_entry->mid));
#ifdef CONFIG_CIFS_STATS2
cERROR(1, ("IsLarge: %d buf: %p time rcv: %ld now: %ld",
mid_entry->largeBuf,
mid_entry->resp_buf,
mid_entry->when_received,
jiffies));
#endif /* STATS2 */
cERROR(1, ("IsMult: %d IsEnd: %d", mid_entry->multiRsp,
mid_entry->multiEnd));
if (mid_entry->resp_buf) {
cifs_dump_detail(mid_entry->resp_buf);
cifs_dump_mem("existing buf: ",
mid_entry->resp_buf,
62 /* fixme */);
}
}
}
spin_unlock(&GlobalMid_Lock);
}
#endif /* CONFIG_CIFS_DEBUG2 */
#ifdef CONFIG_PROC_FS
static int
cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
int count, int *eof, void *data)
{
struct list_head *tmp;
struct list_head *tmp1;
struct mid_q_entry *mid_entry;
struct cifsSesInfo *ses;
struct cifsTconInfo *tcon;
int i;
int length = 0;
char *original_buf = buf;
*beginBuffer = buf + offset;
length =
sprintf(buf,
"Display Internal CIFS Data Structures for Debugging\n"
"---------------------------------------------------\n");
buf += length;
length = sprintf(buf, "CIFS Version %s\n", CIFS_VERSION);
buf += length;
length = sprintf(buf,
"Active VFS Requests: %d\n", GlobalTotalActiveXid);
buf += length;
length = sprintf(buf, "Servers:");
buf += length;
i = 0;
read_lock(&GlobalSMBSeslock);
list_for_each(tmp, &GlobalSMBSessionList) {
i++;
ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
if ((ses->serverDomain == NULL) || (ses->serve