Commit a9bbd05d authored by Steve French's avatar Steve French

Merge bk://linux.bkbits.net/linux-2.5

into hostme.bitkeeper.com:/repos/c/cifs/linux-2.5cifs
parents 740ba8b9 3ff276de
...@@ -20,6 +20,7 @@ Patch Contributors ...@@ -20,6 +20,7 @@ Patch Contributors
Zwane Mwaikambo Zwane Mwaikambo
Andi Kleen Andi Kleen
Amrut Joshi Amrut Joshi
Shobhit Dayal
Test case and Bug Report contributors Test case and Bug Report contributors
------------------------------------- -------------------------------------
......
Version 0.94
------------
Fix to list processing in reopen_files. Fix reconnection when server hung
but tcpip session still alive. Set proper timeout on socket read.
Version 0.93
------------
Add missing mount options including iocharset. SMP fixes in write and open.
Fix errors in reconnecting after TCP session failure. Fix module unloading
of default nls codepage
Version 0.92
------------
Active smb transactions should never go negative (fix double FreeXid). Fix
list processing in file routines. Check return code on kmalloc in open.
Fix spinlock usage for SMP.
Version 0.91 Version 0.91
------------ ------------
Fix oops in reopen_files when invalid dentry. drop dentry on server rename Fix oops in reopen_files when invalid dentry. drop dentry on server rename
......
...@@ -127,6 +127,13 @@ A partial list of the supported mount options follows: ...@@ -127,6 +127,13 @@ A partial list of the supported mount options follows:
this overrides the default mode for directory inodes. this overrides the default mode for directory inodes.
port attempt to contact the server on this tcp port, before port attempt to contact the server on this tcp port, before
trying the usual ports (port 445, then 139). trying the usual ports (port 445, then 139).
iocharset Codepage used to convert local path names to and from
Unicode. Unicode is used by default for network path
names if the server supports it. If iocharset is
not specified then the nls_default specified
during the local client kernel build will be used.
If server does not support Unicode, this parameter is
unused.
rsize default read size rsize default read size
wsize default write size wsize default write size
rw mount the network share read-write (note that the rw mount the network share read-write (note that the
......
/* /*
* fs/cifs_debug.c * fs/cifs_debug.c
* *
* Copyright (c) International Business Machines Corp., 2000,2002 * Copyright (C) International Business Machines Corp., 2000,2003
* *
* Modified by Steve French (sfrench@us.ibm.com) * Modified by Steve French (sfrench@us.ibm.com)
* *
...@@ -84,12 +84,12 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset, ...@@ -84,12 +84,12 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList); ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
length = length =
sprintf(buf, sprintf(buf,
"\n%d) Name: %s Domain: %s Mounts: %d ServerOS: %s ServerNOS: %s\n\tCapabilities: 0x%x", "\n%d) Name: %s Domain: %s Mounts: %d ServerOS: %s \n\tServerNOS: %s\tCapabilities: 0x%x\n\tSMB session status: %d\tTCP session status: %d",
i, ses->serverName, ses->serverDomain, atomic_read(&ses->inUse), i, ses->serverName, ses->serverDomain, atomic_read(&ses->inUse),
ses->serverOS, ses->serverNOS, ses->capabilities); ses->serverOS, ses->serverNOS, ses->capabilities,ses->status,ses->server->tcpStatus);
buf += length; buf += length;
if(ses->server) if(ses->server)
buf += sprintf(buf, "\tLocal Users To Same Server: %d SecMode: 0x%x", buf += sprintf(buf, "\n\tLocal Users To Same Server: %d SecMode: 0x%x",
atomic_read(&ses->server->socketUseCount),ses->server->secMode); atomic_read(&ses->server->socketUseCount),ses->server->secMode);
} }
read_unlock(&GlobalSMBSeslock); read_unlock(&GlobalSMBSeslock);
...@@ -106,13 +106,13 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset, ...@@ -106,13 +106,13 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList); tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
length = length =
sprintf(buf, sprintf(buf,
"\n%d) %s Uses: %d on FS: %s with characteristics: 0x%x Attributes: 0x%x\n\tPathComponentMax: %d", "\n%d) %s Uses: %d on FS: %s with characteristics: 0x%x Attributes: 0x%x\n\tPathComponentMax: %d Status: %d",
i, tcon->treeName, i, tcon->treeName,
atomic_read(&tcon->useCount), atomic_read(&tcon->useCount),
tcon->nativeFileSystem, tcon->nativeFileSystem,
tcon->fsDevInfo.DeviceCharacteristics, tcon->fsDevInfo.DeviceCharacteristics,
tcon->fsAttrInfo.Attributes, tcon->fsAttrInfo.Attributes,
tcon->fsAttrInfo.MaxPathNameComponentLength); tcon->fsAttrInfo.MaxPathNameComponentLength,tcon->tidStatus);
buf += length; buf += length;
if (tcon->fsDevInfo.DeviceType == FILE_DEVICE_DISK) if (tcon->fsDevInfo.DeviceType == FILE_DEVICE_DISK)
length = sprintf(buf, " type: DISK "); length = sprintf(buf, " type: DISK ");
...@@ -123,6 +123,8 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset, ...@@ -123,6 +123,8 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
sprintf(buf, " type: %d ", sprintf(buf, " type: %d ",
tcon->fsDevInfo.DeviceType); tcon->fsDevInfo.DeviceType);
buf += length; buf += length;
if(tcon->tidStatus == CifsNeedReconnect)
buf += sprintf(buf, "\tDISCONNECTED ");
} }
read_unlock(&GlobalSMBSeslock); read_unlock(&GlobalSMBSeslock);
length = sprintf(buf, "\n"); length = sprintf(buf, "\n");
......
/* /*
* fs/cifs/cifsencrypt.c * fs/cifs/cifsencrypt.c
* *
* Copyright (c) International Business Machines Corp., 2003 * Copyright (C) International Business Machines Corp., 2003
* Author(s): Steve French (sfrench@us.ibm.com) * Author(s): Steve French (sfrench@us.ibm.com)
* *
* This library is free software; you can redistribute it and/or modify * This library is free software; you can redistribute it and/or modify
...@@ -64,13 +64,13 @@ int cifs_sign_smb(struct smb_hdr * cifs_pdu, struct cifsSesInfo * ses, ...@@ -64,13 +64,13 @@ int cifs_sign_smb(struct smb_hdr * cifs_pdu, struct cifsSesInfo * ses,
if((le32_to_cpu(cifs_pdu->Flags2) & SMBFLG2_SECURITY_SIGNATURE) == 0) if((le32_to_cpu(cifs_pdu->Flags2) & SMBFLG2_SECURITY_SIGNATURE) == 0)
return rc; return rc;
write_lock(&GlobalMid_Lock); spin_lock(&GlobalMid_Lock);
cifs_pdu->Signature.Sequence.SequenceNumber = cpu_to_le32(ses->sequence_number); cifs_pdu->Signature.Sequence.SequenceNumber = cpu_to_le32(ses->sequence_number);
cifs_pdu->Signature.Sequence.Reserved = 0; cifs_pdu->Signature.Sequence.Reserved = 0;
*pexpected_response_sequence_number = ses->sequence_number++; *pexpected_response_sequence_number = ses->sequence_number++;
ses->sequence_number++; ses->sequence_number++;
write_unlock(&GlobalMid_Lock); spin_unlock(&GlobalMid_Lock);
rc = cifs_calculate_signature(cifs_pdu, ses->mac_signing_key,smb_signature); rc = cifs_calculate_signature(cifs_pdu, ses->mac_signing_key,smb_signature);
if(rc) if(rc)
......
/* /*
* fs/cifs/cifsfs.c * fs/cifs/cifsfs.c
* *
* Copyright (c) International Business Machines Corp., 2002 * Copyright (C) International Business Machines Corp., 2002,2003
* Author(s): Steve French (sfrench@us.ibm.com) * Author(s): Steve French (sfrench@us.ibm.com)
* *
* Common Internet FileSystem (CIFS) client * Common Internet FileSystem (CIFS) client
...@@ -81,7 +81,6 @@ cifs_read_super(struct super_block *sb, void *data, ...@@ -81,7 +81,6 @@ cifs_read_super(struct super_block *sb, void *data,
cifs_sb = CIFS_SB(sb); cifs_sb = CIFS_SB(sb);
if(cifs_sb == NULL) if(cifs_sb == NULL)
return -ENOMEM; return -ENOMEM;
cifs_sb->local_nls = load_nls_default(); /* needed for ASCII cp to Unicode converts */
rc = cifs_mount(sb, cifs_sb, data, devname); rc = cifs_mount(sb, cifs_sb, data, devname);
...@@ -571,8 +570,6 @@ cifs_destroy_mids(void) ...@@ -571,8 +570,6 @@ cifs_destroy_mids(void)
static int cifs_oplock_thread(void * dummyarg) static int cifs_oplock_thread(void * dummyarg)
{ {
struct list_head * tmp;
struct list_head * tmp1;
struct oplock_q_entry * oplock_item; struct oplock_q_entry * oplock_item;
struct cifsTconInfo *pTcon; struct cifsTconInfo *pTcon;
struct inode * inode; struct inode * inode;
...@@ -585,19 +582,22 @@ static int cifs_oplock_thread(void * dummyarg) ...@@ -585,19 +582,22 @@ static int cifs_oplock_thread(void * dummyarg)
oplockThread = current; oplockThread = current;
do { do {
set_current_state(TASK_INTERRUPTIBLE); set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(100*HZ);
/* BB add missing code */ schedule_timeout(39*HZ);
write_lock(&GlobalMid_Lock); spin_lock(&GlobalMid_Lock);
list_for_each_safe(tmp, tmp1, &GlobalOplock_Q) { if(list_empty(&GlobalOplock_Q)) {
oplock_item = list_entry(tmp, struct oplock_q_entry, spin_unlock(&GlobalMid_Lock);
qhead); schedule_timeout(39*HZ);
} else {
oplock_item = list_entry(GlobalOplock_Q.next,
struct oplock_q_entry, qhead);
if(oplock_item) { if(oplock_item) {
pTcon = oplock_item->tcon; pTcon = oplock_item->tcon;
inode = oplock_item->pinode; inode = oplock_item->pinode;
netfid = oplock_item->netfid; netfid = oplock_item->netfid;
spin_unlock(&GlobalMid_Lock);
DeleteOplockQEntry(oplock_item); DeleteOplockQEntry(oplock_item);
write_unlock(&GlobalMid_Lock); if (S_ISREG(inode->i_mode))
if (S_ISREG(inode->i_mode))
rc = filemap_fdatawrite(inode->i_mapping); rc = filemap_fdatawrite(inode->i_mapping);
else else
rc = 0; rc = 0;
...@@ -609,11 +609,9 @@ static int cifs_oplock_thread(void * dummyarg) ...@@ -609,11 +609,9 @@ static int cifs_oplock_thread(void * dummyarg)
0, LOCKING_ANDX_OPLOCK_RELEASE, 0, LOCKING_ANDX_OPLOCK_RELEASE,
0 /* wait flag */); 0 /* wait flag */);
cFYI(1,("Oplock release rc = %d ",rc)); cFYI(1,("Oplock release rc = %d ",rc));
write_lock(&GlobalMid_Lock);
} else } else
break; spin_unlock(&GlobalMid_Lock);
} }
write_unlock(&GlobalMid_Lock);
} while(!signal_pending(current)); } while(!signal_pending(current));
complete_and_exit (&cifs_oplock_exited, 0); complete_and_exit (&cifs_oplock_exited, 0);
} }
...@@ -640,7 +638,7 @@ init_cifs(void) ...@@ -640,7 +638,7 @@ init_cifs(void)
GlobalTotalActiveXid = 0; GlobalTotalActiveXid = 0;
GlobalMaxActiveXid = 0; GlobalMaxActiveXid = 0;
GlobalSMBSeslock = RW_LOCK_UNLOCKED; GlobalSMBSeslock = RW_LOCK_UNLOCKED;
GlobalMid_Lock = RW_LOCK_UNLOCKED; GlobalMid_Lock = SPIN_LOCK_UNLOCKED;
rc = cifs_init_inodecache(); rc = cifs_init_inodecache();
if (!rc) { if (!rc) {
......
/* /*
* fs/cifs/cifsglob.h * fs/cifs/cifsglob.h
* *
* Copyright (c) International Business Machines Corp., 2002 * Copyright (C) International Business Machines Corp., 2002,2003
* Author(s): Steve French (sfrench@us.ibm.com) * Author(s): Steve French (sfrench@us.ibm.com)
* *
* This library is free software; you can redistribute it and/or modify * This library is free software; you can redistribute it and/or modify
...@@ -212,6 +212,7 @@ struct cifsFileInfo { ...@@ -212,6 +212,7 @@ struct cifsFileInfo {
int endOfSearch:1; /* we have reached end of search */ int endOfSearch:1; /* we have reached end of search */
int closePend:1; /* file is marked to close */ int closePend:1; /* file is marked to close */
int emptyDir:1; int emptyDir:1;
int invalidHandle:1; /* file closed via session abend */
char * search_resume_name; char * search_resume_name;
unsigned int resume_name_length; unsigned int resume_name_length;
__u32 resume_key; __u32 resume_key;
...@@ -294,7 +295,27 @@ struct servers_not_supported { /* @z4a */ ...@@ -294,7 +295,27 @@ struct servers_not_supported { /* @z4a */
* following to be declared. * following to be declared.
*/ */
/* BB Every global should have an associated mutex for safe update BB */ /****************************************************************************
* Locking notes. All updates to global variables and lists should be
* protected by spinlocks or semaphores.
*
* Spinlocks
* ---------
* GlobalMid_Lock protects:
* list operations on pending_mid_q and oplockQ
* updates to XID counters, multiplex id and SMB sequence numbers
* GlobalSMBSesLock protects:
* list operations on tcp and SMB session lists and tCon lists
* f_owner.lock protects certain per file struct operations
* mapping->page_lock protects certain per page operations
*
* Semaphores
* ----------
* sesSem operations on smb session
* tconSem operations on tree connection
* i_sem inode operations
*
****************************************************************************/
#ifdef DECLARE_GLOBALS_HERE #ifdef DECLARE_GLOBALS_HERE
#define GLOBAL_EXTERN #define GLOBAL_EXTERN
...@@ -327,7 +348,7 @@ GLOBAL_EXTERN struct list_head GlobalOplock_Q; ...@@ -327,7 +348,7 @@ GLOBAL_EXTERN struct list_head GlobalOplock_Q;
GLOBAL_EXTERN unsigned int GlobalCurrentXid; /* protected by GlobalMid_Sem */ GLOBAL_EXTERN unsigned int GlobalCurrentXid; /* protected by GlobalMid_Sem */
GLOBAL_EXTERN unsigned int GlobalTotalActiveXid; /* prot by GlobalMid_Sem */ GLOBAL_EXTERN unsigned int GlobalTotalActiveXid; /* prot by GlobalMid_Sem */
GLOBAL_EXTERN unsigned int GlobalMaxActiveXid; /* prot by GlobalMid_Sem */ GLOBAL_EXTERN unsigned int GlobalMaxActiveXid; /* prot by GlobalMid_Sem */
GLOBAL_EXTERN rwlock_t GlobalMid_Lock; /* protects above and list operations */ GLOBAL_EXTERN spinlock_t GlobalMid_Lock; /* protects above and list operations */
/* on midQ entries */ /* on midQ entries */
GLOBAL_EXTERN char Local_System_Name[15]; GLOBAL_EXTERN char Local_System_Name[15];
......
...@@ -62,6 +62,7 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon, ...@@ -62,6 +62,7 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
if(!rc) if(!rc)
reopen_files(tcon,nls_codepage); reopen_files(tcon,nls_codepage);
} }
unload_nls(nls_codepage);
} }
} }
if(rc) if(rc)
...@@ -821,7 +822,6 @@ int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon, ...@@ -821,7 +822,6 @@ int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
} else { } else {
len_of_str = cifs_strtoUCS((wchar_t *) rename_info->target_name, target_name, 530, nls_codepage); len_of_str = cifs_strtoUCS((wchar_t *) rename_info->target_name, target_name, 530, nls_codepage);
} }
cFYI(1,("len of str: %d", len_of_str)); /* BB removeme BB */
rename_info->target_name_len = cpu_to_le32(2 * len_of_str); rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
pSMB->DataCount = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2; pSMB->DataCount = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
pSMB->ByteCount += pSMB->DataCount; pSMB->ByteCount += pSMB->DataCount;
......
/* /*
* fs/cifs/connect.c * fs/cifs/connect.c
* *
* Copyright (c) International Business Machines Corp., 2002 * Copyright (C) International Business Machines Corp., 2002,2003
* Author(s): Steve French (sfrench@us.ibm.com) * Author(s): Steve French (sfrench@us.ibm.com)
* *
* This library is free software; you can redistribute it and/or modify * This library is free software; you can redistribute it and/or modify
...@@ -52,6 +52,8 @@ struct smb_vol { ...@@ -52,6 +52,8 @@ struct smb_vol {
char *domainname; char *domainname;
char *UNC; char *UNC;
char *UNCip; char *UNCip;
char *iocharset; /* local code page for mapping to and from Unicode */
char *source_rfc1001_name; /* netbios name of client */
uid_t linux_uid; uid_t linux_uid;
gid_t linux_gid; gid_t linux_gid;
mode_t file_mode; mode_t file_mode;
...@@ -59,6 +61,7 @@ struct smb_vol { ...@@ -59,6 +61,7 @@ struct smb_vol {
int rw; int rw;
unsigned int rsize; unsigned int rsize;
unsigned int wsize; unsigned int wsize;
unsigned int sockopt;
unsigned short int port; unsigned short int port;
}; };
...@@ -81,7 +84,9 @@ cifs_reconnect(struct TCP_Server_Info *server) ...@@ -81,7 +84,9 @@ cifs_reconnect(struct TCP_Server_Info *server)
struct list_head *tmp; struct list_head *tmp;
struct cifsSesInfo *ses; struct cifsSesInfo *ses;
struct cifsTconInfo *tcon; struct cifsTconInfo *tcon;
if(server->tcpStatus == CifsExiting)
return rc;
server->tcpStatus = CifsNeedReconnect; server->tcpStatus = CifsNeedReconnect;
server->maxBuf = 0; server->maxBuf = 0;
...@@ -182,23 +187,26 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) ...@@ -182,23 +187,26 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
sizeof (struct smb_hdr) - sizeof (struct smb_hdr) -
1 /* RFC1001 header and SMB header */ , 1 /* RFC1001 header and SMB header */ ,
MSG_PEEK /* flags see socket.h */ ); MSG_PEEK /* flags see socket.h */ );
if (length < 0) {
if (length == -ECONNRESET) { if(server->tcpStatus == CifsExiting) {
cERROR(1, ("Connection reset by peer "));
cifs_reconnect(server);
csocket = server->ssocket;
continue;
} else { /* find define for the -512 returned at unmount time */
cFYI(1,("Error on sock_recvmsg(peek) length = %d",
length));
}
break; break;
} else if (length == 0) { } else if (server->tcpStatus == CifsNeedReconnect) {
cFYI(1,("Zero length peek received - dead session?")); cFYI(1,("Reconnecting after server stopped responding"));
cifs_reconnect(server);
csocket = server->ssocket;
continue;
} else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) {
schedule_timeout(1); /* minimum sleep to prevent looping
allowing socket to clear and app threads to set
tcpStatus CifsNeedReconnect if server hung */
continue;
} else if (length <= 0) {
cFYI(1,("Reconnecting after unexpected rcvmsg error "));
cifs_reconnect(server); cifs_reconnect(server);
csocket = server->ssocket; csocket = server->ssocket;
continue; continue;
} }
pdu_length = 4 + ntohl(smb_buffer->smb_buf_length); pdu_length = 4 + ntohl(smb_buffer->smb_buf_length);
cFYI(1, ("Peek length rcvd: %d with smb length: %d", length, pdu_length)); cFYI(1, ("Peek length rcvd: %d with smb length: %d", length, pdu_length));
...@@ -222,7 +230,9 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) ...@@ -222,7 +230,9 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
cERROR(1, cERROR(1,
("Unknown RFC 1001 frame received not 0x00 nor 0x85")); ("Unknown RFC 1001 frame received not 0x00 nor 0x85"));
cifs_dump_mem(" Received Data is: ", temp, length); cifs_dump_mem(" Received Data is: ", temp, length);
break; cifs_reconnect(server);
csocket = server->ssocket;
continue;
} else { } else {
if ((length != sizeof (struct smb_hdr) - 1) if ((length != sizeof (struct smb_hdr) - 1)
|| (pdu_length > || (pdu_length >
...@@ -236,11 +246,12 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) ...@@ -236,11 +246,12 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
("Invalid size or format for SMB found with length %d and pdu_lenght %d", ("Invalid size or format for SMB found with length %d and pdu_lenght %d",
length, pdu_length)); length, pdu_length));
cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr)); cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr));
/* BB fix by finding next smb signature - and reading off data until next smb ? BB */ /* could we fix this network corruption by finding next
smb header (instead of killing the session) and
/* BB add reconnect here */ restart reading from next valid SMB found? */
cifs_reconnect(server);
break; csocket = server->ssocket;
continue;
} else { /* length ok */ } else { /* length ok */
length = 0; length = 0;
...@@ -248,19 +259,16 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) ...@@ -248,19 +259,16 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
iov.iov_len = pdu_length; iov.iov_len = pdu_length;
for (total_read = 0; total_read < pdu_length; total_read += length) { for (total_read = 0; total_read < pdu_length; total_read += length) {
/* Should improve check for buffer overflow with bad pdu_length */ /* Should improve check for buffer overflow with bad pdu_length */
/* iov.iov_base = smb_buffer+total_read;
iov.iov_len = pdu_length-total_read; */
length = sock_recvmsg(csocket, &smb_msg, length = sock_recvmsg(csocket, &smb_msg,
pdu_length - total_read, 0); pdu_length - total_read, 0);
/* cERROR(1,("For iovlen %d Length received: %d with total read %d",
iov.iov_len, length,total_read)); */
if (length == 0) { if (length == 0) {
cERROR(1, cERROR(1,
("Zero length receive when expecting %d ", ("Zero length receive when expecting %d ",
pdu_length - total_read)); pdu_length - total_read));
/* BB add reconnect here */ cifs_reconnect(server);
break; csocket = server->ssocket;
} continue;
}
} }
} }
...@@ -272,7 +280,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) ...@@ -272,7 +280,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
} }
task_to_wake = NULL; task_to_wake = NULL;
read_lock(&GlobalMid_Lock); spin_lock(&GlobalMid_Lock);
list_for_each(tmp, &server->pending_mid_q) { list_for_each(tmp, &server->pending_mid_q) {
mid_entry = list_entry(tmp, struct mid_entry = list_entry(tmp, struct
mid_q_entry, mid_q_entry,
...@@ -288,7 +296,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) ...@@ -288,7 +296,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
MID_RESPONSE_RECEIVED; MID_RESPONSE_RECEIVED;
} }
} }
read_unlock(&GlobalMid_Lock); spin_unlock(&GlobalMid_Lock);
if (task_to_wake) { if (task_to_wake) {
smb_buffer = NULL; /* will be freed by users thread after he is done */ smb_buffer = NULL; /* will be freed by users thread after he is done */
wake_up_process(task_to_wake); wake_up_process(task_to_wake);
...@@ -432,6 +440,20 @@ parse_mount_options(char *options, const char *devname, struct smb_vol *vol) ...@@ -432,6 +440,20 @@ parse_mount_options(char *options, const char *devname, struct smb_vol *vol)
printk(KERN_WARNING "CIFS: domain name too long\n"); printk(KERN_WARNING "CIFS: domain name too long\n");
return 1; return 1;
} }
} else if (strnicmp(data, "iocharset", 9) == 0) {
if (!value || !*value) {
printk(KERN_WARNING "CIFS: invalid iocharset specified\n");
return 1; /* needs_arg; */
}
if (strnlen(value, 65) < 65) {
if(strnicmp(value,"default",7))
vol->iocharset = value;
/* if iocharset not set load_nls_default used by caller */
cFYI(1, ("iocharset set to %s",value));
} else {
printk(KERN_WARNING "CIFS: iocharset name too long.\n");
return 1;
}
} else if (strnicmp(data, "uid", 3) == 0) { } else if (strnicmp(data, "uid", 3) == 0) {
if (value && *value) { if (value && *value) {
vol->linux_uid = vol->linux_uid =
...@@ -467,6 +489,19 @@ parse_mount_options(char *options, const char *devname, struct smb_vol *vol) ...@@ -467,6 +489,19 @@ parse_mount_options(char *options, const char *devname, struct smb_vol *vol)
vol->wsize = vol->wsize =
simple_strtoul(value, &value, 0); simple_strtoul(value, &value, 0);
} }
} else if (strnicmp(data, "sockopt", 5) == 0) {
if (value && *value) {
vol->sockopt =
simple_strtoul(value, &value, 0);
}
} else if (strnicmp(data, "netbiosname", 4) == 0) {
if (!value || !*value) {
vol->source_rfc1001_name = NULL;
} else if (strnlen(value, 17) < 17) {
vol->source_rfc1001_name = value;
} else {
printk(KERN_WARNING "CIFS: netbiosname too long (more than 15)\n");
}
} else if (strnicmp(data, "version", 3) == 0) { } else if (strnicmp(data, "version", 3) == 0) {
/* ignore */ /* ignore */
} else if (strnicmp(data, "rw", 2) == 0) { } else if (strnicmp(data, "rw", 2) == 0) {
...@@ -722,13 +757,13 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket) ...@@ -722,13 +757,13 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket)
int rc = 0; int rc = 0;
if(*csocket == NULL) { if(*csocket == NULL) {
rc = sock_create(PF_INET, SOCK_STREAM, IPPROTO_TCP, csocket); rc = sock_create(PF_INET, SOCK_STREAM, IPPROTO_TCP, csocket);
if (rc < 0) { if (rc < 0) {
cERROR(1, ("Error %d creating socket",rc)); cERROR(1, ("Error %d creating socket",rc));
*csocket = NULL; *csocket = NULL;
return rc; return rc;
} else { } else {
/* BB other socket options to set KEEPALIVE, timeouts? NODELAY? */ /* BB other socket options to set KEEPALIVE, NODELAY? */
cFYI(1,("Socket created")); cFYI(1,("Socket created"));
} }
} }
...@@ -763,6 +798,11 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket) ...@@ -763,6 +798,11 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket)
} }
} }
/* Eventually check for other socket options to change from
the default. sock_setsockopt not used because it expects
user space buffer */
(*csocket)->sk->sk_rcvtimeo = 8 * HZ;
return rc; return rc;
} }
...@@ -863,6 +903,19 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, ...@@ -863,6 +903,19 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
return -EINVAL; return -EINVAL;
} }
/* this is needed for ASCII cp to Unicode converts */
if(volume_info.iocharset == NULL) {
cifs_sb->local_nls = load_nls_default();
/* load_nls_default can not return null */
} else {
cifs_sb->local_nls = load_nls(volume_info.iocharset);
if(cifs_sb->local_nls == NULL) {
cERROR(1,("CIFS mount error: iocharset %s not found",volume_info.iocharset));
FreeXid(xid);
return -ELIBACC;
}
}
existingCifsSes = existingCifsSes =
find_tcp_session(sin_server.sin_addr.s_addr, find_tcp_session(sin_server.sin_addr.s_addr,
volume_info.username, &srvTcp); volume_info.username, &srvTcp);
...@@ -999,6 +1052,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, ...@@ -999,6 +1052,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
/* on error free sesinfo and tcon struct if needed */ /* on error free sesinfo and tcon struct if needed */
if (rc) { if (rc) {
if(atomic_read(&srvTcp->socketUseCount) == 0)
srvTcp->tcpStatus = CifsExiting;
/* If find_unc succeeded then rc == 0 so we can not end */ /* If find_unc succeeded then rc == 0 so we can not end */
if (tcon) /* up here accidently freeing someone elses tcon struct */ if (tcon) /* up here accidently freeing someone elses tcon struct */
tconInfoFree(tcon); tconInfoFree(tcon);
......
...@@ -218,6 +218,8 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, ...@@ -218,6 +218,8 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
pCifsFile->netfid = fileHandle; pCifsFile->netfid = fileHandle;
pCifsFile->pid = current->tgid; pCifsFile->pid = current->tgid;
pCifsFile->pInode = newinode; pCifsFile->pInode = newinode;
pCifsFile->invalidHandle = FALSE;
pCifsFile->closePend = FALSE;
/* pCifsFile->pfile = file; */ /* put in at open time */ /* pCifsFile->pfile = file; */ /* put in at open time */
write_lock(&GlobalSMBSeslock); write_lock(&GlobalSMBSeslock);
list_add(&pCifsFile->tlist,&pTcon->openFileList); list_add(&pCifsFile->tlist,&pTcon->openFileList);
......
This diff is collapsed.
/* /*
* fs/cifs/misc.c * fs/cifs/misc.c
* *
* Copyright (c) International Business Machines Corp., 2002,2003 * Copyright (C) International Business Machines Corp., 2002,2003
* Author(s): Steve French (sfrench@us.ibm.com) * Author(s): Steve French (sfrench@us.ibm.com)
* *
* This library is free software; you can redistribute it and/or modify * This library is free software; you can redistribute it and/or modify
...@@ -42,23 +42,23 @@ _GetXid(void) ...@@ -42,23 +42,23 @@ _GetXid(void)
{ {
unsigned int xid; unsigned int xid;
write_lock(&GlobalMid_Lock); spin_lock(&GlobalMid_Lock);
GlobalTotalActiveXid++; GlobalTotalActiveXid++;
if (GlobalTotalActiveXid > GlobalMaxActiveXid) if (GlobalTotalActiveXid > GlobalMaxActiveXid)
GlobalMaxActiveXid = GlobalTotalActiveXid; /* keep high water mark for number of simultaneous vfs ops in our filesystem */ GlobalMaxActiveXid = GlobalTotalActiveXid; /* keep high water mark for number of simultaneous vfs ops in our filesystem */
xid = GlobalCurrentXid++; xid = GlobalCurrentXid++;
write_unlock(&GlobalMid_Lock); spin_unlock(&GlobalMid_Lock);
return xid; return xid;
} }
void void
_FreeXid(unsigned int xid) _FreeXid(unsigned int xid)
{ {
write_lock(&GlobalMid_Lock); spin_lock(&GlobalMid_Lock);
/* if(GlobalTotalActiveXid == 0) /* if(GlobalTotalActiveXid == 0)
BUG(); */ BUG(); */
GlobalTotalActiveXid--; GlobalTotalActiveXid--;
write_unlock(&GlobalMid_Lock); spin_unlock(&GlobalMid_Lock);
} }
struct cifsSesInfo * struct cifsSesInfo *
...@@ -217,10 +217,10 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ , ...@@ -217,10 +217,10 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
buffer->Pid = tmp & 0xFFFF; buffer->Pid = tmp & 0xFFFF;
tmp >>= 16; tmp >>= 16;
buffer->PidHigh = tmp & 0xFFFF; buffer->PidHigh = tmp & 0xFFFF;
write_lock(&GlobalMid_Lock); spin_lock(&GlobalMid_Lock);
GlobalMid++; GlobalMid++;
buffer->Mid = GlobalMid; buffer->Mid = GlobalMid;
write_unlock(&GlobalMid_Lock); spin_unlock(&GlobalMid_Lock);
if (treeCon) { if (treeCon) {
buffer->Tid = treeCon->tid; buffer->Tid = treeCon->tid;
if (treeCon->ses) { if (treeCon->ses) {
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
SMB authentication protocol SMB authentication protocol
Copyright (C) Andrew Tridgell 1998 Copyright (C) Andrew Tridgell 1998
Modified by Steve French (sfrench@us.ibm.com) 2002 Modified by Steve French (sfrench@us.ibm.com) 2002,2003
This program is free software; you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
...@@ -376,41 +376,3 @@ cred_hash3(unsigned char *out, unsigned char *in, unsigned char *key, int forw) ...@@ -376,41 +376,3 @@ cred_hash3(unsigned char *out, unsigned char *in, unsigned char *key, int forw)
key2[0] = key[7]; key2[0] = key[7];
smbhash(out + 8, in + 8, key2, forw); smbhash(out + 8, in + 8, key2, forw);
} }
void
SamOEMhash(unsigned char *data, unsigned char *key, int val)
{
unsigned char s_box[256];
unsigned char index_i = 0;
unsigned char index_j = 0;
unsigned char j = 0;
int ind;
for (ind = 0; ind < 256; ind++) {
s_box[ind] = (unsigned char) ind;
}
for (ind = 0; ind < 256; ind++) {
unsigned char tc;
j += (s_box[ind] + key[ind % 16]);
tc = s_box[ind];
s_box[ind] = s_box[j];
s_box[j] = tc;
}
for (ind = 0; ind < val; ind++) {
unsigned char tc;
unsigned char t;
index_i++;
index_j += s_box[index_i];
tc = s_box[index_i];
s_box[index_i] = s_box[index_j];
s_box[index_j] = tc;
t = s_box[index_i] + s_box[index_j];
data[ind] = data[ind] ^ s_box[t];
}
}
...@@ -63,7 +63,6 @@ void cred_hash1(unsigned char *out, unsigned char *in, unsigned char *key); ...@@ -63,7 +63,6 @@ void cred_hash1(unsigned char *out, unsigned char *in, unsigned char *key);
void cred_hash2(unsigned char *out, unsigned char *in, unsigned char *key); void cred_hash2(unsigned char *out, unsigned char *in, unsigned char *key);
void cred_hash3(unsigned char *out, unsigned char *in, unsigned char *key, void cred_hash3(unsigned char *out, unsigned char *in, unsigned char *key,
int forw); int forw);
void SamOEMhash(unsigned char *data, unsigned char *key, int val);
/*The following definitions come from libsmb/smbencrypt.c */ /*The following definitions come from libsmb/smbencrypt.c */
...@@ -75,8 +74,6 @@ void SMBOWFencrypt(unsigned char passwd[16], unsigned char *c8, ...@@ -75,8 +74,6 @@ void SMBOWFencrypt(unsigned char passwd[16], unsigned char *c8,
void NTLMSSPOWFencrypt(unsigned char passwd[8], void NTLMSSPOWFencrypt(unsigned char passwd[8],
unsigned char *ntlmchalresp, unsigned char p24[24]); unsigned char *ntlmchalresp, unsigned char p24[24]);
void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24); void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24);
int make_oem_passwd_hash(char data[516], const char *passwd,
unsigned char old_pw_hash[16], int unicode);
int decode_pw_buffer(char in_buffer[516], char *new_pwrd, int decode_pw_buffer(char in_buffer[516], char *new_pwrd,
int new_pwrd_size, __u32 * new_pw_len); int new_pwrd_size, __u32 * new_pw_len);
...@@ -346,46 +343,6 @@ static struct data_blob LMv2_generate_response(const unsigned char ntlm_v2_hash[ ...@@ -346,46 +343,6 @@ static struct data_blob LMv2_generate_response(const unsigned char ntlm_v2_hash[
return final_response; return final_response;
} }
int make_oem_passwd_hash(char data[516], const char *passwd,
unsigned char old_pw_hash[16], int unicode)
{
int new_pw_len = strlen(passwd) * (unicode ? 2 : 1);
if (new_pw_len > 512) {
cERROR(1,
("CIFS make_oem_passwd_hash: new password is too long."));
return FALSE;
}
/*
* Now setup the data area.
* We need to generate a random fill
* for this area to make it harder to
* decrypt. JRA.
*
*/
get_random_bytes(data, sizeof (data));
if (unicode) {
/* Note that passwd should be in DOS oem character set. */
/* dos_struni2( &data[512 - new_pw_len], passwd, 512); */
cifs_strtoUCS((wchar_t *) & data[512 - new_pw_len], passwd, 512, /* struct nls_table */
load_nls_default());
/* BB call unload_nls now or get nls differntly */
} else {
/* Note that passwd should be in DOS oem character set. */
strcpy(&data[512 - new_pw_len], passwd);
}
SIVAL(data, 512, new_pw_len);
#ifdef DEBUG_PASSWORD
DEBUG(100, ("make_oem_passwd_hash\n"));
dump_data(100, data, 516);
#endif
SamOEMhash((unsigned char *) data, (unsigned char *) old_pw_hash, 516);
return TRUE;
}
void void
SMBsesskeygen_ntv2(const unsigned char kr[16], SMBsesskeygen_ntv2(const unsigned char kr[16],
const unsigned char *nt_resp, __u8 sess_key[16]) const unsigned char *nt_resp, __u8 sess_key[16])
......
/* /*
* fs/cifs/transport.c * fs/cifs/transport.c
* *
* Copyright (c) International Business Machines Corp., 2002 * Copyright (C) International Business Machines Corp., 2002,2003
* Author(s): Steve French (sfrench@us.ibm.com) * Author(s): Steve French (sfrench@us.ibm.com)
* *
* This library is free software; you can redistribute it and/or modify * This library is free software; you can redistribute it and/or modify
...@@ -39,7 +39,6 @@ AllocMidQEntry(struct smb_hdr *smb_buffer, struct cifsSesInfo *ses) ...@@ -39,7 +39,6 @@ AllocMidQEntry(struct smb_hdr *smb_buffer, struct cifsSesInfo *ses)
struct mid_q_entry *temp; struct mid_q_entry *temp;
int timeout = 10 * HZ; int timeout = 10 * HZ;
/* BB add spinlock to protect midq for each session BB */
if (ses == NULL) { if (ses == NULL) {
cERROR(1, ("Null session passed in to AllocMidQEntry ")); cERROR(1, ("Null session passed in to AllocMidQEntry "));
return NULL; return NULL;
...@@ -72,11 +71,11 @@ AllocMidQEntry(struct smb_hdr *smb_buffer, struct cifsSesInfo *ses) ...@@ -72,11 +71,11 @@ AllocMidQEntry(struct smb_hdr *smb_buffer, struct cifsSesInfo *ses)
} }
if (ses->server->tcpStatus == CifsGood) { if (ses->server->tcpStatus == CifsGood) {
write_lock(&GlobalMid_Lock); spin_lock(&GlobalMid_Lock);
list_add_tail(&temp->qhead, &ses->server->pending_mid_q); list_add_tail(&temp->qhead, &ses->server->pending_mid_q);
atomic_inc(&midCount); atomic_inc(&midCount);
temp->midState = MID_REQUEST_ALLOCATED; temp->midState = MID_REQUEST_ALLOCATED;
write_unlock(&GlobalMid_Lock); spin_unlock(&GlobalMid_Lock);
} else { } else {
cERROR(1,("Need to reconnect after session died to server")); cERROR(1,("Need to reconnect after session died to server"));
if (temp) if (temp)
...@@ -89,12 +88,11 @@ AllocMidQEntry(struct smb_hdr *smb_buffer, struct cifsSesInfo *ses) ...@@ -89,12 +88,11 @@ AllocMidQEntry(struct smb_hdr *smb_buffer, struct cifsSesInfo *ses)
void void
DeleteMidQEntry(struct mid_q_entry *midEntry) DeleteMidQEntry(struct mid_q_entry *midEntry)
{ {
/* BB add spinlock to protect midq for each session BB */ spin_lock(&GlobalMid_Lock);
write_lock(&GlobalMid_Lock);
midEntry->midState = MID_FREE; midEntry->midState = MID_FREE;
list_del(&midEntry->qhead); list_del(&midEntry->qhead);
atomic_dec(&midCount); atomic_dec(&midCount);
write_unlock(&GlobalMid_Lock); spin_unlock(&GlobalMid_Lock);
buf_release(midEntry->resp_buf); buf_release(midEntry->resp_buf);
kmem_cache_free(cifs_mid_cachep, midEntry); kmem_cache_free(cifs_mid_cachep, midEntry);
} }
...@@ -115,9 +113,9 @@ AllocOplockQEntry(struct inode * pinode, __u16 fid, struct cifsTconInfo * tcon) ...@@ -115,9 +113,9 @@ AllocOplockQEntry(struct inode * pinode, __u16 fid, struct cifsTconInfo * tcon)
temp->pinode = pinode; temp->pinode = pinode;
temp->tcon = tcon; temp->tcon = tcon;
temp->netfid = fid; temp->netfid = fid;
write_lock(&GlobalMid_Lock); spin_lock(&GlobalMid_Lock);
list_add_tail(&temp->qhead, &GlobalOplock_Q); list_add_tail(&temp->qhead, &GlobalOplock_Q);
write_unlock(&GlobalMid_Lock); spin_unlock(&GlobalMid_Lock);
} }
return temp; return temp;
...@@ -125,11 +123,10 @@ AllocOplockQEntry(struct inode * pinode, __u16 fid, struct cifsTconInfo * tcon) ...@@ -125,11 +123,10 @@ AllocOplockQEntry(struct inode * pinode, __u16 fid, struct cifsTconInfo * tcon)
void DeleteOplockQEntry(struct oplock_q_entry * oplockEntry) void DeleteOplockQEntry(struct oplock_q_entry * oplockEntry)
{ {
/* BB add spinlock to protect midq for each session BB */ spin_lock(&GlobalMid_Lock);
write_lock(&GlobalMid_Lock);
/* should we check if list empty first? */ /* should we check if list empty first? */
list_del(&oplockEntry->qhead); list_del(&oplockEntry->qhead);
write_unlock(&GlobalMid_Lock); spin_unlock(&GlobalMid_Lock);
kmem_cache_free(cifs_oplock_cachep, oplockEntry); kmem_cache_free(cifs_oplock_cachep, oplockEntry);
} }
...@@ -240,6 +237,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, ...@@ -240,6 +237,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
else { else {
cFYI(1,("No response buffer")); cFYI(1,("No response buffer"));
DeleteMidQEntry(midQ); DeleteMidQEntry(midQ);
ses->server->tcpStatus = CifsNeedReconnect;
return -EIO; return -EIO;
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment