Commit 2aa60962 authored by Steve French's avatar Steve French

Fix locking of global smb list. Add missing rc checks.

parent ecf2c214
...@@ -79,18 +79,20 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset, ...@@ -79,18 +79,20 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
buf += length; buf += length;
i = 0; i = 0;
read_lock(&GlobalSMBSeslock);
list_for_each(tmp, &GlobalSMBSessionList) { list_for_each(tmp, &GlobalSMBSessionList) {
i++; i++;
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 HowManyMounts: %d LocalUsersToSameServer: %d\n\t ServerOS: %s ServerNOS: %s Capabilities: 0x%x ", "\n%d) Name: %s Domain: %s HowManyMounts: %d ServerOS: %s ServerNOS: %s Capabilities: 0x%x\n",
i, ses->serverName, ses->serverDomain, i, ses->serverName, ses->serverDomain, atomic_read(&ses->inUse),
atomic_read(&ses->inUse),
atomic_read(&ses->server->socketUseCount),
ses->serverOS, ses->serverNOS, ses->capabilities); ses->serverOS, ses->serverNOS, ses->capabilities);
buf += length; buf += length;
if(ses->server)
buf += sprintf(buf, "\tLocal Users To Same Server: %d ",atomic_read(&ses->server->socketUseCount));
} }
read_unlock(&GlobalSMBSeslock);
sprintf(buf, "\n"); sprintf(buf, "\n");
buf++; buf++;
printk("\nTotal Buffer so far: %s\n", buf_start); printk("\nTotal Buffer so far: %s\n", buf_start);
...@@ -99,6 +101,7 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset, ...@@ -99,6 +101,7 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
buf += length; buf += length;
i = 0; i = 0;
read_lock(&GlobalSMBSeslock);
list_for_each(tmp, &GlobalTreeConnectionList) { list_for_each(tmp, &GlobalTreeConnectionList) {
i++; i++;
tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList); tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
...@@ -122,6 +125,7 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset, ...@@ -122,6 +125,7 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
tcon->fsDevInfo.DeviceType); tcon->fsDevInfo.DeviceType);
buf += length; buf += length;
} }
read_unlock(&GlobalSMBSeslock);
length = sprintf(buf, "\n"); length = sprintf(buf, "\n");
buf += length; buf += length;
*eof = 1; *eof = 1;
...@@ -262,10 +266,13 @@ cifs_proc_clean(void) ...@@ -262,10 +266,13 @@ cifs_proc_clean(void)
remove_proc_entry("DebugData", proc_fs_cifs); remove_proc_entry("DebugData", proc_fs_cifs);
remove_proc_entry("cifsFYI", proc_fs_cifs); remove_proc_entry("cifsFYI", proc_fs_cifs);
remove_proc_entry("TraceSMB", proc_fs_cifs); remove_proc_entry("TraceSMB", proc_fs_cifs);
remove_proc_entry("MaxSimultaneousOps", proc_fs_cifs); remove_proc_entry("SimultaneousOps", proc_fs_cifs);
remove_proc_entry("TotalOps", proc_fs_cifs); remove_proc_entry("TotalOps", proc_fs_cifs);
remove_proc_entry("MultiuserMount", proc_fs_cifs); remove_proc_entry("MultiuserMount", proc_fs_cifs);
remove_proc_entry("oplockEnabled", proc_fs_cifs); remove_proc_entry("oplockEnabled", proc_fs_cifs);
remove_proc_entry("NTLMV2Enabled",proc_fs_cifs);
remove_proc_entry("ExtendedSecurity",proc_fs_cifs);
remove_proc_entry("PacketSigningEnabled",proc_fs_cifs);
remove_proc_entry("cifs", proc_root_fs); remove_proc_entry("cifs", proc_root_fs);
} }
......
...@@ -66,6 +66,8 @@ cifs_read_super(struct super_block *sb, void *data, char *devname, int silent) ...@@ -66,6 +66,8 @@ cifs_read_super(struct super_block *sb, void *data, char *devname, int silent)
sb->s_fs_info = kmalloc(sizeof(struct cifs_sb_info),GFP_KERNEL); sb->s_fs_info = kmalloc(sizeof(struct cifs_sb_info),GFP_KERNEL);
cifs_sb = CIFS_SB(sb); cifs_sb = CIFS_SB(sb);
if(cifs_sb == NULL)
return -ENOMEM;
cifs_sb->local_nls = load_nls_default(); /* needed for ASCII cp to Unicode converts */ 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);
...@@ -97,9 +99,8 @@ cifs_read_super(struct super_block *sb, void *data, char *devname, int silent) ...@@ -97,9 +99,8 @@ cifs_read_super(struct super_block *sb, void *data, char *devname, int silent)
if (inode) if (inode)
iput(inode); iput(inode);
/* rc = cifs_umount(sb); BB is CIFS unmount routine needed? */
if (rc) { if (rc) {
cERROR(1, ("cifs_umount failed with return code %d\n", rc)); cERROR(1, ("cifs_mount failed with no root inode"));
} }
out_mount_failed: out_mount_failed:
if(cifs_sb) if(cifs_sb)
...@@ -114,15 +115,18 @@ cifs_put_super(struct super_block *sb) ...@@ -114,15 +115,18 @@ cifs_put_super(struct super_block *sb)
struct cifs_sb_info *cifs_sb; struct cifs_sb_info *cifs_sb;
cFYI(1, ("In cifs_put_super\n")); cFYI(1, ("In cifs_put_super\n"));
schedule_timeout(HZ*4);
cifs_sb = CIFS_SB(sb); cifs_sb = CIFS_SB(sb);
if(cifs_sb == NULL) {
cFYI(1,("\nEmpty cifs superblock info passed to unmount"));
return;
}
rc = cifs_umount(sb, cifs_sb); rc = cifs_umount(sb, cifs_sb);
if (rc) { if (rc) {
cERROR(1, ("cifs_umount failed with return code %d\n", rc)); cERROR(1, ("cifs_umount failed with return code %d\n", rc));
} }
if(cifs_sb) {
unload_nls(cifs_sb->local_nls); unload_nls(cifs_sb->local_nls);
kfree(cifs_sb); kfree(cifs_sb);
}
return; return;
} }
...@@ -387,8 +391,11 @@ init_cifs(void) ...@@ -387,8 +391,11 @@ init_cifs(void)
atomic_set(&tconInfoAllocCount, 0); atomic_set(&tconInfoAllocCount, 0);
atomic_set(&bufAllocCount, 0); atomic_set(&bufAllocCount, 0);
atomic_set(&midCount, 0); atomic_set(&midCount, 0);
GlobalCurrentXid = 0;
GlobalTotalActiveXid = 0; GlobalTotalActiveXid = 0;
GlobalMaxActiveXid = 0; GlobalMaxActiveXid = 0;
GlobalSMBSeslock = RW_LOCK_UNLOCKED;
GlobalMid_Lock = RW_LOCK_UNLOCKED;
rc = cifs_init_inodecache(); rc = cifs_init_inodecache();
if (!rc) { if (!rc) {
......
...@@ -292,13 +292,10 @@ GLOBAL_EXTERN struct servers_not_supported *NotSuppList; /*@z4a */ ...@@ -292,13 +292,10 @@ GLOBAL_EXTERN struct servers_not_supported *NotSuppList; /*@z4a */
*/ */
GLOBAL_EXTERN struct smbUidInfo *GlobalUidList[UID_HASH]; GLOBAL_EXTERN struct smbUidInfo *GlobalUidList[UID_HASH];
GLOBAL_EXTERN struct list_head GlobalServerList; /* BB this one is not implemented yet */ GLOBAL_EXTERN struct list_head GlobalServerList; /* BB not implemented yet */
GLOBAL_EXTERN struct list_head GlobalSMBSessionList; GLOBAL_EXTERN struct list_head GlobalSMBSessionList;
GLOBAL_EXTERN struct list_head GlobalTreeConnectionList; GLOBAL_EXTERN struct list_head GlobalTreeConnectionList;
/* GLOBAL_EXTERN rwlock_t GlobalSMBSeslock; /* protects list inserts on 3 above */
* Global list of free SMB structures
*/
GLOBAL_EXTERN void *GlobalFreeSMB;
/* /*
* Global transaction id (XID) information * Global transaction id (XID) information
...@@ -306,7 +303,8 @@ GLOBAL_EXTERN void *GlobalFreeSMB; ...@@ -306,7 +303,8 @@ GLOBAL_EXTERN void *GlobalFreeSMB;
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 */
/* on midQ entries */
GLOBAL_EXTERN char Local_System_Name[15]; GLOBAL_EXTERN char Local_System_Name[15];
/* /*
...@@ -330,4 +328,3 @@ GLOBAL_EXTERN unsigned int extended_security; /* if on, session setup sent ...@@ -330,4 +328,3 @@ GLOBAL_EXTERN unsigned int extended_security; /* if on, session setup sent
GLOBAL_EXTERN unsigned int ntlmv2_support; /* better optional password hash */ GLOBAL_EXTERN unsigned int ntlmv2_support; /* better optional password hash */
GLOBAL_EXTERN unsigned int sign_CIFS_PDUs; /* enable smb packet signing */ GLOBAL_EXTERN unsigned int sign_CIFS_PDUs; /* enable smb packet signing */
...@@ -505,7 +505,8 @@ CIFSSMBRead(const int xid, const struct cifsTconInfo *tcon, ...@@ -505,7 +505,8 @@ CIFSSMBRead(const int xid, const struct cifsTconInfo *tcon,
pReadData = pReadData =
(char *) (&pSMBr->hdr.Protocol) + (char *) (&pSMBr->hdr.Protocol) +
le16_to_cpu(pSMBr->DataOffset); le16_to_cpu(pSMBr->DataOffset);
copy_to_user(buf, pReadData, pSMBr->DataLength); if(copy_to_user(buf, pReadData, pSMBr->DataLength))
rc = -EFAULT;
} }
} }
...@@ -544,7 +545,13 @@ CIFSSMBWrite(const int xid, const struct cifsTconInfo *tcon, ...@@ -544,7 +545,13 @@ CIFSSMBWrite(const int xid, const struct cifsTconInfo *tcon,
pSMB->DataLengthHigh = 0; pSMB->DataLengthHigh = 0;
pSMB->DataOffset = pSMB->DataOffset =
cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4); cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
copy_from_user(pSMB->Data, buf, pSMB->DataLengthLow);
if(copy_from_user(pSMB->Data, buf, pSMB->DataLengthLow)) {
buf_release(pSMB);
return -EFAULT;
}
pSMB->ByteCount += pSMB->DataLengthLow + 1 /* pad */ ; pSMB->ByteCount += pSMB->DataLengthLow + 1 /* pad */ ;
pSMB->DataLengthLow = cpu_to_le16(pSMB->DataLengthLow); pSMB->DataLengthLow = cpu_to_le16(pSMB->DataLengthLow);
......
...@@ -219,6 +219,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) ...@@ -219,6 +219,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
} }
task_to_wake = NULL; task_to_wake = NULL;
read_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,
...@@ -234,7 +235,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) ...@@ -234,7 +235,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
MID_RESPONSE_RECEIVED; MID_RESPONSE_RECEIVED;
} }
} }
read_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);
...@@ -262,6 +263,8 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) ...@@ -262,6 +263,8 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
set_fs(temp_fs); set_fs(temp_fs);
if (smb_buffer) /* buffer usually freed in free_mid - need to free it on error or exit */ if (smb_buffer) /* buffer usually freed in free_mid - need to free it on error or exit */
buf_release(smb_buffer); buf_release(smb_buffer);
read_lock(&GlobalSMBSeslock);
if (list_empty(&server->pending_mid_q)) { if (list_empty(&server->pending_mid_q)) {
/* loop through server session structures attached to this and mark them dead */ /* loop through server session structures attached to this and mark them dead */
list_for_each(tmp, &GlobalSMBSessionList) { list_for_each(tmp, &GlobalSMBSessionList) {
...@@ -279,6 +282,8 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) ...@@ -279,6 +282,8 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
cERROR(1, ("\nThere are still active MIDs in queue and we are exiting but we can not delete mid_q_entries or TCP_Server_Info structure due to pending requests MEMORY LEAK!!\n ")); /* BB wake up waitors, and/or wait and/or free stale mids and try again? BB */ cERROR(1, ("\nThere are still active MIDs in queue and we are exiting but we can not delete mid_q_entries or TCP_Server_Info structure due to pending requests MEMORY LEAK!!\n ")); /* BB wake up waitors, and/or wait and/or free stale mids and try again? BB */
/* BB Need to fix bug in error path above - perhaps wait until smb requests /* BB Need to fix bug in error path above - perhaps wait until smb requests
time out and then free the tcp per server struct BB */ time out and then free the tcp per server struct BB */
read_unlock(&GlobalSMBSeslock);
cFYI(1, ("\nAbout to exit from demultiplex thread\n")); cFYI(1, ("\nAbout to exit from demultiplex thread\n"));
return 0; return 0;
...@@ -421,7 +426,7 @@ find_tcp_session(__u32 new_target_ip_addr, ...@@ -421,7 +426,7 @@ find_tcp_session(__u32 new_target_ip_addr,
struct cifsSesInfo *ses; struct cifsSesInfo *ses;
*psrvTcp = NULL; *psrvTcp = NULL;
read_lock(&GlobalSMBSeslock);
list_for_each(tmp, &GlobalSMBSessionList) { list_for_each(tmp, &GlobalSMBSessionList) {
ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList); ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
if (ses->server) { if (ses->server) {
...@@ -432,12 +437,15 @@ find_tcp_session(__u32 new_target_ip_addr, ...@@ -432,12 +437,15 @@ find_tcp_session(__u32 new_target_ip_addr,
/* BB check if reconnection needed */ /* BB check if reconnection needed */
if (strncmp if (strncmp
(ses->userName, userName, (ses->userName, userName,
MAX_USERNAME_SIZE) == 0) MAX_USERNAME_SIZE) == 0){
read_unlock(&GlobalSMBSeslock);
return ses; /* found exact match on both tcp and SMB sessions */ return ses; /* found exact match on both tcp and SMB sessions */
} }
} }
}
/* else tcp and smb sessions need reconnection */ /* else tcp and smb sessions need reconnection */
} }
read_unlock(&GlobalSMBSeslock);
return NULL; return NULL;
} }
...@@ -447,6 +455,7 @@ find_unc(__u32 new_target_ip_addr, char *uncName, char *userName) ...@@ -447,6 +455,7 @@ find_unc(__u32 new_target_ip_addr, char *uncName, char *userName)
struct list_head *tmp; struct list_head *tmp;
struct cifsTconInfo *tcon; struct cifsTconInfo *tcon;
read_lock(&GlobalSMBSeslock);
list_for_each(tmp, &GlobalTreeConnectionList) { list_for_each(tmp, &GlobalTreeConnectionList) {
cFYI(1, ("\nNext tcon - ")); cFYI(1, ("\nNext tcon - "));
tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList); tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
...@@ -473,13 +482,16 @@ find_unc(__u32 new_target_ip_addr, char *uncName, char *userName) ...@@ -473,13 +482,16 @@ find_unc(__u32 new_target_ip_addr, char *uncName, char *userName)
if (strncmp if (strncmp
(tcon->ses->userName, (tcon->ses->userName,
userName, userName,
MAX_USERNAME_SIZE) == 0) MAX_USERNAME_SIZE) == 0) {
read_unlock(&GlobalSMBSeslock);
return tcon;/* also matched user (smb session)*/ return tcon;/* also matched user (smb session)*/
} }
} }
} }
} }
} }
}
read_unlock(&GlobalSMBSeslock);
return NULL; return NULL;
} }
...@@ -616,7 +628,11 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, ...@@ -616,7 +628,11 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
xid = GetXid(); xid = GetXid();
cFYI(0, ("\nEntering cifs_mount. Xid: %d with: %s\n", xid, mount_data)); cFYI(0, ("\nEntering cifs_mount. Xid: %d with: %s\n", xid, mount_data));
parse_mount_options(mount_data, devname, &volume_info); if(parse_mount_options(mount_data, devname, &volume_info)) {
FreeXid(xid);
return -EINVAL;
}
if (volume_info.username) { if (volume_info.username) {
cFYI(1, ("\nUsername: %s ", volume_info.username)); cFYI(1, ("\nUsername: %s ", volume_info.username));
...@@ -634,7 +650,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, ...@@ -634,7 +650,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
cERROR(1, cERROR(1,
("\nCIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified ")); ("\nCIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified "));
FreeXid(xid); FreeXid(xid);
return -ENODEV; return -EINVAL;
} }
/* BB add support to use the multiuser_mount flag BB */ /* BB add support to use the multiuser_mount flag BB */
existingCifsSes = existingCifsSes =
...@@ -2202,6 +2218,7 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb) ...@@ -2202,6 +2218,7 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
struct cifsSesInfo *ses = NULL; struct cifsSesInfo *ses = NULL;
xid = GetXid(); xid = GetXid();
if (cifs_sb->tcon) { if (cifs_sb->tcon) {
ses = cifs_sb->tcon->ses; /* save ptr to ses before delete tcon!*/ ses = cifs_sb->tcon->ses; /* save ptr to ses before delete tcon!*/
rc = CIFSSMBTDis(xid, cifs_sb->tcon); rc = CIFSSMBTDis(xid, cifs_sb->tcon);
...@@ -2218,15 +2235,10 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb) ...@@ -2218,15 +2235,10 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
FreeXid(xid); FreeXid(xid);
return 0; return 0;
} }
/* wake_up_process(ses->server->tsk);*/ /* was worth a try */
schedule_timeout(HZ / 4); /* give captive thread time to exit */ schedule_timeout(HZ / 4); /* give captive thread time to exit */
if((ses->server) && (ses->server->ssocket)) { if((ses->server) && (ses->server->ssocket)) {
cFYI(1,("\nWaking up socket by sending it signal ")); cFYI(1,("\nWaking up socket by sending it signal "));
send_sig(SIGINT,ses->server->tsk,1); send_sig(SIGINT,ses->server->tsk,1);
/* No luck figuring out a better way to_close socket */
/*ses->server->ssocket->sk->prot->close(ses->server->ssocket->sk,0);*/
/* ses->server->ssocket = NULL; */ /* serialize better */
/* sock_wake_async(ses->server->ssocket,3,POLL_HUP); */
} }
} else } else
cFYI(1, ("\nNo session or bad tcon")); cFYI(1, ("\nNo session or bad tcon"));
......
...@@ -28,7 +28,6 @@ ...@@ -28,7 +28,6 @@
extern kmem_cache_t *cifs_req_cachep; extern kmem_cache_t *cifs_req_cachep;
static DECLARE_MUTEX(GlobalMid_Sem); /* also protects XID globals */
__u16 GlobalMid; /* multiplex id - rotating counter */ __u16 GlobalMid; /* multiplex id - rotating counter */
/* The xid serves as a useful identifier for each incoming vfs request, /* The xid serves as a useful identifier for each incoming vfs request,
...@@ -42,21 +41,21 @@ _GetXid(void) ...@@ -42,21 +41,21 @@ _GetXid(void)
{ {
unsigned int xid; unsigned int xid;
down(&GlobalMid_Sem); write_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++;
up(&GlobalMid_Sem); write_unlock(&GlobalMid_Lock);
return xid; return xid;
} }
void void
_FreeXid(unsigned int xid) _FreeXid(unsigned int xid)
{ {
down(&GlobalMid_Sem); write_lock(&GlobalMid_Lock);
GlobalTotalActiveXid--; GlobalTotalActiveXid--;
up(&GlobalMid_Sem); write_unlock(&GlobalMid_Lock);
} }
struct cifsSesInfo * struct cifsSesInfo *
...@@ -69,9 +68,11 @@ sesInfoAlloc(void) ...@@ -69,9 +68,11 @@ sesInfoAlloc(void)
GFP_KERNEL); GFP_KERNEL);
if (ret_buf) { if (ret_buf) {
memset(ret_buf, 0, sizeof (struct cifsSesInfo)); memset(ret_buf, 0, sizeof (struct cifsSesInfo));
write_lock(&GlobalSMBSeslock);
atomic_inc(&sesInfoAllocCount); atomic_inc(&sesInfoAllocCount);
list_add(&ret_buf->cifsSessionList, &GlobalSMBSessionList); list_add(&ret_buf->cifsSessionList, &GlobalSMBSessionList);
init_MUTEX(&ret_buf->sesSem); init_MUTEX(&ret_buf->sesSem);
write_unlock(&GlobalSMBSeslock);
} }
return ret_buf; return ret_buf;
} }
...@@ -84,8 +85,10 @@ sesInfoFree(struct cifsSesInfo *buf_to_free) ...@@ -84,8 +85,10 @@ sesInfoFree(struct cifsSesInfo *buf_to_free)
return; return;
} }
write_lock(&GlobalSMBSeslock);
atomic_dec(&sesInfoAllocCount); atomic_dec(&sesInfoAllocCount);
list_del(&buf_to_free->cifsSessionList); list_del(&buf_to_free->cifsSessionList);
write_unlock(&GlobalSMBSeslock);
if (buf_to_free->serverOS) if (buf_to_free->serverOS)
kfree(buf_to_free->serverOS); kfree(buf_to_free->serverOS);
if (buf_to_free->serverDomain) if (buf_to_free->serverDomain)
...@@ -104,11 +107,13 @@ tconInfoAlloc(void) ...@@ -104,11 +107,13 @@ tconInfoAlloc(void)
GFP_KERNEL); GFP_KERNEL);
if (ret_buf) { if (ret_buf) {
memset(ret_buf, 0, sizeof (struct cifsTconInfo)); memset(ret_buf, 0, sizeof (struct cifsTconInfo));
write_lock(&GlobalSMBSeslock);
atomic_inc(&tconInfoAllocCount); atomic_inc(&tconInfoAllocCount);
list_add(&ret_buf->cifsConnectionList, list_add(&ret_buf->cifsConnectionList,
&GlobalTreeConnectionList); &GlobalTreeConnectionList);
INIT_LIST_HEAD(&ret_buf->openFileList); INIT_LIST_HEAD(&ret_buf->openFileList);
init_MUTEX(&ret_buf->tconSem); init_MUTEX(&ret_buf->tconSem);
write_unlock(&GlobalSMBSeslock);
} }
return ret_buf; return ret_buf;
} }
...@@ -120,9 +125,10 @@ tconInfoFree(struct cifsTconInfo *buf_to_free) ...@@ -120,9 +125,10 @@ tconInfoFree(struct cifsTconInfo *buf_to_free)
cFYI(1, ("\nNull buffer passed to tconInfoFree")); cFYI(1, ("\nNull buffer passed to tconInfoFree"));
return; return;
} }
write_lock(&GlobalSMBSeslock);
atomic_dec(&tconInfoAllocCount); atomic_dec(&tconInfoAllocCount);
list_del(&buf_to_free->cifsConnectionList); list_del(&buf_to_free->cifsConnectionList);
write_unlock(&GlobalSMBSeslock);
if (buf_to_free->nativeFileSystem) if (buf_to_free->nativeFileSystem)
kfree(buf_to_free->nativeFileSystem); kfree(buf_to_free->nativeFileSystem);
kfree(buf_to_free); kfree(buf_to_free);
...@@ -203,9 +209,10 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ , ...@@ -203,9 +209,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;
down(&GlobalMid_Sem); write_lock(&GlobalMid_Lock);
GlobalMid++; GlobalMid++;
buffer->Mid = GlobalMid; buffer->Mid = GlobalMid;
write_unlock(&GlobalMid_Lock);
if (treeCon) { if (treeCon) {
buffer->Tid = treeCon->tid; buffer->Tid = treeCon->tid;
if (treeCon->ses) { if (treeCon->ses) {
...@@ -220,11 +227,9 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ , ...@@ -220,11 +227,9 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
buffer->Flags2 |= SMBFLG2_DFS; buffer->Flags2 |= SMBFLG2_DFS;
if(treeCon->ses->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) if(treeCon->ses->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
} }
/* endian conversion of flags is now done just before sending */ /* endian conversion of flags is now done just before sending */
up(&GlobalMid_Sem);
buffer->WordCount = (char) word_count; buffer->WordCount = (char) word_count;
return; return;
} }
...@@ -234,7 +239,8 @@ checkSMBhdr(struct smb_hdr *smb, __u16 mid) ...@@ -234,7 +239,8 @@ checkSMBhdr(struct smb_hdr *smb, __u16 mid)
{ {
/* Make sure that this really is an SMB, that it is a response, /* Make sure that this really is an SMB, that it is a response,
and that the message ids match */ and that the message ids match */
if ((*(unsigned int *) smb->Protocol == cpu_to_le32(0x424d53ff)) && (mid == smb->Mid)) { if ((*(unsigned int *) smb->Protocol == cpu_to_le32(0x424d53ff)) &&
(mid == smb->Mid)) {
if(smb->Flags & SMBFLG_RESPONSE) if(smb->Flags & SMBFLG_RESPONSE)
return 0; return 0;
else { else {
...@@ -269,7 +275,7 @@ checkSMB(struct smb_hdr *smb, __u16 mid, int length) ...@@ -269,7 +275,7 @@ checkSMB(struct smb_hdr *smb, __u16 mid, int length)
cERROR(1, ("\n Length less than 2 + sizeof smb_hdr ")); cERROR(1, ("\n Length less than 2 + sizeof smb_hdr "));
if ((length >= sizeof (struct smb_hdr) - 1) if ((length >= sizeof (struct smb_hdr) - 1)
&& (smb->Status.CifsError != 0)) && (smb->Status.CifsError != 0))
return 0; /* this is ok - some error cases do not return wct and bcc */ return 0; /* some error cases do not return wct and bcc */
} }
if (4 + ntohl(smb->smb_buf_length) > if (4 + ntohl(smb->smb_buf_length) >
...@@ -299,6 +305,8 @@ int ...@@ -299,6 +305,8 @@ int
is_valid_oplock_break(struct smb_hdr *buf) is_valid_oplock_break(struct smb_hdr *buf)
{ {
struct smb_com_lock_req * pSMB = (struct smb_com_lock_req *)buf; struct smb_com_lock_req * pSMB = (struct smb_com_lock_req *)buf;
struct list_head *tmp;
struct cifsTconInfo *tcon;
/* could add check for smb response flag 0x80 */ /* could add check for smb response flag 0x80 */
cFYI(1,("\nChecking for oplock break")); cFYI(1,("\nChecking for oplock break"));
...@@ -313,14 +321,24 @@ is_valid_oplock_break(struct smb_hdr *buf) ...@@ -313,14 +321,24 @@ is_valid_oplock_break(struct smb_hdr *buf)
if(!(pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE)) if(!(pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE))
return FALSE; return FALSE;
/* look up tcon based on tid & uid */
read_lock(&GlobalSMBSeslock);
list_for_each(tmp, &GlobalTreeConnectionList) {
tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
if (tcon->tid == buf->Tid)
if(tcon->ses->Suid == buf->Uid) {
/* BB Add following logic: /* BB Add following logic:
1) look up tcon based on tid & uid
2) look up inode from tcon->openFileList->file->f_dentry->d_inode 2) look up inode from tcon->openFileList->file->f_dentry->d_inode
3) flush dirty pages and cached byte range locks and mark inode 3) flush dirty pages and cached byte range locks and mark inode
4) depending on break type change to r/o caching or no caching 4) depending on break type change to r/o caching or no caching
5) send oplock break response to server */ 5) send oplock break response to server */
cFYI(1,("\nNeed to process oplock break ")); read_unlock(&GlobalSMBSeslock);
cFYI(1,("\nFound matching connection, process oplock break"));
return TRUE;
}
}
read_unlock(&GlobalSMBSeslock);
cFYI(1,("\nProcessing oplock break for non-existent connection"));
return TRUE; return TRUE;
} }
......
...@@ -59,9 +59,11 @@ AllocMidQEntry(struct smb_hdr *smb_buffer, struct cifsSesInfo *ses) ...@@ -59,9 +59,11 @@ AllocMidQEntry(struct smb_hdr *smb_buffer, struct cifsSesInfo *ses)
temp->tsk = current; temp->tsk = current;
} }
if (ses->status == CifsGood) { if (ses->status == CifsGood) {
write_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);
} else { /* BB add reconnect code here BB */ } else { /* BB add reconnect code here BB */
cERROR(1, cERROR(1,
...@@ -77,11 +79,13 @@ void ...@@ -77,11 +79,13 @@ void
DeleteMidQEntry(struct mid_q_entry *midEntry) DeleteMidQEntry(struct mid_q_entry *midEntry)
{ {
/* BB add spinlock to protect midq for each session BB */ /* BB add spinlock to protect midq for each session BB */
write_lock(&GlobalMid_Lock);
midEntry->midState = MID_FREE; midEntry->midState = MID_FREE;
buf_release(midEntry->resp_buf);
list_del(&midEntry->qhead); list_del(&midEntry->qhead);
kmem_cache_free(cifs_mid_cachep, midEntry);
atomic_dec(&midCount); atomic_dec(&midCount);
write_unlock(&GlobalMid_Lock);
buf_release(midEntry->resp_buf);
kmem_cache_free(cifs_mid_cachep, midEntry);
} }
int int
......
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